From d5d0da3eadebea6e31743cbed6898790d7ae9131 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 20 Mar 2012 13:13:47 +0100 Subject: [PATCH 001/261] Use LL_UART for io mappings table --- arch/arm/mach-zynq/common.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index ba3f3fdee5cc4..0e75a4049f475 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -92,13 +92,12 @@ struct map_desc io_desc[] __initdata = { .pfn = __phys_to_pfn(SCU_PERIPH_PHYS), .length = SZ_8K, .type = MT_DEVICE, - }, - + }, #ifdef CONFIG_DEBUG_LL { - .virtual = UART1_VIRT, - .pfn = __phys_to_pfn(UART1_PHYS), - .length = SZ_4K, + .virtual = LL_UART_VADDR, + .pfn = __phys_to_pfn(LL_UART_PADDR), + .length = SZ_8K, .type = MT_DEVICE, }, #endif From de8da390ff677036e2cccf1aa60534cc604bacf2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 5 Mar 2012 16:36:27 +0100 Subject: [PATCH 002/261] OF: Add helper function to lookup a I2C adapter by node Similar to the existing helper function to lookup a I2C device by node. Signed-off-by: Lars-Peter Clausen --- drivers/of/of_i2c.c | 14 ++++++++++++++ include/linux/of_i2c.h | 1 + 2 files changed, 15 insertions(+) diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c index f37fbeb66a440..b2ce95a298004 100644 --- a/drivers/of/of_i2c.c +++ b/drivers/of/of_i2c.c @@ -94,4 +94,18 @@ struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) } EXPORT_SYMBOL(of_find_i2c_device_by_node); +/* must call put_device() when done with returned i2c_adapter device */ +struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node) +{ + struct device *dev; + + dev = bus_find_device(&i2c_bus_type, NULL, node, + of_dev_node_match); + if (!dev) + return NULL; + + return to_i2c_adapter(dev); +} +EXPORT_SYMBOL(of_find_i2c_adapter_by_node); + MODULE_LICENSE("GPL"); diff --git a/include/linux/of_i2c.h b/include/linux/of_i2c.h index 0efe8d465f555..10d6c9ab0ebff 100644 --- a/include/linux/of_i2c.h +++ b/include/linux/of_i2c.h @@ -19,6 +19,7 @@ extern void of_i2c_register_devices(struct i2c_adapter *adap); /* must call put_device() when done with returned i2c_client device */ extern struct i2c_client *of_find_i2c_device_by_node(struct device_node *node); +extern struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node); #else static inline void of_i2c_register_devices(struct i2c_adapter *adap) From ea64f71510209313c7595e194fb5abf9f8abc727 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 7 Mar 2012 11:12:58 +0100 Subject: [PATCH 003/261] DMA: Xilinx: VDMA: Allow less then the total number of frames Although the dma controller expects the exact number of frames it was configured for we can allow transfers with less than that number of frames, if the total number of frames is a multiple of it. This is done by repeating the frames until the total number of frames has been reached. Signed-off-by: Lars-Peter Clausen --- drivers/dma/xilinx_dma.c | 90 ++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/drivers/dma/xilinx_dma.c b/drivers/dma/xilinx_dma.c index 377188e77c95e..d059f03597c2b 100644 --- a/drivers/dma/xilinx_dma.c +++ b/drivers/dma/xilinx_dma.c @@ -1219,7 +1219,7 @@ static struct dma_async_tx_descriptor *xilinx_vdma_prep_slave_sg( struct xilinx_dma_chan *chan; struct xilinx_dma_desc_sw *first = NULL, *prev = NULL, *new = NULL; struct xilinx_dma_desc_hw *hw = NULL, *prev_hw = NULL; - int i; + unsigned int i, j; struct scatterlist *sg; dma_addr_t dma_src; @@ -1232,7 +1232,7 @@ static struct dma_async_tx_descriptor *xilinx_vdma_prep_slave_sg( return NULL; /* Enforce one sg entry for one frame */ - if (sg_len != chan->num_frms) { + if (chan->num_frms % sg_len != 0) { dev_err(chan->dev, "number of entries %d not the " "same as num stores %d\n", sg_len, chan->num_frms); @@ -1246,56 +1246,58 @@ static struct dma_async_tx_descriptor *xilinx_vdma_prep_slave_sg( chan->config.stride); } - /* Build transactions using information in the scatter gather list - */ - for_each_sg(sgl, sg, sg_len, i) { + for (j = 0; j < chan->num_frms / sg_len; ++j) { + /* Build transactions using information in the scatter gather list + */ + for_each_sg(sgl, sg, sg_len, i) { - /* Allocate the link descriptor from DMA pool */ - new = xilinx_dma_alloc_descriptor(chan); - if (!new) { - dev_err(chan->dev, "No free memory for " - "link descriptor\n"); - goto fail; - } + /* Allocate the link descriptor from DMA pool */ + new = xilinx_dma_alloc_descriptor(chan); + if (!new) { + dev_err(chan->dev, "No free memory for " + "link descriptor\n"); + goto fail; + } - /* - * Calculate the maximum number of bytes to transfer, - * making sure it is less than the hw limit - */ - hw = &(new->hw); + /* + * Calculate the maximum number of bytes to transfer, + * making sure it is less than the hw limit + */ + hw = &(new->hw); - dma_src = sg_dma_address(sg); - if (chan->has_SG) { - hw->buf_addr = dma_src; + dma_src = sg_dma_address(sg); + if (chan->has_SG) { + hw->buf_addr = dma_src; - /* Fill in the descriptor */ - hw->addr_vsize = chan->config.vsize; - hw->hsize = chan->config.hsize; - hw->control = (chan->config.frm_dly << - XILINX_VDMA_FRMDLY_SHIFT) | - chan->config.stride; - } else { - /* Update the registers */ - DMA_OUT(&(chan->addr_regs->buf_addr[i]), dma_src); - } + /* Fill in the descriptor */ + hw->addr_vsize = chan->config.vsize; + hw->hsize = chan->config.hsize; + hw->control = (chan->config.frm_dly << + XILINX_VDMA_FRMDLY_SHIFT) | + chan->config.stride; + } else { + /* Update the registers */ + DMA_OUT(&(chan->addr_regs->buf_addr[j * sg_len + i]), dma_src); + } - /* If this is not the first descriptor, chain the - * current descriptor after the previous descriptor - */ - if (!first) { - first = new; - } else { - prev_hw = &(prev->hw); - prev_hw->next_desc = new->async_tx.phys; - } + /* If this is not the first descriptor, chain the + * current descriptor after the previous descriptor + */ + if (!first) { + first = new; + } else { + prev_hw = &(prev->hw); + prev_hw->next_desc = new->async_tx.phys; + } - new->async_tx.cookie = 0; - async_tx_ack(&new->async_tx); + new->async_tx.cookie = 0; + async_tx_ack(&new->async_tx); - prev = new; + prev = new; - /* Insert the link descriptor into the list */ - list_add_tail(&new->node, &first->tx_list); + /* Insert the link descriptor into the list */ + list_add_tail(&new->node, &first->tx_list); + } } /* Link the last BD with the first BD */ From 72ee8c1689401f0d05820179d77b0465179ded1f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 9 Mar 2012 10:49:27 +0100 Subject: [PATCH 004/261] dmaengine: Add helper function for generating a cookie Add a small helper function for generating a new cookie. Signed-off-by: Lars-Peter Clausen --- include/linux/dmaengine.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 679b349d9b666..9a2f5dd0e593c 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -366,6 +366,22 @@ static inline const char *dma_chan_name(struct dma_chan *chan) void dma_chan_cleanup(struct kref *kref); +/** + * dma_chan_generate_cookie - generate a new cookie + * @chan: channel for which to generate the cookie + * + * Note: The caller has to make sure that the function is not called + * concurrently. + */ +static inline dma_cookie_t dma_chan_generate_cookie(struct dma_chan *chan) +{ + chan->cookie++; + if (chan->cookie < DMA_MIN_COOKIE) + chan->cookie = DMA_MIN_COOKIE; + + return chan->cookie; +} + /** * typedef dma_filter_fn - callback filter for dma_request_channel * @chan: channel to be reviewed From efaf0c9f73fe1deb6d94aac3d08a75b35f468d32 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Mar 2012 13:46:55 +0100 Subject: [PATCH 005/261] dmaengine: Rework Xilinx DMA driver --- drivers/dma/xilinx_dma.c | 2045 +++++++++++++------------------------- 1 file changed, 670 insertions(+), 1375 deletions(-) diff --git a/drivers/dma/xilinx_dma.c b/drivers/dma/xilinx_dma.c index d059f03597c2b..96c265d823a3c 100644 --- a/drivers/dma/xilinx_dma.c +++ b/drivers/dma/xilinx_dma.c @@ -2,13 +2,13 @@ * Xilinx DMA Engine support * * Copyright (C) 2010 Xilinx, Inc. All rights reserved. + * Copyright (C) 2012 Analog Device Inc. + * Author: Lars-Peter Clausen * * Based on the Freescale DMA driver. * * Description: * This driver supports three Xilinx DMA engines: - * . Axi CDMA engine, it does transfers between memory and memory, it - * only has one channel. * . Axi DMA engine, it does transfers between memory and device. It can be * configured to have one channel or two channels. If configured as two * channels, one is to transmit to a device and another is to receive from @@ -33,10 +33,13 @@ #include #include #include +#include #include #include #include #include +#include +#include /* Hw specific definitions */ @@ -75,13 +78,6 @@ #define XILINX_DMA_RX_CHANNEL_OFFSET 0x30 -/* Axi CDMA special register bits - */ -#define XILINX_CDMA_CR_SGMODE_MASK 0x00000008 /**< Scatter gather mode */ - -#define XILINX_CDMA_SR_SGINCLD_MASK 0x00000008 /**< Hybrid build */ -#define XILINX_CDMA_XR_IRQ_SIMPLE_ALL_MASK 0x00005000 /**< All interrupts for - simple only mode */ /* Axi VDMA special register bits */ #define XILINX_VDMA_CIRC_EN 0x00000002 /* Circular mode */ @@ -97,7 +93,7 @@ #define XILINX_VDMA_DIRECT_REG_OFFSET 0x50 #define XILINX_VDMA_CHAN_DIRECT_REG_SIZE 0x50 -/* BD definitions for Axi Dma and Axi Cdma +/* BD definitions for Axi DMA */ #define XILINX_DMA_BD_STS_COMPL_MASK 0x80000000 #define XILINX_DMA_BD_STS_ERR_MASK 0x70000000 @@ -143,14 +139,24 @@ struct xilinx_dma_desc_hw { u32 app_2; /* 0x28 */ u32 app_3; /* 0x2C */ u32 app_4; /* 0x30 */ -} __attribute__((aligned(64))); +} __aligned(64); struct xilinx_dma_desc_sw { - struct xilinx_dma_desc_hw hw; - struct list_head node; - struct list_head tx_list; + struct xilinx_dma_desc_hw *hw; + dma_addr_t phys; +}; + +struct xilinx_dma_transfer { struct dma_async_tx_descriptor async_tx; -} __attribute__((aligned(64))); + struct list_head head; + + bool cyclic; + unsigned int completed_descs; + + unsigned int current_desc; + unsigned int num_descs; + struct xilinx_dma_desc_sw descs[]; +}; struct xdma_regs { u32 cr; /* 0x00 Control Register */ @@ -167,6 +173,20 @@ struct xdma_regs { u32 version; /* 0x2c version (vdma) */ }; +static struct debugfs_reg32 xilinx_dma_debugfs_regs[] = { + { "Control", 0x00 }, + { "Status", 0x04 }, + { "Current descriptor", 0x08 }, + { "Tail descriptor", 0x10 }, + { "Vertical size", 0x50 }, + { "Horizontal size", 0x54 }, + { "Frame delay/stride", 0x58 }, + { "Frame address 0", 0x5c }, + { "Frame address 1", 0x60 }, + { "Frame address 2", 0x64 }, + { "Frame address 3", 0x68 }, +}; + struct vdma_addr_regs { u32 vsize; /* 0x0 Vertical size */ u32 hsize; /* 0x4 Horizontal size */ @@ -180,9 +200,7 @@ struct xilinx_dma_chan { struct xdma_regs __iomem *regs; /* Control status registers */ struct vdma_addr_regs *addr_regs; /* Direct address registers */ dma_cookie_t completed_cookie; /* The maximum cookie completed */ - dma_cookie_t cookie; /* The current cookie */ spinlock_t lock; /* Descriptor operation lock */ - bool sg_waiting; /* Scatter gather transfer waiting */ struct list_head active_list; /* Active descriptors */ struct list_head pending_list; /* Descriptors waiting */ struct dma_chan common; /* DMA common channel */ @@ -190,9 +208,8 @@ struct xilinx_dma_chan { struct device *dev; /* The dma device */ int irq; /* Channel IRQ */ int id; /* Channel ID */ - enum dma_data_direction direction;/* Transfer direction */ + enum dma_transfer_direction direction;/* Transfer direction */ int max_len; /* Maximum data len per transfer */ - int is_lite; /* Whether is light build */ int num_frms; /* Number of frames */ int has_SG; /* Support scatter transfers */ int has_DRE; /* Support unaligned transfers */ @@ -200,9 +217,11 @@ struct xilinx_dma_chan { int err; /* Channel has errors */ struct tasklet_struct tasklet; /* Cleanup work after irq */ u32 feature; /* IP feature */ - u32 private; /* Match info for channel request */ void (*start_transfer)(struct xilinx_dma_chan *chan); struct xilinx_dma_config config; /* Device configuration info */ + + bool cyclic; + struct debugfs_regset32 debugfs_regset; }; struct xilinx_dma_device { @@ -214,8 +233,83 @@ struct xilinx_dma_device { int irq; }; +static dma_cookie_t xilinx_dma_tx_submit(struct dma_async_tx_descriptor *tx); + #define to_xilinx_chan(chan) container_of(chan, struct xilinx_dma_chan, common) +static void xilinx_dma_free_transfer(struct xilinx_dma_chan *chan, + struct xilinx_dma_transfer *t) +{ + unsigned int i; + for (i = 0; i < t->num_descs; ++i) + dma_pool_free(chan->desc_pool, t->descs[i].hw, t->descs[i].phys); + kfree(t); +} + +static struct xilinx_dma_transfer *xilinx_dma_alloc_transfer( + struct xilinx_dma_chan *chan, unsigned int num_descs) +{ + struct xilinx_dma_desc_hw *new, *prev; + struct xilinx_dma_transfer *t; + dma_addr_t phys; + + if (num_descs == 0) + return NULL; + + t = kzalloc(sizeof(*t) + num_descs * sizeof(*t->descs), GFP_ATOMIC); + if (!t) + return NULL; + + dma_async_tx_descriptor_init(&t->async_tx, &chan->common); + t->async_tx.tx_submit = xilinx_dma_tx_submit; + t->async_tx.cookie = -EBUSY; + + prev = NULL; + new = NULL; + for (; t->num_descs < num_descs; t->num_descs++) { + new = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &phys); + if (!new) { + dev_err(chan->dev, "No free memory for link descriptor\n"); + goto err_free; + } + memset(new, 0, sizeof(*new)); + + if (prev) + prev->next_desc = phys; + + t->descs[t->num_descs].hw = new; + t->descs[t->num_descs].phys = phys; + prev = new; + } + + /* Link the last BD with the first BD */ + new->next_desc = t->descs[0].phys; + + return t; +err_free: + xilinx_dma_free_transfer(chan, t); + return NULL; +} + +static void xilinx_dma_free_transfer_list(struct xilinx_dma_chan *chan, + struct list_head *list) +{ + struct xilinx_dma_transfer *t, *_t; + list_for_each_entry_safe(t, _t, list, head) + xilinx_dma_free_transfer(chan, t); + INIT_LIST_HEAD(list); +} + +static void xilinx_dma_free_transfers(struct xilinx_dma_chan *chan) +{ + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + xilinx_dma_free_transfer_list(chan, &chan->active_list); + xilinx_dma_free_transfer_list(chan, &chan->pending_list); + spin_unlock_irqrestore(&chan->lock, flags); +} + /* Required functions */ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan) @@ -232,95 +326,94 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan) */ chan->desc_pool = dma_pool_create("xilinx_dma_desc_pool", chan->dev, - sizeof(struct xilinx_dma_desc_sw), - __alignof__(struct xilinx_dma_desc_sw), 0); + sizeof(struct xilinx_dma_desc_hw), + __alignof__(struct xilinx_dma_desc_hw), 0); if (!chan->desc_pool) { dev_err(chan->dev, "unable to allocate channel %d " "descriptor pool\n", chan->id); return -ENOMEM; } - chan->completed_cookie = 1; - chan->cookie = 1; + chan->completed_cookie = 0; /* there is at least one descriptor free to be allocated */ return 1; } -static void xilinx_dma_free_desc_list(struct xilinx_dma_chan *chan, - struct list_head *list) -{ - struct xilinx_dma_desc_sw *desc, *_desc; - - list_for_each_entry_safe(desc, _desc, list, node) { - list_del(&desc->node); - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); - } -} - -static void xilinx_dma_free_desc_list_reverse(struct xilinx_dma_chan *chan, - struct list_head *list) -{ - struct xilinx_dma_desc_sw *desc, *_desc; - - list_for_each_entry_safe_reverse(desc, _desc, list, node) { - list_del(&desc->node); - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); - } -} - static void xilinx_dma_free_chan_resources(struct dma_chan *dchan) { struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); - unsigned long flags; dev_dbg(chan->dev, "Free all channel resources.\n"); - spin_lock_irqsave(&chan->lock, flags); - xilinx_dma_free_desc_list(chan, &chan->active_list); - xilinx_dma_free_desc_list(chan, &chan->pending_list); - spin_unlock_irqrestore(&chan->lock, flags); - + xilinx_dma_free_transfers(chan); dma_pool_destroy(chan->desc_pool); chan->desc_pool = NULL; } static enum dma_status xilinx_dma_desc_status(struct xilinx_dma_chan *chan, - struct xilinx_dma_desc_sw *desc) + struct xilinx_dma_transfer *t) { - return dma_async_is_complete(desc->async_tx.cookie, + return dma_async_is_complete(t->async_tx.cookie, chan->completed_cookie, - chan->cookie); + chan->common.cookie); +} + +static void xilinx_dma_chan_handle_cyclic(struct xilinx_dma_chan *chan, + struct xilinx_dma_transfer *t, unsigned long *flags) +{ + unsigned int completed_descs; + dma_async_tx_callback callback; + void *callback_param; + unsigned int i; + + /* We have to be carefull not to dereference 't' anymore after a call to + * the callback function, since it might call terminate_all and as a + * result 't' might be already freed. */ + callback = t->async_tx.callback; + callback_param = t->async_tx.callback_param; + completed_descs = t->completed_descs; + t->completed_descs = 0; + + spin_unlock_irqrestore(&chan->lock, *flags); + for (i = 0; i < completed_descs; i++) + callback(callback_param); + spin_lock_irqsave(&chan->lock, *flags); } static void xilinx_chan_desc_cleanup(struct xilinx_dma_chan *chan) { - struct xilinx_dma_desc_sw *desc, *_desc; + struct xilinx_dma_transfer *t; + dma_async_tx_callback callback; + void *callback_param; unsigned long flags; spin_lock_irqsave(&chan->lock, flags); - list_for_each_entry_safe(desc, _desc, &chan->active_list, node) { - dma_async_tx_callback callback; - void *callback_param; + /* terminate_all might be called from the callback, so we can't iterate over + * the list using list_for_each_entry_safe */ + while (!list_empty(&chan->active_list)) { + t = list_first_entry(&chan->active_list, struct xilinx_dma_transfer, head); + + if (t->cyclic) { + xilinx_dma_chan_handle_cyclic(chan, t, &flags); + break; + } - if (xilinx_dma_desc_status(chan, desc) == DMA_IN_PROGRESS) + if (xilinx_dma_desc_status(chan, t) == DMA_IN_PROGRESS) break; - /* Remove from the list of running transactions */ - list_del(&desc->node); + list_del(&t->head); - /* Run the link descriptor callback function */ - callback = desc->async_tx.callback; - callback_param = desc->async_tx.callback_param; + callback = t->async_tx.callback; + callback_param = t->async_tx.callback_param; if (callback) { spin_unlock_irqrestore(&chan->lock, flags); callback(callback_param); spin_lock_irqsave(&chan->lock, flags); } - /* Run any dependencies, then free the descriptor */ - dma_run_dependencies(&desc->async_tx); - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); + dma_run_dependencies(&t->async_tx); + xilinx_dma_free_transfer(chan, t); } spin_unlock_irqrestore(&chan->lock, flags); @@ -344,27 +437,30 @@ static enum dma_status xilinx_tx_status(struct dma_chan *dchan, return dma_async_is_complete(cookie, last_complete, last_used); } -static int dma_is_running(struct xilinx_dma_chan *chan) +static int xilinx_dma_is_running(struct xilinx_dma_chan *chan) { return !(DMA_IN(&chan->regs->sr) & XILINX_DMA_SR_HALTED_MASK) && (DMA_IN(&chan->regs->cr) & XILINX_DMA_CR_RUNSTOP_MASK); } -static int dma_is_idle(struct xilinx_dma_chan *chan) +static int xilinx_dma_is_idle(struct xilinx_dma_chan *chan) { return DMA_IN(&chan->regs->sr) & XILINX_DMA_SR_IDLE_MASK; } -/* Only needed for Axi CDMA v2_00_a or earlier core - */ -static void dma_sg_toggle(struct xilinx_dma_chan *chan) +static int xilinx_dma_wait_idle(struct xilinx_dma_chan *chan) { + unsigned long timeout = 10000; - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) & ~XILINX_CDMA_CR_SGMODE_MASK); + do { + if (xilinx_dma_is_idle(chan)) + break; + } while (--timeout); - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) | XILINX_CDMA_CR_SGMODE_MASK); + if (!xilinx_dma_is_idle(chan)) + return -ETIMEDOUT; + + return 0; } #define XILINX_DMA_DRIVER_DEBUG 0 @@ -379,167 +475,117 @@ static void desc_dump(struct xilinx_dma_desc_hw *hw) printk(KERN_INFO "\thsize %x\n", hw->hsize); printk(KERN_INFO "\tcontrol %x\n", hw->control); printk(KERN_INFO "\tstatus %x\n", hw->status); - } #endif -static void xilinx_cdma_start_transfer(struct xilinx_dma_chan *chan) +static int xilinx_dma_wait_status(struct xilinx_dma_chan *chan, uint32_t mask, + uint32_t value) { - unsigned long flags; - struct xilinx_dma_desc_sw *desch, *desct; - struct xilinx_dma_desc_hw *hw; + unsigned long timeout = 10000; + uint32_t status; - if (chan->err) - return; + do { + status = DMA_IN(&chan->regs->cr); + printk("status: %x, mask: %x, value: %x\n", status, mask, value); + if ((status & mask) == value) + break; + } while (--timeout); - spin_lock_irqsave(&chan->lock, flags); + if ((status & mask) != value) + return -ETIMEDOUT; - if (list_empty(&chan->pending_list)) - goto out_unlock; + return 0; +} - /* If hardware is busy, cannot submit - */ - if (!dma_is_idle(chan)) { - dev_dbg(chan->dev, "DMA controller still busy %x\n", - DMA_IN(&chan->regs->sr)); - goto out_unlock; - } +static int xilinx_dma_reset(struct xilinx_dma_chan *chan) +{ + int ret; - /* Enable interrupts - */ DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) | XILINX_DMA_XR_IRQ_ALL_MASK); - - desch = list_first_entry(&chan->pending_list, struct xilinx_dma_desc_sw, - node); - - if (chan->has_SG) { - - /* If hybrid mode, append pending list to active list - */ - desct = container_of(chan->pending_list.prev, - struct xilinx_dma_desc_sw, node); - - list_splice_tail_init(&chan->pending_list, &chan->active_list); - - /* If hardware is idle, then all descriptors on the active list - * are done, start new transfers - */ - dma_sg_toggle(chan); + DMA_IN(&chan->regs->cr) | XILINX_DMA_CR_RESET_MASK); - DMA_OUT(&chan->regs->cdr, desch->async_tx.phys); + ret = xilinx_dma_wait_status(chan, XILINX_DMA_CR_RESET_MASK, 0); - /* Update tail ptr register and start the transfer - */ - DMA_OUT(&chan->regs->tdr, desct->async_tx.phys); - goto out_unlock; + if (ret) { + dev_err(chan->dev, "reset timeout, cr %x, sr %x\n", + DMA_IN(&chan->regs->cr), DMA_IN(&chan->regs->sr)); + return 1; } - /* In simple mode - */ - list_del(&desch->node); - list_add_tail(&desch->node, &chan->active_list); - - hw = &desch->hw; - - DMA_OUT(&chan->regs->src, hw->buf_addr); - DMA_OUT(&chan->regs->dst, hw->addr_vsize); - - /* Start the transfer - */ - DMA_OUT(&chan->regs->btt_ref, - hw->control & XILINX_DMA_MAX_TRANS_LEN); + /* re-apply config */ + dmaengine_device_control(&chan->common, DMA_SLAVE_CONFIG, + (unsigned long)&chan->config); -out_unlock: - spin_unlock_irqrestore(&chan->lock, flags); + return 0; } -/* If sg mode, link the pending list to running list; if simple mode, get the - * head of the pending list and submit it to hw - */ -static void xilinx_cdma_issue_pending(struct dma_chan *dchan) +static void xilinx_dma_start_stop(struct xilinx_dma_chan *chan, bool start) { - struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); - xilinx_cdma_start_transfer(chan); + uint32_t status; + uint32_t value; + int ret; + + if (start) + value = XILINX_DMA_CR_RUNSTOP_MASK; + else + value = 0; + + status = DMA_IN(&chan->regs->cr); + status &= ~XILINX_DMA_CR_RUNSTOP_MASK; + status |= value; + DMA_OUT(&chan->regs->cr, status); + + ret = xilinx_dma_wait_status(chan, XILINX_DMA_CR_RUNSTOP_MASK, value); + if (ret) { + dev_dbg(chan->dev, "Cannot %s channel %x: %x\n", + start ? "start" : "stop", chan->id, + DMA_IN(&chan->regs->cr)); + chan->err = 1; + } } /* Stop the hardware, the ongoing transfer will be finished */ static void dma_halt(struct xilinx_dma_chan *chan) { - int loop = XILINX_DMA_HALT_LOOP; - - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) & ~XILINX_DMA_CR_RUNSTOP_MASK); - - /* Wait for the hardware to halt - */ - while (loop) { - if (!(DMA_IN(&chan->regs->cr) & XILINX_DMA_CR_RUNSTOP_MASK)) - break; - - loop -= 1; - } - - if (!loop) { - pr_debug("Cannot stop channel %x: %x\n", - (unsigned int)chan, - (unsigned int)DMA_IN(&chan->regs->cr)); - chan->err = 1; - } - - return; + xilinx_dma_start_stop(chan, false); } /* Start the hardware. Transfers are not started yet */ static void dma_start(struct xilinx_dma_chan *chan) { - int loop = XILINX_DMA_HALT_LOOP; - - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) | XILINX_DMA_CR_RUNSTOP_MASK); - - /* Wait for the hardware to start - */ - while (loop) { - if (DMA_IN(&chan->regs->cr) & XILINX_DMA_CR_RUNSTOP_MASK) - break; - - loop -= 1; - } - - if (!loop) { - pr_debug("Cannot start channel %x: %x\n", - (unsigned int)chan, - (unsigned int)DMA_IN(&chan->regs->cr)); - - chan->err = 1; - } - - return; + xilinx_dma_start_stop(chan, true); } - static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan) { - unsigned long flags; - struct xilinx_dma_desc_sw *desch, *desct; + struct xilinx_dma_transfer *last_transfer, *first_transfer; + dma_addr_t first_addr, last_addr; struct xilinx_dma_desc_hw *hw; - - if (chan->err) - return; + unsigned long flags; + int ret; spin_lock_irqsave(&chan->lock, flags); if (list_empty(&chan->pending_list)) goto out_unlock; + if (chan->err) { + dev_err(chan->dev, "Failed to start transfer\n"); + goto out_unlock; + } + /* If hardware is busy, cannot submit */ - if (dma_is_running(chan) && !dma_is_idle(chan)) { - dev_dbg(chan->dev, "DMA controller still busy\n"); + if (xilinx_dma_is_running(chan) && !xilinx_dma_is_idle(chan)) { + dev_info(chan->dev, "DMA controller still busy\n"); goto out_unlock; } + ret = xilinx_dma_wait_idle(chan); + if (ret) + xilinx_dma_reset(chan); + + /* If hardware is idle, then all descriptors on active list are * done, start new transfers */ @@ -548,14 +594,18 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan) if (chan->err) goto out_unlock; + first_transfer = list_first_entry(&chan->pending_list, + struct xilinx_dma_transfer, head); + if (chan->has_SG) { - desch = list_first_entry(&chan->pending_list, - struct xilinx_dma_desc_sw, node); + uint32_t status; + last_transfer = list_entry(chan->pending_list.prev, + struct xilinx_dma_transfer, head); - desct = container_of(chan->pending_list.prev, - struct xilinx_dma_desc_sw, node); + first_addr = first_transfer->descs[0].phys; + last_addr = last_transfer->descs[last_transfer->num_descs-1].phys; - DMA_OUT(&chan->regs->cdr, desch->async_tx.phys); + DMA_OUT(&chan->regs->cdr, first_addr); dma_start(chan); @@ -563,51 +613,38 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan) goto out_unlock; list_splice_tail_init(&chan->pending_list, &chan->active_list); - /* Enable interrupts - */ + /* Clear pending interrupts and enable interrupts */ + DMA_OUT(&chan->regs->sr, XILINX_DMA_XR_IRQ_ALL_MASK); DMA_OUT(&chan->regs->cr, DMA_IN(&chan->regs->cr) | XILINX_DMA_XR_IRQ_ALL_MASK); - + status = DMA_IN(&chan->regs->sr); /* Update tail ptr register and start the transfer */ - DMA_OUT(&chan->regs->tdr, desct->async_tx.phys); - goto out_unlock; - } - - /* In simple mode - */ - - dma_halt(chan); - - if (chan->err) - goto out_unlock; - - printk(KERN_INFO "xilinx_dma_start_transfer::simple DMA mode\n"); - - desch = list_first_entry(&chan->pending_list, - struct xilinx_dma_desc_sw, node); + DMA_OUT(&chan->regs->tdr, last_addr); + } else { + /* In simple mode */ - list_del(&desch->node); - list_add_tail(&desch->node, &chan->active_list); + list_move_tail(&first_transfer->head, &chan->active_list); - dma_start(chan); + dma_start(chan); - if (chan->err) - goto out_unlock; + if (chan->err) + goto out_unlock; - hw = &desch->hw; + hw = first_transfer->descs[0].hw; - /* Enable interrupts - */ - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) | XILINX_DMA_XR_IRQ_ALL_MASK); + /* Enable interrupts + */ + DMA_OUT(&chan->regs->cr, + DMA_IN(&chan->regs->cr) | XILINX_DMA_XR_IRQ_ALL_MASK); - DMA_OUT(&chan->regs->src, hw->buf_addr); + DMA_OUT(&chan->regs->src, hw->buf_addr); - /* Start the transfer - */ - DMA_OUT(&chan->regs->btt_ref, - hw->control & XILINX_DMA_MAX_TRANS_LEN); + /* Start the transfer + */ + DMA_OUT(&chan->regs->btt_ref, + hw->control & XILINX_DMA_MAX_TRANS_LEN); + } out_unlock: spin_unlock_irqrestore(&chan->lock, flags); @@ -616,214 +653,103 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan) static void xilinx_dma_issue_pending(struct dma_chan *dchan) { struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); - xilinx_dma_start_transfer(chan); + chan->start_transfer(chan); } -static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan) +/** + * xilinx_dma_update_completed_cookie - Update the completed cookie. + * @chan : xilinx DMA channel + * + * CONTEXT: hardirq + */ +static void xilinx_dma_update_completed_cookie(struct xilinx_dma_chan *chan) { + struct xilinx_dma_transfer *t; + struct xilinx_dma_desc_hw *hw = NULL; unsigned long flags; - struct xilinx_dma_desc_sw *desch, *desct = NULL; - struct xilinx_dma_config *config; - u32 reg; - - if (chan->err) - return; + dma_cookie_t cookie = -EBUSY; + bool done = 0; spin_lock_irqsave(&chan->lock, flags); - if (list_empty(&chan->pending_list)) - goto out_unlock; - - /* If it is SG mode and hardware is busy, cannot submit - */ - if (chan->has_SG && dma_is_running(chan) && !dma_is_idle(chan)) { - dev_dbg(chan->dev, "DMA controller still busy\n"); + if (list_empty(&chan->active_list)) { + dev_dbg(chan->dev, "no running descriptors\n"); goto out_unlock; } - /* If hardware is idle, then all descriptors on the running lists are - * done, start new transfers - */ - dma_halt(chan); - - if (chan->err) - goto out_unlock; - - if (chan->has_SG) { - desch = list_first_entry(&chan->pending_list, - struct xilinx_dma_desc_sw, node); - - desct = container_of(chan->pending_list.prev, - struct xilinx_dma_desc_sw, node); + if ((!(chan->feature & XILINX_DMA_IP_VDMA)) && chan->has_SG) { + /* Get the last completed descriptor, update the cookie to that */ + list_for_each_entry(t, &chan->active_list, head) { + if (t->cyclic) { + while (true) { + hw = t->descs[t->current_desc].hw; + if (!(hw->status & XILINX_DMA_BD_STS_ALL_MASK)) + break; + t->completed_descs++; + hw->status = 0; + DMA_OUT(&chan->regs->tdr, t->descs[t->current_desc].phys); + + t->current_desc++; + if (t->current_desc == t->num_descs) + t->current_desc = 0; + } + } else { + for (; t->current_desc < t->num_descs; t->current_desc++) { + hw = t->descs[t->current_desc].hw; + if (!(hw->status & XILINX_DMA_BD_STS_ALL_MASK)) + break; + } + if (t->current_desc != t->num_descs) + break; - DMA_OUT(&chan->regs->cdr, desch->async_tx.phys); + done = true; + cookie = t->async_tx.cookie; + } + } + } else { + /* In non-SG mode, there is only one transfer active at a time */ + t = list_first_entry(&chan->active_list, + struct xilinx_dma_transfer, head); + t->current_desc++; + t->completed_descs++; + if (t->current_desc == t->num_descs) { + if (t->cyclic) { + t->current_desc = 0; + } else { + done = true; + cookie = t->async_tx.cookie; + } + } } - /* Configure the hardware using info in the config structure */ - config = &(chan->config); - reg = DMA_IN(&chan->regs->cr); + if (done) + chan->completed_cookie = cookie; - if (config->frm_cnt_en) - reg |= XILINX_VDMA_FRMCNT_EN; - else - reg &= ~XILINX_VDMA_FRMCNT_EN; +out_unlock: + spin_unlock_irqrestore(&chan->lock, flags); +} - /* With SG, start with circular mode, so that BDs can be fetched. - * In direct register mode, if not parking, enable circular mode */ - if ((chan->has_SG) || (!config->park)) - reg |= XILINX_VDMA_CIRC_EN; +static irqreturn_t dma_intr_handler(int irq, void *data) +{ + struct xilinx_dma_chan *chan = data; + u32 stat; - DMA_OUT(&chan->regs->cr, reg); - - if ((config->park_frm >= 0) && (config->park_frm < chan->num_frms)) { - if (config->direction == DMA_TO_DEVICE) { - DMA_OUT(&chan->regs->btt_ref, - config->park_frm << XILINX_VDMA_WR_REF_SHIFT); - } else { - DMA_OUT(&chan->regs->btt_ref, config->park_frm); - } - } - - /* Start the hardware - */ - dma_start(chan); - - if (chan->err) - goto out_unlock; - list_splice_tail_init(&chan->pending_list, &chan->active_list); - - /* Enable interrupts - * - * park/genlock testing does not use interrupts */ - if (!chan->config.disable_intr) { - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) | XILINX_DMA_XR_IRQ_ALL_MASK); - } - - /* Start the transfer - */ - if (chan->has_SG) - DMA_OUT(&chan->regs->tdr, desct->async_tx.phys); - else - DMA_OUT(&chan->addr_regs->vsize, config->vsize); - -out_unlock: - spin_unlock_irqrestore(&chan->lock, flags); -} - -static void xilinx_vdma_issue_pending(struct dma_chan *dchan) -{ - struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); - xilinx_vdma_start_transfer(chan); -} - -/** - * xilinx_dma_update_completed_cookie - Update the completed cookie. - * @chan : xilinx DMA channel - * - * CONTEXT: hardirq - */ -static void xilinx_dma_update_completed_cookie(struct xilinx_dma_chan *chan) -{ - struct xilinx_dma_desc_sw *desc = NULL; - struct xilinx_dma_desc_hw *hw = NULL; - unsigned long flags; - dma_cookie_t cookie = -EBUSY; - int done = 0; - - spin_lock_irqsave(&chan->lock, flags); - - if (list_empty(&chan->active_list)) { - dev_dbg(chan->dev, "no running descriptors\n"); - goto out_unlock; - } - - /* Get the last completed descriptor, update the cookie to that */ - list_for_each_entry(desc, &chan->active_list, node) { - if ((!(chan->feature & XILINX_DMA_IP_VDMA)) && chan->has_SG) { - hw = &desc->hw; - - /* If a BD has no status bits set, hw has it */ - if (!(hw->status & XILINX_DMA_BD_STS_ALL_MASK)) { - break; - } else { - done = 1; - cookie = desc->async_tx.cookie; - } - } else { - /* In non-SG mode, all active entries are done */ - done = 1; - cookie = desc->async_tx.cookie; - } - } - - if (done) - chan->completed_cookie = cookie; - -out_unlock: - spin_unlock_irqrestore(&chan->lock, flags); -} - -/* Reset hardware - */ -static int dma_init(struct xilinx_dma_chan *chan) -{ - int loop = XILINX_DMA_RESET_LOOP; - u32 tmp; - - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) | XILINX_DMA_CR_RESET_MASK); - - tmp = DMA_IN(&chan->regs->cr) & XILINX_DMA_CR_RESET_MASK; - - /* Wait for the hardware to finish reset - */ - while (loop && tmp) { - tmp = DMA_IN(&chan->regs->cr) & XILINX_DMA_CR_RESET_MASK; - loop -= 1; - } - - if (!loop) { - dev_err(chan->dev, "reset timeout, cr %x, sr %x\n", - DMA_IN(&chan->regs->cr), DMA_IN(&chan->regs->sr)); - return 1; - } - - /* For Axi CDMA, always do sg transfers if sg mode is built in - */ - if ((chan->feature & XILINX_DMA_IP_CDMA) && chan->has_SG) - DMA_OUT(&chan->regs->cr, tmp | XILINX_CDMA_CR_SGMODE_MASK); - - return 0; -} - - -static irqreturn_t dma_intr_handler(int irq, void *data) -{ - struct xilinx_dma_chan *chan = data; - int update_cookie = 0; - int to_transfer = 0; - u32 stat; - - /* Disable intr - */ - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) & ~XILINX_DMA_XR_IRQ_ALL_MASK); - - stat = DMA_IN(&chan->regs->sr); - if (!(stat & XILINX_DMA_XR_IRQ_ALL_MASK)) - return IRQ_NONE; + stat = DMA_IN(&chan->regs->sr); + if (!(stat & XILINX_DMA_XR_IRQ_ALL_MASK)) + return IRQ_NONE; /* Ack the interrupts */ DMA_OUT(&chan->regs->sr, XILINX_DMA_XR_IRQ_ALL_MASK); if (stat & XILINX_DMA_XR_IRQ_ERROR_MASK) { - dev_err(chan->dev, "Channel %x has errors %x, cdr %x tdr %x\n", + dev_err(chan->dev, "Channel %x has errors %x, cr %x, cdr %x tdr %x\n", (unsigned int)chan, (unsigned int)stat, + (unsigned int)DMA_IN(&chan->regs->cr), (unsigned int)DMA_IN(&chan->regs->cdr), (unsigned int)DMA_IN(&chan->regs->tdr)); chan->err = 1; + dma_halt(chan); } /* Device takes too long to do the transfer when user requires @@ -833,15 +759,9 @@ static irqreturn_t dma_intr_handler(int irq, void *data) dev_dbg(chan->dev, "Inter-packet latency too long\n"); if (stat & XILINX_DMA_XR_IRQ_IOC_MASK) { - update_cookie = 1; - to_transfer = 1; - } - - if (update_cookie) xilinx_dma_update_completed_cookie(chan); - - if (to_transfer) chan->start_transfer(chan); + } tasklet_schedule(&chan->tasklet); return IRQ_HANDLED; @@ -850,32 +770,29 @@ static irqreturn_t dma_intr_handler(int irq, void *data) static void dma_do_tasklet(unsigned long data) { struct xilinx_dma_chan *chan = (struct xilinx_dma_chan *)data; - xilinx_chan_desc_cleanup(chan); } /* Append the descriptor list to the pending list */ static void append_desc_queue(struct xilinx_dma_chan *chan, - struct xilinx_dma_desc_sw *desc) + struct xilinx_dma_transfer *t) { - struct xilinx_dma_desc_sw *tail = container_of(chan->pending_list.prev, - struct xilinx_dma_desc_sw, node); + struct xilinx_dma_transfer *tail = container_of(chan->pending_list.prev, + struct xilinx_dma_transfer, head); struct xilinx_dma_desc_hw *hw; - if (list_empty(&chan->pending_list)) - goto out_splice; - - /* Add the hardware descriptor to the chain of hardware descriptors - * that already exists in memory. - */ - hw = &(tail->hw); - hw->next_desc = (u32)desc->async_tx.phys; + if (!list_empty(&chan->pending_list)) { + /* Add the hardware descriptor to the chain of hardware descriptors + * that already exists in memory. + */ + hw = tail->descs[tail->num_descs-1].hw; + hw->next_desc = t->descs[0].phys; + } /* Add the software descriptor and all children to the list * of pending transactions */ -out_splice: - list_splice_tail_init(&desc->tx_list, &chan->pending_list); + list_add_tail(&t->head, &chan->pending_list); } /* Assign cookie to each descriptor, and append the descriptors to the pending @@ -884,189 +801,88 @@ static void append_desc_queue(struct xilinx_dma_chan *chan, static dma_cookie_t xilinx_dma_tx_submit(struct dma_async_tx_descriptor *tx) { struct xilinx_dma_chan *chan = to_xilinx_chan(tx->chan); - struct xilinx_dma_desc_sw *desc = container_of(tx, - struct xilinx_dma_desc_sw, async_tx); - struct xilinx_dma_desc_sw *child; + struct xilinx_dma_transfer *t = container_of(tx, + struct xilinx_dma_transfer, async_tx); unsigned long flags; - dma_cookie_t cookie = -EBUSY; + + spin_lock_irqsave(&chan->lock, flags); + + if (chan->cyclic) + goto err; if (chan->err) { /* If reset fails, need to hard reset the system. * Channel is no longer functional */ - if (!dma_init(chan)) + if (!xilinx_dma_reset(chan)) chan->err = 0; else - return cookie; - } - - spin_lock_irqsave(&chan->lock, flags); - - /* - * assign cookies to all of the software descriptors - * that make up this transaction - */ - cookie = chan->cookie; - list_for_each_entry(child, &desc->tx_list, node) { - cookie++; - if (cookie < 0) - cookie = DMA_MIN_COOKIE; - - child->async_tx.cookie = cookie; + goto err; } - chan->cookie = cookie; - + t->async_tx.cookie = dma_chan_generate_cookie(&chan->common); /* put this transaction onto the tail of the pending queue */ - append_desc_queue(chan, desc); - - spin_unlock_irqrestore(&chan->lock, flags); - - return cookie; -} - -static struct xilinx_dma_desc_sw *xilinx_dma_alloc_descriptor( - struct xilinx_dma_chan *chan) -{ - struct xilinx_dma_desc_sw *desc; - dma_addr_t pdesc; + append_desc_queue(chan, t); - desc = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc); - if (!desc) { - dev_dbg(chan->dev, "out of memory for desc\n"); - return NULL; - } + if (t->cyclic) + chan->cyclic = true; - memset(desc, 0, sizeof(*desc)); - INIT_LIST_HEAD(&desc->tx_list); - dma_async_tx_descriptor_init(&desc->async_tx, &chan->common); - desc->async_tx.tx_submit = xilinx_dma_tx_submit; - desc->async_tx.phys = pdesc; + spin_unlock_irqrestore(&chan->lock, flags); - return desc; + return t->async_tx.cookie; +err: + spin_unlock_irqrestore(&chan->lock, flags); + xilinx_dma_free_transfer(chan, t); + return -EBUSY; } /** - * xilinx_dma_prep_memcpy - prepare descriptors for a memcpy transaction - * @dchan: DMA channel - * @dma_dst: destination address - * @dma_src: source address - * @len: transfer length + * xilinx_dma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction + * @chan: DMA channel + * @sgl: scatterlist to transfer to/from + * @sg_len: number of entries in @scatterlist + * @direction: DMA direction * @flags: transfer ack flags */ -static struct dma_async_tx_descriptor *xilinx_dma_prep_memcpy( - struct dma_chan *dchan, dma_addr_t dma_dst, dma_addr_t dma_src, - size_t len, unsigned long flags) +static struct dma_async_tx_descriptor *xilinx_dma_prep_dma_cyclic( + struct dma_chan *dchan, dma_addr_t buf_addr, size_t buf_len, + size_t period_len, enum dma_transfer_direction direction) { + struct xilinx_dma_desc_hw *hw; + struct xilinx_dma_transfer *t; struct xilinx_dma_chan *chan; - struct xilinx_dma_desc_sw *first = NULL, *prev = NULL, *new; - struct xilinx_dma_desc_hw *hw, *prev_hw; - size_t copy; - dma_addr_t src = dma_src; - dma_addr_t dst = dma_dst; + unsigned int num_periods; + unsigned int i; if (!dchan) return NULL; - if (!len) - return NULL; - chan = to_xilinx_chan(dchan); - if (chan->err) { - - /* If reset fails, need to hard reset the system. - * Channel is no longer functional - */ - if (!dma_init(chan)) - chan->err = 0; - else - return NULL; - } + if (chan->direction != direction) + return NULL; - /* If build does not have Data Realignment Engine (DRE), - * src has to be aligned - */ - if (!chan->has_DRE) { - if ((dma_src & - (chan->feature & XILINX_DMA_FTR_DATA_WIDTH_MASK)) || - (dma_dst & - (chan->feature & XILINX_DMA_FTR_DATA_WIDTH_MASK))) { + num_periods = buf_len / period_len; - dev_err(chan->dev, - "Source or destination address not aligned when no DRE\n"); + t = xilinx_dma_alloc_transfer(chan, num_periods); + if (!t) + return NULL; - return NULL; - } + for (i = 0; i < num_periods; ++i) { + hw = t->descs[i].hw; + hw->buf_addr = buf_addr; + hw->control = period_len; + hw->control |= XILINX_DMA_BD_SOP | XILINX_DMA_BD_EOP; + buf_addr += period_len; } - do { - - /* Allocate descriptor from DMA pool */ - new = xilinx_dma_alloc_descriptor(chan); - if (!new) { - dev_err(chan->dev, - "No free memory for link descriptor\n"); - goto fail; - } - - copy = min(len, (size_t)chan->max_len); - - /* if lite build, transfer cannot cross page boundary - */ - if (chan->is_lite) - copy = min(copy, (size_t)(PAGE_MASK - - (src & PAGE_MASK))); - - if (!copy) { - dev_err(chan->dev, - "Got zero transfer length for %x\n", - (unsigned int)src); - goto fail; - } - - hw = &(new->hw); - hw->control = - (hw->control & ~XILINX_DMA_MAX_TRANS_LEN) | copy; - hw->buf_addr = src; - hw->addr_vsize = dst; - - if (!first) - first = new; - else { - prev_hw = &(prev->hw); - prev_hw->next_desc = new->async_tx.phys; - } - - new->async_tx.cookie = 0; - async_tx_ack(&new->async_tx); - - prev = new; - len -= copy; - src += copy; - dst += copy; - - /* Insert the descriptor to the list */ - list_add_tail(&new->node, &first->tx_list); - } while (len); - - /* Link the last BD with the first BD */ - hw->next_desc = first->async_tx.phys; + t->cyclic = true; - new->async_tx.flags = flags; /* client is in control of this ack */ - new->async_tx.cookie = -EBUSY; - - return &first->async_tx; - -fail: - if (!first) - return NULL; - - xilinx_dma_free_desc_list_reverse(chan, &first->tx_list); - return NULL; + return &t->async_tx; } + /** * xilinx_dma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction * @chan: DMA channel @@ -1077,22 +893,19 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_memcpy( */ static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg( struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_data_direction direction, unsigned long flags) + enum dma_transfer_direction direction, unsigned long flags) { + struct xilinx_dma_desc_hw *hw; + struct xilinx_dma_transfer *t; struct xilinx_dma_chan *chan; - struct xilinx_dma_desc_sw *first = NULL, *prev = NULL, *new = NULL; - struct xilinx_dma_desc_hw *hw = NULL, *prev_hw = NULL; - - size_t copy; - - int i; + unsigned int total_len = 0; + unsigned int num_descs = 0; struct scatterlist *sg; - size_t sg_used; dma_addr_t dma_src; + size_t num_bytes; + size_t sg_used; + unsigned int i, j; -#ifdef TEST_DMA_WITH_LOOPBACK - int total_len; -#endif if (!dchan) return NULL; @@ -1101,107 +914,48 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg( if (chan->direction != direction) return NULL; -#ifdef TEST_DMA_WITH_LOOPBACK - total_len = 0; - for_each_sg(sgl, sg, sg_len, i) { total_len += sg_dma_len(sg); + num_descs += DIV_ROUND_UP(sg_dma_len(sg), chan->max_len); } -#endif + + t = xilinx_dma_alloc_transfer(chan, num_descs); + if (!t) + return NULL; + /* * Build transactions using information in the scatter gather list */ + j = 0; for_each_sg(sgl, sg, sg_len, i) { sg_used = 0; /* Loop until the entire scatterlist entry is used */ while (sg_used < sg_dma_len(sg)) { - - /* Allocate the link descriptor from DMA pool */ - new = xilinx_dma_alloc_descriptor(chan); - if (!new) { - dev_err(chan->dev, "No free memory for " - "link descriptor\n"); - goto fail; - } - /* * Calculate the maximum number of bytes to transfer, * making sure it is less than the hw limit */ - copy = min((size_t)(sg_dma_len(sg) - sg_used), - (size_t)chan->max_len); - hw = &(new->hw); + num_bytes = min_t(size_t, sg_dma_len(sg) - sg_used, + chan->max_len); dma_src = sg_dma_address(sg) + sg_used; + hw = t->descs[j].hw; hw->buf_addr = dma_src; - - /* Fill in the descriptor */ - hw->control = copy; - - /* - * If this is not the first descriptor, chain the - * current descriptor after the previous descriptor - * - * For the first DMA_TO_DEVICE transfer, set SOP - */ - if (!first) { - first = new; - if (direction == DMA_TO_DEVICE) { - hw->control |= XILINX_DMA_BD_SOP; -#ifdef TEST_DMA_WITH_LOOPBACK - hw->app_4 = copy; -#endif - } - } else { - prev_hw = &(prev->hw); - prev_hw->next_desc = new->async_tx.phys; - } - - new->async_tx.cookie = 0; - async_tx_ack(&new->async_tx); - - prev = new; - sg_used += copy; - - /* Insert the link descriptor into the LD ring */ - list_add_tail(&new->node, &first->tx_list); + hw->control = num_bytes; + j++; } } - /* Link the last BD with the first BD */ - hw->next_desc = first->async_tx.phys; - - if (direction == DMA_TO_DEVICE) - hw->control |= XILINX_DMA_BD_EOP; - - /* All scatter gather list entries has length == 0 */ - if (!first || !new) - return NULL; - - new->async_tx.flags = flags; - new->async_tx.cookie = -EBUSY; - - /* Set EOP to the last link descriptor of new list */ - hw->control |= XILINX_DMA_BD_EOP; - - return &first->async_tx; + /* Set EOP to the last link descriptor of new list and + SOP to the first link descriptor. */ + t->descs[0].hw->control |= XILINX_DMA_BD_SOP; + t->descs[t->num_descs-1].hw->control |= XILINX_DMA_BD_EOP; -fail: - /* If first was not set, then we failed to allocate the very first - * descriptor, and we're done */ - if (!first) - return NULL; - - /* - * First is set, so all of the descriptors we allocated have been added - * to first->tx_list, INCLUDING "first" itself. Therefore we - * must traverse the list backwards freeing each descriptor in turn - */ - xilinx_dma_free_desc_list_reverse(chan, &first->tx_list); + t->async_tx.flags = flags; - return NULL; + return &t->async_tx; } /** @@ -1214,13 +968,13 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg( */ static struct dma_async_tx_descriptor *xilinx_vdma_prep_slave_sg( struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_data_direction direction, unsigned long flags) + enum dma_transfer_direction direction, unsigned long flags) { + struct xilinx_dma_desc_hw *hw; + struct xilinx_dma_transfer *t; struct xilinx_dma_chan *chan; - struct xilinx_dma_desc_sw *first = NULL, *prev = NULL, *new = NULL; - struct xilinx_dma_desc_hw *hw = NULL, *prev_hw = NULL; - unsigned int i, j; struct scatterlist *sg; + unsigned int i, j; dma_addr_t dma_src; if (!dchan) @@ -1239,6 +993,10 @@ static struct dma_async_tx_descriptor *xilinx_vdma_prep_slave_sg( return NULL; } + t = xilinx_dma_alloc_transfer(chan, sg_len); + if (!t) + return NULL; + if (!chan->has_SG) { DMA_OUT(&chan->addr_regs->hsize, chan->config.hsize); DMA_OUT(&chan->addr_regs->frmdly_stride, @@ -1250,23 +1008,9 @@ static struct dma_async_tx_descriptor *xilinx_vdma_prep_slave_sg( /* Build transactions using information in the scatter gather list */ for_each_sg(sgl, sg, sg_len, i) { - - /* Allocate the link descriptor from DMA pool */ - new = xilinx_dma_alloc_descriptor(chan); - if (!new) { - dev_err(chan->dev, "No free memory for " - "link descriptor\n"); - goto fail; - } - - /* - * Calculate the maximum number of bytes to transfer, - * making sure it is less than the hw limit - */ - hw = &(new->hw); - dma_src = sg_dma_address(sg); if (chan->has_SG) { + hw = t->descs[j * sg_len + i].hw; hw->buf_addr = dma_src; /* Fill in the descriptor */ @@ -1279,101 +1023,115 @@ static struct dma_async_tx_descriptor *xilinx_vdma_prep_slave_sg( /* Update the registers */ DMA_OUT(&(chan->addr_regs->buf_addr[j * sg_len + i]), dma_src); } - - /* If this is not the first descriptor, chain the - * current descriptor after the previous descriptor - */ - if (!first) { - first = new; - } else { - prev_hw = &(prev->hw); - prev_hw->next_desc = new->async_tx.phys; - } - - new->async_tx.cookie = 0; - async_tx_ack(&new->async_tx); - - prev = new; - - /* Insert the link descriptor into the list */ - list_add_tail(&new->node, &first->tx_list); } } - /* Link the last BD with the first BD */ - hw->next_desc = first->async_tx.phys; - - if (!first || !new) - return NULL; - - new->async_tx.flags = flags; - new->async_tx.cookie = -EBUSY; - - return &first->async_tx; - -fail: - /* If first was not set, then we failed to allocate the very first - * descriptor, and we're done */ - if (!first) - return NULL; + t->async_tx.flags = flags; - /* First is set, so all of the descriptors we allocated have been added - * to first->tx_list, INCLUDING "first" itself. Therefore we - * must traverse the list backwards freeing each descriptor in turn - */ - xilinx_dma_free_desc_list_reverse(chan, &first->tx_list); - return NULL; + return &t->async_tx; } -/* Run-time device configuration for Axi DMA and Axi CDMA */ -static int xilinx_dma_device_control(struct dma_chan *dchan, - enum dma_ctrl_cmd cmd, unsigned long arg) +static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan) { - struct xilinx_dma_chan *chan; unsigned long flags; + struct xilinx_dma_transfer *t; + struct xilinx_dma_config *config; + u32 reg; - if (!dchan) - return -EINVAL; - - chan = to_xilinx_chan(dchan); + if (chan->err) + return; - if (cmd == DMA_TERMINATE_ALL) { - /* Halt the DMA engine */ - dma_halt(chan); + spin_lock_irqsave(&chan->lock, flags); - spin_lock_irqsave(&chan->lock, flags); + if (list_empty(&chan->pending_list)) + goto out_unlock; - /* Remove and free all of the descriptors in the lists */ - xilinx_dma_free_desc_list(chan, &chan->pending_list); - xilinx_dma_free_desc_list(chan, &chan->active_list); + /* If it is SG mode and hardware is busy, cannot submit + */ + if (chan->has_SG && xilinx_dma_is_running(chan) && !xilinx_dma_is_idle(chan)) { + dev_dbg(chan->dev, "DMA controller still busy\n"); + goto out_unlock; + } - spin_unlock_irqrestore(&chan->lock, flags); - return 0; - } else if (cmd == DMA_SLAVE_CONFIG) { - /* Configure interrupt coalescing and delay counter - * Use value XILINX_DMA_NO_CHANGE to signal no change - */ - struct xilinx_dma_config *cfg = (struct xilinx_dma_config *)arg; - u32 reg = DMA_IN(&chan->regs->cr); + /* If hardware is idle, then all descriptors on the running lists are + * done, start new transfers + */ + dma_halt(chan); - if (cfg->coalesc <= XILINX_DMA_COALESCE_MAX) { - reg &= ~XILINX_DMA_XR_COALESCE_MASK; - reg |= cfg->coalesc << XILINX_DMA_COALESCE_SHIFT; + if (chan->err) + goto out_unlock; - chan->config.coalesc = cfg->coalesc; - } + t = list_first_entry(&chan->pending_list, struct xilinx_dma_transfer, head); - if (cfg->delay <= XILINX_DMA_DELAY_MAX) { - reg &= ~XILINX_DMA_XR_DELAY_MASK; - reg |= cfg->delay << XILINX_DMA_DELAY_SHIFT; - chan->config.delay = cfg->delay; + if (chan->has_SG) + DMA_OUT(&chan->regs->cdr, t->descs[0].phys); + + /* Configure the hardware using info in the config structure */ + config = &chan->config; + reg = DMA_IN(&chan->regs->cr); + + if (config->frm_cnt_en) + reg |= XILINX_VDMA_FRMCNT_EN; + else + reg &= ~XILINX_VDMA_FRMCNT_EN; + + /* With SG, start with circular mode, so that BDs can be fetched. + * In direct register mode, if not parking, enable circular mode */ + if ((chan->has_SG) || (!config->park)) + reg |= XILINX_VDMA_CIRC_EN; + + DMA_OUT(&chan->regs->cr, reg); + + if ((config->park_frm >= 0) && (config->park_frm < chan->num_frms)) { + if (config->direction == DMA_MEM_TO_DEV) { + DMA_OUT(&chan->regs->btt_ref, + config->park_frm << XILINX_VDMA_WR_REF_SHIFT); + } else { + DMA_OUT(&chan->regs->btt_ref, config->park_frm); } + } - DMA_OUT(&chan->regs->cr, reg); + /* Start the hardware + */ + dma_start(chan); - return 0; - } else - return -ENXIO; + if (chan->err) + goto out_unlock; + list_splice_tail_init(&chan->pending_list, &chan->active_list); + + /* Enable interrupts + * + * park/genlock testing does not use interrupts */ + /* + if (!chan->config.disable_intr) { + DMA_OUT(&chan->regs->cr, + DMA_IN(&chan->regs->cr) | XILINX_DMA_XR_IRQ_ALL_MASK); + }*/ + + /* Start the transfer + */ + if (chan->has_SG) + DMA_OUT(&chan->regs->tdr, t->descs[t->num_descs-1].phys); + else + DMA_OUT(&chan->addr_regs->vsize, config->vsize); + +out_unlock: + spin_unlock_irqrestore(&chan->lock, flags); +} + +static int xilinx_dma_terminate_all(struct xilinx_dma_chan *chan) +{ + /* Disable intr + */ + DMA_OUT(&chan->regs->cr, + DMA_IN(&chan->regs->cr) & ~XILINX_DMA_XR_IRQ_ALL_MASK); + + /* Halt the DMA engine */ + dma_halt(chan); + xilinx_dma_free_transfers(chan); + chan->cyclic = false; + + return 0; } /* Run-time configuration for Axi VDMA, supports: @@ -1387,28 +1145,19 @@ static int xilinx_vdma_device_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd, unsigned long arg) { struct xilinx_dma_chan *chan; - unsigned long flags; + struct xilinx_dma_config *cfg = (struct xilinx_dma_config *)arg; + u32 reg; if (!dchan) return -EINVAL; chan = to_xilinx_chan(dchan); - if (cmd == DMA_TERMINATE_ALL) { - /* Halt the DMA engine */ - dma_halt(chan); - - spin_lock_irqsave(&chan->lock, flags); - - /* Remove and free all of the descriptors in the lists */ - xilinx_dma_free_desc_list(chan, &chan->pending_list); - xilinx_dma_free_desc_list(chan, &chan->active_list); - - spin_unlock_irqrestore(&chan->lock, flags); - return 0; - } else if (cmd == DMA_SLAVE_CONFIG) { - struct xilinx_dma_config *cfg = (struct xilinx_dma_config *)arg; - u32 reg = DMA_IN(&chan->regs->cr); + switch (cmd) { + case DMA_TERMINATE_ALL: + return xilinx_dma_terminate_all(chan); + case DMA_SLAVE_CONFIG: + reg = DMA_IN(&chan->regs->cr); /* If vsize is -1, it is park-related operations */ if (cfg->vsize == -1) { @@ -1427,13 +1176,11 @@ static int xilinx_vdma_device_control(struct dma_chan *dchan, reg &= ~XILINX_DMA_XR_COALESCE_MASK; reg |= cfg->coalesc << XILINX_DMA_COALESCE_SHIFT; - chan->config.coalesc = cfg->coalesc; } if (cfg->delay <= XILINX_DMA_DELAY_MAX) { reg &= ~XILINX_DMA_XR_DELAY_MASK; reg |= cfg->delay << XILINX_DMA_DELAY_SHIFT; - chan->config.delay = cfg->delay; } DMA_OUT(&chan->regs->cr, reg); @@ -1441,15 +1188,7 @@ static int xilinx_vdma_device_control(struct dma_chan *dchan, } /* Transfer information */ - chan->config.vsize = cfg->vsize; - chan->config.hsize = cfg->hsize; - chan->config.stride = cfg->stride; - chan->config.frm_dly = cfg->frm_dly; - chan->config.park = cfg->park; - - /* genlock settings */ - chan->config.gen_lock = cfg->gen_lock; - chan->config.master = cfg->master; + chan->config = *cfg; if (cfg->gen_lock) { if (chan->genlock) { @@ -1458,50 +1197,66 @@ static int xilinx_vdma_device_control(struct dma_chan *dchan, } } - chan->config.frm_cnt_en = cfg->frm_cnt_en; - if (cfg->park) - chan->config.park_frm = cfg->park_frm; - - chan->config.coalesc = cfg->coalesc; - chan->config.delay = cfg->delay; - if (cfg->coalesc <= XILINX_DMA_COALESCE_MAX) { + if (cfg->coalesc <= XILINX_DMA_COALESCE_MAX) reg |= cfg->coalesc << XILINX_DMA_COALESCE_SHIFT; - chan->config.coalesc = cfg->coalesc; - } - if (cfg->delay <= XILINX_DMA_DELAY_MAX) { + if (cfg->delay <= XILINX_DMA_DELAY_MAX) reg |= cfg->delay << XILINX_DMA_DELAY_SHIFT; - chan->config.delay = cfg->delay; - } - - chan->config.disable_intr = cfg->disable_intr; DMA_OUT(&chan->regs->cr, reg); - return 0; - } else + break; + default: return -ENXIO; + } + + return 0; } -/* Logarithm function to compute alignment shift - * - * Only deals with value less than 4096. - */ -static int my_log(int value) +/* Run-time device configuration for Axi DMA and Axi CDMA */ +static int xilinx_dma_device_control(struct dma_chan *dchan, + enum dma_ctrl_cmd cmd, unsigned long arg) { - int i = 0; - while ((1 << i) < value) { - i++; + struct xilinx_dma_chan *chan; + struct xilinx_dma_config *cfg = (struct xilinx_dma_config *)arg; + u32 reg; - if (i >= 12) - return 0; + if (!dchan) + return -EINVAL; + + chan = to_xilinx_chan(dchan); + + switch (cmd) { + case DMA_TERMINATE_ALL: + return xilinx_dma_terminate_all(chan); + case DMA_SLAVE_CONFIG: + /* Configure interrupt coalescing and delay counter + * Use value XILINX_DMA_NO_CHANGE to signal no change + */ + reg = DMA_IN(&chan->regs->cr); + + chan->config = *cfg; + + if (cfg->coalesc <= XILINX_DMA_COALESCE_MAX) { + reg &= ~XILINX_DMA_XR_COALESCE_MASK; + reg |= cfg->coalesc << XILINX_DMA_COALESCE_SHIFT; + } + + if (cfg->delay <= XILINX_DMA_DELAY_MAX) { + reg &= ~XILINX_DMA_XR_DELAY_MASK; + reg |= cfg->delay << XILINX_DMA_DELAY_SHIFT; + } + + DMA_OUT(&chan->regs->cr, reg); + + break; + default: + return -ENXIO; } - return i; + return 0; } -#ifdef CONFIG_OF - static void xilinx_dma_chan_remove(struct xilinx_dma_chan *chan) { irq_dispose_mapping(chan->irq); @@ -1519,43 +1274,32 @@ static int __devinit xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, struct device_node *node, u32 feature) { struct xilinx_dma_chan *chan; - int err; - int *value; u32 width = 0; + int ret; /* alloc channel */ chan = kzalloc(sizeof(*chan), GFP_KERNEL); if (!chan) { dev_err(xdev->dev, "no free memory for DMA channels!\n"); - err = -ENOMEM; + ret = -ENOMEM; goto out_return; } + spin_lock_init(&chan->lock); + INIT_LIST_HEAD(&chan->pending_list); + INIT_LIST_HEAD(&chan->active_list); + chan->feature = feature; - chan->is_lite = 0; chan->has_DRE = 0; chan->has_SG = 0; chan->max_len = XILINX_DMA_MAX_TRANS_LEN; - value = (int *)of_get_property(node, "xlnx,include-dre", - NULL); - if (value) { - if (be32_to_cpup(value) == 1) - chan->has_DRE = 1; - } + of_property_read_u32(node, "xlnx,include-dre", &chan->has_DRE); + of_property_read_u32(node, "xlnx,genlock-mode", &chan->genlock); + of_property_read_u32(node, "xlnx,datawidth", &width); - value = (int *)of_get_property(node, "xlnx,genlock-mode", - NULL); - if (value) { - if (be32_to_cpup(value) == 1) - chan->genlock = 1; - } - - value = (int *)of_get_property(node, - "xlnx,datawidth", - NULL); - if (value) { - width = be32_to_cpup(value) >> 3; /* convert bits to bytes */ + if (width > 0) { + width >>= 3; /* convert bits to bytes */ /* If data width is greater than 8 bytes, DRE is not in hw */ if (width > 8) @@ -1564,58 +1308,22 @@ static int __devinit xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, chan->feature |= width - 1; } - if (feature & XILINX_DMA_IP_CDMA) { - chan->direction = DMA_BIDIRECTIONAL; - chan->start_transfer = xilinx_cdma_start_transfer; - - chan->has_SG = (xdev->feature & XILINX_DMA_FTR_HAS_SG) >> + chan->has_SG = (xdev->feature & XILINX_DMA_FTR_HAS_SG) >> XILINX_DMA_FTR_HAS_SG_SHIFT; - value = (int *)of_get_property(node, - "xlnx,lite-mode", NULL); - if (value) { - if (be32_to_cpup(value) == 1) { - chan->is_lite = 1; - value = (int *)of_get_property(node, - "xlnx,max-burst-len", NULL); - if (value) { - if (!width) { - dev_err(xdev->dev, - "Lite mode without data width property\n"); - goto out_free_chan; - } - chan->max_len = width * - be32_to_cpup(value); - } - } - } - } - if (feature & XILINX_DMA_IP_DMA) { - chan->has_SG = (xdev->feature & XILINX_DMA_FTR_HAS_SG) >> - XILINX_DMA_FTR_HAS_SG_SHIFT; - chan->start_transfer = xilinx_dma_start_transfer; - if (of_device_is_compatible(node, - "xlnx,axi-dma-mm2s-channel")) - chan->direction = DMA_TO_DEVICE; - - if (of_device_is_compatible(node, - "xlnx,axi-dma-s2mm-channel")) - chan->direction = DMA_FROM_DEVICE; - - } - - if (feature & XILINX_DMA_IP_VDMA) { + if (of_device_is_compatible(node, "xlnx,axi-dma-mm2s-channel")) + chan->direction = DMA_MEM_TO_DEV; + else if (of_device_is_compatible(node, "xlnx,axi-dma-s2mm-channel")) + chan->direction = DMA_DEV_TO_MEM; + } else if (feature & XILINX_DMA_IP_VDMA) { chan->start_transfer = xilinx_vdma_start_transfer; - chan->has_SG = (xdev->feature & XILINX_DMA_FTR_HAS_SG) >> - XILINX_DMA_FTR_HAS_SG_SHIFT; - if (of_device_is_compatible(node, "xlnx,axi-vdma-mm2s-channel")) { - chan->direction = DMA_TO_DEVICE; + chan->direction = DMA_MEM_TO_DEV; if (!chan->has_SG) { chan->addr_regs = (struct vdma_addr_regs *) ((u32)xdev->regs + @@ -1625,7 +1333,7 @@ static int __devinit xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, if (of_device_is_compatible(node, "xlnx,axi-vdma-s2mm-channel")) { - chan->direction = DMA_FROM_DEVICE; + chan->direction = DMA_DEV_TO_MEM; if (!chan->has_SG) { chan->addr_regs = (struct vdma_addr_regs *) ((u32)xdev->regs + @@ -1635,134 +1343,110 @@ static int __devinit xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, } } - chan->regs = (struct xdma_regs *)xdev->regs; - chan->id = 0; - - if (chan->direction == DMA_FROM_DEVICE) { + if (chan->direction == DMA_MEM_TO_DEV) { + chan->regs = (struct xdma_regs *)xdev->regs; + chan->id = 0; + } else { chan->regs = (struct xdma_regs *)((u32)xdev->regs + XILINX_DMA_RX_CHANNEL_OFFSET); chan->id = 1; } + chan->debugfs_regset.regs = xilinx_dma_debugfs_regs; + chan->debugfs_regset.nregs = ARRAY_SIZE(xilinx_dma_debugfs_regs); + chan->debugfs_regset.base = (void __iomem *)chan->regs; + /* Used by dmatest channel matching in slave transfers * Can change it to be a structure to have more matching information */ - chan->private = (chan->direction & 0xFF) | + chan->common.private = (chan->direction & 0xFF) | (chan->feature & XILINX_DMA_IP_MASK); - chan->common.private = (void *)&(chan->private); if (!chan->has_DRE) - xdev->common.copy_align = my_log(width); + xdev->common.copy_align = ilog2(width); chan->dev = xdev->dev; xdev->chan[chan->id] = chan; tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan); - /* Initialize the channel */ - if (dma_init(chan)) { - dev_err(xdev->dev, "Reset channel failed\n"); - goto out_free_chan; - } - - - spin_lock_init(&chan->lock); - INIT_LIST_HEAD(&chan->pending_list); - INIT_LIST_HEAD(&chan->active_list); - chan->common.device = &xdev->common; /* find the IRQ line, if it exists in the device tree */ chan->irq = irq_of_parse_and_map(node, 0); - err = request_irq(chan->irq, dma_intr_handler, IRQF_SHARED, + ret = request_irq(chan->irq, dma_intr_handler, IRQF_SHARED, "xilinx-dma-controller", chan); - if (err) { - dev_err(xdev->dev, "unable to request IRQ\n"); + if (ret) { + dev_err(xdev->dev, "unable to request IRQ %d\n", ret); goto out_free_irq; } /* Add the channel to DMA device channel list */ list_add_tail(&chan->common.device_node, &xdev->common.channels); - xdev->common.chancnt++; - return 0; + /* Initialize the channel */ + if (xilinx_dma_reset(chan)) { + dev_err(xdev->dev, "Reset channel failed\n"); + goto out_free_chan; + } + return 0; out_free_irq: irq_dispose_mapping(chan->irq); out_free_chan: kfree(chan); out_return: - return err; + return ret; } -static int __devinit xilinx_dma_of_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit xilinx_dma_of_probe(struct platform_device *pdev) { struct xilinx_dma_device *xdev; struct device_node *child, *node; - int err; + struct xilinx_dma_chan *chan; + u32 num_frames = 0; + u32 include_sg = 0; + unsigned int i; int *value; - int num_frames = 0; - - dev_info(&op->dev, "Probing xilinx axi dma engines\n"); + int ret; - xdev = kzalloc(sizeof(struct xilinx_dma_device), GFP_KERNEL); + xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL); if (!xdev) { - dev_err(&op->dev, "Not enough memory for device\n"); - err = -ENOMEM; - goto out_return; + dev_err(&pdev->dev, "Not enough memory for device\n"); + return -ENOMEM; } - xdev->dev = &(op->dev); + xdev->dev = &pdev->dev; INIT_LIST_HEAD(&xdev->common.channels); - node = op->dev.of_node; + node = pdev->dev.of_node; xdev->feature = 0; /* iomap registers */ xdev->regs = of_iomap(node, 0); if (!xdev->regs) { - dev_err(&op->dev, "unable to iomap registers\n"); - err = -ENOMEM; - goto out_free_xdev; - } - - /* Axi CDMA only does memcpy - */ - if (of_device_is_compatible(node, "xlnx,axi-cdma")) { - xdev->feature |= XILINX_DMA_IP_CDMA; - - value = (int *)of_get_property(node, "xlnx,include-sg", - NULL); - if (value) { - if (be32_to_cpup(value) == 1) - xdev->feature |= XILINX_DMA_FTR_HAS_SG; - } - - dma_cap_set(DMA_MEMCPY, xdev->common.cap_mask); - xdev->common.device_prep_dma_memcpy = xilinx_dma_prep_memcpy; - xdev->common.device_control = xilinx_dma_device_control; - xdev->common.device_issue_pending = xilinx_cdma_issue_pending; + dev_err(&pdev->dev, "unable to iomap registers\n"); + return -ENXIO; } /* Axi DMA and VDMA only do slave transfers */ if (of_device_is_compatible(node, "xlnx,axi-dma")) { - xdev->feature |= XILINX_DMA_IP_DMA; value = (int *)of_get_property(node, "xlnx,sg-include-stscntrl-strm", NULL); if (value) { - if (be32_to_cpup(value) == 1) { - xdev->feature |= (XILINX_DMA_FTR_STSCNTRL_STRM | - XILINX_DMA_FTR_HAS_SG); - } + xdev->feature |= XILINX_DMA_FTR_HAS_SG; + if (be32_to_cpup(value) == 1) + xdev->feature = XILINX_DMA_FTR_STSCNTRL_STRM; } dma_cap_set(DMA_SLAVE, xdev->common.cap_mask); dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask); + dma_cap_set(DMA_CYCLIC, xdev->common.cap_mask); xdev->common.device_prep_slave_sg = xilinx_dma_prep_slave_sg; + xdev->common.device_prep_dma_cyclic = xilinx_dma_prep_dma_cyclic; xdev->common.device_control = xilinx_dma_device_control; xdev->common.device_issue_pending = xilinx_dma_issue_pending; } @@ -1770,23 +1454,17 @@ static int __devinit xilinx_dma_of_probe(struct platform_device *op, if (of_device_is_compatible(node, "xlnx,axi-vdma")) { xdev->feature |= XILINX_DMA_IP_VDMA; - value = (int *)of_get_property(node, "xlnx,include-sg", - NULL); - if (value) { - if (be32_to_cpup(value) == 1) - xdev->feature |= XILINX_DMA_FTR_HAS_SG; - } + of_property_read_u32(node, "xlnx,include-sg", &include_sg); + if (include_sg) + xdev->feature |= XILINX_DMA_FTR_HAS_SG; - value = (int *)of_get_property(node, "xlnx,num-fstores", - NULL); - if (value) - num_frames = be32_to_cpup(value); + of_property_read_u32(node, "xlnx,num-fstores", &num_frames); dma_cap_set(DMA_SLAVE, xdev->common.cap_mask); dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask); xdev->common.device_prep_slave_sg = xilinx_vdma_prep_slave_sg; xdev->common.device_control = xilinx_vdma_device_control; - xdev->common.device_issue_pending = xilinx_vdma_issue_pending; + xdev->common.device_issue_pending = xilinx_dma_issue_pending; } xdev->common.device_alloc_chan_resources = @@ -1794,40 +1472,50 @@ static int __devinit xilinx_dma_of_probe(struct platform_device *op, xdev->common.device_free_chan_resources = xilinx_dma_free_chan_resources; xdev->common.device_tx_status = xilinx_tx_status; - xdev->common.dev = &op->dev; - - dev_set_drvdata(&op->dev, xdev); + xdev->common.dev = &pdev->dev; for_each_child_of_node(node, child) { - xilinx_dma_chan_probe(xdev, child, xdev->feature); + ret = xilinx_dma_chan_probe(xdev, child, xdev->feature); + if (ret) + goto err_free_chan; } if (xdev->feature & XILINX_DMA_IP_VDMA) { - int i; - for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++) { if (xdev->chan[i]) xdev->chan[i]->num_frms = num_frames; } } - dma_async_device_register(&xdev->common); + ret = dma_async_device_register(&xdev->common); + if (ret) + goto err_free_chan; + + for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++) { + if (xdev->chan[i]) { + chan = xdev->chan[i]; + debugfs_create_regset32(dev_name(&chan->common.dev->device), S_IRUGO, NULL, &chan->debugfs_regset); + } + } + + platform_set_drvdata(pdev, xdev); return 0; -out_free_xdev: - kfree(xdev); +err_free_chan: + for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++) { + if (xdev->chan[i]) + xilinx_dma_chan_remove(xdev->chan[i]); + } -out_return: - return err; + return ret; } -static int xilinx_dma_of_remove(struct platform_device *op) +static int __devexit xilinx_dma_of_remove(struct platform_device *pdev) { - struct xilinx_dma_device *xdev; + struct xilinx_dma_device *xdev = platform_get_drvdata(pdev); int i; - xdev = dev_get_drvdata(&op->dev); dma_async_device_unregister(&xdev->common); for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++) { @@ -1836,16 +1524,13 @@ static int xilinx_dma_of_remove(struct platform_device *op) } iounmap(xdev->regs); - dev_set_drvdata(&op->dev, NULL); - kfree(xdev); return 0; } static const struct of_device_id xilinx_dma_of_ids[] = { - { .compatible = "xlnx,axi-cdma",}, - { .compatible = "xlnx,axi-dma",}, - { .compatible = "xlnx,axi-vdma",}, + { .compatible = "xlnx,axi-dma" }, + { .compatible = "xlnx,axi-vdma" }, {} }; @@ -1856,410 +1541,20 @@ static struct platform_driver xilinx_dma_of_driver = { .of_match_table = xilinx_dma_of_ids, }, .probe = xilinx_dma_of_probe, - .remove = xilinx_dma_of_remove, + .remove = __devexit_p(xilinx_dma_of_remove), }; -/*----------------------------------------------------------------------------*/ -/* Module Init / Exit */ -/*----------------------------------------------------------------------------*/ - -static __init int xilinx_dma_init(void) -{ - int ret; - - pr_info("Xilinx DMA driver\n"); - - ret = platform_driver_register(&xilinx_dma_of_driver); - if (ret) - pr_err("xilinx_dma: failed to register platform driver\n"); - - return ret; -} - -static void __exit xilinx_dma_exit(void) +static int __init xilinx_dma_init(void) { - platform_driver_unregister(&xilinx_dma_of_driver); + return platform_driver_register(&xilinx_dma_of_driver); } - subsys_initcall(xilinx_dma_init); -module_exit(xilinx_dma_exit); - -#else - -/**************************************************/ -/* Platform bus to support ARM before device tree */ -/**************************************************/ - -/* The following probe and chan_probe functions were - copied from the OF section above, then modified - to use platform data. -*/ - -static void xilinx_dma_chan_remove(struct xilinx_dma_chan *chan) -{ - free_irq(chan->irq, chan); - list_del(&chan->common.device_node); - kfree(chan); -} - -/* - * Probing channels - * - * . Get channel features from the device tree entry - * . Initialize special channel handling routines - */ -static int __devinit xilinx_dma_chan_probe(struct platform_device *pdev, - struct xilinx_dma_device *xdev, - struct dma_channel_config *channel_config, - int channel_num, u32 feature) -{ - struct xilinx_dma_chan *chan; - int err; - u32 width = 0; - struct resource *res; - - /* alloc channel */ - - - chan = kzalloc(sizeof(*chan), GFP_KERNEL); - if (!chan) { - dev_err(xdev->dev, "no free memory for DMA channels!\n"); - err = -ENOMEM; - goto out_return; - } - - chan->feature = feature; - chan->is_lite = 0; - chan->has_DRE = 0; - chan->has_SG = 0; - chan->max_len = XILINX_DMA_MAX_TRANS_LEN; - - if (channel_config->include_dre) - chan->has_DRE = 1; - - if (channel_config->genlock_mode) - chan->genlock = 1; - - width = channel_config->datawidth >> 3; - chan->feature |= width - 1; - - if (feature & XILINX_DMA_IP_CDMA) { - - chan->direction = DMA_BIDIRECTIONAL; - chan->start_transfer = xilinx_cdma_start_transfer; - - chan->has_SG = (xdev->feature & XILINX_DMA_FTR_HAS_SG) >> - XILINX_DMA_FTR_HAS_SG_SHIFT; - - if (channel_config->lite_mode) { - chan->is_lite = 1; - chan->max_len = width * channel_config->max_burst_len; - } - } - - if (feature & XILINX_DMA_IP_DMA) { - chan->has_SG = 1; - chan->start_transfer = xilinx_dma_start_transfer; - - if (!strcmp(channel_config->type, "axi-dma-mm2s-channel")) - chan->direction = DMA_TO_DEVICE; - - if (!strcmp(channel_config->type, "axi-dma-s2mm-channel")) - chan->direction = DMA_FROM_DEVICE; - } - - if (feature & XILINX_DMA_IP_VDMA) { - - chan->start_transfer = xilinx_vdma_start_transfer; - - chan->has_SG = (xdev->feature & XILINX_DMA_FTR_HAS_SG) >> - XILINX_DMA_FTR_HAS_SG_SHIFT; - - if (!strcmp(channel_config->type, "axi-vdma-mm2s-channel")) { - - printk(KERN_INFO, "axi-vdma-mm2s-channel found\n"); - - chan->direction = DMA_TO_DEVICE; - if (!chan->has_SG) { - chan->addr_regs = (struct vdma_addr_regs *) - ((u32)xdev->regs + - XILINX_VDMA_DIRECT_REG_OFFSET); - } - } - - if (!strcmp(channel_config->type, "axi-vdma-s2mm-channel")) { - - printk(KERN_INFO, "axi-vdma-s2mm-channel found\n"); - - chan->direction = DMA_FROM_DEVICE; - if (!chan->has_SG) { - chan->addr_regs = (struct vdma_addr_regs *) - ((u32)xdev->regs + - XILINX_VDMA_DIRECT_REG_OFFSET + - XILINX_VDMA_CHAN_DIRECT_REG_SIZE); - } - } - } - - chan->regs = (struct xdma_regs *)xdev->regs; - chan->id = 0; - - if (chan->direction == DMA_FROM_DEVICE) { - chan->regs = (struct xdma_regs *)((u32)xdev->regs + - XILINX_DMA_RX_CHANNEL_OFFSET); - chan->id = 1; - } - - /* Used by dmatest channel matching in slave transfers - * Can change it to be a structure to have more matching information - */ - chan->private = (chan->direction & 0xFF) | - (chan->feature & XILINX_DMA_IP_MASK); - chan->common.private = (void *)&(chan->private); - - if (!chan->has_DRE) - xdev->common.copy_align = my_log(width); - - chan->dev = xdev->dev; - xdev->chan[chan->id] = chan; - - tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan); - - /* Initialize the channel */ - if (dma_init(chan)) { - dev_err(xdev->dev, "Reset channel failed\n"); - goto out_free_chan; - } - - - spin_lock_init(&chan->lock); - INIT_LIST_HEAD(&chan->pending_list); - INIT_LIST_HEAD(&chan->active_list); - - chan->common.device = &xdev->common; - - /* setup the interrupt for the channel */ - - res = platform_get_resource(pdev, IORESOURCE_IRQ, channel_num); - chan->irq = res->start; - - err = request_irq(chan->irq, dma_intr_handler, IRQF_SHARED, - "xilinx-dma-controller", chan); - if (err) { - dev_err(xdev->dev, "unable to request IRQ\n"); - goto out_free_irq; - } else - dev_info(&pdev->dev, "using irq %d\n", chan->irq); - - /* Add the channel to DMA device channel list */ - list_add_tail(&chan->common.device_node, &xdev->common.channels); - xdev->common.chancnt++; - - return 0; - -out_free_irq: - free_irq(chan->irq, chan); -out_free_chan: - kfree(chan); -out_return: - return err; -} - -static int __devinit xilinx_dma_probe(struct platform_device *pdev) -{ - struct xilinx_dma_device *xdev; - int err; - int num_frames = 0; - struct resource *res; - struct device *dev = &pdev->dev; - struct dma_device_config *dma_config; - int channel; - - dev_info(&pdev->dev, "Probing xilinx axi dma engines\n"); - - xdev = kzalloc(sizeof(struct xilinx_dma_device), GFP_KERNEL); - if (!xdev) { - dev_err(&pdev->dev, "Not enough memory for device\n"); - err = -ENOMEM; - goto out_return; - } - - xdev->dev = &(pdev->dev); - INIT_LIST_HEAD(&xdev->common.channels); - - xdev->feature = 0; - - /* iomap registers */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - printk(KERN_ERR "get_resource for MEM resource for dev %d " - "failed\n", pdev->id); - err = -ENOMEM; - goto out_return; - } else { - dev_info(&pdev->dev, "device %d actual base is %x\n", - pdev->id, (unsigned int)res->start); - } - if (!request_mem_region(res->start, 0x1000, "xilinx_axidma")) { - printk(KERN_ERR "memory request failue for base %x\n", - (unsigned int)res->start); - err = -ENOMEM; - goto out_return; - } - - xdev->regs = ioremap(res->start, 0x1000); - pr_info("dma base remapped: %lx\n", (unsigned long)xdev->regs); - if (!xdev->regs) { - dev_err(&pdev->dev, "unable to iomap registers\n"); - err = -ENOMEM; - goto out_free_xdev; - } - - dma_config = (struct dma_device_config *)dev->platform_data; - - /* Axi CDMA only does memcpy - */ - if (!strcmp(dma_config->type, "axi-cdma")) { - - pr_info("found an axi-cdma configuration\n"); - xdev->feature |= XILINX_DMA_IP_CDMA; - - if (dma_config->include_sg) - xdev->feature |= XILINX_DMA_FTR_HAS_SG; - - dma_cap_set(DMA_MEMCPY, xdev->common.cap_mask); - xdev->common.device_prep_dma_memcpy = xilinx_dma_prep_memcpy; - xdev->common.device_control = xilinx_dma_device_control; - xdev->common.device_issue_pending = xilinx_cdma_issue_pending; - } - - /* Axi DMA and VDMA only do slave transfers - */ - if (!strcmp(dma_config->type, "axi-dma")) { - - pr_info("found an axi-dma configuration\n"); - - xdev->feature |= XILINX_DMA_IP_DMA; - if (dma_config->sg_include_stscntrl_strm) - xdev->feature |= XILINX_DMA_FTR_STSCNTRL_STRM; - - dma_cap_set(DMA_SLAVE, xdev->common.cap_mask); - dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask); - xdev->common.device_prep_slave_sg = xilinx_dma_prep_slave_sg; - xdev->common.device_control = xilinx_dma_device_control; - xdev->common.device_issue_pending = xilinx_dma_issue_pending; - } - - if (!strcmp(dma_config->type, "axi-vdma")) { - - pr_info("found an axi-vdma configuration\n"); - - xdev->feature |= XILINX_DMA_IP_VDMA; - - if (dma_config->include_sg) - xdev->feature |= XILINX_DMA_FTR_HAS_SG; - - num_frames = dma_config->num_fstores; - - dma_cap_set(DMA_SLAVE, xdev->common.cap_mask); - dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask); - xdev->common.device_prep_slave_sg = xilinx_vdma_prep_slave_sg; - xdev->common.device_control = xilinx_vdma_device_control; - xdev->common.device_issue_pending = xilinx_vdma_issue_pending; - } - - xdev->common.device_alloc_chan_resources = - xilinx_dma_alloc_chan_resources; - xdev->common.device_free_chan_resources = - xilinx_dma_free_chan_resources; - xdev->common.device_tx_status = xilinx_tx_status; - xdev->common.dev = &pdev->dev; - - dev_set_drvdata(&pdev->dev, xdev); - - for (channel = 0; channel < dma_config->channel_count; channel++) - xilinx_dma_chan_probe(pdev, xdev, - &dma_config->channel_config[channel], - channel, xdev->feature); - - if (xdev->feature & XILINX_DMA_IP_VDMA) { - int i; - - for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++) { - if (xdev->chan[i]) - xdev->chan[i]->num_frms = num_frames; - } - } - - dma_async_device_register(&xdev->common); - - return 0; - -out_free_xdev: - kfree(xdev); - -out_return: - return err; -} - - -static int __exit xilinx_dma_remove(struct platform_device *pdev) -{ - struct xilinx_dma_device *xdev = platform_get_drvdata(pdev); - int i; -#if 1 - dma_async_device_unregister(&xdev->common); -#endif - for (i = 0; i < 2; i++) { - if (xdev->chan[i]) - xilinx_dma_chan_remove(xdev->chan[i]); - } - - iounmap(xdev->regs); - dev_set_drvdata(&pdev->dev, NULL); - kfree(xdev); - - return 0; -} - -static void xilinx_dma_shutdown(struct platform_device *pdev) -{ - struct xilinx_dma_device *xdev = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < 2; i++) - dma_halt(xdev->chan[i]); -} - -static struct platform_driver xilinx_dma_driver = { - .probe = xilinx_dma_probe, - .remove = __exit_p(xilinx_dma_remove), - .shutdown = xilinx_dma_shutdown, - .driver = { - .owner = THIS_MODULE, - .name = "xilinx-axidma", - }, -}; - -/*----------------------------------------------------------------------------*/ -/* Module Init / Exit */ -/*----------------------------------------------------------------------------*/ - -static __init int xilinx_dma_init(void) -{ - int status; - status = platform_driver_register(&xilinx_dma_driver); - return status; -} -module_init(xilinx_dma_init); static void __exit xilinx_dma_exit(void) { - platform_driver_unregister(&xilinx_dma_driver); + platform_driver_unregister(&xilinx_dma_of_driver); } - module_exit(xilinx_dma_exit); -#endif -MODULE_DESCRIPTION("Xilinx DMA/CDMA/VDMA driver"); +MODULE_DESCRIPTION("Xilinx DMA/VDMA driver"); MODULE_LICENSE("GPL"); From 2f2cb69dd3d735198523339b98a19e7b7e024dbb Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Mar 2012 13:47:18 +0100 Subject: [PATCH 006/261] Setup FPGA clocks This is a hack! --- arch/arm/mach-zynq/slcr.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index 1274c03c2818e..3416a4976c72a 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -31,6 +31,7 @@ #define XSLCR_LOCK 0x4 /* SLCR lock register */ #define XSLCR_UNLOCK 0x8 /* SCLR unlock register */ +#define XSLCR_IO_PLL_CTRL_OFFSET 0x108 /* AMBA Peripheral Clk Control */ #define XSLCR_APER_CLK_CTRL_OFFSET 0x12C /* AMBA Peripheral Clk Control */ #define XSLCR_USB0_CLK_CTRL_OFFSET 0x130 /* USB 0 ULPI Clock Control */ #define XSLCR_USB1_CLK_CTRL_OFFSET 0x134 /* USB 1 ULPI Clock Control */ @@ -44,6 +45,10 @@ #define XSLCR_UART_CLK_CTRL_OFFSET 0x154 /* UART Reference Clock Control */ #define XSLCR_SPI_CLK_CTRL_OFFSET 0x158 /* SPI Reference Clock Control */ #define XSLCR_CAN_CLK_CTRL_OFFSET 0x15C /* CAN Reference Clock Control */ +#define XSLCR_FPGA0_CLK_CTRL_OFFSET 0x170 /* FPGA0 Reference Clock Control */ +#define XSLCR_FPGA1_CLK_CTRL_OFFSET 0x180 /* FPGA1 Reference Clock Control */ +#define XSLCR_FPGA2_CLK_CTRL_OFFSET 0x190 /* FPGA2 Reference Clock Control */ +#define XSLCR_FPGA3_CLK_CTRL_OFFSET 0x1a0 /* FPGA3 Reference Clock Control */ #define XSLCR_PSS_RST_CTRL_OFFSET 0x200 /* PSS Software Reset Control */ #define XSLCR_DDR_RST_CTRL_OFFSET 0x204 /* DDR Software Reset Control */ #define XSLCR_AMBA_RST_CTRL_OFFSET 0x208 /* AMBA Software Reset Control */ @@ -2449,6 +2454,11 @@ static int __init xslcr_probe(struct platform_device *pdev) /* unlock the SLCR so that registers can be changed */ xslcr_writereg(slcr->regs + XSLCR_UNLOCK, 0xDF0D); + xslcr_writereg(slcr->regs + XSLCR_FPGA0_CLK_CTRL_OFFSET, 0x100a00); + xslcr_writereg(slcr->regs + XSLCR_FPGA1_CLK_CTRL_OFFSET, 0x100500); + xslcr_writereg(slcr->regs + XSLCR_FPGA2_CLK_CTRL_OFFSET, 0x100700); + xslcr_writereg(slcr->regs + XSLCR_FPGA3_CLK_CTRL_OFFSET, 0x102900); + dev_info(&pdev->dev, "at 0x%08X mapped to 0x%08X\n", res.start, (u32 __force)slcr->regs); platform_set_drvdata(pdev, slcr); From b08df5a1f67fe13762d66da2f7d5a51b8b1b78fd Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 10 Apr 2012 10:02:17 +0200 Subject: [PATCH 007/261] Add function to set fpga3 clock rate This is sort of a hack --- arch/arm/mach-zynq/slcr.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index 3416a4976c72a..c41e047cde11c 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -2481,6 +2481,13 @@ static int __init xslcr_probe(struct platform_device *pdev) return ret; } +void xslcr_set_fpga3_clock(unsigned int rate) +{ + unsigned int div = DIV_ROUND_CLOSEST(1000000000, rate); + + xslcr_writereg(slcr->regs + XSLCR_FPGA2_CLK_CTRL_OFFSET, 0x100000 | (div << 8)); +} + /** * xslcr_remove - Remove call for the device. * From 2d7e1c15003d0a1c4016ee0a66a0acb4c7f9f650 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 10 Feb 2012 13:44:11 +0100 Subject: [PATCH 008/261] drm: Fix EDID color fromat parsing The code should obviously check the EDID feature field for EDID feature flags and not the color_formats field of the drm_display_info struct. Also update the color_formats field with new modes instead of overwriting the current mode. Signed-off-by: Lars-Peter Clausen --- drivers/gpu/drm/drm_edid.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index ece03fc2d3864..1618c1f826201 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1695,10 +1695,10 @@ static void drm_add_display_info(struct edid *edid, } info->color_formats = DRM_COLOR_FORMAT_RGB444; - if (info->color_formats & DRM_EDID_FEATURE_RGB_YCRCB444) - info->color_formats = DRM_COLOR_FORMAT_YCRCB444; - if (info->color_formats & DRM_EDID_FEATURE_RGB_YCRCB422) - info->color_formats = DRM_COLOR_FORMAT_YCRCB422; + if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444) + info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; + if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422) + info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; /* Get data from CEA blocks if present */ edid_ext = drm_find_cea_extension(edid); From b4ee464df8232d980a49bf2b33f0e85e84c61fba Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 10 Feb 2012 14:31:18 +0100 Subject: [PATCH 009/261] drm: Parse color format information in CEA blocks The CEA extension block has a field which describes which YCbCr modes are supported by the device, use it to fill the drm_display_info color_formats fields. Also the existence of a CEA extension block is used as indication that the device supports RGB. Signed-off-by: Lars-Peter Clausen --- drivers/gpu/drm/drm_edid.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 1618c1f826201..b1804a2c0f361 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1308,6 +1308,8 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, #define VENDOR_BLOCK 0x03 #define SPEAKER_BLOCK 0x04 #define EDID_BASIC_AUDIO (1 << 6) +#define EDID_CEA_YCRCB444 (1 << 5) +#define EDID_CEA_YCRCB422 (1 << 4) /** * Search EDID for CEA extension block. @@ -1662,13 +1664,29 @@ static void drm_add_display_info(struct edid *edid, info->bpc = 0; info->color_formats = 0; - /* Only defined for 1.4 with digital displays */ - if (edid->revision < 4) + if (edid->revision < 3) return; if (!(edid->input & DRM_EDID_INPUT_DIGITAL)) return; + /* Get data from CEA blocks if present */ + edid_ext = drm_find_cea_extension(edid); + if (edid_ext) { + info->cea_rev = edid_ext[1]; + + /* The existence of a CEA block should imply RGB support */ + info->color_formats = DRM_COLOR_FORMAT_RGB444; + if (edid_ext[3] & EDID_CEA_YCRCB444) + info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; + if (edid_ext[3] & EDID_CEA_YCRCB422) + info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; + } + + /* Only defined for 1.4 with digital displays */ + if (edid->revision < 4) + return; + switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) { case DRM_EDID_DIGITAL_DEPTH_6: info->bpc = 6; @@ -1694,18 +1712,11 @@ static void drm_add_display_info(struct edid *edid, break; } - info->color_formats = DRM_COLOR_FORMAT_RGB444; + info->color_formats |= DRM_COLOR_FORMAT_RGB444; if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444) info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422) info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; - - /* Get data from CEA blocks if present */ - edid_ext = drm_find_cea_extension(edid); - if (!edid_ext) - return; - - info->cea_rev = edid_ext[1]; } /** From d3cb5427fe4d817d2a2c55a535d5e7a52863d146 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 16 Feb 2012 17:12:46 +0100 Subject: [PATCH 010/261] DMA: Fix dmaengine_prep_slave_single Signed-off-by: Michael Hennerich --- include/linux/dmaengine.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 9a2f5dd0e593c..56bbc4d5b2c3e 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -622,11 +622,15 @@ static inline int dmaengine_slave_config(struct dma_chan *chan, } static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( - struct dma_chan *chan, void *buf, size_t len, + struct dma_chan *chan, dma_addr_t buf, size_t len, enum dma_transfer_direction dir, unsigned long flags) { struct scatterlist sg; - sg_init_one(&sg, buf, len); + sg_init_table(&sg, 1); + sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)), + len, offset_in_page(buf)); + sg_dma_address(&sg) = buf; + sg_dma_len(&sg) = len; return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags); } From 1dd3a9c8b6404e18283a79e46f59a54360ae89da Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 5 Mar 2012 16:30:57 +0100 Subject: [PATCH 011/261] DRM: Add adv7511 encoder driver This patch adds a driver for the Analog Devices adv7511. The adv7511 is a standalone HDMI transmitter chip. It features a HDMI output interface on one end and video and audio input interfaces on the other. Signed-off-by: Lars-Peter Clausen --- drivers/gpu/drm/i2c/Makefile | 3 + drivers/gpu/drm/i2c/adv7511.h | 266 +++++++++++ drivers/gpu/drm/i2c/adv7511_audio.c | 318 +++++++++++++ drivers/gpu/drm/i2c/adv7511_core.c | 672 ++++++++++++++++++++++++++++ 4 files changed, 1259 insertions(+) create mode 100644 drivers/gpu/drm/i2c/adv7511.h create mode 100644 drivers/gpu/drm/i2c/adv7511_audio.c create mode 100644 drivers/gpu/drm/i2c/adv7511_core.c diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile index 92862563e7ee3..2e9638f3f8d05 100644 --- a/drivers/gpu/drm/i2c/Makefile +++ b/drivers/gpu/drm/i2c/Makefile @@ -5,3 +5,6 @@ obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o sil164-y := sil164_drv.o obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o + +adv7511-y := adv7511_core.o adv7511_audio.o +obj-y += adv7511.o diff --git a/drivers/gpu/drm/i2c/adv7511.h b/drivers/gpu/drm/i2c/adv7511.h new file mode 100644 index 0000000000000..2bb6a2a1bd67b --- /dev/null +++ b/drivers/gpu/drm/i2c/adv7511.h @@ -0,0 +1,266 @@ +#ifndef __ADV7511_H__ +#define __ADV7511_H__ + +#define ADV7511_REG_CHIP_REVISION 0x00 +#define ADV7511_REG_N0 0x01 +#define ADV7511_REG_N1 0x02 +#define ADV7511_REG_N2 0x03 +#define ADV7511_REG_SPDIF_FREQ 0x04 +#define ADV7511_REG_CTS_AUTOMATIC1 0x05 +#define ADV7511_REG_CTS_AUTOMATIC2 0x06 +#define ADV7511_REG_CTS_MANUAL0 0x07 +#define ADV7511_REG_CTS_MANUAL1 0x08 +#define ADV7511_REG_CTS_MANUAL2 0x09 +#define ADV7511_REG_AUDIO_SOURCE 0x0a +#define ADV7511_REG_AUDIO_CONFIG 0x0b +#define ADV7511_REG_I2S_CONFIG 0x0c +#define ADV7511_REG_I2S_WIDTH 0x0d +#define ADV7511_REG_CSC_UPPER(x) (0x18 + (x) * 2) +#define ADV7511_REG_CSC_LOWER(x) (0x19 + (x) * 2) +#define ADV7511_REG_SYNC_DECODER(x) (0x30 + (x)) +#define ADV7511_REG_DE_GENERATOR (0x35 + (x)) +#define ADV7511_REG_PIXEL_REPETITION 0x3b +#define ADV7511_REG_VIC_MANUAL 0x3c +#define ADV7511_REG_VIC_SEND 0x3d +#define ADV7511_REG_VIC_DETECTED 0x3e +#define ADV7511_REG_AUX_VIC_DETECTED 0x3f +#define ADV7511_REG_PACKET_ENABLE0 0x40 +#define ADV7511_REG_POWER 0x41 +#define ADV7511_REG_STATUS 0x42 +#define ADV7511_REG_EDID_I2C_ADDR 0x43 +#define ADV7511_REG_PACKET_ENABLE1 0x44 +#define ADV7511_REG_PACKET_I2C_ADDR 0x45 +#define ADV7511_REG_DSD_ENABLE 0x46 +#define ADV7511_REG_GC(x) (0x4b + (x)) /* 0x4b - 0x51 */ +#define ADV7511_REG_AVI_INFOFRAME_VERSION 0x52 +#define ADV7511_REG_AVI_INFOFRAME_LENGTH 0x53 +#define ADV7511_REG_AVI_INFOFRAME_CHECKSUM 0x54 +#define ADV7511_REG_AVI_INFOFRAME(x) (0x55 + (x)) /* 0x55 - 0x6f */ +#define ADV7511_REG_AUDIO_INFOFRAME_VERSION 0x70 +#define ADV7511_REG_AUDIO_INFOFRAME_LENGTH 0x71 +#define ADV7511_REG_AUDIO_INFOFRAME_CHECKSUM 0x72 +#define ADV7511_REG_AUDIO_INFOFRAME(x) (0x73 + (x)) /* 0x73 - 0x7c */ +#define ADV7511_REG_INT_ENABLE(x) (0x94 + (x)) +#define ADV7511_REG_INT(x) (0x96 + (x)) +#define ADV7511_REG_INPUT_CLK_DIV 0x9d +#define ADV7511_REG_PLL_STATUS 0x9e +#define ADV7511_REG_POWER_DOWN 0xa1 +#define ADV7511_REG_AN(x) (0xb0 + (x)) /* 0xb0 - 0xb7 */ +#define ADV7511_REG_HDCP_STATUS 0xb8 +#define ADV7511_REG_BCAPS 0xbe +#define ADV7511_REG_BKSV(x) (0xc0 + (x)) /* 0xc0 - 0xc3 */ +#define ADV7511_REG_EDID_SEGMENT 0xc4 +#define ADV7511_REG_DDC_CONTROLLER_STATUS 0xc8 +#define ADV7511_REG_EDID_READ_CTRL 0xc9 +#define ADV7511_REG_BSTATUS(x) (0xca + (x)) /* 0xca - 0xcb */ +#define ADV7511_REG_ 0xd0 + +#define ADV7511_REG_SYNC_ADJUSTMENT(x) (0xd7 + (x)) /* 0xd7 - 0xdc */ +#define ADV7511_REG_TMDS_CLOCK_INV 0xde +#define ADV7511_REG_ARC_CTRL 0xdf +#define ADV7511_REG_CEC_I2C_ADDR 0xe1 +#define ADV7511_REG_CEC_CTRL 0xe2 +#define ADV7511_REG_CHIP_ID_HIGH 0xf5 +#define ADV7511_REG_CHIP_ID_LOW 0xf6 + +#define ADV7511_CSC_ENABLE BIT(7) +#define ADV7511_CSC_UPDATE_MODE BIT(5) + +#define ADV7511_INT0_HDP BIT(7) +#define ADV7511_INT0_VSYNC BIT(5) +#define ADV7511_INT0_AUDIO_FIFO_FULL BIT(4) +#define ADV7511_INT0_EDID_READY BIT(2) +#define ADV7511_INT0_HDCP_AUTHENTICATED BIT(1) + +#define ADV7511_INT1_DDC_ERROR BIT(7) +#define ADV7511_INT1_BKSV BIT(6) +#define ADV7511_INT1_CEC_TX_READY BIT(5) +#define ADV7511_INT1_CEC_TX_ARBIT_LOST BIT(4) +#define ADV7511_INT1_CEC_TX_RETRY_TIMEOUT BIT(3) +#define ADV7511_INT1_CEC_RX_READY3 BIT(2) +#define ADV7511_INT1_CEC_RX_READY2 BIT(1) +#define ADV7511_INT1_CEC_RX_READY1 BIT(0) + +#define ADV7511_ARC_CTRL_POWER_DOWN BIT(0) + +#define ADV7511_CEC_CTRL_POWER_DOWN BIT(0) + +#define ADV7511_POWER_POWER_DOWN BIT(6) + +#define ADV7511_AUDIO_SELECT_I2C 0x0 +#define ADV7511_AUDIO_SELECT_SPDIF 0x1 +#define ADV7511_AUDIO_SELECT_DSD 0x2 +#define ADV7511_AUDIO_SELECT_HBR 0x3 +#define ADV7511_AUDIO_SELECT_DST 0x4 + +#define ADV7511_I2S_SAMPLE_LEN_16 0x2 +#define ADV7511_I2S_SAMPLE_LEN_20 0x3 +#define ADV7511_I2S_SAMPLE_LEN_18 0x4 +#define ADV7511_I2S_SAMPLE_LEN_22 0x5 +#define ADV7511_I2S_SAMPLE_LEN_19 0x8 +#define ADV7511_I2S_SAMPLE_LEN_23 0x9 +#define ADV7511_I2S_SAMPLE_LEN_24 0xb +#define ADV7511_I2S_SAMPLE_LEN_17 0xc +#define ADV7511_I2S_SAMPLE_LEN_21 0xd + +#define ADV7511_SAMPLE_FREQ_44100 0x0 +#define ADV7511_SAMPLE_FREQ_48000 0x2 +#define ADV7511_SAMPLE_FREQ_32000 0x3 +#define ADV7511_SAMPLE_FREQ_88200 0x8 +#define ADV7511_SAMPLE_FREQ_96000 0xa +#define ADV7511_SAMPLE_FREQ_176400 0xc +#define ADV7511_SAMPLE_FREQ_192000 0xe + +#define ADV7511_STATUS_POWER_DOWN_POLARITY BIT(7) +#define ADV7511_STATUS_HPD BIT(6) +#define ADV7511_STATUS_MONITOR_SENSE BIT(5) +#define ADV7511_STATUS_I2S_32BIT_MODE BIT(3) + +#define ADV7511_PACKET_ENABLE_N_CTS BIT(8+6) +#define ADV7511_PACKET_ENABLE_AUDIO_SAMPLE BIT(8+5) +#define ADV7511_PACKET_ENABLE_AVI_INFOFRAME BIT(8+4) +#define ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME BIT(8+3) +#define ADV7511_PACKET_ENABLE_GC BIT(7) +#define ADV7511_PACKET_ENABLE_SPD BIT(6) +#define ADV7511_PACKET_ENABLE_MPEG BIT(5) +#define ADV7511_PACKET_ENABLE_ACP BIT(4) +#define ADV7511_PACKET_ENABLE_ISRC BIT(3) +#define ADV7511_PACKET_ENABLE_GM BIT(2) +#define ADV7511_PACKET_ENABLE_SPARE2 BIT(1) +#define ADV7511_PACKET_ENABLE_SPARE1 BIT(0) + +#define ADV7511_LOW_REFRESH_RATE_NONE 0x0 +#define ADV7511_LOW_REFRESH_RATE_24HZ 0x1 +#define ADV7511_LOW_REFRESH_RATE_25HZ 0x2 +#define ADV7511_LOW_REFRESH_RATE_30HZ 0x3 + +#include + +struct i2c_client; +struct regmap; + +struct adv7511 { + struct i2c_client *i2c_main; + struct i2c_client *i2c_edid; + struct i2c_client *i2c_packet; + struct i2c_client *i2c_cec; + + struct regmap *regmap; + enum drm_connector_status status; + int dpms_mode; + + unsigned int f_tmds; + unsigned int f_audio; + + unsigned int audio_source; + + unsigned int current_edid_segment; + uint8_t edid_buf[256]; + + wait_queue_head_t wq; + struct drm_encoder *encoder; +}; + +int adv7511_packet_enable(struct adv7511 *adv7511, unsigned int packet); +int adv7511_packet_disable(struct adv7511 *adv7511, unsigned int packet); + +int adv7511_audio_init(struct device *dev); +void adv7511_audio_exit(struct device *dev); + +enum adv7511_input_id { + ADV7511_INPUT_ID_24BIT_RGB444_YCbCr444 = 0, + ADV7511_INPUT_ID_16_20_24BIT_YCbCr422_SEPARATE_SYNC = 1, + ADV7511_INPUT_ID_16_20_24BIT_YCbCr422_EMBEDDED_SYNC = 2, + ADV7511_INPUT_ID_8_10_12BIT_YCbCr422_SEPARATE_SYNC = 3, + ADV7511_INPUT_ID_8_10_12BIT_YCbCr422_EMBEDDED_SYNC = 4, + ADV7511_INPUT_ID_12_15_16BIT_RGB444_YCbCr444 = 5, + ADV7511_INPUT_ID_8_10_12BIT_YCbCr422_DDR_SEPARATE_SYNC1 = 6, + ADV7511_INPUT_ID_8_10_12BIT_YCbCr422_DDR_SEPARATE_SYNC2 = 7, + ADV7511_INPUT_ID_8_10_12BIT_YCbCr422_DDR_EMBEDDED_SYNC = 8, +}; + +enum adv7511_input_color_depth { + ADV7511_INPUT_COLOR_DEPTH_10BIT = 1, + ADV7511_INPUT_COLOR_DEPTH_12BIT = 2, + ADV7511_INPUT_COLOR_DEPTH_8BIT = 3, +}; + +enum adv7511_input_style { + ADV7511_INPUT_STYLE2 = 1, + ADV7511_INPUT_STYLE1 = 2, + ADV7511_INPUT_STYLE3 = 3, +}; + +enum adv7511_input_sync_pulse { + ADV7511_INPUT_SYNC_PULSE_DE = 0, + ADV7511_INPUT_SYNC_PULSE_HSYNC = 1, + ADV7511_INPUT_SYNC_PULSE_VSYNC = 2, + ADV7511_INPUT_SYNC_PULSE_NONE = 3, +}; + +enum adv7511_input_clock_delay { + ADV7511_INPUT_CLOCK_DELAY_MINUS_1200PS = 0, + ADV7511_INPUT_CLOCK_DELAY_MINUS_800PS = 1, + ADV7511_INPUT_CLOCK_DELAY_MINUS_400PS = 2, + ADV7511_INPUT_CLOCK_DELAY_NONE = 3, + ADV7511_INPUT_CLOCK_DELAY_PLUS_400PS = 4, + ADV7511_INPUT_CLOCK_DELAY_PLUS_800PS = 5, + ADV7511_INPUT_CLOCK_DELAY_PLUS_1200PS = 6, + ADV7511_INPUT_CLOCK_DELAY_PLUS_1600PS = 7, +}; + +enum adv7511_input_adjust_delay { + ADV7511_INPUT_ADJUST_DELAY_MINUS_1200PS = 0, + ADV7511_INPUT_ADJUST_DELAY_MINUS_800PS = 1, + ADV7511_INPUT_ADJUST_DELAY_MINUS_400PS = 2, + ADV7511_INPUT_ADJUST_DELAY_NONE = 3, + ADV7511_INPUT_ADJUST_DELAY_PLUS_400PS = 4, + ADV7511_INPUT_ADJUST_DELAY_PLUS_800PS = 5, + ADV7511_INPUT_ADJUST_DELAY_PLUS_1200PS = 6, + ADV7511_INPUT_ADJUST_DELAY_INVERT_CLK = 7, +}; + +enum adv7511_input_ddr_alignment { + ADV7511_INPUT_DDR_ALIGNMENT_17_0 = 0, + ADV7511_INPUT_DDR_ALIGNMENT_35_18 = 1, +}; + +enum adv7511_input_bit_justifiction { + ADV7511_INPUT_BIT_JUSTIFICATION_EVENLY = 0, + ADV7511_INPUT_BIT_JUSTIFICATION_RIGHT = 1, + ADV7511_INPUT_BIT_JUSTIFICATION_LEFT = 2, +}; + +enum adv7511_output_format { + ADV7511_OUTPUT_FORMAT_RGB_444 = 0, + ADV7511_OUTPUT_FORMAT_YCBCR_422 = 1, + ADV7511_OUTPUT_FORMAT_YCBCR_444 = 2, +}; + +struct adv7511_video_input_config { + enum adv7511_input_id id; + enum adv7511_input_style input_style; + enum adv7511_input_sync_pulse sync_pulse; + enum adv7511_input_clock_delay clock_delay; + enum adv7511_input_adjust_delay ddr_negative_clock_delay; + bool reverse_bitorder; + enum adv7511_input_ddr_alignment ddr_alignment; + enum adv7511_input_bit_justifiction bit_justification; + bool ddr_edge_rising; + bool vsync_polartity_low; + bool hsync_polartity_low; + bool up_conversion_first_order_interpolation; + bool enable_ddr_negative_clock_delay; + enum adv7511_input_color_depth input_color_depth; + bool tmds_clock_inversion; + + bool csc_enable; + int csc_scaling_factor; + uint16_t *csc_coefficents; + + enum adv7511_output_format output_format; + int timing_generation_sequence; + bool hdmi_mode; +}; + +#endif diff --git a/drivers/gpu/drm/i2c/adv7511_audio.c b/drivers/gpu/drm/i2c/adv7511_audio.c new file mode 100644 index 0000000000000..9fb99487ac998 --- /dev/null +++ b/drivers/gpu/drm/i2c/adv7511_audio.c @@ -0,0 +1,318 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "adv7511.h" + +static const DECLARE_TLV_DB_SCALE(adv7511_levelshift_tlv, 0, 100, 0); + +static const struct snd_kcontrol_new adv7511_controls[] = { + SOC_SINGLE("Master Playback Switch", 0, 0, 0, 0), + SOC_SINGLE_TLV("Master Playback Volume", 0, 0, 45, 0, + adv7511_levelshift_tlv), +}; + +static const struct snd_soc_dapm_widget adv7511_dapm_widgets[] = { +}; + +static const struct snd_soc_dapm_route adv7511_routes[] = { + { "TMDS", NULL, "DAI IN" }, +}; + +static void adv7511_calc_cts_n(unsigned int f_tmds, unsigned int fs, + unsigned int *cts, unsigned int *n) +{ + switch (fs) { + case 32000: + *n = 4096; + break; + case 44100: + *n = 6272; + break; + case 48000: + *n = 6144; + break; + } + + *cts = (f_tmds * *n) / (128 * fs); +} + +static int adv7511_update_cts_n(struct adv7511 *adv7511) +{ + unsigned int cts = 0; + unsigned int n = 0; + + adv7511_calc_cts_n(adv7511->f_tmds, adv7511->f_audio, &cts, &n); + + regmap_write(adv7511->regmap, ADV7511_REG_N0, (n >> 16) & 0xf); + regmap_write(adv7511->regmap, ADV7511_REG_N1, (n >> 8) & 0xff); + regmap_write(adv7511->regmap, ADV7511_REG_N2, n & 0xff); + + regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL0, (n >> 16) & 0xf); + regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL1, (n >> 8) & 0xff); + regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL2, n & 0xff); + + return 0; +} + +static int adv7511_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->codec; + struct adv7511 *adv7511 = snd_soc_codec_get_drvdata(codec); + unsigned int rate; + unsigned int len; + + switch (params_rate(params)) { + case 32000: + rate = ADV7511_SAMPLE_FREQ_32000; + break; + case 44100: + rate = ADV7511_SAMPLE_FREQ_44100; + break; + case 48000: + rate = ADV7511_SAMPLE_FREQ_48000; + break; + case 88200: + rate = ADV7511_SAMPLE_FREQ_88200; + break; + case 96000: + rate = ADV7511_SAMPLE_FREQ_96000; + break; + case 176400: + rate = ADV7511_SAMPLE_FREQ_176400; + break; + case 192000: + rate = ADV7511_SAMPLE_FREQ_192000; + break; + default: + return -EINVAL; + } + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + len = ADV7511_I2S_SAMPLE_LEN_16; + break; + case SNDRV_PCM_FORMAT_S18_3LE: + len = ADV7511_I2S_SAMPLE_LEN_18; + break; + case SNDRV_PCM_FORMAT_S20_3LE: + len = ADV7511_I2S_SAMPLE_LEN_20; + break; + case SNDRV_PCM_FORMAT_S24_LE: + len = ADV7511_I2S_SAMPLE_LEN_24; + break; + default: + return -EINVAL; + } + + adv7511->f_audio = params_rate(params); + + adv7511_update_cts_n(adv7511); + + regmap_update_bits(adv7511->regmap, 0x14, 0x0f, len); + regmap_update_bits(adv7511->regmap, 0x15, 0xf0, rate << 4); + + return 0; +} + +#define ADV7511_AUDIO_SOURCE_I2S 0 +#define ADV7511_AUDIO_SOURCE_SPDIF 1 + +#define ADV7511_I2S_FORMAT_I2S 0 +#define ADV7511_I2S_FORMAT_RIGHT_J 1 +#define ADV7511_I2S_FORMAT_LEFT_J 2 + +static int adv7511_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct adv7511 *adv7511 = snd_soc_codec_get_drvdata(codec); + unsigned int audio_source, i2s_format = 0; + unsigned int invert_clock; + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + audio_source = ADV7511_AUDIO_SOURCE_I2S; + i2s_format = ADV7511_I2S_FORMAT_I2S; + break; + case SND_SOC_DAIFMT_RIGHT_J: + audio_source = ADV7511_AUDIO_SOURCE_I2S; + i2s_format = ADV7511_I2S_FORMAT_RIGHT_J; + break; + case SND_SOC_DAIFMT_LEFT_J: + audio_source = ADV7511_AUDIO_SOURCE_I2S; + i2s_format = ADV7511_I2S_FORMAT_LEFT_J; + break; + case SND_SOC_DAIFMT_SPDIF: + audio_source = ADV7511_AUDIO_SOURCE_SPDIF; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + break; + default: + return -EINVAL; + } + + /* clock inversion */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + invert_clock = 0; + break; + case SND_SOC_DAIFMT_IB_NF: + invert_clock = 1; + break; + default: + return -EINVAL; + } + + regmap_update_bits(adv7511->regmap, 0x0a, 0x70, audio_source << 4); + regmap_update_bits(adv7511->regmap, 0x0b, BIT(6), invert_clock << 6); + regmap_update_bits(adv7511->regmap, 0x0c, 0x03, i2s_format); + + adv7511->audio_source = audio_source; + + return 0; +} + +static int adv7511_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct adv7511 *adv7511 = snd_soc_codec_get_drvdata(codec); + + switch (level) { + case SND_SOC_BIAS_ON: + switch (adv7511->audio_source) { + case ADV7511_AUDIO_SOURCE_I2S: + break; + case ADV7511_AUDIO_SOURCE_SPDIF: + regmap_update_bits(adv7511->regmap, 0x0b, BIT(7), BIT(7)); + break; + } + break; + case SND_SOC_BIAS_PREPARE: + if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { + adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AUDIO_SAMPLE); + adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME); + adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_N_CTS); + } else { + adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AUDIO_SAMPLE); + adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME); + adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_N_CTS); + } + break; + case SND_SOC_BIAS_STANDBY: + regmap_update_bits(adv7511->regmap, 0x0b, BIT(7), 0); + break; + case SND_SOC_BIAS_OFF: + break; + } + codec->dapm.bias_level = level; + return 0; +} + +#define ADV7511_RATES (SNDRV_PCM_RATE_32000 |\ + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) + +#define ADV7511_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |\ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) + +static const struct snd_soc_dai_ops adv7511_dai_ops = { + .hw_params = adv7511_hw_params, + /*.set_sysclk = adv7511_set_dai_sysclk,*/ + .set_fmt = adv7511_set_dai_fmt, +}; + +static struct snd_soc_dai_driver adv7511_dai = { + .name = "adv7511", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = ADV7511_RATES, + .formats = ADV7511_FORMATS, + }, + .ops = &adv7511_dai_ops, +}; + +static int adv7511_suspend(struct snd_soc_codec *codec) +{ + adv7511_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} + +static int adv7511_resume(struct snd_soc_codec *codec) +{ + adv7511_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + return 0; +} + +static int adv7511_probe(struct snd_soc_codec *codec) +{ + struct adv7511 *adv7511 = snd_soc_codec_get_drvdata(codec); + int ret; + + codec->control_data = adv7511->regmap; + ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; + } + + adv7511_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + return 0; +} + +static int adv7511_remove(struct snd_soc_codec *codec) +{ + adv7511_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} + +static struct snd_soc_codec_driver adv7511_codec_driver = { + .probe = adv7511_probe, + .remove = adv7511_remove, + .suspend = adv7511_suspend, + .resume = adv7511_resume, + .set_bias_level = adv7511_set_bias_level, + +/* + .controls = adv7511_controls, + .num_controls = ARRAY_SIZE(adv7511_controls),*/ + .dapm_widgets = adv7511_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adv7511_dapm_widgets), + .dapm_routes = adv7511_routes, + .num_dapm_routes = ARRAY_SIZE(adv7511_routes), +}; + +int adv7511_audio_init(struct device *dev) +{ + return snd_soc_register_codec(dev, &adv7511_codec_driver, + &adv7511_dai, 1); +} + +void adv7511_audio_exit(struct device *dev) +{ + snd_soc_unregister_codec(dev); +} diff --git a/drivers/gpu/drm/i2c/adv7511_core.c b/drivers/gpu/drm/i2c/adv7511_core.c new file mode 100644 index 0000000000000..7f36e6ecea4dc --- /dev/null +++ b/drivers/gpu/drm/i2c/adv7511_core.c @@ -0,0 +1,672 @@ + +#include +#include +#include +#include + +#include "adv7511.h" + +#include +#include +#include +#include + +static uint8_t adv7511_register_defaults[] = { + 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00 */ + 0x00, 0x00, 0x01, 0x0e, 0xbc, 0x18, 0x01, 0x13, + 0x25, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */ + 0x46, 0x62, 0x04, 0xa8, 0x00, 0x00, 0x1c, 0x84, + 0x1c, 0xbf, 0x04, 0xa8, 0x1e, 0x70, 0x02, 0x1e, /* 20 */ + 0x00, 0x00, 0x04, 0xa8, 0x08, 0x12, 0x1b, 0xac, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30 */ + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, + 0x00, 0x50, 0x90, 0x7e, 0x79, 0x70, 0x00, 0x00, /* 40 */ + 0x00, 0xa8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x00, /* 50 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 60 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 70 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 80 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 90 */ + 0x0b, 0x02, 0x00, 0x18, 0x5a, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x80, 0x08, 0x04, 0x00, 0x00, /* a0 */ + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c0 */ + 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0x04, + 0x30, 0xff, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, /* d0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, + 0x80, 0x75, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, /* e0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x11, 0x00, /* f0 */ + 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* ADI recommanded values for proper operation. */ +static uint8_t adv7511_fixed_registers[][2] = { + { 0x98, 0x03 }, + { 0x9a, 0xe0 }, + { 0x9c, 0x30 }, + { 0x9d, 0x61 }, + { 0xa2, 0xa4 }, + { 0xa3, 0xa4 }, + { 0xe0, 0xd0 }, + { 0xf9, 0x00 }, +}; + +static struct adv7511 *encoder_to_adv7511(struct drm_encoder *encoder) +{ + return to_encoder_slave(encoder)->slave_priv; +} + +static void adv7511_set_colormap(struct adv7511 *adv7511, bool enable, + uint16_t *coeff, unsigned int scaling_factor) +{ + unsigned int i; + + regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(1), + ADV7511_CSC_UPDATE_MODE, ADV7511_CSC_UPDATE_MODE); + + if (enable) { + for (i = 0; i < 12; ++i) { + regmap_update_bits(adv7511->regmap, + ADV7511_REG_CSC_UPPER(i), + 0x1f, coeff[i] >> 8); + regmap_write(adv7511->regmap, + ADV7511_REG_CSC_LOWER(i), + coeff[i] & 0xff); + } + } + + regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(0), + 0xe0, (enable << 7) | (scaling_factor << 5)); + + regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(1), + ADV7511_CSC_UPDATE_MODE, 0); +} + +static void adv7511_set_config(struct drm_encoder *encoder, void *c) +{ + struct adv7511 *adv7511 = encoder_to_adv7511(encoder); + struct adv7511_video_input_config *config = c; + enum adv7511_input_sync_pulse sync_pulse; + bool output_format_422, output_format_ycbcr; + + adv7511_set_colormap(adv7511, config->csc_enable, config->csc_coefficents, + config->csc_scaling_factor); + + switch (config->output_format) { + case ADV7511_OUTPUT_FORMAT_YCBCR_444: + output_format_422 = false; + output_format_ycbcr = true; + break; + case ADV7511_OUTPUT_FORMAT_YCBCR_422: + output_format_422 = true; + output_format_ycbcr = true; + break; + default: + output_format_422 = false; + output_format_ycbcr = false; + break; + } + + switch (config->id) { + case ADV7511_INPUT_ID_12_15_16BIT_RGB444_YCbCr444: + case ADV7511_INPUT_ID_8_10_12BIT_YCbCr422_DDR_SEPARATE_SYNC1: + case ADV7511_INPUT_ID_8_10_12BIT_YCbCr422_DDR_SEPARATE_SYNC2: + case ADV7511_INPUT_ID_8_10_12BIT_YCbCr422_DDR_EMBEDDED_SYNC: + sync_pulse = ADV7511_INPUT_SYNC_PULSE_NONE; + break; + default: + sync_pulse = config->sync_pulse; + break; + } + + regmap_update_bits(adv7511->regmap, 0x15, 0xf, config->id); + regmap_write(adv7511->regmap, 0x16, + (output_format_422 << 7) | + (config->input_color_depth << 4) | + (config->input_style << 2) | + (config->ddr_edge_rising << 1) | + output_format_ycbcr); + regmap_write(adv7511->regmap, 0x48, + (config->reverse_bitorder << 6) | + (config->ddr_alignment << 5) | + (config->bit_justification << 3)); + regmap_write(adv7511->regmap, 0xd0, + (config->enable_ddr_negative_clock_delay << 7) | + (config->ddr_negative_clock_delay << 4) | + (sync_pulse << 2) | + (config->timing_generation_sequence << 1)); +/* regmap_write(adv7511->regmap, 0xba, + (config->clock_delay << 5));*/ + + regmap_update_bits(adv7511->regmap, ADV7511_REG_TMDS_CLOCK_INV, + 0x08, config->tmds_clock_inversion << 3); + + regmap_update_bits(adv7511->regmap, ADV7511_REG_AVI_INFOFRAME(0), + 0x60, config->output_format << 5); + + if (config->hdmi_mode) + regmap_write(adv7511->regmap, 0xaf, 0x06); + else + regmap_write(adv7511->regmap, 0xaf, 0x04); +} + +int adv7511_packet_enable(struct adv7511 *adv7511, unsigned int packet) +{ + if (packet & 0xff) { + regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE0, + packet, 0xff); + } + + if (packet & 0xff00) { + packet >>= 8; + regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1, + packet, 0xff); + } + + return 0; +} + +int adv7511_packet_disable(struct adv7511 *adv7511, unsigned int packet) +{ + if (packet & 0xff) { + regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE0, + packet, 0x00); + } + + if (packet & 0xff00) { + packet >>= 8; + regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1, + packet, 0x00); + } + + return 0; +} + +static bool adv7511_register_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ADV7511_REG_SPDIF_FREQ: + case ADV7511_REG_CTS_AUTOMATIC1: + case ADV7511_REG_CTS_AUTOMATIC2: + case ADV7511_REG_VIC_DETECTED: + case ADV7511_REG_VIC_SEND: + case ADV7511_REG_AUX_VIC_DETECTED: + case ADV7511_REG_STATUS: + case ADV7511_REG_GC(1): + case ADV7511_REG_INT(0): + case ADV7511_REG_INT(1): + case ADV7511_REG_PLL_STATUS: + case ADV7511_REG_AN(0): + case ADV7511_REG_AN(1): + case ADV7511_REG_AN(2): + case ADV7511_REG_AN(3): + case ADV7511_REG_AN(4): + case ADV7511_REG_AN(5): + case ADV7511_REG_AN(6): + case ADV7511_REG_AN(7): + case ADV7511_REG_HDCP_STATUS: + case ADV7511_REG_BCAPS: + case ADV7511_REG_BKSV(0): + case ADV7511_REG_BKSV(1): + case ADV7511_REG_BKSV(2): + case ADV7511_REG_BKSV(3): + case ADV7511_REG_BKSV(4): + case ADV7511_REG_DDC_CONTROLLER_STATUS: + case ADV7511_REG_BSTATUS(0): + case ADV7511_REG_BSTATUS(1): + case ADV7511_REG_CHIP_ID_HIGH: + case ADV7511_REG_CHIP_ID_LOW: + return true; + } + + return false; +} + +static bool adv7511_hpd(struct adv7511 *adv7511) +{ + unsigned int irq0; + int ret; + + ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0); + if (ret < 0) + return false; + + if (irq0 & ADV7511_INT0_HDP) { + regmap_write(adv7511->regmap, ADV7511_REG_INT(0), ADV7511_INT0_HDP); + return true; + } + + return false; +} + +static irqreturn_t adv7511_irq_handler(int irq, void *devid) +{ + struct adv7511 *adv7511 = devid; + + if (adv7511_hpd(adv7511)) + drm_helper_hpd_irq_event(adv7511->encoder->dev); + + wake_up_all(&adv7511->wq); + + return IRQ_HANDLED; +} + +static unsigned int adv7511_is_interrupt_pending(struct adv7511 *adv7511, + unsigned int irq) +{ + unsigned int irq0, irq1; + unsigned int pending; + int ret; + + ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0); + if (ret < 0) + return 0; + ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(1), &irq1); + if (ret < 0) + return 0; + + pending = (irq1 << 8) | irq0; + + return pending & irq; +} + +static int adv7511_wait_for_interrupt(struct adv7511 *adv7511, int irq, int timeout) +{ + unsigned int pending = 0; + int ret; + + if (adv7511->i2c_main->irq) { + ret = wait_event_interruptible_timeout(adv7511->wq, + adv7511_is_interrupt_pending(adv7511, irq), + msecs_to_jiffies(timeout)); + if (ret <= 0) + return 0; + pending = adv7511_is_interrupt_pending(adv7511, irq); + } else { + if (timeout < 25) + timeout = 25; + do { + pending = adv7511_is_interrupt_pending(adv7511, irq); + if (pending) + break; + msleep(25); + timeout -= 25; + } while (timeout >= 25); + } + + return pending; +} + +static int adv7511_get_edid_block(void *data, + unsigned char *buf, int block, int len) +{ + struct drm_encoder *encoder = data; + struct adv7511 *adv7511 = encoder_to_adv7511(encoder); + int ret; + + if (len > 128) + return -EINVAL; + + if (adv7511->current_edid_segment != block / 2) { + unsigned int foo; + regmap_read(adv7511->regmap, 0xc8, &foo); + printk("edid status: %x\n", foo); + + regmap_write(adv7511->regmap, ADV7511_REG_EDID_SEGMENT, block); + ret = adv7511_wait_for_interrupt(adv7511, ADV7511_INT0_EDID_READY | + ADV7511_INT1_DDC_ERROR, 200); + printk("edid ret: %x\n", ret); + + if (!(ret & ADV7511_INT0_EDID_READY)) + return -EIO; + + regmap_write(adv7511->regmap, ADV7511_REG_INT(0), + ADV7511_INT0_EDID_READY | ADV7511_INT1_DDC_ERROR); + + ret = i2c_master_recv(adv7511->i2c_edid, adv7511->edid_buf, 256); + printk("i2c ret: %x\n", ret); + if (ret < 0) + return ret; + else if (ret != 256) + return -EIO; + + adv7511->current_edid_segment = block / 2; + } + + if (block % 2 == 0) + memcpy(buf, adv7511->edid_buf, len); + else + memcpy(buf, adv7511->edid_buf + 128, len); + + return 0; +} + +static int adv7511_get_modes(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct adv7511 *adv7511 = encoder_to_adv7511(encoder); + struct edid *edid; + unsigned int count; + + /* Reading the EDID only works if the device is powered */ + if (adv7511->dpms_mode != DRM_MODE_DPMS_ON) { + regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, + ADV7511_POWER_POWER_DOWN, 0); + adv7511->current_edid_segment = -1; + } + + edid = drm_do_get_edid(connector, adv7511_get_edid_block, encoder); + + if (adv7511->dpms_mode != DRM_MODE_DPMS_ON) + regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, + ADV7511_POWER_POWER_DOWN, ADV7511_POWER_POWER_DOWN); + + if (!edid) + return 0; + + drm_mode_connector_update_edid_property(connector, edid); + count = drm_add_edid_modes(connector, edid); + + connector->display_info.raw_edid = (char *)edid; + + return count; +} + +static void adv7511_encoder_dpms(struct drm_encoder *encoder, int mode) +{ + struct adv7511 *adv7511 = encoder_to_adv7511(encoder); + + switch (mode) { + case DRM_MODE_DPMS_ON: + adv7511->current_edid_segment = -1; + + regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, + ADV7511_POWER_POWER_DOWN, 0); + /* + * Some monitors seem to have a unstable HDP pin when they wakeup from + * standby. When the HDP goes low the adv7511 is reset and the outputs + * are disabled which might cause the monitor to go to standby again. + * To avoid this we ignore the HDP pin for the first few seconds after + * enabeling the output. + */ + regmap_update_bits(adv7511->regmap, 0xd6, 0xc0, 0xc0); + /* Most of the registers are reset during power down or when HPD is low */ + regcache_sync(adv7511->regmap); + break; + default: + /* TODO: setup additional power down modes */ + regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, + ADV7511_POWER_POWER_DOWN, ADV7511_POWER_POWER_DOWN); + regcache_mark_dirty(adv7511->regmap); + break; + } + + adv7511->dpms_mode = mode; +} + +static enum drm_connector_status adv7511_encoder_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct adv7511 *adv7511 = encoder_to_adv7511(encoder); + enum drm_connector_status status; + unsigned int val; + bool hpd; + + regmap_read(adv7511->regmap, ADV7511_REG_STATUS, &val); + + /* Cable connected and monitor turned on ? */ + if (val & (ADV7511_STATUS_HPD)) /* | ADV7511_STATUS_MONITOR_SENSE))*/ + status = connector_status_connected; + else + status = connector_status_disconnected; + + hpd = adv7511_hpd(adv7511); + + printk("detect: %x %d %d %d\n", val, status, hpd, adv7511->dpms_mode); + + /* The chip resets itself when the cable is disconnected, so in case there is + * a pending HPD interrupt and the cable is connected there was at least on + * transition from disconnected to connected and the chip has to be + * reinitialized. */ + if (status == connector_status_connected && hpd && + adv7511->dpms_mode == DRM_MODE_DPMS_ON) { + regcache_mark_dirty(adv7511->regmap); + adv7511_encoder_dpms(encoder, adv7511->dpms_mode); + } else { + /* Renabled HDP sensing */ + regmap_update_bits(adv7511->regmap, 0xd6, 0xc0, 0x0); + } + + adv7511->status = status; + return status; +} + +#define ADV7511_RATIO_NO_DATA (0x0 << 3) +#define ADV7511_RATIO_4_3 (0x1 << 3) +#define ADV7511_RATIO_16_9 (0x2 << 3) +#define ADV7511_RATIO_MASK (0x3 << 3) + +static void adv7511_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adj_mode) +{ + struct adv7511 *adv7511 = encoder_to_adv7511(encoder); + unsigned int low_refresh_rate; + bool embedded_sync = true; + unsigned int ratio; + + if (adj_mode->hdisplay / 4 == adj_mode->vdisplay / 3) + ratio = ADV7511_RATIO_4_3; + else if (adj_mode->hdisplay / 16 == adj_mode->vdisplay / 9) + ratio = ADV7511_RATIO_16_9; + else + ratio = ADV7511_RATIO_NO_DATA; + + if (embedded_sync) { + unsigned int hsync_offset, hsync_len; + unsigned int vsync_offset, vsync_len; + + hsync_offset = adj_mode->crtc_hsync_start - adj_mode->crtc_hdisplay; + vsync_offset = adj_mode->crtc_vsync_start - adj_mode->crtc_vdisplay; + hsync_len = adj_mode->crtc_hsync_end - adj_mode->crtc_hsync_start; + vsync_len = adj_mode->crtc_vsync_end - adj_mode->crtc_vsync_start; + + regmap_write(adv7511->regmap, 0xfa, + ((hsync_offset >> 10) & 0x7) << 5); + regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(0), + (hsync_offset >> 2) & 0xff); + regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(1), + ((hsync_offset & 0x3) << 2) | (hsync_len >> 4)); + regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(2), + ((hsync_len & 0xf) << 4) | (vsync_offset >> 6)); + regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(3), + ((vsync_offset & 0x3f) << 2) | (vsync_len >> 8)); + regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(4), + vsync_len & 0xff); + } + + if (mode->vrefresh <= 24000) + low_refresh_rate = ADV7511_LOW_REFRESH_RATE_24HZ; + else if (mode->vrefresh <= 25000) + low_refresh_rate = ADV7511_LOW_REFRESH_RATE_25HZ; + else if (mode->vrefresh <= 30000) + low_refresh_rate = ADV7511_LOW_REFRESH_RATE_30HZ; + else + low_refresh_rate = ADV7511_LOW_REFRESH_RATE_NONE; + + regmap_update_bits(adv7511->regmap, 0xfb, + 0x6, low_refresh_rate << 1); + regmap_update_bits(adv7511->regmap, 0x56, ADV7511_RATIO_MASK, ratio); + + adv7511->f_tmds = mode->clock; + +/* + switch (adv7511->color_mode) { + case COLOR_MODE_30BIT: + adv7511->f_tmds = adv7511->f_tmds * 5 / 4; + break; + case COLOR_MODE_36BIT: + adv7511->f_tmds = adv7511->f_tmds * 3 / 2; + break; + case COLOR_MODE_48BIT: + adv7511->f_tmds = adv7511->f_tmds * 2; + break; + case COLOR_MODE_24BIT: + break; + } +*/ +} + +static struct drm_encoder_slave_funcs adv7511_encoder_funcs = { + .set_config = adv7511_set_config, + .dpms = adv7511_encoder_dpms, + /* .destroy = adv7511_encoder_destroy,*/ + .mode_set = adv7511_encoder_mode_set, + .detect = adv7511_encoder_detect, + .get_modes = adv7511_get_modes, +}; + +static const struct regmap_config adv7511_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = 0xff, + .cache_type = REGCACHE_RBTREE, + .reg_defaults_raw = adv7511_register_defaults, + .num_reg_defaults_raw = ARRAY_SIZE(adv7511_register_defaults), + + .volatile_reg = adv7511_register_volatile, +}; + +static const int edid_i2c_addr = 0x7e; +static const int packet_i2c_addr = 0x70; +static const int cec_i2c_addr = 0x78; + +static int __devinit adv7511_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct adv7511 *adv7511; + unsigned int val; + unsigned int i; + int ret; + + adv7511 = devm_kzalloc(&i2c->dev, sizeof(*adv7511), GFP_KERNEL); + if (!adv7511) + return -ENOMEM; + + adv7511->regmap = regmap_init_i2c(i2c, &adv7511_regmap_config); + if (IS_ERR(adv7511->regmap)) + return PTR_ERR(adv7511->regmap); + + ret = regmap_read(adv7511->regmap, ADV7511_REG_CHIP_REVISION, &val); + dev_dbg(&i2c->dev, "Rev. %d\n", val); + + regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR, edid_i2c_addr); + regmap_write(adv7511->regmap, ADV7511_REG_PACKET_I2C_ADDR, packet_i2c_addr); + regmap_write(adv7511->regmap, ADV7511_REG_CEC_I2C_ADDR, cec_i2c_addr); + + adv7511->i2c_main = i2c; + adv7511->i2c_edid = i2c_new_dummy(i2c->adapter, edid_i2c_addr >> 1); + adv7511->i2c_packet = i2c_new_dummy(i2c->adapter, packet_i2c_addr >> 1); + adv7511->i2c_cec = i2c_new_dummy(i2c->adapter, cec_i2c_addr >> 1); + + for (i = 0; i < ARRAY_SIZE(adv7511_fixed_registers); ++i) { + regmap_write(adv7511->regmap, adv7511_fixed_registers[i][0], + adv7511_fixed_registers[i][1]); + } + + if (i2c->irq) { + ret = request_threaded_irq(i2c->irq, NULL, adv7511_irq_handler, 0, + dev_name(&i2c->dev), adv7511); + if (ret) + goto err_regmap_exit; + + init_waitqueue_head(&adv7511->wq); + } + + /* CEC is unused for now */ + regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, + ADV7511_CEC_CTRL_POWER_DOWN); + + regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, + ADV7511_POWER_POWER_DOWN, ADV7511_POWER_POWER_DOWN); + + adv7511->current_edid_segment = -1; + + i2c_set_clientdata(i2c, adv7511); + adv7511_audio_init(&i2c->dev); + + return 0; + +err_regmap_exit: + regmap_exit(adv7511->regmap); + + return ret; +} + +static int __devexit adv7511_remove(struct i2c_client *i2c) +{ + struct adv7511 *adv7511 = i2c_get_clientdata(i2c); + + if (i2c->irq) + free_irq(i2c->irq, adv7511); + + regmap_exit(adv7511->regmap); + + i2c_unregister_device(adv7511->i2c_edid); + i2c_unregister_device(adv7511->i2c_packet); + i2c_unregister_device(adv7511->i2c_cec); + + return 0; +} + +static int adv7511_encoder_init(struct i2c_client *i2c, + struct drm_device *dev, struct drm_encoder_slave *encoder) +{ + + struct adv7511 *adv7511 = i2c_get_clientdata(i2c); + + encoder->slave_priv = adv7511; + encoder->slave_funcs = &adv7511_encoder_funcs; + + adv7511->encoder = &encoder->base; + + return 0; +} + +static const struct i2c_device_id adv7511_ids[] = { + { "adv7511", 0 }, + {} +}; + +static struct drm_i2c_encoder_driver adv7511_driver = { + .i2c_driver = { + .driver = { + .name = "adv7511", + }, + .id_table = adv7511_ids, + .probe = adv7511_probe, + .remove = __devexit_p(adv7511_remove), + }, + + .encoder_init = adv7511_encoder_init, +}; + +static int __init adv7511_init(void) +{ + return drm_i2c_encoder_register(THIS_MODULE, &adv7511_driver); +} +module_init(adv7511_init); + +static void __exit adv7511_exit(void) +{ + drm_i2c_encoder_unregister(&adv7511_driver); +} +module_exit(adv7511_exit); From 130a8f0664739e5cf725741c9c1fb62b998168d7 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 5 Mar 2012 16:24:33 +0100 Subject: [PATCH 012/261] DRM: Add driver for Analog Devices FPGA platforms Signed-off-by: Lars-Peter Clausen --- drivers/gpu/drm/Kconfig | 11 +- drivers/gpu/drm/Makefile | 7 +- drivers/gpu/drm/analog/Kconfig | 20 + drivers/gpu/drm/analog/Makefile | 8 + drivers/gpu/drm/analog/analog_drm_buf.c | 76 +++ drivers/gpu/drm/analog/analog_drm_crtc.c | 174 +++++ drivers/gpu/drm/analog/analog_drm_crtc.h | 9 + drivers/gpu/drm/analog/analog_drm_drv.c | 219 +++++++ drivers/gpu/drm/analog/analog_drm_drv.h | 28 + drivers/gpu/drm/analog/analog_drm_encoder.c | 692 ++++++++++++++++++++ drivers/gpu/drm/analog/analog_drm_encoder.h | 6 + drivers/gpu/drm/analog/analog_drm_fbdev.c | 338 ++++++++++ drivers/gpu/drm/analog/analog_drm_fbdev.h | 12 + drivers/gpu/drm/analog/analog_drm_gem.c | 242 +++++++ drivers/gpu/drm/analog/analog_drm_gem.h | 52 ++ drivers/gpu/drm/drm_crtc.c | 2 + drivers/gpu/drm/drm_crtc_helper.c | 1 - drivers/gpu/drm/drm_edid.c | 16 +- drivers/gpu/drm/drm_stub.c | 2 +- include/drm/drm_edid.h | 3 + 20 files changed, 1904 insertions(+), 14 deletions(-) create mode 100644 drivers/gpu/drm/analog/Kconfig create mode 100644 drivers/gpu/drm/analog/Makefile create mode 100644 drivers/gpu/drm/analog/analog_drm_buf.c create mode 100644 drivers/gpu/drm/analog/analog_drm_crtc.c create mode 100644 drivers/gpu/drm/analog/analog_drm_crtc.h create mode 100644 drivers/gpu/drm/analog/analog_drm_drv.c create mode 100644 drivers/gpu/drm/analog/analog_drm_drv.h create mode 100644 drivers/gpu/drm/analog/analog_drm_encoder.c create mode 100644 drivers/gpu/drm/analog/analog_drm_encoder.h create mode 100644 drivers/gpu/drm/analog/analog_drm_fbdev.c create mode 100644 drivers/gpu/drm/analog/analog_drm_fbdev.h create mode 100644 drivers/gpu/drm/analog/analog_drm_gem.c create mode 100644 drivers/gpu/drm/analog/analog_drm_gem.h diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 2418429a98360..22b39c118f4c4 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -6,7 +6,7 @@ # menuconfig DRM tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)" - depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU + depends on (AGP || AGP=n) && !EMULATED_CMPXCHG select I2C select I2C_ALGOBIT help @@ -159,6 +159,15 @@ config DRM_SAVAGE Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister chipset. If M is selected the module will be called savage. +config DRM_ENCODER_ADV7511 + tristate "AV7511 encoder" + depends on I2C && DRM + select REGMAP_I2C + select DRM_KMS_HELPER + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + source "drivers/gpu/drm/exynos/Kconfig" source "drivers/gpu/drm/vmwgfx/Kconfig" diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 0cde1b80fdb19..e42d623b99e9b 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -2,17 +2,17 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -ccflags-y := -Iinclude/drm +ccflags-y := -Iinclude/drm -DDEBUG drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ drm_context.o drm_dma.o \ - drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \ + drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \ drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \ drm_crtc.o drm_modes.o drm_edid.o \ drm_info.o drm_debugfs.o drm_encoder_slave.o \ - drm_trace_points.o drm_global.o drm_usb.o + drm_trace_points.o drm_global.o drm_usb.o drm_gem.o drm-$(CONFIG_COMPAT) += drm_ioc32.o @@ -37,4 +37,5 @@ obj-$(CONFIG_DRM_VIA) +=via/ obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/ obj-$(CONFIG_DRM_EXYNOS) +=exynos/ obj-$(CONFIG_DRM_GMA500) += gma500/ +obj-y += analog/ obj-y += i2c/ diff --git a/drivers/gpu/drm/analog/Kconfig b/drivers/gpu/drm/analog/Kconfig new file mode 100644 index 0000000000000..48e69ece8526b --- /dev/null +++ b/drivers/gpu/drm/analog/Kconfig @@ -0,0 +1,20 @@ +config DRM_ANALOG + tristate "DRM Support for Samsung SoC ANALOG Series" + depends on DRM && PLAT_SAMSUNG + default n + select DRM_KMS_HELPER + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE + help + Choose this option if you have a Samsung SoC ANALOG chipset. + If M is selected the module will be called analogdrm. + +config DRM_ANALOG_FIMD + tristate "Exynos DRM FIMD" + depends on DRM_ANALOG + default n + help + Choose this option if you want to use Exynos FIMD for DRM. + If M is selected, the module will be called analog_drm_fimd diff --git a/drivers/gpu/drm/analog/Makefile b/drivers/gpu/drm/analog/Makefile new file mode 100644 index 0000000000000..147ce59d69ab3 --- /dev/null +++ b/drivers/gpu/drm/analog/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the drm device driver. This driver provides support for the +# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. + +analogdrm-y := analog_drm_encoder.o analog_drm_crtc.o analog_drm_drv.o \ + analog_drm_gem.o analog_drm_fbdev.o + +obj-y += analogdrm.o diff --git a/drivers/gpu/drm/analog/analog_drm_buf.c b/drivers/gpu/drm/analog/analog_drm_buf.c new file mode 100644 index 0000000000000..4e8092519fb8d --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_buf.c @@ -0,0 +1,76 @@ +#include +#include + +#include "analog_drm_drv.h" +#include "analog_drm_gem.h" +#include "analog_drm_buf.h" + +static int lowlevel_buffer_allocate(struct drm_device *dev, + struct analog_drm_gem_buf *buffer) +{ + + buffer->kvaddr = dma_alloc_writecombine(dev->dev, buffer->size, + &buffer->dma_addr, GFP_KERNEL); + if (!buffer->kvaddr) { + DRM_ERROR("failed to allocate buffer. %ld\n", buffer->size); + return -ENOMEM; + } + + DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n", + (unsigned long)buffer->kvaddr, + (unsigned long)buffer->dma_addr, + buffer->size); + + return 0; +} + +static void lowlevel_buffer_deallocate(struct drm_device *dev, + struct analog_drm_gem_buf *buffer) +{ + + if (buffer->dma_addr && buffer->size) + dma_free_coherent(dev->dev, buffer->size, buffer->kvaddr, + (dma_addr_t)buffer->dma_addr); + else + DRM_DEBUG_KMS("buffer data are invalid.\n"); +} + +struct analog_drm_gem_buf *analog_drm_buf_create(struct drm_device *dev, + unsigned int size) +{ + struct analog_drm_gem_buf *buffer; + + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (!buffer) { + DRM_ERROR("failed to allocate analog_drm_gem_buf.\n"); + return ERR_PTR(-ENOMEM); + } + + buffer->size = size; + + /* + * allocate memory region with size and set the memory information + * to vaddr and dma_addr of a buffer object. + */ + if (lowlevel_buffer_allocate(dev, buffer) < 0) { + kfree(buffer); + buffer = NULL; + return ERR_PTR(-ENOMEM); + } + + return buffer; +} + +void analog_drm_buf_destroy(struct drm_device *dev, + struct analog_drm_gem_buf *buffer) +{ + if (!buffer) { + DRM_DEBUG_KMS("buffer is null.\n"); + return; + } + + lowlevel_buffer_deallocate(dev, buffer); + + kfree(buffer); + buffer = NULL; +} diff --git a/drivers/gpu/drm/analog/analog_drm_crtc.c b/drivers/gpu/drm/analog/analog_drm_crtc.c new file mode 100644 index 0000000000000..9536e0bb4d655 --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_crtc.c @@ -0,0 +1,174 @@ +#include +#include +#include +#include + +#include "analog_drm_crtc.h" +#include "analog_drm_fbdev.h" +#include "analog_drm_drv.h" +#include "analog_drm_encoder.h" +#include "analog_drm_gem.h" + +#define to_analog_crtc(x) container_of(x, struct analog_drm_crtc,\ + drm_crtc) + +struct analog_drm_crtc { + struct drm_crtc drm_crtc; + struct dma_chan *dma; + struct xilinx_dma_config dma_config; + int mode; +}; + +static int analog_drm_crtc_update(struct drm_crtc *crtc) +{ + struct analog_drm_crtc *analog_crtc = to_analog_crtc(crtc); + struct drm_display_mode *mode = &crtc->mode; + struct drm_framebuffer *fb = crtc->fb; + struct dma_async_tx_descriptor *desc; + struct analog_drm_gem_obj *obj; + size_t offset; + + if (!mode || !fb) + return -EINVAL; + + if (analog_crtc->mode == DRM_MODE_DPMS_ON) { + obj = analog_drm_fb_get_gem_obj(fb); + if (!obj) + return -EINVAL; + + analog_crtc->dma_config.hsize = mode->hdisplay * fb->bits_per_pixel / 8; + analog_crtc->dma_config.vsize = mode->vdisplay; + analog_crtc->dma_config.stride = fb->pitches[0]; + + dmaengine_device_control(analog_crtc->dma, DMA_SLAVE_CONFIG, + (unsigned long)&analog_crtc->dma_config); + + offset = crtc->x * fb->bits_per_pixel / 8 + crtc->y * fb->pitches[0]; + + desc = dmaengine_prep_slave_single(analog_crtc->dma, + obj->dma_addr + offset, mode->vdisplay * fb->pitches[0], + DMA_MEM_TO_DEV, 0); + if (!desc) { + pr_err("Failed to prepare DMA descriptor\n"); + return -ENOMEM; + } else { + dmaengine_submit(desc); + dma_async_issue_pending(analog_crtc->dma); + } + } else { + dmaengine_terminate_all(analog_crtc->dma); + } + + return 0; +} + +static void analog_drm_crtc_dpms(struct drm_crtc *crtc, int mode) +{ + struct analog_drm_crtc *analog_crtc = to_analog_crtc(crtc); + + if (analog_crtc->mode != mode) { + analog_crtc->mode = mode; + analog_drm_crtc_update(crtc); + } +} + +static void analog_drm_crtc_prepare(struct drm_crtc *crtc) +{ + struct analog_drm_crtc *analog_crtc = to_analog_crtc(crtc); + + dmaengine_terminate_all(analog_crtc->dma); +} + +static void analog_drm_crtc_commit(struct drm_crtc *crtc) +{ + struct analog_drm_crtc *analog_crtc = to_analog_crtc(crtc); + + analog_crtc->mode = DRM_MODE_DPMS_ON; + analog_drm_crtc_update(crtc); +} + +static bool +analog_drm_crtc_mode_fixup(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static int +analog_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, int x, int y, + struct drm_framebuffer *old_fb) +{ + /* We do everything in commit() */ + return 0; +} + +static int analog_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb) +{ + return analog_drm_crtc_update(crtc); +} + +static void analog_drm_crtc_load_lut(struct drm_crtc *crtc) +{ + /* drm framework doesn't check NULL */ +} + +static struct drm_crtc_helper_funcs analog_crtc_helper_funcs = { + .dpms = analog_drm_crtc_dpms, + .prepare = analog_drm_crtc_prepare, + .commit = analog_drm_crtc_commit, + .mode_fixup = analog_drm_crtc_mode_fixup, + .mode_set = analog_drm_crtc_mode_set, + .mode_set_base = analog_drm_crtc_mode_set_base, + .load_lut = analog_drm_crtc_load_lut, +}; + +static void analog_drm_crtc_destroy(struct drm_crtc *crtc) +{ + struct analog_drm_crtc *analog_crtc = to_analog_crtc(crtc); + + drm_crtc_cleanup(crtc); + kfree(analog_crtc); +} + +static struct drm_crtc_funcs analog_crtc_funcs = { + .set_config = drm_crtc_helper_set_config, + .destroy = analog_drm_crtc_destroy, +}; + +static bool xlnx_pcm_filter(struct dma_chan *chan, void *param) +{ + struct xlnx_pcm_dma_params *p = param; + + return chan->device->dev->of_node == p->of_node && + chan->chan_id == p->chan_id; +} + +struct drm_crtc *analog_drm_crtc_create(struct drm_device *dev) +{ + struct analog_drm_private *p = dev->dev_private; + struct analog_drm_crtc *analog_crtc; + struct drm_crtc *crtc; + dma_cap_mask_t mask; + + analog_crtc = kzalloc(sizeof(*analog_crtc), GFP_KERNEL); + if (!analog_crtc) { + DRM_ERROR("failed to allocate analog crtc\n"); + return ERR_PTR(-ENOMEM); + } + + crtc = &analog_crtc->drm_crtc; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_PRIVATE, mask); + + analog_crtc->dma = dma_request_channel(mask, xlnx_pcm_filter, &p->dma_params); + + drm_crtc_init(dev, crtc, &analog_crtc_funcs); + drm_crtc_helper_add(crtc, &analog_crtc_helper_funcs); + + return crtc; +} diff --git a/drivers/gpu/drm/analog/analog_drm_crtc.h b/drivers/gpu/drm/analog/analog_drm_crtc.h new file mode 100644 index 0000000000000..6585042d154b6 --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_crtc.h @@ -0,0 +1,9 @@ +#ifndef _ANALOG_DRM_CRTC_H_ +#define _ANALOG_DRM_CRTC_H_ + +struct drm_device; +struct drm_crtc; + +struct drm_crtc* analog_drm_crtc_create(struct drm_device *dev); + +#endif diff --git a/drivers/gpu/drm/analog/analog_drm_drv.c b/drivers/gpu/drm/analog/analog_drm_drv.c new file mode 100644 index 0000000000000..5406ccc291a51 --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_drv.c @@ -0,0 +1,219 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "analog_drm_drv.h" +#include "analog_drm_crtc.h" +#include "analog_drm_encoder.h" +#include "analog_drm_fbdev.h" +#include "analog_drm_gem.h" + +#define DRIVER_NAME "analog_drm" +#define DRIVER_DESC "ANALOG DRM" +#define DRIVER_DATE "20110530" +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 0 + +static struct platform_device *analog_drm_pdev; +static struct i2c_adapter *slave_adapter; +static struct i2c_adapter *ddc_adapter; + +static int analog_drm_load(struct drm_device *dev, unsigned long flags) +{ + struct analog_drm_private *private; + struct of_phandle_args dma_spec; + struct device_node *of_node; + int ret; + + ret = of_parse_phandle_with_args(analog_drm_pdev->dev.of_node, "dma-request", "#dma-cells", + 0, &dma_spec); + if (ret) { + return ret; + } + + private = kzalloc(sizeof(struct analog_drm_private), GFP_KERNEL); + if (!private) + return -ENOMEM; + + dev->dev_private = (void *)private; + + private->dma_params.of_node = dma_spec.np; + private->dma_params.chan_id = dma_spec.args[0]; + + drm_mode_config_init(dev); + + /* init kms poll for handling hpd */ + drm_kms_helper_poll_init(dev); + + analog_drm_mode_config_init(dev); + + private->crtc = analog_drm_crtc_create(dev); + if (IS_ERR(private->crtc)) { + ret = PTR_ERR(private->crtc); + goto err_crtc; + } + + of_node = dev->platformdev->dev.of_node; + private->base = of_iomap(of_node, 0); + private->base_clock = of_iomap(of_node, 1); + + private->ddc_adapter = ddc_adapter; + private->slave_adapter = slave_adapter; + + analog_drm_encoder_create(dev); + ret = analog_drm_fbdev_init(dev); + if (ret) { + DRM_ERROR("failed to initialize drm fbdev\n"); + goto err_drm_device; + } + + return 0; + +err_drm_device: +/* analog_drm_device_unregister(dev);*/ +err_crtc: + drm_mode_config_cleanup(dev); + kfree(private); + + return ret; +} + +static int analog_drm_unload(struct drm_device *dev) +{ + analog_drm_fbdev_fini(dev); + /*analog_drm_device_unregister(dev);*/ + drm_kms_helper_poll_fini(dev); + drm_mode_config_cleanup(dev); + kfree(dev->dev_private); + + return 0; +} + +static void analog_drm_lastclose(struct drm_device *dev) +{ + analog_drm_fbdev_restore_mode(dev); +} + +static struct vm_operations_struct analog_drm_gem_vm_ops = { + .fault = analog_drm_gem_fault, + .open = drm_gem_vm_open, + .close = drm_gem_vm_close, +}; + +static const struct file_operations analog_drm_driver_fops = { + .owner = THIS_MODULE, + .open = drm_open, + .mmap = analog_drm_gem_mmap, + .poll = drm_poll, + .read = drm_read, + .unlocked_ioctl = drm_ioctl, + .release = drm_release, +}; + +static struct drm_driver analog_drm_driver = { + .driver_features = DRIVER_BUS_PLATFORM | + DRIVER_MODESET | DRIVER_GEM, + .load = analog_drm_load, + .unload = analog_drm_unload, + .lastclose = analog_drm_lastclose, + .gem_free_object = analog_drm_gem_free_object, + .gem_vm_ops = &analog_drm_gem_vm_ops, + .dumb_create = analog_drm_gem_dumb_create, + .dumb_map_offset = analog_drm_gem_dumb_map_offset, + .dumb_destroy = analog_drm_gem_dumb_destroy, + .fops = &analog_drm_driver_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, +}; + +static void drm_register_work(struct work_struct *work) +{ + drm_platform_init(&analog_drm_driver, analog_drm_pdev); +} + +static DECLARE_WORK(register_work, drm_register_work); + +static int analog_drm_attach_i2c_adapter(struct device *dev, void *data) +{ + struct device_node *of_node; + + if (dev->type != &i2c_adapter_type) + return 0; + + if (analog_drm_pdev == NULL || dev->of_node == NULL) + return 0; + + if (/*ddc_adapter && */slave_adapter) + return 0; + + of_node = analog_drm_pdev->dev.of_node; + + +/* if (dev->of_node == of_parse_phandle(of_node, "ddc_adapter", 0)) + ddc_adapter = to_i2c_adapter(dev); + else*/ if (dev->of_node == of_parse_phandle(of_node, "slave_adapter", 0)) + slave_adapter = to_i2c_adapter(dev); + + if (/*ddc_adapter && */slave_adapter) + schedule_work(®ister_work); + + return 0; +} + +static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct device *dev = data; + + switch (action) { + case BUS_NOTIFY_ADD_DEVICE: + analog_drm_attach_i2c_adapter(dev, NULL); + } + + return 0; +} + +static struct notifier_block i2cdev_notifier = { + .notifier_call = i2cdev_notifier_call, +}; + +static int analog_drm_platform_probe(struct platform_device *pdev) +{ + analog_drm_pdev = pdev; + bus_register_notifier(&i2c_bus_type, &i2cdev_notifier); + i2c_for_each_dev(NULL, analog_drm_attach_i2c_adapter); + + return 0; +} + +static int analog_drm_platform_remove(struct platform_device *pdev) +{ + drm_platform_exit(&analog_drm_driver, pdev); + return 0; +} +static const struct of_device_id adv7511_encoder_of_match[] __devinitconst = { + { .compatible = "adi,cf-adv7x11-core-1.00.a", }, + {}, +}; +MODULE_DEVICE_TABLE(of, adv7511_encoder_of_match); + +static struct platform_driver adv7511_encoder_driver = { + .driver = { + .name = "cf-adv7x11-core", + .owner = THIS_MODULE, + .of_match_table = adv7511_encoder_of_match, + }, + .probe = analog_drm_platform_probe, + .remove = __devexit_p(analog_drm_platform_remove), +}; +module_platform_driver(adv7511_encoder_driver); diff --git a/drivers/gpu/drm/analog/analog_drm_drv.h b/drivers/gpu/drm/analog/analog_drm_drv.h new file mode 100644 index 0000000000000..89cc9e59f5256 --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_drv.h @@ -0,0 +1,28 @@ +#ifndef _ANALOG_DRM_DRV_H_ +#define _ANALOG_DRM_DRV_H_ + +#include +#include + +struct xlnx_pcm_dma_params { + struct device_node *of_node; + int chan_id; +}; + +struct analog_drm_fbdev; +struct analog_drm_encoder; + +struct analog_drm_private { + struct analog_drm_fbdev *fbdev; + struct drm_crtc *crtc; + struct analog_drm_encoder *encoder; + struct i2c_adapter *ddc_adapter; + struct i2c_adapter *slave_adapter; + + void __iomem *base; + void __iomem *base_clock; + + struct xlnx_pcm_dma_params dma_params; +}; + +#endif diff --git a/drivers/gpu/drm/analog/analog_drm_encoder.c b/drivers/gpu/drm/analog/analog_drm_encoder.c new file mode 100644 index 0000000000000..7ac1c28ed80c1 --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_encoder.c @@ -0,0 +1,692 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "analog_drm_drv.h" + +#include "../i2c/adv7511.h" + +#define ANALOG_REG_CTRL 0x04 +#define ANALOG_REG_HTIMING1 0x08 +#define ANALOG_REG_HTIMING2 0x0C +/* +#define ANALOG_REG_VTIMING 0x0c +*/ +#define ANALOG_REG_VTIMING1 0x10 +#define ANALOG_REG_VTIMING2 0x14 +#define ANALOG_REG_STATUS 0x10 +#define ANALOG_REG_COLOR_PATTERN 0x1c + +#define ANALOG_CTRL_ENABLE BIT(0) +#define ANALOG_CTRL_CSC_BYPASS BIT(1) +#define ANALOG_CTRL_TPG_ENABLE BIT(2) + +#define ANALOG_STATUS_VMDA_UNDERFLOW BIT(4) +#define ANALOG_STATUS_VMDA_OVERFLOW BIT(3) +#define ANALOG_STATUS_VMDA_BE_ERROR BIT(2) +#define ANALOG_STATUS_VMDA_TPM_OOS BIT(1) +#define ANALOG_STATUS_HDMI_TPM_OOS BIT(0) + +#define ANALOG_COLOR_PATTERN_ENABLE BIT(24) + +static struct debugfs_reg32 analog_drm_encoder_debugfs_regs[] = { + { "Control", ANALOG_REG_CTRL }, + { "HTiming1", ANALOG_REG_HTIMING1 }, + { "HTiming2", ANALOG_REG_HTIMING2 }, + { "VTiming1", ANALOG_REG_VTIMING1 }, + { "VTiming2", ANALOG_REG_VTIMING2 }, + { "Status", ANALOG_REG_STATUS }, +}; + +static uint16_t adv7511_csc_ycbcr_to_rgb[] = { + 0x0734, 0x04ad, 0x0000, 0x1c1b, + 0x1ddc, 0x04ad, 0x1f24, 0x0135, + 0x0000, 0x04ad, 0x087c, 0x1b77, +}; +/* +static struct adv7511_video_input_config adv7511_config = { + .id = ADV7511_INPUT_ID_16_20_24BIT_YCbCr422_EMBEDDED_SYNC, + .input_style = ADV7511_INPUT_STYLE1, + .sync_pulse = ADV7511_INPUT_SYNC_PULSE_NONE, + .clock_delay = ADV7511_INPUT_CLOCK_DELAY_NONE, + .ddr_negative_clock_delay = ADV7511_INPUT_ADJUST_DELAY_NONE, + .reverse_bitorder = 0, + .ddr_alignment = 0, + .bit_justification = 0, + .ddr_edge_rising = false, + .vsync_polartity_low = false, + .hsync_polartity_low = false, + .up_conversion_first_order_interpolation = false, + .enable_ddr_negative_clock_delay = false, + .input_color_depth = ADV7511_INPUT_COLOR_DEPTH_8BIT, + .output_format = ADV7511_OUTPUT_FORMAT_RGB_444, + .csc_enable = true, + .csc_coefficents = adv7511_csc_ycbcr_to_rgb, + .csc_scaling_factor = 3, + .bit_justification = ADV7511_INPUT_BIT_JUSTIFICATION_LEFT, +}; +*/ + +static struct adv7511_video_input_config adv7511_config = { + .id = ADV7511_INPUT_ID_16_20_24BIT_YCbCr422_SEPARATE_SYNC, + .input_style = ADV7511_INPUT_STYLE1, + .sync_pulse = ADV7511_INPUT_SYNC_PULSE_NONE, + .clock_delay = ADV7511_INPUT_CLOCK_DELAY_NONE, + .ddr_negative_clock_delay = ADV7511_INPUT_ADJUST_DELAY_NONE, + .reverse_bitorder = 0, + .ddr_alignment = 0, + .ddr_edge_rising = false, + .vsync_polartity_low = false, + .hsync_polartity_low = false, + .up_conversion_first_order_interpolation = false, + .enable_ddr_negative_clock_delay = false, + .input_color_depth = ADV7511_INPUT_COLOR_DEPTH_8BIT, + .output_format = ADV7511_OUTPUT_FORMAT_RGB_444, + .csc_enable = true, + .csc_coefficents = adv7511_csc_ycbcr_to_rgb, + .csc_scaling_factor = 3, + .bit_justification = ADV7511_INPUT_BIT_JUSTIFICATION_RIGHT, + .tmds_clock_inversion = true, +}; + +struct analog_drm_encoder { + struct drm_encoder_slave encoder; + struct drm_connector connector; + + struct debugfs_regset32 regset; +}; + +#define to_analog_encoder(x) container_of(x, struct analog_drm_encoder,\ + encoder.base) + +static inline struct drm_encoder *connector_to_encoder(struct drm_connector *connector) +{ + struct analog_drm_encoder *enc = container_of(connector, struct analog_drm_encoder, connector); + return &enc->encoder.base; +} + +static int analog_drm_connector_init(struct drm_device *dev, + struct drm_connector *connector, struct drm_encoder *encoder); + +static inline struct drm_encoder_slave_funcs * +get_slave_funcs(struct drm_encoder *enc) +{ + if (!to_encoder_slave(enc)) + return NULL; + + return to_encoder_slave(enc)->slave_funcs; +} + +static int debugfs_cp_get(void *data, u64 *val) +{ + struct analog_drm_private *private = data; + *val = ioread32(private->base + ANALOG_REG_COLOR_PATTERN); + return 0; +} +static int debugfs_cp_set(void *data, u64 val) +{ + struct analog_drm_private *private = data; + iowrite32(0x0000000, private-> base + ANALOG_REG_COLOR_PATTERN); + iowrite32(0x1000000 | val, private-> base + ANALOG_REG_COLOR_PATTERN); + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(fops_cp, debugfs_cp_get, debugfs_cp_set, "0x%08llx\n"); + +static void analog_drm_encoder_dpms(struct drm_encoder *encoder, int mode) +{ + struct analog_drm_encoder *analog_encoder = to_analog_encoder(encoder); + struct drm_connector *connector = &analog_encoder->connector; + struct analog_drm_private *private = encoder->dev->dev_private; + struct drm_encoder_slave_funcs *sfuncs = get_slave_funcs(encoder); + struct adv7511_video_input_config config = adv7511_config; + + switch (mode) { + case DRM_MODE_DPMS_ON: + iowrite32(ANALOG_CTRL_ENABLE, private->base + ANALOG_REG_CTRL); + if (connector->display_info.raw_edid) { + struct edid *edid = (struct edid *)connector->display_info.raw_edid; + config.hdmi_mode = drm_detect_hdmi_monitor(edid); + } else { + config.hdmi_mode = false; + } + + printk("raw_edid: %p %d\n", connector->display_info.raw_edid, + connector->display_info.color_formats); + + if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB422) && + config.hdmi_mode) { + config.csc_enable = false; + config.output_format = ADV7511_OUTPUT_FORMAT_YCBCR_422; + pr_info("Using YCbCr output\n"); + } else { + config.csc_enable = true; + config.output_format = ADV7511_OUTPUT_FORMAT_RGB_444; + pr_info("Using RGB output\n"); + } + + sfuncs->set_config(encoder, &config); + break; + default: + iowrite32(0, private->base + ANALOG_REG_CTRL); + break; + } + + if (sfuncs && sfuncs->dpms) + sfuncs->dpms(encoder, mode); +} + +struct analog_drm_crtc_clock_setting { + long clock; + uint32_t settings[10]; +}; + +static const struct analog_drm_crtc_clock_setting clock_settings[] = { + { /* 162 Mhz */ + .clock = 162000, + .settings = { + 0x00c4, 0x0080, 0x2042, 0x0209, 0x0080, + 0x023f, 0x7c01, 0x7fe9, 0x0100, 0x1090, + }, + }, + { /* 154 Mhz */ + .clock = 154000, + .settings = { + 0x0082, 0x0000, 0x2187, 0x0514, 0x0000, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x1090, + }, + }, + { /* 148.5 Mhz */ + .clock = 148500, + .settings = { + 0x00c3, 0x0000, 0x2146, 0x0619, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x8090, + }, + }, + { /* 146.25 Mhz */ + .clock = 146250, + .settings = { + 0x00c3, 0x0000, 0x2187, 0x071d, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x8090, + }, + }, + { /* 138.5 Mhz */ + .clock = 138500, + .settings = { + 0x0083, 0x0080, 0x2187, 0x0597, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x1090, + }, + }, + { /* 135 Mhz */ + .clock = 135000, + .settings = { + 0x0104, 0x0000, 0x2083, 0x034e, 0x0080, + 0x015e, 0x7c01, 0x7fe9, 0x0100, 0x8090, + }, + }, + { /* 108 Mhz */ + .clock = 108000, + .settings = { + 0x0145, 0x0000, 0x2083, 0x034e, 0x0080, + 0x015e, 0x7c01, 0x7fe9, 0x0100, 0x8090, + }, + }, + { /* 106.5 Mhz */ + .clock = 106500, + .settings = { + 0x00c4, 0x0080, 0x2146, 0x0515, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x1090, + }, + }, + { /* 78.8 Mhz */ + .clock = 78800, + .settings = { + 0x0146, 0x0080, 0x2042, 0x0187, 0x0080, + 0x02ee, 0x7c01, 0x7fe9, 0x0800, 0x9090, + }, + }, + { /* 75 Mhz */ + .clock = 75000, + .settings = { + 0x0104, 0x0000, 0x1041, 0x0042, 0x0080, + 0x03e8, 0x2001, 0x23e9, 0x0100, 0x9890, + }, + }, + { /* 74.25 Mhz */ + .clock = 74250, + .settings = { + 0x0186, 0x0000, 0x2146, 0x0619, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x8090, + }, + }, + { /* 65 Mhz */ + .clock = 65000, + .settings = { + 0x0145, 0x0000, 0x0082, 0x0187, 0x0080, + 0x02ee, 0x7c01, 0x7fe9, 0x0800, 0x9090, + }, + }, + { /* 57.284 Mhz */ + .clock = 57284, + .settings = { + 0x0208, 0x0000, 0x0186, 0x06dc, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x8090, + }, + }, + { /* 50 Mhz */ + .clock = 50000, + .settings = { + 0x0186, 0x0000, 0x1041, 0x0042, 0x0080, + 0x03e8, 0x2001, 0x23e9, 0x0100, 0x9890, + }, + }, + { /* 49.5 Mhz */ + .clock = 49500, + .settings = { + 0x02cb, 0x0000, 0x2105, 0x0619, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x8090, + }, + }, + { /* 40 Mhz */ + .clock = 40000, + .settings = { + 0x01c8, 0x0080, 0x1041, 0x0042, 0x0080, + 0x03e8, 0x2001, 0x23e9, 0x0100, 0x9890, + }, + }, + { /* 36 Mhz */ + .clock = 36000, + .settings = { + 0x030d, 0x0080, 0x0041, 0x0105, 0x0080, + 0x03e8, 0x6401, 0x67e9, 0x0100, 0x9090, + }, + }, + { /* 31.5 Mhz */ + .clock = 31500, + .settings = { + 0x030d, 0x0080, 0x0208, 0x07e0, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x8090, + }, + }, + { /* 30.24 Mhz */ + .clock = 30240, + .settings = { + 0x038f, 0x0080, 0x2187, 0x071d, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x8090, + }, + }, + { /* 28.32 Mhz */ + .clock = 28320, + .settings = { + 0x030d, 0x0080, 0x2187, 0x05d7, 0x0000, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x1090, + }, + + }, + { /* 27 Mhz */ + .clock = 27000, + .settings = { + 0x0514, 0x0000, 0x2083, 0x034e, 0x0080, + 0x015e, 0x7c01, 0x7fe9, 0x0100, 0x8090, + }, + }, + { /* 25.2 MHz */ + .clock = 25200, + .settings = { + 0x030d, 0x0080, 0x028a, 0x07e0, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x8090, + }, + }, + { /* 25.175 Mhz */ + .clock = 25175, + .settings = { + 0x034d, 0x0000, 0x2146, 0x0492, 0x0000, + 0x0113, 0x7c01, 0x7fe9, 0x0100, 0x8090, + }, + }, + { /* 13.5 MHz */ + .clock = 13500, + .settings = { + 0x0a28, 0x0000, 0x2083, 0x034e, 0x0080, + 0x015e, 0x7c01, 0x7fe9, 0x0100, 0x8090, + }, + }, +}; + +static const struct analog_drm_crtc_clock_setting *analog_drm_encoder_closest_clock(long clock) +{ + const struct analog_drm_crtc_clock_setting *best_setting = NULL; + long best_diff, diff; + unsigned int i; + + best_diff = LONG_MAX; + + for (i = 0; i < ARRAY_SIZE(clock_settings); ++i) { + diff = abs(clock_settings[i].clock - clock); + if (diff < best_diff) { + best_diff = diff; + best_setting = &clock_settings[i]; + } + } + + return best_setting; +} + +static bool analog_drm_encoder_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) +{ + struct drm_encoder_slave_funcs *sfuncs = get_slave_funcs(encoder); + + if (sfuncs && sfuncs->mode_fixup) + return sfuncs->mode_fixup(encoder, mode, adjusted_mode); + + return true; +} + +static void analog_drm_write_clock_reg(struct analog_drm_private *private, + unsigned int reg, unsigned int val) +{ + iowrite32(val, private->base_clock + reg); +} + +#define ANALOG_CLOCK_REG_UPDATE_ENABLE 0x04 +#define ANALOG_CLOCK_REG_CONFIG(x) (0x08 + (0x04 * x)) + +void xslcr_set_fpga3_clock(unsigned int rate); + +static int analog_drm_encoder_set_clock(struct analog_drm_private *private, long clock) +{ + const struct analog_drm_crtc_clock_setting *best_setting; + unsigned int i; + +/* + xslcr_set_fpga3_clock(clock * 1000); + return 0; +*/ + xslcr_set_fpga3_clock(200000000); + best_setting = analog_drm_encoder_closest_clock(clock); + + if (!best_setting) + return -EINVAL; + + printk("setting clock to: %lu\n", best_setting->clock); + + analog_drm_write_clock_reg(private, ANALOG_CLOCK_REG_UPDATE_ENABLE, 0); + + for (i = 0; i < 10; ++i) { + analog_drm_write_clock_reg(private, ANALOG_CLOCK_REG_CONFIG(i), + best_setting->settings[i]); + } + + analog_drm_write_clock_reg(private, ANALOG_CLOCK_REG_UPDATE_ENABLE, 1); + + return 0; +} + +static void analog_drm_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) +{ + struct drm_encoder_slave_funcs *sfuncs = get_slave_funcs(encoder); + struct analog_drm_private *private = encoder->dev->dev_private; + unsigned int h_de_min, h_de_max; + unsigned int v_de_min, v_de_max; + unsigned int htotal, hactive; + unsigned int vtotal, vactive; + + if (sfuncs && sfuncs->mode_set) + sfuncs->mode_set(encoder, mode, adjusted_mode); + + htotal = mode->htotal; + hactive = mode->hdisplay; + vtotal = mode->vtotal; + vactive = mode->vdisplay; + + hactive = mode->hsync_end - mode->hsync_start; + vactive = mode->vsync_end - mode->vsync_start; + + h_de_min = htotal - mode->hsync_start; + h_de_max = h_de_min + mode->hdisplay; + v_de_min = vtotal - mode->vsync_start; + v_de_max = v_de_min + mode->vdisplay; + + iowrite32((hactive << 16) | htotal, private->base + ANALOG_REG_HTIMING1); + iowrite32((h_de_min << 16) | h_de_max, private->base + ANALOG_REG_HTIMING2); + iowrite32((vactive << 16) | vtotal, private->base + ANALOG_REG_VTIMING1); + iowrite32((v_de_min << 16) | v_de_max, private->base + ANALOG_REG_VTIMING2); + + analog_drm_encoder_set_clock(private, mode->clock); +} + +static void analog_drm_encoder_commit(struct drm_encoder *encoder) +{ + analog_drm_encoder_dpms(encoder, DRM_MODE_DPMS_ON); +} + +static void analog_drm_encoder_prepare(struct drm_encoder *encoder) +{ + analog_drm_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); +} + +static struct drm_crtc *analog_drm_encoder_get_crtc(struct drm_encoder *encoder) +{ + return encoder->crtc; +} + +static struct drm_encoder_helper_funcs analog_encoder_helper_funcs = { + .dpms = analog_drm_encoder_dpms, + .mode_fixup = analog_drm_encoder_mode_fixup, + .mode_set = analog_drm_encoder_mode_set, + .prepare = analog_drm_encoder_prepare, + .commit = analog_drm_encoder_commit, + .get_crtc = analog_drm_encoder_get_crtc, +}; + +static void analog_drm_encoder_destroy(struct drm_encoder *encoder) +{ + struct drm_encoder_slave_funcs *sfuncs = get_slave_funcs(encoder); + struct analog_drm_encoder *analog_encoder = + to_analog_encoder(encoder); + + if (sfuncs && sfuncs->destroy) + sfuncs->destroy(encoder); + + drm_encoder_cleanup(encoder); + encoder->dev->mode_config.num_encoder--; + kfree(analog_encoder); +} + +static struct drm_encoder_funcs analog_encoder_funcs = { + .destroy = analog_drm_encoder_destroy, +}; + +static struct i2c_board_info fmc_adv7511_encoder_info[] = { + { + I2C_BOARD_INFO("adv7511", 0x39), + }, + { } +}; + +struct drm_encoder *analog_drm_encoder_create(struct drm_device *dev) +{ + struct drm_encoder *encoder; + struct drm_connector *connector; + struct analog_drm_encoder *analog_encoder; + struct analog_drm_private *priv = dev->dev_private; + + analog_encoder = kzalloc(sizeof(*analog_encoder), GFP_KERNEL); + if (!analog_encoder) { + DRM_ERROR("failed to allocate encoder\n"); + return NULL; + } + + encoder = &analog_encoder->encoder.base; + encoder->possible_crtcs = 1; + + drm_encoder_init(dev, encoder, &analog_encoder_funcs, + DRM_MODE_ENCODER_TMDS); + drm_encoder_helper_add(encoder, &analog_encoder_helper_funcs); + + drm_i2c_encoder_init(dev, to_encoder_slave(encoder), + priv->slave_adapter, + fmc_adv7511_encoder_info); + + connector = &analog_encoder->connector; + + analog_drm_connector_init(dev, connector, encoder); + + analog_encoder->regset.base = priv->base; + analog_encoder->regset.regs = analog_drm_encoder_debugfs_regs; + analog_encoder->regset.nregs = ARRAY_SIZE(analog_drm_encoder_debugfs_regs); + debugfs_create_regset32(dev_name(dev->dev), S_IRUGO, NULL, &analog_encoder->regset); + debugfs_create_file("color_pattern", 0666, NULL, priv, &fops_cp); + + return encoder; +} + +static struct i2c_adapter *analog_drm_get_ddc_adapter(struct drm_device *dev) +{ + struct analog_drm_private *priv = dev->dev_private; + + return priv->ddc_adapter; +} + +static int analog_drm_connector_get_modes(struct drm_connector *connector) +{ + struct drm_encoder *encoder = connector_to_encoder(connector); + struct drm_encoder_slave_funcs *sfuncs = get_slave_funcs(encoder); + struct i2c_adapter *adapter = analog_drm_get_ddc_adapter(connector->dev); + struct edid *edid; + int count = 0; + + + kfree(connector->display_info.raw_edid); + connector->display_info.raw_edid = NULL; + + if (adapter) { + edid = drm_get_edid(connector, adapter); + drm_mode_connector_update_edid_property(connector, + edid); + count += drm_add_edid_modes(connector, edid); + } else { + if (sfuncs && sfuncs->get_modes) + count += sfuncs->get_modes(encoder, connector); + } + + return count; +} + +static int analog_drm_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + const struct analog_drm_crtc_clock_setting *best_setting; + long diff; + + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) + return MODE_NO_DBLESCAN; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + return MODE_NO_INTERLACE; + + return MODE_OK; + + best_setting = analog_drm_encoder_closest_clock(mode->clock); + + diff = abs(best_setting->clock - mode->clock); + + /* Allow for a 1% tolerance */ + if (diff / (mode->clock / 100) > 1) + return false; + + return MODE_OK; +} + +static struct drm_encoder *analog_drm_best_encoder(struct drm_connector *connector) +{ + return connector_to_encoder(connector); +} + +static struct drm_connector_helper_funcs analog_connector_helper_funcs = { + .get_modes = analog_drm_connector_get_modes, + .mode_valid = analog_drm_connector_mode_valid, + .best_encoder = analog_drm_best_encoder, +}; + +static enum drm_connector_status +analog_drm_connector_detect(struct drm_connector *connector, bool force) +{ + enum drm_connector_status status = connector_status_unknown; + struct drm_encoder *encoder = connector_to_encoder(connector); + struct drm_encoder_slave_funcs *sfuncs = get_slave_funcs(encoder); + struct i2c_adapter *adapter = analog_drm_get_ddc_adapter(connector->dev); + struct edid *edid; + + if (adapter) { + kfree(connector->display_info.raw_edid); + connector->display_info.raw_edid = NULL; + + edid = drm_get_edid(connector, adapter); + if (edid) + status = connector_status_connected; + else + status = connector_status_disconnected; + } + + if (sfuncs && sfuncs->detect) + status = sfuncs->detect(encoder, connector); + + return status; +} + +static void analog_drm_connector_destroy(struct drm_connector *connector) +{ + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); +} + +static struct drm_connector_funcs analog_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = analog_drm_connector_detect, + .destroy = analog_drm_connector_destroy, +}; + +static int analog_drm_connector_init(struct drm_device *dev, + struct drm_connector *connector, struct drm_encoder *encoder) +{ + int type; + int err; + + type = DRM_MODE_CONNECTOR_HDMIA; + connector->polled = DRM_CONNECTOR_POLL_CONNECT | + DRM_CONNECTOR_POLL_DISCONNECT; + + drm_connector_init(dev, connector, &analog_connector_funcs, type); + drm_connector_helper_add(connector, &analog_connector_helper_funcs); + + err = drm_sysfs_connector_add(connector); + if (err) + goto err_connector; + + connector->encoder = encoder; + + err = drm_mode_connector_attach_encoder(connector, encoder); + if (err) { + DRM_ERROR("failed to attach a connector to a encoder\n"); + goto err_sysfs; + } + + return 0; + +err_sysfs: + drm_sysfs_connector_remove(connector); +err_connector: + drm_connector_cleanup(connector); + return err; +} diff --git a/drivers/gpu/drm/analog/analog_drm_encoder.h b/drivers/gpu/drm/analog/analog_drm_encoder.h new file mode 100644 index 0000000000000..575903b71789f --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_encoder.h @@ -0,0 +1,6 @@ +#ifndef _ANALOG_DRM_ENCODER_H_ +#define _ANALOG_DRM_ENCODER_H_ + +struct drm_encoder *analog_drm_encoder_create(struct drm_device *dev); + +#endif diff --git a/drivers/gpu/drm/analog/analog_drm_fbdev.c b/drivers/gpu/drm/analog/analog_drm_fbdev.c new file mode 100644 index 0000000000000..bf15d03b3532f --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_fbdev.c @@ -0,0 +1,338 @@ +#include +#include +#include +#include +#include + +#include "analog_drm_drv.h" +#include "analog_drm_gem.h" + +#define MAX_CONNECTOR 1 +#define PREFERRED_BPP 32 + +#define to_analog_fbdev(x) container_of(x, struct analog_drm_fbdev,\ + fb_helper) + +#define to_analog_fb(x) container_of(x, struct analog_drm_fb,\ + fb) + +struct analog_drm_fb { + struct drm_framebuffer fb; + struct analog_drm_gem_obj *obj; +}; + +struct analog_drm_fbdev { + struct drm_fb_helper fb_helper; + struct analog_drm_fb *fb; +}; + +static void analog_drm_fb_destroy(struct drm_framebuffer *fb) +{ + struct analog_drm_fb *afb = to_analog_fb(fb); + + if (afb->obj) + drm_gem_object_unreference_unlocked(&afb->obj->base); + + drm_framebuffer_cleanup(fb); + kfree(afb); +} + +static int analog_drm_fb_create_handle(struct drm_framebuffer *fb, + struct drm_file *file_priv, unsigned int *handle) +{ + struct analog_drm_fb *afb = to_analog_fb(fb); + + return drm_gem_handle_create(file_priv, + &afb->obj->base, handle); +} + +static struct drm_framebuffer_funcs analog_drm_fb_funcs = { + .destroy = analog_drm_fb_destroy, + .create_handle = analog_drm_fb_create_handle, +}; + +static struct analog_drm_fb *analog_drm_fb_alloc(struct drm_device *dev, + struct drm_mode_fb_cmd2 *mode_cmd, struct analog_drm_gem_obj *obj) +{ + struct analog_drm_fb *afb; + int ret; + + afb = kzalloc(sizeof(*afb), GFP_KERNEL); + if (!afb) + return ERR_PTR(-ENOMEM); + + afb->obj = obj; + ret = drm_framebuffer_init(dev, &afb->fb, &analog_drm_fb_funcs); + if (ret) { + DRM_ERROR("failed to initialize framebuffer.\n"); + return ERR_PTR(ret); + } + + drm_helper_mode_fill_fb_struct(&afb->fb, mode_cmd); + + return afb; +} + +static struct drm_framebuffer *analog_drm_fb_create(struct drm_device *dev, + struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd) +{ + struct analog_drm_fb *afb; + struct drm_gem_object *obj; + + obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); + if (!obj) { + DRM_ERROR("failed to lookup gem object.\n"); + return ERR_PTR(-ENXIO); + } + + afb = analog_drm_fb_alloc(dev, mode_cmd, to_analog_gem_obj(obj)); + if (IS_ERR(afb)) + return ERR_CAST(afb); + + return &afb->fb; +} + +struct analog_drm_gem_obj *analog_drm_fb_get_gem_obj(struct drm_framebuffer *fb) +{ + struct analog_drm_fb *afb = to_analog_fb(fb); + + return afb->obj; +} + +static void analog_drm_output_poll_changed(struct drm_device *dev) +{ + struct analog_drm_private *private = dev->dev_private; + + if (private->fbdev) + drm_fb_helper_hotplug_event(&private->fbdev->fb_helper); +} + +static struct drm_mode_config_funcs analog_drm_mode_config_funcs = { + .fb_create = analog_drm_fb_create, + .output_poll_changed = analog_drm_output_poll_changed, +}; + +void analog_drm_mode_config_init(struct drm_device *dev) +{ + dev->mode_config.min_width = 0; + dev->mode_config.min_height = 0; + + /* + * set max width and height as default value(4096x4096). + * this value would be used to check framebuffer size limitation + * at drm_mode_addfb(). + */ + dev->mode_config.max_width = 4096; + dev->mode_config.max_height = 4096; + + dev->mode_config.funcs = &analog_drm_mode_config_funcs; +} + +static struct fb_ops analog_drm_fb_ops = { + .owner = THIS_MODULE, + .fb_fillrect = sys_fillrect, + .fb_copyarea = sys_copyarea, + .fb_imageblit = sys_imageblit, + .fb_check_var = drm_fb_helper_check_var, + .fb_set_par = drm_fb_helper_set_par, + .fb_blank = drm_fb_helper_blank, + .fb_pan_display = drm_fb_helper_pan_display, + .fb_setcmap = drm_fb_helper_setcmap, +}; + +static int analog_drm_fbdev_create(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + struct analog_drm_fbdev *afbdev = to_analog_fbdev(helper); + struct drm_mode_fb_cmd2 mode_cmd = { 0 }; + struct drm_device *dev = helper->dev; + struct analog_drm_gem_obj *obj; + struct drm_framebuffer *fb; + unsigned long offset; + struct fb_info *fbi; + size_t size; + int ret; + + DRM_DEBUG_KMS("%s\n", __FILE__); + + DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n", + sizes->surface_width, sizes->surface_height, + sizes->surface_bpp); + + sizes->surface_bpp = 32; + mode_cmd.width = sizes->surface_width; + mode_cmd.height = sizes->surface_height; + mode_cmd.pitches[0] = sizes->surface_width * (sizes->surface_bpp >> 3); + mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, + sizes->surface_depth); + + size = mode_cmd.pitches[0] * mode_cmd.height; + obj = analog_drm_gem_alloc(dev, size); + if (!obj) + return -ENOMEM; + + fbi = framebuffer_alloc(0, dev->dev); + if (!fbi) { + DRM_ERROR("failed to allocate fb info.\n"); + ret = -ENOMEM; + goto out; + } + + afbdev->fb = analog_drm_fb_alloc(dev, &mode_cmd, obj); + if (IS_ERR(afbdev->fb)) { + DRM_ERROR("failed to create drm framebuffer.\n"); + ret = PTR_ERR(afbdev->fb); + goto out; + } + + fb = &afbdev->fb->fb; + helper->fb = fb; + helper->fbdev = fbi; + + fbi->par = helper; + fbi->flags = FBINFO_FLAG_DEFAULT; + fbi->fbops = &analog_drm_fb_ops; + + ret = fb_alloc_cmap(&fbi->cmap, 256, 0); + if (ret) { + DRM_ERROR("failed to allocate cmap.\n"); + goto out; + } + + drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); + drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height); + + offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3); + offset += fbi->var.yoffset * fb->pitches[0]; + + dev->mode_config.fb_base = (resource_size_t)obj->dma_addr; + fbi->screen_base = obj->addr + offset; + fbi->fix.smem_start = (unsigned long)(obj->dma_addr + offset); + fbi->screen_size = size; + fbi->fix.smem_len = size; + + return 0; + +/* TODO: gem obj, free fb */ +out: + return ret; +} + +static int analog_drm_fbdev_probe(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + int ret = 0; + + if (!helper->fb) { + ret = analog_drm_fbdev_create(helper, sizes); + if (ret < 0) { + DRM_ERROR("failed to create fbdev.\n"); + return ret; + } + + /* + * fb_helper expects a value more than 1 if succeed + * because register_framebuffer() should be called. + */ + ret = 1; + } + + + printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__); + return ret; +} + +static struct drm_fb_helper_funcs analog_drm_fb_helper_funcs = { + .fb_probe = analog_drm_fbdev_probe, +}; + +int analog_drm_fbdev_init(struct drm_device *dev) +{ + struct analog_drm_fbdev *afbdev; + struct analog_drm_private *private = dev->dev_private; + struct drm_fb_helper *helper; + int ret; + + DRM_DEBUG_KMS("%s\n", __FILE__); + + afbdev = kzalloc(sizeof(*afbdev), GFP_KERNEL); + if (!afbdev) { + DRM_ERROR("failed to allocate drm fbdev.\n"); + return -ENOMEM; + } + + afbdev->fb_helper.funcs = &analog_drm_fb_helper_funcs; + private->fbdev = afbdev; + helper = &afbdev->fb_helper; + + ret = drm_fb_helper_init(dev, helper, 1, 1); + if (ret < 0) { + DRM_ERROR("failed to initialize drm fb helper.\n"); + goto err_init; + } + + ret = drm_fb_helper_single_add_all_connectors(helper); + if (ret < 0) { + DRM_ERROR("failed to register drm_fb_helper_connector.\n"); + goto err_setup; + + } + + ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP); + if (ret < 0) { + DRM_ERROR("failed to set up hw configuration.\n"); + goto err_setup; + } + + return 0; + +err_setup: + drm_fb_helper_fini(helper); + +err_init: + private->fbdev = NULL; + kfree(afbdev); + + return ret; +} + +void analog_drm_fbdev_fini(struct drm_device *dev) +{ + struct analog_drm_private *private = dev->dev_private; + struct analog_drm_fbdev *afbdev; + + if (!private || !private->fbdev) + return; + + afbdev = private->fbdev; + + private->fbdev = NULL; + + if (afbdev->fb_helper.fbdev) { + struct fb_info *info; + int ret; + + info = afbdev->fb_helper.fbdev; + ret = unregister_framebuffer(info); + if (ret < 0) + DRM_DEBUG_KMS("failed unregister_framebuffer()\n"); + + if (info->cmap.len) + fb_dealloc_cmap(&info->cmap); + + framebuffer_release(info); + } + + drm_fb_helper_fini(&afbdev->fb_helper); + kfree(afbdev); +} + +void analog_drm_fbdev_restore_mode(struct drm_device *dev) +{ + struct analog_drm_private *private = dev->dev_private; + + if (!private || !private->fbdev) + return; + + drm_fb_helper_restore_fbdev_mode(&private->fbdev->fb_helper); +} diff --git a/drivers/gpu/drm/analog/analog_drm_fbdev.h b/drivers/gpu/drm/analog/analog_drm_fbdev.h new file mode 100644 index 0000000000000..4732524c199b5 --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_fbdev.h @@ -0,0 +1,12 @@ +#ifndef _ANALOG_DRM_FBDEV_H_ +#define _ANALOG_DRM_FBDEV_H_ + +int analog_drm_fbdev_init(struct drm_device *dev); +void analog_drm_fbdev_fini(struct drm_device *dev); +void analog_drm_fbdev_restore_mode(struct drm_device *dev); + +void analog_drm_mode_config_init(struct drm_device *dev); + +struct analog_drm_gem_obj *analog_drm_fb_get_gem_obj(struct drm_framebuffer *fb); + +#endif diff --git a/drivers/gpu/drm/analog/analog_drm_gem.c b/drivers/gpu/drm/analog/analog_drm_gem.c new file mode 100644 index 0000000000000..ed7cd929f03d9 --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_gem.c @@ -0,0 +1,242 @@ +#include +#include + +#include + +#include "analog_drm_drv.h" +#include "analog_drm_gem.h" + +static unsigned int convert_to_vm_err_msg(int msg) +{ + unsigned int out_msg; + + switch (msg) { + case 0: + case -ERESTARTSYS: + case -EINTR: + out_msg = VM_FAULT_NOPAGE; + break; + + case -ENOMEM: + out_msg = VM_FAULT_OOM; + break; + + default: + out_msg = VM_FAULT_SIGBUS; + break; + } + + return out_msg; +} + +static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj) +{ + DRM_DEBUG_KMS("%s\n", __FILE__); + + return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT; +} + +struct analog_drm_gem_obj *analog_drm_gem_alloc(struct drm_device *dev, + size_t size) +{ + struct analog_drm_gem_obj *analog_gem_obj; + struct drm_gem_object *obj; + dma_addr_t dma_addr; + void *addr; + int ret; + + size = roundup(size, PAGE_SIZE); + + addr = dma_alloc_writecombine(dev->dev, size, &dma_addr, GFP_KERNEL); + if (!addr) + return ERR_PTR(-ENOMEM); + + analog_gem_obj = kzalloc(sizeof(*analog_gem_obj), GFP_KERNEL); + if (!analog_gem_obj) { + DRM_ERROR("failed to allocate analog gem object.\n"); + ret = -ENOMEM; + goto err_alloc; + } + + analog_gem_obj->addr = addr; + analog_gem_obj->dma_addr = dma_addr; + + obj = &analog_gem_obj->base; + + ret = drm_gem_object_init(dev, obj, size); + if (ret < 0) { + DRM_ERROR("failed to initialize gem object.\n"); + ret = -EINVAL; + goto err_object_init; + } + + return analog_gem_obj; + +err_object_init: + kfree(analog_gem_obj); +err_alloc: + dma_free_coherent(dev->dev, size, addr, dma_addr); + + return ERR_PTR(ret); +} + +static struct analog_drm_gem_obj *analog_drm_gem_create(struct drm_device *dev, + struct drm_file *file, unsigned int *handle, unsigned long size) +{ + struct analog_drm_gem_obj *obj; + int ret; + + obj = analog_drm_gem_alloc(dev, size); + if (IS_ERR(obj)) + return obj; + + ret = drm_gem_handle_create(file, &obj->base, handle); + if (ret) { + drm_gem_object_release(&obj->base); + kfree(obj); + return ERR_PTR(ret); + } + + drm_gem_object_unreference(&obj->base); + return 0; +} + +void analog_drm_gem_free_object(struct drm_gem_object *gem_obj) +{ + struct analog_drm_gem_obj *analog_gem_obj = to_analog_gem_obj(gem_obj); + + DRM_DEBUG_KMS("%s\n", __FILE__); + + DRM_DEBUG_KMS("handle count = %d\n", + atomic_read(&gem_obj->handle_count)); + + if (gem_obj->map_list.map) + drm_gem_free_mmap_offset(gem_obj); + + /* release file pointer to gem object. */ + drm_gem_object_release(gem_obj); + + + dma_free_coherent(gem_obj->dev->dev, analog_gem_obj->base.size, + analog_gem_obj->addr, analog_gem_obj->dma_addr); + + kfree(analog_gem_obj); +} + +int analog_drm_gem_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, struct drm_mode_create_dumb *args) +{ + struct analog_drm_gem_obj *analog_gem_obj; + + args->pitch = args->width * args->bpp >> 3; + args->size = args->pitch * args->height; + + analog_gem_obj = analog_drm_gem_create(dev, file_priv, &args->handle, + args->size); + if (IS_ERR(analog_gem_obj)) + return PTR_ERR(analog_gem_obj); + + return 0; +} + +int analog_drm_gem_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, uint64_t *offset) +{ + struct analog_drm_gem_obj *analog_gem_obj; + struct drm_gem_object *obj; + int ret = 0; + + DRM_DEBUG_KMS("%s\n", __FILE__); + + mutex_lock(&dev->struct_mutex); + + obj = drm_gem_object_lookup(dev, file_priv, handle); + if (!obj) { + DRM_ERROR("failed to lookup gem object.\n"); + mutex_unlock(&dev->struct_mutex); + return -EINVAL; + } + + if (!obj->map_list.map) { + ret = drm_gem_create_mmap_offset(obj); + if (ret) + goto out; + } + + analog_gem_obj = to_analog_gem_obj(obj); + + *offset = get_gem_mmap_offset(&analog_gem_obj->base); + DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset); + +out: + drm_gem_object_unreference(obj); + + + mutex_unlock(&dev->struct_mutex); + + return ret; +} + +int analog_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct drm_gem_object *obj = vma->vm_private_data; + struct analog_drm_gem_obj *analog_gem_obj = to_analog_gem_obj(obj); + struct drm_device *dev = obj->dev; + unsigned int i, page_num; + unsigned long address; + unsigned long pfn; + pgoff_t page_offset; + int ret = 0; + + page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + page_offset = ((unsigned long)vmf->virtual_address - + vma->vm_start) >> PAGE_SHIFT; + + mutex_lock(&dev->struct_mutex); + + pfn = (((unsigned long)analog_gem_obj->dma_addr) >> + PAGE_SHIFT) + page_offset; + + address = (unsigned long)vmf->virtual_address; + + for (i = 0; i < page_num; i++) { + ret = vm_insert_mixed(vma, address, pfn); + if (ret == -EBUSY || (ret != 0 && i > 0)) + break; + else if (ret) + return (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS; + address += PAGE_SIZE; + pfn++; + } + + mutex_unlock(&dev->struct_mutex); + + return convert_to_vm_err_msg(ret); +} + +int analog_drm_gem_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, unsigned int handle) +{ + return drm_gem_handle_delete(file_priv, handle); +} + +int analog_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) +{ + int ret; + + DRM_DEBUG_KMS("%s\n", __FILE__); + + /* set vm_area_struct. */ + ret = drm_gem_mmap(filp, vma); + if (ret < 0) { + DRM_ERROR("failed to mmap.\n"); + return ret; + } + + vma->vm_flags &= ~VM_PFNMAP; + vma->vm_flags |= VM_MIXEDMAP; + + return ret; +} + +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/analog/analog_drm_gem.h b/drivers/gpu/drm/analog/analog_drm_gem.h new file mode 100644 index 0000000000000..68a0b26063ae1 --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_gem.h @@ -0,0 +1,52 @@ +#ifndef _ANALOG_DRM_GEM_H_ +#define _ANALOG_DRM_GEM_H_ + +#define to_analog_gem_obj(x) container_of(x,\ + struct analog_drm_gem_obj, base) + +/* + * analog drm buffer structure. + * + * @base: a gem object. + * - a new handle to this gem object would be created + * by drm_gem_handle_create(). + * @addr: kernel virtual address to allocated memory region. + * @dma_addr: bus address(accessed by dma) to allocated memory region. + * - this address could be physical address without IOMMU and + * device address with IOMMU. + * + */ +struct analog_drm_gem_obj { + struct drm_gem_object base; + void *addr; + dma_addr_t dma_addr; +}; + +struct analog_drm_gem_obj *analog_drm_gem_alloc(struct drm_device *dev, + size_t size); + +/* free gem object. */ +void analog_drm_gem_free_object(struct drm_gem_object *gem_obj); + +/* create memory region for drm framebuffer. */ +int analog_drm_gem_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, struct drm_mode_create_dumb *args); + +/* map memory region for drm framebuffer to user space. */ +int analog_drm_gem_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, uint64_t *offset); + +/* page fault handler and mmap fault address(virtual) to physical memory. */ +int analog_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); + +/* + * destroy memory region allocated. + * - a gem handle and physical memory region pointed by a gem object + * would be released by drm_gem_handle_delete(). + */ +int analog_drm_gem_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, unsigned int handle); + +int analog_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); + +#endif diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 5e818a808acee..8a746e30d54b8 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -424,6 +424,8 @@ EXPORT_SYMBOL(drm_crtc_cleanup); void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode) { + printk("new mode: %dx%d %dx%d %d\n", mode->hdisplay, mode->vdisplay, + mode->htotal, mode->vtotal, mode->clock); list_add(&mode->head, &connector->probed_modes); } EXPORT_SYMBOL(drm_mode_probed_add); diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 84a4a809793ff..9f10b9d377633 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -370,7 +370,6 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, * a chance to reject the mode entirely. */ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - if (encoder->crtc != crtc) continue; encoder_funcs = encoder->helper_private; diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index b1804a2c0f361..4b2204835f243 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -282,8 +282,8 @@ static bool drm_edid_is_zero(u8 *in_edid, int length) return true; } -static u8 * -drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) +struct edid *drm_do_get_edid(struct drm_connector *connector, + int (*get_edid_block)(void *, unsigned char *buf, int, int), void *data) { int i, j = 0, valid_extensions = 0; u8 *block, *new; @@ -293,7 +293,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) /* base block fetch */ for (i = 0; i < 4; i++) { - if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH)) + if (get_edid_block(data, block, 0, EDID_LENGTH)) goto out; if (drm_edid_block_valid(block)) break; @@ -307,7 +307,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) /* if there's no extensions, we're done */ if (block[0x7e] == 0) - return block; + return (struct edid *)block; new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL); if (!new) @@ -316,7 +316,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) for (j = 1; j <= block[0x7e]; j++) { for (i = 0; i < 4; i++) { - if (drm_do_probe_ddc_edid(adapter, + if (get_edid_block(data, block + (valid_extensions + 1) * EDID_LENGTH, j, EDID_LENGTH)) goto out; @@ -340,7 +340,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) block = new; } - return block; + return (struct edid *)block; carp: dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n", @@ -350,6 +350,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) kfree(block); return NULL; } +EXPORT_SYMBOL_GPL(drm_do_get_edid); /** * Probe DDC presence. @@ -381,8 +382,7 @@ struct edid *drm_get_edid(struct drm_connector *connector, struct edid *edid = NULL; if (drm_probe_ddc(adapter)) - edid = (struct edid *)drm_do_get_edid(connector, adapter); - + edid = drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter); connector->display_info.raw_edid = (char *)edid; return edid; diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 6d7b083c5b776..85fc436187808 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -37,7 +37,7 @@ #include "drmP.h" #include "drm_core.h" -unsigned int drm_debug = 0; /* 1 to enable debug output */ +unsigned int drm_debug = 0xff; /* 1 to enable debug output */ EXPORT_SYMBOL(drm_debug); unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */ diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 74ce916846296..489f3efd68b32 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -239,4 +239,7 @@ int drm_av_sync_delay(struct drm_connector *connector, struct drm_connector *drm_select_eld(struct drm_encoder *encoder, struct drm_display_mode *mode); +struct edid *drm_do_get_edid(struct drm_connector *connector, + int (*get_edid_block)(void *, unsigned char *buf, int, int), void *data); + #endif /* __DRM_EDID_H__ */ From 91080308e891adbda9a9678177dfd12317f473f9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 6 Feb 2012 10:08:32 +0100 Subject: [PATCH 013/261] ASoC: Add dmaengine PCM helper functions This patch adds a set of functions which are intended to be used when implementing a dmaengine based sound PCM driver. Signed-off-by: Lars-Peter Clausen --- include/sound/dmaengine_pcm.h | 47 ++++++ sound/soc/Kconfig | 3 + sound/soc/Makefile | 3 + sound/soc/soc-dmaengine-pcm.c | 281 ++++++++++++++++++++++++++++++++++ 4 files changed, 334 insertions(+) create mode 100644 include/sound/dmaengine_pcm.h create mode 100644 sound/soc/soc-dmaengine-pcm.c diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h new file mode 100644 index 0000000000000..129783da65876 --- /dev/null +++ b/include/sound/dmaengine_pcm.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#ifndef __SOUND_DMAENGINE_PCM_H__ +#define __SOUND_DMAENGINE_PCM_H__ + +#include +#include + +/** + * snd_pcm_substream_to_dma_direction - Get dma_transfer_direction for a PCM + * substream + * @substream: PCM substream + */ +static inline enum dma_transfer_direction +snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return DMA_MEM_TO_DEV; + else + return DMA_DEV_TO_MEM; +} + +void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data); +void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream); + +int snd_soc_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config); +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data); +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream); + +#endif diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 35e662d270e61..91c985599d32c 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -25,6 +25,9 @@ if SND_SOC config SND_SOC_AC97_BUS bool +config SND_SOC_DMAENGINE_PCM + bool + # All the supported SoCs source "sound/soc/atmel/Kconfig" source "sound/soc/au1x/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 9ea8ac827adc3..2feaf376e94b2 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,6 +1,9 @@ snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o snd-soc-core-objs += soc-pcm.o soc-io.o +snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o +obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o + obj-$(CONFIG_SND_SOC) += snd-soc-core.o obj-$(CONFIG_SND_SOC) += codecs/ obj-$(CONFIG_SND_SOC) += atmel/ diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c new file mode 100644 index 0000000000000..643147ef885fe --- /dev/null +++ b/sound/soc/soc-dmaengine-pcm.c @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Based on: + * imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer + * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc. + * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek + * Copyright (C) 2006 Applied Data Systems + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include + +struct dmaengine_pcm_runtime_data { + struct dma_chan *dma_chan; + + unsigned int pos; + + void *data; +}; + +static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( + const struct snd_pcm_substream *substream) +{ + return substream->runtime->private_data; +} + +/** + * snd_dmaengine_pcm_set_data - Set dmaengine substream private data + * @substream: PCM substream + * @data: Data to set + */ +void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + prtd->data = data; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_data); + +/** + * snd_dmaengine_pcm_get_data - Get dmaeinge substream private data + * @substream: PCM substream + * + * Returns the data previously set with snd_dmaengine_pcm_set_data + */ +void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + return prtd->data; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_data); + +/** + * snd_soc_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config + * @substream: PCM substream + * @params: hw_params + * @slave_config: DMA slave config + * + * This function can be used to initialize a dma_slave_config from a substream + * and hw_params in a dmaengine based PCM driver implementation. + */ +int snd_soc_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config) +{ + enum dma_slave_buswidth buswidth; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; + break; + case SNDRV_PCM_FORMAT_S16_LE: + buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; + break; + case SNDRV_PCM_FORMAT_S18_3LE: + case SNDRV_PCM_FORMAT_S20_3LE: + case SNDRV_PCM_FORMAT_S24_LE: + case SNDRV_PCM_FORMAT_S32_LE: + buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; + break; + default: + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->direction = DMA_MEM_TO_DEV; + slave_config->dst_addr_width = buswidth; + } else { + slave_config->direction = DMA_DEV_TO_MEM; + slave_config->src_addr_width = buswidth; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_hwparams_to_dma_slave_config); + +static void dmaengine_pcm_dma_complete(void *arg) +{ + struct snd_pcm_substream *substream = arg; + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + prtd->pos += snd_pcm_lib_period_bytes(substream); + if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream)) + prtd->pos = 0; + + snd_pcm_period_elapsed(substream); +} + +static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct dma_chan *chan = prtd->dma_chan; + struct dma_async_tx_descriptor *desc; + enum dma_transfer_direction direction; + + direction = snd_pcm_substream_to_dma_direction(substream); + + prtd->pos = 0; + + desc = chan->device->device_prep_dma_cyclic(chan, + substream->runtime->dma_addr, + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream), direction); + + if (!desc) + return -ENOMEM; + + desc->callback = dmaengine_pcm_dma_complete; + desc->callback_param = substream; + dmaengine_submit(desc); + + return 0; +} + +/** + * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation + * @substream: PCM substream + * @cmd: Trigger command + * + * Returns 0 on success, a negative error code otherwise. + * + * This function can be used as the PCM trigger callback for dmaengine based PCM + * driver implementations. + */ +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + int ret; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + ret = dmaengine_pcm_prepare_and_submit(substream); + if (ret) + return ret; + dma_async_issue_pending(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + dmaengine_resume(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + dmaengine_pause(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_STOP: + dmaengine_terminate_all(prtd->dma_chan); + break; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger); + +/** + * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function can be used as the PCM pointer callback for dmaengine based PCM + * driver implementations. + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + return bytes_to_frames(substream->runtime, prtd->pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); + +static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd, + dma_filter_fn filter_fn, void *filter_data) +{ + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_CYCLIC, mask); + prtd->dma_chan = dma_request_channel(mask, filter_fn, filter_data); + + if (!prtd->dma_chan) + return -ENXIO; + + return 0; +} + +/** + * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream + * @substream: PCM substream + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * Returns 0 on success, a negative error code otherwise. + * + * This function will request a DMA channel using the passed filter function and + * data. The function should usually be called from the pcm open callback. + * + * Note that this function will use private_data field of the substream's + * runtime. So it is not availabe to your pcm driver implementation. If you need + * to keep additional data attached to a substream use + * snd_dmaeinge_pcm_{set,get}_data. + */ +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data) +{ + struct dmaengine_pcm_runtime_data *prtd; + int ret; + + ret = snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + return ret; + + prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); + if (!prtd) + return -ENOMEM; + + ret = dmaengine_pcm_request_channel(prtd, filter_fn, filter_data); + if (ret < 0) { + kfree(prtd); + return ret; + } + + substream->runtime->private_data = prtd; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); + +/** + * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream + * @substream: PCM substream + */ +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dma_release_channel(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); From 6e0f00ad4fde7cc92de133a553ecc2139f855d79 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 6 Mar 2012 19:34:23 +0100 Subject: [PATCH 014/261] ASoC: Add support for Xilinx FPGA based boards Signed-off-by: Lars-Peter Clausen --- sound/soc/Kconfig | 1 + sound/soc/Makefile | 1 + sound/soc/xlnx/Kconfig | 4 + sound/soc/xlnx/Makefile | 3 + sound/soc/xlnx/xilinx-pcm.c | 168 ++++++++++++++++++++++++++++++++++++ 5 files changed, 177 insertions(+) create mode 100644 sound/soc/xlnx/Kconfig create mode 100644 sound/soc/xlnx/Makefile create mode 100644 sound/soc/xlnx/xilinx-pcm.c diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 91c985599d32c..ee16413b81e15 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -48,6 +48,7 @@ source "sound/soc/s6000/Kconfig" source "sound/soc/sh/Kconfig" source "sound/soc/tegra/Kconfig" source "sound/soc/txx9/Kconfig" +source "sound/soc/xlnx/Kconfig" # Supported codecs source "sound/soc/codecs/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 2feaf376e94b2..d986d00f8907d 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_SND_SOC) += s6000/ obj-$(CONFIG_SND_SOC) += sh/ obj-$(CONFIG_SND_SOC) += tegra/ obj-$(CONFIG_SND_SOC) += txx9/ +obj-$(CONFIG_SND_SOC) += xlnx/ diff --git a/sound/soc/xlnx/Kconfig b/sound/soc/xlnx/Kconfig new file mode 100644 index 0000000000000..2db90a11e2a1f --- /dev/null +++ b/sound/soc/xlnx/Kconfig @@ -0,0 +1,4 @@ +config SND_SOC_XILINX + tristate "SoC Audio for Xilinx based boards" + depends on SND_SOC && (MICROBLAZE || ARCH_ZYNQ) + select SND_SOC_DMAENGINE_PCM diff --git a/sound/soc/xlnx/Makefile b/sound/soc/xlnx/Makefile new file mode 100644 index 0000000000000..d9c6b7496c087 --- /dev/null +++ b/sound/soc/xlnx/Makefile @@ -0,0 +1,3 @@ +snd-soc-xilinx-pcm-objs := xilinx-pcm.o + +obj-$(CONFIG_SND_SOC_XILINX) += snd-soc-xilinx-pcm.o diff --git a/sound/soc/xlnx/xilinx-pcm.c b/sound/soc/xlnx/xilinx-pcm.c new file mode 100644 index 0000000000000..a9680aa471917 --- /dev/null +++ b/sound/soc/xlnx/xilinx-pcm.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static const struct snd_pcm_hardware xlnx_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER, + .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S8, + .channels_min = 1, + .channels_max = UINT_MAX, + .period_bytes_min = 1024, + .period_bytes_max = (1 << 20) - 1, + .periods_min = 2, + .periods_max = UINT_MAX, + .buffer_bytes_max = ULONG_MAX, +}; + +static int xlnx_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); +} + +struct xlnx_pcm_dma_params { + struct device_node *of_node; + int chan_id; +}; + +static bool xlnx_pcm_filter(struct dma_chan *chan, void *param) +{ + struct xlnx_pcm_dma_params *p = param; + + return chan->device->dev->of_node == p->of_node && + chan->chan_id == p->chan_id; +} + +static int xlnx_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct device *dev = rtd->platform->dev; + struct xlnx_pcm_dma_params *params = dev_get_drvdata(dev); + int ret; + + ret = snd_soc_set_runtime_hwparams(substream, &xlnx_pcm_hardware); + if (ret) + return ret; + + return snd_dmaengine_pcm_open(substream, xlnx_pcm_filter, params); +} + +static int xlnx_pcm_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_card *card = rtd->card->snd_card; + + return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, + SNDRV_DMA_TYPE_DEV, + card->dev, 8 * 1024 * 1024, + xlnx_pcm_hardware.buffer_bytes_max); +} + +static int xlnx_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + return dma_mmap_coherent(substream->pcm->card->dev, vma, + runtime->dma_area, + runtime->dma_addr, + runtime->dma_bytes); + return remap_pfn_range(vma, vma->vm_start, + substream->dma_buffer.addr >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot); +} + +static struct snd_pcm_ops xlnx_pcm_ops = { + .open = xlnx_pcm_open, + .close = snd_dmaengine_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = xlnx_pcm_hw_params, + .hw_free = snd_pcm_lib_free_pages, + .trigger = snd_dmaengine_pcm_trigger, + .pointer = snd_dmaengine_pcm_pointer, + .mmap = xlnx_pcm_mmap, +}; + +static struct snd_soc_platform_driver xlnx_pcm_soc_platform = { + .pcm_new = xlnx_pcm_new, +/* .pcm_free = snd_pcm_lib_preallocate_free_for_all,*/ + .ops = &xlnx_pcm_ops, +}; + +static int __devinit xlnx_pcm_soc_platform_probe(struct platform_device *pdev) +{ + struct xlnx_pcm_dma_params *params; + struct of_phandle_args dma_spec; + int ret; + + params = devm_kzalloc(&pdev->dev, sizeof(*params), GFP_KERNEL); + if (!params) + return -ENOMEM; + + ret = of_parse_phandle_with_args(pdev->dev.of_node, "dma-request", + "#dma-cells", 0, &dma_spec); + if (ret) + return ret; + + params->of_node = dma_spec.np; + params->chan_id = dma_spec.args[0]; + + dev_set_drvdata(&pdev->dev, params); + + return snd_soc_register_platform(&pdev->dev, &xlnx_pcm_soc_platform); +} + +static int __devexit xlnx_pcm_soc_platform_remove(struct platform_device *pdev) +{ + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static const struct of_device_id xilinx_pcm_of_match[] __devinitconst = { + { .compatible = "xilinx-pcm-audio", }, + {}, +}; +MODULE_DEVICE_TABLE(of, xilinx_pcm_of_match); + +static struct platform_driver xlnx_pcm_driver = { + .driver = { + .name = "xilinx-pcm-audio", + .owner = THIS_MODULE, + .of_match_table = xilinx_pcm_of_match, + }, + .probe = xlnx_pcm_soc_platform_probe, + .remove = __devexit_p(xlnx_pcm_soc_platform_remove), +}; +module_platform_driver(xlnx_pcm_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("Xilinx DMA engine based audio DMA driver"); +MODULE_LICENSE("GPL"); From 51d07a10ed6c84198c9a3691a7e0645144034150 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 6 Mar 2012 19:23:18 +0100 Subject: [PATCH 015/261] ASoC: Add SPDIF DAI format Signed-off-by: Lars-Peter Clausen --- include/sound/soc-dai.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 2413acc54883a..ffd560e5aa15c 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -31,6 +31,7 @@ struct snd_pcm_substream; #define SND_SOC_DAIFMT_DSP_B 5 /* L data MSB during FRM LRC */ #define SND_SOC_DAIFMT_AC97 6 /* AC97 */ #define SND_SOC_DAIFMT_PDM 7 /* Pulse density modulation */ +#define SND_SOC_DAIFMT_SPDIF 8 /* SPDIF */ /* left and right justified also known as MSB and LSB respectively */ #define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J From 533e0768eaed57930ff13def773f4db0644f6085 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 6 Mar 2012 19:34:50 +0100 Subject: [PATCH 016/261] ASoC: Xilinx: Add AXI SPDIF driver Signed-off-by: Lars-Peter Clausen --- sound/soc/xlnx/Kconfig | 3 + sound/soc/xlnx/Makefile | 2 + sound/soc/xlnx/axi-spdif.c | 219 +++++++++++++++++++++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 sound/soc/xlnx/axi-spdif.c diff --git a/sound/soc/xlnx/Kconfig b/sound/soc/xlnx/Kconfig index 2db90a11e2a1f..21671714cbce9 100644 --- a/sound/soc/xlnx/Kconfig +++ b/sound/soc/xlnx/Kconfig @@ -2,3 +2,6 @@ config SND_SOC_XILINX tristate "SoC Audio for Xilinx based boards" depends on SND_SOC && (MICROBLAZE || ARCH_ZYNQ) select SND_SOC_DMAENGINE_PCM + +config SND_SOC_AXI_SPDIF + tristate diff --git a/sound/soc/xlnx/Makefile b/sound/soc/xlnx/Makefile index d9c6b7496c087..193a1d5aaff5c 100644 --- a/sound/soc/xlnx/Makefile +++ b/sound/soc/xlnx/Makefile @@ -1,3 +1,5 @@ snd-soc-xilinx-pcm-objs := xilinx-pcm.o +snd-soc-axi-spdif-objs := axi-spdif.o obj-$(CONFIG_SND_SOC_XILINX) += snd-soc-xilinx-pcm.o +obj-$(CONFIG_SND_SOC_AXI_SPDIF) += snd-soc-axi-spdif.o diff --git a/sound/soc/xlnx/axi-spdif.c b/sound/soc/xlnx/axi-spdif.c new file mode 100644 index 0000000000000..78d2a8ab28b49 --- /dev/null +++ b/sound/soc/xlnx/axi-spdif.c @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +struct axi_spdif { + void __iomem *base; + + unsigned int clock; + + struct debugfs_regset32 regset; +}; + +#define AXI_SPDIF_REG_CTRL 0x0 +#define AXI_SPDIF_REG_STAT 0x4 + +#define AXI_SPDIF_CTRL_TXDATA BIT(1) +#define AXI_SPDIF_CTRL_TXEN BIT(0) +#define AXI_SPDIF_CTRL_RATIO_OFFSET 8 +#define AXI_SPDIF_CTRL_RATIO_MASK (0xff << 8) + +static struct debugfs_reg32 axi_spdif_debugfs_regs[] = { + { "Control", AXI_SPDIF_REG_CTRL }, + { "Status", AXI_SPDIF_REG_STAT }, +}; + +static inline uint32_t axi_spdif_read(const struct axi_spdif *spdif, + unsigned int reg) +{ + return readl(spdif->base + reg); +} + +static inline void axi_spdif_write(const struct axi_spdif *spdif, + unsigned int reg, uint32_t value) +{ + writel(value, spdif->base + reg); +} + +static int axi_spdif_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai); + uint32_t ctrl = axi_spdif_read(spdif, AXI_SPDIF_REG_CTRL); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ctrl |= AXI_SPDIF_CTRL_TXDATA; + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ctrl &= ~AXI_SPDIF_CTRL_TXDATA; + break; + default: + return -EINVAL; + } + + axi_spdif_write(spdif, AXI_SPDIF_REG_CTRL, ctrl); + + return 0; +} + +static int axi_spdif_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai); + uint32_t ctrl = axi_spdif_read(spdif, AXI_SPDIF_REG_CTRL); + unsigned int ratio; + + ratio = DIV_ROUND_CLOSEST(spdif->clock, (params_rate(params) * 64 * 2)) - 1; + + ctrl &= ~AXI_SPDIF_CTRL_RATIO_MASK; + ctrl |= ratio << AXI_SPDIF_CTRL_RATIO_OFFSET; + + axi_spdif_write(spdif, AXI_SPDIF_REG_CTRL, ctrl); + + return 0; +} +/* +static int axi_spdif_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai); + uint32_t ctrl; + + if (dai->active) + return 0; + + ctrl = axi_spdif_read(spdif, AXI_SPDIF_REG_CTRL); + ctrl |= AXI_SPDIF_CTRL_TXEN; + axi_spdif_write(spdif, AXI_SPDIF_REG_CTRL, ctrl); + + return 0; +} + +static void axi_spdif_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai); + uint32_t ctrl; + + if (dai->active) + return; + + ctrl = axi_spdif_read(spdif, AXI_SPDIF_REG_CTRL); + ctrl &= ~AXI_SPDIF_CTRL_TXEN; + axi_spdif_write(spdif, AXI_SPDIF_REG_CTRL, ctrl); +} +*/ +static const struct snd_soc_dai_ops axi_spdif_dai_ops = { + .trigger = axi_spdif_trigger, + .hw_params = axi_spdif_hw_params, +}; + +static struct snd_soc_dai_driver axi_spdif_dai = { + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &axi_spdif_dai_ops, +}; + +static int __devinit axi_spdif_probe(struct platform_device *pdev) +{ + struct axi_spdif *spdif; + struct resource *res; + int ret; + + spdif = devm_kzalloc(&pdev->dev, sizeof(*spdif), GFP_KERNEL); + + if (!spdif) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + spdif->base = devm_request_and_ioremap(&pdev->dev, res); + if (!spdif->base) + return -EBUSY; + + platform_set_drvdata(pdev, spdif); + + of_property_read_u32(pdev->dev.of_node, "clock-frequency", &spdif->clock); + + ret = snd_soc_register_dai(&pdev->dev, &axi_spdif_dai); + + if (ret) { + dev_err(&pdev->dev, "Failed to register DAI\n"); + return ret; + } + + spdif->regset.base = spdif->base; + spdif->regset.regs = axi_spdif_debugfs_regs; + spdif->regset.nregs = ARRAY_SIZE(axi_spdif_debugfs_regs); + + debugfs_create_regset32(dev_name(&pdev->dev), 0777, NULL, &spdif->regset); + + axi_spdif_write(spdif, AXI_SPDIF_REG_CTRL, AXI_SPDIF_CTRL_TXEN); + + return 0; +} + +static int __devexit axi_spdif_dev_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dai(&pdev->dev); + + return 0; +} + +static const struct of_device_id axi_spdif_of_match[] __devinitconst = { + { .compatible = "adi,axi-spdif-tx-1.00.a", }, + {}, +}; +MODULE_DEVICE_TABLE(of, axi_spdif_of_match); + +static struct platform_driver axi_spdif_driver = { + .driver = { + .name = "axi-spdif", + .owner = THIS_MODULE, + .of_match_table = axi_spdif_of_match, + }, + .probe = axi_spdif_probe, + .remove = __devexit_p(axi_spdif_dev_remove), +}; +module_platform_driver(axi_spdif_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("AXI SPDIF driver"); +MODULE_LICENSE("GPL"); From d8dfbdbf9188375ef35b4856373edf0287b4c25c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 7 Mar 2012 10:09:24 +0100 Subject: [PATCH 017/261] ASoC: Xilinx: Add ADV7511 HDMI board driver Signed-off-by: Lars-Peter Clausen --- sound/soc/xlnx/Kconfig | 5 ++ sound/soc/xlnx/Makefile | 2 + sound/soc/xlnx/adv7511_hdmi.c | 90 +++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 sound/soc/xlnx/adv7511_hdmi.c diff --git a/sound/soc/xlnx/Kconfig b/sound/soc/xlnx/Kconfig index 21671714cbce9..69192fcbba0ea 100644 --- a/sound/soc/xlnx/Kconfig +++ b/sound/soc/xlnx/Kconfig @@ -5,3 +5,8 @@ config SND_SOC_XILINX config SND_SOC_AXI_SPDIF tristate + +config SND_SOC_ADV7511_HDMI + tristate "ADV7511 HDMI transmitter sound support" + depends on SND_SOC_XILINX + select SND_SOC_AXI_SPDIF diff --git a/sound/soc/xlnx/Makefile b/sound/soc/xlnx/Makefile index 193a1d5aaff5c..d758bbd0c28b4 100644 --- a/sound/soc/xlnx/Makefile +++ b/sound/soc/xlnx/Makefile @@ -1,5 +1,7 @@ snd-soc-xilinx-pcm-objs := xilinx-pcm.o snd-soc-axi-spdif-objs := axi-spdif.o +snd-soc-adv7511-hdmi-objs := adv7511_hdmi.o obj-$(CONFIG_SND_SOC_XILINX) += snd-soc-xilinx-pcm.o obj-$(CONFIG_SND_SOC_AXI_SPDIF) += snd-soc-axi-spdif.o +obj-$(CONFIG_SND_SOC_ADV7511_HDMI) += snd-soc-adv7511-hdmi.o diff --git a/sound/soc/xlnx/adv7511_hdmi.c b/sound/soc/xlnx/adv7511_hdmi.c new file mode 100644 index 0000000000000..79be998c40fd7 --- /dev/null +++ b/sound/soc/xlnx/adv7511_hdmi.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct snd_soc_dai_link hdmi_dai_link = { + .name = "HDMI", + .stream_name = "HDMI", +/* .cpu_dai_name = "75c00000.axi-spdif-tx", + .platform_name = "xilinx_pcm_audio.2",*/ + .codec_name = "adv7511.2-0039", + .codec_dai_name = "adv7511", + .dai_fmt = SND_SOC_DAIFMT_SPDIF | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, +}; + +static struct snd_soc_card hdmi_card = { + .name = "HDMI monitor", + .owner = THIS_MODULE, + .dai_link = &hdmi_dai_link, + .num_links = 1, +}; + +static int __devinit adv7511_hdmi_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &hdmi_card; + struct device_node *of_node = pdev->dev.of_node; + + if (!of_node) + return -ENXIO; + + card->dev = &pdev->dev; + +/* hdmi_dai_link.codec_of_node = of_parse_phandle(of_node, "audio-codec", 0);*/ + hdmi_dai_link.cpu_dai_of_node = of_parse_phandle(of_node, "cpu-dai", 0); + hdmi_dai_link.platform_of_node = of_parse_phandle(of_node, "pcm", 0); + + if (/*!hdmi_dai_link.codec_of_node || */!hdmi_dai_link.cpu_dai_of_node || + !hdmi_dai_link.platform_of_node) + return -ENXIO; + + return snd_soc_register_card(card); +} + +static int __devexit adv7511_hdmi_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + snd_soc_unregister_card(card); + + return 0; +} + +static const struct of_device_id adv7511_hdmi_of_match[] __devinitconst = { + { .compatible = "adv7511-hdmi-snd", }, + {}, +}; +MODULE_DEVICE_TABLE(of, adv7511_hdmi_of_match); + +static struct platform_driver hdmi_card_driver = { + .driver = { + .name = "adv7511-hdmi-snd", + .owner = THIS_MODULE, + .of_match_table = adv7511_hdmi_of_match, + .pm = &snd_soc_pm_ops, + }, + .probe = adv7511_hdmi_probe, + .remove = __devexit_p(adv7511_hdmi_remove), +}; +module_platform_driver(hdmi_card_driver); From a410fc7975454aab3e71a3182d5f7aa9dcb07096 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Mar 2012 10:45:21 +0100 Subject: [PATCH 018/261] regmap: rbtree: Fix register default look-up in sync The code currently passes the register offset in the current block to regcache_lookup_reg. This works fine as long as there is only one block and with base register of 0, but in all other cases it will look-up the default for a wrong register, which can cause unnecessary register writes. This patch fixes it by passing the actual register number to regcache_lookup_reg. Signed-off-by: Lars-Peter Clausen Cc: --- drivers/base/regmap/regcache-rbtree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c index 32620c4f16834..918997b17003a 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c @@ -376,7 +376,7 @@ static int regcache_rbtree_sync(struct regmap *map) map->cache_word_size); /* Is this the hardware default? If so skip. */ - ret = regcache_lookup_reg(map, i); + ret = regcache_lookup_reg(map, regtmp); if (ret > 0 && val == map->reg_defaults[ret].def) continue; From 37e13cb019b1321ce7b91bee1f7ee9ddf9014e5d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 10 Apr 2012 09:44:33 +0200 Subject: [PATCH 019/261] Increase DMA memory region We need this for now to be able to allocate the framebuffer memory region until we have CMA support. --- arch/arm/Kconfig | 2 +- arch/arm/include/asm/pgtable.h | 2 +- arch/arm/mach-zynq/common.c | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3ac754fabd4a7..96e3b953d9d63 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1732,7 +1732,7 @@ config FORCE_MAX_ZONEORDER int "Maximum zone order" if ARCH_SHMOBILE range 11 64 if ARCH_SHMOBILE default "9" if SA1111 - default "11" + default "15" help The kernel memory allocator divides physically contiguous memory blocks into "zones", where each zone is a power of two number of diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index f66626d71e7d1..48d9d1474f1c4 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -40,7 +40,7 @@ */ #define VMALLOC_OFFSET (8*1024*1024) #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) -#define VMALLOC_END 0xff000000UL +#define VMALLOC_END 0xfd000000UL #define LIBRARY_TEXT_START 0x0c000000 diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 0e75a4049f475..69035bfb4ad4b 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -126,6 +127,7 @@ struct map_desc io_desc[] __initdata = { void __init xilinx_map_io(void) { iotable_init(io_desc, ARRAY_SIZE(io_desc)); + init_consistent_dma_size(40 << 20); } /** From e985464737bf17e62303e8f2e4d59aecca8e5474 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 26 Mar 2012 10:38:26 +0200 Subject: [PATCH 020/261] Do not register I2C devices from board file We do this from the device tree. --- arch/arm/mach-zynq/board_zc702.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-zynq/board_zc702.c b/arch/arm/mach-zynq/board_zc702.c index 0a37a0f995542..b4aee636b97ed 100644 --- a/arch/arm/mach-zynq/board_zc702.c +++ b/arch/arm/mach-zynq/board_zc702.c @@ -176,6 +176,7 @@ static void __init board_zc702_init(void) ARRAY_SIZE(xilinx_spipss_0_boardinfo)); #endif +#if 0 #if defined(CONFIG_I2C_XILINX_PS) && defined(CONFIG_I2C_MUX_PCA954x) i2c_register_board_info(0, pca954x_i2c_devices, ARRAY_SIZE(pca954x_i2c_devices)); @@ -187,6 +188,7 @@ static void __init board_zc702_init(void) i2c_register_board_info(4, tca6416_board_info, ARRAY_SIZE(tca6416_board_info)); #endif +#endif #endif } From e908811efb5b91d06cc66ba671d540de0462f58a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 10 Apr 2012 10:01:07 +0200 Subject: [PATCH 021/261] Configure the I2C pins for GPIO functionality The I2C core really likes to act up, so fall back to GPIO I2C bitbanging for now. --- arch/arm/mach-zynq/slcr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index c41e047cde11c..4e47803518e4c 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -67,6 +67,7 @@ #define XSLCR_DEVC_RST_CTRL_OFFSET 0x23C /* Dev Cfg SW Reset Control */ #define XSLCR_FPGA_RST_CTRL_OFFSET 0x240 /* FPGA Software Reset Control */ #define XSLCR_MIO_PIN_00_OFFSET 0x700 /* MIO PIN0 control register */ +#define XSLCR_MIO_PIN(x) (0x700 + (x) * 4) /* MIO PIN0 control register */ #define XSLCR_LVL_SHFTR_EN_OFFSET 0x900 /* Level Shifters Enable */ /* Bit masks for AMBA Peripheral Clock Control register */ @@ -2385,7 +2386,7 @@ static void xslcr_get_mio_status(void) * * Return: 0 on success, negative error otherwise. **/ -static int __init xslcr_probe(struct platform_device *pdev) +static int __devinit xslcr_probe(struct platform_device *pdev) { struct resource res; int ret; @@ -2458,6 +2459,8 @@ static int __init xslcr_probe(struct platform_device *pdev) xslcr_writereg(slcr->regs + XSLCR_FPGA1_CLK_CTRL_OFFSET, 0x100500); xslcr_writereg(slcr->regs + XSLCR_FPGA2_CLK_CTRL_OFFSET, 0x100700); xslcr_writereg(slcr->regs + XSLCR_FPGA3_CLK_CTRL_OFFSET, 0x102900); + xslcr_writereg(slcr->regs + XSLCR_MIO_PIN(50), 0x200); + xslcr_writereg(slcr->regs + XSLCR_MIO_PIN(51), 0x200); dev_info(&pdev->dev, "at 0x%08X mapped to 0x%08X\n", res.start, (u32 __force)slcr->regs); From 7a4e362dd65c0d1aa8a687531735dc1fff61f4f6 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Tue, 7 Feb 2012 12:12:51 +0800 Subject: [PATCH 022/261] of: introduce helper to manage boolean of_property_read_bool Search for a property in a device node. Returns true if the property exist false otherwise. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Rob Herring Acked-by: Arnd Bergmann Acked-by: Grant Likely --- include/linux/of.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/linux/of.h b/include/linux/of.h index 92cf6ad35e0ea..612f84b007c63 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -350,6 +350,22 @@ static inline int of_machine_is_compatible(const char *compat) #define of_match_node(_matches, _node) NULL #endif /* CONFIG_OF */ +/** + * of_property_read_bool - Findfrom a property + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * + * Search for a property in a device node. + * Returns true if the property exist false otherwise. + */ +static inline bool of_property_read_bool(const struct device_node *np, + const char *propname) +{ + struct property *prop = of_find_property(np, propname, NULL); + + return prop ? true : false; +} + static inline int of_property_read_u32(const struct device_node *np, const char *propname, u32 *out_value) From 675c3532792f55f63839cf46e5bb36ad5b3d931b Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sun, 5 Feb 2012 18:22:34 +0800 Subject: [PATCH 023/261] i2c/gpio: add DT support To achieve DT support, we need to populate a custom platform_data in a private struct from DT information. To simplify code, the adapter and algorithm are also put into the private struct. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Grant Likely Acked-by: Rob Herring Acked-by: Wolfram Sang Cc: Nicolas Ferre --- .../devicetree/bindings/gpio/gpio_i2c.txt | 32 ++++++ drivers/i2c/busses/i2c-gpio.c | 98 ++++++++++++++----- 2 files changed, 108 insertions(+), 22 deletions(-) create mode 100644 Documentation/devicetree/bindings/gpio/gpio_i2c.txt diff --git a/Documentation/devicetree/bindings/gpio/gpio_i2c.txt b/Documentation/devicetree/bindings/gpio/gpio_i2c.txt new file mode 100644 index 0000000000000..4f8ec947c6bd9 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio_i2c.txt @@ -0,0 +1,32 @@ +Device-Tree bindings for i2c gpio driver + +Required properties: + - compatible = "i2c-gpio"; + - gpios: sda and scl gpio + + +Optional properties: + - i2c-gpio,sda-open-drain: sda as open drain + - i2c-gpio,scl-open-drain: scl as open drain + - i2c-gpio,scl-output-only: scl as output only + - i2c-gpio,delay-us: delay between GPIO operations (may depend on each platform) + - i2c-gpio,timeout-ms: timeout to get data + +Example nodes: + +i2c@0 { + compatible = "i2c-gpio"; + gpios = <&pioA 23 0 /* sda */ + &pioA 24 0 /* scl */ + >; + i2c-gpio,sda-open-drain; + i2c-gpio,scl-open-drain; + i2c-gpio,delay-us = <2>; /* ~100 kHz */ + #address-cells = <1>; + #size-cells = <0>; + + rv3029c2@56 { + compatible = "rv3029c2"; + reg = <0x56>; + }; +}; diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index a651779d9ff7a..c0330a41db039 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -14,8 +14,15 @@ #include #include #include - -#include +#include +#include +#include + +struct i2c_gpio_private_data { + struct i2c_adapter adap; + struct i2c_algo_bit_data bit_data; + struct i2c_gpio_platform_data pdata; +}; /* Toggle SDA by changing the direction of the pin */ static void i2c_gpio_setsda_dir(void *data, int state) @@ -78,24 +85,62 @@ static int i2c_gpio_getscl(void *data) return gpio_get_value(pdata->scl_pin); } +static int __devinit of_i2c_gpio_probe(struct device_node *np, + struct i2c_gpio_platform_data *pdata) +{ + u32 reg; + + if (of_gpio_count(np) < 2) + return -ENODEV; + + pdata->sda_pin = of_get_gpio(np, 0); + pdata->scl_pin = of_get_gpio(np, 1); + + if (!gpio_is_valid(pdata->sda_pin) || !gpio_is_valid(pdata->scl_pin)) { + pr_err("%s: invalid GPIO pins, sda=%d/scl=%d\n", + np->full_name, pdata->sda_pin, pdata->scl_pin); + return -ENODEV; + } + + of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay); + + if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", ®)) + pdata->timeout = msecs_to_jiffies(reg); + + pdata->sda_is_open_drain = + of_property_read_bool(np, "i2c-gpio,sda-open-drain"); + pdata->scl_is_open_drain = + of_property_read_bool(np, "i2c-gpio,scl-open-drain"); + pdata->scl_is_output_only = + of_property_read_bool(np, "i2c-gpio,scl-output-only"); + + return 0; +} + static int __devinit i2c_gpio_probe(struct platform_device *pdev) { + struct i2c_gpio_private_data *priv; struct i2c_gpio_platform_data *pdata; struct i2c_algo_bit_data *bit_data; struct i2c_adapter *adap; int ret; - pdata = pdev->dev.platform_data; - if (!pdata) - return -ENXIO; - - ret = -ENOMEM; - adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); - if (!adap) - goto err_alloc_adap; - bit_data = kzalloc(sizeof(struct i2c_algo_bit_data), GFP_KERNEL); - if (!bit_data) - goto err_alloc_bit_data; + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + adap = &priv->adap; + bit_data = &priv->bit_data; + pdata = &priv->pdata; + + if (pdev->dev.of_node) { + ret = of_i2c_gpio_probe(pdev->dev.of_node, pdata); + if (ret) + return ret; + } else { + if (!pdev->dev.platform_data) + return -ENXIO; + memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata)); + } ret = gpio_request(pdata->sda_pin, "sda"); if (ret) @@ -143,6 +188,7 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev) adap->algo_data = bit_data; adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adap->dev.parent = &pdev->dev; + adap->dev.of_node = pdev->dev.of_node; /* * If "dev->id" is negative we consider it as zero. @@ -154,7 +200,9 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev) if (ret) goto err_add_bus; - platform_set_drvdata(pdev, adap); + of_i2c_register_devices(adap); + + platform_set_drvdata(pdev, priv); dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n", pdata->sda_pin, pdata->scl_pin, @@ -168,34 +216,40 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev) err_request_scl: gpio_free(pdata->sda_pin); err_request_sda: - kfree(bit_data); -err_alloc_bit_data: - kfree(adap); -err_alloc_adap: return ret; } static int __devexit i2c_gpio_remove(struct platform_device *pdev) { + struct i2c_gpio_private_data *priv; struct i2c_gpio_platform_data *pdata; struct i2c_adapter *adap; - adap = platform_get_drvdata(pdev); - pdata = pdev->dev.platform_data; + priv = platform_get_drvdata(pdev); + adap = &priv->adap; + pdata = &priv->pdata; i2c_del_adapter(adap); gpio_free(pdata->scl_pin); gpio_free(pdata->sda_pin); - kfree(adap->algo_data); - kfree(adap); return 0; } +#if defined(CONFIG_OF) +static const struct of_device_id i2c_gpio_dt_ids[] = { + { .compatible = "i2c-gpio", }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, i2c_gpio_dt_ids); +#endif + static struct platform_driver i2c_gpio_driver = { .driver = { .name = "i2c-gpio", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(i2c_gpio_dt_ids), }, .probe = i2c_gpio_probe, .remove = __devexit_p(i2c_gpio_remove), From f3bbdafe84054844204d8cc78c983d08f4aed3df Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 12 Apr 2012 14:14:22 -0700 Subject: [PATCH 024/261] i2c: Add a struct device * parameter to i2c_add_mux_adapter() And adjust all callers. The new device parameter is used in the next patch to initialize the mux's of_node so that its children may be automatically populated. Signed-off-by: David Daney Cc: Lars-Peter Clausen --- drivers/i2c/i2c-mux.c | 19 ++++++++++--------- drivers/i2c/muxes/gpio-i2cmux.c | 3 ++- drivers/i2c/muxes/pca9541.c | 3 ++- drivers/i2c/muxes/pca954x.c | 2 +- include/linux/i2c-mux.h | 3 ++- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index d7a4833be4161..26ab31dd742b7 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -31,11 +31,11 @@ struct i2c_mux_priv { struct i2c_algorithm algo; struct i2c_adapter *parent; - void *mux_dev; /* the mux chip/device */ + void *mux_priv; /* the mux chip/device */ u32 chan_id; /* the channel id */ - int (*select)(struct i2c_adapter *, void *mux_dev, u32 chan_id); - int (*deselect)(struct i2c_adapter *, void *mux_dev, u32 chan_id); + int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id); + int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id); }; static int i2c_mux_master_xfer(struct i2c_adapter *adap, @@ -47,11 +47,11 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap, /* Switch to the right mux port and perform the transfer. */ - ret = priv->select(parent, priv->mux_dev, priv->chan_id); + ret = priv->select(parent, priv->mux_priv, priv->chan_id); if (ret >= 0) ret = parent->algo->master_xfer(parent, msgs, num); if (priv->deselect) - priv->deselect(parent, priv->mux_dev, priv->chan_id); + priv->deselect(parent, priv->mux_priv, priv->chan_id); return ret; } @@ -67,12 +67,12 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap, /* Select the right mux port and perform the transfer. */ - ret = priv->select(parent, priv->mux_dev, priv->chan_id); + ret = priv->select(parent, priv->mux_priv, priv->chan_id); if (ret >= 0) ret = parent->algo->smbus_xfer(parent, addr, flags, read_write, command, size, data); if (priv->deselect) - priv->deselect(parent, priv->mux_dev, priv->chan_id); + priv->deselect(parent, priv->mux_priv, priv->chan_id); return ret; } @@ -87,7 +87,8 @@ static u32 i2c_mux_functionality(struct i2c_adapter *adap) } struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, - void *mux_dev, u32 force_nr, u32 chan_id, + struct device *mux_dev, + void *mux_priv, u32 force_nr, u32 chan_id, int (*select) (struct i2c_adapter *, void *, u32), int (*deselect) (struct i2c_adapter *, @@ -102,7 +103,7 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, /* Set up private adapter data */ priv->parent = parent; - priv->mux_dev = mux_dev; + priv->mux_priv = mux_priv; priv->chan_id = chan_id; priv->select = select; priv->deselect = deselect; diff --git a/drivers/i2c/muxes/gpio-i2cmux.c b/drivers/i2c/muxes/gpio-i2cmux.c index e5fa695eb0fa6..fc5c1ef9b6ecb 100644 --- a/drivers/i2c/muxes/gpio-i2cmux.c +++ b/drivers/i2c/muxes/gpio-i2cmux.c @@ -105,7 +105,8 @@ static int __devinit gpiomux_probe(struct platform_device *pdev) for (i = 0; i < pdata->n_values; i++) { u32 nr = pdata->base_nr ? (pdata->base_nr + i) : 0; - mux->adap[i] = i2c_add_mux_adapter(parent, mux, nr, i, + mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, + nr, i, gpiomux_select, deselect); if (!mux->adap[i]) { ret = -ENODEV; diff --git a/drivers/i2c/muxes/pca9541.c b/drivers/i2c/muxes/pca9541.c index ed699c5aa79d0..e9e07ba0f1852 100644 --- a/drivers/i2c/muxes/pca9541.c +++ b/drivers/i2c/muxes/pca9541.c @@ -353,7 +353,8 @@ static int pca9541_probe(struct i2c_client *client, force = 0; if (pdata) force = pdata->modes[0].adap_id; - data->mux_adap = i2c_add_mux_adapter(adap, client, force, 0, + data->mux_adap = i2c_add_mux_adapter(adap, &client->dev, client, + force, 0, pca9541_select_chan, pca9541_release_chan); diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c index 6f89536646365..5c6ecc759d021 100644 --- a/drivers/i2c/muxes/pca954x.c +++ b/drivers/i2c/muxes/pca954x.c @@ -226,7 +226,7 @@ static int pca954x_probe(struct i2c_client *client, } data->virt_adaps[num] = - i2c_add_mux_adapter(adap, client, + i2c_add_mux_adapter(adap, &client->dev, client, force, num, pca954x_select_chan, (pdata && pdata->modes[num].deselect_on_exit) ? pca954x_deselect_mux : NULL); diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h index 34536effd652d..260ca6ad9ae32 100644 --- a/include/linux/i2c-mux.h +++ b/include/linux/i2c-mux.h @@ -33,7 +33,8 @@ * mux control. */ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, - void *mux_dev, u32 force_nr, u32 chan_id, + struct device *mux_dev, + void *mux_priv, u32 force_nr, u32 chan_id, int (*select) (struct i2c_adapter *, void *mux_dev, u32 chan_id), int (*deselect) (struct i2c_adapter *, From 83488b39bd195ffd6c247aa293f050487d9437db Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 12 Apr 2012 14:14:23 -0700 Subject: [PATCH 025/261] i2c/of: Automatically populate i2c mux busses from device tree data. For 'normal' i2c bus drivers, we can call of_i2c_register_devices() and have the device tree framework automatically populate the bus with the devices specified in the device tree. This patch adds a common code to the i2c mux framework to have the mux sub-busses be populated by the of_i2c_register_devices() too. If the mux device has an of_node, we populate the sub-bus' of_node so that the subsequent call to of_i2c_register_devices() will find the corresponding devices. It seemed better to put this logic in i2c_add_mux_adapter() rather than the individual mux drivers, as they will all probably want to do the same thing. Signed-off-by: David Daney Cc: Lars-Peter Clausen --- Documentation/devicetree/bindings/i2c/mux.txt | 60 +++++++++++++++++++ drivers/i2c/i2c-mux.c | 24 ++++++++ 2 files changed, 84 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/mux.txt diff --git a/Documentation/devicetree/bindings/i2c/mux.txt b/Documentation/devicetree/bindings/i2c/mux.txt new file mode 100644 index 0000000000000..af84cce5cd7bc --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/mux.txt @@ -0,0 +1,60 @@ +Common i2c bus multiplexer/switch properties. + +An i2c bus multiplexer/switch will have several child busses that are +numbered uniquely in a device dependent manner. The nodes for an i2c bus +multiplexer/switch will have one child node for each child +bus. + +Required properties: +- #address-cells = <1>; +- #size-cells = <0>; + +Required properties for child nodes: +- #address-cells = <1>; +- #size-cells = <0>; +- reg : The sub-bus number. + +Optional properties for child nodes: +- Other properties specific to the multiplexer/switch hardware. +- Child nodes conforming to i2c bus binding + + +Example : + + /* + An NXP pca9548 8 channel I2C multiplexer at address 0x70 + with two NXP pca8574 GPIO expanders attached, one each to + ports 3 and 4. + */ + + mux@70 { + compatible = "nxp,pca9548"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + gpio1: gpio@38 { + compatible = "nxp,pca8574"; + reg = <0x38>; + #gpio-cells = <2>; + gpio-controller; + }; + }; + i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + + gpio2: gpio@38 { + compatible = "nxp,pca8574"; + reg = <0x38>; + #gpio-cells = <2>; + gpio-controller; + }; + }; + }; diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 26ab31dd742b7..609794b9ccfe0 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include /* multiplexer per channel data */ struct i2c_mux_priv { @@ -125,6 +127,26 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, priv->adap.algo_data = priv; priv->adap.dev.parent = &parent->dev; + /* + * Try to get populate the mux adapter's of_node, expands to + * nothing if !CONFIG_OF. + */ + if (mux_dev->of_node) { + struct device_node *child; + u32 reg; + int ret; + + for_each_child_of_node(mux_dev->of_node, child) { + ret = of_property_read_u32(child, "reg", ®); + if (ret) + continue; + if (chan_id == reg) { + priv->adap.dev.of_node = child; + break; + } + } + } + if (force_nr) { priv->adap.nr = force_nr; ret = i2c_add_numbered_adapter(&priv->adap); @@ -142,6 +164,8 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, dev_info(&parent->dev, "Added multiplexed i2c bus %d\n", i2c_adapter_id(&priv->adap)); + of_i2c_register_devices(&priv->adap); + return &priv->adap; } EXPORT_SYMBOL_GPL(i2c_add_mux_adapter); From e82248b849f5bae006b60dec83dcdf339fed7029 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 25 Mar 2012 16:52:26 +0200 Subject: [PATCH 026/261] Add ZC702 + ADV7511 device tree --- arch/arm/boot/dts/zynq-zc702-adv7511.dts | 217 +++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 arch/arm/boot/dts/zynq-zc702-adv7511.dts diff --git a/arch/arm/boot/dts/zynq-zc702-adv7511.dts b/arch/arm/boot/dts/zynq-zc702-adv7511.dts new file mode 100644 index 0000000000000..520f658ac7e64 --- /dev/null +++ b/arch/arm/boot/dts/zynq-zc702-adv7511.dts @@ -0,0 +1,217 @@ +/dts-v1/; + +/ { + model = "Xilinx Zynq ZC702"; + compatible = "xlnx,zynq-zc702"; + #address-cells = <0x1>; + #size-cells = <0x1>; + interrupt-parent = <0x1>; + + memory { + device_type = "memory"; + reg = <0x000000000 0x40000000>; + }; + chosen { +// bootargs = "console=ttyPS0,115200 root=/dev/ram rw initrd=0x1100000,33M ip=:::::eth0:dhcp earlyprintk"; + bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0"; + linux,stdout-path = "/amba@0/uart@E0001000"; + }; + + amba@0 { + compatible = "simple-bus"; + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + + gic: intc@f8f01000 { + interrupt-controller; + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + reg = < 0xf8f01000 0x1000 >, + < 0xf8f00100 0x0100 >; + }; + + uart@e0001000 { + compatible = "xlnx,ps7-uart-1.00.a"; + reg = <0xe0001000 0x1000>; + interrupts = < 0 50 0 >; + interrupt-parent = <&gic>; + clock = <50000000>; + }; + + timer@0xf8001000 { + compatible = "xlnx,ps7-ttc-1.00.a"; + reg = <0xf8001000 0x1000>; + interrupts = <0 10 0>,<0 11 0>,<0 12 0>; + interrupt-parent = <&gic>; +/* clock-frequency = <111111111>;*/ + clock-frequency = <133000000>; + }; + + swdt@f8005000 { + device_type = "watchdog"; + compatible = "xlnx,ps7-wdt-1.00.a"; + reg = <0xf8005000 0x100>; + }; + + eth@e000b000 { + compatible = "xlnx,ps7-ethernet-1.00.a"; + reg = <0xe000b000 0x1000>; + interrupts = <0 22 0>; + interrupt-parent = <&gic>; + phy-handle = <&phy0>; + #address-cells = <0x1>; + #size-cells = <0x0>; + + phy0: phy@7 { + compatible = "marvell,88e1116r"; + device_type = "ethernet-phy"; + reg = <0x7>; + }; + }; + + gpio: gpio@e000a000 { + compatible = "xlnx,ps7-gpio-1.00.a"; + reg = <0xe000a000 0x1000>; + interrupts = <0 20 0>; + interrupt-parent = <&gic>; + gpio-controller; + #gpio-cells = <2>; + }; + +/* + i2c0: i2c@e0004000 { + compatible = "xlnx,ps7-i2c-1.00.a"; + reg = <0xe0004000 0x1000>; + interrupts = <0 25 0>; + interrupt-parent = <&gic>; + bus-id = <0>; + input-clk = <111111111>; + i2c-clk = <100000>; +*/ + + i2c0: i2c@0 { + compatible = "i2c-gpio"; + gpios = <&gpio 51 0 &gpio 50 0>; + i2c-gpio,delay-us = <2>; + #address-cells = <1>; + #size-cells = <0>; + + mux@74 { + compatible = "pca9548"; + reg = <0x74>; + #address-cells = <1>; + #size-cells = <0>; + i2c_adv7511: i2c@1 { + #size-cells = <0>; + #address-cells = <1>; + reg = <1>; + }; + + i2c@4 { + #size-cells = <0>; + #address-cells = <1>; + reg = <4>; + rtc@51 { + compatible = "rtc8564"; + reg = <0x51>; + }; + }; + }; + + }; + + sdhci@e0100000 { + compatible = "xlnx,ps7-sdhci-1.00.a"; + reg = <0xe0100000 0x1000>; + interrupts = <0 24 0>; + interrupt-parent = <&gic>; + clock-frequency = <33333000>; + }; + + usb@e0002000 { + compatible = "xlnx,ps7-usb-1.00.a"; + reg = <0xe0002000 0x1000>; + interrupts = <0 21 0>; + interrupt-parent = <&gic>; + dr_mode = "host"; + phy_type = "ulpi"; + }; + + qspi0: spi@e000d000 { + compatible = "xlnx,ps7-qspi-1.00.a"; + reg = <0xE000D000 0x1000>; + interrupts = <0 19 0>; + interrupt-parent = <&gic>; + speed-hz = <200000000>; + bus-num = <1>; + num-chip-select = <1>; + is-dual = <0>; + }; + + devcfg@f8007000 { + compatible = "xlnx,ps7-dev-cfg-1.00.a"; + reg = <0xf8007000 0x1000>; + interrupts = <0 8 0>; + interrupt-parent = <&gic>; + }; + + axi_dma_0: axidma@40400000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + reg = < 0x40400000 0x1000 >; + xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@40400000 { + compatible = "xlnx,axi-dma-mm2s-channel"; + interrupts = < 0 58 0x4 >; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + }; + }; + + axi_spdif_tx_0: axi-spdif-tx@0x75c00000 { + compatible = "adi,axi-spdif-tx-1.00.a"; + reg = < 0x75c00000 0x1000 >; + clock-frequency = <12288000>; + }; + + axi_vdma_0: axivdma@43000000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-vdma"; + reg = <0x43000000 0x1000>; + xlnx,include-sg = <0x0>; + xlnx,num-fstores = <0x3>; + dma-channel@7e200000 { + compatible = "xlnx,axi-vdma-mm2s-channel"; + interrupts = <0 59 0x4>; + xlnx,datawidth = <0x40>; + xlnx,genlock-mode = <0x0>; + xlnx,include-dre = <0x0>; + }; + }; + + cf_adv7x11_core_0: cf-adv7x11-core@6c000000 { + compatible = "adi,cf-adv7x11-core-1.00.a"; + reg = <0x6c000000 0x10000 + 0x66000000 0x10000>; + slave_adapter = <&i2c_adv7511>; + dma-request = <&axi_vdma_0 0>; + }; + + xilinx_pcm_audio: xilinx_pcm_audio { + compatible = "xilinx-pcm-audio"; + dma-request = <&axi_dma_0 0>; + }; + + adv7511_hdmi_snd: adv7511_hdmi_snd { + compatible = "adv7511-hdmi-snd"; + audio-codec = <&i2c_adv7511>; + cpu-dai = <&axi_spdif_tx_0>; + pcm = <&xilinx_pcm_audio>; + }; + }; +}; From cdeac10ff978c46748db7f6f06bd526219382359 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 13 Feb 2012 11:16:22 +0100 Subject: [PATCH 027/261] I2C: xiic: Add OF support Signed-off-by: Lars-Peter Clausen --- .../devicetree/bindings/i2c/xiic.txt | 22 ++++++++++++++++++ drivers/i2c/busses/i2c-xiic.c | 23 +++++++++++++++---- 2 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 Documentation/devicetree/bindings/i2c/xiic.txt diff --git a/Documentation/devicetree/bindings/i2c/xiic.txt b/Documentation/devicetree/bindings/i2c/xiic.txt new file mode 100644 index 0000000000000..5945b5cdd520f --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/xiic.txt @@ -0,0 +1,22 @@ +Xilinx IIC controller: + +Required properties: +- compatible : Must be "xlnx,xps-iic-2.00.a" +- reg : IIC Register location and length +- interrupts : IIC Interrupt +- #address-cells = <1> +- #size-cells = <0> + +Optional properties: +- Child nodes conforming to i2c bus binding + +Example: + + axi_iic_0: i2c@40800000 { + compatible = "xlnx,axi-iic-1.01.b" "xlnx,xps-iic-2.00.a"; + interrupts = < 1 2 >; + reg = < 0x40800000 0x10000 >; + + #size-cells = <0>; + #address-cells = <1>; + }; diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 2bded7647ef25..641d0e5e33036 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -40,6 +40,7 @@ #include #include #include +#include #define DRIVER_NAME "xiic-i2c" @@ -705,8 +706,6 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev) goto resource_missing; pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data; - if (!pdata) - return -EINVAL; i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); if (!i2c) @@ -730,6 +729,7 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev) i2c->adap = xiic_adapter; i2c_set_adapdata(&i2c->adap, i2c); i2c->adap.dev.parent = &pdev->dev; + i2c->adap.dev.of_node = pdev->dev.of_node; xiic_reinit(i2c); @@ -748,9 +748,13 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev) goto add_adapter_failed; } - /* add in known devices to the bus */ - for (i = 0; i < pdata->num_devices; i++) - i2c_new_device(&i2c->adap, pdata->devices + i); + if (pdata) { + /* add in known devices to the bus */ + for (i = 0; i < pdata->num_devices; i++) + i2c_new_device(&i2c->adap, pdata->devices + i); + } + + of_i2c_register_devices(&i2c->adap); return 0; @@ -795,12 +799,21 @@ static int __devexit xiic_i2c_remove(struct platform_device* pdev) return 0; } +#if defined(CONFIG_OF) +static const struct of_device_id xiic_of_match[] __devinitconst = { + { .compatible = "xlnx,xps-iic-2.00.a", }, + {}, +}; +MODULE_DEVICE_TABLE(of, xiic_of_match); +#endif + static struct platform_driver xiic_i2c_driver = { .probe = xiic_i2c_probe, .remove = __devexit_p(xiic_i2c_remove), .driver = { .owner = THIS_MODULE, .name = DRIVER_NAME, + .of_match_table = of_match_ptr(xiic_of_match), }, }; From e984159935f0efd8a89f6234753b07796e5c658e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 20 Feb 2012 13:40:58 +0100 Subject: [PATCH 028/261] I2C: xiic: Always use 32bit access Always use 32bit access to avoid endianess issues. Signed-off-by: Lars-Peter Clausen --- drivers/i2c/busses/i2c-xiic.c | 107 ++++++++++++++-------------------- 1 file changed, 45 insertions(+), 62 deletions(-) diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 641d0e5e33036..52f480e88b998 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -174,47 +174,32 @@ struct xiic_i2c { static void xiic_start_xfer(struct xiic_i2c *i2c); static void __xiic_start_xfer(struct xiic_i2c *i2c); -static inline void xiic_setreg8(struct xiic_i2c *i2c, int reg, u8 value) -{ - iowrite8(value, i2c->base + reg); -} - -static inline u8 xiic_getreg8(struct xiic_i2c *i2c, int reg) -{ - return ioread8(i2c->base + reg); -} - -static inline void xiic_setreg16(struct xiic_i2c *i2c, int reg, u16 value) -{ - iowrite16(value, i2c->base + reg); -} - -static inline void xiic_setreg32(struct xiic_i2c *i2c, int reg, int value) +static inline void xiic_setreg(struct xiic_i2c *i2c, int reg, int value) { iowrite32(value, i2c->base + reg); } -static inline int xiic_getreg32(struct xiic_i2c *i2c, int reg) +static inline int xiic_getreg(struct xiic_i2c *i2c, int reg) { return ioread32(i2c->base + reg); } static inline void xiic_irq_dis(struct xiic_i2c *i2c, u32 mask) { - u32 ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); - xiic_setreg32(i2c, XIIC_IIER_OFFSET, ier & ~mask); + u32 ier = xiic_getreg(i2c, XIIC_IIER_OFFSET); + xiic_setreg(i2c, XIIC_IIER_OFFSET, ier & ~mask); } static inline void xiic_irq_en(struct xiic_i2c *i2c, u32 mask) { - u32 ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); - xiic_setreg32(i2c, XIIC_IIER_OFFSET, ier | mask); + u32 ier = xiic_getreg(i2c, XIIC_IIER_OFFSET); + xiic_setreg(i2c, XIIC_IIER_OFFSET, ier | mask); } static inline void xiic_irq_clr(struct xiic_i2c *i2c, u32 mask) { - u32 isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET); - xiic_setreg32(i2c, XIIC_IISR_OFFSET, isr & mask); + u32 isr = xiic_getreg(i2c, XIIC_IISR_OFFSET); + xiic_setreg(i2c, XIIC_IISR_OFFSET, isr & mask); } static inline void xiic_irq_clr_en(struct xiic_i2c *i2c, u32 mask) @@ -226,30 +211,30 @@ static inline void xiic_irq_clr_en(struct xiic_i2c *i2c, u32 mask) static void xiic_clear_rx_fifo(struct xiic_i2c *i2c) { u8 sr; - for (sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET); + for (sr = xiic_getreg(i2c, XIIC_SR_REG_OFFSET); !(sr & XIIC_SR_RX_FIFO_EMPTY_MASK); - sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET)) - xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET); + sr = xiic_getreg(i2c, XIIC_SR_REG_OFFSET)) + xiic_getreg(i2c, XIIC_DRR_REG_OFFSET); } static void xiic_reinit(struct xiic_i2c *i2c) { - xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); + xiic_setreg(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); /* Set receive Fifo depth to maximum (zero based). */ - xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1); + xiic_setreg(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1); /* Reset Tx Fifo. */ - xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK); + xiic_setreg(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK); /* Enable IIC Device, remove Tx Fifo reset & disable general call. */ - xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_ENABLE_DEVICE_MASK); + xiic_setreg(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_ENABLE_DEVICE_MASK); /* make sure RX fifo is empty */ xiic_clear_rx_fifo(i2c); /* Enable interrupts */ - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); + xiic_setreg(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); xiic_irq_clr_en(i2c, XIIC_INTR_AAS_MASK | XIIC_INTR_ARB_LOST_MASK); } @@ -258,11 +243,11 @@ static void xiic_deinit(struct xiic_i2c *i2c) { u8 cr; - xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); + xiic_setreg(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); /* Disable IIC Device. */ - cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET); - xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr & ~XIIC_CR_ENABLE_DEVICE_MASK); + cr = xiic_getreg(i2c, XIIC_CR_REG_OFFSET); + xiic_setreg(i2c, XIIC_CR_REG_OFFSET, cr & ~XIIC_CR_ENABLE_DEVICE_MASK); } static void xiic_read_rx(struct xiic_i2c *i2c) @@ -270,22 +255,22 @@ static void xiic_read_rx(struct xiic_i2c *i2c) u8 bytes_in_fifo; int i; - bytes_in_fifo = xiic_getreg8(i2c, XIIC_RFO_REG_OFFSET) + 1; + bytes_in_fifo = xiic_getreg(i2c, XIIC_RFO_REG_OFFSET) + 1; dev_dbg(i2c->adap.dev.parent, "%s entry, bytes in fifo: %d, msg: %d" ", SR: 0x%x, CR: 0x%x\n", __func__, bytes_in_fifo, xiic_rx_space(i2c), - xiic_getreg8(i2c, XIIC_SR_REG_OFFSET), - xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); + xiic_getreg(i2c, XIIC_SR_REG_OFFSET), + xiic_getreg(i2c, XIIC_CR_REG_OFFSET)); if (bytes_in_fifo > xiic_rx_space(i2c)) bytes_in_fifo = xiic_rx_space(i2c); for (i = 0; i < bytes_in_fifo; i++) i2c->rx_msg->buf[i2c->rx_pos++] = - xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET); + xiic_getreg(i2c, XIIC_DRR_REG_OFFSET); - xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, + xiic_setreg(i2c, XIIC_RFD_REG_OFFSET, (xiic_rx_space(i2c) > IIC_RX_FIFO_DEPTH) ? IIC_RX_FIFO_DEPTH - 1 : xiic_rx_space(i2c) - 1); } @@ -293,7 +278,7 @@ static void xiic_read_rx(struct xiic_i2c *i2c) static int xiic_tx_fifo_space(struct xiic_i2c *i2c) { /* return the actual space left in the FIFO */ - return IIC_TX_FIFO_DEPTH - xiic_getreg8(i2c, XIIC_TFO_REG_OFFSET) - 1; + return IIC_TX_FIFO_DEPTH - xiic_getreg(i2c, XIIC_TFO_REG_OFFSET) - 1; } static void xiic_fill_tx_fifo(struct xiic_i2c *i2c) @@ -313,9 +298,9 @@ static void xiic_fill_tx_fifo(struct xiic_i2c *i2c) data |= XIIC_TX_DYN_STOP_MASK; dev_dbg(i2c->adap.dev.parent, "%s TX STOP\n", __func__); - xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data); + xiic_setreg(i2c, XIIC_DTR_REG_OFFSET, data); } else - xiic_setreg8(i2c, XIIC_DTR_REG_OFFSET, data); + xiic_setreg(i2c, XIIC_DTR_REG_OFFSET, data); } } @@ -338,13 +323,13 @@ static void xiic_process(struct xiic_i2c *i2c) * To find which interrupts are pending; AND interrupts pending with * interrupts masked. */ - isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET); - ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); + isr = xiic_getreg(i2c, XIIC_IISR_OFFSET); + ier = xiic_getreg(i2c, XIIC_IIER_OFFSET); pend = isr & ier; dev_dbg(i2c->adap.dev.parent, "%s entry, IER: 0x%x, ISR: 0x%x, " "pend: 0x%x, SR: 0x%x, msg: %p, nmsgs: %d\n", - __func__, ier, isr, pend, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET), + __func__, ier, isr, pend, xiic_getreg(i2c, XIIC_SR_REG_OFFSET), i2c->tx_msg, i2c->nmsgs); /* Do not processes a devices interrupts if the device has no @@ -408,6 +393,8 @@ static void xiic_process(struct xiic_i2c *i2c) "%s will start next...\n", __func__); __xiic_start_xfer(i2c); + } else { + xiic_wakeup(i2c, STATE_DONE); } } } else if (pend & XIIC_INTR_BNB_MASK) { @@ -470,12 +457,12 @@ static void xiic_process(struct xiic_i2c *i2c) out: dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr); - xiic_setreg32(i2c, XIIC_IISR_OFFSET, clr); + xiic_setreg(i2c, XIIC_IISR_OFFSET, clr); } static int xiic_bus_busy(struct xiic_i2c *i2c) { - u8 sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET); + u8 sr = xiic_getreg(i2c, XIIC_SR_REG_OFFSET); return (sr & XIIC_SR_BUS_BUSY_MASK) ? -EBUSY : 0; } @@ -518,22 +505,18 @@ static void xiic_start_recv(struct xiic_i2c *i2c) rx_watermark = msg->len; if (rx_watermark > IIC_RX_FIFO_DEPTH) rx_watermark = IIC_RX_FIFO_DEPTH; - xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rx_watermark - 1); + xiic_setreg(i2c, XIIC_RFD_REG_OFFSET, rx_watermark - 1); if (!(msg->flags & I2C_M_NOSTART)) /* write the address */ - xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, + xiic_setreg(i2c, XIIC_DTR_REG_OFFSET, (msg->addr << 1) | XIIC_READ_OPERATION | XIIC_TX_DYN_START_MASK); xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK); - xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, + xiic_setreg(i2c, XIIC_DTR_REG_OFFSET, msg->len | ((i2c->nmsgs == 1) ? XIIC_TX_DYN_STOP_MASK : 0)); - if (i2c->nmsgs == 1) - /* very last, enable bus not busy as well */ - xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK); - /* the message is tx:ed */ i2c->tx_pos = msg->len; } @@ -546,8 +529,8 @@ static void xiic_start_send(struct xiic_i2c *i2c) dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, len: %d, " "ISR: 0x%x, CR: 0x%x\n", - __func__, msg, msg->len, xiic_getreg32(i2c, XIIC_IISR_OFFSET), - xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); + __func__, msg, msg->len, xiic_getreg(i2c, XIIC_IISR_OFFSET), + xiic_getreg(i2c, XIIC_CR_REG_OFFSET)); if (!(msg->flags & I2C_M_NOSTART)) { /* write the address */ @@ -557,7 +540,7 @@ static void xiic_start_send(struct xiic_i2c *i2c) /* no data and last message -> add STOP */ data |= XIIC_TX_DYN_STOP_MASK; - xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data); + xiic_setreg(i2c, XIIC_DTR_REG_OFFSET, data); } xiic_fill_tx_fifo(i2c); @@ -573,13 +556,13 @@ static irqreturn_t xiic_isr(int irq, void *dev_id) spin_lock(&i2c->lock); /* disable interrupts globally */ - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, 0); + xiic_setreg(i2c, XIIC_DGIER_OFFSET, 0); dev_dbg(i2c->adap.dev.parent, "%s entry\n", __func__); xiic_process(i2c); - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); + xiic_setreg(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); spin_unlock(&i2c->lock); return IRQ_HANDLED; @@ -636,11 +619,11 @@ static void xiic_start_xfer(struct xiic_i2c *i2c) spin_lock_irqsave(&i2c->lock, flags); xiic_reinit(i2c); /* disable interrupts globally */ - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, 0); + xiic_setreg(i2c, XIIC_DGIER_OFFSET, 0); spin_unlock_irqrestore(&i2c->lock, flags); __xiic_start_xfer(i2c); - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); + xiic_setreg(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); } static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) @@ -649,7 +632,7 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) int err; dev_dbg(adap->dev.parent, "%s entry SR: 0x%x\n", __func__, - xiic_getreg8(i2c, XIIC_SR_REG_OFFSET)); + xiic_getreg(i2c, XIIC_SR_REG_OFFSET)); err = xiic_busy(i2c); if (err) From 480fd2fc00929b63d3e4af6fe47d03a03475d24e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 23 Apr 2012 15:51:31 +0200 Subject: [PATCH 029/261] DRM: adv7511: Split EDID reading into multiple blocks Not all I2C controllers support reading 256 byte blocks, so split the reading into multiple smaller blocks. --- drivers/gpu/drm/i2c/adv7511_core.c | 32 ++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i2c/adv7511_core.c b/drivers/gpu/drm/i2c/adv7511_core.c index 7f36e6ecea4dc..68b1185b95f8a 100644 --- a/drivers/gpu/drm/i2c/adv7511_core.c +++ b/drivers/gpu/drm/i2c/adv7511_core.c @@ -309,6 +309,9 @@ static int adv7511_get_edid_block(void *data, { struct drm_encoder *encoder = data; struct adv7511 *adv7511 = encoder_to_adv7511(encoder); + struct i2c_msg xfer[2]; + uint8_t offset; + int i; int ret; if (len > 128) @@ -330,12 +333,29 @@ static int adv7511_get_edid_block(void *data, regmap_write(adv7511->regmap, ADV7511_REG_INT(0), ADV7511_INT0_EDID_READY | ADV7511_INT1_DDC_ERROR); - ret = i2c_master_recv(adv7511->i2c_edid, adv7511->edid_buf, 256); - printk("i2c ret: %x\n", ret); - if (ret < 0) - return ret; - else if (ret != 256) - return -EIO; + /* Break this apart, hopefully more I2C controllers will support 64 + * byte transfers than 256 byte transfers */ + + xfer[0].addr = adv7511->i2c_edid->addr; + xfer[0].flags = 0; + xfer[0].len = 1; + xfer[0].buf = &offset; + xfer[1].addr = adv7511->i2c_edid->addr; + xfer[1].flags = I2C_M_RD; + xfer[1].len = 64; + xfer[1].buf = adv7511->edid_buf; + + for (i = 0; i < 4; ++i) { + ret = i2c_transfer(adv7511->i2c_edid->adapter, xfer, ARRAY_SIZE(xfer)); + printk("i2c ret: %d\n", ret); + if (ret < 0) + return ret; + else if (ret != 2) + return -EIO; + + xfer[1].buf += 64; + offset += 64; + } adv7511->current_edid_segment = block / 2; } From 551ff2a75916b546fcf741c1d52fce85d414d706 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 23 Apr 2012 16:57:39 +0200 Subject: [PATCH 030/261] Add ZED + ADV7511 device tree --- arch/arm/boot/dts/zynq-zed-adv7511.dts | 187 +++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 arch/arm/boot/dts/zynq-zed-adv7511.dts diff --git a/arch/arm/boot/dts/zynq-zed-adv7511.dts b/arch/arm/boot/dts/zynq-zed-adv7511.dts new file mode 100644 index 0000000000000..a34acccf23043 --- /dev/null +++ b/arch/arm/boot/dts/zynq-zed-adv7511.dts @@ -0,0 +1,187 @@ +/dts-v1/; + +/ { + model = "Xilinx Zynq ZED"; + compatible = "xlnx,zynq-zc702"; + #address-cells = <0x1>; + #size-cells = <0x1>; + interrupt-parent = <0x1>; + + memory { + device_type = "memory"; + reg = <0x000000000 0x40000000>; + }; + chosen { +// bootargs = "console=ttyPS0,115200 root=/dev/ram rw initrd=0x1100000,33M ip=:::::eth0:dhcp earlyprintk"; + bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0"; + linux,stdout-path = "/amba@0/uart@E0001000"; + }; + + amba@0 { + compatible = "simple-bus"; + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + + gic: intc@f8f01000 { + interrupt-controller; + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + reg = < 0xf8f01000 0x1000 >, + < 0xf8f00100 0x0100 >; + }; + + uart@e0001000 { + compatible = "xlnx,ps7-uart-1.00.a"; + reg = <0xe0001000 0x1000>; + interrupts = < 0 50 0 >; + interrupt-parent = <&gic>; + clock = <50000000>; + }; + + timer@0xf8001000 { + compatible = "xlnx,ps7-ttc-1.00.a"; + reg = <0xf8001000 0x1000>; + interrupts = <0 10 0>,<0 11 0>,<0 12 0>; + interrupt-parent = <&gic>; +/* clock-frequency = <111111111>;*/ + clock-frequency = <133000000>; + }; + + swdt@f8005000 { + device_type = "watchdog"; + compatible = "xlnx,ps7-wdt-1.00.a"; + reg = <0xf8005000 0x100>; + }; + + eth@e000b000 { + compatible = "xlnx,ps7-ethernet-1.00.a"; + reg = <0xe000b000 0x1000>; + interrupts = <0 22 0>; + interrupt-parent = <&gic>; + phy-handle = <&phy0>; + #address-cells = <0x1>; + #size-cells = <0x0>; + + phy0: phy@0 { + compatible = "marvell,88e1510"; + device_type = "ethernet-phy"; + reg = <0x0>; + marvell,reg-init=<3 16 0xff00 0x1e 3 17 0xfff0 0x0a>; + }; + }; + + gpio: gpio@e000a000 { + compatible = "xlnx,ps7-gpio-1.00.a"; + reg = <0xe000a000 0x1000>; + interrupts = <0 20 0>; + interrupt-parent = <&gic>; + gpio-controller; + #gpio-cells = <2>; + }; + + + axi_iic_0: i2c@41600000 { + compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; + interrupt-parent = <&gic>; + interrupts = < 0 56 0x4 >; + reg = < 0x41600000 0x10000 >; + + #size-cells = <0>; + #address-cells = <1>; + }; + + sdhci@e0100000 { + compatible = "xlnx,ps7-sdhci-1.00.a"; + reg = <0xe0100000 0x1000>; + interrupts = <0 24 0>; + interrupt-parent = <&gic>; + clock-frequency = <33333000>; + }; + + usb@e0002000 { + compatible = "xlnx,ps7-usb-1.00.a"; + reg = <0xe0002000 0x1000>; + interrupts = <0 21 0>; + interrupt-parent = <&gic>; + dr_mode = "host"; + phy_type = "ulpi"; + }; + + qspi0: spi@e000d000 { + compatible = "xlnx,ps7-qspi-1.00.a"; + reg = <0xE000D000 0x1000>; + interrupts = <0 19 0>; + interrupt-parent = <&gic>; + speed-hz = <200000000>; + bus-num = <1>; + num-chip-select = <1>; + is-dual = <0>; + }; + + devcfg@f8007000 { + compatible = "xlnx,ps7-dev-cfg-1.00.a"; + reg = <0xf8007000 0x1000>; + interrupts = <0 8 0>; + interrupt-parent = <&gic>; + }; + + axi_dma_0: axidma@40400000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + reg = < 0x40400000 0x1000 >; + xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@40400000 { + compatible = "xlnx,axi-dma-mm2s-channel"; + interrupts = < 0 58 0x4 >; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + }; + }; + + axi_spdif_tx_0: axi-spdif-tx@0x75c00000 { + compatible = "adi,axi-spdif-tx-1.00.a"; + reg = < 0x75c00000 0x1000 >; + clock-frequency = <12288000>; + }; + + axi_vdma_0: axivdma@43000000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-vdma"; + reg = <0x43000000 0x1000>; + xlnx,include-sg = <0x0>; + xlnx,num-fstores = <0x3>; + dma-channel@7e200000 { + compatible = "xlnx,axi-vdma-mm2s-channel"; + interrupts = <0 59 0x4>; + xlnx,datawidth = <0x40>; + xlnx,genlock-mode = <0x0>; + xlnx,include-dre = <0x0>; + }; + }; + + cf_adv7x11_core_0: cf-adv7x11-core@6c000000 { + compatible = "adi,cf-adv7x11-core-1.00.a"; + reg = <0x6c000000 0x10000 + 0x66000000 0x10000>; + slave_adapter = <&axi_iic_0>; + dma-request = <&axi_vdma_0 0>; + }; + + xilinx_pcm_audio: xilinx_pcm_audio { + compatible = "xilinx-pcm-audio"; + dma-request = <&axi_dma_0 0>; + }; + + adv7511_hdmi_snd: adv7511_hdmi_snd { + compatible = "adv7511-hdmi-snd"; +// audio-codec = <&>; + cpu-dai = <&axi_spdif_tx_0>; + pcm = <&xilinx_pcm_audio>; + }; + }; +}; From f082ed0a1b8ca4f2e457b7e0e517ef22b212b1a1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 20 Mar 2012 13:13:47 +0100 Subject: [PATCH 031/261] Use LL_UART for io mappings table --- arch/arm/mach-zynq/common.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index ba3f3fdee5cc4..0e75a4049f475 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -92,13 +92,12 @@ struct map_desc io_desc[] __initdata = { .pfn = __phys_to_pfn(SCU_PERIPH_PHYS), .length = SZ_8K, .type = MT_DEVICE, - }, - + }, #ifdef CONFIG_DEBUG_LL { - .virtual = UART1_VIRT, - .pfn = __phys_to_pfn(UART1_PHYS), - .length = SZ_4K, + .virtual = LL_UART_VADDR, + .pfn = __phys_to_pfn(LL_UART_PADDR), + .length = SZ_8K, .type = MT_DEVICE, }, #endif From ef7c4bfb33eb8364735295d45e638ce39cb4948b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 5 Mar 2012 16:36:27 +0100 Subject: [PATCH 032/261] OF: Add helper function to lookup a I2C adapter by node Similar to the existing helper function to lookup a I2C device by node. Signed-off-by: Lars-Peter Clausen --- drivers/of/of_i2c.c | 14 ++++++++++++++ include/linux/of_i2c.h | 1 + 2 files changed, 15 insertions(+) diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c index f37fbeb66a440..b2ce95a298004 100644 --- a/drivers/of/of_i2c.c +++ b/drivers/of/of_i2c.c @@ -94,4 +94,18 @@ struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) } EXPORT_SYMBOL(of_find_i2c_device_by_node); +/* must call put_device() when done with returned i2c_adapter device */ +struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node) +{ + struct device *dev; + + dev = bus_find_device(&i2c_bus_type, NULL, node, + of_dev_node_match); + if (!dev) + return NULL; + + return to_i2c_adapter(dev); +} +EXPORT_SYMBOL(of_find_i2c_adapter_by_node); + MODULE_LICENSE("GPL"); diff --git a/include/linux/of_i2c.h b/include/linux/of_i2c.h index 0efe8d465f555..10d6c9ab0ebff 100644 --- a/include/linux/of_i2c.h +++ b/include/linux/of_i2c.h @@ -19,6 +19,7 @@ extern void of_i2c_register_devices(struct i2c_adapter *adap); /* must call put_device() when done with returned i2c_client device */ extern struct i2c_client *of_find_i2c_device_by_node(struct device_node *node); +extern struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node); #else static inline void of_i2c_register_devices(struct i2c_adapter *adap) From 00074c693eea242b04e83e885badc9218ae2f8cf Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 7 Mar 2012 11:12:58 +0100 Subject: [PATCH 033/261] DMA: Xilinx: VDMA: Allow less then the total number of frames Although the dma controller expects the exact number of frames it was configured for we can allow transfers with less than that number of frames, if the total number of frames is a multiple of it. This is done by repeating the frames until the total number of frames has been reached. Signed-off-by: Lars-Peter Clausen --- drivers/dma/xilinx_dma.c | 90 ++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/drivers/dma/xilinx_dma.c b/drivers/dma/xilinx_dma.c index 34a0230f11292..b7bfca76fa263 100644 --- a/drivers/dma/xilinx_dma.c +++ b/drivers/dma/xilinx_dma.c @@ -1231,7 +1231,7 @@ static struct dma_async_tx_descriptor *xilinx_vdma_prep_slave_sg( struct xilinx_dma_chan *chan; struct xilinx_dma_desc_sw *first = NULL, *prev = NULL, *new = NULL; struct xilinx_dma_desc_hw *hw = NULL, *prev_hw = NULL; - int i; + unsigned int i, j; struct scatterlist *sg; dma_addr_t dma_src; @@ -1244,7 +1244,7 @@ static struct dma_async_tx_descriptor *xilinx_vdma_prep_slave_sg( return NULL; /* Enforce one sg entry for one frame */ - if (sg_len != chan->num_frms) { + if (chan->num_frms % sg_len != 0) { dev_err(chan->dev, "number of entries %d not the " "same as num stores %d\n", sg_len, chan->num_frms); @@ -1258,56 +1258,58 @@ static struct dma_async_tx_descriptor *xilinx_vdma_prep_slave_sg( chan->config.stride); } - /* Build transactions using information in the scatter gather list - */ - for_each_sg(sgl, sg, sg_len, i) { + for (j = 0; j < chan->num_frms / sg_len; ++j) { + /* Build transactions using information in the scatter gather list + */ + for_each_sg(sgl, sg, sg_len, i) { - /* Allocate the link descriptor from DMA pool */ - new = xilinx_dma_alloc_descriptor(chan); - if (!new) { - dev_err(chan->dev, "No free memory for " - "link descriptor\n"); - goto fail; - } + /* Allocate the link descriptor from DMA pool */ + new = xilinx_dma_alloc_descriptor(chan); + if (!new) { + dev_err(chan->dev, "No free memory for " + "link descriptor\n"); + goto fail; + } - /* - * Calculate the maximum number of bytes to transfer, - * making sure it is less than the hw limit - */ - hw = &(new->hw); + /* + * Calculate the maximum number of bytes to transfer, + * making sure it is less than the hw limit + */ + hw = &(new->hw); - dma_src = sg_dma_address(sg); - if (chan->has_SG) { - hw->buf_addr = dma_src; + dma_src = sg_dma_address(sg); + if (chan->has_SG) { + hw->buf_addr = dma_src; - /* Fill in the descriptor */ - hw->addr_vsize = chan->config.vsize; - hw->hsize = chan->config.hsize; - hw->control = (chan->config.frm_dly << - XILINX_VDMA_FRMDLY_SHIFT) | - chan->config.stride; - } else { - /* Update the registers */ - DMA_OUT(&(chan->addr_regs->buf_addr[i]), dma_src); - } + /* Fill in the descriptor */ + hw->addr_vsize = chan->config.vsize; + hw->hsize = chan->config.hsize; + hw->control = (chan->config.frm_dly << + XILINX_VDMA_FRMDLY_SHIFT) | + chan->config.stride; + } else { + /* Update the registers */ + DMA_OUT(&(chan->addr_regs->buf_addr[j * sg_len + i]), dma_src); + } - /* If this is not the first descriptor, chain the - * current descriptor after the previous descriptor - */ - if (!first) { - first = new; - } else { - prev_hw = &(prev->hw); - prev_hw->next_desc = new->async_tx.phys; - } + /* If this is not the first descriptor, chain the + * current descriptor after the previous descriptor + */ + if (!first) { + first = new; + } else { + prev_hw = &(prev->hw); + prev_hw->next_desc = new->async_tx.phys; + } - new->async_tx.cookie = 0; - async_tx_ack(&new->async_tx); + new->async_tx.cookie = 0; + async_tx_ack(&new->async_tx); - prev = new; + prev = new; - /* Insert the link descriptor into the list */ - list_add_tail(&new->node, &first->tx_list); + /* Insert the link descriptor into the list */ + list_add_tail(&new->node, &first->tx_list); + } } /* Link the last BD with the first BD */ From e401ac0d86e1420c394e0a6581855fcd8fb5ca75 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 9 Mar 2012 10:49:27 +0100 Subject: [PATCH 034/261] dmaengine: Add helper function for generating a cookie Add a small helper function for generating a new cookie. Signed-off-by: Lars-Peter Clausen --- include/linux/dmaengine.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 679b349d9b666..9a2f5dd0e593c 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -366,6 +366,22 @@ static inline const char *dma_chan_name(struct dma_chan *chan) void dma_chan_cleanup(struct kref *kref); +/** + * dma_chan_generate_cookie - generate a new cookie + * @chan: channel for which to generate the cookie + * + * Note: The caller has to make sure that the function is not called + * concurrently. + */ +static inline dma_cookie_t dma_chan_generate_cookie(struct dma_chan *chan) +{ + chan->cookie++; + if (chan->cookie < DMA_MIN_COOKIE) + chan->cookie = DMA_MIN_COOKIE; + + return chan->cookie; +} + /** * typedef dma_filter_fn - callback filter for dma_request_channel * @chan: channel to be reviewed From 90282bd0ab4aefd46dd447ed609818316952dd44 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Mar 2012 13:46:55 +0100 Subject: [PATCH 035/261] dmaengine: Rework Xilinx DMA driver --- drivers/dma/xilinx_dma.c | 2069 ++++++++++++-------------------------- 1 file changed, 671 insertions(+), 1398 deletions(-) diff --git a/drivers/dma/xilinx_dma.c b/drivers/dma/xilinx_dma.c index b7bfca76fa263..96c265d823a3c 100644 --- a/drivers/dma/xilinx_dma.c +++ b/drivers/dma/xilinx_dma.c @@ -2,13 +2,13 @@ * Xilinx DMA Engine support * * Copyright (C) 2010 Xilinx, Inc. All rights reserved. + * Copyright (C) 2012 Analog Device Inc. + * Author: Lars-Peter Clausen * * Based on the Freescale DMA driver. * * Description: * This driver supports three Xilinx DMA engines: - * . Axi CDMA engine, it does transfers between memory and memory, it - * only has one channel. * . Axi DMA engine, it does transfers between memory and device. It can be * configured to have one channel or two channels. If configured as two * channels, one is to transmit to a device and another is to receive from @@ -33,10 +33,13 @@ #include #include #include +#include #include #include #include #include +#include +#include /* Hw specific definitions */ @@ -75,13 +78,6 @@ #define XILINX_DMA_RX_CHANNEL_OFFSET 0x30 -/* Axi CDMA special register bits - */ -#define XILINX_CDMA_CR_SGMODE_MASK 0x00000008 /**< Scatter gather mode */ - -#define XILINX_CDMA_SR_SGINCLD_MASK 0x00000008 /**< Hybrid build */ -#define XILINX_CDMA_XR_IRQ_SIMPLE_ALL_MASK 0x00005000 /**< All interrupts for - simple only mode */ /* Axi VDMA special register bits */ #define XILINX_VDMA_CIRC_EN 0x00000002 /* Circular mode */ @@ -97,9 +93,7 @@ #define XILINX_VDMA_DIRECT_REG_OFFSET 0x50 #define XILINX_VDMA_CHAN_DIRECT_REG_SIZE 0x50 -#define XILINX_VDMA_PARK_REG_OFFSET 0x28 - -/* BD definitions for Axi Dma and Axi Cdma +/* BD definitions for Axi DMA */ #define XILINX_DMA_BD_STS_COMPL_MASK 0x80000000 #define XILINX_DMA_BD_STS_ERR_MASK 0x70000000 @@ -122,10 +116,6 @@ #define XILINX_DMA_RESET_LOOP 1000000 #define XILINX_DMA_HALT_LOOP 1000000 -/* Device Id in the private structure - */ -#define XILINX_DMA_DEVICE_ID_SHIFT 28 - /* IO accessors */ #define DMA_OUT(addr, val) (iowrite32(val, addr)) @@ -149,14 +139,24 @@ struct xilinx_dma_desc_hw { u32 app_2; /* 0x28 */ u32 app_3; /* 0x2C */ u32 app_4; /* 0x30 */ -} __attribute__((aligned(64))); +} __aligned(64); struct xilinx_dma_desc_sw { - struct xilinx_dma_desc_hw hw; - struct list_head node; - struct list_head tx_list; + struct xilinx_dma_desc_hw *hw; + dma_addr_t phys; +}; + +struct xilinx_dma_transfer { struct dma_async_tx_descriptor async_tx; -} __attribute__((aligned(64))); + struct list_head head; + + bool cyclic; + unsigned int completed_descs; + + unsigned int current_desc; + unsigned int num_descs; + struct xilinx_dma_desc_sw descs[]; +}; struct xdma_regs { u32 cr; /* 0x00 Control Register */ @@ -173,6 +173,20 @@ struct xdma_regs { u32 version; /* 0x2c version (vdma) */ }; +static struct debugfs_reg32 xilinx_dma_debugfs_regs[] = { + { "Control", 0x00 }, + { "Status", 0x04 }, + { "Current descriptor", 0x08 }, + { "Tail descriptor", 0x10 }, + { "Vertical size", 0x50 }, + { "Horizontal size", 0x54 }, + { "Frame delay/stride", 0x58 }, + { "Frame address 0", 0x5c }, + { "Frame address 1", 0x60 }, + { "Frame address 2", 0x64 }, + { "Frame address 3", 0x68 }, +}; + struct vdma_addr_regs { u32 vsize; /* 0x0 Vertical size */ u32 hsize; /* 0x4 Horizontal size */ @@ -186,9 +200,7 @@ struct xilinx_dma_chan { struct xdma_regs __iomem *regs; /* Control status registers */ struct vdma_addr_regs *addr_regs; /* Direct address registers */ dma_cookie_t completed_cookie; /* The maximum cookie completed */ - dma_cookie_t cookie; /* The current cookie */ spinlock_t lock; /* Descriptor operation lock */ - bool sg_waiting; /* Scatter gather transfer waiting */ struct list_head active_list; /* Active descriptors */ struct list_head pending_list; /* Descriptors waiting */ struct dma_chan common; /* DMA common channel */ @@ -196,9 +208,8 @@ struct xilinx_dma_chan { struct device *dev; /* The dma device */ int irq; /* Channel IRQ */ int id; /* Channel ID */ - enum dma_data_direction direction;/* Transfer direction */ + enum dma_transfer_direction direction;/* Transfer direction */ int max_len; /* Maximum data len per transfer */ - int is_lite; /* Whether is light build */ int num_frms; /* Number of frames */ int has_SG; /* Support scatter transfers */ int has_DRE; /* Support unaligned transfers */ @@ -206,9 +217,11 @@ struct xilinx_dma_chan { int err; /* Channel has errors */ struct tasklet_struct tasklet; /* Cleanup work after irq */ u32 feature; /* IP feature */ - u32 private; /* Match info for channel request */ void (*start_transfer)(struct xilinx_dma_chan *chan); struct xilinx_dma_config config; /* Device configuration info */ + + bool cyclic; + struct debugfs_regset32 debugfs_regset; }; struct xilinx_dma_device { @@ -220,8 +233,83 @@ struct xilinx_dma_device { int irq; }; +static dma_cookie_t xilinx_dma_tx_submit(struct dma_async_tx_descriptor *tx); + #define to_xilinx_chan(chan) container_of(chan, struct xilinx_dma_chan, common) +static void xilinx_dma_free_transfer(struct xilinx_dma_chan *chan, + struct xilinx_dma_transfer *t) +{ + unsigned int i; + for (i = 0; i < t->num_descs; ++i) + dma_pool_free(chan->desc_pool, t->descs[i].hw, t->descs[i].phys); + kfree(t); +} + +static struct xilinx_dma_transfer *xilinx_dma_alloc_transfer( + struct xilinx_dma_chan *chan, unsigned int num_descs) +{ + struct xilinx_dma_desc_hw *new, *prev; + struct xilinx_dma_transfer *t; + dma_addr_t phys; + + if (num_descs == 0) + return NULL; + + t = kzalloc(sizeof(*t) + num_descs * sizeof(*t->descs), GFP_ATOMIC); + if (!t) + return NULL; + + dma_async_tx_descriptor_init(&t->async_tx, &chan->common); + t->async_tx.tx_submit = xilinx_dma_tx_submit; + t->async_tx.cookie = -EBUSY; + + prev = NULL; + new = NULL; + for (; t->num_descs < num_descs; t->num_descs++) { + new = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &phys); + if (!new) { + dev_err(chan->dev, "No free memory for link descriptor\n"); + goto err_free; + } + memset(new, 0, sizeof(*new)); + + if (prev) + prev->next_desc = phys; + + t->descs[t->num_descs].hw = new; + t->descs[t->num_descs].phys = phys; + prev = new; + } + + /* Link the last BD with the first BD */ + new->next_desc = t->descs[0].phys; + + return t; +err_free: + xilinx_dma_free_transfer(chan, t); + return NULL; +} + +static void xilinx_dma_free_transfer_list(struct xilinx_dma_chan *chan, + struct list_head *list) +{ + struct xilinx_dma_transfer *t, *_t; + list_for_each_entry_safe(t, _t, list, head) + xilinx_dma_free_transfer(chan, t); + INIT_LIST_HEAD(list); +} + +static void xilinx_dma_free_transfers(struct xilinx_dma_chan *chan) +{ + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + xilinx_dma_free_transfer_list(chan, &chan->active_list); + xilinx_dma_free_transfer_list(chan, &chan->pending_list); + spin_unlock_irqrestore(&chan->lock, flags); +} + /* Required functions */ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan) @@ -238,95 +326,94 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan) */ chan->desc_pool = dma_pool_create("xilinx_dma_desc_pool", chan->dev, - sizeof(struct xilinx_dma_desc_sw), - __alignof__(struct xilinx_dma_desc_sw), 0); + sizeof(struct xilinx_dma_desc_hw), + __alignof__(struct xilinx_dma_desc_hw), 0); if (!chan->desc_pool) { dev_err(chan->dev, "unable to allocate channel %d " "descriptor pool\n", chan->id); return -ENOMEM; } - chan->completed_cookie = 1; - chan->cookie = 1; + chan->completed_cookie = 0; /* there is at least one descriptor free to be allocated */ return 1; } -static void xilinx_dma_free_desc_list(struct xilinx_dma_chan *chan, - struct list_head *list) -{ - struct xilinx_dma_desc_sw *desc, *_desc; - - list_for_each_entry_safe(desc, _desc, list, node) { - list_del(&desc->node); - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); - } -} - -static void xilinx_dma_free_desc_list_reverse(struct xilinx_dma_chan *chan, - struct list_head *list) -{ - struct xilinx_dma_desc_sw *desc, *_desc; - - list_for_each_entry_safe_reverse(desc, _desc, list, node) { - list_del(&desc->node); - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); - } -} - static void xilinx_dma_free_chan_resources(struct dma_chan *dchan) { struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); - unsigned long flags; dev_dbg(chan->dev, "Free all channel resources.\n"); - spin_lock_irqsave(&chan->lock, flags); - xilinx_dma_free_desc_list(chan, &chan->active_list); - xilinx_dma_free_desc_list(chan, &chan->pending_list); - spin_unlock_irqrestore(&chan->lock, flags); - + xilinx_dma_free_transfers(chan); dma_pool_destroy(chan->desc_pool); chan->desc_pool = NULL; } static enum dma_status xilinx_dma_desc_status(struct xilinx_dma_chan *chan, - struct xilinx_dma_desc_sw *desc) + struct xilinx_dma_transfer *t) { - return dma_async_is_complete(desc->async_tx.cookie, + return dma_async_is_complete(t->async_tx.cookie, chan->completed_cookie, - chan->cookie); + chan->common.cookie); +} + +static void xilinx_dma_chan_handle_cyclic(struct xilinx_dma_chan *chan, + struct xilinx_dma_transfer *t, unsigned long *flags) +{ + unsigned int completed_descs; + dma_async_tx_callback callback; + void *callback_param; + unsigned int i; + + /* We have to be carefull not to dereference 't' anymore after a call to + * the callback function, since it might call terminate_all and as a + * result 't' might be already freed. */ + callback = t->async_tx.callback; + callback_param = t->async_tx.callback_param; + completed_descs = t->completed_descs; + t->completed_descs = 0; + + spin_unlock_irqrestore(&chan->lock, *flags); + for (i = 0; i < completed_descs; i++) + callback(callback_param); + spin_lock_irqsave(&chan->lock, *flags); } static void xilinx_chan_desc_cleanup(struct xilinx_dma_chan *chan) { - struct xilinx_dma_desc_sw *desc, *_desc; + struct xilinx_dma_transfer *t; + dma_async_tx_callback callback; + void *callback_param; unsigned long flags; spin_lock_irqsave(&chan->lock, flags); - list_for_each_entry_safe(desc, _desc, &chan->active_list, node) { - dma_async_tx_callback callback; - void *callback_param; + /* terminate_all might be called from the callback, so we can't iterate over + * the list using list_for_each_entry_safe */ + while (!list_empty(&chan->active_list)) { + t = list_first_entry(&chan->active_list, struct xilinx_dma_transfer, head); - if (xilinx_dma_desc_status(chan, desc) == DMA_IN_PROGRESS) + if (t->cyclic) { + xilinx_dma_chan_handle_cyclic(chan, t, &flags); + break; + } + + if (xilinx_dma_desc_status(chan, t) == DMA_IN_PROGRESS) break; - /* Remove from the list of running transactions */ - list_del(&desc->node); + list_del(&t->head); - /* Run the link descriptor callback function */ - callback = desc->async_tx.callback; - callback_param = desc->async_tx.callback_param; + callback = t->async_tx.callback; + callback_param = t->async_tx.callback_param; if (callback) { spin_unlock_irqrestore(&chan->lock, flags); callback(callback_param); spin_lock_irqsave(&chan->lock, flags); } - /* Run any dependencies, then free the descriptor */ - dma_run_dependencies(&desc->async_tx); - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); + dma_run_dependencies(&t->async_tx); + xilinx_dma_free_transfer(chan, t); } spin_unlock_irqrestore(&chan->lock, flags); @@ -350,27 +437,30 @@ static enum dma_status xilinx_tx_status(struct dma_chan *dchan, return dma_async_is_complete(cookie, last_complete, last_used); } -static int dma_is_running(struct xilinx_dma_chan *chan) +static int xilinx_dma_is_running(struct xilinx_dma_chan *chan) { return !(DMA_IN(&chan->regs->sr) & XILINX_DMA_SR_HALTED_MASK) && (DMA_IN(&chan->regs->cr) & XILINX_DMA_CR_RUNSTOP_MASK); } -static int dma_is_idle(struct xilinx_dma_chan *chan) +static int xilinx_dma_is_idle(struct xilinx_dma_chan *chan) { return DMA_IN(&chan->regs->sr) & XILINX_DMA_SR_IDLE_MASK; } -/* Only needed for Axi CDMA v2_00_a or earlier core - */ -static void dma_sg_toggle(struct xilinx_dma_chan *chan) +static int xilinx_dma_wait_idle(struct xilinx_dma_chan *chan) { + unsigned long timeout = 10000; - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) & ~XILINX_CDMA_CR_SGMODE_MASK); + do { + if (xilinx_dma_is_idle(chan)) + break; + } while (--timeout); - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) | XILINX_CDMA_CR_SGMODE_MASK); + if (!xilinx_dma_is_idle(chan)) + return -ETIMEDOUT; + + return 0; } #define XILINX_DMA_DRIVER_DEBUG 0 @@ -385,167 +475,117 @@ static void desc_dump(struct xilinx_dma_desc_hw *hw) printk(KERN_INFO "\thsize %x\n", hw->hsize); printk(KERN_INFO "\tcontrol %x\n", hw->control); printk(KERN_INFO "\tstatus %x\n", hw->status); - } #endif -static void xilinx_cdma_start_transfer(struct xilinx_dma_chan *chan) +static int xilinx_dma_wait_status(struct xilinx_dma_chan *chan, uint32_t mask, + uint32_t value) { - unsigned long flags; - struct xilinx_dma_desc_sw *desch, *desct; - struct xilinx_dma_desc_hw *hw; + unsigned long timeout = 10000; + uint32_t status; - if (chan->err) - return; + do { + status = DMA_IN(&chan->regs->cr); + printk("status: %x, mask: %x, value: %x\n", status, mask, value); + if ((status & mask) == value) + break; + } while (--timeout); - spin_lock_irqsave(&chan->lock, flags); + if ((status & mask) != value) + return -ETIMEDOUT; - if (list_empty(&chan->pending_list)) - goto out_unlock; + return 0; +} - /* If hardware is busy, cannot submit - */ - if (!dma_is_idle(chan)) { - dev_dbg(chan->dev, "DMA controller still busy %x\n", - DMA_IN(&chan->regs->sr)); - goto out_unlock; - } +static int xilinx_dma_reset(struct xilinx_dma_chan *chan) +{ + int ret; - /* Enable interrupts - */ DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) | XILINX_DMA_XR_IRQ_ALL_MASK); - - desch = list_first_entry(&chan->pending_list, struct xilinx_dma_desc_sw, - node); - - if (chan->has_SG) { - - /* If hybrid mode, append pending list to active list - */ - desct = container_of(chan->pending_list.prev, - struct xilinx_dma_desc_sw, node); - - list_splice_tail_init(&chan->pending_list, &chan->active_list); - - /* If hardware is idle, then all descriptors on the active list - * are done, start new transfers - */ - dma_sg_toggle(chan); + DMA_IN(&chan->regs->cr) | XILINX_DMA_CR_RESET_MASK); - DMA_OUT(&chan->regs->cdr, desch->async_tx.phys); + ret = xilinx_dma_wait_status(chan, XILINX_DMA_CR_RESET_MASK, 0); - /* Update tail ptr register and start the transfer - */ - DMA_OUT(&chan->regs->tdr, desct->async_tx.phys); - goto out_unlock; + if (ret) { + dev_err(chan->dev, "reset timeout, cr %x, sr %x\n", + DMA_IN(&chan->regs->cr), DMA_IN(&chan->regs->sr)); + return 1; } - /* In simple mode - */ - list_del(&desch->node); - list_add_tail(&desch->node, &chan->active_list); - - hw = &desch->hw; + /* re-apply config */ + dmaengine_device_control(&chan->common, DMA_SLAVE_CONFIG, + (unsigned long)&chan->config); - DMA_OUT(&chan->regs->src, hw->buf_addr); - DMA_OUT(&chan->regs->dst, hw->addr_vsize); - - /* Start the transfer - */ - DMA_OUT(&chan->regs->btt_ref, - hw->control & XILINX_DMA_MAX_TRANS_LEN); - -out_unlock: - spin_unlock_irqrestore(&chan->lock, flags); + return 0; } -/* If sg mode, link the pending list to running list; if simple mode, get the - * head of the pending list and submit it to hw - */ -static void xilinx_cdma_issue_pending(struct dma_chan *dchan) +static void xilinx_dma_start_stop(struct xilinx_dma_chan *chan, bool start) { - struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); - xilinx_cdma_start_transfer(chan); + uint32_t status; + uint32_t value; + int ret; + + if (start) + value = XILINX_DMA_CR_RUNSTOP_MASK; + else + value = 0; + + status = DMA_IN(&chan->regs->cr); + status &= ~XILINX_DMA_CR_RUNSTOP_MASK; + status |= value; + DMA_OUT(&chan->regs->cr, status); + + ret = xilinx_dma_wait_status(chan, XILINX_DMA_CR_RUNSTOP_MASK, value); + if (ret) { + dev_dbg(chan->dev, "Cannot %s channel %x: %x\n", + start ? "start" : "stop", chan->id, + DMA_IN(&chan->regs->cr)); + chan->err = 1; + } } /* Stop the hardware, the ongoing transfer will be finished */ static void dma_halt(struct xilinx_dma_chan *chan) { - int loop = XILINX_DMA_HALT_LOOP; - - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) & ~XILINX_DMA_CR_RUNSTOP_MASK); - - /* Wait for the hardware to halt - */ - while (loop) { - if (!(DMA_IN(&chan->regs->cr) & XILINX_DMA_CR_RUNSTOP_MASK)) - break; - - loop -= 1; - } - - if (!loop) { - pr_debug("Cannot stop channel %x: %x\n", - (unsigned int)chan, - (unsigned int)DMA_IN(&chan->regs->cr)); - chan->err = 1; - } - - return; + xilinx_dma_start_stop(chan, false); } /* Start the hardware. Transfers are not started yet */ static void dma_start(struct xilinx_dma_chan *chan) { - int loop = XILINX_DMA_HALT_LOOP; - - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) | XILINX_DMA_CR_RUNSTOP_MASK); - - /* Wait for the hardware to start - */ - while (loop) { - if (DMA_IN(&chan->regs->cr) & XILINX_DMA_CR_RUNSTOP_MASK) - break; - - loop -= 1; - } - - if (!loop) { - pr_debug("Cannot start channel %x: %x\n", - (unsigned int)chan, - (unsigned int)DMA_IN(&chan->regs->cr)); - - chan->err = 1; - } - - return; + xilinx_dma_start_stop(chan, true); } - static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan) { - unsigned long flags; - struct xilinx_dma_desc_sw *desch, *desct; + struct xilinx_dma_transfer *last_transfer, *first_transfer; + dma_addr_t first_addr, last_addr; struct xilinx_dma_desc_hw *hw; - - if (chan->err) - return; + unsigned long flags; + int ret; spin_lock_irqsave(&chan->lock, flags); if (list_empty(&chan->pending_list)) goto out_unlock; + if (chan->err) { + dev_err(chan->dev, "Failed to start transfer\n"); + goto out_unlock; + } + /* If hardware is busy, cannot submit */ - if (dma_is_running(chan) && !dma_is_idle(chan)) { - dev_dbg(chan->dev, "DMA controller still busy\n"); + if (xilinx_dma_is_running(chan) && !xilinx_dma_is_idle(chan)) { + dev_info(chan->dev, "DMA controller still busy\n"); goto out_unlock; } + ret = xilinx_dma_wait_idle(chan); + if (ret) + xilinx_dma_reset(chan); + + /* If hardware is idle, then all descriptors on active list are * done, start new transfers */ @@ -554,14 +594,18 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan) if (chan->err) goto out_unlock; + first_transfer = list_first_entry(&chan->pending_list, + struct xilinx_dma_transfer, head); + if (chan->has_SG) { - desch = list_first_entry(&chan->pending_list, - struct xilinx_dma_desc_sw, node); + uint32_t status; + last_transfer = list_entry(chan->pending_list.prev, + struct xilinx_dma_transfer, head); - desct = container_of(chan->pending_list.prev, - struct xilinx_dma_desc_sw, node); + first_addr = first_transfer->descs[0].phys; + last_addr = last_transfer->descs[last_transfer->num_descs-1].phys; - DMA_OUT(&chan->regs->cdr, desch->async_tx.phys); + DMA_OUT(&chan->regs->cdr, first_addr); dma_start(chan); @@ -569,51 +613,38 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan) goto out_unlock; list_splice_tail_init(&chan->pending_list, &chan->active_list); - /* Enable interrupts - */ + /* Clear pending interrupts and enable interrupts */ + DMA_OUT(&chan->regs->sr, XILINX_DMA_XR_IRQ_ALL_MASK); DMA_OUT(&chan->regs->cr, DMA_IN(&chan->regs->cr) | XILINX_DMA_XR_IRQ_ALL_MASK); - + status = DMA_IN(&chan->regs->sr); /* Update tail ptr register and start the transfer */ - DMA_OUT(&chan->regs->tdr, desct->async_tx.phys); - goto out_unlock; - } - - /* In simple mode - */ - - dma_halt(chan); - - if (chan->err) - goto out_unlock; - - printk(KERN_INFO "xilinx_dma_start_transfer::simple DMA mode\n"); - - desch = list_first_entry(&chan->pending_list, - struct xilinx_dma_desc_sw, node); + DMA_OUT(&chan->regs->tdr, last_addr); + } else { + /* In simple mode */ - list_del(&desch->node); - list_add_tail(&desch->node, &chan->active_list); + list_move_tail(&first_transfer->head, &chan->active_list); - dma_start(chan); + dma_start(chan); - if (chan->err) - goto out_unlock; + if (chan->err) + goto out_unlock; - hw = &desch->hw; + hw = first_transfer->descs[0].hw; - /* Enable interrupts - */ - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) | XILINX_DMA_XR_IRQ_ALL_MASK); + /* Enable interrupts + */ + DMA_OUT(&chan->regs->cr, + DMA_IN(&chan->regs->cr) | XILINX_DMA_XR_IRQ_ALL_MASK); - DMA_OUT(&chan->regs->src, hw->buf_addr); + DMA_OUT(&chan->regs->src, hw->buf_addr); - /* Start the transfer - */ - DMA_OUT(&chan->regs->btt_ref, - hw->control & XILINX_DMA_MAX_TRANS_LEN); + /* Start the transfer + */ + DMA_OUT(&chan->regs->btt_ref, + hw->control & XILINX_DMA_MAX_TRANS_LEN); + } out_unlock: spin_unlock_irqrestore(&chan->lock, flags); @@ -622,220 +653,103 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan) static void xilinx_dma_issue_pending(struct dma_chan *dchan) { struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); - xilinx_dma_start_transfer(chan); + chan->start_transfer(chan); } -static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan) +/** + * xilinx_dma_update_completed_cookie - Update the completed cookie. + * @chan : xilinx DMA channel + * + * CONTEXT: hardirq + */ +static void xilinx_dma_update_completed_cookie(struct xilinx_dma_chan *chan) { + struct xilinx_dma_transfer *t; + struct xilinx_dma_desc_hw *hw = NULL; unsigned long flags; - struct xilinx_dma_desc_sw *desch, *desct = NULL; - struct xilinx_dma_config *config; - u32 reg; - u8 *chan_base; - - if (chan->err) - return; + dma_cookie_t cookie = -EBUSY; + bool done = 0; spin_lock_irqsave(&chan->lock, flags); - if (list_empty(&chan->pending_list)) - goto out_unlock; - - /* If it is SG mode and hardware is busy, cannot submit - */ - if (chan->has_SG && dma_is_running(chan) && !dma_is_idle(chan)) { - dev_dbg(chan->dev, "DMA controller still busy\n"); + if (list_empty(&chan->active_list)) { + dev_dbg(chan->dev, "no running descriptors\n"); goto out_unlock; } - /* If hardware is idle, then all descriptors on the running lists are - * done, start new transfers - */ - if (chan->err) - goto out_unlock; - - if (chan->has_SG) { - desch = list_first_entry(&chan->pending_list, - struct xilinx_dma_desc_sw, node); - - desct = container_of(chan->pending_list.prev, - struct xilinx_dma_desc_sw, node); + if ((!(chan->feature & XILINX_DMA_IP_VDMA)) && chan->has_SG) { + /* Get the last completed descriptor, update the cookie to that */ + list_for_each_entry(t, &chan->active_list, head) { + if (t->cyclic) { + while (true) { + hw = t->descs[t->current_desc].hw; + if (!(hw->status & XILINX_DMA_BD_STS_ALL_MASK)) + break; + t->completed_descs++; + hw->status = 0; + DMA_OUT(&chan->regs->tdr, t->descs[t->current_desc].phys); + + t->current_desc++; + if (t->current_desc == t->num_descs) + t->current_desc = 0; + } + } else { + for (; t->current_desc < t->num_descs; t->current_desc++) { + hw = t->descs[t->current_desc].hw; + if (!(hw->status & XILINX_DMA_BD_STS_ALL_MASK)) + break; + } + if (t->current_desc != t->num_descs) + break; - DMA_OUT(&chan->regs->cdr, desch->async_tx.phys); + done = true; + cookie = t->async_tx.cookie; + } + } + } else { + /* In non-SG mode, there is only one transfer active at a time */ + t = list_first_entry(&chan->active_list, + struct xilinx_dma_transfer, head); + t->current_desc++; + t->completed_descs++; + if (t->current_desc == t->num_descs) { + if (t->cyclic) { + t->current_desc = 0; + } else { + done = true; + cookie = t->async_tx.cookie; + } + } } - /* Configure the hardware using info in the config structure */ - config = &(chan->config); - reg = DMA_IN(&chan->regs->cr); + if (done) + chan->completed_cookie = cookie; - if (config->frm_cnt_en) - reg |= XILINX_VDMA_FRMCNT_EN; - else - reg &= ~XILINX_VDMA_FRMCNT_EN; +out_unlock: + spin_unlock_irqrestore(&chan->lock, flags); +} - /* With SG, start with circular mode, so that BDs can be fetched. - * In direct register mode, if not parking, enable circular mode */ - if ((chan->has_SG) || (!config->park)) - reg |= XILINX_VDMA_CIRC_EN; +static irqreturn_t dma_intr_handler(int irq, void *data) +{ + struct xilinx_dma_chan *chan = data; + u32 stat; - if (config->park) - reg &= ~XILINX_VDMA_CIRC_EN; - - DMA_OUT(&chan->regs->cr, reg); - - if ((config->park_frm >= 0) && (config->park_frm < chan->num_frms)) { - if (config->direction == DMA_TO_DEVICE) { - chan_base = (char *)chan->regs; - DMA_OUT((chan_base + XILINX_VDMA_PARK_REG_OFFSET), - config->park_frm); - } else { - chan_base = ((char *)chan->regs - - XILINX_DMA_RX_CHANNEL_OFFSET); - DMA_OUT((chan_base + XILINX_VDMA_PARK_REG_OFFSET), - config->park_frm << XILINX_VDMA_WR_REF_SHIFT); - } - } - - /* Start the hardware - */ - dma_start(chan); - - if (chan->err) - goto out_unlock; - list_splice_tail_init(&chan->pending_list, &chan->active_list); - - /* Enable interrupts - * - * park/genlock testing does not use interrupts */ - if (!chan->config.disable_intr) { - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) | XILINX_DMA_XR_IRQ_ALL_MASK); - } - - /* Start the transfer - */ - if (chan->has_SG) - DMA_OUT(&chan->regs->tdr, desct->async_tx.phys); - else - DMA_OUT(&chan->addr_regs->vsize, config->vsize); - -out_unlock: - spin_unlock_irqrestore(&chan->lock, flags); -} - -static void xilinx_vdma_issue_pending(struct dma_chan *dchan) -{ - struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); - xilinx_vdma_start_transfer(chan); -} - -/** - * xilinx_dma_update_completed_cookie - Update the completed cookie. - * @chan : xilinx DMA channel - * - * CONTEXT: hardirq - */ -static void xilinx_dma_update_completed_cookie(struct xilinx_dma_chan *chan) -{ - struct xilinx_dma_desc_sw *desc = NULL; - struct xilinx_dma_desc_hw *hw = NULL; - unsigned long flags; - dma_cookie_t cookie = -EBUSY; - int done = 0; - - spin_lock_irqsave(&chan->lock, flags); - - if (list_empty(&chan->active_list)) { - dev_dbg(chan->dev, "no running descriptors\n"); - goto out_unlock; - } - - /* Get the last completed descriptor, update the cookie to that */ - list_for_each_entry(desc, &chan->active_list, node) { - if ((!(chan->feature & XILINX_DMA_IP_VDMA)) && chan->has_SG) { - hw = &desc->hw; - - /* If a BD has no status bits set, hw has it */ - if (!(hw->status & XILINX_DMA_BD_STS_ALL_MASK)) { - break; - } else { - done = 1; - cookie = desc->async_tx.cookie; - } - } else { - /* In non-SG mode, all active entries are done */ - done = 1; - cookie = desc->async_tx.cookie; - } - } - - if (done) - chan->completed_cookie = cookie; - -out_unlock: - spin_unlock_irqrestore(&chan->lock, flags); -} - -/* Reset hardware - */ -static int dma_init(struct xilinx_dma_chan *chan) -{ - int loop = XILINX_DMA_RESET_LOOP; - u32 tmp; - - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) | XILINX_DMA_CR_RESET_MASK); - - tmp = DMA_IN(&chan->regs->cr) & XILINX_DMA_CR_RESET_MASK; - - /* Wait for the hardware to finish reset - */ - while (loop && tmp) { - tmp = DMA_IN(&chan->regs->cr) & XILINX_DMA_CR_RESET_MASK; - loop -= 1; - } - - if (!loop) { - dev_err(chan->dev, "reset timeout, cr %x, sr %x\n", - DMA_IN(&chan->regs->cr), DMA_IN(&chan->regs->sr)); - return 1; - } - - /* For Axi CDMA, always do sg transfers if sg mode is built in - */ - if ((chan->feature & XILINX_DMA_IP_CDMA) && chan->has_SG) - DMA_OUT(&chan->regs->cr, tmp | XILINX_CDMA_CR_SGMODE_MASK); - - return 0; -} - - -static irqreturn_t dma_intr_handler(int irq, void *data) -{ - struct xilinx_dma_chan *chan = data; - int update_cookie = 0; - int to_transfer = 0; - u32 stat; - - /* Disable intr - */ - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) & ~XILINX_DMA_XR_IRQ_ALL_MASK); - - stat = DMA_IN(&chan->regs->sr); - if (!(stat & XILINX_DMA_XR_IRQ_ALL_MASK)) - return IRQ_NONE; + stat = DMA_IN(&chan->regs->sr); + if (!(stat & XILINX_DMA_XR_IRQ_ALL_MASK)) + return IRQ_NONE; /* Ack the interrupts */ DMA_OUT(&chan->regs->sr, XILINX_DMA_XR_IRQ_ALL_MASK); if (stat & XILINX_DMA_XR_IRQ_ERROR_MASK) { - dev_err(chan->dev, "Channel %x has errors %x, cdr %x tdr %x\n", + dev_err(chan->dev, "Channel %x has errors %x, cr %x, cdr %x tdr %x\n", (unsigned int)chan, (unsigned int)stat, + (unsigned int)DMA_IN(&chan->regs->cr), (unsigned int)DMA_IN(&chan->regs->cdr), (unsigned int)DMA_IN(&chan->regs->tdr)); chan->err = 1; + dma_halt(chan); } /* Device takes too long to do the transfer when user requires @@ -845,15 +759,9 @@ static irqreturn_t dma_intr_handler(int irq, void *data) dev_dbg(chan->dev, "Inter-packet latency too long\n"); if (stat & XILINX_DMA_XR_IRQ_IOC_MASK) { - update_cookie = 1; - to_transfer = 1; - } - - if (update_cookie) xilinx_dma_update_completed_cookie(chan); - - if (to_transfer) chan->start_transfer(chan); + } tasklet_schedule(&chan->tasklet); return IRQ_HANDLED; @@ -862,32 +770,29 @@ static irqreturn_t dma_intr_handler(int irq, void *data) static void dma_do_tasklet(unsigned long data) { struct xilinx_dma_chan *chan = (struct xilinx_dma_chan *)data; - xilinx_chan_desc_cleanup(chan); } /* Append the descriptor list to the pending list */ static void append_desc_queue(struct xilinx_dma_chan *chan, - struct xilinx_dma_desc_sw *desc) + struct xilinx_dma_transfer *t) { - struct xilinx_dma_desc_sw *tail = container_of(chan->pending_list.prev, - struct xilinx_dma_desc_sw, node); + struct xilinx_dma_transfer *tail = container_of(chan->pending_list.prev, + struct xilinx_dma_transfer, head); struct xilinx_dma_desc_hw *hw; - if (list_empty(&chan->pending_list)) - goto out_splice; - - /* Add the hardware descriptor to the chain of hardware descriptors - * that already exists in memory. - */ - hw = &(tail->hw); - hw->next_desc = (u32)desc->async_tx.phys; + if (!list_empty(&chan->pending_list)) { + /* Add the hardware descriptor to the chain of hardware descriptors + * that already exists in memory. + */ + hw = tail->descs[tail->num_descs-1].hw; + hw->next_desc = t->descs[0].phys; + } /* Add the software descriptor and all children to the list * of pending transactions */ -out_splice: - list_splice_tail_init(&desc->tx_list, &chan->pending_list); + list_add_tail(&t->head, &chan->pending_list); } /* Assign cookie to each descriptor, and append the descriptors to the pending @@ -896,189 +801,88 @@ static void append_desc_queue(struct xilinx_dma_chan *chan, static dma_cookie_t xilinx_dma_tx_submit(struct dma_async_tx_descriptor *tx) { struct xilinx_dma_chan *chan = to_xilinx_chan(tx->chan); - struct xilinx_dma_desc_sw *desc = container_of(tx, - struct xilinx_dma_desc_sw, async_tx); - struct xilinx_dma_desc_sw *child; + struct xilinx_dma_transfer *t = container_of(tx, + struct xilinx_dma_transfer, async_tx); unsigned long flags; - dma_cookie_t cookie = -EBUSY; + + spin_lock_irqsave(&chan->lock, flags); + + if (chan->cyclic) + goto err; if (chan->err) { /* If reset fails, need to hard reset the system. * Channel is no longer functional */ - if (!dma_init(chan)) + if (!xilinx_dma_reset(chan)) chan->err = 0; else - return cookie; - } - - spin_lock_irqsave(&chan->lock, flags); - - /* - * assign cookies to all of the software descriptors - * that make up this transaction - */ - cookie = chan->cookie; - list_for_each_entry(child, &desc->tx_list, node) { - cookie++; - if (cookie < 0) - cookie = DMA_MIN_COOKIE; - - child->async_tx.cookie = cookie; + goto err; } - chan->cookie = cookie; - + t->async_tx.cookie = dma_chan_generate_cookie(&chan->common); /* put this transaction onto the tail of the pending queue */ - append_desc_queue(chan, desc); - - spin_unlock_irqrestore(&chan->lock, flags); - - return cookie; -} - -static struct xilinx_dma_desc_sw *xilinx_dma_alloc_descriptor( - struct xilinx_dma_chan *chan) -{ - struct xilinx_dma_desc_sw *desc; - dma_addr_t pdesc; + append_desc_queue(chan, t); - desc = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc); - if (!desc) { - dev_dbg(chan->dev, "out of memory for desc\n"); - return NULL; - } + if (t->cyclic) + chan->cyclic = true; - memset(desc, 0, sizeof(*desc)); - INIT_LIST_HEAD(&desc->tx_list); - dma_async_tx_descriptor_init(&desc->async_tx, &chan->common); - desc->async_tx.tx_submit = xilinx_dma_tx_submit; - desc->async_tx.phys = pdesc; + spin_unlock_irqrestore(&chan->lock, flags); - return desc; + return t->async_tx.cookie; +err: + spin_unlock_irqrestore(&chan->lock, flags); + xilinx_dma_free_transfer(chan, t); + return -EBUSY; } /** - * xilinx_dma_prep_memcpy - prepare descriptors for a memcpy transaction - * @dchan: DMA channel - * @dma_dst: destination address - * @dma_src: source address - * @len: transfer length + * xilinx_dma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction + * @chan: DMA channel + * @sgl: scatterlist to transfer to/from + * @sg_len: number of entries in @scatterlist + * @direction: DMA direction * @flags: transfer ack flags */ -static struct dma_async_tx_descriptor *xilinx_dma_prep_memcpy( - struct dma_chan *dchan, dma_addr_t dma_dst, dma_addr_t dma_src, - size_t len, unsigned long flags) +static struct dma_async_tx_descriptor *xilinx_dma_prep_dma_cyclic( + struct dma_chan *dchan, dma_addr_t buf_addr, size_t buf_len, + size_t period_len, enum dma_transfer_direction direction) { + struct xilinx_dma_desc_hw *hw; + struct xilinx_dma_transfer *t; struct xilinx_dma_chan *chan; - struct xilinx_dma_desc_sw *first = NULL, *prev = NULL, *new; - struct xilinx_dma_desc_hw *hw, *prev_hw; - size_t copy; - dma_addr_t src = dma_src; - dma_addr_t dst = dma_dst; + unsigned int num_periods; + unsigned int i; if (!dchan) return NULL; - if (!len) - return NULL; - chan = to_xilinx_chan(dchan); - if (chan->err) { - - /* If reset fails, need to hard reset the system. - * Channel is no longer functional - */ - if (!dma_init(chan)) - chan->err = 0; - else - return NULL; - } + if (chan->direction != direction) + return NULL; - /* If build does not have Data Realignment Engine (DRE), - * src has to be aligned - */ - if (!chan->has_DRE) { - if ((dma_src & - (chan->feature & XILINX_DMA_FTR_DATA_WIDTH_MASK)) || - (dma_dst & - (chan->feature & XILINX_DMA_FTR_DATA_WIDTH_MASK))) { + num_periods = buf_len / period_len; - dev_err(chan->dev, - "Source or destination address not aligned when no DRE\n"); + t = xilinx_dma_alloc_transfer(chan, num_periods); + if (!t) + return NULL; - return NULL; - } + for (i = 0; i < num_periods; ++i) { + hw = t->descs[i].hw; + hw->buf_addr = buf_addr; + hw->control = period_len; + hw->control |= XILINX_DMA_BD_SOP | XILINX_DMA_BD_EOP; + buf_addr += period_len; } - do { - - /* Allocate descriptor from DMA pool */ - new = xilinx_dma_alloc_descriptor(chan); - if (!new) { - dev_err(chan->dev, - "No free memory for link descriptor\n"); - goto fail; - } - - copy = min(len, (size_t)chan->max_len); - - /* if lite build, transfer cannot cross page boundary - */ - if (chan->is_lite) - copy = min(copy, (size_t)(PAGE_MASK - - (src & PAGE_MASK))); - - if (!copy) { - dev_err(chan->dev, - "Got zero transfer length for %x\n", - (unsigned int)src); - goto fail; - } - - hw = &(new->hw); - hw->control = - (hw->control & ~XILINX_DMA_MAX_TRANS_LEN) | copy; - hw->buf_addr = src; - hw->addr_vsize = dst; - - if (!first) - first = new; - else { - prev_hw = &(prev->hw); - prev_hw->next_desc = new->async_tx.phys; - } - - new->async_tx.cookie = 0; - async_tx_ack(&new->async_tx); - - prev = new; - len -= copy; - src += copy; - dst += copy; - - /* Insert the descriptor to the list */ - list_add_tail(&new->node, &first->tx_list); - } while (len); - - /* Link the last BD with the first BD */ - hw->next_desc = first->async_tx.phys; + t->cyclic = true; - new->async_tx.flags = flags; /* client is in control of this ack */ - new->async_tx.cookie = -EBUSY; - - return &first->async_tx; - -fail: - if (!first) - return NULL; - - xilinx_dma_free_desc_list_reverse(chan, &first->tx_list); - return NULL; + return &t->async_tx; } + /** * xilinx_dma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction * @chan: DMA channel @@ -1089,22 +893,19 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_memcpy( */ static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg( struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_data_direction direction, unsigned long flags) + enum dma_transfer_direction direction, unsigned long flags) { + struct xilinx_dma_desc_hw *hw; + struct xilinx_dma_transfer *t; struct xilinx_dma_chan *chan; - struct xilinx_dma_desc_sw *first = NULL, *prev = NULL, *new = NULL; - struct xilinx_dma_desc_hw *hw = NULL, *prev_hw = NULL; - - size_t copy; - - int i; + unsigned int total_len = 0; + unsigned int num_descs = 0; struct scatterlist *sg; - size_t sg_used; dma_addr_t dma_src; + size_t num_bytes; + size_t sg_used; + unsigned int i, j; -#ifdef TEST_DMA_WITH_LOOPBACK - int total_len; -#endif if (!dchan) return NULL; @@ -1113,107 +914,48 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg( if (chan->direction != direction) return NULL; -#ifdef TEST_DMA_WITH_LOOPBACK - total_len = 0; - for_each_sg(sgl, sg, sg_len, i) { total_len += sg_dma_len(sg); + num_descs += DIV_ROUND_UP(sg_dma_len(sg), chan->max_len); } -#endif + + t = xilinx_dma_alloc_transfer(chan, num_descs); + if (!t) + return NULL; + /* * Build transactions using information in the scatter gather list */ + j = 0; for_each_sg(sgl, sg, sg_len, i) { sg_used = 0; /* Loop until the entire scatterlist entry is used */ while (sg_used < sg_dma_len(sg)) { - - /* Allocate the link descriptor from DMA pool */ - new = xilinx_dma_alloc_descriptor(chan); - if (!new) { - dev_err(chan->dev, "No free memory for " - "link descriptor\n"); - goto fail; - } - /* * Calculate the maximum number of bytes to transfer, * making sure it is less than the hw limit */ - copy = min((size_t)(sg_dma_len(sg) - sg_used), - (size_t)chan->max_len); - hw = &(new->hw); + num_bytes = min_t(size_t, sg_dma_len(sg) - sg_used, + chan->max_len); dma_src = sg_dma_address(sg) + sg_used; + hw = t->descs[j].hw; hw->buf_addr = dma_src; - - /* Fill in the descriptor */ - hw->control = copy; - - /* - * If this is not the first descriptor, chain the - * current descriptor after the previous descriptor - * - * For the first DMA_TO_DEVICE transfer, set SOP - */ - if (!first) { - first = new; - if (direction == DMA_TO_DEVICE) { - hw->control |= XILINX_DMA_BD_SOP; -#ifdef TEST_DMA_WITH_LOOPBACK - hw->app_4 = copy; -#endif - } - } else { - prev_hw = &(prev->hw); - prev_hw->next_desc = new->async_tx.phys; - } - - new->async_tx.cookie = 0; - async_tx_ack(&new->async_tx); - - prev = new; - sg_used += copy; - - /* Insert the link descriptor into the LD ring */ - list_add_tail(&new->node, &first->tx_list); + hw->control = num_bytes; + j++; } } - /* Link the last BD with the first BD */ - hw->next_desc = first->async_tx.phys; - - if (direction == DMA_TO_DEVICE) - hw->control |= XILINX_DMA_BD_EOP; - - /* All scatter gather list entries has length == 0 */ - if (!first || !new) - return NULL; - - new->async_tx.flags = flags; - new->async_tx.cookie = -EBUSY; - - /* Set EOP to the last link descriptor of new list */ - hw->control |= XILINX_DMA_BD_EOP; - - return &first->async_tx; + /* Set EOP to the last link descriptor of new list and + SOP to the first link descriptor. */ + t->descs[0].hw->control |= XILINX_DMA_BD_SOP; + t->descs[t->num_descs-1].hw->control |= XILINX_DMA_BD_EOP; -fail: - /* If first was not set, then we failed to allocate the very first - * descriptor, and we're done */ - if (!first) - return NULL; - - /* - * First is set, so all of the descriptors we allocated have been added - * to first->tx_list, INCLUDING "first" itself. Therefore we - * must traverse the list backwards freeing each descriptor in turn - */ - xilinx_dma_free_desc_list_reverse(chan, &first->tx_list); + t->async_tx.flags = flags; - return NULL; + return &t->async_tx; } /** @@ -1226,13 +968,13 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg( */ static struct dma_async_tx_descriptor *xilinx_vdma_prep_slave_sg( struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_data_direction direction, unsigned long flags) + enum dma_transfer_direction direction, unsigned long flags) { + struct xilinx_dma_desc_hw *hw; + struct xilinx_dma_transfer *t; struct xilinx_dma_chan *chan; - struct xilinx_dma_desc_sw *first = NULL, *prev = NULL, *new = NULL; - struct xilinx_dma_desc_hw *hw = NULL, *prev_hw = NULL; - unsigned int i, j; struct scatterlist *sg; + unsigned int i, j; dma_addr_t dma_src; if (!dchan) @@ -1251,6 +993,10 @@ static struct dma_async_tx_descriptor *xilinx_vdma_prep_slave_sg( return NULL; } + t = xilinx_dma_alloc_transfer(chan, sg_len); + if (!t) + return NULL; + if (!chan->has_SG) { DMA_OUT(&chan->addr_regs->hsize, chan->config.hsize); DMA_OUT(&chan->addr_regs->frmdly_stride, @@ -1262,23 +1008,9 @@ static struct dma_async_tx_descriptor *xilinx_vdma_prep_slave_sg( /* Build transactions using information in the scatter gather list */ for_each_sg(sgl, sg, sg_len, i) { - - /* Allocate the link descriptor from DMA pool */ - new = xilinx_dma_alloc_descriptor(chan); - if (!new) { - dev_err(chan->dev, "No free memory for " - "link descriptor\n"); - goto fail; - } - - /* - * Calculate the maximum number of bytes to transfer, - * making sure it is less than the hw limit - */ - hw = &(new->hw); - dma_src = sg_dma_address(sg); if (chan->has_SG) { + hw = t->descs[j * sg_len + i].hw; hw->buf_addr = dma_src; /* Fill in the descriptor */ @@ -1291,101 +1023,115 @@ static struct dma_async_tx_descriptor *xilinx_vdma_prep_slave_sg( /* Update the registers */ DMA_OUT(&(chan->addr_regs->buf_addr[j * sg_len + i]), dma_src); } - - /* If this is not the first descriptor, chain the - * current descriptor after the previous descriptor - */ - if (!first) { - first = new; - } else { - prev_hw = &(prev->hw); - prev_hw->next_desc = new->async_tx.phys; - } - - new->async_tx.cookie = 0; - async_tx_ack(&new->async_tx); - - prev = new; - - /* Insert the link descriptor into the list */ - list_add_tail(&new->node, &first->tx_list); } } - /* Link the last BD with the first BD */ - hw->next_desc = first->async_tx.phys; - - if (!first || !new) - return NULL; - - new->async_tx.flags = flags; - new->async_tx.cookie = -EBUSY; - - return &first->async_tx; - -fail: - /* If first was not set, then we failed to allocate the very first - * descriptor, and we're done */ - if (!first) - return NULL; + t->async_tx.flags = flags; - /* First is set, so all of the descriptors we allocated have been added - * to first->tx_list, INCLUDING "first" itself. Therefore we - * must traverse the list backwards freeing each descriptor in turn - */ - xilinx_dma_free_desc_list_reverse(chan, &first->tx_list); - return NULL; + return &t->async_tx; } -/* Run-time device configuration for Axi DMA and Axi CDMA */ -static int xilinx_dma_device_control(struct dma_chan *dchan, - enum dma_ctrl_cmd cmd, unsigned long arg) +static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan) { - struct xilinx_dma_chan *chan; unsigned long flags; + struct xilinx_dma_transfer *t; + struct xilinx_dma_config *config; + u32 reg; - if (!dchan) - return -EINVAL; - - chan = to_xilinx_chan(dchan); + if (chan->err) + return; - if (cmd == DMA_TERMINATE_ALL) { - /* Halt the DMA engine */ - dma_halt(chan); + spin_lock_irqsave(&chan->lock, flags); - spin_lock_irqsave(&chan->lock, flags); + if (list_empty(&chan->pending_list)) + goto out_unlock; - /* Remove and free all of the descriptors in the lists */ - xilinx_dma_free_desc_list(chan, &chan->pending_list); - xilinx_dma_free_desc_list(chan, &chan->active_list); + /* If it is SG mode and hardware is busy, cannot submit + */ + if (chan->has_SG && xilinx_dma_is_running(chan) && !xilinx_dma_is_idle(chan)) { + dev_dbg(chan->dev, "DMA controller still busy\n"); + goto out_unlock; + } - spin_unlock_irqrestore(&chan->lock, flags); - return 0; - } else if (cmd == DMA_SLAVE_CONFIG) { - /* Configure interrupt coalescing and delay counter - * Use value XILINX_DMA_NO_CHANGE to signal no change - */ - struct xilinx_dma_config *cfg = (struct xilinx_dma_config *)arg; - u32 reg = DMA_IN(&chan->regs->cr); + /* If hardware is idle, then all descriptors on the running lists are + * done, start new transfers + */ + dma_halt(chan); - if (cfg->coalesc <= XILINX_DMA_COALESCE_MAX) { - reg &= ~XILINX_DMA_XR_COALESCE_MASK; - reg |= cfg->coalesc << XILINX_DMA_COALESCE_SHIFT; + if (chan->err) + goto out_unlock; - chan->config.coalesc = cfg->coalesc; - } + t = list_first_entry(&chan->pending_list, struct xilinx_dma_transfer, head); - if (cfg->delay <= XILINX_DMA_DELAY_MAX) { - reg &= ~XILINX_DMA_XR_DELAY_MASK; - reg |= cfg->delay << XILINX_DMA_DELAY_SHIFT; - chan->config.delay = cfg->delay; + if (chan->has_SG) + DMA_OUT(&chan->regs->cdr, t->descs[0].phys); + + /* Configure the hardware using info in the config structure */ + config = &chan->config; + reg = DMA_IN(&chan->regs->cr); + + if (config->frm_cnt_en) + reg |= XILINX_VDMA_FRMCNT_EN; + else + reg &= ~XILINX_VDMA_FRMCNT_EN; + + /* With SG, start with circular mode, so that BDs can be fetched. + * In direct register mode, if not parking, enable circular mode */ + if ((chan->has_SG) || (!config->park)) + reg |= XILINX_VDMA_CIRC_EN; + + DMA_OUT(&chan->regs->cr, reg); + + if ((config->park_frm >= 0) && (config->park_frm < chan->num_frms)) { + if (config->direction == DMA_MEM_TO_DEV) { + DMA_OUT(&chan->regs->btt_ref, + config->park_frm << XILINX_VDMA_WR_REF_SHIFT); + } else { + DMA_OUT(&chan->regs->btt_ref, config->park_frm); } + } - DMA_OUT(&chan->regs->cr, reg); + /* Start the hardware + */ + dma_start(chan); - return 0; - } else - return -ENXIO; + if (chan->err) + goto out_unlock; + list_splice_tail_init(&chan->pending_list, &chan->active_list); + + /* Enable interrupts + * + * park/genlock testing does not use interrupts */ + /* + if (!chan->config.disable_intr) { + DMA_OUT(&chan->regs->cr, + DMA_IN(&chan->regs->cr) | XILINX_DMA_XR_IRQ_ALL_MASK); + }*/ + + /* Start the transfer + */ + if (chan->has_SG) + DMA_OUT(&chan->regs->tdr, t->descs[t->num_descs-1].phys); + else + DMA_OUT(&chan->addr_regs->vsize, config->vsize); + +out_unlock: + spin_unlock_irqrestore(&chan->lock, flags); +} + +static int xilinx_dma_terminate_all(struct xilinx_dma_chan *chan) +{ + /* Disable intr + */ + DMA_OUT(&chan->regs->cr, + DMA_IN(&chan->regs->cr) & ~XILINX_DMA_XR_IRQ_ALL_MASK); + + /* Halt the DMA engine */ + dma_halt(chan); + xilinx_dma_free_transfers(chan); + chan->cyclic = false; + + return 0; } /* Run-time configuration for Axi VDMA, supports: @@ -1399,32 +1145,18 @@ static int xilinx_vdma_device_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd, unsigned long arg) { struct xilinx_dma_chan *chan; - unsigned long flags; + struct xilinx_dma_config *cfg = (struct xilinx_dma_config *)arg; + u32 reg; if (!dchan) return -EINVAL; chan = to_xilinx_chan(dchan); - if (cmd == DMA_TERMINATE_ALL) { - /* Halt the DMA engine */ - dma_halt(chan); - - spin_lock_irqsave(&chan->lock, flags); - - /* Remove and free all of the descriptors in the lists */ - xilinx_dma_free_desc_list(chan, &chan->pending_list); - xilinx_dma_free_desc_list(chan, &chan->active_list); - - spin_unlock_irqrestore(&chan->lock, flags); - return 0; - } else if (cmd == DMA_SLAVE_CONFIG) { - struct xilinx_dma_config *cfg = (struct xilinx_dma_config *)arg; - u32 reg; - - if (cfg->reset) - dma_init(chan); - + switch (cmd) { + case DMA_TERMINATE_ALL: + return xilinx_dma_terminate_all(chan); + case DMA_SLAVE_CONFIG: reg = DMA_IN(&chan->regs->cr); /* If vsize is -1, it is park-related operations */ @@ -1444,13 +1176,11 @@ static int xilinx_vdma_device_control(struct dma_chan *dchan, reg &= ~XILINX_DMA_XR_COALESCE_MASK; reg |= cfg->coalesc << XILINX_DMA_COALESCE_SHIFT; - chan->config.coalesc = cfg->coalesc; } if (cfg->delay <= XILINX_DMA_DELAY_MAX) { reg &= ~XILINX_DMA_XR_DELAY_MASK; reg |= cfg->delay << XILINX_DMA_DELAY_SHIFT; - chan->config.delay = cfg->delay; } DMA_OUT(&chan->regs->cr, reg); @@ -1458,15 +1188,7 @@ static int xilinx_vdma_device_control(struct dma_chan *dchan, } /* Transfer information */ - chan->config.vsize = cfg->vsize; - chan->config.hsize = cfg->hsize; - chan->config.stride = cfg->stride; - chan->config.frm_dly = cfg->frm_dly; - chan->config.park = cfg->park; - - /* genlock settings */ - chan->config.gen_lock = cfg->gen_lock; - chan->config.master = cfg->master; + chan->config = *cfg; if (cfg->gen_lock) { if (chan->genlock) { @@ -1475,50 +1197,66 @@ static int xilinx_vdma_device_control(struct dma_chan *dchan, } } - chan->config.frm_cnt_en = cfg->frm_cnt_en; - if (cfg->park) - chan->config.park_frm = cfg->park_frm; - - chan->config.coalesc = cfg->coalesc; - chan->config.delay = cfg->delay; - if (cfg->coalesc <= XILINX_DMA_COALESCE_MAX) { + if (cfg->coalesc <= XILINX_DMA_COALESCE_MAX) reg |= cfg->coalesc << XILINX_DMA_COALESCE_SHIFT; - chan->config.coalesc = cfg->coalesc; - } - if (cfg->delay <= XILINX_DMA_DELAY_MAX) { + if (cfg->delay <= XILINX_DMA_DELAY_MAX) reg |= cfg->delay << XILINX_DMA_DELAY_SHIFT; - chan->config.delay = cfg->delay; - } - - chan->config.disable_intr = cfg->disable_intr; DMA_OUT(&chan->regs->cr, reg); - return 0; - } else + break; + default: return -ENXIO; + } + + return 0; } -/* Logarithm function to compute alignment shift - * - * Only deals with value less than 4096. - */ -static int my_log(int value) +/* Run-time device configuration for Axi DMA and Axi CDMA */ +static int xilinx_dma_device_control(struct dma_chan *dchan, + enum dma_ctrl_cmd cmd, unsigned long arg) { - int i = 0; - while ((1 << i) < value) { - i++; + struct xilinx_dma_chan *chan; + struct xilinx_dma_config *cfg = (struct xilinx_dma_config *)arg; + u32 reg; - if (i >= 12) - return 0; + if (!dchan) + return -EINVAL; + + chan = to_xilinx_chan(dchan); + + switch (cmd) { + case DMA_TERMINATE_ALL: + return xilinx_dma_terminate_all(chan); + case DMA_SLAVE_CONFIG: + /* Configure interrupt coalescing and delay counter + * Use value XILINX_DMA_NO_CHANGE to signal no change + */ + reg = DMA_IN(&chan->regs->cr); + + chan->config = *cfg; + + if (cfg->coalesc <= XILINX_DMA_COALESCE_MAX) { + reg &= ~XILINX_DMA_XR_COALESCE_MASK; + reg |= cfg->coalesc << XILINX_DMA_COALESCE_SHIFT; + } + + if (cfg->delay <= XILINX_DMA_DELAY_MAX) { + reg &= ~XILINX_DMA_XR_DELAY_MASK; + reg |= cfg->delay << XILINX_DMA_DELAY_SHIFT; + } + + DMA_OUT(&chan->regs->cr, reg); + + break; + default: + return -ENXIO; } - return i; + return 0; } -#ifdef CONFIG_OF - static void xilinx_dma_chan_remove(struct xilinx_dma_chan *chan) { irq_dispose_mapping(chan->irq); @@ -1536,43 +1274,32 @@ static int __devinit xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, struct device_node *node, u32 feature) { struct xilinx_dma_chan *chan; - int err; - int *value; - u32 width = 0, device_id = 0; + u32 width = 0; + int ret; /* alloc channel */ chan = kzalloc(sizeof(*chan), GFP_KERNEL); if (!chan) { dev_err(xdev->dev, "no free memory for DMA channels!\n"); - err = -ENOMEM; + ret = -ENOMEM; goto out_return; } + spin_lock_init(&chan->lock); + INIT_LIST_HEAD(&chan->pending_list); + INIT_LIST_HEAD(&chan->active_list); + chan->feature = feature; - chan->is_lite = 0; chan->has_DRE = 0; chan->has_SG = 0; chan->max_len = XILINX_DMA_MAX_TRANS_LEN; - value = (int *)of_get_property(node, "xlnx,include-dre", - NULL); - if (value) { - if (be32_to_cpup(value) == 1) - chan->has_DRE = 1; - } - - value = (int *)of_get_property(node, "xlnx,genlock-mode", - NULL); - if (value) { - if (be32_to_cpup(value) == 1) - chan->genlock = 1; - } + of_property_read_u32(node, "xlnx,include-dre", &chan->has_DRE); + of_property_read_u32(node, "xlnx,genlock-mode", &chan->genlock); + of_property_read_u32(node, "xlnx,datawidth", &width); - value = (int *)of_get_property(node, - "xlnx,datawidth", - NULL); - if (value) { - width = be32_to_cpup(value) >> 3; /* convert bits to bytes */ + if (width > 0) { + width >>= 3; /* convert bits to bytes */ /* If data width is greater than 8 bytes, DRE is not in hw */ if (width > 8) @@ -1581,62 +1308,22 @@ static int __devinit xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, chan->feature |= width - 1; } - value = (int *)of_get_property(node, "xlnx,device-id", NULL); - if (value) - device_id = be32_to_cpup(value); - - if (feature & XILINX_DMA_IP_CDMA) { - chan->direction = DMA_BIDIRECTIONAL; - chan->start_transfer = xilinx_cdma_start_transfer; - - chan->has_SG = (xdev->feature & XILINX_DMA_FTR_HAS_SG) >> + chan->has_SG = (xdev->feature & XILINX_DMA_FTR_HAS_SG) >> XILINX_DMA_FTR_HAS_SG_SHIFT; - value = (int *)of_get_property(node, - "xlnx,lite-mode", NULL); - if (value) { - if (be32_to_cpup(value) == 1) { - chan->is_lite = 1; - value = (int *)of_get_property(node, - "xlnx,max-burst-len", NULL); - if (value) { - if (!width) { - dev_err(xdev->dev, - "Lite mode without data width property\n"); - goto out_free_chan; - } - chan->max_len = width * - be32_to_cpup(value); - } - } - } - } - if (feature & XILINX_DMA_IP_DMA) { - chan->has_SG = (xdev->feature & XILINX_DMA_FTR_HAS_SG) >> - XILINX_DMA_FTR_HAS_SG_SHIFT; - chan->start_transfer = xilinx_dma_start_transfer; - if (of_device_is_compatible(node, - "xlnx,axi-dma-mm2s-channel")) - chan->direction = DMA_TO_DEVICE; - - if (of_device_is_compatible(node, - "xlnx,axi-dma-s2mm-channel")) - chan->direction = DMA_FROM_DEVICE; - - } - - if (feature & XILINX_DMA_IP_VDMA) { + if (of_device_is_compatible(node, "xlnx,axi-dma-mm2s-channel")) + chan->direction = DMA_MEM_TO_DEV; + else if (of_device_is_compatible(node, "xlnx,axi-dma-s2mm-channel")) + chan->direction = DMA_DEV_TO_MEM; + } else if (feature & XILINX_DMA_IP_VDMA) { chan->start_transfer = xilinx_vdma_start_transfer; - chan->has_SG = (xdev->feature & XILINX_DMA_FTR_HAS_SG) >> - XILINX_DMA_FTR_HAS_SG_SHIFT; - if (of_device_is_compatible(node, "xlnx,axi-vdma-mm2s-channel")) { - chan->direction = DMA_TO_DEVICE; + chan->direction = DMA_MEM_TO_DEV; if (!chan->has_SG) { chan->addr_regs = (struct vdma_addr_regs *) ((u32)xdev->regs + @@ -1646,7 +1333,7 @@ static int __devinit xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, if (of_device_is_compatible(node, "xlnx,axi-vdma-s2mm-channel")) { - chan->direction = DMA_FROM_DEVICE; + chan->direction = DMA_DEV_TO_MEM; if (!chan->has_SG) { chan->addr_regs = (struct vdma_addr_regs *) ((u32)xdev->regs + @@ -1656,135 +1343,110 @@ static int __devinit xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, } } - chan->regs = (struct xdma_regs *)xdev->regs; - chan->id = 0; - - if (chan->direction == DMA_FROM_DEVICE) { + if (chan->direction == DMA_MEM_TO_DEV) { + chan->regs = (struct xdma_regs *)xdev->regs; + chan->id = 0; + } else { chan->regs = (struct xdma_regs *)((u32)xdev->regs + XILINX_DMA_RX_CHANNEL_OFFSET); chan->id = 1; } + chan->debugfs_regset.regs = xilinx_dma_debugfs_regs; + chan->debugfs_regset.nregs = ARRAY_SIZE(xilinx_dma_debugfs_regs); + chan->debugfs_regset.base = (void __iomem *)chan->regs; + /* Used by dmatest channel matching in slave transfers * Can change it to be a structure to have more matching information */ - chan->private = (chan->direction & 0xFF) | - (chan->feature & XILINX_DMA_IP_MASK) | - (device_id << XILINX_DMA_DEVICE_ID_SHIFT); - chan->common.private = (void *)&(chan->private); + chan->common.private = (chan->direction & 0xFF) | + (chan->feature & XILINX_DMA_IP_MASK); if (!chan->has_DRE) - xdev->common.copy_align = my_log(width); + xdev->common.copy_align = ilog2(width); chan->dev = xdev->dev; xdev->chan[chan->id] = chan; tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan); - /* Initialize the channel */ - if (dma_init(chan)) { - dev_err(xdev->dev, "Reset channel failed\n"); - goto out_free_chan; - } - - - spin_lock_init(&chan->lock); - INIT_LIST_HEAD(&chan->pending_list); - INIT_LIST_HEAD(&chan->active_list); - chan->common.device = &xdev->common; /* find the IRQ line, if it exists in the device tree */ chan->irq = irq_of_parse_and_map(node, 0); - err = request_irq(chan->irq, dma_intr_handler, IRQF_SHARED, + ret = request_irq(chan->irq, dma_intr_handler, IRQF_SHARED, "xilinx-dma-controller", chan); - if (err) { - dev_err(xdev->dev, "unable to request IRQ\n"); + if (ret) { + dev_err(xdev->dev, "unable to request IRQ %d\n", ret); goto out_free_irq; } /* Add the channel to DMA device channel list */ list_add_tail(&chan->common.device_node, &xdev->common.channels); - xdev->common.chancnt++; - return 0; + /* Initialize the channel */ + if (xilinx_dma_reset(chan)) { + dev_err(xdev->dev, "Reset channel failed\n"); + goto out_free_chan; + } + return 0; out_free_irq: irq_dispose_mapping(chan->irq); out_free_chan: kfree(chan); out_return: - return err; + return ret; } -static int __devinit xilinx_dma_of_probe(struct platform_device *op, - const struct of_device_id *match) +static int __devinit xilinx_dma_of_probe(struct platform_device *pdev) { struct xilinx_dma_device *xdev; struct device_node *child, *node; - int err; + struct xilinx_dma_chan *chan; + u32 num_frames = 0; + u32 include_sg = 0; + unsigned int i; int *value; - int num_frames = 0; - - dev_info(&op->dev, "Probing xilinx axi dma engines\n"); + int ret; - xdev = kzalloc(sizeof(struct xilinx_dma_device), GFP_KERNEL); + xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL); if (!xdev) { - dev_err(&op->dev, "Not enough memory for device\n"); - err = -ENOMEM; - goto out_return; + dev_err(&pdev->dev, "Not enough memory for device\n"); + return -ENOMEM; } - xdev->dev = &(op->dev); + xdev->dev = &pdev->dev; INIT_LIST_HEAD(&xdev->common.channels); - node = op->dev.of_node; + node = pdev->dev.of_node; xdev->feature = 0; /* iomap registers */ xdev->regs = of_iomap(node, 0); if (!xdev->regs) { - dev_err(&op->dev, "unable to iomap registers\n"); - err = -ENOMEM; - goto out_free_xdev; - } - - /* Axi CDMA only does memcpy - */ - if (of_device_is_compatible(node, "xlnx,axi-cdma")) { - xdev->feature |= XILINX_DMA_IP_CDMA; - - value = (int *)of_get_property(node, "xlnx,include-sg", - NULL); - if (value) { - if (be32_to_cpup(value) == 1) - xdev->feature |= XILINX_DMA_FTR_HAS_SG; - } - - dma_cap_set(DMA_MEMCPY, xdev->common.cap_mask); - xdev->common.device_prep_dma_memcpy = xilinx_dma_prep_memcpy; - xdev->common.device_control = xilinx_dma_device_control; - xdev->common.device_issue_pending = xilinx_cdma_issue_pending; + dev_err(&pdev->dev, "unable to iomap registers\n"); + return -ENXIO; } /* Axi DMA and VDMA only do slave transfers */ if (of_device_is_compatible(node, "xlnx,axi-dma")) { - xdev->feature |= XILINX_DMA_IP_DMA; value = (int *)of_get_property(node, "xlnx,sg-include-stscntrl-strm", NULL); if (value) { - if (be32_to_cpup(value) == 1) { - xdev->feature |= (XILINX_DMA_FTR_STSCNTRL_STRM | - XILINX_DMA_FTR_HAS_SG); - } + xdev->feature |= XILINX_DMA_FTR_HAS_SG; + if (be32_to_cpup(value) == 1) + xdev->feature = XILINX_DMA_FTR_STSCNTRL_STRM; } dma_cap_set(DMA_SLAVE, xdev->common.cap_mask); dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask); + dma_cap_set(DMA_CYCLIC, xdev->common.cap_mask); xdev->common.device_prep_slave_sg = xilinx_dma_prep_slave_sg; + xdev->common.device_prep_dma_cyclic = xilinx_dma_prep_dma_cyclic; xdev->common.device_control = xilinx_dma_device_control; xdev->common.device_issue_pending = xilinx_dma_issue_pending; } @@ -1792,23 +1454,17 @@ static int __devinit xilinx_dma_of_probe(struct platform_device *op, if (of_device_is_compatible(node, "xlnx,axi-vdma")) { xdev->feature |= XILINX_DMA_IP_VDMA; - value = (int *)of_get_property(node, "xlnx,include-sg", - NULL); - if (value) { - if (be32_to_cpup(value) == 1) - xdev->feature |= XILINX_DMA_FTR_HAS_SG; - } + of_property_read_u32(node, "xlnx,include-sg", &include_sg); + if (include_sg) + xdev->feature |= XILINX_DMA_FTR_HAS_SG; - value = (int *)of_get_property(node, "xlnx,num-fstores", - NULL); - if (value) - num_frames = be32_to_cpup(value); + of_property_read_u32(node, "xlnx,num-fstores", &num_frames); dma_cap_set(DMA_SLAVE, xdev->common.cap_mask); dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask); xdev->common.device_prep_slave_sg = xilinx_vdma_prep_slave_sg; xdev->common.device_control = xilinx_vdma_device_control; - xdev->common.device_issue_pending = xilinx_vdma_issue_pending; + xdev->common.device_issue_pending = xilinx_dma_issue_pending; } xdev->common.device_alloc_chan_resources = @@ -1816,40 +1472,50 @@ static int __devinit xilinx_dma_of_probe(struct platform_device *op, xdev->common.device_free_chan_resources = xilinx_dma_free_chan_resources; xdev->common.device_tx_status = xilinx_tx_status; - xdev->common.dev = &op->dev; - - dev_set_drvdata(&op->dev, xdev); + xdev->common.dev = &pdev->dev; for_each_child_of_node(node, child) { - xilinx_dma_chan_probe(xdev, child, xdev->feature); + ret = xilinx_dma_chan_probe(xdev, child, xdev->feature); + if (ret) + goto err_free_chan; } if (xdev->feature & XILINX_DMA_IP_VDMA) { - int i; - for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++) { if (xdev->chan[i]) xdev->chan[i]->num_frms = num_frames; } } - dma_async_device_register(&xdev->common); + ret = dma_async_device_register(&xdev->common); + if (ret) + goto err_free_chan; + + for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++) { + if (xdev->chan[i]) { + chan = xdev->chan[i]; + debugfs_create_regset32(dev_name(&chan->common.dev->device), S_IRUGO, NULL, &chan->debugfs_regset); + } + } + + platform_set_drvdata(pdev, xdev); return 0; -out_free_xdev: - kfree(xdev); +err_free_chan: + for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++) { + if (xdev->chan[i]) + xilinx_dma_chan_remove(xdev->chan[i]); + } -out_return: - return err; + return ret; } -static int xilinx_dma_of_remove(struct platform_device *op) +static int __devexit xilinx_dma_of_remove(struct platform_device *pdev) { - struct xilinx_dma_device *xdev; + struct xilinx_dma_device *xdev = platform_get_drvdata(pdev); int i; - xdev = dev_get_drvdata(&op->dev); dma_async_device_unregister(&xdev->common); for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++) { @@ -1858,16 +1524,13 @@ static int xilinx_dma_of_remove(struct platform_device *op) } iounmap(xdev->regs); - dev_set_drvdata(&op->dev, NULL); - kfree(xdev); return 0; } static const struct of_device_id xilinx_dma_of_ids[] = { - { .compatible = "xlnx,axi-cdma",}, - { .compatible = "xlnx,axi-dma",}, - { .compatible = "xlnx,axi-vdma",}, + { .compatible = "xlnx,axi-dma" }, + { .compatible = "xlnx,axi-vdma" }, {} }; @@ -1878,410 +1541,20 @@ static struct platform_driver xilinx_dma_of_driver = { .of_match_table = xilinx_dma_of_ids, }, .probe = xilinx_dma_of_probe, - .remove = xilinx_dma_of_remove, + .remove = __devexit_p(xilinx_dma_of_remove), }; -/*----------------------------------------------------------------------------*/ -/* Module Init / Exit */ -/*----------------------------------------------------------------------------*/ - -static __init int xilinx_dma_init(void) +static int __init xilinx_dma_init(void) { - int ret; - - pr_info("Xilinx DMA driver\n"); - - ret = platform_driver_register(&xilinx_dma_of_driver); - if (ret) - pr_err("xilinx_dma: failed to register platform driver\n"); - - return ret; -} - -static void __exit xilinx_dma_exit(void) -{ - platform_driver_unregister(&xilinx_dma_of_driver); + return platform_driver_register(&xilinx_dma_of_driver); } - subsys_initcall(xilinx_dma_init); -module_exit(xilinx_dma_exit); - -#else - -/**************************************************/ -/* Platform bus to support ARM before device tree */ -/**************************************************/ - -/* The following probe and chan_probe functions were - copied from the OF section above, then modified - to use platform data. -*/ - -static void xilinx_dma_chan_remove(struct xilinx_dma_chan *chan) -{ - free_irq(chan->irq, chan); - list_del(&chan->common.device_node); - kfree(chan); -} - -/* - * Probing channels - * - * . Get channel features from the device tree entry - * . Initialize special channel handling routines - */ -static int __devinit xilinx_dma_chan_probe(struct platform_device *pdev, - struct xilinx_dma_device *xdev, - struct dma_channel_config *channel_config, - int channel_num, u32 feature) -{ - struct xilinx_dma_chan *chan; - int err; - u32 width = 0; - struct resource *res; - - /* alloc channel */ - - - chan = kzalloc(sizeof(*chan), GFP_KERNEL); - if (!chan) { - dev_err(xdev->dev, "no free memory for DMA channels!\n"); - err = -ENOMEM; - goto out_return; - } - - chan->feature = feature; - chan->is_lite = 0; - chan->has_DRE = 0; - chan->has_SG = 0; - chan->max_len = XILINX_DMA_MAX_TRANS_LEN; - - if (channel_config->include_dre) - chan->has_DRE = 1; - - if (channel_config->genlock_mode) - chan->genlock = 1; - - width = channel_config->datawidth >> 3; - chan->feature |= width - 1; - - if (feature & XILINX_DMA_IP_CDMA) { - - chan->direction = DMA_BIDIRECTIONAL; - chan->start_transfer = xilinx_cdma_start_transfer; - - chan->has_SG = (xdev->feature & XILINX_DMA_FTR_HAS_SG) >> - XILINX_DMA_FTR_HAS_SG_SHIFT; - - if (channel_config->lite_mode) { - chan->is_lite = 1; - chan->max_len = width * channel_config->max_burst_len; - } - } - - if (feature & XILINX_DMA_IP_DMA) { - chan->has_SG = 1; - chan->start_transfer = xilinx_dma_start_transfer; - - if (!strcmp(channel_config->type, "axi-dma-mm2s-channel")) - chan->direction = DMA_TO_DEVICE; - - if (!strcmp(channel_config->type, "axi-dma-s2mm-channel")) - chan->direction = DMA_FROM_DEVICE; - } - - if (feature & XILINX_DMA_IP_VDMA) { - - chan->start_transfer = xilinx_vdma_start_transfer; - - chan->has_SG = (xdev->feature & XILINX_DMA_FTR_HAS_SG) >> - XILINX_DMA_FTR_HAS_SG_SHIFT; - - if (!strcmp(channel_config->type, "axi-vdma-mm2s-channel")) { - - printk(KERN_INFO, "axi-vdma-mm2s-channel found\n"); - - chan->direction = DMA_TO_DEVICE; - if (!chan->has_SG) { - chan->addr_regs = (struct vdma_addr_regs *) - ((u32)xdev->regs + - XILINX_VDMA_DIRECT_REG_OFFSET); - } - } - - if (!strcmp(channel_config->type, "axi-vdma-s2mm-channel")) { - - printk(KERN_INFO, "axi-vdma-s2mm-channel found\n"); - - chan->direction = DMA_FROM_DEVICE; - if (!chan->has_SG) { - chan->addr_regs = (struct vdma_addr_regs *) - ((u32)xdev->regs + - XILINX_VDMA_DIRECT_REG_OFFSET + - XILINX_VDMA_CHAN_DIRECT_REG_SIZE); - } - } - } - - chan->regs = (struct xdma_regs *)xdev->regs; - chan->id = 0; - - if (chan->direction == DMA_FROM_DEVICE) { - chan->regs = (struct xdma_regs *)((u32)xdev->regs + - XILINX_DMA_RX_CHANNEL_OFFSET); - chan->id = 1; - } - - /* Used by dmatest channel matching in slave transfers - * Can change it to be a structure to have more matching information - */ - chan->private = (chan->direction & 0xFF) | - (chan->feature & XILINX_DMA_IP_MASK); - chan->common.private = (void *)&(chan->private); - - if (!chan->has_DRE) - xdev->common.copy_align = my_log(width); - - chan->dev = xdev->dev; - xdev->chan[chan->id] = chan; - - tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan); - - /* Initialize the channel */ - if (dma_init(chan)) { - dev_err(xdev->dev, "Reset channel failed\n"); - goto out_free_chan; - } - - - spin_lock_init(&chan->lock); - INIT_LIST_HEAD(&chan->pending_list); - INIT_LIST_HEAD(&chan->active_list); - - chan->common.device = &xdev->common; - - /* setup the interrupt for the channel */ - - res = platform_get_resource(pdev, IORESOURCE_IRQ, channel_num); - chan->irq = res->start; - - err = request_irq(chan->irq, dma_intr_handler, IRQF_SHARED, - "xilinx-dma-controller", chan); - if (err) { - dev_err(xdev->dev, "unable to request IRQ\n"); - goto out_free_irq; - } else - dev_info(&pdev->dev, "using irq %d\n", chan->irq); - - /* Add the channel to DMA device channel list */ - list_add_tail(&chan->common.device_node, &xdev->common.channels); - xdev->common.chancnt++; - - return 0; - -out_free_irq: - free_irq(chan->irq, chan); -out_free_chan: - kfree(chan); -out_return: - return err; -} - -static int __devinit xilinx_dma_probe(struct platform_device *pdev) -{ - struct xilinx_dma_device *xdev; - int err; - int num_frames = 0; - struct resource *res; - struct device *dev = &pdev->dev; - struct dma_device_config *dma_config; - int channel; - - dev_info(&pdev->dev, "Probing xilinx axi dma engines\n"); - - xdev = kzalloc(sizeof(struct xilinx_dma_device), GFP_KERNEL); - if (!xdev) { - dev_err(&pdev->dev, "Not enough memory for device\n"); - err = -ENOMEM; - goto out_return; - } - - xdev->dev = &(pdev->dev); - INIT_LIST_HEAD(&xdev->common.channels); - - xdev->feature = 0; - - /* iomap registers */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - printk(KERN_ERR "get_resource for MEM resource for dev %d " - "failed\n", pdev->id); - err = -ENOMEM; - goto out_return; - } else { - dev_info(&pdev->dev, "device %d actual base is %x\n", - pdev->id, (unsigned int)res->start); - } - if (!request_mem_region(res->start, 0x1000, "xilinx_axidma")) { - printk(KERN_ERR "memory request failue for base %x\n", - (unsigned int)res->start); - err = -ENOMEM; - goto out_return; - } - - xdev->regs = ioremap(res->start, 0x1000); - pr_info("dma base remapped: %lx\n", (unsigned long)xdev->regs); - if (!xdev->regs) { - dev_err(&pdev->dev, "unable to iomap registers\n"); - err = -ENOMEM; - goto out_free_xdev; - } - - dma_config = (struct dma_device_config *)dev->platform_data; - - /* Axi CDMA only does memcpy - */ - if (!strcmp(dma_config->type, "axi-cdma")) { - - pr_info("found an axi-cdma configuration\n"); - xdev->feature |= XILINX_DMA_IP_CDMA; - - if (dma_config->include_sg) - xdev->feature |= XILINX_DMA_FTR_HAS_SG; - - dma_cap_set(DMA_MEMCPY, xdev->common.cap_mask); - xdev->common.device_prep_dma_memcpy = xilinx_dma_prep_memcpy; - xdev->common.device_control = xilinx_dma_device_control; - xdev->common.device_issue_pending = xilinx_cdma_issue_pending; - } - - /* Axi DMA and VDMA only do slave transfers - */ - if (!strcmp(dma_config->type, "axi-dma")) { - - pr_info("found an axi-dma configuration\n"); - - xdev->feature |= XILINX_DMA_IP_DMA; - if (dma_config->sg_include_stscntrl_strm) - xdev->feature |= XILINX_DMA_FTR_STSCNTRL_STRM; - - dma_cap_set(DMA_SLAVE, xdev->common.cap_mask); - dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask); - xdev->common.device_prep_slave_sg = xilinx_dma_prep_slave_sg; - xdev->common.device_control = xilinx_dma_device_control; - xdev->common.device_issue_pending = xilinx_dma_issue_pending; - } - - if (!strcmp(dma_config->type, "axi-vdma")) { - - pr_info("found an axi-vdma configuration\n"); - - xdev->feature |= XILINX_DMA_IP_VDMA; - - if (dma_config->include_sg) - xdev->feature |= XILINX_DMA_FTR_HAS_SG; - - num_frames = dma_config->num_fstores; - - dma_cap_set(DMA_SLAVE, xdev->common.cap_mask); - dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask); - xdev->common.device_prep_slave_sg = xilinx_vdma_prep_slave_sg; - xdev->common.device_control = xilinx_vdma_device_control; - xdev->common.device_issue_pending = xilinx_vdma_issue_pending; - } - - xdev->common.device_alloc_chan_resources = - xilinx_dma_alloc_chan_resources; - xdev->common.device_free_chan_resources = - xilinx_dma_free_chan_resources; - xdev->common.device_tx_status = xilinx_tx_status; - xdev->common.dev = &pdev->dev; - - dev_set_drvdata(&pdev->dev, xdev); - - for (channel = 0; channel < dma_config->channel_count; channel++) - xilinx_dma_chan_probe(pdev, xdev, - &dma_config->channel_config[channel], - channel, xdev->feature); - - if (xdev->feature & XILINX_DMA_IP_VDMA) { - int i; - - for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++) { - if (xdev->chan[i]) - xdev->chan[i]->num_frms = num_frames; - } - } - - dma_async_device_register(&xdev->common); - - return 0; - -out_free_xdev: - kfree(xdev); - -out_return: - return err; -} - - -static int __exit xilinx_dma_remove(struct platform_device *pdev) -{ - struct xilinx_dma_device *xdev = platform_get_drvdata(pdev); - int i; -#if 1 - dma_async_device_unregister(&xdev->common); -#endif - for (i = 0; i < 2; i++) { - if (xdev->chan[i]) - xilinx_dma_chan_remove(xdev->chan[i]); - } - - iounmap(xdev->regs); - dev_set_drvdata(&pdev->dev, NULL); - kfree(xdev); - - return 0; -} - -static void xilinx_dma_shutdown(struct platform_device *pdev) -{ - struct xilinx_dma_device *xdev = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < 2; i++) - dma_halt(xdev->chan[i]); -} - -static struct platform_driver xilinx_dma_driver = { - .probe = xilinx_dma_probe, - .remove = __exit_p(xilinx_dma_remove), - .shutdown = xilinx_dma_shutdown, - .driver = { - .owner = THIS_MODULE, - .name = "xilinx-axidma", - }, -}; - -/*----------------------------------------------------------------------------*/ -/* Module Init / Exit */ -/*----------------------------------------------------------------------------*/ - -static __init int xilinx_dma_init(void) -{ - int status; - status = platform_driver_register(&xilinx_dma_driver); - return status; -} -module_init(xilinx_dma_init); static void __exit xilinx_dma_exit(void) { - platform_driver_unregister(&xilinx_dma_driver); + platform_driver_unregister(&xilinx_dma_of_driver); } - module_exit(xilinx_dma_exit); -#endif -MODULE_DESCRIPTION("Xilinx DMA/CDMA/VDMA driver"); +MODULE_DESCRIPTION("Xilinx DMA/VDMA driver"); MODULE_LICENSE("GPL"); From 2221fcc163401bf08090563f06dab2ac12cfe464 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Mar 2012 13:47:18 +0100 Subject: [PATCH 036/261] Setup FPGA clocks This is a hack! --- arch/arm/mach-zynq/slcr.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index 1274c03c2818e..3416a4976c72a 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -31,6 +31,7 @@ #define XSLCR_LOCK 0x4 /* SLCR lock register */ #define XSLCR_UNLOCK 0x8 /* SCLR unlock register */ +#define XSLCR_IO_PLL_CTRL_OFFSET 0x108 /* AMBA Peripheral Clk Control */ #define XSLCR_APER_CLK_CTRL_OFFSET 0x12C /* AMBA Peripheral Clk Control */ #define XSLCR_USB0_CLK_CTRL_OFFSET 0x130 /* USB 0 ULPI Clock Control */ #define XSLCR_USB1_CLK_CTRL_OFFSET 0x134 /* USB 1 ULPI Clock Control */ @@ -44,6 +45,10 @@ #define XSLCR_UART_CLK_CTRL_OFFSET 0x154 /* UART Reference Clock Control */ #define XSLCR_SPI_CLK_CTRL_OFFSET 0x158 /* SPI Reference Clock Control */ #define XSLCR_CAN_CLK_CTRL_OFFSET 0x15C /* CAN Reference Clock Control */ +#define XSLCR_FPGA0_CLK_CTRL_OFFSET 0x170 /* FPGA0 Reference Clock Control */ +#define XSLCR_FPGA1_CLK_CTRL_OFFSET 0x180 /* FPGA1 Reference Clock Control */ +#define XSLCR_FPGA2_CLK_CTRL_OFFSET 0x190 /* FPGA2 Reference Clock Control */ +#define XSLCR_FPGA3_CLK_CTRL_OFFSET 0x1a0 /* FPGA3 Reference Clock Control */ #define XSLCR_PSS_RST_CTRL_OFFSET 0x200 /* PSS Software Reset Control */ #define XSLCR_DDR_RST_CTRL_OFFSET 0x204 /* DDR Software Reset Control */ #define XSLCR_AMBA_RST_CTRL_OFFSET 0x208 /* AMBA Software Reset Control */ @@ -2449,6 +2454,11 @@ static int __init xslcr_probe(struct platform_device *pdev) /* unlock the SLCR so that registers can be changed */ xslcr_writereg(slcr->regs + XSLCR_UNLOCK, 0xDF0D); + xslcr_writereg(slcr->regs + XSLCR_FPGA0_CLK_CTRL_OFFSET, 0x100a00); + xslcr_writereg(slcr->regs + XSLCR_FPGA1_CLK_CTRL_OFFSET, 0x100500); + xslcr_writereg(slcr->regs + XSLCR_FPGA2_CLK_CTRL_OFFSET, 0x100700); + xslcr_writereg(slcr->regs + XSLCR_FPGA3_CLK_CTRL_OFFSET, 0x102900); + dev_info(&pdev->dev, "at 0x%08X mapped to 0x%08X\n", res.start, (u32 __force)slcr->regs); platform_set_drvdata(pdev, slcr); From 965d5a2d45f07da3109172c867628872c39ea9f2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 10 Feb 2012 13:44:11 +0100 Subject: [PATCH 037/261] drm: Fix EDID color fromat parsing The code should obviously check the EDID feature field for EDID feature flags and not the color_formats field of the drm_display_info struct. Also update the color_formats field with new modes instead of overwriting the current mode. Signed-off-by: Lars-Peter Clausen --- drivers/gpu/drm/drm_edid.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index ece03fc2d3864..1618c1f826201 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1695,10 +1695,10 @@ static void drm_add_display_info(struct edid *edid, } info->color_formats = DRM_COLOR_FORMAT_RGB444; - if (info->color_formats & DRM_EDID_FEATURE_RGB_YCRCB444) - info->color_formats = DRM_COLOR_FORMAT_YCRCB444; - if (info->color_formats & DRM_EDID_FEATURE_RGB_YCRCB422) - info->color_formats = DRM_COLOR_FORMAT_YCRCB422; + if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444) + info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; + if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422) + info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; /* Get data from CEA blocks if present */ edid_ext = drm_find_cea_extension(edid); From c15777370031b3186f68b65c32d45814d2946c39 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 10 Feb 2012 14:31:18 +0100 Subject: [PATCH 038/261] drm: Parse color format information in CEA blocks The CEA extension block has a field which describes which YCbCr modes are supported by the device, use it to fill the drm_display_info color_formats fields. Also the existence of a CEA extension block is used as indication that the device supports RGB. Signed-off-by: Lars-Peter Clausen --- drivers/gpu/drm/drm_edid.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 1618c1f826201..b1804a2c0f361 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1308,6 +1308,8 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, #define VENDOR_BLOCK 0x03 #define SPEAKER_BLOCK 0x04 #define EDID_BASIC_AUDIO (1 << 6) +#define EDID_CEA_YCRCB444 (1 << 5) +#define EDID_CEA_YCRCB422 (1 << 4) /** * Search EDID for CEA extension block. @@ -1662,13 +1664,29 @@ static void drm_add_display_info(struct edid *edid, info->bpc = 0; info->color_formats = 0; - /* Only defined for 1.4 with digital displays */ - if (edid->revision < 4) + if (edid->revision < 3) return; if (!(edid->input & DRM_EDID_INPUT_DIGITAL)) return; + /* Get data from CEA blocks if present */ + edid_ext = drm_find_cea_extension(edid); + if (edid_ext) { + info->cea_rev = edid_ext[1]; + + /* The existence of a CEA block should imply RGB support */ + info->color_formats = DRM_COLOR_FORMAT_RGB444; + if (edid_ext[3] & EDID_CEA_YCRCB444) + info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; + if (edid_ext[3] & EDID_CEA_YCRCB422) + info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; + } + + /* Only defined for 1.4 with digital displays */ + if (edid->revision < 4) + return; + switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) { case DRM_EDID_DIGITAL_DEPTH_6: info->bpc = 6; @@ -1694,18 +1712,11 @@ static void drm_add_display_info(struct edid *edid, break; } - info->color_formats = DRM_COLOR_FORMAT_RGB444; + info->color_formats |= DRM_COLOR_FORMAT_RGB444; if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444) info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422) info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; - - /* Get data from CEA blocks if present */ - edid_ext = drm_find_cea_extension(edid); - if (!edid_ext) - return; - - info->cea_rev = edid_ext[1]; } /** From 159b4cbfce42f492b3449a917be7653eb6d7fa72 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 16 Feb 2012 17:12:46 +0100 Subject: [PATCH 039/261] DMA: Fix dmaengine_prep_slave_single Signed-off-by: Michael Hennerich --- include/linux/dmaengine.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 9a2f5dd0e593c..56bbc4d5b2c3e 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -622,11 +622,15 @@ static inline int dmaengine_slave_config(struct dma_chan *chan, } static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( - struct dma_chan *chan, void *buf, size_t len, + struct dma_chan *chan, dma_addr_t buf, size_t len, enum dma_transfer_direction dir, unsigned long flags) { struct scatterlist sg; - sg_init_one(&sg, buf, len); + sg_init_table(&sg, 1); + sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)), + len, offset_in_page(buf)); + sg_dma_address(&sg) = buf; + sg_dma_len(&sg) = len; return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags); } From 0abd06eab64fbc0415594cd9cc8a7568eade0a22 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 27 Apr 2012 11:11:58 +0200 Subject: [PATCH 040/261] drm: Decouple edid parsing from i2c adapter Signed-off-by: Lars-Peter Clausen --- drivers/gpu/drm/drm_edid.c | 19 ++++++++++--------- include/drm/drm_edid.h | 3 +++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index b1804a2c0f361..8500a882f8882 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -239,9 +239,10 @@ EXPORT_SYMBOL(drm_edid_is_valid); * Try to fetch EDID information by calling i2c driver function. */ static int -drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, +drm_do_probe_ddc_edid(void *data, unsigned char *buf, int block, int len) { + struct i2c_adapter *adapter = data; unsigned char start = block * EDID_LENGTH; int ret, retries = 5; @@ -282,8 +283,8 @@ static bool drm_edid_is_zero(u8 *in_edid, int length) return true; } -static u8 * -drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) +struct edid *drm_do_get_edid(struct drm_connector *connector, + int (*get_edid_block)(void *, unsigned char *buf, int, int), void *data) { int i, j = 0, valid_extensions = 0; u8 *block, *new; @@ -293,7 +294,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) /* base block fetch */ for (i = 0; i < 4; i++) { - if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH)) + if (get_edid_block(data, block, 0, EDID_LENGTH)) goto out; if (drm_edid_block_valid(block)) break; @@ -307,7 +308,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) /* if there's no extensions, we're done */ if (block[0x7e] == 0) - return block; + return (struct edid *)block; new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL); if (!new) @@ -316,7 +317,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) for (j = 1; j <= block[0x7e]; j++) { for (i = 0; i < 4; i++) { - if (drm_do_probe_ddc_edid(adapter, + if (get_edid_block(data, block + (valid_extensions + 1) * EDID_LENGTH, j, EDID_LENGTH)) goto out; @@ -340,7 +341,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) block = new; } - return block; + return (struct edid *)block; carp: dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n", @@ -350,6 +351,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) kfree(block); return NULL; } +EXPORT_SYMBOL_GPL(drm_do_get_edid); /** * Probe DDC presence. @@ -381,8 +383,7 @@ struct edid *drm_get_edid(struct drm_connector *connector, struct edid *edid = NULL; if (drm_probe_ddc(adapter)) - edid = (struct edid *)drm_do_get_edid(connector, adapter); - + edid = drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter); connector->display_info.raw_edid = (char *)edid; return edid; diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 74ce916846296..489f3efd68b32 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -239,4 +239,7 @@ int drm_av_sync_delay(struct drm_connector *connector, struct drm_connector *drm_select_eld(struct drm_encoder *encoder, struct drm_display_mode *mode); +struct edid *drm_do_get_edid(struct drm_connector *connector, + int (*get_edid_block)(void *, unsigned char *buf, int, int), void *data); + #endif /* __DRM_EDID_H__ */ From a371b850270b5f7316f02b5322a1bf7a24071c80 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 5 Mar 2012 16:30:57 +0100 Subject: [PATCH 041/261] DRM: Add adv7511 encoder driver This patch adds a driver for the Analog Devices adv7511. The adv7511 is a standalone HDMI transmitter chip. It features a HDMI output interface on one end and video and audio input interfaces on the other. Signed-off-by: Lars-Peter Clausen --- drivers/gpu/drm/Kconfig | 9 + drivers/gpu/drm/i2c/Makefile | 3 + drivers/gpu/drm/i2c/adv7511.h | 260 +++++++++++ drivers/gpu/drm/i2c/adv7511_audio.c | 318 +++++++++++++ drivers/gpu/drm/i2c/adv7511_core.c | 699 ++++++++++++++++++++++++++++ 5 files changed, 1289 insertions(+) create mode 100644 drivers/gpu/drm/i2c/adv7511.h create mode 100644 drivers/gpu/drm/i2c/adv7511_audio.c create mode 100644 drivers/gpu/drm/i2c/adv7511_core.c diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 2418429a98360..0c03c96b4895e 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -159,6 +159,15 @@ config DRM_SAVAGE Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister chipset. If M is selected the module will be called savage. +config DRM_ENCODER_ADV7511 + tristate "AV7511 encoder" + depends on I2C && DRM + select REGMAP_I2C + select DRM_KMS_HELPER + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + source "drivers/gpu/drm/exynos/Kconfig" source "drivers/gpu/drm/vmwgfx/Kconfig" diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile index 92862563e7ee3..d7b40ed23c67b 100644 --- a/drivers/gpu/drm/i2c/Makefile +++ b/drivers/gpu/drm/i2c/Makefile @@ -5,3 +5,6 @@ obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o sil164-y := sil164_drv.o obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o + +adv7511-y := adv7511_core.o adv7511_audio.o +obj-$(CONFIG_DRM_ENCODER_ADV7511) += adv7511.o diff --git a/drivers/gpu/drm/i2c/adv7511.h b/drivers/gpu/drm/i2c/adv7511.h new file mode 100644 index 0000000000000..a80916add627e --- /dev/null +++ b/drivers/gpu/drm/i2c/adv7511.h @@ -0,0 +1,260 @@ +#ifndef __ADV7511_H__ +#define __ADV7511_H__ + +#define ADV7511_REG_CHIP_REVISION 0x00 +#define ADV7511_REG_N0 0x01 +#define ADV7511_REG_N1 0x02 +#define ADV7511_REG_N2 0x03 +#define ADV7511_REG_SPDIF_FREQ 0x04 +#define ADV7511_REG_CTS_AUTOMATIC1 0x05 +#define ADV7511_REG_CTS_AUTOMATIC2 0x06 +#define ADV7511_REG_CTS_MANUAL0 0x07 +#define ADV7511_REG_CTS_MANUAL1 0x08 +#define ADV7511_REG_CTS_MANUAL2 0x09 +#define ADV7511_REG_AUDIO_SOURCE 0x0a +#define ADV7511_REG_AUDIO_CONFIG 0x0b +#define ADV7511_REG_I2S_CONFIG 0x0c +#define ADV7511_REG_I2S_WIDTH 0x0d +#define ADV7511_REG_VIDEO_INPUT_CFG1 0x16 +#define ADV7511_REG_CSC_UPPER(x) (0x18 + (x) * 2) +#define ADV7511_REG_CSC_LOWER(x) (0x19 + (x) * 2) +#define ADV7511_REG_SYNC_DECODER(x) (0x30 + (x)) +#define ADV7511_REG_DE_GENERATOR (0x35 + (x)) +#define ADV7511_REG_PIXEL_REPETITION 0x3b +#define ADV7511_REG_VIC_MANUAL 0x3c +#define ADV7511_REG_VIC_SEND 0x3d +#define ADV7511_REG_VIC_DETECTED 0x3e +#define ADV7511_REG_AUX_VIC_DETECTED 0x3f +#define ADV7511_REG_PACKET_ENABLE0 0x40 +#define ADV7511_REG_POWER 0x41 +#define ADV7511_REG_STATUS 0x42 +#define ADV7511_REG_EDID_I2C_ADDR 0x43 +#define ADV7511_REG_PACKET_ENABLE1 0x44 +#define ADV7511_REG_PACKET_I2C_ADDR 0x45 +#define ADV7511_REG_DSD_ENABLE 0x46 +#define ADV7511_REG_VIDEO_INPUT_CFG2 0x48 +#define ADV7511_REG_GC(x) (0x4b + (x)) /* 0x4b - 0x51 */ +#define ADV7511_REG_AVI_INFOFRAME_VERSION 0x52 +#define ADV7511_REG_AVI_INFOFRAME_LENGTH 0x53 +#define ADV7511_REG_AVI_INFOFRAME_CHECKSUM 0x54 +#define ADV7511_REG_AVI_INFOFRAME(x) (0x55 + (x)) /* 0x55 - 0x6f */ +#define ADV7511_REG_AUDIO_INFOFRAME_VERSION 0x70 +#define ADV7511_REG_AUDIO_INFOFRAME_LENGTH 0x71 +#define ADV7511_REG_AUDIO_INFOFRAME_CHECKSUM 0x72 +#define ADV7511_REG_AUDIO_INFOFRAME(x) (0x73 + (x)) /* 0x73 - 0x7c */ +#define ADV7511_REG_INT_ENABLE(x) (0x94 + (x)) +#define ADV7511_REG_INT(x) (0x96 + (x)) +#define ADV7511_REG_INPUT_CLK_DIV 0x9d +#define ADV7511_REG_PLL_STATUS 0x9e +#define ADV7511_REG_POWER_DOWN 0xa1 +#define ADV7511_REG_HDCP_HDMI_CFG 0xaf +#define ADV7511_REG_AN(x) (0xb0 + (x)) /* 0xb0 - 0xb7 */ +#define ADV7511_REG_HDCP_STATUS 0xb8 +#define ADV7511_REG_BCAPS 0xbe +#define ADV7511_REG_BKSV(x) (0xc0 + (x)) /* 0xc0 - 0xc3 */ +#define ADV7511_REG_EDID_SEGMENT 0xc4 +#define ADV7511_REG_DDC_CONTROLLER_STATUS 0xc8 +#define ADV7511_REG_EDID_READ_CTRL 0xc9 +#define ADV7511_REG_BSTATUS(x) (0xca + (x)) /* 0xca - 0xcb */ +#define ADV7511_REG_TIMING_GEN_SEQ 0xd0 +#define ADV7511_REG_HSYNC_PLACEMENT_MSB 0xfa + +#define ADV7511_REG_SYNC_ADJUSTMENT(x) (0xd7 + (x)) /* 0xd7 - 0xdc */ +#define ADV7511_REG_TMDS_CLOCK_INV 0xde +#define ADV7511_REG_ARC_CTRL 0xdf +#define ADV7511_REG_CEC_I2C_ADDR 0xe1 +#define ADV7511_REG_CEC_CTRL 0xe2 +#define ADV7511_REG_CHIP_ID_HIGH 0xf5 +#define ADV7511_REG_CHIP_ID_LOW 0xf6 + +#define ADV7511_CSC_ENABLE BIT(7) +#define ADV7511_CSC_UPDATE_MODE BIT(5) + +#define ADV7511_INT0_HDP BIT(7) +#define ADV7511_INT0_VSYNC BIT(5) +#define ADV7511_INT0_AUDIO_FIFO_FULL BIT(4) +#define ADV7511_INT0_EDID_READY BIT(2) +#define ADV7511_INT0_HDCP_AUTHENTICATED BIT(1) + +#define ADV7511_INT1_DDC_ERROR BIT(7) +#define ADV7511_INT1_BKSV BIT(6) +#define ADV7511_INT1_CEC_TX_READY BIT(5) +#define ADV7511_INT1_CEC_TX_ARBIT_LOST BIT(4) +#define ADV7511_INT1_CEC_TX_RETRY_TIMEOUT BIT(3) +#define ADV7511_INT1_CEC_RX_READY3 BIT(2) +#define ADV7511_INT1_CEC_RX_READY2 BIT(1) +#define ADV7511_INT1_CEC_RX_READY1 BIT(0) + +#define ADV7511_ARC_CTRL_POWER_DOWN BIT(0) + +#define ADV7511_CEC_CTRL_POWER_DOWN BIT(0) + +#define ADV7511_POWER_POWER_DOWN BIT(6) + +#define ADV7511_AUDIO_SELECT_I2C 0x0 +#define ADV7511_AUDIO_SELECT_SPDIF 0x1 +#define ADV7511_AUDIO_SELECT_DSD 0x2 +#define ADV7511_AUDIO_SELECT_HBR 0x3 +#define ADV7511_AUDIO_SELECT_DST 0x4 + +#define ADV7511_I2S_SAMPLE_LEN_16 0x2 +#define ADV7511_I2S_SAMPLE_LEN_20 0x3 +#define ADV7511_I2S_SAMPLE_LEN_18 0x4 +#define ADV7511_I2S_SAMPLE_LEN_22 0x5 +#define ADV7511_I2S_SAMPLE_LEN_19 0x8 +#define ADV7511_I2S_SAMPLE_LEN_23 0x9 +#define ADV7511_I2S_SAMPLE_LEN_24 0xb +#define ADV7511_I2S_SAMPLE_LEN_17 0xc +#define ADV7511_I2S_SAMPLE_LEN_21 0xd + +#define ADV7511_SAMPLE_FREQ_44100 0x0 +#define ADV7511_SAMPLE_FREQ_48000 0x2 +#define ADV7511_SAMPLE_FREQ_32000 0x3 +#define ADV7511_SAMPLE_FREQ_88200 0x8 +#define ADV7511_SAMPLE_FREQ_96000 0xa +#define ADV7511_SAMPLE_FREQ_176400 0xc +#define ADV7511_SAMPLE_FREQ_192000 0xe + +#define ADV7511_STATUS_POWER_DOWN_POLARITY BIT(7) +#define ADV7511_STATUS_HPD BIT(6) +#define ADV7511_STATUS_MONITOR_SENSE BIT(5) +#define ADV7511_STATUS_I2S_32BIT_MODE BIT(3) + +#define ADV7511_PACKET_ENABLE_N_CTS BIT(8+6) +#define ADV7511_PACKET_ENABLE_AUDIO_SAMPLE BIT(8+5) +#define ADV7511_PACKET_ENABLE_AVI_INFOFRAME BIT(8+4) +#define ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME BIT(8+3) +#define ADV7511_PACKET_ENABLE_GC BIT(7) +#define ADV7511_PACKET_ENABLE_SPD BIT(6) +#define ADV7511_PACKET_ENABLE_MPEG BIT(5) +#define ADV7511_PACKET_ENABLE_ACP BIT(4) +#define ADV7511_PACKET_ENABLE_ISRC BIT(3) +#define ADV7511_PACKET_ENABLE_GM BIT(2) +#define ADV7511_PACKET_ENABLE_SPARE2 BIT(1) +#define ADV7511_PACKET_ENABLE_SPARE1 BIT(0) + +#define ADV7511_LOW_REFRESH_RATE_NONE 0x0 +#define ADV7511_LOW_REFRESH_RATE_24HZ 0x1 +#define ADV7511_LOW_REFRESH_RATE_25HZ 0x2 +#define ADV7511_LOW_REFRESH_RATE_30HZ 0x3 + +#include + +struct i2c_client; +struct regmap; + +struct adv7511 { + struct i2c_client *i2c_main; + struct i2c_client *i2c_edid; + struct i2c_client *i2c_packet; + struct i2c_client *i2c_cec; + + struct regmap *regmap; + enum drm_connector_status status; + int dpms_mode; + + unsigned int f_tmds; + unsigned int f_audio; + + unsigned int audio_source; + + unsigned int current_edid_segment; + uint8_t edid_buf[256]; + + wait_queue_head_t wq; + struct drm_encoder *encoder; + + bool embedded_sync; +}; + +int adv7511_packet_enable(struct adv7511 *adv7511, unsigned int packet); +int adv7511_packet_disable(struct adv7511 *adv7511, unsigned int packet); + +int adv7511_audio_init(struct device *dev); +void adv7511_audio_exit(struct device *dev); + +enum adv7511_input_id { + ADV7511_INPUT_ID_24BIT_RGB444_YCbCr444 = 0, + ADV7511_INPUT_ID_16_20_24BIT_YCbCr422_SEPARATE_SYNC = 1, + ADV7511_INPUT_ID_16_20_24BIT_YCbCr422_EMBEDDED_SYNC = 2, + ADV7511_INPUT_ID_8_10_12BIT_YCbCr422_SEPARATE_SYNC = 3, + ADV7511_INPUT_ID_8_10_12BIT_YCbCr422_EMBEDDED_SYNC = 4, + ADV7511_INPUT_ID_12_15_16BIT_RGB444_YCbCr444 = 5, +}; + +enum adv7511_input_color_depth { + ADV7511_INPUT_COLOR_DEPTH_10BIT = 1, + ADV7511_INPUT_COLOR_DEPTH_12BIT = 2, + ADV7511_INPUT_COLOR_DEPTH_8BIT = 3, +}; + +enum adv7511_input_style { + ADV7511_INPUT_STYLE2 = 1, + ADV7511_INPUT_STYLE1 = 2, + ADV7511_INPUT_STYLE3 = 3, +}; + +enum adv7511_input_sync_pulse { + ADV7511_INPUT_SYNC_PULSE_DE = 0, + ADV7511_INPUT_SYNC_PULSE_HSYNC = 1, + ADV7511_INPUT_SYNC_PULSE_VSYNC = 2, + ADV7511_INPUT_SYNC_PULSE_NONE = 3, +}; + +enum adv7511_input_clock_delay { + ADV7511_INPUT_CLOCK_DELAY_MINUS_1200PS = 0, + ADV7511_INPUT_CLOCK_DELAY_MINUS_800PS = 1, + ADV7511_INPUT_CLOCK_DELAY_MINUS_400PS = 2, + ADV7511_INPUT_CLOCK_DELAY_NONE = 3, + ADV7511_INPUT_CLOCK_DELAY_PLUS_400PS = 4, + ADV7511_INPUT_CLOCK_DELAY_PLUS_800PS = 5, + ADV7511_INPUT_CLOCK_DELAY_PLUS_1200PS = 6, + ADV7511_INPUT_CLOCK_DELAY_PLUS_1600PS = 7, +}; + +enum adv7511_input_adjust_delay { + ADV7511_INPUT_ADJUST_DELAY_MINUS_1200PS = 0, + ADV7511_INPUT_ADJUST_DELAY_MINUS_800PS = 1, + ADV7511_INPUT_ADJUST_DELAY_MINUS_400PS = 2, + ADV7511_INPUT_ADJUST_DELAY_NONE = 3, + ADV7511_INPUT_ADJUST_DELAY_PLUS_400PS = 4, + ADV7511_INPUT_ADJUST_DELAY_PLUS_800PS = 5, + ADV7511_INPUT_ADJUST_DELAY_PLUS_1200PS = 6, + ADV7511_INPUT_ADJUST_DELAY_INVERT_CLK = 7, +}; + +enum adv7511_input_bit_justifiction { + ADV7511_INPUT_BIT_JUSTIFICATION_EVENLY = 0, + ADV7511_INPUT_BIT_JUSTIFICATION_RIGHT = 1, + ADV7511_INPUT_BIT_JUSTIFICATION_LEFT = 2, +}; + +enum adv7511_output_format { + ADV7511_OUTPUT_FORMAT_RGB_444 = 0, + ADV7511_OUTPUT_FORMAT_YCBCR_422 = 1, + ADV7511_OUTPUT_FORMAT_YCBCR_444 = 2, +}; + +struct adv7511_video_input_config { + enum adv7511_input_id id; + enum adv7511_input_style input_style; + enum adv7511_input_sync_pulse sync_pulse; + enum adv7511_input_clock_delay clock_delay; + bool reverse_bitorder; + enum adv7511_input_bit_justifiction bit_justification; + bool vsync_polartity_low; + bool hsync_polartity_low; + bool up_conversion_first_order_interpolation; + enum adv7511_input_color_depth input_color_depth; + bool tmds_clock_inversion; + + bool csc_enable; + int csc_scaling_factor; + uint16_t *csc_coefficents; + + enum adv7511_output_format output_format; + int timing_generation_sequence; + bool hdmi_mode; +}; + +#endif diff --git a/drivers/gpu/drm/i2c/adv7511_audio.c b/drivers/gpu/drm/i2c/adv7511_audio.c new file mode 100644 index 0000000000000..9fb99487ac998 --- /dev/null +++ b/drivers/gpu/drm/i2c/adv7511_audio.c @@ -0,0 +1,318 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "adv7511.h" + +static const DECLARE_TLV_DB_SCALE(adv7511_levelshift_tlv, 0, 100, 0); + +static const struct snd_kcontrol_new adv7511_controls[] = { + SOC_SINGLE("Master Playback Switch", 0, 0, 0, 0), + SOC_SINGLE_TLV("Master Playback Volume", 0, 0, 45, 0, + adv7511_levelshift_tlv), +}; + +static const struct snd_soc_dapm_widget adv7511_dapm_widgets[] = { +}; + +static const struct snd_soc_dapm_route adv7511_routes[] = { + { "TMDS", NULL, "DAI IN" }, +}; + +static void adv7511_calc_cts_n(unsigned int f_tmds, unsigned int fs, + unsigned int *cts, unsigned int *n) +{ + switch (fs) { + case 32000: + *n = 4096; + break; + case 44100: + *n = 6272; + break; + case 48000: + *n = 6144; + break; + } + + *cts = (f_tmds * *n) / (128 * fs); +} + +static int adv7511_update_cts_n(struct adv7511 *adv7511) +{ + unsigned int cts = 0; + unsigned int n = 0; + + adv7511_calc_cts_n(adv7511->f_tmds, adv7511->f_audio, &cts, &n); + + regmap_write(adv7511->regmap, ADV7511_REG_N0, (n >> 16) & 0xf); + regmap_write(adv7511->regmap, ADV7511_REG_N1, (n >> 8) & 0xff); + regmap_write(adv7511->regmap, ADV7511_REG_N2, n & 0xff); + + regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL0, (n >> 16) & 0xf); + regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL1, (n >> 8) & 0xff); + regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL2, n & 0xff); + + return 0; +} + +static int adv7511_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->codec; + struct adv7511 *adv7511 = snd_soc_codec_get_drvdata(codec); + unsigned int rate; + unsigned int len; + + switch (params_rate(params)) { + case 32000: + rate = ADV7511_SAMPLE_FREQ_32000; + break; + case 44100: + rate = ADV7511_SAMPLE_FREQ_44100; + break; + case 48000: + rate = ADV7511_SAMPLE_FREQ_48000; + break; + case 88200: + rate = ADV7511_SAMPLE_FREQ_88200; + break; + case 96000: + rate = ADV7511_SAMPLE_FREQ_96000; + break; + case 176400: + rate = ADV7511_SAMPLE_FREQ_176400; + break; + case 192000: + rate = ADV7511_SAMPLE_FREQ_192000; + break; + default: + return -EINVAL; + } + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + len = ADV7511_I2S_SAMPLE_LEN_16; + break; + case SNDRV_PCM_FORMAT_S18_3LE: + len = ADV7511_I2S_SAMPLE_LEN_18; + break; + case SNDRV_PCM_FORMAT_S20_3LE: + len = ADV7511_I2S_SAMPLE_LEN_20; + break; + case SNDRV_PCM_FORMAT_S24_LE: + len = ADV7511_I2S_SAMPLE_LEN_24; + break; + default: + return -EINVAL; + } + + adv7511->f_audio = params_rate(params); + + adv7511_update_cts_n(adv7511); + + regmap_update_bits(adv7511->regmap, 0x14, 0x0f, len); + regmap_update_bits(adv7511->regmap, 0x15, 0xf0, rate << 4); + + return 0; +} + +#define ADV7511_AUDIO_SOURCE_I2S 0 +#define ADV7511_AUDIO_SOURCE_SPDIF 1 + +#define ADV7511_I2S_FORMAT_I2S 0 +#define ADV7511_I2S_FORMAT_RIGHT_J 1 +#define ADV7511_I2S_FORMAT_LEFT_J 2 + +static int adv7511_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct adv7511 *adv7511 = snd_soc_codec_get_drvdata(codec); + unsigned int audio_source, i2s_format = 0; + unsigned int invert_clock; + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + audio_source = ADV7511_AUDIO_SOURCE_I2S; + i2s_format = ADV7511_I2S_FORMAT_I2S; + break; + case SND_SOC_DAIFMT_RIGHT_J: + audio_source = ADV7511_AUDIO_SOURCE_I2S; + i2s_format = ADV7511_I2S_FORMAT_RIGHT_J; + break; + case SND_SOC_DAIFMT_LEFT_J: + audio_source = ADV7511_AUDIO_SOURCE_I2S; + i2s_format = ADV7511_I2S_FORMAT_LEFT_J; + break; + case SND_SOC_DAIFMT_SPDIF: + audio_source = ADV7511_AUDIO_SOURCE_SPDIF; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + break; + default: + return -EINVAL; + } + + /* clock inversion */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + invert_clock = 0; + break; + case SND_SOC_DAIFMT_IB_NF: + invert_clock = 1; + break; + default: + return -EINVAL; + } + + regmap_update_bits(adv7511->regmap, 0x0a, 0x70, audio_source << 4); + regmap_update_bits(adv7511->regmap, 0x0b, BIT(6), invert_clock << 6); + regmap_update_bits(adv7511->regmap, 0x0c, 0x03, i2s_format); + + adv7511->audio_source = audio_source; + + return 0; +} + +static int adv7511_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct adv7511 *adv7511 = snd_soc_codec_get_drvdata(codec); + + switch (level) { + case SND_SOC_BIAS_ON: + switch (adv7511->audio_source) { + case ADV7511_AUDIO_SOURCE_I2S: + break; + case ADV7511_AUDIO_SOURCE_SPDIF: + regmap_update_bits(adv7511->regmap, 0x0b, BIT(7), BIT(7)); + break; + } + break; + case SND_SOC_BIAS_PREPARE: + if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { + adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AUDIO_SAMPLE); + adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME); + adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_N_CTS); + } else { + adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AUDIO_SAMPLE); + adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME); + adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_N_CTS); + } + break; + case SND_SOC_BIAS_STANDBY: + regmap_update_bits(adv7511->regmap, 0x0b, BIT(7), 0); + break; + case SND_SOC_BIAS_OFF: + break; + } + codec->dapm.bias_level = level; + return 0; +} + +#define ADV7511_RATES (SNDRV_PCM_RATE_32000 |\ + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) + +#define ADV7511_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |\ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) + +static const struct snd_soc_dai_ops adv7511_dai_ops = { + .hw_params = adv7511_hw_params, + /*.set_sysclk = adv7511_set_dai_sysclk,*/ + .set_fmt = adv7511_set_dai_fmt, +}; + +static struct snd_soc_dai_driver adv7511_dai = { + .name = "adv7511", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = ADV7511_RATES, + .formats = ADV7511_FORMATS, + }, + .ops = &adv7511_dai_ops, +}; + +static int adv7511_suspend(struct snd_soc_codec *codec) +{ + adv7511_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} + +static int adv7511_resume(struct snd_soc_codec *codec) +{ + adv7511_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + return 0; +} + +static int adv7511_probe(struct snd_soc_codec *codec) +{ + struct adv7511 *adv7511 = snd_soc_codec_get_drvdata(codec); + int ret; + + codec->control_data = adv7511->regmap; + ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; + } + + adv7511_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + return 0; +} + +static int adv7511_remove(struct snd_soc_codec *codec) +{ + adv7511_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} + +static struct snd_soc_codec_driver adv7511_codec_driver = { + .probe = adv7511_probe, + .remove = adv7511_remove, + .suspend = adv7511_suspend, + .resume = adv7511_resume, + .set_bias_level = adv7511_set_bias_level, + +/* + .controls = adv7511_controls, + .num_controls = ARRAY_SIZE(adv7511_controls),*/ + .dapm_widgets = adv7511_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adv7511_dapm_widgets), + .dapm_routes = adv7511_routes, + .num_dapm_routes = ARRAY_SIZE(adv7511_routes), +}; + +int adv7511_audio_init(struct device *dev) +{ + return snd_soc_register_codec(dev, &adv7511_codec_driver, + &adv7511_dai, 1); +} + +void adv7511_audio_exit(struct device *dev) +{ + snd_soc_unregister_codec(dev); +} diff --git a/drivers/gpu/drm/i2c/adv7511_core.c b/drivers/gpu/drm/i2c/adv7511_core.c new file mode 100644 index 0000000000000..096ff90a82df0 --- /dev/null +++ b/drivers/gpu/drm/i2c/adv7511_core.c @@ -0,0 +1,699 @@ + +#include +#include +#include +#include + +#include "adv7511.h" + +#include +#include +#include +#include + +static uint8_t adv7511_register_defaults[] = { + 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00 */ + 0x00, 0x00, 0x01, 0x0e, 0xbc, 0x18, 0x01, 0x13, + 0x25, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */ + 0x46, 0x62, 0x04, 0xa8, 0x00, 0x00, 0x1c, 0x84, + 0x1c, 0xbf, 0x04, 0xa8, 0x1e, 0x70, 0x02, 0x1e, /* 20 */ + 0x00, 0x00, 0x04, 0xa8, 0x08, 0x12, 0x1b, 0xac, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30 */ + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, + 0x00, 0x50, 0x90, 0x7e, 0x79, 0x70, 0x00, 0x00, /* 40 */ + 0x00, 0xa8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x00, /* 50 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 60 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 70 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 80 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 90 */ + 0x0b, 0x02, 0x00, 0x18, 0x5a, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x80, 0x08, 0x04, 0x00, 0x00, /* a0 */ + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c0 */ + 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0x04, + 0x30, 0xff, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, /* d0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, + 0x80, 0x75, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, /* e0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x11, 0x00, /* f0 */ + 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* ADI recommanded values for proper operation. */ +static uint8_t adv7511_fixed_registers[][2] = { + { 0x98, 0x03 }, + { 0x9a, 0xe0 }, + { 0x9c, 0x30 }, + { 0x9d, 0x61 }, + { 0xa2, 0xa4 }, + { 0xa3, 0xa4 }, + { 0xe0, 0xd0 }, + { 0xf9, 0x00 }, + { 0x55, 0x02 }, +}; + +static struct adv7511 *encoder_to_adv7511(struct drm_encoder *encoder) +{ + return to_encoder_slave(encoder)->slave_priv; +} + +static void adv7511_set_colormap(struct adv7511 *adv7511, bool enable, + uint16_t *coeff, unsigned int scaling_factor) +{ + unsigned int i; + + regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(1), + ADV7511_CSC_UPDATE_MODE, ADV7511_CSC_UPDATE_MODE); + + if (enable) { + for (i = 0; i < 12; ++i) { + regmap_update_bits(adv7511->regmap, + ADV7511_REG_CSC_UPPER(i), + 0x1f, coeff[i] >> 8); + regmap_write(adv7511->regmap, + ADV7511_REG_CSC_LOWER(i), + coeff[i] & 0xff); + } + } + + regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(0), + 0xe0, (enable << 7) | (scaling_factor << 5)); + + regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(1), + ADV7511_CSC_UPDATE_MODE, 0); +} + +#define ADV7511_HDMI_CFG_MODE_DVI 0x0 +#define ADV7511_HDMI_CFG_MODE_HDMI 0x2 + +static void adv7511_set_config(struct drm_encoder *encoder, void *c) +{ + struct adv7511 *adv7511 = encoder_to_adv7511(encoder); + struct adv7511_video_input_config *config = c; + enum adv7511_input_sync_pulse sync_pulse; + bool output_format_422, output_format_ycbcr; + unsigned int mode; + + adv7511_set_colormap(adv7511, config->csc_enable, config->csc_coefficents, + config->csc_scaling_factor); + + switch (config->output_format) { + case ADV7511_OUTPUT_FORMAT_YCBCR_444: + output_format_422 = false; + output_format_ycbcr = true; + break; + case ADV7511_OUTPUT_FORMAT_YCBCR_422: + output_format_422 = true; + output_format_ycbcr = true; + break; + default: + output_format_422 = false; + output_format_ycbcr = false; + break; + } + + switch (config->id) { + case ADV7511_INPUT_ID_12_15_16BIT_RGB444_YCbCr444: + sync_pulse = ADV7511_INPUT_SYNC_PULSE_NONE; + break; + default: + sync_pulse = config->sync_pulse; + break; + } + + switch (config->id) { + case ADV7511_INPUT_ID_16_20_24BIT_YCbCr422_EMBEDDED_SYNC: + case ADV7511_INPUT_ID_8_10_12BIT_YCbCr422_EMBEDDED_SYNC: + adv7511->embedded_sync = true; + break; + default: + adv7511->embedded_sync = false; + break; + } + + regmap_update_bits(adv7511->regmap, 0x15, 0xf, config->id); + regmap_write(adv7511->regmap, ADV7511_REG_VIDEO_INPUT_CFG1, + (output_format_422 << 7) | + (config->input_color_depth << 4) | + (config->input_style << 2) | + output_format_ycbcr); + regmap_write(adv7511->regmap, ADV7511_REG_VIDEO_INPUT_CFG2, + (config->reverse_bitorder << 6) | + (config->bit_justification << 3)); + regmap_write(adv7511->regmap, ADV7511_REG_TIMING_GEN_SEQ, + (sync_pulse << 2) | + (config->timing_generation_sequence << 1)); +/* regmap_write(adv7511->regmap, 0xba, + (config->clock_delay << 5));*/ + + regmap_update_bits(adv7511->regmap, ADV7511_REG_TMDS_CLOCK_INV, + 0x08, config->tmds_clock_inversion << 3); + + regmap_update_bits(adv7511->regmap, ADV7511_REG_AVI_INFOFRAME(0), + 0x60, config->output_format << 5); + + if (config->hdmi_mode) + mode = ADV7511_HDMI_CFG_MODE_HDMI; + else + mode = ADV7511_HDMI_CFG_MODE_DVI; + + regmap_update_bits(adv7511->regmap, ADV7511_REG_HDCP_HDMI_CFG, + 0x2, mode); +} + +int adv7511_packet_enable(struct adv7511 *adv7511, unsigned int packet) +{ + if (packet & 0xff) { + regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE0, + packet, 0xff); + } + + if (packet & 0xff00) { + packet >>= 8; + regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1, + packet, 0xff); + } + + return 0; +} + +int adv7511_packet_disable(struct adv7511 *adv7511, unsigned int packet) +{ + if (packet & 0xff) { + regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE0, + packet, 0x00); + } + + if (packet & 0xff00) { + packet >>= 8; + regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1, + packet, 0x00); + } + + return 0; +} + +static bool adv7511_register_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ADV7511_REG_SPDIF_FREQ: + case ADV7511_REG_CTS_AUTOMATIC1: + case ADV7511_REG_CTS_AUTOMATIC2: + case ADV7511_REG_VIC_DETECTED: + case ADV7511_REG_VIC_SEND: + case ADV7511_REG_AUX_VIC_DETECTED: + case ADV7511_REG_STATUS: + case ADV7511_REG_GC(1): + case ADV7511_REG_INT(0): + case ADV7511_REG_INT(1): + case ADV7511_REG_PLL_STATUS: + case ADV7511_REG_AN(0): + case ADV7511_REG_AN(1): + case ADV7511_REG_AN(2): + case ADV7511_REG_AN(3): + case ADV7511_REG_AN(4): + case ADV7511_REG_AN(5): + case ADV7511_REG_AN(6): + case ADV7511_REG_AN(7): + case ADV7511_REG_HDCP_STATUS: + case ADV7511_REG_BCAPS: + case ADV7511_REG_BKSV(0): + case ADV7511_REG_BKSV(1): + case ADV7511_REG_BKSV(2): + case ADV7511_REG_BKSV(3): + case ADV7511_REG_BKSV(4): + case ADV7511_REG_DDC_CONTROLLER_STATUS: + case ADV7511_REG_BSTATUS(0): + case ADV7511_REG_BSTATUS(1): + case ADV7511_REG_CHIP_ID_HIGH: + case ADV7511_REG_CHIP_ID_LOW: + return true; + } + + return false; +} + +static bool adv7511_hpd(struct adv7511 *adv7511) +{ + unsigned int irq0; + int ret; + + ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0); + if (ret < 0) + return false; + + if (irq0 & ADV7511_INT0_HDP) { + regmap_write(adv7511->regmap, ADV7511_REG_INT(0), ADV7511_INT0_HDP); + return true; + } + + return false; +} + +static irqreturn_t adv7511_irq_handler(int irq, void *devid) +{ + struct adv7511 *adv7511 = devid; + + if (adv7511_hpd(adv7511)) + drm_helper_hpd_irq_event(adv7511->encoder->dev); + + wake_up_all(&adv7511->wq); + + return IRQ_HANDLED; +} + +static unsigned int adv7511_is_interrupt_pending(struct adv7511 *adv7511, + unsigned int irq) +{ + unsigned int irq0, irq1; + unsigned int pending; + int ret; + + ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0); + if (ret < 0) + return 0; + ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(1), &irq1); + if (ret < 0) + return 0; + + pending = (irq1 << 8) | irq0; + + return pending & irq; +} + +static int adv7511_wait_for_interrupt(struct adv7511 *adv7511, int irq, int timeout) +{ + unsigned int pending = 0; + int ret; + + if (adv7511->i2c_main->irq) { + ret = wait_event_interruptible_timeout(adv7511->wq, + adv7511_is_interrupt_pending(adv7511, irq), + msecs_to_jiffies(timeout)); + if (ret <= 0) + return 0; + pending = adv7511_is_interrupt_pending(adv7511, irq); + } else { + if (timeout < 25) + timeout = 25; + do { + pending = adv7511_is_interrupt_pending(adv7511, irq); + if (pending) + break; + msleep(25); + timeout -= 25; + } while (timeout >= 25); + } + + return pending; +} + +int adv7511_get_edid_block(void *data, + unsigned char *buf, int block, int len) +{ + struct drm_encoder *encoder = data; + struct adv7511 *adv7511 = encoder_to_adv7511(encoder); + struct i2c_msg xfer[2]; + uint8_t offset; + int i; + int ret; + + if (len > 128) + return -EINVAL; + + if (adv7511->current_edid_segment != block / 2) { + unsigned int status; + regmap_read(adv7511->regmap, 0xc8, &status); + printk("edid status: %x\n", status); + + if (status != 2) { + regmap_write(adv7511->regmap, ADV7511_REG_EDID_SEGMENT, block); + ret = adv7511_wait_for_interrupt(adv7511, ADV7511_INT0_EDID_READY | + ADV7511_INT1_DDC_ERROR, 200); + printk("edid ret: %x\n", ret); + + if (!(ret & ADV7511_INT0_EDID_READY)) + return -EIO; + } + + regmap_write(adv7511->regmap, ADV7511_REG_INT(0), + ADV7511_INT0_EDID_READY | ADV7511_INT1_DDC_ERROR); + + /* Break this apart, hopefully more I2C controllers will support 64 + * byte transfers than 256 byte transfers */ + + xfer[0].addr = adv7511->i2c_edid->addr; + xfer[0].flags = 0; + xfer[0].len = 1; + xfer[0].buf = &offset; + xfer[1].addr = adv7511->i2c_edid->addr; + xfer[1].flags = I2C_M_RD; + xfer[1].len = 64; + xfer[1].buf = adv7511->edid_buf; + + offset = 0; + + for (i = 0; i < 4; ++i) { + ret = i2c_transfer(adv7511->i2c_edid->adapter, xfer, ARRAY_SIZE(xfer)); + printk("i2c ret: %d\n", ret); + if (ret < 0) + return ret; + else if (ret != 2) + return -EIO; + + xfer[1].buf += 64; + offset += 64; + } + + adv7511->current_edid_segment = block / 2; + } + + if (block % 2 == 0) + memcpy(buf, adv7511->edid_buf, len); + else + memcpy(buf, adv7511->edid_buf + 128, len); + + return 0; +} + +static int adv7511_get_modes(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct adv7511 *adv7511 = encoder_to_adv7511(encoder); + struct edid *edid; + unsigned int count; + + /* Reading the EDID only works if the device is powered */ + if (adv7511->dpms_mode != DRM_MODE_DPMS_ON) { + regmap_write(adv7511->regmap, ADV7511_REG_INT(0), + ADV7511_INT0_EDID_READY | ADV7511_INT1_DDC_ERROR); + regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, + ADV7511_POWER_POWER_DOWN, 0); + adv7511->current_edid_segment = -1; + } + + edid = drm_do_get_edid(connector, adv7511_get_edid_block, encoder); + + if (adv7511->dpms_mode != DRM_MODE_DPMS_ON) + regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, + ADV7511_POWER_POWER_DOWN, ADV7511_POWER_POWER_DOWN); + + if (!edid) + return 0; + + drm_mode_connector_update_edid_property(connector, edid); + count = drm_add_edid_modes(connector, edid); + + connector->display_info.raw_edid = (char *)edid; + + return count; +} + +static void adv7511_encoder_dpms(struct drm_encoder *encoder, int mode) +{ + struct adv7511 *adv7511 = encoder_to_adv7511(encoder); + + switch (mode) { + case DRM_MODE_DPMS_ON: + adv7511->current_edid_segment = -1; + + regmap_write(adv7511->regmap, ADV7511_REG_INT(0), + ADV7511_INT0_EDID_READY | ADV7511_INT1_DDC_ERROR); + regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, + ADV7511_POWER_POWER_DOWN, 0); + /* + * Per spec it is allowed to pulse the HDP signal to indicate + * that the EDID information has changed. Some monitors do this + * when they wakeup from standby or are enabled. When the HDP + * goes low the adv7511 is reset and the outputs are disabled + * which might cause the monitor to go to standby again. To + * avoid this we ignore the HDP pin for the first few seconds + * after enabeling the output. + */ + regmap_update_bits(adv7511->regmap, 0xd6, 0xc0, 0xc0); + /* Most of the registers are reset during power down or when HPD is low */ + regcache_sync(adv7511->regmap); + break; + default: + /* TODO: setup additional power down modes */ + regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, + ADV7511_POWER_POWER_DOWN, ADV7511_POWER_POWER_DOWN); + regcache_mark_dirty(adv7511->regmap); + break; + } + + adv7511->dpms_mode = mode; +} + +static enum drm_connector_status adv7511_encoder_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct adv7511 *adv7511 = encoder_to_adv7511(encoder); + enum drm_connector_status status; + unsigned int val; + bool hpd; + + regmap_read(adv7511->regmap, ADV7511_REG_STATUS, &val); + + /* Cable connected and monitor turned on ? */ + if (val & (ADV7511_STATUS_HPD)) /* | ADV7511_STATUS_MONITOR_SENSE))*/ + status = connector_status_connected; + else + status = connector_status_disconnected; + + hpd = adv7511_hpd(adv7511); + + printk("detect: %x %d %d %d\n", val, status, hpd, adv7511->dpms_mode); + + /* The chip resets itself when the cable is disconnected, so in case there is + * a pending HPD interrupt and the cable is connected there was at least on + * transition from disconnected to connected and the chip has to be + * reinitialized. */ + if (status == connector_status_connected && hpd && + adv7511->dpms_mode == DRM_MODE_DPMS_ON) { + regcache_mark_dirty(adv7511->regmap); + adv7511_encoder_dpms(encoder, adv7511->dpms_mode); +/* adv7511_get_modes(encoder, connector);*/ + } else { + /* Renable HDP sensing */ + regmap_update_bits(adv7511->regmap, 0xd6, 0xc0, 0x0); + } + + adv7511->status = status; + return status; +} + +static void adv7511_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adj_mode) +{ + struct adv7511 *adv7511 = encoder_to_adv7511(encoder); + unsigned int low_refresh_rate; + + if (adv7511->embedded_sync) { + unsigned int hsync_offset, hsync_len; + unsigned int vsync_offset, vsync_len; + + hsync_offset = adj_mode->crtc_hsync_start - adj_mode->crtc_hdisplay; + vsync_offset = adj_mode->crtc_vsync_start - adj_mode->crtc_vdisplay; + hsync_len = adj_mode->crtc_hsync_end - adj_mode->crtc_hsync_start; + vsync_len = adj_mode->crtc_vsync_end - adj_mode->crtc_vsync_start; + + regmap_write(adv7511->regmap, ADV7511_REG_HSYNC_PLACEMENT_MSB, + ((hsync_offset >> 10) & 0x7) << 5); + regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(0), + (hsync_offset >> 2) & 0xff); + regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(1), + ((hsync_offset & 0x3) << 2) | (hsync_len >> 4)); + regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(2), + ((hsync_len & 0xf) << 4) | (vsync_offset >> 6)); + regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(3), + ((vsync_offset & 0x3f) << 2) | (vsync_len >> 8)); + regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(4), + vsync_len & 0xff); + } + + if (mode->vrefresh <= 24000) + low_refresh_rate = ADV7511_LOW_REFRESH_RATE_24HZ; + else if (mode->vrefresh <= 25000) + low_refresh_rate = ADV7511_LOW_REFRESH_RATE_25HZ; + else if (mode->vrefresh <= 30000) + low_refresh_rate = ADV7511_LOW_REFRESH_RATE_30HZ; + else + low_refresh_rate = ADV7511_LOW_REFRESH_RATE_NONE; + + regmap_update_bits(adv7511->regmap, 0xfb, + 0x6, low_refresh_rate << 1); + + adv7511->f_tmds = mode->clock; + +/* + switch (adv7511->color_mode) { + case COLOR_MODE_30BIT: + adv7511->f_tmds = adv7511->f_tmds * 5 / 4; + break; + case COLOR_MODE_36BIT: + adv7511->f_tmds = adv7511->f_tmds * 3 / 2; + break; + case COLOR_MODE_48BIT: + adv7511->f_tmds = adv7511->f_tmds * 2; + break; + case COLOR_MODE_24BIT: + break; + } +*/ +} + +static struct drm_encoder_slave_funcs adv7511_encoder_funcs = { + .set_config = adv7511_set_config, + .dpms = adv7511_encoder_dpms, + /* .destroy = adv7511_encoder_destroy,*/ + .mode_set = adv7511_encoder_mode_set, + .detect = adv7511_encoder_detect, + .get_modes = adv7511_get_modes, +}; + +static const struct regmap_config adv7511_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = 0xff, + .cache_type = REGCACHE_RBTREE, + .reg_defaults_raw = adv7511_register_defaults, + .num_reg_defaults_raw = ARRAY_SIZE(adv7511_register_defaults), + + .volatile_reg = adv7511_register_volatile, +}; + +static const int edid_i2c_addr = 0x7e; +static const int packet_i2c_addr = 0x70; +static const int cec_i2c_addr = 0x78; + +static int __devinit adv7511_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct adv7511 *adv7511; + unsigned int val; + unsigned int i; + int ret; + + adv7511 = devm_kzalloc(&i2c->dev, sizeof(*adv7511), GFP_KERNEL); + if (!adv7511) + return -ENOMEM; + + adv7511->regmap = regmap_init_i2c(i2c, &adv7511_regmap_config); + if (IS_ERR(adv7511->regmap)) + return PTR_ERR(adv7511->regmap); + + ret = regmap_read(adv7511->regmap, ADV7511_REG_CHIP_REVISION, &val); + dev_dbg(&i2c->dev, "Rev. %d\n", val); + + regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR, edid_i2c_addr); + regmap_write(adv7511->regmap, ADV7511_REG_PACKET_I2C_ADDR, packet_i2c_addr); + regmap_write(adv7511->regmap, ADV7511_REG_CEC_I2C_ADDR, cec_i2c_addr); + + adv7511->i2c_main = i2c; + adv7511->i2c_edid = i2c_new_dummy(i2c->adapter, edid_i2c_addr >> 1); + adv7511->i2c_packet = i2c_new_dummy(i2c->adapter, packet_i2c_addr >> 1); + adv7511->i2c_cec = i2c_new_dummy(i2c->adapter, cec_i2c_addr >> 1); + + for (i = 0; i < ARRAY_SIZE(adv7511_fixed_registers); ++i) { + regmap_write(adv7511->regmap, adv7511_fixed_registers[i][0], + adv7511_fixed_registers[i][1]); + } + + if (i2c->irq) { + ret = request_threaded_irq(i2c->irq, NULL, adv7511_irq_handler, 0, + dev_name(&i2c->dev), adv7511); + if (ret) + goto err_regmap_exit; + + init_waitqueue_head(&adv7511->wq); + } + + /* CEC is unused for now */ + regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, + ADV7511_CEC_CTRL_POWER_DOWN); + + regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, + ADV7511_POWER_POWER_DOWN, ADV7511_POWER_POWER_DOWN); + + adv7511->current_edid_segment = -1; + + i2c_set_clientdata(i2c, adv7511); + adv7511_audio_init(&i2c->dev); + + return 0; + +err_regmap_exit: + regmap_exit(adv7511->regmap); + + return ret; +} + +static int __devexit adv7511_remove(struct i2c_client *i2c) +{ + struct adv7511 *adv7511 = i2c_get_clientdata(i2c); + + if (i2c->irq) + free_irq(i2c->irq, adv7511); + + regmap_exit(adv7511->regmap); + + i2c_unregister_device(adv7511->i2c_edid); + i2c_unregister_device(adv7511->i2c_packet); + i2c_unregister_device(adv7511->i2c_cec); + + return 0; +} + +static int adv7511_encoder_init(struct i2c_client *i2c, + struct drm_device *dev, struct drm_encoder_slave *encoder) +{ + + struct adv7511 *adv7511 = i2c_get_clientdata(i2c); + + encoder->slave_priv = adv7511; + encoder->slave_funcs = &adv7511_encoder_funcs; + + adv7511->encoder = &encoder->base; + + return 0; +} + +static const struct i2c_device_id adv7511_ids[] = { + { "adv7511", 0 }, + {} +}; + +static struct drm_i2c_encoder_driver adv7511_driver = { + .i2c_driver = { + .driver = { + .name = "adv7511", + }, + .id_table = adv7511_ids, + .probe = adv7511_probe, + .remove = __devexit_p(adv7511_remove), + }, + + .encoder_init = adv7511_encoder_init, +}; + +static int __init adv7511_init(void) +{ + return drm_i2c_encoder_register(THIS_MODULE, &adv7511_driver); +} +module_init(adv7511_init); + +static void __exit adv7511_exit(void) +{ + drm_i2c_encoder_unregister(&adv7511_driver); +} +module_exit(adv7511_exit); From 87a8fd6b98eeee317c7a486846cc8405d0bd68d8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 27 Apr 2012 11:08:13 +0200 Subject: [PATCH 042/261] DRM: Add driver for Analog Devices FPGA platforms Signed-off-by: Lars-Peter Clausen --- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/analog/Kconfig | 9 + drivers/gpu/drm/analog/Makefile | 8 + drivers/gpu/drm/analog/analog_drm_buf.c | 76 +++ drivers/gpu/drm/analog/analog_drm_crtc.c | 174 +++++ drivers/gpu/drm/analog/analog_drm_crtc.h | 9 + drivers/gpu/drm/analog/analog_drm_drv.c | 219 +++++++ drivers/gpu/drm/analog/analog_drm_drv.h | 28 + drivers/gpu/drm/analog/analog_drm_encoder.c | 667 ++++++++++++++++++++ drivers/gpu/drm/analog/analog_drm_encoder.h | 6 + drivers/gpu/drm/analog/analog_drm_fbdev.c | 338 ++++++++++ drivers/gpu/drm/analog/analog_drm_fbdev.h | 12 + drivers/gpu/drm/analog/analog_drm_gem.c | 242 +++++++ drivers/gpu/drm/analog/analog_drm_gem.h | 52 ++ 15 files changed, 1843 insertions(+) create mode 100644 drivers/gpu/drm/analog/Kconfig create mode 100644 drivers/gpu/drm/analog/Makefile create mode 100644 drivers/gpu/drm/analog/analog_drm_buf.c create mode 100644 drivers/gpu/drm/analog/analog_drm_crtc.c create mode 100644 drivers/gpu/drm/analog/analog_drm_crtc.h create mode 100644 drivers/gpu/drm/analog/analog_drm_drv.c create mode 100644 drivers/gpu/drm/analog/analog_drm_drv.h create mode 100644 drivers/gpu/drm/analog/analog_drm_encoder.c create mode 100644 drivers/gpu/drm/analog/analog_drm_encoder.h create mode 100644 drivers/gpu/drm/analog/analog_drm_fbdev.c create mode 100644 drivers/gpu/drm/analog/analog_drm_fbdev.h create mode 100644 drivers/gpu/drm/analog/analog_drm_gem.c create mode 100644 drivers/gpu/drm/analog/analog_drm_gem.h diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 0c03c96b4895e..86f3f72125b97 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -168,6 +168,8 @@ config DRM_ENCODER_ADV7511 select FB_SYS_COPYAREA select FB_SYS_IMAGEBLIT +source "drivers/gpu/drm/analog/Kconfig" + source "drivers/gpu/drm/exynos/Kconfig" source "drivers/gpu/drm/vmwgfx/Kconfig" diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 0cde1b80fdb19..a6f09e19b8c29 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -37,4 +37,5 @@ obj-$(CONFIG_DRM_VIA) +=via/ obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/ obj-$(CONFIG_DRM_EXYNOS) +=exynos/ obj-$(CONFIG_DRM_GMA500) += gma500/ +obj-$(CONFIG_DRM_ANALOG) += analog/ obj-y += i2c/ diff --git a/drivers/gpu/drm/analog/Kconfig b/drivers/gpu/drm/analog/Kconfig new file mode 100644 index 0000000000000..e70391744ddd1 --- /dev/null +++ b/drivers/gpu/drm/analog/Kconfig @@ -0,0 +1,9 @@ +config DRM_ANALOG + tristate "DRM Support for Analog FPGA platforms" + depends on DRM + default n + select DRM_KMS_HELPER + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE diff --git a/drivers/gpu/drm/analog/Makefile b/drivers/gpu/drm/analog/Makefile new file mode 100644 index 0000000000000..147ce59d69ab3 --- /dev/null +++ b/drivers/gpu/drm/analog/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the drm device driver. This driver provides support for the +# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. + +analogdrm-y := analog_drm_encoder.o analog_drm_crtc.o analog_drm_drv.o \ + analog_drm_gem.o analog_drm_fbdev.o + +obj-y += analogdrm.o diff --git a/drivers/gpu/drm/analog/analog_drm_buf.c b/drivers/gpu/drm/analog/analog_drm_buf.c new file mode 100644 index 0000000000000..4e8092519fb8d --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_buf.c @@ -0,0 +1,76 @@ +#include +#include + +#include "analog_drm_drv.h" +#include "analog_drm_gem.h" +#include "analog_drm_buf.h" + +static int lowlevel_buffer_allocate(struct drm_device *dev, + struct analog_drm_gem_buf *buffer) +{ + + buffer->kvaddr = dma_alloc_writecombine(dev->dev, buffer->size, + &buffer->dma_addr, GFP_KERNEL); + if (!buffer->kvaddr) { + DRM_ERROR("failed to allocate buffer. %ld\n", buffer->size); + return -ENOMEM; + } + + DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n", + (unsigned long)buffer->kvaddr, + (unsigned long)buffer->dma_addr, + buffer->size); + + return 0; +} + +static void lowlevel_buffer_deallocate(struct drm_device *dev, + struct analog_drm_gem_buf *buffer) +{ + + if (buffer->dma_addr && buffer->size) + dma_free_coherent(dev->dev, buffer->size, buffer->kvaddr, + (dma_addr_t)buffer->dma_addr); + else + DRM_DEBUG_KMS("buffer data are invalid.\n"); +} + +struct analog_drm_gem_buf *analog_drm_buf_create(struct drm_device *dev, + unsigned int size) +{ + struct analog_drm_gem_buf *buffer; + + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (!buffer) { + DRM_ERROR("failed to allocate analog_drm_gem_buf.\n"); + return ERR_PTR(-ENOMEM); + } + + buffer->size = size; + + /* + * allocate memory region with size and set the memory information + * to vaddr and dma_addr of a buffer object. + */ + if (lowlevel_buffer_allocate(dev, buffer) < 0) { + kfree(buffer); + buffer = NULL; + return ERR_PTR(-ENOMEM); + } + + return buffer; +} + +void analog_drm_buf_destroy(struct drm_device *dev, + struct analog_drm_gem_buf *buffer) +{ + if (!buffer) { + DRM_DEBUG_KMS("buffer is null.\n"); + return; + } + + lowlevel_buffer_deallocate(dev, buffer); + + kfree(buffer); + buffer = NULL; +} diff --git a/drivers/gpu/drm/analog/analog_drm_crtc.c b/drivers/gpu/drm/analog/analog_drm_crtc.c new file mode 100644 index 0000000000000..9536e0bb4d655 --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_crtc.c @@ -0,0 +1,174 @@ +#include +#include +#include +#include + +#include "analog_drm_crtc.h" +#include "analog_drm_fbdev.h" +#include "analog_drm_drv.h" +#include "analog_drm_encoder.h" +#include "analog_drm_gem.h" + +#define to_analog_crtc(x) container_of(x, struct analog_drm_crtc,\ + drm_crtc) + +struct analog_drm_crtc { + struct drm_crtc drm_crtc; + struct dma_chan *dma; + struct xilinx_dma_config dma_config; + int mode; +}; + +static int analog_drm_crtc_update(struct drm_crtc *crtc) +{ + struct analog_drm_crtc *analog_crtc = to_analog_crtc(crtc); + struct drm_display_mode *mode = &crtc->mode; + struct drm_framebuffer *fb = crtc->fb; + struct dma_async_tx_descriptor *desc; + struct analog_drm_gem_obj *obj; + size_t offset; + + if (!mode || !fb) + return -EINVAL; + + if (analog_crtc->mode == DRM_MODE_DPMS_ON) { + obj = analog_drm_fb_get_gem_obj(fb); + if (!obj) + return -EINVAL; + + analog_crtc->dma_config.hsize = mode->hdisplay * fb->bits_per_pixel / 8; + analog_crtc->dma_config.vsize = mode->vdisplay; + analog_crtc->dma_config.stride = fb->pitches[0]; + + dmaengine_device_control(analog_crtc->dma, DMA_SLAVE_CONFIG, + (unsigned long)&analog_crtc->dma_config); + + offset = crtc->x * fb->bits_per_pixel / 8 + crtc->y * fb->pitches[0]; + + desc = dmaengine_prep_slave_single(analog_crtc->dma, + obj->dma_addr + offset, mode->vdisplay * fb->pitches[0], + DMA_MEM_TO_DEV, 0); + if (!desc) { + pr_err("Failed to prepare DMA descriptor\n"); + return -ENOMEM; + } else { + dmaengine_submit(desc); + dma_async_issue_pending(analog_crtc->dma); + } + } else { + dmaengine_terminate_all(analog_crtc->dma); + } + + return 0; +} + +static void analog_drm_crtc_dpms(struct drm_crtc *crtc, int mode) +{ + struct analog_drm_crtc *analog_crtc = to_analog_crtc(crtc); + + if (analog_crtc->mode != mode) { + analog_crtc->mode = mode; + analog_drm_crtc_update(crtc); + } +} + +static void analog_drm_crtc_prepare(struct drm_crtc *crtc) +{ + struct analog_drm_crtc *analog_crtc = to_analog_crtc(crtc); + + dmaengine_terminate_all(analog_crtc->dma); +} + +static void analog_drm_crtc_commit(struct drm_crtc *crtc) +{ + struct analog_drm_crtc *analog_crtc = to_analog_crtc(crtc); + + analog_crtc->mode = DRM_MODE_DPMS_ON; + analog_drm_crtc_update(crtc); +} + +static bool +analog_drm_crtc_mode_fixup(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static int +analog_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, int x, int y, + struct drm_framebuffer *old_fb) +{ + /* We do everything in commit() */ + return 0; +} + +static int analog_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb) +{ + return analog_drm_crtc_update(crtc); +} + +static void analog_drm_crtc_load_lut(struct drm_crtc *crtc) +{ + /* drm framework doesn't check NULL */ +} + +static struct drm_crtc_helper_funcs analog_crtc_helper_funcs = { + .dpms = analog_drm_crtc_dpms, + .prepare = analog_drm_crtc_prepare, + .commit = analog_drm_crtc_commit, + .mode_fixup = analog_drm_crtc_mode_fixup, + .mode_set = analog_drm_crtc_mode_set, + .mode_set_base = analog_drm_crtc_mode_set_base, + .load_lut = analog_drm_crtc_load_lut, +}; + +static void analog_drm_crtc_destroy(struct drm_crtc *crtc) +{ + struct analog_drm_crtc *analog_crtc = to_analog_crtc(crtc); + + drm_crtc_cleanup(crtc); + kfree(analog_crtc); +} + +static struct drm_crtc_funcs analog_crtc_funcs = { + .set_config = drm_crtc_helper_set_config, + .destroy = analog_drm_crtc_destroy, +}; + +static bool xlnx_pcm_filter(struct dma_chan *chan, void *param) +{ + struct xlnx_pcm_dma_params *p = param; + + return chan->device->dev->of_node == p->of_node && + chan->chan_id == p->chan_id; +} + +struct drm_crtc *analog_drm_crtc_create(struct drm_device *dev) +{ + struct analog_drm_private *p = dev->dev_private; + struct analog_drm_crtc *analog_crtc; + struct drm_crtc *crtc; + dma_cap_mask_t mask; + + analog_crtc = kzalloc(sizeof(*analog_crtc), GFP_KERNEL); + if (!analog_crtc) { + DRM_ERROR("failed to allocate analog crtc\n"); + return ERR_PTR(-ENOMEM); + } + + crtc = &analog_crtc->drm_crtc; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_PRIVATE, mask); + + analog_crtc->dma = dma_request_channel(mask, xlnx_pcm_filter, &p->dma_params); + + drm_crtc_init(dev, crtc, &analog_crtc_funcs); + drm_crtc_helper_add(crtc, &analog_crtc_helper_funcs); + + return crtc; +} diff --git a/drivers/gpu/drm/analog/analog_drm_crtc.h b/drivers/gpu/drm/analog/analog_drm_crtc.h new file mode 100644 index 0000000000000..6585042d154b6 --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_crtc.h @@ -0,0 +1,9 @@ +#ifndef _ANALOG_DRM_CRTC_H_ +#define _ANALOG_DRM_CRTC_H_ + +struct drm_device; +struct drm_crtc; + +struct drm_crtc* analog_drm_crtc_create(struct drm_device *dev); + +#endif diff --git a/drivers/gpu/drm/analog/analog_drm_drv.c b/drivers/gpu/drm/analog/analog_drm_drv.c new file mode 100644 index 0000000000000..5406ccc291a51 --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_drv.c @@ -0,0 +1,219 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "analog_drm_drv.h" +#include "analog_drm_crtc.h" +#include "analog_drm_encoder.h" +#include "analog_drm_fbdev.h" +#include "analog_drm_gem.h" + +#define DRIVER_NAME "analog_drm" +#define DRIVER_DESC "ANALOG DRM" +#define DRIVER_DATE "20110530" +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 0 + +static struct platform_device *analog_drm_pdev; +static struct i2c_adapter *slave_adapter; +static struct i2c_adapter *ddc_adapter; + +static int analog_drm_load(struct drm_device *dev, unsigned long flags) +{ + struct analog_drm_private *private; + struct of_phandle_args dma_spec; + struct device_node *of_node; + int ret; + + ret = of_parse_phandle_with_args(analog_drm_pdev->dev.of_node, "dma-request", "#dma-cells", + 0, &dma_spec); + if (ret) { + return ret; + } + + private = kzalloc(sizeof(struct analog_drm_private), GFP_KERNEL); + if (!private) + return -ENOMEM; + + dev->dev_private = (void *)private; + + private->dma_params.of_node = dma_spec.np; + private->dma_params.chan_id = dma_spec.args[0]; + + drm_mode_config_init(dev); + + /* init kms poll for handling hpd */ + drm_kms_helper_poll_init(dev); + + analog_drm_mode_config_init(dev); + + private->crtc = analog_drm_crtc_create(dev); + if (IS_ERR(private->crtc)) { + ret = PTR_ERR(private->crtc); + goto err_crtc; + } + + of_node = dev->platformdev->dev.of_node; + private->base = of_iomap(of_node, 0); + private->base_clock = of_iomap(of_node, 1); + + private->ddc_adapter = ddc_adapter; + private->slave_adapter = slave_adapter; + + analog_drm_encoder_create(dev); + ret = analog_drm_fbdev_init(dev); + if (ret) { + DRM_ERROR("failed to initialize drm fbdev\n"); + goto err_drm_device; + } + + return 0; + +err_drm_device: +/* analog_drm_device_unregister(dev);*/ +err_crtc: + drm_mode_config_cleanup(dev); + kfree(private); + + return ret; +} + +static int analog_drm_unload(struct drm_device *dev) +{ + analog_drm_fbdev_fini(dev); + /*analog_drm_device_unregister(dev);*/ + drm_kms_helper_poll_fini(dev); + drm_mode_config_cleanup(dev); + kfree(dev->dev_private); + + return 0; +} + +static void analog_drm_lastclose(struct drm_device *dev) +{ + analog_drm_fbdev_restore_mode(dev); +} + +static struct vm_operations_struct analog_drm_gem_vm_ops = { + .fault = analog_drm_gem_fault, + .open = drm_gem_vm_open, + .close = drm_gem_vm_close, +}; + +static const struct file_operations analog_drm_driver_fops = { + .owner = THIS_MODULE, + .open = drm_open, + .mmap = analog_drm_gem_mmap, + .poll = drm_poll, + .read = drm_read, + .unlocked_ioctl = drm_ioctl, + .release = drm_release, +}; + +static struct drm_driver analog_drm_driver = { + .driver_features = DRIVER_BUS_PLATFORM | + DRIVER_MODESET | DRIVER_GEM, + .load = analog_drm_load, + .unload = analog_drm_unload, + .lastclose = analog_drm_lastclose, + .gem_free_object = analog_drm_gem_free_object, + .gem_vm_ops = &analog_drm_gem_vm_ops, + .dumb_create = analog_drm_gem_dumb_create, + .dumb_map_offset = analog_drm_gem_dumb_map_offset, + .dumb_destroy = analog_drm_gem_dumb_destroy, + .fops = &analog_drm_driver_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, +}; + +static void drm_register_work(struct work_struct *work) +{ + drm_platform_init(&analog_drm_driver, analog_drm_pdev); +} + +static DECLARE_WORK(register_work, drm_register_work); + +static int analog_drm_attach_i2c_adapter(struct device *dev, void *data) +{ + struct device_node *of_node; + + if (dev->type != &i2c_adapter_type) + return 0; + + if (analog_drm_pdev == NULL || dev->of_node == NULL) + return 0; + + if (/*ddc_adapter && */slave_adapter) + return 0; + + of_node = analog_drm_pdev->dev.of_node; + + +/* if (dev->of_node == of_parse_phandle(of_node, "ddc_adapter", 0)) + ddc_adapter = to_i2c_adapter(dev); + else*/ if (dev->of_node == of_parse_phandle(of_node, "slave_adapter", 0)) + slave_adapter = to_i2c_adapter(dev); + + if (/*ddc_adapter && */slave_adapter) + schedule_work(®ister_work); + + return 0; +} + +static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct device *dev = data; + + switch (action) { + case BUS_NOTIFY_ADD_DEVICE: + analog_drm_attach_i2c_adapter(dev, NULL); + } + + return 0; +} + +static struct notifier_block i2cdev_notifier = { + .notifier_call = i2cdev_notifier_call, +}; + +static int analog_drm_platform_probe(struct platform_device *pdev) +{ + analog_drm_pdev = pdev; + bus_register_notifier(&i2c_bus_type, &i2cdev_notifier); + i2c_for_each_dev(NULL, analog_drm_attach_i2c_adapter); + + return 0; +} + +static int analog_drm_platform_remove(struct platform_device *pdev) +{ + drm_platform_exit(&analog_drm_driver, pdev); + return 0; +} +static const struct of_device_id adv7511_encoder_of_match[] __devinitconst = { + { .compatible = "adi,cf-adv7x11-core-1.00.a", }, + {}, +}; +MODULE_DEVICE_TABLE(of, adv7511_encoder_of_match); + +static struct platform_driver adv7511_encoder_driver = { + .driver = { + .name = "cf-adv7x11-core", + .owner = THIS_MODULE, + .of_match_table = adv7511_encoder_of_match, + }, + .probe = analog_drm_platform_probe, + .remove = __devexit_p(analog_drm_platform_remove), +}; +module_platform_driver(adv7511_encoder_driver); diff --git a/drivers/gpu/drm/analog/analog_drm_drv.h b/drivers/gpu/drm/analog/analog_drm_drv.h new file mode 100644 index 0000000000000..89cc9e59f5256 --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_drv.h @@ -0,0 +1,28 @@ +#ifndef _ANALOG_DRM_DRV_H_ +#define _ANALOG_DRM_DRV_H_ + +#include +#include + +struct xlnx_pcm_dma_params { + struct device_node *of_node; + int chan_id; +}; + +struct analog_drm_fbdev; +struct analog_drm_encoder; + +struct analog_drm_private { + struct analog_drm_fbdev *fbdev; + struct drm_crtc *crtc; + struct analog_drm_encoder *encoder; + struct i2c_adapter *ddc_adapter; + struct i2c_adapter *slave_adapter; + + void __iomem *base; + void __iomem *base_clock; + + struct xlnx_pcm_dma_params dma_params; +}; + +#endif diff --git a/drivers/gpu/drm/analog/analog_drm_encoder.c b/drivers/gpu/drm/analog/analog_drm_encoder.c new file mode 100644 index 0000000000000..da7b781ac40a9 --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_encoder.c @@ -0,0 +1,667 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "analog_drm_drv.h" + +#include "../i2c/adv7511.h" + +#define ANALOG_REG_CTRL 0x04 +#define ANALOG_REG_HTIMING1 0x08 +#define ANALOG_REG_HTIMING2 0x0C +/* +#define ANALOG_REG_VTIMING 0x0c +*/ +#define ANALOG_REG_VTIMING1 0x10 +#define ANALOG_REG_VTIMING2 0x14 +#define ANALOG_REG_STATUS 0x10 +#define ANALOG_REG_COLOR_PATTERN 0x1c + +#define ANALOG_CTRL_ENABLE BIT(0) +#define ANALOG_CTRL_CSC_BYPASS BIT(1) +#define ANALOG_CTRL_TPG_ENABLE BIT(2) + +#define ANALOG_STATUS_VMDA_UNDERFLOW BIT(4) +#define ANALOG_STATUS_VMDA_OVERFLOW BIT(3) +#define ANALOG_STATUS_VMDA_BE_ERROR BIT(2) +#define ANALOG_STATUS_VMDA_TPM_OOS BIT(1) +#define ANALOG_STATUS_HDMI_TPM_OOS BIT(0) + +#define ANALOG_COLOR_PATTERN_ENABLE BIT(24) + +static struct debugfs_reg32 analog_drm_encoder_debugfs_regs[] = { + { "Control", ANALOG_REG_CTRL }, + { "HTiming1", ANALOG_REG_HTIMING1 }, + { "HTiming2", ANALOG_REG_HTIMING2 }, + { "VTiming1", ANALOG_REG_VTIMING1 }, + { "VTiming2", ANALOG_REG_VTIMING2 }, + { "Status", ANALOG_REG_STATUS }, +}; + +static uint16_t adv7511_csc_ycbcr_to_rgb[] = { + 0x0734, 0x04ad, 0x0000, 0x1c1b, + 0x1ddc, 0x04ad, 0x1f24, 0x0135, + 0x0000, 0x04ad, 0x087c, 0x1b77, +}; + +/* +static struct adv7511_video_input_config adv7511_config_imageon = { + .id = ADV7511_INPUT_ID_16_20_24BIT_YCbCr422_EMBEDDED_SYNC, + .input_style = ADV7511_INPUT_STYLE1, + .sync_pulse = ADV7511_INPUT_SYNC_PULSE_NONE, + .clock_delay = ADV7511_INPUT_CLOCK_DELAY_NONE, + .reverse_bitorder = 0, + .bit_justification = 0, + .vsync_polartity_low = false, + .hsync_polartity_low = false, + .up_conversion_first_order_interpolation = false, + .input_color_depth = ADV7511_INPUT_COLOR_DEPTH_8BIT, + .output_format = ADV7511_OUTPUT_FORMAT_RGB_444, + .csc_enable = true, + .csc_coefficents = adv7511_csc_ycbcr_to_rgb, + .csc_scaling_factor = 3, + .bit_justification = ADV7511_INPUT_BIT_JUSTIFICATION_LEFT, +}; +*/ + +static struct adv7511_video_input_config adv7511_config_zc702 = { + .id = ADV7511_INPUT_ID_16_20_24BIT_YCbCr422_SEPARATE_SYNC, + .input_style = ADV7511_INPUT_STYLE1, + .sync_pulse = ADV7511_INPUT_SYNC_PULSE_NONE, + .clock_delay = ADV7511_INPUT_CLOCK_DELAY_NONE, + .reverse_bitorder = 0, + .vsync_polartity_low = false, + .hsync_polartity_low = false, + .up_conversion_first_order_interpolation = false, + .input_color_depth = ADV7511_INPUT_COLOR_DEPTH_8BIT, + .output_format = ADV7511_OUTPUT_FORMAT_RGB_444, + .csc_enable = true, + .csc_coefficents = adv7511_csc_ycbcr_to_rgb, + .csc_scaling_factor = 3, + .bit_justification = ADV7511_INPUT_BIT_JUSTIFICATION_RIGHT, + .tmds_clock_inversion = true, +}; + +struct analog_drm_encoder { + struct drm_encoder_slave encoder; + struct drm_connector connector; + + struct debugfs_regset32 regset; +}; + +#define to_analog_encoder(x) container_of(x, struct analog_drm_encoder,\ + encoder.base) + +static inline struct drm_encoder *connector_to_encoder(struct drm_connector *connector) +{ + struct analog_drm_encoder *enc = container_of(connector, struct analog_drm_encoder, connector); + return &enc->encoder.base; +} + +static int analog_drm_connector_init(struct drm_device *dev, + struct drm_connector *connector, struct drm_encoder *encoder); + +static inline struct drm_encoder_slave_funcs * +get_slave_funcs(struct drm_encoder *enc) +{ + if (!to_encoder_slave(enc)) + return NULL; + + return to_encoder_slave(enc)->slave_funcs; +} + +static int debugfs_cp_get(void *data, u64 *val) +{ + struct analog_drm_private *private = data; + *val = ioread32(private->base + ANALOG_REG_COLOR_PATTERN); + return 0; +} +static int debugfs_cp_set(void *data, u64 val) +{ + struct analog_drm_private *private = data; + iowrite32(0x0000000, private-> base + ANALOG_REG_COLOR_PATTERN); + iowrite32(0x1000000 | val, private-> base + ANALOG_REG_COLOR_PATTERN); + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(fops_cp, debugfs_cp_get, debugfs_cp_set, "0x%08llx\n"); + +static void analog_drm_encoder_dpms(struct drm_encoder *encoder, int mode) +{ + struct analog_drm_encoder *analog_encoder = to_analog_encoder(encoder); + struct drm_connector *connector = &analog_encoder->connector; + struct analog_drm_private *private = encoder->dev->dev_private; + struct drm_encoder_slave_funcs *sfuncs = get_slave_funcs(encoder); + struct adv7511_video_input_config config = adv7511_config_zc702; + + switch (mode) { + case DRM_MODE_DPMS_ON: + iowrite32(ANALOG_CTRL_ENABLE, private->base + ANALOG_REG_CTRL); + if (connector->display_info.raw_edid) { + struct edid *edid = (struct edid *)connector->display_info.raw_edid; + config.hdmi_mode = drm_detect_hdmi_monitor(edid); + } else { + config.hdmi_mode = false; + } + + printk("raw_edid: %p %d\n", connector->display_info.raw_edid, + connector->display_info.color_formats); + + if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB422) && + config.hdmi_mode) { + config.csc_enable = false; + config.output_format = ADV7511_OUTPUT_FORMAT_YCBCR_422; + pr_info("Using YCbCr output\n"); + } else { + config.csc_enable = true; + config.output_format = ADV7511_OUTPUT_FORMAT_RGB_444; + pr_info("Using RGB output\n"); + } + + sfuncs->set_config(encoder, &config); + break; + default: + iowrite32(0, private->base + ANALOG_REG_CTRL); + break; + } + + if (sfuncs && sfuncs->dpms) + sfuncs->dpms(encoder, mode); +} + +struct analog_drm_crtc_clock_setting { + long clock; + uint32_t settings[10]; +}; + +static const struct analog_drm_crtc_clock_setting clock_settings[] = { + { /* 162 Mhz */ + .clock = 162000, + .settings = { + 0x00c4, 0x0080, 0x2042, 0x0209, 0x0080, + 0x023f, 0x7c01, 0x7fe9, 0x0100, 0x1090, + }, + }, + { /* 154 Mhz */ + .clock = 154000, + .settings = { + 0x0082, 0x0000, 0x2187, 0x0514, 0x0000, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x1090, + }, + }, + { /* 148.5 Mhz */ + .clock = 148500, + .settings = { + 0x00c3, 0x0000, 0x2146, 0x0619, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x8090, + }, + }, + { /* 146.25 Mhz */ + .clock = 146250, + .settings = { + 0x00c3, 0x0000, 0x2187, 0x071d, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x8090, + }, + }, + { /* 138.5 Mhz */ + .clock = 138500, + .settings = { + 0x0083, 0x0080, 0x2187, 0x0597, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x1090, + }, + }, + { /* 135 Mhz */ + .clock = 135000, + .settings = { + 0x0104, 0x0000, 0x2083, 0x034e, 0x0080, + 0x015e, 0x7c01, 0x7fe9, 0x0100, 0x8090, + }, + }, + { /* 108 Mhz */ + .clock = 108000, + .settings = { + 0x0145, 0x0000, 0x2083, 0x034e, 0x0080, + 0x015e, 0x7c01, 0x7fe9, 0x0100, 0x8090, + }, + }, + { /* 106.5 Mhz */ + .clock = 106500, + .settings = { + 0x00c4, 0x0080, 0x2146, 0x0515, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x1090, + }, + }, + { /* 78.8 Mhz */ + .clock = 78800, + .settings = { + 0x0146, 0x0080, 0x2042, 0x0187, 0x0080, + 0x02ee, 0x7c01, 0x7fe9, 0x0800, 0x9090, + }, + }, + { /* 75 Mhz */ + .clock = 75000, + .settings = { + 0x0104, 0x0000, 0x1041, 0x0042, 0x0080, + 0x03e8, 0x2001, 0x23e9, 0x0100, 0x9890, + }, + }, + { /* 74.25 Mhz */ + .clock = 74250, + .settings = { + 0x0186, 0x0000, 0x2146, 0x0619, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x8090, + }, + }, + { /* 65 Mhz */ + .clock = 65000, + .settings = { + 0x0145, 0x0000, 0x0082, 0x0187, 0x0080, + 0x02ee, 0x7c01, 0x7fe9, 0x0800, 0x9090, + }, + }, + { /* 57.284 Mhz */ + .clock = 57284, + .settings = { + 0x0208, 0x0000, 0x0186, 0x06dc, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x8090, + }, + }, + { /* 50 Mhz */ + .clock = 50000, + .settings = { + 0x0186, 0x0000, 0x1041, 0x0042, 0x0080, + 0x03e8, 0x2001, 0x23e9, 0x0100, 0x9890, + }, + }, + { /* 49.5 Mhz */ + .clock = 49500, + .settings = { + 0x02cb, 0x0000, 0x2105, 0x0619, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x8090, + }, + }, + { /* 40 Mhz */ + .clock = 40000, + .settings = { + 0x01c8, 0x0080, 0x1041, 0x0042, 0x0080, + 0x03e8, 0x2001, 0x23e9, 0x0100, 0x9890, + }, + }, + { /* 36 Mhz */ + .clock = 36000, + .settings = { + 0x030d, 0x0080, 0x0041, 0x0105, 0x0080, + 0x03e8, 0x6401, 0x67e9, 0x0100, 0x9090, + }, + }, + { /* 31.5 Mhz */ + .clock = 31500, + .settings = { + 0x030d, 0x0080, 0x0208, 0x07e0, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x8090, + }, + }, + { /* 30.24 Mhz */ + .clock = 30240, + .settings = { + 0x038f, 0x0080, 0x2187, 0x071d, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x8090, + }, + }, + { /* 28.32 Mhz */ + .clock = 28320, + .settings = { + 0x030d, 0x0080, 0x2187, 0x05d7, 0x0000, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x1090, + }, + + }, + { /* 27 Mhz */ + .clock = 27000, + .settings = { + 0x0514, 0x0000, 0x2083, 0x034e, 0x0080, + 0x015e, 0x7c01, 0x7fe9, 0x0100, 0x8090, + }, + }, + { /* 25.2 MHz */ + .clock = 25200, + .settings = { + 0x030d, 0x0080, 0x028a, 0x07e0, 0x0080, + 0x00fa, 0x7c01, 0x7fe9, 0x0800, 0x8090, + }, + }, + { /* 25.175 Mhz */ + .clock = 25175, + .settings = { + 0x034d, 0x0000, 0x2146, 0x0492, 0x0000, + 0x0113, 0x7c01, 0x7fe9, 0x0100, 0x8090, + }, + }, + { /* 13.5 MHz */ + .clock = 13500, + .settings = { + 0x0a28, 0x0000, 0x2083, 0x034e, 0x0080, + 0x015e, 0x7c01, 0x7fe9, 0x0100, 0x8090, + }, + }, +}; + +static const struct analog_drm_crtc_clock_setting *analog_drm_encoder_closest_clock(long clock) +{ + const struct analog_drm_crtc_clock_setting *best_setting = NULL; + long best_diff, diff; + unsigned int i; + + best_diff = LONG_MAX; + + for (i = 0; i < ARRAY_SIZE(clock_settings); ++i) { + diff = abs(clock_settings[i].clock - clock); + if (diff < best_diff) { + best_diff = diff; + best_setting = &clock_settings[i]; + } + } + + return best_setting; +} + +static bool analog_drm_encoder_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) +{ + struct drm_encoder_slave_funcs *sfuncs = get_slave_funcs(encoder); + + if (sfuncs && sfuncs->mode_fixup) + return sfuncs->mode_fixup(encoder, mode, adjusted_mode); + + return true; +} + +static void analog_drm_write_clock_reg(struct analog_drm_private *private, + unsigned int reg, unsigned int val) +{ + iowrite32(val, private->base_clock + reg); +} + +#define ANALOG_CLOCK_REG_UPDATE_ENABLE 0x04 +#define ANALOG_CLOCK_REG_CONFIG(x) (0x08 + (0x04 * x)) + +static int analog_drm_encoder_set_clock(struct analog_drm_private *private, long clock) +{ + const struct analog_drm_crtc_clock_setting *best_setting; + unsigned int i; + + best_setting = analog_drm_encoder_closest_clock(clock); + + if (!best_setting) + return -EINVAL; + + printk("setting clock to: %lu\n", best_setting->clock); + + analog_drm_write_clock_reg(private, ANALOG_CLOCK_REG_UPDATE_ENABLE, 0); + + for (i = 0; i < 10; ++i) { + analog_drm_write_clock_reg(private, ANALOG_CLOCK_REG_CONFIG(i), + best_setting->settings[i]); + } + + analog_drm_write_clock_reg(private, ANALOG_CLOCK_REG_UPDATE_ENABLE, 1); + + return 0; +} + +static void analog_drm_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) +{ + struct drm_encoder_slave_funcs *sfuncs = get_slave_funcs(encoder); + struct analog_drm_private *private = encoder->dev->dev_private; + unsigned int h_de_min, h_de_max; + unsigned int v_de_min, v_de_max; + unsigned int htotal, hactive; + unsigned int vtotal, vactive; + + if (sfuncs && sfuncs->mode_set) + sfuncs->mode_set(encoder, mode, adjusted_mode); + + htotal = mode->htotal; + hactive = mode->hdisplay; + vtotal = mode->vtotal; + vactive = mode->vdisplay; + + hactive = mode->hsync_end - mode->hsync_start; + vactive = mode->vsync_end - mode->vsync_start; + + h_de_min = htotal - mode->hsync_start; + h_de_max = h_de_min + mode->hdisplay; + v_de_min = vtotal - mode->vsync_start; + v_de_max = v_de_min + mode->vdisplay; + + iowrite32((hactive << 16) | htotal, private->base + ANALOG_REG_HTIMING1); + iowrite32((h_de_min << 16) | h_de_max, private->base + ANALOG_REG_HTIMING2); + iowrite32((vactive << 16) | vtotal, private->base + ANALOG_REG_VTIMING1); + iowrite32((v_de_min << 16) | v_de_max, private->base + ANALOG_REG_VTIMING2); + + analog_drm_encoder_set_clock(private, mode->clock); +} + +static void analog_drm_encoder_commit(struct drm_encoder *encoder) +{ + analog_drm_encoder_dpms(encoder, DRM_MODE_DPMS_ON); +} + +static void analog_drm_encoder_prepare(struct drm_encoder *encoder) +{ + analog_drm_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); +} + +static struct drm_crtc *analog_drm_encoder_get_crtc(struct drm_encoder *encoder) +{ + return encoder->crtc; +} + +static struct drm_encoder_helper_funcs analog_encoder_helper_funcs = { + .dpms = analog_drm_encoder_dpms, + .mode_fixup = analog_drm_encoder_mode_fixup, + .mode_set = analog_drm_encoder_mode_set, + .prepare = analog_drm_encoder_prepare, + .commit = analog_drm_encoder_commit, + .get_crtc = analog_drm_encoder_get_crtc, +}; + +static void analog_drm_encoder_destroy(struct drm_encoder *encoder) +{ + struct drm_encoder_slave_funcs *sfuncs = get_slave_funcs(encoder); + struct analog_drm_encoder *analog_encoder = + to_analog_encoder(encoder); + + if (sfuncs && sfuncs->destroy) + sfuncs->destroy(encoder); + + drm_encoder_cleanup(encoder); + encoder->dev->mode_config.num_encoder--; + kfree(analog_encoder); +} + +static struct drm_encoder_funcs analog_encoder_funcs = { + .destroy = analog_drm_encoder_destroy, +}; + +static struct i2c_board_info fmc_adv7511_encoder_info[] = { + { + I2C_BOARD_INFO("adv7511", 0x39), + }, + { } +}; + +struct drm_encoder *analog_drm_encoder_create(struct drm_device *dev) +{ + struct drm_encoder *encoder; + struct drm_connector *connector; + struct analog_drm_encoder *analog_encoder; + struct analog_drm_private *priv = dev->dev_private; + + analog_encoder = kzalloc(sizeof(*analog_encoder), GFP_KERNEL); + if (!analog_encoder) { + DRM_ERROR("failed to allocate encoder\n"); + return NULL; + } + + encoder = &analog_encoder->encoder.base; + encoder->possible_crtcs = 1; + + drm_encoder_init(dev, encoder, &analog_encoder_funcs, + DRM_MODE_ENCODER_TMDS); + drm_encoder_helper_add(encoder, &analog_encoder_helper_funcs); + + drm_i2c_encoder_init(dev, to_encoder_slave(encoder), + priv->slave_adapter, + fmc_adv7511_encoder_info); + + connector = &analog_encoder->connector; + + analog_drm_connector_init(dev, connector, encoder); + + analog_encoder->regset.base = priv->base; + analog_encoder->regset.regs = analog_drm_encoder_debugfs_regs; + analog_encoder->regset.nregs = ARRAY_SIZE(analog_drm_encoder_debugfs_regs); + debugfs_create_regset32(dev_name(dev->dev), S_IRUGO, NULL, &analog_encoder->regset); + debugfs_create_file("color_pattern", 0666, NULL, priv, &fops_cp); + + return encoder; +} + +static struct i2c_adapter *analog_drm_get_ddc_adapter(struct drm_device *dev) +{ + struct analog_drm_private *priv = dev->dev_private; + + return priv->ddc_adapter; +} + +static int analog_drm_connector_get_modes(struct drm_connector *connector) +{ + struct drm_encoder *encoder = connector_to_encoder(connector); + struct drm_encoder_slave_funcs *sfuncs = get_slave_funcs(encoder); + struct i2c_adapter *adapter = analog_drm_get_ddc_adapter(connector->dev); + struct edid *edid; + int count = 0; + + + kfree(connector->display_info.raw_edid); + connector->display_info.raw_edid = NULL; + + if (adapter) { + edid = drm_get_edid(connector, adapter); + drm_mode_connector_update_edid_property(connector, + edid); + count += drm_add_edid_modes(connector, edid); + } else { + if (sfuncs && sfuncs->get_modes) + count += sfuncs->get_modes(encoder, connector); + } + + return count; +} + +static int analog_drm_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + const struct analog_drm_crtc_clock_setting *best_setting; + + if (mode->clock > 165000) + return MODE_CLOCK_HIGH; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + return MODE_NO_INTERLACE; + + return MODE_OK; +} + +static struct drm_encoder *analog_drm_best_encoder(struct drm_connector *connector) +{ + return connector_to_encoder(connector); +} + +static struct drm_connector_helper_funcs analog_connector_helper_funcs = { + .get_modes = analog_drm_connector_get_modes, + .mode_valid = analog_drm_connector_mode_valid, + .best_encoder = analog_drm_best_encoder, +}; + +static enum drm_connector_status +analog_drm_connector_detect(struct drm_connector *connector, bool force) +{ + enum drm_connector_status status = connector_status_unknown; + struct drm_encoder *encoder = connector_to_encoder(connector); + struct drm_encoder_slave_funcs *sfuncs = get_slave_funcs(encoder); + struct i2c_adapter *adapter = analog_drm_get_ddc_adapter(connector->dev); + struct edid *edid; + + if (adapter) { + kfree(connector->display_info.raw_edid); + connector->display_info.raw_edid = NULL; + + edid = drm_get_edid(connector, adapter); + if (edid) + status = connector_status_connected; + else + status = connector_status_disconnected; + } + + if (sfuncs && sfuncs->detect) + status = sfuncs->detect(encoder, connector); + + return status; +} + +static void analog_drm_connector_destroy(struct drm_connector *connector) +{ + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); +} + +static struct drm_connector_funcs analog_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = analog_drm_connector_detect, + .destroy = analog_drm_connector_destroy, +}; + +static int analog_drm_connector_init(struct drm_device *dev, + struct drm_connector *connector, struct drm_encoder *encoder) +{ + int type; + int err; + + type = DRM_MODE_CONNECTOR_HDMIA; + connector->polled = DRM_CONNECTOR_POLL_CONNECT | + DRM_CONNECTOR_POLL_DISCONNECT; + + drm_connector_init(dev, connector, &analog_connector_funcs, type); + drm_connector_helper_add(connector, &analog_connector_helper_funcs); + + err = drm_sysfs_connector_add(connector); + if (err) + goto err_connector; + + connector->encoder = encoder; + + err = drm_mode_connector_attach_encoder(connector, encoder); + if (err) { + DRM_ERROR("failed to attach a connector to a encoder\n"); + goto err_sysfs; + } + + return 0; + +err_sysfs: + drm_sysfs_connector_remove(connector); +err_connector: + drm_connector_cleanup(connector); + return err; +} diff --git a/drivers/gpu/drm/analog/analog_drm_encoder.h b/drivers/gpu/drm/analog/analog_drm_encoder.h new file mode 100644 index 0000000000000..575903b71789f --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_encoder.h @@ -0,0 +1,6 @@ +#ifndef _ANALOG_DRM_ENCODER_H_ +#define _ANALOG_DRM_ENCODER_H_ + +struct drm_encoder *analog_drm_encoder_create(struct drm_device *dev); + +#endif diff --git a/drivers/gpu/drm/analog/analog_drm_fbdev.c b/drivers/gpu/drm/analog/analog_drm_fbdev.c new file mode 100644 index 0000000000000..bf15d03b3532f --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_fbdev.c @@ -0,0 +1,338 @@ +#include +#include +#include +#include +#include + +#include "analog_drm_drv.h" +#include "analog_drm_gem.h" + +#define MAX_CONNECTOR 1 +#define PREFERRED_BPP 32 + +#define to_analog_fbdev(x) container_of(x, struct analog_drm_fbdev,\ + fb_helper) + +#define to_analog_fb(x) container_of(x, struct analog_drm_fb,\ + fb) + +struct analog_drm_fb { + struct drm_framebuffer fb; + struct analog_drm_gem_obj *obj; +}; + +struct analog_drm_fbdev { + struct drm_fb_helper fb_helper; + struct analog_drm_fb *fb; +}; + +static void analog_drm_fb_destroy(struct drm_framebuffer *fb) +{ + struct analog_drm_fb *afb = to_analog_fb(fb); + + if (afb->obj) + drm_gem_object_unreference_unlocked(&afb->obj->base); + + drm_framebuffer_cleanup(fb); + kfree(afb); +} + +static int analog_drm_fb_create_handle(struct drm_framebuffer *fb, + struct drm_file *file_priv, unsigned int *handle) +{ + struct analog_drm_fb *afb = to_analog_fb(fb); + + return drm_gem_handle_create(file_priv, + &afb->obj->base, handle); +} + +static struct drm_framebuffer_funcs analog_drm_fb_funcs = { + .destroy = analog_drm_fb_destroy, + .create_handle = analog_drm_fb_create_handle, +}; + +static struct analog_drm_fb *analog_drm_fb_alloc(struct drm_device *dev, + struct drm_mode_fb_cmd2 *mode_cmd, struct analog_drm_gem_obj *obj) +{ + struct analog_drm_fb *afb; + int ret; + + afb = kzalloc(sizeof(*afb), GFP_KERNEL); + if (!afb) + return ERR_PTR(-ENOMEM); + + afb->obj = obj; + ret = drm_framebuffer_init(dev, &afb->fb, &analog_drm_fb_funcs); + if (ret) { + DRM_ERROR("failed to initialize framebuffer.\n"); + return ERR_PTR(ret); + } + + drm_helper_mode_fill_fb_struct(&afb->fb, mode_cmd); + + return afb; +} + +static struct drm_framebuffer *analog_drm_fb_create(struct drm_device *dev, + struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd) +{ + struct analog_drm_fb *afb; + struct drm_gem_object *obj; + + obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); + if (!obj) { + DRM_ERROR("failed to lookup gem object.\n"); + return ERR_PTR(-ENXIO); + } + + afb = analog_drm_fb_alloc(dev, mode_cmd, to_analog_gem_obj(obj)); + if (IS_ERR(afb)) + return ERR_CAST(afb); + + return &afb->fb; +} + +struct analog_drm_gem_obj *analog_drm_fb_get_gem_obj(struct drm_framebuffer *fb) +{ + struct analog_drm_fb *afb = to_analog_fb(fb); + + return afb->obj; +} + +static void analog_drm_output_poll_changed(struct drm_device *dev) +{ + struct analog_drm_private *private = dev->dev_private; + + if (private->fbdev) + drm_fb_helper_hotplug_event(&private->fbdev->fb_helper); +} + +static struct drm_mode_config_funcs analog_drm_mode_config_funcs = { + .fb_create = analog_drm_fb_create, + .output_poll_changed = analog_drm_output_poll_changed, +}; + +void analog_drm_mode_config_init(struct drm_device *dev) +{ + dev->mode_config.min_width = 0; + dev->mode_config.min_height = 0; + + /* + * set max width and height as default value(4096x4096). + * this value would be used to check framebuffer size limitation + * at drm_mode_addfb(). + */ + dev->mode_config.max_width = 4096; + dev->mode_config.max_height = 4096; + + dev->mode_config.funcs = &analog_drm_mode_config_funcs; +} + +static struct fb_ops analog_drm_fb_ops = { + .owner = THIS_MODULE, + .fb_fillrect = sys_fillrect, + .fb_copyarea = sys_copyarea, + .fb_imageblit = sys_imageblit, + .fb_check_var = drm_fb_helper_check_var, + .fb_set_par = drm_fb_helper_set_par, + .fb_blank = drm_fb_helper_blank, + .fb_pan_display = drm_fb_helper_pan_display, + .fb_setcmap = drm_fb_helper_setcmap, +}; + +static int analog_drm_fbdev_create(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + struct analog_drm_fbdev *afbdev = to_analog_fbdev(helper); + struct drm_mode_fb_cmd2 mode_cmd = { 0 }; + struct drm_device *dev = helper->dev; + struct analog_drm_gem_obj *obj; + struct drm_framebuffer *fb; + unsigned long offset; + struct fb_info *fbi; + size_t size; + int ret; + + DRM_DEBUG_KMS("%s\n", __FILE__); + + DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n", + sizes->surface_width, sizes->surface_height, + sizes->surface_bpp); + + sizes->surface_bpp = 32; + mode_cmd.width = sizes->surface_width; + mode_cmd.height = sizes->surface_height; + mode_cmd.pitches[0] = sizes->surface_width * (sizes->surface_bpp >> 3); + mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, + sizes->surface_depth); + + size = mode_cmd.pitches[0] * mode_cmd.height; + obj = analog_drm_gem_alloc(dev, size); + if (!obj) + return -ENOMEM; + + fbi = framebuffer_alloc(0, dev->dev); + if (!fbi) { + DRM_ERROR("failed to allocate fb info.\n"); + ret = -ENOMEM; + goto out; + } + + afbdev->fb = analog_drm_fb_alloc(dev, &mode_cmd, obj); + if (IS_ERR(afbdev->fb)) { + DRM_ERROR("failed to create drm framebuffer.\n"); + ret = PTR_ERR(afbdev->fb); + goto out; + } + + fb = &afbdev->fb->fb; + helper->fb = fb; + helper->fbdev = fbi; + + fbi->par = helper; + fbi->flags = FBINFO_FLAG_DEFAULT; + fbi->fbops = &analog_drm_fb_ops; + + ret = fb_alloc_cmap(&fbi->cmap, 256, 0); + if (ret) { + DRM_ERROR("failed to allocate cmap.\n"); + goto out; + } + + drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); + drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height); + + offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3); + offset += fbi->var.yoffset * fb->pitches[0]; + + dev->mode_config.fb_base = (resource_size_t)obj->dma_addr; + fbi->screen_base = obj->addr + offset; + fbi->fix.smem_start = (unsigned long)(obj->dma_addr + offset); + fbi->screen_size = size; + fbi->fix.smem_len = size; + + return 0; + +/* TODO: gem obj, free fb */ +out: + return ret; +} + +static int analog_drm_fbdev_probe(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + int ret = 0; + + if (!helper->fb) { + ret = analog_drm_fbdev_create(helper, sizes); + if (ret < 0) { + DRM_ERROR("failed to create fbdev.\n"); + return ret; + } + + /* + * fb_helper expects a value more than 1 if succeed + * because register_framebuffer() should be called. + */ + ret = 1; + } + + + printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__); + return ret; +} + +static struct drm_fb_helper_funcs analog_drm_fb_helper_funcs = { + .fb_probe = analog_drm_fbdev_probe, +}; + +int analog_drm_fbdev_init(struct drm_device *dev) +{ + struct analog_drm_fbdev *afbdev; + struct analog_drm_private *private = dev->dev_private; + struct drm_fb_helper *helper; + int ret; + + DRM_DEBUG_KMS("%s\n", __FILE__); + + afbdev = kzalloc(sizeof(*afbdev), GFP_KERNEL); + if (!afbdev) { + DRM_ERROR("failed to allocate drm fbdev.\n"); + return -ENOMEM; + } + + afbdev->fb_helper.funcs = &analog_drm_fb_helper_funcs; + private->fbdev = afbdev; + helper = &afbdev->fb_helper; + + ret = drm_fb_helper_init(dev, helper, 1, 1); + if (ret < 0) { + DRM_ERROR("failed to initialize drm fb helper.\n"); + goto err_init; + } + + ret = drm_fb_helper_single_add_all_connectors(helper); + if (ret < 0) { + DRM_ERROR("failed to register drm_fb_helper_connector.\n"); + goto err_setup; + + } + + ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP); + if (ret < 0) { + DRM_ERROR("failed to set up hw configuration.\n"); + goto err_setup; + } + + return 0; + +err_setup: + drm_fb_helper_fini(helper); + +err_init: + private->fbdev = NULL; + kfree(afbdev); + + return ret; +} + +void analog_drm_fbdev_fini(struct drm_device *dev) +{ + struct analog_drm_private *private = dev->dev_private; + struct analog_drm_fbdev *afbdev; + + if (!private || !private->fbdev) + return; + + afbdev = private->fbdev; + + private->fbdev = NULL; + + if (afbdev->fb_helper.fbdev) { + struct fb_info *info; + int ret; + + info = afbdev->fb_helper.fbdev; + ret = unregister_framebuffer(info); + if (ret < 0) + DRM_DEBUG_KMS("failed unregister_framebuffer()\n"); + + if (info->cmap.len) + fb_dealloc_cmap(&info->cmap); + + framebuffer_release(info); + } + + drm_fb_helper_fini(&afbdev->fb_helper); + kfree(afbdev); +} + +void analog_drm_fbdev_restore_mode(struct drm_device *dev) +{ + struct analog_drm_private *private = dev->dev_private; + + if (!private || !private->fbdev) + return; + + drm_fb_helper_restore_fbdev_mode(&private->fbdev->fb_helper); +} diff --git a/drivers/gpu/drm/analog/analog_drm_fbdev.h b/drivers/gpu/drm/analog/analog_drm_fbdev.h new file mode 100644 index 0000000000000..4732524c199b5 --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_fbdev.h @@ -0,0 +1,12 @@ +#ifndef _ANALOG_DRM_FBDEV_H_ +#define _ANALOG_DRM_FBDEV_H_ + +int analog_drm_fbdev_init(struct drm_device *dev); +void analog_drm_fbdev_fini(struct drm_device *dev); +void analog_drm_fbdev_restore_mode(struct drm_device *dev); + +void analog_drm_mode_config_init(struct drm_device *dev); + +struct analog_drm_gem_obj *analog_drm_fb_get_gem_obj(struct drm_framebuffer *fb); + +#endif diff --git a/drivers/gpu/drm/analog/analog_drm_gem.c b/drivers/gpu/drm/analog/analog_drm_gem.c new file mode 100644 index 0000000000000..ed7cd929f03d9 --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_gem.c @@ -0,0 +1,242 @@ +#include +#include + +#include + +#include "analog_drm_drv.h" +#include "analog_drm_gem.h" + +static unsigned int convert_to_vm_err_msg(int msg) +{ + unsigned int out_msg; + + switch (msg) { + case 0: + case -ERESTARTSYS: + case -EINTR: + out_msg = VM_FAULT_NOPAGE; + break; + + case -ENOMEM: + out_msg = VM_FAULT_OOM; + break; + + default: + out_msg = VM_FAULT_SIGBUS; + break; + } + + return out_msg; +} + +static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj) +{ + DRM_DEBUG_KMS("%s\n", __FILE__); + + return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT; +} + +struct analog_drm_gem_obj *analog_drm_gem_alloc(struct drm_device *dev, + size_t size) +{ + struct analog_drm_gem_obj *analog_gem_obj; + struct drm_gem_object *obj; + dma_addr_t dma_addr; + void *addr; + int ret; + + size = roundup(size, PAGE_SIZE); + + addr = dma_alloc_writecombine(dev->dev, size, &dma_addr, GFP_KERNEL); + if (!addr) + return ERR_PTR(-ENOMEM); + + analog_gem_obj = kzalloc(sizeof(*analog_gem_obj), GFP_KERNEL); + if (!analog_gem_obj) { + DRM_ERROR("failed to allocate analog gem object.\n"); + ret = -ENOMEM; + goto err_alloc; + } + + analog_gem_obj->addr = addr; + analog_gem_obj->dma_addr = dma_addr; + + obj = &analog_gem_obj->base; + + ret = drm_gem_object_init(dev, obj, size); + if (ret < 0) { + DRM_ERROR("failed to initialize gem object.\n"); + ret = -EINVAL; + goto err_object_init; + } + + return analog_gem_obj; + +err_object_init: + kfree(analog_gem_obj); +err_alloc: + dma_free_coherent(dev->dev, size, addr, dma_addr); + + return ERR_PTR(ret); +} + +static struct analog_drm_gem_obj *analog_drm_gem_create(struct drm_device *dev, + struct drm_file *file, unsigned int *handle, unsigned long size) +{ + struct analog_drm_gem_obj *obj; + int ret; + + obj = analog_drm_gem_alloc(dev, size); + if (IS_ERR(obj)) + return obj; + + ret = drm_gem_handle_create(file, &obj->base, handle); + if (ret) { + drm_gem_object_release(&obj->base); + kfree(obj); + return ERR_PTR(ret); + } + + drm_gem_object_unreference(&obj->base); + return 0; +} + +void analog_drm_gem_free_object(struct drm_gem_object *gem_obj) +{ + struct analog_drm_gem_obj *analog_gem_obj = to_analog_gem_obj(gem_obj); + + DRM_DEBUG_KMS("%s\n", __FILE__); + + DRM_DEBUG_KMS("handle count = %d\n", + atomic_read(&gem_obj->handle_count)); + + if (gem_obj->map_list.map) + drm_gem_free_mmap_offset(gem_obj); + + /* release file pointer to gem object. */ + drm_gem_object_release(gem_obj); + + + dma_free_coherent(gem_obj->dev->dev, analog_gem_obj->base.size, + analog_gem_obj->addr, analog_gem_obj->dma_addr); + + kfree(analog_gem_obj); +} + +int analog_drm_gem_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, struct drm_mode_create_dumb *args) +{ + struct analog_drm_gem_obj *analog_gem_obj; + + args->pitch = args->width * args->bpp >> 3; + args->size = args->pitch * args->height; + + analog_gem_obj = analog_drm_gem_create(dev, file_priv, &args->handle, + args->size); + if (IS_ERR(analog_gem_obj)) + return PTR_ERR(analog_gem_obj); + + return 0; +} + +int analog_drm_gem_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, uint64_t *offset) +{ + struct analog_drm_gem_obj *analog_gem_obj; + struct drm_gem_object *obj; + int ret = 0; + + DRM_DEBUG_KMS("%s\n", __FILE__); + + mutex_lock(&dev->struct_mutex); + + obj = drm_gem_object_lookup(dev, file_priv, handle); + if (!obj) { + DRM_ERROR("failed to lookup gem object.\n"); + mutex_unlock(&dev->struct_mutex); + return -EINVAL; + } + + if (!obj->map_list.map) { + ret = drm_gem_create_mmap_offset(obj); + if (ret) + goto out; + } + + analog_gem_obj = to_analog_gem_obj(obj); + + *offset = get_gem_mmap_offset(&analog_gem_obj->base); + DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset); + +out: + drm_gem_object_unreference(obj); + + + mutex_unlock(&dev->struct_mutex); + + return ret; +} + +int analog_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct drm_gem_object *obj = vma->vm_private_data; + struct analog_drm_gem_obj *analog_gem_obj = to_analog_gem_obj(obj); + struct drm_device *dev = obj->dev; + unsigned int i, page_num; + unsigned long address; + unsigned long pfn; + pgoff_t page_offset; + int ret = 0; + + page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + page_offset = ((unsigned long)vmf->virtual_address - + vma->vm_start) >> PAGE_SHIFT; + + mutex_lock(&dev->struct_mutex); + + pfn = (((unsigned long)analog_gem_obj->dma_addr) >> + PAGE_SHIFT) + page_offset; + + address = (unsigned long)vmf->virtual_address; + + for (i = 0; i < page_num; i++) { + ret = vm_insert_mixed(vma, address, pfn); + if (ret == -EBUSY || (ret != 0 && i > 0)) + break; + else if (ret) + return (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS; + address += PAGE_SIZE; + pfn++; + } + + mutex_unlock(&dev->struct_mutex); + + return convert_to_vm_err_msg(ret); +} + +int analog_drm_gem_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, unsigned int handle) +{ + return drm_gem_handle_delete(file_priv, handle); +} + +int analog_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) +{ + int ret; + + DRM_DEBUG_KMS("%s\n", __FILE__); + + /* set vm_area_struct. */ + ret = drm_gem_mmap(filp, vma); + if (ret < 0) { + DRM_ERROR("failed to mmap.\n"); + return ret; + } + + vma->vm_flags &= ~VM_PFNMAP; + vma->vm_flags |= VM_MIXEDMAP; + + return ret; +} + +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/analog/analog_drm_gem.h b/drivers/gpu/drm/analog/analog_drm_gem.h new file mode 100644 index 0000000000000..68a0b26063ae1 --- /dev/null +++ b/drivers/gpu/drm/analog/analog_drm_gem.h @@ -0,0 +1,52 @@ +#ifndef _ANALOG_DRM_GEM_H_ +#define _ANALOG_DRM_GEM_H_ + +#define to_analog_gem_obj(x) container_of(x,\ + struct analog_drm_gem_obj, base) + +/* + * analog drm buffer structure. + * + * @base: a gem object. + * - a new handle to this gem object would be created + * by drm_gem_handle_create(). + * @addr: kernel virtual address to allocated memory region. + * @dma_addr: bus address(accessed by dma) to allocated memory region. + * - this address could be physical address without IOMMU and + * device address with IOMMU. + * + */ +struct analog_drm_gem_obj { + struct drm_gem_object base; + void *addr; + dma_addr_t dma_addr; +}; + +struct analog_drm_gem_obj *analog_drm_gem_alloc(struct drm_device *dev, + size_t size); + +/* free gem object. */ +void analog_drm_gem_free_object(struct drm_gem_object *gem_obj); + +/* create memory region for drm framebuffer. */ +int analog_drm_gem_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, struct drm_mode_create_dumb *args); + +/* map memory region for drm framebuffer to user space. */ +int analog_drm_gem_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, uint64_t *offset); + +/* page fault handler and mmap fault address(virtual) to physical memory. */ +int analog_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); + +/* + * destroy memory region allocated. + * - a gem handle and physical memory region pointed by a gem object + * would be released by drm_gem_handle_delete(). + */ +int analog_drm_gem_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, unsigned int handle); + +int analog_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); + +#endif From 146fcb01d7a024a54c00d27ce0168e7d68f24a33 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 27 Apr 2012 11:13:01 +0200 Subject: [PATCH 043/261] DRM: Enabled debugging by default Enable DRM debugging by default for now. --- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/drm_stub.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index a6f09e19b8c29..4cb65096c9d13 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -2,7 +2,7 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -ccflags-y := -Iinclude/drm +ccflags-y := -Iinclude/drm -DDEBUG drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ drm_context.o drm_dma.o \ diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 6d7b083c5b776..85fc436187808 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -37,7 +37,7 @@ #include "drmP.h" #include "drm_core.h" -unsigned int drm_debug = 0; /* 1 to enable debug output */ +unsigned int drm_debug = 0xff; /* 1 to enable debug output */ EXPORT_SYMBOL(drm_debug); unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */ From 7b70b3c7cfc3d1af3948de2e07a0cc602afbf2ac Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 6 Feb 2012 10:08:32 +0100 Subject: [PATCH 044/261] ASoC: Add dmaengine PCM helper functions This patch adds a set of functions which are intended to be used when implementing a dmaengine based sound PCM driver. Signed-off-by: Lars-Peter Clausen --- include/sound/dmaengine_pcm.h | 47 ++++++ sound/soc/Kconfig | 3 + sound/soc/Makefile | 3 + sound/soc/soc-dmaengine-pcm.c | 281 ++++++++++++++++++++++++++++++++++ 4 files changed, 334 insertions(+) create mode 100644 include/sound/dmaengine_pcm.h create mode 100644 sound/soc/soc-dmaengine-pcm.c diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h new file mode 100644 index 0000000000000..129783da65876 --- /dev/null +++ b/include/sound/dmaengine_pcm.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#ifndef __SOUND_DMAENGINE_PCM_H__ +#define __SOUND_DMAENGINE_PCM_H__ + +#include +#include + +/** + * snd_pcm_substream_to_dma_direction - Get dma_transfer_direction for a PCM + * substream + * @substream: PCM substream + */ +static inline enum dma_transfer_direction +snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream) +{ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return DMA_MEM_TO_DEV; + else + return DMA_DEV_TO_MEM; +} + +void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data); +void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream); + +int snd_soc_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config); +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream); + +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data); +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream); + +#endif diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 35e662d270e61..91c985599d32c 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -25,6 +25,9 @@ if SND_SOC config SND_SOC_AC97_BUS bool +config SND_SOC_DMAENGINE_PCM + bool + # All the supported SoCs source "sound/soc/atmel/Kconfig" source "sound/soc/au1x/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 9ea8ac827adc3..2feaf376e94b2 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,6 +1,9 @@ snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o snd-soc-core-objs += soc-pcm.o soc-io.o +snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o +obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o + obj-$(CONFIG_SND_SOC) += snd-soc-core.o obj-$(CONFIG_SND_SOC) += codecs/ obj-$(CONFIG_SND_SOC) += atmel/ diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c new file mode 100644 index 0000000000000..643147ef885fe --- /dev/null +++ b/sound/soc/soc-dmaengine-pcm.c @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Based on: + * imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer + * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc. + * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek + * Copyright (C) 2006 Applied Data Systems + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include + +struct dmaengine_pcm_runtime_data { + struct dma_chan *dma_chan; + + unsigned int pos; + + void *data; +}; + +static inline struct dmaengine_pcm_runtime_data *substream_to_prtd( + const struct snd_pcm_substream *substream) +{ + return substream->runtime->private_data; +} + +/** + * snd_dmaengine_pcm_set_data - Set dmaengine substream private data + * @substream: PCM substream + * @data: Data to set + */ +void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + prtd->data = data; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_data); + +/** + * snd_dmaengine_pcm_get_data - Get dmaeinge substream private data + * @substream: PCM substream + * + * Returns the data previously set with snd_dmaengine_pcm_set_data + */ +void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + return prtd->data; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_data); + +/** + * snd_soc_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config + * @substream: PCM substream + * @params: hw_params + * @slave_config: DMA slave config + * + * This function can be used to initialize a dma_slave_config from a substream + * and hw_params in a dmaengine based PCM driver implementation. + */ +int snd_soc_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, + const struct snd_pcm_hw_params *params, + struct dma_slave_config *slave_config) +{ + enum dma_slave_buswidth buswidth; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; + break; + case SNDRV_PCM_FORMAT_S16_LE: + buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; + break; + case SNDRV_PCM_FORMAT_S18_3LE: + case SNDRV_PCM_FORMAT_S20_3LE: + case SNDRV_PCM_FORMAT_S24_LE: + case SNDRV_PCM_FORMAT_S32_LE: + buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; + break; + default: + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config->direction = DMA_MEM_TO_DEV; + slave_config->dst_addr_width = buswidth; + } else { + slave_config->direction = DMA_DEV_TO_MEM; + slave_config->src_addr_width = buswidth; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_hwparams_to_dma_slave_config); + +static void dmaengine_pcm_dma_complete(void *arg) +{ + struct snd_pcm_substream *substream = arg; + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + prtd->pos += snd_pcm_lib_period_bytes(substream); + if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream)) + prtd->pos = 0; + + snd_pcm_period_elapsed(substream); +} + +static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct dma_chan *chan = prtd->dma_chan; + struct dma_async_tx_descriptor *desc; + enum dma_transfer_direction direction; + + direction = snd_pcm_substream_to_dma_direction(substream); + + prtd->pos = 0; + + desc = chan->device->device_prep_dma_cyclic(chan, + substream->runtime->dma_addr, + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream), direction); + + if (!desc) + return -ENOMEM; + + desc->callback = dmaengine_pcm_dma_complete; + desc->callback_param = substream; + dmaengine_submit(desc); + + return 0; +} + +/** + * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation + * @substream: PCM substream + * @cmd: Trigger command + * + * Returns 0 on success, a negative error code otherwise. + * + * This function can be used as the PCM trigger callback for dmaengine based PCM + * driver implementations. + */ +int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + int ret; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + ret = dmaengine_pcm_prepare_and_submit(substream); + if (ret) + return ret; + dma_async_issue_pending(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + dmaengine_resume(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + dmaengine_pause(prtd->dma_chan); + break; + case SNDRV_PCM_TRIGGER_STOP: + dmaengine_terminate_all(prtd->dma_chan); + break; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger); + +/** + * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function can be used as the PCM pointer callback for dmaengine based PCM + * driver implementations. + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + return bytes_to_frames(substream->runtime, prtd->pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); + +static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd, + dma_filter_fn filter_fn, void *filter_data) +{ + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_CYCLIC, mask); + prtd->dma_chan = dma_request_channel(mask, filter_fn, filter_data); + + if (!prtd->dma_chan) + return -ENXIO; + + return 0; +} + +/** + * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream + * @substream: PCM substream + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * Returns 0 on success, a negative error code otherwise. + * + * This function will request a DMA channel using the passed filter function and + * data. The function should usually be called from the pcm open callback. + * + * Note that this function will use private_data field of the substream's + * runtime. So it is not availabe to your pcm driver implementation. If you need + * to keep additional data attached to a substream use + * snd_dmaeinge_pcm_{set,get}_data. + */ +int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data) +{ + struct dmaengine_pcm_runtime_data *prtd; + int ret; + + ret = snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + return ret; + + prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); + if (!prtd) + return -ENOMEM; + + ret = dmaengine_pcm_request_channel(prtd, filter_fn, filter_data); + if (ret < 0) { + kfree(prtd); + return ret; + } + + substream->runtime->private_data = prtd; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); + +/** + * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream + * @substream: PCM substream + */ +int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + + dma_release_channel(prtd->dma_chan); + kfree(prtd); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); From fec50de1edb590fd0aab60feef5e8d343cd887cd Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 6 Mar 2012 19:34:23 +0100 Subject: [PATCH 045/261] ASoC: Add support for Xilinx FPGA based boards Signed-off-by: Lars-Peter Clausen --- sound/soc/Kconfig | 1 + sound/soc/Makefile | 1 + sound/soc/xlnx/Kconfig | 4 + sound/soc/xlnx/Makefile | 3 + sound/soc/xlnx/xilinx-pcm.c | 168 ++++++++++++++++++++++++++++++++++++ 5 files changed, 177 insertions(+) create mode 100644 sound/soc/xlnx/Kconfig create mode 100644 sound/soc/xlnx/Makefile create mode 100644 sound/soc/xlnx/xilinx-pcm.c diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 91c985599d32c..ee16413b81e15 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -48,6 +48,7 @@ source "sound/soc/s6000/Kconfig" source "sound/soc/sh/Kconfig" source "sound/soc/tegra/Kconfig" source "sound/soc/txx9/Kconfig" +source "sound/soc/xlnx/Kconfig" # Supported codecs source "sound/soc/codecs/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 2feaf376e94b2..d986d00f8907d 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_SND_SOC) += s6000/ obj-$(CONFIG_SND_SOC) += sh/ obj-$(CONFIG_SND_SOC) += tegra/ obj-$(CONFIG_SND_SOC) += txx9/ +obj-$(CONFIG_SND_SOC) += xlnx/ diff --git a/sound/soc/xlnx/Kconfig b/sound/soc/xlnx/Kconfig new file mode 100644 index 0000000000000..2db90a11e2a1f --- /dev/null +++ b/sound/soc/xlnx/Kconfig @@ -0,0 +1,4 @@ +config SND_SOC_XILINX + tristate "SoC Audio for Xilinx based boards" + depends on SND_SOC && (MICROBLAZE || ARCH_ZYNQ) + select SND_SOC_DMAENGINE_PCM diff --git a/sound/soc/xlnx/Makefile b/sound/soc/xlnx/Makefile new file mode 100644 index 0000000000000..d9c6b7496c087 --- /dev/null +++ b/sound/soc/xlnx/Makefile @@ -0,0 +1,3 @@ +snd-soc-xilinx-pcm-objs := xilinx-pcm.o + +obj-$(CONFIG_SND_SOC_XILINX) += snd-soc-xilinx-pcm.o diff --git a/sound/soc/xlnx/xilinx-pcm.c b/sound/soc/xlnx/xilinx-pcm.c new file mode 100644 index 0000000000000..a9680aa471917 --- /dev/null +++ b/sound/soc/xlnx/xilinx-pcm.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static const struct snd_pcm_hardware xlnx_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER, + .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S8, + .channels_min = 1, + .channels_max = UINT_MAX, + .period_bytes_min = 1024, + .period_bytes_max = (1 << 20) - 1, + .periods_min = 2, + .periods_max = UINT_MAX, + .buffer_bytes_max = ULONG_MAX, +}; + +static int xlnx_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); +} + +struct xlnx_pcm_dma_params { + struct device_node *of_node; + int chan_id; +}; + +static bool xlnx_pcm_filter(struct dma_chan *chan, void *param) +{ + struct xlnx_pcm_dma_params *p = param; + + return chan->device->dev->of_node == p->of_node && + chan->chan_id == p->chan_id; +} + +static int xlnx_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct device *dev = rtd->platform->dev; + struct xlnx_pcm_dma_params *params = dev_get_drvdata(dev); + int ret; + + ret = snd_soc_set_runtime_hwparams(substream, &xlnx_pcm_hardware); + if (ret) + return ret; + + return snd_dmaengine_pcm_open(substream, xlnx_pcm_filter, params); +} + +static int xlnx_pcm_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_card *card = rtd->card->snd_card; + + return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, + SNDRV_DMA_TYPE_DEV, + card->dev, 8 * 1024 * 1024, + xlnx_pcm_hardware.buffer_bytes_max); +} + +static int xlnx_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + return dma_mmap_coherent(substream->pcm->card->dev, vma, + runtime->dma_area, + runtime->dma_addr, + runtime->dma_bytes); + return remap_pfn_range(vma, vma->vm_start, + substream->dma_buffer.addr >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot); +} + +static struct snd_pcm_ops xlnx_pcm_ops = { + .open = xlnx_pcm_open, + .close = snd_dmaengine_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = xlnx_pcm_hw_params, + .hw_free = snd_pcm_lib_free_pages, + .trigger = snd_dmaengine_pcm_trigger, + .pointer = snd_dmaengine_pcm_pointer, + .mmap = xlnx_pcm_mmap, +}; + +static struct snd_soc_platform_driver xlnx_pcm_soc_platform = { + .pcm_new = xlnx_pcm_new, +/* .pcm_free = snd_pcm_lib_preallocate_free_for_all,*/ + .ops = &xlnx_pcm_ops, +}; + +static int __devinit xlnx_pcm_soc_platform_probe(struct platform_device *pdev) +{ + struct xlnx_pcm_dma_params *params; + struct of_phandle_args dma_spec; + int ret; + + params = devm_kzalloc(&pdev->dev, sizeof(*params), GFP_KERNEL); + if (!params) + return -ENOMEM; + + ret = of_parse_phandle_with_args(pdev->dev.of_node, "dma-request", + "#dma-cells", 0, &dma_spec); + if (ret) + return ret; + + params->of_node = dma_spec.np; + params->chan_id = dma_spec.args[0]; + + dev_set_drvdata(&pdev->dev, params); + + return snd_soc_register_platform(&pdev->dev, &xlnx_pcm_soc_platform); +} + +static int __devexit xlnx_pcm_soc_platform_remove(struct platform_device *pdev) +{ + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static const struct of_device_id xilinx_pcm_of_match[] __devinitconst = { + { .compatible = "xilinx-pcm-audio", }, + {}, +}; +MODULE_DEVICE_TABLE(of, xilinx_pcm_of_match); + +static struct platform_driver xlnx_pcm_driver = { + .driver = { + .name = "xilinx-pcm-audio", + .owner = THIS_MODULE, + .of_match_table = xilinx_pcm_of_match, + }, + .probe = xlnx_pcm_soc_platform_probe, + .remove = __devexit_p(xlnx_pcm_soc_platform_remove), +}; +module_platform_driver(xlnx_pcm_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("Xilinx DMA engine based audio DMA driver"); +MODULE_LICENSE("GPL"); From 6c9636d2415e29311227e7ea956fec62c9463348 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 6 Mar 2012 19:23:18 +0100 Subject: [PATCH 046/261] ASoC: Add SPDIF DAI format Signed-off-by: Lars-Peter Clausen --- include/sound/soc-dai.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 2413acc54883a..ffd560e5aa15c 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -31,6 +31,7 @@ struct snd_pcm_substream; #define SND_SOC_DAIFMT_DSP_B 5 /* L data MSB during FRM LRC */ #define SND_SOC_DAIFMT_AC97 6 /* AC97 */ #define SND_SOC_DAIFMT_PDM 7 /* Pulse density modulation */ +#define SND_SOC_DAIFMT_SPDIF 8 /* SPDIF */ /* left and right justified also known as MSB and LSB respectively */ #define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J From becc9406f3e62f3191ca2cc917c28d7a0c2b346f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 6 Mar 2012 19:34:50 +0100 Subject: [PATCH 047/261] ASoC: Xilinx: Add AXI SPDIF driver Signed-off-by: Lars-Peter Clausen --- sound/soc/xlnx/Kconfig | 3 + sound/soc/xlnx/Makefile | 2 + sound/soc/xlnx/axi-spdif.c | 219 +++++++++++++++++++++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 sound/soc/xlnx/axi-spdif.c diff --git a/sound/soc/xlnx/Kconfig b/sound/soc/xlnx/Kconfig index 2db90a11e2a1f..21671714cbce9 100644 --- a/sound/soc/xlnx/Kconfig +++ b/sound/soc/xlnx/Kconfig @@ -2,3 +2,6 @@ config SND_SOC_XILINX tristate "SoC Audio for Xilinx based boards" depends on SND_SOC && (MICROBLAZE || ARCH_ZYNQ) select SND_SOC_DMAENGINE_PCM + +config SND_SOC_AXI_SPDIF + tristate diff --git a/sound/soc/xlnx/Makefile b/sound/soc/xlnx/Makefile index d9c6b7496c087..193a1d5aaff5c 100644 --- a/sound/soc/xlnx/Makefile +++ b/sound/soc/xlnx/Makefile @@ -1,3 +1,5 @@ snd-soc-xilinx-pcm-objs := xilinx-pcm.o +snd-soc-axi-spdif-objs := axi-spdif.o obj-$(CONFIG_SND_SOC_XILINX) += snd-soc-xilinx-pcm.o +obj-$(CONFIG_SND_SOC_AXI_SPDIF) += snd-soc-axi-spdif.o diff --git a/sound/soc/xlnx/axi-spdif.c b/sound/soc/xlnx/axi-spdif.c new file mode 100644 index 0000000000000..78d2a8ab28b49 --- /dev/null +++ b/sound/soc/xlnx/axi-spdif.c @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +struct axi_spdif { + void __iomem *base; + + unsigned int clock; + + struct debugfs_regset32 regset; +}; + +#define AXI_SPDIF_REG_CTRL 0x0 +#define AXI_SPDIF_REG_STAT 0x4 + +#define AXI_SPDIF_CTRL_TXDATA BIT(1) +#define AXI_SPDIF_CTRL_TXEN BIT(0) +#define AXI_SPDIF_CTRL_RATIO_OFFSET 8 +#define AXI_SPDIF_CTRL_RATIO_MASK (0xff << 8) + +static struct debugfs_reg32 axi_spdif_debugfs_regs[] = { + { "Control", AXI_SPDIF_REG_CTRL }, + { "Status", AXI_SPDIF_REG_STAT }, +}; + +static inline uint32_t axi_spdif_read(const struct axi_spdif *spdif, + unsigned int reg) +{ + return readl(spdif->base + reg); +} + +static inline void axi_spdif_write(const struct axi_spdif *spdif, + unsigned int reg, uint32_t value) +{ + writel(value, spdif->base + reg); +} + +static int axi_spdif_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai); + uint32_t ctrl = axi_spdif_read(spdif, AXI_SPDIF_REG_CTRL); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ctrl |= AXI_SPDIF_CTRL_TXDATA; + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ctrl &= ~AXI_SPDIF_CTRL_TXDATA; + break; + default: + return -EINVAL; + } + + axi_spdif_write(spdif, AXI_SPDIF_REG_CTRL, ctrl); + + return 0; +} + +static int axi_spdif_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai); + uint32_t ctrl = axi_spdif_read(spdif, AXI_SPDIF_REG_CTRL); + unsigned int ratio; + + ratio = DIV_ROUND_CLOSEST(spdif->clock, (params_rate(params) * 64 * 2)) - 1; + + ctrl &= ~AXI_SPDIF_CTRL_RATIO_MASK; + ctrl |= ratio << AXI_SPDIF_CTRL_RATIO_OFFSET; + + axi_spdif_write(spdif, AXI_SPDIF_REG_CTRL, ctrl); + + return 0; +} +/* +static int axi_spdif_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai); + uint32_t ctrl; + + if (dai->active) + return 0; + + ctrl = axi_spdif_read(spdif, AXI_SPDIF_REG_CTRL); + ctrl |= AXI_SPDIF_CTRL_TXEN; + axi_spdif_write(spdif, AXI_SPDIF_REG_CTRL, ctrl); + + return 0; +} + +static void axi_spdif_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai); + uint32_t ctrl; + + if (dai->active) + return; + + ctrl = axi_spdif_read(spdif, AXI_SPDIF_REG_CTRL); + ctrl &= ~AXI_SPDIF_CTRL_TXEN; + axi_spdif_write(spdif, AXI_SPDIF_REG_CTRL, ctrl); +} +*/ +static const struct snd_soc_dai_ops axi_spdif_dai_ops = { + .trigger = axi_spdif_trigger, + .hw_params = axi_spdif_hw_params, +}; + +static struct snd_soc_dai_driver axi_spdif_dai = { + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &axi_spdif_dai_ops, +}; + +static int __devinit axi_spdif_probe(struct platform_device *pdev) +{ + struct axi_spdif *spdif; + struct resource *res; + int ret; + + spdif = devm_kzalloc(&pdev->dev, sizeof(*spdif), GFP_KERNEL); + + if (!spdif) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + spdif->base = devm_request_and_ioremap(&pdev->dev, res); + if (!spdif->base) + return -EBUSY; + + platform_set_drvdata(pdev, spdif); + + of_property_read_u32(pdev->dev.of_node, "clock-frequency", &spdif->clock); + + ret = snd_soc_register_dai(&pdev->dev, &axi_spdif_dai); + + if (ret) { + dev_err(&pdev->dev, "Failed to register DAI\n"); + return ret; + } + + spdif->regset.base = spdif->base; + spdif->regset.regs = axi_spdif_debugfs_regs; + spdif->regset.nregs = ARRAY_SIZE(axi_spdif_debugfs_regs); + + debugfs_create_regset32(dev_name(&pdev->dev), 0777, NULL, &spdif->regset); + + axi_spdif_write(spdif, AXI_SPDIF_REG_CTRL, AXI_SPDIF_CTRL_TXEN); + + return 0; +} + +static int __devexit axi_spdif_dev_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dai(&pdev->dev); + + return 0; +} + +static const struct of_device_id axi_spdif_of_match[] __devinitconst = { + { .compatible = "adi,axi-spdif-tx-1.00.a", }, + {}, +}; +MODULE_DEVICE_TABLE(of, axi_spdif_of_match); + +static struct platform_driver axi_spdif_driver = { + .driver = { + .name = "axi-spdif", + .owner = THIS_MODULE, + .of_match_table = axi_spdif_of_match, + }, + .probe = axi_spdif_probe, + .remove = __devexit_p(axi_spdif_dev_remove), +}; +module_platform_driver(axi_spdif_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("AXI SPDIF driver"); +MODULE_LICENSE("GPL"); From 0557270edf6fe2898f07d599816352a828698d30 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 7 Mar 2012 10:09:24 +0100 Subject: [PATCH 048/261] ASoC: Xilinx: Add ADV7511 HDMI board driver Signed-off-by: Lars-Peter Clausen --- sound/soc/xlnx/Kconfig | 5 ++ sound/soc/xlnx/Makefile | 2 + sound/soc/xlnx/adv7511_hdmi.c | 90 +++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 sound/soc/xlnx/adv7511_hdmi.c diff --git a/sound/soc/xlnx/Kconfig b/sound/soc/xlnx/Kconfig index 21671714cbce9..69192fcbba0ea 100644 --- a/sound/soc/xlnx/Kconfig +++ b/sound/soc/xlnx/Kconfig @@ -5,3 +5,8 @@ config SND_SOC_XILINX config SND_SOC_AXI_SPDIF tristate + +config SND_SOC_ADV7511_HDMI + tristate "ADV7511 HDMI transmitter sound support" + depends on SND_SOC_XILINX + select SND_SOC_AXI_SPDIF diff --git a/sound/soc/xlnx/Makefile b/sound/soc/xlnx/Makefile index 193a1d5aaff5c..d758bbd0c28b4 100644 --- a/sound/soc/xlnx/Makefile +++ b/sound/soc/xlnx/Makefile @@ -1,5 +1,7 @@ snd-soc-xilinx-pcm-objs := xilinx-pcm.o snd-soc-axi-spdif-objs := axi-spdif.o +snd-soc-adv7511-hdmi-objs := adv7511_hdmi.o obj-$(CONFIG_SND_SOC_XILINX) += snd-soc-xilinx-pcm.o obj-$(CONFIG_SND_SOC_AXI_SPDIF) += snd-soc-axi-spdif.o +obj-$(CONFIG_SND_SOC_ADV7511_HDMI) += snd-soc-adv7511-hdmi.o diff --git a/sound/soc/xlnx/adv7511_hdmi.c b/sound/soc/xlnx/adv7511_hdmi.c new file mode 100644 index 0000000000000..79be998c40fd7 --- /dev/null +++ b/sound/soc/xlnx/adv7511_hdmi.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct snd_soc_dai_link hdmi_dai_link = { + .name = "HDMI", + .stream_name = "HDMI", +/* .cpu_dai_name = "75c00000.axi-spdif-tx", + .platform_name = "xilinx_pcm_audio.2",*/ + .codec_name = "adv7511.2-0039", + .codec_dai_name = "adv7511", + .dai_fmt = SND_SOC_DAIFMT_SPDIF | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, +}; + +static struct snd_soc_card hdmi_card = { + .name = "HDMI monitor", + .owner = THIS_MODULE, + .dai_link = &hdmi_dai_link, + .num_links = 1, +}; + +static int __devinit adv7511_hdmi_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &hdmi_card; + struct device_node *of_node = pdev->dev.of_node; + + if (!of_node) + return -ENXIO; + + card->dev = &pdev->dev; + +/* hdmi_dai_link.codec_of_node = of_parse_phandle(of_node, "audio-codec", 0);*/ + hdmi_dai_link.cpu_dai_of_node = of_parse_phandle(of_node, "cpu-dai", 0); + hdmi_dai_link.platform_of_node = of_parse_phandle(of_node, "pcm", 0); + + if (/*!hdmi_dai_link.codec_of_node || */!hdmi_dai_link.cpu_dai_of_node || + !hdmi_dai_link.platform_of_node) + return -ENXIO; + + return snd_soc_register_card(card); +} + +static int __devexit adv7511_hdmi_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + snd_soc_unregister_card(card); + + return 0; +} + +static const struct of_device_id adv7511_hdmi_of_match[] __devinitconst = { + { .compatible = "adv7511-hdmi-snd", }, + {}, +}; +MODULE_DEVICE_TABLE(of, adv7511_hdmi_of_match); + +static struct platform_driver hdmi_card_driver = { + .driver = { + .name = "adv7511-hdmi-snd", + .owner = THIS_MODULE, + .of_match_table = adv7511_hdmi_of_match, + .pm = &snd_soc_pm_ops, + }, + .probe = adv7511_hdmi_probe, + .remove = __devexit_p(adv7511_hdmi_remove), +}; +module_platform_driver(hdmi_card_driver); From 19a80b6632da0ca8e1e2f6de8c41e56a2f29adc6 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Mar 2012 10:45:21 +0100 Subject: [PATCH 049/261] regmap: rbtree: Fix register default look-up in sync The code currently passes the register offset in the current block to regcache_lookup_reg. This works fine as long as there is only one block and with base register of 0, but in all other cases it will look-up the default for a wrong register, which can cause unnecessary register writes. This patch fixes it by passing the actual register number to regcache_lookup_reg. Signed-off-by: Lars-Peter Clausen Cc: --- drivers/base/regmap/regcache-rbtree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c index 32620c4f16834..918997b17003a 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c @@ -376,7 +376,7 @@ static int regcache_rbtree_sync(struct regmap *map) map->cache_word_size); /* Is this the hardware default? If so skip. */ - ret = regcache_lookup_reg(map, i); + ret = regcache_lookup_reg(map, regtmp); if (ret > 0 && val == map->reg_defaults[ret].def) continue; From 8a797e461986eddfb15757a1f01284d4e63c5259 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 10 Apr 2012 09:44:33 +0200 Subject: [PATCH 050/261] Increase DMA memory region We need this for now to be able to allocate the framebuffer memory region until we have CMA support. --- arch/arm/Kconfig | 2 +- arch/arm/include/asm/pgtable.h | 2 +- arch/arm/mach-zynq/common.c | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d5cd37c10a319..df8e735ded0ac 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1730,7 +1730,7 @@ config FORCE_MAX_ZONEORDER int "Maximum zone order" if ARCH_SHMOBILE range 11 64 if ARCH_SHMOBILE default "9" if SA1111 - default "11" + default "15" help The kernel memory allocator divides physically contiguous memory blocks into "zones", where each zone is a power of two number of diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index f66626d71e7d1..48d9d1474f1c4 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -40,7 +40,7 @@ */ #define VMALLOC_OFFSET (8*1024*1024) #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) -#define VMALLOC_END 0xff000000UL +#define VMALLOC_END 0xfd000000UL #define LIBRARY_TEXT_START 0x0c000000 diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 0e75a4049f475..69035bfb4ad4b 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -126,6 +127,7 @@ struct map_desc io_desc[] __initdata = { void __init xilinx_map_io(void) { iotable_init(io_desc, ARRAY_SIZE(io_desc)); + init_consistent_dma_size(40 << 20); } /** From ea4a013409db55602f1ca50fcc237e639ae978f6 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 26 Mar 2012 10:38:26 +0200 Subject: [PATCH 051/261] Do not register I2C devices from board file We do this from the device tree. --- arch/arm/mach-zynq/board_zc702.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-zynq/board_zc702.c b/arch/arm/mach-zynq/board_zc702.c index ea4f167a4ad00..4213b32dc7ffa 100644 --- a/arch/arm/mach-zynq/board_zc702.c +++ b/arch/arm/mach-zynq/board_zc702.c @@ -205,6 +205,7 @@ static void __init board_zc702_init(void) ARRAY_SIZE(xilinx_spipss_0_boardinfo)); #endif +#if 0 #if defined(CONFIG_I2C_XILINX_PS) && defined(CONFIG_I2C_MUX_PCA954x) i2c_register_board_info(0, pca954x_i2c_devices, ARRAY_SIZE(pca954x_i2c_devices)); @@ -230,6 +231,7 @@ static void __init board_zc702_init(void) #endif +#endif #endif } From 8556ceff466a0d2353bfa41c29bb0e7cd2d813c9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 10 Apr 2012 10:01:07 +0200 Subject: [PATCH 052/261] Configure the I2C pins for GPIO functionality The I2C core really likes to act up, so fall back to GPIO I2C bitbanging for now. --- arch/arm/mach-zynq/slcr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index 3416a4976c72a..623173d23da43 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -67,6 +67,7 @@ #define XSLCR_DEVC_RST_CTRL_OFFSET 0x23C /* Dev Cfg SW Reset Control */ #define XSLCR_FPGA_RST_CTRL_OFFSET 0x240 /* FPGA Software Reset Control */ #define XSLCR_MIO_PIN_00_OFFSET 0x700 /* MIO PIN0 control register */ +#define XSLCR_MIO_PIN(x) (0x700 + (x) * 4) /* MIO PIN0 control register */ #define XSLCR_LVL_SHFTR_EN_OFFSET 0x900 /* Level Shifters Enable */ /* Bit masks for AMBA Peripheral Clock Control register */ @@ -2385,7 +2386,7 @@ static void xslcr_get_mio_status(void) * * Return: 0 on success, negative error otherwise. **/ -static int __init xslcr_probe(struct platform_device *pdev) +static int __devinit xslcr_probe(struct platform_device *pdev) { struct resource res; int ret; @@ -2458,6 +2459,8 @@ static int __init xslcr_probe(struct platform_device *pdev) xslcr_writereg(slcr->regs + XSLCR_FPGA1_CLK_CTRL_OFFSET, 0x100500); xslcr_writereg(slcr->regs + XSLCR_FPGA2_CLK_CTRL_OFFSET, 0x100700); xslcr_writereg(slcr->regs + XSLCR_FPGA3_CLK_CTRL_OFFSET, 0x102900); + xslcr_writereg(slcr->regs + XSLCR_MIO_PIN(50), 0x200); + xslcr_writereg(slcr->regs + XSLCR_MIO_PIN(51), 0x200); dev_info(&pdev->dev, "at 0x%08X mapped to 0x%08X\n", res.start, (u32 __force)slcr->regs); From 780c2c510d98f59257bfd2a158d53be3e70f266d Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Tue, 7 Feb 2012 12:12:51 +0800 Subject: [PATCH 053/261] of: introduce helper to manage boolean of_property_read_bool Search for a property in a device node. Returns true if the property exist false otherwise. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Rob Herring Acked-by: Arnd Bergmann Acked-by: Grant Likely --- include/linux/of.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/linux/of.h b/include/linux/of.h index 92cf6ad35e0ea..612f84b007c63 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -350,6 +350,22 @@ static inline int of_machine_is_compatible(const char *compat) #define of_match_node(_matches, _node) NULL #endif /* CONFIG_OF */ +/** + * of_property_read_bool - Findfrom a property + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * + * Search for a property in a device node. + * Returns true if the property exist false otherwise. + */ +static inline bool of_property_read_bool(const struct device_node *np, + const char *propname) +{ + struct property *prop = of_find_property(np, propname, NULL); + + return prop ? true : false; +} + static inline int of_property_read_u32(const struct device_node *np, const char *propname, u32 *out_value) From 7047462ba943d267d9ad5adaccf2a7a27ac0c0cd Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Sun, 5 Feb 2012 18:22:34 +0800 Subject: [PATCH 054/261] i2c/gpio: add DT support To achieve DT support, we need to populate a custom platform_data in a private struct from DT information. To simplify code, the adapter and algorithm are also put into the private struct. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: Grant Likely Acked-by: Rob Herring Acked-by: Wolfram Sang Cc: Nicolas Ferre --- .../devicetree/bindings/gpio/gpio_i2c.txt | 32 ++++++ drivers/i2c/busses/i2c-gpio.c | 98 ++++++++++++++----- 2 files changed, 108 insertions(+), 22 deletions(-) create mode 100644 Documentation/devicetree/bindings/gpio/gpio_i2c.txt diff --git a/Documentation/devicetree/bindings/gpio/gpio_i2c.txt b/Documentation/devicetree/bindings/gpio/gpio_i2c.txt new file mode 100644 index 0000000000000..4f8ec947c6bd9 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio_i2c.txt @@ -0,0 +1,32 @@ +Device-Tree bindings for i2c gpio driver + +Required properties: + - compatible = "i2c-gpio"; + - gpios: sda and scl gpio + + +Optional properties: + - i2c-gpio,sda-open-drain: sda as open drain + - i2c-gpio,scl-open-drain: scl as open drain + - i2c-gpio,scl-output-only: scl as output only + - i2c-gpio,delay-us: delay between GPIO operations (may depend on each platform) + - i2c-gpio,timeout-ms: timeout to get data + +Example nodes: + +i2c@0 { + compatible = "i2c-gpio"; + gpios = <&pioA 23 0 /* sda */ + &pioA 24 0 /* scl */ + >; + i2c-gpio,sda-open-drain; + i2c-gpio,scl-open-drain; + i2c-gpio,delay-us = <2>; /* ~100 kHz */ + #address-cells = <1>; + #size-cells = <0>; + + rv3029c2@56 { + compatible = "rv3029c2"; + reg = <0x56>; + }; +}; diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index a651779d9ff7a..c0330a41db039 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -14,8 +14,15 @@ #include #include #include - -#include +#include +#include +#include + +struct i2c_gpio_private_data { + struct i2c_adapter adap; + struct i2c_algo_bit_data bit_data; + struct i2c_gpio_platform_data pdata; +}; /* Toggle SDA by changing the direction of the pin */ static void i2c_gpio_setsda_dir(void *data, int state) @@ -78,24 +85,62 @@ static int i2c_gpio_getscl(void *data) return gpio_get_value(pdata->scl_pin); } +static int __devinit of_i2c_gpio_probe(struct device_node *np, + struct i2c_gpio_platform_data *pdata) +{ + u32 reg; + + if (of_gpio_count(np) < 2) + return -ENODEV; + + pdata->sda_pin = of_get_gpio(np, 0); + pdata->scl_pin = of_get_gpio(np, 1); + + if (!gpio_is_valid(pdata->sda_pin) || !gpio_is_valid(pdata->scl_pin)) { + pr_err("%s: invalid GPIO pins, sda=%d/scl=%d\n", + np->full_name, pdata->sda_pin, pdata->scl_pin); + return -ENODEV; + } + + of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay); + + if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", ®)) + pdata->timeout = msecs_to_jiffies(reg); + + pdata->sda_is_open_drain = + of_property_read_bool(np, "i2c-gpio,sda-open-drain"); + pdata->scl_is_open_drain = + of_property_read_bool(np, "i2c-gpio,scl-open-drain"); + pdata->scl_is_output_only = + of_property_read_bool(np, "i2c-gpio,scl-output-only"); + + return 0; +} + static int __devinit i2c_gpio_probe(struct platform_device *pdev) { + struct i2c_gpio_private_data *priv; struct i2c_gpio_platform_data *pdata; struct i2c_algo_bit_data *bit_data; struct i2c_adapter *adap; int ret; - pdata = pdev->dev.platform_data; - if (!pdata) - return -ENXIO; - - ret = -ENOMEM; - adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); - if (!adap) - goto err_alloc_adap; - bit_data = kzalloc(sizeof(struct i2c_algo_bit_data), GFP_KERNEL); - if (!bit_data) - goto err_alloc_bit_data; + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + adap = &priv->adap; + bit_data = &priv->bit_data; + pdata = &priv->pdata; + + if (pdev->dev.of_node) { + ret = of_i2c_gpio_probe(pdev->dev.of_node, pdata); + if (ret) + return ret; + } else { + if (!pdev->dev.platform_data) + return -ENXIO; + memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata)); + } ret = gpio_request(pdata->sda_pin, "sda"); if (ret) @@ -143,6 +188,7 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev) adap->algo_data = bit_data; adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adap->dev.parent = &pdev->dev; + adap->dev.of_node = pdev->dev.of_node; /* * If "dev->id" is negative we consider it as zero. @@ -154,7 +200,9 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev) if (ret) goto err_add_bus; - platform_set_drvdata(pdev, adap); + of_i2c_register_devices(adap); + + platform_set_drvdata(pdev, priv); dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n", pdata->sda_pin, pdata->scl_pin, @@ -168,34 +216,40 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev) err_request_scl: gpio_free(pdata->sda_pin); err_request_sda: - kfree(bit_data); -err_alloc_bit_data: - kfree(adap); -err_alloc_adap: return ret; } static int __devexit i2c_gpio_remove(struct platform_device *pdev) { + struct i2c_gpio_private_data *priv; struct i2c_gpio_platform_data *pdata; struct i2c_adapter *adap; - adap = platform_get_drvdata(pdev); - pdata = pdev->dev.platform_data; + priv = platform_get_drvdata(pdev); + adap = &priv->adap; + pdata = &priv->pdata; i2c_del_adapter(adap); gpio_free(pdata->scl_pin); gpio_free(pdata->sda_pin); - kfree(adap->algo_data); - kfree(adap); return 0; } +#if defined(CONFIG_OF) +static const struct of_device_id i2c_gpio_dt_ids[] = { + { .compatible = "i2c-gpio", }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, i2c_gpio_dt_ids); +#endif + static struct platform_driver i2c_gpio_driver = { .driver = { .name = "i2c-gpio", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(i2c_gpio_dt_ids), }, .probe = i2c_gpio_probe, .remove = __devexit_p(i2c_gpio_remove), From 6cf4c8f830a3a6591e8dd93d14b7a31ace9c4c69 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 25 Mar 2012 16:52:26 +0200 Subject: [PATCH 055/261] Add ZC702 + ADV7511 device tree --- arch/arm/boot/dts/zynq-zc702-adv7511.dts | 219 +++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 arch/arm/boot/dts/zynq-zc702-adv7511.dts diff --git a/arch/arm/boot/dts/zynq-zc702-adv7511.dts b/arch/arm/boot/dts/zynq-zc702-adv7511.dts new file mode 100644 index 0000000000000..56ff4393cf1a9 --- /dev/null +++ b/arch/arm/boot/dts/zynq-zc702-adv7511.dts @@ -0,0 +1,219 @@ +/dts-v1/; + +/ { + model = "Xilinx Zynq ZC702"; + compatible = "xlnx,zynq-zc702"; + #address-cells = <0x1>; + #size-cells = <0x1>; + interrupt-parent = <0x1>; + + memory { + device_type = "memory"; + reg = <0x000000000 0x40000000>; + }; + chosen { +// bootargs = "console=ttyPS0,115200 root=/dev/ram rw initrd=0x1100000,33M ip=:::::eth0:dhcp earlyprintk"; + bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0"; + linux,stdout-path = "/amba@0/uart@E0001000"; + }; + + amba@0 { + compatible = "simple-bus"; + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + + gic: intc@f8f01000 { + interrupt-controller; + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + reg = < 0xf8f01000 0x1000 >, + < 0xf8f00100 0x0100 >; + }; + + uart@e0001000 { + compatible = "xlnx,ps7-uart-1.00.a"; + reg = <0xe0001000 0x1000>; + interrupts = < 0 50 0 >; + interrupt-parent = <&gic>; + clock = <50000000>; + }; + + timer@0xf8001000 { + compatible = "xlnx,ps7-ttc-1.00.a"; + reg = <0xf8001000 0x1000>; + interrupts = <0 10 0>,<0 11 0>,<0 12 0>; + interrupt-parent = <&gic>; +/* clock-frequency = <111111111>;*/ + clock-frequency-timer0 = <133000000>; + clock-frequency-timer1 = <133000000>; + clock-frequency-timer2 = <133000000>; + }; + + swdt@f8005000 { + device_type = "watchdog"; + compatible = "xlnx,ps7-wdt-1.00.a"; + reg = <0xf8005000 0x100>; + }; + + eth@e000b000 { + compatible = "xlnx,ps7-ethernet-1.00.a"; + reg = <0xe000b000 0x1000>; + interrupts = <0 22 0>; + interrupt-parent = <&gic>; + phy-handle = <&phy0>; + #address-cells = <0x1>; + #size-cells = <0x0>; + + phy0: phy@7 { + compatible = "marvell,88e1116r"; + device_type = "ethernet-phy"; + reg = <0x7>; + }; + }; + + gpio: gpio@e000a000 { + compatible = "xlnx,ps7-gpio-1.00.a"; + reg = <0xe000a000 0x1000>; + interrupts = <0 20 0>; + interrupt-parent = <&gic>; + gpio-controller; + #gpio-cells = <2>; + }; + +/* + i2c0: i2c@e0004000 { + compatible = "xlnx,ps7-i2c-1.00.a"; + reg = <0xe0004000 0x1000>; + interrupts = <0 25 0>; + interrupt-parent = <&gic>; + bus-id = <0>; + input-clk = <111111111>; + i2c-clk = <100000>; +*/ + + i2c0: i2c@0 { + compatible = "i2c-gpio"; + gpios = <&gpio 51 0 &gpio 50 0>; + i2c-gpio,delay-us = <2>; + #address-cells = <1>; + #size-cells = <0>; + + mux@74 { + compatible = "pca9548"; + reg = <0x74>; + #address-cells = <1>; + #size-cells = <0>; + i2c_adv7511: i2c@1 { + #size-cells = <0>; + #address-cells = <1>; + reg = <1>; + }; + + i2c@4 { + #size-cells = <0>; + #address-cells = <1>; + reg = <4>; + rtc@51 { + compatible = "rtc8564"; + reg = <0x51>; + }; + }; + }; + + }; + + sdhci@e0100000 { + compatible = "xlnx,ps7-sdhci-1.00.a"; + reg = <0xe0100000 0x1000>; + interrupts = <0 24 0>; + interrupt-parent = <&gic>; + clock-frequency = <33333000>; + }; + + usb@e0002000 { + compatible = "xlnx,ps7-usb-1.00.a"; + reg = <0xe0002000 0x1000>; + interrupts = <0 21 0>; + interrupt-parent = <&gic>; + dr_mode = "host"; + phy_type = "ulpi"; + }; + + qspi0: spi@e000d000 { + compatible = "xlnx,ps7-qspi-1.00.a"; + reg = <0xE000D000 0x1000>; + interrupts = <0 19 0>; + interrupt-parent = <&gic>; + speed-hz = <200000000>; + bus-num = <1>; + num-chip-select = <1>; + is-dual = <0>; + }; + + devcfg@f8007000 { + compatible = "xlnx,ps7-dev-cfg-1.00.a"; + reg = <0xf8007000 0x1000>; + interrupts = <0 8 0>; + interrupt-parent = <&gic>; + }; + + axi_dma_0: axidma@40400000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + reg = < 0x40400000 0x1000 >; + xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@40400000 { + compatible = "xlnx,axi-dma-mm2s-channel"; + interrupts = < 0 58 0x4 >; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + }; + }; + + axi_spdif_tx_0: axi-spdif-tx@0x75c00000 { + compatible = "adi,axi-spdif-tx-1.00.a"; + reg = < 0x75c00000 0x1000 >; + clock-frequency = <12288000>; + }; + + axi_vdma_0: axivdma@43000000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-vdma"; + reg = <0x43000000 0x1000>; + xlnx,include-sg = <0x0>; + xlnx,num-fstores = <0x3>; + dma-channel@7e200000 { + compatible = "xlnx,axi-vdma-mm2s-channel"; + interrupts = <0 59 0x4>; + xlnx,datawidth = <0x40>; + xlnx,genlock-mode = <0x0>; + xlnx,include-dre = <0x0>; + }; + }; + + cf_adv7x11_core_0: cf-adv7x11-core@6c000000 { + compatible = "adi,cf-adv7x11-core-1.00.a"; + reg = <0x6c000000 0x10000 + 0x66000000 0x10000>; + slave_adapter = <&i2c_adv7511>; + dma-request = <&axi_vdma_0 0>; + }; + + xilinx_pcm_audio: xilinx_pcm_audio { + compatible = "xilinx-pcm-audio"; + dma-request = <&axi_dma_0 0>; + }; + + adv7511_hdmi_snd: adv7511_hdmi_snd { + compatible = "adv7511-hdmi-snd"; + audio-codec = <&i2c_adv7511>; + cpu-dai = <&axi_spdif_tx_0>; + pcm = <&xilinx_pcm_audio>; + }; + }; +}; From 4d3c50e3f1083e61481febe29eb96da4345cb873 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 13 Feb 2012 11:16:22 +0100 Subject: [PATCH 056/261] I2C: xiic: Add OF binding support Signed-off-by: Lars-Peter Clausen --- .../devicetree/bindings/i2c/xiic.txt | 22 ++++++++++++++++++ drivers/i2c/busses/i2c-xiic.c | 23 +++++++++++++++---- 2 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 Documentation/devicetree/bindings/i2c/xiic.txt diff --git a/Documentation/devicetree/bindings/i2c/xiic.txt b/Documentation/devicetree/bindings/i2c/xiic.txt new file mode 100644 index 0000000000000..ceabbe91ae449 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/xiic.txt @@ -0,0 +1,22 @@ +Xilinx IIC controller: + +Required properties: +- compatible : Must be "xlnx,xps-iic-2.00.a" +- reg : IIC register location and length +- interrupts : IIC controller unterrupt +- #address-cells = <1> +- #size-cells = <0> + +Optional properties: +- Child nodes conforming to i2c bus binding + +Example: + + axi_iic_0: i2c@40800000 { + compatible = "xlnx,xps-iic-2.00.a"; + interrupts = < 1 2 >; + reg = < 0x40800000 0x10000 >; + + #size-cells = <0>; + #address-cells = <1>; + }; diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 2bded7647ef25..641d0e5e33036 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -40,6 +40,7 @@ #include #include #include +#include #define DRIVER_NAME "xiic-i2c" @@ -705,8 +706,6 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev) goto resource_missing; pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data; - if (!pdata) - return -EINVAL; i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); if (!i2c) @@ -730,6 +729,7 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev) i2c->adap = xiic_adapter; i2c_set_adapdata(&i2c->adap, i2c); i2c->adap.dev.parent = &pdev->dev; + i2c->adap.dev.of_node = pdev->dev.of_node; xiic_reinit(i2c); @@ -748,9 +748,13 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev) goto add_adapter_failed; } - /* add in known devices to the bus */ - for (i = 0; i < pdata->num_devices; i++) - i2c_new_device(&i2c->adap, pdata->devices + i); + if (pdata) { + /* add in known devices to the bus */ + for (i = 0; i < pdata->num_devices; i++) + i2c_new_device(&i2c->adap, pdata->devices + i); + } + + of_i2c_register_devices(&i2c->adap); return 0; @@ -795,12 +799,21 @@ static int __devexit xiic_i2c_remove(struct platform_device* pdev) return 0; } +#if defined(CONFIG_OF) +static const struct of_device_id xiic_of_match[] __devinitconst = { + { .compatible = "xlnx,xps-iic-2.00.a", }, + {}, +}; +MODULE_DEVICE_TABLE(of, xiic_of_match); +#endif + static struct platform_driver xiic_i2c_driver = { .probe = xiic_i2c_probe, .remove = __devexit_p(xiic_i2c_remove), .driver = { .owner = THIS_MODULE, .name = DRIVER_NAME, + .of_match_table = of_match_ptr(xiic_of_match), }, }; From de4d1b7734a0228ec686743232d4ce0256de47ba Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 20 Feb 2012 13:40:58 +0100 Subject: [PATCH 057/261] I2C: xiic: Always use 32bit access Always use 32bit access to avoid endianess issues. Signed-off-by: Lars-Peter Clausen --- drivers/i2c/busses/i2c-xiic.c | 107 ++++++++++++++-------------------- 1 file changed, 45 insertions(+), 62 deletions(-) diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 641d0e5e33036..52f480e88b998 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -174,47 +174,32 @@ struct xiic_i2c { static void xiic_start_xfer(struct xiic_i2c *i2c); static void __xiic_start_xfer(struct xiic_i2c *i2c); -static inline void xiic_setreg8(struct xiic_i2c *i2c, int reg, u8 value) -{ - iowrite8(value, i2c->base + reg); -} - -static inline u8 xiic_getreg8(struct xiic_i2c *i2c, int reg) -{ - return ioread8(i2c->base + reg); -} - -static inline void xiic_setreg16(struct xiic_i2c *i2c, int reg, u16 value) -{ - iowrite16(value, i2c->base + reg); -} - -static inline void xiic_setreg32(struct xiic_i2c *i2c, int reg, int value) +static inline void xiic_setreg(struct xiic_i2c *i2c, int reg, int value) { iowrite32(value, i2c->base + reg); } -static inline int xiic_getreg32(struct xiic_i2c *i2c, int reg) +static inline int xiic_getreg(struct xiic_i2c *i2c, int reg) { return ioread32(i2c->base + reg); } static inline void xiic_irq_dis(struct xiic_i2c *i2c, u32 mask) { - u32 ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); - xiic_setreg32(i2c, XIIC_IIER_OFFSET, ier & ~mask); + u32 ier = xiic_getreg(i2c, XIIC_IIER_OFFSET); + xiic_setreg(i2c, XIIC_IIER_OFFSET, ier & ~mask); } static inline void xiic_irq_en(struct xiic_i2c *i2c, u32 mask) { - u32 ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); - xiic_setreg32(i2c, XIIC_IIER_OFFSET, ier | mask); + u32 ier = xiic_getreg(i2c, XIIC_IIER_OFFSET); + xiic_setreg(i2c, XIIC_IIER_OFFSET, ier | mask); } static inline void xiic_irq_clr(struct xiic_i2c *i2c, u32 mask) { - u32 isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET); - xiic_setreg32(i2c, XIIC_IISR_OFFSET, isr & mask); + u32 isr = xiic_getreg(i2c, XIIC_IISR_OFFSET); + xiic_setreg(i2c, XIIC_IISR_OFFSET, isr & mask); } static inline void xiic_irq_clr_en(struct xiic_i2c *i2c, u32 mask) @@ -226,30 +211,30 @@ static inline void xiic_irq_clr_en(struct xiic_i2c *i2c, u32 mask) static void xiic_clear_rx_fifo(struct xiic_i2c *i2c) { u8 sr; - for (sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET); + for (sr = xiic_getreg(i2c, XIIC_SR_REG_OFFSET); !(sr & XIIC_SR_RX_FIFO_EMPTY_MASK); - sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET)) - xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET); + sr = xiic_getreg(i2c, XIIC_SR_REG_OFFSET)) + xiic_getreg(i2c, XIIC_DRR_REG_OFFSET); } static void xiic_reinit(struct xiic_i2c *i2c) { - xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); + xiic_setreg(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); /* Set receive Fifo depth to maximum (zero based). */ - xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1); + xiic_setreg(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1); /* Reset Tx Fifo. */ - xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK); + xiic_setreg(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK); /* Enable IIC Device, remove Tx Fifo reset & disable general call. */ - xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_ENABLE_DEVICE_MASK); + xiic_setreg(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_ENABLE_DEVICE_MASK); /* make sure RX fifo is empty */ xiic_clear_rx_fifo(i2c); /* Enable interrupts */ - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); + xiic_setreg(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); xiic_irq_clr_en(i2c, XIIC_INTR_AAS_MASK | XIIC_INTR_ARB_LOST_MASK); } @@ -258,11 +243,11 @@ static void xiic_deinit(struct xiic_i2c *i2c) { u8 cr; - xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); + xiic_setreg(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); /* Disable IIC Device. */ - cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET); - xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr & ~XIIC_CR_ENABLE_DEVICE_MASK); + cr = xiic_getreg(i2c, XIIC_CR_REG_OFFSET); + xiic_setreg(i2c, XIIC_CR_REG_OFFSET, cr & ~XIIC_CR_ENABLE_DEVICE_MASK); } static void xiic_read_rx(struct xiic_i2c *i2c) @@ -270,22 +255,22 @@ static void xiic_read_rx(struct xiic_i2c *i2c) u8 bytes_in_fifo; int i; - bytes_in_fifo = xiic_getreg8(i2c, XIIC_RFO_REG_OFFSET) + 1; + bytes_in_fifo = xiic_getreg(i2c, XIIC_RFO_REG_OFFSET) + 1; dev_dbg(i2c->adap.dev.parent, "%s entry, bytes in fifo: %d, msg: %d" ", SR: 0x%x, CR: 0x%x\n", __func__, bytes_in_fifo, xiic_rx_space(i2c), - xiic_getreg8(i2c, XIIC_SR_REG_OFFSET), - xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); + xiic_getreg(i2c, XIIC_SR_REG_OFFSET), + xiic_getreg(i2c, XIIC_CR_REG_OFFSET)); if (bytes_in_fifo > xiic_rx_space(i2c)) bytes_in_fifo = xiic_rx_space(i2c); for (i = 0; i < bytes_in_fifo; i++) i2c->rx_msg->buf[i2c->rx_pos++] = - xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET); + xiic_getreg(i2c, XIIC_DRR_REG_OFFSET); - xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, + xiic_setreg(i2c, XIIC_RFD_REG_OFFSET, (xiic_rx_space(i2c) > IIC_RX_FIFO_DEPTH) ? IIC_RX_FIFO_DEPTH - 1 : xiic_rx_space(i2c) - 1); } @@ -293,7 +278,7 @@ static void xiic_read_rx(struct xiic_i2c *i2c) static int xiic_tx_fifo_space(struct xiic_i2c *i2c) { /* return the actual space left in the FIFO */ - return IIC_TX_FIFO_DEPTH - xiic_getreg8(i2c, XIIC_TFO_REG_OFFSET) - 1; + return IIC_TX_FIFO_DEPTH - xiic_getreg(i2c, XIIC_TFO_REG_OFFSET) - 1; } static void xiic_fill_tx_fifo(struct xiic_i2c *i2c) @@ -313,9 +298,9 @@ static void xiic_fill_tx_fifo(struct xiic_i2c *i2c) data |= XIIC_TX_DYN_STOP_MASK; dev_dbg(i2c->adap.dev.parent, "%s TX STOP\n", __func__); - xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data); + xiic_setreg(i2c, XIIC_DTR_REG_OFFSET, data); } else - xiic_setreg8(i2c, XIIC_DTR_REG_OFFSET, data); + xiic_setreg(i2c, XIIC_DTR_REG_OFFSET, data); } } @@ -338,13 +323,13 @@ static void xiic_process(struct xiic_i2c *i2c) * To find which interrupts are pending; AND interrupts pending with * interrupts masked. */ - isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET); - ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); + isr = xiic_getreg(i2c, XIIC_IISR_OFFSET); + ier = xiic_getreg(i2c, XIIC_IIER_OFFSET); pend = isr & ier; dev_dbg(i2c->adap.dev.parent, "%s entry, IER: 0x%x, ISR: 0x%x, " "pend: 0x%x, SR: 0x%x, msg: %p, nmsgs: %d\n", - __func__, ier, isr, pend, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET), + __func__, ier, isr, pend, xiic_getreg(i2c, XIIC_SR_REG_OFFSET), i2c->tx_msg, i2c->nmsgs); /* Do not processes a devices interrupts if the device has no @@ -408,6 +393,8 @@ static void xiic_process(struct xiic_i2c *i2c) "%s will start next...\n", __func__); __xiic_start_xfer(i2c); + } else { + xiic_wakeup(i2c, STATE_DONE); } } } else if (pend & XIIC_INTR_BNB_MASK) { @@ -470,12 +457,12 @@ static void xiic_process(struct xiic_i2c *i2c) out: dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr); - xiic_setreg32(i2c, XIIC_IISR_OFFSET, clr); + xiic_setreg(i2c, XIIC_IISR_OFFSET, clr); } static int xiic_bus_busy(struct xiic_i2c *i2c) { - u8 sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET); + u8 sr = xiic_getreg(i2c, XIIC_SR_REG_OFFSET); return (sr & XIIC_SR_BUS_BUSY_MASK) ? -EBUSY : 0; } @@ -518,22 +505,18 @@ static void xiic_start_recv(struct xiic_i2c *i2c) rx_watermark = msg->len; if (rx_watermark > IIC_RX_FIFO_DEPTH) rx_watermark = IIC_RX_FIFO_DEPTH; - xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rx_watermark - 1); + xiic_setreg(i2c, XIIC_RFD_REG_OFFSET, rx_watermark - 1); if (!(msg->flags & I2C_M_NOSTART)) /* write the address */ - xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, + xiic_setreg(i2c, XIIC_DTR_REG_OFFSET, (msg->addr << 1) | XIIC_READ_OPERATION | XIIC_TX_DYN_START_MASK); xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK); - xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, + xiic_setreg(i2c, XIIC_DTR_REG_OFFSET, msg->len | ((i2c->nmsgs == 1) ? XIIC_TX_DYN_STOP_MASK : 0)); - if (i2c->nmsgs == 1) - /* very last, enable bus not busy as well */ - xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK); - /* the message is tx:ed */ i2c->tx_pos = msg->len; } @@ -546,8 +529,8 @@ static void xiic_start_send(struct xiic_i2c *i2c) dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, len: %d, " "ISR: 0x%x, CR: 0x%x\n", - __func__, msg, msg->len, xiic_getreg32(i2c, XIIC_IISR_OFFSET), - xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); + __func__, msg, msg->len, xiic_getreg(i2c, XIIC_IISR_OFFSET), + xiic_getreg(i2c, XIIC_CR_REG_OFFSET)); if (!(msg->flags & I2C_M_NOSTART)) { /* write the address */ @@ -557,7 +540,7 @@ static void xiic_start_send(struct xiic_i2c *i2c) /* no data and last message -> add STOP */ data |= XIIC_TX_DYN_STOP_MASK; - xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data); + xiic_setreg(i2c, XIIC_DTR_REG_OFFSET, data); } xiic_fill_tx_fifo(i2c); @@ -573,13 +556,13 @@ static irqreturn_t xiic_isr(int irq, void *dev_id) spin_lock(&i2c->lock); /* disable interrupts globally */ - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, 0); + xiic_setreg(i2c, XIIC_DGIER_OFFSET, 0); dev_dbg(i2c->adap.dev.parent, "%s entry\n", __func__); xiic_process(i2c); - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); + xiic_setreg(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); spin_unlock(&i2c->lock); return IRQ_HANDLED; @@ -636,11 +619,11 @@ static void xiic_start_xfer(struct xiic_i2c *i2c) spin_lock_irqsave(&i2c->lock, flags); xiic_reinit(i2c); /* disable interrupts globally */ - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, 0); + xiic_setreg(i2c, XIIC_DGIER_OFFSET, 0); spin_unlock_irqrestore(&i2c->lock, flags); __xiic_start_xfer(i2c); - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); + xiic_setreg(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); } static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) @@ -649,7 +632,7 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) int err; dev_dbg(adap->dev.parent, "%s entry SR: 0x%x\n", __func__, - xiic_getreg8(i2c, XIIC_SR_REG_OFFSET)); + xiic_getreg(i2c, XIIC_SR_REG_OFFSET)); err = xiic_busy(i2c); if (err) From d52c2e5a7de0bae3ce20c5984feda668340194f8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 23 Apr 2012 16:57:39 +0200 Subject: [PATCH 058/261] Add ZED + ADV7511 device tree --- arch/arm/boot/dts/zynq-zed-adv7511.dts | 188 +++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 arch/arm/boot/dts/zynq-zed-adv7511.dts diff --git a/arch/arm/boot/dts/zynq-zed-adv7511.dts b/arch/arm/boot/dts/zynq-zed-adv7511.dts new file mode 100644 index 0000000000000..d09e58656672c --- /dev/null +++ b/arch/arm/boot/dts/zynq-zed-adv7511.dts @@ -0,0 +1,188 @@ +/dts-v1/; + +/ { + model = "Xilinx Zynq ZED"; + compatible = "xlnx,zynq-zc702"; + #address-cells = <0x1>; + #size-cells = <0x1>; + interrupt-parent = <0x1>; + + memory { + device_type = "memory"; + reg = <0x000000000 0x40000000>; + }; + chosen { +// bootargs = "console=ttyPS0,115200 root=/dev/ram rw initrd=0x1100000,33M ip=:::::eth0:dhcp earlyprintk"; + bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0"; + linux,stdout-path = "/amba@0/uart@E0001000"; + }; + + amba@0 { + compatible = "simple-bus"; + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + + gic: intc@f8f01000 { + interrupt-controller; + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + reg = < 0xf8f01000 0x1000 >, + < 0xf8f00100 0x0100 >; + }; + + uart@e0001000 { + compatible = "xlnx,ps7-uart-1.00.a"; + reg = <0xe0001000 0x1000>; + interrupts = < 0 50 0 >; + interrupt-parent = <&gic>; + clock = <50000000>; + }; + + timer@0xf8001000 { + compatible = "xlnx,ps7-ttc-1.00.a"; + reg = <0xf8001000 0x1000>; + interrupts = <0 10 0>,<0 11 0>,<0 12 0>; + interrupt-parent = <&gic>; +/* clock-frequency = <111111111>;*/ + clock-frequency-timer0 = <111111111>; + clock-frequency-timer1 = <111111111>; + clock-frequency-timer2 = <111111111>; + }; + + swdt@f8005000 { + device_type = "watchdog"; + compatible = "xlnx,ps7-wdt-1.00.a"; + reg = <0xf8005000 0x100>; + }; + + eth@e000b000 { + compatible = "xlnx,ps7-ethernet-1.00.a"; + reg = <0xe000b000 0x1000>; + interrupts = <0 22 0>; + interrupt-parent = <&gic>; + phy-handle = <&phy0>; + #address-cells = <0x1>; + #size-cells = <0x0>; + + phy0: phy@0 { + compatible = "marvell,88e1510"; + device_type = "ethernet-phy"; + reg = <0x0>; + marvell,reg-init=<3 16 0xff00 0x1e 3 17 0xfff0 0x0a>; + }; + }; + + gpio: gpio@e000a000 { + compatible = "xlnx,ps7-gpio-1.00.a"; + reg = <0xe000a000 0x1000>; + interrupts = <0 20 0>; + interrupt-parent = <&gic>; + gpio-controller; + #gpio-cells = <2>; + }; + + axi_iic_0: i2c@41600000 { + compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; + interrupt-parent = <&gic>; + interrupts = < 0 56 0x4 >; + reg = < 0x41600000 0x10000 >; + + #size-cells = <0>; + #address-cells = <1>; + }; + + sdhci@e0100000 { + compatible = "xlnx,ps7-sdhci-1.00.a"; + reg = <0xe0100000 0x1000>; + interrupts = <0 24 0>; + interrupt-parent = <&gic>; + clock-frequency = <50000000>; + }; + + usb@e0002000 { + compatible = "xlnx,ps7-usb-1.00.a"; + reg = <0xe0002000 0x1000>; + interrupts = <0 21 0>; + interrupt-parent = <&gic>; + dr_mode = "host"; + phy_type = "ulpi"; + }; + + qspi0: spi@e000d000 { + compatible = "xlnx,ps7-qspi-1.00.a"; + reg = <0xE000D000 0x1000>; + interrupts = <0 19 0>; + interrupt-parent = <&gic>; + speed-hz = <200000000>; + bus-num = <1>; + num-chip-select = <1>; + is-dual = <0>; + }; + + devcfg@f8007000 { + compatible = "xlnx,ps7-dev-cfg-1.00.a"; + reg = <0xf8007000 0x1000>; + interrupts = <0 8 0>; + interrupt-parent = <&gic>; + }; + + axi_dma_0: axidma@40400000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + reg = < 0x40400000 0x1000 >; + xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@40400000 { + compatible = "xlnx,axi-dma-mm2s-channel"; + interrupts = < 0 58 0x4 >; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + }; + }; + + axi_spdif_tx_0: axi-spdif-tx@0x75c00000 { + compatible = "adi,axi-spdif-tx-1.00.a"; + reg = < 0x75c00000 0x1000 >; + clock-frequency = <12288000>; + }; + + axi_vdma_0: axivdma@43000000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-vdma"; + reg = <0x43000000 0x1000>; + xlnx,include-sg = <0x0>; + xlnx,num-fstores = <0x3>; + dma-channel@7e200000 { + compatible = "xlnx,axi-vdma-mm2s-channel"; + interrupts = <0 59 0x4>; + xlnx,datawidth = <0x40>; + xlnx,genlock-mode = <0x0>; + xlnx,include-dre = <0x0>; + }; + }; + + cf_adv7x11_core_0: cf-adv7x11-core@6c000000 { + compatible = "adi,cf-adv7x11-core-1.00.a"; + reg = <0x6c000000 0x10000 + 0x66000000 0x10000>; + slave_adapter = <&axi_iic_0>; + dma-request = <&axi_vdma_0 0>; + }; + + xilinx_pcm_audio: xilinx_pcm_audio { + compatible = "xilinx-pcm-audio"; + dma-request = <&axi_dma_0 0>; + }; + + adv7511_hdmi_snd: adv7511_hdmi_snd { + compatible = "adv7511-hdmi-snd"; +// audio-codec = <&>; + cpu-dai = <&axi_spdif_tx_0>; + pcm = <&xilinx_pcm_audio>; + }; + }; +}; From 7255baf5baeafead8905adacdd4f781a09f6c160 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 14 May 2012 18:43:48 +0200 Subject: [PATCH 059/261] Ethernet fixes for ZED Signed-off-by: Lars-Peter Clausen --- drivers/net/ethernet/xilinx/xilinx_emacps.c | 5 ++++ drivers/net/phy/marvell.c | 32 +++++++++++++++++++++ include/linux/marvell_phy.h | 1 + 3 files changed, 38 insertions(+) diff --git a/drivers/net/ethernet/xilinx/xilinx_emacps.c b/drivers/net/ethernet/xilinx/xilinx_emacps.c index 350acc8411d58..7dbc368c70047 100755 --- a/drivers/net/ethernet/xilinx/xilinx_emacps.c +++ b/drivers/net/ethernet/xilinx/xilinx_emacps.c @@ -840,6 +840,11 @@ static int xemacps_mii_probe(struct net_device *ndev) xemacps_adjust_link, 0, PHY_INTERFACE_MODE_RGMII_ID); + + if (!phydev) { + printk(KERN_ERR "%s: no PHY found\n", ndev->name); + return -1; + } } #else for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index f901180a3abf9..57555bb7e3696 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -350,6 +350,24 @@ static int m88e1318_config_aneg(struct phy_device *phydev) return m88e1121_config_aneg(phydev); } +static int m88e1510_config_aneg(struct phy_device *phydev) +/* + Initialization for the 88E151x PHY. Note that the user can run an + additional initialization sequence on a PHY for an embedded system + after running the default configuration as defined for the 88E1318 PHY. + This additional initialization sequence is used for the Xilinx Zynq-based + ZED board. +*/ +{ + int err; + + err = m88e1318_config_aneg(phydev); + if (err < 0) + return err; + + return marvell_of_reg_init(phydev); +} + static int m88e1116r_config_init(struct phy_device *phydev) { int temp; @@ -899,6 +917,19 @@ static struct phy_driver marvell_drivers[] = { .config_intr = &marvell_config_intr, .driver = { .owner = THIS_MODULE }, }, + { + .phy_id = MARVELL_PHY_ID_88E1510, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E1510", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &m88e1510_config_aneg, + .read_status = &marvell_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .did_interrupt = &m88e1121_did_interrupt, + .driver = { .owner = THIS_MODULE }, + }, }; static int __init marvell_init(void) @@ -941,6 +972,7 @@ static struct mdio_device_id __maybe_unused marvell_tbl[] = { { 0x01410e30, 0xfffffff0 }, { 0x01410e90, 0xfffffff0 }, { 0x01410e40, 0xfffffff0 }, + { 0x01410dd0, 0xfffffff0 }, { } }; diff --git a/include/linux/marvell_phy.h b/include/linux/marvell_phy.h index ec41025cb86e4..8e9a029e093d6 100644 --- a/include/linux/marvell_phy.h +++ b/include/linux/marvell_phy.h @@ -15,6 +15,7 @@ #define MARVELL_PHY_ID_88E1240 0x01410e30 #define MARVELL_PHY_ID_88E1318S 0x01410e90 #define MARVELL_PHY_ID_88E1116R 0x01410e40 +#define MARVELL_PHY_ID_88E1510 0x01410dd0 /* struct phy_device dev_flags definitions */ #define MARVELL_PHY_M1145_FLAGS_RESISTANCE 0x00000001 From e9d9d1cd2b554eade81b70d47e2422ee2b27737b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 16 May 2012 12:15:10 +0200 Subject: [PATCH 060/261] ZED USB fixes --- arch/arm/mach-zynq/Kconfig | 12 ++++++++++++ drivers/usb/host/ehci-hcd.c | 7 +++++++ drivers/usb/host/ehci-xilinx-usbps.c | 26 ++++++++++++++++++++++++++ drivers/usb/host/ehci.h | 3 +++ drivers/usb/otg/ulpi.c | 1 + 5 files changed, 49 insertions(+) diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig index 836bb6ced5993..af5c783f895d4 100644 --- a/arch/arm/mach-zynq/Kconfig +++ b/arch/arm/mach-zynq/Kconfig @@ -42,6 +42,18 @@ config XILINX_L2_PREFETCH in many cases. This may not always be the best performance depending on the usage. +config XILINX_ZED + bool "Using USB OTG on the Digilent ZED board" + default n + depends on USB_SUPPORT + select USB_ULPI if USB_SUPPORT + select USB_ULPI_VIEWPORT if USB_SUPPORT + help + Select this option if using the USB OTG port on the Digilent ZED board + as a USB on-the-go port. This option is necessary to properly + initialize the TUSB1210 USB PHY used on the ZED board as an + on-the-go USB port that can supply power to a USB slave device. + config XILINX_TEST bool "Testing On Kernel Boot" default n diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 2594e9e127409..3365ae4cbd24f 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -817,6 +817,13 @@ static int ehci_run (struct usb_hcd *hcd) /* Modifying FIFO Burst Threshold value from 2 to 8 */ temp = readl(non_ehci + 0x164); ehci_writel(ehci, 0x00080000, non_ehci + 0x164); +#if CONFIG_XILINX_ZED + if (ehci->ulpi) { + struct otg_transceiver *otg = ehci->ulpi; + + otg_set_vbus(otg, 1); + } +#endif #endif /* GRR this is run-once init(), being done every time the HC starts. * So long as they're part of class devices, we can't do it init() diff --git a/drivers/usb/host/ehci-xilinx-usbps.c b/drivers/usb/host/ehci-xilinx-usbps.c index d0bfcfbc64dcd..5e5ea17902c2c 100755 --- a/drivers/usb/host/ehci-xilinx-usbps.c +++ b/drivers/usb/host/ehci-xilinx-usbps.c @@ -23,6 +23,9 @@ #include #include #include +#ifdef CONFIG_XILINX_ZED +#include +#endif #include #include "ehci-xilinx-usbps.h" @@ -165,6 +168,16 @@ static int usb_hcd_xusbps_probe(const struct hc_driver *driver, #ifdef CONFIG_USB_XUSBPS_OTG ehci = hcd_to_ehci(hcd); if (pdata->otg) { +#ifdef CONFIG_XILINX_ZED + pr_info ("usb_hcd_xusbps_probe: Have OTG assigned.\n"); + + retval = otg_init(pdata->otg); + if (retval) { + dev_err(&pdev->dev, "Unable to init transceiver, probably missing\n"); + return ENODEV; + } +#endif + ehci->transceiver = pdata->otg; retval = otg_set_host(ehci->transceiver, &ehci_to_hcd(ehci)->self); @@ -177,6 +190,19 @@ static int usb_hcd_xusbps_probe(const struct hc_driver *driver, /* inform otg driver about host driver */ xusbps_update_transceiver(); } else { +#ifdef CONFIG_XILINX_ZED + pr_info ("usb_hcd_xusbps_probe: No OTG assigned!\n"); + if (!pdata->otg) { + pdata->otg = otg_ulpi_create (&ulpi_viewport_access_ops, + ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT); + if (pdata->otg) { + pdata->otg->io_priv = hcd->regs + XUSBPS_SOC_USB_ULPIVP; + ehci->ulpi = pdata->otg; + } + } + pr_info ("usb_hcd_xusbps_probe: OTG now assigned!\n"); +#endif + retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (retval != 0) goto err2; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 92d2421aa508c..00d6aa3e8f191 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -120,6 +120,9 @@ struct ehci_hcd { /* one per controller */ #ifdef CONFIG_USB_XUSBPS_OTG void (*start_hnp)(struct ehci_hcd *ehci); +#ifdef CONFIG_XILINX_ZED + struct otg_transceiver *ulpi; +#endif #endif /* per-HC memory pools (could be per-bus, but ...) */ diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c index 0b0466728fdc3..c4e8b90abbe7b 100644 --- a/drivers/usb/otg/ulpi.c +++ b/drivers/usb/otg/ulpi.c @@ -47,6 +47,7 @@ struct ulpi_info { static struct ulpi_info ulpi_ids[] = { ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"), ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"), + ULPI_INFO(ULPI_ID(0x0451, 0x1507), "TI TUSB1210"), }; static int ulpi_set_otg_flags(struct otg_transceiver *otg) From 6b2928ca3af10ef4f089716447ca81d6b6f1a083 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 16 May 2012 12:17:22 +0200 Subject: [PATCH 061/261] Add config for ZED + ADV7511 --- arch/arm/configs/zed_adv7511_config | 2233 +++++++++++++++++++++++++++ 1 file changed, 2233 insertions(+) create mode 100644 arch/arm/configs/zed_adv7511_config diff --git a/arch/arm/configs/zed_adv7511_config b/arch/arm/configs/zed_adv7511_config new file mode 100644 index 0000000000000..c1eebd4a76b91 --- /dev/null +++ b/arch/arm/configs/zed_adv7511_config @@ -0,0 +1,2233 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.3.0 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_KTIME_SCALAR=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_LOCKBREAK=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0xffff0000 +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0x0 +CONFIG_GENERIC_BUG=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_HAVE_IRQ_WORK=y +CONFIG_IRQ_WORK=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_HAVE_SPARSE_IRQ=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_IRQ_DOMAIN=y +# CONFIG_SPARSE_IRQ is not set + +# +# RCU Subsystem +# +CONFIG_TREE_PREEMPT_RCU=y +CONFIG_PREEMPT_RCU=y +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_BOOST is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +# CONFIG_INLINE_SPIN_UNLOCK is not set +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +# CONFIG_INLINE_READ_UNLOCK is not set +# CONFIG_INLINE_READ_UNLOCK_BH is not set +# CONFIG_INLINE_READ_UNLOCK_IRQ is not set +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +# CONFIG_INLINE_WRITE_UNLOCK is not set +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_FREEZER is not set + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_PRIMA2 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_PICOXCELL is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_VT8500 is not set +CONFIG_ARCH_ZYNQ=y +# CONFIG_GPIO_PCA953X is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set + +# +# System MMU +# + +# +# Xilinx Specific Options +# +CONFIG_ZYNQ_EARLY_UART1=y +# CONFIG_ZYNQ_EARLY_UART_EP107 is not set +CONFIG_XILINX_FIXED_DEVTREE_ADDR=y +CONFIG_XILINX_L1_PREFETCH=y +CONFIG_XILINX_L2_PREFETCH=y +CONFIG_XILINX_ZED=y +# CONFIG_XILINX_TEST is not set +CONFIG_ZYNQ_DEFAULT_KERNEL=y +# CONFIG_ZYNQ_AMP_CPU0_MASTER is not set +# CONFIG_ZYNQ_AMP_CPU1_SLAVE is not set +# CONFIG_ZYNQ_CPU1_TEST is not set + +# +# Processor Type +# +CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_LPAE is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_ARM_NR_BANKS=8 +CONFIG_CPU_HAS_PMU=y +CONFIG_MULTI_IRQ_HANDLER=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_742230 is not set +# CONFIG_ARM_ERRATA_742231 is not set +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_PL310_ERRATA_753970 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_764369 is not set +# CONFIG_PL310_ERRATA_769419 is not set +CONFIG_ARM_GIC=y +CONFIG_ICST=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y +CONFIG_ISA_DMA_API=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_HAVE_SMP=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_ARM_CPU_TOPOLOGY=y +# CONFIG_SCHED_MC is not set +# CONFIG_SCHED_SMT is not set +CONFIG_HAVE_ARM_SCU=y +CONFIG_HAVE_ARM_TWD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_NR_CPUS=4 +# CONFIG_HOTPLUG_CPU is not set +CONFIG_LOCAL_TIMERS=y +CONFIG_ARCH_NR_GPIO=0 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +CONFIG_HZ=100 +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HW_PERF_EVENTS=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=999999 +# CONFIG_COMPACTION is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_CLEANCACHE is not set +CONFIG_FORCE_MAX_ZONEORDER=15 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +# CONFIG_CC_STACKPROTECTOR is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set + +# +# Boot options +# +CONFIG_USE_OF=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_ARM_APPENDED_DTB is not set +CONFIG_CMDLINE="console=ttyPS0,115200n8 root=/dev/ram rw initrd=0x00800000,16M earlyprintk mtdparts=physmap-flash.0:512K(nor-fsbl),512K(nor-u-boot),5M(nor-linux),9M(nor-user),1M(nor-scratch),-(nor-rootfs)" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_CMDLINE_EXTEND is not set +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_XIP_KERNEL is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_AUTO_ZRELADDR is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_SUSPEND is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_PM_CLK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_ARM_CPU_SUSPEND is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=m +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +CONFIG_VLAN_8021Q=m +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +CONFIG_BQL=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=m +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +# CONFIG_DMA_SHARED_BUFFER is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +# CONFIG_M25PXX_USE_FAST_READ is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_DOCG3 is not set +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +CONFIG_MTD_NAND_XILINX_PSS=y +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_DEVICE=y +CONFIG_OF_GPIO=y +CONFIG_OF_I2C=y +CONFIG_OF_NET=y +CONFIG_OF_SPI=y +CONFIG_OF_MDIO=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=35384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set + +# +# Misc devices +# +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_ATMEL_PWM is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085 is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SI570 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_MII is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set + +# +# CAIF transport drivers +# +CONFIG_ETHERNET=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_ETHOC is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +CONFIG_NET_VENDOR_XILINX=y +CONFIG_XILINX_PS_EMAC=y +CONFIG_XILINX_PS_EMAC_HWTSTAMP=y +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=y +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +CONFIG_MDIO_BITBANG=y +# CONFIG_MDIO_GPIO is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_WLAN is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +CONFIG_INPUT_SPARSEKMAP=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +CONFIG_SERIAL_XILINX_PS_UART=y +CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +CONFIG_XILINX_DEVCFG=y +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_RAMOOPS is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +# CONFIG_I2C_CHARDEV is not set +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +CONFIG_I2C_MUX_PCA954x=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX_PS is not set +CONFIG_I2C_XILINX=y + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_XILINX is not set +CONFIG_SPI_XILINX_PS_QSPI=y +# CONFIG_XILINX_PS_QSPI_USE_DUAL_FLASH is not set +CONFIG_SPI_XILINX_PS_SPI=y +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_XILINX is not set +CONFIG_GPIO_XILINX_PS=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_CORE is not set +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_MPCORE_WATCHDOG is not set +# CONFIG_XILINX_PS_WATCHDOG is not set +# CONFIG_XILINX_SCU_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_S5M_CORE is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_REGULATOR is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +# CONFIG_MEDIA_CONTROLLER is not set +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_COMMON=y +# CONFIG_DVB_CORE is not set +CONFIG_VIDEO_MEDIA=y + +# +# Multimedia drivers +# +# CONFIG_RC_CORE is not set +# CONFIG_MEDIA_ATTACH is not set +CONFIG_MEDIA_TUNER=y +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA827X=y +CONFIG_MEDIA_TUNER_TDA18271=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=y +CONFIG_MEDIA_TUNER_TEA5767=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_XC4000=y +CONFIG_MEDIA_TUNER_MC44S803=y +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_VMALLOC=y +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set + +# +# Encoders, decoders, sensors and other helper chips +# + +# +# Audio decoders, processors and mixers +# +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS5345 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_VP27SMPX is not set + +# +# RDS decoders +# +# CONFIG_VIDEO_SAA6588 is not set + +# +# Video decoders +# +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_SAA7110 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA7191 is not set +# CONFIG_VIDEO_TVP514X is not set +# CONFIG_VIDEO_TVP5150 is not set +# CONFIG_VIDEO_TVP7002 is not set +# CONFIG_VIDEO_VPX3220 is not set + +# +# Video and audio decoders +# +# CONFIG_VIDEO_SAA717X is not set +# CONFIG_VIDEO_CX25840 is not set + +# +# MPEG video encoders +# +# CONFIG_VIDEO_CX2341X is not set + +# +# Video encoders +# +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_ADV7343 is not set +# CONFIG_VIDEO_AK881X is not set + +# +# Camera sensor devices +# +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_TCM825X is not set +# CONFIG_VIDEO_SR030PC30 is not set + +# +# Flash devices +# + +# +# Video improvement chips +# +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set + +# +# Miscelaneous helper chips +# +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_M52790 is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_V4L_USB_DRIVERS=y +CONFIG_USB_VIDEO_CLASS=y +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=y +# CONFIG_USB_M5602 is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GSPCA_BENQ is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_JL2005BCD is not set +# CONFIG_USB_GSPCA_KINECT is not set +# CONFIG_USB_GSPCA_KONICA is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_NW80X is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7302 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SE401 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +# CONFIG_USB_GSPCA_SPCA500 is not set +# CONFIG_USB_GSPCA_SPCA501 is not set +# CONFIG_USB_GSPCA_SPCA505 is not set +# CONFIG_USB_GSPCA_SPCA506 is not set +# CONFIG_USB_GSPCA_SPCA508 is not set +# CONFIG_USB_GSPCA_SPCA561 is not set +# CONFIG_USB_GSPCA_SPCA1528 is not set +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_SQ930X is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_STV0680 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TOPRO is not set +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_VICAM is not set +# CONFIG_USB_GSPCA_XIRLINK_CIT is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_VIDEO_PVRUSB2 is not set +# CONFIG_VIDEO_HDPVR is not set +# CONFIG_VIDEO_EM28XX is not set +# CONFIG_VIDEO_USBVISION is not set +# CONFIG_USB_ET61X251 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_PWC is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +# CONFIG_V4L_PLATFORM_DRIVERS is not set +# CONFIG_V4L_MEM2MEM_DRIVERS is not set +# CONFIG_RADIO_ADAPTERS is not set + +# +# Graphics support +# +CONFIG_DRM=y +CONFIG_DRM_KMS_HELPER=y +CONFIG_DRM_ENCODER_ADV7511=y +CONFIG_DRM_ANALOG=y +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_WMT_GE_ROPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_XILINX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_XYLON is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +# CONFIG_SND_SUPPORT_OLD_API is not set +# CONFIG_SND_VERBOSE_PROCFS is not set +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +# CONFIG_SND_USB is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_DMAENGINE_PCM=y +CONFIG_SND_SOC_XILINX=y +CONFIG_SND_SOC_AXI_SPDIF=y +CONFIG_SND_SOC_ADV7511_HDMI=y +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACRUX is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LOGITECH is not set +CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB_ARCH_HAS_XHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_SUSPEND=y +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_XUSBPS_DR_OF=y +CONFIG_USB_EHCI_XUSBPS=y +# CONFIG_USB_EHCI_MV is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_RENESAS_USBHS is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +CONFIG_USB_GADGET_XUSBPS=y +CONFIG_USB_XUSBPS=y +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +CONFIG_USB_ZERO=m +# CONFIG_USB_ZERO_HNPTEST is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_GPIO_VBUS is not set +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_USB_XUSBPS_OTG=y +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF_XILINX_PS=y +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_WBSD is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +CONFIG_RTC_DRV_PCF8563=y +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_XILINX_DMA=y +# CONFIG_AMBA_PL08X is not set +# CONFIG_DW_DMAC is not set +# CONFIG_TIMB_DMA is not set +# CONFIG_PL330_DMA is not set +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_BALLOON is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +# CONFIG_STAGING is not set +CONFIG_CLKDEV_LOOKUP=y + +# +# Hardware Spinlock drivers +# +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT23=y +CONFIG_EXT4_FS_XATTR=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=20 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +# CONFIG_PROVE_RCU_REPEATEDLY is not set +# CONFIG_SPARSE_RCU_POINTER is not set +CONFIG_LOCKDEP=y +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_LOCKDEP is not set +CONFIG_TRACE_IRQFLAGS=y +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_CPU_STALL_VERBOSE is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_LKDTM is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +CONFIG_DEBUG_LL=y +CONFIG_DEBUG_LL_UART_NONE=y +# CONFIG_DEBUG_ICEDCC is not set +CONFIG_EARLY_PRINTK=y +# CONFIG_OC_ETM is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_RNG=m +CONFIG_CRYPTO_RNG2=m +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_PCI_IOMAP=y +# CONFIG_CRC_CCITT is not set +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +# CONFIG_CRC8 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set From ff46106eea16d954a67d0b09112eab69c2ab21b4 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Thu, 22 Dec 2011 18:44:43 -0800 Subject: [PATCH 062/261] staging:iio: isl29018: add of_match table for device-tree probing As simple as can be right now; just one ID and no custom properties to parse. Signed-off-by: Olof Johansson Acked-by: Grant Likely Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/light/isl29018.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 849d6a564afa9..38ec52b65dfa7 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -592,11 +592,18 @@ static const struct i2c_device_id isl29018_id[] = { MODULE_DEVICE_TABLE(i2c, isl29018_id); +static const struct of_device_id isl29018_of_match[] = { + { .compatible = "invn,isl29018", }, + { }, +}; +MODULE_DEVICE_TABLE(of, isl29018_of_match); + static struct i2c_driver isl29018_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "isl29018", .owner = THIS_MODULE, + .of_match_table = isl29018_of_match, }, .probe = isl29018_probe, .remove = __devexit_p(isl29018_remove), From f94eca32a4a265f7189b3bc7ff732f2f7d9bc82b Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Thu, 22 Dec 2011 18:46:42 -0800 Subject: [PATCH 063/261] staging:iio: ak8975: add of_match table for device-tree probing Just like isl29018; trivial addition. Using both asahi-kasei,ak8975 and the non-prefixed version (I couldn't figure out if Asahi Kasei had a stock symbol to use, I only found numerical indexes for their stock info). Signed-off-by: Olof Johansson Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/magnetometer/ak8975.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c index 3158f12cb051f..d5ddac3d88311 100644 --- a/drivers/staging/iio/magnetometer/ak8975.c +++ b/drivers/staging/iio/magnetometer/ak8975.c @@ -564,9 +564,17 @@ static const struct i2c_device_id ak8975_id[] = { MODULE_DEVICE_TABLE(i2c, ak8975_id); +static const struct of_device_id ak8975_of_match[] = { + { .compatible = "asahi-kasei,ak8975", }, + { .compatible = "ak8975", }, + { } +}; +MODULE_DEVICE_TABLE(of, ak8975_of_match); + static struct i2c_driver ak8975_driver = { .driver = { .name = "ak8975", + .of_match_table = ak8975_of_match, }, .probe = ak8975_probe, .remove = __devexit_p(ak8975_remove), From ca20428f5c8521bbda40d0cb81b64453cd07f68b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 3 Jan 2012 11:02:51 +0100 Subject: [PATCH 064/261] staging:iio: Setup buffer access functions when allocating the buffer Setup the buffer access functions in the buffer allocate function. There is no need to let each driver handle this on its own. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16201_ring.c | 2 - drivers/staging/iio/accel/adis16203_ring.c | 2 - drivers/staging/iio/accel/adis16204_ring.c | 2 - drivers/staging/iio/accel/adis16209_ring.c | 2 - drivers/staging/iio/accel/adis16240_ring.c | 2 - drivers/staging/iio/accel/lis3l02dq.h | 2 - drivers/staging/iio/accel/lis3l02dq_ring.c | 2 - drivers/staging/iio/adc/ad7192.c | 2 - drivers/staging/iio/adc/ad7298_ring.c | 3 -- drivers/staging/iio/adc/ad7476_ring.c | 2 - drivers/staging/iio/adc/ad7606_ring.c | 2 - drivers/staging/iio/adc/ad7793.c | 2 - drivers/staging/iio/adc/ad7887_ring.c | 2 - drivers/staging/iio/adc/ad799x_ring.c | 2 - drivers/staging/iio/adc/max1363_ring.c | 2 - drivers/staging/iio/gyro/adis16260_ring.c | 2 - drivers/staging/iio/iio_simple_dummy_buffer.c | 2 - .../staging/iio/impedance-analyzer/ad5933.c | 3 -- drivers/staging/iio/imu/adis16400_ring.c | 2 - drivers/staging/iio/kfifo_buf.c | 46 +++++++++---------- drivers/staging/iio/kfifo_buf.h | 2 - drivers/staging/iio/meter/ade7758_ring.c | 2 - drivers/staging/iio/ring_sw.c | 22 ++++----- drivers/staging/iio/ring_sw.h | 5 -- 24 files changed, 34 insertions(+), 83 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c index 26c610faee3fd..97f9e6b159d9f 100644 --- a/drivers/staging/iio/accel/adis16201_ring.c +++ b/drivers/staging/iio/accel/adis16201_ring.c @@ -115,9 +115,7 @@ int adis16201_configure_ring(struct iio_dev *indio_dev) return ret; } indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ ring->scan_timestamp = true; - ring->access = &ring_sw_access_funcs; indio_dev->setup_ops = &adis16201_ring_setup_ops; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c index 064640d15e41e..6a8963db4f60a 100644 --- a/drivers/staging/iio/accel/adis16203_ring.c +++ b/drivers/staging/iio/accel/adis16203_ring.c @@ -117,9 +117,7 @@ int adis16203_configure_ring(struct iio_dev *indio_dev) return ret; } indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ ring->scan_timestamp = true; - ring->access = &ring_sw_access_funcs; indio_dev->setup_ops = &adis16203_ring_setup_ops; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c index 4081179dfa5c4..5c8ab73388645 100644 --- a/drivers/staging/iio/accel/adis16204_ring.c +++ b/drivers/staging/iio/accel/adis16204_ring.c @@ -112,8 +112,6 @@ int adis16204_configure_ring(struct iio_dev *indio_dev) return ret; } indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->access = &ring_sw_access_funcs; ring->scan_timestamp = true; indio_dev->setup_ops = &adis16204_ring_setup_ops; diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c index 2a6fd334f5f13..57254b6b38b73 100644 --- a/drivers/staging/iio/accel/adis16209_ring.c +++ b/drivers/staging/iio/accel/adis16209_ring.c @@ -113,8 +113,6 @@ int adis16209_configure_ring(struct iio_dev *indio_dev) return ret; } indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->access = &ring_sw_access_funcs; ring->scan_timestamp = true; indio_dev->setup_ops = &adis16209_ring_setup_ops; diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c index e23622d96f9f1..43ba84e993ade 100644 --- a/drivers/staging/iio/accel/adis16240_ring.c +++ b/drivers/staging/iio/accel/adis16240_ring.c @@ -110,8 +110,6 @@ int adis16240_configure_ring(struct iio_dev *indio_dev) return ret; } indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->access = &ring_sw_access_funcs; ring->scan_timestamp = true; indio_dev->setup_ops = &adis16240_ring_setup_ops; diff --git a/drivers/staging/iio/accel/lis3l02dq.h b/drivers/staging/iio/accel/lis3l02dq.h index 2db383fc27433..ae5f225b4bb29 100644 --- a/drivers/staging/iio/accel/lis3l02dq.h +++ b/drivers/staging/iio/accel/lis3l02dq.h @@ -187,12 +187,10 @@ void lis3l02dq_unconfigure_buffer(struct iio_dev *indio_dev); #ifdef CONFIG_LIS3L02DQ_BUF_RING_SW #define lis3l02dq_free_buf iio_sw_rb_free #define lis3l02dq_alloc_buf iio_sw_rb_allocate -#define lis3l02dq_access_funcs ring_sw_access_funcs #endif #ifdef CONFIG_LIS3L02DQ_BUF_KFIFO #define lis3l02dq_free_buf iio_kfifo_free #define lis3l02dq_alloc_buf iio_kfifo_allocate -#define lis3l02dq_access_funcs kfifo_access_funcs #endif irqreturn_t lis3l02dq_data_rdy_trig_poll(int irq, void *private); #define lis3l02dq_th lis3l02dq_data_rdy_trig_poll diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 98c5c92d3450f..ca0a1fe6ff3fa 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -406,8 +406,6 @@ int lis3l02dq_configure_buffer(struct iio_dev *indio_dev) return -ENOMEM; indio_dev->buffer = buffer; - /* Effectively select the buffer implementation */ - indio_dev->buffer->access = &lis3l02dq_access_funcs; buffer->scan_timestamp = true; indio_dev->setup_ops = &lis3l02dq_buffer_setup_ops; diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 45f4504ed9278..9d251653307ca 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -561,8 +561,6 @@ static int ad7192_register_ring_funcs_and_init(struct iio_dev *indio_dev) ret = -ENOMEM; goto error_ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &ad7192_trigger_handler, IRQF_ONESHOT, diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c index d1a12dd015e2c..feeb0eeba59ab 100644 --- a/drivers/staging/iio/adc/ad7298_ring.c +++ b/drivers/staging/iio/adc/ad7298_ring.c @@ -131,9 +131,6 @@ int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev) ret = -ENOMEM; goto error_ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; - indio_dev->pollfunc = iio_alloc_pollfunc(NULL, &ad7298_trigger_handler, IRQF_ONESHOT, diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c index 4e298b2a05b2a..35a8576a22712 100644 --- a/drivers/staging/iio/adc/ad7476_ring.c +++ b/drivers/staging/iio/adc/ad7476_ring.c @@ -98,8 +98,6 @@ int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev) ret = -ENOMEM; goto error_ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(NULL, &ad7476_trigger_handler, diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c index e8f94a18a9431..1ef9fbcaf2def 100644 --- a/drivers/staging/iio/adc/ad7606_ring.c +++ b/drivers/staging/iio/adc/ad7606_ring.c @@ -110,8 +110,6 @@ int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev) goto error_ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(&ad7606_trigger_handler_th_bh, &ad7606_trigger_handler_th_bh, 0, diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index 6a058b19c49ad..84ecde1ad0422 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -427,8 +427,6 @@ static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev) ret = -ENOMEM; goto error_ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &ad7793_trigger_handler, IRQF_ONESHOT, diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c index 85076cd962e7d..d1809079b63da 100644 --- a/drivers/staging/iio/adc/ad7887_ring.c +++ b/drivers/staging/iio/adc/ad7887_ring.c @@ -131,8 +131,6 @@ int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev) ret = -ENOMEM; goto error_ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &ad7887_trigger_handler, IRQF_ONESHOT, diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c index 5dded9e7820ae..28e9a4192910a 100644 --- a/drivers/staging/iio/adc/ad799x_ring.c +++ b/drivers/staging/iio/adc/ad799x_ring.c @@ -141,8 +141,6 @@ int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev) ret = -ENOMEM; goto error_ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(NULL, &ad799x_trigger_handler, IRQF_ONESHOT, diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c index f730b3fb971af..d0a60a3829309 100644 --- a/drivers/staging/iio/adc/max1363_ring.c +++ b/drivers/staging/iio/adc/max1363_ring.c @@ -116,8 +116,6 @@ int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) ret = -ENOMEM; goto error_deallocate_sw_rb; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; /* Ring buffer functions - here trigger setup related */ indio_dev->setup_ops = &max1363_ring_setup_ops; diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c index 699a6152c4093..711f15122a088 100644 --- a/drivers/staging/iio/gyro/adis16260_ring.c +++ b/drivers/staging/iio/gyro/adis16260_ring.c @@ -115,8 +115,6 @@ int adis16260_configure_ring(struct iio_dev *indio_dev) return ret; } indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->access = &ring_sw_access_funcs; ring->scan_timestamp = true; indio_dev->setup_ops = &adis16260_ring_setup_ops; diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index d6a1c0e82a5b0..bb4daf744362a 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -142,8 +142,6 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) } indio_dev->buffer = buffer; - /* Tell the core how to access the buffer */ - buffer->access = &kfifo_access_funcs; /* Enable timestamps by default */ buffer->scan_timestamp = true; diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 9a2ca55625f40..cd82b56d58af6 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -607,9 +607,6 @@ static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev) if (!indio_dev->buffer) return -ENOMEM; - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; - /* Ring buffer functions - here trigger setup related */ indio_dev->setup_ops = &ad5933_ring_setup_ops; diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c index ac22de573f3e9..8daa038b23e66 100644 --- a/drivers/staging/iio/imu/adis16400_ring.c +++ b/drivers/staging/iio/imu/adis16400_ring.c @@ -187,8 +187,6 @@ int adis16400_configure_ring(struct iio_dev *indio_dev) return ret; } indio_dev->buffer = ring; - /* Effectively select the ring buffer implementation */ - ring->access = &ring_sw_access_funcs; ring->scan_timestamp = true; indio_dev->setup_ops = &adis16400_ring_setup_ops; diff --git a/drivers/staging/iio/kfifo_buf.c b/drivers/staging/iio/kfifo_buf.c index e1e9c06cde4a0..9f3bd59c0e72b 100644 --- a/drivers/staging/iio/kfifo_buf.c +++ b/drivers/staging/iio/kfifo_buf.c @@ -59,21 +59,6 @@ static struct attribute_group iio_kfifo_attribute_group = { .name = "buffer", }; -struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) -{ - struct iio_kfifo *kf; - - kf = kzalloc(sizeof *kf, GFP_KERNEL); - if (!kf) - return NULL; - kf->update_needed = true; - iio_buffer_init(&kf->buffer); - kf->buffer.attrs = &iio_kfifo_attribute_group; - - return &kf->buffer; -} -EXPORT_SYMBOL(iio_kfifo_allocate); - static int iio_get_bytes_per_datum_kfifo(struct iio_buffer *r) { return r->bytes_per_datum; @@ -104,12 +89,6 @@ static int iio_set_length_kfifo(struct iio_buffer *r, int length) return 0; } -void iio_kfifo_free(struct iio_buffer *r) -{ - kfree(iio_to_kfifo(r)); -} -EXPORT_SYMBOL(iio_kfifo_free); - static int iio_store_to_kfifo(struct iio_buffer *r, u8 *data, s64 timestamp) @@ -137,7 +116,7 @@ static int iio_read_first_n_kfifo(struct iio_buffer *r, return copied; } -const struct iio_buffer_access_funcs kfifo_access_funcs = { +static const struct iio_buffer_access_funcs kfifo_access_funcs = { .store_to = &iio_store_to_kfifo, .read_first_n = &iio_read_first_n_kfifo, .request_update = &iio_request_update_kfifo, @@ -146,6 +125,27 @@ const struct iio_buffer_access_funcs kfifo_access_funcs = { .get_length = &iio_get_length_kfifo, .set_length = &iio_set_length_kfifo, }; -EXPORT_SYMBOL(kfifo_access_funcs); + +struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) +{ + struct iio_kfifo *kf; + + kf = kzalloc(sizeof *kf, GFP_KERNEL); + if (!kf) + return NULL; + kf->update_needed = true; + iio_buffer_init(&kf->buffer); + kf->buffer.attrs = &iio_kfifo_attribute_group; + kf->buffer.access = &kfifo_access_funcs; + + return &kf->buffer; +} +EXPORT_SYMBOL(iio_kfifo_allocate); + +void iio_kfifo_free(struct iio_buffer *r) +{ + kfree(iio_to_kfifo(r)); +} +EXPORT_SYMBOL(iio_kfifo_free); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/kfifo_buf.h b/drivers/staging/iio/kfifo_buf.h index cc2bd9a1ccfe6..9f7da016af04d 100644 --- a/drivers/staging/iio/kfifo_buf.h +++ b/drivers/staging/iio/kfifo_buf.h @@ -3,8 +3,6 @@ #include "iio.h" #include "buffer.h" -extern const struct iio_buffer_access_funcs kfifo_access_funcs; - struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev); void iio_kfifo_free(struct iio_buffer *r); diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index f29f2b278fe45..c5c522bb69ab6 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -144,8 +144,6 @@ int ade7758_configure_ring(struct iio_dev *indio_dev) return ret; } - /* Effectively select the ring buffer implementation */ - indio_dev->buffer->access = &ring_sw_access_funcs; indio_dev->setup_ops = &ade7758_ring_setup_ops; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c index 3e24ec4558547..eeac0daf47bd1 100644 --- a/drivers/staging/iio/ring_sw.c +++ b/drivers/staging/iio/ring_sw.c @@ -329,6 +329,16 @@ static struct attribute_group iio_ring_attribute_group = { .name = "buffer", }; +static const struct iio_buffer_access_funcs ring_sw_access_funcs = { + .store_to = &iio_store_to_sw_rb, + .read_first_n = &iio_read_first_n_sw_rb, + .request_update = &iio_request_update_sw_rb, + .get_bytes_per_datum = &iio_get_bytes_per_datum_sw_rb, + .set_bytes_per_datum = &iio_set_bytes_per_datum_sw_rb, + .get_length = &iio_get_length_sw_rb, + .set_length = &iio_set_length_sw_rb, +}; + struct iio_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev) { struct iio_buffer *buf; @@ -341,6 +351,7 @@ struct iio_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev) buf = &ring->buf; iio_buffer_init(buf); buf->attrs = &iio_ring_attribute_group; + buf->access = &ring_sw_access_funcs; return buf; } @@ -352,16 +363,5 @@ void iio_sw_rb_free(struct iio_buffer *r) } EXPORT_SYMBOL(iio_sw_rb_free); -const struct iio_buffer_access_funcs ring_sw_access_funcs = { - .store_to = &iio_store_to_sw_rb, - .read_first_n = &iio_read_first_n_sw_rb, - .request_update = &iio_request_update_sw_rb, - .get_bytes_per_datum = &iio_get_bytes_per_datum_sw_rb, - .set_bytes_per_datum = &iio_set_bytes_per_datum_sw_rb, - .get_length = &iio_get_length_sw_rb, - .set_length = &iio_set_length_sw_rb, -}; -EXPORT_SYMBOL(ring_sw_access_funcs); - MODULE_DESCRIPTION("Industrialio I/O software ring buffer"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/iio/ring_sw.h b/drivers/staging/iio/ring_sw.h index e6a6e2c409600..7556e2122367e 100644 --- a/drivers/staging/iio/ring_sw.h +++ b/drivers/staging/iio/ring_sw.h @@ -25,11 +25,6 @@ #define _IIO_RING_SW_H_ #include "buffer.h" -/** - * ring_sw_access_funcs - access functions for a software ring buffer - **/ -extern const struct iio_buffer_access_funcs ring_sw_access_funcs; - struct iio_buffer *iio_sw_rb_allocate(struct iio_dev *indio_dev); void iio_sw_rb_free(struct iio_buffer *ring); #endif /* _IIO_RING_SW_H_ */ From 7bd42cebf2fecfd61876659f1ed3ccac8cf63a6a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 3 Jan 2012 14:59:37 +0100 Subject: [PATCH 065/261] staging:iio: Update iio_event_interface documentation The documentation for the iio_event_interface does not match the actual struct anymore. This patch removes the documentation for non-existing fields and adds documentation for missing fields. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/industrialio-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 19f897f3c85ee..580f3738d59f2 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -112,13 +112,14 @@ struct iio_detected_event_list { /** * struct iio_event_interface - chrdev interface for an event line - * @dev: device assocated with event interface * @wait: wait queue to allow blocking reads of events * @event_list_lock: mutex to protect the list of detected events * @det_events: list of detected events * @max_events: maximum number of events before new ones are dropped * @current_events: number of events in detected list + * @dev_attr_list: list of event interface sysfs attribute * @flags: file operations related flags including busy flag. + * @group: event interface sysfs attribute group */ struct iio_event_interface { wait_queue_head_t wait; From 38ae1bf3d9721f81607411b75510e15bb3d338e6 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 3 Jan 2012 14:59:38 +0100 Subject: [PATCH 066/261] staging:iio: Factor out event handling into its own file The core iio file has gotten quite cluttered over time. This patch moves the event handling code into its own file. Since the event handling code is largely independent from the core code the only code changes necessary for this are to make the moved iio_device_register_eventset, iio_device_unregister_eventset and iio_event_getfd functions non static. This has also the advantage that industrialio-core.c is now closer again to its counterpart in the outofstaging branch. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/Makefile | 2 +- drivers/staging/iio/iio_core.h | 4 + drivers/staging/iio/industrialio-core.c | 459 --------------------- drivers/staging/iio/industrialio-event.c | 483 +++++++++++++++++++++++ 4 files changed, 488 insertions(+), 460 deletions(-) create mode 100644 drivers/staging/iio/industrialio-event.c diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile index 1340aead18b40..657710b266b01 100644 --- a/drivers/staging/iio/Makefile +++ b/drivers/staging/iio/Makefile @@ -3,7 +3,7 @@ # obj-$(CONFIG_IIO) += industrialio.o -industrialio-y := industrialio-core.o +industrialio-y := industrialio-core.o industrialio-event.o industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o diff --git a/drivers/staging/iio/iio_core.h b/drivers/staging/iio/iio_core.h index 107cfb1cbb013..c9dfcba0bac8d 100644 --- a/drivers/staging/iio/iio_core.h +++ b/drivers/staging/iio/iio_core.h @@ -49,4 +49,8 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, #endif +int iio_device_register_eventset(struct iio_dev *indio_dev); +void iio_device_unregister_eventset(struct iio_dev *indio_dev); +int iio_event_getfd(struct iio_dev *indio_dev); + #endif diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 580f3738d59f2..e4824fe8b4051 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -100,72 +100,6 @@ const struct iio_chan_spec return NULL; } -/** - * struct iio_detected_event_list - list element for events that have occurred - * @list: linked list header - * @ev: the event itself - */ -struct iio_detected_event_list { - struct list_head list; - struct iio_event_data ev; -}; - -/** - * struct iio_event_interface - chrdev interface for an event line - * @wait: wait queue to allow blocking reads of events - * @event_list_lock: mutex to protect the list of detected events - * @det_events: list of detected events - * @max_events: maximum number of events before new ones are dropped - * @current_events: number of events in detected list - * @dev_attr_list: list of event interface sysfs attribute - * @flags: file operations related flags including busy flag. - * @group: event interface sysfs attribute group - */ -struct iio_event_interface { - wait_queue_head_t wait; - struct mutex event_list_lock; - struct list_head det_events; - int max_events; - int current_events; - struct list_head dev_attr_list; - unsigned long flags; - struct attribute_group group; -}; - -int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) -{ - struct iio_event_interface *ev_int = indio_dev->event_interface; - struct iio_detected_event_list *ev; - int ret = 0; - - /* Does anyone care? */ - mutex_lock(&ev_int->event_list_lock); - if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { - if (ev_int->current_events == ev_int->max_events) { - mutex_unlock(&ev_int->event_list_lock); - return 0; - } - ev = kmalloc(sizeof(*ev), GFP_KERNEL); - if (ev == NULL) { - ret = -ENOMEM; - mutex_unlock(&ev_int->event_list_lock); - goto error_ret; - } - ev->ev.id = ev_code; - ev->ev.timestamp = timestamp; - - list_add_tail(&ev->list, &ev_int->det_events); - ev_int->current_events++; - mutex_unlock(&ev_int->event_list_lock); - wake_up_interruptible(&ev_int->wait); - } else - mutex_unlock(&ev_int->event_list_lock); - -error_ret: - return ret; -} -EXPORT_SYMBOL(iio_push_event); - /* This turns up an awful lot */ ssize_t iio_read_const_attr(struct device *dev, struct device_attribute *attr, @@ -175,110 +109,6 @@ ssize_t iio_read_const_attr(struct device *dev, } EXPORT_SYMBOL(iio_read_const_attr); -static ssize_t iio_event_chrdev_read(struct file *filep, - char __user *buf, - size_t count, - loff_t *f_ps) -{ - struct iio_event_interface *ev_int = filep->private_data; - struct iio_detected_event_list *el; - size_t len = sizeof(el->ev); - int ret; - - if (count < len) - return -EINVAL; - - mutex_lock(&ev_int->event_list_lock); - if (list_empty(&ev_int->det_events)) { - if (filep->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - goto error_mutex_unlock; - } - mutex_unlock(&ev_int->event_list_lock); - /* Blocking on device; waiting for something to be there */ - ret = wait_event_interruptible(ev_int->wait, - !list_empty(&ev_int - ->det_events)); - if (ret) - goto error_ret; - /* Single access device so no one else can get the data */ - mutex_lock(&ev_int->event_list_lock); - } - - el = list_first_entry(&ev_int->det_events, - struct iio_detected_event_list, - list); - if (copy_to_user(buf, &(el->ev), len)) { - ret = -EFAULT; - goto error_mutex_unlock; - } - list_del(&el->list); - ev_int->current_events--; - mutex_unlock(&ev_int->event_list_lock); - kfree(el); - - return len; - -error_mutex_unlock: - mutex_unlock(&ev_int->event_list_lock); -error_ret: - - return ret; -} - -static int iio_event_chrdev_release(struct inode *inode, struct file *filep) -{ - struct iio_event_interface *ev_int = filep->private_data; - struct iio_detected_event_list *el, *t; - - mutex_lock(&ev_int->event_list_lock); - clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); - /* - * In order to maintain a clean state for reopening, - * clear out any awaiting events. The mask will prevent - * any new __iio_push_event calls running. - */ - list_for_each_entry_safe(el, t, &ev_int->det_events, list) { - list_del(&el->list); - kfree(el); - } - ev_int->current_events = 0; - mutex_unlock(&ev_int->event_list_lock); - - return 0; -} - -static const struct file_operations iio_event_chrdev_fileops = { - .read = iio_event_chrdev_read, - .release = iio_event_chrdev_release, - .owner = THIS_MODULE, - .llseek = noop_llseek, -}; - -static int iio_event_getfd(struct iio_dev *indio_dev) -{ - struct iio_event_interface *ev_int = indio_dev->event_interface; - int fd; - - if (ev_int == NULL) - return -ENODEV; - - mutex_lock(&ev_int->event_list_lock); - if (test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { - mutex_unlock(&ev_int->event_list_lock); - return -EBUSY; - } - mutex_unlock(&ev_int->event_list_lock); - fd = anon_inode_getfd("iio:event", - &iio_event_chrdev_fileops, ev_int, O_RDONLY); - if (fd < 0) { - mutex_lock(&ev_int->event_list_lock); - clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); - mutex_unlock(&ev_int->event_list_lock); - } - return fd; -} - static int __init iio_init(void) { int ret; @@ -727,295 +557,6 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) kfree(indio_dev->chan_attr_group.attrs); } -static const char * const iio_ev_type_text[] = { - [IIO_EV_TYPE_THRESH] = "thresh", - [IIO_EV_TYPE_MAG] = "mag", - [IIO_EV_TYPE_ROC] = "roc", - [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", - [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", -}; - -static const char * const iio_ev_dir_text[] = { - [IIO_EV_DIR_EITHER] = "either", - [IIO_EV_DIR_RISING] = "rising", - [IIO_EV_DIR_FALLING] = "falling" -}; - -static ssize_t iio_ev_state_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret; - bool val; - - ret = strtobool(buf, &val); - if (ret < 0) - return ret; - - ret = indio_dev->info->write_event_config(indio_dev, - this_attr->address, - val); - return (ret < 0) ? ret : len; -} - -static ssize_t iio_ev_state_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int val = indio_dev->info->read_event_config(indio_dev, - this_attr->address); - - if (val < 0) - return val; - else - return sprintf(buf, "%d\n", val); -} - -static ssize_t iio_ev_value_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int val, ret; - - ret = indio_dev->info->read_event_value(indio_dev, - this_attr->address, &val); - if (ret < 0) - return ret; - - return sprintf(buf, "%d\n", val); -} - -static ssize_t iio_ev_value_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - unsigned long val; - int ret; - - if (!indio_dev->info->write_event_value) - return -EINVAL; - - ret = strict_strtoul(buf, 10, &val); - if (ret) - return ret; - - ret = indio_dev->info->write_event_value(indio_dev, this_attr->address, - val); - if (ret < 0) - return ret; - - return len; -} - -static int iio_device_add_event_sysfs(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan) -{ - int ret = 0, i, attrcount = 0; - u64 mask = 0; - char *postfix; - if (!chan->event_mask) - return 0; - - for_each_set_bit(i, &chan->event_mask, sizeof(chan->event_mask)*8) { - postfix = kasprintf(GFP_KERNEL, "%s_%s_en", - iio_ev_type_text[i/IIO_EV_DIR_MAX], - iio_ev_dir_text[i%IIO_EV_DIR_MAX]); - if (postfix == NULL) { - ret = -ENOMEM; - goto error_ret; - } - if (chan->modified) - mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel, - i/IIO_EV_DIR_MAX, - i%IIO_EV_DIR_MAX); - else if (chan->differential) - mask = IIO_EVENT_CODE(chan->type, - 0, 0, - i%IIO_EV_DIR_MAX, - i/IIO_EV_DIR_MAX, - 0, - chan->channel, - chan->channel2); - else - mask = IIO_UNMOD_EVENT_CODE(chan->type, - chan->channel, - i/IIO_EV_DIR_MAX, - i%IIO_EV_DIR_MAX); - - ret = __iio_add_chan_devattr(postfix, - chan, - &iio_ev_state_show, - iio_ev_state_store, - mask, - 0, - &indio_dev->dev, - &indio_dev->event_interface-> - dev_attr_list); - kfree(postfix); - if (ret) - goto error_ret; - attrcount++; - postfix = kasprintf(GFP_KERNEL, "%s_%s_value", - iio_ev_type_text[i/IIO_EV_DIR_MAX], - iio_ev_dir_text[i%IIO_EV_DIR_MAX]); - if (postfix == NULL) { - ret = -ENOMEM; - goto error_ret; - } - ret = __iio_add_chan_devattr(postfix, chan, - iio_ev_value_show, - iio_ev_value_store, - mask, - 0, - &indio_dev->dev, - &indio_dev->event_interface-> - dev_attr_list); - kfree(postfix); - if (ret) - goto error_ret; - attrcount++; - } - ret = attrcount; -error_ret: - return ret; -} - -static inline void __iio_remove_event_config_attrs(struct iio_dev *indio_dev) -{ - struct iio_dev_attr *p, *n; - list_for_each_entry_safe(p, n, - &indio_dev->event_interface-> - dev_attr_list, l) { - kfree(p->dev_attr.attr.name); - kfree(p); - } -} - -static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev) -{ - int j, ret, attrcount = 0; - - INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list); - /* Dynically created from the channels array */ - for (j = 0; j < indio_dev->num_channels; j++) { - ret = iio_device_add_event_sysfs(indio_dev, - &indio_dev->channels[j]); - if (ret < 0) - goto error_clear_attrs; - attrcount += ret; - } - return attrcount; - -error_clear_attrs: - __iio_remove_event_config_attrs(indio_dev); - - return ret; -} - -static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev) -{ - int j; - - for (j = 0; j < indio_dev->num_channels; j++) - if (indio_dev->channels[j].event_mask != 0) - return true; - return false; -} - -static void iio_setup_ev_int(struct iio_event_interface *ev_int) -{ - mutex_init(&ev_int->event_list_lock); - /* discussion point - make this variable? */ - ev_int->max_events = 10; - ev_int->current_events = 0; - INIT_LIST_HEAD(&ev_int->det_events); - init_waitqueue_head(&ev_int->wait); -} - -static const char *iio_event_group_name = "events"; -static int iio_device_register_eventset(struct iio_dev *indio_dev) -{ - struct iio_dev_attr *p; - int ret = 0, attrcount_orig = 0, attrcount, attrn; - struct attribute **attr; - - if (!(indio_dev->info->event_attrs || - iio_check_for_dynamic_events(indio_dev))) - return 0; - - indio_dev->event_interface = - kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL); - if (indio_dev->event_interface == NULL) { - ret = -ENOMEM; - goto error_ret; - } - - iio_setup_ev_int(indio_dev->event_interface); - if (indio_dev->info->event_attrs != NULL) { - attr = indio_dev->info->event_attrs->attrs; - while (*attr++ != NULL) - attrcount_orig++; - } - attrcount = attrcount_orig; - if (indio_dev->channels) { - ret = __iio_add_event_config_attrs(indio_dev); - if (ret < 0) - goto error_free_setup_event_lines; - attrcount += ret; - } - - indio_dev->event_interface->group.name = iio_event_group_name; - indio_dev->event_interface->group.attrs = kcalloc(attrcount + 1, - sizeof(indio_dev->event_interface->group.attrs[0]), - GFP_KERNEL); - if (indio_dev->event_interface->group.attrs == NULL) { - ret = -ENOMEM; - goto error_free_setup_event_lines; - } - if (indio_dev->info->event_attrs) - memcpy(indio_dev->event_interface->group.attrs, - indio_dev->info->event_attrs->attrs, - sizeof(indio_dev->event_interface->group.attrs[0]) - *attrcount_orig); - attrn = attrcount_orig; - /* Add all elements from the list. */ - list_for_each_entry(p, - &indio_dev->event_interface->dev_attr_list, - l) - indio_dev->event_interface->group.attrs[attrn++] = - &p->dev_attr.attr; - indio_dev->groups[indio_dev->groupcounter++] = - &indio_dev->event_interface->group; - - return 0; - -error_free_setup_event_lines: - __iio_remove_event_config_attrs(indio_dev); - kfree(indio_dev->event_interface); -error_ret: - - return ret; -} - -static void iio_device_unregister_eventset(struct iio_dev *indio_dev) -{ - if (indio_dev->event_interface == NULL) - return; - __iio_remove_event_config_attrs(indio_dev); - kfree(indio_dev->event_interface->group.attrs); - kfree(indio_dev->event_interface); -} - static void iio_dev_release(struct device *device) { struct iio_dev *indio_dev = container_of(device, struct iio_dev, dev); diff --git a/drivers/staging/iio/industrialio-event.c b/drivers/staging/iio/industrialio-event.c new file mode 100644 index 0000000000000..a7b345ddc257e --- /dev/null +++ b/drivers/staging/iio/industrialio-event.c @@ -0,0 +1,483 @@ +/* Industrial I/O event handling + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * Based on elements of hwmon and input subsystems. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "iio.h" +#include "iio_core.h" +#include "sysfs.h" +#include "events.h" + +/** + * struct iio_detected_event_list - list element for events that have occurred + * @list: linked list header + * @ev: the event itself + */ +struct iio_detected_event_list { + struct list_head list; + struct iio_event_data ev; +}; + +/** + * struct iio_event_interface - chrdev interface for an event line + * @wait: wait queue to allow blocking reads of events + * @event_list_lock: mutex to protect the list of detected events + * @det_events: list of detected events + * @max_events: maximum number of events before new ones are dropped + * @current_events: number of events in detected list + * @dev_attr_list: list of event interface sysfs attribute + * @flags: file operations related flags including busy flag. + * @group: event interface sysfs attribute group + */ +struct iio_event_interface { + wait_queue_head_t wait; + struct mutex event_list_lock; + struct list_head det_events; + int max_events; + int current_events; + struct list_head dev_attr_list; + unsigned long flags; + struct attribute_group group; +}; + +int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) +{ + struct iio_event_interface *ev_int = indio_dev->event_interface; + struct iio_detected_event_list *ev; + int ret = 0; + + /* Does anyone care? */ + mutex_lock(&ev_int->event_list_lock); + if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { + if (ev_int->current_events == ev_int->max_events) { + mutex_unlock(&ev_int->event_list_lock); + return 0; + } + ev = kmalloc(sizeof(*ev), GFP_KERNEL); + if (ev == NULL) { + ret = -ENOMEM; + mutex_unlock(&ev_int->event_list_lock); + goto error_ret; + } + ev->ev.id = ev_code; + ev->ev.timestamp = timestamp; + + list_add_tail(&ev->list, &ev_int->det_events); + ev_int->current_events++; + mutex_unlock(&ev_int->event_list_lock); + wake_up_interruptible(&ev_int->wait); + } else + mutex_unlock(&ev_int->event_list_lock); + +error_ret: + return ret; +} +EXPORT_SYMBOL(iio_push_event); + +static ssize_t iio_event_chrdev_read(struct file *filep, + char __user *buf, + size_t count, + loff_t *f_ps) +{ + struct iio_event_interface *ev_int = filep->private_data; + struct iio_detected_event_list *el; + size_t len = sizeof(el->ev); + int ret; + + if (count < len) + return -EINVAL; + + mutex_lock(&ev_int->event_list_lock); + if (list_empty(&ev_int->det_events)) { + if (filep->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + goto error_mutex_unlock; + } + mutex_unlock(&ev_int->event_list_lock); + /* Blocking on device; waiting for something to be there */ + ret = wait_event_interruptible(ev_int->wait, + !list_empty(&ev_int + ->det_events)); + if (ret) + goto error_ret; + /* Single access device so no one else can get the data */ + mutex_lock(&ev_int->event_list_lock); + } + + el = list_first_entry(&ev_int->det_events, + struct iio_detected_event_list, + list); + if (copy_to_user(buf, &(el->ev), len)) { + ret = -EFAULT; + goto error_mutex_unlock; + } + list_del(&el->list); + ev_int->current_events--; + mutex_unlock(&ev_int->event_list_lock); + kfree(el); + + return len; + +error_mutex_unlock: + mutex_unlock(&ev_int->event_list_lock); +error_ret: + + return ret; +} + +static int iio_event_chrdev_release(struct inode *inode, struct file *filep) +{ + struct iio_event_interface *ev_int = filep->private_data; + struct iio_detected_event_list *el, *t; + + mutex_lock(&ev_int->event_list_lock); + clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); + /* + * In order to maintain a clean state for reopening, + * clear out any awaiting events. The mask will prevent + * any new __iio_push_event calls running. + */ + list_for_each_entry_safe(el, t, &ev_int->det_events, list) { + list_del(&el->list); + kfree(el); + } + ev_int->current_events = 0; + mutex_unlock(&ev_int->event_list_lock); + + return 0; +} + +static const struct file_operations iio_event_chrdev_fileops = { + .read = iio_event_chrdev_read, + .release = iio_event_chrdev_release, + .owner = THIS_MODULE, + .llseek = noop_llseek, +}; + +int iio_event_getfd(struct iio_dev *indio_dev) +{ + struct iio_event_interface *ev_int = indio_dev->event_interface; + int fd; + + if (ev_int == NULL) + return -ENODEV; + + mutex_lock(&ev_int->event_list_lock); + if (test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { + mutex_unlock(&ev_int->event_list_lock); + return -EBUSY; + } + mutex_unlock(&ev_int->event_list_lock); + fd = anon_inode_getfd("iio:event", + &iio_event_chrdev_fileops, ev_int, O_RDONLY); + if (fd < 0) { + mutex_lock(&ev_int->event_list_lock); + clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); + mutex_unlock(&ev_int->event_list_lock); + } + return fd; +} + +static const char * const iio_ev_type_text[] = { + [IIO_EV_TYPE_THRESH] = "thresh", + [IIO_EV_TYPE_MAG] = "mag", + [IIO_EV_TYPE_ROC] = "roc", + [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", + [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", +}; + +static const char * const iio_ev_dir_text[] = { + [IIO_EV_DIR_EITHER] = "either", + [IIO_EV_DIR_RISING] = "rising", + [IIO_EV_DIR_FALLING] = "falling" +}; + +static ssize_t iio_ev_state_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + bool val; + + ret = strtobool(buf, &val); + if (ret < 0) + return ret; + + ret = indio_dev->info->write_event_config(indio_dev, + this_attr->address, + val); + return (ret < 0) ? ret : len; +} + +static ssize_t iio_ev_state_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int val = indio_dev->info->read_event_config(indio_dev, + this_attr->address); + + if (val < 0) + return val; + else + return sprintf(buf, "%d\n", val); +} + +static ssize_t iio_ev_value_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int val, ret; + + ret = indio_dev->info->read_event_value(indio_dev, + this_attr->address, &val); + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", val); +} + +static ssize_t iio_ev_value_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + unsigned long val; + int ret; + + if (!indio_dev->info->write_event_value) + return -EINVAL; + + ret = strict_strtoul(buf, 10, &val); + if (ret) + return ret; + + ret = indio_dev->info->write_event_value(indio_dev, this_attr->address, + val); + if (ret < 0) + return ret; + + return len; +} + +static int iio_device_add_event_sysfs(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + int ret = 0, i, attrcount = 0; + u64 mask = 0; + char *postfix; + if (!chan->event_mask) + return 0; + + for_each_set_bit(i, &chan->event_mask, sizeof(chan->event_mask)*8) { + postfix = kasprintf(GFP_KERNEL, "%s_%s_en", + iio_ev_type_text[i/IIO_EV_DIR_MAX], + iio_ev_dir_text[i%IIO_EV_DIR_MAX]); + if (postfix == NULL) { + ret = -ENOMEM; + goto error_ret; + } + if (chan->modified) + mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel, + i/IIO_EV_DIR_MAX, + i%IIO_EV_DIR_MAX); + else if (chan->differential) + mask = IIO_EVENT_CODE(chan->type, + 0, 0, + i%IIO_EV_DIR_MAX, + i/IIO_EV_DIR_MAX, + 0, + chan->channel, + chan->channel2); + else + mask = IIO_UNMOD_EVENT_CODE(chan->type, + chan->channel, + i/IIO_EV_DIR_MAX, + i%IIO_EV_DIR_MAX); + + ret = __iio_add_chan_devattr(postfix, + chan, + &iio_ev_state_show, + iio_ev_state_store, + mask, + 0, + &indio_dev->dev, + &indio_dev->event_interface-> + dev_attr_list); + kfree(postfix); + if (ret) + goto error_ret; + attrcount++; + postfix = kasprintf(GFP_KERNEL, "%s_%s_value", + iio_ev_type_text[i/IIO_EV_DIR_MAX], + iio_ev_dir_text[i%IIO_EV_DIR_MAX]); + if (postfix == NULL) { + ret = -ENOMEM; + goto error_ret; + } + ret = __iio_add_chan_devattr(postfix, chan, + iio_ev_value_show, + iio_ev_value_store, + mask, + 0, + &indio_dev->dev, + &indio_dev->event_interface-> + dev_attr_list); + kfree(postfix); + if (ret) + goto error_ret; + attrcount++; + } + ret = attrcount; +error_ret: + return ret; +} + +static inline void __iio_remove_event_config_attrs(struct iio_dev *indio_dev) +{ + struct iio_dev_attr *p, *n; + list_for_each_entry_safe(p, n, + &indio_dev->event_interface-> + dev_attr_list, l) { + kfree(p->dev_attr.attr.name); + kfree(p); + } +} + +static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev) +{ + int j, ret, attrcount = 0; + + INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list); + /* Dynically created from the channels array */ + for (j = 0; j < indio_dev->num_channels; j++) { + ret = iio_device_add_event_sysfs(indio_dev, + &indio_dev->channels[j]); + if (ret < 0) + goto error_clear_attrs; + attrcount += ret; + } + return attrcount; + +error_clear_attrs: + __iio_remove_event_config_attrs(indio_dev); + + return ret; +} + +static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev) +{ + int j; + + for (j = 0; j < indio_dev->num_channels; j++) + if (indio_dev->channels[j].event_mask != 0) + return true; + return false; +} + +static void iio_setup_ev_int(struct iio_event_interface *ev_int) +{ + mutex_init(&ev_int->event_list_lock); + /* discussion point - make this variable? */ + ev_int->max_events = 10; + ev_int->current_events = 0; + INIT_LIST_HEAD(&ev_int->det_events); + init_waitqueue_head(&ev_int->wait); +} + +static const char *iio_event_group_name = "events"; +int iio_device_register_eventset(struct iio_dev *indio_dev) +{ + struct iio_dev_attr *p; + int ret = 0, attrcount_orig = 0, attrcount, attrn; + struct attribute **attr; + + if (!(indio_dev->info->event_attrs || + iio_check_for_dynamic_events(indio_dev))) + return 0; + + indio_dev->event_interface = + kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL); + if (indio_dev->event_interface == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + iio_setup_ev_int(indio_dev->event_interface); + if (indio_dev->info->event_attrs != NULL) { + attr = indio_dev->info->event_attrs->attrs; + while (*attr++ != NULL) + attrcount_orig++; + } + attrcount = attrcount_orig; + if (indio_dev->channels) { + ret = __iio_add_event_config_attrs(indio_dev); + if (ret < 0) + goto error_free_setup_event_lines; + attrcount += ret; + } + + indio_dev->event_interface->group.name = iio_event_group_name; + indio_dev->event_interface->group.attrs = kcalloc(attrcount + 1, + sizeof(indio_dev->event_interface->group.attrs[0]), + GFP_KERNEL); + if (indio_dev->event_interface->group.attrs == NULL) { + ret = -ENOMEM; + goto error_free_setup_event_lines; + } + if (indio_dev->info->event_attrs) + memcpy(indio_dev->event_interface->group.attrs, + indio_dev->info->event_attrs->attrs, + sizeof(indio_dev->event_interface->group.attrs[0]) + *attrcount_orig); + attrn = attrcount_orig; + /* Add all elements from the list. */ + list_for_each_entry(p, + &indio_dev->event_interface->dev_attr_list, + l) + indio_dev->event_interface->group.attrs[attrn++] = + &p->dev_attr.attr; + indio_dev->groups[indio_dev->groupcounter++] = + &indio_dev->event_interface->group; + + return 0; + +error_free_setup_event_lines: + __iio_remove_event_config_attrs(indio_dev); + kfree(indio_dev->event_interface); +error_ret: + + return ret; +} + +void iio_device_unregister_eventset(struct iio_dev *indio_dev) +{ + if (indio_dev->event_interface == NULL) + return; + __iio_remove_event_config_attrs(indio_dev); + kfree(indio_dev->event_interface->group.attrs); + kfree(indio_dev->event_interface); +} From 28d2a4daadfa3466382c2505ceadd45b189de35b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 3 Jan 2012 14:59:39 +0100 Subject: [PATCH 067/261] staging:iio:events: Use kfifo for event queue The current IIO event code uses a list to emulate FIFO like behavior. Just use a kfifo directly instead to implement the event queue. As part of this patch the maximum of events in the queue is increased from 10 to 16 since kfifo requires a power of two for the number of FIFO elements. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/industrialio-event.c | 85 ++++++------------------ 1 file changed, 21 insertions(+), 64 deletions(-) diff --git a/drivers/staging/iio/industrialio-event.c b/drivers/staging/iio/industrialio-event.c index a7b345ddc257e..335b615bd1629 100644 --- a/drivers/staging/iio/industrialio-event.c +++ b/drivers/staging/iio/industrialio-event.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -23,23 +24,11 @@ #include "sysfs.h" #include "events.h" -/** - * struct iio_detected_event_list - list element for events that have occurred - * @list: linked list header - * @ev: the event itself - */ -struct iio_detected_event_list { - struct list_head list; - struct iio_event_data ev; -}; - /** * struct iio_event_interface - chrdev interface for an event line * @wait: wait queue to allow blocking reads of events * @event_list_lock: mutex to protect the list of detected events * @det_events: list of detected events - * @max_events: maximum number of events before new ones are dropped - * @current_events: number of events in detected list * @dev_attr_list: list of event interface sysfs attribute * @flags: file operations related flags including busy flag. * @group: event interface sysfs attribute group @@ -47,9 +36,8 @@ struct iio_detected_event_list { struct iio_event_interface { wait_queue_head_t wait; struct mutex event_list_lock; - struct list_head det_events; - int max_events; - int current_events; + DECLARE_KFIFO(det_events, struct iio_event_data, 16); + struct list_head dev_attr_list; unsigned long flags; struct attribute_group group; @@ -58,34 +46,25 @@ struct iio_event_interface { int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) { struct iio_event_interface *ev_int = indio_dev->event_interface; - struct iio_detected_event_list *ev; - int ret = 0; + struct iio_event_data ev; + int copied; /* Does anyone care? */ mutex_lock(&ev_int->event_list_lock); if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { - if (ev_int->current_events == ev_int->max_events) { - mutex_unlock(&ev_int->event_list_lock); - return 0; - } - ev = kmalloc(sizeof(*ev), GFP_KERNEL); - if (ev == NULL) { - ret = -ENOMEM; - mutex_unlock(&ev_int->event_list_lock); - goto error_ret; - } - ev->ev.id = ev_code; - ev->ev.timestamp = timestamp; - list_add_tail(&ev->list, &ev_int->det_events); - ev_int->current_events++; + ev.id = ev_code; + ev.timestamp = timestamp; + + copied = kfifo_put(&ev_int->det_events, &ev); + mutex_unlock(&ev_int->event_list_lock); - wake_up_interruptible(&ev_int->wait); + if (copied != 0) + wake_up_interruptible(&ev_int->wait); } else mutex_unlock(&ev_int->event_list_lock); -error_ret: - return ret; + return 0; } EXPORT_SYMBOL(iio_push_event); @@ -95,15 +74,14 @@ static ssize_t iio_event_chrdev_read(struct file *filep, loff_t *f_ps) { struct iio_event_interface *ev_int = filep->private_data; - struct iio_detected_event_list *el; - size_t len = sizeof(el->ev); + unsigned int copied; int ret; - if (count < len) + if (count < sizeof(struct iio_event_data)) return -EINVAL; mutex_lock(&ev_int->event_list_lock); - if (list_empty(&ev_int->det_events)) { + if (kfifo_is_empty(&ev_int->det_events)) { if (filep->f_flags & O_NONBLOCK) { ret = -EAGAIN; goto error_mutex_unlock; @@ -111,39 +89,25 @@ static ssize_t iio_event_chrdev_read(struct file *filep, mutex_unlock(&ev_int->event_list_lock); /* Blocking on device; waiting for something to be there */ ret = wait_event_interruptible(ev_int->wait, - !list_empty(&ev_int - ->det_events)); + !kfifo_is_empty(&ev_int->det_events)); if (ret) goto error_ret; /* Single access device so no one else can get the data */ mutex_lock(&ev_int->event_list_lock); } - el = list_first_entry(&ev_int->det_events, - struct iio_detected_event_list, - list); - if (copy_to_user(buf, &(el->ev), len)) { - ret = -EFAULT; - goto error_mutex_unlock; - } - list_del(&el->list); - ev_int->current_events--; mutex_unlock(&ev_int->event_list_lock); - kfree(el); - - return len; + ret = kfifo_to_user(&ev_int->det_events, buf, count, &copied); error_mutex_unlock: mutex_unlock(&ev_int->event_list_lock); error_ret: - - return ret; + return ret ? ret : copied; } static int iio_event_chrdev_release(struct inode *inode, struct file *filep) { struct iio_event_interface *ev_int = filep->private_data; - struct iio_detected_event_list *el, *t; mutex_lock(&ev_int->event_list_lock); clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); @@ -152,11 +116,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep) * clear out any awaiting events. The mask will prevent * any new __iio_push_event calls running. */ - list_for_each_entry_safe(el, t, &ev_int->det_events, list) { - list_del(&el->list); - kfree(el); - } - ev_int->current_events = 0; + kfifo_reset_out(&ev_int->det_events); mutex_unlock(&ev_int->event_list_lock); return 0; @@ -401,10 +361,7 @@ static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev) static void iio_setup_ev_int(struct iio_event_interface *ev_int) { mutex_init(&ev_int->event_list_lock); - /* discussion point - make this variable? */ - ev_int->max_events = 10; - ev_int->current_events = 0; - INIT_LIST_HEAD(&ev_int->det_events); + INIT_KFIFO(ev_int->det_events); init_waitqueue_head(&ev_int->wait); } From 4c022afaaa0847cb67ced23edf9a239638a20eef Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 3 Jan 2012 14:59:40 +0100 Subject: [PATCH 068/261] staging:iio:events: Use waitqueue lock to protect event queue Use the waitqueue lock to protect the event queue instead of a custom mutex. This has the advantage that we can call the waitqueue operations with the lock held, which simplifies the code flow a bit. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/industrialio-event.c | 43 ++++++++++-------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/drivers/staging/iio/industrialio-event.c b/drivers/staging/iio/industrialio-event.c index 335b615bd1629..f0c41f1f505a0 100644 --- a/drivers/staging/iio/industrialio-event.c +++ b/drivers/staging/iio/industrialio-event.c @@ -35,7 +35,6 @@ */ struct iio_event_interface { wait_queue_head_t wait; - struct mutex event_list_lock; DECLARE_KFIFO(det_events, struct iio_event_data, 16); struct list_head dev_attr_list; @@ -50,19 +49,17 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) int copied; /* Does anyone care? */ - mutex_lock(&ev_int->event_list_lock); + spin_lock(&ev_int->wait.lock); if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { ev.id = ev_code; ev.timestamp = timestamp; copied = kfifo_put(&ev_int->det_events, &ev); - - mutex_unlock(&ev_int->event_list_lock); if (copied != 0) - wake_up_interruptible(&ev_int->wait); - } else - mutex_unlock(&ev_int->event_list_lock); + wake_up_locked(&ev_int->wait); + } + spin_unlock(&ev_int->wait.lock); return 0; } @@ -80,28 +77,25 @@ static ssize_t iio_event_chrdev_read(struct file *filep, if (count < sizeof(struct iio_event_data)) return -EINVAL; - mutex_lock(&ev_int->event_list_lock); + spin_lock(&ev_int->wait.lock); if (kfifo_is_empty(&ev_int->det_events)) { if (filep->f_flags & O_NONBLOCK) { ret = -EAGAIN; - goto error_mutex_unlock; + goto error_unlock; } - mutex_unlock(&ev_int->event_list_lock); /* Blocking on device; waiting for something to be there */ - ret = wait_event_interruptible(ev_int->wait, + ret = wait_event_interruptible_locked(ev_int->wait, !kfifo_is_empty(&ev_int->det_events)); if (ret) - goto error_ret; + goto error_unlock; /* Single access device so no one else can get the data */ - mutex_lock(&ev_int->event_list_lock); } - mutex_unlock(&ev_int->event_list_lock); ret = kfifo_to_user(&ev_int->det_events, buf, count, &copied); -error_mutex_unlock: - mutex_unlock(&ev_int->event_list_lock); -error_ret: +error_unlock: + spin_unlock(&ev_int->wait.lock); + return ret ? ret : copied; } @@ -109,7 +103,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep) { struct iio_event_interface *ev_int = filep->private_data; - mutex_lock(&ev_int->event_list_lock); + spin_lock(&ev_int->wait.lock); clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); /* * In order to maintain a clean state for reopening, @@ -117,7 +111,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep) * any new __iio_push_event calls running. */ kfifo_reset_out(&ev_int->det_events); - mutex_unlock(&ev_int->event_list_lock); + spin_unlock(&ev_int->wait.lock); return 0; } @@ -137,18 +131,18 @@ int iio_event_getfd(struct iio_dev *indio_dev) if (ev_int == NULL) return -ENODEV; - mutex_lock(&ev_int->event_list_lock); + spin_lock(&ev_int->wait.lock); if (test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { - mutex_unlock(&ev_int->event_list_lock); + spin_unlock(&ev_int->wait.lock); return -EBUSY; } - mutex_unlock(&ev_int->event_list_lock); + spin_unlock(&ev_int->wait.lock); fd = anon_inode_getfd("iio:event", &iio_event_chrdev_fileops, ev_int, O_RDONLY); if (fd < 0) { - mutex_lock(&ev_int->event_list_lock); + spin_lock(&ev_int->wait.lock); clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); - mutex_unlock(&ev_int->event_list_lock); + spin_unlock(&ev_int->wait.lock); } return fd; } @@ -360,7 +354,6 @@ static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev) static void iio_setup_ev_int(struct iio_event_interface *ev_int) { - mutex_init(&ev_int->event_list_lock); INIT_KFIFO(ev_int->det_events); init_waitqueue_head(&ev_int->wait); } From c89fcd176a1b1435f56e4a9a829a587223b75e17 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 3 Jan 2012 14:59:41 +0100 Subject: [PATCH 069/261] staging:iio:events: Add poll support Add poll support to the event queue. This will allow us to check for pending events in a application's event loop using poll() or similar. Since we already have support for blocking reads adding poll support as well is trivial. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/industrialio-event.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/staging/iio/industrialio-event.c b/drivers/staging/iio/industrialio-event.c index f0c41f1f505a0..800f67d4cce15 100644 --- a/drivers/staging/iio/industrialio-event.c +++ b/drivers/staging/iio/industrialio-event.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -57,7 +58,7 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) copied = kfifo_put(&ev_int->det_events, &ev); if (copied != 0) - wake_up_locked(&ev_int->wait); + wake_up_locked_poll(&ev_int->wait, POLLIN); } spin_unlock(&ev_int->wait.lock); @@ -65,6 +66,25 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) } EXPORT_SYMBOL(iio_push_event); +/** + * iio_event_poll() - poll the event queue to find out if it has data + */ +static unsigned int iio_event_poll(struct file *filep, + struct poll_table_struct *wait) +{ + struct iio_event_interface *ev_int = filep->private_data; + unsigned int events = 0; + + poll_wait(filep, &ev_int->wait, wait); + + spin_lock(&ev_int->wait.lock); + if (!kfifo_is_empty(&ev_int->det_events)) + events = POLLIN | POLLRDNORM; + spin_unlock(&ev_int->wait.lock); + + return events; +} + static ssize_t iio_event_chrdev_read(struct file *filep, char __user *buf, size_t count, @@ -118,6 +138,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep) static const struct file_operations iio_event_chrdev_fileops = { .read = iio_event_chrdev_read, + .poll = iio_event_poll, .release = iio_event_chrdev_release, .owner = THIS_MODULE, .llseek = noop_llseek, From 1be1741746d91b9591e916e2edc6810fddee47fb Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 3 Jan 2012 14:59:42 +0100 Subject: [PATCH 070/261] staging:iio:events: Use non-atmoic bitops We always hold the waitqueue lock when modifying the flags field. So it is safe to use the non-atomic bitops here instead of the atomic versions. The lock has to be held, because we need to clear the busy flag and flush the event FIFO in one atomic operation when closing the event file descriptor. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/industrialio-event.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/industrialio-event.c b/drivers/staging/iio/industrialio-event.c index 800f67d4cce15..66d320bf30205 100644 --- a/drivers/staging/iio/industrialio-event.c +++ b/drivers/staging/iio/industrialio-event.c @@ -124,7 +124,7 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep) struct iio_event_interface *ev_int = filep->private_data; spin_lock(&ev_int->wait.lock); - clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); + __clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); /* * In order to maintain a clean state for reopening, * clear out any awaiting events. The mask will prevent @@ -153,7 +153,7 @@ int iio_event_getfd(struct iio_dev *indio_dev) return -ENODEV; spin_lock(&ev_int->wait.lock); - if (test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { + if (__test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { spin_unlock(&ev_int->wait.lock); return -EBUSY; } @@ -162,7 +162,7 @@ int iio_event_getfd(struct iio_dev *indio_dev) &iio_event_chrdev_fileops, ev_int, O_RDONLY); if (fd < 0) { spin_lock(&ev_int->wait.lock); - clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); + __clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); spin_unlock(&ev_int->wait.lock); } return fd; From fa35d693f8f550d5271d194aaf74efe27fedde48 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 29 Jan 2012 11:07:00 +0000 Subject: [PATCH 071/261] staging:iio:adc:ad7192 unwind use of is_visible for attribute group. It saves a couple of lines of code but reduces simplicity of code. I generally wish to discourage use of is_visible throughout IIO. Signed-off-by: Jonathan Cameron Acked-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/ad7192.c | 43 +++++++++++++++++++------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 9d251653307ca..9fd6d63d29997 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -822,25 +822,20 @@ static struct attribute *ad7192_attributes[] = { NULL }; -static umode_t ad7192_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7192_state *st = iio_priv(indio_dev); - - umode_t mode = attr->mode; - - if ((st->devid != ID_AD7195) && - (attr == &iio_dev_attr_ac_excitation_en.dev_attr.attr)) - mode = 0; - - return mode; -} - static const struct attribute_group ad7192_attribute_group = { .attrs = ad7192_attributes, - .is_visible = ad7192_attr_is_visible, +}; + +static struct attribute *ad7195_attributes[] = { + &iio_dev_attr_sampling_frequency.dev_attr.attr, + &iio_dev_attr_in_v_m_v_scale_available.dev_attr.attr, + &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, + &iio_dev_attr_bridge_switch_en.dev_attr.attr, + NULL +}; + +static const struct attribute_group ad7195_attribute_group = { + .attrs = ad7195_attributes, }; static int ad7192_read_raw(struct iio_dev *indio_dev, @@ -970,6 +965,15 @@ static const struct iio_info ad7192_info = { .driver_module = THIS_MODULE, }; +static const struct iio_info ad7195_info = { + .read_raw = &ad7192_read_raw, + .write_raw = &ad7192_write_raw, + .write_raw_get_fmt = &ad7192_write_raw_get_fmt, + .attrs = &ad7195_attribute_group, + .validate_trigger = ad7192_validate_trigger, + .driver_module = THIS_MODULE, +}; + #define AD7192_CHAN_DIFF(_chan, _chan2, _name, _address, _si) \ { .type = IIO_VOLTAGE, \ .differential = 1, \ @@ -1062,7 +1066,10 @@ static int __devinit ad7192_probe(struct spi_device *spi) indio_dev->channels = ad7192_channels; indio_dev->num_channels = ARRAY_SIZE(ad7192_channels); indio_dev->available_scan_masks = st->available_scan_masks; - indio_dev->info = &ad7192_info; + if (st->devid == ID_AD7195) + indio_dev->info = &ad7195_info; + else + indio_dev->info = &ad7192_info; for (i = 0; i < indio_dev->num_channels; i++) st->available_scan_masks[i] = (1 << i) | (1 << From 6e9574d74e592ac358ac070b1b2ca395de786588 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 29 Jan 2012 11:07:01 +0000 Subject: [PATCH 072/261] staging:iio:dds:ad9834 unwind use of is_visible for attrs. Trivial usecase in which just having two different attr groups covers all options. Slightly more code, but a simpler to follow result. Signed-off-by: Jonathan Cameron Acked-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dds/ad9834.c | 53 +++++++++++++++++++------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/drivers/staging/iio/dds/ad9834.c b/drivers/staging/iio/dds/ad9834.c index 5e67104fea18c..38a2de08626fb 100644 --- a/drivers/staging/iio/dds/ad9834.c +++ b/drivers/staging/iio/dds/ad9834.c @@ -281,29 +281,27 @@ static struct attribute *ad9834_attributes[] = { NULL, }; -static umode_t ad9834_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad9834_state *st = iio_priv(indio_dev); - - umode_t mode = attr->mode; - - if (((st->devid == ID_AD9833) || (st->devid == ID_AD9837)) && - ((attr == &iio_dev_attr_dds0_out1_enable.dev_attr.attr) || - (attr == &iio_dev_attr_dds0_out1_wavetype.dev_attr.attr) || - (attr == - &iio_dev_attr_dds0_out1_wavetype_available.dev_attr.attr) || - (attr == &iio_dev_attr_dds0_pincontrol_en.dev_attr.attr))) - mode = 0; - - return mode; -} +static struct attribute *ad9833_attributes[] = { + &iio_dev_attr_dds0_freq0.dev_attr.attr, + &iio_dev_attr_dds0_freq1.dev_attr.attr, + &iio_const_attr_dds0_freq_scale.dev_attr.attr, + &iio_dev_attr_dds0_phase0.dev_attr.attr, + &iio_dev_attr_dds0_phase1.dev_attr.attr, + &iio_const_attr_dds0_phase_scale.dev_attr.attr, + &iio_dev_attr_dds0_freqsymbol.dev_attr.attr, + &iio_dev_attr_dds0_phasesymbol.dev_attr.attr, + &iio_dev_attr_dds0_out_enable.dev_attr.attr, + &iio_dev_attr_dds0_out0_wavetype.dev_attr.attr, + &iio_dev_attr_dds0_out0_wavetype_available.dev_attr.attr, + NULL, +}; static const struct attribute_group ad9834_attribute_group = { .attrs = ad9834_attributes, - .is_visible = ad9834_attr_is_visible, +}; + +static const struct attribute_group ad9833_attribute_group = { + .attrs = ad9833_attributes, }; static const struct iio_info ad9834_info = { @@ -311,6 +309,11 @@ static const struct iio_info ad9834_info = { .driver_module = THIS_MODULE, }; +static const struct iio_info ad9833_info = { + .attrs = &ad9833_attribute_group, + .driver_module = THIS_MODULE, +}; + static int __devinit ad9834_probe(struct spi_device *spi) { struct ad9834_platform_data *pdata = spi->dev.platform_data; @@ -344,7 +347,15 @@ static int __devinit ad9834_probe(struct spi_device *spi) st->reg = reg; indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->info = &ad9834_info; + switch (st->devid) { + case ID_AD9833: + case ID_AD9837: + indio_dev->info = &ad9833_info; + break; + default: + indio_dev->info = &ad9834_info; + break; + } indio_dev->modes = INDIO_DIRECT_MODE; /* Setup default messages */ From f71f62e68dd596bf31a551119f410c67c1b0ce47 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 29 Jan 2012 11:07:02 +0000 Subject: [PATCH 073/261] staging:iio:dac:ad5446 unwind use of is_visible for attrs. Trivial case where no attributes are valid for some parts. Better handled using two iio_info structures and selecting the right one at probe time. Signed-off-by: Jonathan Cameron Acked-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5446.c | 33 ++++++++++---------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c index 693e7482524c2..e439baea33326 100644 --- a/drivers/staging/iio/dac/ad5446.c +++ b/drivers/staging/iio/dac/ad5446.c @@ -149,30 +149,8 @@ static struct attribute *ad5446_attributes[] = { NULL, }; -static umode_t ad5446_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5446_state *st = iio_priv(indio_dev); - - umode_t mode = attr->mode; - - if (!st->chip_info->store_pwr_down && - (attr == &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr || - attr == &iio_dev_attr_out_voltage_powerdown_mode. - dev_attr.attr || - attr == - &iio_const_attr_out_voltage_powerdown_mode_available. - dev_attr.attr)) - mode = 0; - - return mode; -} - static const struct attribute_group ad5446_attribute_group = { .attrs = ad5446_attributes, - .is_visible = ad5446_attr_is_visible, }; #define AD5446_CHANNEL(bits, storage, shift) { \ @@ -321,6 +299,12 @@ static const struct iio_info ad5446_info = { .driver_module = THIS_MODULE, }; +static const struct iio_info ad5446_info_no_pwr_down = { + .read_raw = ad5446_read_raw, + .write_raw = ad5446_write_raw, + .driver_module = THIS_MODULE, +}; + static int __devinit ad5446_probe(struct spi_device *spi) { struct ad5446_state *st; @@ -353,7 +337,10 @@ static int __devinit ad5446_probe(struct spi_device *spi) /* Estabilish that the iio_dev is a child of the spi device */ indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->info = &ad5446_info; + if (st->chip_info->store_pwr_down) + indio_dev->info = &ad5446_info; + else + indio_dev->info = &ad5446_info_no_pwr_down; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = &st->chip_info->channel; indio_dev->num_channels = 1; From 70f9dc4c59d699566e8c024c4694be7e2ce506d0 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 29 Jan 2012 11:07:03 +0000 Subject: [PATCH 074/261] staging:iio:adc:ad7606 unwind use of is_visible for attrs. This is the most controversial of this set of is_visible removals. There are two conditions controlling availability of attrs resulting in 4 different attribute groups. Still for a few more lines things are clearer to read to my mind. Signed-off-by: Jonathan Cameron Acked-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/ad7606_core.c | 83 +++++++++++++++++---------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index ddb7ef92f5c1b..97e8d3d4471e7 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -197,7 +197,7 @@ static IIO_DEVICE_ATTR(oversampling_ratio, S_IRUGO | S_IWUSR, ad7606_store_oversampling_ratio, 0); static IIO_CONST_ATTR(oversampling_ratio_available, "0 2 4 8 16 32 64"); -static struct attribute *ad7606_attributes[] = { +static struct attribute *ad7606_attributes_os_and_range[] = { &iio_dev_attr_in_voltage_range.dev_attr.attr, &iio_const_attr_in_voltage_range_available.dev_attr.attr, &iio_dev_attr_oversampling_ratio.dev_attr.attr, @@ -205,34 +205,28 @@ static struct attribute *ad7606_attributes[] = { NULL, }; -static umode_t ad7606_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7606_state *st = iio_priv(indio_dev); +static const struct attribute_group ad7606_attribute_group_os_and_range = { + .attrs = ad7606_attributes_os_and_range, +}; - umode_t mode = attr->mode; - - if (!(gpio_is_valid(st->pdata->gpio_os0) && - gpio_is_valid(st->pdata->gpio_os1) && - gpio_is_valid(st->pdata->gpio_os2)) && - (attr == &iio_dev_attr_oversampling_ratio.dev_attr.attr || - attr == - &iio_const_attr_oversampling_ratio_available.dev_attr.attr)) - mode = 0; - else if (!gpio_is_valid(st->pdata->gpio_range) && - (attr == &iio_dev_attr_in_voltage_range.dev_attr.attr || - attr == - &iio_const_attr_in_voltage_range_available.dev_attr.attr)) - mode = 0; - - return mode; -} +static struct attribute *ad7606_attributes_os[] = { + &iio_dev_attr_oversampling_ratio.dev_attr.attr, + &iio_const_attr_oversampling_ratio_available.dev_attr.attr, + NULL, +}; -static const struct attribute_group ad7606_attribute_group = { - .attrs = ad7606_attributes, - .is_visible = ad7606_attr_is_visible, +static const struct attribute_group ad7606_attribute_group_os = { + .attrs = ad7606_attributes_os, +}; + +static struct attribute *ad7606_attributes_range[] = { + &iio_dev_attr_in_voltage_range.dev_attr.attr, + &iio_const_attr_in_voltage_range_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7606_attribute_group_range = { + .attrs = ad7606_attributes_range, }; #define AD7606_CHANNEL(num) \ @@ -435,10 +429,27 @@ static irqreturn_t ad7606_interrupt(int irq, void *dev_id) return IRQ_HANDLED; }; -static const struct iio_info ad7606_info = { +static const struct iio_info ad7606_info_no_os_or_range = { .driver_module = THIS_MODULE, .read_raw = &ad7606_read_raw, - .attrs = &ad7606_attribute_group, +}; + +static const struct iio_info ad7606_info_os_and_range = { + .driver_module = THIS_MODULE, + .read_raw = &ad7606_read_raw, + .attrs = &ad7606_attribute_group_os_and_range, +}; + +static const struct iio_info ad7606_info_os = { + .driver_module = THIS_MODULE, + .read_raw = &ad7606_read_raw, + .attrs = &ad7606_attribute_group_os, +}; + +static const struct iio_info ad7606_info_range = { + .driver_module = THIS_MODULE, + .read_raw = &ad7606_read_raw, + .attrs = &ad7606_attribute_group_range, }; struct iio_dev *ad7606_probe(struct device *dev, int irq, @@ -483,7 +494,19 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, st->chip_info = &ad7606_chip_info_tbl[id]; indio_dev->dev.parent = dev; - indio_dev->info = &ad7606_info; + if (gpio_is_valid(st->pdata->gpio_os0) && + gpio_is_valid(st->pdata->gpio_os1) && + gpio_is_valid(st->pdata->gpio_os2)) { + if (gpio_is_valid(st->pdata->gpio_range)) + indio_dev->info = &ad7606_info_os_and_range; + else + indio_dev->info = &ad7606_info_os; + } else { + if (gpio_is_valid(st->pdata->gpio_range)) + indio_dev->info = &ad7606_info_range; + else + indio_dev->info = &ad7606_info_no_os_or_range; + } indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->name = st->chip_info->name; indio_dev->channels = st->chip_info->channels; From 7498ab58a65498599960afa5e0b85f3537b84e82 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 29 Jan 2012 11:07:04 +0000 Subject: [PATCH 075/261] staging:iio:adc:adt7310/7410 sticking plaster fix for broken event attrs. Neither of these drivers has ever been anywhere near the iio abi. Probably as a result of this the fact they had two event groups each was not picked up when we restricted IIO to having only 1 event line per device (as part of the chrdev merge set). As such these definitely didn't work before. This patch squishes the only element from the 'comparator' event line that isn't in the 'interrupt' one into it and kills off the 'comparator' one. Ultimately both of these drivers belong in hwmon not IIO and are just waiting here because I don't want to kill off a driver that may prove useful to someone. (Ultimately I will ask Greg to scrap these two if no one steps up to deal with them.) Signed-off-by: Jonathan Cameron Acked-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/adt7310.c | 21 ++++----------------- drivers/staging/iio/adc/adt7410.c | 21 ++++----------------- 2 files changed, 8 insertions(+), 34 deletions(-) diff --git a/drivers/staging/iio/adc/adt7310.c b/drivers/staging/iio/adc/adt7310.c index eec2f325d5494..caf57c1169b14 100644 --- a/drivers/staging/iio/adc/adt7310.c +++ b/drivers/staging/iio/adc/adt7310.c @@ -725,32 +725,19 @@ static struct attribute *adt7310_event_int_attributes[] = { &iio_dev_attr_fault_queue.dev_attr.attr, &iio_dev_attr_t_alarm_high.dev_attr.attr, &iio_dev_attr_t_alarm_low.dev_attr.attr, - &iio_dev_attr_t_hyst.dev_attr.attr, - NULL, -}; - -static struct attribute *adt7310_event_ct_attributes[] = { - &iio_dev_attr_event_mode.dev_attr.attr, - &iio_dev_attr_available_event_modes.dev_attr.attr, - &iio_dev_attr_fault_queue.dev_attr.attr, &iio_dev_attr_t_crit.dev_attr.attr, &iio_dev_attr_t_hyst.dev_attr.attr, NULL, }; -static struct attribute_group adt7310_event_attribute_group[ADT7310_IRQS] = { - { - .attrs = adt7310_event_int_attributes, - .name = "events", - }, { - .attrs = adt7310_event_ct_attributes, - .name = "events", - } +static struct attribute_group adt7310_event_attribute_group = { + .attrs = adt7310_event_int_attributes, + .name = "events", }; static const struct iio_info adt7310_info = { .attrs = &adt7310_attribute_group, - .event_attrs = adt7310_event_attribute_group, + .event_attrs = &adt7310_event_attribute_group, .driver_module = THIS_MODULE, }; diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c index c62248ceb37a2..dff3e8ca2d785 100644 --- a/drivers/staging/iio/adc/adt7410.c +++ b/drivers/staging/iio/adc/adt7410.c @@ -693,32 +693,19 @@ static struct attribute *adt7410_event_int_attributes[] = { &iio_dev_attr_fault_queue.dev_attr.attr, &iio_dev_attr_t_alarm_high.dev_attr.attr, &iio_dev_attr_t_alarm_low.dev_attr.attr, - &iio_dev_attr_t_hyst.dev_attr.attr, - NULL, -}; - -static struct attribute *adt7410_event_ct_attributes[] = { - &iio_dev_attr_event_mode.dev_attr.attr, - &iio_dev_attr_available_event_modes.dev_attr.attr, - &iio_dev_attr_fault_queue.dev_attr.attr, &iio_dev_attr_t_crit.dev_attr.attr, &iio_dev_attr_t_hyst.dev_attr.attr, NULL, }; -static struct attribute_group adt7410_event_attribute_group[ADT7410_IRQS] = { - { - .attrs = adt7410_event_int_attributes, - .name = "events", - }, { - .attrs = adt7410_event_ct_attributes, - .name = "events", - } +static struct attribute_group adt7410_event_attribute_group = { + .attrs = adt7410_event_int_attributes, + .name = "events", }; static const struct iio_info adt7410_info = { .attrs = &adt7410_attribute_group, - .event_attrs = adt7410_event_attribute_group, + .event_attrs = &adt7410_event_attribute_group, .driver_module = THIS_MODULE, }; From 7c4608e8ef2e7dc5bd309b29b91502e35931a63e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 11 Feb 2012 09:00:48 +0800 Subject: [PATCH 076/261] staging:iio:dac: Fix kcalloc parameters swapped The first parameter should be "number of elements" and the second parameter should be "element size". Signed-off-by: Axel Lin Acked-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5360.c | 4 ++-- drivers/staging/iio/dac/ad5380.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/iio/dac/ad5360.c b/drivers/staging/iio/dac/ad5360.c index 710b256affcc6..cec3693b50a37 100644 --- a/drivers/staging/iio/dac/ad5360.c +++ b/drivers/staging/iio/dac/ad5360.c @@ -439,8 +439,8 @@ static int __devinit ad5360_alloc_channels(struct iio_dev *indio_dev) struct iio_chan_spec *channels; unsigned int i; - channels = kcalloc(sizeof(struct iio_chan_spec), - st->chip_info->num_channels, GFP_KERNEL); + channels = kcalloc(st->chip_info->num_channels, + sizeof(struct iio_chan_spec), GFP_KERNEL); if (!channels) return -ENOMEM; diff --git a/drivers/staging/iio/dac/ad5380.c b/drivers/staging/iio/dac/ad5380.c index eff97ae05c4be..4c50716fa8015 100644 --- a/drivers/staging/iio/dac/ad5380.c +++ b/drivers/staging/iio/dac/ad5380.c @@ -363,8 +363,8 @@ static int __devinit ad5380_alloc_channels(struct iio_dev *indio_dev) struct iio_chan_spec *channels; unsigned int i; - channels = kcalloc(sizeof(struct iio_chan_spec), - st->chip_info->num_channels, GFP_KERNEL); + channels = kcalloc(st->chip_info->num_channels, + sizeof(struct iio_chan_spec), GFP_KERNEL); if (!channels) return -ENOMEM; From 50806102f67f2bb6a4ec11d2201edfb737ee9b62 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 13 Feb 2012 10:25:31 +0100 Subject: [PATCH 077/261] staging:iio:events: Remove obsolete documentation Commit 43ba1100 ("staging:iio:events: Use waitqueue lock to protect event queue") removed the event_list_lock field from the iio_event_interface struct, but missed to remove the same field from the documentation for that function. Signed-off-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/industrialio-event.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/iio/industrialio-event.c b/drivers/staging/iio/industrialio-event.c index 66d320bf30205..5fdf739e38f9d 100644 --- a/drivers/staging/iio/industrialio-event.c +++ b/drivers/staging/iio/industrialio-event.c @@ -28,7 +28,6 @@ /** * struct iio_event_interface - chrdev interface for an event line * @wait: wait queue to allow blocking reads of events - * @event_list_lock: mutex to protect the list of detected events * @det_events: list of detected events * @dev_attr_list: list of event interface sysfs attribute * @flags: file operations related flags including busy flag. From 4fdc677fd28d283b4fe3b8155929f13128d97908 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 13 Feb 2012 10:25:32 +0100 Subject: [PATCH 078/261] staging:iio: Rename IIO_EVENT_CODE_EXTRACT_NUM to IIO_EVENT_CODE_EXTRACT_CHAN We name this field "chan" throughout IIO with the exception of this one macro. Rename it to be more consistent. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/ad7291.c | 14 +++++++------- drivers/staging/iio/adc/ad799x_core.c | 4 ++-- drivers/staging/iio/adc/max1363_core.c | 12 ++++++------ drivers/staging/iio/cdc/ad7150.c | 10 +++++----- drivers/staging/iio/events.h | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c index 0a13616e3db91..81d6b6128cb00 100644 --- a/drivers/staging/iio/adc/ad7291.c +++ b/drivers/staging/iio/adc/ad7291.c @@ -321,7 +321,7 @@ static int ad7291_read_event_value(struct iio_dev *indio_dev, switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { case IIO_VOLTAGE: - reg = ad7291_limit_regs[IIO_EVENT_CODE_EXTRACT_NUM(event_code)] + reg = ad7291_limit_regs[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)] [!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING)]; @@ -359,7 +359,7 @@ static int ad7291_write_event_value(struct iio_dev *indio_dev, case IIO_VOLTAGE: if (val > AD7291_VALUE_MASK || val < 0) return -EINVAL; - reg = ad7291_limit_regs[IIO_EVENT_CODE_EXTRACT_NUM(event_code)] + reg = ad7291_limit_regs[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)] [!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING)]; return ad7291_i2c_write(chip, reg, val); @@ -386,7 +386,7 @@ static int ad7291_read_event_config(struct iio_dev *indio_dev, switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { case IIO_VOLTAGE: if (chip->c_mask & - (1 << (15 - IIO_EVENT_CODE_EXTRACT_NUM(event_code)))) + (1 << (15 - IIO_EVENT_CODE_EXTRACT_CHAN(event_code)))) return 1; else return 0; @@ -418,12 +418,12 @@ static int ad7291_write_event_config(struct iio_dev *indio_dev, switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { case IIO_VOLTAGE: if ((!state) && (chip->c_mask & (1 << (15 - - IIO_EVENT_CODE_EXTRACT_NUM(event_code))))) - chip->c_mask &= ~(1 << (15 - IIO_EVENT_CODE_EXTRACT_NUM + IIO_EVENT_CODE_EXTRACT_CHAN(event_code))))) + chip->c_mask &= ~(1 << (15 - IIO_EVENT_CODE_EXTRACT_CHAN (event_code))); else if (state && (!(chip->c_mask & (1 << (15 - - IIO_EVENT_CODE_EXTRACT_NUM(event_code)))))) - chip->c_mask |= (1 << (15 - IIO_EVENT_CODE_EXTRACT_NUM + IIO_EVENT_CODE_EXTRACT_CHAN(event_code)))))) + chip->c_mask |= (1 << (15 - IIO_EVENT_CODE_EXTRACT_CHAN (event_code))); else break; diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index d5b581d8bc2bf..a8458669350fb 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -256,7 +256,7 @@ static int ad799x_write_event_value(struct iio_dev *indio_dev, struct ad799x_state *st = iio_priv(indio_dev); int direction = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING); - int number = IIO_EVENT_CODE_EXTRACT_NUM(event_code); + int number = IIO_EVENT_CODE_EXTRACT_CHAN(event_code); mutex_lock(&indio_dev->mlock); ret = ad799x_i2c_write16(st, @@ -275,7 +275,7 @@ static int ad799x_read_event_value(struct iio_dev *indio_dev, struct ad799x_state *st = iio_priv(indio_dev); int direction = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING); - int number = IIO_EVENT_CODE_EXTRACT_NUM(event_code); + int number = IIO_EVENT_CODE_EXTRACT_CHAN(event_code); u16 valin; mutex_lock(&indio_dev->mlock); diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c index b92cb4af18ce4..3a5bd2084e645 100644 --- a/drivers/staging/iio/adc/max1363_core.c +++ b/drivers/staging/iio/adc/max1363_core.c @@ -543,9 +543,9 @@ static int max1363_read_thresh(struct iio_dev *indio_dev, { struct max1363_state *st = iio_priv(indio_dev); if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING) - *val = st->thresh_low[IIO_EVENT_CODE_EXTRACT_NUM(event_code)]; + *val = st->thresh_low[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)]; else - *val = st->thresh_high[IIO_EVENT_CODE_EXTRACT_NUM(event_code)]; + *val = st->thresh_high[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)]; return 0; } @@ -568,10 +568,10 @@ static int max1363_write_thresh(struct iio_dev *indio_dev, switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) { case IIO_EV_DIR_FALLING: - st->thresh_low[IIO_EVENT_CODE_EXTRACT_NUM(event_code)] = val; + st->thresh_low[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)] = val; break; case IIO_EV_DIR_RISING: - st->thresh_high[IIO_EVENT_CODE_EXTRACT_NUM(event_code)] = val; + st->thresh_high[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)] = val; break; } @@ -622,7 +622,7 @@ static int max1363_read_event_config(struct iio_dev *indio_dev, struct max1363_state *st = iio_priv(indio_dev); int val; - int number = IIO_EVENT_CODE_EXTRACT_NUM(event_code); + int number = IIO_EVENT_CODE_EXTRACT_CHAN(event_code); mutex_lock(&indio_dev->mlock); if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING) val = (1 << number) & st->mask_low; @@ -775,7 +775,7 @@ static int max1363_write_event_config(struct iio_dev *indio_dev, int ret = 0; struct max1363_state *st = iio_priv(indio_dev); u16 unifiedmask; - int number = IIO_EVENT_CODE_EXTRACT_NUM(event_code); + int number = IIO_EVENT_CODE_EXTRACT_CHAN(event_code); mutex_lock(&indio_dev->mlock); unifiedmask = st->mask_low | st->mask_high; diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index b73007dcf4b31..e4a08dc9b6f56 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -167,7 +167,7 @@ static int ad7150_write_event_params(struct iio_dev *indio_dev, u64 event_code) u16 value; u8 sens, timeout; struct ad7150_chip_info *chip = iio_priv(indio_dev); - int chan = IIO_EVENT_CODE_EXTRACT_NUM(event_code); + int chan = IIO_EVENT_CODE_EXTRACT_CHAN(event_code); int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING); @@ -279,7 +279,7 @@ static int ad7150_read_event_value(struct iio_dev *indio_dev, u64 event_code, int *val) { - int chan = IIO_EVENT_CODE_EXTRACT_NUM(event_code); + int chan = IIO_EVENT_CODE_EXTRACT_CHAN(event_code); struct ad7150_chip_info *chip = iio_priv(indio_dev); int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING); @@ -309,7 +309,7 @@ static int ad7150_write_event_value(struct iio_dev *indio_dev, { int ret; struct ad7150_chip_info *chip = iio_priv(indio_dev); - int chan = IIO_EVENT_CODE_EXTRACT_NUM(event_code); + int chan = IIO_EVENT_CODE_EXTRACT_CHAN(event_code); int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING); @@ -347,7 +347,7 @@ static ssize_t ad7150_show_timeout(struct device *dev, u8 value; /* use the event code for consistency reasons */ - int chan = IIO_EVENT_CODE_EXTRACT_NUM(this_attr->address); + int chan = IIO_EVENT_CODE_EXTRACT_CHAN(this_attr->address); int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(this_attr->address) == IIO_EV_DIR_RISING); @@ -373,7 +373,7 @@ static ssize_t ad7150_store_timeout(struct device *dev, struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad7150_chip_info *chip = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int chan = IIO_EVENT_CODE_EXTRACT_NUM(this_attr->address); + int chan = IIO_EVENT_CODE_EXTRACT_CHAN(this_attr->address); int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(this_attr->address) == IIO_EV_DIR_RISING); u8 data; diff --git a/drivers/staging/iio/events.h b/drivers/staging/iio/events.h index bfb63400fa606..416800e23651f 100644 --- a/drivers/staging/iio/events.h +++ b/drivers/staging/iio/events.h @@ -96,7 +96,7 @@ enum iio_event_direction { /* Event code number extraction depends on which type of event we have. * Perhaps review this function in the future*/ -#define IIO_EVENT_CODE_EXTRACT_NUM(mask) ((__s16)(mask & 0xFFFF)) +#define IIO_EVENT_CODE_EXTRACT_CHAN(mask) ((__s16)(mask & 0xFFFF)) #define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 40) & 0xFF) From cabebb6966a633102d5e5f5f136beb7db3849da5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 13 Feb 2012 10:25:33 +0100 Subject: [PATCH 079/261] staging:iio: Add missing event code extract macros Add macros for extracting whether the event is for a differential channel and the second channel number from the event code. These were the only two fields which did not have such an macro yet. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/events.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/iio/events.h b/drivers/staging/iio/events.h index 416800e23651f..c25f0e3c92e9f 100644 --- a/drivers/staging/iio/events.h +++ b/drivers/staging/iio/events.h @@ -97,7 +97,9 @@ enum iio_event_direction { /* Event code number extraction depends on which type of event we have. * Perhaps review this function in the future*/ #define IIO_EVENT_CODE_EXTRACT_CHAN(mask) ((__s16)(mask & 0xFFFF)) +#define IIO_EVENT_CODE_EXTRACT_CHAN2(mask) ((__s16)(((mask) >> 16) & 0xFFFF)) #define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 40) & 0xFF) +#define IIO_EVENT_CODE_EXTRACT_DIFF(mask) (((mask) >> 55) & 0x1) #endif From 95a9f809e5e983fa7deeedf750cc97b6cd4aa60a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 13 Feb 2012 10:25:34 +0100 Subject: [PATCH 080/261] staging:iio: Add event monitor example application Add a small evtest like application to monitor events generated by an IIO device. The application can be used as an example on how to listen for IIO events and also is usful for testing and debugging device drivers which generate IIO events. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- .../iio/Documentation/iio_event_monitor.c | 241 ++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 drivers/staging/iio/Documentation/iio_event_monitor.c diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c new file mode 100644 index 0000000000000..0d21a277305f4 --- /dev/null +++ b/drivers/staging/iio/Documentation/iio_event_monitor.c @@ -0,0 +1,241 @@ +/* Industrialio event test code. + * + * Copyright (c) 2011-2012 Lars-Peter Clausen + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is primarily intended as an example application. + * Reads the current buffer setup from sysfs and starts a short capture + * from the specified device, pretty printing the result after appropriate + * conversion. + * + * Usage: + * iio_event_monitor + * + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include "iio_utils.h" +#include "../events.h" + +static const char * const iio_chan_type_name_spec[] = { + [IIO_VOLTAGE] = "voltage", + [IIO_CURRENT] = "current", + [IIO_POWER] = "power", + [IIO_ACCEL] = "accel", + [IIO_ANGL_VEL] = "anglvel", + [IIO_MAGN] = "magn", + [IIO_LIGHT] = "illuminance", + [IIO_INTENSITY] = "intensity", + [IIO_PROXIMITY] = "proximity", + [IIO_TEMP] = "temp", + [IIO_INCLI] = "incli", + [IIO_ROT] = "rot", + [IIO_ANGL] = "angl", + [IIO_TIMESTAMP] = "timestamp", + [IIO_CAPACITANCE] = "capacitance", +}; + +static const char * const iio_ev_type_text[] = { + [IIO_EV_TYPE_THRESH] = "thresh", + [IIO_EV_TYPE_MAG] = "mag", + [IIO_EV_TYPE_ROC] = "roc", + [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", + [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", +}; + +static const char * const iio_ev_dir_text[] = { + [IIO_EV_DIR_EITHER] = "either", + [IIO_EV_DIR_RISING] = "rising", + [IIO_EV_DIR_FALLING] = "falling" +}; + +static const char * const iio_modifier_names[] = { + [IIO_MOD_X] = "x", + [IIO_MOD_Y] = "y", + [IIO_MOD_Z] = "z", + [IIO_MOD_LIGHT_BOTH] = "both", + [IIO_MOD_LIGHT_IR] = "ir", +}; + +static bool event_is_known(struct iio_event_data *event) +{ + enum iio_chan_type type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id); + enum iio_modifier mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id); + enum iio_event_type ev_type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id); + enum iio_event_direction dir = IIO_EVENT_CODE_EXTRACT_DIR(event->id); + + switch (type) { + case IIO_VOLTAGE: + case IIO_CURRENT: + case IIO_POWER: + case IIO_ACCEL: + case IIO_ANGL_VEL: + case IIO_MAGN: + case IIO_LIGHT: + case IIO_INTENSITY: + case IIO_PROXIMITY: + case IIO_TEMP: + case IIO_INCLI: + case IIO_ROT: + case IIO_ANGL: + case IIO_TIMESTAMP: + case IIO_CAPACITANCE: + break; + default: + return false; + } + + switch (mod) { + case IIO_NO_MOD: + case IIO_MOD_X: + case IIO_MOD_Y: + case IIO_MOD_Z: + case IIO_MOD_LIGHT_BOTH: + case IIO_MOD_LIGHT_IR: + break; + default: + return false; + } + + switch (ev_type) { + case IIO_EV_TYPE_THRESH: + case IIO_EV_TYPE_MAG: + case IIO_EV_TYPE_ROC: + case IIO_EV_TYPE_THRESH_ADAPTIVE: + case IIO_EV_TYPE_MAG_ADAPTIVE: + break; + default: + return false; + } + + switch (dir) { + case IIO_EV_DIR_EITHER: + case IIO_EV_DIR_RISING: + case IIO_EV_DIR_FALLING: + break; + default: + return false; + } + + return true; +} + +static void print_event(struct iio_event_data *event) +{ + enum iio_chan_type type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id); + enum iio_modifier mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id); + enum iio_event_type ev_type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id); + enum iio_event_direction dir = IIO_EVENT_CODE_EXTRACT_DIR(event->id); + int chan = IIO_EVENT_CODE_EXTRACT_CHAN(event->id); + int chan2 = IIO_EVENT_CODE_EXTRACT_CHAN2(event->id); + bool diff = IIO_EVENT_CODE_EXTRACT_DIFF(event->id); + + if (!event_is_known(event)) { + printf("Unknown event: time: %lld, id: %llx\n", + event->timestamp, event->id); + return; + } + + printf("Event: time: %lld, ", event->timestamp); + + if (mod != IIO_NO_MOD) { + printf("type: %s(%s), ", + iio_chan_type_name_spec[type], + iio_modifier_names[mod]); + } else { + printf("type: %s, ", + iio_chan_type_name_spec[type]); + } + + if (diff && chan >= 0 && chan2 >= 0) + printf("channel: %d-%d, ", chan, chan2); + else if (chan >= 0) + printf("channel: %d, ", chan); + + printf("evtype: %s, direction: %s\n", + iio_ev_type_text[ev_type], + iio_ev_dir_text[dir]); +} + +int main(int argc, char **argv) +{ + struct iio_event_data event; + const char *device_name; + char *chrdev_name; + int ret; + int dev_num; + int fd, event_fd; + + if (argc <= 1) { + printf("Usage: %s \n", argv[0]); + return -1; + } + + device_name = argv[1]; + + dev_num = find_type_by_name(device_name, "iio:device"); + if (dev_num >= 0) { + printf("Found IIO device with name %s with device number %d\n", + device_name, dev_num); + ret = asprintf(&chrdev_name, "/dev/iio:device%d", dev_num); + if (ret < 0) { + ret = -ENOMEM; + goto error_ret; + } + } else { + /* If we can't find a IIO device by name assume device_name is a + IIO chrdev */ + chrdev_name = strdup(device_name); + } + + fd = open(chrdev_name, 0); + if (fd == -1) { + fprintf(stdout, "Failed to open %s\n", chrdev_name); + ret = -errno; + goto error_free_chrdev_name; + } + + ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd); + + close(fd); + + if (ret == -1 || event_fd == -1) { + fprintf(stdout, "Failed to retrieve event fd\n"); + ret = -errno; + goto error_free_chrdev_name; + } + + while (true) { + ret = read(event_fd, &event, sizeof(event)); + if (ret == -1) { + if (errno == EAGAIN) { + printf("nothing available\n"); + continue; + } else { + perror("Failed to read event from device"); + ret = -errno; + break; + } + } + + print_event(&event); + } + + close(event_fd); +error_free_chrdev_name: + free(chrdev_name); +error_ret: + return ret; +} From 389779fec1d7ee740aac3d0987999e61ce2516fa Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Tue, 14 Feb 2012 19:44:56 +0100 Subject: [PATCH 081/261] staging: iio: LPC32xx: ADC driver This patch adds a 3-channel ADC driver for the LPC32xx ARM SoC Signed-off-by: Roland Stigge Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/Kconfig | 9 + drivers/staging/iio/adc/Makefile | 1 + drivers/staging/iio/adc/lpc32xx_adc.c | 237 ++++++++++++++++++++++++++ 3 files changed, 247 insertions(+) create mode 100644 drivers/staging/iio/adc/lpc32xx_adc.c diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index d9decea4fa620..592eabd85f365 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -193,4 +193,13 @@ config MAX1363_RING_BUFFER Say yes here to include ring buffer support in the MAX1363 ADC driver. +config LPC32XX_ADC + tristate "NXP LPC32XX ADC" + depends on ARCH_LPC32XX && !TOUCHSCREEN_LPC32XX + help + Say yes here to build support for the integrated ADC inside the + LPC32XX SoC. Note that this feature uses the same hardware as the + touchscreen driver, so you can only select one of the two drivers + (lpc32xx_adc or lpc32xx_ts). Provides direct access via sysfs. + endmenu diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile index ceee7f3c3061a..f83ab9551d8ee 100644 --- a/drivers/staging/iio/adc/Makefile +++ b/drivers/staging/iio/adc/Makefile @@ -37,3 +37,4 @@ obj-$(CONFIG_AD7192) += ad7192.o obj-$(CONFIG_ADT7310) += adt7310.o obj-$(CONFIG_ADT7410) += adt7410.o obj-$(CONFIG_AD7280) += ad7280a.o +obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c new file mode 100644 index 0000000000000..dfc9033843a37 --- /dev/null +++ b/drivers/staging/iio/adc/lpc32xx_adc.c @@ -0,0 +1,237 @@ +/* + * lpc32xx_adc.c - Support for ADC in LPC32XX + * + * 3-channel, 10-bit ADC + * + * Copyright (C) 2011, 2012 Roland Stigge + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +/* + * LPC32XX registers definitions + */ +#define LPC32XX_ADC_SELECT(x) ((x) + 0x04) +#define LPC32XX_ADC_CTRL(x) ((x) + 0x08) +#define LPC32XX_ADC_VALUE(x) ((x) + 0x48) + +/* Bit definitions for LPC32XX_ADC_SELECT: */ +#define AD_REFm 0x00000200 /* constant, always write this value! */ +#define AD_REFp 0x00000080 /* constant, always write this value! */ +#define AD_IN 0x00000010 /* multiple of this is the */ + /* channel number: 0, 1, 2 */ +#define AD_INTERNAL 0x00000004 /* constant, always write this value! */ + +/* Bit definitions for LPC32XX_ADC_CTRL: */ +#define AD_STROBE 0x00000002 +#define AD_PDN_CTRL 0x00000004 + +/* Bit definitions for LPC32XX_ADC_VALUE: */ +#define ADC_VALUE_MASK 0x000003FF + +#define MOD_NAME "lpc32xx-adc" + +struct lpc32xx_adc_info { + void __iomem *adc_base; + struct clk *clk; + struct completion completion; + + u32 value; +}; + +static int lpc32xx_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + struct lpc32xx_adc_info *info = iio_priv(indio_dev); + + if (mask == 0) { + mutex_lock(&indio_dev->mlock); + clk_enable(info->clk); + /* Measurement setup */ + __raw_writel(AD_INTERNAL | (chan->address) | AD_REFp | AD_REFm, + LPC32XX_ADC_SELECT(info->adc_base)); + /* Trigger conversion */ + __raw_writel(AD_PDN_CTRL | AD_STROBE, + LPC32XX_ADC_CTRL(info->adc_base)); + wait_for_completion(&info->completion); /* set by ISR */ + clk_disable(info->clk); + *val = info->value; + mutex_unlock(&indio_dev->mlock); + + return IIO_VAL_INT; + } + + return -EINVAL; +} + +static const struct iio_info lpc32xx_adc_iio_info = { + .read_raw = &lpc32xx_read_raw, + .driver_module = THIS_MODULE, +}; + +#define LPC32XX_ADC_CHANNEL(_index) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = _index, \ + .address = AD_IN * _index, \ + .scan_index = _index, \ +} + +static struct iio_chan_spec lpc32xx_adc_iio_channels[] = { + LPC32XX_ADC_CHANNEL(0), + LPC32XX_ADC_CHANNEL(1), + LPC32XX_ADC_CHANNEL(2), +}; + +static irqreturn_t lpc32xx_adc_isr(int irq, void *dev_id) +{ + struct lpc32xx_adc_info *info = (struct lpc32xx_adc_info *) dev_id; + + /* Read value and clear irq */ + info->value = __raw_readl(LPC32XX_ADC_VALUE(info->adc_base)) & + ADC_VALUE_MASK; + complete(&info->completion); + + return IRQ_HANDLED; +} + +static int __devinit lpc32xx_adc_probe(struct platform_device *pdev) +{ + struct lpc32xx_adc_info *info = NULL; + struct resource *res; + int retval = -ENODEV; + struct iio_dev *iodev = NULL; + int irq; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "failed to get platform I/O memory\n"); + retval = -EBUSY; + goto errout1; + } + + iodev = iio_allocate_device(sizeof(struct lpc32xx_adc_info)); + if (!iodev) { + dev_err(&pdev->dev, "failed allocating iio device\n"); + retval = -ENOMEM; + goto errout1; + } + + info = iio_priv(iodev); + + info->adc_base = ioremap(res->start, res->end - res->start + 1); + if (!info->adc_base) { + dev_err(&pdev->dev, "failed mapping memory\n"); + retval = -EBUSY; + goto errout2; + } + + info->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(info->clk)) { + dev_err(&pdev->dev, "failed getting clock\n"); + goto errout3; + } + + irq = platform_get_irq(pdev, 0); + if ((irq < 0) || (irq >= NR_IRQS)) { + dev_err(&pdev->dev, "failed getting interrupt resource\n"); + retval = -EINVAL; + goto errout4; + } + + retval = request_irq(irq, lpc32xx_adc_isr, 0, MOD_NAME, info); + if (retval < 0) { + dev_err(&pdev->dev, "failed requesting interrupt\n"); + goto errout4; + } + + platform_set_drvdata(pdev, iodev); + + init_completion(&info->completion); + + iodev->name = MOD_NAME; + iodev->dev.parent = &pdev->dev; + iodev->info = &lpc32xx_adc_iio_info; + iodev->modes = INDIO_DIRECT_MODE; + iodev->channels = lpc32xx_adc_iio_channels; + iodev->num_channels = ARRAY_SIZE(lpc32xx_adc_iio_channels); + + retval = iio_device_register(iodev); + if (retval) + goto errout5; + + dev_info(&pdev->dev, "LPC32XX ADC driver loaded, IRQ %d\n", irq); + + return 0; + +errout5: + free_irq(irq, iodev); +errout4: + clk_put(info->clk); +errout3: + iounmap(info->adc_base); +errout2: + iio_free_device(iodev); +errout1: + return retval; +} + +static int __devexit lpc32xx_adc_remove(struct platform_device *pdev) +{ + struct iio_dev *iodev = platform_get_drvdata(pdev); + struct lpc32xx_adc_info *info = iio_priv(iodev); + int irq = platform_get_irq(pdev, 0); + + iio_device_unregister(iodev); + free_irq(irq, iodev); + platform_set_drvdata(pdev, NULL); + clk_put(info->clk); + iounmap(info->adc_base); + iio_free_device(iodev); + + return 0; +} + +static struct platform_driver lpc32xx_adc_driver = { + .probe = lpc32xx_adc_probe, + .remove = __devexit_p(lpc32xx_adc_remove), + .driver = { + .name = MOD_NAME, + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(lpc32xx_adc_driver); + +MODULE_AUTHOR("Roland Stigge "); +MODULE_DESCRIPTION("LPC32XX ADC driver"); +MODULE_LICENSE("GPL"); From 20da942b604054b1c9547d03305b81c8644c8cd9 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 15 Feb 2012 19:48:00 +0000 Subject: [PATCH 082/261] staging:iio:core set the iio_dev.info pointer to null on unregister under lock. This prevents use of provider callbacks after it has been unregistered. Note that all code using this that can be called from a consumer *must* check the pointer before using and hold the info_exist_lock throughout the usage of the callbacks in info. Signed-off-by: Jonathan Cameron Acked-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/iio.h | 2 ++ drivers/staging/iio/industrialio-core.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h index be6ced31f65e6..478dbe5924cbd 100644 --- a/drivers/staging/iio/iio.h +++ b/drivers/staging/iio/iio.h @@ -310,6 +310,7 @@ struct iio_buffer_setup_ops { * @chan_attr_group: [INTERN] group for all attrs in base directory * @name: [DRIVER] name of the device. * @info: [DRIVER] callbacks and constant info from driver + * @info_exist_lock: [INTERN] lock to prevent use during removal * @chrdev: [INTERN] associated character device * @groups: [INTERN] attribute groups * @groupcounter: [INTERN] index of next attribute group @@ -340,6 +341,7 @@ struct iio_dev { struct attribute_group chan_attr_group; const char *name; const struct iio_info *info; + struct mutex info_exist_lock; const struct iio_buffer_setup_ops *setup_ops; struct cdev chrdev; #define IIO_MAX_GROUPS 6 diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index e4824fe8b4051..3a2d080266245 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -594,6 +594,7 @@ struct iio_dev *iio_allocate_device(int sizeof_priv) device_initialize(&dev->dev); dev_set_drvdata(&dev->dev, (void *)dev); mutex_init(&dev->mlock); + mutex_init(&dev->info_exist_lock); dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); if (dev->id < 0) { @@ -718,6 +719,9 @@ EXPORT_SYMBOL(iio_device_register); void iio_device_unregister(struct iio_dev *indio_dev) { + mutex_lock(&indio_dev->info_exist_lock); + indio_dev->info = NULL; + mutex_unlock(&indio_dev->info_exist_lock); device_unregister(&indio_dev->dev); } EXPORT_SYMBOL(iio_device_unregister); From 87c5625db21d3c6aff014a827582172e9ad5eb2c Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 15 Feb 2012 19:48:01 +0000 Subject: [PATCH 083/261] staging:iio:core add in kernel interface mapping and getting IIO channels. Lifted from proposal for in kernel interface built on the out of staging branch. Two elements here: * Map as defined in "inkern.h" * Matching code to actually get the iio_dev and channel that we want from the global list of IIO devices. V4: Everything now built if iio is built (rather than being optional) Removal race condition prevented by using info pointer as a check of removal under a lock. V3: Drop the option of registering / getting channels using dev pointer. Stick to name only as suggested by Mark Brown (this has caused user confusion in the regulator framework.) V2: As per Greg KH suggestion, move over to registration by passing the tables into the provider drivers (how regulator does it). This does not prevent us using the original more flexible approach if at a later date there is a usecase that demands it. Signed-off-by: Jonathan Cameron Acked-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/Makefile | 2 +- drivers/staging/iio/consumer.h | 96 +++++++++++ drivers/staging/iio/driver.h | 34 ++++ drivers/staging/iio/inkern.c | 292 +++++++++++++++++++++++++++++++++ drivers/staging/iio/machine.h | 24 +++ 5 files changed, 447 insertions(+), 1 deletion(-) create mode 100644 drivers/staging/iio/consumer.h create mode 100644 drivers/staging/iio/driver.h create mode 100644 drivers/staging/iio/inkern.c create mode 100644 drivers/staging/iio/machine.h diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile index 657710b266b01..ff059d448c2ea 100644 --- a/drivers/staging/iio/Makefile +++ b/drivers/staging/iio/Makefile @@ -3,7 +3,7 @@ # obj-$(CONFIG_IIO) += industrialio.o -industrialio-y := industrialio-core.o industrialio-event.o +industrialio-y := industrialio-core.o industrialio-event.o inkern.o industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o diff --git a/drivers/staging/iio/consumer.h b/drivers/staging/iio/consumer.h new file mode 100644 index 0000000000000..36a060cd3a21d --- /dev/null +++ b/drivers/staging/iio/consumer.h @@ -0,0 +1,96 @@ +/* + * Industrial I/O in kernel consumer interface + * + * Copyright (c) 2011 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#ifndef _IIO_INKERN_CONSUMER_H_ +#define _IIO_INKERN_CONSUMER_H +#include "types.h" + +struct iio_dev; +struct iio_chan_spec; + +/** + * struct iio_channel - everything needed for a consumer to use a channel + * @indio_dev: Device on which the channel exists. + * @channel: Full description of the channel. + */ +struct iio_channel { + struct iio_dev *indio_dev; + const struct iio_chan_spec *channel; +}; + +/** + * iio_channel_get() - get description of all that is needed to access channel. + * @name: Unique name of the device as provided in the iio_map + * with which the desired provider to consumer mapping + * was registered. + * @consumer_channel: Unique name to identify the channel on the consumer + * side. This typically describes the channels use within + * the consumer. E.g. 'battery_voltage' + */ +struct iio_channel *iio_st_channel_get(const char *name, + const char *consumer_channel); + +/** + * iio_st_channel_release() - release channels obtained via iio_st_channel_get + * @chan: The channel to be released. + */ +void iio_st_channel_release(struct iio_channel *chan); + +/** + * iio_st_channel_get_all() - get all channels associated with a client + * @name: name of consumer device. + * + * Returns an array of iio_channel structures terminated with one with + * null iio_dev pointer. + * This function is used by fairly generic consumers to get all the + * channels registered as having this consumer. + */ +struct iio_channel *iio_st_channel_get_all(const char *name); + +/** + * iio_st_channel_release_all() - reverse iio_st_get_all + * @chan: Array of channels to be released. + */ +void iio_st_channel_release_all(struct iio_channel *chan); + +/** + * iio_st_read_channel_raw() - read from a given channel + * @channel: The channel being queried. + * @val: Value read back. + * + * Note raw reads from iio channels are in adc counts and hence + * scale will need to be applied if standard units required. + */ +int iio_st_read_channel_raw(struct iio_channel *chan, + int *val); + +/** + * iio_st_get_channel_type() - get the type of a channel + * @channel: The channel being queried. + * @type: The type of the channel. + * + * returns the enum iio_chan_type of the channel + */ +int iio_st_get_channel_type(struct iio_channel *channel, + enum iio_chan_type *type); + +/** + * iio_st_read_channel_scale() - read the scale value for a channel + * @channel: The channel being queried. + * @val: First part of value read back. + * @val2: Second part of value read back. + * + * Note returns a description of what is in val and val2, such + * as IIO_VAL_INT_PLUS_MICRO telling us we have a value of val + * + val2/1e6 + */ +int iio_st_read_channel_scale(struct iio_channel *chan, int *val, + int *val2); + +#endif diff --git a/drivers/staging/iio/driver.h b/drivers/staging/iio/driver.h new file mode 100644 index 0000000000000..a4f8b2e05af5e --- /dev/null +++ b/drivers/staging/iio/driver.h @@ -0,0 +1,34 @@ +/* + * Industrial I/O in kernel access map interface. + * + * Copyright (c) 2011 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#ifndef _IIO_INKERN_H_ +#define _IIO_INKERN_H_ + +struct iio_map; + +/** + * iio_map_array_register() - tell the core about inkernel consumers + * @indio_dev: provider device + * @map: array of mappings specifying association of channel with client + */ +int iio_map_array_register(struct iio_dev *indio_dev, + struct iio_map *map); + +/** + * iio_map_array_unregister() - tell the core to remove consumer mappings + * @indio_dev: provider device + * @map: array of mappings to remove. Note these must have same memory + * addresses as those originally added not just equal parameter + * values. + */ +int iio_map_array_unregister(struct iio_dev *indio_dev, + struct iio_map *map); + +#endif diff --git a/drivers/staging/iio/inkern.c b/drivers/staging/iio/inkern.c new file mode 100644 index 0000000000000..de2c8ea649653 --- /dev/null +++ b/drivers/staging/iio/inkern.c @@ -0,0 +1,292 @@ +/* The industrial I/O core in kernel channel mapping + * + * Copyright (c) 2011 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#include +#include +#include +#include + +#include "iio.h" +#include "iio_core.h" +#include "machine.h" +#include "driver.h" +#include "consumer.h" + +struct iio_map_internal { + struct iio_dev *indio_dev; + struct iio_map *map; + struct list_head l; +}; + +static LIST_HEAD(iio_map_list); +static DEFINE_MUTEX(iio_map_list_lock); + +int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps) +{ + int i = 0, ret = 0; + struct iio_map_internal *mapi; + + if (maps == NULL) + return 0; + + mutex_lock(&iio_map_list_lock); + while (maps[i].consumer_dev_name != NULL) { + mapi = kzalloc(sizeof(*mapi), GFP_KERNEL); + if (mapi == NULL) { + ret = -ENOMEM; + goto error_ret; + } + mapi->map = &maps[i]; + mapi->indio_dev = indio_dev; + list_add(&mapi->l, &iio_map_list); + i++; + } +error_ret: + mutex_unlock(&iio_map_list_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_map_array_register); + + +/* Assumes the exact same array (e.g. memory locations) + * used at unregistration as used at registration rather than + * more complex checking of contents. + */ +int iio_map_array_unregister(struct iio_dev *indio_dev, + struct iio_map *maps) +{ + int i = 0, ret = 0; + bool found_it; + struct iio_map_internal *mapi; + + if (maps == NULL) + return 0; + + mutex_lock(&iio_map_list_lock); + while (maps[i].consumer_dev_name != NULL) { + found_it = false; + list_for_each_entry(mapi, &iio_map_list, l) + if (&maps[i] == mapi->map) { + list_del(&mapi->l); + kfree(mapi); + found_it = true; + break; + } + if (found_it == false) { + ret = -ENODEV; + goto error_ret; + } + } +error_ret: + mutex_unlock(&iio_map_list_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_map_array_unregister); + +static const struct iio_chan_spec +*iio_chan_spec_from_name(const struct iio_dev *indio_dev, + const char *name) +{ + int i; + const struct iio_chan_spec *chan = NULL; + + for (i = 0; i < indio_dev->num_channels; i++) + if (indio_dev->channels[i].datasheet_name && + strcmp(name, indio_dev->channels[i].datasheet_name) == 0) { + chan = &indio_dev->channels[i]; + break; + } + return chan; +} + + +struct iio_channel *iio_st_channel_get(const char *name, + const char *channel_name) +{ + struct iio_map_internal *c_i = NULL, *c = NULL; + struct iio_channel *channel; + + if (name == NULL && channel_name == NULL) + return ERR_PTR(-ENODEV); + + /* first find matching entry the channel map */ + mutex_lock(&iio_map_list_lock); + list_for_each_entry(c_i, &iio_map_list, l) { + if ((name && strcmp(name, c_i->map->consumer_dev_name) != 0) || + (channel_name && + strcmp(channel_name, c_i->map->consumer_channel) != 0)) + continue; + c = c_i; + get_device(&c->indio_dev->dev); + break; + } + mutex_unlock(&iio_map_list_lock); + if (c == NULL) + return ERR_PTR(-ENODEV); + + channel = kmalloc(sizeof(*channel), GFP_KERNEL); + if (channel == NULL) + return ERR_PTR(-ENOMEM); + + channel->indio_dev = c->indio_dev; + + if (c->map->adc_channel_label) + channel->channel = + iio_chan_spec_from_name(channel->indio_dev, + c->map->adc_channel_label); + + return channel; +} +EXPORT_SYMBOL_GPL(iio_st_channel_get); + +void iio_st_channel_release(struct iio_channel *channel) +{ + put_device(&channel->indio_dev->dev); + kfree(channel); +} +EXPORT_SYMBOL_GPL(iio_st_channel_release); + +struct iio_channel *iio_st_channel_get_all(const char *name) +{ + struct iio_channel *chans; + struct iio_map_internal *c = NULL; + int nummaps = 0; + int mapind = 0; + int i, ret; + + if (name == NULL) + return ERR_PTR(-EINVAL); + + mutex_lock(&iio_map_list_lock); + /* first count the matching maps */ + list_for_each_entry(c, &iio_map_list, l) + if (name && strcmp(name, c->map->consumer_dev_name) != 0) + continue; + else + nummaps++; + + if (nummaps == 0) { + ret = -ENODEV; + goto error_ret; + } + + /* NULL terminated array to save passing size */ + chans = kzalloc(sizeof(*chans)*(nummaps + 1), GFP_KERNEL); + if (chans == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + /* for each map fill in the chans element */ + list_for_each_entry(c, &iio_map_list, l) { + if (name && strcmp(name, c->map->consumer_dev_name) != 0) + continue; + chans[mapind].indio_dev = c->indio_dev; + chans[mapind].channel = + iio_chan_spec_from_name(chans[mapind].indio_dev, + c->map->adc_channel_label); + if (chans[mapind].channel == NULL) { + ret = -EINVAL; + put_device(&chans[mapind].indio_dev->dev); + goto error_free_chans; + } + get_device(&chans[mapind].indio_dev->dev); + mapind++; + } + mutex_unlock(&iio_map_list_lock); + if (mapind == 0) { + ret = -ENODEV; + goto error_free_chans; + } + return chans; + +error_free_chans: + for (i = 0; i < nummaps; i++) + if (chans[i].indio_dev) + put_device(&chans[i].indio_dev->dev); + kfree(chans); +error_ret: + mutex_unlock(&iio_map_list_lock); + + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(iio_st_channel_get_all); + +void iio_st_channel_release_all(struct iio_channel *channels) +{ + struct iio_channel *chan = &channels[0]; + + while (chan->indio_dev) { + put_device(&chan->indio_dev->dev); + chan++; + } + kfree(channels); +} +EXPORT_SYMBOL_GPL(iio_st_channel_release_all); + +int iio_st_read_channel_raw(struct iio_channel *chan, int *val) +{ + int val2, ret; + + mutex_lock(&chan->indio_dev->info_exist_lock); + if (chan->indio_dev->info == NULL) { + ret = -ENODEV; + goto err_unlock; + } + + ret = chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel, + val, &val2, 0); +err_unlock: + mutex_unlock(&chan->indio_dev->info_exist_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_st_read_channel_raw); + +int iio_st_read_channel_scale(struct iio_channel *chan, int *val, int *val2) +{ + int ret; + + mutex_lock(&chan->indio_dev->info_exist_lock); + if (chan->indio_dev->info == NULL) { + ret = -ENODEV; + goto err_unlock; + } + + ret = chan->indio_dev->info->read_raw(chan->indio_dev, + chan->channel, + val, val2, + IIO_CHAN_INFO_SCALE); +err_unlock: + mutex_unlock(&chan->indio_dev->info_exist_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_st_read_channel_scale); + +int iio_st_get_channel_type(struct iio_channel *chan, + enum iio_chan_type *type) +{ + int ret = 0; + /* Need to verify underlying driver has not gone away */ + + mutex_lock(&chan->indio_dev->info_exist_lock); + if (chan->indio_dev->info == NULL) { + ret = -ENODEV; + goto err_unlock; + } + + *type = chan->channel->type; +err_unlock: + mutex_unlock(&chan->indio_dev->info_exist_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_st_get_channel_type); diff --git a/drivers/staging/iio/machine.h b/drivers/staging/iio/machine.h new file mode 100644 index 0000000000000..0b1f19bfdc44c --- /dev/null +++ b/drivers/staging/iio/machine.h @@ -0,0 +1,24 @@ +/* + * Industrial I/O in kernel access map definitions for board files. + * + * Copyright (c) 2011 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +/** + * struct iio_map - description of link between consumer and device channels + * @adc_channel_label: Label used to identify the channel on the provider. + * This is matched against the datasheet_name element + * of struct iio_chan_spec. + * @consumer_dev_name: Name to uniquely identify the consumer device. + * @consumer_channel: Unique name used to idenitify the channel on the + * consumer side. + */ +struct iio_map { + const char *adc_channel_label; + const char *consumer_dev_name; + const char *consumer_channel; +}; From 6da80320f8e67f61ff6d142c9881cbb1a27694c2 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 15 Feb 2012 19:48:02 +0000 Subject: [PATCH 084/261] staging:iio: move iio data return types into types.h for use by inkern In kernel interfaces need these, so make them available. Signed-off-by: Jonathan Cameron Acked-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/iio.h | 6 ------ drivers/staging/iio/types.h | 4 ++++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h index 478dbe5924cbd..9459c17dee48e 100644 --- a/drivers/staging/iio/iio.h +++ b/drivers/staging/iio/iio.h @@ -197,12 +197,6 @@ static inline s64 iio_get_time_ns(void) #define INDIO_ALL_BUFFER_MODES \ (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE) -/* Vast majority of this is set by the industrialio subsystem on a - * call to iio_device_register. */ -#define IIO_VAL_INT 1 -#define IIO_VAL_INT_PLUS_MICRO 2 -#define IIO_VAL_INT_PLUS_NANO 3 - struct iio_trigger; /* forward declaration */ struct iio_dev; diff --git a/drivers/staging/iio/types.h b/drivers/staging/iio/types.h index b7d26474ad064..0c32136669019 100644 --- a/drivers/staging/iio/types.h +++ b/drivers/staging/iio/types.h @@ -46,4 +46,8 @@ enum iio_modifier { IIO_MOD_LIGHT_IR, }; +#define IIO_VAL_INT 1 +#define IIO_VAL_INT_PLUS_MICRO 2 +#define IIO_VAL_INT_PLUS_NANO 3 + #endif /* _IIO_TYPES_H_ */ From 00a18334e74b80f69ae2268a537493a45ff86e9e Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 15 Feb 2012 19:48:03 +0000 Subject: [PATCH 085/261] staging:iio::hwmon interface client driver. Direct copy of version proposed for the non staging branch. Needed here to allow testing of more advanced inkernel interface code. Minimal support of simple in, curr and temp attributes so far. Signed-off-by: Jonathan Cameron Acked-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/Kconfig | 7 + drivers/staging/iio/Makefile | 2 + drivers/staging/iio/iio_hwmon.c | 232 ++++++++++++++++++++++++++++++++ 3 files changed, 241 insertions(+) create mode 100644 drivers/staging/iio/iio_hwmon.c diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig index 90162aa8b2df4..24c6ed9d91641 100644 --- a/drivers/staging/iio/Kconfig +++ b/drivers/staging/iio/Kconfig @@ -11,6 +11,13 @@ menuconfig IIO number of different physical interfaces (i2c, spi, etc). See drivers/staging/iio/Documentation for more information. if IIO +config IIO_ST_HWMON + tristate "Hwmon driver that uses channels specified via iio maps" + depends on HWMON + help + This is a platform driver that in combination with a suitable + map allows IIO devices to provide basic hwmon functionality + for those channels specified in the map. config IIO_BUFFER bool "Enable buffer support within IIO" diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile index ff059d448c2ea..5075291dda7ad 100644 --- a/drivers/staging/iio/Makefile +++ b/drivers/staging/iio/Makefile @@ -17,6 +17,8 @@ iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_BUFFER) += iio_simple_dummy_buffer.o obj-$(CONFIG_IIO_DUMMY_EVGEN) += iio_dummy_evgen.o +obj-$(CONFIG_IIO_ST_HWMON) += iio_hwmon.o + obj-y += accel/ obj-y += adc/ obj-y += addac/ diff --git a/drivers/staging/iio/iio_hwmon.c b/drivers/staging/iio/iio_hwmon.c new file mode 100644 index 0000000000000..a603a5f51f938 --- /dev/null +++ b/drivers/staging/iio/iio_hwmon.c @@ -0,0 +1,232 @@ +/* Hwmon client for industrial I/O devices + * + * Copyright (c) 2011 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "consumer.h" +#include "types.h" + +/** + * struct iio_hwmon_state - device instance state + * @channels: filled with array of channels from iio + * @num_channels: number of channels in channels (saves counting twice) + * @hwmon_dev: associated hwmon device + * @attr_group: the group of attributes + * @attrs: null terminated array of attribute pointers. + */ +struct iio_hwmon_state { + struct iio_channel *channels; + int num_channels; + struct device *hwmon_dev; + struct attribute_group attr_group; + struct attribute **attrs; +}; + +/* + * Assumes that IIO and hwmon operate in the same base units. + * This is supposed to be true, but needs verification for + * new channel types. + */ +static ssize_t iio_hwmon_read_val(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + long result; + int val, ret, scaleint, scalepart; + struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); + struct iio_hwmon_state *state = dev_get_drvdata(dev); + + /* + * No locking between this pair, so theoretically possible + * the scale has changed. + */ + ret = iio_st_read_channel_raw(&state->channels[sattr->index], + &val); + if (ret < 0) + return ret; + + ret = iio_st_read_channel_scale(&state->channels[sattr->index], + &scaleint, &scalepart); + if (ret < 0) + return ret; + switch (ret) { + case IIO_VAL_INT: + result = val * scaleint; + break; + case IIO_VAL_INT_PLUS_MICRO: + result = (s64)val * (s64)scaleint + + div_s64((s64)val * (s64)scalepart, 1000000LL); + break; + case IIO_VAL_INT_PLUS_NANO: + result = (s64)val * (s64)scaleint + + div_s64((s64)val * (s64)scalepart, 1000000000LL); + break; + default: + return -EINVAL; + } + return sprintf(buf, "%ld\n", result); +} + +static void iio_hwmon_free_attrs(struct iio_hwmon_state *st) +{ + int i; + struct sensor_device_attribute *a; + for (i = 0; i < st->num_channels; i++) + if (st->attrs[i]) { + a = to_sensor_dev_attr( + container_of(st->attrs[i], + struct device_attribute, + attr)); + kfree(a); + } +} + +static int __devinit iio_hwmon_probe(struct platform_device *pdev) +{ + struct iio_hwmon_state *st; + struct sensor_device_attribute *a; + int ret, i; + int in_i = 1, temp_i = 1, curr_i = 1; + enum iio_chan_type type; + + st = kzalloc(sizeof(*st), GFP_KERNEL); + if (st == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + st->channels = iio_st_channel_get_all(dev_name(&pdev->dev)); + if (IS_ERR(st->channels)) { + ret = PTR_ERR(st->channels); + goto error_free_state; + } + + /* count how many attributes we have */ + while (st->channels[st->num_channels].indio_dev) + st->num_channels++; + + st->attrs = kzalloc(sizeof(st->attrs) * (st->num_channels + 1), + GFP_KERNEL); + if (st->attrs == NULL) { + ret = -ENOMEM; + goto error_release_channels; + } + for (i = 0; i < st->num_channels; i++) { + a = kzalloc(sizeof(*a), GFP_KERNEL); + if (a == NULL) { + ret = -ENOMEM; + goto error_free_attrs; + } + + sysfs_attr_init(&a->dev_attr.attr); + ret = iio_st_get_channel_type(&st->channels[i], &type); + if (ret < 0) { + kfree(a); + goto error_free_attrs; + } + switch (type) { + case IIO_VOLTAGE: + a->dev_attr.attr.name = kasprintf(GFP_KERNEL, + "in%d_input", + in_i++); + break; + case IIO_TEMP: + a->dev_attr.attr.name = kasprintf(GFP_KERNEL, + "temp%d_input", + temp_i++); + break; + case IIO_CURRENT: + a->dev_attr.attr.name = kasprintf(GFP_KERNEL, + "curr%d_input", + curr_i++); + break; + default: + ret = -EINVAL; + kfree(a); + goto error_free_attrs; + } + if (a->dev_attr.attr.name == NULL) { + kfree(a); + ret = -ENOMEM; + goto error_free_attrs; + } + a->dev_attr.show = iio_hwmon_read_val; + a->dev_attr.attr.mode = S_IRUGO; + a->index = i; + st->attrs[i] = &a->dev_attr.attr; + } + + st->attr_group.attrs = st->attrs; + platform_set_drvdata(pdev, st); + ret = sysfs_create_group(&pdev->dev.kobj, &st->attr_group); + if (ret < 0) + goto error_free_attrs; + + st->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(st->hwmon_dev)) { + ret = PTR_ERR(st->hwmon_dev); + goto error_remove_group; + } + return 0; + +error_remove_group: + sysfs_remove_group(&pdev->dev.kobj, &st->attr_group); +error_free_attrs: + iio_hwmon_free_attrs(st); + kfree(st->attrs); +error_release_channels: + iio_st_channel_release_all(st->channels); +error_free_state: + kfree(st); +error_ret: + return ret; +} + +static int __devexit iio_hwmon_remove(struct platform_device *pdev) +{ + struct iio_hwmon_state *st = platform_get_drvdata(pdev); + + hwmon_device_unregister(st->hwmon_dev); + sysfs_remove_group(&pdev->dev.kobj, &st->attr_group); + iio_hwmon_free_attrs(st); + kfree(st->attrs); + iio_st_channel_release_all(st->channels); + + return 0; +} + +static struct platform_driver __refdata iio_hwmon_driver = { + .driver = { + .name = "iio_hwmon", + .owner = THIS_MODULE, + }, + .probe = iio_hwmon_probe, + .remove = __devexit_p(iio_hwmon_remove), +}; + +static int iio_inkern_init(void) +{ + return platform_driver_register(&iio_hwmon_driver); +} +module_init(iio_inkern_init); + +static void iio_inkern_exit(void) +{ + platform_driver_unregister(&iio_hwmon_driver); +} +module_exit(iio_inkern_exit); + +MODULE_AUTHOR("Jonathan Cameron "); +MODULE_DESCRIPTION("IIO to hwmon driver"); +MODULE_LICENSE("GPL v2"); From f25ce6839eb4ca25c0949a0379a7e3df0d93eb79 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 15 Feb 2012 19:48:04 +0000 Subject: [PATCH 086/261] staging:iio:Documentation in kernel pull description. Very basic description of the way iio consumers work and how to use this functionality. Signed-off-by: Jonathan Cameron Acked-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- .../staging/iio/Documentation/inkernel.txt | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 drivers/staging/iio/Documentation/inkernel.txt diff --git a/drivers/staging/iio/Documentation/inkernel.txt b/drivers/staging/iio/Documentation/inkernel.txt new file mode 100644 index 0000000000000..a05823e955d22 --- /dev/null +++ b/drivers/staging/iio/Documentation/inkernel.txt @@ -0,0 +1,58 @@ +Industrial I/O Subsystem in kernel consumers. + +The IIO subsystem can act as a layer under other elements of the kernel +providing a means of obtaining ADC type readings or of driving DAC type +signals. The functionality supported will grow as use cases arise. + +Describing the channel mapping (iio/machine.h) + +Channel associations are described using: + +struct iio_map { + const char *adc_channel_label; + const char *consumer_dev_name; + const char *consumer_channel; +}; + +adc_channel_label identifies the channel on the IIO device by being +matched against the datasheet_name field of the iio_chan_spec. + +consumer_dev_name allows identification of the consumer device. +This are then used to find the channel mapping from the consumer device (see +below). + +Finally consumer_channel is a string identifying the channel to the consumer. +(Perhaps 'battery_voltage' or similar). + +An array of these structures is then passed to the IIO driver. + +Supporting in kernel interfaces in the driver (driver.h) + +The driver must provide datasheet_name values for its channels and +must pass the iio_map structures and a pointer to its own iio_dev structure + on to the core via a call to iio_map_array_register. On removal, +iio_map_array_unregister reverses this process. + +The result of this is that the IIO core now has all the information needed +to associate a given channel with the consumer requesting it. + +Acting as an IIO consumer (consumer.h) + +The consumer first has to obtain an iio_channel structure from the core +by calling iio_channel_get(). The correct channel is identified by: + +* matching dev or dev_name against consumer_dev and consumer_dev_name +* matching consumer_channel against consumer_channel in the map + +There are then a number of functions that can be used to get information +about this channel such as it's current reading. + +e.g. +iio_st_read_channel_raw() - get a reading +iio_st_read_channel_type() - get the type of channel + +There is also provision for retrieving all of the channels associated +with a given consumer. This is useful for generic drivers such as +iio_hwmon where the number and naming of channels is not known by the +consumer driver. To do this, use iio_st_channel_get_all. + From 221eec8e5977372518a79ed087b134cf1744304d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 20 Feb 2012 19:37:05 +0100 Subject: [PATCH 087/261] staging:iio: Use dev_pm_ops Use dev_pm_ops instead of legacy suspend/resume callbacks for IIO drivers. Note that this patch introduces a few new #ifdef CONFIG_PM_SLEEP around the suspend and resume callbacks to avoid warnings of unused functions if CONFIG_PM_SLEEP is not defined. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/addac/adt7316-i2c.c | 18 +-------------- drivers/staging/iio/addac/adt7316-spi.c | 18 +-------------- drivers/staging/iio/addac/adt7316.c | 11 ++++----- drivers/staging/iio/addac/adt7316.h | 9 +++++--- drivers/staging/iio/dac/max517.c | 18 ++++++++++----- drivers/staging/iio/light/tsl2563.c | 26 +++++++++++++--------- drivers/staging/iio/light/tsl2583.c | 17 +++++++++----- drivers/staging/iio/magnetometer/hmc5843.c | 20 +++++++++++------ 8 files changed, 66 insertions(+), 71 deletions(-) diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c index 2c03a39220e8f..9e128dd7d457a 100644 --- a/drivers/staging/iio/addac/adt7316-i2c.c +++ b/drivers/staging/iio/addac/adt7316-i2c.c @@ -125,30 +125,14 @@ static const struct i2c_device_id adt7316_i2c_id[] = { MODULE_DEVICE_TABLE(i2c, adt7316_i2c_id); -#ifdef CONFIG_PM -static int adt7316_i2c_suspend(struct i2c_client *client, pm_message_t message) -{ - return adt7316_disable(&client->dev); -} - -static int adt7316_i2c_resume(struct i2c_client *client) -{ - return adt7316_enable(&client->dev); -} -#else -# define adt7316_i2c_suspend NULL -# define adt7316_i2c_resume NULL -#endif - static struct i2c_driver adt7316_driver = { .driver = { .name = "adt7316", + .pm = ADT7316_PM_OPS, .owner = THIS_MODULE, }, .probe = adt7316_i2c_probe, .remove = __devexit_p(adt7316_i2c_remove), - .suspend = adt7316_i2c_suspend, - .resume = adt7316_i2c_resume, .id_table = adt7316_i2c_id, }; module_i2c_driver(adt7316_driver); diff --git a/drivers/staging/iio/addac/adt7316-spi.c b/drivers/staging/iio/addac/adt7316-spi.c index 1ea3cd06299de..985f7d8a6eb24 100644 --- a/drivers/staging/iio/addac/adt7316-spi.c +++ b/drivers/staging/iio/addac/adt7316-spi.c @@ -133,30 +133,14 @@ static const struct spi_device_id adt7316_spi_id[] = { MODULE_DEVICE_TABLE(spi, adt7316_spi_id); -#ifdef CONFIG_PM -static int adt7316_spi_suspend(struct spi_device *spi_dev, pm_message_t message) -{ - return adt7316_disable(&spi_dev->dev); -} - -static int adt7316_spi_resume(struct spi_device *spi_dev) -{ - return adt7316_enable(&spi_dev->dev); -} -#else -# define adt7316_spi_suspend NULL -# define adt7316_spi_resume NULL -#endif - static struct spi_driver adt7316_driver = { .driver = { .name = "adt7316", + .pm = ADT7316_PM_OPS, .owner = THIS_MODULE, }, .probe = adt7316_spi_probe, .remove = __devexit_p(adt7316_spi_remove), - .suspend = adt7316_spi_suspend, - .resume = adt7316_spi_resume, .id_table = adt7316_spi_id, }; module_spi_driver(adt7316_driver); diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index 13c39292d3f2f..fd6a454440589 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -2089,24 +2089,25 @@ static struct attribute_group adt7516_event_attribute_group = { .name = "events", }; -#ifdef CONFIG_PM -int adt7316_disable(struct device *dev) +#ifdef CONFIG_PM_SLEEP +static int adt7316_disable(struct device *dev) { struct iio_dev *dev_info = dev_get_drvdata(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return _adt7316_store_enabled(chip, 0); } -EXPORT_SYMBOL(adt7316_disable); -int adt7316_enable(struct device *dev) +static int adt7316_enable(struct device *dev) { struct iio_dev *dev_info = dev_get_drvdata(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); return _adt7316_store_enabled(chip, 1); } -EXPORT_SYMBOL(adt7316_enable); + +SIMPLE_DEV_PM_OPS(adt7316_pm_ops, adt7316_disable, adt7316_enable); +EXPORT_SYMBOL_GPL(adt7316_pm_ops); #endif static const struct iio_info adt7316_info = { diff --git a/drivers/staging/iio/addac/adt7316.h b/drivers/staging/iio/addac/adt7316.h index d34bd679bb4e5..4d3efff46ae71 100644 --- a/drivers/staging/iio/addac/adt7316.h +++ b/drivers/staging/iio/addac/adt7316.h @@ -10,6 +10,7 @@ #define _ADT7316_H_ #include +#include #define ADT7316_REG_MAX_ADDR 0x3F @@ -23,9 +24,11 @@ struct adt7316_bus { int (*multi_write) (void *client, u8 first_reg, u8 count, u8 *data); }; -#ifdef CONFIG_PM -int adt7316_disable(struct device *dev); -int adt7316_enable(struct device *dev); +#ifdef CONFIG_PM_SLEEP +extern const struct dev_pm_ops adt7316_pm_ops; +#define ADT7316_PM_OPS (&adt7316_pm_ops) +#else +#define ADT7316_PM_OPS NULL #endif int adt7316_probe(struct device *dev, struct adt7316_bus *bus, const char *name); int adt7316_remove(struct device *dev); diff --git a/drivers/staging/iio/dac/max517.c b/drivers/staging/iio/dac/max517.c index a4df6d7443c1f..41483c72cec15 100644 --- a/drivers/staging/iio/dac/max517.c +++ b/drivers/staging/iio/dac/max517.c @@ -179,20 +179,27 @@ static struct attribute_group max518_attribute_group = { .attrs = max518_attributes, }; -static int max517_suspend(struct i2c_client *client, pm_message_t mesg) +#ifdef CONFIG_PM_SLEEP +static int max517_suspend(struct device *dev) { u8 outbuf = COMMAND_PD; - return i2c_master_send(client, &outbuf, 1); + return i2c_master_send(to_i2c_client(dev), &outbuf, 1); } -static int max517_resume(struct i2c_client *client) +static int max517_resume(struct device *dev) { u8 outbuf = 0; - return i2c_master_send(client, &outbuf, 1); + return i2c_master_send(to_i2c_client(dev), &outbuf, 1); } +static SIMPLE_DEV_PM_OPS(max517_pm_ops, max517_suspend, max517_resume); +#define MAX517_PM_OPS (&max517_pm_ops) +#else +#define MAX517_PM_OPS NULL +#endif + static const struct iio_info max517_info = { .attrs = &max517_attribute_group, .driver_module = THIS_MODULE, @@ -273,11 +280,10 @@ MODULE_DEVICE_TABLE(i2c, max517_id); static struct i2c_driver max517_driver = { .driver = { .name = MAX517_DRV_NAME, + .pm = MAX517_PM_OPS, }, .probe = max517_probe, .remove = max517_remove, - .suspend = max517_suspend, - .resume = max517_resume, .id_table = max517_id, }; module_i2c_driver(max517_driver); diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c index ffca85e81ef55..aca1e0380ef86 100644 --- a/drivers/staging/iio/light/tsl2563.c +++ b/drivers/staging/iio/light/tsl2563.c @@ -118,7 +118,7 @@ struct tsl2563_chip { struct delayed_work poweroff_work; /* Remember state for suspend and resume functions */ - pm_message_t state; + bool suspended; struct tsl2563_gainlevel_coeff const *gainlevel; @@ -315,7 +315,7 @@ static int tsl2563_get_adc(struct tsl2563_chip *chip) int retry = 1; int ret = 0; - if (chip->state.event != PM_EVENT_ON) + if (chip->suspended) goto out; if (!chip->int_enabled) { @@ -810,9 +810,10 @@ static int tsl2563_remove(struct i2c_client *client) return 0; } -static int tsl2563_suspend(struct i2c_client *client, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int tsl2563_suspend(struct device *dev) { - struct tsl2563_chip *chip = i2c_get_clientdata(client); + struct tsl2563_chip *chip = i2c_get_clientdata(to_i2c_client(dev)); int ret; mutex_lock(&chip->lock); @@ -821,16 +822,16 @@ static int tsl2563_suspend(struct i2c_client *client, pm_message_t state) if (ret) goto out; - chip->state = state; + chip->suspended = true; out: mutex_unlock(&chip->lock); return ret; } -static int tsl2563_resume(struct i2c_client *client) +static int tsl2563_resume(struct device *dev) { - struct tsl2563_chip *chip = i2c_get_clientdata(client); + struct tsl2563_chip *chip = i2c_get_clientdata(to_i2c_client(dev)); int ret; mutex_lock(&chip->lock); @@ -843,13 +844,19 @@ static int tsl2563_resume(struct i2c_client *client) if (ret) goto out; - chip->state.event = PM_EVENT_ON; + chip->suspended = false; out: mutex_unlock(&chip->lock); return ret; } +static SIMPLE_DEV_PM_OPS(tsl2563_pm_ops, tsl2563_suspend, tsl2563_resume); +#define TSL2563_PM_OPS (&tsl2563_pm_ops) +#else +#define TSL2563_PM_OPS NULL +#endif + static const struct i2c_device_id tsl2563_id[] = { { "tsl2560", 0 }, { "tsl2561", 1 }, @@ -862,9 +869,8 @@ MODULE_DEVICE_TABLE(i2c, tsl2563_id); static struct i2c_driver tsl2563_i2c_driver = { .driver = { .name = "tsl2563", + .pm = TSL2563_PM_OPS, }, - .suspend = tsl2563_suspend, - .resume = tsl2563_resume, .probe = tsl2563_probe, .remove = __devexit_p(tsl2563_remove), .id_table = tsl2563_id, diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index 5b6455a238d8b..9fe9a671ecff9 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -884,9 +884,10 @@ static int __devinit taos_probe(struct i2c_client *clientp, return ret; } -static int taos_suspend(struct i2c_client *client, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int taos_suspend(struct device *dev) { - struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); struct tsl2583_chip *chip = iio_priv(indio_dev); int ret = 0; @@ -901,9 +902,9 @@ static int taos_suspend(struct i2c_client *client, pm_message_t state) return ret; } -static int taos_resume(struct i2c_client *client) +static int taos_resume(struct device *dev) { - struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); struct tsl2583_chip *chip = iio_priv(indio_dev); int ret = 0; @@ -916,6 +917,11 @@ static int taos_resume(struct i2c_client *client) return ret; } +static SIMPLE_DEV_PM_OPS(taos_pm_ops, taos_suspend, taos_resume); +#define TAOS_PM_OPS (&taos_pm_ops) +#else +#define TAOS_PM_OPS NULL +#endif static int __devexit taos_remove(struct i2c_client *client) { @@ -937,10 +943,9 @@ MODULE_DEVICE_TABLE(i2c, taos_idtable); static struct i2c_driver taos_driver = { .driver = { .name = "tsl2583", + .pm = TAOS_PM_OPS, }, .id_table = taos_idtable, - .suspend = taos_suspend, - .resume = taos_resume, .probe = taos_probe, .remove = __devexit_p(taos_remove), }; diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index f2e85a9cf196e..d24992ceb2b0b 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -588,19 +588,26 @@ static int hmc5843_remove(struct i2c_client *client) return 0; } -static int hmc5843_suspend(struct i2c_client *client, pm_message_t mesg) +#ifdef CONFIG_PM_SLEEP +static int hmc5843_suspend(struct device *dev) { - hmc5843_configure(client, MODE_SLEEP); + hmc5843_configure(to_i2c_client(dev), MODE_SLEEP); return 0; } -static int hmc5843_resume(struct i2c_client *client) +static int hmc5843_resume(struct device *dev) { - struct hmc5843_data *data = i2c_get_clientdata(client); - hmc5843_configure(client, data->operating_mode); + struct hmc5843_data *data = i2c_get_clientdata(to_i2c_client(dev)); + hmc5843_configure(to_i2c_client(dev), data->operating_mode); return 0; } +static SIMPLE_DEV_PM_OPS(hmc5843_pm_ops, hmc5843_suspend, hmc5843_resume); +#define HMC5843_PM_OPS (&hmc5843_pm_ops) +#else +#define HMC5843_PM_OPS NULL +#endif + static const struct i2c_device_id hmc5843_id[] = { { "hmc5843", 0 }, { } @@ -610,14 +617,13 @@ MODULE_DEVICE_TABLE(i2c, hmc5843_id); static struct i2c_driver hmc5843_driver = { .driver = { .name = "hmc5843", + .pm = HMC5843_PM_OPS, }, .id_table = hmc5843_id, .probe = hmc5843_probe, .remove = hmc5843_remove, .detect = hmc5843_detect, .address_list = normal_i2c, - .suspend = hmc5843_suspend, - .resume = hmc5843_resume, }; module_i2c_driver(hmc5843_driver); From 6869e1387186fcadbde662f89dcf763d5ebae31c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 20 Feb 2012 19:42:38 +0100 Subject: [PATCH 088/261] staging:iio: Convert remaining drivers to module_spi_driver Convert the IIO drivers which have not been converted yet to module_spi_driver. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5421.c | 13 +------------ drivers/staging/iio/dac/ad5764.c | 13 +------------ 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/drivers/staging/iio/dac/ad5421.c b/drivers/staging/iio/dac/ad5421.c index 71ee86824763e..0b040b2046978 100644 --- a/drivers/staging/iio/dac/ad5421.c +++ b/drivers/staging/iio/dac/ad5421.c @@ -536,18 +536,7 @@ static struct spi_driver ad5421_driver = { .probe = ad5421_probe, .remove = __devexit_p(ad5421_remove), }; - -static __init int ad5421_init(void) -{ - return spi_register_driver(&ad5421_driver); -} -module_init(ad5421_init); - -static __exit void ad5421_exit(void) -{ - spi_unregister_driver(&ad5421_driver); -} -module_exit(ad5421_exit); +module_spi_driver(ad5421_driver); MODULE_AUTHOR("Lars-Peter Clausen "); MODULE_DESCRIPTION("Analog Devices AD5421 DAC"); diff --git a/drivers/staging/iio/dac/ad5764.c b/drivers/staging/iio/dac/ad5764.c index ff91480ae65c9..f73a73079490a 100644 --- a/drivers/staging/iio/dac/ad5764.c +++ b/drivers/staging/iio/dac/ad5764.c @@ -375,18 +375,7 @@ static struct spi_driver ad5764_driver = { .remove = __devexit_p(ad5764_remove), .id_table = ad5764_ids, }; - -static int __init ad5764_spi_init(void) -{ - return spi_register_driver(&ad5764_driver); -} -module_init(ad5764_spi_init); - -static void __exit ad5764_spi_exit(void) -{ - spi_unregister_driver(&ad5764_driver); -} -module_exit(ad5764_spi_exit); +module_spi_driver(ad5764_driver); MODULE_AUTHOR("Lars-Peter Clausen "); MODULE_DESCRIPTION("Analog Devices AD5744/AD5744R/AD5764/AD5764R DAC"); From cf3db7aa92dc72e6133bf4829c1a28cbe4c14740 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 21 Feb 2012 18:38:12 +0100 Subject: [PATCH 089/261] staging:iio: Add extended IIO channel info Sometimes devices have per channel properties which either do not map nicely to the current channel info scheme (e.g. string properties) or are very device specific, so it does not make sense to add generic support for them. Currently drivers define these attributes by hand for each channel. Depending on the number of channels this can amount to quite a few lines of boilerplate code. Especially if a driver supports multiple variations of a chip with different numbers of channels. In this case it becomes necessary to have a individual attribute list per chip variation and also a individual iio_info struct. This patch introduces a new scheme for handling such per channel attributes called extended channel info attributes. A extended channel info attribute consist of a name, a flag whether it is shared and read and write callbacks. The read and write callbacks are similar to the {read,write}_raw callbacks and take a IIO device and a channel as their first parameters, but instead of pre-parsed integer values they directly get passed the raw string value, which has been written to the sysfs file. It is possible to assign a list of extended channel info attributes to a channel. For each extended channel info attribute the IIO core will create a new sysfs attribute conforming to the IIO channel naming spec for the channels type, similar as for normal info attributes. Read and write access to this sysfs attribute will be redirected to the extended channel info attributes read and write callbacks. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/iio.h | 23 +++++++++++ drivers/staging/iio/industrialio-core.c | 53 +++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h index 9459c17dee48e..b9bce9aeb19e7 100644 --- a/drivers/staging/iio/iio.h +++ b/drivers/staging/iio/iio.h @@ -88,6 +88,25 @@ enum iio_endian { IIO_LE, }; +struct iio_chan_spec; +struct iio_dev; + +/** + * struct iio_chan_spec_ext_info - Extended channel info attribute + * @name: Info attribute name + * @shared: Whether this attribute is shared between all channels. + * @read: Read callback for this info attribute, may be NULL. + * @write: Write callback for this info attribute, may be NULL. + */ +struct iio_chan_spec_ext_info { + const char *name; + bool shared; + ssize_t (*read)(struct iio_dev *, struct iio_chan_spec const *, + char *buf); + ssize_t (*write)(struct iio_dev *, struct iio_chan_spec const *, + const char *buf, size_t len); +}; + /** * struct iio_chan_spec - specification of a single channel * @type: What type of measurement is the channel making. @@ -107,6 +126,9 @@ enum iio_endian { * @info_mask: What information is to be exported about this channel. * This includes calibbias, scale etc. * @event_mask: What events can this channel produce. + * @ext_info: Array of extended info attributes for this channel. + * The array is NULL terminated, the last element should + * have it's name field set to NULL. * @extend_name: Allows labeling of channel attributes with an * informative name. Note this has no effect codes etc, * unlike modifiers. @@ -141,6 +163,7 @@ struct iio_chan_spec { } scan_type; long info_mask; long event_mask; + const struct iio_chan_spec_ext_info *ext_info; char *extend_name; const char *datasheet_name; unsigned processed_val:1; diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 3a2d080266245..645bb45c89e80 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -144,6 +144,33 @@ static void __exit iio_exit(void) bus_unregister(&iio_bus_type); } +static ssize_t iio_read_channel_ext_info(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + const struct iio_chan_spec_ext_info *ext_info; + + ext_info = &this_attr->c->ext_info[this_attr->address]; + + return ext_info->read(indio_dev, this_attr->c, buf); +} + +static ssize_t iio_write_channel_ext_info(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + const struct iio_chan_spec_ext_info *ext_info; + + ext_info = &this_attr->c->ext_info[this_attr->address]; + + return ext_info->write(indio_dev, this_attr->c, buf, len); +} + static ssize_t iio_read_channel_info(struct device *dev, struct device_attribute *attr, char *buf) @@ -423,6 +450,7 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, struct iio_chan_spec const *chan) { int ret, i, attrcount = 0; + const struct iio_chan_spec_ext_info *ext_info; if (chan->channel < 0) return 0; @@ -457,6 +485,31 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, goto error_ret; attrcount++; } + + if (chan->ext_info) { + unsigned int i = 0; + for (ext_info = chan->ext_info; ext_info->name; ext_info++) { + ret = __iio_add_chan_devattr(ext_info->name, + chan, + ext_info->read ? + &iio_read_channel_ext_info : NULL, + ext_info->write ? + &iio_write_channel_ext_info : NULL, + i, + ext_info->shared, + &indio_dev->dev, + &indio_dev->channel_attr_list); + i++; + if (ret == -EBUSY && ext_info->shared) + continue; + + if (ret) + goto error_ret; + + attrcount++; + } + } + ret = attrcount; error_ret: return ret; From 54757ce8ab22c24dc6bdd39b99a90ac505e2ab9a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 21 Feb 2012 18:38:13 +0100 Subject: [PATCH 090/261] staging:iio:dac:ad5064: Convert to extended channel info attributes Use extended channel info attributes for the powerdown, powerdown_mode and powerdown_mode_available attributes. Note that this patch moves the chip info defintion around to avoid having to use forward declarations for the extended channel info attributes callbacks. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5064.c | 188 ++++++++++++++----------------- 1 file changed, 82 insertions(+), 106 deletions(-) diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c index 049a855039c2b..52fef75b82d75 100644 --- a/drivers/staging/iio/dac/ad5064.c +++ b/drivers/staging/iio/dac/ad5064.c @@ -86,47 +86,6 @@ enum ad5064_type { ID_AD5064_1, }; -#define AD5064_CHANNEL(chan, bits) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .output = 1, \ - .channel = (chan), \ - .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ - .address = AD5064_ADDR_DAC(chan), \ - .scan_type = IIO_ST('u', (bits), 16, 20 - (bits)) \ -} - -static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { - [ID_AD5024] = { - .shared_vref = false, - .channel[0] = AD5064_CHANNEL(0, 12), - .channel[1] = AD5064_CHANNEL(1, 12), - .channel[2] = AD5064_CHANNEL(2, 12), - .channel[3] = AD5064_CHANNEL(3, 12), - }, - [ID_AD5044] = { - .shared_vref = false, - .channel[0] = AD5064_CHANNEL(0, 14), - .channel[1] = AD5064_CHANNEL(1, 14), - .channel[2] = AD5064_CHANNEL(2, 14), - .channel[3] = AD5064_CHANNEL(3, 14), - }, - [ID_AD5064] = { - .shared_vref = false, - .channel[0] = AD5064_CHANNEL(0, 16), - .channel[1] = AD5064_CHANNEL(1, 16), - .channel[2] = AD5064_CHANNEL(2, 16), - .channel[3] = AD5064_CHANNEL(3, 16), - }, - [ID_AD5064_1] = { - .shared_vref = true, - .channel[0] = AD5064_CHANNEL(0, 16), - .channel[1] = AD5064_CHANNEL(1, 16), - .channel[2] = AD5064_CHANNEL(2, 16), - .channel[3] = AD5064_CHANNEL(3, 16), - }, -}; - static int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd, unsigned int addr, unsigned int val, unsigned int shift) { @@ -160,22 +119,25 @@ static const char ad5064_powerdown_modes[][15] = { [AD5064_LDAC_PWRDN_3STATE] = "three_state", }; -static ssize_t ad5064_read_powerdown_mode(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t ad5064_read_powerdown_mode_available(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, char *buf) +{ + return sprintf(buf, "%s %s %s\n", ad5064_powerdown_modes[1], + ad5064_powerdown_modes[2], ad5064_powerdown_modes[3]); +} + +static ssize_t ad5064_read_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, char *buf) { - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad5064_state *st = iio_priv(indio_dev); return sprintf(buf, "%s\n", - ad5064_powerdown_modes[st->pwr_down_mode[this_attr->address]]); + ad5064_powerdown_modes[st->pwr_down_mode[chan->channel]]); } -static ssize_t ad5064_write_powerdown_mode(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) +static ssize_t ad5064_write_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, const char *buf, size_t len) { - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad5064_state *st = iio_priv(indio_dev); unsigned int mode, i; int ret; @@ -192,31 +154,26 @@ static ssize_t ad5064_write_powerdown_mode(struct device *dev, return -EINVAL; mutex_lock(&indio_dev->mlock); - st->pwr_down_mode[this_attr->address] = mode; + st->pwr_down_mode[chan->channel] = mode; - ret = ad5064_sync_powerdown_mode(st, this_attr->address); + ret = ad5064_sync_powerdown_mode(st, chan->channel); mutex_unlock(&indio_dev->mlock); return ret ? ret : len; } -static ssize_t ad5064_read_dac_powerdown(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t ad5064_read_dac_powerdown(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, char *buf) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad5064_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - return sprintf(buf, "%d\n", st->pwr_down[this_attr->address]); + return sprintf(buf, "%d\n", st->pwr_down[chan->channel]); } -static ssize_t ad5064_write_dac_powerdown(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) +static ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, const char *buf, size_t len) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad5064_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); bool pwr_down; int ret; @@ -225,54 +182,13 @@ static ssize_t ad5064_write_dac_powerdown(struct device *dev, return ret; mutex_lock(&indio_dev->mlock); - st->pwr_down[this_attr->address] = pwr_down; + st->pwr_down[chan->channel] = pwr_down; - ret = ad5064_sync_powerdown_mode(st, this_attr->address); + ret = ad5064_sync_powerdown_mode(st, chan->channel); mutex_unlock(&indio_dev->mlock); return ret ? ret : len; } -static IIO_CONST_ATTR(out_voltage_powerdown_mode_available, - "1kohm_to_gnd 100kohm_to_gnd three_state"); - -#define IIO_DEV_ATTR_DAC_POWERDOWN_MODE(_chan) \ - IIO_DEVICE_ATTR(out_voltage##_chan##_powerdown_mode, \ - S_IRUGO | S_IWUSR, \ - ad5064_read_powerdown_mode, \ - ad5064_write_powerdown_mode, _chan); - -#define IIO_DEV_ATTR_DAC_POWERDOWN(_chan) \ - IIO_DEVICE_ATTR(out_voltage##_chan##_powerdown, \ - S_IRUGO | S_IWUSR, \ - ad5064_read_dac_powerdown, \ - ad5064_write_dac_powerdown, _chan) - -static IIO_DEV_ATTR_DAC_POWERDOWN(0); -static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(0); -static IIO_DEV_ATTR_DAC_POWERDOWN(1); -static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(1); -static IIO_DEV_ATTR_DAC_POWERDOWN(2); -static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(2); -static IIO_DEV_ATTR_DAC_POWERDOWN(3); -static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(3); - -static struct attribute *ad5064_attributes[] = { - &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage1_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage2_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage3_powerdown.dev_attr.attr, - &iio_dev_attr_out_voltage0_powerdown_mode.dev_attr.attr, - &iio_dev_attr_out_voltage1_powerdown_mode.dev_attr.attr, - &iio_dev_attr_out_voltage2_powerdown_mode.dev_attr.attr, - &iio_dev_attr_out_voltage3_powerdown_mode.dev_attr.attr, - &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad5064_attribute_group = { - .attrs = ad5064_attributes, -}; - static int ad5064_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, @@ -331,10 +247,70 @@ static int ad5064_write_raw(struct iio_dev *indio_dev, static const struct iio_info ad5064_info = { .read_raw = ad5064_read_raw, .write_raw = ad5064_write_raw, - .attrs = &ad5064_attribute_group, .driver_module = THIS_MODULE, }; +static struct iio_chan_spec_ext_info ad5064_ext_info[] = { + { + .name = "powerdown", + .read = ad5064_read_dac_powerdown, + .write = ad5064_write_dac_powerdown, + }, + { + .name = "powerdown_mode", + .read = ad5064_read_powerdown_mode, + .write = ad5064_write_powerdown_mode, + }, + { + .name = "powerdown_mode_available", + .shared = true, + .read = ad5064_read_powerdown_mode_available, + }, + { }, +}; + +#define AD5064_CHANNEL(chan, bits) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (chan), \ + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ + .address = AD5064_ADDR_DAC(chan), \ + .scan_type = IIO_ST('u', (bits), 16, 20 - (bits)), \ + .ext_info = ad5064_ext_info, \ +} + +static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { + [ID_AD5024] = { + .shared_vref = false, + .channel[0] = AD5064_CHANNEL(0, 12), + .channel[1] = AD5064_CHANNEL(1, 12), + .channel[2] = AD5064_CHANNEL(2, 12), + .channel[3] = AD5064_CHANNEL(3, 12), + }, + [ID_AD5044] = { + .shared_vref = false, + .channel[0] = AD5064_CHANNEL(0, 14), + .channel[1] = AD5064_CHANNEL(1, 14), + .channel[2] = AD5064_CHANNEL(2, 14), + .channel[3] = AD5064_CHANNEL(3, 14), + }, + [ID_AD5064] = { + .shared_vref = false, + .channel[0] = AD5064_CHANNEL(0, 16), + .channel[1] = AD5064_CHANNEL(1, 16), + .channel[2] = AD5064_CHANNEL(2, 16), + .channel[3] = AD5064_CHANNEL(3, 16), + }, + [ID_AD5064_1] = { + .shared_vref = true, + .channel[0] = AD5064_CHANNEL(0, 16), + .channel[1] = AD5064_CHANNEL(1, 16), + .channel[2] = AD5064_CHANNEL(2, 16), + .channel[3] = AD5064_CHANNEL(3, 16), + }, +}; + static inline unsigned int ad5064_num_vref(struct ad5064_state *st) { return st->chip_info->shared_vref ? 1 : AD5064_DAC_CHANNELS; From 44396a9f767e75a806e0311f907d289959034d1f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 21 Feb 2012 18:38:14 +0100 Subject: [PATCH 091/261] staging:iio:dac:ad5064: Prepare driver for the addition of chip variants Prepare the driver for the addition of chip variants with a different number of channels. This is done by not hard-coding the number of channels, but instead add a field to the chip info struct holding the number of channels. Also do not embed the channel specs into the chip info, but rather store them independently. This allows sharing the same channel spec between different chip infos. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5064.c | 61 ++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c index 52fef75b82d75..40db679881038 100644 --- a/drivers/staging/iio/dac/ad5064.c +++ b/drivers/staging/iio/dac/ad5064.c @@ -19,7 +19,8 @@ #include "../sysfs.h" #include "dac.h" -#define AD5064_DAC_CHANNELS 4 +#define AD5064_MAX_DAC_CHANNELS 4 +#define AD5064_MAX_VREFS 4 #define AD5064_ADDR(x) ((x) << 20) #define AD5064_CMD(x) ((x) << 24) @@ -46,11 +47,13 @@ * struct ad5064_chip_info - chip specific information * @shared_vref: whether the vref supply is shared between channels * @channel: channel specification -*/ + * @num_channels: number of channels + */ struct ad5064_chip_info { bool shared_vref; - struct iio_chan_spec channel[AD5064_DAC_CHANNELS]; + const struct iio_chan_spec *channels; + unsigned int num_channels; }; /** @@ -67,10 +70,10 @@ struct ad5064_chip_info { struct ad5064_state { struct spi_device *spi; const struct ad5064_chip_info *chip_info; - struct regulator_bulk_data vref_reg[AD5064_DAC_CHANNELS]; - bool pwr_down[AD5064_DAC_CHANNELS]; - u8 pwr_down_mode[AD5064_DAC_CHANNELS]; - unsigned int dac_cache[AD5064_DAC_CHANNELS]; + struct regulator_bulk_data vref_reg[AD5064_MAX_VREFS]; + bool pwr_down[AD5064_MAX_DAC_CHANNELS]; + u8 pwr_down_mode[AD5064_MAX_DAC_CHANNELS]; + unsigned int dac_cache[AD5064_MAX_DAC_CHANNELS]; /* * DMA (thus cache coherency maintenance) requires the @@ -280,40 +283,44 @@ static struct iio_chan_spec_ext_info ad5064_ext_info[] = { .ext_info = ad5064_ext_info, \ } +#define DECLARE_AD5064_CHANNELS(name, bits) \ +const struct iio_chan_spec name[] = { \ + AD5064_CHANNEL(0, bits), \ + AD5064_CHANNEL(1, bits), \ + AD5064_CHANNEL(2, bits), \ + AD5064_CHANNEL(3, bits), \ +} + +static DECLARE_AD5064_CHANNELS(ad5024_channels, 12); +static DECLARE_AD5064_CHANNELS(ad5044_channels, 14); +static DECLARE_AD5064_CHANNELS(ad5064_channels, 16); + static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { [ID_AD5024] = { .shared_vref = false, - .channel[0] = AD5064_CHANNEL(0, 12), - .channel[1] = AD5064_CHANNEL(1, 12), - .channel[2] = AD5064_CHANNEL(2, 12), - .channel[3] = AD5064_CHANNEL(3, 12), + .channels = ad5024_channels, + .num_channels = 4, }, [ID_AD5044] = { .shared_vref = false, - .channel[0] = AD5064_CHANNEL(0, 14), - .channel[1] = AD5064_CHANNEL(1, 14), - .channel[2] = AD5064_CHANNEL(2, 14), - .channel[3] = AD5064_CHANNEL(3, 14), + .channels = ad5044_channels, + .num_channels = 4, }, [ID_AD5064] = { .shared_vref = false, - .channel[0] = AD5064_CHANNEL(0, 16), - .channel[1] = AD5064_CHANNEL(1, 16), - .channel[2] = AD5064_CHANNEL(2, 16), - .channel[3] = AD5064_CHANNEL(3, 16), + .channels = ad5064_channels, + .num_channels = 4, }, [ID_AD5064_1] = { .shared_vref = true, - .channel[0] = AD5064_CHANNEL(0, 16), - .channel[1] = AD5064_CHANNEL(1, 16), - .channel[2] = AD5064_CHANNEL(2, 16), - .channel[3] = AD5064_CHANNEL(3, 16), + .channels = ad5064_channels, + .num_channels = 4, }, }; static inline unsigned int ad5064_num_vref(struct ad5064_state *st) { - return st->chip_info->shared_vref ? 1 : AD5064_DAC_CHANNELS; + return st->chip_info->shared_vref ? 1 : st->chip_info->num_channels; } static const char * const ad5064_vref_names[] = { @@ -359,7 +366,7 @@ static int __devinit ad5064_probe(struct spi_device *spi) if (ret) goto error_free_reg; - for (i = 0; i < AD5064_DAC_CHANNELS; ++i) { + for (i = 0; i < st->chip_info->num_channels; ++i) { st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K; st->dac_cache[i] = 0x8000; } @@ -368,8 +375,8 @@ static int __devinit ad5064_probe(struct spi_device *spi) indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad5064_info; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = st->chip_info->channel; - indio_dev->num_channels = AD5064_DAC_CHANNELS; + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = st->chip_info->num_channels; ret = iio_device_register(indio_dev); if (ret) From 6e00bf222ca4f984d8631617e9fbb76bc19ce460 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 21 Feb 2012 18:38:15 +0100 Subject: [PATCH 092/261] staging:iio:dac:ad5064: Add AD5025/AD5045/AD5065 support The AD5025/AD5045/AD5065 are identical to the AD5024/AD5044/AD5064 except that they have 2 instead of 4 DAC channels. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/Kconfig | 6 +++--- drivers/staging/iio/dac/ad5064.c | 26 ++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/staging/iio/dac/Kconfig b/drivers/staging/iio/dac/Kconfig index 13e27979df245..66b2504a1edd2 100644 --- a/drivers/staging/iio/dac/Kconfig +++ b/drivers/staging/iio/dac/Kconfig @@ -4,11 +4,11 @@ menu "Digital to analog converters" config AD5064 - tristate "Analog Devices AD5064/64-1/44/24 DAC driver" + tristate "Analog Devices AD5064/64-1/65/44/45/24/25 DAC driver" depends on SPI help - Say yes here to build support for Analog Devices AD5064, AD5064-1, - AD5044, AD5024 Digital to Analog Converter. + Say yes here to build support for Analog Devices AD5024, AD5025, AD5044, + AD5045, AD5064, AD5064-1, AD5065 Digital to Analog Converter. To compile this driver as a module, choose M here: the module will be called ad5064. diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c index 40db679881038..865e81fc2da9b 100644 --- a/drivers/staging/iio/dac/ad5064.c +++ b/drivers/staging/iio/dac/ad5064.c @@ -1,5 +1,6 @@ /* - * AD5064, AD5064-1, AD5044, AD5024 Digital to analog converters driver + * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1 Digital to analog converters + * driver * * Copyright 2011 Analog Devices Inc. * @@ -84,9 +85,12 @@ struct ad5064_state { enum ad5064_type { ID_AD5024, + ID_AD5025, ID_AD5044, + ID_AD5045, ID_AD5064, ID_AD5064_1, + ID_AD5065, }; static int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd, @@ -301,11 +305,21 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { .channels = ad5024_channels, .num_channels = 4, }, + [ID_AD5025] = { + .shared_vref = false, + .channels = ad5024_channels, + .num_channels = 2, + }, [ID_AD5044] = { .shared_vref = false, .channels = ad5044_channels, .num_channels = 4, }, + [ID_AD5045] = { + .shared_vref = false, + .channels = ad5044_channels, + .num_channels = 2, + }, [ID_AD5064] = { .shared_vref = false, .channels = ad5064_channels, @@ -316,6 +330,11 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { .channels = ad5064_channels, .num_channels = 4, }, + [ID_AD5065] = { + .shared_vref = false, + .channels = ad5064_channels, + .num_channels = 2, + }, }; static inline unsigned int ad5064_num_vref(struct ad5064_state *st) @@ -412,9 +431,12 @@ static int __devexit ad5064_remove(struct spi_device *spi) static const struct spi_device_id ad5064_id[] = { {"ad5024", ID_AD5024}, + {"ad5025", ID_AD5025}, {"ad5044", ID_AD5044}, + {"ad5045", ID_AD5045}, {"ad5064", ID_AD5064}, {"ad5064-1", ID_AD5064_1}, + {"ad5065", ID_AD5065}, {} }; MODULE_DEVICE_TABLE(spi, ad5064_id); @@ -431,5 +453,5 @@ static struct spi_driver ad5064_driver = { module_spi_driver(ad5064_driver); MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_DESCRIPTION("Analog Devices AD5064/64-1/44/24 DAC"); +MODULE_DESCRIPTION("Analog Devices AD5024/25/44/45/64/64-1/65 DAC"); MODULE_LICENSE("GPL v2"); From fb13f935e7571915d47c4540de435deaa4ffdee3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 21 Feb 2012 18:38:16 +0100 Subject: [PATCH 093/261] staging:iio:dac:ad5064: Add AD5628/AD5648/AD5668 support The AD5628/AD5648/AD5668 are similar to the AD5024/AD5044/AD5064. The difference being that they have an internal reference voltage and 8 instead of 4 DAC channels. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/Kconfig | 5 +- drivers/staging/iio/dac/ad5064.c | 122 ++++++++++++++++++++++++++----- 2 files changed, 107 insertions(+), 20 deletions(-) diff --git a/drivers/staging/iio/dac/Kconfig b/drivers/staging/iio/dac/Kconfig index 66b2504a1edd2..ab8516d76bcd1 100644 --- a/drivers/staging/iio/dac/Kconfig +++ b/drivers/staging/iio/dac/Kconfig @@ -4,11 +4,12 @@ menu "Digital to analog converters" config AD5064 - tristate "Analog Devices AD5064/64-1/65/44/45/24/25 DAC driver" + tristate "Analog Devices AD5064/64-1/65/44/45/24/25, AD5628/48/68 DAC driver" depends on SPI help Say yes here to build support for Analog Devices AD5024, AD5025, AD5044, - AD5045, AD5064, AD5064-1, AD5065 Digital to Analog Converter. + AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5648, AD5668 Digital to Analog + Converter. To compile this driver as a module, choose M here: the module will be called ad5064. diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c index 865e81fc2da9b..6dab0645aa623 100644 --- a/drivers/staging/iio/dac/ad5064.c +++ b/drivers/staging/iio/dac/ad5064.c @@ -1,6 +1,6 @@ /* - * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1 Digital to analog converters - * driver + * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5648, + * AD5668 Digital to analog converters driver * * Copyright 2011 Analog Devices Inc. * @@ -20,7 +20,7 @@ #include "../sysfs.h" #include "dac.h" -#define AD5064_MAX_DAC_CHANNELS 4 +#define AD5064_MAX_DAC_CHANNELS 8 #define AD5064_MAX_VREFS 4 #define AD5064_ADDR(x) ((x) << 20) @@ -37,7 +37,10 @@ #define AD5064_CMD_CLEAR 0x5 #define AD5064_CMD_LDAC_MASK 0x6 #define AD5064_CMD_RESET 0x7 -#define AD5064_CMD_DAISY_CHAIN_ENABLE 0x8 +#define AD5064_CMD_CONFIG 0x8 + +#define AD5064_CONFIG_DAISY_CHAIN_ENABLE BIT(1) +#define AD5064_CONFIG_INT_VREF_ENABLE BIT(0) #define AD5064_LDAC_PWRDN_NONE 0x0 #define AD5064_LDAC_PWRDN_1K 0x1 @@ -47,12 +50,15 @@ /** * struct ad5064_chip_info - chip specific information * @shared_vref: whether the vref supply is shared between channels + * @internal_vref: internal reference voltage. 0 if the chip has no internal + * vref. * @channel: channel specification * @num_channels: number of channels */ struct ad5064_chip_info { bool shared_vref; + unsigned long internal_vref; const struct iio_chan_spec *channels; unsigned int num_channels; }; @@ -65,6 +71,8 @@ struct ad5064_chip_info { * @pwr_down: whether channel is powered down * @pwr_down_mode: channel's current power down mode * @dac_cache: current DAC raw value (chip does not support readback) + * @use_internal_vref: set to true if the internal reference voltage should be + * used. * @data: spi transfer buffers */ @@ -75,6 +83,7 @@ struct ad5064_state { bool pwr_down[AD5064_MAX_DAC_CHANNELS]; u8 pwr_down_mode[AD5064_MAX_DAC_CHANNELS]; unsigned int dac_cache[AD5064_MAX_DAC_CHANNELS]; + bool use_internal_vref; /* * DMA (thus cache coherency maintenance) requires the @@ -91,6 +100,12 @@ enum ad5064_type { ID_AD5064, ID_AD5064_1, ID_AD5065, + ID_AD5628_1, + ID_AD5628_2, + ID_AD5648_1, + ID_AD5648_2, + ID_AD5668_1, + ID_AD5668_2, }; static int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd, @@ -196,6 +211,18 @@ static ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev, return ret ? ret : len; } +static int ad5064_get_vref(struct ad5064_state *st, + struct iio_chan_spec const *chan) +{ + unsigned int i; + + if (st->use_internal_vref) + return st->chip_info->internal_vref; + + i = st->chip_info->shared_vref ? 0 : chan->channel; + return regulator_get_voltage(st->vref_reg[i].consumer); +} + static int ad5064_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, @@ -203,7 +230,6 @@ static int ad5064_read_raw(struct iio_dev *indio_dev, long m) { struct ad5064_state *st = iio_priv(indio_dev); - unsigned int vref; int scale_uv; switch (m) { @@ -211,8 +237,7 @@ static int ad5064_read_raw(struct iio_dev *indio_dev, *val = st->dac_cache[chan->channel]; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - vref = st->chip_info->shared_vref ? 0 : chan->channel; - scale_uv = regulator_get_voltage(st->vref_reg[vref].consumer); + scale_uv = ad5064_get_vref(st, chan); if (scale_uv < 0) return scale_uv; @@ -293,6 +318,10 @@ const struct iio_chan_spec name[] = { \ AD5064_CHANNEL(1, bits), \ AD5064_CHANNEL(2, bits), \ AD5064_CHANNEL(3, bits), \ + AD5064_CHANNEL(4, bits), \ + AD5064_CHANNEL(5, bits), \ + AD5064_CHANNEL(6, bits), \ + AD5064_CHANNEL(7, bits), \ } static DECLARE_AD5064_CHANNELS(ad5024_channels, 12); @@ -335,6 +364,42 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { .channels = ad5064_channels, .num_channels = 2, }, + [ID_AD5628_1] = { + .shared_vref = true, + .internal_vref = 2500000, + .channels = ad5024_channels, + .num_channels = 8, + }, + [ID_AD5628_2] = { + .shared_vref = true, + .internal_vref = 5000000, + .channels = ad5024_channels, + .num_channels = 8, + }, + [ID_AD5648_1] = { + .shared_vref = true, + .internal_vref = 2500000, + .channels = ad5044_channels, + .num_channels = 8, + }, + [ID_AD5648_2] = { + .shared_vref = true, + .internal_vref = 5000000, + .channels = ad5044_channels, + .num_channels = 8, + }, + [ID_AD5668_1] = { + .shared_vref = true, + .internal_vref = 2500000, + .channels = ad5064_channels, + .num_channels = 8, + }, + [ID_AD5668_2] = { + .shared_vref = true, + .internal_vref = 5000000, + .channels = ad5064_channels, + .num_channels = 8, + }, }; static inline unsigned int ad5064_num_vref(struct ad5064_state *st) @@ -378,12 +443,22 @@ static int __devinit ad5064_probe(struct spi_device *spi) ret = regulator_bulk_get(&st->spi->dev, ad5064_num_vref(st), st->vref_reg); - if (ret) - goto error_free; - - ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg); - if (ret) - goto error_free_reg; + if (ret) { + if (!st->chip_info->internal_vref) + goto error_free; + st->use_internal_vref = true; + ret = ad5064_spi_write(st, AD5064_CMD_CONFIG, 0, + AD5064_CONFIG_INT_VREF_ENABLE, 0); + if (ret) { + dev_err(&spi->dev, "Failed to enable internal vref: %d\n", + ret); + goto error_free; + } + } else { + ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg); + if (ret) + goto error_free_reg; + } for (i = 0; i < st->chip_info->num_channels; ++i) { st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K; @@ -404,9 +479,11 @@ static int __devinit ad5064_probe(struct spi_device *spi) return 0; error_disable_reg: - regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); + if (!st->use_internal_vref) + regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); error_free_reg: - regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); + if (!st->use_internal_vref) + regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); error_free: iio_free_device(indio_dev); @@ -421,8 +498,10 @@ static int __devexit ad5064_remove(struct spi_device *spi) iio_device_unregister(indio_dev); - regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); - regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); + if (!st->use_internal_vref) { + regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); + regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); + } iio_free_device(indio_dev); @@ -437,6 +516,13 @@ static const struct spi_device_id ad5064_id[] = { {"ad5064", ID_AD5064}, {"ad5064-1", ID_AD5064_1}, {"ad5065", ID_AD5065}, + {"ad5628-1", ID_AD5628_1}, + {"ad5628-2", ID_AD5628_2}, + {"ad5648-1", ID_AD5648_1}, + {"ad5648-2", ID_AD5648_2}, + {"ad5668-1", ID_AD5668_1}, + {"ad5668-2", ID_AD5668_2}, + {"ad5668-3", ID_AD5668_2}, /* similar enough to ad5668-2 */ {} }; MODULE_DEVICE_TABLE(spi, ad5064_id); @@ -453,5 +539,5 @@ static struct spi_driver ad5064_driver = { module_spi_driver(ad5064_driver); MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_DESCRIPTION("Analog Devices AD5024/25/44/45/64/64-1/65 DAC"); +MODULE_DESCRIPTION("Analog Devices AD5024/25/44/45/64/64-1/65, AD5628/48/68 DAC"); MODULE_LICENSE("GPL v2"); From fac01ee413d87efcfe2a19b0659484c1a3bf1486 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 21 Feb 2012 18:38:17 +0100 Subject: [PATCH 094/261] staging:iio:dac:ad5064: Add AD5666 support The AD5666 is identical to the ad5064-1, except that it has a internal reference voltage. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/Kconfig | 6 +++--- drivers/staging/iio/dac/ad5064.c | 20 ++++++++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/staging/iio/dac/Kconfig b/drivers/staging/iio/dac/Kconfig index ab8516d76bcd1..a57803a5d1a72 100644 --- a/drivers/staging/iio/dac/Kconfig +++ b/drivers/staging/iio/dac/Kconfig @@ -4,12 +4,12 @@ menu "Digital to analog converters" config AD5064 - tristate "Analog Devices AD5064/64-1/65/44/45/24/25, AD5628/48/68 DAC driver" + tristate "Analog Devices AD5064/64-1/65/44/45/24/25, AD5628/48/66/68 DAC driver" depends on SPI help Say yes here to build support for Analog Devices AD5024, AD5025, AD5044, - AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5648, AD5668 Digital to Analog - Converter. + AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5648, AD5666, AD5668 Digital + to Analog Converter. To compile this driver as a module, choose M here: the module will be called ad5064. diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c index 6dab0645aa623..06b162745a3e7 100644 --- a/drivers/staging/iio/dac/ad5064.c +++ b/drivers/staging/iio/dac/ad5064.c @@ -1,6 +1,6 @@ /* * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5648, - * AD5668 Digital to analog converters driver + * AD5666, AD5668 Digital to analog converters driver * * Copyright 2011 Analog Devices Inc. * @@ -104,6 +104,8 @@ enum ad5064_type { ID_AD5628_2, ID_AD5648_1, ID_AD5648_2, + ID_AD5666_1, + ID_AD5666_2, ID_AD5668_1, ID_AD5668_2, }; @@ -388,6 +390,18 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { .channels = ad5044_channels, .num_channels = 8, }, + [ID_AD5666_1] = { + .shared_vref = true, + .internal_vref = 2500000, + .channels = ad5064_channels, + .num_channels = 4, + }, + [ID_AD5666_2] = { + .shared_vref = true, + .internal_vref = 5000000, + .channels = ad5064_channels, + .num_channels = 4, + }, [ID_AD5668_1] = { .shared_vref = true, .internal_vref = 2500000, @@ -520,6 +534,8 @@ static const struct spi_device_id ad5064_id[] = { {"ad5628-2", ID_AD5628_2}, {"ad5648-1", ID_AD5648_1}, {"ad5648-2", ID_AD5648_2}, + {"ad5666-1", ID_AD5666_1}, + {"ad5666-2", ID_AD5666_2}, {"ad5668-1", ID_AD5668_1}, {"ad5668-2", ID_AD5668_2}, {"ad5668-3", ID_AD5668_2}, /* similar enough to ad5668-2 */ @@ -539,5 +555,5 @@ static struct spi_driver ad5064_driver = { module_spi_driver(ad5064_driver); MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_DESCRIPTION("Analog Devices AD5024/25/44/45/64/64-1/65, AD5628/48/68 DAC"); +MODULE_DESCRIPTION("Analog Devices AD5024/25/44/45/64/64-1/65, AD5628/48/66/68 DAC"); MODULE_LICENSE("GPL v2"); From 699d1e2daa48eaeed7eef88433e728160c78317e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 21 Feb 2012 18:53:39 +0100 Subject: [PATCH 095/261] staging:iio: Remove declaration for non existing function The declaration for iio_buffer_deinit has been around for quite some time, but the function itself has never been added. So remove the declaration. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/buffer.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/iio/buffer.h b/drivers/staging/iio/buffer.h index 6fb6e64181a59..df2046dcb623e 100644 --- a/drivers/staging/iio/buffer.h +++ b/drivers/staging/iio/buffer.h @@ -91,8 +91,6 @@ struct iio_buffer { **/ void iio_buffer_init(struct iio_buffer *buffer); -void iio_buffer_deinit(struct iio_buffer *buffer); - /** * __iio_update_buffer() - update common elements of buffers * @buffer: buffer that is the event source From 083688c6abfb6ff0c2d14441af1f93b14b1baac6 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 22 Feb 2012 13:16:49 +0100 Subject: [PATCH 096/261] iio: core: constitfy available_scan_mask The core must not modify available_scan_mask, because it causes problems with drivers where multiple instances of the driver share the same mask set. So make this explicit by marking available scan masks as const. The max1363 driver needs some minor adjustment to accommodate this change. Pull scan mask allocation into a separate function. Signed-off-by: Michael Hennerich Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/max1363_core.c | 36 +++++++++++++++-------- drivers/staging/iio/iio.h | 4 +-- drivers/staging/iio/industrialio-buffer.c | 6 ++-- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c index 3a5bd2084e645..7f39ca3c936f1 100644 --- a/drivers/staging/iio/adc/max1363_core.c +++ b/drivers/staging/iio/adc/max1363_core.c @@ -1245,10 +1245,31 @@ static int max1363_initial_setup(struct max1363_state *st) return max1363_set_scan_mode(st); } +static int __devinit max1363_alloc_scan_masks(struct iio_dev *indio_dev) +{ + struct max1363_state *st = iio_priv(indio_dev); + unsigned long *masks; + int i; + + masks = kzalloc(BITS_TO_LONGS(MAX1363_MAX_CHANNELS)*sizeof(long)* + (st->chip_info->num_modes + 1), GFP_KERNEL); + if (!masks) + return -ENOMEM; + + for (i = 0; i < st->chip_info->num_modes; i++) + bitmap_copy(masks + BITS_TO_LONGS(MAX1363_MAX_CHANNELS)*i, + max1363_mode_table[st->chip_info->mode_list[i]] + .modemask, MAX1363_MAX_CHANNELS); + + indio_dev->available_scan_masks = masks; + + return 0; +} + static int __devinit max1363_probe(struct i2c_client *client, const struct i2c_device_id *id) { - int ret, i; + int ret; struct max1363_state *st; struct iio_dev *indio_dev; struct regulator *reg; @@ -1276,19 +1297,10 @@ static int __devinit max1363_probe(struct i2c_client *client, st->chip_info = &max1363_chip_info_tbl[id->driver_data]; st->client = client; - indio_dev->available_scan_masks - = kzalloc(BITS_TO_LONGS(MAX1363_MAX_CHANNELS)*sizeof(long)* - (st->chip_info->num_modes + 1), GFP_KERNEL); - if (!indio_dev->available_scan_masks) { - ret = -ENOMEM; + ret = max1363_alloc_scan_masks(indio_dev); + if (ret) goto error_free_device; - } - for (i = 0; i < st->chip_info->num_modes; i++) - bitmap_copy(indio_dev->available_scan_masks + - BITS_TO_LONGS(MAX1363_MAX_CHANNELS)*i, - max1363_mode_table[st->chip_info->mode_list[i]] - .modemask, MAX1363_MAX_CHANNELS); /* Estabilish that the iio_dev is a child of the i2c device */ indio_dev->dev.parent = &client->dev; indio_dev->name = id->name; diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h index b9bce9aeb19e7..76a3f509e5a67 100644 --- a/drivers/staging/iio/iio.h +++ b/drivers/staging/iio/iio.h @@ -345,9 +345,9 @@ struct iio_dev { struct iio_buffer *buffer; struct mutex mlock; - unsigned long *available_scan_masks; + const unsigned long *available_scan_masks; unsigned masklength; - unsigned long *active_scan_mask; + const unsigned long *active_scan_mask; struct iio_trigger *trig; struct iio_poll_func *pollfunc; diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c index d7b1e9e435aed..386ba760f3f1b 100644 --- a/drivers/staging/iio/industrialio-buffer.c +++ b/drivers/staging/iio/industrialio-buffer.c @@ -489,9 +489,9 @@ ssize_t iio_buffer_show_enable(struct device *dev, EXPORT_SYMBOL(iio_buffer_show_enable); /* note NULL used as error indicator as it doesn't make sense. */ -static unsigned long *iio_scan_mask_match(unsigned long *av_masks, +static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks, unsigned int masklength, - unsigned long *mask) + const unsigned long *mask) { if (bitmap_empty(mask, masklength)) return NULL; @@ -554,7 +554,7 @@ EXPORT_SYMBOL(iio_sw_buffer_preenable); int iio_scan_mask_set(struct iio_dev *indio_dev, struct iio_buffer *buffer, int bit) { - unsigned long *mask; + const unsigned long *mask; unsigned long *trialmask; trialmask = kmalloc(sizeof(*trialmask)* From f2a04d396517e3dba6602f12a69034b44b423711 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 16 Feb 2012 17:18:04 +0100 Subject: [PATCH 097/261] SPI XCOMM Bridge Driver - keep local Signed-off-by: Michael Hennerich --- drivers/spi/Kconfig | 7 + drivers/spi/Makefile | 1 + drivers/spi/spi-bitbang.c | 3 +- drivers/spi/spi-xcomm.c | 255 ++++++++++++++++++++++++++++++++ include/linux/spi/spi_bitbang.h | 4 +- 5 files changed, 267 insertions(+), 3 deletions(-) create mode 100644 drivers/spi/spi-xcomm.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 8eb3767c0784b..8f35d0ffaf0f7 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -359,6 +359,13 @@ config SPI_TXX9 help SPI driver for Toshiba TXx9 MIPS SoCs +config SPI_XCOMM + tristate "SPI-I2C-bridge driver for the ADI Xcomm board" + depends on I2C + select SPI_BITBANG + help + Support for the SPI-I2C-bridge IC found on the ADI Xcomm board. + config SPI_XILINX tristate "Xilinx SPI controller common module" depends on HAS_IOMEM && EXPERIMENTAL diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index c755e830744e5..154a1aff91588 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -57,6 +57,7 @@ obj-$(CONFIG_SPI_TI_SSP) += spi-ti-ssp.o obj-$(CONFIG_SPI_TLE62X0) += spi-tle62x0.o obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o obj-$(CONFIG_SPI_TXX9) += spi-txx9.o +obj-$(CONFIG_SPI_XCOMM) += spi-xcomm.o obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o obj-$(CONFIG_SPI_XILINX_PS_SPI) += spi-xilinx-ps.o obj-$(CONFIG_SPI_XILINX_PS_QSPI) += spi-xilinx-qps.o diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index aef59b1a15f7f..f4ddf541aaaba 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -330,7 +330,8 @@ static void bitbang_work(struct work_struct *work) */ if (!m->is_dma_mapped) t->rx_dma = t->tx_dma = 0; - status = bitbang->txrx_bufs(spi, t); + status = bitbang->txrx_bufs(spi, t, t->transfer_list.next == &m->transfers); +// status = bitbang->txrx_bufs(spi, t); } if (status > 0) m->actual_length += status; diff --git a/drivers/spi/spi-xcomm.c b/drivers/spi/spi-xcomm.c new file mode 100644 index 0000000000000..a97ec46642796 --- /dev/null +++ b/drivers/spi/spi-xcomm.c @@ -0,0 +1,255 @@ +#include +#include +#include +#include +#include + + +#include +#include +#include + +#define SPI_XCOMM_SETTINGS_3WIRE BIT(6) +#define SPI_XCOMM_SETTINGS_CS_HIGH BIT(5) +#define SPI_XCOMM_SETTINGS_SAMPLE_END BIT(4) +#define SPI_XCOMM_SETTINGS_CPHA BIT(3) +#define SPI_XCOMM_SETTINGS_CPOL BIT(2) +#define SPI_XCOMM_SETTINGS_CLOCK_DIV_MASK 0x3 +#define SPI_XCOMM_SETTINGS_CLOCK_DIV_64 0x2 +#define SPI_XCOMM_SETTINGS_CLOCK_DIV_16 0x1 +#define SPI_XCOMM_SETTINGS_CLOCK_DIV_4 0x0 + +#define SPI_XCOMM_CMD_UPDATE_CONFIG 0x03 +#define SPI_XCOMM_CMD_WRITE 0x04 + +struct spi_xcomm { + struct spi_bitbang bitbang; /* keep this one here !!! */ + struct i2c_client *i2c; + uint16_t settings; + uint16_t chipselect; + + unsigned int clock; + unsigned int current_speed; +}; + +static int spi_xcomm_sync_config(struct spi_xcomm *spi_xcomm) +{ + uint8_t buf[5]; + + buf[0] = SPI_XCOMM_CMD_UPDATE_CONFIG; + buf[1] = spi_xcomm->settings >> 8; + buf[2] = spi_xcomm->settings & 0xff; + buf[3] = spi_xcomm->chipselect >> 8; + buf[4] = spi_xcomm->chipselect & 0xff; + + return i2c_master_send(spi_xcomm->i2c, buf, 5); +} + + + +static void spi_xcomm_chipselect(struct spi_device *spi, int is_active) +{ + struct spi_xcomm *spi_xcomm = spi_master_get_devdata(spi->master); + unsigned long cs = spi->chip_select; + uint16_t chipselect = spi_xcomm->chipselect; + uint16_t settings = spi_xcomm->settings; +// static int cs = 0; + + if (is_active) { + settings &= ~BIT(5); + chipselect |= BIT(cs); + } else { + settings |= BIT(5); + chipselect &= ~BIT(cs); + } + + if (chipselect != spi_xcomm->chipselect || settings != spi_xcomm->settings) { + spi_xcomm->chipselect = chipselect; + spi_xcomm->settings = settings; + spi_xcomm_sync_config(spi_xcomm); + } + +// if (!is_active) { +// printk("cs: %d\n", cs); +// cs = (cs + 1) % 16; +// } +} +static int spi_xcomm_setup_transfer(struct spi_device *spi, + struct spi_transfer *t) +{ + struct spi_xcomm *spi_xcomm = spi_master_get_devdata(spi->master); + unsigned int settings = spi_xcomm->settings; + unsigned int speed; + + if ((t->bits_per_word && t->bits_per_word != 8) || t->len > 62) + return -EINVAL; + + speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz; + + if (speed != spi_xcomm->current_speed) { + unsigned int divider = spi_xcomm->clock / speed; + if (divider >= 64 || 1) + settings |= SPI_XCOMM_SETTINGS_CLOCK_DIV_64; + else if (divider >= 16) + settings |= SPI_XCOMM_SETTINGS_CLOCK_DIV_16; + else + settings |= SPI_XCOMM_SETTINGS_CLOCK_DIV_4; + + spi_xcomm->current_speed = speed; + } + + if (spi->mode & SPI_CPOL) + settings |= SPI_XCOMM_SETTINGS_CPOL; + else + settings &= ~SPI_XCOMM_SETTINGS_CPOL; + + if (!(spi->mode & SPI_CPHA)) + settings |= SPI_XCOMM_SETTINGS_CPHA; + else + settings &= ~SPI_XCOMM_SETTINGS_CPHA; + + if (spi->mode & SPI_3WIRE) + settings |= SPI_XCOMM_SETTINGS_3WIRE; + else + settings &= ~SPI_XCOMM_SETTINGS_3WIRE; + + if (settings != spi_xcomm->settings) { + spi_xcomm->settings = settings; + spi_xcomm_sync_config(spi_xcomm); + } + + return 0; +} + +static int spi_xcomm_txrx_bufs(struct spi_device *spi, struct spi_transfer *t, bool is_last) +{ + struct spi_xcomm *spi_xcomm = spi_master_get_devdata(spi->master); + int ret; + unsigned int settings = spi_xcomm->settings; + + if (is_last) + settings |= BIT(5); + else + settings &= ~BIT(5); + + if (t->tx_buf) { + uint8_t buf[63]; + if (settings != spi_xcomm->settings) { + spi_xcomm->settings = settings; + spi_xcomm_sync_config(spi_xcomm); + } + buf[0] = SPI_XCOMM_CMD_WRITE; + memcpy(buf + 1, t->tx_buf, t->len); + + ret = i2c_master_send(spi_xcomm->i2c, buf, t->len + 1); + if (ret < 0) + return ret; + else if (ret != t->len + 1) + return -EIO; + } else if (t->rx_buf) { + uint8_t rx_buf[t->len + 1]; + spi_xcomm->settings = settings & ~(0x3f << 10); + spi_xcomm->settings |= /*(t->len == 1 ? 2 :*/ t->len/*)*/ << 10; + spi_xcomm_sync_config(spi_xcomm); + spi_xcomm->settings &= ~(0x3f << 10); + + ret = i2c_master_recv(spi_xcomm->i2c, rx_buf, /*t->len == 1 ? 2 : */t->len); + if (ret < 0) + return ret; + else if (ret != /*(t->len == 1 ? 2 : */t->len/*)*/) + return -EIO; + memcpy(t->rx_buf, rx_buf, t->len); + } +// msleep(3); + return t->len; +} + +static int spi_xcomm_setup(struct spi_device *spi) +{ + if (spi->bits_per_word != 8) + return -EINVAL; + + return 0; +} + +static int __devinit spi_xcomm_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + uint8_t buf[] = {0x2}; + int ret; + struct spi_master *master; + struct spi_xcomm *spi_xcomm; + + master = spi_alloc_master(&i2c->dev, sizeof(*spi_xcomm)); + if (!master) + return -ENOMEM; + + spi_xcomm = spi_master_get_devdata(master); + i2c_set_clientdata(i2c, spi_xcomm); + spi_xcomm->i2c = i2c; + master->dev.of_node = i2c->dev.of_node; + + master->num_chipselect = 16; + master->setup = spi_xcomm_setup; + master->cleanup = spi_bitbang_cleanup; + + spi_xcomm->bitbang.master = spi_master_get(master); + spi_xcomm->bitbang.chipselect = spi_xcomm_chipselect; + + spi_xcomm->bitbang.setup_transfer = spi_xcomm_setup_transfer; + spi_xcomm->bitbang.txrx_bufs = spi_xcomm_txrx_bufs; + master->flags = SPI_MASTER_HALF_DUPLEX; + + master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_3WIRE; + + spi_xcomm->clock = 48000000; + + ret = spi_bitbang_start(&spi_xcomm->bitbang); + if (ret < 0) + spi_master_put(master); + +// i2c_master_send(i2c, buf, 1); + + return ret; +} + +static int __devexit spi_xcomm_remove(struct i2c_client *i2c) +{ + struct spi_xcomm *spi_xcomm = i2c_get_clientdata(i2c); + int ret; + + ret = spi_bitbang_stop(&spi_xcomm->bitbang); + spi_master_put(spi_xcomm->bitbang.master); + + return ret; +} + +static const struct i2c_device_id spi_xcomm_ids[] = { + { "spi-xcomm", 0 }, + { }, +}; + +static struct i2c_driver spi_xcomm_driver = { + .driver = { + .name = "spi-xcomm", + .owner = THIS_MODULE, + }, + .id_table = spi_xcomm_ids, + .probe = spi_xcomm_probe, + .remove = __devexit_p(spi_xcomm_remove), +}; +/*module_i2c_driver(spi_xcomm_driver);*/ + +static int __init spi_xcomm_init(void) +{ + return i2c_add_driver(&spi_xcomm_driver); +} +module_init(spi_xcomm_init); + +static void __exit spi_xcomm_exit(void) +{ + i2c_del_driver(&spi_xcomm_driver); +} +module_exit(spi_xcomm_exit); + +MODULE_LICENSE("GPL"); diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h index f987a2bee16a8..392fe10d171f5 100644 --- a/include/linux/spi/spi_bitbang.h +++ b/include/linux/spi/spi_bitbang.h @@ -28,8 +28,8 @@ struct spi_bitbang { /* txrx_bufs() may handle dma mapping for transfers that don't * already have one (transfer.{tx,rx}_dma is zero), or use PIO */ - int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t); - +// int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t); + int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t, bool is_last); /* txrx_word[SPI_MODE_*]() just looks like a shift register */ u32 (*txrx_word[4])(struct spi_device *spi, unsigned nsecs, From de31d20c3a2343756e23ae93927081d0eab9387b Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 16 Feb 2012 17:22:25 +0100 Subject: [PATCH 098/261] XCOMM Platform settings - keep local Signed-off-by: Michael Hennerich --- arch/microblaze/platform/platform.c | 265 ++++++++++++++++++++++++++++ 1 file changed, 265 insertions(+) diff --git a/arch/microblaze/platform/platform.c b/arch/microblaze/platform/platform.c index b9529caa507af..eec3d58b8a514 100644 --- a/arch/microblaze/platform/platform.c +++ b/arch/microblaze/platform/platform.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include static struct of_device_id xilinx_of_bus_ids[] __initdata = { { .compatible = "simple-bus", }, @@ -21,10 +23,273 @@ static struct of_device_id xilinx_of_bus_ids[] __initdata = { {} }; +static struct i2c_board_info __initdata xcomm_i2c_board_info[] = { + { + I2C_BOARD_INFO("spi-xcomm", 0x50), + }, +}; + +#if defined(CONFIG_AD9523) || defined(CONFIG_AD9523_MODULE) +#include "../../../../drivers/staging/iio/frequency/ad9523.h" + +struct ad9523_channel_spec ad9523_channels[] = { + { /* ZD output */ + .channel_num = 0, + .extended_name = "ZD_OUTPUT", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = LVDS_7mA, + .divider_phase = 0, + .channel_divider = 5, + .use_alt_clock_src = false, + .output_dis = true, + }, + { /* DAC CLK */ + .channel_num = 1, + .extended_name = "DAC_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = LVPECL_8mA, + .divider_phase = 0, + .channel_divider = 2, + }, + { /* ADC CLK */ + .channel_num = 2, + .extended_name = "ADC_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = LVDS_7mA, + .divider_phase = 0, + .channel_divider = 4, + }, + { /* DAC REF CLK */ + .channel_num = 4, + .extended_name = "DAC_REF_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = LVDS_7mA, + .divider_phase = 0, + .channel_divider = 8, + }, + { /* TX LO REF */ + .channel_num = 5, + .extended_name = "TX_LO_REF_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = CMOS_CONF3, /* HiZ on - */ + .divider_phase = 0, + .channel_divider = 8, + }, + { /* DAC DCO */ + .channel_num = 6, + .extended_name = "DAC_DCO_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = LVDS_7mA, + .divider_phase = 0, + .channel_divider = 2, + }, + { /* ADC SYNC */ + .channel_num = 8, + .extended_name = "ADC_SYNC_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = CMOS_CONF3, /* HiZ on - */ + .divider_phase = 0, + .channel_divider = 32, + .output_dis = true, + }, + { /* RX LO REF */ + .channel_num = 9, + .extended_name = "RX_LO_REF_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = CMOS_CONF3, /* HiZ on - */ + .divider_phase = 0, + .channel_divider = 8, + }, +}; +#if 0 +struct ad9523_platform_data ad9523_pdata = { + .vcxo_freq = 122880000, + + /* Single-Ended Input Configuration */ + .refa_diff_rcv_en = true, + .refb_diff_rcv_en = true, + .zd_in_diff_en = true, + .osc_in_diff_en = false, + + .osc_in_cmos_neg_inp_en = true, + + .refa_r_div = 8, + .refb_r_div = 8, + .pll1_feedback_div = 32, + .pll1_charge_pump_current_nA = 9000, + .zero_delay_mode_internal_en = false, + .osc_in_feedback_en = true, + .pll1_loop_filter_rzero = 3, + + .ref_mode = 1, + + .pll2_charge_pump_current_nA = 420000, + .pll2_ndiv_a_cnt = 0, + .pll2_ndiv_b_cnt = 3, + .pll2_freq_doubler_en = true, + .pll2_r2_div = 1, + .pll2_vco_diff_m1 = 3, + .pll2_vco_diff_m2 = 3, + + .rpole2 = 0, + .rzero = 2, + .cpole1 = 2, + .rzero_bypass_en = false, + + /* Output Channel Configuration */ + .num_channels = ARRAY_SIZE(ad9523_channels), + .channels = ad9523_channels, +}; +#endif +struct ad9523_platform_data ad9523_pdata = { + .vcxo_freq = 122880000, + + /* Single-Ended Input Configuration */ + .refa_diff_rcv_en = true, + .refb_diff_rcv_en = true, + .zd_in_diff_en = false, + .osc_in_diff_en = false, + .osc_in_cmos_neg_inp_en = true, + + .refa_r_div = 0, + .refb_r_div = 0, + .pll1_feedback_div = 4, + .pll1_charge_pump_current_nA = 6000, + .zero_delay_mode_internal_en = true, + .osc_in_feedback_en = true, + .pll1_loop_filter_rzero = 0, + + .ref_mode = 1, + + .pll2_charge_pump_current_nA = 420000, + .pll2_ndiv_a_cnt = 0, + .pll2_ndiv_b_cnt = 3, + .pll2_freq_doubler_en = true, + .pll2_r2_div = 1, + .pll2_vco_diff_m1 = 3, + .pll2_vco_diff_m2 = 3, + + .rpole2 = 0, + .rzero = 2, + .cpole1 = 2, + .rzero_bypass_en = false, + + /* Output Channel Configuration */ + .num_channels = ARRAY_SIZE(ad9523_channels), + .channels = ad9523_channels, +}; +#endif + +#if defined(CONFIG_ADF4350) || defined(CONFIG_ADF4350_MODULE) +#include "../../../../drivers/staging/iio/frequency/adf4350.h" +static struct adf4350_platform_data adf4350_tx_pdata = { + .name = "adf4351-tx", + .clkin = 122880000, + .channel_spacing = 10000, + .r2_user_settings = ADF4350_REG2_PD_POLARITY_POS, + ADF4350_REG2_CHARGE_PUMP_CURR_uA(2500), + .r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0), + .r4_user_settings = ADF4350_REG4_OUTPUT_PWR(3) | + ADF4350_REG4_MUTE_TILL_LOCK_EN, + .gpio_lock_detect = -1, + .power_up_frequency = 2400000000, +}; + +static struct adf4350_platform_data adf4350_rx_pdata = { + .name = "adf4351-rx", + .clkin = 122880000, + .channel_spacing = 10000, + .r2_user_settings = ADF4350_REG2_PD_POLARITY_POS, + ADF4350_REG2_CHARGE_PUMP_CURR_uA(2500), + .r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0), + .r4_user_settings = ADF4350_REG4_OUTPUT_PWR(3) | + ADF4350_REG4_MUTE_TILL_LOCK_EN, + .gpio_lock_detect = -1, + .power_up_frequency = 2400000000, +}; +#endif + +static struct spi_board_info xcomm_spi_board_info[] __initdata = { +#if defined(CONFIG_AD9523) || defined(CONFIG_AD9523_MODULE) + { + .modalias = "ad9523", + .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 3, /* GPIO controlled SSEL */ + .platform_data = &ad9523_pdata, /* No spi_driver specific config */ + .mode = SPI_MODE_0 | SPI_3WIRE, + }, +#endif +#if defined(CONFIG_AD8366) || defined(CONFIG_AD8366_MODULE) + { + .modalias = "ad8366", + .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 6, /* GPIO controlled SSEL */ + .mode = SPI_MODE_0 | SPI_3WIRE, + }, +#endif +#if defined(CONFIG_ADF4350) || defined(CONFIG_ADF4350_MODULE) + { + .modalias = "adf4351", + .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 4, /* GPIO controlled SSEL */ + .platform_data = &adf4350_rx_pdata, /* No spi_driver specific config */ + .mode = SPI_MODE_0, + }, + { + .modalias = "adf4351", + .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 5, /* GPIO controlled SSEL */ + .platform_data = &adf4350_tx_pdata, /* No spi_driver specific config */ + .mode = SPI_MODE_0, + }, +#endif +#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE) + { + .modalias = "spidev", + .max_speed_hz = 10000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 2, /* AD9548 */ + }, +#if 0 +{ + .modalias = "spidev", + .max_speed_hz = 10000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 0, /* AD9122 */ + }, +#endif +#endif +}; + static int __init microblaze_device_probe(void) { of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL); of_platform_reset_gpio_probe(); + + i2c_register_board_info(1, xcomm_i2c_board_info, + ARRAY_SIZE(xcomm_i2c_board_info)); + spi_register_board_info(xcomm_spi_board_info, ARRAY_SIZE(xcomm_spi_board_info)); + return 0; } device_initcall(microblaze_device_probe); From 41e95381b5696aea9439f858e4945245d2351981 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 17 Feb 2012 13:16:27 +0100 Subject: [PATCH 099/261] BF537-STAMP board mods - keep local Signed-off-by: Michael Hennerich --- arch/blackfin/mach-bf537/boards/stamp.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 2221173e489e5..ab1a48dfb7716 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -1418,9 +1418,18 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { .mode = SPI_MODE_3, }, #endif +//#if defined(CONFIG_AD525X_DPOT) || defined(CONFIG_AD525X_DPOT_MODULE) + { + .modalias = "ad5160", + .max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 1, //GPIO_PF10 + MAX_CTRL_CS, + .mode = SPI_MODE_0, + }, +//#endif }; -#if defined(CONFIG_SPI_BFIN5XX) || defined(CONFIG_SPI_BFIN5XX_MODULE) +//#if defined(CONFIG_SPI_BFIN5XX) || defined(CONFIG_SPI_BFIN5XX_MODULE) /* SPI controller data */ static struct bfin5xx_spi_master bfin_spi0_info = { .num_chipselect = MAX_CTRL_CS + MAX_BLACKFIN_GPIOS, @@ -1456,7 +1465,7 @@ static struct platform_device bfin_spi0_device = { .platform_data = &bfin_spi0_info, /* Passed to driver */ }, }; -#endif /* spi master and devices */ +//#endif /* spi master and devices */ #if defined(CONFIG_SPI_BFIN_SPORT) || defined(CONFIG_SPI_BFIN_SPORT_MODULE) @@ -2781,9 +2790,9 @@ static struct platform_device *stamp_devices[] __initdata = { &net2272_bfin_device, #endif -#if defined(CONFIG_SPI_BFIN5XX) || defined(CONFIG_SPI_BFIN5XX_MODULE) +//#if defined(CONFIG_SPI_BFIN5XX) || defined(CONFIG_SPI_BFIN5XX_MODULE) &bfin_spi0_device, -#endif +//#endif #if defined(CONFIG_SPI_BFIN_SPORT) || defined(CONFIG_SPI_BFIN_SPORT_MODULE) &bfin_sport_spi0_device, From f19f4e28dc8315b089f917f5c75161df61c0104a Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 16 Feb 2012 15:17:31 +0100 Subject: [PATCH 100/261] iio: core: Introduce debugfs support, add support for direct register access Changes since V1: debugfs: Exclude iio debugfs code in case CONFIG_DEBUG_FS isn't enabled. Introduce helper function iio_get_debugfs_dentry. Document additions to struct iio_dev iio_debugfs_read_reg: Use snprintf. Use a shorter fixed length. Introduce len instead of pointer math. iio_debugfs_write_reg: Fix return value use PT_ERR. Signed-off-by: Michael Hennerich --- drivers/staging/iio/iio.h | 27 ++++- drivers/staging/iio/industrialio-core.c | 137 +++++++++++++++++++++++- 2 files changed, 162 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h index 76a3f509e5a67..82f7e22ca9c46 100644 --- a/drivers/staging/iio/iio.h +++ b/drivers/staging/iio/iio.h @@ -286,6 +286,9 @@ struct iio_info { struct iio_trigger *trig); int (*update_scan_mode)(struct iio_dev *indio_dev, const unsigned long *scan_mask); + int (*debugfs_reg_access)(struct iio_dev *indio_dev, + unsigned reg, unsigned writeval, + unsigned *readval); }; /** @@ -332,7 +335,9 @@ struct iio_buffer_setup_ops { * @groups: [INTERN] attribute groups * @groupcounter: [INTERN] index of next attribute group * @flags: [INTERN] file ops related flags including busy flag. - **/ + * @debugfs_dentry: [INTERN] device specific debugfs dentry. + * @cached_reg_addr: [INTERN] cached register address for debugfs reads. +**/ struct iio_dev { int id; @@ -366,6 +371,10 @@ struct iio_dev { int groupcounter; unsigned long flags; +#if defined(CONFIG_DEBUG_FS) + struct dentry *debugfs_dentry; + unsigned cached_reg_addr; +#endif }; /** @@ -443,4 +452,20 @@ static inline bool iio_buffer_enabled(struct iio_dev *indio_dev) & (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE); }; +/** + * iio_get_debugfs_dentry() - helper function to get the debugfs_dentry + * @indio_dev: IIO device info structure for device + **/ +#if defined(CONFIG_DEBUG_FS) +static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) +{ + return indio_dev->debugfs_dentry; +}; +#else +static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) +{ + return NULL; +}; +#endif + #endif /* _INDUSTRIAL_IO_H_ */ diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 645bb45c89e80..67ee3d85f39a1 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "iio.h" #include "iio_core.h" #include "iio_core_trigger.h" @@ -39,6 +40,8 @@ struct bus_type iio_bus_type = { }; EXPORT_SYMBOL(iio_bus_type); +static struct dentry *iio_debugfs_dentry; + static const char * const iio_data_type_name[] = { [IIO_RAW] = "raw", [IIO_PROCESSED] = "input", @@ -129,6 +132,8 @@ static int __init iio_init(void) goto error_unregister_bus_type; } + iio_debugfs_dentry = debugfs_create_dir("iio", NULL); + return 0; error_unregister_bus_type: @@ -142,6 +147,84 @@ static void __exit iio_exit(void) if (iio_devt) unregister_chrdev_region(iio_devt, IIO_DEV_MAX); bus_unregister(&iio_bus_type); + debugfs_remove_recursive(iio_debugfs_dentry); +} + +#if defined(CONFIG_DEBUG_FS) +static int iio_debugfs_open(struct inode *inode, struct file *file) +{ + if (inode->i_private) + file->private_data = inode->i_private; + + return 0; +} + +static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct iio_dev *indio_dev = file->private_data; + char buf[20]; + unsigned val = 0; + ssize_t len; + int ret; + + ret = indio_dev->info->debugfs_reg_access(indio_dev, + indio_dev->cached_reg_addr, + 0, &val); + if (ret) + dev_err(indio_dev->dev.parent, "%s: read failed\n", __func__); + + len = snprintf(buf, sizeof(buf), "0x%X\n", val); + + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} + +static ssize_t iio_debugfs_write_reg(struct file *file, + const char __user *userbuf, size_t count, loff_t *ppos) +{ + struct iio_dev *indio_dev = file->private_data; + unsigned reg, val; + char buf[80]; + int ret; + + count = min_t(size_t, count, (sizeof(buf)-1)); + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + buf[count] = 0; + + ret = sscanf(buf, "%i %i", ®, &val); + + switch (ret) { + case 1: + indio_dev->cached_reg_addr = reg; + break; + case 2: + indio_dev->cached_reg_addr = reg; + ret = indio_dev->info->debugfs_reg_access(indio_dev, reg, + val, NULL); + if (ret) { + dev_err(indio_dev->dev.parent, "%s: write failed\n", + __func__); + return ret; + } + break; + default: + return -EINVAL; + } + + return count; +} + +static const struct file_operations iio_debugfs_reg_fops = { + .open = iio_debugfs_open, + .read = iio_debugfs_read_reg, + .write = iio_debugfs_write_reg, +}; + +static void iio_device_unregister_debugfs(struct iio_dev *indio_dev) +{ + debugfs_remove_recursive(indio_dev->debugfs_dentry); } static ssize_t iio_read_channel_ext_info(struct device *dev, @@ -171,6 +254,49 @@ static ssize_t iio_write_channel_ext_info(struct device *dev, return ext_info->write(indio_dev, this_attr->c, buf, len); } +static int iio_device_register_debugfs(struct iio_dev *indio_dev) +{ + struct dentry *d; + + if (indio_dev->info->debugfs_reg_access == NULL) + return 0; + + if (IS_ERR(iio_debugfs_dentry)) + return 0; + + indio_dev->debugfs_dentry = + debugfs_create_dir(dev_name(&indio_dev->dev), + iio_debugfs_dentry); + if (IS_ERR(indio_dev->debugfs_dentry)) + return PTR_ERR(indio_dev->debugfs_dentry); + + if (indio_dev->debugfs_dentry == NULL) { + dev_warn(indio_dev->dev.parent, + "Failed to create debugfs directory\n"); + return -EFAULT; + } + + d = debugfs_create_file("direct_reg_access", 0644, + indio_dev->debugfs_dentry, + indio_dev, &iio_debugfs_reg_fops); + if (!d) { + iio_device_unregister_debugfs(indio_dev); + return -ENOMEM; + } + + return 0; +} +#else +static int iio_device_register_debugfs(struct iio_dev *indio_dev) +{ + return 0; +} + +static void iio_device_unregister_debugfs(struct iio_dev *indio_dev) +{ +} +#endif /* CONFIG_DEBUG_FS */ + static ssize_t iio_read_channel_info(struct device *dev, struct device_attribute *attr, char *buf) @@ -618,6 +744,7 @@ static void iio_dev_release(struct device *device) iio_device_unregister_trigger_consumer(indio_dev); iio_device_unregister_eventset(indio_dev); iio_device_unregister_sysfs(indio_dev); + iio_device_unregister_debugfs(indio_dev); } static struct device_type iio_dev_type = { @@ -734,11 +861,17 @@ int iio_device_register(struct iio_dev *indio_dev) /* configure elements for the chrdev */ indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); + ret = iio_device_register_debugfs(indio_dev); + if (ret) { + dev_err(indio_dev->dev.parent, + "Failed to register debugfs interfaces\n"); + goto error_ret; + } ret = iio_device_register_sysfs(indio_dev); if (ret) { dev_err(indio_dev->dev.parent, "Failed to register sysfs interfaces\n"); - goto error_ret; + goto error_unreg_debugfs; } ret = iio_device_register_eventset(indio_dev); if (ret) { @@ -765,6 +898,8 @@ int iio_device_register(struct iio_dev *indio_dev) iio_device_unregister_eventset(indio_dev); error_free_sysfs: iio_device_unregister_sysfs(indio_dev); +error_unreg_debugfs: + iio_device_unregister_debugfs(indio_dev); error_ret: return ret; } From c1042a2adf0085b93b9591ef0ec18db5d754bace Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 21 Feb 2012 18:04:40 +0100 Subject: [PATCH 101/261] iio: core: Avoid NULL pointer de-ref in case indio_dev->setup_ops are not in use Drivers may not need setup_ops at all, so let the core supply some empty ops. Signed-off-by: Michael Hennerich --- drivers/staging/iio/industrialio-core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 67ee3d85f39a1..5e2056f8e28cd 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -854,6 +854,8 @@ static const struct file_operations iio_buffer_fileops = { .compat_ioctl = iio_ioctl, }; +static const struct iio_buffer_setup_ops noop_ring_setup_ops; + int iio_device_register(struct iio_dev *indio_dev) { int ret; @@ -882,6 +884,10 @@ int iio_device_register(struct iio_dev *indio_dev) if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) iio_device_register_trigger_consumer(indio_dev); + if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) && + indio_dev->setup_ops == NULL) + indio_dev->setup_ops = &noop_ring_setup_ops; + ret = device_add(&indio_dev->dev); if (ret < 0) goto error_unreg_eventset; From a4540f227104fa0dbe069f8b394211cf136b5b53 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 17 Feb 2012 17:04:41 +0100 Subject: [PATCH 102/261] iio: Convert platform_drivers to use module_platform_driver No functional changes. Signed-off-by: Michael Hennerich --- drivers/staging/iio/adc/ad7606_par.c | 13 +------------ drivers/staging/iio/trigger/iio-trig-bfin-timer.c | 12 +----------- drivers/staging/iio/trigger/iio-trig-gpio.c | 12 +----------- drivers/staging/iio/trigger/iio-trig-periodic-rtc.c | 12 +----------- 4 files changed, 4 insertions(+), 45 deletions(-) diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c index cff97568189e4..bb152a8e8c920 100644 --- a/drivers/staging/iio/adc/ad7606_par.c +++ b/drivers/staging/iio/adc/ad7606_par.c @@ -173,18 +173,7 @@ static struct platform_driver ad7606_driver = { }, }; -static int __init ad7606_init(void) -{ - return platform_driver_register(&ad7606_driver); -} - -static void __exit ad7606_cleanup(void) -{ - platform_driver_unregister(&ad7606_driver); -} - -module_init(ad7606_init); -module_exit(ad7606_cleanup); +module_platform_driver(ad7606_driver); MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c index 1cbb25dff8b5d..665653d79f029 100644 --- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c +++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c @@ -232,17 +232,7 @@ static struct platform_driver iio_bfin_tmr_trigger_driver = { .remove = __devexit_p(iio_bfin_tmr_trigger_remove), }; -static int __init iio_bfin_tmr_trig_init(void) -{ - return platform_driver_register(&iio_bfin_tmr_trigger_driver); -} -module_init(iio_bfin_tmr_trig_init); - -static void __exit iio_bfin_tmr_trig_exit(void) -{ - platform_driver_unregister(&iio_bfin_tmr_trigger_driver); -} -module_exit(iio_bfin_tmr_trig_exit); +module_platform_driver(iio_bfin_tmr_trigger_driver); MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("Blackfin system timer based trigger for the iio subsystem"); diff --git a/drivers/staging/iio/trigger/iio-trig-gpio.c b/drivers/staging/iio/trigger/iio-trig-gpio.c index f2a6559816223..a3465947235ea 100644 --- a/drivers/staging/iio/trigger/iio-trig-gpio.c +++ b/drivers/staging/iio/trigger/iio-trig-gpio.c @@ -160,17 +160,7 @@ static struct platform_driver iio_gpio_trigger_driver = { }, }; -static int __init iio_gpio_trig_init(void) -{ - return platform_driver_register(&iio_gpio_trigger_driver); -} -module_init(iio_gpio_trig_init); - -static void __exit iio_gpio_trig_exit(void) -{ - platform_driver_unregister(&iio_gpio_trigger_driver); -} -module_exit(iio_gpio_trig_exit); +module_platform_driver(iio_gpio_trigger_driver); MODULE_AUTHOR("Jonathan Cameron "); MODULE_DESCRIPTION("Example gpio trigger for the iio subsystem"); diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c index bd7416b2c561a..a80cf67bf84d5 100644 --- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c +++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c @@ -195,18 +195,8 @@ static struct platform_driver iio_trig_periodic_rtc_driver = { }, }; -static int __init iio_trig_periodic_rtc_init(void) -{ - return platform_driver_register(&iio_trig_periodic_rtc_driver); -} - -static void __exit iio_trig_periodic_rtc_exit(void) -{ - return platform_driver_unregister(&iio_trig_periodic_rtc_driver); -} +module_platform_driver(iio_trig_periodic_rtc_driver); -module_init(iio_trig_periodic_rtc_init); -module_exit(iio_trig_periodic_rtc_exit); MODULE_AUTHOR("Jonathan Cameron "); MODULE_DESCRIPTION("Periodic realtime clock trigger for the iio subsystem"); MODULE_LICENSE("GPL v2"); From d8526ebb43999fa23a174b52d4ac7ad9e0b93f23 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 17 Feb 2012 13:35:31 +0100 Subject: [PATCH 103/261] of_spi: New function spi_of_node_to_master look up master associated with of_node Signed-off-by: Michael Hennerich --- drivers/of/of_spi.c | 28 ++++++++++++++++++++++++++++ drivers/spi/spi.c | 4 ++-- include/linux/of_spi.h | 1 + include/linux/spi/spi.h | 2 ++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/drivers/of/of_spi.c b/drivers/of/of_spi.c index 6dbc074e4876a..f3dee01dcd4c0 100644 --- a/drivers/of/of_spi.c +++ b/drivers/of/of_spi.c @@ -97,3 +97,31 @@ void of_register_spi_devices(struct spi_master *master) } } EXPORT_SYMBOL(of_register_spi_devices); + +static int __spi_master_of_match(struct device *dev, void *data) +{ + struct device_node *of_node = data; + return dev->of_node == of_node; +} + +/** + * spi_of_node_to_master - look up master associated with of_node + * @of_node: pointer to the device tree node. + * Context: can sleep + * + * Returns a pointer to the relevant spi_master, or NULL if there is + * no such master registered. + */ +struct spi_master *spi_of_node_to_master(struct device_node *of_node) +{ + struct device *dev; + struct spi_master *master = NULL; + + dev = class_find_device(&spi_master_class, NULL, of_node, + __spi_master_of_match); + if (dev) + master = container_of(dev, struct spi_master, dev); + + return master; +} +EXPORT_SYMBOL_GPL(spi_of_node_to_master); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index b2ccdea30cb92..6f63a8ee4b3bf 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -515,12 +515,12 @@ static void spi_master_release(struct device *dev) kfree(master); } -static struct class spi_master_class = { +struct class spi_master_class = { .name = "spi_master", .owner = THIS_MODULE, .dev_release = spi_master_release, }; - +EXPORT_SYMBOL_GPL(spi_master_class); /** * spi_alloc_master - allocate SPI master controller diff --git a/include/linux/of_spi.h b/include/linux/of_spi.h index 9e3e70f78ae64..e1bafd279601b 100644 --- a/include/linux/of_spi.h +++ b/include/linux/of_spi.h @@ -13,6 +13,7 @@ #if defined(CONFIG_OF_SPI) || defined(CONFIG_OF_SPI_MODULE) extern void of_register_spi_devices(struct spi_master *master); +extern struct spi_master *spi_of_node_to_master(struct device_node *of_node); #else static inline void of_register_spi_devices(struct spi_master *master) { diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 176fce9cc6b18..62e566e2abb84 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -805,4 +805,6 @@ spi_unregister_device(struct spi_device *spi) extern const struct spi_device_id * spi_get_device_id(const struct spi_device *sdev); +extern struct class spi_master_class; + #endif /* __LINUX_SPI_H */ From 94c289e30bd6962d9eed0c04f6f7c8ae198bb6de Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 17 Feb 2012 13:09:05 +0100 Subject: [PATCH 104/261] iio: adc: New driver for AD9467 and AD9643 High-Speed LVDS ADCs Suitable FPGA interface HDL is available here: http://wiki.analog.com/resources/fpga/xilinx/fmc/ad9467 Changes since V1: Use iio_get_debugfs_dentry. Return error in case the no scale matches. Remove extend_name. No need to register ring functions, remove them. No need to clear stufftoread Minor miscellaneous cleanup, no functional changes. Signed-off-by: Michael Hennerich --- drivers/staging/iio/adc/Kconfig | 13 + drivers/staging/iio/adc/Makefile | 3 + drivers/staging/iio/adc/cf_ad9467.h | 160 ++++++ drivers/staging/iio/adc/cf_ad9467_core.c | 590 +++++++++++++++++++++++ drivers/staging/iio/adc/cf_ad9467_ring.c | 186 +++++++ 5 files changed, 952 insertions(+) create mode 100644 drivers/staging/iio/adc/cf_ad9467.h create mode 100644 drivers/staging/iio/adc/cf_ad9467_core.c create mode 100644 drivers/staging/iio/adc/cf_ad9467_ring.c diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index 592eabd85f365..5793c612de2cd 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -169,6 +169,19 @@ config AD7280 To compile this driver as a module, choose M here: the module will be called ad7280a +config CF_AD9467 + tristate "Analog Devices AD9467 AD9643 High-Speed ADC driver" + select IIO_BUFFER + help + Say yes here to build support for Analog Devices AD9467 and AD9643, + High-Speed LVDS analog to digital converters (ADC). + FPGA interface HDL is available here: + http://wiki.analog.com/resources/fpga/xilinx/fmc/ad9467 + If unsure, say N (but it's safe to say "Y"). + + To compile this driver as a module, choose M here: the + module will be called cf_ad9467. + config MAX1363 tristate "Maxim max1363 ADC driver" depends on I2C diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile index f83ab9551d8ee..dfc1287da7b3d 100644 --- a/drivers/staging/iio/adc/Makefile +++ b/drivers/staging/iio/adc/Makefile @@ -29,6 +29,9 @@ ad7298-y := ad7298_core.o ad7298-$(CONFIG_IIO_BUFFER) += ad7298_ring.o obj-$(CONFIG_AD7298) += ad7298.o +cf_ad9467-y := cf_ad9467_core.o cf_ad9467_ring.o +obj-$(CONFIG_CF_AD9467) += cf_ad9467.o + obj-$(CONFIG_AD7291) += ad7291.o obj-$(CONFIG_AD7780) += ad7780.o obj-$(CONFIG_AD7793) += ad7793.o diff --git a/drivers/staging/iio/adc/cf_ad9467.h b/drivers/staging/iio/adc/cf_ad9467.h new file mode 100644 index 0000000000000..24bae295ae552 --- /dev/null +++ b/drivers/staging/iio/adc/cf_ad9467.h @@ -0,0 +1,160 @@ +/* + * ADI-AIM ADI ADC Interface Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + * + * http://wiki.analog.com/resources/fpga/xilinx/fmc/ad9467 + */ + +#ifndef ADI_AIM_H_ +#define ADI_AIM_H_ + +/* PCORE CoreFPGA register map */ + +#define AD9467_PCORE_VERSION 0x00 +#define AD9467_PCORE_SPI_CTRL 0x04 +#define AD9467_PCORE_SPI_RDSTAT 0x08 +#define AD9467_PCORE_DMA_CTRL 0x0C +#define AD9467_PCORE_DMA_STAT 0x10 +#define AD9467_PCORE_ADC_STAT 0x14 +#define AD9467_PCORE_PN_ERR_CTRL 0x24 + +/* AD9467_PCORE_SPI_CTRL */ +#define AD9647_SPI_START (1 << 25) +#define AD9647_SPI_SEL(x) (((x) & 0x1) << 24) +#define AD9647_SPI_READ (1 << 23) +#define AD9647_SPI_WRITE (0 << 23) +#define AD9647_SPI_ADDR(x) (((x) & 0x1FFF) << 8) +#define AD9647_SPI_DATA(x) (((x) & 0xFF) << 0) + +/* AD9467_PCORE_SPI_RDSTAT */ +#define AD9647_SPI_IDLE (1 << 8) +#define AD9647_SPI_READVAL(x) ((x) & 0xFF) + +/* AD9467_PCORE_DMA_CTRL */ +#define AD9647_DMA_CAP_EN (1 << 16) +#define AD9647_DMA_CNT(x) (((x) & 0xFFFF) << 0) + +/* AD9467_PCORE_DMA_STAT */ +#define AD9647_DMA_STAT_BUSY (1 << 0) +#define AD9647_DMA_STAT_OVF (1 << 1) +#define AD9647_DMA_STAT_UNF (1 << 2) + +/* AD9467_PCORE_ADC_STAT */ +#define AD9467_PCORE_ADC_STAT_OVR (1 << 0) +#define AD9467_PCORE_ADC_STAT_PN_OOS (1 << 1) /* W1C */ +#define AD9467_PCORE_ADC_STAT_PN_ERR (1 << 2) /* W1C */ + +/* AD9467_PCORE_PN_ERR_CTRL */ +#define AD9467_PN23_EN (1 << 0) +#define AD9467_PN9_EN (0 << 0) + +/* + * ADI High-Speed ADC common spi interface registers + * See Application-Note AN-877 + */ + +#define ADC_REG_CHIP_PORT_CONF 0x00 +#define ADC_REG_CHIP_ID 0x01 +#define ADC_REG_CHIP_GRADE 0x02 +#define ADC_REG_TRANSFER 0xFF +#define ADC_REG_MODES 0x08 +#define ADC_REG_TEST_IO 0x0D +#define ADC_REG_ADC_INPUT 0x0F +#define ADC_REG_OFFSET 0x10 +#define ADC_REG_OUTPUT_MODE 0x14 +#define ADC_REG_OUTPUT_ADJUST 0x15 +#define ADC_REG_OUTPUT_PHASE 0x16 +#define ADC_REG_OUTPUT_DELAY 0x17 +#define ADC_REG_VREF 0x18 +#define ADC_REG_ANALOG_INPUT 0x2C + +/* ADC_REG_TRANSFER */ +#define TRANSFER_SYNC 0x1 + +/* ADC_REG_TEST_IO */ +#define TESTMODE_OFF 0x0 +#define TESTMODE_MIDSCALE_SHORT 0x1 +#define TESTMODE_POS_FULLSCALE 0x2 +#define TESTMODE_NEG_FULLSCALE 0x3 +#define TESTMODE_ALT_CHECKERBOARD 0x4 +#define TESTMODE_PN23_SEQ 0x5 +#define TESTMODE_PN9_SEQ 0x6 +#define TESTMODE_ONE_ZERO_TOGGLE 0x7 + +/* ADC_REG_OUTPUT_MODE */ +#define OUTPUT_MODE_OFFSET_BINARY 0x0 +#define OUTPUT_MODE_TWOS_COMPLEMENT 0x1 +#define OUTPUT_MODE_GRAY_CODE 0x2 + +/* + * Analog Devices AD9467 16-Bit, 200/250 MSPS ADC + */ + +#define AD9467_DEF_OUTPUT_MODE 0x08 +#define AD9467_REG_VREF_MASK 0x0F +#define CHIPID_AD9467 0x50 + +/* + * Analog Devices AD9643 Dual 14-Bit, 170/210/250 MSPS ADC + */ + +#define CHIPID_AD9643 0x82 +#define AD9643_REG_VREF_MASK 0x1F +#define AD9643_DEF_OUTPUT_MODE 0x04 + +enum { + ID_AD9467, + ID_AD9643, +}; + +struct aim_chip_info { + char name[8]; + unsigned num_channels; + unsigned long available_scan_masks[2]; + const int (*scale_table)[2]; + int num_scales; + struct iio_chan_spec channel[2]; +}; + +struct aim_state { + struct spi_device *spi; + struct mutex lock; + struct completion dma_complete; + struct dma_chan *rx_chan; + const struct aim_chip_info *chip_info; + void __iomem *regs; + void *buf_virt; + dma_addr_t buf_phys; + unsigned spi_ssel; + unsigned ring_lenght; + unsigned bytes_per_datum; + unsigned id; + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + + unsigned char data[3] ____cacheline_aligned; +}; + +/* + * IO accessors + */ + +static inline void aim_write(struct aim_state *st, unsigned reg, unsigned val) +{ + iowrite32(val, st->regs + reg); +} + +static inline unsigned int aim_read(struct aim_state *st, unsigned reg) +{ + return ioread32(st->regs + reg); +} + +int aim_configure_ring(struct iio_dev *indio_dev); +void aim_unconfigure_ring(struct iio_dev *indio_dev); + +#endif /* ADI_AIM_H_ */ diff --git a/drivers/staging/iio/adc/cf_ad9467_core.c b/drivers/staging/iio/adc/cf_ad9467_core.c new file mode 100644 index 0000000000000..206fe38ecfd68 --- /dev/null +++ b/drivers/staging/iio/adc/cf_ad9467_core.c @@ -0,0 +1,590 @@ +/* + * ADI-AIM ADI ADC Interface Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + * + * http://wiki.analog.com/resources/fpga/xilinx/fmc/ad9467 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "../buffer.h" + +#include "cf_ad9467.h" + +static int aim_spi_read(struct aim_state *st, unsigned reg) +{ + unsigned long timeout = jiffies + HZ / 4; + int ret; + + if (st->spi) { + unsigned char *buf = st->data; + buf[0] = 0x80 | (reg >> 8); + buf[1] = reg & 0xFF; + + ret = spi_write_then_read(st->spi, &buf[0], 2, &buf[2], 1); + if (ret < 0) + return ret; + + return buf[2]; + } + + aim_write(st, AD9467_PCORE_SPI_CTRL, 0); + aim_write(st, AD9467_PCORE_SPI_CTRL, + AD9647_SPI_START | + AD9647_SPI_READ | + AD9647_SPI_SEL(st->spi_ssel) | + AD9647_SPI_ADDR(reg)); + + while (!(aim_read(st, AD9467_PCORE_SPI_RDSTAT) & AD9647_SPI_IDLE)) { + cpu_relax(); + if (time_after(jiffies, timeout)) + return -EIO; + } + + return AD9647_SPI_READVAL(aim_read(st, AD9467_PCORE_SPI_RDSTAT)); +} + +static int aim_spi_write(struct aim_state *st, unsigned reg, unsigned val) +{ + unsigned long timeout = jiffies + HZ / 4; + + int ret; + + if (st->spi) { + unsigned char *buf = st->data; + buf[0] = reg >> 8; + buf[1] = reg & 0xFF; + buf[2] = val; + ret = spi_write(st->spi, buf, 3); + if (ret < 0) + return ret; + + return 0; + } + + aim_write(st, AD9467_PCORE_SPI_CTRL, 0); + aim_write(st, AD9467_PCORE_SPI_CTRL, + AD9647_SPI_START | + AD9647_SPI_WRITE | + AD9647_SPI_SEL(st->spi_ssel) | + AD9647_SPI_ADDR(reg) | + AD9647_SPI_DATA(val)); + + + while (!(aim_read(st, AD9467_PCORE_SPI_RDSTAT) & AD9647_SPI_IDLE)) { + cpu_relax(); + if (time_after(jiffies, timeout)) + return -EIO; + } + + return 0; +} + +static int aim_debugfs_open(struct inode *inode, struct file *file) +{ + if (inode->i_private) + file->private_data = inode->i_private; + + return 0; +} + +static ssize_t aim_debugfs_pncheck_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct iio_dev *indio_dev = file->private_data; + struct aim_state *st = iio_priv(indio_dev); + char buf[80]; + ssize_t len; + unsigned stat; + + stat = aim_read(st, AD9467_PCORE_ADC_STAT); + len = sprintf(buf, "%s %s\n", (stat & AD9467_PCORE_ADC_STAT_PN_OOS) ? + "Out of Sync :" : "In Sync :", + (stat & AD9467_PCORE_ADC_STAT_PN_ERR) ? + "PN Error" : "No Error"); + + aim_write(st, AD9467_PCORE_ADC_STAT, 0xF); + + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} + +static ssize_t aim_debugfs_pncheck_write(struct file *file, + const char __user *userbuf, size_t count, loff_t *ppos) +{ + struct iio_dev *indio_dev = file->private_data; + struct aim_state *st = iio_priv(indio_dev); + unsigned mode; + char buf[80], *p = buf; + + count = min_t(size_t, count, (sizeof(buf)-1)); + if (copy_from_user(p, userbuf, count)) + return -EFAULT; + + p[count] = 0; + + if (sysfs_streq(p, "PN9")) + mode = TESTMODE_PN9_SEQ; + else if (sysfs_streq(p, "PN23")) + mode = TESTMODE_PN23_SEQ; + else + mode = TESTMODE_OFF; + + aim_spi_write(st, ADC_REG_TEST_IO, mode); + aim_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); + + aim_write(st, AD9467_PCORE_PN_ERR_CTRL, (mode == TESTMODE_PN23_SEQ) ? + AD9467_PN23_EN : AD9467_PN9_EN); + + mdelay(1); /* FIXME */ + + aim_write(st, AD9467_PCORE_ADC_STAT, + AD9467_PCORE_ADC_STAT_PN_OOS | + AD9467_PCORE_ADC_STAT_PN_OOS | + AD9467_PCORE_ADC_STAT_OVR); + + return count; +} + +static const struct file_operations aim_debugfs_pncheck_fops = { + .open = aim_debugfs_open, + .read = aim_debugfs_pncheck_read, + .write = aim_debugfs_pncheck_write, +}; + +static int aim_reg_access(struct iio_dev *indio_dev, + unsigned reg, unsigned writeval, + unsigned *readval) +{ + struct aim_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&indio_dev->mlock); + if (readval == NULL) { + ret = aim_spi_write(st, reg, writeval); + aim_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); + } else { + ret = aim_spi_read(st, reg); + if (ret < 0) + return ret; + *readval = ret; + + ret = 0; + } + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int aim_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct aim_state *st = iio_priv(indio_dev); + int i; + unsigned vref_val; + + switch (m) { + case IIO_CHAN_INFO_SCALE: + vref_val = aim_spi_read(st, ADC_REG_VREF) & + (st->id == CHIPID_AD9643 ? AD9643_REG_VREF_MASK : + AD9467_REG_VREF_MASK); + + for (i = 0; i < st->chip_info->num_scales; i++) + if (vref_val == st->chip_info->scale_table[i][1]) + break; + + *val = 0; + *val2 = st->chip_info->scale_table[i][0]; + + return IIO_VAL_INT_PLUS_MICRO; + } + return -EINVAL; +} + + +static int aim_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct aim_state *st = iio_priv(indio_dev); + int i; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + if (val != 0) + return -EINVAL; + + for (i = 0; i < st->chip_info->num_scales; i++) + if (val2 == st->chip_info->scale_table[i][0]) { + aim_spi_write(st, ADC_REG_VREF, + st->chip_info->scale_table[i][1]); + aim_spi_write(st, ADC_REG_TRANSFER, + TRANSFER_SYNC); + return 0; + } + + return -EINVAL; + default: + return -EINVAL; + } +} + +static ssize_t aim_show_scale_available(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct aim_state *st = iio_priv(indio_dev); + int i, len = 0; + + for (i = 0; i < st->chip_info->num_scales; i++) + len += sprintf(buf + len, "0.%06u ", + st->chip_info->scale_table[i][0]); + + len += sprintf(buf + len, "\n"); + + return len; +} + +static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO, + aim_show_scale_available, NULL, 0); + +static struct attribute *aim_attributes[] = { + &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group aim_attribute_group = { + .attrs = aim_attributes, +}; + +static const int ad9467_scale_table[][2] = { + {30517, 0}, {32043, 6}, {33569, 7}, + {35095, 8}, {36621, 9}, {38146, 10}, +}; + +static const int ad9643_scale_table[][2] = { + {31738, 0xF}, {31403, 0xE}, {31067, 0xD}, {30731, 0xC}, {30396, 0xB}, + {30060, 0xA}, {29724, 0x9}, {29388, 0x8}, {29053, 0x7}, {28717, 0x6}, + {28381, 0x5}, {28046, 0x4}, {27710, 0x3}, {27374, 0x2}, {27039, 0x1}, + {26703, 0x0}, {26367, 0x1F}, {26031, 0x1E}, {25696, 0x1D}, + {25360, 0x1C}, {25024, 0x1B}, {24689, 0x1A}, {24353, 0x19}, + {24017, 0x18}, {23682, 0x17}, {23346, 0x16}, {23010, 0x15}, + {22675, 0x14}, {22339, 0x13}, {22003, 0x12}, {21667, 0x11}, + {21332, 0x10}, +}; + +#define AIM_CHAN(_chan, _si, _bits, _sign) \ + { .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = _chan, \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .scan_index = _si, \ + .scan_type = IIO_ST(_sign, _bits, 16, 0)} + +static const struct aim_chip_info aim_chip_info_tbl[] = { + [ID_AD9467] = { + .name = "AD9467", + .scale_table = ad9467_scale_table, + .num_scales = ARRAY_SIZE(ad9467_scale_table), + .num_channels = 1, + .available_scan_masks[0] = BIT(0), + .channel[0] = AIM_CHAN(0, 0, 16, 's'), + }, + [ID_AD9643] = { + .name = "AD9643", + .scale_table = ad9643_scale_table, + .num_scales = ARRAY_SIZE(ad9643_scale_table), + .num_channels = 2, + .available_scan_masks[0] = BIT(0) | BIT(1), + .channel[0] = AIM_CHAN(0, 0, 14, 'u'), + .channel[1] = AIM_CHAN(1, 1, 14, 'u'), + }, +}; + +static const struct iio_info aim_info = { + .driver_module = THIS_MODULE, + .read_raw = &aim_read_raw, + .write_raw = &aim_write_raw, + .attrs = &aim_attribute_group, + .debugfs_reg_access = &aim_reg_access, +}; + +struct aim_dma_params { + struct device_node *of_node; + int chan_id; +}; + +static bool aim_dma_filter(struct dma_chan *chan, void *param) +{ + struct aim_dma_params *p = param; + + return chan->device->dev->of_node == p->of_node && + chan->chan_id == p->chan_id; +} + +/** + * aim_of_probe - probe method for the AIM device. + * @of_dev: pointer to OF device structure + * @match: pointer to the structure used for matching a device + * + * This function probes the AIM device in the device tree. + * It initializes the driver data structure and the hardware. + * It returns 0, if the driver is bound to the AIM device, or a negative + * value if there is an error. + */ +static int __devinit aim_of_probe(struct platform_device *op) +{ + struct iio_dev *indio_dev; + struct device *dev = &op->dev; + struct aim_state *st; + struct resource r_mem; /* IO mem resources */ + struct spi_master *spi_master; + struct device_node *nspi; + struct aim_dma_params dma_params; + struct of_phandle_args dma_spec; + dma_cap_mask_t mask; + resource_size_t remap_size, phys_addr; + unsigned def_mode; + int ret; + + dev_info(dev, "Device Tree Probing \'%s\'\n", + op->dev.of_node->name); + + /* Get iospace for the device */ + ret = of_address_to_resource(op->dev.of_node, 0, &r_mem); + if (ret) { + dev_err(dev, "invalid address\n"); + return ret; + } + + indio_dev = iio_allocate_device(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + + dev_set_drvdata(dev, indio_dev); + mutex_init(&st->lock); + + phys_addr = r_mem.start; + remap_size = resource_size(&r_mem); + if (!request_mem_region(phys_addr, remap_size, KBUILD_MODNAME)) { + dev_err(dev, "Couldn't lock memory region at 0x%08llX\n", + (unsigned long long)phys_addr); + ret = -EBUSY; + goto failed1; + } + + st->regs = ioremap(phys_addr, remap_size); + if (st->regs == NULL) { + dev_err(dev, "Couldn't ioremap memory at 0x%08llX\n", + (unsigned long long)phys_addr); + ret = -EFAULT; + goto failed2; + } + /* Get dma channel for the device */ + ret = of_parse_phandle_with_args(op->dev.of_node, "dma-request", + "#dma-cells", 0, &dma_spec); + if (ret) { + dev_err(dev, "Couldn't parse dma-request\n"); + goto failed2; + } + + dma_params.of_node = dma_spec.np; + dma_params.chan_id = dma_spec.args[0]; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE | DMA_PRIVATE, mask); + + st->rx_chan = dma_request_channel(mask, aim_dma_filter, &dma_params); + if (!st->rx_chan) { + dev_err(dev, "failed to find rx dma device\n"); + goto failed2; + } + /* + * Get SPI configuration interface for the device + * We are platform_driver, so we need other means to get the + * associated control interface. + */ + ret = of_property_read_u32(op->dev.of_node, + "spibus-slaveselect-connected", + &st->spi_ssel); + if (ret) { + dev_err(dev, "failed to get connected SPI slave select\n"); + goto failed3; + } + + nspi = of_parse_phandle(op->dev.of_node, "spibus-connected", 0); + spi_master = spi_of_node_to_master(nspi); + + if (spi_master != NULL) { + struct spi_board_info info = { + .modalias = KBUILD_MODNAME, + .max_speed_hz = 1000000, + .chip_select = st->spi_ssel, + .mode = SPI_MODE_0 | SPI_3WIRE, + }; + st->spi = spi_new_device(spi_master, &info); + if (st->spi == NULL) { + dev_err(dev, "failed to add spi device\n"); + goto failed3; + } + } else { + dev_dbg(dev, "could not find SPI master node," + "using pcore spi implementation\n"); + } + + /* Probe device */ + st->id = aim_spi_read(st, ADC_REG_CHIP_ID); + + switch (st->id) { + case CHIPID_AD9467: + st->chip_info = &aim_chip_info_tbl[ID_AD9467]; + def_mode = AD9467_DEF_OUTPUT_MODE | OUTPUT_MODE_TWOS_COMPLEMENT; + break; + case CHIPID_AD9643: + st->chip_info = &aim_chip_info_tbl[ID_AD9643]; + def_mode = AD9643_DEF_OUTPUT_MODE | OUTPUT_MODE_OFFSET_BINARY; + break; + default: + dev_err(dev, "Unrecognized CHIP_ID 0x%X\n", st->id); + ret = -ENODEV; + goto failed3; + } + + indio_dev->dev.parent = dev; + indio_dev->name = op->dev.of_node->name; + indio_dev->channels = st->chip_info->channel; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->num_channels = st->chip_info->num_channels; + indio_dev->available_scan_masks = st->chip_info->available_scan_masks; + indio_dev->info = &aim_info; + + init_completion(&st->dma_complete); + + aim_spi_write(st, ADC_REG_OUTPUT_MODE, def_mode); + aim_spi_write(st, ADC_REG_TEST_IO, TESTMODE_OFF); + aim_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); + + aim_configure_ring(indio_dev); + ret = iio_buffer_register(indio_dev, + st->chip_info->channel, + ARRAY_SIZE(st->chip_info->channel)); + if (ret) + goto failed4; + + ret = iio_device_register(indio_dev); + if (ret) + goto failed4; + + dev_info(dev, "ADI AIM (0x%X) at 0x%08llX mapped to 0x%p," + " DMA-%d probed ADC %s\n", + aim_read(st, AD9467_PCORE_VERSION), + (unsigned long long)phys_addr, st->regs, + st->rx_chan->chan_id, st->chip_info->name); + + if (iio_get_debugfs_dentry(indio_dev)) + debugfs_create_file("pseudorandom_err_check", 0644, + iio_get_debugfs_dentry(indio_dev), + indio_dev, &aim_debugfs_pncheck_fops); + + return 0; + +failed4: + aim_unconfigure_ring(indio_dev); +failed3: + dma_release_channel(st->rx_chan); +failed2: + release_mem_region(phys_addr, remap_size); +failed1: + iio_free_device(indio_dev); + dev_set_drvdata(dev, NULL); + + return ret; +} + +/** + * aim_of_remove - unbinds the driver from the AIM device. + * @of_dev: pointer to OF device structure + * + * This function is called if a device is physically removed from the system or + * if the driver module is being unloaded. It frees any resources allocated to + * the device. + */ +static int __devexit aim_of_remove(struct platform_device *op) +{ + struct device *dev = &op->dev; + struct resource r_mem; /* IO mem resources */ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct aim_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_buffer_unregister(indio_dev); + aim_unconfigure_ring(indio_dev); + + dma_release_channel(st->rx_chan); + + iounmap(st->regs); + + /* Get iospace of the device */ + if (of_address_to_resource(op->dev.of_node, 0, &r_mem)) + dev_err(dev, "invalid address\n"); + else + release_mem_region(r_mem.start, resource_size(&r_mem)); + + iio_free_device(indio_dev); + + dev_set_drvdata(dev, NULL); + + return 0; +} + +/* Match table for of_platform binding */ +static const struct of_device_id aim_of_match[] __devinitconst = { + { .compatible = "xlnx,cf-ad9467-core-1.00.a", }, + { .compatible = "xlnx,cf-ad9643-core-1.00.a", }, + { /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, aim_of_match); + +static struct platform_driver aim_of_driver = { + .driver = { + .name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .of_match_table = aim_of_match, + }, + .probe = aim_of_probe, + .remove = __devexit_p(aim_of_remove), +}; + +module_platform_driver(aim_of_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices ADI-AIM"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/cf_ad9467_ring.c b/drivers/staging/iio/adc/cf_ad9467_ring.c new file mode 100644 index 0000000000000..d55ae7fcc69a8 --- /dev/null +++ b/drivers/staging/iio/adc/cf_ad9467_ring.c @@ -0,0 +1,186 @@ +/* + * ADI-AIM ADC Interface Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "../buffer.h" +#include "../ring_hw.h" +#include "cf_ad9467.h" + +static int aim_read_first_n_hw_rb(struct iio_buffer *r, + size_t count, char __user *buf) +{ + struct iio_hw_buffer *hw_ring = iio_to_hw_buf(r); + struct iio_dev *indio_dev = hw_ring->private; + struct aim_state *st = iio_priv(indio_dev); + struct dma_async_tx_descriptor *desc; + dma_cookie_t cookie; + unsigned rcount; + int ret; + + mutex_lock(&st->lock); + if (count == 0) { + ret = -EINVAL; + goto error_ret; + } + + if (count % 8) + rcount = (count + 8) & 0xFFFFFFF8; + else + rcount = count; + + st->buf_virt = dma_alloc_coherent(indio_dev->dev.parent, + PAGE_ALIGN(rcount), &st->buf_phys, + GFP_KERNEL); + if (st->buf_virt == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + desc = dmaengine_prep_slave_single(st->rx_chan, st->buf_phys, rcount, + DMA_FROM_DEVICE, DMA_PREP_INTERRUPT); + if (!desc) { + dev_err(indio_dev->dev.parent, + "Failed to allocate a dma descriptor\n"); + ret = -ENOMEM; + goto error_free; + } + + desc->callback = (dma_async_tx_callback) complete; + desc->callback_param = &st->dma_complete; + + cookie = dmaengine_submit(desc); + if (cookie < 0) { + dev_err(indio_dev->dev.parent, + "Failed to submit a dma transfer\n"); + ret = cookie; + goto error_free; + } + + dma_async_issue_pending(st->rx_chan); + + aim_write(st, AD9467_PCORE_DMA_CTRL, 0); + aim_read(st, AD9467_PCORE_DMA_STAT); + aim_write(st, AD9467_PCORE_DMA_CTRL, + AD9647_DMA_CAP_EN | AD9647_DMA_CNT((rcount / 8) - 1)); + + ret = wait_for_completion_interruptible_timeout(&st->dma_complete, + 2 * HZ); + if (ret == 0) { + ret = -ETIMEDOUT; + goto error_free; + } else if (ret < 0) { + goto error_free; + } + + if (copy_to_user(buf, st->buf_virt, count)) + ret = -EFAULT; + +error_free: + dma_free_coherent(indio_dev->dev.parent, PAGE_ALIGN(rcount), + st->buf_virt, st->buf_phys); + r->stufftoread = 0; +error_ret: + mutex_unlock(&st->lock); + + return ret ? ret : count; +} + +static int aim_ring_get_length(struct iio_buffer *r) +{ + struct iio_hw_buffer *hw_ring = iio_to_hw_buf(r); + struct iio_dev *indio_dev = hw_ring->private; + struct aim_state *st = iio_priv(indio_dev); + + return st->ring_lenght; +} + +static int aim_ring_set_length(struct iio_buffer *r, int lenght) +{ + struct iio_hw_buffer *hw_ring = iio_to_hw_buf(r); + struct aim_state *st = iio_priv(hw_ring->private); + + st->ring_lenght = lenght; + + return 0; +} + +static int aim_ring_get_bytes_per_datum(struct iio_buffer *r) +{ + struct iio_hw_buffer *hw_ring = iio_to_hw_buf(r); + struct aim_state *st = iio_priv(hw_ring->private); + + return st->bytes_per_datum; +} + +static IIO_BUFFER_ENABLE_ATTR; +static IIO_BUFFER_LENGTH_ATTR; + +static struct attribute *aim_ring_attributes[] = { + &dev_attr_length.attr, + &dev_attr_enable.attr, + NULL, +}; + +static struct attribute_group aim_ring_attr = { + .attrs = aim_ring_attributes, + .name = "buffer", +}; + +static struct iio_buffer *aim_rb_allocate(struct iio_dev *indio_dev) +{ + struct iio_buffer *buf; + struct iio_hw_buffer *ring; + + ring = kzalloc(sizeof *ring, GFP_KERNEL); + if (!ring) + return NULL; + + ring->private = indio_dev; + buf = &ring->buf; + buf->attrs = &aim_ring_attr; + iio_buffer_init(buf); + + return buf; +} + +static inline void aim_rb_free(struct iio_buffer *r) +{ + kfree(iio_to_hw_buf(r)); +} + +static const struct iio_buffer_access_funcs aim_ring_access_funcs = { + .read_first_n = &aim_read_first_n_hw_rb, + .get_length = &aim_ring_get_length, + .set_length = &aim_ring_set_length, + .get_bytes_per_datum = &aim_ring_get_bytes_per_datum, +}; + +int aim_configure_ring(struct iio_dev *indio_dev) +{ + indio_dev->buffer = aim_rb_allocate(indio_dev); + if (indio_dev->buffer == NULL) + return -ENOMEM; + + indio_dev->modes |= INDIO_BUFFER_HARDWARE; + indio_dev->buffer->access = &aim_ring_access_funcs; + + return 0; +} + +void aim_unconfigure_ring(struct iio_dev *indio_dev) +{ + aim_rb_free(indio_dev->buffer); +} From 533289faafbb7f6f4e5b98dfd9e4cf87c5948e84 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 17 Feb 2012 14:33:18 +0100 Subject: [PATCH 105/261] iio: Rename iio/dds to iio/frequency Generalize naming to allow other frequency synthesis techniques as well. No functional changes. Signed-off-by: Michael Hennerich --- drivers/staging/iio/Kconfig | 2 +- drivers/staging/iio/Makefile | 2 +- drivers/staging/iio/{dds => frequency}/Kconfig | 7 +++++-- drivers/staging/iio/{dds => frequency}/Makefile | 0 drivers/staging/iio/{dds => frequency}/ad5930.c | 0 drivers/staging/iio/{dds => frequency}/ad9832.c | 0 drivers/staging/iio/{dds => frequency}/ad9832.h | 0 drivers/staging/iio/{dds => frequency}/ad9834.c | 0 drivers/staging/iio/{dds => frequency}/ad9834.h | 0 drivers/staging/iio/{dds => frequency}/ad9850.c | 0 drivers/staging/iio/{dds => frequency}/ad9852.c | 0 drivers/staging/iio/{dds => frequency}/ad9910.c | 0 drivers/staging/iio/{dds => frequency}/ad9951.c | 0 drivers/staging/iio/{dds => frequency}/dds.h | 0 14 files changed, 7 insertions(+), 4 deletions(-) rename drivers/staging/iio/{dds => frequency}/Kconfig (90%) rename drivers/staging/iio/{dds => frequency}/Makefile (100%) rename drivers/staging/iio/{dds => frequency}/ad5930.c (100%) rename drivers/staging/iio/{dds => frequency}/ad9832.c (100%) rename drivers/staging/iio/{dds => frequency}/ad9832.h (100%) rename drivers/staging/iio/{dds => frequency}/ad9834.c (100%) rename drivers/staging/iio/{dds => frequency}/ad9834.h (100%) rename drivers/staging/iio/{dds => frequency}/ad9850.c (100%) rename drivers/staging/iio/{dds => frequency}/ad9852.c (100%) rename drivers/staging/iio/{dds => frequency}/ad9910.c (100%) rename drivers/staging/iio/{dds => frequency}/ad9951.c (100%) rename drivers/staging/iio/{dds => frequency}/dds.h (100%) diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig index 24c6ed9d91641..be8b16219fdb1 100644 --- a/drivers/staging/iio/Kconfig +++ b/drivers/staging/iio/Kconfig @@ -68,7 +68,7 @@ source "drivers/staging/iio/adc/Kconfig" source "drivers/staging/iio/addac/Kconfig" source "drivers/staging/iio/cdc/Kconfig" source "drivers/staging/iio/dac/Kconfig" -source "drivers/staging/iio/dds/Kconfig" +source "drivers/staging/iio/frequency/Kconfig" source "drivers/staging/iio/gyro/Kconfig" source "drivers/staging/iio/impedance-analyzer/Kconfig" source "drivers/staging/iio/imu/Kconfig" diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile index 5075291dda7ad..d25d4f45ea7a3 100644 --- a/drivers/staging/iio/Makefile +++ b/drivers/staging/iio/Makefile @@ -24,7 +24,7 @@ obj-y += adc/ obj-y += addac/ obj-y += cdc/ obj-y += dac/ -obj-y += dds/ +obj-y += frequency/ obj-y += gyro/ obj-y += impedance-analyzer/ obj-y += imu/ diff --git a/drivers/staging/iio/dds/Kconfig b/drivers/staging/iio/frequency/Kconfig similarity index 90% rename from drivers/staging/iio/dds/Kconfig rename to drivers/staging/iio/frequency/Kconfig index 93b7141b2c1fb..14862576ba9a6 100644 --- a/drivers/staging/iio/dds/Kconfig +++ b/drivers/staging/iio/frequency/Kconfig @@ -1,7 +1,10 @@ # -# Direct Digital Synthesis drivers +# Frequency +# Direct Digital Synthesis drivers (DDS) +# Clock Distribution device drivers +# Phase Locked Loop device drivers (PLL) # -menu "Direct Digital Synthesis" +menu "Frequency DDS/PLL" config AD5930 tristate "Analog Devices ad5930/5932 driver" diff --git a/drivers/staging/iio/dds/Makefile b/drivers/staging/iio/frequency/Makefile similarity index 100% rename from drivers/staging/iio/dds/Makefile rename to drivers/staging/iio/frequency/Makefile diff --git a/drivers/staging/iio/dds/ad5930.c b/drivers/staging/iio/frequency/ad5930.c similarity index 100% rename from drivers/staging/iio/dds/ad5930.c rename to drivers/staging/iio/frequency/ad5930.c diff --git a/drivers/staging/iio/dds/ad9832.c b/drivers/staging/iio/frequency/ad9832.c similarity index 100% rename from drivers/staging/iio/dds/ad9832.c rename to drivers/staging/iio/frequency/ad9832.c diff --git a/drivers/staging/iio/dds/ad9832.h b/drivers/staging/iio/frequency/ad9832.h similarity index 100% rename from drivers/staging/iio/dds/ad9832.h rename to drivers/staging/iio/frequency/ad9832.h diff --git a/drivers/staging/iio/dds/ad9834.c b/drivers/staging/iio/frequency/ad9834.c similarity index 100% rename from drivers/staging/iio/dds/ad9834.c rename to drivers/staging/iio/frequency/ad9834.c diff --git a/drivers/staging/iio/dds/ad9834.h b/drivers/staging/iio/frequency/ad9834.h similarity index 100% rename from drivers/staging/iio/dds/ad9834.h rename to drivers/staging/iio/frequency/ad9834.h diff --git a/drivers/staging/iio/dds/ad9850.c b/drivers/staging/iio/frequency/ad9850.c similarity index 100% rename from drivers/staging/iio/dds/ad9850.c rename to drivers/staging/iio/frequency/ad9850.c diff --git a/drivers/staging/iio/dds/ad9852.c b/drivers/staging/iio/frequency/ad9852.c similarity index 100% rename from drivers/staging/iio/dds/ad9852.c rename to drivers/staging/iio/frequency/ad9852.c diff --git a/drivers/staging/iio/dds/ad9910.c b/drivers/staging/iio/frequency/ad9910.c similarity index 100% rename from drivers/staging/iio/dds/ad9910.c rename to drivers/staging/iio/frequency/ad9910.c diff --git a/drivers/staging/iio/dds/ad9951.c b/drivers/staging/iio/frequency/ad9951.c similarity index 100% rename from drivers/staging/iio/dds/ad9951.c rename to drivers/staging/iio/frequency/ad9951.c diff --git a/drivers/staging/iio/dds/dds.h b/drivers/staging/iio/frequency/dds.h similarity index 100% rename from drivers/staging/iio/dds/dds.h rename to drivers/staging/iio/frequency/dds.h From 41a69130a498f80609203365ac30750d383a9304 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 17 Feb 2012 16:46:22 +0100 Subject: [PATCH 106/261] iio: core: Introduce IIO_ALTVOLTAGE and appropriate channel info elements Signed-off-by: Michael Hennerich --- drivers/staging/iio/iio.h | 10 ++++++++++ drivers/staging/iio/industrialio-core.c | 3 +++ drivers/staging/iio/types.h | 1 + 3 files changed, 14 insertions(+) diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h index 82f7e22ca9c46..63cf8297ea407 100644 --- a/drivers/staging/iio/iio.h +++ b/drivers/staging/iio/iio.h @@ -36,6 +36,8 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW, IIO_CHAN_INFO_AVERAGE_RAW, IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY, + IIO_CHAN_INFO_FREQUENCY, + IIO_CHAN_INFO_PHASE, }; #define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2) @@ -81,6 +83,14 @@ enum iio_chan_info_enum { #define IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT \ IIO_CHAN_INFO_SEPARATE_BIT( \ IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) +#define IIO_CHAN_INFO_FREQUENCY_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_FREQUENCY) +#define IIO_CHAN_INFO_FREQUENCY_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_FREQUENCY) +#define IIO_CHAN_INFO_PHASE_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PHASE) +#define IIO_CHAN_INFO_PHASE_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PHASE) enum iio_endian { IIO_CPU, diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 5e2056f8e28cd..17e1f4300ab25 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -68,6 +68,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_ANGL] = "angl", [IIO_TIMESTAMP] = "timestamp", [IIO_CAPACITANCE] = "capacitance", + [IIO_ALTVOLTAGE] = "altvoltage", }; static const char * const iio_modifier_names[] = { @@ -90,6 +91,8 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw", [IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY] = "filter_low_pass_3db_frequency", + [IIO_CHAN_INFO_FREQUENCY] = "frequency", + [IIO_CHAN_INFO_PHASE] = "phase", }; const struct iio_chan_spec diff --git a/drivers/staging/iio/types.h b/drivers/staging/iio/types.h index 0c32136669019..a471fd5a4d954 100644 --- a/drivers/staging/iio/types.h +++ b/drivers/staging/iio/types.h @@ -27,6 +27,7 @@ enum iio_chan_type { IIO_ANGL, IIO_TIMESTAMP, IIO_CAPACITANCE, + IIO_ALTVOLTAGE, }; enum iio_modifier { From be5490848fc5c3514e137fd555ec826f5aa0ab08 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 22 Feb 2012 15:17:27 +0100 Subject: [PATCH 107/261] iio: frequency: Update DDS drivers to use new channel naming convention Signed-off-by: Michael Hennerich --- drivers/staging/iio/frequency/ad9832.c | 24 +++++------ drivers/staging/iio/frequency/ad9834.c | 56 +++++++++++++------------- drivers/staging/iio/frequency/dds.h | 54 ++++++++++++------------- 3 files changed, 67 insertions(+), 67 deletions(-) diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c index 2ccf25dd92894..5015463dcde24 100644 --- a/drivers/staging/iio/frequency/ad9832.c +++ b/drivers/staging/iio/frequency/ad9832.c @@ -177,18 +177,18 @@ static IIO_DEV_ATTR_OUT_ENABLE(0, S_IWUSR, NULL, ad9832_write, AD9832_OUTPUT_EN); static struct attribute *ad9832_attributes[] = { - &iio_dev_attr_dds0_freq0.dev_attr.attr, - &iio_dev_attr_dds0_freq1.dev_attr.attr, - &iio_const_attr_dds0_freq_scale.dev_attr.attr, - &iio_dev_attr_dds0_phase0.dev_attr.attr, - &iio_dev_attr_dds0_phase1.dev_attr.attr, - &iio_dev_attr_dds0_phase2.dev_attr.attr, - &iio_dev_attr_dds0_phase3.dev_attr.attr, - &iio_const_attr_dds0_phase_scale.dev_attr.attr, - &iio_dev_attr_dds0_pincontrol_en.dev_attr.attr, - &iio_dev_attr_dds0_freqsymbol.dev_attr.attr, - &iio_dev_attr_dds0_phasesymbol.dev_attr.attr, - &iio_dev_attr_dds0_out_enable.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequency0.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequency1.dev_attr.attr, + &iio_const_attr_out_altvoltage0_frequency_scale.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phase0.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phase1.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phase2.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phase3.dev_attr.attr, + &iio_const_attr_out_altvoltage0_phase_scale.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_pincontrol_en.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequencysymbol.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phasesymbol.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out_enable.dev_attr.attr, NULL, }; diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c index 38a2de08626fb..f5682d763b662 100644 --- a/drivers/staging/iio/frequency/ad9834.c +++ b/drivers/staging/iio/frequency/ad9834.c @@ -218,7 +218,7 @@ static ssize_t ad9834_show_out0_wavetype_available(struct device *dev, } -static IIO_DEVICE_ATTR(dds0_out0_wavetype_available, S_IRUGO, +static IIO_DEVICE_ATTR(out_altvoltage0_out0_wavetype_available, S_IRUGO, ad9834_show_out0_wavetype_available, NULL, 0); static ssize_t ad9834_show_out1_wavetype_available(struct device *dev, @@ -237,7 +237,7 @@ static ssize_t ad9834_show_out1_wavetype_available(struct device *dev, return sprintf(buf, "%s\n", str); } -static IIO_DEVICE_ATTR(dds0_out1_wavetype_available, S_IRUGO, +static IIO_DEVICE_ATTR(out_altvoltage0_out1_wavetype_available, S_IRUGO, ad9834_show_out1_wavetype_available, NULL, 0); /** @@ -263,36 +263,36 @@ static IIO_DEV_ATTR_OUT_WAVETYPE(0, 0, ad9834_store_wavetype, 0); static IIO_DEV_ATTR_OUT_WAVETYPE(0, 1, ad9834_store_wavetype, 1); static struct attribute *ad9834_attributes[] = { - &iio_dev_attr_dds0_freq0.dev_attr.attr, - &iio_dev_attr_dds0_freq1.dev_attr.attr, - &iio_const_attr_dds0_freq_scale.dev_attr.attr, - &iio_dev_attr_dds0_phase0.dev_attr.attr, - &iio_dev_attr_dds0_phase1.dev_attr.attr, - &iio_const_attr_dds0_phase_scale.dev_attr.attr, - &iio_dev_attr_dds0_pincontrol_en.dev_attr.attr, - &iio_dev_attr_dds0_freqsymbol.dev_attr.attr, - &iio_dev_attr_dds0_phasesymbol.dev_attr.attr, - &iio_dev_attr_dds0_out_enable.dev_attr.attr, - &iio_dev_attr_dds0_out1_enable.dev_attr.attr, - &iio_dev_attr_dds0_out0_wavetype.dev_attr.attr, - &iio_dev_attr_dds0_out1_wavetype.dev_attr.attr, - &iio_dev_attr_dds0_out0_wavetype_available.dev_attr.attr, - &iio_dev_attr_dds0_out1_wavetype_available.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequency0.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequency1.dev_attr.attr, + &iio_const_attr_out_altvoltage0_frequency_scale.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phase0.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phase1.dev_attr.attr, + &iio_const_attr_out_altvoltage0_phase_scale.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_pincontrol_en.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequencysymbol.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phasesymbol.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out_enable.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out1_enable.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out0_wavetype.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out1_wavetype.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out0_wavetype_available.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out1_wavetype_available.dev_attr.attr, NULL, }; static struct attribute *ad9833_attributes[] = { - &iio_dev_attr_dds0_freq0.dev_attr.attr, - &iio_dev_attr_dds0_freq1.dev_attr.attr, - &iio_const_attr_dds0_freq_scale.dev_attr.attr, - &iio_dev_attr_dds0_phase0.dev_attr.attr, - &iio_dev_attr_dds0_phase1.dev_attr.attr, - &iio_const_attr_dds0_phase_scale.dev_attr.attr, - &iio_dev_attr_dds0_freqsymbol.dev_attr.attr, - &iio_dev_attr_dds0_phasesymbol.dev_attr.attr, - &iio_dev_attr_dds0_out_enable.dev_attr.attr, - &iio_dev_attr_dds0_out0_wavetype.dev_attr.attr, - &iio_dev_attr_dds0_out0_wavetype_available.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequency0.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequency1.dev_attr.attr, + &iio_const_attr_out_altvoltage0_frequency_scale.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phase0.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phase1.dev_attr.attr, + &iio_const_attr_out_altvoltage0_phase_scale.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_frequencysymbol.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_phasesymbol.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out_enable.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out0_wavetype.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_out0_wavetype_available.dev_attr.attr, NULL, }; diff --git a/drivers/staging/iio/frequency/dds.h b/drivers/staging/iio/frequency/dds.h index d8ac3a93baf6a..c3342f6e052b0 100644 --- a/drivers/staging/iio/frequency/dds.h +++ b/drivers/staging/iio/frequency/dds.h @@ -7,104 +7,104 @@ */ /** - * /sys/bus/iio/devices/.../ddsX_freqY + * /sys/bus/iio/devices/.../out_altvoltageX_frequencyY */ #define IIO_DEV_ATTR_FREQ(_channel, _num, _mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(dds##_channel##_freq##_num, \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_frequency##_num, \ _mode, _show, _store, _addr) /** - * /sys/bus/iio/devices/.../ddsX_freqY_scale + * /sys/bus/iio/devices/.../out_altvoltageX_frequencyY_scale */ #define IIO_CONST_ATTR_FREQ_SCALE(_channel, _string) \ - IIO_CONST_ATTR(dds##_channel##_freq_scale, _string) + IIO_CONST_ATTR(out_altvoltage##_channel##_frequency_scale, _string) /** - * /sys/bus/iio/devices/.../ddsX_freqsymbol + * /sys/bus/iio/devices/.../out_altvoltageX_frequencysymbol */ #define IIO_DEV_ATTR_FREQSYMBOL(_channel, _mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(dds##_channel##_freqsymbol, \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_frequencysymbol, \ _mode, _show, _store, _addr); /** - * /sys/bus/iio/devices/.../ddsX_phaseY + * /sys/bus/iio/devices/.../out_altvoltageX_phaseY */ #define IIO_DEV_ATTR_PHASE(_channel, _num, _mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(dds##_channel##_phase##_num, \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_phase##_num, \ _mode, _show, _store, _addr) /** - * /sys/bus/iio/devices/.../ddsX_phaseY_scale + * /sys/bus/iio/devices/.../out_altvoltageX_phaseY_scale */ #define IIO_CONST_ATTR_PHASE_SCALE(_channel, _string) \ - IIO_CONST_ATTR(dds##_channel##_phase_scale, _string) + IIO_CONST_ATTR(out_altvoltage##_channel##_phase_scale, _string) /** - * /sys/bus/iio/devices/.../ddsX_phasesymbol + * /sys/bus/iio/devices/.../out_altvoltageX_phasesymbol */ #define IIO_DEV_ATTR_PHASESYMBOL(_channel, _mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(dds##_channel##_phasesymbol, \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_phasesymbol, \ _mode, _show, _store, _addr); /** - * /sys/bus/iio/devices/.../ddsX_pincontrol_en + * /sys/bus/iio/devices/.../out_altvoltageX_pincontrol_en */ #define IIO_DEV_ATTR_PINCONTROL_EN(_channel, _mode, _show, _store, _addr)\ - IIO_DEVICE_ATTR(dds##_channel##_pincontrol_en, \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_pincontrol_en, \ _mode, _show, _store, _addr); /** - * /sys/bus/iio/devices/.../ddsX_pincontrol_freq_en + * /sys/bus/iio/devices/.../out_altvoltageX_pincontrol_frequency_en */ #define IIO_DEV_ATTR_PINCONTROL_FREQ_EN(_channel, _mode, _show, _store, _addr)\ - IIO_DEVICE_ATTR(dds##_channel##_pincontrol_freq_en, \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_pincontrol_frequency_en,\ _mode, _show, _store, _addr); /** - * /sys/bus/iio/devices/.../ddsX_pincontrol_phase_en + * /sys/bus/iio/devices/.../out_altvoltageX_pincontrol_phase_en */ #define IIO_DEV_ATTR_PINCONTROL_PHASE_EN(_channel, _mode, _show, _store, _addr)\ - IIO_DEVICE_ATTR(dds##_channel##_pincontrol_phase_en, \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_pincontrol_phase_en, \ _mode, _show, _store, _addr); /** - * /sys/bus/iio/devices/.../ddsX_out_enable + * /sys/bus/iio/devices/.../out_altvoltageX_out_enable */ #define IIO_DEV_ATTR_OUT_ENABLE(_channel, _mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(dds##_channel##_out_enable, \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_out_enable, \ _mode, _show, _store, _addr); /** - * /sys/bus/iio/devices/.../ddsX_outY_enable + * /sys/bus/iio/devices/.../out_altvoltageX_outY_enable */ #define IIO_DEV_ATTR_OUTY_ENABLE(_channel, _output, \ _mode, _show, _store, _addr) \ - IIO_DEVICE_ATTR(dds##_channel##_out##_output##_enable, \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_out##_output##_enable,\ _mode, _show, _store, _addr); /** - * /sys/bus/iio/devices/.../ddsX_outY_wavetype + * /sys/bus/iio/devices/.../out_altvoltageX_outY_wavetype */ #define IIO_DEV_ATTR_OUT_WAVETYPE(_channel, _output, _store, _addr) \ - IIO_DEVICE_ATTR(dds##_channel##_out##_output##_wavetype, \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_out##_output##_wavetype,\ S_IWUSR, NULL, _store, _addr); /** - * /sys/bus/iio/devices/.../ddsX_outY_wavetype_available + * /sys/bus/iio/devices/.../out_altvoltageX_outY_wavetype_available */ #define IIO_CONST_ATTR_OUT_WAVETYPES_AVAILABLE(_channel, _output, _modes)\ - IIO_CONST_ATTR(dds##_channel##_out##_output##_wavetype_available,\ - _modes); + IIO_CONST_ATTR( \ + out_altvoltage##_channel##_out##_output##_wavetype_available, _modes); From 4e473f337fcca5573e2cb40cd255785352f3eaf3 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 22 Feb 2012 11:48:16 +0100 Subject: [PATCH 108/261] iio: amplifiers: New driver for AD8366 Dual-Digital Variable Gain Amplifier Signed-off-by: Michael Hennerich --- drivers/staging/iio/Kconfig | 1 + drivers/staging/iio/Makefile | 1 + drivers/staging/iio/amplifiers/Kconfig | 17 ++ drivers/staging/iio/amplifiers/Makefile | 5 + drivers/staging/iio/amplifiers/ad8366.c | 220 ++++++++++++++++++++++++ 5 files changed, 244 insertions(+) create mode 100644 drivers/staging/iio/amplifiers/Kconfig create mode 100644 drivers/staging/iio/amplifiers/Makefile create mode 100644 drivers/staging/iio/amplifiers/ad8366.c diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig index be8b16219fdb1..8ac9d5d7efda3 100644 --- a/drivers/staging/iio/Kconfig +++ b/drivers/staging/iio/Kconfig @@ -66,6 +66,7 @@ config IIO_CONSUMERS_PER_TRIGGER source "drivers/staging/iio/accel/Kconfig" source "drivers/staging/iio/adc/Kconfig" source "drivers/staging/iio/addac/Kconfig" +source "drivers/staging/iio/amplifiers/Kconfig" source "drivers/staging/iio/cdc/Kconfig" source "drivers/staging/iio/dac/Kconfig" source "drivers/staging/iio/frequency/Kconfig" diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile index d25d4f45ea7a3..05c701dcbbb12 100644 --- a/drivers/staging/iio/Makefile +++ b/drivers/staging/iio/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_IIO_ST_HWMON) += iio_hwmon.o obj-y += accel/ obj-y += adc/ obj-y += addac/ +obj-y += amplifiers/ obj-y += cdc/ obj-y += dac/ obj-y += frequency/ diff --git a/drivers/staging/iio/amplifiers/Kconfig b/drivers/staging/iio/amplifiers/Kconfig new file mode 100644 index 0000000000000..05d707ed7d4f9 --- /dev/null +++ b/drivers/staging/iio/amplifiers/Kconfig @@ -0,0 +1,17 @@ +# +# Gain Amplifiers, etc. +# +menu "Amplifiers" + +config AD8366 + tristate "Analog Devices AD8366 VGA" + depends on SPI + select BITREVERSE + help + Say yes here to build support for Analog Devices AD8366 + SPI Dual-Digital Variable Gain Amplifier (VGA). + + To compile this driver as a module, choose M here: the + module will be called ad8366. + +endmenu diff --git a/drivers/staging/iio/amplifiers/Makefile b/drivers/staging/iio/amplifiers/Makefile new file mode 100644 index 0000000000000..a6ca366908e07 --- /dev/null +++ b/drivers/staging/iio/amplifiers/Makefile @@ -0,0 +1,5 @@ +# +# Makefile iio/amplifiers +# + +obj-$(CONFIG_AD8366) += ad8366.o diff --git a/drivers/staging/iio/amplifiers/ad8366.c b/drivers/staging/iio/amplifiers/ad8366.c new file mode 100644 index 0000000000000..0815e3026b8d5 --- /dev/null +++ b/drivers/staging/iio/amplifiers/ad8366.c @@ -0,0 +1,220 @@ +/* + * AD8366 SPI Dual-Digital Variable Gain Amplifier (VGA) + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +struct ad8366_state { + struct spi_device *spi; + struct regulator *reg; + unsigned char ch[2]; + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + unsigned char data[2] ____cacheline_aligned; +}; + +static int ad8366_write(struct iio_dev *indio_dev, + unsigned char ch_a, char unsigned ch_b) +{ + struct ad8366_state *st = iio_priv(indio_dev); + int ret; + + ch_a = bitrev8(ch_a & 0x3F); + ch_b = bitrev8(ch_b & 0x3F); + + st->data[0] = ch_b >> 4; + st->data[1] = (ch_b << 4) | (ch_a >> 2); + + ret = spi_write(st->spi, st->data, ARRAY_SIZE(st->data)); + if (ret < 0) + dev_err(&indio_dev->dev, "write failed (%d)", ret); + + return ret; +} + +static int ad8366_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad8366_state *st = iio_priv(indio_dev); + int ret; + unsigned code; + + mutex_lock(&indio_dev->mlock); + switch (m) { + case 0: + code = st->ch[chan->channel]; + + /* Values in dB */ + code = code * 253 + 4500; + *val = code / 1000; + *val2 = (code % 1000) * 1000; + + ret = IIO_VAL_INT_PLUS_MICRO; + break; + default: + ret = -EINVAL; + } + mutex_unlock(&indio_dev->mlock); + + return ret; +}; + +static int ad8366_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad8366_state *st = iio_priv(indio_dev); + unsigned code; + int ret; + + /* Values in dB */ + code = (((u8)val * 1000) + ((u32)val2 / 1000)); + + if (code > 20500 || code < 4500) + return -EINVAL; + + code = (code - 4500) / 253; + + mutex_lock(&indio_dev->mlock); + switch (mask) { + case 0: + st->ch[chan->channel] = code; + ret = ad8366_write(indio_dev, st->ch[0], st->ch[1]); + break; + default: + ret = -EINVAL; + } + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static const struct iio_info ad8366_info = { + .read_raw = &ad8366_read_raw, + .write_raw = &ad8366_write_raw, + .driver_module = THIS_MODULE, +}; + +#define AD8366_CHAN(_channel, _name) { \ + .type = IIO_ALTVOLTAGE, \ + .output = 1, \ + .indexed = 1, \ + .processed_val = 1, \ + .channel = _channel, \ + .extend_name = _name, \ +} + +static const struct iio_chan_spec ad8366_channels[] = { + AD8366_CHAN(0, "gain"), + AD8366_CHAN(1, "gain"), +}; + +static int __devinit ad8366_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct ad8366_state *st; + int ret; + + indio_dev = iio_allocate_device(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + + st->reg = regulator_get(&spi->dev, "vcc"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) + goto error_put_reg; + } + + spi_set_drvdata(spi, indio_dev); + st->spi = spi; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->info = &ad8366_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ad8366_channels; + indio_dev->num_channels = ARRAY_SIZE(ad8366_channels); + + ret = iio_device_register(indio_dev); + if (ret) + goto error_disable_reg; + + ad8366_write(indio_dev, 0 , 0); + + return 0; + +error_disable_reg: + if (!IS_ERR(st->reg)) + regulator_disable(st->reg); +error_put_reg: + if (!IS_ERR(st->reg)) + regulator_put(st->reg); + + iio_free_device(indio_dev); + + return ret; +} + +static int __devexit ad8366_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad8366_state *st = iio_priv(indio_dev); + struct regulator *reg = st->reg; + + iio_device_unregister(indio_dev); + + if (!IS_ERR(reg)) { + regulator_disable(reg); + regulator_put(reg); + } + + iio_free_device(indio_dev); + + return 0; +} + +static const struct spi_device_id ad8366_id[] = { + {"ad8366", 0}, + {} +}; + +static struct spi_driver ad8366_driver = { + .driver = { + .name = KBUILD_MODNAME, + .owner = THIS_MODULE, + }, + .probe = ad8366_probe, + .remove = __devexit_p(ad8366_remove), + .id_table = ad8366_id, +}; + +module_spi_driver(ad8366_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD8366 VGA"); +MODULE_LICENSE("GPL v2"); From 83bc11f5cd78cf25ba7991c6943aec276c1c8355 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 23 Feb 2012 14:13:12 +0100 Subject: [PATCH 109/261] iio: core: iio_chan_spec_ext_info: Add private handle There is currently on user for it, but we might need it in future. So better add it now, before we have to convert drivers afterwards. Signed-off-by: Michael Hennerich --- drivers/staging/iio/iio.h | 13 ++++++++----- drivers/staging/iio/industrialio-core.c | 5 +++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h index 63cf8297ea407..b2c8059758532 100644 --- a/drivers/staging/iio/iio.h +++ b/drivers/staging/iio/iio.h @@ -107,14 +107,17 @@ struct iio_dev; * @shared: Whether this attribute is shared between all channels. * @read: Read callback for this info attribute, may be NULL. * @write: Write callback for this info attribute, may be NULL. - */ + * @private: Data private to the driver. +*/ struct iio_chan_spec_ext_info { const char *name; bool shared; - ssize_t (*read)(struct iio_dev *, struct iio_chan_spec const *, - char *buf); - ssize_t (*write)(struct iio_dev *, struct iio_chan_spec const *, - const char *buf, size_t len); + ssize_t (*read)(struct iio_dev *, uintptr_t private, + struct iio_chan_spec const *, char *buf); + ssize_t (*write)(struct iio_dev *, uintptr_t private, + struct iio_chan_spec const *, const char *buf, + size_t len); + uintptr_t private; }; /** diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 17e1f4300ab25..d070645ec87eb 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -240,7 +240,7 @@ static ssize_t iio_read_channel_ext_info(struct device *dev, ext_info = &this_attr->c->ext_info[this_attr->address]; - return ext_info->read(indio_dev, this_attr->c, buf); + return ext_info->read(indio_dev, ext_info->private, this_attr->c, buf); } static ssize_t iio_write_channel_ext_info(struct device *dev, @@ -254,7 +254,8 @@ static ssize_t iio_write_channel_ext_info(struct device *dev, ext_info = &this_attr->c->ext_info[this_attr->address]; - return ext_info->write(indio_dev, this_attr->c, buf, len); + return ext_info->write(indio_dev, ext_info->private, + this_attr->c, buf, len); } static int iio_device_register_debugfs(struct iio_dev *indio_dev) From e22dc5747995df61411fe4b2e70232a02de208d5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 13 Dec 2011 13:35:48 +0100 Subject: [PATCH 110/261] iio: write buffer support Signed-off-by: Lars-Peter Clausen --- drivers/staging/iio/buffer.h | 20 ++++++++++ drivers/staging/iio/dac/ad5360.c | 21 ++++++++-- drivers/staging/iio/iio_core.h | 2 + drivers/staging/iio/industrialio-buffer.c | 17 ++++++++ drivers/staging/iio/industrialio-core.c | 37 ++++++++++++++++- drivers/staging/iio/industrialio-trigger.c | 46 ++++++++++++++++++++++ drivers/staging/iio/kfifo_buf.c | 28 +++++++++++++ 7 files changed, 166 insertions(+), 5 deletions(-) diff --git a/drivers/staging/iio/buffer.h b/drivers/staging/iio/buffer.h index df2046dcb623e..05484d439c949 100644 --- a/drivers/staging/iio/buffer.h +++ b/drivers/staging/iio/buffer.h @@ -40,6 +40,8 @@ struct iio_buffer_access_funcs { int (*read_first_n)(struct iio_buffer *buffer, size_t n, char __user *buf); + int (*remove_from)(struct iio_buffer *buffer, u8 *data); + int (*write)(struct iio_buffer *buffer, size_t n, const char __user *buf); int (*request_update)(struct iio_buffer *buffer); @@ -49,6 +51,12 @@ struct iio_buffer_access_funcs { int (*set_length)(struct iio_buffer *buffer, int length); }; +enum iio_buffer_direction +{ + IIO_BUFFER_DIRECTION_IN, + IIO_BUFFER_DIRECTION_OUT, +}; + /** * struct iio_buffer - general buffer structure * @length: [DEVICE] number of datums in buffer @@ -83,8 +91,20 @@ struct iio_buffer { const struct attribute_group *attrs; struct list_head demux_list; unsigned char *demux_bounce; + enum iio_buffer_direction direction; }; +static inline int iio_buffer_write(struct iio_buffer *buffer, size_t n, + const char __user *buf) +{ + return buffer->access->write(buffer, n, buf); +} + +static inline int iio_buffer_remove_sample(struct iio_buffer *buffer, u8 *data) +{ + return buffer->access->remove_from(buffer, data); +} + /** * iio_buffer_init() - Initialize the buffer structure * @buffer: buffer to be initialized diff --git a/drivers/staging/iio/dac/ad5360.c b/drivers/staging/iio/dac/ad5360.c index cec3693b50a37..6249064c7aff9 100644 --- a/drivers/staging/iio/dac/ad5360.c +++ b/drivers/staging/iio/dac/ad5360.c @@ -317,15 +317,20 @@ static int ad5360_write_raw(struct iio_dev *indio_dev, struct ad5360_state *st = iio_priv(indio_dev); int max_val = (1 << chan->scan_type.realbits); unsigned int ofs_index; + unsigned int shift; switch (mask) { case 0: if (val >= max_val || val < 0) return -EINVAL; - return ad5360_write(indio_dev, AD5360_CMD_WRITE_DATA, - chan->address, val, chan->scan_type.shift); + if (iio_buffer_enabled(indio_dev)) + shift = 0; + else + shift = chan->scan_type.shift; + return ad5360_write(indio_dev, AD5360_CMD_WRITE_DATA, + chan->address, val, shift); case IIO_CHAN_INFO_CALIBBIAS: if (val >= max_val || val < 0) return -EINVAL; @@ -504,14 +509,23 @@ static int __devinit ad5360_probe(struct spi_device *spi) goto error_free_reg; } + ret = iio_triggered_buffer_setup(indio_dev, &iio_kfifo_allocate, NULL, + &iio_simple_trigger_handler, NULL); + if (ret) { + dev_err(&spi->dev, "Failed to setup buffer: %d\n", ret); + goto error_disable_reg; + } + ret = iio_device_register(indio_dev); if (ret) { dev_err(&spi->dev, "Failed to register iio device: %d\n", ret); - goto error_disable_reg; + goto error_cleanup_buffer; } return 0; +error_cleanup_buffer: + iio_triggered_buffer_cleanup(indio_dev); error_disable_reg: regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg); error_free_reg: @@ -530,6 +544,7 @@ static int __devexit ad5360_remove(struct spi_device *spi) struct ad5360_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); kfree(indio_dev->channels); diff --git a/drivers/staging/iio/iio_core.h b/drivers/staging/iio/iio_core.h index c9dfcba0bac8d..adc9c909cdfc5 100644 --- a/drivers/staging/iio/iio_core.h +++ b/drivers/staging/iio/iio_core.h @@ -37,6 +37,8 @@ unsigned int iio_buffer_poll(struct file *filp, struct poll_table_struct *wait); ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, size_t n, loff_t *f_ps); +ssize_t iio_buffer_chrdev_write(struct file *filp, const char __user *buf, + size_t n, loff_t *f_ps); #define iio_buffer_poll_addr (&iio_buffer_poll) diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c index 386ba760f3f1b..4d5497f6a1db8 100644 --- a/drivers/staging/iio/industrialio-buffer.c +++ b/drivers/staging/iio/industrialio-buffer.c @@ -48,6 +48,23 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, return rb->access->read_first_n(rb, n, buf); } +/** + * iio_buffer_read_first_n_outer() - chrdev read for buffer access + * + * This function relies on all buffer implementations having an + * iio_buffer as their first element. + **/ +ssize_t iio_buffer_chrdev_write(struct file *filp, const char __user *buf, + size_t n, loff_t *f_ps) +{ + struct iio_dev *indio_dev = filp->private_data; + struct iio_buffer *rb = indio_dev->buffer; + + if (!rb || !rb->access->write) + return -EINVAL; + return rb->access->write(rb, n, buf); +} + /** * iio_buffer_poll() - poll the buffer to find out if it has data */ diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index d070645ec87eb..7caded4de7da3 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -23,6 +23,8 @@ #include #include #include + +#include "buffer.h" #include "iio.h" #include "iio_core.h" #include "iio_core_trigger.h" @@ -847,7 +849,16 @@ static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -EINVAL; } -static const struct file_operations iio_buffer_fileops = { +static const struct file_operations iio_buffer_none_fileops = { + .release = iio_chrdev_release, + .open = iio_chrdev_open, + .owner = THIS_MODULE, + .llseek = noop_llseek, + .unlocked_ioctl = iio_ioctl, + .compat_ioctl = iio_ioctl, +}; + +static const struct file_operations iio_buffer_in_fileops = { .read = iio_buffer_read_first_n_outer_addr, .release = iio_chrdev_release, .open = iio_chrdev_open, @@ -858,10 +869,23 @@ static const struct file_operations iio_buffer_fileops = { .compat_ioctl = iio_ioctl, }; + static const struct iio_buffer_setup_ops noop_ring_setup_ops; +static const struct file_operations iio_buffer_out_fileops = { + .write = iio_buffer_chrdev_write, + .release = iio_chrdev_release, + .open = iio_chrdev_open, + .poll = iio_buffer_poll_addr, + .owner = THIS_MODULE, + .llseek = noop_llseek, + .unlocked_ioctl = iio_ioctl, + .compat_ioctl = iio_ioctl, +}; + int iio_device_register(struct iio_dev *indio_dev) { + const struct file_operations *fops; int ret; /* configure elements for the chrdev */ @@ -888,14 +912,23 @@ int iio_device_register(struct iio_dev *indio_dev) if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) iio_device_register_trigger_consumer(indio_dev); + if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) && indio_dev->setup_ops == NULL) indio_dev->setup_ops = &noop_ring_setup_ops; + if (indio_dev->buffer) { + if (indio_dev->buffer->direction == IIO_BUFFER_DIRECTION_IN) + fops = &iio_buffer_in_fileops; + else + fops = &iio_buffer_out_fileops; + } else { + fops = &iio_buffer_none_fileops; + } ret = device_add(&indio_dev->dev); if (ret < 0) goto error_unreg_eventset; - cdev_init(&indio_dev->chrdev, &iio_buffer_fileops); + cdev_init(&indio_dev->chrdev, fops); indio_dev->chrdev.owner = indio_dev->info->driver_module; ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1); if (ret < 0) diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/staging/iio/industrialio-trigger.c index 47ecadd4818d5..8441b79a322d1 100644 --- a/drivers/staging/iio/industrialio-trigger.c +++ b/drivers/staging/iio/industrialio-trigger.c @@ -16,6 +16,7 @@ #include #include "iio.h" +#include "buffer.h" #include "trigger.h" #include "iio_core.h" #include "iio_core_trigger.h" @@ -507,3 +508,48 @@ int iio_triggered_buffer_predisable(struct iio_dev *indio_dev) indio_dev->pollfunc); } EXPORT_SYMBOL(iio_triggered_buffer_predisable); + +int iio_simple_trigger_handler(int irq, void *devid) +{ + struct iio_poll_func *pf = devid; + struct iio_dev *indio_dev = pf->indio_dev; + struct iio_buffer *buffer = indio_dev->buffer; + const struct iio_chan_spec *ch; + unsigned int val; + u8 sample[100]; + u8 *p = sample; + int ret; + int i; + + ret = iio_buffer_remove_sample(buffer, sample); + if (ret < 0) + return IRQ_HANDLED; + + for_each_set_bit(i, + indio_dev->active_scan_mask, + indio_dev->masklength) { + ch = iio_find_channel_from_si(indio_dev, i); + + p = PTR_ALIGN(p, ch->scan_type.storagebits / 8); + + switch (ch->scan_type.storagebits) { + case 32: + val = *((u32 *)p); + break; + case 16: + val = *((u16 *)p); + break; + case 8: + val = *((u8 *)p); + break; + default: + dev_err(&indio_dev->dev, "Unsupported storage size\n"); + return IRQ_HANDLED; + } + indio_dev->info->write_raw(indio_dev, ch, val, 0, 0); + + p += ch->scan_type.storagebits / 8; + } + + return IRQ_HANDLED; +} diff --git a/drivers/staging/iio/kfifo_buf.c b/drivers/staging/iio/kfifo_buf.c index 9f3bd59c0e72b..1bf0b76218d7d 100644 --- a/drivers/staging/iio/kfifo_buf.c +++ b/drivers/staging/iio/kfifo_buf.c @@ -116,9 +116,37 @@ static int iio_read_first_n_kfifo(struct iio_buffer *r, return copied; } +static int iio_remove_from_kfifo(struct iio_buffer *r, + u8 *data) +{ + int ret; + struct iio_kfifo *kf = iio_to_kfifo(r); + + if (kfifo_size(&kf->kf) < r->bytes_per_datum) + return -EBUSY; + + ret = kfifo_out(&kf->kf, data, r->bytes_per_datum); + if (ret != r->bytes_per_datum) + return -EBUSY; + return 0; +} + +static int iio_write_kfifo(struct iio_buffer *r, + size_t n, char __user *buf) +{ + int ret, copied; + struct iio_kfifo *kf = iio_to_kfifo(r); + + ret = kfifo_from_user(&kf->kf, buf, n, &copied); + + return copied; +} + static const struct iio_buffer_access_funcs kfifo_access_funcs = { .store_to = &iio_store_to_kfifo, + .remove_from = &iio_remove_from_kfifo, .read_first_n = &iio_read_first_n_kfifo, + .write = &iio_write_kfifo, .request_update = &iio_request_update_kfifo, .get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo, .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, From 96902d09e5a87f7a75f2f9c6569e3a4486821b34 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 6 Mar 2012 11:46:32 +0100 Subject: [PATCH 111/261] drivercore: Add driver probe deferral mechanism Allow drivers to report at probe time that they cannot get all the resources required by the device, and should be retried at a later time. This should completely solve the problem of getting devices initialized in the right order. Right now this is mostly handled by mucking about with initcall ordering which is a complete hack, and doesn't even remotely handle the case where device drivers are in modules. This approach completely sidesteps the issues by allowing driver registration to occur in any order, and any driver can request to be retried after a few more other drivers get probed. v4: - Integrate Manjunath's addition of a separate workqueue - Change -EAGAIN to -EPROBE_DEFER for drivers to trigger deferral - Update comment blocks to reflect how the code really works v3: - Hold off workqueue scheduling until late_initcall so that the bulk of driver probes are complete before we start retrying deferred devices. - Tested with simple use cases. Still needs more testing though. Using it to get rid of the gpio early_initcall madness, or to replace the ASoC internal probe deferral code would be ideal. v2: - added locking so it should no longer be utterly broken in that regard - remove device from deferred list at device_del time. - Still completely untested with any real use case, but has been boot tested. Signed-off-by: Grant Likely Cc: Greg Kroah-Hartman Cc: Mark Brown Cc: Arnd Bergmann Cc: Dilan Lee Cc: Manjunath GKondaiah Cc: Alan Stern Cc: Tony Lindgren --- drivers/base/base.h | 1 + drivers/base/core.c | 2 + drivers/base/dd.c | 138 ++++++++++++++++++++++++++++++++++++++++- include/linux/device.h | 5 ++ include/linux/errno.h | 1 + 5 files changed, 146 insertions(+), 1 deletion(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index b858dfd9a37c9..2c13deae5f827 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -105,6 +105,7 @@ extern void bus_remove_driver(struct device_driver *drv); extern void driver_detach(struct device_driver *drv); extern int driver_probe_device(struct device_driver *drv, struct device *dev); +extern void driver_deferred_probe_del(struct device *dev); static inline int driver_match_device(struct device_driver *drv, struct device *dev) { diff --git a/drivers/base/core.c b/drivers/base/core.c index 74dda4f697f92..d4ff7adce38c4 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -644,6 +644,7 @@ void device_initialize(struct device *dev) { dev->kobj.kset = devices_kset; kobject_init(&dev->kobj, &device_ktype); + INIT_LIST_HEAD(&dev->deferred_probe); INIT_LIST_HEAD(&dev->dma_pools); mutex_init(&dev->mutex); lockdep_set_novalidate_class(&dev->mutex); @@ -1188,6 +1189,7 @@ void device_del(struct device *dev) device_remove_file(dev, &uevent_attr); device_remove_attrs(dev); bus_remove_device(dev); + driver_deferred_probe_del(dev); /* * Some platform devices are driven without driver attached diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 142e3d600f145..442b7641a086e 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -28,6 +28,133 @@ #include "base.h" #include "power/power.h" +/* + * Deferred Probe infrastructure. + * + * Sometimes driver probe order matters, but the kernel doesn't always have + * dependency information which means some drivers will get probed before a + * resource it depends on is available. For example, an SDHCI driver may + * first need a GPIO line from an i2c GPIO controller before it can be + * initialized. If a required resource is not available yet, a driver can + * request probing to be deferred by returning -EPROBE_DEFER from its probe hook + * + * Deferred probe maintains two lists of devices, a pending list and an active + * list. A driver returning -EPROBE_DEFER causes the device to be added to the + * pending list. A successful driver probe will trigger moving all devices + * from the pending to the active list so that the workqueue will eventually + * retry them. + * + * The deferred_probe_mutex must be held any time the deferred_probe_*_list + * of the (struct device*)->deferred_probe pointers are manipulated + */ +static DEFINE_MUTEX(deferred_probe_mutex); +static LIST_HEAD(deferred_probe_pending_list); +static LIST_HEAD(deferred_probe_active_list); +static struct workqueue_struct *deferred_wq; + +/** + * deferred_probe_work_func() - Retry probing devices in the active list. + */ +static void deferred_probe_work_func(struct work_struct *work) +{ + struct device *dev; + /* + * This block processes every device in the deferred 'active' list. + * Each device is removed from the active list and passed to + * bus_probe_device() to re-attempt the probe. The loop continues + * until every device in the active list is removed and retried. + * + * Note: Once the device is removed from the list and the mutex is + * released, it is possible for the device get freed by another thread + * and cause a illegal pointer dereference. This code uses + * get/put_device() to ensure the device structure cannot disappear + * from under our feet. + */ + mutex_lock(&deferred_probe_mutex); + while (!list_empty(&deferred_probe_active_list)) { + dev = list_first_entry(&deferred_probe_active_list, + typeof(*dev), deferred_probe); + list_del_init(&dev->deferred_probe); + + get_device(dev); + + /* Drop the mutex while probing each device; the probe path + * may manipulate the deferred list */ + mutex_unlock(&deferred_probe_mutex); + dev_dbg(dev, "Retrying from deferred list\n"); + bus_probe_device(dev); + mutex_lock(&deferred_probe_mutex); + + put_device(dev); + } + mutex_unlock(&deferred_probe_mutex); +} +static DECLARE_WORK(deferred_probe_work, deferred_probe_work_func); + +static void driver_deferred_probe_add(struct device *dev) +{ + mutex_lock(&deferred_probe_mutex); + if (list_empty(&dev->deferred_probe)) { + dev_dbg(dev, "Added to deferred list\n"); + list_add(&dev->deferred_probe, &deferred_probe_pending_list); + } + mutex_unlock(&deferred_probe_mutex); +} + +void driver_deferred_probe_del(struct device *dev) +{ + mutex_lock(&deferred_probe_mutex); + if (!list_empty(&dev->deferred_probe)) { + dev_dbg(dev, "Removed from deferred list\n"); + list_del_init(&dev->deferred_probe); + } + mutex_unlock(&deferred_probe_mutex); +} + +static bool driver_deferred_probe_enable = false; +/** + * driver_deferred_probe_trigger() - Kick off re-probing deferred devices + * + * This functions moves all devices from the pending list to the active + * list and schedules the deferred probe workqueue to process them. It + * should be called anytime a driver is successfully bound to a device. + */ +static void driver_deferred_probe_trigger(void) +{ + if (!driver_deferred_probe_enable) + return; + + /* A successful probe means that all the devices in the pending list + * should be triggered to be reprobed. Move all the deferred devices + * into the active list so they can be retried by the workqueue */ + mutex_lock(&deferred_probe_mutex); + list_splice_tail_init(&deferred_probe_pending_list, + &deferred_probe_active_list); + mutex_unlock(&deferred_probe_mutex); + + /* Kick the re-probe thread. It may already be scheduled, but + * it is safe to kick it again. */ + queue_work(deferred_wq, &deferred_probe_work); +} + +/** + * deferred_probe_initcall() - Enable probing of deferred devices + * + * We don't want to get in the way when the bulk of drivers are getting probed. + * Instead, this initcall makes sure that deferred probing is delayed until + * late_initcall time. + */ +static int deferred_probe_initcall(void) +{ + deferred_wq = create_singlethread_workqueue("deferwq"); + if (WARN_ON(!deferred_wq)) + return -ENOMEM; + + driver_deferred_probe_enable = true; + driver_deferred_probe_trigger(); + return 0; +} +late_initcall(deferred_probe_initcall); static void driver_bound(struct device *dev) { @@ -42,6 +169,11 @@ static void driver_bound(struct device *dev) klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); + /* Make sure the device is no longer in one of the deferred lists + * and kick off retrying all pending devices */ + driver_deferred_probe_del(dev); + driver_deferred_probe_trigger(); + if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_BOUND_DRIVER, dev); @@ -142,7 +274,11 @@ static int really_probe(struct device *dev, struct device_driver *drv) driver_sysfs_remove(dev); dev->driver = NULL; - if (ret != -ENODEV && ret != -ENXIO) { + if (ret == -EPROBE_DEFER) { + /* Driver requested deferred probing */ + dev_info(dev, "Driver %s requests probe deferral\n", drv->name); + driver_deferred_probe_add(dev); + } else if (ret != -ENODEV && ret != -ENXIO) { /* driver matched but the probe failed */ printk(KERN_WARNING "%s: probe of %s failed with error %d\n", diff --git a/include/linux/device.h b/include/linux/device.h index b63fb393aa58a..adf090d485dac 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -587,6 +587,10 @@ struct device_dma_parameters { * @mutex: Mutex to synchronize calls to its driver. * @bus: Type of bus device is on. * @driver: Which driver has allocated this + * @deferred_probe: entry in deferred_probe_list which is used to retry the + * binding of drivers which were unable to get all the resources + * needed by the device; typically because it depends on another + * driver getting probed first. * @platform_data: Platform data specific to the device. * Example: For devices on custom boards, as typical of embedded * and SOC based hardware, Linux often uses platform_data to point @@ -646,6 +650,7 @@ struct device { struct bus_type *bus; /* type of bus device is on */ struct device_driver *driver; /* which driver has allocated this device */ + struct list_head deferred_probe; void *platform_data; /* Platform specific data, device core doesn't touch it */ struct dev_pm_info power; diff --git a/include/linux/errno.h b/include/linux/errno.h index 46685832ed991..2d09bfa5c2628 100644 --- a/include/linux/errno.h +++ b/include/linux/errno.h @@ -16,6 +16,7 @@ #define ERESTARTNOHAND 514 /* restart if no handler.. */ #define ENOIOCTLCMD 515 /* No ioctl command */ #define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */ +#define EPROBE_DEFER 517 /* Driver requests probe retry */ /* Defined for the NFSv3 protocol */ #define EBADHANDLE 521 /* Illegal NFS file handle */ From 623078485fb02c5377a02e0b645e7ef9e1a3d397 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 9 Mar 2012 13:14:28 +0100 Subject: [PATCH 112/261] iio: frequency: New driver for AD9523 SPI Low Jitter Clock Generator Signed-off-by: Michael Hennerich --- drivers/staging/iio/frequency/Kconfig | 21 +- drivers/staging/iio/frequency/Makefile | 3 +- drivers/staging/iio/frequency/ad9523.c | 839 +++++++++++++++++++++++++ drivers/staging/iio/frequency/ad9523.h | 316 ++++++++++ 4 files changed, 1176 insertions(+), 3 deletions(-) create mode 100644 drivers/staging/iio/frequency/ad9523.c create mode 100644 drivers/staging/iio/frequency/ad9523.h diff --git a/drivers/staging/iio/frequency/Kconfig b/drivers/staging/iio/frequency/Kconfig index 14862576ba9a6..7b2c0c36300db 100644 --- a/drivers/staging/iio/frequency/Kconfig +++ b/drivers/staging/iio/frequency/Kconfig @@ -2,9 +2,25 @@ # Frequency # Direct Digital Synthesis drivers (DDS) # Clock Distribution device drivers -# Phase Locked Loop device drivers (PLL) +# Phase-Locked Loop (PLL) frequency synthesizers # -menu "Frequency DDS/PLL" + +menu "Frequency Synthesizers DDS/PLL" +menu "Clock Generator/Distribution" + +config AD9523 + tristate "Analog Devices AD9523 Low Jitter Clock Generator" + depends on SPI + help + Say yes here to build support for Analog Devices AD9523 Low Jitter + Clock Generator. The driver provides direct access via sysfs. + + To compile this driver as a module, choose M here: the + module will be called ad9523. + +endmenu + +menu "Direct Digital Synthesis" config AD5930 tristate "Analog Devices ad5930/5932 driver" @@ -62,3 +78,4 @@ config AD9951 ad9951, provides direct access via sysfs. endmenu +endmenu diff --git a/drivers/staging/iio/frequency/Makefile b/drivers/staging/iio/frequency/Makefile index 147746176b9b7..2f869006a5ed6 100644 --- a/drivers/staging/iio/frequency/Makefile +++ b/drivers/staging/iio/frequency/Makefile @@ -1,7 +1,8 @@ # -# Makefile for Direct Digital Synthesis drivers +# Makefile iio/frequency # +obj-$(CONFIG_AD9523) += ad9523.o obj-$(CONFIG_AD5930) += ad5930.o obj-$(CONFIG_AD9832) += ad9832.o obj-$(CONFIG_AD9834) += ad9834.o diff --git a/drivers/staging/iio/frequency/ad9523.c b/drivers/staging/iio/frequency/ad9523.c new file mode 100644 index 0000000000000..c43a7efc84ac3 --- /dev/null +++ b/drivers/staging/iio/frequency/ad9523.c @@ -0,0 +1,839 @@ +/* + * AD9523 SPI Low Jitter Clock Generator + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +#include "ad9523.h" + +enum { + AD9523_STATUS0, + AD9523_VCO1_FREQ, + AD9523_VCO2_FREQ, + AD9523_VCO_FREQ_AVAIL, + AD9523_SYNC, + AD9523_EEPROM, + AD9523_ALT_SRC_CH0, + AD9523_ALT_SRC_CH1, + AD9523_ALT_SRC_CH2, + AD9523_ALT_SRC_CH3, + AD9523_ALT_SRC_CH4, + AD9523_ALT_SRC_CH5, + AD9523_ALT_SRC_CH6, + AD9523_ALT_SRC_CH7, + AD9523_ALT_SRC_CH8, + AD9523_ALT_SRC_CH9, +}; + +#define AD_IF(_pde, _a) ((pdata->_pde) ? _a : 0) +#define AD_IFE(_pde, _a, _b) ((pdata->_pde) ? _a : _b) + +struct ad9523_state { + struct spi_device *spi; + struct regulator *reg; + struct ad9523_platform_data *pdata; + struct iio_chan_spec ad9523_channels[14]; + + unsigned long vcxo_freq; + unsigned long vco_freq; + unsigned long vco_out_freq[3]; + unsigned char vco_out_map[14]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + union { + __be32 d32; + u8 d8[4]; + } data[2] ____cacheline_aligned; +}; + +static struct ad9523_platform_data default_pdata = { + +}; + +static int ad9523_read(struct iio_dev *indio_dev, unsigned addr) +{ + struct ad9523_state *st = iio_priv(indio_dev); + struct spi_message m; + int ret; + struct spi_transfer t[] = { + { + .tx_buf = &st->data[0].d8[2], + .len = 2, + .cs_change = 0, + }, { + .rx_buf = &st->data[1].d8[4 - AD9523_TRANSFER_LEN(addr)], + .len = AD9523_TRANSFER_LEN(addr), + }, + }; + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + st->data[0].d32 = cpu_to_be32(AD9523_READ | + AD9523_CNT(AD9523_TRANSFER_LEN(addr)) | + AD9523_ADDR(addr)); + + ret = spi_sync(st->spi, &m); + if (ret >= 0) + ret = be32_to_cpu(st->data[1].d32) & (0xFFFFFF >> + (8 * (3 - AD9523_TRANSFER_LEN(addr)))); + else + dev_err(&indio_dev->dev, "read failed (%d)", ret); + + return ret; +}; + +static int ad9523_write(struct iio_dev *indio_dev, unsigned addr, unsigned val) +{ + struct ad9523_state *st = iio_priv(indio_dev); + struct spi_message m; + int ret; + struct spi_transfer t[] = { + { + .tx_buf = &st->data[0].d8[2], + .len = 2, + .cs_change = 0, + }, { + .tx_buf = &st->data[1].d8[4 - AD9523_TRANSFER_LEN(addr)], + .len = AD9523_TRANSFER_LEN(addr), + }, + }; + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + st->data[0].d32 = cpu_to_be32(AD9523_WRITE | + AD9523_CNT(AD9523_TRANSFER_LEN(addr)) | + AD9523_ADDR(addr)); + st->data[1].d32 = cpu_to_be32(val); + + ret = spi_sync(st->spi, &m); + + + if (ret < 0) + dev_err(&indio_dev->dev, "write failed (%d)", ret); + + return ret; +} + +static int ad9523_io_update(struct iio_dev *indio_dev) +{ + return ad9523_write(indio_dev, AD9523_IO_UPDATE, AD9523_IO_UPDATE_EN); +} + +static int ad9523_vco_out_map(struct iio_dev *indio_dev, + unsigned ch, unsigned out) +{ + struct ad9523_state *st = iio_priv(indio_dev); + int ret; + unsigned mask; + + switch (ch) { + case 0 ... 3: + ret = ad9523_read(indio_dev, AD9523_PLL1_OUTPUT_CHANNEL_CTRL); + if (ret < 0) + break; + mask = AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH0 << ch; + if (out) { + ret |= mask; + out = 2; + } else { + ret &= ~mask; + } + ret = ad9523_write(indio_dev, AD9523_PLL1_OUTPUT_CHANNEL_CTRL, ret); + break; + case 4 ... 6: + ret = ad9523_read(indio_dev, AD9523_PLL1_OUTPUT_CTRL); + if (ret < 0) + break; + mask = AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH4_M2 << (ch - 4); + if (out) + ret |= mask; + else + ret &= ~mask; + ret = ad9523_write(indio_dev, AD9523_PLL1_OUTPUT_CTRL, ret); + break; + case 7 ... 9: + ret = ad9523_read(indio_dev, AD9523_PLL1_OUTPUT_CHANNEL_CTRL); + if (ret < 0) + break; + mask = AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH7_M2 << (ch - 7); + if (out) + ret |= mask; + else + ret &= ~mask; + ret = ad9523_write(indio_dev, AD9523_PLL1_OUTPUT_CHANNEL_CTRL, ret); + break; + default: + return 0; + } + + st->vco_out_map[ch] = out; + return ret; +} + + +static ssize_t ad9523_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad9523_state *st = iio_priv(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + unsigned long readin, tmp; + int ret; + + ret = kstrtoul(buf, 10, &readin); + if (ret) + return ret; + + mutex_lock(&indio_dev->mlock); + switch ((u32)this_attr->address) { + case AD9523_VCO1_FREQ: + ret = ad9523_read(indio_dev, AD9523_PLL2_VCO_DIVIDER); + if (ret < 0) + goto out; + + tmp = st->vco_freq / readin; + if (tmp < 3 || tmp > 5) { + ret = -EINVAL; + goto out; + } + + ret &= 0xFC; + ret |= AD9523_PLL2_VCO_DIV_M1(tmp); + ret = ad9523_write(indio_dev, AD9523_PLL2_VCO_DIVIDER, ret); + if (ret < 0) + goto out; + st->vco_out_freq[0] = st->vco_freq / tmp; + break; + case AD9523_VCO2_FREQ: + ret = ad9523_read(indio_dev, AD9523_PLL2_VCO_DIVIDER); + if (ret < 0) + goto out; + + tmp = st->vco_freq / readin; + if (tmp < 3 || tmp > 5) { + ret = -EINVAL; + goto out; + } + + ret &= 0xCF; + ret |= AD9523_PLL2_VCO_DIV_M2(tmp); + ret = ad9523_write(indio_dev, AD9523_PLL2_VCO_DIVIDER, ret); + if (ret < 0) + goto out; + st->vco_out_freq[1] = st->vco_freq / tmp; + break; + case AD9523_ALT_SRC_CH0 ... AD9523_ALT_SRC_CH9: + ret = ad9523_vco_out_map(indio_dev, (u32)this_attr->address - + AD9523_ALT_SRC_CH0, !!readin); + if (ret < 0) + goto out; + break; + case AD9523_SYNC: + ret = ad9523_read(indio_dev, AD9523_STATUS_SIGNALS); + if (ret < 0) + goto out; + tmp = ret; + tmp |= AD9523_STATUS_SIGNALS_SYNC_MAN_CTRL; + ret = ad9523_write(indio_dev, AD9523_STATUS_SIGNALS, tmp); + if (ret < 0) + goto out; + ad9523_io_update(indio_dev); + tmp &= ~AD9523_STATUS_SIGNALS_SYNC_MAN_CTRL; + ret = ad9523_write(indio_dev, AD9523_STATUS_SIGNALS, tmp); + if (ret < 0) + goto out; + break; + case AD9523_EEPROM: + ret = ad9523_write(indio_dev, AD9523_EEPROM_CTRL1, + AD9523_EEPROM_CTRL1_EEPROM_WRITE_PROT_DIS); + if (ret < 0) + goto out; + ret = ad9523_write(indio_dev, AD9523_EEPROM_CTRL2, + AD9523_EEPROM_CTRL2_REG2EEPROM); + if (ret < 0) + goto out; + + tmp = 4; + do { + msleep(16); + ret = ad9523_read(indio_dev, + AD9523_EEPROM_DATA_XFER_STATUS); + if (ret < 0) + goto out; + } while ((ret & AD9523_EEPROM_DATA_XFER_IN_PROGRESS) && tmp--); + + ret = ad9523_write(indio_dev, AD9523_EEPROM_CTRL1, 0); + if (ret < 0) + goto out; + + ret = ad9523_read(indio_dev, AD9523_EEPROM_ERROR_READBACK); + if (ret < 0) + goto out; + + if (ret & AD9523_EEPROM_ERROR_READBACK_FAIL) { + dev_err(&indio_dev->dev, "Verify EEPROM failed"); + ret = -EIO; + } + break; + default: + ret = -ENODEV; + goto out; + } + + ret = ad9523_io_update(indio_dev); +out: + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static ssize_t ad9523_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad9523_state *st = iio_priv(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret = 0; + + mutex_lock(&indio_dev->mlock); + switch ((u32)this_attr->address) { + case AD9523_STATUS0: + ret = ad9523_read(indio_dev, AD9523_READBACK_0); + if (ret >= 0) { + ret = sprintf(buf, "PLL2 reference clock:\t%s\nPLL2 feedback clock:\t%s\nVCXO:\t%s\nREF_TEST:\t%s\nREFB:\t%s\nREFA:\t%s\nPLL2 lock detect:\t%s\nPLL1 lock detect:\t%s\n", + ((ret & AD9523_READBACK_0_STAT_PLL2_REF_CLK) ? "OK" : "MISSING"), + ((ret & AD9523_READBACK_0_STAT_PLL2_FB_CLK) ? "OK" : "MISSING"), + ((ret & AD9523_READBACK_0_STAT_VCXO) ? "OK" : "MISSING"), + ((ret & AD9523_READBACK_0_STAT_REF_TEST) ? "OK" : "MISSING"), + ((ret & AD9523_READBACK_0_STAT_REFB) ? "OK" : "MISSING"), + ((ret & AD9523_READBACK_0_STAT_REFA) ? "OK" : "MISSING"), + ((ret & AD9523_READBACK_0_STAT_PLL2_LD) ? "OK" : "FAIL"), + ((ret & AD9523_READBACK_0_STAT_PLL1_LD) ? "OK" : "FAIL")); + } + + break; + case AD9523_VCO1_FREQ: + ret = ad9523_read(indio_dev, AD9523_PLL2_VCO_DIVIDER); + if (ret < 0) + break; + ret = sprintf(buf, "%lu\n", st->vco_freq / ((ret & 0x3) + 3)); + break; + case AD9523_VCO2_FREQ: + ret = ad9523_read(indio_dev, AD9523_PLL2_VCO_DIVIDER); + if (ret < 0) + break; + ret = sprintf(buf, "%lu\n", st->vco_freq / + (((ret >> 4) & 0x3) + 3)); + break; + case AD9523_VCO_FREQ_AVAIL: + ret = sprintf(buf, "%lu %lu %lu\n", st->vco_freq / 3, + st->vco_freq / 4, st->vco_freq / 5); + break; + } + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static IIO_DEVICE_ATTR(vco1_frequency, S_IRUGO | S_IWUSR, + ad9523_show, + ad9523_store, + AD9523_VCO1_FREQ); + +static IIO_DEVICE_ATTR(vco2_frequency, S_IRUGO | S_IWUSR, + ad9523_show, + ad9523_store, + AD9523_VCO2_FREQ); + +static IIO_DEVICE_ATTR(vco_frequency_available, S_IRUGO, + ad9523_show, + NULL, + AD9523_VCO_FREQ_AVAIL); + +static IIO_DEVICE_ATTR(status, S_IRUGO, + ad9523_show, + NULL, + AD9523_STATUS0); + +static IIO_DEVICE_ATTR(sync, S_IWUSR, + NULL, + ad9523_store, + AD9523_SYNC); + +static IIO_DEVICE_ATTR(store_eeprom, S_IWUSR, + NULL, + ad9523_store, + AD9523_EEPROM); + +#define IIO_DEV_ATTR_CLK_SRC(_channel, _name) \ + IIO_DEVICE_ATTR(out_altvoltage##_channel##_clk_src_##_name##_en,\ + S_IRUGO | S_IWUSR, ad9523_show, ad9523_store, \ + AD9523_ALT_SRC_CH##_channel) + +static IIO_DEV_ATTR_CLK_SRC(0, vcxo); +static IIO_DEV_ATTR_CLK_SRC(1, vcxo); +static IIO_DEV_ATTR_CLK_SRC(2, vcxo); +static IIO_DEV_ATTR_CLK_SRC(3, vcxo); +static IIO_DEV_ATTR_CLK_SRC(4, vco2); +static IIO_DEV_ATTR_CLK_SRC(5, vco2); +static IIO_DEV_ATTR_CLK_SRC(6, vco2); +static IIO_DEV_ATTR_CLK_SRC(7, vco2); +static IIO_DEV_ATTR_CLK_SRC(8, vco2); +static IIO_DEV_ATTR_CLK_SRC(9, vco2); + +static struct attribute *ad9523_attributes[] = { + &iio_dev_attr_status.dev_attr.attr, + &iio_dev_attr_sync.dev_attr.attr, + &iio_dev_attr_store_eeprom.dev_attr.attr, + &iio_dev_attr_vco_frequency_available.dev_attr.attr, + &iio_dev_attr_vco1_frequency.dev_attr.attr, + &iio_dev_attr_vco2_frequency.dev_attr.attr, + &iio_dev_attr_out_altvoltage0_clk_src_vcxo_en.dev_attr.attr, + &iio_dev_attr_out_altvoltage1_clk_src_vcxo_en.dev_attr.attr, + &iio_dev_attr_out_altvoltage2_clk_src_vcxo_en.dev_attr.attr, + &iio_dev_attr_out_altvoltage3_clk_src_vcxo_en.dev_attr.attr, + &iio_dev_attr_out_altvoltage4_clk_src_vco2_en.dev_attr.attr, + &iio_dev_attr_out_altvoltage5_clk_src_vco2_en.dev_attr.attr, + &iio_dev_attr_out_altvoltage6_clk_src_vco2_en.dev_attr.attr, + &iio_dev_attr_out_altvoltage7_clk_src_vco2_en.dev_attr.attr, + &iio_dev_attr_out_altvoltage8_clk_src_vco2_en.dev_attr.attr, + &iio_dev_attr_out_altvoltage9_clk_src_vco2_en.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad9523_attribute_group = { + .attrs = ad9523_attributes, +}; + +static int ad9523_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad9523_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&indio_dev->mlock); + ret = ad9523_read(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel)); + mutex_unlock(&indio_dev->mlock); + + if (ret < 0) + return ret; + + switch (m) { + case 0: + *val = !(ret & AD9523_CLOCK_DIST_PWR_DOWN_EN); + return IIO_VAL_INT; + case IIO_CHAN_INFO_FREQUENCY: + *val = st->vco_out_freq[st->vco_out_map[chan->channel]] / + (((ret >> 8) & 0x3FF) + 1); + return IIO_VAL_INT; + case IIO_CHAN_INFO_PHASE: + *val = (ret >> 18) & 0x3F; + return IIO_VAL_INT; + default: + return -EINVAL; + } +}; + +static int ad9523_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad9523_state *st = iio_priv(indio_dev); + unsigned reg; + int ret, tmp; + + mutex_lock(&indio_dev->mlock); + ret = ad9523_read(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel)); + if (ret < 0) + goto out; + + reg = ret; + + switch (mask) { + case 0: + if (val) + reg &= ~AD9523_CLOCK_DIST_PWR_DOWN_EN; + else + reg |= AD9523_CLOCK_DIST_PWR_DOWN_EN; + break; + case IIO_CHAN_INFO_FREQUENCY: + tmp = st->vco_out_freq[st->vco_out_map[chan->channel]] / val; + tmp = clamp(tmp, 1, 1024); + reg &= ~(0x3FF << 8); + reg |= AD9523_CLOCK_DIST_DIV(tmp); + break; + case IIO_CHAN_INFO_PHASE: + if (val < 0 || val > 63) { + ret = -EINVAL; + goto out; + } + reg &= ~(0x3F << 18); + reg |= AD9523_CLOCK_DIST_DIV_PHASE(val); + break; + default: + ret = -EINVAL; + goto out; + } + + ret = ad9523_write(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel), + reg); + if (ret < 0) + goto out; + + ad9523_io_update(indio_dev); +out: + mutex_unlock(&indio_dev->mlock); + return ret; +} + +static int ad9523_reg_access(struct iio_dev *indio_dev, + unsigned reg, unsigned writeval, + unsigned *readval) +{ + int ret; + + mutex_lock(&indio_dev->mlock); + if (readval == NULL) { + ret = ad9523_write(indio_dev, reg | AD9523_R1B, writeval); + ad9523_io_update(indio_dev); + } else { + ret = ad9523_read(indio_dev, reg | AD9523_R1B); + if (ret < 0) + return ret; + *readval = ret; + ret = 0; + } + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static const struct iio_info ad9523_info = { + .read_raw = &ad9523_read_raw, + .write_raw = &ad9523_write_raw, + .debugfs_reg_access = &ad9523_reg_access, + .attrs = &ad9523_attribute_group, + .driver_module = THIS_MODULE, +}; + +static int ad9523_setup(struct iio_dev *indio_dev) +{ + struct ad9523_state *st = iio_priv(indio_dev); + struct ad9523_platform_data *pdata = st->pdata; + struct ad9523_channel_spec *chan; + int ret, i; + + ret = ad9523_write(indio_dev, AD9523_SERIAL_PORT_CONFIG, + AD9523_SER_CONF_SOFT_RESET | + (st->spi->mode & SPI_3WIRE ? 0 : AD9523_SER_CONF_SDO_ACTIVE)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_READBACK_CTRL, + AD9523_READBACK_CTRL_READ_BUFFERED); + if (ret < 0) + return ret; + + ret = ad9523_io_update(indio_dev); + if (ret < 0) + return ret; + + /* + * PLL1 Setup + */ + ret = ad9523_write(indio_dev, AD9523_PLL1_REF_A_DIVIDER, + pdata->refa_r_div); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_REF_B_DIVIDER, + pdata->refb_r_div); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_FEEDBACK_DIVIDER, + pdata->pll1_feedback_div); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_CHARGE_PUMP_CTRL, + AD9523_PLL1_CHARGE_PUMP_CURRENT_nA(pdata->pll1_charge_pump_current_nA) | + AD9523_PLL1_CHARGE_PUMP_MODE_NORMAL | + AD9523_PLL1_BACKLASH_PW_MIN); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_INPUT_RECEIVERS_CTRL, + AD_IF(refa_diff_rcv_en, AD9523_PLL1_REFA_RCV_EN) | + AD_IF(refb_diff_rcv_en, AD9523_PLL1_REFB_RCV_EN) | + AD_IF(osc_in_diff_en, AD9523_PLL1_OSC_IN_DIFF_EN) | + AD_IF(osc_in_cmos_neg_inp_en, AD9523_PLL1_OSC_IN_CMOS_NEG_INP_EN) | + AD_IF(refa_diff_rcv_en, AD9523_PLL1_REFA_DIFF_RCV_EN) | + AD_IF(refa_diff_rcv_en, AD9523_PLL1_REFB_DIFF_RCV_EN)); + if (ret < 0) + return ret; + + + ret = ad9523_write(indio_dev, AD9523_PLL1_REF_CTRL, + AD_IF(zd_in_diff_en, AD9523_PLL1_ZD_IN_DIFF_EN) | + AD_IF(zd_in_cmos_neg_inp_en, AD9523_PLL1_ZD_IN_CMOS_NEG_INP_EN) | + AD_IF(zero_delay_mode_internal_en, AD9523_PLL1_ZERO_DELAY_MODE_INT) | + AD_IF(osc_in_feedback_en, AD9523_PLL1_OSC_IN_PLL_FEEDBACK_EN) | + AD_IF(refa_cmos_neg_inp_en, AD9523_PLL1_REFA_CMOS_NEG_INP_EN) | + AD_IF(refb_cmos_neg_inp_en, AD9523_PLL1_REFB_CMOS_NEG_INP_EN)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_MISC_CTRL, + AD9523_PLL1_REFB_INDEP_DIV_CTRL_EN | + /*AD9523_PLL1_OSC_CTRL_FAIL_VCC_BY2_EN |*/ + AD9523_PLL1_REF_MODE(pdata->ref_mode)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_LOOP_FILTER_CTRL, + AD9523_PLL1_LOOP_FILTER_RZERO(pdata->pll1_loop_filter_rzero)); + if (ret < 0) + return ret; + /* + * PLL2 Setup + */ + + ret = ad9523_write(indio_dev, AD9523_PLL2_CHARGE_PUMP, + AD9523_PLL2_CHARGE_PUMP_CURRENT_nA(pdata->pll2_charge_pump_current_nA)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL2_FEEDBACK_DIVIDER_AB, + AD9523_PLL2_FB_NDIV_A_CNT(pdata->pll2_ndiv_a_cnt) | + AD9523_PLL2_FB_NDIV_B_CNT(pdata->pll2_ndiv_b_cnt)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL2_CTRL, + AD9523_PLL2_CHARGE_PUMP_MODE_NORMAL | + AD9523_PLL2_BACKLASH_CTRL_EN | + AD_IF(pll2_freq_doubler_en, AD9523_PLL2_FREQ_DOUBLER_EN)); + if (ret < 0) + return ret; + + st->vco_freq = (pdata->vcxo_freq * (pdata->pll2_freq_doubler_en ? 2 : 1) + / pdata->pll2_r2_div) * + AD9523_PLL2_FB_NDIV(pdata->pll2_ndiv_a_cnt, pdata->pll2_ndiv_b_cnt); + + ret = ad9523_write(indio_dev, AD9523_PLL2_VCO_CTRL, + AD9523_PLL2_VCO_CALIBRATE); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL2_VCO_DIVIDER, + AD9523_PLL2_VCO_DIV_M1(pdata->pll2_vco_diff_m1) | + AD9523_PLL2_VCO_DIV_M2(pdata->pll2_vco_diff_m2) | + AD_IFE(pll2_vco_diff_m1, 0, AD9523_PLL2_VCO_DIV_M1_PWR_DOWN_EN) | + AD_IFE(pll2_vco_diff_m2, 0, AD9523_PLL2_VCO_DIV_M2_PWR_DOWN_EN)); + if (ret < 0) + return ret; + + if (pdata->pll2_vco_diff_m1) + st->vco_out_freq[0] = st->vco_freq / pdata->pll2_vco_diff_m1; + + if (pdata->pll2_vco_diff_m2) + st->vco_out_freq[1] = st->vco_freq / pdata->pll2_vco_diff_m2; + + st->vco_out_freq[2] = pdata->vcxo_freq; + + ret = ad9523_write(indio_dev, AD9523_PLL2_R2_DIVIDER, + AD9523_PLL2_R2_DIVIDER_VAL(pdata->pll2_r2_div)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL2_LOOP_FILTER_CTRL, + AD9523_PLL2_LOOP_FILTER_CPOLE1(pdata->cpole1) | + AD9523_PLL2_LOOP_FILTER_RZERO(pdata->rzero) | + AD9523_PLL2_LOOP_FILTER_RPOLE2(pdata->rpole2) | + AD_IF(rzero_bypass_en, AD9523_PLL2_LOOP_FILTER_RZERO_BYPASS_EN)); + if (ret < 0) + return ret; + + for (i = 0; i < pdata->num_channels; i++) { + chan = &pdata->channels[i]; + if (chan->channel_num < 14) { + ret = ad9523_write(indio_dev, + AD9523_CHANNEL_CLOCK_DIST(chan->channel_num), + AD9523_CLOCK_DIST_DRIVER_MODE(chan->driver_mode) | + AD9523_CLOCK_DIST_DIV(chan->channel_divider) | + AD9523_CLOCK_DIST_DIV_PHASE(chan->divider_phase) | + (chan->sync_ignore_en ? AD9523_CLOCK_DIST_IGNORE_SYNC_EN : 0) | + (chan->divider_output_invert_en ? AD9523_CLOCK_DIST_INV_DIV_OUTPUT_EN : 0) | + (chan->low_power_mode_en ? AD9523_CLOCK_DIST_LOW_PWR_MODE_EN : 0) | + (chan->output_dis ? AD9523_CLOCK_DIST_PWR_DOWN_EN : 0)); + if (ret < 0) + return ret; + + ret = ad9523_vco_out_map(indio_dev, chan->channel_num, + chan->use_alt_clock_src); + if (ret < 0) + return ret; + + st->ad9523_channels[i].type = IIO_ALTVOLTAGE; + st->ad9523_channels[i].output = 1; + st->ad9523_channels[i].indexed = 1; + st->ad9523_channels[i].channel = chan->channel_num; + st->ad9523_channels[i].extend_name = chan->extended_name; + st->ad9523_channels[i].info_mask = IIO_CHAN_INFO_PHASE_SEPARATE_BIT | + IIO_CHAN_INFO_FREQUENCY_SEPARATE_BIT; + + } + } + + ret = ad9523_write(indio_dev, AD9523_POWER_DOWN_CTRL, 0); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_STATUS_SIGNALS, 0x000302); + if (ret < 0) + return ret; + + ret = ad9523_io_update(indio_dev); + if (ret < 0) + return ret; + + return 0; +} + +static int __devinit ad9523_probe(struct spi_device *spi) +{ + struct ad9523_platform_data *pdata = spi->dev.platform_data; + struct iio_dev *indio_dev; + struct ad9523_state *st; + int ret; + + if (!pdata) { + dev_dbg(&spi->dev, "no platform data?\n"); + pdata = &default_pdata; + } + + indio_dev = iio_allocate_device(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + + st->reg = regulator_get(&spi->dev, "vcc"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) + goto error_put_reg; + } + + spi_set_drvdata(spi, indio_dev); + st->spi = spi; + st->pdata = pdata; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->info = &ad9523_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = st->ad9523_channels; + indio_dev->num_channels = pdata->num_channels; + + ret = ad9523_setup(indio_dev); + if (ret < 0) + goto error_disable_reg; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_disable_reg; + + return 0; + +error_disable_reg: + if (!IS_ERR(st->reg)) + regulator_disable(st->reg); +error_put_reg: + if (!IS_ERR(st->reg)) + regulator_put(st->reg); + + iio_free_device(indio_dev); + + return ret; +} + +static int __devexit ad9523_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad9523_state *st = iio_priv(indio_dev); + struct regulator *reg = st->reg; + + iio_device_unregister(indio_dev); + + if (!IS_ERR(reg)) { + regulator_disable(reg); + regulator_put(reg); + } + + iio_free_device(indio_dev); + + return 0; +} + +static const struct spi_device_id ad9523_id[] = { + {"ad9523", 9523}, + {} +}; + +static struct spi_driver ad9523_driver = { + .driver = { + .name = "ad9523", + .owner = THIS_MODULE, + }, + .probe = ad9523_probe, + .remove = __devexit_p(ad9523_remove), + .id_table = ad9523_id, +}; + +static int __init ad9523_init(void) +{ + return spi_register_driver(&ad9523_driver); +} +module_init(ad9523_init); + +static void __exit ad9523_exit(void) +{ + spi_unregister_driver(&ad9523_driver); +} +module_exit(ad9523_exit); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD9523 CLOCKDIST/PLL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/frequency/ad9523.h b/drivers/staging/iio/frequency/ad9523.h new file mode 100644 index 0000000000000..5867ae06346cf --- /dev/null +++ b/drivers/staging/iio/frequency/ad9523.h @@ -0,0 +1,316 @@ +/* + * AD9523 SPI Low Jitter Clock Generator + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#ifndef IIO_PLL_AD9523_H_ +#define IIO_PLL_AD9523_H_ + +#define AD9523_READ (1 << 15) +#define AD9523_WRITE (0 << 15) +#define AD9523_CNT(x) (((x) - 1) << 13) +#define AD9523_ADDR(x) ((x) & 0xFFF) + +#define AD9523_R1B (1 << 16) +#define AD9523_R2B (2 << 16) +#define AD9523_R3B (3 << 16) +#define AD9523_TRANSFER_LEN(x) ((x) >> 16) + +#define AD9523_SERIAL_PORT_CONFIG (AD9523_R1B | 0x0) +#define AD9523_VERSION_REGISTER (AD9523_R1B | 0x2) +#define AD9523_PART_REGISTER (AD9523_R1B | 0x3) +#define AD9523_READBACK_CTRL (AD9523_R1B | 0x4) + +#define AD9523_EEPROM_CUSTOMER_VERSION_ID (AD9523_R2B | 0x6) + +#define AD9523_PLL1_REF_A_DIVIDER (AD9523_R2B | 0x11) +#define AD9523_PLL1_REF_B_DIVIDER (AD9523_R2B | 0x13) +#define AD9523_PLL1_REF_TEST_DIVIDER (AD9523_R1B | 0x14) +#define AD9523_PLL1_FEEDBACK_DIVIDER (AD9523_R2B | 0x17) +#define AD9523_PLL1_CHARGE_PUMP_CTRL (AD9523_R2B | 0x19) +#define AD9523_PLL1_INPUT_RECEIVERS_CTRL (AD9523_R1B | 0x1A) +#define AD9523_PLL1_REF_CTRL (AD9523_R1B | 0x1B) +#define AD9523_PLL1_MISC_CTRL (AD9523_R1B | 0x1C) +#define AD9523_PLL1_LOOP_FILTER_CTRL (AD9523_R1B | 0x1D) + +#define AD9523_PLL2_CHARGE_PUMP (AD9523_R1B | 0xF0) +#define AD9523_PLL2_FEEDBACK_DIVIDER_AB (AD9523_R1B | 0xF1) +#define AD9523_PLL2_CTRL (AD9523_R1B | 0xF2) +#define AD9523_PLL2_VCO_CTRL (AD9523_R1B | 0xF3) +#define AD9523_PLL2_VCO_DIVIDER (AD9523_R1B | 0xF4) +#define AD9523_PLL2_LOOP_FILTER_CTRL (AD9523_R2B | 0xF6) +#define AD9523_PLL2_R2_DIVIDER (AD9523_R1B | 0xF7) + +#define AD9523_CHANNEL_CLOCK_DIST(ch) (AD9523_R3B | (0x192 + 3 * ch)) + +#define AD9523_PLL1_OUTPUT_CTRL (AD9523_R1B | 0x1BA) +#define AD9523_PLL1_OUTPUT_CHANNEL_CTRL (AD9523_R1B | 0x1BB) + +#define AD9523_READBACK_0 (AD9523_R1B | 0x22C) +#define AD9523_READBACK_1 (AD9523_R1B | 0x22D) + +#define AD9523_STATUS_SIGNALS (AD9523_R3B | 0x232) +#define AD9523_POWER_DOWN_CTRL (AD9523_R1B | 0x233) +#define AD9523_IO_UPDATE (AD9523_R1B | 0x234) + +#define AD9523_EEPROM_DATA_XFER_STATUS (AD9523_R1B | 0xB00) +#define AD9523_EEPROM_ERROR_READBACK (AD9523_R1B | 0xB01) +#define AD9523_EEPROM_CTRL1 (AD9523_R1B | 0xB02) +#define AD9523_EEPROM_CTRL2 (AD9523_R1B | 0xB03) + +/* AD9523_SERIAL_PORT_CONFIG */ + +#define AD9523_SER_CONF_SDO_ACTIVE (1 << 7) +#define AD9523_SER_CONF_SOFT_RESET (1 << 5) + +/* AD9523_READBACK_CTRL */ +#define AD9523_READBACK_CTRL_READ_BUFFERED (1 << 0) + +/* AD9523_PLL1_CHARGE_PUMP_CTRL */ +#define AD9523_PLL1_CHARGE_PUMP_CURRENT_nA(x) (((x) / 500) & 0x7F) /* 0,5uA..63,5uA */ +#define AD9523_PLL1_CHARGE_PUMP_TRISTATE (1 << 7) +#define AD9523_PLL1_CHARGE_PUMP_MODE_NORMAL (3 << 8) +#define AD9523_PLL1_CHARGE_PUMP_MODE_PUMP_DOWN (2 << 8) +#define AD9523_PLL1_CHARGE_PUMP_MODE_PUMP_UP (1 << 8) +#define AD9523_PLL1_CHARGE_PUMP_MODE_TRISTATE (0 << 8) +#define AD9523_PLL1_BACKLASH_PW_MIN (0 << 10) +#define AD9523_PLL1_BACKLASH_PW_LOW (1 << 10) +#define AD9523_PLL1_BACKLASH_PW_HIGH (2 << 10) +#define AD9523_PLL1_BACKLASH_PW_MAX (3 << 10) + +/* AD9523_PLL1_INPUT_RECEIVERS_CTRL */ +#define AD9523_PLL1_REF_TEST_RCV_EN (1 << 7) +#define AD9523_PLL1_REFB_DIFF_RCV_EN (1 << 6) +#define AD9523_PLL1_REFA_DIFF_RCV_EN (1 << 5) +#define AD9523_PLL1_REFB_RCV_EN (1 << 4) +#define AD9523_PLL1_REFA_RCV_EN (1 << 3) +#define AD9523_PLL1_REFA_REFB_PWR_CTRL_EN (1 << 2) +#define AD9523_PLL1_OSC_IN_CMOS_NEG_INP_EN (1 << 1) +#define AD9523_PLL1_OSC_IN_DIFF_EN (1 << 0) + +/* AD9523_PLL1_REF_CTRL */ +#define AD9523_PLL1_BYPASS_REF_TEST_DIV_EN (1 << 7) +#define AD9523_PLL1_BYPASS_FEEDBACK_DIV_EN (1 << 6) +#define AD9523_PLL1_ZERO_DELAY_MODE_INT (1 << 5) +#define AD9523_PLL1_ZERO_DELAY_MODE_EXT (0 << 5) +#define AD9523_PLL1_OSC_IN_PLL_FEEDBACK_EN (1 << 4) +#define AD9523_PLL1_ZD_IN_CMOS_NEG_INP_EN (1 << 3) +#define AD9523_PLL1_ZD_IN_DIFF_EN (1 << 2) +#define AD9523_PLL1_REFB_CMOS_NEG_INP_EN (1 << 1) +#define AD9523_PLL1_REFA_CMOS_NEG_INP_EN (1 << 0) + +/* AD9523_PLL1_MISC_CTRL */ +#define AD9523_PLL1_REFB_INDEP_DIV_CTRL_EN (1 << 7) +#define AD9523_PLL1_OSC_CTRL_FAIL_VCC_BY2_EN (1 << 6) +#define AD9523_PLL1_REF_MODE(x) ((x) << 2) +#define AD9523_PLL1_BYPASS_REFB_DIV (1 << 1) +#define AD9523_PLL1_BYPASS_REFA_DIV (1 << 0) + +/* AD9523_PLL1_LOOP_FILTER_CTRL */ +#define AD9523_PLL1_LOOP_FILTER_RZERO(x) ((x) & 0xF) + +/* AD9523_PLL2_CHARGE_PUMP */ +#define AD9523_PLL2_CHARGE_PUMP_CURRENT_nA(x) ((x) / 3500) /* 3,5uA..900uA */ + +/* AD9523_PLL2_FEEDBACK_DIVIDER_AB */ +#define AD9523_PLL2_FB_NDIV_A_CNT(x) (((x) & 0x3) << 6) +#define AD9523_PLL2_FB_NDIV_B_CNT(x) (((x) & 0x3F) << 0) +#define AD9523_PLL2_FB_NDIV(a, b) (4 * (b) + (a)) + +/* AD9523_PLL2_CTRL */ +#define AD9523_PLL2_CHARGE_PUMP_MODE_NORMAL (3 << 0) +#define AD9523_PLL2_CHARGE_PUMP_MODE_PUMP_DOWN (2 << 0) +#define AD9523_PLL2_CHARGE_PUMP_MODE_PUMP_UP (1 << 0) +#define AD9523_PLL2_CHARGE_PUMP_MODE_TRISTATE (0 << 0) +#define AD9523_PLL2_BACKLASH_PW_MIN (0 << 2) +#define AD9523_PLL2_BACKLASH_PW_LOW (1 << 2) +#define AD9523_PLL2_BACKLASH_PW_HIGH (2 << 2) +#define AD9523_PLL2_BACKLASH_PW_MAX (3 << 1) +#define AD9523_PLL2_BACKLASH_CTRL_EN (1 << 4) +#define AD9523_PLL2_FREQ_DOUBLER_EN (1 << 5) +#define AD9523_PLL2_LOCK_DETECT_PWR_DOWN_EN (1 << 7) + +/* AD9523_PLL2_VCO_CTRL */ +#define AD9523_PLL2_VCO_CALIBRATE (1 << 1) +#define AD9523_PLL2_FORCE_VCO_MIDSCALE (1 << 2) +#define AD9523_PLL2_FORCE_REFERENCE_VALID (1 << 3) +#define AD9523_PLL2_FORCE_RELEASE_SYNC (1 << 4) + +/* AD9523_PLL2_VCO_DIVIDER */ +#define AD9523_PLL2_VCO_DIV_M1(x) ((((x) - 3) & 0x3) << 0) +#define AD9523_PLL2_VCO_DIV_M2(x) ((((x) - 3) & 0x3) << 4) +#define AD9523_PLL2_VCO_DIV_M1_PWR_DOWN_EN (1 << 2) +#define AD9523_PLL2_VCO_DIV_M2_PWR_DOWN_EN (1 << 6) + +/* AD9523_PLL2_LOOP_FILTER_CTRL */ +#define AD9523_PLL2_LOOP_FILTER_CPOLE1(x) (((x) & 0x7) << 0) +#define AD9523_PLL2_LOOP_FILTER_RZERO(x) (((x) & 0x7) << 3) +#define AD9523_PLL2_LOOP_FILTER_RPOLE2(x) (((x) & 0x7) << 6) +#define AD9523_PLL2_LOOP_FILTER_RZERO_BYPASS_EN (1 << 8) + +/* AD9523_PLL2_R2_DIVIDER */ +#define AD9523_PLL2_R2_DIVIDER_VAL(x) (((x) & 0x1F) << 0) + +/* AD9523_CHANNEL_CLOCK_DIST */ +#define AD9523_CLOCK_DIST_DIV_PHASE(x) (((x) & 0x3F) << 18) +#define AD9523_CLOCK_DIST_DIV(x) ((((x) - 1) & 0x3FF) << 8) +#define AD9523_CLOCK_DIST_INV_DIV_OUTPUT_EN (1 << 7) +#define AD9523_CLOCK_DIST_IGNORE_SYNC_EN (1 << 6) +#define AD9523_CLOCK_DIST_PWR_DOWN_EN (1 << 5) +#define AD9523_CLOCK_DIST_LOW_PWR_MODE_EN (1 << 4) +#define AD9523_CLOCK_DIST_DRIVER_MODE(x) (((x) & 0xF) << 0) + +enum driver_mode { + TRISTATE, + LVPECL_8mA, + LVDS_4mA, + LVDS_7mA, + HSTL0_16mA, + HSTL1_8mA, + CMOS_CONF1, + CMOS_CONF2, + CMOS_CONF3, + CMOS_CONF4, + CMOS_CONF5, + CMOS_CONF6, + CMOS_CONF7, + CMOS_CONF8, + CMOS_CONF9 +}; + +/* AD9523_PLL1_OUTPUT_CTRL */ +#define AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH6_M2 (1 << 7) +#define AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH5_M2 (1 << 6) +#define AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH4_M2 (1 << 5) +#define AD9523_PLL1_OUTP_CTRL_CMOS_DRV_WEAK (1 << 4) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_1 (0 << 0) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_2 (1 << 0) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_4 (2 << 0) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_8 (4 << 0) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_16 (8 << 0) + +/* AD9523_PLL1_OUTPUT_CHANNEL_CTRL */ +#define AD9523_PLL1_OUTP_CH_CTRL_OUTPUT_PWR_DOWN_EN (1 << 7) +#define AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH9_M2 (1 << 6) +#define AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH8_M2 (1 << 5) +#define AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH7_M2 (1 << 4) +#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH3 (1 << 3) +#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH2 (1 << 2) +#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH1 (1 << 1) +#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH0 (1 << 0) + +/* AD9523_READBACK_0 */ +#define AD9523_READBACK_0_STAT_PLL2_REF_CLK (1 << 7) +#define AD9523_READBACK_0_STAT_PLL2_FB_CLK (1 << 6) +#define AD9523_READBACK_0_STAT_VCXO (1 << 5) +#define AD9523_READBACK_0_STAT_REF_TEST (1 << 4) +#define AD9523_READBACK_0_STAT_REFB (1 << 3) +#define AD9523_READBACK_0_STAT_REFA (1 << 2) +#define AD9523_READBACK_0_STAT_PLL2_LD (1 << 1) +#define AD9523_READBACK_0_STAT_PLL1_LD (1 << 0) + +/* AD9523_READBACK_1 */ +#define AD9523_READBACK_1_HOLDOVER_ACTIVE (1 << 3) +#define AD9523_READBACK_1_AUTOMODE_SEL_REFB (1 << 2) +#define AD9523_READBACK_1_VCO_CALIB_IN_PROGRESS (1 << 0) + +/* AD9523_STATUS_SIGNALS */ +#define AD9523_STATUS_SIGNALS_SYNC_MAN_CTRL (1 << 16) +/* AD9523_POWER_DOWN_CTRL */ +#define AD9523_POWER_DOWN_CTRL_PLL1_PWR_DOWN (1 << 2) +#define AD9523_POWER_DOWN_CTRL_PLL2_PWR_DOWN (1 << 1) +#define AD9523_POWER_DOWN_CTRL_DIST_PWR_DOWN (1 << 0) + +/* AD9523_IO_UPDATE */ +#define AD9523_IO_UPDATE_EN (1 << 0) + +/* AD9523_EEPROM_DATA_XFER_STATUS */ +#define AD9523_EEPROM_DATA_XFER_IN_PROGRESS (1 << 0) + +/* AD9523_EEPROM_ERROR_READBACK */ +#define AD9523_EEPROM_ERROR_READBACK_FAIL (1 << 0) + +/* AD9523_EEPROM_CTRL1 */ +#define AD9523_EEPROM_CTRL1_SOFT_EEPROM (1 << 1) +#define AD9523_EEPROM_CTRL1_EEPROM_WRITE_PROT_DIS (1 << 0) + +/* AD9523_EEPROM_CTRL2 */ +#define AD9523_EEPROM_CTRL2_REG2EEPROM (1 << 0) + + +struct ad9523_channel_spec { + unsigned channel_num; + bool divider_output_invert_en; + bool sync_ignore_en; + bool low_power_mode_en; + bool use_alt_clock_src; /* CH0..CH3 VCXO, CH4..CH9 VCO2 */ + bool output_dis; + unsigned char driver_mode; + unsigned char divider_phase; + unsigned short channel_divider; + char extended_name[16]; +}; + +/* + * TODO: struct adf4350_platform_data needs to go into include/linux/iio + */ + +/* + * struct ad9523_platform_data - platform specific information + * @clkin: REFin frequency in Hz. + */ + +struct ad9523_platform_data { + unsigned long vcxo_freq; + + /* Differential/ Single-Ended Input Configuration */ + bool refa_diff_rcv_en; + bool refb_diff_rcv_en; + bool zd_in_diff_en; + bool osc_in_diff_en; + + /* + * Valid if differential input disabled + * if not true defaults to pos input + */ + bool refa_cmos_neg_inp_en; + bool refb_cmos_neg_inp_en; + bool zd_in_cmos_neg_inp_en; + bool osc_in_cmos_neg_inp_en; + + /* PLL1 Setting */ + unsigned short refa_r_div; + unsigned short refb_r_div; + unsigned short pll1_feedback_div; + unsigned short pll1_charge_pump_current_nA; + bool zero_delay_mode_internal_en; + bool osc_in_feedback_en; + unsigned char pll1_loop_filter_rzero; + + /* Reference */ + unsigned char ref_mode; + + /* PLL2 Setting */ + unsigned int pll2_charge_pump_current_nA; + unsigned char pll2_ndiv_a_cnt; + unsigned char pll2_ndiv_b_cnt; + bool pll2_freq_doubler_en; + unsigned char pll2_r2_div; + unsigned char pll2_vco_diff_m1; /* 3..5 */ + unsigned char pll2_vco_diff_m2; /* 3..5 */ + + /* Loop Filter PLL2 */ + unsigned char rpole2; + unsigned char rzero; + unsigned char cpole1; + bool rzero_bypass_en; + + /* Output Channel Configuration */ + int num_channels; + struct ad9523_channel_spec *channels; +}; + +#endif /* IIO_PLL_AD9523_H_ */ From 89fdcad8f78a24f008b26b3092bc7326eb8c9a18 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 9 Mar 2012 13:37:04 +0100 Subject: [PATCH 113/261] iio: frequency: New driver for DDS PCORE/COREFPGA Module using AD9122 DAC Signed-off-by: Michael Hennerich --- drivers/staging/iio/frequency/Kconfig | 14 + drivers/staging/iio/frequency/Makefile | 2 + drivers/staging/iio/frequency/ad9122.c | 185 ++++ drivers/staging/iio/frequency/cf_ad9122.c | 498 +++++++++ drivers/staging/iio/frequency/cf_ad9122.h | 1151 +++++++++++++++++++++ 5 files changed, 1850 insertions(+) create mode 100644 drivers/staging/iio/frequency/ad9122.c create mode 100644 drivers/staging/iio/frequency/cf_ad9122.c create mode 100644 drivers/staging/iio/frequency/cf_ad9122.h diff --git a/drivers/staging/iio/frequency/Kconfig b/drivers/staging/iio/frequency/Kconfig index 7b2c0c36300db..f735cb97acb42 100644 --- a/drivers/staging/iio/frequency/Kconfig +++ b/drivers/staging/iio/frequency/Kconfig @@ -77,5 +77,19 @@ config AD9951 Say yes here to build support for Analog Devices DDS chip ad9951, provides direct access via sysfs. +config AD9122_CF + tristate "Analog Devices AD9122 DDS driver" + depends on SPI + help + Say yes here to build support for Analog Devices DDS chip + AD9122, provides direct access via sysfs. + +config AD9122_CF_DAC + tristate "Analog Devices AD9122 DAC" + depends on AD9122_CF + help + Say yes here to build support for Analog Devices AD9122 DAC chip + ad9122, provides direct access via sysfs. + endmenu endmenu diff --git a/drivers/staging/iio/frequency/Makefile b/drivers/staging/iio/frequency/Makefile index 2f869006a5ed6..c02528196b44a 100644 --- a/drivers/staging/iio/frequency/Makefile +++ b/drivers/staging/iio/frequency/Makefile @@ -10,3 +10,5 @@ obj-$(CONFIG_AD9850) += ad9850.o obj-$(CONFIG_AD9852) += ad9852.o obj-$(CONFIG_AD9910) += ad9910.o obj-$(CONFIG_AD9951) += ad9951.o +obj-$(CONFIG_AD9122_CF) += cf_ad9122.o +obj-$(CONFIG_AD9122_CF_DAC) += ad9122.o diff --git a/drivers/staging/iio/frequency/ad9122.c b/drivers/staging/iio/frequency/ad9122.c new file mode 100644 index 0000000000000..044deb939cfab --- /dev/null +++ b/drivers/staging/iio/frequency/ad9122.c @@ -0,0 +1,185 @@ +/* + * AD9122 SPI DAC driver for DDS PCORE/COREFPGA Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" + +#include "cf_ad9122.h" + +#define CHIPID_AD9122 0x8 + +static const unsigned char ad9122_reg_defaults[][2] = { + {0x00, 0x00}, + {0x01, 0x10}, + {0x03, 0x80}, + {0x04, 0x00}, + {0x05, 0x00}, + {0x08, 0x3F}, + {0x0A, 0x40}, + {0x0C, 0xD1}, + {0x0D, 0xD6}, + {0x10, 0x48}, + {0x11, 0x00}, + {0x16, 0x00}, + {0x17, 0x04}, + {0x18, 0x00}, + {0x1B, 0xE0}, + {0x1C, 0x01}, + {0x1D, 0x01}, + {0x1E, 0x01}, + {0x30, 0x00}, + {0x31, 0x00}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0x00}, + {0x38, 0x00}, + {0x39, 0x00}, + {0x3A, 0x00}, + {0x3B, 0x00}, + {0x3C, 0x00}, + {0x3D, 0x00}, + {0x3E, 0x00}, + {0x3F, 0x00}, + {0x40, 0xF9}, + {0x41, 0x01}, + {0x42, 0x00}, + {0x43, 0x00}, + {0x44, 0xF9}, + {0x45, 0x01}, + {0x46, 0x00}, + {0x47, 0x00}, + {0x48, 0x02}, +}; + +static int ad9122_read(struct spi_device *spi, unsigned reg) +{ + unsigned char buf[2]; + int ret; + + buf[0] = 0x80 | reg; + + ret = spi_write_then_read(spi, &buf[0], 1, &buf[1], 1); + if (ret < 0) + return ret; + + return buf[1]; +} + +static int ad9122_write(struct spi_device *spi, + unsigned reg, unsigned val) +{ + unsigned char buf[2]; + int ret; + + buf[0] = reg; + buf[1] = val; + ret = spi_write(spi, buf, 2); + if (ret < 0) + return ret; + + return 0; +} + +static int ad9122_setup(struct spi_device *spi, unsigned mode) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(ad9122_reg_defaults); i++) + ad9122_write(spi, ad9122_reg_defaults[i][0], + ad9122_reg_defaults[i][1]); + + ad9122_write(spi, 0x18, 0x2); + i = 255; + do { + ret = ad9122_read(spi, 0x18); + if (ret < 0) + return ret; + + } while (i-- && (ret & 0x2)); + + ad9122_write(spi, 0x18, 0x0); + + i = 255; + do { + ret = ad9122_read(spi, 0x18); + if (ret < 0) + return ret; + + } while (i-- && !(ret & 0x2)); + + return 0; +} + + +static int __devinit ad9122_probe(struct spi_device *spi) +{ + struct ad9122_converter *conv; + unsigned id; + int ret; + + conv = kzalloc(sizeof(*conv), GFP_KERNEL); + if (conv == NULL) + return -ENOMEM; + + + id = ad9122_read(spi, 0x1f); + if (id != CHIPID_AD9122) { + dev_err(&spi->dev, "Unrecognized CHIP_ID 0x%X\n", id); + ret = -ENODEV; + goto out; + } + + conv->write = ad9122_write; + conv->read = ad9122_read; + conv->setup = ad9122_setup; + conv->spi = spi; + conv->id = ID_AD9122; + spi_set_drvdata(spi, conv); + + return 0; +out: + kfree(conv); + return ret; +} + +static int ad9122_remove(struct spi_device *spi) +{ + spi_set_drvdata(spi, NULL); + + return 0; +} + +static const struct spi_device_id ad9122_id[] = { + {"ad9122", 0}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad9122_id); + +static struct spi_driver ad9122_driver = { + .driver = { + .name = "ad9122", + .owner = THIS_MODULE, + }, + .probe = ad9122_probe, + .remove = __devexit_p(ad9122_remove), + .id_table = ad9122_id, +}; +module_spi_driver(ad9122_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD9122 ADC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/frequency/cf_ad9122.c b/drivers/staging/iio/frequency/cf_ad9122.c new file mode 100644 index 0000000000000..473069e3c2de6 --- /dev/null +++ b/drivers/staging/iio/frequency/cf_ad9122.c @@ -0,0 +1,498 @@ +/* + * DDS PCORE/COREFPGA Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "../buffer.h" + +#define CF_AD9122_WAVDATA +#include "cf_ad9122.h" + +#define DRIVER_NAME "cf_ad9122" + +struct dds_spidev { + struct device_node *of_nspi; + struct device *dev_spi; +}; + +static u32 ad9122_ddsx(u32 phase, u32 sin_clk, u32 dac_clk) { + + u32 p_offset; + u32 p_incr; + + p_offset = (phase * 0xffff)/360; + p_incr = (sin_clk * 0xffff)/dac_clk; + + return((p_offset << 16) | p_incr); +} + +static void ad9122_dds_mem_init(struct ad9122_dds_state *st) { + + u32 i, sample, addr, data; + + sample = 0; + addr = 0; + + for (i = 0; i < ARRAY_SIZE(ad9122_ia_data); i++) { + data = (sample << 24) | (addr << 16); + AD9122_DDS_OUT(st->regs + AD9122_DDS_MEM_CTRL, ((0 << 26) | data | ad9122_ia_data[i])); + AD9122_DDS_OUT(st->regs + AD9122_DDS_MEM_CTRL, ((1 << 26) | data | ad9122_ib_data[i])); + AD9122_DDS_OUT(st->regs + AD9122_DDS_MEM_CTRL, ((2 << 26) | data | ad9122_qa_data[i])); + AD9122_DDS_OUT(st->regs + AD9122_DDS_MEM_CTRL, ((3 << 26) | data | ad9122_qb_data[i])); + sample++; + if (sample >= 3) { + addr++; + sample = 0; + } + } +} + +static const int ad9122_dds_scale_table[16] = { + 10000, 5000, 2500, 1250, 625, 313, 156, +}; + +static int ad9122_dds_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad9122_dds_state *st = iio_priv(indio_dev); + unsigned long long val64; + unsigned reg; + + switch (m) { + case 0: + if (!chan->output) { + return -EINVAL; + } + reg = AD9122_DDS_IN(st->regs + AD9122_DDS_CTRL); + if (reg & (1 << (chan->channel * 2))) + *val = 1; + else + *val = 0; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + reg = AD9122_DDS_IN(st->regs + AD9122_DDS_SCALE); + reg = (reg >> (chan->channel * 4)) & 0xF; + if (!reg) { + *val = 1; + *val2 = 0; + } else { + *val = 0; + *val2 = 1000000 >> reg; + } + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_FREQUENCY: + if (!chan->output) { + *val = st->dac_clk; + return IIO_VAL_INT; + } + reg = AD9122_DDS_IN(st->regs + chan->address); + val64 = (u64)(reg & 0xFFFF) * (u64)st->dac_clk; + do_div(val64, 0xFFFF); + *val = val64; + return IIO_VAL_INT; + case IIO_CHAN_INFO_PHASE: + reg = AD9122_DDS_IN(st->regs + chan->address); + val64 = (u64)(reg >> 16) * 360000ULL; + do_div(val64, 0xFFFF); + *val = val64; + return IIO_VAL_INT; + } + return -EINVAL; +} + +static int ad9122_dds_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad9122_dds_state *st = iio_priv(indio_dev); + unsigned long long val64; + unsigned reg, ctrl_reg; + int i; + + ctrl_reg = AD9122_DDS_IN(st->regs + AD9122_DDS_CTRL); + + switch (mask) { + case 0: + if (!chan->output) { + return -EINVAL; + } + if (val) + ctrl_reg |= 1 << (chan->channel * 2); + else + ctrl_reg &= ~(1 << (chan->channel * 2)); + + AD9122_DDS_OUT(st->regs + AD9122_DDS_CTRL, ctrl_reg); + break; + case IIO_CHAN_INFO_SCALE: + if (val == 1) { + i = 0; + } else { + for (i = 1; i < 16; i++) + if (val2 == (1000000 >> i)) + break; + } + AD9122_DDS_OUT(st->regs + AD9122_DDS_CTRL, 0); + reg = AD9122_DDS_IN(st->regs + AD9122_DDS_SCALE); + + reg &= ~(0xF << (chan->channel * 4)); + reg |= (i << (chan->channel * 4)); + printk("%s: %d REG = 0x%X\n",__func__,__LINE__, reg); + AD9122_DDS_OUT(st->regs + AD9122_DDS_SCALE, reg); + AD9122_DDS_OUT(st->regs + AD9122_DDS_CTRL, ctrl_reg); + break; + case IIO_CHAN_INFO_FREQUENCY: + if (!chan->output) { + st->dac_clk = val; + break; + } + if (val > (st->dac_clk / 2)) + return -EINVAL; + AD9122_DDS_OUT(st->regs + AD9122_DDS_CTRL, 0); + reg = AD9122_DDS_IN(st->regs + chan->address); + reg &= 0xFFFF0000; + val64 = (u64) val * 0xFFFFULL; + do_div(val64, st->dac_clk); + reg |= val64 & 0xFFFF; + AD9122_DDS_OUT(st->regs + chan->address, reg); + AD9122_DDS_OUT(st->regs + AD9122_DDS_CTRL, ctrl_reg); + break; + case IIO_CHAN_INFO_PHASE: + if (val < 0 || val > 360000) + return -EINVAL; + AD9122_DDS_OUT(st->regs + AD9122_DDS_CTRL, 0); + reg = AD9122_DDS_IN(st->regs + chan->address); + reg &= 0x0000FFFF; + val64 = (u64) val * 0xFFFFULL; + do_div(val64, 360000); + reg |= val64 << 16; + AD9122_DDS_OUT(st->regs + chan->address, reg); + AD9122_DDS_OUT(st->regs + AD9122_DDS_CTRL, ctrl_reg); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ad9122_dds_reg_access(struct iio_dev *indio_dev, + unsigned reg, unsigned writeval, + unsigned *readval) +{ + struct ad9122_dds_state *st = iio_priv(indio_dev); + struct ad9122_converter *conv = to_converter(st->dev_spi); + int ret; + + if (IS_ERR(conv)) + return PTR_ERR(conv); + + if (reg > 0xFF) + return -EINVAL; + + mutex_lock(&indio_dev->mlock); + if (readval == NULL) { + ret = conv->write(conv->spi, reg, writeval & 0xFF); + } else { + ret = conv->read(conv->spi, reg); + if (ret < 0) + return ret; + *readval = ret; + ret = 0; + } + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static IIO_CONST_ATTR(out_altvoltage_scale_available, + "1.000000 0.500000 0.250000 0.125000 ..."); + +static struct attribute *ad9122_dds_attributes[] = { + &iio_const_attr_out_altvoltage_scale_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad9122_dds_attribute_group = { + .attrs = ad9122_dds_attributes, +}; + +#define AD9122_DDS_CHAN(_chan, _address, _extend_name) \ + { .type = IIO_ALTVOLTAGE, \ + .indexed = 1, \ + .channel = _chan, \ + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \ + IIO_CHAN_INFO_PHASE_SEPARATE_BIT | \ + IIO_CHAN_INFO_FREQUENCY_SEPARATE_BIT, \ + .address = _address, \ + .output = 1, \ + .extend_name = _extend_name, \ + } + +#define AD9122_DDS_CHAN_CLK_IN(_chan, _extend_name) \ + { .type = IIO_ALTVOLTAGE, \ + .indexed = 1, \ + .channel = _chan, \ + .info_mask = IIO_CHAN_INFO_FREQUENCY_SEPARATE_BIT, \ + .extend_name = _extend_name, \ + } + +static const struct ad9122_dds_chip_info ad9122_dds_chip_info_tbl[] = { + [ID_AD9122] = { + .name = "AD9122", + .channel[0] = AD9122_DDS_CHAN(0, AD9122_DDS_1A_OUTPUT_CTRL, "1A"), + .channel[1] = AD9122_DDS_CHAN(1, AD9122_DDS_1B_OUTPUT_CTRL, "1B"), + .channel[2] = AD9122_DDS_CHAN(2, AD9122_DDS_2A_OUTPUT_CTRL, "2A"), + .channel[3] = AD9122_DDS_CHAN(3, AD9122_DDS_2B_OUTPUT_CTRL, "2B"), + .channel[4] = AD9122_DDS_CHAN_CLK_IN(0, "DAC_CLK"), + }, + [ID_AD9739A] = { + .name = "AD9739A", + .channel[0] = AD9122_DDS_CHAN(0, AD9122_DDS_1A_OUTPUT_CTRL, "1A"), + .channel[1] = AD9122_DDS_CHAN(1, AD9122_DDS_1B_OUTPUT_CTRL, "1B"), + .channel[2] = AD9122_DDS_CHAN(2, AD9122_DDS_2A_OUTPUT_CTRL, "2A"), + .channel[3] = AD9122_DDS_CHAN(3, AD9122_DDS_2B_OUTPUT_CTRL, "2B"), + .channel[4] = AD9122_DDS_CHAN_CLK_IN(0, "DAC_CLK"), + }, +}; + +static const struct iio_info ad9122_dds_info = { + .driver_module = THIS_MODULE, + .read_raw = &ad9122_dds_read_raw, + .write_raw = &ad9122_dds_write_raw, + .debugfs_reg_access = &ad9122_dds_reg_access, + .attrs = &ad9122_dds_attribute_group, +}; + +static int dds_attach_spi_client(struct device *dev, void *data) +{ + struct dds_spidev *dds_spidev = data; + + if ((dds_spidev->of_nspi == dev->of_node) && dev->driver) { + dds_spidev->dev_spi = dev; + return 1; + } + + return 0; +} +/** + * ad9122_dds_of_probe - probe method for the AIM device. + * @of_dev: pointer to OF device structure + * @match: pointer to the stucture used for matching a device + * + * This function probes the AIM device in the device tree. + * It initializes the driver data structure and the hardware. + * It returns 0, if the driver is bound to the AIM device, or a negative + * value if there is an error. + */ +static int __devinit ad9122_dds_of_probe(struct platform_device *op) +{ + struct ad9122_dds_state *st; + struct iio_dev *indio_dev; + struct device *dev = &op->dev; + resource_size_t remap_size, phys_addr; + struct dds_spidev dds_spidev; + struct ad9122_converter *conv; + int ret; + + dev_info(dev, "Device Tree Probing \'%s\'\n", + op->dev.of_node->name); + + /* Defer driver probe until matching spi + * converter driver is registered + */ + dds_spidev.of_nspi = of_parse_phandle(op->dev.of_node, + "spibus-connected", 0); + if (!dds_spidev.of_nspi) { + dev_err(&op->dev, "could not find spi node\n"); + return -ENODEV; + } + + ret = bus_for_each_dev(&spi_bus_type, NULL, &dds_spidev, + dds_attach_spi_client); + if (ret == 0) + return -EPROBE_DEFER; + + if (!try_module_get(dds_spidev.dev_spi->driver->owner)) + return -ENODEV; + get_device(dds_spidev.dev_spi); + + indio_dev = iio_allocate_device(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + st->dev_spi = dds_spidev.dev_spi; + + dev_set_drvdata(dev, indio_dev); + + /* Get iospace for the device */ + ret = of_address_to_resource(op->dev.of_node, 0, &st->r_mem); + if (ret) { + dev_err(dev, "invalid address\n"); + goto failed1; + } + + phys_addr = st->r_mem.start; + remap_size = resource_size(&st->r_mem); + if (!request_mem_region(phys_addr, remap_size, DRIVER_NAME)) { + dev_err(dev, "Couldn't lock memory region at 0x%08llX\n", + (unsigned long long)phys_addr); + ret = -EBUSY; + goto failed1; + } + + /* Fill in configuration data and add them to the list */ + st->regs = ioremap(phys_addr, remap_size); + if (st->regs == NULL) { + dev_err(dev, "Couldn't ioremap memory at 0x%08llX\n", + (unsigned long long)phys_addr); + ret = -EFAULT; + goto failed2; + } + + conv = to_converter(st->dev_spi); + if (IS_ERR(conv)) { + ret = PTR_ERR(conv); + goto failed3; + } + + ret = conv->setup(conv->spi, 0); + if (ret) { + dev_err(&op->dev, "failed to setup spi device\n"); + goto failed3; + } + + st->chip_info = &ad9122_dds_chip_info_tbl[conv->id]; + + indio_dev->dev.parent = dev; + indio_dev->name = op->dev.of_node->name; + indio_dev->channels = st->chip_info->channel; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->num_channels = 5; + indio_dev->info = &ad9122_dds_info; + + st->dac_clk = 491520000; + + ad9122_dds_mem_init(st); + + AD9122_DDS_OUT(st->regs + 0x04, 0x0); + AD9122_DDS_OUT(st->regs + 0x20, 0x1111); /* divide by 4 */ + AD9122_DDS_OUT(st->regs + 0x08, ad9122_ddsx(90, 40, 492)); + AD9122_DDS_OUT(st->regs + 0x0c, ad9122_ddsx(90, 40, 492)); + AD9122_DDS_OUT(st->regs + 0x10, ad9122_ddsx( 0, 40, 492)); + AD9122_DDS_OUT(st->regs + 0x14, ad9122_ddsx( 0, 40, 492)); + AD9122_DDS_OUT(st->regs + 0x04, 0x1ff); /* clk, dds enable & ddsx select */ + + ret = iio_device_register(indio_dev); + if (ret) + goto failed3; + + dev_info(dev, "Analog Devices AD9122_DDS (0x%X) at 0x%08llX mapped" + " to 0x%p, probed DDS %s\n", + AD9122_DDS_IN(st->regs + AD9122_DDS_VERSION_ID), + (unsigned long long)phys_addr, st->regs, st->chip_info->name); + + return 0; /* success */ + +failed3: + iounmap(st->regs); +failed2: + release_mem_region(phys_addr, remap_size); +failed1: + put_device(st->dev_spi); + module_put(st->dev_spi->driver->owner); + dev_set_drvdata(dev, NULL); + iio_free_device(indio_dev); + + return ret; +} + +/** + * ad9122_dds_of_remove - unbinds the driver from the AIM device. + * @op: pointer to platform_device structure + * + * This function is called if a device is physically removed from the system or + * if the driver module is being unloaded. It frees any resources allocated to + * the device. + */ +static int __devexit ad9122_dds_of_remove(struct platform_device *op) +{ + struct device *dev = &op->dev; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad9122_dds_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + put_device(st->dev_spi); + module_put(st->dev_spi->driver->owner); + iounmap(st->regs); + release_mem_region(st->r_mem.start, resource_size(&st->r_mem)); + + iio_free_device(indio_dev); + dev_set_drvdata(dev, NULL); + + return 0; +} + +/* Match table for of_platform binding */ +static const struct of_device_id ad9122_dds_of_match[] __devinitconst = { + { .compatible = "xlnx,cf-ad9122-core-1.00.a", }, + { .compatible = "xlnx,cf-ad9739a-core-1.00.a", }, +{ /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, ad9122_dds_of_match); + +static struct platform_driver ad9122_dds_of_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = ad9122_dds_of_match, + }, + .probe = ad9122_dds_of_probe, + .remove = __devexit_p(ad9122_dds_of_remove), +}; + +static int __init ad9122_dds_init(void) +{ + return platform_driver_register(&ad9122_dds_of_driver); +} + +static void __exit ad9122_dds_cleanup(void) +{ + platform_driver_unregister(&ad9122_dds_of_driver); +} + +module_init(ad9122_dds_init); +module_exit(ad9122_dds_cleanup); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices DDS"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/frequency/cf_ad9122.h b/drivers/staging/iio/frequency/cf_ad9122.h new file mode 100644 index 0000000000000..6f84c00bea8a8 --- /dev/null +++ b/drivers/staging/iio/frequency/cf_ad9122.h @@ -0,0 +1,1151 @@ +/**************************************************************************** +* *************************************************************************** +* Rejeesh.Kutty@Analog.com (c) Analog Devices Inc. +* *************************************************************************** +* *************************************************************************** +* Address Map (AD9122) +* Address offset 0x00 +* [31: 0]: 0x00_01_00_61 +* Address offset 0x04 +* [ 8: 8]: dds clock enable (0x1) or disable (0x0). +* [ 7: 7]: dds-2b select dds-Xilinx(0x1) or dds-mem (0x0). +* [ 6: 6]: dds-2b enable (0x1) or disable (0x0). +* [ 5: 5]: dds-2a select dds-Xilinx(0x1) or dds-mem (0x0). +* [ 4: 4]: dds-2a enable (0x1) or disable (0x0). +* [ 3: 3]: dds-1b select dds-Xilinx(0x1) or dds-mem (0x0). +* [ 2: 2]: dds-1b enable (0x1) or disable (0x0). +* [ 1: 1]: dds-1a select dds-Xilinx(0x1) or dds-mem (0x0). +* [ 0: 0]: dds-1a enable (0x1) or disable (0x0). +* Address offset 0x08 +* [31:16]: dds-1a init (phase offset) count +* [15: 0]: dds-1a increment count +* Address offset 0x0c +* [31:16]: dds-1b init (phase offset) count +* [15: 0]: dds-1b increment count +* Address offset 0x10 +* [31:16]: dds-2a init (phase offset) count +* [15: 0]: dds-2a increment count +* Address offset 0x14 +* [31:16]: dds-2b init (phase offset) count +* [15: 0]: dds-2b increment count +* Address offset 0x18 +* [27:27]: dds mem select i/q (0 to 1). +* [26:26]: dds mem select a/b (0 to 1). +* [25:24]: dds mem sample select (0 to 2). +* [23:16]: dds mem write address +* [15: 0]: dds mem write data +* Address offset 0x20 (data = data >> scale) +* [15:12]: dds scale 2b +* [11: 8]: dds scale 2a +* [ 7: 4]: dds scale 1b +* [ 3: 0]: dds scale 1a +* ***************************************************************************/ + +#define AD9122_DDS_VERSION_ID 0x00 +#define AD9122_DDS_CTRL 0x04 +#define AD9122_DDS_1A_OUTPUT_CTRL 0x08 +#define AD9122_DDS_1B_OUTPUT_CTRL 0x0C +#define AD9122_DDS_2A_OUTPUT_CTRL 0x10 +#define AD9122_DDS_2B_OUTPUT_CTRL 0x14 +#define AD9122_DDS_MEM_CTRL 0x18 +#define AD9122_DDS_SCALE 0x20 + +#define AD9122_DDS_CTRL_DDS_CLK_EN (1 << 8) + + +/* AD9122 internal registers */ + +#define AD9122_I_PHASE_ADJ 0x39 +#define AD9122_Q_PHASE_ADJ 0x3B + +#define AD9122_I_DAC_OFFS 0x3D +#define AD9122_Q_DAC_OFFS 0x3F + +#define AD9122_I_DAC_FS_ADJ 0x41 +#define AD9122_Q_DAC_FS_ADJ 0x45 +#define AD9122_I_AUX_DAC 0x43 + + +/* IO accessors + */ +#define AD9122_DDS_OUT(addr, val) (iowrite32(val, addr)) +#define AD9122_DDS_IN(addr) (ioread32(addr)) + +enum { + ID_AD9122, + ID_AD9739A, +}; + +struct ad9122_dds_chip_info { + char name[8]; + struct iio_chan_spec channel[5]; +}; + +struct ad9122_dds_state { + struct list_head list; + struct device *dev_spi; + struct resource r_mem; /* IO mem resources */ + u16 int_vref_mv; + int irq; + void __iomem *regs; + unsigned int flags; + const struct ad9122_dds_chip_info *chip_info; + unsigned long dac_clk; +}; + +struct ad9122_converter { + struct spi_device *spi; + unsigned id; + int (*read)(struct spi_device *spi, unsigned reg); + int (*write)(struct spi_device *spi, + unsigned reg, unsigned val); + int (*setup)(struct spi_device *spi, unsigned mode); +}; + +static inline struct ad9122_converter *to_converter(struct device *dev) +{ + struct ad9122_converter *conv = spi_get_drvdata(to_spi_device(dev)); + + if (conv) + return conv; + + return ERR_PTR(-ENODEV); +}; + +#if defined(CF_AD9122_WAVDATA) +static u32 ad9122_ia_data[] = { + 0x7fff, 0xbf16, 0xedc8, + 0xfff4, 0xf0e1, 0xc479, + 0x8647, 0x4673, 0x1592, + 0x0059, 0x0c4a, 0x364b, + 0x7373, 0xb3de, 0xe6ce, + 0xff08, 0xf640, 0xcebe, + 0x92c7, 0x51ee, 0x1d0e, + 0x01e2, 0x077b, 0x2c64, + 0x6706, 0xa825, 0xded6, + 0xfce2, 0xfa7b, 0xd841, + 0x9f19, 0x5ddc, 0x257d, + 0x04a3, 0x03d6, 0x234c, + 0x5ad7, 0x9c0a, 0xd5f4, + 0xf988, 0xfd88, 0xe0ea, + 0xab1e, 0x6a1d, 0x2ecc, + 0x0894, 0x0163, 0x1b17, + 0x4f04, 0x8faa, 0xcc3e, + 0xf503, 0xff60, 0xe8a5, + 0xb6b9, 0x7695, 0x38e3, + 0x0dab, 0x0027, 0x13dc, + 0x43a9, 0x8323, 0xc1cd, + 0xef5d, 0xfffe, 0xef5d, + 0xc1cd, 0x8323, 0x43a9, + 0x13dc, 0x0027, 0x0dab, + 0x38e3, 0x7695, 0xb6b9, + 0xe8a5, 0xff60, 0xf503, + 0xcc3e, 0x8faa, 0x4f04, + 0x1b17, 0x0163, 0x0894, + 0x2ecc, 0x6a1d, 0xab1e, + 0xe0ea, 0xfd88, 0xf988, + 0xd5f4, 0x9c0a, 0x5ad7, + 0x234c, 0x03d6, 0x04a3, + 0x257d, 0x5ddc, 0x9f19, + 0xd841, 0xfa7b, 0xfce2, + 0xded6, 0xa825, 0x6706, + 0x2c64, 0x077b, 0x01e2, + 0x1d0e, 0x51ee, 0x92c7, + 0xcebe, 0xf640, 0xff08, + 0xe6ce, 0xb3de, 0x7373, + 0x364b, 0x0c4a, 0x0059, + 0x1592, 0x4673, 0x8647, + 0xc479, 0xf0e1, 0xfff4, + 0xedc8, 0xbf16, 0x7fff, + 0x40e8, 0x1236, 0x000a, + 0x0f1d, 0x3b85, 0x79b7, + 0xb98b, 0xea6c, 0xffa5, + 0xf3b4, 0xc9b3, 0x8c8b, + 0x4c20, 0x1930, 0x00f6, + 0x09be, 0x3140, 0x6d37, + 0xae10, 0xe2f0, 0xfe1c, + 0xf883, 0xd39a, 0x98f8, + 0x57d9, 0x2128, 0x031c, + 0x0583, 0x27bd, 0x60e5, + 0xa222, 0xda81, 0xfb5b, + 0xfc28, 0xdcb2, 0xa527, + 0x63f4, 0x2a0a, 0x0676, + 0x0276, 0x1f14, 0x54e0, + 0x95e1, 0xd132, 0xf76a, + 0xfe9b, 0xe4e7, 0xb0fa, + 0x7054, 0x33c0, 0x0afb, + 0x009e, 0x1759, 0x4945, + 0x8969, 0xc71b, 0xf253, + 0xffd7, 0xec22, 0xbc55, + 0x7cdb, 0x3e31, 0x10a1, + 0x0000, 0x10a1, 0x3e31, + 0x7cdb, 0xbc55, 0xec22, + 0xffd7, 0xf253, 0xc71b, + 0x8969, 0x4945, 0x1759, + 0x009e, 0x0afb, 0x33c0, + 0x7054, 0xb0fa, 0xe4e7, + 0xfe9b, 0xf76a, 0xd132, + 0x95e1, 0x54e0, 0x1f14, + 0x0276, 0x0676, 0x2a0a, + 0x63f4, 0xa527, 0xdcb2, + 0xfc28, 0xfb5b, 0xda81, + 0xa222, 0x60e5, 0x27bd, + 0x0583, 0x031c, 0x2128, + 0x57d9, 0x98f8, 0xd39a, + 0xf883, 0xfe1c, 0xe2f0, + 0xae10, 0x6d37, 0x3140, + 0x09be, 0x00f6, 0x1930, + 0x4c20, 0x8c8b, 0xc9b3, + 0xf3b4, 0xffa5, 0xea6c, + 0xb98b, 0x79b7, 0x3b85, + 0x0f1d, 0x000a, 0x1236, + 0x40e8, 0x7fff, 0xbf16, + 0xedc8, 0xfff4, 0xf0e1, + 0xc479, 0x8647, 0x4673, + 0x1592, 0x0059, 0x0c4a, + 0x364b, 0x7373, 0xb3de, + 0xe6ce, 0xff08, 0xf640, + 0xcebe, 0x92c7, 0x51ee, + 0x1d0e, 0x01e2, 0x077b, + 0x2c64, 0x6706, 0xa825, + 0xded6, 0xfce2, 0xfa7b, + 0xd841, 0x9f19, 0x5ddc, + 0x257d, 0x04a3, 0x03d6, + 0x234c, 0x5ad7, 0x9c0a, + 0xd5f4, 0xf988, 0xfd88, + 0xe0ea, 0xab1e, 0x6a1d, + 0x2ecc, 0x0894, 0x0163, + 0x1b17, 0x4f04, 0x8faa, + 0xcc3e, 0xf503, 0xff60, + 0xe8a5, 0xb6b9, 0x7695, + 0x38e3, 0x0dab, 0x0027, + 0x13dc, 0x43a9, 0x8323, + 0xc1cd, 0xef5d, 0xfffe, + 0xef5d, 0xc1cd, 0x8323, + 0x43a9, 0x13dc, 0x0027, + 0x0dab, 0x38e3, 0x7695, + 0xb6b9, 0xe8a5, 0xff60, + 0xf503, 0xcc3e, 0x8faa, + 0x4f04, 0x1b17, 0x0163, + 0x0894, 0x2ecc, 0x6a1d, + 0xab1e, 0xe0ea, 0xfd88, + 0xf988, 0xd5f4, 0x9c0a, + 0x5ad7, 0x234c, 0x03d6, + 0x04a3, 0x257d, 0x5ddc, + 0x9f19, 0xd841, 0xfa7b, + 0xfce2, 0xded6, 0xa825, + 0x6706, 0x2c64, 0x077b, + 0x01e2, 0x1d0e, 0x51ee, + 0x92c7, 0xcebe, 0xf640, + 0xff08, 0xe6ce, 0xb3de, + 0x7373, 0x364b, 0x0c4a, + 0x0059, 0x1592, 0x4673, + 0x8647, 0xc479, 0xf0e1, + 0xfff4, 0xedc8, 0xbf16, + 0x7fff, 0x40e8, 0x1236, + 0x000a, 0x0f1d, 0x3b85, + 0x79b7, 0xb98b, 0xea6c, + 0xffa5, 0xf3b4, 0xc9b3, + 0x8c8b, 0x4c20, 0x1930, + 0x00f6, 0x09be, 0x3140, + 0x6d37, 0xae10, 0xe2f0, + 0xfe1c, 0xf883, 0xd39a, + 0x98f8, 0x57d9, 0x2128, + 0x031c, 0x0583, 0x27bd, + 0x60e5, 0xa222, 0xda81, + 0xfb5b, 0xfc28, 0xdcb2, + 0xa527, 0x63f4, 0x2a0a, + 0x0676, 0x0276, 0x1f14, + 0x54e0, 0x95e1, 0xd132, + 0xf76a, 0xfe9b, 0xe4e7, + 0xb0fa, 0x7054, 0x33c0, + 0x0afb, 0x009e, 0x1759, + 0x4945, 0x8969, 0xc71b, + 0xf253, 0xffd7, 0xec22, + 0xbc55, 0x7cdb, 0x3e31, + 0x10a1, 0x0000, 0x10a1, + 0x3e31, 0x7cdb, 0xbc55, + 0xec22, 0xffd7, 0xf253, + 0xc71b, 0x8969, 0x4945, + 0x1759, 0x009e, 0x0afb, + 0x33c0, 0x7054, 0xb0fa, + 0xe4e7, 0xfe9b, 0xf76a, + 0xd132, 0x95e1, 0x54e0, + 0x1f14, 0x0276, 0x0676, + 0x2a0a, 0x63f4, 0xa527, + 0xdcb2, 0xfc28, 0xfb5b, + 0xda81, 0xa222, 0x60e5, + 0x27bd, 0x0583, 0x031c, + 0x2128, 0x57d9, 0x98f8, + 0xd39a, 0xf883, 0xfe1c, + 0xe2f0, 0xae10, 0x6d37, + 0x3140, 0x09be, 0x00f6, + 0x1930, 0x4c20, 0x8c8b, + 0xc9b3, 0xf3b4, 0xffa5, + 0xea6c, 0xb98b, 0x79b7, + 0x3b85, 0x0f1d, 0x000a, + 0x1236, 0x40e8, 0x7fff, + 0xbf16, 0xedc8, 0xfff4, + 0xf0e1, 0xc479, 0x8647, + 0x4673, 0x1592, 0x0059, + 0x0c4a, 0x364b, 0x7373, + 0xb3de, 0xe6ce, 0xff08, + 0xf640, 0xcebe, 0x92c7, + 0x51ee, 0x1d0e, 0x01e2, + 0x077b, 0x2c64, 0x6706, + 0xa825, 0xded6, 0xfce2, + 0xfa7b, 0xd841, 0x9f19, + 0x5ddc, 0x257d, 0x04a3, + 0x03d6, 0x234c, 0x5ad7, + 0x9c0a, 0xd5f4, 0xf988, + 0xfd88, 0xe0ea, 0xab1e, + 0x6a1d, 0x2ecc, 0x0894, + 0x0163, 0x1b17, 0x4f04, + 0x8faa, 0xcc3e, 0xf503, + 0xff60, 0xe8a5, 0xb6b9, + 0x7695, 0x38e3, 0x0dab, + 0x0027, 0x13dc, 0x43a9, + 0x8323, 0xc1cd, 0xef5d, + 0xfffe, 0xef5d, 0xc1cd, + 0x8323, 0x43a9, 0x13dc, + 0x0027, 0x0dab, 0x38e3, + 0x7695, 0xb6b9, 0xe8a5, + 0xff60, 0xf503, 0xcc3e, + 0x8faa, 0x4f04, 0x1b17, + 0x0163, 0x0894, 0x2ecc, + 0x6a1d, 0xab1e, 0xe0ea, + 0xfd88, 0xf988, 0xd5f4, + 0x9c0a, 0x5ad7, 0x234c, + 0x03d6, 0x04a3, 0x257d, + 0x5ddc, 0x9f19, 0xd841, + 0xfa7b, 0xfce2, 0xded6, + 0xa825, 0x6706, 0x2c64, + 0x077b, 0x01e2, 0x1d0e, + 0x51ee, 0x92c7, 0xcebe, + 0xf640, 0xff08, 0xe6ce, + 0xb3de, 0x7373, 0x364b, + 0x0c4a, 0x0059, 0x1592, + 0x4673, 0x8647, 0xc479, + 0xf0e1, 0xfff4, 0xedc8, + 0xbf16, 0x7fff, 0x40e8, + 0x1236, 0x000a, 0x0f1d, + 0x3b85, 0x79b7, 0xb98b, + 0xea6c, 0xffa5, 0xf3b4, + 0xc9b3, 0x8c8b, 0x4c20, + 0x1930, 0x00f6, 0x09be, + 0x3140, 0x6d37, 0xae10, + 0xe2f0, 0xfe1c, 0xf883, + 0xd39a, 0x98f8, 0x57d9, + 0x2128, 0x031c, 0x0583, + 0x27bd, 0x60e5, 0xa222, + 0xda81, 0xfb5b, 0xfc28, + 0xdcb2, 0xa527, 0x63f4, + 0x2a0a, 0x0676, 0x0276, + 0x1f14, 0x54e0, 0x95e1, + 0xd132, 0xf76a, 0xfe9b, + 0xe4e7, 0xb0fa, 0x7054, + 0x33c0, 0x0afb, 0x009e, + 0x1759, 0x4945, 0x8969, + 0xc71b, 0xf253, 0xffd7, + 0xec22, 0xbc55, 0x7cdb, + 0x3e31, 0x10a1, 0x0000, + 0x10a1, 0x3e31, 0x7cdb, + 0xbc55, 0xec22, 0xffd7, + 0xf253, 0xc71b, 0x8969, + 0x4945, 0x1759, 0x009e, + 0x0afb, 0x33c0, 0x7054, + 0xb0fa, 0xe4e7, 0xfe9b, + 0xf76a, 0xd132, 0x95e1, + 0x54e0, 0x1f14, 0x0276, + 0x0676, 0x2a0a, 0x63f4, + 0xa527, 0xdcb2, 0xfc28, + 0xfb5b, 0xda81, 0xa222, + 0x60e5, 0x27bd, 0x0583, + 0x031c, 0x2128, 0x57d9, + 0x98f8, 0xd39a, 0xf883, + 0xfe1c, 0xe2f0, 0xae10, + 0x6d37, 0x3140, 0x09be, + 0x00f6, 0x1930, 0x4c20, + 0x8c8b, 0xc9b3, 0xf3b4, + 0xffa5, 0xea6c, 0xb98b, + 0x79b7, 0x3b85, 0x0f1d, + 0x000a, 0x1236, 0x40e8 +}; + +static u32 ad9122_ib_data[] = { + 0x7fff, 0xbf16, 0xedc8, + 0xfff4, 0xf0e1, 0xc479, + 0x8647, 0x4673, 0x1592, + 0x0059, 0x0c4a, 0x364b, + 0x7373, 0xb3de, 0xe6ce, + 0xff08, 0xf640, 0xcebe, + 0x92c7, 0x51ee, 0x1d0e, + 0x01e2, 0x077b, 0x2c64, + 0x6706, 0xa825, 0xded6, + 0xfce2, 0xfa7b, 0xd841, + 0x9f19, 0x5ddc, 0x257d, + 0x04a3, 0x03d6, 0x234c, + 0x5ad7, 0x9c0a, 0xd5f4, + 0xf988, 0xfd88, 0xe0ea, + 0xab1e, 0x6a1d, 0x2ecc, + 0x0894, 0x0163, 0x1b17, + 0x4f04, 0x8faa, 0xcc3e, + 0xf503, 0xff60, 0xe8a5, + 0xb6b9, 0x7695, 0x38e3, + 0x0dab, 0x0027, 0x13dc, + 0x43a9, 0x8323, 0xc1cd, + 0xef5d, 0xfffe, 0xef5d, + 0xc1cd, 0x8323, 0x43a9, + 0x13dc, 0x0027, 0x0dab, + 0x38e3, 0x7695, 0xb6b9, + 0xe8a5, 0xff60, 0xf503, + 0xcc3e, 0x8faa, 0x4f04, + 0x1b17, 0x0163, 0x0894, + 0x2ecc, 0x6a1d, 0xab1e, + 0xe0ea, 0xfd88, 0xf988, + 0xd5f4, 0x9c0a, 0x5ad7, + 0x234c, 0x03d6, 0x04a3, + 0x257d, 0x5ddc, 0x9f19, + 0xd841, 0xfa7b, 0xfce2, + 0xded6, 0xa825, 0x6706, + 0x2c64, 0x077b, 0x01e2, + 0x1d0e, 0x51ee, 0x92c7, + 0xcebe, 0xf640, 0xff08, + 0xe6ce, 0xb3de, 0x7373, + 0x364b, 0x0c4a, 0x0059, + 0x1592, 0x4673, 0x8647, + 0xc479, 0xf0e1, 0xfff4, + 0xedc8, 0xbf16, 0x7fff, + 0x40e8, 0x1236, 0x000a, + 0x0f1d, 0x3b85, 0x79b7, + 0xb98b, 0xea6c, 0xffa5, + 0xf3b4, 0xc9b3, 0x8c8b, + 0x4c20, 0x1930, 0x00f6, + 0x09be, 0x3140, 0x6d37, + 0xae10, 0xe2f0, 0xfe1c, + 0xf883, 0xd39a, 0x98f8, + 0x57d9, 0x2128, 0x031c, + 0x0583, 0x27bd, 0x60e5, + 0xa222, 0xda81, 0xfb5b, + 0xfc28, 0xdcb2, 0xa527, + 0x63f4, 0x2a0a, 0x0676, + 0x0276, 0x1f14, 0x54e0, + 0x95e1, 0xd132, 0xf76a, + 0xfe9b, 0xe4e7, 0xb0fa, + 0x7054, 0x33c0, 0x0afb, + 0x009e, 0x1759, 0x4945, + 0x8969, 0xc71b, 0xf253, + 0xffd7, 0xec22, 0xbc55, + 0x7cdb, 0x3e31, 0x10a1, + 0x0000, 0x10a1, 0x3e31, + 0x7cdb, 0xbc55, 0xec22, + 0xffd7, 0xf253, 0xc71b, + 0x8969, 0x4945, 0x1759, + 0x009e, 0x0afb, 0x33c0, + 0x7054, 0xb0fa, 0xe4e7, + 0xfe9b, 0xf76a, 0xd132, + 0x95e1, 0x54e0, 0x1f14, + 0x0276, 0x0676, 0x2a0a, + 0x63f4, 0xa527, 0xdcb2, + 0xfc28, 0xfb5b, 0xda81, + 0xa222, 0x60e5, 0x27bd, + 0x0583, 0x031c, 0x2128, + 0x57d9, 0x98f8, 0xd39a, + 0xf883, 0xfe1c, 0xe2f0, + 0xae10, 0x6d37, 0x3140, + 0x09be, 0x00f6, 0x1930, + 0x4c20, 0x8c8b, 0xc9b3, + 0xf3b4, 0xffa5, 0xea6c, + 0xb98b, 0x79b7, 0x3b85, + 0x0f1d, 0x000a, 0x1236, + 0x40e8, 0x7fff, 0xbf16, + 0xedc8, 0xfff4, 0xf0e1, + 0xc479, 0x8647, 0x4673, + 0x1592, 0x0059, 0x0c4a, + 0x364b, 0x7373, 0xb3de, + 0xe6ce, 0xff08, 0xf640, + 0xcebe, 0x92c7, 0x51ee, + 0x1d0e, 0x01e2, 0x077b, + 0x2c64, 0x6706, 0xa825, + 0xded6, 0xfce2, 0xfa7b, + 0xd841, 0x9f19, 0x5ddc, + 0x257d, 0x04a3, 0x03d6, + 0x234c, 0x5ad7, 0x9c0a, + 0xd5f4, 0xf988, 0xfd88, + 0xe0ea, 0xab1e, 0x6a1d, + 0x2ecc, 0x0894, 0x0163, + 0x1b17, 0x4f04, 0x8faa, + 0xcc3e, 0xf503, 0xff60, + 0xe8a5, 0xb6b9, 0x7695, + 0x38e3, 0x0dab, 0x0027, + 0x13dc, 0x43a9, 0x8323, + 0xc1cd, 0xef5d, 0xfffe, + 0xef5d, 0xc1cd, 0x8323, + 0x43a9, 0x13dc, 0x0027, + 0x0dab, 0x38e3, 0x7695, + 0xb6b9, 0xe8a5, 0xff60, + 0xf503, 0xcc3e, 0x8faa, + 0x4f04, 0x1b17, 0x0163, + 0x0894, 0x2ecc, 0x6a1d, + 0xab1e, 0xe0ea, 0xfd88, + 0xf988, 0xd5f4, 0x9c0a, + 0x5ad7, 0x234c, 0x03d6, + 0x04a3, 0x257d, 0x5ddc, + 0x9f19, 0xd841, 0xfa7b, + 0xfce2, 0xded6, 0xa825, + 0x6706, 0x2c64, 0x077b, + 0x01e2, 0x1d0e, 0x51ee, + 0x92c7, 0xcebe, 0xf640, + 0xff08, 0xe6ce, 0xb3de, + 0x7373, 0x364b, 0x0c4a, + 0x0059, 0x1592, 0x4673, + 0x8647, 0xc479, 0xf0e1, + 0xfff4, 0xedc8, 0xbf16, + 0x7fff, 0x40e8, 0x1236, + 0x000a, 0x0f1d, 0x3b85, + 0x79b7, 0xb98b, 0xea6c, + 0xffa5, 0xf3b4, 0xc9b3, + 0x8c8b, 0x4c20, 0x1930, + 0x00f6, 0x09be, 0x3140, + 0x6d37, 0xae10, 0xe2f0, + 0xfe1c, 0xf883, 0xd39a, + 0x98f8, 0x57d9, 0x2128, + 0x031c, 0x0583, 0x27bd, + 0x60e5, 0xa222, 0xda81, + 0xfb5b, 0xfc28, 0xdcb2, + 0xa527, 0x63f4, 0x2a0a, + 0x0676, 0x0276, 0x1f14, + 0x54e0, 0x95e1, 0xd132, + 0xf76a, 0xfe9b, 0xe4e7, + 0xb0fa, 0x7054, 0x33c0, + 0x0afb, 0x009e, 0x1759, + 0x4945, 0x8969, 0xc71b, + 0xf253, 0xffd7, 0xec22, + 0xbc55, 0x7cdb, 0x3e31, + 0x10a1, 0x0000, 0x10a1, + 0x3e31, 0x7cdb, 0xbc55, + 0xec22, 0xffd7, 0xf253, + 0xc71b, 0x8969, 0x4945, + 0x1759, 0x009e, 0x0afb, + 0x33c0, 0x7054, 0xb0fa, + 0xe4e7, 0xfe9b, 0xf76a, + 0xd132, 0x95e1, 0x54e0, + 0x1f14, 0x0276, 0x0676, + 0x2a0a, 0x63f4, 0xa527, + 0xdcb2, 0xfc28, 0xfb5b, + 0xda81, 0xa222, 0x60e5, + 0x27bd, 0x0583, 0x031c, + 0x2128, 0x57d9, 0x98f8, + 0xd39a, 0xf883, 0xfe1c, + 0xe2f0, 0xae10, 0x6d37, + 0x3140, 0x09be, 0x00f6, + 0x1930, 0x4c20, 0x8c8b, + 0xc9b3, 0xf3b4, 0xffa5, + 0xea6c, 0xb98b, 0x79b7, + 0x3b85, 0x0f1d, 0x000a, + 0x1236, 0x40e8, 0x7fff, + 0xbf16, 0xedc8, 0xfff4, + 0xf0e1, 0xc479, 0x8647, + 0x4673, 0x1592, 0x0059, + 0x0c4a, 0x364b, 0x7373, + 0xb3de, 0xe6ce, 0xff08, + 0xf640, 0xcebe, 0x92c7, + 0x51ee, 0x1d0e, 0x01e2, + 0x077b, 0x2c64, 0x6706, + 0xa825, 0xded6, 0xfce2, + 0xfa7b, 0xd841, 0x9f19, + 0x5ddc, 0x257d, 0x04a3, + 0x03d6, 0x234c, 0x5ad7, + 0x9c0a, 0xd5f4, 0xf988, + 0xfd88, 0xe0ea, 0xab1e, + 0x6a1d, 0x2ecc, 0x0894, + 0x0163, 0x1b17, 0x4f04, + 0x8faa, 0xcc3e, 0xf503, + 0xff60, 0xe8a5, 0xb6b9, + 0x7695, 0x38e3, 0x0dab, + 0x0027, 0x13dc, 0x43a9, + 0x8323, 0xc1cd, 0xef5d, + 0xfffe, 0xef5d, 0xc1cd, + 0x8323, 0x43a9, 0x13dc, + 0x0027, 0x0dab, 0x38e3, + 0x7695, 0xb6b9, 0xe8a5, + 0xff60, 0xf503, 0xcc3e, + 0x8faa, 0x4f04, 0x1b17, + 0x0163, 0x0894, 0x2ecc, + 0x6a1d, 0xab1e, 0xe0ea, + 0xfd88, 0xf988, 0xd5f4, + 0x9c0a, 0x5ad7, 0x234c, + 0x03d6, 0x04a3, 0x257d, + 0x5ddc, 0x9f19, 0xd841, + 0xfa7b, 0xfce2, 0xded6, + 0xa825, 0x6706, 0x2c64, + 0x077b, 0x01e2, 0x1d0e, + 0x51ee, 0x92c7, 0xcebe, + 0xf640, 0xff08, 0xe6ce, + 0xb3de, 0x7373, 0x364b, + 0x0c4a, 0x0059, 0x1592, + 0x4673, 0x8647, 0xc479, + 0xf0e1, 0xfff4, 0xedc8, + 0xbf16, 0x7fff, 0x40e8, + 0x1236, 0x000a, 0x0f1d, + 0x3b85, 0x79b7, 0xb98b, + 0xea6c, 0xffa5, 0xf3b4, + 0xc9b3, 0x8c8b, 0x4c20, + 0x1930, 0x00f6, 0x09be, + 0x3140, 0x6d37, 0xae10, + 0xe2f0, 0xfe1c, 0xf883, + 0xd39a, 0x98f8, 0x57d9, + 0x2128, 0x031c, 0x0583, + 0x27bd, 0x60e5, 0xa222, + 0xda81, 0xfb5b, 0xfc28, + 0xdcb2, 0xa527, 0x63f4, + 0x2a0a, 0x0676, 0x0276, + 0x1f14, 0x54e0, 0x95e1, + 0xd132, 0xf76a, 0xfe9b, + 0xe4e7, 0xb0fa, 0x7054, + 0x33c0, 0x0afb, 0x009e, + 0x1759, 0x4945, 0x8969, + 0xc71b, 0xf253, 0xffd7, + 0xec22, 0xbc55, 0x7cdb, + 0x3e31, 0x10a1, 0x0000, + 0x10a1, 0x3e31, 0x7cdb, + 0xbc55, 0xec22, 0xffd7, + 0xf253, 0xc71b, 0x8969, + 0x4945, 0x1759, 0x009e, + 0x0afb, 0x33c0, 0x7054, + 0xb0fa, 0xe4e7, 0xfe9b, + 0xf76a, 0xd132, 0x95e1, + 0x54e0, 0x1f14, 0x0276, + 0x0676, 0x2a0a, 0x63f4, + 0xa527, 0xdcb2, 0xfc28, + 0xfb5b, 0xda81, 0xa222, + 0x60e5, 0x27bd, 0x0583, + 0x031c, 0x2128, 0x57d9, + 0x98f8, 0xd39a, 0xf883, + 0xfe1c, 0xe2f0, 0xae10, + 0x6d37, 0x3140, 0x09be, + 0x00f6, 0x1930, 0x4c20, + 0x8c8b, 0xc9b3, 0xf3b4, + 0xffa5, 0xea6c, 0xb98b, + 0x79b7, 0x3b85, 0x0f1d, + 0x000a, 0x1236, 0x40e8 +}; + +static u32 ad9122_qa_data[] = { + 0x0000, 0x10a1, 0x3e31, + 0x7cdb, 0xbc55, 0xec22, + 0xffd7, 0xf253, 0xc71b, + 0x8969, 0x4945, 0x1759, + 0x009e, 0x0afb, 0x33c0, + 0x7054, 0xb0fa, 0xe4e7, + 0xfe9b, 0xf76a, 0xd132, + 0x95e1, 0x54e0, 0x1f14, + 0x0276, 0x0676, 0x2a0a, + 0x63f4, 0xa527, 0xdcb2, + 0xfc28, 0xfb5b, 0xda81, + 0xa222, 0x60e5, 0x27bd, + 0x0583, 0x031c, 0x2128, + 0x57d9, 0x98f8, 0xd39a, + 0xf883, 0xfe1c, 0xe2f0, + 0xae10, 0x6d37, 0x3140, + 0x09be, 0x00f6, 0x1930, + 0x4c20, 0x8c8b, 0xc9b3, + 0xf3b4, 0xffa5, 0xea6c, + 0xb98b, 0x79b7, 0x3b85, + 0x0f1d, 0x000a, 0x1236, + 0x40e8, 0x7fff, 0xbf16, + 0xedc8, 0xfff4, 0xf0e1, + 0xc479, 0x8647, 0x4673, + 0x1592, 0x0059, 0x0c4a, + 0x364b, 0x7373, 0xb3de, + 0xe6ce, 0xff08, 0xf640, + 0xcebe, 0x92c7, 0x51ee, + 0x1d0e, 0x01e2, 0x077b, + 0x2c64, 0x6706, 0xa825, + 0xded6, 0xfce2, 0xfa7b, + 0xd841, 0x9f19, 0x5ddc, + 0x257d, 0x04a3, 0x03d6, + 0x234c, 0x5ad7, 0x9c0a, + 0xd5f4, 0xf988, 0xfd88, + 0xe0ea, 0xab1e, 0x6a1d, + 0x2ecc, 0x0894, 0x0163, + 0x1b17, 0x4f04, 0x8faa, + 0xcc3e, 0xf503, 0xff60, + 0xe8a5, 0xb6b9, 0x7695, + 0x38e3, 0x0dab, 0x0027, + 0x13dc, 0x43a9, 0x8323, + 0xc1cd, 0xef5d, 0xfffe, + 0xef5d, 0xc1cd, 0x8323, + 0x43a9, 0x13dc, 0x0027, + 0x0dab, 0x38e3, 0x7695, + 0xb6b9, 0xe8a5, 0xff60, + 0xf503, 0xcc3e, 0x8faa, + 0x4f04, 0x1b17, 0x0163, + 0x0894, 0x2ecc, 0x6a1d, + 0xab1e, 0xe0ea, 0xfd88, + 0xf988, 0xd5f4, 0x9c0a, + 0x5ad7, 0x234c, 0x03d6, + 0x04a3, 0x257d, 0x5ddc, + 0x9f19, 0xd841, 0xfa7b, + 0xfce2, 0xded6, 0xa825, + 0x6706, 0x2c64, 0x077b, + 0x01e2, 0x1d0e, 0x51ee, + 0x92c7, 0xcebe, 0xf640, + 0xff08, 0xe6ce, 0xb3de, + 0x7373, 0x364b, 0x0c4a, + 0x0059, 0x1592, 0x4673, + 0x8647, 0xc479, 0xf0e1, + 0xfff4, 0xedc8, 0xbf16, + 0x7fff, 0x40e8, 0x1236, + 0x000a, 0x0f1d, 0x3b85, + 0x79b7, 0xb98b, 0xea6c, + 0xffa5, 0xf3b4, 0xc9b3, + 0x8c8b, 0x4c20, 0x1930, + 0x00f6, 0x09be, 0x3140, + 0x6d37, 0xae10, 0xe2f0, + 0xfe1c, 0xf883, 0xd39a, + 0x98f8, 0x57d9, 0x2128, + 0x031c, 0x0583, 0x27bd, + 0x60e5, 0xa222, 0xda81, + 0xfb5b, 0xfc28, 0xdcb2, + 0xa527, 0x63f4, 0x2a0a, + 0x0676, 0x0276, 0x1f14, + 0x54e0, 0x95e1, 0xd132, + 0xf76a, 0xfe9b, 0xe4e7, + 0xb0fa, 0x7054, 0x33c0, + 0x0afb, 0x009e, 0x1759, + 0x4945, 0x8969, 0xc71b, + 0xf253, 0xffd7, 0xec22, + 0xbc55, 0x7cdb, 0x3e31, + 0x10a1, 0x0000, 0x10a1, + 0x3e31, 0x7cdb, 0xbc55, + 0xec22, 0xffd7, 0xf253, + 0xc71b, 0x8969, 0x4945, + 0x1759, 0x009e, 0x0afb, + 0x33c0, 0x7054, 0xb0fa, + 0xe4e7, 0xfe9b, 0xf76a, + 0xd132, 0x95e1, 0x54e0, + 0x1f14, 0x0276, 0x0676, + 0x2a0a, 0x63f4, 0xa527, + 0xdcb2, 0xfc28, 0xfb5b, + 0xda81, 0xa222, 0x60e5, + 0x27bd, 0x0583, 0x031c, + 0x2128, 0x57d9, 0x98f8, + 0xd39a, 0xf883, 0xfe1c, + 0xe2f0, 0xae10, 0x6d37, + 0x3140, 0x09be, 0x00f6, + 0x1930, 0x4c20, 0x8c8b, + 0xc9b3, 0xf3b4, 0xffa5, + 0xea6c, 0xb98b, 0x79b7, + 0x3b85, 0x0f1d, 0x000a, + 0x1236, 0x40e8, 0x7fff, + 0xbf16, 0xedc8, 0xfff4, + 0xf0e1, 0xc479, 0x8647, + 0x4673, 0x1592, 0x0059, + 0x0c4a, 0x364b, 0x7373, + 0xb3de, 0xe6ce, 0xff08, + 0xf640, 0xcebe, 0x92c7, + 0x51ee, 0x1d0e, 0x01e2, + 0x077b, 0x2c64, 0x6706, + 0xa825, 0xded6, 0xfce2, + 0xfa7b, 0xd841, 0x9f19, + 0x5ddc, 0x257d, 0x04a3, + 0x03d6, 0x234c, 0x5ad7, + 0x9c0a, 0xd5f4, 0xf988, + 0xfd88, 0xe0ea, 0xab1e, + 0x6a1d, 0x2ecc, 0x0894, + 0x0163, 0x1b17, 0x4f04, + 0x8faa, 0xcc3e, 0xf503, + 0xff60, 0xe8a5, 0xb6b9, + 0x7695, 0x38e3, 0x0dab, + 0x0027, 0x13dc, 0x43a9, + 0x8323, 0xc1cd, 0xef5d, + 0xfffe, 0xef5d, 0xc1cd, + 0x8323, 0x43a9, 0x13dc, + 0x0027, 0x0dab, 0x38e3, + 0x7695, 0xb6b9, 0xe8a5, + 0xff60, 0xf503, 0xcc3e, + 0x8faa, 0x4f04, 0x1b17, + 0x0163, 0x0894, 0x2ecc, + 0x6a1d, 0xab1e, 0xe0ea, + 0xfd88, 0xf988, 0xd5f4, + 0x9c0a, 0x5ad7, 0x234c, + 0x03d6, 0x04a3, 0x257d, + 0x5ddc, 0x9f19, 0xd841, + 0xfa7b, 0xfce2, 0xded6, + 0xa825, 0x6706, 0x2c64, + 0x077b, 0x01e2, 0x1d0e, + 0x51ee, 0x92c7, 0xcebe, + 0xf640, 0xff08, 0xe6ce, + 0xb3de, 0x7373, 0x364b, + 0x0c4a, 0x0059, 0x1592, + 0x4673, 0x8647, 0xc479, + 0xf0e1, 0xfff4, 0xedc8, + 0xbf16, 0x7fff, 0x40e8, + 0x1236, 0x000a, 0x0f1d, + 0x3b85, 0x79b7, 0xb98b, + 0xea6c, 0xffa5, 0xf3b4, + 0xc9b3, 0x8c8b, 0x4c20, + 0x1930, 0x00f6, 0x09be, + 0x3140, 0x6d37, 0xae10, + 0xe2f0, 0xfe1c, 0xf883, + 0xd39a, 0x98f8, 0x57d9, + 0x2128, 0x031c, 0x0583, + 0x27bd, 0x60e5, 0xa222, + 0xda81, 0xfb5b, 0xfc28, + 0xdcb2, 0xa527, 0x63f4, + 0x2a0a, 0x0676, 0x0276, + 0x1f14, 0x54e0, 0x95e1, + 0xd132, 0xf76a, 0xfe9b, + 0xe4e7, 0xb0fa, 0x7054, + 0x33c0, 0x0afb, 0x009e, + 0x1759, 0x4945, 0x8969, + 0xc71b, 0xf253, 0xffd7, + 0xec22, 0xbc55, 0x7cdb, + 0x3e31, 0x10a1, 0x0000, + 0x10a1, 0x3e31, 0x7cdb, + 0xbc55, 0xec22, 0xffd7, + 0xf253, 0xc71b, 0x8969, + 0x4945, 0x1759, 0x009e, + 0x0afb, 0x33c0, 0x7054, + 0xb0fa, 0xe4e7, 0xfe9b, + 0xf76a, 0xd132, 0x95e1, + 0x54e0, 0x1f14, 0x0276, + 0x0676, 0x2a0a, 0x63f4, + 0xa527, 0xdcb2, 0xfc28, + 0xfb5b, 0xda81, 0xa222, + 0x60e5, 0x27bd, 0x0583, + 0x031c, 0x2128, 0x57d9, + 0x98f8, 0xd39a, 0xf883, + 0xfe1c, 0xe2f0, 0xae10, + 0x6d37, 0x3140, 0x09be, + 0x00f6, 0x1930, 0x4c20, + 0x8c8b, 0xc9b3, 0xf3b4, + 0xffa5, 0xea6c, 0xb98b, + 0x79b7, 0x3b85, 0x0f1d, + 0x000a, 0x1236, 0x40e8, + 0x7fff, 0xbf16, 0xedc8, + 0xfff4, 0xf0e1, 0xc479, + 0x8647, 0x4673, 0x1592, + 0x0059, 0x0c4a, 0x364b, + 0x7373, 0xb3de, 0xe6ce, + 0xff08, 0xf640, 0xcebe, + 0x92c7, 0x51ee, 0x1d0e, + 0x01e2, 0x077b, 0x2c64, + 0x6706, 0xa825, 0xded6, + 0xfce2, 0xfa7b, 0xd841, + 0x9f19, 0x5ddc, 0x257d, + 0x04a3, 0x03d6, 0x234c, + 0x5ad7, 0x9c0a, 0xd5f4, + 0xf988, 0xfd88, 0xe0ea, + 0xab1e, 0x6a1d, 0x2ecc, + 0x0894, 0x0163, 0x1b17, + 0x4f04, 0x8faa, 0xcc3e, + 0xf503, 0xff60, 0xe8a5, + 0xb6b9, 0x7695, 0x38e3, + 0x0dab, 0x0027, 0x13dc, + 0x43a9, 0x8323, 0xc1cd, + 0xef5d, 0xfffe, 0xef5d, + 0xc1cd, 0x8323, 0x43a9, + 0x13dc, 0x0027, 0x0dab, + 0x38e3, 0x7695, 0xb6b9, + 0xe8a5, 0xff60, 0xf503, + 0xcc3e, 0x8faa, 0x4f04, + 0x1b17, 0x0163, 0x0894, + 0x2ecc, 0x6a1d, 0xab1e, + 0xe0ea, 0xfd88, 0xf988, + 0xd5f4, 0x9c0a, 0x5ad7, + 0x234c, 0x03d6, 0x04a3, + 0x257d, 0x5ddc, 0x9f19, + 0xd841, 0xfa7b, 0xfce2, + 0xded6, 0xa825, 0x6706, + 0x2c64, 0x077b, 0x01e2, + 0x1d0e, 0x51ee, 0x92c7, + 0xcebe, 0xf640, 0xff08, + 0xe6ce, 0xb3de, 0x7373, + 0x364b, 0x0c4a, 0x0059, + 0x1592, 0x4673, 0x8647, + 0xc479, 0xf0e1, 0xfff4, + 0xedc8, 0xbf16, 0x7fff, + 0x40e8, 0x1236, 0x000a, + 0x0f1d, 0x3b85, 0x79b7, + 0xb98b, 0xea6c, 0xffa5, + 0xf3b4, 0xc9b3, 0x8c8b, + 0x4c20, 0x1930, 0x00f6, + 0x09be, 0x3140, 0x6d37, + 0xae10, 0xe2f0, 0xfe1c, + 0xf883, 0xd39a, 0x98f8, + 0x57d9, 0x2128, 0x031c, + 0x0583, 0x27bd, 0x60e5, + 0xa222, 0xda81, 0xfb5b, + 0xfc28, 0xdcb2, 0xa527, + 0x63f4, 0x2a0a, 0x0676, + 0x0276, 0x1f14, 0x54e0, + 0x95e1, 0xd132, 0xf76a, + 0xfe9b, 0xe4e7, 0xb0fa, + 0x7054, 0x33c0, 0x0afb, + 0x009e, 0x1759, 0x4945, + 0x8969, 0xc71b, 0xf253, + 0xffd7, 0xec22, 0xbc55, + 0x7cdb, 0x3e31, 0x10a1 +}; + +static u32 ad9122_qb_data[] = { + 0x0000, 0x10a1, 0x3e31, + 0x7cdb, 0xbc55, 0xec22, + 0xffd7, 0xf253, 0xc71b, + 0x8969, 0x4945, 0x1759, + 0x009e, 0x0afb, 0x33c0, + 0x7054, 0xb0fa, 0xe4e7, + 0xfe9b, 0xf76a, 0xd132, + 0x95e1, 0x54e0, 0x1f14, + 0x0276, 0x0676, 0x2a0a, + 0x63f4, 0xa527, 0xdcb2, + 0xfc28, 0xfb5b, 0xda81, + 0xa222, 0x60e5, 0x27bd, + 0x0583, 0x031c, 0x2128, + 0x57d9, 0x98f8, 0xd39a, + 0xf883, 0xfe1c, 0xe2f0, + 0xae10, 0x6d37, 0x3140, + 0x09be, 0x00f6, 0x1930, + 0x4c20, 0x8c8b, 0xc9b3, + 0xf3b4, 0xffa5, 0xea6c, + 0xb98b, 0x79b7, 0x3b85, + 0x0f1d, 0x000a, 0x1236, + 0x40e8, 0x7fff, 0xbf16, + 0xedc8, 0xfff4, 0xf0e1, + 0xc479, 0x8647, 0x4673, + 0x1592, 0x0059, 0x0c4a, + 0x364b, 0x7373, 0xb3de, + 0xe6ce, 0xff08, 0xf640, + 0xcebe, 0x92c7, 0x51ee, + 0x1d0e, 0x01e2, 0x077b, + 0x2c64, 0x6706, 0xa825, + 0xded6, 0xfce2, 0xfa7b, + 0xd841, 0x9f19, 0x5ddc, + 0x257d, 0x04a3, 0x03d6, + 0x234c, 0x5ad7, 0x9c0a, + 0xd5f4, 0xf988, 0xfd88, + 0xe0ea, 0xab1e, 0x6a1d, + 0x2ecc, 0x0894, 0x0163, + 0x1b17, 0x4f04, 0x8faa, + 0xcc3e, 0xf503, 0xff60, + 0xe8a5, 0xb6b9, 0x7695, + 0x38e3, 0x0dab, 0x0027, + 0x13dc, 0x43a9, 0x8323, + 0xc1cd, 0xef5d, 0xfffe, + 0xef5d, 0xc1cd, 0x8323, + 0x43a9, 0x13dc, 0x0027, + 0x0dab, 0x38e3, 0x7695, + 0xb6b9, 0xe8a5, 0xff60, + 0xf503, 0xcc3e, 0x8faa, + 0x4f04, 0x1b17, 0x0163, + 0x0894, 0x2ecc, 0x6a1d, + 0xab1e, 0xe0ea, 0xfd88, + 0xf988, 0xd5f4, 0x9c0a, + 0x5ad7, 0x234c, 0x03d6, + 0x04a3, 0x257d, 0x5ddc, + 0x9f19, 0xd841, 0xfa7b, + 0xfce2, 0xded6, 0xa825, + 0x6706, 0x2c64, 0x077b, + 0x01e2, 0x1d0e, 0x51ee, + 0x92c7, 0xcebe, 0xf640, + 0xff08, 0xe6ce, 0xb3de, + 0x7373, 0x364b, 0x0c4a, + 0x0059, 0x1592, 0x4673, + 0x8647, 0xc479, 0xf0e1, + 0xfff4, 0xedc8, 0xbf16, + 0x7fff, 0x40e8, 0x1236, + 0x000a, 0x0f1d, 0x3b85, + 0x79b7, 0xb98b, 0xea6c, + 0xffa5, 0xf3b4, 0xc9b3, + 0x8c8b, 0x4c20, 0x1930, + 0x00f6, 0x09be, 0x3140, + 0x6d37, 0xae10, 0xe2f0, + 0xfe1c, 0xf883, 0xd39a, + 0x98f8, 0x57d9, 0x2128, + 0x031c, 0x0583, 0x27bd, + 0x60e5, 0xa222, 0xda81, + 0xfb5b, 0xfc28, 0xdcb2, + 0xa527, 0x63f4, 0x2a0a, + 0x0676, 0x0276, 0x1f14, + 0x54e0, 0x95e1, 0xd132, + 0xf76a, 0xfe9b, 0xe4e7, + 0xb0fa, 0x7054, 0x33c0, + 0x0afb, 0x009e, 0x1759, + 0x4945, 0x8969, 0xc71b, + 0xf253, 0xffd7, 0xec22, + 0xbc55, 0x7cdb, 0x3e31, + 0x10a1, 0x0000, 0x10a1, + 0x3e31, 0x7cdb, 0xbc55, + 0xec22, 0xffd7, 0xf253, + 0xc71b, 0x8969, 0x4945, + 0x1759, 0x009e, 0x0afb, + 0x33c0, 0x7054, 0xb0fa, + 0xe4e7, 0xfe9b, 0xf76a, + 0xd132, 0x95e1, 0x54e0, + 0x1f14, 0x0276, 0x0676, + 0x2a0a, 0x63f4, 0xa527, + 0xdcb2, 0xfc28, 0xfb5b, + 0xda81, 0xa222, 0x60e5, + 0x27bd, 0x0583, 0x031c, + 0x2128, 0x57d9, 0x98f8, + 0xd39a, 0xf883, 0xfe1c, + 0xe2f0, 0xae10, 0x6d37, + 0x3140, 0x09be, 0x00f6, + 0x1930, 0x4c20, 0x8c8b, + 0xc9b3, 0xf3b4, 0xffa5, + 0xea6c, 0xb98b, 0x79b7, + 0x3b85, 0x0f1d, 0x000a, + 0x1236, 0x40e8, 0x7fff, + 0xbf16, 0xedc8, 0xfff4, + 0xf0e1, 0xc479, 0x8647, + 0x4673, 0x1592, 0x0059, + 0x0c4a, 0x364b, 0x7373, + 0xb3de, 0xe6ce, 0xff08, + 0xf640, 0xcebe, 0x92c7, + 0x51ee, 0x1d0e, 0x01e2, + 0x077b, 0x2c64, 0x6706, + 0xa825, 0xded6, 0xfce2, + 0xfa7b, 0xd841, 0x9f19, + 0x5ddc, 0x257d, 0x04a3, + 0x03d6, 0x234c, 0x5ad7, + 0x9c0a, 0xd5f4, 0xf988, + 0xfd88, 0xe0ea, 0xab1e, + 0x6a1d, 0x2ecc, 0x0894, + 0x0163, 0x1b17, 0x4f04, + 0x8faa, 0xcc3e, 0xf503, + 0xff60, 0xe8a5, 0xb6b9, + 0x7695, 0x38e3, 0x0dab, + 0x0027, 0x13dc, 0x43a9, + 0x8323, 0xc1cd, 0xef5d, + 0xfffe, 0xef5d, 0xc1cd, + 0x8323, 0x43a9, 0x13dc, + 0x0027, 0x0dab, 0x38e3, + 0x7695, 0xb6b9, 0xe8a5, + 0xff60, 0xf503, 0xcc3e, + 0x8faa, 0x4f04, 0x1b17, + 0x0163, 0x0894, 0x2ecc, + 0x6a1d, 0xab1e, 0xe0ea, + 0xfd88, 0xf988, 0xd5f4, + 0x9c0a, 0x5ad7, 0x234c, + 0x03d6, 0x04a3, 0x257d, + 0x5ddc, 0x9f19, 0xd841, + 0xfa7b, 0xfce2, 0xded6, + 0xa825, 0x6706, 0x2c64, + 0x077b, 0x01e2, 0x1d0e, + 0x51ee, 0x92c7, 0xcebe, + 0xf640, 0xff08, 0xe6ce, + 0xb3de, 0x7373, 0x364b, + 0x0c4a, 0x0059, 0x1592, + 0x4673, 0x8647, 0xc479, + 0xf0e1, 0xfff4, 0xedc8, + 0xbf16, 0x7fff, 0x40e8, + 0x1236, 0x000a, 0x0f1d, + 0x3b85, 0x79b7, 0xb98b, + 0xea6c, 0xffa5, 0xf3b4, + 0xc9b3, 0x8c8b, 0x4c20, + 0x1930, 0x00f6, 0x09be, + 0x3140, 0x6d37, 0xae10, + 0xe2f0, 0xfe1c, 0xf883, + 0xd39a, 0x98f8, 0x57d9, + 0x2128, 0x031c, 0x0583, + 0x27bd, 0x60e5, 0xa222, + 0xda81, 0xfb5b, 0xfc28, + 0xdcb2, 0xa527, 0x63f4, + 0x2a0a, 0x0676, 0x0276, + 0x1f14, 0x54e0, 0x95e1, + 0xd132, 0xf76a, 0xfe9b, + 0xe4e7, 0xb0fa, 0x7054, + 0x33c0, 0x0afb, 0x009e, + 0x1759, 0x4945, 0x8969, + 0xc71b, 0xf253, 0xffd7, + 0xec22, 0xbc55, 0x7cdb, + 0x3e31, 0x10a1, 0x0000, + 0x10a1, 0x3e31, 0x7cdb, + 0xbc55, 0xec22, 0xffd7, + 0xf253, 0xc71b, 0x8969, + 0x4945, 0x1759, 0x009e, + 0x0afb, 0x33c0, 0x7054, + 0xb0fa, 0xe4e7, 0xfe9b, + 0xf76a, 0xd132, 0x95e1, + 0x54e0, 0x1f14, 0x0276, + 0x0676, 0x2a0a, 0x63f4, + 0xa527, 0xdcb2, 0xfc28, + 0xfb5b, 0xda81, 0xa222, + 0x60e5, 0x27bd, 0x0583, + 0x031c, 0x2128, 0x57d9, + 0x98f8, 0xd39a, 0xf883, + 0xfe1c, 0xe2f0, 0xae10, + 0x6d37, 0x3140, 0x09be, + 0x00f6, 0x1930, 0x4c20, + 0x8c8b, 0xc9b3, 0xf3b4, + 0xffa5, 0xea6c, 0xb98b, + 0x79b7, 0x3b85, 0x0f1d, + 0x000a, 0x1236, 0x40e8, + 0x7fff, 0xbf16, 0xedc8, + 0xfff4, 0xf0e1, 0xc479, + 0x8647, 0x4673, 0x1592, + 0x0059, 0x0c4a, 0x364b, + 0x7373, 0xb3de, 0xe6ce, + 0xff08, 0xf640, 0xcebe, + 0x92c7, 0x51ee, 0x1d0e, + 0x01e2, 0x077b, 0x2c64, + 0x6706, 0xa825, 0xded6, + 0xfce2, 0xfa7b, 0xd841, + 0x9f19, 0x5ddc, 0x257d, + 0x04a3, 0x03d6, 0x234c, + 0x5ad7, 0x9c0a, 0xd5f4, + 0xf988, 0xfd88, 0xe0ea, + 0xab1e, 0x6a1d, 0x2ecc, + 0x0894, 0x0163, 0x1b17, + 0x4f04, 0x8faa, 0xcc3e, + 0xf503, 0xff60, 0xe8a5, + 0xb6b9, 0x7695, 0x38e3, + 0x0dab, 0x0027, 0x13dc, + 0x43a9, 0x8323, 0xc1cd, + 0xef5d, 0xfffe, 0xef5d, + 0xc1cd, 0x8323, 0x43a9, + 0x13dc, 0x0027, 0x0dab, + 0x38e3, 0x7695, 0xb6b9, + 0xe8a5, 0xff60, 0xf503, + 0xcc3e, 0x8faa, 0x4f04, + 0x1b17, 0x0163, 0x0894, + 0x2ecc, 0x6a1d, 0xab1e, + 0xe0ea, 0xfd88, 0xf988, + 0xd5f4, 0x9c0a, 0x5ad7, + 0x234c, 0x03d6, 0x04a3, + 0x257d, 0x5ddc, 0x9f19, + 0xd841, 0xfa7b, 0xfce2, + 0xded6, 0xa825, 0x6706, + 0x2c64, 0x077b, 0x01e2, + 0x1d0e, 0x51ee, 0x92c7, + 0xcebe, 0xf640, 0xff08, + 0xe6ce, 0xb3de, 0x7373, + 0x364b, 0x0c4a, 0x0059, + 0x1592, 0x4673, 0x8647, + 0xc479, 0xf0e1, 0xfff4, + 0xedc8, 0xbf16, 0x7fff, + 0x40e8, 0x1236, 0x000a, + 0x0f1d, 0x3b85, 0x79b7, + 0xb98b, 0xea6c, 0xffa5, + 0xf3b4, 0xc9b3, 0x8c8b, + 0x4c20, 0x1930, 0x00f6, + 0x09be, 0x3140, 0x6d37, + 0xae10, 0xe2f0, 0xfe1c, + 0xf883, 0xd39a, 0x98f8, + 0x57d9, 0x2128, 0x031c, + 0x0583, 0x27bd, 0x60e5, + 0xa222, 0xda81, 0xfb5b, + 0xfc28, 0xdcb2, 0xa527, + 0x63f4, 0x2a0a, 0x0676, + 0x0276, 0x1f14, 0x54e0, + 0x95e1, 0xd132, 0xf76a, + 0xfe9b, 0xe4e7, 0xb0fa, + 0x7054, 0x33c0, 0x0afb, + 0x009e, 0x1759, 0x4945, + 0x8969, 0xc71b, 0xf253, + 0xffd7, 0xec22, 0xbc55, + 0x7cdb, 0x3e31, 0x10a1 +}; +#endif From 24be9558314799b43dd410a09f9fd815c91f51af Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 9 Mar 2012 13:42:54 +0100 Subject: [PATCH 114/261] iio: frequency: New driver for Analog Devices ADF4350/ADF4351 Wideband Synthesizers Signed-off-by: Michael Hennerich --- drivers/staging/iio/frequency/Kconfig | 18 + drivers/staging/iio/frequency/Makefile | 1 + drivers/staging/iio/frequency/adf4350.c | 503 ++++++++++++++++++++++++ drivers/staging/iio/frequency/adf4350.h | 122 ++++++ 4 files changed, 644 insertions(+) create mode 100644 drivers/staging/iio/frequency/adf4350.c create mode 100644 drivers/staging/iio/frequency/adf4350.h diff --git a/drivers/staging/iio/frequency/Kconfig b/drivers/staging/iio/frequency/Kconfig index f735cb97acb42..ba94957801311 100644 --- a/drivers/staging/iio/frequency/Kconfig +++ b/drivers/staging/iio/frequency/Kconfig @@ -91,5 +91,23 @@ config AD9122_CF_DAC Say yes here to build support for Analog Devices AD9122 DAC chip ad9122, provides direct access via sysfs. +endmenu + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# + +menu "Phase-Locked Loop (PLL) frequency synthesizers" + +config ADF4350 + tristate "Analog Devices ADF4350/ADF4351 Wideband Synthesizers" + depends on SPI + help + Say yes here to build support for Analog Devices ADF4350/ADF4351 + Wideband Synthesizers. The driver provides direct access via sysfs. + + To compile this driver as a module, choose M here: the + module will be called adf4350. + endmenu endmenu diff --git a/drivers/staging/iio/frequency/Makefile b/drivers/staging/iio/frequency/Makefile index c02528196b44a..364c240e78c2e 100644 --- a/drivers/staging/iio/frequency/Makefile +++ b/drivers/staging/iio/frequency/Makefile @@ -10,5 +10,6 @@ obj-$(CONFIG_AD9850) += ad9850.o obj-$(CONFIG_AD9852) += ad9852.o obj-$(CONFIG_AD9910) += ad9910.o obj-$(CONFIG_AD9951) += ad9951.o +obj-$(CONFIG_ADF4350) += adf4350.o obj-$(CONFIG_AD9122_CF) += cf_ad9122.o obj-$(CONFIG_AD9122_CF_DAC) += ad9122.o diff --git a/drivers/staging/iio/frequency/adf4350.c b/drivers/staging/iio/frequency/adf4350.c new file mode 100644 index 0000000000000..17df1b7c0c158 --- /dev/null +++ b/drivers/staging/iio/frequency/adf4350.c @@ -0,0 +1,503 @@ +/* + * ADF4350/ADF4351 SPI Wideband Synthesizer driver + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +#include "adf4350.h" + +enum { + ADF4350_SET_FREQ, + ADF4350_SET_FREQ_REFIN, + ADF4350_SET_FREQ_RESOLUTION, + ADF4350_PLL_LOCKED, + ADF4350_PLL_PWRDOWN, +}; + +struct adf4350_state { + struct spi_device *spi; + struct regulator *reg; + struct adf4350_platform_data *pdata; + unsigned long clkin; + unsigned long chspc; /* Channel Spacing */ + unsigned long fpfd; /* Phase Frequency Detector */ + unsigned long min_out_freq; + unsigned r0_fract; + unsigned r0_int; + unsigned r1_mod; + unsigned r4_rf_div_sel; + unsigned long regs[6]; + unsigned long regs_hw[6]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + __be32 val ____cacheline_aligned; +}; + +static struct adf4350_platform_data default_pdata = { + .clkin = 122880000, + .channel_spacing = 10000, + .r2_user_settings = ADF4350_REG2_PD_POLARITY_POS, + ADF4350_REG2_CHARGE_PUMP_CURR_uA(2500), + .r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0), + .r4_user_settings = ADF4350_REG4_OUTPUT_PWR(0) | + ADF4350_REG4_MUTE_TILL_LOCK_EN, + .gpio_lock_detect = -1, +}; + +static int adf4350_sync_config(struct adf4350_state *st) +{ + int ret, i, doublebuf = 0; + + for (i = ADF4350_REG5; i >= ADF4350_REG0; i--) { + if ((st->regs_hw[i] != st->regs[i]) || + ((i == ADF4350_REG0) && doublebuf)) { + + switch (i) { + case ADF4350_REG1: + case ADF4350_REG4: + doublebuf = 1; + break; + } + + st->val = cpu_to_be32(st->regs[i] | i); + ret = spi_write(st->spi, &st->val, 4); + if (ret < 0) + return ret; + st->regs_hw[i] = st->regs[i]; + dev_dbg(&st->spi->dev, "[%d] 0x%X\n", + i, (u32)st->regs[i] | i); + } + } + return 0; +} + +static int adf4350_reg_access(struct iio_dev *indio_dev, + unsigned reg, unsigned writeval, + unsigned *readval) +{ + struct adf4350_state *st = iio_priv(indio_dev); + int ret; + + if (reg > ADF4350_REG5) + return -EINVAL; + + mutex_lock(&indio_dev->mlock); + if (readval == NULL) { + st->regs[reg] = writeval & ~(BIT(0) | BIT(1) | BIT(2)); + ret = adf4350_sync_config(st); + } else { + *readval = st->regs_hw[reg]; + ret = 0; + } + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int adf4350_tune_r_cnt(struct adf4350_state *st, unsigned short r_cnt) +{ + struct adf4350_platform_data *pdata = st->pdata; + + do { + r_cnt++; + st->fpfd = (st->clkin * (pdata->ref_doubler_en ? 2 : 1)) / + (r_cnt * (pdata->ref_div2_en ? 2 : 1)); + } while (st->fpfd > ADF4350_MAX_FREQ_PFD); + + return r_cnt; +} + +static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) +{ + struct adf4350_platform_data *pdata = st->pdata; + u64 tmp; + u32 div_gcd, prescaler; + u16 mdiv, r_cnt = 0; + u8 band_sel_div; + + if (freq > ADF4350_MAX_OUT_FREQ || freq < st->min_out_freq) + return -EINVAL; + + if (freq > ADF4350_MAX_FREQ_45_PRESC) { + prescaler = ADF4350_REG1_PRESCALER; + mdiv = 75; + } else { + prescaler = 0; + mdiv = 23; + } + + st->r4_rf_div_sel = 0; + + while (freq < ADF4350_MIN_VCO_FREQ) { + freq <<= 1; + st->r4_rf_div_sel++; + } + + /* + * Allow a predefined reference division factor + * if not set, compute our own + */ + if (pdata->ref_div_factor) + r_cnt = pdata->ref_div_factor - 1; + + do { + r_cnt = adf4350_tune_r_cnt(st, r_cnt); + + st->r1_mod = st->fpfd / st->chspc; + while (st->r1_mod > ADF4350_MAX_MODULUS) { + r_cnt = adf4350_tune_r_cnt(st, r_cnt); + st->r1_mod = st->fpfd / st->chspc; + } + + tmp = freq * (u64)st->r1_mod + (st->fpfd > 1); + do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */ + st->r0_fract = do_div(tmp, st->r1_mod); + st->r0_int = tmp; + } while (mdiv > st->r0_int); + + band_sel_div = DIV_ROUND_UP(st->fpfd, ADF4350_MAX_BANDSEL_CLK); + + if (st->r0_fract && st->r1_mod) { + div_gcd = gcd(st->r1_mod, st->r0_fract); + st->r1_mod /= div_gcd; + st->r0_fract /= div_gcd; + } else { + st->r0_fract = 0; + st->r1_mod = 1; + } + + dev_dbg(&st->spi->dev, "VCO: %llu Hz, PFD %lu Hz\n" + "REF_DIV %d, R0_INT %d, R0_FRACT %d\n" + "R1_MOD %d, RF_DIV %d\nPRESCALER %s, BAND_SEL_DIV %d\n", + freq, st->fpfd, r_cnt, st->r0_int, st->r0_fract, st->r1_mod, + 1 << st->r4_rf_div_sel, prescaler ? "8/9" : "4/5", + band_sel_div); + + st->regs[ADF4350_REG0] = ADF4350_REG0_INT(st->r0_int) | + ADF4350_REG0_FRACT(st->r0_fract); + + st->regs[ADF4350_REG1] = ADF4350_REG1_PHASE(0) | + ADF4350_REG1_MOD(st->r1_mod) | + prescaler; + + st->regs[ADF4350_REG2] = + ADF4350_REG2_10BIT_R_CNT(r_cnt) | + ADF4350_REG2_DOUBLE_BUFF_EN | + (pdata->ref_doubler_en ? ADF4350_REG2_RMULT2_EN : 0) | + (pdata->ref_div2_en ? ADF4350_REG2_RDIV2_EN : 0) | + (pdata->r2_user_settings & (ADF4350_REG2_PD_POLARITY_POS | + ADF4350_REG2_LDP_6ns | ADF4350_REG2_LDF_INT_N | + ADF4350_REG2_CHARGE_PUMP_CURR_uA(5000) | + ADF4350_REG2_MUXOUT(0x7) | ADF4350_REG2_NOISE_MODE(0x9))); + + st->regs[ADF4350_REG3] = pdata->r3_user_settings & + (ADF4350_REG3_12BIT_CLKDIV(0xFFF) | + ADF4350_REG3_12BIT_CLKDIV_MODE(0x3) | + ADF4350_REG3_12BIT_CSR_EN | + ADF4351_REG3_CHARGE_CANCELLATION_EN | + ADF4351_REG3_ANTI_BACKLASH_3ns_EN | + ADF4351_REG3_BAND_SEL_CLOCK_MODE_HIGH); + + st->regs[ADF4350_REG4] = + ADF4350_REG4_FEEDBACK_FUND | + ADF4350_REG4_RF_DIV_SEL(st->r4_rf_div_sel) | + ADF4350_REG4_8BIT_BAND_SEL_CLKDIV(band_sel_div) | + ADF4350_REG4_RF_OUT_EN | + (pdata->r4_user_settings & + (ADF4350_REG4_OUTPUT_PWR(0x3) | + ADF4350_REG4_AUX_OUTPUT_PWR(0x3) | + ADF4350_REG4_AUX_OUTPUT_EN | + ADF4350_REG4_AUX_OUTPUT_FUND | + ADF4350_REG4_MUTE_TILL_LOCK_EN)); + + st->regs[ADF4350_REG5] = ADF4350_REG5_LD_PIN_MODE_DIGITAL; + + return adf4350_sync_config(st); +} + +static ssize_t adf4350_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adf4350_state *st = iio_priv(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + unsigned long long readin; + int ret; + + ret = kstrtoull(buf, 10, &readin); + if (ret) + return ret; + + mutex_lock(&indio_dev->mlock); + switch ((u32)this_attr->address) { + case ADF4350_SET_FREQ: + ret = adf4350_set_freq(st, readin); + break; + case ADF4350_SET_FREQ_REFIN: + if (readin > ADF4350_MAX_FREQ_REFIN) + ret = -EINVAL; + else + st->clkin = readin; + break; + case ADF4350_SET_FREQ_RESOLUTION: + if (readin == 0) + ret = -EINVAL; + else + st->chspc = readin; + break; + case ADF4350_PLL_PWRDOWN: + if (readin) + st->regs[ADF4350_REG2] |= ADF4350_REG2_POWER_DOWN_EN; + else + st->regs[ADF4350_REG2] &= ~ADF4350_REG2_POWER_DOWN_EN; + + adf4350_sync_config(st); + break; + default: + ret = -ENODEV; + } + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static ssize_t adf4350_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adf4350_state *st = iio_priv(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + unsigned long long val; + int ret = 0; + + mutex_lock(&indio_dev->mlock); + switch ((u32)this_attr->address) { + case ADF4350_SET_FREQ: + val = (u64)((st->r0_int * st->r1_mod) + st->r0_fract) * + (u64)st->fpfd; + do_div(val, st->r1_mod * (1 << st->r4_rf_div_sel)); + break; + case ADF4350_SET_FREQ_REFIN: + val = st->clkin; + break; + case ADF4350_SET_FREQ_RESOLUTION: + val = st->chspc; + break; + case ADF4350_PLL_LOCKED: + if (gpio_is_valid(st->pdata->gpio_lock_detect)) + val = gpio_get_value(st->pdata->gpio_lock_detect); + else + ret = -ENODEV; + break; + case ADF4350_PLL_PWRDOWN: + val = !!(st->regs[ADF4350_REG2] & ADF4350_REG2_POWER_DOWN_EN); + break; + } + mutex_unlock(&indio_dev->mlock); + + return ret < 0 ? ret : sprintf(buf, "%llu\n", val); +} + +static IIO_DEVICE_ATTR(out_pll0_freq, S_IRUGO | S_IWUSR, + adf4350_show, + adf4350_store, + ADF4350_SET_FREQ); + +static IIO_DEVICE_ATTR(out_pll0_refin_freq, S_IRUGO | S_IWUSR, + adf4350_show, + adf4350_store, + ADF4350_SET_FREQ_REFIN); + +static IIO_DEVICE_ATTR(out_pll0_freq_resolution, S_IRUGO | S_IWUSR, + adf4350_show, + adf4350_store, + ADF4350_SET_FREQ_RESOLUTION); + +static IIO_DEVICE_ATTR(out_pll0_locked, S_IRUGO, + adf4350_show, + NULL, + ADF4350_PLL_LOCKED); + +static IIO_DEVICE_ATTR(out_pll0_powerdown, S_IRUGO | S_IWUSR, + adf4350_show, + adf4350_store, + ADF4350_PLL_PWRDOWN); + +static struct attribute *adf4350_attributes[] = { + &iio_dev_attr_out_pll0_freq.dev_attr.attr, + &iio_dev_attr_out_pll0_refin_freq.dev_attr.attr, + &iio_dev_attr_out_pll0_freq_resolution.dev_attr.attr, + &iio_dev_attr_out_pll0_locked.dev_attr.attr, + &iio_dev_attr_out_pll0_powerdown.dev_attr.attr, + NULL, +}; + +static const struct attribute_group adf4350_attribute_group = { + .attrs = adf4350_attributes, +}; + +static const struct iio_info adf4350_info = { + .attrs = &adf4350_attribute_group, + .debugfs_reg_access = &adf4350_reg_access, + .driver_module = THIS_MODULE, +}; + +static int __devinit adf4350_probe(struct spi_device *spi) +{ + struct adf4350_platform_data *pdata = spi->dev.platform_data; + struct iio_dev *indio_dev; + struct adf4350_state *st; + int ret; + + if (!pdata) { + dev_warn(&spi->dev, "no platform data? using default\n");/*FIXME*/ + pdata = &default_pdata; + } + + indio_dev = iio_allocate_device(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + + st->reg = regulator_get(&spi->dev, "vcc"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) + goto error_put_reg; + } + + spi_set_drvdata(spi, indio_dev); + st->spi = spi; + st->pdata = pdata; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = (pdata->name[0] != 0) ? pdata->name : spi_get_device_id(spi)->name; + + printk("%s: %d::: %s %s\n",__func__,__LINE__, pdata->name, spi_get_device_id(spi)->name); + indio_dev->info = &adf4350_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + st->chspc = pdata->channel_spacing; + st->clkin = pdata->clkin; + + st->min_out_freq = spi_get_device_id(spi)->driver_data == 4351 ? + ADF4351_MIN_OUT_FREQ : ADF4350_MIN_OUT_FREQ; + + memset(st->regs_hw, 0xFF, sizeof(st->regs_hw)); + + if (gpio_is_valid(pdata->gpio_lock_detect)) { + ret = gpio_request(pdata->gpio_lock_detect, indio_dev->name); + if (ret) { + dev_err(&spi->dev, "fail to request lock detect GPIO-%d", + pdata->gpio_lock_detect); + goto error_disable_reg; + } + gpio_direction_input(pdata->gpio_lock_detect); + } + + if (pdata->power_up_frequency) { + ret = adf4350_set_freq(st, pdata->power_up_frequency); + if (ret) + goto error_free_gpio; + } + + ret = iio_device_register(indio_dev); + if (ret) + goto error_free_gpio; + + return 0; + +error_free_gpio: + if (gpio_is_valid(pdata->gpio_lock_detect)) + gpio_free(pdata->gpio_lock_detect); + +error_disable_reg: + if (!IS_ERR(st->reg)) + regulator_disable(st->reg); +error_put_reg: + if (!IS_ERR(st->reg)) + regulator_put(st->reg); + + iio_free_device(indio_dev); + + return ret; +} + +static int __devexit adf4350_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct adf4350_state *st = iio_priv(indio_dev); + struct regulator *reg = st->reg; + + st->regs[ADF4350_REG2] |= ADF4350_REG2_POWER_DOWN_EN; + adf4350_sync_config(st); + + if (gpio_is_valid(st->pdata->gpio_lock_detect)) + gpio_free(st->pdata->gpio_lock_detect); + + iio_device_unregister(indio_dev); + + if (!IS_ERR(reg)) { + regulator_disable(reg); + regulator_put(reg); + } + + iio_free_device(indio_dev); + + return 0; +} + +static const struct spi_device_id adf4350_id[] = { + {"adf4350", 4350}, + {"adf4351", 4351}, + {} +}; + +static struct spi_driver adf4350_driver = { + .driver = { + .name = "adf4350", + .owner = THIS_MODULE, + }, + .probe = adf4350_probe, + .remove = __devexit_p(adf4350_remove), + .id_table = adf4350_id, +}; + +static int __init adf4350_init(void) +{ + return spi_register_driver(&adf4350_driver); +} +module_init(adf4350_init); + +static void __exit adf4350_exit(void) +{ + spi_unregister_driver(&adf4350_driver); +} +module_exit(adf4350_exit); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices ADF4350/ADF4351 PLL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/frequency/adf4350.h b/drivers/staging/iio/frequency/adf4350.h new file mode 100644 index 0000000000000..5955f4fce06c2 --- /dev/null +++ b/drivers/staging/iio/frequency/adf4350.h @@ -0,0 +1,122 @@ +/* + * ADF4350/ADF4351 SPI PLL driver + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#ifndef IIO_PLL_ADF4350_H_ +#define IIO_PLL_ADF4350_H_ + +/* Registers */ +#define ADF4350_REG0 0 +#define ADF4350_REG1 1 +#define ADF4350_REG2 2 +#define ADF4350_REG3 3 +#define ADF4350_REG4 4 +#define ADF4350_REG5 5 + +/* REG0 Bit Definitions */ +#define ADF4350_REG0_FRACT(x) (((x) & 0xFFF) << 3) +#define ADF4350_REG0_INT(x) (((x) & 0xFFFF) << 15) + +/* REG1 Bit Definitions */ +#define ADF4350_REG1_MOD(x) (((x) & 0xFFF) << 3) +#define ADF4350_REG1_PHASE(x) (((x) & 0xFFF) << 15) +#define ADF4350_REG1_PRESCALER (1 << 27) + +/* REG2 Bit Definitions */ +#define ADF4350_REG2_COUNTER_RESET_EN (1 << 3) +#define ADF4350_REG2_CP_THREESTATE_EN (1 << 4) +#define ADF4350_REG2_POWER_DOWN_EN (1 << 5) +#define ADF4350_REG2_PD_POLARITY_POS (1 << 6) +#define ADF4350_REG2_LDP_6ns (1 << 7) +#define ADF4350_REG2_LDP_10ns (0 << 7) +#define ADF4350_REG2_LDF_FRACT_N (0 << 8) +#define ADF4350_REG2_LDF_INT_N (1 << 8) +#define ADF4350_REG2_CHARGE_PUMP_CURR_uA(x) (((((x)-312) / 312) & 0xF) << 9) +#define ADF4350_REG2_DOUBLE_BUFF_EN (1 << 13) +#define ADF4350_REG2_10BIT_R_CNT(x) ((x) << 14) +#define ADF4350_REG2_RDIV2_EN (1 << 24) +#define ADF4350_REG2_RMULT2_EN (1 << 25) +#define ADF4350_REG2_MUXOUT(x) ((x) << 26) +#define ADF4350_REG2_NOISE_MODE(x) ((x) << 29) + +/* REG3 Bit Definitions */ +#define ADF4350_REG3_12BIT_CLKDIV(x) ((x) << 3) +#define ADF4350_REG3_12BIT_CLKDIV_MODE(x) ((x) << 16) +#define ADF4350_REG3_12BIT_CSR_EN (1 << 18) +#define ADF4351_REG3_CHARGE_CANCELLATION_EN (1 << 21) +#define ADF4351_REG3_ANTI_BACKLASH_3ns_EN (1 << 22) +#define ADF4351_REG3_BAND_SEL_CLOCK_MODE_HIGH (1 << 23) + +/* REG4 Bit Definitions */ +#define ADF4350_REG4_OUTPUT_PWR(x) ((x) << 3) +#define ADF4350_REG4_RF_OUT_EN (1 << 5) +#define ADF4350_REG4_AUX_OUTPUT_PWR(x) ((x) << 6) +#define ADF4350_REG4_AUX_OUTPUT_EN (1 << 8) +#define ADF4350_REG4_AUX_OUTPUT_FUND (1 << 9) +#define ADF4350_REG4_AUX_OUTPUT_DIV (0 << 9) +#define ADF4350_REG4_MUTE_TILL_LOCK_EN (1 << 10) +#define ADF4350_REG4_VCO_PWRDOWN_EN (1 << 11) +#define ADF4350_REG4_8BIT_BAND_SEL_CLKDIV(x) ((x) << 12) +#define ADF4350_REG4_RF_DIV_SEL(x) ((x) << 20) +#define ADF4350_REG4_FEEDBACK_DIVIDED (0 << 23) +#define ADF4350_REG4_FEEDBACK_FUND (1 << 23) + +/* REG5 Bit Definitions */ +#define ADF4350_REG5_LD_PIN_MODE_LOW (0 << 22) +#define ADF4350_REG5_LD_PIN_MODE_DIGITAL (1 << 22) +#define ADF4350_REG5_LD_PIN_MODE_HIGH (3 << 22) + +/* Specifications */ +#define ADF4350_MAX_OUT_FREQ 4400000000ULL /* Hz */ +#define ADF4350_MIN_OUT_FREQ 137500000 /* Hz */ +#define ADF4351_MIN_OUT_FREQ 34375000 /* Hz */ +#define ADF4350_MIN_VCO_FREQ 2200000000ULL /* Hz */ +#define ADF4350_MAX_FREQ_45_PRESC 3000000000ULL /* Hz */ +#define ADF4350_MAX_FREQ_PFD 32000000 /* Hz */ +#define ADF4350_MAX_BANDSEL_CLK 125000 /* Hz */ +#define ADF4350_MAX_FREQ_REFIN 250000000 /* Hz */ +#define ADF4350_MAX_MODULUS 4095 + +/* + * TODO: struct adf4350_platform_data needs to go into include/linux/iio + */ + +/** + * struct adf4350_platform_data - platform specific information + * @clkin: REFin frequency in Hz. + * @channel_spacing: Channel spacing in Hz (influences MODULUS). + * @power_up_frequency: Optional, If set in Hz the PLL tunes to the desired + * frequency on probe. + * @ref_div_factor: Optional, if set the driver skips dynamic calculation + * and uses this default value instead. + * @ref_doubler_en: Enables reference doubler. + * @ref_div2_en: Enables reference divider. + * @r2_user_settings: User defined settings for ADF4350/1 REGISTER_2. + * @r3_user_settings: User defined settings for ADF4350/1 REGISTER_3. + * @r4_user_settings: User defined settings for ADF4350/1 REGISTER_4. + * @gpio_lock_detect: Optional, if set with a valid GPIO number, + * a PLL_LOCKED device attribute is created. + * If not used - set to -1. + */ + +struct adf4350_platform_data { + char name[32]; + unsigned long clkin; + unsigned long channel_spacing; + unsigned long long power_up_frequency; + + unsigned short ref_div_factor; /* 10-bit R counter */ + bool ref_doubler_en; + bool ref_div2_en; + + unsigned r2_user_settings; + unsigned r3_user_settings; + unsigned r4_user_settings; + int gpio_lock_detect; +}; + +#endif /* IIO_PLL_ADF4350_H_ */ From 30ea1d478a9fa9e521583615a664ef7e9f704fac Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 9 Mar 2012 14:04:48 +0100 Subject: [PATCH 115/261] platform: Add config and device-tree for XCOMM on ML605 Signed-off-by: Michael Hennerich --- arch/microblaze/boot/dts/ml605_xcomm.dts | 346 +++++ arch/microblaze/configs/ml605_xcomm_defconfig | 1300 +++++++++++++++++ 2 files changed, 1646 insertions(+) create mode 100644 arch/microblaze/boot/dts/ml605_xcomm.dts create mode 100644 arch/microblaze/configs/ml605_xcomm_defconfig diff --git a/arch/microblaze/boot/dts/ml605_xcomm.dts b/arch/microblaze/boot/dts/ml605_xcomm.dts new file mode 100644 index 0000000000000..34f1b9e76e3b9 --- /dev/null +++ b/arch/microblaze/boot/dts/ml605_xcomm.dts @@ -0,0 +1,346 @@ +/* + * Device Tree Generator version: 1.3 + * + * (C) Copyright 2007-2008 Xilinx, Inc. + * (C) Copyright 2007-2009 Michal Simek + * + * Michal SIMEK + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * CAUTION: This file is automatically generated by libgen. + * Version: Xilinx EDK 13.3 EDK_O.76xd + * + * XPS project directory: device-tree_bsp_0 + */ + +/dts-v1/; +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,microblaze"; + model = "testing"; + DDR3_SDRAM: memory@c0000000 { + device_type = "memory"; + reg = < 0xc0000000 0x20000000 >; + } ; + aliases { + ethernet0 = &Ethernet_Lite; + serial0 = &RS232_Uart_1; + } ; + chosen { + bootargs = "console=ttyS0 root=/dev/ram"; + } ; + cpus { + #address-cells = <1>; + #cpus = <0x1>; + #size-cells = <0>; + microblaze_0: cpu@0 { + clock-frequency = <100000000>; + compatible = "xlnx,microblaze-8.20.a"; + d-cache-baseaddr = <0xc0000000>; + d-cache-highaddr = <0xdfffffff>; + d-cache-line-size = <0x10>; + d-cache-size = <0x4000>; + device_type = "cpu"; + i-cache-baseaddr = <0xc0000000>; + i-cache-highaddr = <0xdfffffff>; + i-cache-line-size = <0x20>; + i-cache-size = <0x4000>; + model = "microblaze,8.20.a"; + reg = <0>; + timebase-frequency = <100000000>; + xlnx,addr-tag-bits = <0xf>; + xlnx,allow-dcache-wr = <0x1>; + xlnx,allow-icache-wr = <0x1>; + xlnx,area-optimized = <0x0>; + xlnx,avoid-primitives = <0x0>; + xlnx,branch-target-cache-size = <0x0>; + xlnx,cache-byte-size = <0x4000>; + xlnx,d-axi = <0x1>; + xlnx,d-lmb = <0x1>; + xlnx,d-plb = <0x0>; + xlnx,data-size = <0x20>; + xlnx,dcache-addr-tag = <0xf>; + xlnx,dcache-always-used = <0x1>; + xlnx,dcache-byte-size = <0x4000>; + xlnx,dcache-data-width = <0x0>; + xlnx,dcache-force-tag-lutram = <0x0>; + xlnx,dcache-interface = <0x0>; + xlnx,dcache-line-len = <0x4>; + xlnx,dcache-use-fsl = <0x0>; + xlnx,dcache-use-writeback = <0x0>; + xlnx,dcache-victims = <0x0>; + xlnx,debug-enabled = <0x1>; + xlnx,div-zero-exception = <0x1>; + xlnx,dynamic-bus-sizing = <0x1>; + xlnx,ecc-use-ce-exception = <0x0>; + xlnx,edge-is-positive = <0x1>; + xlnx,endianness = <0x1>; + xlnx,family = "virtex6"; + xlnx,fault-tolerant = <0x0>; + xlnx,fpu-exception = <0x0>; + xlnx,freq = <0x5f5e100>; + xlnx,fsl-data-size = <0x20>; + xlnx,fsl-exception = <0x0>; + xlnx,fsl-links = <0x0>; + xlnx,i-axi = <0x0>; + xlnx,i-lmb = <0x1>; + xlnx,i-plb = <0x0>; + xlnx,icache-always-used = <0x1>; + xlnx,icache-data-width = <0x0>; + xlnx,icache-force-tag-lutram = <0x0>; + xlnx,icache-interface = <0x0>; + xlnx,icache-line-len = <0x8>; + xlnx,icache-streams = <0x1>; + xlnx,icache-use-fsl = <0x0>; + xlnx,icache-victims = <0x8>; + xlnx,ill-opcode-exception = <0x1>; + xlnx,instance = "microblaze_0"; + xlnx,interconnect = <0x2>; + xlnx,interconnect-m-axi-dc-read-issuing = <0x2>; + xlnx,interconnect-m-axi-dc-write-issuing = <0x20>; + xlnx,interconnect-m-axi-dp-read-issuing = <0x1>; + xlnx,interconnect-m-axi-dp-write-issuing = <0x1>; + xlnx,interconnect-m-axi-ic-read-issuing = <0x8>; + xlnx,interconnect-m-axi-ip-read-issuing = <0x1>; + xlnx,interrupt-is-edge = <0x0>; + xlnx,lockstep-slave = <0x0>; + xlnx,mmu-dtlb-size = <0x4>; + xlnx,mmu-itlb-size = <0x2>; + xlnx,mmu-privileged-instr = <0x0>; + xlnx,mmu-tlb-access = <0x3>; + xlnx,mmu-zones = <0x2>; + xlnx,number-of-pc-brk = <0x1>; + xlnx,number-of-rd-addr-brk = <0x0>; + xlnx,number-of-wr-addr-brk = <0x0>; + xlnx,opcode-0x0-illegal = <0x1>; + xlnx,optimization = <0x0>; + xlnx,pvr = <0x2>; + xlnx,pvr-user1 = <0x0>; + xlnx,pvr-user2 = <0x0>; + xlnx,reset-msr = <0x0>; + xlnx,sco = <0x0>; + xlnx,stream-interconnect = <0x0>; + xlnx,unaligned-exceptions = <0x1>; + xlnx,use-barrel = <0x1>; + xlnx,use-branch-target-cache = <0x0>; + xlnx,use-dcache = <0x1>; + xlnx,use-div = <0x1>; + xlnx,use-ext-brk = <0x1>; + xlnx,use-ext-nm-brk = <0x1>; + xlnx,use-extended-fsl-instr = <0x0>; + xlnx,use-fpu = <0x0>; + xlnx,use-hw-mul = <0x2>; + xlnx,use-icache = <0x1>; + xlnx,use-interrupt = <0x1>; + xlnx,use-mmu = <0x3>; + xlnx,use-msr-instr = <0x1>; + xlnx,use-pcmp-instr = <0x1>; + xlnx,use-stack-protection = <0x0>; + } ; + } ; + axi4lite_0: axi@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,axi-interconnect-1.04.a", "simple-bus"; + ranges ; + Ethernet_Lite: ethernet@40e00000 { + compatible = "xlnx,axi-ethernetlite-1.01.a", "xlnx,xps-ethernetlite-1.00.a"; + device_type = "network"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 3 0 >; + local-mac-address = [ 00 0a 35 4f 78 00 ]; + phy-handle = <&phy0>; + reg = < 0x40e00000 0x10000 >; + xlnx,duplex = <0x1>; + xlnx,family = "virtex6"; + xlnx,include-global-buffers = <0x0>; + xlnx,include-internal-loopback = <0x0>; + xlnx,include-mdio = <0x1>; + xlnx,include-phy-constraints = <0x1>; + xlnx,interconnect-s-axi-read-acceptance = <0x1>; + xlnx,interconnect-s-axi-write-acceptance = <0x1>; + xlnx,rx-ping-pong = <0x0>; + xlnx,s-axi-aclk-period-ps = <0x2710>; + xlnx,s-axi-id-width = <0x1>; + xlnx,s-axi-supports-narrow-burst = <0x0>; + xlnx,tx-ping-pong = <0x0>; + mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: phy@7 { + compatible = "marvell,88e1111"; + device_type = "ethernet-phy"; + reg = <7>; + } ; + } ; + } ; + RS232_Uart_1: serial@40600000 { + clock-frequency = <100000000>; + compatible = "xlnx,axi-uartlite-1.02.a", "xlnx,xps-uartlite-1.00.a"; + current-speed = <57600>; + device_type = "serial"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 4 0 >; + port-number = <0>; + reg = < 0x40600000 0x10000 >; + xlnx,baudrate = <0xe100>; + xlnx,data-bits = <0x8>; + xlnx,family = "virtex6"; + xlnx,odd-parity = <0x1>; + xlnx,s-axi-aclk-freq-hz = <0x5f5e100>; + xlnx,use-parity = <0x0>; + } ; + + axi_dma_0: axidma@41e00000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + ranges = < 0x41e00000 0x41e00000 0x10000 >; + reg = < 0x41e00000 0x10000 >; + xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@41e00000 { + compatible = "xlnx,axi-dma-s2mm-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 1 2 >; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + } ; + } ; +/* + axi_dma_0: axi-dma@41e00000 { + compatible = "xlnx,axi-dma"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 1 2 >; + reg = < 0x41e00000 0x10000 >; + xlnx,dlytmr-resolution = <0x7d>; + xlnx,family = "virtex6"; + xlnx,include-mm2s = <0x0>; + xlnx,include-mm2s-dre = <0x0>; + xlnx,include-mm2s-sf = <0x1>; + xlnx,include-s2mm = <0x1>; + xlnx,include-s2mm-dre = <0x0>; + xlnx,include-s2mm-sf = <0x1>; + xlnx,include-sg = <0x0>; + xlnx,interconnect-m-axi-mm2s-read-fifo-depth = <0x0>; + xlnx,interconnect-m-axi-mm2s-read-issuing = <0x4>; + xlnx,interconnect-m-axi-s2mm-write-fifo-depth = <0x0>; + xlnx,interconnect-m-axi-s2mm-write-issuing = <0x4>; + xlnx,mm2s-burst-size = <0x10>; + xlnx,prmry-is-aclk-async = <0x1>; + xlnx,s-axi-lite-aclk-freq-hz = <0x5f5e100>; + xlnx,s-axi-lite-addr-width = <0x20>; + xlnx,s-axi-lite-data-width = <0x20>; + xlnx,s-axi-lite-protocol = "AXI4LITE"; + xlnx,s-axi-lite-supports-read = <0x1>; + xlnx,s-axi-lite-supports-write = <0x1>; + xlnx,s2mm-burst-size = <0x10>; + xlnx,sg-include-desc-queue = <0x0>; + xlnx,sg-include-stscntrl-strm = <0x1>; + xlnx,sg-length-width = <0xe>; + xlnx,sg-use-stsapp-length = <0x1>; + } ; +*/ + axi_iic_0: i2c@40800000 { + compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 0 2 >; + reg = < 0x40800000 0x10000 >; + xlnx,family = "virtex6"; + xlnx,gpo-width = <0x1>; + xlnx,iic-freq = <0x186a0>; + xlnx,s-axi-aclk-freq-hz = <0x5f5e100>; + xlnx,scl-inertial-delay = <0x0>; + xlnx,sda-inertial-delay = <0x0>; + xlnx,sda-level = <0x1>; + xlnx,ten-bit-adr = <0x0>; + spi_xcomm: spi_xcomm@50 { + compatible = "spi-xcomm"; + reg = <0x50>; + dac_ad9122: ad9122@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ad9122"; + reg = <0>; + spi-max-frequency = <10000000>; + }; + + }; + } ; + axi_intc_0: interrupt-controller@41200000 { + #interrupt-cells = <0x2>; + compatible = "xlnx,axi-intc-1.01.a", "xlnx,xps-intc-1.00.a"; + interrupt-controller ; + reg = < 0x41200000 0x10000 >; + xlnx,kind-of-intr = <0x18>; + xlnx,num-intr-inputs = <0x5>; + } ; + axi_timer_0: timer@41c00000 { + clock-frequency = <100000000>; + compatible = "xlnx,axi-timer-1.03.a", "xlnx,xps-timer-1.00.a"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 2 2 >; + reg = < 0x41c00000 0x10000 >; + xlnx,count-width = <0x20>; + xlnx,family = "virtex6"; + xlnx,gen0-assert = <0x1>; + xlnx,gen1-assert = <0x1>; + xlnx,one-timer-only = <0x0>; + xlnx,trig0-assert = <0x1>; + xlnx,trig1-assert = <0x1>; + } ; + cf_ad9122_core_0: cf-ad9122-core@73020000 { + compatible = "xlnx,cf-ad9122-core-1.00.a"; + reg = < 0x73020000 0x10000 >; + spibus-connected = <&dac_ad9122>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "virtex6"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + cf_ad9643_core_0: cf-ad9643-core@73000000 { + compatible = "xlnx,cf-ad9643-core-1.00.a"; + reg = < 0x73000000 0x10000 >; + axistream-connected = <&axi_dma_0>; + spibus-connected = <&spi_xcomm>; + spibus-slaveselect-connected = <0x1>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "virtex6"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + dma-request = <&axi_dma_0 0>; + } ; + debug_module: debug@74800000 { + compatible = "xlnx,mdm-2.00.b"; + reg = < 0x74800000 0x10000 >; + xlnx,family = "virtex6"; + xlnx,interconnect = <0x2>; + xlnx,jtag-chain = <0x2>; + xlnx,mb-dbg-ports = <0x1>; + xlnx,use-uart = <0x1>; + } ; + } ; +} ; diff --git a/arch/microblaze/configs/ml605_xcomm_defconfig b/arch/microblaze/configs/ml605_xcomm_defconfig new file mode 100644 index 0000000000000..182af56473134 --- /dev/null +++ b/arch/microblaze/configs/ml605_xcomm_defconfig @@ -0,0 +1,1300 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/microblaze 3.3.0-rc3 Kernel Configuration +# +CONFIG_MICROBLAZE=y +# CONFIG_SWAP is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +# CONFIG_GENERIC_TIME_VSYSCALL is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_CSUM=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y + +# +# RCU Subsystem +# +CONFIG_TINY_RCU=y +# CONFIG_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="rootfs.cpio.gz" +CONFIG_INITRAMFS_ROOT_UID=0 +CONFIG_INITRAMFS_ROOT_GID=0 +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +CONFIG_INITRAMFS_COMPRESSION_NONE=y +# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_API_DEBUG=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_BLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_FREEZER is not set + +# +# Platform options +# +CONFIG_PLATFORM_GENERIC=y +# CONFIG_OPT_LIB_FUNCTION is not set + +# +# Definitions for MICROBLAZE0 +# +CONFIG_KERNEL_BASE_ADDR=0xc0000000 +CONFIG_XILINX_MICROBLAZE0_FAMILY="virtex6" +CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1 +CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1 +CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1 +CONFIG_XILINX_MICROBLAZE0_USE_DIV=1 +CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL=2 +CONFIG_XILINX_MICROBLAZE0_USE_FPU=0 +CONFIG_XILINX_MICROBLAZE0_HW_VER="8.20.a" + +# +# Processor type and features +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_SCHED_HRTICK=y +CONFIG_MMU=y + +# +# Boot options +# +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyUL0,57600 root=/dev/ram" +CONFIG_CMDLINE_FORCE=y +# CONFIG_SECCOMP is not set + +# +# Advanced setup +# +CONFIG_ADVANCED_OPTIONS=y +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE_BOOL=y +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_MANUAL_RESET_VECTOR=0x0 +CONFIG_KERNEL_START_BOOL=y +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE_BOOL=y +CONFIG_TASK_SIZE=0x80000000 +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_NEED_PER_CPU_KM=y +# CONFIG_CLEANCACHE is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Bus Options +# +# CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS is not set +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +# CONFIG_DNS_RESOLVER is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +CONFIG_BQL=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +CONFIG_GENERIC_CPU_DEVICES=y +# CONFIG_DMA_SHARED_BUFFER is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=y +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_GPIO_ADDR is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_LATCH_ADDR is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_DEVICE=y +CONFIG_OF_GPIO=y +CONFIG_OF_I2C=y +CONFIG_OF_NET=y +CONFIG_OF_SPI=y +CONFIG_OF_MDIO=y +# CONFIG_PARPORT is not set + +# +# Misc devices +# +CONFIG_AD525X_DPOT=y +CONFIG_AD525X_DPOT_I2C=y +CONFIG_AD525X_DPOT_SPI=y +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085 is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_MII is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set + +# +# CAIF transport drivers +# +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_INTEL=y +CONFIG_NET_VENDOR_I825XX=y +CONFIG_NET_VENDOR_MARVELL=y +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +CONFIG_NET_VENDOR_NATSEMI=y +CONFIG_NET_VENDOR_8390=y +# CONFIG_ETHOC is not set +CONFIG_NET_VENDOR_SEEQ=y +# CONFIG_SEEQ8005 is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_XILINX=y +CONFIG_XILINX_EMACLITE=y +# CONFIG_XILINX_LL_TEMAC is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_WLAN=y +# CONFIG_HOSTAP is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_DW is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_UARTLITE=y +CONFIG_SERIAL_UARTLITE_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_TTY_PRINTK is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_XILINX_HWICAP is not set +# CONFIG_R3964 is not set + +# +# PCMCIA character devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_RAMOOPS is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_MUX is not set +# CONFIG_I2C_HELPER_AUTO is not set +# CONFIG_I2C_SMBUS is not set + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +CONFIG_I2C_XILINX=y + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=y +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX_PCI is not set +CONFIG_SPI_XCOMM=y +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +CONFIG_GPIO_XILINX=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_S5M_CORE is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_SOUND is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_RTC_CLASS is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_XILINX_DMA=y +# CONFIG_TIMB_DMA is not set +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_BALLOON is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_ECHO is not set +# CONFIG_RTLLIB is not set +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +CONFIG_IIO_SW_RING=y +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16204 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_KXSD9 is not set +# CONFIG_LIS3L02DQ is not set +# CONFIG_SCA3000 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7291 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7606 is not set +# CONFIG_AD799X is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_ADT7310 is not set +# CONFIG_ADT7410 is not set +# CONFIG_AD7280 is not set +CONFIG_CF_AD9467=y +# CONFIG_MAX1363 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Amplifiers +# +CONFIG_AD8366=y + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD5686 is not set +# CONFIG_MAX517 is not set + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +CONFIG_AD9523=y + +# +# Direct Digital Synthesis +# +# CONFIG_AD5930 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_AD9850 is not set +# CONFIG_AD9852 is not set +# CONFIG_AD9910 is not set +# CONFIG_AD9951 is not set +CONFIG_AD9122_CF=y +CONFIG_AD9122_CF_DAC=y + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +CONFIG_ADF4350=y + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16060 is not set +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set + +# +# Light sensors +# +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_TSL2563 is not set +# CONFIG_TSL2583 is not set + +# +# Magnetometer sensors +# +# CONFIG_SENSORS_AK8975 is not set +# CONFIG_SENSORS_HMC5843 is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7753 is not set +# CONFIG_ADE7754 is not set +# CONFIG_ADE7758 is not set +# CONFIG_ADE7759 is not set +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_GPIO_TRIGGER is not set +# CONFIG_IIO_SYSFS_TRIGGER is not set +# CONFIG_IIO_SIMPLE_DUMMY is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +# CONFIG_ANDROID is not set +# CONFIG_PHONE is not set + +# +# Hardware Spinlock drivers +# +CONFIG_IOMMU_SUPPORT=y +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set + +# +# File systems +# +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ECRYPT_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set +# CONFIG_MINIX_FS_NATIVE_ENDIAN is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_TEST_KSTRTOX is not set +CONFIG_EARLY_PRINTK=y +# CONFIG_HEART_BEAT is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_ENCRYPTED_KEYS is not set +CONFIG_KEYS_DEBUG_PROC_KEYS=y +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_PCI_IOMAP=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +# CONFIG_CRC8 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_GENERIC_ATOMIC64=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set From 4249b23b90f7ddedc8bf15fc362cc71525adb16f Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Mon, 2 Apr 2012 17:15:30 +0200 Subject: [PATCH 116/261] arch: microblaze: Add support for kintex7 families and cpu version 8.20.b Signed-off-by: Michael Hennerich --- arch/microblaze/kernel/cpu/cpuinfo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index 54194b28574af..8b2f95a80d394 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c @@ -35,6 +35,7 @@ const struct cpu_ver_key cpu_ver_lookup[] = { {"8.00.b", 0x13}, {"8.10.a", 0x14}, {"8.20.a", 0x15}, + {"8.20.b", 0x16}, {NULL, 0}, }; @@ -55,6 +56,7 @@ const struct family_string_key family_string_lookup[] = { {"virtex6", 0xe}, /* FIXME There is no key code defined for spartan2 */ {"spartan2", 0xf0}, + {"kintex7", 0x10}, {NULL, 0}, }; From 7c49e778890660ad6ba5adb95dbe402e8ae340de Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 24 Apr 2012 10:10:24 +0200 Subject: [PATCH 117/261] SPI XCOMM Bridge Driver: Increment bus numbers and blink LED on probe Signed-off-by: Michael Hennerich --- drivers/spi/spi-xcomm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-xcomm.c b/drivers/spi/spi-xcomm.c index a97ec46642796..2996621a2a788 100644 --- a/drivers/spi/spi-xcomm.c +++ b/drivers/spi/spi-xcomm.c @@ -22,6 +22,8 @@ #define SPI_XCOMM_CMD_UPDATE_CONFIG 0x03 #define SPI_XCOMM_CMD_WRITE 0x04 +unsigned bus_num = 0; + struct spi_xcomm { struct spi_bitbang bitbang; /* keep this one here !!! */ struct i2c_client *i2c; @@ -194,6 +196,7 @@ static int __devinit spi_xcomm_probe(struct i2c_client *i2c, master->cleanup = spi_bitbang_cleanup; spi_xcomm->bitbang.master = spi_master_get(master); + spi_xcomm->bitbang.master->bus_num = bus_num++; spi_xcomm->bitbang.chipselect = spi_xcomm_chipselect; spi_xcomm->bitbang.setup_transfer = spi_xcomm_setup_transfer; @@ -208,7 +211,7 @@ static int __devinit spi_xcomm_probe(struct i2c_client *i2c, if (ret < 0) spi_master_put(master); -// i2c_master_send(i2c, buf, 1); + i2c_master_send(i2c, buf, 1); return ret; } From f92ab2b1bf7d168983deb0ae4c2e3378113599a1 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 24 Apr 2012 10:17:52 +0200 Subject: [PATCH 118/261] iio: frequency: adf4350: remove debug information, no functional changes. Signed-off-by: Michael Hennerich --- drivers/staging/iio/frequency/adf4350.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/iio/frequency/adf4350.c b/drivers/staging/iio/frequency/adf4350.c index 17df1b7c0c158..3d5c0bd3e5d1f 100644 --- a/drivers/staging/iio/frequency/adf4350.c +++ b/drivers/staging/iio/frequency/adf4350.c @@ -396,7 +396,6 @@ static int __devinit adf4350_probe(struct spi_device *spi) indio_dev->dev.parent = &spi->dev; indio_dev->name = (pdata->name[0] != 0) ? pdata->name : spi_get_device_id(spi)->name; - printk("%s: %d::: %s %s\n",__func__,__LINE__, pdata->name, spi_get_device_id(spi)->name); indio_dev->info = &adf4350_info; indio_dev->modes = INDIO_DIRECT_MODE; From 04dd266f01d76ad7eb9d0b74823cb93894f31a12 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 24 Apr 2012 12:48:35 +0200 Subject: [PATCH 119/261] mb: platform: Move xcomm spi board information into dedicated file Add proper CONFIG defines Signed-off-by: Michael Hennerich --- arch/microblaze/platform/Kconfig.platform | 22 +- arch/microblaze/platform/Makefile | 2 + arch/microblaze/platform/platform.c | 264 --------------- arch/microblaze/platform/platform_xcomm.c | 370 ++++++++++++++++++++++ 4 files changed, 391 insertions(+), 267 deletions(-) create mode 100644 arch/microblaze/platform/platform_xcomm.c diff --git a/arch/microblaze/platform/Kconfig.platform b/arch/microblaze/platform/Kconfig.platform index 669c7eec293eb..638e313fe7b19 100644 --- a/arch/microblaze/platform/Kconfig.platform +++ b/arch/microblaze/platform/Kconfig.platform @@ -16,8 +16,25 @@ config PLATFORM_GENERIC help Choose this option for the Generic platform. +config PLATFORM_ML605_ADIXCOMM + bool "Analog Devices XCOMM on Xilinx ML605" + help + Choose this option for the XCOMM ML605 platform. + +config PLATFORM_KC705_ADIXCOMM + bool "Analog Devices XCOMM on Xilinx KC705" + help + Choose this option for the XCOMM KC705 platform. + endchoice +config ADIXCOMM_SYNC + bool "XCOMM Sync Clocks" + depends on PLATFORM_KC705_ADIXCOMM || PLATFORM_ML605_ADIXCOMM + default n + help + Choose this option for the XCOMM platform to sync clocks. + config SELFMOD bool "Use self modified code for intc/timer" depends on EXPERIMENTAL && NO_MMU @@ -59,8 +76,7 @@ config OPT_LIB_ASM Allows turn on optimalized library function (memcpy and memmove). Function are written in asm code. -if PLATFORM_GENERIC=y - source "arch/microblaze/platform/generic/Kconfig.auto" -endif + +source "arch/microblaze/platform/generic/Kconfig.auto" endmenu diff --git a/arch/microblaze/platform/Makefile b/arch/microblaze/platform/Makefile index ea1b75cc57758..637fc54ecfc0c 100644 --- a/arch/microblaze/platform/Makefile +++ b/arch/microblaze/platform/Makefile @@ -4,3 +4,5 @@ #obj-$(CONFIG_PLATFORM_GENERIC) += generic/ obj-y += platform.o +obj-$(CONFIG_PLATFORM_ML605_ADIXCOMM) += platform_xcomm.o +obj-$(CONFIG_PLATFORM_KC705_ADIXCOMM) += platform_xcomm.o diff --git a/arch/microblaze/platform/platform.c b/arch/microblaze/platform/platform.c index eec3d58b8a514..9b187a90ca658 100644 --- a/arch/microblaze/platform/platform.c +++ b/arch/microblaze/platform/platform.c @@ -14,8 +14,6 @@ #include #include #include -#include -#include static struct of_device_id xilinx_of_bus_ids[] __initdata = { { .compatible = "simple-bus", }, @@ -23,273 +21,11 @@ static struct of_device_id xilinx_of_bus_ids[] __initdata = { {} }; -static struct i2c_board_info __initdata xcomm_i2c_board_info[] = { - { - I2C_BOARD_INFO("spi-xcomm", 0x50), - }, -}; - -#if defined(CONFIG_AD9523) || defined(CONFIG_AD9523_MODULE) -#include "../../../../drivers/staging/iio/frequency/ad9523.h" - -struct ad9523_channel_spec ad9523_channels[] = { - { /* ZD output */ - .channel_num = 0, - .extended_name = "ZD_OUTPUT", - .divider_output_invert_en = false, - .sync_ignore_en = false, - .low_power_mode_en = false, - .driver_mode = LVDS_7mA, - .divider_phase = 0, - .channel_divider = 5, - .use_alt_clock_src = false, - .output_dis = true, - }, - { /* DAC CLK */ - .channel_num = 1, - .extended_name = "DAC_CLK", - .divider_output_invert_en = false, - .sync_ignore_en = false, - .low_power_mode_en = false, - .driver_mode = LVPECL_8mA, - .divider_phase = 0, - .channel_divider = 2, - }, - { /* ADC CLK */ - .channel_num = 2, - .extended_name = "ADC_CLK", - .divider_output_invert_en = false, - .sync_ignore_en = false, - .low_power_mode_en = false, - .driver_mode = LVDS_7mA, - .divider_phase = 0, - .channel_divider = 4, - }, - { /* DAC REF CLK */ - .channel_num = 4, - .extended_name = "DAC_REF_CLK", - .divider_output_invert_en = false, - .sync_ignore_en = false, - .low_power_mode_en = false, - .driver_mode = LVDS_7mA, - .divider_phase = 0, - .channel_divider = 8, - }, - { /* TX LO REF */ - .channel_num = 5, - .extended_name = "TX_LO_REF_CLK", - .divider_output_invert_en = false, - .sync_ignore_en = false, - .low_power_mode_en = false, - .driver_mode = CMOS_CONF3, /* HiZ on - */ - .divider_phase = 0, - .channel_divider = 8, - }, - { /* DAC DCO */ - .channel_num = 6, - .extended_name = "DAC_DCO_CLK", - .divider_output_invert_en = false, - .sync_ignore_en = false, - .low_power_mode_en = false, - .driver_mode = LVDS_7mA, - .divider_phase = 0, - .channel_divider = 2, - }, - { /* ADC SYNC */ - .channel_num = 8, - .extended_name = "ADC_SYNC_CLK", - .divider_output_invert_en = false, - .sync_ignore_en = false, - .low_power_mode_en = false, - .driver_mode = CMOS_CONF3, /* HiZ on - */ - .divider_phase = 0, - .channel_divider = 32, - .output_dis = true, - }, - { /* RX LO REF */ - .channel_num = 9, - .extended_name = "RX_LO_REF_CLK", - .divider_output_invert_en = false, - .sync_ignore_en = false, - .low_power_mode_en = false, - .driver_mode = CMOS_CONF3, /* HiZ on - */ - .divider_phase = 0, - .channel_divider = 8, - }, -}; -#if 0 -struct ad9523_platform_data ad9523_pdata = { - .vcxo_freq = 122880000, - - /* Single-Ended Input Configuration */ - .refa_diff_rcv_en = true, - .refb_diff_rcv_en = true, - .zd_in_diff_en = true, - .osc_in_diff_en = false, - - .osc_in_cmos_neg_inp_en = true, - - .refa_r_div = 8, - .refb_r_div = 8, - .pll1_feedback_div = 32, - .pll1_charge_pump_current_nA = 9000, - .zero_delay_mode_internal_en = false, - .osc_in_feedback_en = true, - .pll1_loop_filter_rzero = 3, - - .ref_mode = 1, - - .pll2_charge_pump_current_nA = 420000, - .pll2_ndiv_a_cnt = 0, - .pll2_ndiv_b_cnt = 3, - .pll2_freq_doubler_en = true, - .pll2_r2_div = 1, - .pll2_vco_diff_m1 = 3, - .pll2_vco_diff_m2 = 3, - - .rpole2 = 0, - .rzero = 2, - .cpole1 = 2, - .rzero_bypass_en = false, - - /* Output Channel Configuration */ - .num_channels = ARRAY_SIZE(ad9523_channels), - .channels = ad9523_channels, -}; -#endif -struct ad9523_platform_data ad9523_pdata = { - .vcxo_freq = 122880000, - - /* Single-Ended Input Configuration */ - .refa_diff_rcv_en = true, - .refb_diff_rcv_en = true, - .zd_in_diff_en = false, - .osc_in_diff_en = false, - .osc_in_cmos_neg_inp_en = true, - - .refa_r_div = 0, - .refb_r_div = 0, - .pll1_feedback_div = 4, - .pll1_charge_pump_current_nA = 6000, - .zero_delay_mode_internal_en = true, - .osc_in_feedback_en = true, - .pll1_loop_filter_rzero = 0, - - .ref_mode = 1, - - .pll2_charge_pump_current_nA = 420000, - .pll2_ndiv_a_cnt = 0, - .pll2_ndiv_b_cnt = 3, - .pll2_freq_doubler_en = true, - .pll2_r2_div = 1, - .pll2_vco_diff_m1 = 3, - .pll2_vco_diff_m2 = 3, - - .rpole2 = 0, - .rzero = 2, - .cpole1 = 2, - .rzero_bypass_en = false, - - /* Output Channel Configuration */ - .num_channels = ARRAY_SIZE(ad9523_channels), - .channels = ad9523_channels, -}; -#endif - -#if defined(CONFIG_ADF4350) || defined(CONFIG_ADF4350_MODULE) -#include "../../../../drivers/staging/iio/frequency/adf4350.h" -static struct adf4350_platform_data adf4350_tx_pdata = { - .name = "adf4351-tx", - .clkin = 122880000, - .channel_spacing = 10000, - .r2_user_settings = ADF4350_REG2_PD_POLARITY_POS, - ADF4350_REG2_CHARGE_PUMP_CURR_uA(2500), - .r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0), - .r4_user_settings = ADF4350_REG4_OUTPUT_PWR(3) | - ADF4350_REG4_MUTE_TILL_LOCK_EN, - .gpio_lock_detect = -1, - .power_up_frequency = 2400000000, -}; - -static struct adf4350_platform_data adf4350_rx_pdata = { - .name = "adf4351-rx", - .clkin = 122880000, - .channel_spacing = 10000, - .r2_user_settings = ADF4350_REG2_PD_POLARITY_POS, - ADF4350_REG2_CHARGE_PUMP_CURR_uA(2500), - .r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0), - .r4_user_settings = ADF4350_REG4_OUTPUT_PWR(3) | - ADF4350_REG4_MUTE_TILL_LOCK_EN, - .gpio_lock_detect = -1, - .power_up_frequency = 2400000000, -}; -#endif - -static struct spi_board_info xcomm_spi_board_info[] __initdata = { -#if defined(CONFIG_AD9523) || defined(CONFIG_AD9523_MODULE) - { - .modalias = "ad9523", - .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ - .bus_num = 0, - .chip_select = 3, /* GPIO controlled SSEL */ - .platform_data = &ad9523_pdata, /* No spi_driver specific config */ - .mode = SPI_MODE_0 | SPI_3WIRE, - }, -#endif -#if defined(CONFIG_AD8366) || defined(CONFIG_AD8366_MODULE) - { - .modalias = "ad8366", - .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ - .bus_num = 0, - .chip_select = 6, /* GPIO controlled SSEL */ - .mode = SPI_MODE_0 | SPI_3WIRE, - }, -#endif -#if defined(CONFIG_ADF4350) || defined(CONFIG_ADF4350_MODULE) - { - .modalias = "adf4351", - .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ - .bus_num = 0, - .chip_select = 4, /* GPIO controlled SSEL */ - .platform_data = &adf4350_rx_pdata, /* No spi_driver specific config */ - .mode = SPI_MODE_0, - }, - { - .modalias = "adf4351", - .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ - .bus_num = 0, - .chip_select = 5, /* GPIO controlled SSEL */ - .platform_data = &adf4350_tx_pdata, /* No spi_driver specific config */ - .mode = SPI_MODE_0, - }, -#endif -#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE) - { - .modalias = "spidev", - .max_speed_hz = 10000000, /* max spi clock (SCK) speed in HZ */ - .bus_num = 0, - .chip_select = 2, /* AD9548 */ - }, -#if 0 -{ - .modalias = "spidev", - .max_speed_hz = 10000000, /* max spi clock (SCK) speed in HZ */ - .bus_num = 0, - .chip_select = 0, /* AD9122 */ - }, -#endif -#endif -}; - static int __init microblaze_device_probe(void) { of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL); of_platform_reset_gpio_probe(); - i2c_register_board_info(1, xcomm_i2c_board_info, - ARRAY_SIZE(xcomm_i2c_board_info)); - spi_register_board_info(xcomm_spi_board_info, ARRAY_SIZE(xcomm_spi_board_info)); - return 0; } device_initcall(microblaze_device_probe); diff --git a/arch/microblaze/platform/platform_xcomm.c b/arch/microblaze/platform/platform_xcomm.c new file mode 100644 index 0000000000000..771411170e996 --- /dev/null +++ b/arch/microblaze/platform/platform_xcomm.c @@ -0,0 +1,370 @@ +/* + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include + +#if defined(CONFIG_PLATFORM_ML605_ADIXCOMM) +#define SPIBUS_NUM_LPC 0 +#define SPIBUS_NUM_HPC 1 +#elif defined(CONFIG_PLATFORM_KC705_ADIXCOMM) +#define SPIBUS_NUM_LPC 1 +#define SPIBUS_NUM_HPC 0 +#endif + +#if defined(CONFIG_AD9523) || defined(CONFIG_AD9523_MODULE) +#include "../../../../drivers/staging/iio/frequency/ad9523.h" + +struct ad9523_channel_spec ad9523_channels[] = { + { /* ZD output */ + .channel_num = 0, + .extended_name = "ZD_OUTPUT", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = LVDS_4mA, + .divider_phase = 0, + .channel_divider = 8, + .use_alt_clock_src = false, + .output_dis = false, + }, + { /* DAC CLK */ + .channel_num = 1, + .extended_name = "DAC_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = LVPECL_8mA, + .divider_phase = 0, + .channel_divider = 2, + }, + { /* ADC CLK */ + .channel_num = 2, + .extended_name = "ADC_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = LVDS_7mA, + .divider_phase = 0, + .channel_divider = 4, + }, + { /* DAC REF CLK */ + .channel_num = 4, + .extended_name = "DAC_REF_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = LVDS_4mA, + .divider_phase = 0, + .channel_divider = 16, + }, + { /* TX LO REF */ + .channel_num = 5, + .extended_name = "TX_LO_REF_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = CMOS_CONF3, /* HiZ on - */ + .divider_phase = 0, + .channel_divider = 8, + }, + { /* DAC DCO */ + .channel_num = 6, + .extended_name = "DAC_DCO_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = LVDS_7mA, + .divider_phase = 0, + .channel_divider = 2, + }, + { /* ADC SYNC */ + .channel_num = 8, + .extended_name = "ADC_SYNC_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = CMOS_CONF3, /* HiZ on - */ + .divider_phase = 1, + .channel_divider = 32, + .output_dis = false, + }, + { /* RX LO REF */ + .channel_num = 9, + .extended_name = "RX_LO_REF_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = CMOS_CONF3, /* HiZ on - */ + .divider_phase = 0, + .channel_divider = 8, + }, +}; + +struct ad9523_platform_data ad9523_pdata_lpc = { + .vcxo_freq = 122880000, + + /* Single-Ended Input Configuration */ + .refa_diff_rcv_en = true, + .refb_diff_rcv_en = false, + .zd_in_diff_en = true, + .osc_in_diff_en = false, + .osc_in_cmos_neg_inp_en = true, + + .refa_r_div = 0, + .refb_r_div = 0, + .pll1_feedback_div = 4, + .pll1_charge_pump_current_nA = 2000, +#if defined(CONFIG_ADIXCOMM_SYNC) + .zero_delay_mode_internal_en = false, +#else + .zero_delay_mode_internal_en = true, +#endif + .osc_in_feedback_en = false, + .refb_cmos_neg_inp_en = true, + .pll1_loop_filter_rzero = 3, + +#if defined(CONFIG_ADIXCOMM_SYNC) + .ref_mode = 3, /* 3 ?*/ +#else + .ref_mode = 1, /* 3 ?*/ +#endif + + .pll2_charge_pump_current_nA = 420000, + .pll2_ndiv_a_cnt = 0, + .pll2_ndiv_b_cnt = 3, + .pll2_freq_doubler_en = true, + .pll2_r2_div = 1, + .pll2_vco_diff_m1 = 3, + .pll2_vco_diff_m2 = 3, + + .rpole2 = 0, + .rzero = 2, + .cpole1 = 2, + .rzero_bypass_en = false, + + /* Output Channel Configuration */ + .num_channels = ARRAY_SIZE(ad9523_channels), + .channels = ad9523_channels, + .name = "ad9523-lpc" +}; + +struct ad9523_platform_data ad9523_pdata_hpc = { + .vcxo_freq = 122880000, + + /* Single-Ended Input Configuration */ + .refa_diff_rcv_en = true, + .refb_diff_rcv_en = false, + .zd_in_diff_en = true, + .osc_in_diff_en = false, + .osc_in_cmos_neg_inp_en = true, + + .refa_r_div = 0, + .refb_r_div = 0, + .pll1_feedback_div = 4, + .pll1_charge_pump_current_nA = 2000, +#if defined(CONFIG_ADIXCOMM_SYNC) + .zero_delay_mode_internal_en = false, +#else + .zero_delay_mode_internal_en = true, +#endif + .osc_in_feedback_en = false, + .refb_cmos_neg_inp_en = true, + .pll1_loop_filter_rzero = 3, + +#if defined(CONFIG_ADIXCOMM_SYNC) + .ref_mode = 3, /* 3 ?*/ +#else + .ref_mode = 1, /* 3 ?*/ +#endif + + .pll2_charge_pump_current_nA = 420000, + .pll2_ndiv_a_cnt = 0, + .pll2_ndiv_b_cnt = 3, + .pll2_freq_doubler_en = true, + .pll2_r2_div = 1, + .pll2_vco_diff_m1 = 3, + .pll2_vco_diff_m2 = 3, + + .rpole2 = 0, + .rzero = 2, + .cpole1 = 2, + .rzero_bypass_en = false, + + /* Output Channel Configuration */ + .num_channels = ARRAY_SIZE(ad9523_channels), + .channels = ad9523_channels, + .name = "ad9523-hpc" +}; +#endif + +#if defined(CONFIG_ADF4350) || defined(CONFIG_ADF4350_MODULE) +#include "../../../../drivers/staging/iio/frequency/adf4350.h" +static struct adf4350_platform_data adf4350_tx_pdata_lpc = { + .name = "adf4351-tx-lpc", + .clkin = 122880000, + .channel_spacing = 10000, + .r2_user_settings = ADF4350_REG2_PD_POLARITY_POS, + ADF4350_REG2_CHARGE_PUMP_CURR_uA(2500), + .r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0), + .r4_user_settings = ADF4350_REG4_OUTPUT_PWR(3) | + ADF4350_REG4_MUTE_TILL_LOCK_EN, + .gpio_lock_detect = -1, + .power_up_frequency = 2400000000, +}; + +static struct adf4350_platform_data adf4350_rx_pdata_lpc = { + .name = "adf4351-rx-lpc", + .clkin = 122880000, + .channel_spacing = 10000, + .r2_user_settings = ADF4350_REG2_PD_POLARITY_POS, + ADF4350_REG2_CHARGE_PUMP_CURR_uA(2500), + .r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0), + .r4_user_settings = ADF4350_REG4_OUTPUT_PWR(3) | + ADF4350_REG4_MUTE_TILL_LOCK_EN, + .gpio_lock_detect = -1, + .power_up_frequency = 2400000000, +}; +static struct adf4350_platform_data adf4350_tx_pdata_hpc = { + .name = "adf4351-tx-hpc", + .clkin = 122880000, + .channel_spacing = 10000, + .r2_user_settings = ADF4350_REG2_PD_POLARITY_POS, + ADF4350_REG2_CHARGE_PUMP_CURR_uA(2500), + .r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0), + .r4_user_settings = ADF4350_REG4_OUTPUT_PWR(3) | + ADF4350_REG4_MUTE_TILL_LOCK_EN, + .gpio_lock_detect = -1, + .power_up_frequency = 2400000000, +}; + +static struct adf4350_platform_data adf4350_rx_pdata_hpc = { + .name = "adf4351-rx-hpc", + .clkin = 122880000, + .channel_spacing = 10000, + .r2_user_settings = ADF4350_REG2_PD_POLARITY_POS, + ADF4350_REG2_CHARGE_PUMP_CURR_uA(2500), + .r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0), + .r4_user_settings = ADF4350_REG4_OUTPUT_PWR(3) | + ADF4350_REG4_MUTE_TILL_LOCK_EN, + .gpio_lock_detect = -1, + .power_up_frequency = 2400000000, +}; +#endif + +static struct spi_board_info xcomm_spi_board_info[] __initdata = { +#if defined(CONFIG_AD9548) || defined(CONFIG_AD9548_MODULE) + { + .modalias = "ad9548", + .max_speed_hz = 10000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_LPC, + .chip_select = 2, /* AD9548 */ + .mode = SPI_MODE_0 | SPI_3WIRE, + }, + { + .modalias = "ad9548", + .max_speed_hz = 10000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_HPC, + .chip_select = 2, /* AD9548 */ + .mode = SPI_MODE_0 | SPI_3WIRE, + }, +#endif +#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE) + { + .modalias = "spidev", + .max_speed_hz = 10000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_LPC, + .chip_select = 2, /* AD9548 */ + }, + { + .modalias = "spidev", + .max_speed_hz = 10000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_HPC, + .chip_select = 2, /* AD9548 */ + }, +#endif +#if defined(CONFIG_AD9523) || defined(CONFIG_AD9523_MODULE) + { + .modalias = "ad9523", + .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_LPC, + .chip_select = 3, /* GPIO controlled SSEL */ + .platform_data = &ad9523_pdata_lpc, /* spi_driver specific config */ + .mode = SPI_MODE_0 | SPI_3WIRE, + }, + { + .modalias = "ad9523", + .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_HPC, + .chip_select = 3, /* GPIO controlled SSEL */ + .platform_data = &ad9523_pdata_hpc, /* spi_driver specific config */ + .mode = SPI_MODE_0 | SPI_3WIRE, + }, +#endif +#if defined(CONFIG_AD8366) || defined(CONFIG_AD8366_MODULE) + { + .modalias = "ad8366", + .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_LPC, + .chip_select = 6, /* GPIO controlled SSEL */ + .platform_data = "ad8366-lpc", /* spi_driver specific config */ + .mode = SPI_MODE_0 | SPI_3WIRE, + }, + { + .modalias = "ad8366", + .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_HPC, + .chip_select = 6, /* GPIO controlled SSEL */ + .platform_data = "ad8366-hpc", /* spi_driver specific config */ + .mode = SPI_MODE_0 | SPI_3WIRE, + }, +#endif +#if defined(CONFIG_ADF4350) || defined(CONFIG_ADF4350_MODULE) + { + .modalias = "adf4351", + .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_LPC, + .chip_select = 4, /* GPIO controlled SSEL */ + .platform_data = &adf4350_rx_pdata_lpc, /* No spi_driver specific config */ + .mode = SPI_MODE_0, + }, + { + .modalias = "adf4351", + .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_LPC, + .chip_select = 5, /* GPIO controlled SSEL */ + .platform_data = &adf4350_tx_pdata_lpc, /* No spi_driver specific config */ + .mode = SPI_MODE_0, + }, + { + .modalias = "adf4351", + .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_HPC, + .chip_select = 4, /* GPIO controlled SSEL */ + .platform_data = &adf4350_rx_pdata_hpc, /* No spi_driver specific config */ + .mode = SPI_MODE_0, + }, + { + .modalias = "adf4351", + .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_HPC, + .chip_select = 5, /* GPIO controlled SSEL */ + .platform_data = &adf4350_tx_pdata_hpc, /* No spi_driver specific config */ + .mode = SPI_MODE_0, + }, + +#endif +}; + +static int __init xcomm_device_probe(void) +{ + spi_register_board_info(xcomm_spi_board_info, ARRAY_SIZE(xcomm_spi_board_info)); + + return 0; +} +device_initcall(xcomm_device_probe); From ad2b289c1a5f4240ded170aef199b101ac420187 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 24 Apr 2012 12:58:29 +0200 Subject: [PATCH 120/261] iio: frequency: Add AD9548 Network Clock Generator/Synchronizer driver Signed-off-by: Michael Hennerich --- drivers/staging/iio/frequency/Kconfig | 10 + drivers/staging/iio/frequency/Makefile | 1 + drivers/staging/iio/frequency/ad9548.c | 287 +++++++++++++++++++++++++ 3 files changed, 298 insertions(+) create mode 100644 drivers/staging/iio/frequency/ad9548.c diff --git a/drivers/staging/iio/frequency/Kconfig b/drivers/staging/iio/frequency/Kconfig index ba94957801311..80665121ade05 100644 --- a/drivers/staging/iio/frequency/Kconfig +++ b/drivers/staging/iio/frequency/Kconfig @@ -18,6 +18,16 @@ config AD9523 To compile this driver as a module, choose M here: the module will be called ad9523. +config AD9548 + tristate "Analog Devices AD9548 Network Clock Generator/Synchronizer" + depends on SPI + help + Say yes here to build support for Analog Devices AD9548 + Quad/Octal Input Network Clock Generator/Synchronizer. + + To compile this driver as a module, choose M here: the + module will be called ad9548. + endmenu menu "Direct Digital Synthesis" diff --git a/drivers/staging/iio/frequency/Makefile b/drivers/staging/iio/frequency/Makefile index 364c240e78c2e..3f82cd368c149 100644 --- a/drivers/staging/iio/frequency/Makefile +++ b/drivers/staging/iio/frequency/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_AD9951) += ad9951.o obj-$(CONFIG_ADF4350) += adf4350.o obj-$(CONFIG_AD9122_CF) += cf_ad9122.o obj-$(CONFIG_AD9122_CF_DAC) += ad9122.o +obj-$(CONFIG_AD9548) += ad9548.o diff --git a/drivers/staging/iio/frequency/ad9548.c b/drivers/staging/iio/frequency/ad9548.c new file mode 100644 index 0000000000000..02cd754a9bcaa --- /dev/null +++ b/drivers/staging/iio/frequency/ad9548.c @@ -0,0 +1,287 @@ +/* + * AD9548 SPI Network Clock Generator/Synchronizer + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" + +#define AD_READ (1 << 15) +#define AD_WRITE (0 << 15) +#define AD_CNT(x) (((x) - 1) << 13) +#define AD_ADDR(x) ((x) & 0xFFF) +#define WAIT_B 0xFFFF +#define CHIPID_AD9548 0x48 + +static const unsigned short ad9548_regs[][2] = { + {0x0000, 0x30}, /* Reset */ + {0x0000, 0x10}, + {0x0000, 0x10}, + {0x0000, 0x10}, + {0x0000, 0x10}, + {0x0000, 0x10}, + {0x0100, 0x18}, /* System clock */ + {0x0101, 0x28}, + {0x0102, 0x45}, + {0x0103, 0x43}, + {0x0104, 0xDE}, + {0x0105, 0x13}, + {0x0106, 0x01}, + {0x0107, 0x00}, + {0x0108, 0x00}, + {0x0005, 0x01}, /* I/O Update */ + {0x0A02, 0x01}, /* Calibrate sysem clock */ + {0x0005, 0x01}, + {WAIT_B, 0x00}, + {0x0A02, 0x00}, + {0x0005, 0x01}, + {0x0208, 0x00}, /* IRQ Pin Output Mode */ + {0x0209, 0x00}, /* IRQ Masks */ + {0x020A, 0x00}, + {0x020B, 0x00}, + {0x020C, 0x00}, + {0x020D, 0x00}, + {0x020E, 0x00}, + {0x020F, 0x00}, + {0x0210, 0x00}, + {0x0211, 0x00}, /* Watchdog timer */ + {0x0212, 0x00}, + {0x0213, 0xFF}, /* Auxiliary DAC */ + {0x0214, 0x01}, + {0x0300, 0x29}, /* DPLL */ + {0x0301, 0x5C}, + {0x0302, 0x8F}, + {0x0303, 0xC2}, + {0x0304, 0xF5}, + {0x0305, 0x28}, + {0x0307, 0x00}, + {0x0308, 0x00}, + {0x0309, 0x00}, + {0x030A, 0xFF}, + {0x030B, 0xFF}, + {0x030C, 0xFF}, + {0x030D, 0x00}, + {0x030E, 0x00}, + {0x030F, 0x00}, + {0x0310, 0x00}, + {0x0311, 0x00}, + {0x0312, 0x00}, + {0x0313, 0x00}, + {0x0314, 0xE8}, + {0x0315, 0x03}, + {0x0316, 0x00}, + {0x0317, 0x00}, + {0x0318, 0x30}, + {0x0319, 0x75}, + {0x031A, 0x00}, + {0x031B, 0x00}, + {0x0306, 0x01}, /* Update TW */ + {0x0400, 0x0C}, /* Clock distribution output */ + {0x0401, 0x03}, + {0x0402, 0x00}, + {0x0403, 0x02}, + {0x0404, 0x04}, + {0x0405, 0x08}, + {0x0406, 0x03}, + {0x0407, 0x03}, + {0x0408, 0x03}, + {0x0409, 0x00}, + {0x040A, 0x00}, + {0x040B, 0x00}, + {0x040C, 0x03}, + {0x040D, 0x00}, + {0x040E, 0x00}, + {0x040F, 0x00}, + {0x0410, 0x00}, + {0x0411, 0x00}, + {0x0412, 0x00}, + {0x0413, 0x00}, + {0x0414, 0x00}, + {0x0415, 0x00}, + {0x0416, 0x00}, + {0x0417, 0x00}, + {0x0500, 0xFE}, /* Reference inputs */ + {0x0501, 0x00}, + {0x0502, 0x00}, + {0x0503, 0x08}, + {0x0504, 0x00}, + {0x0505, 0x00}, + {0x0506, 0x00}, + {0x0507, 0x00}, + {0x0600, 0x00}, /* Profiles are 0x0600-0x07FF */ + {0x0601, 0x55}, /* Profile 0 */ + {0x0602, 0xA0}, /* 30MHz input from FPGA, 122.880MHz output clock */ + {0x0603, 0xFC}, + {0x0604, 0x01}, + {0x0605, 0x00}, + {0x0606, 0x00}, + {0x0607, 0x00}, + {0x0608, 0xE8}, + {0x0609, 0x03}, + {0x060A, 0x00}, + {0x060B, 0xE8}, + {0x060C, 0x03}, + {0x060D, 0x00}, + {0x060E, 0x88}, + {0x060F, 0x13}, + {0x0610, 0x88}, + {0x0611, 0x13}, + {0x0612, 0x0E}, + {0x0613, 0xB2}, + {0x0614, 0x08}, + {0x0615, 0x82}, + {0x0616, 0x62}, + {0x0617, 0x42}, + {0x0618, 0xD8}, + {0x0619, 0x47}, + {0x061A, 0x21}, + {0x061B, 0xCB}, + {0x061C, 0xC4}, + {0x061D, 0x05}, + {0x061E, 0x7F}, + {0x061F, 0x00}, + {0x0620, 0x00}, + {0x0621, 0x00}, + {0x0622, 0x0B}, + {0x0623, 0x02}, + {0x0624, 0x00}, + {0x0625, 0x00}, + {0x0626, 0x26}, + {0x0627, 0xB0}, + {0x0628, 0x00}, + {0x0629, 0x10}, + {0x062A, 0x27}, + {0x062B, 0x20}, + {0x062C, 0x44}, + {0x062D, 0xF4}, + {0x062E, 0x01}, + {0x062F, 0x00}, + {0x0630, 0x20}, + {0x0631, 0x44}, + {0x0005, 0x01}, /* I/O Update */ + {0x0A0E, 0x01}, /* Force validation timeout */ + {0x0005, 0x01}, /* I/O Update */ + {0x0A02, 0x02}, /* Sync distribution */ + {0x0005, 0x01}, + {0x0A02, 0x00}, + {0x0005, 0x01}, +}; + +static int ad9548_read(struct spi_device *spi, unsigned reg) +{ + unsigned char buf[3]; + int ret; + u16 cmd; + + cmd = AD_READ | AD_CNT(1) | AD_ADDR(reg); + buf[0] = cmd >> 8; + buf[1] = cmd & 0xFF; + + + ret = spi_write_then_read(spi, &buf[0], 2, &buf[2], 1); + if (ret < 0) + return ret; + + return buf[2]; +} + +static int ad9548_write(struct spi_device *spi, + unsigned reg, unsigned val) +{ + unsigned char buf[3]; + int ret; + u16 cmd; + + cmd = AD_WRITE | AD_CNT(1) | AD_ADDR(reg); + buf[0] = cmd >> 8; + buf[1] = cmd & 0xFF; + buf[2] = val; + + ret = spi_write(spi, buf, 3); + if (ret < 0) + return ret; + + return 0; +} + +static int __devinit ad9548_probe(struct spi_device *spi) +{ + int i, ret, timeout; + + ret = ad9548_read(spi, 0x3); + if (ret < 0) + return ret; + if (ret != CHIPID_AD9548) { + dev_err(&spi->dev, "Unrecognized CHIP_ID 0x%X\n", ret); + return -ENODEV; + } + + for (i = 0; i < ARRAY_SIZE(ad9548_regs); i++) + switch (ad9548_regs[i][0]) { + case WAIT_B: + timeout = 100; + do { + ret = ad9548_read(spi, 0xD01); + if (ret < 0) + return ret; + if (ret & BIT(0)) + break; + mdelay(1); + } while (timeout--); + + if (timeout <= 0) + return -ETIMEDOUT; + break; + default: + ret = ad9548_write(spi, ad9548_regs[i][0], + ad9548_regs[i][1]); + if (ret < 0) + return ret; + break; + } + + spi_set_drvdata(spi, NULL); + dev_info(&spi->dev, "Rev. 0x%X probed\n", ad9548_read(spi, 0x2)); + + return 0; +} + +static int ad9548_remove(struct spi_device *spi) +{ + spi_set_drvdata(spi, NULL); + + return 0; +} + +static const struct spi_device_id ad9548_id[] = { + {"ad9548", 0}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad9548_id); + +static struct spi_driver ad9548_driver = { + .driver = { + .name = "ad9548", + .owner = THIS_MODULE, + }, + .probe = ad9548_probe, + .remove = __devexit_p(ad9548_remove), + .id_table = ad9548_id, +}; +module_spi_driver(ad9548_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD9548"); +MODULE_LICENSE("GPL v2"); From b0c26ef481155becf019bf16ff2cb5d11d742a29 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 24 Apr 2012 14:09:28 +0200 Subject: [PATCH 121/261] iio: frequency: AD9523 Add device name via pdata, disable unused outputs Signed-off-by: Michael Hennerich --- drivers/staging/iio/frequency/ad9523.c | 18 +++++++++++++++--- drivers/staging/iio/frequency/ad9523.h | 3 +++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/frequency/ad9523.c b/drivers/staging/iio/frequency/ad9523.c index c43a7efc84ac3..1c1fff657ac2c 100644 --- a/drivers/staging/iio/frequency/ad9523.c +++ b/drivers/staging/iio/frequency/ad9523.c @@ -551,6 +551,7 @@ static int ad9523_setup(struct iio_dev *indio_dev) struct ad9523_state *st = iio_priv(indio_dev); struct ad9523_platform_data *pdata = st->pdata; struct ad9523_channel_spec *chan; + unsigned active_mask = 0; int ret, i; ret = ad9523_write(indio_dev, AD9523_SERIAL_PORT_CONFIG, @@ -599,7 +600,7 @@ static int ad9523_setup(struct iio_dev *indio_dev) AD_IF(osc_in_diff_en, AD9523_PLL1_OSC_IN_DIFF_EN) | AD_IF(osc_in_cmos_neg_inp_en, AD9523_PLL1_OSC_IN_CMOS_NEG_INP_EN) | AD_IF(refa_diff_rcv_en, AD9523_PLL1_REFA_DIFF_RCV_EN) | - AD_IF(refa_diff_rcv_en, AD9523_PLL1_REFB_DIFF_RCV_EN)); + AD_IF(refb_diff_rcv_en, AD9523_PLL1_REFB_DIFF_RCV_EN)); if (ret < 0) return ret; @@ -687,7 +688,8 @@ static int ad9523_setup(struct iio_dev *indio_dev) for (i = 0; i < pdata->num_channels; i++) { chan = &pdata->channels[i]; - if (chan->channel_num < 14) { + if (chan->channel_num <= AD9523_NUM_CHAN) { + active_mask |= (1 << chan->channel_num); ret = ad9523_write(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel_num), AD9523_CLOCK_DIST_DRIVER_MODE(chan->driver_mode) | @@ -716,6 +718,13 @@ static int ad9523_setup(struct iio_dev *indio_dev) } } + for (i = 0; i <= AD9523_NUM_CHAN; i++) + if (!(active_mask & (1 << i))) + ad9523_write(indio_dev, + AD9523_CHANNEL_CLOCK_DIST(i), + AD9523_CLOCK_DIST_DRIVER_MODE(TRISTATE) | + AD9523_CLOCK_DIST_PWR_DOWN_EN); + ret = ad9523_write(indio_dev, AD9523_POWER_DOWN_CTRL, 0); if (ret < 0) return ret; @@ -761,7 +770,8 @@ static int __devinit ad9523_probe(struct spi_device *spi) st->pdata = pdata; indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->name = (pdata->name[0] != 0) ? pdata->name : + spi_get_device_id(spi)->name; indio_dev->info = &ad9523_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->ad9523_channels; @@ -775,6 +785,8 @@ static int __devinit ad9523_probe(struct spi_device *spi) if (ret) goto error_disable_reg; + dev_info(&spi->dev, "probed %s\n", indio_dev->name); + return 0; error_disable_reg: diff --git a/drivers/staging/iio/frequency/ad9523.h b/drivers/staging/iio/frequency/ad9523.h index 5867ae06346cf..47dd26f54aeb0 100644 --- a/drivers/staging/iio/frequency/ad9523.h +++ b/drivers/staging/iio/frequency/ad9523.h @@ -240,6 +240,7 @@ enum driver_mode { /* AD9523_EEPROM_CTRL2 */ #define AD9523_EEPROM_CTRL2_REG2EEPROM (1 << 0) +#define AD9523_NUM_CHAN 13 struct ad9523_channel_spec { unsigned channel_num; @@ -311,6 +312,8 @@ struct ad9523_platform_data { /* Output Channel Configuration */ int num_channels; struct ad9523_channel_spec *channels; + + char name[SPI_NAME_SIZE]; }; #endif /* IIO_PLL_AD9523_H_ */ From fa470613418ed4512a217e8934e220d506e97ebe Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 24 Apr 2012 14:11:25 +0200 Subject: [PATCH 122/261] iio: frequency: cf_ad9122: Add support HDL version 2 Signed-off-by: Michael Hennerich --- drivers/staging/iio/frequency/cf_ad9122.c | 150 ++++++++++++++-------- drivers/staging/iio/frequency/cf_ad9122.h | 33 ++++- 2 files changed, 124 insertions(+), 59 deletions(-) diff --git a/drivers/staging/iio/frequency/cf_ad9122.c b/drivers/staging/iio/frequency/cf_ad9122.c index 473069e3c2de6..100b03baa63fd 100644 --- a/drivers/staging/iio/frequency/cf_ad9122.c +++ b/drivers/staging/iio/frequency/cf_ad9122.c @@ -39,13 +39,23 @@ struct dds_spidev { struct device *dev_spi; }; +static void ad9122_dds_sync_frame(struct ad9122_dds_state *st) { + dds_write(st, AD9122_DDS_FRAME, 0); + dds_write(st, AD9122_DDS_FRAME, AD9122_DDS_FRAME_SYNC); +} + +static void ad9122_dds_stop(struct ad9122_dds_state *st) { + dds_write(st, AD9122_DDS_CTRL, (st->vers_id > 1) ? + AD9122_DDS_CTRL_DDS_CLK_EN_V2 : AD9122_DDS_CTRL_DDS_CLK_EN_V1); +} + static u32 ad9122_ddsx(u32 phase, u32 sin_clk, u32 dac_clk) { u32 p_offset; u32 p_incr; - p_offset = (phase * 0xffff)/360; - p_incr = (sin_clk * 0xffff)/dac_clk; + p_offset = (phase * 0xffff) / 360; + p_incr = ((sin_clk * 0xffff) / dac_clk) | 1; return((p_offset << 16) | p_incr); } @@ -59,10 +69,10 @@ static void ad9122_dds_mem_init(struct ad9122_dds_state *st) { for (i = 0; i < ARRAY_SIZE(ad9122_ia_data); i++) { data = (sample << 24) | (addr << 16); - AD9122_DDS_OUT(st->regs + AD9122_DDS_MEM_CTRL, ((0 << 26) | data | ad9122_ia_data[i])); - AD9122_DDS_OUT(st->regs + AD9122_DDS_MEM_CTRL, ((1 << 26) | data | ad9122_ib_data[i])); - AD9122_DDS_OUT(st->regs + AD9122_DDS_MEM_CTRL, ((2 << 26) | data | ad9122_qa_data[i])); - AD9122_DDS_OUT(st->regs + AD9122_DDS_MEM_CTRL, ((3 << 26) | data | ad9122_qb_data[i])); + dds_write(st, AD9122_DDS_MEM_CTRL, ((0 << 26) | data | ad9122_ia_data[i])); + dds_write(st, AD9122_DDS_MEM_CTRL, ((1 << 26) | data | ad9122_ib_data[i])); + dds_write(st, AD9122_DDS_MEM_CTRL, ((2 << 26) | data | ad9122_qa_data[i])); + dds_write(st, AD9122_DDS_MEM_CTRL, ((3 << 26) | data | ad9122_qb_data[i])); sample++; if (sample >= 3) { addr++; @@ -90,14 +100,22 @@ static int ad9122_dds_read_raw(struct iio_dev *indio_dev, if (!chan->output) { return -EINVAL; } - reg = AD9122_DDS_IN(st->regs + AD9122_DDS_CTRL); - if (reg & (1 << (chan->channel * 2))) - *val = 1; - else - *val = 0; + reg = dds_read(st, AD9122_DDS_CTRL); + if (st->vers_id > 1) { + if (reg & 0x2) + *val = 1; + else + *val = 0; + + } else { + if (reg & (1 << (chan->channel * 2))) + *val = 1; + else + *val = 0; + } return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - reg = AD9122_DDS_IN(st->regs + AD9122_DDS_SCALE); + reg = dds_read(st, AD9122_DDS_SCALE); reg = (reg >> (chan->channel * 4)) & 0xF; if (!reg) { *val = 1; @@ -112,13 +130,13 @@ static int ad9122_dds_read_raw(struct iio_dev *indio_dev, *val = st->dac_clk; return IIO_VAL_INT; } - reg = AD9122_DDS_IN(st->regs + chan->address); + reg = dds_read(st, chan->address); val64 = (u64)(reg & 0xFFFF) * (u64)st->dac_clk; do_div(val64, 0xFFFF); *val = val64; return IIO_VAL_INT; case IIO_CHAN_INFO_PHASE: - reg = AD9122_DDS_IN(st->regs + chan->address); + reg = dds_read(st, chan->address); val64 = (u64)(reg >> 16) * 360000ULL; do_div(val64, 0xFFFF); *val = val64; @@ -138,19 +156,27 @@ static int ad9122_dds_write_raw(struct iio_dev *indio_dev, unsigned reg, ctrl_reg; int i; - ctrl_reg = AD9122_DDS_IN(st->regs + AD9122_DDS_CTRL); + ctrl_reg = dds_read(st, AD9122_DDS_CTRL); switch (mask) { case 0: if (!chan->output) { return -EINVAL; } - if (val) - ctrl_reg |= 1 << (chan->channel * 2); - else - ctrl_reg &= ~(1 << (chan->channel * 2)); - AD9122_DDS_OUT(st->regs + AD9122_DDS_CTRL, ctrl_reg); + if (st->vers_id > 1) { + if (val) + ctrl_reg |= 0x3; + else + ctrl_reg &= ~(0x2); + } else { + if (val) + ctrl_reg |= 1 << (chan->channel * 2); + else + ctrl_reg &= ~(1 << (chan->channel * 2)); + } + + dds_write(st, AD9122_DDS_CTRL, ctrl_reg); break; case IIO_CHAN_INFO_SCALE: if (val == 1) { @@ -160,14 +186,13 @@ static int ad9122_dds_write_raw(struct iio_dev *indio_dev, if (val2 == (1000000 >> i)) break; } - AD9122_DDS_OUT(st->regs + AD9122_DDS_CTRL, 0); - reg = AD9122_DDS_IN(st->regs + AD9122_DDS_SCALE); + ad9122_dds_stop(st); + reg = dds_read(st, AD9122_DDS_SCALE); reg &= ~(0xF << (chan->channel * 4)); reg |= (i << (chan->channel * 4)); - printk("%s: %d REG = 0x%X\n",__func__,__LINE__, reg); - AD9122_DDS_OUT(st->regs + AD9122_DDS_SCALE, reg); - AD9122_DDS_OUT(st->regs + AD9122_DDS_CTRL, ctrl_reg); + dds_write(st, AD9122_DDS_SCALE, reg); + dds_write(st, AD9122_DDS_CTRL, ctrl_reg); break; case IIO_CHAN_INFO_FREQUENCY: if (!chan->output) { @@ -176,31 +201,33 @@ static int ad9122_dds_write_raw(struct iio_dev *indio_dev, } if (val > (st->dac_clk / 2)) return -EINVAL; - AD9122_DDS_OUT(st->regs + AD9122_DDS_CTRL, 0); - reg = AD9122_DDS_IN(st->regs + chan->address); + ad9122_dds_stop(st); + reg = dds_read(st, chan->address); reg &= 0xFFFF0000; val64 = (u64) val * 0xFFFFULL; do_div(val64, st->dac_clk); - reg |= val64 & 0xFFFF; - AD9122_DDS_OUT(st->regs + chan->address, reg); - AD9122_DDS_OUT(st->regs + AD9122_DDS_CTRL, ctrl_reg); + reg |= (val64 & 0xFFFF) | 1; + dds_write(st, chan->address, reg); + dds_write(st, AD9122_DDS_CTRL, ctrl_reg); break; case IIO_CHAN_INFO_PHASE: if (val < 0 || val > 360000) return -EINVAL; - AD9122_DDS_OUT(st->regs + AD9122_DDS_CTRL, 0); - reg = AD9122_DDS_IN(st->regs + chan->address); + ad9122_dds_stop(st); + reg = dds_read(st, chan->address); reg &= 0x0000FFFF; val64 = (u64) val * 0xFFFFULL; do_div(val64, 360000); reg |= val64 << 16; - AD9122_DDS_OUT(st->regs + chan->address, reg); - AD9122_DDS_OUT(st->regs + AD9122_DDS_CTRL, ctrl_reg); + dds_write(st, chan->address, reg); + dds_write(st, AD9122_DDS_CTRL, ctrl_reg); break; default: return -EINVAL; } + ad9122_dds_sync_frame(st); + return 0; } @@ -303,6 +330,17 @@ static int dds_attach_spi_client(struct device *dev, void *data) return 0; } + +/* Match table for of_platform binding */ +static const struct of_device_id ad9122_dds_of_match[] __devinitconst = { + { .compatible = "xlnx,cf-ad9122-core-1.00.a", .data = (void*) 1}, + { .compatible = "xlnx,cf-ad9739a-core-1.00.a", .data = (void*) 1}, + { .compatible = "xlnx,cf-ad9122x2-core-1.00.a", .data = (void*) 1}, + { .compatible = "xlnx,cf-ad9122-core-2.00.a", .data = (void*) 2}, +{ /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, ad9122_dds_of_match); + /** * ad9122_dds_of_probe - probe method for the AIM device. * @of_dev: pointer to OF device structure @@ -323,6 +361,9 @@ static int __devinit ad9122_dds_of_probe(struct platform_device *op) struct ad9122_converter *conv; int ret; + const struct of_device_id *of_id = + of_match_device(ad9122_dds_of_match, &op->dev); + dev_info(dev, "Device Tree Probing \'%s\'\n", op->dev.of_node->name); @@ -354,6 +395,12 @@ static int __devinit ad9122_dds_of_probe(struct platform_device *op) dev_set_drvdata(dev, indio_dev); + if (of_id && of_id->data) + st->vers_id = (unsigned) of_id->data; + else + goto failed1; + + /* Get iospace for the device */ ret = of_address_to_resource(op->dev.of_node, 0, &st->r_mem); if (ret) { @@ -404,22 +451,29 @@ static int __devinit ad9122_dds_of_probe(struct platform_device *op) ad9122_dds_mem_init(st); - AD9122_DDS_OUT(st->regs + 0x04, 0x0); - AD9122_DDS_OUT(st->regs + 0x20, 0x1111); /* divide by 4 */ - AD9122_DDS_OUT(st->regs + 0x08, ad9122_ddsx(90, 40, 492)); - AD9122_DDS_OUT(st->regs + 0x0c, ad9122_ddsx(90, 40, 492)); - AD9122_DDS_OUT(st->regs + 0x10, ad9122_ddsx( 0, 40, 492)); - AD9122_DDS_OUT(st->regs + 0x14, ad9122_ddsx( 0, 40, 492)); - AD9122_DDS_OUT(st->regs + 0x04, 0x1ff); /* clk, dds enable & ddsx select */ + dds_write(st, AD9122_DDS_CTRL, 0x0); + dds_write(st, 0x20, 0x1111); /* divide by 4 */ + dds_write(st, 0x08, ad9122_ddsx(90, 40, 492)); + dds_write(st, 0x0c, ad9122_ddsx(90, 40, 492)); + dds_write(st, 0x10, ad9122_ddsx( 0, 40, 492)); + dds_write(st, 0x14, ad9122_ddsx( 0, 40, 492)); + if (st->vers_id > 1) + dds_write(st, AD9122_DDS_CTRL, 0x3); /* clk, dds enable & ddsx select */ + else + dds_write(st, AD9122_DDS_CTRL, 0x1ff); /* clk, dds enable & ddsx select */ + + ad9122_dds_sync_frame(st); ret = iio_device_register(indio_dev); if (ret) goto failed3; - dev_info(dev, "Analog Devices AD9122_DDS (0x%X) at 0x%08llX mapped" + dev_info(dev, "Analog Devices AD9122_DDS %s (0x%X) at 0x%08llX mapped" " to 0x%p, probed DDS %s\n", - AD9122_DDS_IN(st->regs + AD9122_DDS_VERSION_ID), - (unsigned long long)phys_addr, st->regs, st->chip_info->name); + (dds_read(st, AD9122_DDS_PCORE_IDENT) & + AD9122_DDS_PCORE_IDENT_SLAVE) ? "SLAVE" : "MASTER", + dds_read(st, AD9122_DDS_VERSION_ID), + (unsigned long long)phys_addr, st->regs, st->chip_info->name); return 0; /* success */ @@ -462,14 +516,6 @@ static int __devexit ad9122_dds_of_remove(struct platform_device *op) return 0; } -/* Match table for of_platform binding */ -static const struct of_device_id ad9122_dds_of_match[] __devinitconst = { - { .compatible = "xlnx,cf-ad9122-core-1.00.a", }, - { .compatible = "xlnx,cf-ad9739a-core-1.00.a", }, -{ /* end of list */ }, -}; -MODULE_DEVICE_TABLE(of, ad9122_dds_of_match); - static struct platform_driver ad9122_dds_of_driver = { .driver = { .name = DRIVER_NAME, diff --git a/drivers/staging/iio/frequency/cf_ad9122.h b/drivers/staging/iio/frequency/cf_ad9122.h index 6f84c00bea8a8..932b9e37a7935 100644 --- a/drivers/staging/iio/frequency/cf_ad9122.h +++ b/drivers/staging/iio/frequency/cf_ad9122.h @@ -49,9 +49,17 @@ #define AD9122_DDS_2B_OUTPUT_CTRL 0x14 #define AD9122_DDS_MEM_CTRL 0x18 #define AD9122_DDS_SCALE 0x20 +#define AD9122_DDS_FRAME 0x24 +#define AD9122_DDS_PCORE_IDENT 0x48 -#define AD9122_DDS_CTRL_DDS_CLK_EN (1 << 8) +#define AD9122_DDS_CTRL_DDS_CLK_EN_V1 (1 << 8) +#define AD9122_DDS_CTRL_DDS_CLK_EN_V2 (1 << 0) +/* AD9122_DDS_FRAME */ +#define AD9122_DDS_FRAME_SYNC 0x1 + +/* AD9122_DDS_PCORE_IDENT */ +#define AD9122_DDS_PCORE_IDENT_SLAVE 0x1 /* AD9122 internal registers */ @@ -65,12 +73,6 @@ #define AD9122_Q_DAC_FS_ADJ 0x45 #define AD9122_I_AUX_DAC 0x43 - -/* IO accessors - */ -#define AD9122_DDS_OUT(addr, val) (iowrite32(val, addr)) -#define AD9122_DDS_IN(addr) (ioread32(addr)) - enum { ID_AD9122, ID_AD9739A, @@ -91,6 +93,7 @@ struct ad9122_dds_state { unsigned int flags; const struct ad9122_dds_chip_info *chip_info; unsigned long dac_clk; + unsigned vers_id; }; struct ad9122_converter { @@ -112,6 +115,22 @@ static inline struct ad9122_converter *to_converter(struct device *dev) return ERR_PTR(-ENODEV); }; +/* + * IO accessors + */ + +static inline void dds_write(struct ad9122_dds_state *st, + unsigned reg, unsigned val) +{ + iowrite32(val, st->regs + reg); +} + +static inline unsigned int dds_read(struct ad9122_dds_state *st, unsigned reg) +{ + return ioread32(st->regs + reg); +} + + #if defined(CF_AD9122_WAVDATA) static u32 ad9122_ia_data[] = { 0x7fff, 0xbf16, 0xedc8, From 3e269924112a271c7b9a63def8b8a111cff87e7b Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 24 Apr 2012 14:13:05 +0200 Subject: [PATCH 123/261] iio: amplifiers: ad8366: abort probe on write error, add support for name via pdata Signed-off-by: Michael Hennerich --- drivers/staging/iio/amplifiers/ad8366.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/amplifiers/ad8366.c b/drivers/staging/iio/amplifiers/ad8366.c index 0815e3026b8d5..b042b6ce24548 100644 --- a/drivers/staging/iio/amplifiers/ad8366.c +++ b/drivers/staging/iio/amplifiers/ad8366.c @@ -154,18 +154,21 @@ static int __devinit ad8366_probe(struct spi_device *spi) st->spi = spi; indio_dev->dev.parent = &spi->dev; - indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->name = spi->dev.platform_data ? spi->dev.platform_data : + spi_get_device_id(spi)->name; indio_dev->info = &ad8366_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ad8366_channels; indio_dev->num_channels = ARRAY_SIZE(ad8366_channels); + ret = ad8366_write(indio_dev, 0 , 0); + if (ret < 0) + goto error_disable_reg; + ret = iio_device_register(indio_dev); if (ret) goto error_disable_reg; - ad8366_write(indio_dev, 0 , 0); - return 0; error_disable_reg: From 89b168df602088dbad8d5ebbb9e6da7cd44f45ef Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 24 Apr 2012 14:15:49 +0200 Subject: [PATCH 124/261] iio: frequency: ad9122: update default setup procedure Signed-off-by: Michael Hennerich --- drivers/staging/iio/frequency/ad9122.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/staging/iio/frequency/ad9122.c b/drivers/staging/iio/frequency/ad9122.c index 044deb939cfab..a245da8af80eb 100644 --- a/drivers/staging/iio/frequency/ad9122.c +++ b/drivers/staging/iio/frequency/ad9122.c @@ -13,14 +13,16 @@ #include #include #include +#include #include "../iio.h" - #include "cf_ad9122.h" #define CHIPID_AD9122 0x8 static const unsigned char ad9122_reg_defaults[][2] = { + {0x00, 0x00}, + {0x00, 0x20}, {0x00, 0x00}, {0x01, 0x10}, {0x03, 0x80}, @@ -63,6 +65,7 @@ static const unsigned char ad9122_reg_defaults[][2] = { {0x46, 0x00}, {0x47, 0x00}, {0x48, 0x02}, + {0x18, 0x02}, }; static int ad9122_read(struct spi_device *spi, unsigned reg) @@ -101,25 +104,26 @@ static int ad9122_setup(struct spi_device *spi, unsigned mode) for (i = 0; i < ARRAY_SIZE(ad9122_reg_defaults); i++) ad9122_write(spi, ad9122_reg_defaults[i][0], ad9122_reg_defaults[i][1]); - - ad9122_write(spi, 0x18, 0x2); i = 255; do { + mdelay(1); ret = ad9122_read(spi, 0x18); if (ret < 0) return ret; - } while (i-- && (ret & 0x2)); + } while (i-- && ((ret & (1 << 2) == 0))); ad9122_write(spi, 0x18, 0x0); + ad9122_write(spi, 0x10, 0x88); i = 255; do { - ret = ad9122_read(spi, 0x18); + mdelay(1); + ret = ad9122_read(spi, 0x12); if (ret < 0) return ret; - } while (i-- && !(ret & 0x2)); + } while (i-- && ((ret & (1 << 6)) == 0)); return 0; } From d3bae4afb3694590d63814f9e5bee336699e8b6a Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 24 Apr 2012 14:24:13 +0200 Subject: [PATCH 125/261] iio: adc: cf_ad9467: Add dco delay of property, add PCORE IDENT Signed-off-by: Michael Hennerich --- drivers/staging/iio/adc/cf_ad9467.h | 5 +++++ drivers/staging/iio/adc/cf_ad9467_core.c | 15 ++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/adc/cf_ad9467.h b/drivers/staging/iio/adc/cf_ad9467.h index 24bae295ae552..610d850afedb6 100644 --- a/drivers/staging/iio/adc/cf_ad9467.h +++ b/drivers/staging/iio/adc/cf_ad9467.h @@ -20,6 +20,8 @@ #define AD9467_PCORE_DMA_STAT 0x10 #define AD9467_PCORE_ADC_STAT 0x14 #define AD9467_PCORE_PN_ERR_CTRL 0x24 +#define AD9467_PCORE_IDENT 0x28 + /* AD9467_PCORE_SPI_CTRL */ #define AD9647_SPI_START (1 << 25) @@ -51,6 +53,9 @@ #define AD9467_PN23_EN (1 << 0) #define AD9467_PN9_EN (0 << 0) +/* AD9467_PCORE_IDENT */ +#define AD9467_PCORE_IDENT_SLAVE 0x1 + /* * ADI High-Speed ADC common spi interface registers * See Application-Note AN-877 diff --git a/drivers/staging/iio/adc/cf_ad9467_core.c b/drivers/staging/iio/adc/cf_ad9467_core.c index 206fe38ecfd68..731de0dca61cc 100644 --- a/drivers/staging/iio/adc/cf_ad9467_core.c +++ b/drivers/staging/iio/adc/cf_ad9467_core.c @@ -370,7 +370,7 @@ static int __devinit aim_of_probe(struct platform_device *op) struct of_phandle_args dma_spec; dma_cap_mask_t mask; resource_size_t remap_size, phys_addr; - unsigned def_mode; + unsigned def_mode, dco_delay; int ret; dev_info(dev, "Device Tree Probing \'%s\'\n", @@ -490,6 +490,13 @@ static int __devinit aim_of_probe(struct platform_device *op) aim_spi_write(st, ADC_REG_OUTPUT_MODE, def_mode); aim_spi_write(st, ADC_REG_TEST_IO, TESTMODE_OFF); + + ret = of_property_read_u32(op->dev.of_node, + "dco-output-delay", + &dco_delay); + if (!ret) { + aim_spi_write(st, ADC_REG_OUTPUT_DELAY, dco_delay); + } aim_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); aim_configure_ring(indio_dev); @@ -504,10 +511,12 @@ static int __devinit aim_of_probe(struct platform_device *op) goto failed4; dev_info(dev, "ADI AIM (0x%X) at 0x%08llX mapped to 0x%p," - " DMA-%d probed ADC %s\n", + " DMA-%d probed ADC %s as %s\n", aim_read(st, AD9467_PCORE_VERSION), (unsigned long long)phys_addr, st->regs, - st->rx_chan->chan_id, st->chip_info->name); + st->rx_chan->chan_id, st->chip_info->name, + (aim_read(st, AD9467_PCORE_IDENT) & + AD9467_PCORE_IDENT_SLAVE) ? "SLAVE" : "MASTER"); if (iio_get_debugfs_dentry(indio_dev)) debugfs_create_file("pseudorandom_err_check", 0644, From 38544aea651a8f3f859f283eaa18f01b9bbc2ab9 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 24 Apr 2012 14:29:28 +0200 Subject: [PATCH 126/261] =?UTF-8?q?=C3=ADio:=20adc:=20Add=20HW=20FFT=20sup?= =?UTF-8?q?port?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michael Hennerich --- drivers/staging/iio/adc/Makefile | 1 + drivers/staging/iio/adc/cf_fft_core.c | 337 ++++++++++++++++++++++++++ drivers/staging/iio/adc/cf_fft_core.h | 16 ++ 3 files changed, 354 insertions(+) create mode 100644 drivers/staging/iio/adc/cf_fft_core.c create mode 100644 drivers/staging/iio/adc/cf_fft_core.h diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile index dfc1287da7b3d..6f830caf32aef 100644 --- a/drivers/staging/iio/adc/Makefile +++ b/drivers/staging/iio/adc/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_AD7298) += ad7298.o cf_ad9467-y := cf_ad9467_core.o cf_ad9467_ring.o obj-$(CONFIG_CF_AD9467) += cf_ad9467.o +obj-$(CONFIG_CF_FFT) += cf_fft_core.o obj-$(CONFIG_AD7291) += ad7291.o obj-$(CONFIG_AD7780) += ad7780.o diff --git a/drivers/staging/iio/adc/cf_fft_core.c b/drivers/staging/iio/adc/cf_fft_core.c new file mode 100644 index 0000000000000..32de84fb701de --- /dev/null +++ b/drivers/staging/iio/adc/cf_fft_core.c @@ -0,0 +1,337 @@ +/* + * ADI-FFT Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + * + * http://wiki.analog.com/resources/fpga/xilinx/ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/*************************************************************************** + * register definitions (fft) + * 5'h00: + * [31: 0]: version(32'h00010061) + * 5'h01: + * [31: 0]: up_cfg_data, fft cfg data (refer Xilinx fft core for details). + * 5'h02: + * [ 3: 3]: up_status_ovf, fft overflow (mapped to Xilinx fft core outputs). + * [ 2: 2]: up_status_lm, fft tlast missing (mapped to core). + * [ 1: 1]: up_status_lu, fft tlast unexpected (mapped to core). + * [ 0: 0]: up_status_fs, fft frame start (mapped to core). + ***************************************************************************/ + +#define FFT_PCORE_VERSION 0x0 +#define FFT_PCORE_CFG 0x4 +#define FFT_PCORE_STAT 0x8 + +struct fft_state { + struct device *dev; + struct mutex lock; + struct completion dma_complete; + struct dma_chan *rx_chan; + struct dma_chan *tx_chan; + void __iomem *regs; + int compl_stat; +}; + +struct fft_dma_params { + struct device_node *of_node; + enum dma_transfer_direction direction; + int chan_id; +}; + +struct fft_state *fft_state_glob; + +/* + * IO accessors + */ + +static inline void fft_write(struct fft_state *st, unsigned reg, unsigned val) +{ + iowrite32(val, st->regs + reg); +} + +static inline unsigned int fft_read(struct fft_state *st, unsigned reg) +{ + return ioread32(st->regs + reg); +} + +static bool fft_dma_filter(struct dma_chan *chan, void *param) +{ + struct fft_dma_params *p = param; + + return chan->device->dev->of_node == p->of_node && + chan->chan_id == p->chan_id; +} + +int fft_calculate(dma_addr_t src, dma_addr_t dest, unsigned int size) +{ + struct fft_state *st = fft_state_glob; + struct dma_async_tx_descriptor *tx_desc, *rx_desc; + dma_cookie_t tx_cookie, rx_cookie; + unsigned nfft = ilog2(size); + int ret = 0; + + if (st == NULL) + return -ENODEV; + + if (((1 << nfft) != size) || !src || !dest) + return -EINVAL; + + /* printk("%s: %d: SRC: %p DEST: %p SIZE %d NFFT %d\n",__func__,__LINE__, src, dest, size, nfft); */ + + mutex_lock(&st->lock); + + fft_write(st, FFT_PCORE_CFG, 0x10000 | nfft); + + tx_desc = dmaengine_prep_slave_single(st->tx_chan, src, size * 4, + DMA_TO_DEVICE, 0); + if (!tx_desc) { + dev_err(st->dev, + "Failed to allocate a dma descriptor\n"); + ret = -ENOMEM; + goto error_ret; + } + + tx_cookie = dmaengine_submit(tx_desc); + if (tx_cookie < 0) { + dev_err(st->dev, + "Failed to submit a dma transfer\n"); + ret = tx_cookie; + goto error_ret; + } + + rx_desc = dmaengine_prep_slave_single(st->rx_chan, dest, size * 4, + DMA_FROM_DEVICE, DMA_PREP_INTERRUPT); + if (!rx_desc) { + dev_err(st->dev, + "Failed to allocate a dma descriptor\n"); + ret = -ENOMEM; + goto error_ret; + } + + rx_desc->callback = (dma_async_tx_callback) complete; + rx_desc->callback_param = &st->dma_complete; + + rx_cookie = dmaengine_submit(rx_desc); + if (rx_cookie < 0) { + dev_err(st->dev, + "Failed to submit a dma transfer\n"); + ret = rx_cookie; + goto error_ret; + } + + dma_async_issue_pending(st->tx_chan); + dma_async_issue_pending(st->rx_chan); + + ret = wait_for_completion_interruptible_timeout(&st->dma_complete, + 4 * HZ); + if (ret == 0) { + ret = -ETIMEDOUT; + goto error_ret; + } else if (ret < 0) { + goto error_ret; + } + + ret = 0; + +error_ret: + mutex_unlock(&st->lock); + return ret; +} +EXPORT_SYMBOL_GPL(fft_calculate); + +/** + * fft_of_probe - probe method for the AIM device. + * @of_dev: pointer to OF device structure + * @match: pointer to the structure used for matching a device + * + * This function probes the AIM device in the device tree. + * It initializes the driver data structure and the hardware. + * It returns 0, if the driver is bound to the AIM device, or a negative + * value if there is an error. + */ +static int __devinit fft_of_probe(struct platform_device *op) +{ + struct device *dev = &op->dev; + struct fft_state *st; + struct resource r_mem; /* IO mem resources */ + struct fft_dma_params dma_params; + struct of_phandle_args dma_spec; + dma_cap_mask_t mask; + resource_size_t remap_size, phys_addr; + int ret; + + dev_info(dev, "Device Tree Probing \'%s\'\n", + op->dev.of_node->name); + + st = devm_kzalloc(&op->dev, sizeof(*st), GFP_KERNEL); + if (!st) { + dev_err(dev, "Not enough memory for device\n"); + return -ENOMEM; + } + + st->dev = dev; + dev_set_drvdata(dev, st); + mutex_init(&st->lock); + + /* Get iospace for the device */ + ret = of_address_to_resource(op->dev.of_node, 0, &r_mem); + if (ret) { + dev_err(dev, "invalid address\n"); + return ret; + } + + phys_addr = r_mem.start; + remap_size = resource_size(&r_mem); + if (!request_mem_region(phys_addr, remap_size, KBUILD_MODNAME)) { + dev_err(dev, "Couldn't lock memory region at 0x%08llX\n", + (unsigned long long)phys_addr); + ret = -EBUSY; + goto failed1; + } + + st->regs = ioremap(phys_addr, remap_size); + if (st->regs == NULL) { + dev_err(dev, "Couldn't ioremap memory at 0x%08llX\n", + (unsigned long long)phys_addr); + ret = -EFAULT; + goto failed2; + } + + /* Get dma channel for the device */ + ret = of_parse_phandle_with_args(op->dev.of_node, "dma-request", + "#dma-cells", 0, &dma_spec); + if (ret) { + dev_err(dev, "Couldn't parse dma-request\n"); + goto failed2; + } + + dma_params.of_node = dma_spec.np; + dma_params.chan_id = dma_spec.args[0]; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE | DMA_PRIVATE, mask); + + st->tx_chan = dma_request_channel(mask, fft_dma_filter, &dma_params); + if (!st->tx_chan) { + dev_err(dev, "failed to find tx dma device\n"); + goto failed2; + } + + /* Get dma channel for the device */ + ret = of_parse_phandle_with_args(op->dev.of_node, "dma-request", + "#dma-cells", 1, &dma_spec); + if (ret) { + dev_err(dev, "Couldn't parse dma-request\n"); + goto failed2; + } + + dma_params.of_node = dma_spec.np; + dma_params.chan_id = dma_spec.args[0]; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE | DMA_PRIVATE, mask); + + st->rx_chan = dma_request_channel(mask, fft_dma_filter, &dma_params); + if (!st->rx_chan) { + dev_err(dev, "failed to find rx dma device\n"); + goto failed2; + } + + init_completion(&st->dma_complete); + + dev_info(dev, "ADI-FFT (0x%X) at 0x%08llX mapped to 0x%p," + " DMA-%d, DMA-%d probed\n", + fft_read(st, FFT_PCORE_VERSION), + (unsigned long long)phys_addr, st->regs, + st->rx_chan->chan_id, st->tx_chan->chan_id); + + fft_state_glob = st; + + return 0; + +failed3: + dma_release_channel(st->rx_chan); +failed2: + release_mem_region(phys_addr, remap_size); +failed1: + dev_set_drvdata(dev, NULL); + + return ret; +} + +/** + * fft_of_remove - unbinds the driver from the AIM device. + * @of_dev: pointer to OF device structure + * + * This function is called if a device is physically removed from the system or + * if the driver module is being unloaded. It frees any resources allocated to + * the device. + */ +static int __devexit fft_of_remove(struct platform_device *op) +{ + struct device *dev = &op->dev; + struct resource r_mem; /* IO mem resources */ + struct fft_state *st = dev_get_drvdata(dev); + + dma_release_channel(st->rx_chan); + dma_release_channel(st->tx_chan); + + iounmap(st->regs); + + /* Get iospace of the device */ + if (of_address_to_resource(op->dev.of_node, 0, &r_mem)) + dev_err(dev, "invalid address\n"); + else + release_mem_region(r_mem.start, resource_size(&r_mem)); + + dev_set_drvdata(dev, NULL); + fft_state_glob = NULL; + + return 0; +} + +/* Match table for of_platform binding */ +static const struct of_device_id fft_of_match[] __devinitconst = { + { .compatible = "xlnx,cf-fft-core-1.00.a", }, + { /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, fft_of_match); + +static struct platform_driver fft_of_driver = { + .driver = { + .name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .of_match_table = fft_of_match, + }, + .probe = fft_of_probe, + .remove = __devexit_p(fft_of_remove), +}; + +module_platform_driver(fft_of_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices CF FFT"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/cf_fft_core.h b/drivers/staging/iio/adc/cf_fft_core.h new file mode 100644 index 0000000000000..a39d9f9341e29 --- /dev/null +++ b/drivers/staging/iio/adc/cf_fft_core.h @@ -0,0 +1,16 @@ +/* + * ADI-FFT Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + * + * http://wiki.analog.com/resources/fpga/xilinx/ + */ + +#ifndef ADI_FFT_H_ +#define ADI_FFT_H_ + +int fft_calculate(dma_addr_t src, dma_addr_t dest, unsigned int size); + +#endif /* ADI_FFT_H_ */ From 2abd0fe0708da00cba639de07ccd2fe417dbecb8 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 24 Apr 2012 14:46:51 +0200 Subject: [PATCH 127/261] iio: adc: ad9467: Start capture in ring enable, add support for HW FFT EXPERIMENTAL: HW FFT support is work in progress. Signed-off-by: Michael Hennerich --- drivers/staging/iio/adc/cf_ad9467.h | 4 + drivers/staging/iio/adc/cf_ad9467_ring.c | 183 ++++++++++++++++------- 2 files changed, 132 insertions(+), 55 deletions(-) diff --git a/drivers/staging/iio/adc/cf_ad9467.h b/drivers/staging/iio/adc/cf_ad9467.h index 610d850afedb6..4ec7c77dced10 100644 --- a/drivers/staging/iio/adc/cf_ad9467.h +++ b/drivers/staging/iio/adc/cf_ad9467.h @@ -133,10 +133,14 @@ struct aim_state { void __iomem *regs; void *buf_virt; dma_addr_t buf_phys; + int compl_stat; unsigned spi_ssel; unsigned ring_lenght; + unsigned rcount; + unsigned fftcount; unsigned bytes_per_datum; unsigned id; + /* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. diff --git a/drivers/staging/iio/adc/cf_ad9467_ring.c b/drivers/staging/iio/adc/cf_ad9467_ring.c index d55ae7fcc69a8..871b451de0ee9 100644 --- a/drivers/staging/iio/adc/cf_ad9467_ring.c +++ b/drivers/staging/iio/adc/cf_ad9467_ring.c @@ -18,6 +18,7 @@ #include "../buffer.h" #include "../ring_hw.h" #include "cf_ad9467.h" +#include "cf_fft_core.h" static int aim_read_first_n_hw_rb(struct iio_buffer *r, size_t count, char __user *buf) @@ -25,74 +26,46 @@ static int aim_read_first_n_hw_rb(struct iio_buffer *r, struct iio_hw_buffer *hw_ring = iio_to_hw_buf(r); struct iio_dev *indio_dev = hw_ring->private; struct aim_state *st = iio_priv(indio_dev); - struct dma_async_tx_descriptor *desc; - dma_cookie_t cookie; - unsigned rcount; int ret; + unsigned stat; mutex_lock(&st->lock); - if (count == 0) { - ret = -EINVAL; - goto error_ret; - } - - if (count % 8) - rcount = (count + 8) & 0xFFFFFFF8; - else - rcount = count; - st->buf_virt = dma_alloc_coherent(indio_dev->dev.parent, - PAGE_ALIGN(rcount), &st->buf_phys, - GFP_KERNEL); - if (st->buf_virt == NULL) { - ret = -ENOMEM; + ret = wait_for_completion_interruptible_timeout(&st->dma_complete, + 4 * HZ); + if (st->compl_stat < 0) { + ret = st->compl_stat; goto error_ret; - } - - desc = dmaengine_prep_slave_single(st->rx_chan, st->buf_phys, rcount, - DMA_FROM_DEVICE, DMA_PREP_INTERRUPT); - if (!desc) { + } else if (ret == 0) { + ret = -ETIMEDOUT; dev_err(indio_dev->dev.parent, - "Failed to allocate a dma descriptor\n"); - ret = -ENOMEM; - goto error_free; + "timeout: DMA_STAT 0x%X, ADC_STAT 0x%X\n", + aim_read(st, AD9467_PCORE_DMA_STAT), + aim_read(st, AD9467_PCORE_ADC_STAT)); + goto error_ret; + } else if (ret < 0) { + goto error_ret; } - desc->callback = (dma_async_tx_callback) complete; - desc->callback_param = &st->dma_complete; - - cookie = dmaengine_submit(desc); - if (cookie < 0) { - dev_err(indio_dev->dev.parent, - "Failed to submit a dma transfer\n"); - ret = cookie; - goto error_free; +#if defined(CONFIG_CF_FFT) + if (st->fftcount) { + ret = fft_calculate(st->buf_phys, st->buf_phys + st->fftcount, st->fftcount / 4); } +#endif + if (copy_to_user(buf, st->buf_virt + st->fftcount, count)) + ret = -EFAULT; - dma_async_issue_pending(st->rx_chan); - - aim_write(st, AD9467_PCORE_DMA_CTRL, 0); - aim_read(st, AD9467_PCORE_DMA_STAT); - aim_write(st, AD9467_PCORE_DMA_CTRL, - AD9647_DMA_CAP_EN | AD9647_DMA_CNT((rcount / 8) - 1)); - - ret = wait_for_completion_interruptible_timeout(&st->dma_complete, - 2 * HZ); - if (ret == 0) { - ret = -ETIMEDOUT; - goto error_free; - } else if (ret < 0) { - goto error_free; - } + stat = aim_read(st, AD9467_PCORE_ADC_STAT); - if (copy_to_user(buf, st->buf_virt, count)) - ret = -EFAULT; + if (stat) + dev_warn(indio_dev->dev.parent, + "STATUS: DMA_STAT 0x%X, ADC_STAT 0x%X\n", + aim_read(st, AD9467_PCORE_DMA_STAT), + stat); -error_free: - dma_free_coherent(indio_dev->dev.parent, PAGE_ALIGN(rcount), - st->buf_virt, st->buf_phys); - r->stufftoread = 0; error_ret: + r->stufftoread = 0; + mutex_unlock(&st->lock); return ret ? ret : count; @@ -168,6 +141,105 @@ static const struct iio_buffer_access_funcs aim_ring_access_funcs = { .get_bytes_per_datum = &aim_ring_get_bytes_per_datum, }; +static int __aim_hw_ring_state_set(struct iio_dev *indio_dev, bool state) +{ + struct aim_state *st = iio_priv(indio_dev); + struct dma_async_tx_descriptor *desc; + dma_cookie_t cookie; + int ret = 0; + + if (!state) { + if (!completion_done(&st->dma_complete)) { + st->compl_stat = -EPERM; + dmaengine_terminate_all(st->rx_chan); + complete(&st->dma_complete); + } + + dma_free_coherent(indio_dev->dev.parent, + PAGE_ALIGN(st->rcount + st->fftcount), + st->buf_virt, st->buf_phys); + return 0; + } + + st->compl_stat = 0; + + if (st->ring_lenght == 0) { + ret = -EINVAL; + goto error_ret; + } + + if (st->ring_lenght % 8) + st->rcount = (st->ring_lenght + 8) & 0xFFFFFFF8; + else + st->rcount = st->ring_lenght; + +#if defined(CONFIG_CF_FFT) + st->fftcount = st->rcount; +#else + st->fftcount = 0; +#endif + + st->buf_virt = dma_alloc_coherent(indio_dev->dev.parent, + PAGE_ALIGN(st->rcount + st->fftcount), &st->buf_phys, + GFP_KERNEL); + if (st->buf_virt == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + desc = dmaengine_prep_slave_single(st->rx_chan, st->buf_phys, st->rcount, + DMA_FROM_DEVICE, DMA_PREP_INTERRUPT); + if (!desc) { + dev_err(indio_dev->dev.parent, + "Failed to allocate a dma descriptor\n"); + ret = -ENOMEM; + goto error_free; + } + + desc->callback = (dma_async_tx_callback) complete; + desc->callback_param = &st->dma_complete; + + cookie = dmaengine_submit(desc); + if (cookie < 0) { + dev_err(indio_dev->dev.parent, + "Failed to submit a dma transfer\n"); + ret = cookie; + goto error_free; + } + + dma_async_issue_pending(st->rx_chan); + + aim_write(st, AD9467_PCORE_DMA_CTRL, 0); + aim_write(st, AD9467_PCORE_ADC_STAT, 0xFF); + aim_read(st, AD9467_PCORE_DMA_STAT); + aim_write(st, AD9467_PCORE_DMA_CTRL, + AD9647_DMA_CAP_EN | AD9647_DMA_CNT((st->rcount / 8) - 1)); + + return 0; + +error_free: + dma_free_coherent(indio_dev->dev.parent, PAGE_ALIGN(st->rcount), + st->buf_virt, st->buf_phys); +error_ret: + + return ret; +} + +static int aim_hw_ring_preenable(struct iio_dev *indio_dev) +{ + return __aim_hw_ring_state_set(indio_dev, 1); +} + +static int aim_hw_ring_postdisable(struct iio_dev *indio_dev) +{ + return __aim_hw_ring_state_set(indio_dev, 0); +} + +static const struct iio_buffer_setup_ops aim_ring_setup_ops = { + .preenable = &aim_hw_ring_preenable, + .postdisable = &aim_hw_ring_postdisable, +}; + int aim_configure_ring(struct iio_dev *indio_dev) { indio_dev->buffer = aim_rb_allocate(indio_dev); @@ -176,6 +248,7 @@ int aim_configure_ring(struct iio_dev *indio_dev) indio_dev->modes |= INDIO_BUFFER_HARDWARE; indio_dev->buffer->access = &aim_ring_access_funcs; + indio_dev->setup_ops = &aim_ring_setup_ops; return 0; } From 56588257ef943d102b1baa7cf3f35de0d7a4ed78 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 24 Apr 2012 15:38:31 +0200 Subject: [PATCH 128/261] configs: update ML605 defconfig Signed-off-by: Michael Hennerich --- arch/microblaze/configs/ml605_xcomm_defconfig | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/microblaze/configs/ml605_xcomm_defconfig b/arch/microblaze/configs/ml605_xcomm_defconfig index 182af56473134..2170239baa90b 100644 --- a/arch/microblaze/configs/ml605_xcomm_defconfig +++ b/arch/microblaze/configs/ml605_xcomm_defconfig @@ -157,8 +157,12 @@ CONFIG_INLINE_WRITE_UNLOCK_IRQ=y # # Platform options # -CONFIG_PLATFORM_GENERIC=y -# CONFIG_OPT_LIB_FUNCTION is not set +# CONFIG_PLATFORM_GENERIC is not set +CONFIG_PLATFORM_ML605_ADIXCOMM=y +# CONFIG_PLATFORM_KC705_ADIXCOMM is not set +# CONFIG_ADIXCOMM_SYNC is not set +CONFIG_OPT_LIB_FUNCTION=y +# CONFIG_OPT_LIB_ASM is not set # # Definitions for MICROBLAZE0 @@ -696,7 +700,7 @@ CONFIG_SPI_XCOMM=y # # SPI Protocol Masters # -CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_SPIDEV is not set # CONFIG_SPI_TLE62X0 is not set # @@ -938,6 +942,7 @@ CONFIG_AD8366=y # Clock Generator/Distribution # CONFIG_AD9523=y +CONFIG_AD9548=y # # Direct Digital Synthesis From 2f9d380900bd65b6bc058d00dd24f2a394b3cd27 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 24 Apr 2012 15:40:25 +0200 Subject: [PATCH 129/261] mb: dts: add device trees XCOMM LPC/HPC for ML605 and KC705 Signed-off-by: Michael Hennerich --- arch/microblaze/boot/dts/kc705_2xcomm_fft.dts | 461 ++++++++++++++++++ arch/microblaze/boot/dts/ml605_2xcomm_fft.dts | 458 +++++++++++++++++ 2 files changed, 919 insertions(+) create mode 100644 arch/microblaze/boot/dts/kc705_2xcomm_fft.dts create mode 100644 arch/microblaze/boot/dts/ml605_2xcomm_fft.dts diff --git a/arch/microblaze/boot/dts/kc705_2xcomm_fft.dts b/arch/microblaze/boot/dts/kc705_2xcomm_fft.dts new file mode 100644 index 0000000000000..74c5fe530d59b --- /dev/null +++ b/arch/microblaze/boot/dts/kc705_2xcomm_fft.dts @@ -0,0 +1,461 @@ +/* + * Device Tree Generator version: 1.3 + * + * (C) Copyright 2007-2008 Xilinx, Inc. + * (C) Copyright 2007-2009 Michal Simek + * + * Michal SIMEK + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * CAUTION: This file is automatically generated by libgen. + * Version: Xilinx EDK 13.4 EDK_O.87xd + * + * XPS project directory: device-tree_bsp_1 + */ + +/dts-v1/; +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,microblaze"; + model = "testing"; + DDR3_SDRAM: memory@c0000000 { + device_type = "memory"; + reg = < 0xc0000000 0x20000000 >; + } ; + aliases { + ethernet0 = &Ethernet_Lite; + serial0 = &RS232_Uart_1; + } ; + chosen { + bootargs = "console=ttyS0 root=/dev/ram"; + } ; + cpus { + #address-cells = <1>; + #cpus = <0x1>; + #size-cells = <0>; + microblaze_0: cpu@0 { + clock-frequency = <100000000>; + compatible = "xlnx,microblaze-8.20.b"; + d-cache-baseaddr = <0xc0000000>; + d-cache-highaddr = <0xdfffffff>; + d-cache-line-size = <0x10>; + d-cache-size = <0x4000>; + device_type = "cpu"; + i-cache-baseaddr = <0xc0000000>; + i-cache-highaddr = <0xdfffffff>; + i-cache-line-size = <0x20>; + i-cache-size = <0x4000>; + model = "microblaze,8.20.b"; + reg = <0>; + timebase-frequency = <100000000>; + xlnx,addr-tag-bits = <0xf>; + xlnx,allow-dcache-wr = <0x1>; + xlnx,allow-icache-wr = <0x1>; + xlnx,area-optimized = <0x0>; + xlnx,avoid-primitives = <0x0>; + xlnx,branch-target-cache-size = <0x0>; + xlnx,cache-byte-size = <0x4000>; + xlnx,d-axi = <0x1>; + xlnx,d-lmb = <0x1>; + xlnx,d-plb = <0x0>; + xlnx,data-size = <0x20>; + xlnx,dcache-addr-tag = <0xf>; + xlnx,dcache-always-used = <0x1>; + xlnx,dcache-byte-size = <0x4000>; + xlnx,dcache-data-width = <0x0>; + xlnx,dcache-force-tag-lutram = <0x0>; + xlnx,dcache-interface = <0x0>; + xlnx,dcache-line-len = <0x4>; + xlnx,dcache-use-fsl = <0x0>; + xlnx,dcache-use-writeback = <0x0>; + xlnx,dcache-victims = <0x0>; + xlnx,debug-enabled = <0x1>; + xlnx,div-zero-exception = <0x1>; + xlnx,dynamic-bus-sizing = <0x1>; + xlnx,ecc-use-ce-exception = <0x0>; + xlnx,edge-is-positive = <0x1>; + xlnx,endianness = <0x1>; + xlnx,family = "kintex7"; + xlnx,fault-tolerant = <0x0>; + xlnx,fpu-exception = <0x0>; + xlnx,freq = <0x5f5e100>; + xlnx,fsl-data-size = <0x20>; + xlnx,fsl-exception = <0x0>; + xlnx,fsl-links = <0x0>; + xlnx,i-axi = <0x0>; + xlnx,i-lmb = <0x1>; + xlnx,i-plb = <0x0>; + xlnx,icache-always-used = <0x1>; + xlnx,icache-data-width = <0x0>; + xlnx,icache-force-tag-lutram = <0x0>; + xlnx,icache-interface = <0x0>; + xlnx,icache-line-len = <0x8>; + xlnx,icache-streams = <0x1>; + xlnx,icache-use-fsl = <0x0>; + xlnx,icache-victims = <0x8>; + xlnx,ill-opcode-exception = <0x1>; + xlnx,instance = "microblaze_0"; + xlnx,interconnect = <0x2>; + xlnx,interconnect-m-axi-dc-read-issuing = <0x2>; + xlnx,interconnect-m-axi-dc-write-issuing = <0x20>; + xlnx,interconnect-m-axi-dp-read-issuing = <0x1>; + xlnx,interconnect-m-axi-dp-write-issuing = <0x1>; + xlnx,interconnect-m-axi-ic-read-issuing = <0x8>; + xlnx,interconnect-m-axi-ip-read-issuing = <0x1>; + xlnx,interrupt-is-edge = <0x0>; + xlnx,lockstep-slave = <0x0>; + xlnx,mmu-dtlb-size = <0x4>; + xlnx,mmu-itlb-size = <0x2>; + xlnx,mmu-privileged-instr = <0x0>; + xlnx,mmu-tlb-access = <0x3>; + xlnx,mmu-zones = <0x2>; + xlnx,number-of-pc-brk = <0x1>; + xlnx,number-of-rd-addr-brk = <0x0>; + xlnx,number-of-wr-addr-brk = <0x0>; + xlnx,opcode-0x0-illegal = <0x1>; + xlnx,optimization = <0x0>; + xlnx,pvr = <0x2>; + xlnx,pvr-user1 = <0x0>; + xlnx,pvr-user2 = <0x0>; + xlnx,reset-msr = <0x0>; + xlnx,sco = <0x0>; + xlnx,stream-interconnect = <0x0>; + xlnx,unaligned-exceptions = <0x1>; + xlnx,use-barrel = <0x1>; + xlnx,use-branch-target-cache = <0x0>; + xlnx,use-dcache = <0x1>; + xlnx,use-div = <0x1>; + xlnx,use-ext-brk = <0x1>; + xlnx,use-ext-nm-brk = <0x1>; + xlnx,use-extended-fsl-instr = <0x0>; + xlnx,use-fpu = <0x0>; + xlnx,use-hw-mul = <0x2>; + xlnx,use-icache = <0x1>; + xlnx,use-interrupt = <0x1>; + xlnx,use-mmu = <0x3>; + xlnx,use-msr-instr = <0x1>; + xlnx,use-pcmp-instr = <0x1>; + xlnx,use-stack-protection = <0x0>; + } ; + } ; + axi4lite_0: axi@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,axi-interconnect-1.05.a", "simple-bus"; + ranges ; + Ethernet_Lite: ethernet@40e00000 { + compatible = "xlnx,axi-ethernetlite-1.01.b", "xlnx,xps-ethernetlite-1.00.a"; + device_type = "network"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 8 0 >; + local-mac-address = [ 00 0a 35 bb 67 00 ]; + phy-handle = <&phy0>; + reg = < 0x40e00000 0x10000 >; + xlnx,duplex = <0x1>; + xlnx,family = "kintex7"; + xlnx,include-global-buffers = <0x0>; + xlnx,include-internal-loopback = <0x0>; + xlnx,include-mdio = <0x1>; + xlnx,include-phy-constraints = <0x1>; + xlnx,interconnect-s-axi-read-acceptance = <0x1>; + xlnx,interconnect-s-axi-write-acceptance = <0x1>; + xlnx,rx-ping-pong = <0x0>; + xlnx,s-axi-aclk-period-ps = <0x2710>; + xlnx,s-axi-id-width = <0x1>; + xlnx,s-axi-supports-narrow-burst = <0x0>; + xlnx,tx-ping-pong = <0x0>; + mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: phy@7 { + compatible = "marvell,88e1111"; + device_type = "ethernet-phy"; + reg = <7>; + } ; + } ; + } ; + RS232_Uart_1: serial@40600000 { + clock-frequency = <100000000>; + compatible = "xlnx,axi-uartlite-1.02.a", "xlnx,xps-uartlite-1.00.a"; + current-speed = <57600>; + device_type = "serial"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 9 0 >; + port-number = <0>; + reg = < 0x40600000 0x10000 >; + xlnx,baudrate = <0xe100>; + xlnx,data-bits = <0x8>; + xlnx,family = "kintex7"; + xlnx,odd-parity = <0x1>; + xlnx,s-axi-aclk-freq-hz = <0x5f5e100>; + xlnx,use-parity = <0x0>; + } ; + axi_dma_0: axidma@41e20000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + ranges = < 0x41e20000 0x41e20000 0x10000 >; + reg = < 0x41e20000 0x10000 >; +// xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@41e20030 { + compatible = "xlnx,axi-dma-s2mm-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 5 2 >; + xlnx,datawidth = <0x40>; + xlnx,include-dre = <0x0>; + } ; + } ; + axi_dma_1: axidma@41e00000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + ranges = < 0x41e00000 0x41e00000 0x10000 >; + reg = < 0x41e00000 0x10000 >; +// xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@41e00030 { + compatible = "xlnx,axi-dma-s2mm-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 4 2 >; + xlnx,datawidth = <0x40>; + xlnx,include-dre = <0x0>; + } ; + } ; + axi_iic_0: i2c@40800000 { + compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 6 2 >; + reg = < 0x40800000 0x10000 >; + xlnx,family = "kintex7"; + xlnx,gpo-width = <0x1>; + xlnx,iic-freq = <0x186a0>; + xlnx,s-axi-aclk-freq-hz = <0x5f5e100>; + xlnx,scl-inertial-delay = <0x5>; + xlnx,sda-inertial-delay = <0x5>; + xlnx,sda-level = <0x1>; + xlnx,ten-bit-adr = <0x0>; + mux@74 { + compatible = "pca9548"; + reg = <0x74>; + mux1: i2c@1 { /* HPC */ + #size-cells = <0>; + #address-cells = <1>; + cell-index = <1>; + spi_xcomm1: spi_xcomm1@58 { + compatible = "spi-xcomm"; + reg = <0x58>; + dac1_ad9122: ad9122@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ad9122"; + reg = <0>; + spi-max-frequency = <10000000>; + }; + + }; + }; + + mux2: i2c@2 { /* LPC */ + #size-cells = <0>; + #address-cells = <1>; + cell-index = <2>; + spi_xcomm0: spi_xcomm0@58 { + compatible = "spi-xcomm"; + reg = <0x58>; + dac0_ad9122: ad9122@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ad9122"; + reg = <0>; + spi-max-frequency = <10000000>; + }; + + }; + }; + }; + } ; + axi_intc_0: interrupt-controller@41200000 { + #interrupt-cells = <0x2>; + compatible = "xlnx,axi-intc-1.01.a", "xlnx,xps-intc-1.00.a"; + interrupt-controller ; + reg = < 0x41200000 0x10000 >; + xlnx,kind-of-intr = <0x300>; + xlnx,num-intr-inputs = <0xa>; + } ; +// axi_interconnect_1: axi@41e40000 { +// #address-cells = <1>; +// #size-cells = <1>; +// compatible = "xlnx,axi-interconnect-1.05.a", "simple-bus"; + axi_dma_2: axidma@41e40000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + ranges = < 0x41e40000 0x41e40000 0x10000 >; + reg = < 0x41e40000 0x10000 >; +// xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@41e40000 { + compatible = "xlnx,axi-dma-mm2s-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 1 2 >; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + } ; + dma-channel@41e40030 { + compatible = "xlnx,axi-dma-s2mm-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 0 2 >; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + } ; + } ; +// } ; + axi_timer_0: timer@41c00000 { + clock-frequency = <100000000>; + compatible = "xlnx,axi-timer-1.02.a", "xlnx,xps-timer-1.00.a"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 7 2 >; + reg = < 0x41c00000 0x10000 >; + xlnx,count-width = <0x20>; + xlnx,family = "kintex7"; + xlnx,gen0-assert = <0x1>; + xlnx,gen1-assert = <0x1>; + xlnx,one-timer-only = <0x0>; + xlnx,trig0-assert = <0x1>; + xlnx,trig1-assert = <0x1>; + } ; + axi_vdma_0: axivdma@7e220000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-vdma"; + ranges = < 0x7e220000 0x7e220000 0x10000 >; + reg = < 0x7e220000 0x10000 >; + xlnx,include-sg = <0x0>; + xlnx,num-fstores = <0x3>; + dma-channel@7e220000 { + compatible = "xlnx,axi-vdma-mm2s-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 3 2 >; + xlnx,datawidth = <0x40>; + xlnx,genlock-mode = <0x0>; + xlnx,include-dre = <0x0>; + } ; + } ; + axi_vdma_1: axivdma@7e200000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-vdma"; + ranges = < 0x7e200000 0x7e200000 0x10000 >; + reg = < 0x7e200000 0x10000 >; + xlnx,include-sg = <0x0>; + xlnx,num-fstores = <0x3>; + dma-channel@7e200000 { + compatible = "xlnx,axi-vdma-mm2s-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 2 2 >; + xlnx,datawidth = <0x40>; + xlnx,genlock-mode = <0x0>; + xlnx,include-dre = <0x0>; + } ; + } ; + cf_ad9122_core_0: cf-ad9122-core-lpc@73060000 { + compatible = "xlnx,cf-ad9122-core-2.00.a"; + reg = < 0x73060000 0x10000 >; + spibus-connected = <&dac0_ad9122>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "kintex7"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + cf_ad9122_core_1: cf-ad9122-core-hpc@73040000 { + compatible = "xlnx,cf-ad9122-core-2.00.a"; + reg = < 0x73040000 0x10000 >; + spibus-connected = <&dac1_ad9122>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "kintex7"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + cf_ad9643_core_0: cf-ad9643-core-lpc@73020000 { + compatible = "xlnx,cf-ad9643-core-1.00.a"; + reg = < 0x73020000 0x10000 >; + dma-request = <&axi_dma_0 0>; + spibus-connected = <&spi_xcomm0>; + spibus-slaveselect-connected = <0x1>; + dco-output-delay = <0x89>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "kintex7"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + cf_ad9643_core_1: cf-ad9643-core-hpc@73000000 { + compatible = "xlnx,cf-ad9643-core-1.00.a"; + reg = < 0x73000000 0x10000 >; + dma-request = <&axi_dma_1 0>; + spibus-connected = <&spi_xcomm1>; + spibus-slaveselect-connected = <0x1>; + dco-output-delay = <0x50>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "kintex7"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + cf_fft_core_0: cf-fft-core@7a200000 { + compatible = "xlnx,cf-fft-core-1.00.a"; + reg = < 0x7a200000 0x10000 >; + dma-request = <&axi_dma_2 0 + &axi_dma_2 1>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "kintex7"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + debug_module: debug@41400000 { + compatible = "xlnx,mdm-2.00.b"; + reg = < 0x41400000 0x10000 >; + xlnx,family = "kintex7"; + xlnx,interconnect = <0x2>; + xlnx,jtag-chain = <0x2>; + xlnx,mb-dbg-ports = <0x1>; + xlnx,use-uart = <0x1>; + } ; + } ; +} ; diff --git a/arch/microblaze/boot/dts/ml605_2xcomm_fft.dts b/arch/microblaze/boot/dts/ml605_2xcomm_fft.dts new file mode 100644 index 0000000000000..def8911556d6b --- /dev/null +++ b/arch/microblaze/boot/dts/ml605_2xcomm_fft.dts @@ -0,0 +1,458 @@ +/* + * Device Tree Generator version: 1.3 + * + * (C) Copyright 2007-2008 Xilinx, Inc. + * (C) Copyright 2007-2009 Michal Simek + * + * Michal SIMEK + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * CAUTION: This file is automatically generated by libgen. + * Version: Xilinx EDK 13.4 EDK_O.87xd + * + * XPS project directory: device-tree_bsp_1 + */ + +/dts-v1/; +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,microblaze"; + model = "testing"; + DDR3_SDRAM: memory@c0000000 { + device_type = "memory"; + reg = < 0xc0000000 0x20000000 >; + } ; + aliases { + ethernet0 = &Ethernet_Lite; + serial0 = &RS232_Uart_1; + } ; + chosen { + bootargs = "console=ttyS0 root=/dev/ram"; + } ; + cpus { + #address-cells = <1>; + #cpus = <0x1>; + #size-cells = <0>; + microblaze_0: cpu@0 { + clock-frequency = <100000000>; + compatible = "xlnx,microblaze-8.20.b"; + d-cache-baseaddr = <0xc0000000>; + d-cache-highaddr = <0xdfffffff>; + d-cache-line-size = <0x10>; + d-cache-size = <0x4000>; + device_type = "cpu"; + i-cache-baseaddr = <0xc0000000>; + i-cache-highaddr = <0xdfffffff>; + i-cache-line-size = <0x20>; + i-cache-size = <0x4000>; + model = "microblaze,8.20.b"; + reg = <0>; + timebase-frequency = <100000000>; + xlnx,addr-tag-bits = <0xf>; + xlnx,allow-dcache-wr = <0x1>; + xlnx,allow-icache-wr = <0x1>; + xlnx,area-optimized = <0x0>; + xlnx,avoid-primitives = <0x0>; + xlnx,branch-target-cache-size = <0x0>; + xlnx,cache-byte-size = <0x4000>; + xlnx,d-axi = <0x1>; + xlnx,d-lmb = <0x1>; + xlnx,d-plb = <0x0>; + xlnx,data-size = <0x20>; + xlnx,dcache-addr-tag = <0xf>; + xlnx,dcache-always-used = <0x1>; + xlnx,dcache-byte-size = <0x4000>; + xlnx,dcache-data-width = <0x0>; + xlnx,dcache-force-tag-lutram = <0x0>; + xlnx,dcache-interface = <0x0>; + xlnx,dcache-line-len = <0x4>; + xlnx,dcache-use-fsl = <0x0>; + xlnx,dcache-use-writeback = <0x0>; + xlnx,dcache-victims = <0x0>; + xlnx,debug-enabled = <0x1>; + xlnx,div-zero-exception = <0x1>; + xlnx,dynamic-bus-sizing = <0x1>; + xlnx,ecc-use-ce-exception = <0x0>; + xlnx,edge-is-positive = <0x1>; + xlnx,endianness = <0x1>; + xlnx,family = "virtex6"; + xlnx,fault-tolerant = <0x0>; + xlnx,fpu-exception = <0x0>; + xlnx,freq = <0x5f5e100>; + xlnx,fsl-data-size = <0x20>; + xlnx,fsl-exception = <0x0>; + xlnx,fsl-links = <0x0>; + xlnx,i-axi = <0x0>; + xlnx,i-lmb = <0x1>; + xlnx,i-plb = <0x0>; + xlnx,icache-always-used = <0x1>; + xlnx,icache-data-width = <0x0>; + xlnx,icache-force-tag-lutram = <0x0>; + xlnx,icache-interface = <0x0>; + xlnx,icache-line-len = <0x8>; + xlnx,icache-streams = <0x1>; + xlnx,icache-use-fsl = <0x0>; + xlnx,icache-victims = <0x8>; + xlnx,ill-opcode-exception = <0x1>; + xlnx,instance = "microblaze_0"; + xlnx,interconnect = <0x2>; + xlnx,interconnect-m-axi-dc-read-issuing = <0x2>; + xlnx,interconnect-m-axi-dc-write-issuing = <0x20>; + xlnx,interconnect-m-axi-dp-read-issuing = <0x1>; + xlnx,interconnect-m-axi-dp-write-issuing = <0x1>; + xlnx,interconnect-m-axi-ic-read-issuing = <0x8>; + xlnx,interconnect-m-axi-ip-read-issuing = <0x1>; + xlnx,interrupt-is-edge = <0x0>; + xlnx,lockstep-slave = <0x0>; + xlnx,mmu-dtlb-size = <0x4>; + xlnx,mmu-itlb-size = <0x2>; + xlnx,mmu-privileged-instr = <0x0>; + xlnx,mmu-tlb-access = <0x3>; + xlnx,mmu-zones = <0x2>; + xlnx,number-of-pc-brk = <0x1>; + xlnx,number-of-rd-addr-brk = <0x0>; + xlnx,number-of-wr-addr-brk = <0x0>; + xlnx,opcode-0x0-illegal = <0x1>; + xlnx,optimization = <0x0>; + xlnx,pvr = <0x2>; + xlnx,pvr-user1 = <0x0>; + xlnx,pvr-user2 = <0x0>; + xlnx,reset-msr = <0x0>; + xlnx,sco = <0x0>; + xlnx,stream-interconnect = <0x0>; + xlnx,unaligned-exceptions = <0x1>; + xlnx,use-barrel = <0x1>; + xlnx,use-branch-target-cache = <0x0>; + xlnx,use-dcache = <0x1>; + xlnx,use-div = <0x1>; + xlnx,use-ext-brk = <0x1>; + xlnx,use-ext-nm-brk = <0x1>; + xlnx,use-extended-fsl-instr = <0x0>; + xlnx,use-fpu = <0x0>; + xlnx,use-hw-mul = <0x2>; + xlnx,use-icache = <0x1>; + xlnx,use-interrupt = <0x1>; + xlnx,use-mmu = <0x3>; + xlnx,use-msr-instr = <0x1>; + xlnx,use-pcmp-instr = <0x1>; + xlnx,use-stack-protection = <0x0>; + } ; + } ; + axi4lite_0: axi@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,axi-interconnect-1.05.a", "simple-bus"; + ranges ; + Ethernet_Lite: ethernet@40e00000 { + compatible = "xlnx,axi-ethernetlite-1.01.b", "xlnx,xps-ethernetlite-1.00.a"; + device_type = "network"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 9 0 >; + local-mac-address = [ 00 0a 35 69 1c 00 ]; + phy-handle = <&phy0>; + reg = < 0x40e00000 0x10000 >; + xlnx,duplex = <0x1>; + xlnx,family = "virtex6"; + xlnx,include-global-buffers = <0x0>; + xlnx,include-internal-loopback = <0x0>; + xlnx,include-mdio = <0x1>; + xlnx,include-phy-constraints = <0x1>; + xlnx,interconnect-s-axi-read-acceptance = <0x1>; + xlnx,interconnect-s-axi-write-acceptance = <0x1>; + xlnx,rx-ping-pong = <0x0>; + xlnx,s-axi-aclk-period-ps = <0x2710>; + xlnx,s-axi-id-width = <0x1>; + xlnx,s-axi-supports-narrow-burst = <0x0>; + xlnx,tx-ping-pong = <0x0>; + mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: phy@7 { + compatible = "marvell,88e1111"; + device_type = "ethernet-phy"; + reg = <7>; + } ; + } ; + } ; + RS232_Uart_1: serial@40600000 { + clock-frequency = <100000000>; + compatible = "xlnx,axi-uartlite-1.02.a", "xlnx,xps-uartlite-1.00.a"; + current-speed = <57600>; + device_type = "serial"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 10 0 >; + port-number = <0>; + reg = < 0x40600000 0x10000 >; + xlnx,baudrate = <0xe100>; + xlnx,data-bits = <0x8>; + xlnx,family = "virtex6"; + xlnx,odd-parity = <0x1>; + xlnx,s-axi-aclk-freq-hz = <0x5f5e100>; + xlnx,use-parity = <0x0>; + } ; + axi_dma_0: axidma@41e00000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + ranges = < 0x41e00000 0x41e00000 0x10000 >; + reg = < 0x41e00000 0x10000 >; +// xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@41e00030 { + compatible = "xlnx,axi-dma-s2mm-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 7 2 >; + xlnx,datawidth = <0x40>; + xlnx,include-dre = <0x0>; + } ; + } ; + axi_dma_1: axidma@41e10000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + ranges = < 0x41e10000 0x41e10000 0x10000 >; + reg = < 0x41e10000 0x10000 >; +// xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@41e10030 { + compatible = "xlnx,axi-dma-s2mm-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 6 2 >; + xlnx,datawidth = <0x40>; + xlnx,include-dre = <0x0>; + } ; + } ; + axi_iic_0: i2c@40800000 { + compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 5 2 >; + reg = < 0x40800000 0x10000 >; + xlnx,family = "virtex6"; + xlnx,gpo-width = <0x1>; + xlnx,iic-freq = <0x186a0>; + xlnx,s-axi-aclk-freq-hz = <0x5f5e100>; + xlnx,scl-inertial-delay = <0x5>; + xlnx,sda-inertial-delay = <0x5>; + xlnx,sda-level = <0x1>; + xlnx,ten-bit-adr = <0x0>; + spi_xcomm0: spi_xcomm0@59 { + compatible = "spi-xcomm"; + reg = <0x59>; + dac0_ad9122: ad9122@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ad9122"; + reg = <0>; + spi-max-frequency = <10000000>; + }; + + }; + } ; + axi_iic_1: i2c@40810000 { + compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 4 2 >; + reg = < 0x40810000 0x10000 >; + xlnx,family = "virtex6"; + xlnx,gpo-width = <0x1>; + xlnx,iic-freq = <0x186a0>; + xlnx,s-axi-aclk-freq-hz = <0x5f5e100>; + xlnx,scl-inertial-delay = <0x5>; + xlnx,sda-inertial-delay = <0x5>; + xlnx,sda-level = <0x1>; + xlnx,ten-bit-adr = <0x0>; + spi_xcomm1: spi_xcomm1@58 { + compatible = "spi-xcomm"; + reg = <0x58>; + dac1_ad9122: ad9122@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ad9122"; + reg = <0>; + spi-max-frequency = <10000000>; + }; + + }; + } ; + axi_intc_0: interrupt-controller@41200000 { + #interrupt-cells = <0x2>; + compatible = "xlnx,axi-intc-1.01.a", "xlnx,xps-intc-1.00.a"; + interrupt-controller ; + reg = < 0x41200000 0x10000 >; + xlnx,kind-of-intr = <0x600>; + xlnx,num-intr-inputs = <0xb>; + } ; +// axi_interconnect_1: axi@41e40000 { +// #address-cells = <1>; +// #size-cells = <1>; +// compatible = "xlnx,axi-interconnect-1.05.a", "simple-bus"; + axi_dma_2: axidma@41e40000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + ranges = < 0x41e40000 0x41e40000 0x10000 >; + reg = < 0x41e40000 0x10000 >; +// xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@41e40000 { + compatible = "xlnx,axi-dma-mm2s-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 1 2 >; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + } ; + dma-channel@41e40030 { + compatible = "xlnx,axi-dma-s2mm-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 0 2 >; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + } ; + } ; + cf_fft_core_0: cf-fft-core@7a200000 { + compatible = "xlnx,cf-fft-core-1.00.a"; + reg = < 0x7a200000 0x10000 >; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "virtex6"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; +// } ; + axi_timer_0: timer@41c00000 { + clock-frequency = <100000000>; + compatible = "xlnx,axi-timer-1.03.a", "xlnx,xps-timer-1.00.a"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 8 2 >; + reg = < 0x41c00000 0x10000 >; + xlnx,count-width = <0x20>; + xlnx,family = "virtex6"; + xlnx,gen0-assert = <0x1>; + xlnx,gen1-assert = <0x1>; + xlnx,one-timer-only = <0x0>; + xlnx,trig0-assert = <0x1>; + xlnx,trig1-assert = <0x1>; + } ; + axi_vdma_0: axivdma@7e220000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-vdma"; + ranges = < 0x7e220000 0x7e220000 0x10000 >; + reg = < 0x7e220000 0x10000 >; + xlnx,include-sg = <0x0>; + xlnx,num-fstores = <0x3>; + dma-channel@7e220000 { + compatible = "xlnx,axi-vdma-mm2s-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 3 2 >; + xlnx,datawidth = <0x40>; + xlnx,genlock-mode = <0x0>; + xlnx,include-dre = <0x0>; + } ; + } ; + axi_vdma_1: axivdma@7e200000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-vdma"; + ranges = < 0x7e200000 0x7e200000 0x10000 >; + reg = < 0x7e200000 0x10000 >; + xlnx,include-sg = <0x0>; + xlnx,num-fstores = <0x3>; + dma-channel@7e200000 { + compatible = "xlnx,axi-vdma-mm2s-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 2 2 >; + xlnx,datawidth = <0x40>; + xlnx,genlock-mode = <0x0>; + xlnx,include-dre = <0x0>; + } ; + } ; + cf_ad9122_core_0: cf-ad9122-core-lpc@73020000 { + compatible = "xlnx,cf-ad9122-core-2.00.a"; + reg = < 0x73020000 0x10000 >; + spibus-connected = <&dac0_ad9122>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "virtex6"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + cf_ad9122_core_1: cf-ad9122-core-hpc@73030000 { + compatible = "xlnx,cf-ad9122-core-2.00.a"; + reg = < 0x73030000 0x10000 >; + spibus-connected = <&dac1_ad9122>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "virtex6"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + cf_ad9643_core_0: cf-ad9643-core-lpc@73000000 { + compatible = "xlnx,cf-ad9643-core-1.00.a"; + reg = < 0x73000000 0x10000 >; + dma-request = <&axi_dma_0 0>; + spibus-connected = <&spi_xcomm0>; + spibus-slaveselect-connected = <0x1>; + dco-output-delay = <0x8c>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "virtex6"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + cf_ad9643_core_1: cf-ad9643-core-hpc@73010000 { + compatible = "xlnx,cf-ad9643-core-1.00.a"; + reg = < 0x73010000 0x10000 >; + dma-request = <&axi_dma_1 0>; + spibus-connected = <&spi_xcomm1>; + spibus-slaveselect-connected = <0x1>; + dco-output-delay = <0x89>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "virtex6"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + debug_module: debug@74800000 { + compatible = "xlnx,mdm-2.00.b"; + reg = < 0x74800000 0x10000 >; + xlnx,family = "virtex6"; + xlnx,interconnect = <0x2>; + xlnx,jtag-chain = <0x2>; + xlnx,mb-dbg-ports = <0x1>; + xlnx,use-uart = <0x1>; + } ; + } ; +} ; From 34c609eb3a66b8489a96f0d107ebdd422844cfd3 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 24 Apr 2012 15:43:20 +0200 Subject: [PATCH 130/261] configs: add XCOMM KC705 defconfig Signed-off-by: Michael Hennerich --- arch/microblaze/configs/kc705_xcomm_defconfig | 1312 +++++++++++++++++ 1 file changed, 1312 insertions(+) create mode 100644 arch/microblaze/configs/kc705_xcomm_defconfig diff --git a/arch/microblaze/configs/kc705_xcomm_defconfig b/arch/microblaze/configs/kc705_xcomm_defconfig new file mode 100644 index 0000000000000..a4d7d99c21e96 --- /dev/null +++ b/arch/microblaze/configs/kc705_xcomm_defconfig @@ -0,0 +1,1312 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/microblaze 3.3.0-rc3 Kernel Configuration +# +CONFIG_MICROBLAZE=y +# CONFIG_SWAP is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +# CONFIG_GENERIC_TIME_VSYSCALL is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_CSUM=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y + +# +# RCU Subsystem +# +CONFIG_TINY_RCU=y +# CONFIG_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="rootfs.cpio.gz" +CONFIG_INITRAMFS_ROOT_UID=0 +CONFIG_INITRAMFS_ROOT_GID=0 +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +CONFIG_INITRAMFS_COMPRESSION_NONE=y +# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_API_DEBUG=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_BLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_FREEZER is not set + +# +# Platform options +# +# CONFIG_PLATFORM_GENERIC is not set +# CONFIG_PLATFORM_ML605_ADIXCOMM is not set +CONFIG_PLATFORM_KC705_ADIXCOMM=y +# CONFIG_ADIXCOMM_SYNC is not set +CONFIG_OPT_LIB_FUNCTION=y +# CONFIG_OPT_LIB_ASM is not set + +# +# Definitions for MICROBLAZE0 +# +CONFIG_KERNEL_BASE_ADDR=0xc0000000 +CONFIG_XILINX_MICROBLAZE0_FAMILY="kintex7" +CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1 +CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1 +CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1 +CONFIG_XILINX_MICROBLAZE0_USE_DIV=1 +CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL=2 +CONFIG_XILINX_MICROBLAZE0_USE_FPU=0 +CONFIG_XILINX_MICROBLAZE0_HW_VER="8.20.b" + +# +# Processor type and features +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_SCHED_HRTICK=y +CONFIG_MMU=y + +# +# Boot options +# +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyUL0,57600 root=/dev/ram" +CONFIG_CMDLINE_FORCE=y +# CONFIG_SECCOMP is not set + +# +# Advanced setup +# +CONFIG_ADVANCED_OPTIONS=y +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE_BOOL=y +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_MANUAL_RESET_VECTOR=0x0 +CONFIG_KERNEL_START_BOOL=y +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE_BOOL=y +CONFIG_TASK_SIZE=0x80000000 +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_NEED_PER_CPU_KM=y +# CONFIG_CLEANCACHE is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Bus Options +# +# CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS is not set +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +# CONFIG_DNS_RESOLVER is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +CONFIG_BQL=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +CONFIG_GENERIC_CPU_DEVICES=y +# CONFIG_DMA_SHARED_BUFFER is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=y +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_GPIO_ADDR is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_LATCH_ADDR is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_DEVICE=y +CONFIG_OF_GPIO=y +CONFIG_OF_I2C=y +CONFIG_OF_NET=y +CONFIG_OF_SPI=y +CONFIG_OF_MDIO=y +# CONFIG_PARPORT is not set + +# +# Misc devices +# +CONFIG_AD525X_DPOT=y +CONFIG_AD525X_DPOT_I2C=y +CONFIG_AD525X_DPOT_SPI=y +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085 is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_MII is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set + +# +# CAIF transport drivers +# +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_INTEL=y +CONFIG_NET_VENDOR_I825XX=y +CONFIG_NET_VENDOR_MARVELL=y +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +CONFIG_NET_VENDOR_NATSEMI=y +CONFIG_NET_VENDOR_8390=y +# CONFIG_ETHOC is not set +CONFIG_NET_VENDOR_SEEQ=y +# CONFIG_SEEQ8005 is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_XILINX=y +CONFIG_XILINX_EMACLITE=y +# CONFIG_XILINX_LL_TEMAC is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_WLAN=y +# CONFIG_HOSTAP is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_DW is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_UARTLITE=y +CONFIG_SERIAL_UARTLITE_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_TTY_PRINTK is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_XILINX_HWICAP is not set +# CONFIG_R3964 is not set + +# +# PCMCIA character devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_RAMOOPS is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +CONFIG_I2C_MUX_PCA954x=y +# CONFIG_I2C_HELPER_AUTO is not set +# CONFIG_I2C_SMBUS is not set + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +CONFIG_I2C_XILINX=y + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=y +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX_PCI is not set +CONFIG_SPI_XCOMM=y +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +CONFIG_GPIO_XILINX=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_S5M_CORE is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_SOUND is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_RTC_CLASS is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_XILINX_DMA=y +# CONFIG_TIMB_DMA is not set +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_BALLOON is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_ECHO is not set +# CONFIG_RTLLIB is not set +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +CONFIG_IIO_SW_RING=y +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16204 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_KXSD9 is not set +# CONFIG_LIS3L02DQ is not set +# CONFIG_SCA3000 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7291 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7606 is not set +# CONFIG_AD799X is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_ADT7310 is not set +# CONFIG_ADT7410 is not set +# CONFIG_AD7280 is not set +CONFIG_CF_AD9467=y +# CONFIG_MAX1363 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Amplifiers +# +CONFIG_AD8366=y + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD5686 is not set +# CONFIG_MAX517 is not set + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +CONFIG_AD9523=y +CONFIG_AD9548=y + +# +# Direct Digital Synthesis +# +# CONFIG_AD5930 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_AD9850 is not set +# CONFIG_AD9852 is not set +# CONFIG_AD9910 is not set +# CONFIG_AD9951 is not set +CONFIG_AD9122_CF=y +CONFIG_AD9122_CF_DAC=y + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +CONFIG_ADF4350=y + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16060 is not set +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set + +# +# Light sensors +# +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_TSL2563 is not set +# CONFIG_TSL2583 is not set + +# +# Magnetometer sensors +# +# CONFIG_SENSORS_AK8975 is not set +# CONFIG_SENSORS_HMC5843 is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7753 is not set +# CONFIG_ADE7754 is not set +# CONFIG_ADE7758 is not set +# CONFIG_ADE7759 is not set +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_GPIO_TRIGGER is not set +# CONFIG_IIO_SYSFS_TRIGGER is not set +# CONFIG_IIO_SIMPLE_DUMMY is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +# CONFIG_ANDROID is not set +# CONFIG_PHONE is not set + +# +# Hardware Spinlock drivers +# +CONFIG_IOMMU_SUPPORT=y +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set + +# +# File systems +# +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ECRYPT_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set +# CONFIG_MINIX_FS_NATIVE_ENDIAN is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_TEST_KSTRTOX is not set +CONFIG_EARLY_PRINTK=y +# CONFIG_HEART_BEAT is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_ENCRYPTED_KEYS is not set +CONFIG_KEYS_DEBUG_PROC_KEYS=y +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_PCI_IOMAP=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +# CONFIG_CRC8 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_GENERIC_ATOMIC64=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set From 77921376b543ba19164a3091c6f462038b9f17ce Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 23 May 2012 13:47:39 +0200 Subject: [PATCH 131/261] Some DMA fixes Signed-off-by: Michael Hennerich --- drivers/dma/xilinx_dma.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/dma/xilinx_dma.c b/drivers/dma/xilinx_dma.c index 96c265d823a3c..b1a4a2f6f44d9 100644 --- a/drivers/dma/xilinx_dma.c +++ b/drivers/dma/xilinx_dma.c @@ -486,7 +486,6 @@ static int xilinx_dma_wait_status(struct xilinx_dma_chan *chan, uint32_t mask, do { status = DMA_IN(&chan->regs->cr); - printk("status: %x, mask: %x, value: %x\n", status, mask, value); if ((status & mask) == value) break; } while (--timeout); @@ -581,10 +580,6 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan) goto out_unlock; } - ret = xilinx_dma_wait_idle(chan); - if (ret) - xilinx_dma_reset(chan); - /* If hardware is idle, then all descriptors on active list are * done, start new transfers @@ -944,6 +939,7 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg( hw = t->descs[j].hw; hw->buf_addr = dma_src; hw->control = num_bytes; + sg_used += num_bytes; j++; } } From ae635e5fff35e9fe5928b4aca7264a1e5313a6b8 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Tue, 5 Jun 2012 15:35:33 -0700 Subject: [PATCH 132/261] Ethernet fix for ZED --- drivers/net/ethernet/xilinx/xilinx_emacps.c | 5 ++++ drivers/net/phy/marvell.c | 32 +++++++++++++++++++++ include/linux/marvell_phy.h | 1 + 3 files changed, 38 insertions(+) diff --git a/drivers/net/ethernet/xilinx/xilinx_emacps.c b/drivers/net/ethernet/xilinx/xilinx_emacps.c index 6b87e5b312860..c42b6615d9b48 100755 --- a/drivers/net/ethernet/xilinx/xilinx_emacps.c +++ b/drivers/net/ethernet/xilinx/xilinx_emacps.c @@ -806,6 +806,11 @@ static int xemacps_mii_probe(struct net_device *ndev) xemacps_adjust_link, 0, PHY_INTERFACE_MODE_RGMII_ID); + + if (!phydev) { + printk(KERN_ERR "%s: no PHY found\n", ndev->name); + return -1; + } } #else for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index f901180a3abf9..57555bb7e3696 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -350,6 +350,24 @@ static int m88e1318_config_aneg(struct phy_device *phydev) return m88e1121_config_aneg(phydev); } +static int m88e1510_config_aneg(struct phy_device *phydev) +/* + Initialization for the 88E151x PHY. Note that the user can run an + additional initialization sequence on a PHY for an embedded system + after running the default configuration as defined for the 88E1318 PHY. + This additional initialization sequence is used for the Xilinx Zynq-based + ZED board. +*/ +{ + int err; + + err = m88e1318_config_aneg(phydev); + if (err < 0) + return err; + + return marvell_of_reg_init(phydev); +} + static int m88e1116r_config_init(struct phy_device *phydev) { int temp; @@ -899,6 +917,19 @@ static struct phy_driver marvell_drivers[] = { .config_intr = &marvell_config_intr, .driver = { .owner = THIS_MODULE }, }, + { + .phy_id = MARVELL_PHY_ID_88E1510, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E1510", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &m88e1510_config_aneg, + .read_status = &marvell_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .did_interrupt = &m88e1121_did_interrupt, + .driver = { .owner = THIS_MODULE }, + }, }; static int __init marvell_init(void) @@ -941,6 +972,7 @@ static struct mdio_device_id __maybe_unused marvell_tbl[] = { { 0x01410e30, 0xfffffff0 }, { 0x01410e90, 0xfffffff0 }, { 0x01410e40, 0xfffffff0 }, + { 0x01410dd0, 0xfffffff0 }, { } }; diff --git a/include/linux/marvell_phy.h b/include/linux/marvell_phy.h index ec41025cb86e4..8e9a029e093d6 100644 --- a/include/linux/marvell_phy.h +++ b/include/linux/marvell_phy.h @@ -15,6 +15,7 @@ #define MARVELL_PHY_ID_88E1240 0x01410e30 #define MARVELL_PHY_ID_88E1318S 0x01410e90 #define MARVELL_PHY_ID_88E1116R 0x01410e40 +#define MARVELL_PHY_ID_88E1510 0x01410dd0 /* struct phy_device dev_flags definitions */ #define MARVELL_PHY_M1145_FLAGS_RESISTANCE 0x00000001 From 2ce5ab37ba6fc3ced54ee53275619c91cd7aa1be Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Tue, 5 Jun 2012 15:38:19 -0700 Subject: [PATCH 133/261] ZED USB Fixes --- arch/arm/mach-zynq/Kconfig | 12 ++++++++++++ drivers/usb/host/ehci-hcd.c | 7 +++++++ drivers/usb/host/ehci-xilinx-usbps.c | 26 ++++++++++++++++++++++++++ drivers/usb/host/ehci.h | 3 +++ drivers/usb/otg/ulpi.c | 1 + 5 files changed, 49 insertions(+) diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig index 836bb6ced5993..af5c783f895d4 100644 --- a/arch/arm/mach-zynq/Kconfig +++ b/arch/arm/mach-zynq/Kconfig @@ -42,6 +42,18 @@ config XILINX_L2_PREFETCH in many cases. This may not always be the best performance depending on the usage. +config XILINX_ZED + bool "Using USB OTG on the Digilent ZED board" + default n + depends on USB_SUPPORT + select USB_ULPI if USB_SUPPORT + select USB_ULPI_VIEWPORT if USB_SUPPORT + help + Select this option if using the USB OTG port on the Digilent ZED board + as a USB on-the-go port. This option is necessary to properly + initialize the TUSB1210 USB PHY used on the ZED board as an + on-the-go USB port that can supply power to a USB slave device. + config XILINX_TEST bool "Testing On Kernel Boot" default n diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 2594e9e127409..3365ae4cbd24f 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -817,6 +817,13 @@ static int ehci_run (struct usb_hcd *hcd) /* Modifying FIFO Burst Threshold value from 2 to 8 */ temp = readl(non_ehci + 0x164); ehci_writel(ehci, 0x00080000, non_ehci + 0x164); +#if CONFIG_XILINX_ZED + if (ehci->ulpi) { + struct otg_transceiver *otg = ehci->ulpi; + + otg_set_vbus(otg, 1); + } +#endif #endif /* GRR this is run-once init(), being done every time the HC starts. * So long as they're part of class devices, we can't do it init() diff --git a/drivers/usb/host/ehci-xilinx-usbps.c b/drivers/usb/host/ehci-xilinx-usbps.c index d0bfcfbc64dcd..5e5ea17902c2c 100755 --- a/drivers/usb/host/ehci-xilinx-usbps.c +++ b/drivers/usb/host/ehci-xilinx-usbps.c @@ -23,6 +23,9 @@ #include #include #include +#ifdef CONFIG_XILINX_ZED +#include +#endif #include #include "ehci-xilinx-usbps.h" @@ -165,6 +168,16 @@ static int usb_hcd_xusbps_probe(const struct hc_driver *driver, #ifdef CONFIG_USB_XUSBPS_OTG ehci = hcd_to_ehci(hcd); if (pdata->otg) { +#ifdef CONFIG_XILINX_ZED + pr_info ("usb_hcd_xusbps_probe: Have OTG assigned.\n"); + + retval = otg_init(pdata->otg); + if (retval) { + dev_err(&pdev->dev, "Unable to init transceiver, probably missing\n"); + return ENODEV; + } +#endif + ehci->transceiver = pdata->otg; retval = otg_set_host(ehci->transceiver, &ehci_to_hcd(ehci)->self); @@ -177,6 +190,19 @@ static int usb_hcd_xusbps_probe(const struct hc_driver *driver, /* inform otg driver about host driver */ xusbps_update_transceiver(); } else { +#ifdef CONFIG_XILINX_ZED + pr_info ("usb_hcd_xusbps_probe: No OTG assigned!\n"); + if (!pdata->otg) { + pdata->otg = otg_ulpi_create (&ulpi_viewport_access_ops, + ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT); + if (pdata->otg) { + pdata->otg->io_priv = hcd->regs + XUSBPS_SOC_USB_ULPIVP; + ehci->ulpi = pdata->otg; + } + } + pr_info ("usb_hcd_xusbps_probe: OTG now assigned!\n"); +#endif + retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (retval != 0) goto err2; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 92d2421aa508c..00d6aa3e8f191 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -120,6 +120,9 @@ struct ehci_hcd { /* one per controller */ #ifdef CONFIG_USB_XUSBPS_OTG void (*start_hnp)(struct ehci_hcd *ehci); +#ifdef CONFIG_XILINX_ZED + struct otg_transceiver *ulpi; +#endif #endif /* per-HC memory pools (could be per-bus, but ...) */ diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c index 0b0466728fdc3..c4e8b90abbe7b 100644 --- a/drivers/usb/otg/ulpi.c +++ b/drivers/usb/otg/ulpi.c @@ -47,6 +47,7 @@ struct ulpi_info { static struct ulpi_info ulpi_ids[] = { ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"), ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"), + ULPI_INFO(ULPI_ID(0x0451, 0x1507), "TI TUSB1210"), }; static int ulpi_set_otg_flags(struct otg_transceiver *otg) From b3de1b288be5b315a9d0ff78893be534e66737d1 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 7 Jun 2012 11:22:12 -0700 Subject: [PATCH 134/261] Add Digilent Default Configuration for ZED(RevB) Board --- arch/arm/configs/digilent_zed_defconfig | 2223 ++++++++++++++++++++++ arch/arm/configs/zed_adv7511_config | 2233 +++++++++++++++++++++++ 2 files changed, 4456 insertions(+) create mode 100755 arch/arm/configs/digilent_zed_defconfig create mode 100644 arch/arm/configs/zed_adv7511_config diff --git a/arch/arm/configs/digilent_zed_defconfig b/arch/arm/configs/digilent_zed_defconfig new file mode 100755 index 0000000000000..9a338a429e3ee --- /dev/null +++ b/arch/arm/configs/digilent_zed_defconfig @@ -0,0 +1,2223 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.3.0 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_KTIME_SCALAR=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_LOCKBREAK=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0xffff0000 +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0x0 +CONFIG_GENERIC_BUG=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_HAVE_IRQ_WORK=y +CONFIG_IRQ_WORK=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_FHANDLE is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_HAVE_SPARSE_IRQ=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_IRQ_DOMAIN=y +# CONFIG_SPARSE_IRQ is not set + +# +# RCU Subsystem +# +CONFIG_TREE_PREEMPT_RCU=y +CONFIG_PREEMPT_RCU=y +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_BOOST is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +# CONFIG_INLINE_SPIN_UNLOCK is not set +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +# CONFIG_INLINE_READ_UNLOCK is not set +# CONFIG_INLINE_READ_UNLOCK_BH is not set +# CONFIG_INLINE_READ_UNLOCK_IRQ is not set +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +# CONFIG_INLINE_WRITE_UNLOCK is not set +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y +# CONFIG_FREEZER is not set + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_PRIMA2 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_PICOXCELL is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_VT8500 is not set +CONFIG_ARCH_ZYNQ=y +# CONFIG_GPIO_PCA953X is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set + +# +# System MMU +# +CONFIG_XILINX_FIXED_DEVTREE_ADDR=y +CONFIG_XILINX_L1_PREFETCH=y +CONFIG_XILINX_L2_PREFETCH=y +# CONFIG_XILINX_TEST is not set + +# +# Xilinx Specific Options +# +CONFIG_ZYNQ_EARLY_UART1=y +# CONFIG_ZYNQ_EARLY_UART_EP107 is not set +CONFIG_XILINX_ZED=y +CONFIG_ZYNQ_DEFAULT_KERNEL=y +# CONFIG_ZYNQ_AMP_CPU0_MASTER is not set +# CONFIG_ZYNQ_AMP_CPU1_SLAVE is not set +# CONFIG_ZYNQ_CPU1_TEST is not set + +# +# Processor Type +# +CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_LPAE is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_ARM_NR_BANKS=8 +CONFIG_CPU_HAS_PMU=y +CONFIG_MULTI_IRQ_HANDLER=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_742230 is not set +# CONFIG_ARM_ERRATA_742231 is not set +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_PL310_ERRATA_753970 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_764369 is not set +# CONFIG_PL310_ERRATA_769419 is not set +CONFIG_ARM_GIC=y +CONFIG_ICST=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y +CONFIG_ISA_DMA_API=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_HAVE_SMP=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_ARM_CPU_TOPOLOGY=y +# CONFIG_SCHED_MC is not set +# CONFIG_SCHED_SMT is not set +CONFIG_HAVE_ARM_SCU=y +CONFIG_HAVE_ARM_TWD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_NR_CPUS=4 +# CONFIG_HOTPLUG_CPU is not set +CONFIG_LOCAL_TIMERS=y +CONFIG_ARCH_NR_GPIO=0 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +CONFIG_HZ=100 +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HW_PERF_EVENTS=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_CLEANCACHE is not set +CONFIG_FORCE_MAX_ZONEORDER=15 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +# CONFIG_CC_STACKPROTECTOR is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set + +# +# Boot options +# +CONFIG_USE_OF=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_ARM_APPENDED_DTB is not set +CONFIG_CMDLINE="console=ttyPS0,115200n8 root=/dev/ram rw initrd=0x00800000,16M earlyprintk mtdparts=physmap-flash.0:512K(nor-fsbl),512K(nor-u-boot),5M(nor-linux),9M(nor-user),1M(nor-scratch),-(nor-rootfs)" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_CMDLINE_EXTEND is not set +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_XIP_KERNEL is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_AUTO_ZRELADDR is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_SUSPEND is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_PM_CLK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_ARM_CPU_SUSPEND is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=m +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +CONFIG_VLAN_8021Q=m +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +CONFIG_BQL=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=m +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +# CONFIG_DMA_SHARED_BUFFER is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +# CONFIG_M25PXX_USE_FAST_READ is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_DOCG3 is not set +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +CONFIG_MTD_NAND_XILINX_PSS=y +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_DEVICE=y +CONFIG_OF_GPIO=y +CONFIG_OF_I2C=y +CONFIG_OF_NET=y +CONFIG_OF_SPI=y +CONFIG_OF_MDIO=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=35384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set + +# +# Misc devices +# +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_ATMEL_PWM is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085 is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_MII is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set + +# +# CAIF transport drivers +# +CONFIG_ETHERNET=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_ETHOC is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +CONFIG_NET_VENDOR_XILINX=y +CONFIG_XILINX_PS_EMAC=y +CONFIG_XILINX_PS_EMAC_HWTSTAMP=y +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=y +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +CONFIG_MDIO_BITBANG=y +# CONFIG_MDIO_GPIO is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_WLAN is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +CONFIG_INPUT_SPARSEKMAP=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +CONFIG_SERIAL_XILINX_PS_UART=y +CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +CONFIG_XILINX_DEVCFG=y +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_RAMOOPS is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +# CONFIG_I2C_CHARDEV is not set +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +CONFIG_I2C_MUX_PCA954x=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +CONFIG_I2C_XILINX_PS=y +CONFIG_I2C_XILINX=y + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_XILINX is not set +CONFIG_SPI_XILINX_PS_QSPI=y +# CONFIG_XILINX_PS_QSPI_USE_DUAL_FLASH is not set +CONFIG_SPI_XILINX_PS_SPI=y +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_XILINX is not set +CONFIG_GPIO_XILINX_PS=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_CORE is not set +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_MPCORE_WATCHDOG is not set +CONFIG_XILINX_PS_WATCHDOG=y +# CONFIG_XILINX_SCU_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_S5M_CORE is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_REGULATOR is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +# CONFIG_MEDIA_CONTROLLER is not set +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_COMMON=y +# CONFIG_DVB_CORE is not set +CONFIG_VIDEO_MEDIA=y + +# +# Multimedia drivers +# +# CONFIG_RC_CORE is not set +# CONFIG_MEDIA_ATTACH is not set +CONFIG_MEDIA_TUNER=y +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA827X=y +CONFIG_MEDIA_TUNER_TDA18271=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=y +CONFIG_MEDIA_TUNER_TEA5767=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_XC4000=y +CONFIG_MEDIA_TUNER_MC44S803=y +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_VMALLOC=y +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set + +# +# Encoders, decoders, sensors and other helper chips +# + +# +# Audio decoders, processors and mixers +# +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS5345 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_VP27SMPX is not set + +# +# RDS decoders +# +# CONFIG_VIDEO_SAA6588 is not set + +# +# Video decoders +# +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_SAA7110 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA7191 is not set +# CONFIG_VIDEO_TVP514X is not set +# CONFIG_VIDEO_TVP5150 is not set +# CONFIG_VIDEO_TVP7002 is not set +# CONFIG_VIDEO_VPX3220 is not set + +# +# Video and audio decoders +# +# CONFIG_VIDEO_SAA717X is not set +# CONFIG_VIDEO_CX25840 is not set + +# +# MPEG video encoders +# +# CONFIG_VIDEO_CX2341X is not set + +# +# Video encoders +# +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_ADV7343 is not set +# CONFIG_VIDEO_AK881X is not set + +# +# Camera sensor devices +# +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_TCM825X is not set +# CONFIG_VIDEO_SR030PC30 is not set + +# +# Flash devices +# + +# +# Video improvement chips +# +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set + +# +# Miscelaneous helper chips +# +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_M52790 is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_V4L_USB_DRIVERS=y +CONFIG_USB_VIDEO_CLASS=y +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=y +# CONFIG_USB_M5602 is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GSPCA_BENQ is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_JL2005BCD is not set +# CONFIG_USB_GSPCA_KINECT is not set +# CONFIG_USB_GSPCA_KONICA is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_NW80X is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7302 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SE401 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +# CONFIG_USB_GSPCA_SPCA500 is not set +# CONFIG_USB_GSPCA_SPCA501 is not set +# CONFIG_USB_GSPCA_SPCA505 is not set +# CONFIG_USB_GSPCA_SPCA506 is not set +# CONFIG_USB_GSPCA_SPCA508 is not set +# CONFIG_USB_GSPCA_SPCA561 is not set +# CONFIG_USB_GSPCA_SPCA1528 is not set +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_SQ930X is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_STV0680 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TOPRO is not set +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_VICAM is not set +# CONFIG_USB_GSPCA_XIRLINK_CIT is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_VIDEO_PVRUSB2 is not set +# CONFIG_VIDEO_HDPVR is not set +# CONFIG_VIDEO_EM28XX is not set +# CONFIG_VIDEO_USBVISION is not set +# CONFIG_USB_ET61X251 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_PWC is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +# CONFIG_V4L_PLATFORM_DRIVERS is not set +# CONFIG_V4L_MEM2MEM_DRIVERS is not set +# CONFIG_RADIO_ADAPTERS is not set + +# +# Graphics support +# +CONFIG_DRM=y +CONFIG_DRM_KMS_HELPER=y +CONFIG_DRM_ENCODER_ADV7511=y +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_WMT_GE_ROPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_XILINX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_XYLON is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +# CONFIG_SND_SUPPORT_OLD_API is not set +# CONFIG_SND_VERBOSE_PROCFS is not set +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +# CONFIG_SND_USB is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_DMAENGINE_PCM=y +CONFIG_SND_SOC_XILINX=y +CONFIG_SND_SOC_AXI_SPDIF=y +CONFIG_SND_SOC_ADV7511_HDMI=y +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACRUX is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LOGITECH is not set +CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB_ARCH_HAS_XHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_SUSPEND=y +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_XUSBPS_DR_OF=y +CONFIG_USB_EHCI_XUSBPS=y +# CONFIG_USB_EHCI_MV is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_RENESAS_USBHS is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +CONFIG_USB_GADGET_XUSBPS=y +CONFIG_USB_XUSBPS=y +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +CONFIG_USB_ZERO=m +# CONFIG_USB_ZERO_HNPTEST is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_GPIO_VBUS is not set +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_USB_XUSBPS_OTG=y +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF_XILINX_PS=y +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_WBSD is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +CONFIG_RTC_DRV_PCF8563=y +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_XILINX_DMA=y +# CONFIG_AMBA_PL08X is not set +# CONFIG_DW_DMAC is not set +# CONFIG_TIMB_DMA is not set +# CONFIG_PL330_DMA is not set +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_BALLOON is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +# CONFIG_STAGING is not set +CONFIG_CLKDEV_LOOKUP=y + +# +# Hardware Spinlock drivers +# +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT23=y +CONFIG_EXT4_FS_XATTR=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +CONFIG_PRINTK_TIME=y +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_CPU_STALL_VERBOSE is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_LKDTM is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +CONFIG_DEBUG_LL=y +CONFIG_DEBUG_LL_UART_NONE=y +# CONFIG_DEBUG_ICEDCC is not set +CONFIG_EARLY_PRINTK=y +# CONFIG_OC_ETM is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_RNG=m +CONFIG_CRYPTO_RNG2=m +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_PCI_IOMAP=y +# CONFIG_CRC_CCITT is not set +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +# CONFIG_CRC8 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set diff --git a/arch/arm/configs/zed_adv7511_config b/arch/arm/configs/zed_adv7511_config new file mode 100644 index 0000000000000..c1eebd4a76b91 --- /dev/null +++ b/arch/arm/configs/zed_adv7511_config @@ -0,0 +1,2233 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.3.0 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_KTIME_SCALAR=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_LOCKBREAK=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0xffff0000 +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0x0 +CONFIG_GENERIC_BUG=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_HAVE_IRQ_WORK=y +CONFIG_IRQ_WORK=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_HAVE_SPARSE_IRQ=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_IRQ_DOMAIN=y +# CONFIG_SPARSE_IRQ is not set + +# +# RCU Subsystem +# +CONFIG_TREE_PREEMPT_RCU=y +CONFIG_PREEMPT_RCU=y +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_BOOST is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +# CONFIG_INLINE_SPIN_UNLOCK is not set +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +# CONFIG_INLINE_READ_UNLOCK is not set +# CONFIG_INLINE_READ_UNLOCK_BH is not set +# CONFIG_INLINE_READ_UNLOCK_IRQ is not set +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +# CONFIG_INLINE_WRITE_UNLOCK is not set +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_FREEZER is not set + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_PRIMA2 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_PICOXCELL is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_VT8500 is not set +CONFIG_ARCH_ZYNQ=y +# CONFIG_GPIO_PCA953X is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set + +# +# System MMU +# + +# +# Xilinx Specific Options +# +CONFIG_ZYNQ_EARLY_UART1=y +# CONFIG_ZYNQ_EARLY_UART_EP107 is not set +CONFIG_XILINX_FIXED_DEVTREE_ADDR=y +CONFIG_XILINX_L1_PREFETCH=y +CONFIG_XILINX_L2_PREFETCH=y +CONFIG_XILINX_ZED=y +# CONFIG_XILINX_TEST is not set +CONFIG_ZYNQ_DEFAULT_KERNEL=y +# CONFIG_ZYNQ_AMP_CPU0_MASTER is not set +# CONFIG_ZYNQ_AMP_CPU1_SLAVE is not set +# CONFIG_ZYNQ_CPU1_TEST is not set + +# +# Processor Type +# +CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_LPAE is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_ARM_NR_BANKS=8 +CONFIG_CPU_HAS_PMU=y +CONFIG_MULTI_IRQ_HANDLER=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_742230 is not set +# CONFIG_ARM_ERRATA_742231 is not set +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_PL310_ERRATA_753970 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_764369 is not set +# CONFIG_PL310_ERRATA_769419 is not set +CONFIG_ARM_GIC=y +CONFIG_ICST=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y +CONFIG_ISA_DMA_API=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_HAVE_SMP=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_ARM_CPU_TOPOLOGY=y +# CONFIG_SCHED_MC is not set +# CONFIG_SCHED_SMT is not set +CONFIG_HAVE_ARM_SCU=y +CONFIG_HAVE_ARM_TWD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_NR_CPUS=4 +# CONFIG_HOTPLUG_CPU is not set +CONFIG_LOCAL_TIMERS=y +CONFIG_ARCH_NR_GPIO=0 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +CONFIG_HZ=100 +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HW_PERF_EVENTS=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=999999 +# CONFIG_COMPACTION is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_CLEANCACHE is not set +CONFIG_FORCE_MAX_ZONEORDER=15 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +# CONFIG_CC_STACKPROTECTOR is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set + +# +# Boot options +# +CONFIG_USE_OF=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_ARM_APPENDED_DTB is not set +CONFIG_CMDLINE="console=ttyPS0,115200n8 root=/dev/ram rw initrd=0x00800000,16M earlyprintk mtdparts=physmap-flash.0:512K(nor-fsbl),512K(nor-u-boot),5M(nor-linux),9M(nor-user),1M(nor-scratch),-(nor-rootfs)" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_CMDLINE_EXTEND is not set +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_XIP_KERNEL is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_AUTO_ZRELADDR is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_SUSPEND is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_PM_CLK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_ARM_CPU_SUSPEND is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=m +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +CONFIG_VLAN_8021Q=m +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +CONFIG_BQL=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=m +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +# CONFIG_DMA_SHARED_BUFFER is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +# CONFIG_M25PXX_USE_FAST_READ is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_DOCG3 is not set +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +CONFIG_MTD_NAND_XILINX_PSS=y +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_DEVICE=y +CONFIG_OF_GPIO=y +CONFIG_OF_I2C=y +CONFIG_OF_NET=y +CONFIG_OF_SPI=y +CONFIG_OF_MDIO=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=35384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set + +# +# Misc devices +# +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_ATMEL_PWM is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085 is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SI570 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_MII is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set + +# +# CAIF transport drivers +# +CONFIG_ETHERNET=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_ETHOC is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +CONFIG_NET_VENDOR_XILINX=y +CONFIG_XILINX_PS_EMAC=y +CONFIG_XILINX_PS_EMAC_HWTSTAMP=y +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=y +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +CONFIG_MDIO_BITBANG=y +# CONFIG_MDIO_GPIO is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_WLAN is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +CONFIG_INPUT_SPARSEKMAP=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +CONFIG_SERIAL_XILINX_PS_UART=y +CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +CONFIG_XILINX_DEVCFG=y +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_RAMOOPS is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +# CONFIG_I2C_CHARDEV is not set +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +CONFIG_I2C_MUX_PCA954x=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX_PS is not set +CONFIG_I2C_XILINX=y + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_XILINX is not set +CONFIG_SPI_XILINX_PS_QSPI=y +# CONFIG_XILINX_PS_QSPI_USE_DUAL_FLASH is not set +CONFIG_SPI_XILINX_PS_SPI=y +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_XILINX is not set +CONFIG_GPIO_XILINX_PS=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_CORE is not set +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_MPCORE_WATCHDOG is not set +# CONFIG_XILINX_PS_WATCHDOG is not set +# CONFIG_XILINX_SCU_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_S5M_CORE is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_REGULATOR is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +# CONFIG_MEDIA_CONTROLLER is not set +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_COMMON=y +# CONFIG_DVB_CORE is not set +CONFIG_VIDEO_MEDIA=y + +# +# Multimedia drivers +# +# CONFIG_RC_CORE is not set +# CONFIG_MEDIA_ATTACH is not set +CONFIG_MEDIA_TUNER=y +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA827X=y +CONFIG_MEDIA_TUNER_TDA18271=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=y +CONFIG_MEDIA_TUNER_TEA5767=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_XC4000=y +CONFIG_MEDIA_TUNER_MC44S803=y +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_VMALLOC=y +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set + +# +# Encoders, decoders, sensors and other helper chips +# + +# +# Audio decoders, processors and mixers +# +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS5345 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_VP27SMPX is not set + +# +# RDS decoders +# +# CONFIG_VIDEO_SAA6588 is not set + +# +# Video decoders +# +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_SAA7110 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA7191 is not set +# CONFIG_VIDEO_TVP514X is not set +# CONFIG_VIDEO_TVP5150 is not set +# CONFIG_VIDEO_TVP7002 is not set +# CONFIG_VIDEO_VPX3220 is not set + +# +# Video and audio decoders +# +# CONFIG_VIDEO_SAA717X is not set +# CONFIG_VIDEO_CX25840 is not set + +# +# MPEG video encoders +# +# CONFIG_VIDEO_CX2341X is not set + +# +# Video encoders +# +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_ADV7343 is not set +# CONFIG_VIDEO_AK881X is not set + +# +# Camera sensor devices +# +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_TCM825X is not set +# CONFIG_VIDEO_SR030PC30 is not set + +# +# Flash devices +# + +# +# Video improvement chips +# +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set + +# +# Miscelaneous helper chips +# +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_M52790 is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_V4L_USB_DRIVERS=y +CONFIG_USB_VIDEO_CLASS=y +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=y +# CONFIG_USB_M5602 is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GSPCA_BENQ is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_JL2005BCD is not set +# CONFIG_USB_GSPCA_KINECT is not set +# CONFIG_USB_GSPCA_KONICA is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_NW80X is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7302 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SE401 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +# CONFIG_USB_GSPCA_SPCA500 is not set +# CONFIG_USB_GSPCA_SPCA501 is not set +# CONFIG_USB_GSPCA_SPCA505 is not set +# CONFIG_USB_GSPCA_SPCA506 is not set +# CONFIG_USB_GSPCA_SPCA508 is not set +# CONFIG_USB_GSPCA_SPCA561 is not set +# CONFIG_USB_GSPCA_SPCA1528 is not set +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_SQ930X is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_STV0680 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TOPRO is not set +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_VICAM is not set +# CONFIG_USB_GSPCA_XIRLINK_CIT is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_VIDEO_PVRUSB2 is not set +# CONFIG_VIDEO_HDPVR is not set +# CONFIG_VIDEO_EM28XX is not set +# CONFIG_VIDEO_USBVISION is not set +# CONFIG_USB_ET61X251 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_PWC is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +# CONFIG_V4L_PLATFORM_DRIVERS is not set +# CONFIG_V4L_MEM2MEM_DRIVERS is not set +# CONFIG_RADIO_ADAPTERS is not set + +# +# Graphics support +# +CONFIG_DRM=y +CONFIG_DRM_KMS_HELPER=y +CONFIG_DRM_ENCODER_ADV7511=y +CONFIG_DRM_ANALOG=y +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_WMT_GE_ROPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_XILINX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_XYLON is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +# CONFIG_SND_SUPPORT_OLD_API is not set +# CONFIG_SND_VERBOSE_PROCFS is not set +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +# CONFIG_SND_USB is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_DMAENGINE_PCM=y +CONFIG_SND_SOC_XILINX=y +CONFIG_SND_SOC_AXI_SPDIF=y +CONFIG_SND_SOC_ADV7511_HDMI=y +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACRUX is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LOGITECH is not set +CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB_ARCH_HAS_XHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_SUSPEND=y +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_XUSBPS_DR_OF=y +CONFIG_USB_EHCI_XUSBPS=y +# CONFIG_USB_EHCI_MV is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_RENESAS_USBHS is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +CONFIG_USB_GADGET_XUSBPS=y +CONFIG_USB_XUSBPS=y +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +CONFIG_USB_ZERO=m +# CONFIG_USB_ZERO_HNPTEST is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_GPIO_VBUS is not set +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_USB_XUSBPS_OTG=y +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF_XILINX_PS=y +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_WBSD is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +CONFIG_RTC_DRV_PCF8563=y +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_XILINX_DMA=y +# CONFIG_AMBA_PL08X is not set +# CONFIG_DW_DMAC is not set +# CONFIG_TIMB_DMA is not set +# CONFIG_PL330_DMA is not set +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_BALLOON is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +# CONFIG_STAGING is not set +CONFIG_CLKDEV_LOOKUP=y + +# +# Hardware Spinlock drivers +# +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT23=y +CONFIG_EXT4_FS_XATTR=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=20 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +# CONFIG_PROVE_RCU_REPEATEDLY is not set +# CONFIG_SPARSE_RCU_POINTER is not set +CONFIG_LOCKDEP=y +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_LOCKDEP is not set +CONFIG_TRACE_IRQFLAGS=y +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_CPU_STALL_VERBOSE is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_LKDTM is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +CONFIG_DEBUG_LL=y +CONFIG_DEBUG_LL_UART_NONE=y +# CONFIG_DEBUG_ICEDCC is not set +CONFIG_EARLY_PRINTK=y +# CONFIG_OC_ETM is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_RNG=m +CONFIG_CRYPTO_RNG2=m +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_PCI_IOMAP=y +# CONFIG_CRC_CCITT is not set +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +# CONFIG_CRC8 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set From 056193a8ba84b9a2d16b60d7a2e4cddcbbdd3fa4 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 7 Jun 2012 11:28:28 -0700 Subject: [PATCH 135/261] Remove zed_adv7511_config --- arch/arm/configs/zed_adv7511_config | 2233 --------------------------- 1 file changed, 2233 deletions(-) delete mode 100644 arch/arm/configs/zed_adv7511_config diff --git a/arch/arm/configs/zed_adv7511_config b/arch/arm/configs/zed_adv7511_config deleted file mode 100644 index c1eebd4a76b91..0000000000000 --- a/arch/arm/configs/zed_adv7511_config +++ /dev/null @@ -1,2233 +0,0 @@ -# -# Automatically generated file; DO NOT EDIT. -# Linux/arm 3.3.0 Kernel Configuration -# -CONFIG_ARM=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_GENERIC_GPIO=y -# CONFIG_ARCH_USES_GETTIMEOFFSET is not set -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_KTIME_SCALAR=y -CONFIG_HAVE_PROC_CPU=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_TRACE_IRQFLAGS_SUPPORT=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_GENERIC_LOCKBREAK=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_VECTORS_BASE=0xffff0000 -# CONFIG_ARM_PATCH_PHYS_VIRT is not set -CONFIG_PHYS_OFFSET=0x0 -CONFIG_GENERIC_BUG=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -CONFIG_HAVE_IRQ_WORK=y -CONFIG_IRQ_WORK=y - -# -# General setup -# -CONFIG_EXPERIMENTAL=y -CONFIG_INIT_ENV_ARG_LIMIT=32 -CONFIG_CROSS_COMPILE="" -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -CONFIG_HAVE_KERNEL_GZIP=y -CONFIG_HAVE_KERNEL_LZMA=y -CONFIG_HAVE_KERNEL_LZO=y -CONFIG_KERNEL_GZIP=y -# CONFIG_KERNEL_LZMA is not set -# CONFIG_KERNEL_LZO is not set -CONFIG_DEFAULT_HOSTNAME="(none)" -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -CONFIG_SYSVIPC_SYSCTL=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_FHANDLE is not set -# CONFIG_TASKSTATS is not set -# CONFIG_AUDIT is not set -CONFIG_HAVE_GENERIC_HARDIRQS=y - -# -# IRQ subsystem -# -CONFIG_GENERIC_HARDIRQS=y -CONFIG_HAVE_SPARSE_IRQ=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_IRQ_DOMAIN=y -# CONFIG_SPARSE_IRQ is not set - -# -# RCU Subsystem -# -CONFIG_TREE_PREEMPT_RCU=y -CONFIG_PREEMPT_RCU=y -# CONFIG_RCU_TRACE is not set -CONFIG_RCU_FANOUT=32 -# CONFIG_RCU_FANOUT_EXACT is not set -# CONFIG_TREE_RCU_TRACE is not set -# CONFIG_RCU_BOOST is not set -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set -# CONFIG_CHECKPOINT_RESTORE is not set -# CONFIG_NAMESPACES is not set -# CONFIG_SCHED_AUTOGROUP is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y -# CONFIG_RELAY is not set -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_RD_GZIP=y -# CONFIG_RD_BZIP2 is not set -# CONFIG_RD_LZMA is not set -# CONFIG_RD_XZ is not set -# CONFIG_RD_LZO is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SYSCTL=y -CONFIG_ANON_INODES=y -CONFIG_EXPERT=y -CONFIG_UID16=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS=y -CONFIG_KALLSYMS_ALL=y -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_AIO=y -CONFIG_EMBEDDED=y -CONFIG_HAVE_PERF_EVENTS=y -CONFIG_PERF_USE_VMALLOC=y - -# -# Kernel Performance Events And Counters -# -CONFIG_PERF_EVENTS=y -# CONFIG_PERF_COUNTERS is not set -# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_COMPAT_BRK=y -CONFIG_SLAB=y -# CONFIG_SLUB is not set -# CONFIG_SLOB is not set -# CONFIG_PROFILING is not set -CONFIG_HAVE_OPROFILE=y -# CONFIG_KPROBES is not set -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_USE_GENERIC_SMP_HELPERS=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_CLK=y -CONFIG_HAVE_DMA_API_DEBUG=y -CONFIG_HAVE_HW_BREAKPOINT=y - -# -# GCOV-based kernel profiling -# -# CONFIG_GCOV_KERNEL is not set -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_SLABINFO=y -CONFIG_RT_MUTEXES=y -CONFIG_BASE_SMALL=0 -CONFIG_MODULES=y -# CONFIG_MODULE_FORCE_LOAD is not set -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MODVERSIONS=y -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_STOP_MACHINE=y -CONFIG_BLOCK=y -CONFIG_LBDAF=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_BLK_DEV_BSGLIB is not set -# CONFIG_BLK_DEV_INTEGRITY is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_CFQ=y -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" -# CONFIG_INLINE_SPIN_TRYLOCK is not set -# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK is not set -# CONFIG_INLINE_SPIN_LOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK_IRQ is not set -# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set -# CONFIG_INLINE_SPIN_UNLOCK is not set -# CONFIG_INLINE_SPIN_UNLOCK_BH is not set -# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set -# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_READ_TRYLOCK is not set -# CONFIG_INLINE_READ_LOCK is not set -# CONFIG_INLINE_READ_LOCK_BH is not set -# CONFIG_INLINE_READ_LOCK_IRQ is not set -# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set -# CONFIG_INLINE_READ_UNLOCK is not set -# CONFIG_INLINE_READ_UNLOCK_BH is not set -# CONFIG_INLINE_READ_UNLOCK_IRQ is not set -# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_WRITE_TRYLOCK is not set -# CONFIG_INLINE_WRITE_LOCK is not set -# CONFIG_INLINE_WRITE_LOCK_BH is not set -# CONFIG_INLINE_WRITE_LOCK_IRQ is not set -# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set -# CONFIG_INLINE_WRITE_UNLOCK is not set -# CONFIG_INLINE_WRITE_UNLOCK_BH is not set -# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set -# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set -# CONFIG_MUTEX_SPIN_ON_OWNER is not set -# CONFIG_FREEZER is not set - -# -# System Type -# -CONFIG_MMU=y -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_REALVIEW is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_VEXPRESS is not set -# CONFIG_ARCH_AT91 is not set -# CONFIG_ARCH_BCMRING is not set -# CONFIG_ARCH_HIGHBANK is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CNS3XXX is not set -# CONFIG_ARCH_GEMINI is not set -# CONFIG_ARCH_PRIMA2 is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_EP93XX is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_MXC is not set -# CONFIG_ARCH_MXS is not set -# CONFIG_ARCH_NETX is not set -# CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_IOP13XX is not set -# CONFIG_ARCH_IOP32X is not set -# CONFIG_ARCH_IOP33X is not set -# CONFIG_ARCH_IXP23XX is not set -# CONFIG_ARCH_IXP2000 is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_DOVE is not set -# CONFIG_ARCH_KIRKWOOD is not set -# CONFIG_ARCH_LPC32XX is not set -# CONFIG_ARCH_MV78XX0 is not set -# CONFIG_ARCH_ORION5X is not set -# CONFIG_ARCH_MMP is not set -# CONFIG_ARCH_KS8695 is not set -# CONFIG_ARCH_W90X900 is not set -# CONFIG_ARCH_TEGRA is not set -# CONFIG_ARCH_PICOXCELL is not set -# CONFIG_ARCH_PNX4008 is not set -# CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_MSM is not set -# CONFIG_ARCH_SHMOBILE is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_S3C64XX is not set -# CONFIG_ARCH_S5P64X0 is not set -# CONFIG_ARCH_S5PC100 is not set -# CONFIG_ARCH_S5PV210 is not set -# CONFIG_ARCH_EXYNOS is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_U300 is not set -# CONFIG_ARCH_U8500 is not set -# CONFIG_ARCH_NOMADIK is not set -# CONFIG_ARCH_DAVINCI is not set -# CONFIG_ARCH_OMAP is not set -# CONFIG_PLAT_SPEAR is not set -# CONFIG_ARCH_VT8500 is not set -CONFIG_ARCH_ZYNQ=y -# CONFIG_GPIO_PCA953X is not set -# CONFIG_KEYBOARD_GPIO_POLLED is not set - -# -# System MMU -# - -# -# Xilinx Specific Options -# -CONFIG_ZYNQ_EARLY_UART1=y -# CONFIG_ZYNQ_EARLY_UART_EP107 is not set -CONFIG_XILINX_FIXED_DEVTREE_ADDR=y -CONFIG_XILINX_L1_PREFETCH=y -CONFIG_XILINX_L2_PREFETCH=y -CONFIG_XILINX_ZED=y -# CONFIG_XILINX_TEST is not set -CONFIG_ZYNQ_DEFAULT_KERNEL=y -# CONFIG_ZYNQ_AMP_CPU0_MASTER is not set -# CONFIG_ZYNQ_AMP_CPU1_SLAVE is not set -# CONFIG_ZYNQ_CPU1_TEST is not set - -# -# Processor Type -# -CONFIG_CPU_V7=y -CONFIG_CPU_32v6K=y -CONFIG_CPU_32v7=y -CONFIG_CPU_ABRT_EV7=y -CONFIG_CPU_PABRT_V7=y -CONFIG_CPU_CACHE_V7=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_TLB_V7=y -CONFIG_CPU_HAS_ASID=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y - -# -# Processor Features -# -# CONFIG_ARM_LPAE is not set -# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set -CONFIG_ARM_THUMB=y -# CONFIG_ARM_THUMBEE is not set -CONFIG_SWP_EMULATE=y -# CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set -# CONFIG_CPU_BPREDICT_DISABLE is not set -CONFIG_OUTER_CACHE=y -CONFIG_OUTER_CACHE_SYNC=y -CONFIG_CACHE_L2X0=y -CONFIG_CACHE_PL310=y -CONFIG_ARM_L1_CACHE_SHIFT_6=y -CONFIG_ARM_L1_CACHE_SHIFT=6 -CONFIG_ARM_DMA_MEM_BUFFERABLE=y -CONFIG_ARM_NR_BANKS=8 -CONFIG_CPU_HAS_PMU=y -CONFIG_MULTI_IRQ_HANDLER=y -# CONFIG_ARM_ERRATA_430973 is not set -# CONFIG_ARM_ERRATA_458693 is not set -# CONFIG_ARM_ERRATA_460075 is not set -# CONFIG_ARM_ERRATA_742230 is not set -# CONFIG_ARM_ERRATA_742231 is not set -# CONFIG_PL310_ERRATA_588369 is not set -# CONFIG_ARM_ERRATA_720789 is not set -# CONFIG_PL310_ERRATA_727915 is not set -# CONFIG_ARM_ERRATA_743622 is not set -# CONFIG_ARM_ERRATA_751472 is not set -# CONFIG_PL310_ERRATA_753970 is not set -# CONFIG_ARM_ERRATA_754322 is not set -# CONFIG_ARM_ERRATA_754327 is not set -# CONFIG_ARM_ERRATA_764369 is not set -# CONFIG_PL310_ERRATA_769419 is not set -CONFIG_ARM_GIC=y -CONFIG_ICST=y - -# -# Bus support -# -CONFIG_ARM_AMBA=y -CONFIG_ISA_DMA_API=y -# CONFIG_PCI_SYSCALL is not set -# CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCCARD is not set - -# -# Kernel Features -# -CONFIG_TICK_ONESHOT=y -# CONFIG_NO_HZ is not set -CONFIG_HIGH_RES_TIMERS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -CONFIG_HAVE_SMP=y -CONFIG_SMP=y -CONFIG_SMP_ON_UP=y -CONFIG_ARM_CPU_TOPOLOGY=y -# CONFIG_SCHED_MC is not set -# CONFIG_SCHED_SMT is not set -CONFIG_HAVE_ARM_SCU=y -CONFIG_HAVE_ARM_TWD=y -CONFIG_VMSPLIT_3G=y -# CONFIG_VMSPLIT_2G is not set -# CONFIG_VMSPLIT_1G is not set -CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_NR_CPUS=4 -# CONFIG_HOTPLUG_CPU is not set -CONFIG_LOCAL_TIMERS=y -CONFIG_ARCH_NR_GPIO=0 -# CONFIG_PREEMPT_NONE is not set -# CONFIG_PREEMPT_VOLUNTARY is not set -CONFIG_PREEMPT=y -CONFIG_PREEMPT_COUNT=y -CONFIG_HZ=100 -# CONFIG_THUMB2_KERNEL is not set -CONFIG_AEABI=y -# CONFIG_OABI_COMPAT is not set -# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set -# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set -CONFIG_HAVE_ARCH_PFN_VALID=y -CONFIG_HIGHMEM=y -# CONFIG_HIGHPTE is not set -CONFIG_HW_PERF_EVENTS=y -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -CONFIG_HAVE_MEMBLOCK=y -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_SPLIT_PTLOCK_CPUS=999999 -# CONFIG_COMPACTION is not set -# CONFIG_PHYS_ADDR_T_64BIT is not set -CONFIG_ZONE_DMA_FLAG=0 -CONFIG_BOUNCE=y -CONFIG_VIRT_TO_BUS=y -# CONFIG_KSM is not set -CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 -# CONFIG_CLEANCACHE is not set -CONFIG_FORCE_MAX_ZONEORDER=15 -CONFIG_ALIGNMENT_TRAP=y -# CONFIG_UACCESS_WITH_MEMCPY is not set -# CONFIG_SECCOMP is not set -# CONFIG_CC_STACKPROTECTOR is not set -# CONFIG_DEPRECATED_PARAM_STRUCT is not set - -# -# Boot options -# -CONFIG_USE_OF=y -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -# CONFIG_ARM_APPENDED_DTB is not set -CONFIG_CMDLINE="console=ttyPS0,115200n8 root=/dev/ram rw initrd=0x00800000,16M earlyprintk mtdparts=physmap-flash.0:512K(nor-fsbl),512K(nor-u-boot),5M(nor-linux),9M(nor-user),1M(nor-scratch),-(nor-rootfs)" -CONFIG_CMDLINE_FROM_BOOTLOADER=y -# CONFIG_CMDLINE_EXTEND is not set -# CONFIG_CMDLINE_FORCE is not set -# CONFIG_XIP_KERNEL is not set -# CONFIG_CRASH_DUMP is not set -# CONFIG_AUTO_ZRELADDR is not set - -# -# CPU Power Management -# -# CONFIG_CPU_IDLE is not set - -# -# Floating point emulation -# - -# -# At least one emulation must be selected -# -CONFIG_VFP=y -CONFIG_VFPv3=y -CONFIG_NEON=y - -# -# Userspace binary formats -# -CONFIG_BINFMT_ELF=y -CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_HAVE_AOUT=y -# CONFIG_BINFMT_AOUT is not set -# CONFIG_BINFMT_MISC is not set - -# -# Power management options -# -# CONFIG_SUSPEND is not set -CONFIG_PM_RUNTIME=y -CONFIG_PM=y -# CONFIG_PM_DEBUG is not set -# CONFIG_APM_EMULATION is not set -CONFIG_PM_CLK=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -# CONFIG_ARM_CPU_SUSPEND is not set -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_UNIX=y -# CONFIG_UNIX_DIAG is not set -CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set -# CONFIG_XFRM_SUB_POLICY is not set -# CONFIG_XFRM_MIGRATE is not set -# CONFIG_XFRM_STATISTICS is not set -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_IP_PNP_RARP=y -CONFIG_NET_IPIP=m -# CONFIG_NET_IPGRE_DEMUX is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_XFRM_TUNNEL is not set -CONFIG_INET_TUNNEL=m -CONFIG_INET_XFRM_MODE_TRANSPORT=y -CONFIG_INET_XFRM_MODE_TUNNEL=y -CONFIG_INET_XFRM_MODE_BEET=y -CONFIG_INET_LRO=y -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_INET_UDP_DIAG is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set -CONFIG_IPV6=m -# CONFIG_IPV6_PRIVACY is not set -# CONFIG_IPV6_ROUTER_PREF is not set -# CONFIG_IPV6_OPTIMISTIC_DAD is not set -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_IPV6_MIP6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set -CONFIG_INET6_XFRM_MODE_TRANSPORT=m -CONFIG_INET6_XFRM_MODE_TUNNEL=m -CONFIG_INET6_XFRM_MODE_BEET=m -# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set -CONFIG_IPV6_SIT=m -# CONFIG_IPV6_SIT_6RD is not set -CONFIG_IPV6_NDISC_NODETYPE=y -# CONFIG_IPV6_TUNNEL is not set -# CONFIG_IPV6_MULTIPLE_TABLES is not set -# CONFIG_IPV6_MROUTE is not set -# CONFIG_NETWORK_SECMARK is not set -# CONFIG_NETWORK_PHY_TIMESTAMPING is not set -# CONFIG_NETFILTER is not set -# CONFIG_IP_DCCP is not set -# CONFIG_IP_SCTP is not set -# CONFIG_RDS is not set -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -# CONFIG_L2TP is not set -# CONFIG_BRIDGE is not set -# CONFIG_NET_DSA is not set -CONFIG_VLAN_8021Q=m -# CONFIG_VLAN_8021Q_GVRP is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_PHONET is not set -# CONFIG_IEEE802154 is not set -# CONFIG_NET_SCHED is not set -# CONFIG_DCB is not set -# CONFIG_BATMAN_ADV is not set -# CONFIG_OPENVSWITCH is not set -CONFIG_RPS=y -CONFIG_RFS_ACCEL=y -CONFIG_XPS=y -CONFIG_BQL=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_HAMRADIO is not set -# CONFIG_CAN is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_AF_RXRPC is not set -CONFIG_WIRELESS=y -# CONFIG_CFG80211 is not set -# CONFIG_LIB80211 is not set - -# -# CFG80211 needs to be enabled for MAC80211 -# -# CONFIG_WIMAX is not set -# CONFIG_RFKILL is not set -# CONFIG_NET_9P is not set -# CONFIG_CAIF is not set -# CONFIG_CEPH_LIB is not set -# CONFIG_NFC is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m -CONFIG_FIRMWARE_IN_KERNEL=y -CONFIG_EXTRA_FIRMWARE="" -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_SYS_HYPERVISOR is not set -# CONFIG_GENERIC_CPU_DEVICES is not set -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -CONFIG_REGMAP_SPI=y -# CONFIG_DMA_SHARED_BUFFER is not set -CONFIG_CONNECTOR=y -CONFIG_PROC_EVENTS=y -CONFIG_MTD=y -# CONFIG_MTD_TESTS is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set -CONFIG_MTD_OF_PARTS=y -# CONFIG_MTD_AR7_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLKDEVS=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set -# CONFIG_RFD_FTL is not set -# CONFIG_SSFDC is not set -# CONFIG_SM_FTL is not set -# CONFIG_MTD_OOPS is not set -# CONFIG_MTD_SWAP is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -CONFIG_MTD_MAP_BANK_WIDTH_4=y -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CFI_AMDSTD=y -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=y -# CONFIG_MTD_PHYSMAP_COMPAT is not set -CONFIG_MTD_PHYSMAP_OF=y -# CONFIG_MTD_PLATRAM is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_DATAFLASH is not set -CONFIG_MTD_M25P80=y -# CONFIG_M25PXX_USE_FAST_READ is not set -# CONFIG_MTD_SST25L is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLOCK2MTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set -# CONFIG_MTD_DOCG3 is not set -CONFIG_MTD_NAND_ECC=y -# CONFIG_MTD_NAND_ECC_SMC is not set -CONFIG_MTD_NAND=y -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -# CONFIG_MTD_NAND_ECC_BCH is not set -# CONFIG_MTD_SM_COMMON is not set -# CONFIG_MTD_NAND_MUSEUM_IDS is not set -# CONFIG_MTD_NAND_GPIO is not set -CONFIG_MTD_NAND_IDS=y -# CONFIG_MTD_NAND_DISKONCHIP is not set -# CONFIG_MTD_NAND_NANDSIM is not set -# CONFIG_MTD_NAND_PLATFORM is not set -# CONFIG_MTD_ALAUDA is not set -CONFIG_MTD_NAND_XILINX_PSS=y -# CONFIG_MTD_ONENAND is not set - -# -# LPDDR flash memory drivers -# -# CONFIG_MTD_LPDDR is not set -# CONFIG_MTD_UBI is not set -CONFIG_DTC=y -CONFIG_OF=y - -# -# Device Tree and Open Firmware support -# -CONFIG_PROC_DEVICETREE=y -# CONFIG_OF_SELFTEST is not set -CONFIG_OF_FLATTREE=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_IRQ=y -CONFIG_OF_DEVICE=y -CONFIG_OF_GPIO=y -CONFIG_OF_I2C=y -CONFIG_OF_NET=y -CONFIG_OF_SPI=y -CONFIG_OF_MDIO=y -# CONFIG_PARPORT is not set -CONFIG_BLK_DEV=y -# CONFIG_BLK_DEV_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_DRBD is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_UB is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=35384 -# CONFIG_BLK_DEV_XIP is not set -# CONFIG_CDROM_PKTCDVD is not set -# CONFIG_ATA_OVER_ETH is not set -# CONFIG_MG_DISK is not set -# CONFIG_BLK_DEV_RBD is not set - -# -# Misc devices -# -# CONFIG_SENSORS_LIS3LV02D is not set -# CONFIG_AD525X_DPOT is not set -# CONFIG_ATMEL_PWM is not set -# CONFIG_ICS932S401 is not set -# CONFIG_ENCLOSURE_SERVICES is not set -# CONFIG_APDS9802ALS is not set -# CONFIG_ISL29003 is not set -# CONFIG_ISL29020 is not set -# CONFIG_SENSORS_TSL2550 is not set -# CONFIG_SENSORS_BH1780 is not set -# CONFIG_SENSORS_BH1770 is not set -# CONFIG_SENSORS_APDS990X is not set -# CONFIG_HMC6352 is not set -# CONFIG_DS1682 is not set -# CONFIG_TI_DAC7512 is not set -# CONFIG_BMP085 is not set -# CONFIG_USB_SWITCH_FSA9480 is not set -# CONFIG_SI570 is not set -# CONFIG_C2PORT is not set - -# -# EEPROM support -# -CONFIG_EEPROM_AT24=y -CONFIG_EEPROM_AT25=y -# CONFIG_EEPROM_LEGACY is not set -# CONFIG_EEPROM_MAX6875 is not set -# CONFIG_EEPROM_93CX6 is not set -# CONFIG_EEPROM_93XX46 is not set -# CONFIG_IWMC3200TOP is not set - -# -# Texas Instruments shared transport line discipline -# -# CONFIG_TI_ST is not set -# CONFIG_SENSORS_LIS3_SPI is not set -# CONFIG_SENSORS_LIS3_I2C is not set - -# -# Altera FPGA firmware download module -# -# CONFIG_ALTERA_STAPL is not set - -# -# SCSI device support -# -CONFIG_SCSI_MOD=y -# CONFIG_RAID_ATTRS is not set -CONFIG_SCSI=y -CONFIG_SCSI_DMA=y -# CONFIG_SCSI_TGT is not set -# CONFIG_SCSI_NETLINK is not set -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -# CONFIG_BLK_DEV_SR is not set -CONFIG_CHR_DEV_SG=y -# CONFIG_CHR_DEV_SCH is not set -CONFIG_SCSI_MULTI_LUN=y -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set -# CONFIG_SCSI_SCAN_ASYNC is not set -CONFIG_SCSI_WAIT_SCAN=m - -# -# SCSI Transports -# -# CONFIG_SCSI_SPI_ATTRS is not set -# CONFIG_SCSI_FC_ATTRS is not set -# CONFIG_SCSI_ISCSI_ATTRS is not set -# CONFIG_SCSI_SAS_ATTRS is not set -# CONFIG_SCSI_SAS_LIBSAS is not set -# CONFIG_SCSI_SRP_ATTRS is not set -CONFIG_SCSI_LOWLEVEL=y -# CONFIG_ISCSI_TCP is not set -# CONFIG_ISCSI_BOOT_SYSFS is not set -# CONFIG_LIBFC is not set -# CONFIG_LIBFCOE is not set -# CONFIG_SCSI_DEBUG is not set -# CONFIG_SCSI_DH is not set -# CONFIG_SCSI_OSD_INITIATOR is not set -# CONFIG_ATA is not set -# CONFIG_MD is not set -# CONFIG_TARGET_CORE is not set -CONFIG_NETDEVICES=y -CONFIG_NET_CORE=y -# CONFIG_BONDING is not set -# CONFIG_DUMMY is not set -# CONFIG_EQUALIZER is not set -# CONFIG_MII is not set -# CONFIG_NET_TEAM is not set -# CONFIG_MACVLAN is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_TUN is not set -# CONFIG_VETH is not set - -# -# CAIF transport drivers -# -CONFIG_ETHERNET=y -# CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_NET_CALXEDA_XGMAC is not set -# CONFIG_NET_VENDOR_CHELSIO is not set -# CONFIG_DM9000 is not set -# CONFIG_DNET is not set -# CONFIG_NET_VENDOR_FARADAY is not set -# CONFIG_NET_VENDOR_INTEL is not set -# CONFIG_NET_VENDOR_MARVELL is not set -# CONFIG_NET_VENDOR_MICREL is not set -# CONFIG_NET_VENDOR_MICROCHIP is not set -# CONFIG_NET_VENDOR_NATSEMI is not set -# CONFIG_ETHOC is not set -# CONFIG_NET_VENDOR_SEEQ is not set -# CONFIG_NET_VENDOR_SMSC is not set -# CONFIG_NET_VENDOR_STMICRO is not set -CONFIG_NET_VENDOR_XILINX=y -CONFIG_XILINX_PS_EMAC=y -CONFIG_XILINX_PS_EMAC_HWTSTAMP=y -CONFIG_PHYLIB=y - -# -# MII PHY device drivers -# -CONFIG_MARVELL_PHY=y -# CONFIG_DAVICOM_PHY is not set -# CONFIG_QSEMI_PHY is not set -# CONFIG_LXT_PHY is not set -# CONFIG_CICADA_PHY is not set -# CONFIG_VITESSE_PHY is not set -# CONFIG_SMSC_PHY is not set -# CONFIG_BROADCOM_PHY is not set -# CONFIG_ICPLUS_PHY is not set -# CONFIG_REALTEK_PHY is not set -# CONFIG_NATIONAL_PHY is not set -# CONFIG_STE10XP is not set -# CONFIG_LSI_ET1011C_PHY is not set -# CONFIG_MICREL_PHY is not set -# CONFIG_FIXED_PHY is not set -CONFIG_MDIO_BITBANG=y -# CONFIG_MDIO_GPIO is not set -# CONFIG_MICREL_KS8995MA is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# USB Network Adapters -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set -# CONFIG_USB_IPHETH is not set -# CONFIG_WLAN is not set - -# -# Enable WiMAX (Networking options) to see the WiMAX drivers -# -# CONFIG_WAN is not set -# CONFIG_ISDN is not set -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set -# CONFIG_INPUT_POLLDEV is not set -CONFIG_INPUT_SPARSEKMAP=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -# CONFIG_KEYBOARD_ADP5588 is not set -# CONFIG_KEYBOARD_ADP5589 is not set -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_QT1070 is not set -# CONFIG_KEYBOARD_QT2160 is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_GPIO is not set -# CONFIG_KEYBOARD_TCA6416 is not set -# CONFIG_KEYBOARD_TCA8418 is not set -# CONFIG_KEYBOARD_MATRIX is not set -# CONFIG_KEYBOARD_MAX7359 is not set -# CONFIG_KEYBOARD_MCS is not set -# CONFIG_KEYBOARD_MPR121 is not set -# CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_KEYBOARD_OPENCORES is not set -# CONFIG_KEYBOARD_SAMSUNG is not set -# CONFIG_KEYBOARD_STOWAWAY is not set -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=y -CONFIG_MOUSE_PS2_ALPS=y -CONFIG_MOUSE_PS2_LOGIPS2PP=y -CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_TRACKPOINT=y -# CONFIG_MOUSE_PS2_ELANTECH is not set -# CONFIG_MOUSE_PS2_SENTELIC is not set -# CONFIG_MOUSE_PS2_TOUCHKIT is not set -# CONFIG_MOUSE_SERIAL is not set -# CONFIG_MOUSE_APPLETOUCH is not set -# CONFIG_MOUSE_BCM5974 is not set -# CONFIG_MOUSE_VSXXXAA is not set -# CONFIG_MOUSE_GPIO is not set -# CONFIG_MOUSE_SYNAPTICS_I2C is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TABLET is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_AMBAKMI is not set -CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set -# CONFIG_SERIO_ALTERA_PS2 is not set -# CONFIG_SERIO_PS2MULT is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -CONFIG_VT_HW_CONSOLE_BINDING=y -CONFIG_UNIX98_PTYS=y -# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_N_GSM is not set -# CONFIG_TRACE_SINK is not set -# CONFIG_DEVKMEM is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -# CONFIG_SERIAL_AMBA_PL010 is not set -# CONFIG_SERIAL_AMBA_PL011 is not set -# CONFIG_SERIAL_MAX3100 is not set -# CONFIG_SERIAL_MAX3107 is not set -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_TIMBERDALE is not set -# CONFIG_SERIAL_ALTERA_JTAGUART is not set -# CONFIG_SERIAL_ALTERA_UART is not set -# CONFIG_SERIAL_IFX6X60 is not set -CONFIG_SERIAL_XILINX_PS_UART=y -CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y -# CONFIG_TTY_PRINTK is not set -# CONFIG_HVC_DCC is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_HW_RANDOM is not set -CONFIG_XILINX_DEVCFG=y -# CONFIG_R3964 is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set -# CONFIG_RAMOOPS is not set -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_COMPAT=y -# CONFIG_I2C_CHARDEV is not set -CONFIG_I2C_MUX=y - -# -# Multiplexer I2C Chip support -# -# CONFIG_I2C_MUX_GPIO is not set -# CONFIG_I2C_MUX_PCA9541 is not set -CONFIG_I2C_MUX_PCA954x=y -CONFIG_I2C_HELPER_AUTO=y -CONFIG_I2C_ALGOBIT=y - -# -# I2C Hardware Bus support -# - -# -# I2C system bus drivers (mostly embedded / system-on-chip) -# -# CONFIG_I2C_DESIGNWARE_PLATFORM is not set -CONFIG_I2C_GPIO=y -# CONFIG_I2C_OCORES is not set -# CONFIG_I2C_PCA_PLATFORM is not set -# CONFIG_I2C_PXA_PCI is not set -# CONFIG_I2C_SIMTEC is not set -# CONFIG_I2C_XILINX_PS is not set -CONFIG_I2C_XILINX=y - -# -# External I2C/SMBus adapter drivers -# -# CONFIG_I2C_DIOLAN_U2C is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_TAOS_EVM is not set -# CONFIG_I2C_TINY_USB is not set - -# -# Other I2C/SMBus bus drivers -# -# CONFIG_I2C_STUB is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -CONFIG_SPI=y -# CONFIG_SPI_DEBUG is not set -CONFIG_SPI_MASTER=y - -# -# SPI Master Controller Drivers -# -# CONFIG_SPI_ALTERA is not set -# CONFIG_SPI_BITBANG is not set -# CONFIG_SPI_GPIO is not set -# CONFIG_SPI_OC_TINY is not set -# CONFIG_SPI_PL022 is not set -# CONFIG_SPI_PXA2XX_PCI is not set -# CONFIG_SPI_XILINX is not set -CONFIG_SPI_XILINX_PS_QSPI=y -# CONFIG_XILINX_PS_QSPI_USE_DUAL_FLASH is not set -CONFIG_SPI_XILINX_PS_SPI=y -# CONFIG_SPI_DESIGNWARE is not set - -# -# SPI Protocol Masters -# -# CONFIG_SPI_SPIDEV is not set -# CONFIG_SPI_TLE62X0 is not set - -# -# PPS support -# -# CONFIG_PPS is not set - -# -# PPS generators support -# - -# -# PTP clock support -# - -# -# Enable Device Drivers -> PPS to see the PTP clock options. -# -CONFIG_ARCH_REQUIRE_GPIOLIB=y -CONFIG_GPIOLIB=y -# CONFIG_DEBUG_GPIO is not set -CONFIG_GPIO_SYSFS=y - -# -# Memory mapped GPIO drivers: -# -# CONFIG_GPIO_GENERIC_PLATFORM is not set -# CONFIG_GPIO_PL061 is not set -# CONFIG_GPIO_XILINX is not set -CONFIG_GPIO_XILINX_PS=y - -# -# I2C GPIO expanders: -# -# CONFIG_GPIO_MAX7300 is not set -# CONFIG_GPIO_MAX732X is not set -# CONFIG_GPIO_PCF857X is not set -# CONFIG_GPIO_SX150X is not set -# CONFIG_GPIO_ADP5588 is not set - -# -# PCI GPIO expanders: -# - -# -# SPI GPIO expanders: -# -# CONFIG_GPIO_MAX7301 is not set -# CONFIG_GPIO_MCP23S08 is not set -# CONFIG_GPIO_MC33880 is not set -# CONFIG_GPIO_74X164 is not set - -# -# AC97 GPIO expanders: -# - -# -# MODULbus GPIO expanders: -# -# CONFIG_W1 is not set -# CONFIG_POWER_SUPPLY is not set -# CONFIG_HWMON is not set -# CONFIG_THERMAL is not set -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_CORE is not set -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_ARM_SP805_WATCHDOG is not set -# CONFIG_DW_WATCHDOG is not set -# CONFIG_MPCORE_WATCHDOG is not set -# CONFIG_XILINX_PS_WATCHDOG is not set -# CONFIG_XILINX_SCU_WATCHDOG is not set -# CONFIG_MAX63XX_WATCHDOG is not set - -# -# USB-based Watchdog Cards -# -# CONFIG_USBPCWATCHDOG is not set -CONFIG_SSB_POSSIBLE=y - -# -# Sonics Silicon Backplane -# -# CONFIG_SSB is not set -CONFIG_BCMA_POSSIBLE=y - -# -# Broadcom specific AMBA -# -# CONFIG_BCMA is not set - -# -# Multifunction device drivers -# -# CONFIG_MFD_CORE is not set -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_MFD_ASIC3 is not set -# CONFIG_HTC_EGPIO is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_HTC_I2CPLD is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS65010 is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS65910 is not set -# CONFIG_MFD_TPS65912_I2C is not set -# CONFIG_MFD_TPS65912_SPI is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MFD_TC6387XB is not set -# CONFIG_MFD_TC6393XB is not set -# CONFIG_PMIC_DA903X is not set -# CONFIG_MFD_DA9052_SPI is not set -# CONFIG_MFD_DA9052_I2C is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_MAX8925 is not set -# CONFIG_MFD_MAX8997 is not set -# CONFIG_MFD_MAX8998 is not set -# CONFIG_MFD_S5M_CORE is not set -# CONFIG_MFD_WM8400 is not set -# CONFIG_MFD_WM831X_I2C is not set -# CONFIG_MFD_WM831X_SPI is not set -# CONFIG_MFD_WM8350_I2C is not set -# CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_EZX_PCAP is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_AAT2870_CORE is not set -# CONFIG_REGULATOR is not set -CONFIG_MEDIA_SUPPORT=y - -# -# Multimedia core support -# -# CONFIG_MEDIA_CONTROLLER is not set -CONFIG_VIDEO_DEV=y -CONFIG_VIDEO_V4L2_COMMON=y -# CONFIG_DVB_CORE is not set -CONFIG_VIDEO_MEDIA=y - -# -# Multimedia drivers -# -# CONFIG_RC_CORE is not set -# CONFIG_MEDIA_ATTACH is not set -CONFIG_MEDIA_TUNER=y -# CONFIG_MEDIA_TUNER_CUSTOMISE is not set -CONFIG_MEDIA_TUNER_SIMPLE=y -CONFIG_MEDIA_TUNER_TDA8290=y -CONFIG_MEDIA_TUNER_TDA827X=y -CONFIG_MEDIA_TUNER_TDA18271=y -CONFIG_MEDIA_TUNER_TDA9887=y -CONFIG_MEDIA_TUNER_TEA5761=y -CONFIG_MEDIA_TUNER_TEA5767=y -CONFIG_MEDIA_TUNER_MT20XX=y -CONFIG_MEDIA_TUNER_XC2028=y -CONFIG_MEDIA_TUNER_XC5000=y -CONFIG_MEDIA_TUNER_XC4000=y -CONFIG_MEDIA_TUNER_MC44S803=y -CONFIG_VIDEO_V4L2=y -CONFIG_VIDEOBUF2_CORE=y -CONFIG_VIDEOBUF2_MEMOPS=y -CONFIG_VIDEOBUF2_VMALLOC=y -CONFIG_VIDEO_CAPTURE_DRIVERS=y -# CONFIG_VIDEO_ADV_DEBUG is not set -# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set -# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set - -# -# Encoders, decoders, sensors and other helper chips -# - -# -# Audio decoders, processors and mixers -# -# CONFIG_VIDEO_TVAUDIO is not set -# CONFIG_VIDEO_TDA7432 is not set -# CONFIG_VIDEO_TDA9840 is not set -# CONFIG_VIDEO_TEA6415C is not set -# CONFIG_VIDEO_TEA6420 is not set -# CONFIG_VIDEO_MSP3400 is not set -# CONFIG_VIDEO_CS5345 is not set -# CONFIG_VIDEO_CS53L32A is not set -# CONFIG_VIDEO_TLV320AIC23B is not set -# CONFIG_VIDEO_WM8775 is not set -# CONFIG_VIDEO_WM8739 is not set -# CONFIG_VIDEO_VP27SMPX is not set - -# -# RDS decoders -# -# CONFIG_VIDEO_SAA6588 is not set - -# -# Video decoders -# -# CONFIG_VIDEO_ADV7180 is not set -# CONFIG_VIDEO_BT819 is not set -# CONFIG_VIDEO_BT856 is not set -# CONFIG_VIDEO_BT866 is not set -# CONFIG_VIDEO_KS0127 is not set -# CONFIG_VIDEO_SAA7110 is not set -# CONFIG_VIDEO_SAA711X is not set -# CONFIG_VIDEO_SAA7191 is not set -# CONFIG_VIDEO_TVP514X is not set -# CONFIG_VIDEO_TVP5150 is not set -# CONFIG_VIDEO_TVP7002 is not set -# CONFIG_VIDEO_VPX3220 is not set - -# -# Video and audio decoders -# -# CONFIG_VIDEO_SAA717X is not set -# CONFIG_VIDEO_CX25840 is not set - -# -# MPEG video encoders -# -# CONFIG_VIDEO_CX2341X is not set - -# -# Video encoders -# -# CONFIG_VIDEO_SAA7127 is not set -# CONFIG_VIDEO_SAA7185 is not set -# CONFIG_VIDEO_ADV7170 is not set -# CONFIG_VIDEO_ADV7175 is not set -# CONFIG_VIDEO_ADV7343 is not set -# CONFIG_VIDEO_AK881X is not set - -# -# Camera sensor devices -# -# CONFIG_VIDEO_OV7670 is not set -# CONFIG_VIDEO_MT9V011 is not set -# CONFIG_VIDEO_TCM825X is not set -# CONFIG_VIDEO_SR030PC30 is not set - -# -# Flash devices -# - -# -# Video improvement chips -# -# CONFIG_VIDEO_UPD64031A is not set -# CONFIG_VIDEO_UPD64083 is not set - -# -# Miscelaneous helper chips -# -# CONFIG_VIDEO_THS7303 is not set -# CONFIG_VIDEO_M52790 is not set -# CONFIG_VIDEO_VIVI is not set -CONFIG_V4L_USB_DRIVERS=y -CONFIG_USB_VIDEO_CLASS=y -CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y -CONFIG_USB_GSPCA=y -# CONFIG_USB_M5602 is not set -# CONFIG_USB_STV06XX is not set -# CONFIG_USB_GL860 is not set -# CONFIG_USB_GSPCA_BENQ is not set -# CONFIG_USB_GSPCA_CONEX is not set -# CONFIG_USB_GSPCA_CPIA1 is not set -# CONFIG_USB_GSPCA_ETOMS is not set -# CONFIG_USB_GSPCA_FINEPIX is not set -# CONFIG_USB_GSPCA_JEILINJ is not set -# CONFIG_USB_GSPCA_JL2005BCD is not set -# CONFIG_USB_GSPCA_KINECT is not set -# CONFIG_USB_GSPCA_KONICA is not set -# CONFIG_USB_GSPCA_MARS is not set -# CONFIG_USB_GSPCA_MR97310A is not set -# CONFIG_USB_GSPCA_NW80X is not set -# CONFIG_USB_GSPCA_OV519 is not set -# CONFIG_USB_GSPCA_OV534 is not set -# CONFIG_USB_GSPCA_OV534_9 is not set -# CONFIG_USB_GSPCA_PAC207 is not set -# CONFIG_USB_GSPCA_PAC7302 is not set -# CONFIG_USB_GSPCA_PAC7311 is not set -# CONFIG_USB_GSPCA_SE401 is not set -# CONFIG_USB_GSPCA_SN9C2028 is not set -# CONFIG_USB_GSPCA_SN9C20X is not set -# CONFIG_USB_GSPCA_SONIXB is not set -# CONFIG_USB_GSPCA_SONIXJ is not set -# CONFIG_USB_GSPCA_SPCA500 is not set -# CONFIG_USB_GSPCA_SPCA501 is not set -# CONFIG_USB_GSPCA_SPCA505 is not set -# CONFIG_USB_GSPCA_SPCA506 is not set -# CONFIG_USB_GSPCA_SPCA508 is not set -# CONFIG_USB_GSPCA_SPCA561 is not set -# CONFIG_USB_GSPCA_SPCA1528 is not set -# CONFIG_USB_GSPCA_SQ905 is not set -# CONFIG_USB_GSPCA_SQ905C is not set -# CONFIG_USB_GSPCA_SQ930X is not set -# CONFIG_USB_GSPCA_STK014 is not set -# CONFIG_USB_GSPCA_STV0680 is not set -# CONFIG_USB_GSPCA_SUNPLUS is not set -# CONFIG_USB_GSPCA_T613 is not set -# CONFIG_USB_GSPCA_TOPRO is not set -# CONFIG_USB_GSPCA_TV8532 is not set -# CONFIG_USB_GSPCA_VC032X is not set -# CONFIG_USB_GSPCA_VICAM is not set -# CONFIG_USB_GSPCA_XIRLINK_CIT is not set -# CONFIG_USB_GSPCA_ZC3XX is not set -# CONFIG_VIDEO_PVRUSB2 is not set -# CONFIG_VIDEO_HDPVR is not set -# CONFIG_VIDEO_EM28XX is not set -# CONFIG_VIDEO_USBVISION is not set -# CONFIG_USB_ET61X251 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_PWC is not set -# CONFIG_VIDEO_CPIA2 is not set -# CONFIG_USB_ZR364XX is not set -# CONFIG_USB_STKWEBCAM is not set -# CONFIG_USB_S2255 is not set -# CONFIG_V4L_PLATFORM_DRIVERS is not set -# CONFIG_V4L_MEM2MEM_DRIVERS is not set -# CONFIG_RADIO_ADAPTERS is not set - -# -# Graphics support -# -CONFIG_DRM=y -CONFIG_DRM_KMS_HELPER=y -CONFIG_DRM_ENCODER_ADV7511=y -CONFIG_DRM_ANALOG=y -# CONFIG_VGASTATE is not set -# CONFIG_VIDEO_OUTPUT_CONTROL is not set -CONFIG_FB=y -# CONFIG_FIRMWARE_EDID is not set -# CONFIG_FB_DDC is not set -# CONFIG_FB_BOOT_VESA_SUPPORT is not set -# CONFIG_FB_CFB_FILLRECT is not set -# CONFIG_FB_CFB_COPYAREA is not set -# CONFIG_FB_CFB_IMAGEBLIT is not set -# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -CONFIG_FB_SYS_FILLRECT=y -CONFIG_FB_SYS_COPYAREA=y -CONFIG_FB_SYS_IMAGEBLIT=y -# CONFIG_FB_FOREIGN_ENDIAN is not set -# CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set -# CONFIG_FB_SVGALIB is not set -# CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set -# CONFIG_FB_MODE_HELPERS is not set -# CONFIG_FB_TILEBLITTING is not set - -# -# Frame buffer hardware drivers -# -# CONFIG_FB_ARMCLCD is not set -# CONFIG_FB_UVESA is not set -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_SMSCUFX is not set -# CONFIG_FB_UDL is not set -# CONFIG_FB_XILINX is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FB_METRONOME is not set -# CONFIG_FB_BROADSHEET is not set -# CONFIG_FB_XYLON is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Console display driver support -# -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -CONFIG_FONTS=y -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_7x14 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set -# CONFIG_FONT_MINI_4x6 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_10x18 is not set -CONFIG_LOGO=y -CONFIG_LOGO_LINUX_MONO=y -CONFIG_LOGO_LINUX_VGA16=y -CONFIG_LOGO_LINUX_CLUT224=y -CONFIG_SOUND=y -# CONFIG_SOUND_OSS_CORE is not set -CONFIG_SND=y -CONFIG_SND_TIMER=y -CONFIG_SND_PCM=y -CONFIG_SND_JACK=y -# CONFIG_SND_SEQUENCER is not set -# CONFIG_SND_MIXER_OSS is not set -# CONFIG_SND_PCM_OSS is not set -# CONFIG_SND_HRTIMER is not set -# CONFIG_SND_DYNAMIC_MINORS is not set -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_VERBOSE_PROCFS is not set -# CONFIG_SND_VERBOSE_PRINTK is not set -# CONFIG_SND_DEBUG is not set -# CONFIG_SND_RAWMIDI_SEQ is not set -# CONFIG_SND_OPL3_LIB_SEQ is not set -# CONFIG_SND_OPL4_LIB_SEQ is not set -# CONFIG_SND_SBAWE_SEQ is not set -# CONFIG_SND_EMU10K1_SEQ is not set -# CONFIG_SND_DRIVERS is not set -# CONFIG_SND_ARM is not set -# CONFIG_SND_SPI is not set -# CONFIG_SND_USB is not set -CONFIG_SND_SOC=y -CONFIG_SND_SOC_DMAENGINE_PCM=y -CONFIG_SND_SOC_XILINX=y -CONFIG_SND_SOC_AXI_SPDIF=y -CONFIG_SND_SOC_ADV7511_HDMI=y -CONFIG_SND_SOC_I2C_AND_SPI=y -# CONFIG_SND_SOC_ALL_CODECS is not set -# CONFIG_SOUND_PRIME is not set -CONFIG_HID_SUPPORT=y -CONFIG_HID=y -# CONFIG_HIDRAW is not set - -# -# USB Input Devices -# -CONFIG_USB_HID=y -# CONFIG_HID_PID is not set -# CONFIG_USB_HIDDEV is not set - -# -# Special HID drivers -# -# CONFIG_HID_A4TECH is not set -# CONFIG_HID_ACRUX is not set -# CONFIG_HID_APPLE is not set -# CONFIG_HID_BELKIN is not set -# CONFIG_HID_CHERRY is not set -# CONFIG_HID_CHICONY is not set -# CONFIG_HID_PRODIKEYS is not set -# CONFIG_HID_CYPRESS is not set -# CONFIG_HID_DRAGONRISE is not set -# CONFIG_HID_EMS_FF is not set -# CONFIG_HID_EZKEY is not set -# CONFIG_HID_HOLTEK is not set -# CONFIG_HID_KEYTOUCH is not set -# CONFIG_HID_KYE is not set -# CONFIG_HID_UCLOGIC is not set -# CONFIG_HID_WALTOP is not set -# CONFIG_HID_GYRATION is not set -# CONFIG_HID_TWINHAN is not set -# CONFIG_HID_KENSINGTON is not set -# CONFIG_HID_LCPOWER is not set -# CONFIG_HID_LOGITECH is not set -CONFIG_HID_MICROSOFT=y -# CONFIG_HID_MONTEREY is not set -# CONFIG_HID_MULTITOUCH is not set -# CONFIG_HID_NTRIG is not set -# CONFIG_HID_ORTEK is not set -# CONFIG_HID_PANTHERLORD is not set -# CONFIG_HID_PETALYNX is not set -# CONFIG_HID_PICOLCD is not set -# CONFIG_HID_PRIMAX is not set -# CONFIG_HID_ROCCAT is not set -# CONFIG_HID_SAMSUNG is not set -# CONFIG_HID_SONY is not set -# CONFIG_HID_SPEEDLINK is not set -# CONFIG_HID_SUNPLUS is not set -# CONFIG_HID_GREENASIA is not set -# CONFIG_HID_SMARTJOYPLUS is not set -# CONFIG_HID_TOPSEED is not set -# CONFIG_HID_THRUSTMASTER is not set -# CONFIG_HID_ZEROPLUS is not set -# CONFIG_HID_ZYDACRON is not set -CONFIG_USB_SUPPORT=y -CONFIG_USB_COMMON=y -CONFIG_USB_ARCH_HAS_HCD=y -# CONFIG_USB_ARCH_HAS_OHCI is not set -CONFIG_USB_ARCH_HAS_EHCI=y -# CONFIG_USB_ARCH_HAS_XHCI is not set -CONFIG_USB=y -# CONFIG_USB_DEBUG is not set -# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -CONFIG_USB_DEVICE_CLASS=y -# CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y -CONFIG_USB_OTG=y -# CONFIG_USB_OTG_WHITELIST is not set -# CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set -# CONFIG_USB_MON is not set -# CONFIG_USB_WUSB_CBAF is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_C67X00_HCD is not set -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_ROOT_HUB_TT=y -# CONFIG_USB_EHCI_TT_NEWSCHED is not set -CONFIG_USB_XUSBPS_DR_OF=y -CONFIG_USB_EHCI_XUSBPS=y -# CONFIG_USB_EHCI_MV is not set -# CONFIG_USB_OXU210HP_HCD is not set -# CONFIG_USB_ISP116X_HCD is not set -# CONFIG_USB_ISP1760_HCD is not set -# CONFIG_USB_ISP1362_HCD is not set -# CONFIG_USB_SL811_HCD is not set -# CONFIG_USB_R8A66597_HCD is not set -# CONFIG_USB_MUSB_HDRC is not set -# CONFIG_USB_RENESAS_USBHS is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_WDM is not set -# CONFIG_USB_TMC is not set - -# -# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may -# - -# -# also be needed; see USB_STORAGE Help for more info -# -CONFIG_USB_STORAGE=y -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_REALTEK is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_USBAT is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_SDDR55 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_ALAUDA is not set -# CONFIG_USB_STORAGE_ONETOUCH is not set -# CONFIG_USB_STORAGE_KARMA is not set -# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set -# CONFIG_USB_STORAGE_ENE_UB6250 is not set -# CONFIG_USB_UAS is not set -# CONFIG_USB_LIBUSUAL is not set - -# -# USB Imaging devices -# -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set - -# -# USB port drivers -# -# CONFIG_USB_SERIAL is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_ADUTUX is not set -# CONFIG_USB_SEVSEG is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYPRESS_CY7C63 is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_IDMOUSE is not set -# CONFIG_USB_FTDI_ELAN is not set -# CONFIG_USB_APPLEDISPLAY is not set -# CONFIG_USB_SISUSBVGA is not set -# CONFIG_USB_LD is not set -# CONFIG_USB_TRANCEVIBRATOR is not set -# CONFIG_USB_IOWARRIOR is not set -# CONFIG_USB_TEST is not set -# CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_YUREX is not set -CONFIG_USB_GADGET=y -# CONFIG_USB_GADGET_DEBUG is not set -# CONFIG_USB_GADGET_DEBUG_FILES is not set -# CONFIG_USB_GADGET_DEBUG_FS is not set -CONFIG_USB_GADGET_VBUS_DRAW=2 -CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 -CONFIG_USB_GADGET_XUSBPS=y -CONFIG_USB_XUSBPS=y -# CONFIG_USB_FUSB300 is not set -# CONFIG_USB_R8A66597 is not set -# CONFIG_USB_GADGET_XILINX is not set -# CONFIG_USB_MV_UDC is not set -# CONFIG_USB_M66592 is not set -# CONFIG_USB_NET2272 is not set -# CONFIG_USB_DUMMY_HCD is not set -CONFIG_USB_GADGET_DUALSPEED=y -CONFIG_USB_ZERO=m -# CONFIG_USB_ZERO_HNPTEST is not set -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_ETH is not set -# CONFIG_USB_G_NCM is not set -# CONFIG_USB_GADGETFS is not set -# CONFIG_USB_FUNCTIONFS is not set -CONFIG_USB_FILE_STORAGE=m -# CONFIG_USB_FILE_STORAGE_TEST is not set -# CONFIG_USB_MASS_STORAGE is not set -# CONFIG_USB_G_SERIAL is not set -# CONFIG_USB_MIDI_GADGET is not set -# CONFIG_USB_G_PRINTER is not set -# CONFIG_USB_CDC_COMPOSITE is not set -# CONFIG_USB_G_ACM_MS is not set -# CONFIG_USB_G_MULTI is not set -# CONFIG_USB_G_HID is not set -# CONFIG_USB_G_DBGP is not set -# CONFIG_USB_G_WEBCAM is not set - -# -# OTG and related infrastructure -# -CONFIG_USB_OTG_UTILS=y -# CONFIG_USB_GPIO_VBUS is not set -CONFIG_USB_ULPI=y -CONFIG_USB_ULPI_VIEWPORT=y -# CONFIG_NOP_USB_XCEIV is not set -CONFIG_USB_XUSBPS_OTG=y -CONFIG_MMC=y -# CONFIG_MMC_DEBUG is not set -# CONFIG_MMC_UNSAFE_RESUME is not set -# CONFIG_MMC_CLKGATE is not set - -# -# MMC/SD/SDIO Card Drivers -# -CONFIG_MMC_BLOCK=y -CONFIG_MMC_BLOCK_MINORS=8 -CONFIG_MMC_BLOCK_BOUNCE=y -# CONFIG_SDIO_UART is not set -# CONFIG_MMC_TEST is not set - -# -# MMC/SD/SDIO Host Controller Drivers -# -# CONFIG_MMC_ARMMMCI is not set -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMC_SDHCI_OF_XILINX_PS=y -# CONFIG_MMC_SDHCI_PXAV3 is not set -# CONFIG_MMC_SDHCI_PXAV2 is not set -# CONFIG_MMC_WBSD is not set -# CONFIG_MMC_DW is not set -# CONFIG_MMC_VUB300 is not set -# CONFIG_MMC_USHC is not set -# CONFIG_MEMSTICK is not set -# CONFIG_NEW_LEDS is not set -# CONFIG_ACCESSIBILITY is not set -CONFIG_RTC_LIB=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_HCTOSYS=y -CONFIG_RTC_HCTOSYS_DEVICE="rtc0" -# CONFIG_RTC_DEBUG is not set - -# -# RTC interfaces -# -CONFIG_RTC_INTF_SYSFS=y -CONFIG_RTC_INTF_PROC=y -CONFIG_RTC_INTF_DEV=y -# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set -# CONFIG_RTC_DRV_TEST is not set - -# -# I2C RTC drivers -# -# CONFIG_RTC_DRV_DS1307 is not set -# CONFIG_RTC_DRV_DS1374 is not set -# CONFIG_RTC_DRV_DS1672 is not set -# CONFIG_RTC_DRV_DS3232 is not set -# CONFIG_RTC_DRV_MAX6900 is not set -# CONFIG_RTC_DRV_RS5C372 is not set -# CONFIG_RTC_DRV_ISL1208 is not set -# CONFIG_RTC_DRV_ISL12022 is not set -# CONFIG_RTC_DRV_X1205 is not set -CONFIG_RTC_DRV_PCF8563=y -# CONFIG_RTC_DRV_PCF8583 is not set -# CONFIG_RTC_DRV_M41T80 is not set -# CONFIG_RTC_DRV_BQ32K is not set -# CONFIG_RTC_DRV_S35390A is not set -# CONFIG_RTC_DRV_FM3130 is not set -# CONFIG_RTC_DRV_RX8581 is not set -# CONFIG_RTC_DRV_RX8025 is not set -# CONFIG_RTC_DRV_EM3027 is not set -# CONFIG_RTC_DRV_RV3029C2 is not set - -# -# SPI RTC drivers -# -# CONFIG_RTC_DRV_M41T93 is not set -# CONFIG_RTC_DRV_M41T94 is not set -# CONFIG_RTC_DRV_DS1305 is not set -# CONFIG_RTC_DRV_DS1390 is not set -# CONFIG_RTC_DRV_MAX6902 is not set -# CONFIG_RTC_DRV_R9701 is not set -# CONFIG_RTC_DRV_RS5C348 is not set -# CONFIG_RTC_DRV_DS3234 is not set -# CONFIG_RTC_DRV_PCF2123 is not set - -# -# Platform RTC drivers -# -# CONFIG_RTC_DRV_CMOS is not set -# CONFIG_RTC_DRV_DS1286 is not set -# CONFIG_RTC_DRV_DS1511 is not set -# CONFIG_RTC_DRV_DS1553 is not set -# CONFIG_RTC_DRV_DS1742 is not set -# CONFIG_RTC_DRV_STK17TA8 is not set -# CONFIG_RTC_DRV_M48T86 is not set -# CONFIG_RTC_DRV_M48T35 is not set -# CONFIG_RTC_DRV_M48T59 is not set -# CONFIG_RTC_DRV_MSM6242 is not set -# CONFIG_RTC_DRV_BQ4802 is not set -# CONFIG_RTC_DRV_RP5C01 is not set -# CONFIG_RTC_DRV_V3020 is not set - -# -# on-CPU RTC drivers -# -# CONFIG_RTC_DRV_PL030 is not set -# CONFIG_RTC_DRV_PL031 is not set -CONFIG_DMADEVICES=y -# CONFIG_DMADEVICES_DEBUG is not set - -# -# DMA Devices -# -CONFIG_XILINX_DMA=y -# CONFIG_AMBA_PL08X is not set -# CONFIG_DW_DMAC is not set -# CONFIG_TIMB_DMA is not set -# CONFIG_PL330_DMA is not set -CONFIG_DMA_ENGINE=y - -# -# DMA Clients -# -# CONFIG_NET_DMA is not set -# CONFIG_ASYNC_TX_DMA is not set -# CONFIG_DMATEST is not set -# CONFIG_AUXDISPLAY is not set -# CONFIG_UIO is not set - -# -# Virtio drivers -# -# CONFIG_VIRTIO_BALLOON is not set -# CONFIG_VIRTIO_MMIO is not set - -# -# Microsoft Hyper-V guest support -# -# CONFIG_STAGING is not set -CONFIG_CLKDEV_LOOKUP=y - -# -# Hardware Spinlock drivers -# -# CONFIG_IOMMU_SUPPORT is not set -# CONFIG_VIRT_DRIVERS is not set -# CONFIG_PM_DEVFREQ is not set - -# -# File systems -# -# CONFIG_EXT2_FS is not set -# CONFIG_EXT3_FS is not set -CONFIG_EXT4_FS=y -CONFIG_EXT4_USE_FOR_EXT23=y -CONFIG_EXT4_FS_XATTR=y -# CONFIG_EXT4_FS_POSIX_ACL is not set -# CONFIG_EXT4_FS_SECURITY is not set -# CONFIG_EXT4_DEBUG is not set -CONFIG_JBD2=y -# CONFIG_JBD2_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set -# CONFIG_BTRFS_FS is not set -# CONFIG_NILFS2_FS is not set -# CONFIG_FS_POSIX_ACL is not set -CONFIG_FILE_LOCKING=y -CONFIG_FSNOTIFY=y -# CONFIG_DNOTIFY is not set -CONFIG_INOTIFY_USER=y -# CONFIG_FANOTIFY is not set -# CONFIG_QUOTA is not set -# CONFIG_QUOTACTL is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set - -# -# Caches -# -# CONFIG_FSCACHE is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_SYSCTL=y -CONFIG_PROC_PAGE_MONITOR=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -# CONFIG_TMPFS_POSIX_ACL is not set -# CONFIG_TMPFS_XATTR is not set -# CONFIG_HUGETLB_PAGE is not set -# CONFIG_CONFIGFS_FS is not set -CONFIG_MISC_FILESYSTEMS=y -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS2_FS is not set -# CONFIG_LOGFS is not set -# CONFIG_CRAMFS is not set -# CONFIG_SQUASHFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_OMFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_PSTORE is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set -# CONFIG_NETWORK_FILESYSTEMS is not set -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=y -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -CONFIG_NLS_ASCII=y -CONFIG_NLS_ISO8859_1=y -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set -CONFIG_FRAME_WARN=1024 -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_STRIP_ASM_SYMS is not set -# CONFIG_UNUSED_SYMBOLS is not set -CONFIG_DEBUG_FS=y -# CONFIG_HEADERS_CHECK is not set -# CONFIG_DEBUG_SECTION_MISMATCH is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SHIRQ is not set -# CONFIG_LOCKUP_DETECTOR is not set -# CONFIG_HARDLOCKUP_DETECTOR is not set -CONFIG_DETECT_HUNG_TASK=y -CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=20 -# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 -# CONFIG_SCHED_DEBUG is not set -# CONFIG_SCHEDSTATS is not set -# CONFIG_TIMER_STATS is not set -# CONFIG_DEBUG_OBJECTS is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_KMEMLEAK is not set -# CONFIG_DEBUG_PREEMPT is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set -CONFIG_DEBUG_SPINLOCK=y -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_LOCK_ALLOC=y -CONFIG_PROVE_LOCKING=y -CONFIG_PROVE_RCU=y -# CONFIG_PROVE_RCU_REPEATEDLY is not set -# CONFIG_SPARSE_RCU_POINTER is not set -CONFIG_LOCKDEP=y -# CONFIG_LOCK_STAT is not set -# CONFIG_DEBUG_LOCKDEP is not set -CONFIG_TRACE_IRQFLAGS=y -# CONFIG_DEBUG_ATOMIC_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -CONFIG_STACKTRACE=y -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_KOBJECT is not set -# CONFIG_DEBUG_HIGHMEM is not set -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_INFO=y -# CONFIG_DEBUG_INFO_REDUCED is not set -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_WRITECOUNT is not set -# CONFIG_DEBUG_MEMORY_INIT is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_TEST_LIST_SORT is not set -# CONFIG_DEBUG_SG is not set -# CONFIG_DEBUG_NOTIFIERS is not set -# CONFIG_DEBUG_CREDENTIALS is not set -# CONFIG_BOOT_PRINTK_DELAY is not set -# CONFIG_RCU_TORTURE_TEST is not set -CONFIG_RCU_CPU_STALL_TIMEOUT=60 -# CONFIG_RCU_CPU_STALL_VERBOSE is not set -# CONFIG_BACKTRACE_SELF_TEST is not set -# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set -# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set -# CONFIG_DEBUG_PER_CPU_MAPS is not set -# CONFIG_LKDTM is not set -# CONFIG_FAULT_INJECTION is not set -# CONFIG_SYSCTL_SYSCALL_CHECK is not set -# CONFIG_DEBUG_PAGEALLOC is not set -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -CONFIG_HAVE_C_RECORDMCOUNT=y -CONFIG_TRACING_SUPPORT=y -# CONFIG_FTRACE is not set -# CONFIG_DYNAMIC_DEBUG is not set -# CONFIG_DMA_API_DEBUG is not set -# CONFIG_ATOMIC64_SELFTEST is not set -# CONFIG_SAMPLES is not set -CONFIG_HAVE_ARCH_KGDB=y -# CONFIG_KGDB is not set -# CONFIG_TEST_KSTRTOX is not set -# CONFIG_STRICT_DEVMEM is not set -CONFIG_ARM_UNWIND=y -# CONFIG_DEBUG_USER is not set -CONFIG_DEBUG_LL=y -CONFIG_DEBUG_LL_UART_NONE=y -# CONFIG_DEBUG_ICEDCC is not set -CONFIG_EARLY_PRINTK=y -# CONFIG_OC_ETM is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY_DMESG_RESTRICT is not set -# CONFIG_SECURITY is not set -# CONFIG_SECURITYFS is not set -CONFIG_DEFAULT_SECURITY_DAC=y -CONFIG_DEFAULT_SECURITY="" -CONFIG_CRYPTO=y - -# -# Crypto core or helper -# -# CONFIG_CRYPTO_FIPS is not set -CONFIG_CRYPTO_ALGAPI=m -CONFIG_CRYPTO_ALGAPI2=m -CONFIG_CRYPTO_RNG=m -CONFIG_CRYPTO_RNG2=m -# CONFIG_CRYPTO_MANAGER is not set -# CONFIG_CRYPTO_MANAGER2 is not set -# CONFIG_CRYPTO_USER is not set -# CONFIG_CRYPTO_GF128MUL is not set -# CONFIG_CRYPTO_NULL is not set -# CONFIG_CRYPTO_PCRYPT is not set -# CONFIG_CRYPTO_CRYPTD is not set -# CONFIG_CRYPTO_AUTHENC is not set -# CONFIG_CRYPTO_TEST is not set - -# -# Authenticated Encryption with Associated Data -# -# CONFIG_CRYPTO_CCM is not set -# CONFIG_CRYPTO_GCM is not set -# CONFIG_CRYPTO_SEQIV is not set - -# -# Block modes -# -# CONFIG_CRYPTO_CBC is not set -# CONFIG_CRYPTO_CTR is not set -# CONFIG_CRYPTO_CTS is not set -# CONFIG_CRYPTO_ECB is not set -# CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_PCBC is not set -# CONFIG_CRYPTO_XTS is not set - -# -# Hash modes -# -# CONFIG_CRYPTO_HMAC is not set -# CONFIG_CRYPTO_XCBC is not set -# CONFIG_CRYPTO_VMAC is not set - -# -# Digest -# -# CONFIG_CRYPTO_CRC32C is not set -# CONFIG_CRYPTO_GHASH is not set -# CONFIG_CRYPTO_MD4 is not set -# CONFIG_CRYPTO_MD5 is not set -# CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_RMD128 is not set -# CONFIG_CRYPTO_RMD160 is not set -# CONFIG_CRYPTO_RMD256 is not set -# CONFIG_CRYPTO_RMD320 is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_WP512 is not set - -# -# Ciphers -# -CONFIG_CRYPTO_AES=m -# CONFIG_CRYPTO_ANUBIS is not set -# CONFIG_CRYPTO_ARC4 is not set -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_CAMELLIA is not set -# CONFIG_CRYPTO_CAST5 is not set -# CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_FCRYPT is not set -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_SALSA20 is not set -# CONFIG_CRYPTO_SEED is not set -# CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_TEA is not set -# CONFIG_CRYPTO_TWOFISH is not set - -# -# Compression -# -# CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_ZLIB is not set -# CONFIG_CRYPTO_LZO is not set - -# -# Random Number Generation -# -CONFIG_CRYPTO_ANSI_CPRNG=m -# CONFIG_CRYPTO_USER_API_HASH is not set -# CONFIG_CRYPTO_USER_API_SKCIPHER is not set -CONFIG_CRYPTO_HW=y -# CONFIG_BINARY_PRINTF is not set - -# -# Library routines -# -CONFIG_BITREVERSE=y -CONFIG_GENERIC_PCI_IOMAP=y -# CONFIG_CRC_CCITT is not set -CONFIG_CRC16=y -# CONFIG_CRC_T10DIF is not set -# CONFIG_CRC_ITU_T is not set -CONFIG_CRC32=y -# CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set -# CONFIG_CRC8 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -# CONFIG_XZ_DEC is not set -# CONFIG_XZ_DEC_BCJ is not set -CONFIG_DECOMPRESS_GZIP=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y -CONFIG_CPU_RMAP=y -CONFIG_DQL=y -CONFIG_NLATTR=y -# CONFIG_AVERAGE is not set -# CONFIG_CORDIC is not set From 100fe56f8ab2883f4fed2aca7b818e10b707348a Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 14 Jun 2012 14:06:23 -0700 Subject: [PATCH 136/261] Serial: xilinx_uartps: Add timeout to xuartps_console_wait_tx For reasons yet unknown it is possible that we end up polling the status from register while the FIFO is not empty, but transmission has been disabled. This causes a endless loop. Add a time out in order to recover from this situation. --- drivers/tty/serial/xilinx_uartps.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 5de0f072f16c4..0a2edab4f497b 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -834,8 +834,10 @@ static struct uart_port *xuartps_get_port(void) **/ static void xuartps_console_wait_tx(struct uart_port *port) { + unsigned int timeout = 10000; + while ((xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_TXEMPTY) - != XUARTPS_SR_TXEMPTY) + != XUARTPS_SR_TXEMPTY && --timeout) barrier(); } From d5c30132aafc99e6a6f72143c6e25fb8af34eefe Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 14 Jun 2012 15:26:48 -0700 Subject: [PATCH 137/261] DRM: Adv7511: Fix uninitialized variable Initialize the offset variable to 0 before starting the first I2C EDID read. Without this fix, it is possible to read the wrong EDID bits which causes EDID data corruption. Author: Lars-Peter Clausen --- drivers/gpu/drm/i2c/adv7511_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i2c/adv7511_core.c b/drivers/gpu/drm/i2c/adv7511_core.c index 68b1185b95f8a..a7fffb274d1f1 100644 --- a/drivers/gpu/drm/i2c/adv7511_core.c +++ b/drivers/gpu/drm/i2c/adv7511_core.c @@ -336,6 +336,7 @@ static int adv7511_get_edid_block(void *data, /* Break this apart, hopefully more I2C controllers will support 64 * byte transfers than 256 byte transfers */ + offset = 0; xfer[0].addr = adv7511->i2c_edid->addr; xfer[0].flags = 0; xfer[0].len = 1; From 2af948fb2778b7688ced539b7e0143cc79f61e22 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 14 Jun 2012 18:21:48 -0700 Subject: [PATCH 138/261] Update to provide new board file for ZED. Update to provide new board file for ZED: - New board type added for ZED - New device tree digilent-zed.dts to support ZED board type --- arch/arm/boot/dts/digilent-zed.dts | 197 +++++++++++++++++++++++++++++ arch/arm/mach-zynq/Makefile | 2 +- arch/arm/mach-zynq/board_zed.c | 74 +++++++++++ 3 files changed, 272 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/digilent-zed.dts create mode 100644 arch/arm/mach-zynq/board_zed.c diff --git a/arch/arm/boot/dts/digilent-zed.dts b/arch/arm/boot/dts/digilent-zed.dts new file mode 100644 index 0000000000000..ebbb14f19521d --- /dev/null +++ b/arch/arm/boot/dts/digilent-zed.dts @@ -0,0 +1,197 @@ +/dts-v1/; + +/ { + model = "Xilinx Zynq ZED"; + compatible = "xlnx,zynq-zed"; + #address-cells = <0x1>; + #size-cells = <0x1>; + interrupt-parent = <0x1>; + + memory { + device_type = "memory"; + reg = <0x0 0x20000000>; + }; + + chosen { + bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0"; + linux,stdout-path = "/amba@0/uart@E0001000"; + }; + + amba@0 { + compatible = "simple-bus"; + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + + intc@f8f01000 { + interrupt-controller; + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <0x3>; + reg = <0xf8f01000 0x1000 0xf8f00100 0x100>; + linux,phandle = <0x1>; + phandle = <0x1>; + }; + + uart@e0001000 { + compatible = "xlnx,ps7-uart-1.00.a"; + reg = <0xe0001000 0x1000>; + interrupts = <0x0 0x32 0x0>; + interrupt-parent = <0x1>; + clock = <0x2faf080>; + }; + + timer@0xf8001000 { + compatible = "xlnx,ps7-ttc-1.00.a"; + reg = <0xf8001000 0x1000>; + interrupts = <0x0 0xa 0x0 0x0 0xb 0x0 0x0 0xc 0x0>; + interrupt-parent = <0x1>; + clock-frequency = <0x7ed6b40>; + }; + + swdt@f8005000 { + device_type = "watchdog"; + compatible = "xlnx,ps7-wdt-1.00.a"; + reg = <0xf8005000 0x100>; + }; + + eth@e000b000 { + compatible = "xlnx,ps7-ethernet-1.00.a"; + reg = <0xe000b000 0x1000>; + interrupts = <0x0 0x16 0x0>; + interrupt-parent = <0x1>; + phy-handle = <0x2>; + #address-cells = <0x1>; + #size-cells = <0x0>; + + phy@0 { + compatible = "marvell,88e1510"; + device_type = "ethernet-phy"; + reg = <0x0>; + marvell,reg-init = <0x3 0x10 0xff00 0x1e 0x3 0x11 0xfff0 0xa>; + linux,phandle = <0x2>; + phandle = <0x2>; + }; + }; + + gpio@e000a000 { + compatible = "xlnx,ps7-gpio-1.00.a"; + reg = <0xe000a000 0x1000>; + interrupts = <0x0 0x14 0x0>; + interrupt-parent = <0x1>; + gpio-controller; + #gpio-cells = <0x2>; + }; + + i2c@41600000 { + compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; + interrupt-parent = <0x1>; + interrupts = <0x0 0x38 0x4>; + reg = <0x41600000 0x10000>; + #size-cells = <0x0>; + #address-cells = <0x1>; + linux,phandle = <0x3>; + phandle = <0x3>; + }; + + sdhci@e0100000 { + compatible = "xlnx,ps7-sdhci-1.00.a"; + reg = <0xe0100000 0x1000>; + interrupts = <0x0 0x18 0x0>; + interrupt-parent = <0x1>; + clock-frequency = <0x1fc9f08>; + }; + + usb@e0002000 { + compatible = "xlnx,ps7-usb-1.00.a"; + reg = <0xe0002000 0x1000>; + interrupts = <0x0 0x15 0x0>; + interrupt-parent = <0x1>; + dr_mode = "host"; + phy_type = "ulpi"; + }; + + spi@e000d000 { + compatible = "xlnx,ps7-qspi-1.00.a"; + reg = <0xe000d000 0x1000>; + interrupts = <0x0 0x13 0x0>; + interrupt-parent = <0x1>; + speed-hz = <0xbebc200>; + bus-num = <0x1>; + num-chip-select = <0x1>; + is-dual = <0x0>; + }; + + devcfg@f8007000 { + compatible = "xlnx,ps7-dev-cfg-1.00.a"; + reg = <0xf8007000 0x1000>; + interrupts = <0x0 0x8 0x0>; + interrupt-parent = <0x1>; + }; + + axidma@40400000 { + #address-cells = <0x1>; + #size-cells = <0x1>; + #dma-cells = <0x1>; + compatible = "xlnx,axi-dma"; + reg = <0x40400000 0x1000>; + xlnx,sg-include-stscntrl-strm = <0x0>; + linux,phandle = <0x5>; + phandle = <0x5>; + + dma-channel@40400000 { + compatible = "xlnx,axi-dma-mm2s-channel"; + interrupts = <0x0 0x3a 0x4>; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + }; + }; + + axi-spdif-tx@0x75c00000 { + compatible = "adi,axi-spdif-tx-1.00.a"; + reg = <0x75c00000 0x1000>; + clock-frequency = <0xbb8000>; + linux,phandle = <0x6>; + phandle = <0x6>; + }; + + axivdma@43000000 { + #address-cells = <0x1>; + #size-cells = <0x1>; + #dma-cells = <0x1>; + compatible = "xlnx,axi-vdma"; + reg = <0x43000000 0x1000>; + xlnx,include-sg = <0x0>; + xlnx,num-fstores = <0x3>; + linux,phandle = <0x4>; + phandle = <0x4>; + + dma-channel@7e200000 { + compatible = "xlnx,axi-vdma-mm2s-channel"; + interrupts = <0x0 0x3b 0x4>; + xlnx,datawidth = <0x40>; + xlnx,genlock-mode = <0x0>; + xlnx,include-dre = <0x0>; + }; + }; + + cf-adv7x11-core@6c000000 { + compatible = "adi,cf-adv7x11-core-1.00.a"; + reg = <0x6c000000 0x10000 0x66000000 0x10000>; + slave_adapter = <0x3>; + dma-request = <0x4 0x0>; + }; + + xilinx_pcm_audio { + compatible = "xilinx-pcm-audio"; + dma-request = <0x5 0x0>; + linux,phandle = <0x7>; + phandle = <0x7>; + }; + + adv7511_hdmi_snd { + compatible = "adv7511-hdmi-snd"; + cpu-dai = <0x6>; + pcm = <0x7>; + }; + }; +}; diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile index ce071f4fd3f61..c315f5d9a8fc3 100644 --- a/arch/arm/mach-zynq/Makefile +++ b/arch/arm/mach-zynq/Makefile @@ -3,7 +3,7 @@ # # Common support -obj-y := common.o timer.o slcr.o scu_gtimer.o board_ep107.o board_zc702.o board_zc770.o board_zc770_xm010.o pl330.o platform_devices.o +obj-y := common.o timer.o slcr.o scu_gtimer.o board_ep107.o board_zc702.o board_zc770.o board_zc770_xm010.o board_zed.o pl330.o platform_devices.o obj-$(CONFIG_SMP) += platsmp.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o diff --git a/arch/arm/mach-zynq/board_zed.c b/arch/arm/mach-zynq/board_zed.c new file mode 100644 index 0000000000000..b615ed8c9f567 --- /dev/null +++ b/arch/arm/mach-zynq/board_zed.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2011 Xilinx + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * New portions Copyright (c) 2012 Digilent Inc. + * ZED board definition file based on the board_zc702.c file. + * Additional functionality provided by the ZED board definition: + * - Recognition of ZED board in the device tree to support a single Zynq + * kernel that runs on several Zynq based boards. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "common.h" + +//#define ZED_REV_B + +extern struct sys_timer xttcpss_sys_timer; + +static void __init board_zed_init(void) +{ + + /* initialize the xilinx common code before the board + * specific + */ + xilinx_init_machine(); + + printk("\n###############################################\n"); + printk ("# #\n"); + printk ("# Board ZED Init #\n"); + printk ("# #\n"); + printk ("###############################################\n\n"); +} + +static const char *xilinx_dt_match[] = { + "xlnx,zynq-zed", + NULL +}; + +MACHINE_START(XILINX, "Xilinx Zynq Platform") + .map_io = xilinx_map_io, + .init_irq = xilinx_irq_init, +#ifdef GIC_CPU_CTRL + .handle_irq = gic_handle_irq, +#endif + .init_machine = board_zed_init, + .timer = &xttcpss_sys_timer, + .dt_compat = xilinx_dt_match, + .reserve = xilinx_memory_init, +MACHINE_END From 869460c6fc0392939ad9468d15d10bcf1d6421ca Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 14 Jun 2012 18:24:29 -0700 Subject: [PATCH 139/261] DRM: ADV7511: Fix recursive dependency error. Fix the recursive dependency error caused by DRM_ENCODER_ADV7511 DRM_ENCODER_ADV7511 depends only on DRM, which selects I2C automatically. --- drivers/gpu/drm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 22b39c118f4c4..83143a423b65f 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -161,7 +161,7 @@ config DRM_SAVAGE config DRM_ENCODER_ADV7511 tristate "AV7511 encoder" - depends on I2C && DRM + depends on DRM select REGMAP_I2C select DRM_KMS_HELPER select FB_SYS_FILLRECT From 9d26b892edb64b4870c526c58adcc9c8042d2759 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 14 Jun 2012 18:29:50 -0700 Subject: [PATCH 140/261] digilent_zed_defconfig Cleanup Uncheck driver support for SPI Flashes, I2C Muxes, RTC Chips which do not exist on ZED --- arch/arm/configs/digilent_zed_defconfig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/arm/configs/digilent_zed_defconfig b/arch/arm/configs/digilent_zed_defconfig index 9a338a429e3ee..69bc833c49126 100755 --- a/arch/arm/configs/digilent_zed_defconfig +++ b/arch/arm/configs/digilent_zed_defconfig @@ -666,7 +666,7 @@ CONFIG_MTD_PHYSMAP_OF=y # Self-contained MTD device drivers # # CONFIG_MTD_DATAFLASH is not set -CONFIG_MTD_M25P80=y +# CONFIG_MTD_M25P80 is not set # CONFIG_M25PXX_USE_FAST_READ is not set # CONFIG_MTD_SST25L is not set # CONFIG_MTD_SLRAM is not set @@ -1039,7 +1039,7 @@ CONFIG_I2C_MUX=y # # CONFIG_I2C_MUX_GPIO is not set # CONFIG_I2C_MUX_PCA9541 is not set -CONFIG_I2C_MUX_PCA954x=y +# CONFIG_I2C_MUX_PCA954x is not set CONFIG_I2C_HELPER_AUTO=y CONFIG_I2C_ALGOBIT=y @@ -1436,6 +1436,7 @@ CONFIG_DRM_ENCODER_ADV7511=y # CONFIG_VIDEO_OUTPUT_CONTROL is not set CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set # CONFIG_FB_BOOT_VESA_SUPPORT is not set # CONFIG_FB_CFB_FILLRECT is not set # CONFIG_FB_CFB_COPYAREA is not set @@ -1789,7 +1790,7 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_ISL1208 is not set # CONFIG_RTC_DRV_ISL12022 is not set # CONFIG_RTC_DRV_X1205 is not set -CONFIG_RTC_DRV_PCF8563=y +# CONFIG_RTC_DRV_PCF8563 is not set # CONFIG_RTC_DRV_PCF8583 is not set # CONFIG_RTC_DRV_M41T80 is not set # CONFIG_RTC_DRV_BQ32K is not set From 516509252fb00dcfb7e52d7648d3151ab61bfdb5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 8 Jun 2012 19:58:03 +0200 Subject: [PATCH 141/261] serial: xilinx_uartps: Add timeout to xuartps_console_wait_tx For reasons yet unknown it is possible that we end up polling the status register while the FIFO is not empty, but transmission has been disabled. This causes a endless loop. Add a timeout in order to recover from this situation. Signed-off-by: Lars-Peter Clausen --- drivers/tty/serial/xilinx_uartps.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 61ee653d08e76..60dd19d82447c 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -939,8 +939,10 @@ static struct uart_port *xuartps_get_port(void) **/ static void xuartps_console_wait_tx(struct uart_port *port) { + unsigned int timeout = 10000; + while ((xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_TXEMPTY) - != XUARTPS_SR_TXEMPTY) + != XUARTPS_SR_TXEMPTY && --timeout) barrier(); } @@ -967,7 +969,7 @@ static void xuartps_console_write(struct console *co, const char *s, { struct uart_port *port = &xuartps_port[co->index]; unsigned long flags; - unsigned int imr; + unsigned int imr, ctrl; int locked = 1; if (oops_in_progress) @@ -979,9 +981,19 @@ static void xuartps_console_write(struct console *co, const char *s, imr = xuartps_readl(XUARTPS_IMR_OFFSET); xuartps_writel(imr, XUARTPS_IDR_OFFSET); + /* + * Make sure that the tx part is enabled. Set the TX enable bit and clear + * the TX disable bit to enable the transmitter. + */ + ctrl = xuartps_readl(XUARTPS_CR_OFFSET); + xuartps_writel((ctrl & ~XUARTPS_CR_TX_DIS) | XUARTPS_CR_TX_EN, + XUARTPS_CR_OFFSET); + uart_console_write(port, s, count, xuartps_console_putchar); xuartps_console_wait_tx(port); + xuartps_writel(XUARTPS_CR_OFFSET, ctrl); + /* restore interrupt state, it seems like there may be a h/w bug * in that the interrupt enable register should not need to be * written based on the data sheet From c06e64034b4d8e220fe0e706cdc3eadba40e3f04 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 19 Jun 2012 11:54:39 +0200 Subject: [PATCH 142/261] mach: zynq: set clock divider for FPGA clock 2 Signed-off-by: Michael Hennerich --- arch/arm/mach-zynq/slcr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index 623173d23da43..4e057437baeb4 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -2457,7 +2457,7 @@ static int __devinit xslcr_probe(struct platform_device *pdev) xslcr_writereg(slcr->regs + XSLCR_FPGA0_CLK_CTRL_OFFSET, 0x100a00); xslcr_writereg(slcr->regs + XSLCR_FPGA1_CLK_CTRL_OFFSET, 0x100500); - xslcr_writereg(slcr->regs + XSLCR_FPGA2_CLK_CTRL_OFFSET, 0x100700); + xslcr_writereg(slcr->regs + XSLCR_FPGA2_CLK_CTRL_OFFSET, 0x100500); xslcr_writereg(slcr->regs + XSLCR_FPGA3_CLK_CTRL_OFFSET, 0x102900); xslcr_writereg(slcr->regs + XSLCR_MIO_PIN(50), 0x200); xslcr_writereg(slcr->regs + XSLCR_MIO_PIN(51), 0x200); From 64f59bf41be58b8ca4d68c7a08e16f09bf6c91c8 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 19 Jun 2012 11:55:59 +0200 Subject: [PATCH 143/261] board: zynq: zc702: add xcomm related resources Signed-off-by: Michael Hennerich --- arch/arm/mach-zynq/board_zc702.c | 231 ++++++++++++++++++++++++++++--- 1 file changed, 215 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-zynq/board_zc702.c b/arch/arm/mach-zynq/board_zc702.c index 4213b32dc7ffa..681a741538113 100644 --- a/arch/arm/mach-zynq/board_zc702.c +++ b/arch/arm/mach-zynq/board_zc702.c @@ -62,7 +62,7 @@ static struct flash_platform_data spi_flash_pdata = { .name = "serial_flash", .parts = spi_flash_partitions, .nr_parts = ARRAY_SIZE(spi_flash_partitions), - .type = "sst25wf080" + .type = "sst25wf080" }; #endif @@ -157,7 +157,7 @@ static struct i2c_board_info __initdata si570_board_info[] = { }; #endif /* CONFIG_SI570 */ - + #if defined(CONFIG_EEPROM_AT24) static struct i2c_board_info __initdata m24c08_board_info[] = { @@ -170,25 +170,224 @@ static struct i2c_board_info __initdata m24c08_board_info[] = { #endif /* CONFIG_I2C_XILINX_PS && CONFIG_I2C_MUX_PCA954x */ -#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_MTD_M25P80) +#define SPIBUS_NUM_LPC 0 + +#if defined(CONFIG_AD9523) || defined(CONFIG_AD9523_MODULE) +#include "../../../../drivers/staging/iio/frequency/ad9523.h" + +struct ad9523_channel_spec ad9523_channels[] = { + { /* ZD output */ + .channel_num = 0, + .extended_name = "ZD_OUTPUT", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = LVDS_4mA, + .divider_phase = 0, + .channel_divider = 8, + .use_alt_clock_src = false, + .output_dis = false, + }, + { /* DAC CLK */ + .channel_num = 1, + .extended_name = "DAC_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = LVPECL_8mA, + .divider_phase = 0, + .channel_divider = 2, + }, + { /* ADC CLK */ + .channel_num = 2, + .extended_name = "ADC_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = LVDS_7mA, + .divider_phase = 0, + .channel_divider = 4, + }, + { /* DAC REF CLK */ + .channel_num = 4, + .extended_name = "DAC_REF_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = LVDS_4mA, + .divider_phase = 0, + .channel_divider = 16, + }, + { /* TX LO REF */ + .channel_num = 5, + .extended_name = "TX_LO_REF_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = CMOS_CONF3, /* HiZ on - */ + .divider_phase = 0, + .channel_divider = 8, + }, + { /* DAC DCO */ + .channel_num = 6, + .extended_name = "DAC_DCO_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = LVDS_7mA, + .divider_phase = 0, + .channel_divider = 2, + }, + { /* ADC SYNC */ + .channel_num = 8, + .extended_name = "ADC_SYNC_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = CMOS_CONF3, /* HiZ on - */ + .divider_phase = 1, + .channel_divider = 32, + .output_dis = false, + }, + { /* RX LO REF */ + .channel_num = 9, + .extended_name = "RX_LO_REF_CLK", + .divider_output_invert_en = false, + .sync_ignore_en = false, + .low_power_mode_en = false, + .driver_mode = CMOS_CONF3, /* HiZ on - */ + .divider_phase = 0, + .channel_divider = 8, + }, +}; + +struct ad9523_platform_data ad9523_pdata_lpc = { + .vcxo_freq = 122880000, + + /* Single-Ended Input Configuration */ + .refa_diff_rcv_en = true, + .refb_diff_rcv_en = false, + .zd_in_diff_en = true, + .osc_in_diff_en = false, + .osc_in_cmos_neg_inp_en = true, + + .refa_r_div = 0, + .refb_r_div = 0, + .pll1_feedback_div = 4, + .pll1_charge_pump_current_nA = 2000, +#if defined(CONFIG_ADIXCOMM_SYNC) + .zero_delay_mode_internal_en = false, +#else + .zero_delay_mode_internal_en = true, +#endif + .osc_in_feedback_en = false, + .refb_cmos_neg_inp_en = true, + .pll1_loop_filter_rzero = 3, + +#if defined(CONFIG_ADIXCOMM_SYNC) + .ref_mode = 3, /* 3 ?*/ +#else + .ref_mode = 1, /* 3 ?*/ +#endif + + .pll2_charge_pump_current_nA = 420000, + .pll2_ndiv_a_cnt = 0, + .pll2_ndiv_b_cnt = 3, + .pll2_freq_doubler_en = true, + .pll2_r2_div = 1, + .pll2_vco_diff_m1 = 3, + .pll2_vco_diff_m2 = 3, + + .rpole2 = 0, + .rzero = 2, + .cpole1 = 2, + .rzero_bypass_en = false, + + /* Output Channel Configuration */ + .num_channels = ARRAY_SIZE(ad9523_channels), + .channels = ad9523_channels, + .name = "ad9523-lpc" +}; +#endif + +#if defined(CONFIG_ADF4350) || defined(CONFIG_ADF4350_MODULE) +#include "../../../../drivers/staging/iio/frequency/adf4350.h" +static struct adf4350_platform_data adf4350_tx_pdata_lpc = { + .name = "adf4351-tx-lpc", + .clkin = 122880000, + .channel_spacing = 10000, + .r2_user_settings = ADF4350_REG2_PD_POLARITY_POS, + ADF4350_REG2_CHARGE_PUMP_CURR_uA(2500), + .r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0), + .r4_user_settings = ADF4350_REG4_OUTPUT_PWR(3) | + ADF4350_REG4_MUTE_TILL_LOCK_EN, + .gpio_lock_detect = -1, + .power_up_frequency = 2400000000, +}; + +static struct adf4350_platform_data adf4350_rx_pdata_lpc = { + .name = "adf4351-rx-lpc", + .clkin = 122880000, + .channel_spacing = 10000, + .r2_user_settings = ADF4350_REG2_PD_POLARITY_POS, + ADF4350_REG2_CHARGE_PUMP_CURR_uA(2500), + .r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0), + .r4_user_settings = ADF4350_REG4_OUTPUT_PWR(3) | + ADF4350_REG4_MUTE_TILL_LOCK_EN, + .gpio_lock_detect = -1, + .power_up_frequency = 2400000000, +}; +#endif static struct spi_board_info __initdata xilinx_spipss_0_boardinfo[] = { +#if defined(CONFIG_AD9548) || defined(CONFIG_AD9548_MODULE) { -#ifdef CONFIG_SPI_SPIDEV - .modalias = "spidev", - .platform_data = &spi_0_pdata, -#else - .modalias = "m25p80", - .platform_data = &spi_flash_pdata, + .modalias = "ad9548", + .max_speed_hz = 10000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_LPC, + .chip_select = 2, /* AD9548 */ + .mode = SPI_MODE_0 | SPI_3WIRE, + }, #endif - .irq = IRQ_SPI1, - .max_speed_hz = 40000000, /* max sample rate at 3V */ - .bus_num = 0, - .chip_select = 1, +#if defined(CONFIG_AD9523) || defined(CONFIG_AD9523_MODULE) + { + .modalias = "ad9523", + .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_LPC, + .chip_select = 3, /* GPIO controlled SSEL */ + .platform_data = &ad9523_pdata_lpc, /* spi_driver specific config */ + .mode = SPI_MODE_0 | SPI_3WIRE, }, -}; - #endif +#if defined(CONFIG_AD8366) || defined(CONFIG_AD8366_MODULE) + { + .modalias = "ad8366", + .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_LPC, + .chip_select = 6, /* GPIO controlled SSEL */ + .platform_data = "ad8366-lpc", /* spi_driver specific config */ + .mode = SPI_MODE_0 | SPI_3WIRE, + }, +#endif +#if defined(CONFIG_ADF4350) || defined(CONFIG_ADF4350_MODULE) + { + .modalias = "adf4351", + .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_LPC, + .chip_select = 4, /* GPIO controlled SSEL */ + .platform_data = &adf4350_rx_pdata_lpc, /* No spi_driver specific config */ + .mode = SPI_MODE_0, + }, + { + .modalias = "adf4351", + .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = SPIBUS_NUM_LPC, + .chip_select = 5, /* GPIO controlled SSEL */ + .platform_data = &adf4350_tx_pdata_lpc, /* No spi_driver specific config */ + .mode = SPI_MODE_0, + }, +#endif +}; extern struct sys_timer xttcpss_sys_timer; @@ -201,7 +400,7 @@ static void __init board_zc702_init(void) xilinx_init_machine(); #if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_MTD_M25P80) - spi_register_board_info(&xilinx_spipss_0_boardinfo[0], + spi_register_board_info(&xilinx_spipss_0_boardinfo[0], ARRAY_SIZE(xilinx_spipss_0_boardinfo)); #endif From 55ccd206877bd3f2858061f9dc2808ba9b126aa8 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 19 Jun 2012 11:56:33 +0200 Subject: [PATCH 144/261] drivers: iio: ad9467: update status reporting Signed-off-by: Michael Hennerich --- drivers/staging/iio/adc/cf_ad9467_ring.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/staging/iio/adc/cf_ad9467_ring.c b/drivers/staging/iio/adc/cf_ad9467_ring.c index 871b451de0ee9..76746fe4eb310 100644 --- a/drivers/staging/iio/adc/cf_ad9467_ring.c +++ b/drivers/staging/iio/adc/cf_ad9467_ring.c @@ -27,12 +27,16 @@ static int aim_read_first_n_hw_rb(struct iio_buffer *r, struct iio_dev *indio_dev = hw_ring->private; struct aim_state *st = iio_priv(indio_dev); int ret; - unsigned stat; + unsigned stat, dma_stat; mutex_lock(&st->lock); ret = wait_for_completion_interruptible_timeout(&st->dma_complete, 4 * HZ); + + stat = aim_read(st, AD9467_PCORE_ADC_STAT); + dma_stat = aim_read(st, AD9467_PCORE_DMA_STAT); + if (st->compl_stat < 0) { ret = st->compl_stat; goto error_ret; @@ -40,8 +44,7 @@ static int aim_read_first_n_hw_rb(struct iio_buffer *r, ret = -ETIMEDOUT; dev_err(indio_dev->dev.parent, "timeout: DMA_STAT 0x%X, ADC_STAT 0x%X\n", - aim_read(st, AD9467_PCORE_DMA_STAT), - aim_read(st, AD9467_PCORE_ADC_STAT)); + dma_stat, stat); goto error_ret; } else if (ret < 0) { goto error_ret; @@ -55,20 +58,17 @@ static int aim_read_first_n_hw_rb(struct iio_buffer *r, if (copy_to_user(buf, st->buf_virt + st->fftcount, count)) ret = -EFAULT; - stat = aim_read(st, AD9467_PCORE_ADC_STAT); - - if (stat) + if ((stat & AD9467_PCORE_ADC_STAT_OVR) || dma_stat) dev_warn(indio_dev->dev.parent, "STATUS: DMA_STAT 0x%X, ADC_STAT 0x%X\n", - aim_read(st, AD9467_PCORE_DMA_STAT), - stat); + dma_stat, stat); error_ret: r->stufftoread = 0; mutex_unlock(&st->lock); - return ret ? ret : count; + return ret < 0 ? ret : count; } static int aim_ring_get_length(struct iio_buffer *r) @@ -206,12 +206,12 @@ static int __aim_hw_ring_state_set(struct iio_dev *indio_dev, bool state) ret = cookie; goto error_free; } - + INIT_COMPLETION(st->dma_complete); dma_async_issue_pending(st->rx_chan); aim_write(st, AD9467_PCORE_DMA_CTRL, 0); aim_write(st, AD9467_PCORE_ADC_STAT, 0xFF); - aim_read(st, AD9467_PCORE_DMA_STAT); + aim_write(st, AD9467_PCORE_DMA_STAT, 0xFF); aim_write(st, AD9467_PCORE_DMA_CTRL, AD9647_DMA_CAP_EN | AD9647_DMA_CNT((st->rcount / 8) - 1)); From 5f87fc726f88934efc4c651f6352bcf030f61765 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 19 Jun 2012 12:41:56 +0200 Subject: [PATCH 145/261] zed: xcomm: add config and device tree Signed-off-by: Michael Hennerich --- arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts | 279 ++ arch/arm/configs/xcomm_adv7511_zed_defconfig | 2418 ++++++++++++++++++ 2 files changed, 2697 insertions(+) create mode 100644 arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts create mode 100644 arch/arm/configs/xcomm_adv7511_zed_defconfig diff --git a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts new file mode 100644 index 0000000000000..900e50e791087 --- /dev/null +++ b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts @@ -0,0 +1,279 @@ +/dts-v1/; + +/ { + model = "Xilinx Zynq ZC702"; + compatible = "xlnx,zynq-zc702"; + #address-cells = <0x1>; + #size-cells = <0x1>; + interrupt-parent = <0x1>; + + memory { + device_type = "memory"; + reg = <0x000000000 0x20000000>; + }; + chosen { +// bootargs = "console=ttyPS0,115200 root=/dev/ram rw initrd=0x1100000,33M ip=:::::eth0:dhcp earlyprintk"; + bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0"; + linux,stdout-path = "/amba@0/uart@E0001000"; + }; + + amba@0 { + compatible = "simple-bus"; + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + + gic: intc@f8f01000 { + interrupt-controller; + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + reg = < 0xf8f01000 0x1000 >, + < 0xf8f00100 0x0100 >; + }; + + uart@e0001000 { + compatible = "xlnx,ps7-uart-1.00.a"; + reg = <0xe0001000 0x1000>; + interrupts = < 0 50 0 >; + interrupt-parent = <&gic>; + clock = <50000000>; + }; + + timer@0xf8001000 { + compatible = "xlnx,ps7-ttc-1.00.a"; + reg = <0xf8001000 0x1000>; + interrupts = <0 10 0>,<0 11 0>,<0 12 0>; + interrupt-parent = <&gic>; +/* clock-frequency = <111111111>;*/ + clock-frequency-timer0 = <133000000>; + clock-frequency-timer1 = <133000000>; + clock-frequency-timer2 = <133000000>; + }; + + swdt@f8005000 { + device_type = "watchdog"; + compatible = "xlnx,ps7-wdt-1.00.a"; + reg = <0xf8005000 0x100>; + }; + + eth@e000b000 { + compatible = "xlnx,ps7-ethernet-1.00.a"; + reg = <0xe000b000 0x1000>; + interrupts = <0 22 0>; + interrupt-parent = <&gic>; + phy-handle = <&phy0>; + #address-cells = <0x1>; + #size-cells = <0x0>; + + phy0: phy@0 { + compatible = "marvell,88e1510"; + device_type = "ethernet-phy"; + reg = <0x0>; + marvell,reg-init=<3 16 0xff00 0x1e 3 17 0xfff0 0x0a>; + }; + }; + + gpio: gpio@e000a000 { + compatible = "xlnx,ps7-gpio-1.00.a"; + reg = <0xe000a000 0x1000>; + interrupts = <0 20 0>; + interrupt-parent = <&gic>; + gpio-controller; + #gpio-cells = <2>; + }; + + + i2c_adv7511: i2c@41620000 { + compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; + interrupt-parent = <&gic>; + interrupts = < 0 52 0x4 >; + reg = < 0x41620000 0x10000 >; + + #size-cells = <0>; + #address-cells = <1>; + }; + + axi_iic_1: i2c@41600000 { + compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; + interrupt-parent = <&gic>; + interrupts = < 0 36 0x4 >; + reg = < 0x41600000 0x10000 >; + + #size-cells = <0>; + #address-cells = <1>; + + spi_xcomm0: spi_xcomm0@58 { + #size-cells = <0>; + #address-cells = <1>; + compatible = "spi-xcomm"; + reg = <0x58>; + dac0_ad9122: ad9122@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ad9122"; + reg = <0>; + spi-max-frequency = <10000000>; + }; + }; + }; + + sdhci@e0100000 { + compatible = "xlnx,ps7-sdhci-1.00.a"; + reg = <0xe0100000 0x1000>; + interrupts = <0 24 0>; + interrupt-parent = <&gic>; + clock-frequency = <50000000>; + }; + + usb@e0002000 { + compatible = "xlnx,ps7-usb-1.00.a"; + reg = <0xe0002000 0x1000>; + interrupts = <0 21 0>; + interrupt-parent = <&gic>; + dr_mode = "host"; + phy_type = "ulpi"; + }; + + devcfg@f8007000 { + compatible = "xlnx,ps7-dev-cfg-1.00.a"; + reg = <0xf8007000 0x1000>; + interrupts = <0 8 0>; + interrupt-parent = <&gic>; + }; + + axi_dma_0: axidma@40440000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + reg = < 0x40440000 0x1000 >; + xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@40440000 { + compatible = "xlnx,axi-dma-mm2s-channel"; + interrupts = < 0 54 0x4 >; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + }; + }; + + axi_spdif_tx_0: axi-spdif-tx@0x75c00000 { + compatible = "adi,axi-spdif-tx-1.00.a"; + reg = < 0x75c00000 0x1000 >; + clock-frequency = <12288000>; + }; + + axi_vdma_0: axivdma@43020000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-vdma"; + reg = <0x43020000 0x1000>; + xlnx,include-sg = <0x0>; + xlnx,num-fstores = <0x3>; + dma-channel@43000000 { + compatible = "xlnx,axi-vdma-mm2s-channel"; + interrupts = <0 59 0x4>; + xlnx,datawidth = <0x40>; + xlnx,genlock-mode = <0x0>; + xlnx,include-dre = <0x0>; + }; + }; + + cf_adv7x11_core_0: cf-adv7x11-core@6c000000 { + compatible = "adi,cf-adv7x11-core-1.00.a"; + reg = <0x70e00000 0x10000 + 0x79000000 0x10000>; + slave_adapter = <&i2c_adv7511>; + dma-request = <&axi_vdma_0 0>; + }; + + xilinx_pcm_audio: xilinx_pcm_audio { + compatible = "xilinx-pcm-audio"; + dma-request = <&axi_dma_0 0>; + }; + + adv7511_hdmi_snd: adv7511_hdmi_snd { + compatible = "adv7511-hdmi-snd"; + audio-codec = <&i2c_adv7511>; + cpu-dai = <&axi_spdif_tx_0>; + pcm = <&xilinx_pcm_audio>; + }; + + axi_dma_1: axidma@40420000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + reg = < 0x40420000 0x10000 >; +// xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@40420000 { + compatible = "xlnx,axi-dma-s2mm-channel"; + interrupts = < 0 56 0x4 >; + xlnx,datawidth = <0x40>; + xlnx,include-dre = <0x0>; + } ; + } ; + + axi_dma_2: axidma@40400000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + reg = < 0x40400000 0x10000 >; + dma-channel@40400000 { + compatible = "xlnx,axi-dma-mm2s-channel"; + interrupts = < 0 58 0x4 >; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + } ; + dma-channel@40400030 { + compatible = "xlnx,axi-dma-s2mm-channel"; + interrupts = < 0 59 0x4 >; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + } ; + } ; + + cf_ad9643_core_0: cf-ad9643-core-lpc@79020000 { + compatible = "xlnx,cf-ad9643-core-1.00.a"; + reg = < 0x79020000 0x10000 >; + dma-request = <&axi_dma_1 0>; + spibus-connected = <&spi_xcomm0>; + spibus-slaveselect-connected = <0x1>; + dco-output-delay = <0x8c>; + xlnx,dphase-timeout = <0x8>; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + + cf_ad9122_core_0: cf-ad9122-core-lpc@74200000 { + compatible = "xlnx,cf-ad9122-core-2.00.a"; + reg = < 0x74200000 0x10000 >; + spibus-connected = <&dac0_ad9122>; + xlnx,dphase-timeout = <0x8>; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + + cf_fft_core_0: cf-fft-core@7de00000 { + compatible = "xlnx,cf-fft-core-1.00.a"; + reg = < 0x7de00000 0x10000 >; + xlnx,dphase-timeout = <0x8>; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + + }; +}; diff --git a/arch/arm/configs/xcomm_adv7511_zed_defconfig b/arch/arm/configs/xcomm_adv7511_zed_defconfig new file mode 100644 index 0000000000000..62abc73a942f2 --- /dev/null +++ b/arch/arm/configs/xcomm_adv7511_zed_defconfig @@ -0,0 +1,2418 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.3.0 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_KTIME_SCALAR=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_LOCKBREAK=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0xffff0000 +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0x0 +CONFIG_GENERIC_BUG=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_HAVE_IRQ_WORK=y +CONFIG_IRQ_WORK=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_HAVE_SPARSE_IRQ=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_IRQ_DOMAIN=y +# CONFIG_SPARSE_IRQ is not set + +# +# RCU Subsystem +# +CONFIG_TREE_PREEMPT_RCU=y +CONFIG_PREEMPT_RCU=y +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_BOOST is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +# CONFIG_INLINE_SPIN_UNLOCK is not set +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +# CONFIG_INLINE_READ_UNLOCK is not set +# CONFIG_INLINE_READ_UNLOCK_BH is not set +# CONFIG_INLINE_READ_UNLOCK_IRQ is not set +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +# CONFIG_INLINE_WRITE_UNLOCK is not set +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_FREEZER is not set + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_PRIMA2 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_PICOXCELL is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_VT8500 is not set +CONFIG_ARCH_ZYNQ=y +# CONFIG_GPIO_PCA953X is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set + +# +# System MMU +# + +# +# Xilinx Specific Options +# +CONFIG_ZYNQ_EARLY_UART1=y +# CONFIG_ZYNQ_EARLY_UART_EP107 is not set +CONFIG_XILINX_FIXED_DEVTREE_ADDR=y +CONFIG_XILINX_L1_PREFETCH=y +CONFIG_XILINX_L2_PREFETCH=y +CONFIG_XILINX_ZED=y +# CONFIG_XILINX_TEST is not set +CONFIG_ZYNQ_DEFAULT_KERNEL=y +# CONFIG_ZYNQ_AMP_CPU0_MASTER is not set +# CONFIG_ZYNQ_AMP_CPU1_SLAVE is not set +# CONFIG_ZYNQ_CPU1_TEST is not set + +# +# Processor Type +# +CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_LPAE is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_ARM_NR_BANKS=8 +CONFIG_CPU_HAS_PMU=y +CONFIG_MULTI_IRQ_HANDLER=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_742230 is not set +# CONFIG_ARM_ERRATA_742231 is not set +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_PL310_ERRATA_753970 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_764369 is not set +# CONFIG_PL310_ERRATA_769419 is not set +CONFIG_ARM_GIC=y +CONFIG_ICST=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y +CONFIG_ISA_DMA_API=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_HAVE_SMP=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_ARM_CPU_TOPOLOGY=y +# CONFIG_SCHED_MC is not set +# CONFIG_SCHED_SMT is not set +CONFIG_HAVE_ARM_SCU=y +CONFIG_HAVE_ARM_TWD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_NR_CPUS=4 +# CONFIG_HOTPLUG_CPU is not set +CONFIG_LOCAL_TIMERS=y +CONFIG_ARCH_NR_GPIO=0 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +CONFIG_HZ=100 +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HW_PERF_EVENTS=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=999999 +# CONFIG_COMPACTION is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_CLEANCACHE is not set +CONFIG_FORCE_MAX_ZONEORDER=15 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +# CONFIG_CC_STACKPROTECTOR is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set + +# +# Boot options +# +CONFIG_USE_OF=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_ARM_APPENDED_DTB is not set +CONFIG_CMDLINE="console=ttyPS0,115200n8 root=/dev/ram rw initrd=0x00800000,16M earlyprintk mtdparts=physmap-flash.0:512K(nor-fsbl),512K(nor-u-boot),5M(nor-linux),9M(nor-user),1M(nor-scratch),-(nor-rootfs)" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_CMDLINE_EXTEND is not set +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_XIP_KERNEL is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_AUTO_ZRELADDR is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_SUSPEND is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_PM_CLK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_ARM_CPU_SUSPEND is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=m +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +CONFIG_VLAN_8021Q=m +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +CONFIG_BQL=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=m +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +# CONFIG_DMA_SHARED_BUFFER is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +# CONFIG_M25PXX_USE_FAST_READ is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_DOCG3 is not set +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +CONFIG_MTD_NAND_XILINX_PSS=y +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_DEVICE=y +CONFIG_OF_GPIO=y +CONFIG_OF_I2C=y +CONFIG_OF_NET=y +CONFIG_OF_SPI=y +CONFIG_OF_MDIO=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=35384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set + +# +# Misc devices +# +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_ATMEL_PWM is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085 is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SI570 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_MII is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set + +# +# CAIF transport drivers +# +CONFIG_ETHERNET=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_ETHOC is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +CONFIG_NET_VENDOR_XILINX=y +CONFIG_XILINX_PS_EMAC=y +CONFIG_XILINX_PS_EMAC_HWTSTAMP=y +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=y +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +CONFIG_MDIO_BITBANG=y +# CONFIG_MDIO_GPIO is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_WLAN is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +CONFIG_INPUT_SPARSEKMAP=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +CONFIG_SERIAL_XILINX_PS_UART=y +CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +CONFIG_XILINX_DEVCFG=y +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_RAMOOPS is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +CONFIG_I2C_MUX_PCA954x=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX_PS is not set +CONFIG_I2C_XILINX=y + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=y +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX_PCI is not set +CONFIG_SPI_XCOMM=y +# CONFIG_SPI_XILINX is not set +CONFIG_SPI_XILINX_PS_QSPI=y +# CONFIG_XILINX_PS_QSPI_USE_DUAL_FLASH is not set +CONFIG_SPI_XILINX_PS_SPI=y +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_XILINX is not set +CONFIG_GPIO_XILINX_PS=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_CORE is not set +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_MPCORE_WATCHDOG is not set +# CONFIG_XILINX_PS_WATCHDOG is not set +# CONFIG_XILINX_SCU_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_S5M_CORE is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_REGULATOR is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +# CONFIG_MEDIA_CONTROLLER is not set +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_COMMON=y +# CONFIG_DVB_CORE is not set +CONFIG_VIDEO_MEDIA=y + +# +# Multimedia drivers +# +# CONFIG_RC_CORE is not set +# CONFIG_MEDIA_ATTACH is not set +CONFIG_MEDIA_TUNER=y +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA827X=y +CONFIG_MEDIA_TUNER_TDA18271=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=y +CONFIG_MEDIA_TUNER_TEA5767=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_XC4000=y +CONFIG_MEDIA_TUNER_MC44S803=y +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_VMALLOC=y +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set + +# +# Encoders, decoders, sensors and other helper chips +# + +# +# Audio decoders, processors and mixers +# +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS5345 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_VP27SMPX is not set + +# +# RDS decoders +# +# CONFIG_VIDEO_SAA6588 is not set + +# +# Video decoders +# +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_SAA7110 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA7191 is not set +# CONFIG_VIDEO_TVP514X is not set +# CONFIG_VIDEO_TVP5150 is not set +# CONFIG_VIDEO_TVP7002 is not set +# CONFIG_VIDEO_VPX3220 is not set + +# +# Video and audio decoders +# +# CONFIG_VIDEO_SAA717X is not set +# CONFIG_VIDEO_CX25840 is not set + +# +# MPEG video encoders +# +# CONFIG_VIDEO_CX2341X is not set + +# +# Video encoders +# +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_ADV7343 is not set +# CONFIG_VIDEO_AK881X is not set + +# +# Camera sensor devices +# +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_TCM825X is not set +# CONFIG_VIDEO_SR030PC30 is not set + +# +# Flash devices +# + +# +# Video improvement chips +# +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set + +# +# Miscelaneous helper chips +# +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_M52790 is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_V4L_USB_DRIVERS=y +CONFIG_USB_VIDEO_CLASS=y +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=y +# CONFIG_USB_M5602 is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GSPCA_BENQ is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_JL2005BCD is not set +# CONFIG_USB_GSPCA_KINECT is not set +# CONFIG_USB_GSPCA_KONICA is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_NW80X is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7302 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SE401 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +# CONFIG_USB_GSPCA_SPCA500 is not set +# CONFIG_USB_GSPCA_SPCA501 is not set +# CONFIG_USB_GSPCA_SPCA505 is not set +# CONFIG_USB_GSPCA_SPCA506 is not set +# CONFIG_USB_GSPCA_SPCA508 is not set +# CONFIG_USB_GSPCA_SPCA561 is not set +# CONFIG_USB_GSPCA_SPCA1528 is not set +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_SQ930X is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_STV0680 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TOPRO is not set +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_VICAM is not set +# CONFIG_USB_GSPCA_XIRLINK_CIT is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_VIDEO_PVRUSB2 is not set +# CONFIG_VIDEO_HDPVR is not set +# CONFIG_VIDEO_EM28XX is not set +# CONFIG_VIDEO_USBVISION is not set +# CONFIG_USB_ET61X251 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_PWC is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +# CONFIG_V4L_PLATFORM_DRIVERS is not set +# CONFIG_V4L_MEM2MEM_DRIVERS is not set +# CONFIG_RADIO_ADAPTERS is not set + +# +# Graphics support +# +CONFIG_DRM=y +CONFIG_DRM_KMS_HELPER=y +CONFIG_DRM_ENCODER_ADV7511=y +CONFIG_DRM_ANALOG=y +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_WMT_GE_ROPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_XILINX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_XYLON is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +# CONFIG_SND_SUPPORT_OLD_API is not set +# CONFIG_SND_VERBOSE_PROCFS is not set +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +# CONFIG_SND_USB is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_DMAENGINE_PCM=y +CONFIG_SND_SOC_XILINX=y +CONFIG_SND_SOC_AXI_SPDIF=y +CONFIG_SND_SOC_ADV7511_HDMI=y +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACRUX is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LOGITECH is not set +CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB_ARCH_HAS_XHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_SUSPEND=y +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_XUSBPS_DR_OF=y +CONFIG_USB_EHCI_XUSBPS=y +# CONFIG_USB_EHCI_MV is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_RENESAS_USBHS is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +CONFIG_USB_GADGET_XUSBPS=y +CONFIG_USB_XUSBPS=y +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +CONFIG_USB_ZERO=m +# CONFIG_USB_ZERO_HNPTEST is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_GPIO_VBUS is not set +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_USB_XUSBPS_OTG=y +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF_XILINX_PS=y +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_WBSD is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +CONFIG_RTC_DRV_PCF8563=y +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_XILINX_DMA=y +# CONFIG_AMBA_PL08X is not set +# CONFIG_DW_DMAC is not set +# CONFIG_TIMB_DMA is not set +# CONFIG_PL330_DMA is not set +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_BALLOON is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_USBIP_CORE is not set +# CONFIG_ECHO is not set +# CONFIG_ASUS_OLED is not set +# CONFIG_RTS5139 is not set +# CONFIG_TRANZPORT is not set +# CONFIG_LINE6_USB is not set + +# +# I2C encoder or helper chips +# +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_SIL164 is not set +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +CONFIG_IIO_SW_RING=y +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16204 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_KXSD9 is not set +# CONFIG_LIS3L02DQ is not set +# CONFIG_SCA3000 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7291 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7606 is not set +# CONFIG_AD799X is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_ADT7310 is not set +# CONFIG_ADT7410 is not set +# CONFIG_AD7280 is not set +CONFIG_CF_AD9467=y +# CONFIG_MAX1363 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Amplifiers +# +CONFIG_AD8366=y + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD5686 is not set +# CONFIG_MAX517 is not set + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +CONFIG_AD9523=y +CONFIG_AD9548=y + +# +# Direct Digital Synthesis +# +# CONFIG_AD5930 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_AD9850 is not set +# CONFIG_AD9852 is not set +# CONFIG_AD9910 is not set +# CONFIG_AD9951 is not set +CONFIG_AD9122_CF=y +CONFIG_AD9122_CF_DAC=y + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +CONFIG_ADF4350=y + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16060 is not set +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set + +# +# Light sensors +# +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_TSL2563 is not set +# CONFIG_TSL2583 is not set + +# +# Magnetometer sensors +# +# CONFIG_SENSORS_AK8975 is not set +# CONFIG_SENSORS_HMC5843 is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7753 is not set +# CONFIG_ADE7754 is not set +# CONFIG_ADE7758 is not set +# CONFIG_ADE7759 is not set +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set +# CONFIG_IIO_GPIO_TRIGGER is not set +# CONFIG_IIO_SYSFS_TRIGGER is not set +# CONFIG_IIO_SIMPLE_DUMMY is not set +# CONFIG_XVMALLOC is not set +# CONFIG_ZRAM is not set +# CONFIG_FB_SM7XX is not set +# CONFIG_USB_ENESTORAGE is not set +# CONFIG_BCM_WIMAX is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +# CONFIG_ANDROID is not set +CONFIG_CLKDEV_LOOKUP=y + +# +# Hardware Spinlock drivers +# +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT23=y +CONFIG_EXT4_FS_XATTR=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=20 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +# CONFIG_PROVE_RCU_REPEATEDLY is not set +# CONFIG_SPARSE_RCU_POINTER is not set +CONFIG_LOCKDEP=y +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_LOCKDEP is not set +CONFIG_TRACE_IRQFLAGS=y +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_CPU_STALL_VERBOSE is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_LKDTM is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +CONFIG_DEBUG_LL=y +CONFIG_DEBUG_LL_UART_NONE=y +# CONFIG_DEBUG_ICEDCC is not set +CONFIG_EARLY_PRINTK=y +# CONFIG_OC_ETM is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_RNG=m +CONFIG_CRYPTO_RNG2=m +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_PCI_IOMAP=y +# CONFIG_CRC_CCITT is not set +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +# CONFIG_CRC8 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set From 051f39ff99b71f93b70a131993cec673aed13e83 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Mon, 25 Jun 2012 19:42:33 -0700 Subject: [PATCH 146/261] xgpiops: Fix for xgpiops state change --- drivers/gpio/xilinx_gpiops.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/xilinx_gpiops.c b/drivers/gpio/xilinx_gpiops.c index 16463582e9fa0..f569fe049f6e3 100755 --- a/drivers/gpio/xilinx_gpiops.c +++ b/drivers/gpio/xilinx_gpiops.c @@ -215,7 +215,9 @@ static void xgpiops_set_value(struct gpio_chip *chip, unsigned int pin, * get the 32 bit value to be written to the mask/data register where * the upper 16 bits is the mask and lower 16 bits is the data */ - state &= 0x01; + //state &= 0x01; + if(state) + state = 1; state = ~(1 << (bank_pin_num + 16)) & ((state << bank_pin_num) | 0xFFFF0000); From 6bdf0f45225447753a165d7e6b3f2e2da1e9dc3a Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Mon, 25 Jun 2012 19:52:48 -0700 Subject: [PATCH 147/261] Initial Commit for PmodOLED driver THis commit includes the driver for PmodOLED device (compatible with on-board OLED for ZED Rev.B as well). ZED on-board OLED device is added into ZED default device tree. PmodOLED is selected in digilent_zed_defconfig. There is a bug when PmodOLED is compiled as loadable module. The bug may cause kernel panic after inserting to and removing from the kernel for several times. --- arch/arm/boot/dts/digilent-zed.dts | 29 +- arch/arm/configs/digilent_zed_defconfig | 8 +- drivers/Kconfig | 2 + drivers/Makefile | 2 + drivers/pmods/Kconfig | 20 + drivers/pmods/Makefile | 5 + drivers/pmods/pmodoled.c | 771 ++++++++++++++++++++++++ 7 files changed, 828 insertions(+), 9 deletions(-) create mode 100644 drivers/pmods/Kconfig create mode 100644 drivers/pmods/Makefile create mode 100644 drivers/pmods/pmodoled.c diff --git a/arch/arm/boot/dts/digilent-zed.dts b/arch/arm/boot/dts/digilent-zed.dts index ebbb14f19521d..240f11b44fba5 100644 --- a/arch/arm/boot/dts/digilent-zed.dts +++ b/arch/arm/boot/dts/digilent-zed.dts @@ -77,9 +77,26 @@ compatible = "xlnx,ps7-gpio-1.00.a"; reg = <0xe000a000 0x1000>; interrupts = <0x0 0x14 0x0>; - interrupt-parent = <0x1>; - gpio-controller; - #gpio-cells = <0x2>; + + oled@0 { + compatible = "dglnt,pmodoled-1.00.a"; + spi-bus-num = <2>; + spi-speed-hz = <4000000>; + gpio-width = <0x6>; + gpio-pins = <0x37 0x38 0x39 0x3a 0x3b 0x3c>; + }; + + sw@1 { + compatible = "dglnt,sw-gpio-1.00.a"; + gpio-width = <0x8>; + gpio-pins = <69 70 71 72 73 74 75 76>; + }; + + led@2 { + compatible = "dglnt,led-gpio-1.00.a"; + gpio-width = <0x8>; + gpio-pins = <61 62 63 64 65 66 67 68>; + }; }; i2c@41600000 { @@ -165,7 +182,7 @@ linux,phandle = <0x4>; phandle = <0x4>; - dma-channel@7e200000 { + dma-channel@43000000 { compatible = "xlnx,axi-vdma-mm2s-channel"; interrupts = <0x0 0x3b 0x4>; xlnx,datawidth = <0x40>; @@ -174,9 +191,9 @@ }; }; - cf-adv7x11-core@6c000000 { + cf-adv7x11-core@70e00000 { compatible = "adi,cf-adv7x11-core-1.00.a"; - reg = <0x6c000000 0x10000 0x66000000 0x10000>; + reg = <0x70e00000 0x10000 0x79000000 0x10000>; slave_adapter = <0x3>; dma-request = <0x4 0x0>; }; diff --git a/arch/arm/configs/digilent_zed_defconfig b/arch/arm/configs/digilent_zed_defconfig index 69bc833c49126..7dd7ff8f29717 100755 --- a/arch/arm/configs/digilent_zed_defconfig +++ b/arch/arm/configs/digilent_zed_defconfig @@ -667,7 +667,6 @@ CONFIG_MTD_PHYSMAP_OF=y # # CONFIG_MTD_DATAFLASH is not set # CONFIG_MTD_M25P80 is not set -# CONFIG_M25PXX_USE_FAST_READ is not set # CONFIG_MTD_SST25L is not set # CONFIG_MTD_SLRAM is not set # CONFIG_MTD_PHRAM is not set @@ -1082,8 +1081,8 @@ CONFIG_SPI_MASTER=y # SPI Master Controller Drivers # # CONFIG_SPI_ALTERA is not set -# CONFIG_SPI_BITBANG is not set -# CONFIG_SPI_GPIO is not set +CONFIG_SPI_BITBANG=y +CONFIG_SPI_GPIO=y # CONFIG_SPI_OC_TINY is not set # CONFIG_SPI_PL022 is not set # CONFIG_SPI_PXA2XX_PCI is not set @@ -1876,6 +1875,9 @@ CONFIG_CLKDEV_LOOKUP=y # CONFIG_IOMMU_SUPPORT is not set # CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set +CONFIG_PMODS=y +CONFIG_PMODS_DEBUG=y +CONFIG_PMODOLED=y # # File systems diff --git a/drivers/Kconfig b/drivers/Kconfig index fe2d57f705e9e..06dfe36b48796 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -138,4 +138,6 @@ source "drivers/virt/Kconfig" source "drivers/devfreq/Kconfig" +source "drivers/pmods/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 88f5627415b02..abcf8e6e91163 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -134,3 +134,5 @@ obj-$(CONFIG_VIRT_DRIVERS) += virt/ obj-$(CONFIG_HYPERV) += hv/ obj-$(CONFIG_PM_DEVFREQ) += devfreq/ + +obj-$(CONFIG_PMODS) += pmods/ diff --git a/drivers/pmods/Kconfig b/drivers/pmods/Kconfig new file mode 100644 index 0000000000000..207dcaac2116b --- /dev/null +++ b/drivers/pmods/Kconfig @@ -0,0 +1,20 @@ +menuconfig PMODS + bool "Pmod Support" + depends on HAS_IOMEM && OF + help + Digilent PMOD Support + +if PMODS + +config PMODS_DEBUG + bool "Enable Debug Message" + +config PMODOLED + tristate "PmodOLED1" + select SPI_BITBANG + select SPI_GPIO + help + The Digilent PmodOLED1, as well as ZED on-board OLED. Uses SPI over GPIO. + Configuration SPI_BITBANG and SPI_GPIO will be selected automatically. + +endif # PMODS diff --git a/drivers/pmods/Makefile b/drivers/pmods/Makefile new file mode 100644 index 0000000000000..40031dbaada77 --- /dev/null +++ b/drivers/pmods/Makefile @@ -0,0 +1,5 @@ + +ccflags-$(CONFIG_PMODS_DEBUG) += -DDEBUG + +obj-$(CONFIG_PMODOLED) += pmodoled.o + diff --git a/drivers/pmods/pmodoled.c b/drivers/pmods/pmodoled.c new file mode 100644 index 0000000000000..11a94fea6bf02 --- /dev/null +++ b/drivers/pmods/pmodoled.c @@ -0,0 +1,771 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "pmodoled" +#define DISPLAY_BUF_SZ 512 /* 32 x 128 bit monochrome == 512 bytes */ +#define MAX_LINE_LEN 16 /* 128 bits wide and current char width is 8 bit */ +#define MAX_ROW 4 +#define OLED_MAX_PG_CNT 4 /* number of display pages in OLED controller */ +#define OLED_CONTROLLER_PG_SZ 128 +#define OLED_CONTROLLER_CMD 0 +#define OLED_CONTROLLER_DATA 1 + +/* commands for the OLED display controller */ +#define OLED_SET_PG_ADDR 0x22 +#define OLED_DISPLAY_OFF 0xAE +#define OLED_DISPLAY_ON 0xAF +#define OLED_CONTRAST_CTRL 0x81 +#define OLED_SET_PRECHARGE_PERIOD 0xD9 +#define OLED_SET_SEGMENT_REMAP 0xA1 +#define OLED_SET_COM_DIR 0xC8 +#define OLED_SET_COM_PINS 0xDA + +dev_t pmodoled_dev_id = 0; +static unsigned int device_num = 0; +static unsigned int cur_minor = 0; +struct mutex minor_mutex; + +struct pmodoled_device { + /* R/W Mutex Lock */ + struct mutex mutex; + /* Display Buffers */ + uint8_t disp_on; + uint8_t *disp_buf; + /* Pin Assignment */ + unsigned long iVBAT; + unsigned long iVDD; + unsigned long iRES; + unsigned long iDC; + unsigned long iCLK; + unsigned long iMOSI; + unsigned long iCS; + /* SPI Info */ + uint32_t spi_id; + /* platform device structures */ +// struct spi_gpio_platform_data pdata; + struct platform_device *pdev; + /* Char Device */ + struct cdev cdev; + struct spi_device *spi; + dev_t dev_id; +}; + +/** + * screen_buf_to_display - + * @screen_buf - + * @dev - + * + */ +static int screen_buf_to_display(uint8_t *screen_buf, struct pmodoled_device *dev) +{ + uint32_t pg; + int status; + uint8_t lower_start_column = 0x00; + uint8_t upper_start_column = 0x10; + uint8_t wr_buf[10]; + + for(pg = 0; pg < OLED_MAX_PG_CNT; pg++) { + wr_buf[0] = OLED_SET_PG_ADDR; + wr_buf[1] = pg; + wr_buf[2] = lower_start_column; + wr_buf[3] = upper_start_column; + gpio_set_value(dev->iDC, OLED_CONTROLLER_CMD); + status = spi_write(dev->spi, wr_buf, 4); + if(status) { + printk(KERN_INFO DRIVER_NAME "screen_buf_to_display: Error writing to SPI\n"); + break; + } + + gpio_set_value(dev->iDC, OLED_CONTROLLER_DATA); + status = spi_write(dev->spi, (uint8_t *) (screen_buf + + (pg*OLED_CONTROLLER_PG_SZ)), OLED_CONTROLLER_PG_SZ); + if(status) { + printk(KERN_INFO DRIVER_NAME "screen_buf_to_display: Error writing to SPI\n"); + break; + } + } + return status; +} + +/** + * A basic open function. It exists mainly to save the id of + * the OLED and some other basic information. + */ +static int pmodoled_open(struct inode *inode, struct file *fp) +{ + struct pmodoled_device *dev; + + dev = container_of(inode->i_cdev, struct pmodoled_device, cdev); + fp->private_data = dev; +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO "pmodoled: VBAT\t%d\n", dev->iVBAT); + printk(KERN_INFO "pmodoled: VDD\t%d\n", dev->iVDD); + printk(KERN_INFO "pmodoled: RES\t%d\n", dev->iRES); + printk(KERN_INFO "pmodoled: DC\t%d\n", dev->iDC); + printk(KERN_INFO "pmodoled: SCLK\t%d\n", dev->iCLK); + printk(KERN_INFO "pmodoled: SDIN\t%d\n", dev->iMOSI); +#endif + + return 0; +} + +static int pmodoled_close(struct inode *inode, struct file *fp) +{ + return 0; +} + +/** + * Driver write function + * + * This function uses a generic SPI write to send values to the Pmod device + * It takes a raw data array from the app in the buffer, copied it into + * device dispay buffer, and finally sends the buffer to the OLED using SPI + */ +static ssize_t pmodoled_write(struct file *fp, const char __user *buffer, size_t length, loff_t *offset) +{ + ssize_t retval = 0; + struct pmodoled_device *dev; + unsigned int minor_id; + int cnt; + int status; + + dev = fp->private_data; + minor_id = MINOR(dev->dev_id); + + if(mutex_lock_interruptible(&dev->mutex)) { + retval = -ERESTARTSYS; + goto write_lock_err; + } + + if (buffer == NULL) { + printk(KERN_ALERT "oled_write: ERROR: invalid buffer address: 0x%08x\n", + (unsigned int) buffer); + retval = -EINVAL; + goto quit_write; + } + + if(length > DISPLAY_BUF_SZ) { + cnt = DISPLAY_BUF_SZ; + } + else { + cnt = length; + } + + printk(KERN_INFO "oled_write: data length %d\n", cnt); + if(copy_from_user(dev->disp_buf, buffer, cnt)) { + printk(KERN_ALERT "oled_write: copy_from_user failed\n"); + retval = -EFAULT; + goto quit_write; + } + else { + retval = cnt; + } + + status = screen_buf_to_display(dev->disp_buf, dev); + if(status) { + printk(KERN_ALERT "oled_write: Error sending string to display\n"); + retval = -EFAULT; + goto quit_write; + } + +quit_write: + mutex_unlock(&dev->mutex); +write_lock_err: + return retval; +} + +/** + * Driver Read Function + * + * This function does not actually read the Pmod as it is a write-only device. Instead + * It returns data in the buffer generated for the display that was used when the OLED + * was last programmed. + */ +static ssize_t pmodoled_read(struct file *fp, char __user *buffer, size_t length, loff_t *offset) +{ + ssize_t retval = 0; + struct pmodoled_device *dev; + unsigned int minor_id; + int cnt; + + dev = fp->private_data; + minor_id = MINOR(dev->dev_id); + + if(mutex_lock_interruptible(&dev->mutex)) { + retval = -ERESTARTSYS; + goto read_lock_err; + } + + if (buffer == NULL) { + dev_err(&dev->spi->dev, "OLED_read: ERROR: invalid buffer " + "address: 0x%08X\n", (unsigned int)buffer); + retval = -EINVAL; + goto quit_read; + } + + if (length > DISPLAY_BUF_SZ) + cnt = DISPLAY_BUF_SZ; + else + cnt = length; + retval = copy_to_user((void *)buffer, dev->disp_buf, cnt); + if (!retval) + retval = cnt; /* copy success, return amount in buffer */ + +quit_read: + mutex_unlock(&dev->mutex); +read_lock_err: + return(retval); +} + +struct file_operations pmodoled_cdev_fops = { + .owner = THIS_MODULE, + .write = pmodoled_write, + .read = pmodoled_read, + .open = pmodoled_open, + .release = pmodoled_close, +}; + +static const struct of_device_id pmodoled_of_match[] = { + { .compatible = "dglnt,pmodoled-1.00.a", }, + {}, +}; + +static int __init add_pmodoled_device_to_bus(struct pmodoled_device* dev) { + struct spi_master *spi_master; + struct spi_device *spi_device; + int status = 0; + + spi_master = spi_busnum_to_master(dev->spi_id); + if(!spi_master) { + printk(KERN_ALERT "spi_busnum_to_master(%d) returned NULL\n", dev->spi_id); + return -ENOSYS; + } + + spi_device = spi_alloc_device(spi_master); + if(!spi_device) { + put_device(&spi_master->dev); + printk(KERN_ALERT "spi_alloc_device() failed\n"); + return -ENOMEM; + } + + spi_device->chip_select = 0; + spi_device->max_speed_hz = 4000000; + spi_device->mode = SPI_MODE_0; + spi_device->bits_per_word = 8; + spi_device->controller_data = dev->iCS; + spi_device->dev.platform_data = (void *)dev; + strlcpy(spi_device->modalias, DRIVER_NAME, sizeof(DRIVER_NAME)); + + status = spi_add_device(spi_device); + if(status < 0) { + spi_dev_put(spi_device); + printk(KERN_ALERT "spi_add_device() failed %d\n", status); + return status; + } + dev->spi = spi_device; + + put_device(&spi_master->dev); + + return status; +} + +/** + * pmodoled_of_probe - Probe method for ZED on-board OLED device. + * @np: pointer to device tree node + * + * This function probes the OLED device in the device tree. It initializes the + * OLED driver data structure. It returns 0, if the driver is bound to the OLED + * device, or a negative value if there is an error. + */ +static int __init pmodoled_of_probe(struct device_node *np) +{ + struct pmodoled_device *pmodoled_dev; + struct platform_device *pmodoled_pdev; + struct spi_gpio_platform_data *pmodoled_pdata; + const u32* tree_info; + int status = 0; + + /* Alloc Space for platform device structure */ + pmodoled_dev = (struct pmodoled_device*) kzalloc(sizeof(*pmodoled_dev), GFP_KERNEL); + if(!pmodoled_dev) { + status = -ENOMEM; + goto dev_alloc_err; + } + pmodoled_dev->disp_buf = NULL; + + /* Get CS for SPI_GPIO */ + tree_info = of_get_property(np, "spi-chip-select", NULL); + if(tree_info) { + pmodoled_dev->iCS = be32_to_cpup((tree_info)); + } + else { + pmodoled_dev->iCS = SPI_GPIO_NO_CHIPSELECT; + } + + /* Get the Pin index */ + tree_info = of_get_property(np, "gpio-pins", NULL); + if(tree_info) { + pmodoled_dev->iVBAT = be32_to_cpup((tree_info)); + pmodoled_dev->iVDD = be32_to_cpup((tree_info + 1)); + pmodoled_dev->iRES = be32_to_cpup((tree_info + 2)); + pmodoled_dev->iDC = be32_to_cpup((tree_info + 3)); + pmodoled_dev->iCLK = be32_to_cpup((tree_info + 4)); + pmodoled_dev->iMOSI = be32_to_cpup((tree_info + 5)); +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO "pmodoled: VBAT\t%d\n", pmodoled_dev->iVBAT); + printk(KERN_INFO "pmodoled: VDD\t%d\n", pmodoled_dev->iVDD); + printk(KERN_INFO "pmodoled: RES\t%d\n", pmodoled_dev->iRES); + printk(KERN_INFO "pmodoled: DC\t%d\n", pmodoled_dev->iDC); + printk(KERN_INFO "pmodoled: SCLK\t%d\n",pmodoled_dev->iCLK); + printk(KERN_INFO "pmodoled: SDIN\t%d\n", pmodoled_dev->iMOSI); +#endif + } + + /* Get SPI Related Params */ + tree_info = of_get_property(np, "spi-bus-num", NULL); + if(tree_info) { + pmodoled_dev->spi_id = be32_to_cpup((tree_info)); +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO "pmodoled: BUS_ID\t%x\n", pmodoled_dev->spi_id); +#endif + } + + /* Alloc Space for platform data structure */ + pmodoled_pdata = (struct spi_gpio_platform_data*) kzalloc(sizeof(*pmodoled_pdata), GFP_KERNEL); + if(!pmodoled_pdata) { + status = -ENOMEM; + goto pdata_alloc_err; + } + + /* Fill up Platform Data Structure */ + pmodoled_pdata->sck = pmodoled_dev->iCLK; + pmodoled_pdata->miso = SPI_GPIO_NO_MISO; + pmodoled_pdata->mosi = pmodoled_dev->iMOSI; + pmodoled_pdata->num_chipselect = 1; + + /* Alloc Space for platform data structure */ + pmodoled_pdev = (struct platform_device*) kzalloc(sizeof(*pmodoled_pdev), GFP_KERNEL); + if(!pmodoled_pdev) { + status = -ENOMEM; + goto pdev_alloc_err; + } + + /* Fill up Platform Device Structure */ + pmodoled_pdev->name = "spi_gpio"; + pmodoled_pdev->id = pmodoled_dev->spi_id; + pmodoled_pdev->dev.platform_data = pmodoled_pdata; + pmodoled_dev->pdev = pmodoled_pdev; + + /* Register spi_gpio master */ + status = platform_device_register(pmodoled_dev->pdev); + if(status < 0) { + printk(KERN_ALERT "platform_device_register failed: %d\n", status); + goto pdev_reg_err; + } + /* Fill up Board Info for SPI device */ + status = add_pmodoled_device_to_bus(pmodoled_dev); + if(status < 0) { + printk(KERN_ALERT "add_pmodoled_device_to_bus failed: %d\n", status); + goto spi_add_err; + } + + /* Point device node data to pmodoled_device structure */ + if(np->data == NULL) + np->data = pmodoled_dev; + + device_num ++; + return status; + +spi_add_err: + platform_device_unregister(pmodoled_dev->pdev); +pdev_reg_err: + kfree(pmodoled_pdev); +pdev_alloc_err: + kfree(pmodoled_pdata); +pdata_alloc_err: + kfree(pmodoled_dev); +dev_alloc_err: + return status; +} + +/** + * pmodoled_of_remove - Remove method for ZED on-board OLED device. + * @np: pointer to device tree node + * + * This function removes the OLED device in the device tree. It frees the + * OLED driver data structure. It returns 0, if the driver is successfully + * removed, or a negative value if there is an error. + */ +static int __exit pmodoled_of_remove(struct device_node *np) +{ + struct pmodoled_device *pmodoled_dev; + + if(np->data == NULL) { + printk(KERN_ERR "pmodoled %s: ERROR: No pmodoled_device structure found!\n", np->name); + return -ENOSYS; + } + pmodoled_dev = (struct pmodoled_device*) (np->data); + + if(pmodoled_dev->spi != NULL) { + spi_unregister_device(pmodoled_dev->spi); + } + + platform_device_unregister(pmodoled_dev->pdev); + + if(pmodoled_dev->disp_buf != NULL) { + kfree(pmodoled_dev->disp_buf); + } + + kfree(pmodoled_dev); + np->data = NULL; + + return 0; +} + +/** + * pmodoled_setup_cdev - Setup Char Device for ZED on-board OLED device. + * @dev: pointer to device tree node + * @dev_id: pointer to device major and minor number + * @spi: pointer to spi_device structure + * + * This function initializes char device for OLED device, and add it into + * kernel device structure. It returns 0, if the cdev is successfully + * initialized, or a negative value if there is an error. + */ +static int pmodoled_setup_cdev(struct pmodoled_device *dev, dev_t *dev_id, struct spi_device *spi) +{ + int status; + + cdev_init(&dev->cdev, &pmodoled_cdev_fops); + dev->cdev.owner = THIS_MODULE; + dev->cdev.ops = &pmodoled_cdev_fops; + dev->spi = spi; + + *dev_id = MKDEV(MAJOR(pmodoled_dev_id), cur_minor++); + status = cdev_add(&dev->cdev, *dev_id, 1); + + return status; +} + +/** + * pmodoled_init_gpio - Initialize GPIO for ZED Onboard OLED + * @dev - pmodoled_device + * + * Initializes OLED GPIO Control Pins. + * It returns 0, if the gpio pins are successfully + * initialized, or a negative value if there is an error. + */ +static int pmodoled_init_gpio(struct pmodoled_device *dev) +{ + + struct gpio pmodoled_ctrl[] = { + {dev->iVBAT, GPIOF_OUT_INIT_HIGH, "OLED VBat"}, + {dev->iVDD, GPIOF_OUT_INIT_HIGH, "OLED VDD"}, + {dev->iRES, GPIOF_OUT_INIT_HIGH, "OLED_RESET"}, + {dev->iDC, GPIOF_OUT_INIT_HIGH, "OLED_D/C"}, + }; + int status; + int i; + + for (i = 0; i < ARRAY_SIZE(pmodoled_ctrl); i++) { + status = gpio_is_valid(pmodoled_ctrl[i].gpio); + if(!status) { + printk(KERN_INFO DRIVER_NAME "!! gpio_is_valid for GPIO %d, %s FAILED!, status: %d\n", + pmodoled_ctrl[i].gpio, pmodoled_ctrl[i].label, status); + goto gpio_invalid; + } + } + + status = gpio_request_array(pmodoled_ctrl, ARRAY_SIZE(pmodoled_ctrl)); + if(status) { + printk(KERN_INFO DRIVER_NAME "!! gpio_request_array FAILED!\n"); + printk(KERN_INFO DRIVER_NAME " status is: %d\n", status); + goto gpio_invalid; + } + +gpio_invalid: + return status; +} + +/** + * pmodoled_disp_init - + * @dev: + * + */ +static void pmodoled_disp_init(struct pmodoled_device *dev) +{ + int status; + uint8_t wr_buf[20]; + + // We are going to be sending commands + // so clear the data/cmd bit + gpio_set_value(dev->iDC, OLED_CONTROLLER_CMD); + + // Start by turning VDD on and wait for the power to come up + gpio_set_value(dev->iVDD, 0); + msleep(1); + + // Display off Command + wr_buf[0] = OLED_DISPLAY_OFF; + status = spi_write(dev->spi, wr_buf, 1); + + /* Bring Reset Low and then High */ + gpio_set_value(dev->iRES, 1); + msleep(1); + gpio_set_value(dev->iRES, 0); + msleep(1); + gpio_set_value(dev->iRES, 1); + + // Send the set charge pump and set precharge period commands + wr_buf[0] = 0x8D; + wr_buf[1] = 0x14; + wr_buf[2] = OLED_SET_PRECHARGE_PERIOD; + wr_buf[3] = 0xF1; + + status = spi_write(dev->spi, wr_buf, 4); + + /* Turn on VCC and wait 100ms */ + gpio_set_value(dev->iVBAT, 0); + msleep(100); + + /* Set Display COntrast */ + wr_buf[0] = OLED_CONTRAST_CTRL; + wr_buf[1] = 0x0F; + + /* Invert the display */ + wr_buf[2] = OLED_SET_SEGMENT_REMAP; // Remap Columns + wr_buf[3] = OLED_SET_COM_DIR; // Remap Rows + + // Select sequential COM configuration + wr_buf[4] = OLED_SET_COM_PINS; + wr_buf[5] = 0x00; + wr_buf[6] = 0xC0; + wr_buf[7] = 0x20; + wr_buf[8] = 0x00; + + // Turn on Display + wr_buf[9] = OLED_DISPLAY_ON; + + status = spi_write(dev->spi, wr_buf, 10); +} + + +/** + * SPI hardware probe. Sets correct SPI mode, attempts + * to obtain memory needed by the driver, and performs + * a simple initialization of the device. + */ +static int pmodoled_spi_probe(struct spi_device *spi) { + int status = 0; + struct pmodoled_device *pmodoled_dev; + + printk(KERN_INFO DRIVER_NAME "oled_spi_probe: Probing %s ..........\n", DRIVER_NAME); + + /* We rely on full duplex transfers, mostly to reduce + * per transfer overheads (by making few transfers). + */ + if (spi->master->flags & SPI_MASTER_HALF_DUPLEX) { + status = -EINVAL; + printk(KERN_INFO DRIVER_NAME "SPI settings incorrect: %d\n", status); + goto spi_err; + } + + /* We must use SPI_MODE_0 */ + spi->mode = SPI_MODE_0; + spi->bits_per_word = 8; + + status = spi_setup(spi); + if(status < 0) { + printk(KERN_INFO DRIVER_NAME "needs SPI mode %02x, %d KHz; %d\n", + spi->mode, spi->max_speed_hz / 1000, + status); + goto spi_err; + } + + /* Get pmodoled_device structure */ + pmodoled_dev = (struct pmodoled_device*) spi->dev.platform_data; + if(pmodoled_dev == NULL) { + printk(KERN_INFO DRIVER_NAME "Cannot get pmodoled_device.\n"); + goto spi_platform_data_err; + } + + /* Alloc Graphic Buffer for device */ + pmodoled_dev->disp_buf = (uint8_t*) kmalloc(DISPLAY_BUF_SZ, GFP_KERNEL); + if(!pmodoled_dev->disp_buf) { + status = -ENOMEM; + printk(KERN_INFO DRIVER_NAME "Device Display data buffer allocation failed: %d\n", status); + goto disp_buf_alloc_err; + } + + /* Setup char driver */ + status = pmodoled_setup_cdev(pmodoled_dev, &(pmodoled_dev->dev_id), spi); + if (status) { + printk(KERN_INFO DRIVER_NAME "oled_spi_probe: Error adding %s device: %d\n", DRIVER_NAME, status); + goto cdev_add_err; + } + + /* Initialize Mutex */ + mutex_init(&pmodoled_dev->mutex); + + /** + * It is important to the OLED's longevity that the lines that + * control it's power are carefully controlled. This is a good + * time to ensure that the device is ot turned on until it is + * instructed to do so. + */ + status = pmodoled_init_gpio(pmodoled_dev); + if(status) { + printk(KERN_INFO DRIVER_NAME "oled_spi_probe: Error initializing GPIO\n"); + goto oled_init_error; + } + + pmodoled_disp_init(pmodoled_dev); + + memset(pmodoled_dev->disp_buf, 0xF0, DISPLAY_BUF_SZ); + + status = screen_buf_to_display(pmodoled_dev->disp_buf, pmodoled_dev); + if(status) { + printk(KERN_INFO DRIVER_NAME "oled_spi_probe: Error sending initial Display String\n"); + goto oled_init_error; + } + return status; + +oled_init_error: +cdev_add_err: + if (&pmodoled_dev->cdev) + cdev_del(&pmodoled_dev->cdev); + if(pmodoled_dev->disp_buf) + kfree(pmodoled_dev->disp_buf); +disp_buf_alloc_err: +spi_platform_data_err: +spi_err: + return(status); +} + +static int __devexit pmodoled_spi_remove(struct spi_device *spi) +{ + int status; + struct pmodoled_device *dev; + uint8_t wr_buf[10]; + + dev = (struct pmodoled_device*) spi->dev.platform_data; + + /* Clear Display */ + memset(dev->disp_buf, 0, DISPLAY_BUF_SZ); + status = screen_buf_to_display(dev->disp_buf, dev); + + /* Turn off display */ + wr_buf[0] = OLED_DISPLAY_OFF; + status = spi_write(spi, wr_buf, 1); + if(status) { + dev_err(&spi->dev, "oled_spi_remove: Error writing to SPI device\n"); + } + + /* Turn off VCC (VBAT) */ + gpio_set_value(dev->iVBAT, 1); + msleep(100); + /* TUrn off VDD Power */ + gpio_set_value(dev->iVDD, 1); + +{ + struct gpio pmodoled_ctrl[] = { + {dev->iVBAT, GPIOF_OUT_INIT_HIGH, "OLED VBat"}, + {dev->iVDD, GPIOF_OUT_INIT_HIGH, "OLED VDD"}, + {dev->iRES, GPIOF_OUT_INIT_HIGH, "OLED_RESET"}, + {dev->iDC, GPIOF_OUT_INIT_HIGH, "OLED_D/C"}, + }; + + gpio_free_array(pmodoled_ctrl, 4); +} + + if(dev->disp_buf) { + kfree(dev->disp_buf); + } + + if(&dev->cdev) { + cdev_del(&dev->cdev); + } + + return status; +} + +static struct spi_driver pmodoled_spi_driver = { + .driver = { + .name = DRIVER_NAME, + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = pmodoled_spi_probe, + .remove = __devexit_p(pmodoled_spi_remove), +}; + +/** + * pmodoled_init - Initial driver registration call + */ + +static int __init pmodoled_init(void) +{ + int status; +#ifdef CONFIG_OF + struct device_node *np; + + for_each_matching_node(np, pmodoled_of_match) + pmodoled_of_probe(np); +#else + printk(KERN_INFO "pmodoled: CONFIG_OF needs to be enabled!\n"); + return 0; +#endif + + /* Alloc Major & Minor number for char device */ + status = alloc_chrdev_region(&pmodoled_dev_id, 0, device_num, DRIVER_NAME); + if(status) { + printk(KERN_INFO DRIVER_NAME "Character device region not allocated correctly: %d\n", status); + return status; + } + + return spi_register_driver(&pmodoled_spi_driver); +} + +/** + * pmodoled_exit - Clean up function when module gets removed + */ + +static void __exit pmodoled_exit(void) +{ + spi_unregister_driver(&pmodoled_spi_driver); + + unregister_chrdev_region(pmodoled_dev_id, device_num); + +#ifdef CONFIG_OF +{ + struct device_node *np; + + for_each_matching_node(np, pmodoled_of_match) + pmodoled_of_remove(np); +} +#endif + + return; +} + +module_init(pmodoled_init); +module_exit(pmodoled_exit); + +MODULE_AUTHOR("Digilent, Inc."); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(DRIVER_NAME": ZED On-board OLED display driver"); +MODULE_ALIAS("spi:"DRIVER_NAME); From 78a8fc17742547997141c522bd9360658978b12c Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Wed, 27 Jun 2012 19:42:06 -0700 Subject: [PATCH 148/261] Pmods: pmodoled: Fix module removal procedure which causes kernel panic This commit fixes the bug of Pmodoled when compiled as loadable module. --- drivers/pmods/pmodoled.c | 47 +++++++++++++++------------------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/drivers/pmods/pmodoled.c b/drivers/pmods/pmodoled.c index 11a94fea6bf02..284af366e8fee 100644 --- a/drivers/pmods/pmodoled.c +++ b/drivers/pmods/pmodoled.c @@ -56,7 +56,6 @@ struct pmodoled_device { /* SPI Info */ uint32_t spi_id; /* platform device structures */ -// struct spi_gpio_platform_data pdata; struct platform_device *pdev; /* Char Device */ struct cdev cdev; @@ -267,7 +266,7 @@ static int __init add_pmodoled_device_to_bus(struct pmodoled_device* dev) { spi_device->mode = SPI_MODE_0; spi_device->bits_per_word = 8; spi_device->controller_data = dev->iCS; - spi_device->dev.platform_data = (void *)dev; + spi_device->dev.platform_data = dev; strlcpy(spi_device->modalias, DRIVER_NAME, sizeof(DRIVER_NAME)); status = spi_add_device(spi_device); @@ -305,7 +304,14 @@ static int __init pmodoled_of_probe(struct device_node *np) status = -ENOMEM; goto dev_alloc_err; } - pmodoled_dev->disp_buf = NULL; + + /* Alloc Graphic Buffer for device */ + pmodoled_dev->disp_buf = (uint8_t*) kmalloc(DISPLAY_BUF_SZ, GFP_KERNEL); + if(!pmodoled_dev->disp_buf) { + status = -ENOMEM; + printk(KERN_INFO DRIVER_NAME "Device Display data buffer allocation failed: %d\n", status); + goto disp_buf_alloc_err; + } /* Get CS for SPI_GPIO */ tree_info = of_get_property(np, "spi-chip-select", NULL); @@ -397,6 +403,8 @@ static int __init pmodoled_of_probe(struct device_node *np) pdev_alloc_err: kfree(pmodoled_pdata); pdata_alloc_err: + kfree(pmodoled_dev->disp_buf); +disp_buf_alloc_err: kfree(pmodoled_dev); dev_alloc_err: return status; @@ -420,17 +428,11 @@ static int __exit pmodoled_of_remove(struct device_node *np) } pmodoled_dev = (struct pmodoled_device*) (np->data); - if(pmodoled_dev->spi != NULL) { - spi_unregister_device(pmodoled_dev->spi); - } - - platform_device_unregister(pmodoled_dev->pdev); - if(pmodoled_dev->disp_buf != NULL) { kfree(pmodoled_dev->disp_buf); } + platform_device_unregister(pmodoled_dev->pdev); - kfree(pmodoled_dev); np->data = NULL; return 0; @@ -603,14 +605,6 @@ static int pmodoled_spi_probe(struct spi_device *spi) { goto spi_platform_data_err; } - /* Alloc Graphic Buffer for device */ - pmodoled_dev->disp_buf = (uint8_t*) kmalloc(DISPLAY_BUF_SZ, GFP_KERNEL); - if(!pmodoled_dev->disp_buf) { - status = -ENOMEM; - printk(KERN_INFO DRIVER_NAME "Device Display data buffer allocation failed: %d\n", status); - goto disp_buf_alloc_err; - } - /* Setup char driver */ status = pmodoled_setup_cdev(pmodoled_dev, &(pmodoled_dev->dev_id), spi); if (status) { @@ -635,7 +629,7 @@ static int pmodoled_spi_probe(struct spi_device *spi) { pmodoled_disp_init(pmodoled_dev); - memset(pmodoled_dev->disp_buf, 0xF0, DISPLAY_BUF_SZ); + memset(pmodoled_dev->disp_buf, 0x00, DISPLAY_BUF_SZ); status = screen_buf_to_display(pmodoled_dev->disp_buf, pmodoled_dev); if(status) { @@ -648,9 +642,6 @@ static int pmodoled_spi_probe(struct spi_device *spi) { cdev_add_err: if (&pmodoled_dev->cdev) cdev_del(&pmodoled_dev->cdev); - if(pmodoled_dev->disp_buf) - kfree(pmodoled_dev->disp_buf); -disp_buf_alloc_err: spi_platform_data_err: spi_err: return(status); @@ -692,10 +683,6 @@ static int __devexit pmodoled_spi_remove(struct spi_device *spi) gpio_free_array(pmodoled_ctrl, 4); } - if(dev->disp_buf) { - kfree(dev->disp_buf); - } - if(&dev->cdev) { cdev_del(&dev->cdev); } @@ -746,10 +733,6 @@ static int __init pmodoled_init(void) static void __exit pmodoled_exit(void) { - spi_unregister_driver(&pmodoled_spi_driver); - - unregister_chrdev_region(pmodoled_dev_id, device_num); - #ifdef CONFIG_OF { struct device_node *np; @@ -758,6 +741,10 @@ static void __exit pmodoled_exit(void) pmodoled_of_remove(np); } #endif + + spi_unregister_driver(&pmodoled_spi_driver); + + unregister_chrdev_region(pmodoled_dev_id, device_num); return; } From 363e84a7a1a502d10b325a6808a57caea8bc167d Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Tue, 3 Jul 2012 11:09:56 -0700 Subject: [PATCH 149/261] Remove redundant zynq-ep107.dtb --- zynq-ep107.dtb | Bin 4951 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 zynq-ep107.dtb diff --git a/zynq-ep107.dtb b/zynq-ep107.dtb deleted file mode 100644 index 2715c80ced49386c938b2e74e0622add51301090..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4951 zcmb_g&yN&E6z)M8K*a#!uiFIF5Hij7EW68!*<>ypNF=Trm3Uctx@%@S+tb~2_prO1 zI2ez{3nwom+>L*M@xaxDi+3>brpX>OAs&d|_o}PAXL^VT7OCy3SKoW@t5;R8in)LE z@gJ7;+835(ty|WKckn%fdK~o_DoX1-y1(o8%->egdja1QY+nt+AlmJGxffmUT-xk8 z7c_w5wAJ1XquuUJjM^$GMmhE(D*e%(>38P(-J;)`s7ajep{KEj@ZFe`9fs^O0mTFk zpxN@qai$_l#m7~AuXu5k#i82B^S#Yaoo=tUy6iZeG>-F)C12fGO5I5(-RT5Tkf;8J zv%BuFbl0zRl$(ZoNg71?b|*+SF0!b6>|FH6USfQ_fyU=c?quNhou#Rp=KV`zz;TGM zEa9bxrO&y)jM~nENfIi1FwIK&zr~2aF=`8xy#8=~==9)A)MdVG#i;bb__W=0(j5gJ znx*XWqkTq<$sA%Dw2G1WvDil3lR#+_QV< z9Os-1am~N@F8!0|UDUG#p%@O|TkpMl2YvCGgcB#XLfq@9l|O=N4hxLzlSk+j zbJq5D{9Np<&cyEsKpQ)5?v4F;Br4j^?7W~`b3-15k4-e?xM&~VRC^gZ&f2m=bHqN$ z$D0_d%|(=JZffz{Z+C!Y6+g1))Xbi1#)hD}HO)nMKY*dyelY9tfrvGZd*sIhfA8PI zch+aM0sf;;u76_>d;%d0Z8dymNzmss*UBXm-0a!_RGTL46mz_WX2ah_2w9B3d&L}0 z|7Sg1j{kx_dFk~n_*{4xm@y1$4M?gc3( zCif2h^^gM7XN(vR(Cd(_Hv%IBLlE#z%szV_P^>~KcZr&9Hg($`z@1#vsnQxkV z>#J)k{nZ{Jg5iE_7jh%xo}wPtpL#Q~s#28bKV_^)p%E(zSqxXks=ikLSFBdW%hSc` zGhoX(kCGsk4dRv?gj{F$FhR8qf^lMsbAAWS#=KV`WRbXLxV@Q4n7WF~llrfswnr*b zY2ev{p+?=dm~Gg`drHcj?J_YwrES`6*#4+)JBri3!qcT>t+~AfOxqg<_Aqp_u~wi@ z?5S28U$edvpI;#$QIrDn#5Y+h!Icr@K^*lRgU7ya9S0A4m<>X)Qj3rD>7|Hsr7xSG z{_yV6`cr#=_m^NP7jE)*q5d*~#9^*lA1~19E~Rz<4Bw{6WGyQHlESDDgx1HqFYuI| zr%F+w;&2T;9iTZIvW18%V=&EBiatxFKS1vrkjQFjO;E1 zXHZ$h2VTW;YzO8Im7(r|m?rZ-d=cGuTc4~0069Yx(J=|PbLD8>hKGyR(WZM5qg_&#Re)Ru{d_gwM# z2__ryxB?+d!A0W1w&8XhZFA;%uXIpZBpy8-O=6!n9@IBJ8IL*##)JJb9+4aQeWf$5 zg8>wd&*pW4Y8$Y?(9h+E_`^v(z`t5dIKM^nC3I2#()ojKssu(Ja(3`7ObhRtez{Nd z*`6iISpIz!#39QoZKy#Do^Zv{Hg}EYsQGYIhL8r2l6c!qG${be3 zp-N(vKC>Ec!-jsD!*E^-9i`^UuVE^c!406ziHFeV)S4A^MiBWb-`C89g$I zeHB_>JW1R<7=+3??fQPIvds37GBfLR7Ti=t8^1rOG@T~7jayblxuy5xR=$@gD^(+l z*SnjJGD|jkH_QEaN^m~5Qa2i@%&JV_2bw&M!w}c$>6%oWYV~A{Jr73ZXl8j~>}}h_ zR9&B{$lKF>D@&B}?eR?uzpB{LbYh{}-Z)6?OohtJtst}gDOQH#fe(WTXnEnb#s75h eJ8+|IdnfQgG;{|D2yO$raPOyE3=&0prvCti@wxf{ From d03c28374109ae9353e103f872843118d3e95b28 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Tue, 3 Jul 2012 12:18:11 -0700 Subject: [PATCH 150/261] Pmods: pmodoled: Create pmodoled device node automatically Register pmodoled device class in /sys filesystem. Pmodoled device node will be created automatically in /dev and /sys/class/pmodoled. The device node is named as . (%s.%d) --- arch/arm/boot/dts/digilent-zed.dts | 12 +++--- drivers/pmods/pmodoled.c | 63 +++++++++++++++++++----------- 2 files changed, 47 insertions(+), 28 deletions(-) diff --git a/arch/arm/boot/dts/digilent-zed.dts b/arch/arm/boot/dts/digilent-zed.dts index 240f11b44fba5..105e222ecbf66 100644 --- a/arch/arm/boot/dts/digilent-zed.dts +++ b/arch/arm/boot/dts/digilent-zed.dts @@ -73,12 +73,14 @@ }; }; - gpio@e000a000 { + gpiops: gpio@e000a000 { compatible = "xlnx,ps7-gpio-1.00.a"; + #gpio-cells = <2>; reg = <0xe000a000 0x1000>; interrupts = <0x0 0x14 0x0>; - - oled@0 { + gpio-controller; + + zed_oled { compatible = "dglnt,pmodoled-1.00.a"; spi-bus-num = <2>; spi-speed-hz = <4000000>; @@ -86,13 +88,13 @@ gpio-pins = <0x37 0x38 0x39 0x3a 0x3b 0x3c>; }; - sw@1 { + zed_sw { compatible = "dglnt,sw-gpio-1.00.a"; gpio-width = <0x8>; gpio-pins = <69 70 71 72 73 74 75 76>; }; - led@2 { + zed_led { compatible = "dglnt,led-gpio-1.00.a"; gpio-width = <0x8>; gpio-pins = <61 62 63 64 65 66 67 68>; diff --git a/drivers/pmods/pmodoled.c b/drivers/pmods/pmodoled.c index 284af366e8fee..4b8708ef03806 100644 --- a/drivers/pmods/pmodoled.c +++ b/drivers/pmods/pmodoled.c @@ -38,8 +38,10 @@ dev_t pmodoled_dev_id = 0; static unsigned int device_num = 0; static unsigned int cur_minor = 0; struct mutex minor_mutex; +static struct class *pmodoled_class = NULL; struct pmodoled_device { + char *name; /* R/W Mutex Lock */ struct mutex mutex; /* Display Buffers */ @@ -110,14 +112,6 @@ static int pmodoled_open(struct inode *inode, struct file *fp) dev = container_of(inode->i_cdev, struct pmodoled_device, cdev); fp->private_data = dev; -#ifdef CONFIG_PMODS_DEBUG - printk(KERN_INFO "pmodoled: VBAT\t%d\n", dev->iVBAT); - printk(KERN_INFO "pmodoled: VDD\t%d\n", dev->iVDD); - printk(KERN_INFO "pmodoled: RES\t%d\n", dev->iRES); - printk(KERN_INFO "pmodoled: DC\t%d\n", dev->iDC); - printk(KERN_INFO "pmodoled: SCLK\t%d\n", dev->iCLK); - printk(KERN_INFO "pmodoled: SDIN\t%d\n", dev->iMOSI); -#endif return 0; } @@ -265,7 +259,7 @@ static int __init add_pmodoled_device_to_bus(struct pmodoled_device* dev) { spi_device->max_speed_hz = 4000000; spi_device->mode = SPI_MODE_0; spi_device->bits_per_word = 8; - spi_device->controller_data = dev->iCS; + spi_device->controller_data = (void *) dev->iCS; spi_device->dev.platform_data = dev; strlcpy(spi_device->modalias, DRIVER_NAME, sizeof(DRIVER_NAME)); @@ -331,14 +325,6 @@ static int __init pmodoled_of_probe(struct device_node *np) pmodoled_dev->iDC = be32_to_cpup((tree_info + 3)); pmodoled_dev->iCLK = be32_to_cpup((tree_info + 4)); pmodoled_dev->iMOSI = be32_to_cpup((tree_info + 5)); -#ifdef CONFIG_PMODS_DEBUG - printk(KERN_INFO "pmodoled: VBAT\t%d\n", pmodoled_dev->iVBAT); - printk(KERN_INFO "pmodoled: VDD\t%d\n", pmodoled_dev->iVDD); - printk(KERN_INFO "pmodoled: RES\t%d\n", pmodoled_dev->iRES); - printk(KERN_INFO "pmodoled: DC\t%d\n", pmodoled_dev->iDC); - printk(KERN_INFO "pmodoled: SCLK\t%d\n",pmodoled_dev->iCLK); - printk(KERN_INFO "pmodoled: SDIN\t%d\n", pmodoled_dev->iMOSI); -#endif } /* Get SPI Related Params */ @@ -392,7 +378,8 @@ static int __init pmodoled_of_probe(struct device_node *np) /* Point device node data to pmodoled_device structure */ if(np->data == NULL) np->data = pmodoled_dev; - + + pmodoled_dev->name = np->name; device_num ++; return status; @@ -431,7 +418,10 @@ static int __exit pmodoled_of_remove(struct device_node *np) if(pmodoled_dev->disp_buf != NULL) { kfree(pmodoled_dev->disp_buf); } - platform_device_unregister(pmodoled_dev->pdev); + + if(pmodoled_dev->pdev != NULL) { + platform_device_unregister(pmodoled_dev->pdev); + } np->data = NULL; @@ -450,7 +440,8 @@ static int __exit pmodoled_of_remove(struct device_node *np) */ static int pmodoled_setup_cdev(struct pmodoled_device *dev, dev_t *dev_id, struct spi_device *spi) { - int status; + int status = 0; + struct device *device; cdev_init(&dev->cdev, &pmodoled_cdev_fops); dev->cdev.owner = THIS_MODULE; @@ -459,6 +450,20 @@ static int pmodoled_setup_cdev(struct pmodoled_device *dev, dev_t *dev_id, struc *dev_id = MKDEV(MAJOR(pmodoled_dev_id), cur_minor++); status = cdev_add(&dev->cdev, *dev_id, 1); + if(status < 0) { + return status; + } + + /* Add Device node in system */ + device = device_create(pmodoled_class, NULL, + *dev_id, NULL, + "%s.%d", dev->name, (cur_minor - 1)); + if(IS_ERR(device)) { + status = PTR_ERR(device); + printk(KERN_WARNING "failed to create device node %s.%d, err %d\n", + dev->name, (cur_minor-1), status); + cdev_del(&dev->cdev); + } return status; } @@ -496,6 +501,7 @@ static int pmodoled_init_gpio(struct pmodoled_device *dev) if(status) { printk(KERN_INFO DRIVER_NAME "!! gpio_request_array FAILED!\n"); printk(KERN_INFO DRIVER_NAME " status is: %d\n", status); + gpio_free_array(pmodoled_ctrl, 4); goto gpio_invalid; } @@ -611,7 +617,7 @@ static int pmodoled_spi_probe(struct spi_device *spi) { printk(KERN_INFO DRIVER_NAME "oled_spi_probe: Error adding %s device: %d\n", DRIVER_NAME, status); goto cdev_add_err; } - + /* Initialize Mutex */ mutex_init(&pmodoled_dev->mutex); @@ -639,9 +645,9 @@ static int pmodoled_spi_probe(struct spi_device *spi) { return status; oled_init_error: -cdev_add_err: if (&pmodoled_dev->cdev) cdev_del(&pmodoled_dev->cdev); +cdev_add_err: spi_platform_data_err: spi_err: return(status); @@ -684,6 +690,7 @@ static int __devexit pmodoled_spi_remove(struct spi_device *spi) } if(&dev->cdev) { + device_destroy(pmodoled_class, dev->dev_id); cdev_del(&dev->cdev); } @@ -723,7 +730,13 @@ static int __init pmodoled_init(void) printk(KERN_INFO DRIVER_NAME "Character device region not allocated correctly: %d\n", status); return status; } - + + pmodoled_class = class_create(THIS_MODULE, DRIVER_NAME); + if (IS_ERR(pmodoled_class)) { + status = PTR_ERR(pmodoled_class); + return status; + } + return spi_register_driver(&pmodoled_spi_driver); } @@ -743,6 +756,10 @@ static void __exit pmodoled_exit(void) #endif spi_unregister_driver(&pmodoled_spi_driver); + + if(pmodoled_class) { + class_destroy(pmodoled_class); + } unregister_chrdev_region(pmodoled_dev_id, device_num); From a24432dc50ac3d50d1f8d3c2529ef4a070f9257b Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 5 Jul 2012 16:15:39 -0700 Subject: [PATCH 151/261] ASoC: Adv7511_HDMI: Enabled Sound over HDMI To get sound working properly in Linaro Ubuntu system, "glitcher free" feature of pulse audio should be disabled by appending "tsched=0" in /etc/pulse/default.pa --- sound/soc/xlnx/adv7511_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/xlnx/adv7511_hdmi.c b/sound/soc/xlnx/adv7511_hdmi.c index 79be998c40fd7..52de788a38382 100644 --- a/sound/soc/xlnx/adv7511_hdmi.c +++ b/sound/soc/xlnx/adv7511_hdmi.c @@ -27,7 +27,7 @@ static struct snd_soc_dai_link hdmi_dai_link = { .stream_name = "HDMI", /* .cpu_dai_name = "75c00000.axi-spdif-tx", .platform_name = "xilinx_pcm_audio.2",*/ - .codec_name = "adv7511.2-0039", + .codec_name = "adv7511.0-0039", .codec_dai_name = "adv7511", .dai_fmt = SND_SOC_DAIFMT_SPDIF | SND_SOC_DAIFMT_NB_NF | From 3a9389414f14a55fbe022d6be1be6bdfaa4408ed Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 5 Jul 2012 16:26:56 -0700 Subject: [PATCH 152/261] DTS: Updated Default device tree for ZED Board Device tree entries updated for timer Device tree entries updated for EmacPs Device tree entr4ies updated for wdtps Device tree update for Timer Frequencies Device tree update for SD --- arch/arm/boot/dts/digilent-zed.dts | 137 +++++++++++++++-------------- 1 file changed, 73 insertions(+), 64 deletions(-) diff --git a/arch/arm/boot/dts/digilent-zed.dts b/arch/arm/boot/dts/digilent-zed.dts index 105e222ecbf66..01050419527d5 100644 --- a/arch/arm/boot/dts/digilent-zed.dts +++ b/arch/arm/boot/dts/digilent-zed.dts @@ -5,7 +5,7 @@ compatible = "xlnx,zynq-zed"; #address-cells = <0x1>; #size-cells = <0x1>; - interrupt-parent = <0x1>; + interrupt-parent = <&gic>; memory { device_type = "memory"; @@ -23,61 +23,106 @@ #size-cells = <0x1>; ranges; - intc@f8f01000 { + gic: intc@f8f01000 { interrupt-controller; compatible = "arm,cortex-a9-gic"; #interrupt-cells = <0x3>; - reg = <0xf8f01000 0x1000 0xf8f00100 0x100>; - linux,phandle = <0x1>; - phandle = <0x1>; + reg = < 0xf8f01000 0x1000 >, + < 0xf8f00100 0x0100 >; + }; + + pl310@f8f02000 { + compatible = "arm,pl310-cache"; + cache-unified; + cache-level = <2>; + reg = <0xf8f02000 0x1000>; + arm,data-latency = <3 2 2>; + arm,tag-latency = <2 2 2>; + interrupts = <0 34 4>; }; uart@e0001000 { compatible = "xlnx,ps7-uart-1.00.a"; reg = <0xe0001000 0x1000>; interrupts = <0x0 0x32 0x0>; - interrupt-parent = <0x1>; - clock = <0x2faf080>; + interrupt-parent = <&gic>; + clock = <50000000>; }; timer@0xf8001000 { compatible = "xlnx,ps7-ttc-1.00.a"; reg = <0xf8001000 0x1000>; - interrupts = <0x0 0xa 0x0 0x0 0xb 0x0 0x0 0xc 0x0>; - interrupt-parent = <0x1>; - clock-frequency = <0x7ed6b40>; + interrupts = <0 10 0>,<0 11 0>,<0 12 0>; + interrupt-parent = <&gic>; + clock-frequency-timer0 = <0x7ed6b40>; + clock-frequency-timer1 = <0x7ed6b40>; + clock-frequency-timer2 = <0x7ed6b40>; }; swdt@f8005000 { device_type = "watchdog"; compatible = "xlnx,ps7-wdt-1.00.a"; reg = <0xf8005000 0x100>; + clock-frequency = <111111111>; }; eth@e000b000 { compatible = "xlnx,ps7-ethernet-1.00.a"; reg = <0xe000b000 0x1000>; interrupts = <0x0 0x16 0x0>; - interrupt-parent = <0x1>; - phy-handle = <0x2>; + interrupt-parent = <&gic>; + phy-handle = <&phy0>; #address-cells = <0x1>; #size-cells = <0x0>; - - phy@0 { + xlnx,ptp-enet-clock = <111111111>; + xlnx,slcr-div0-1000Mbps = <8>; + xlnx,slcr-div0-100Mbps = <8>; + xlnx,slcr-div0-10Mbps = <8>; + xlnx,slcr-div1-1000Mbps = <1>; + xlnx,slcr-div1-100Mbps = <5>; + xlnx,slcr-div1-10Mbps = <50>; + + phy0: phy@0 { compatible = "marvell,88e1510"; device_type = "ethernet-phy"; reg = <0x0>; marvell,reg-init = <0x3 0x10 0xff00 0x1e 0x3 0x11 0xfff0 0xa>; - linux,phandle = <0x2>; - phandle = <0x2>; }; }; + ps7_i2c: i2c@41600000 { + compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; + interrupt-parent = <&gic>; + interrupts = <0x0 0x38 0x4>; + reg = <0x41600000 0x10000>; + #size-cells = <0x0>; + #address-cells = <0x1>; + }; + + sdhci@e0100000 { + compatible = "xlnx,ps7-sdhci-1.00.a"; + reg = <0xe0100000 0x1000>; + interrupts = <0x0 0x18 0x0>; + interrupt-parent = <&gic>; + xlnx,has-cd = <0x1>; + clock-frequency = <0x1fc9f08>; + }; + + usb@e0002000 { + compatible = "xlnx,ps7-usb-1.00.a"; + reg = <0xe0002000 0x1000>; + interrupts = <0x0 0x15 0x0>; + interrupt-parent = <&gic>; + dr_mode = "host"; + phy_type = "ulpi"; + }; + gpiops: gpio@e000a000 { compatible = "xlnx,ps7-gpio-1.00.a"; #gpio-cells = <2>; reg = <0xe000a000 0x1000>; interrupts = <0x0 0x14 0x0>; + interrupt-parent = <&gic>; gpio-controller; zed_oled { @@ -101,39 +146,11 @@ }; }; - i2c@41600000 { - compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; - interrupt-parent = <0x1>; - interrupts = <0x0 0x38 0x4>; - reg = <0x41600000 0x10000>; - #size-cells = <0x0>; - #address-cells = <0x1>; - linux,phandle = <0x3>; - phandle = <0x3>; - }; - - sdhci@e0100000 { - compatible = "xlnx,ps7-sdhci-1.00.a"; - reg = <0xe0100000 0x1000>; - interrupts = <0x0 0x18 0x0>; - interrupt-parent = <0x1>; - clock-frequency = <0x1fc9f08>; - }; - - usb@e0002000 { - compatible = "xlnx,ps7-usb-1.00.a"; - reg = <0xe0002000 0x1000>; - interrupts = <0x0 0x15 0x0>; - interrupt-parent = <0x1>; - dr_mode = "host"; - phy_type = "ulpi"; - }; - - spi@e000d000 { + qspi@e000d000 { compatible = "xlnx,ps7-qspi-1.00.a"; reg = <0xe000d000 0x1000>; interrupts = <0x0 0x13 0x0>; - interrupt-parent = <0x1>; + interrupt-parent = <&gic>; speed-hz = <0xbebc200>; bus-num = <0x1>; num-chip-select = <0x1>; @@ -144,18 +161,16 @@ compatible = "xlnx,ps7-dev-cfg-1.00.a"; reg = <0xf8007000 0x1000>; interrupts = <0x0 0x8 0x0>; - interrupt-parent = <0x1>; + interrupt-parent = <&gic>; }; - axidma@40400000 { + axi_dma: axidma@40400000 { #address-cells = <0x1>; #size-cells = <0x1>; #dma-cells = <0x1>; compatible = "xlnx,axi-dma"; reg = <0x40400000 0x1000>; xlnx,sg-include-stscntrl-strm = <0x0>; - linux,phandle = <0x5>; - phandle = <0x5>; dma-channel@40400000 { compatible = "xlnx,axi-dma-mm2s-channel"; @@ -165,15 +180,13 @@ }; }; - axi-spdif-tx@0x75c00000 { + axi_spdif: axi-spdif-tx@0x75c00000 { compatible = "adi,axi-spdif-tx-1.00.a"; reg = <0x75c00000 0x1000>; clock-frequency = <0xbb8000>; - linux,phandle = <0x6>; - phandle = <0x6>; }; - axivdma@43000000 { + axi_vdma: axivdma@43000000 { #address-cells = <0x1>; #size-cells = <0x1>; #dma-cells = <0x1>; @@ -181,8 +194,6 @@ reg = <0x43000000 0x1000>; xlnx,include-sg = <0x0>; xlnx,num-fstores = <0x3>; - linux,phandle = <0x4>; - phandle = <0x4>; dma-channel@43000000 { compatible = "xlnx,axi-vdma-mm2s-channel"; @@ -196,21 +207,19 @@ cf-adv7x11-core@70e00000 { compatible = "adi,cf-adv7x11-core-1.00.a"; reg = <0x70e00000 0x10000 0x79000000 0x10000>; - slave_adapter = <0x3>; - dma-request = <0x4 0x0>; + slave_adapter = <&ps7_i2c>; + dma-request = <&axi_vdma 0x0>; }; - xilinx_pcm_audio { + xlnx_pcm: xilinx_pcm_audio { compatible = "xilinx-pcm-audio"; - dma-request = <0x5 0x0>; - linux,phandle = <0x7>; - phandle = <0x7>; + dma-request = <&axi_dma 0x0>; }; adv7511_hdmi_snd { compatible = "adv7511-hdmi-snd"; - cpu-dai = <0x6>; - pcm = <0x7>; + cpu-dai = <&axi_spdif>; + pcm = <&xlnx_pcm>; }; }; }; From c46688297e9143d284312554504a5de29894a450 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 5 Jul 2012 16:45:56 -0700 Subject: [PATCH 153/261] LED: ZED on-board LED9 used as SD Card Disk Light in ZED Default Config Enabled LED_CLASS, LED_GPIO, LED_TRIGGER in digilent_zed_defconfig Add MIO7 (LD9) in digilent_zed.dts (ZED default device tree source) as SD Card Disk Light. --- arch/arm/boot/dts/digilent-zed.dts | 10 +++++ arch/arm/configs/digilent_zed_defconfig | 54 ++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/digilent-zed.dts b/arch/arm/boot/dts/digilent-zed.dts index 01050419527d5..cef01c170c7c9 100644 --- a/arch/arm/boot/dts/digilent-zed.dts +++ b/arch/arm/boot/dts/digilent-zed.dts @@ -221,5 +221,15 @@ cpu-dai = <&axi_spdif>; pcm = <&xlnx_pcm>; }; + + leds { + compatible = "gpio-leds"; + + mmc_led { + label = "mmc_led"; + gpios = <&gpiops 7 0>; + linux,default-trigger = "mmc0"; + }; + }; }; }; diff --git a/arch/arm/configs/digilent_zed_defconfig b/arch/arm/configs/digilent_zed_defconfig index 7dd7ff8f29717..a49c1fbce12c9 100755 --- a/arch/arm/configs/digilent_zed_defconfig +++ b/arch/arm/configs/digilent_zed_defconfig @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 3.3.0 Kernel Configuration +# Linux/arm 3.3.0-14.2-build1 Kernel Configuration # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -272,17 +272,17 @@ CONFIG_ARCH_ZYNQ=y # # System MMU # -CONFIG_XILINX_FIXED_DEVTREE_ADDR=y -CONFIG_XILINX_L1_PREFETCH=y -CONFIG_XILINX_L2_PREFETCH=y -# CONFIG_XILINX_TEST is not set # # Xilinx Specific Options # CONFIG_ZYNQ_EARLY_UART1=y # CONFIG_ZYNQ_EARLY_UART_EP107 is not set +CONFIG_XILINX_FIXED_DEVTREE_ADDR=y +CONFIG_XILINX_L1_PREFETCH=y +CONFIG_XILINX_L2_PREFETCH=y CONFIG_XILINX_ZED=y +# CONFIG_XILINX_TEST is not set CONFIG_ZYNQ_DEFAULT_KERNEL=y # CONFIG_ZYNQ_AMP_CPU0_MASTER is not set # CONFIG_ZYNQ_AMP_CPU1_SLAVE is not set @@ -757,6 +757,7 @@ CONFIG_BLK_DEV_RAM_SIZE=35384 # CONFIG_TI_DAC7512 is not set # CONFIG_BMP085 is not set # CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SI570 is not set # CONFIG_C2PORT is not set # @@ -941,6 +942,7 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_TCA6416 is not set # CONFIG_KEYBOARD_TCA8418 is not set # CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set # CONFIG_KEYBOARD_MAX7359 is not set # CONFIG_KEYBOARD_MCS is not set # CONFIG_KEYBOARD_MPR121 is not set @@ -1760,7 +1762,39 @@ CONFIG_MMC_SDHCI_OF_XILINX_PS=y # CONFIG_MMC_VUB300 is not set # CONFIG_MMC_USHC is not set # CONFIG_MEMSTICK is not set -# CONFIG_NEW_LEDS is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_RENESAS_TPU is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_OT200 is not set +CONFIG_LEDS_TRIGGERS=y + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_GPIO=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# # CONFIG_ACCESSIBILITY is not set CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y @@ -1868,6 +1902,14 @@ CONFIG_DMA_ENGINE=y # # CONFIG_STAGING is not set CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Common Clock Framework +# +# CONFIG_COMMON_CLK_DISABLE_UNUSED is not set +# CONFIG_COMMON_CLK_DEBUG is not set # # Hardware Spinlock drivers From f3747716bd8fad6f28f3d59c2cea5334499c8354 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 12 Jul 2012 16:45:39 -0700 Subject: [PATCH 154/261] Pmods: pmodoled: Modified Insertion and Removal of Pmodoled Pmodoled is instantiated as a son of axi bus instead of son of xgpio, as the way led-gpio is implemented. As a result, probe function will be called when a pmodoled device is found in the device tree. Some other changes are made in this commit: * compitable string changed to "dglnt,pmodoled-gpio" * moved pmodoled.c to pmodoled-gpio.c * standardized gpio reference in device tree * removed minor number in the device node name created automatically in /dev * removed PMOD_DEBUG in default config * updated debug message output --- arch/arm/boot/dts/digilent-zed.dts | 100 ++- arch/arm/configs/digilent_zed_defconfig | 2 +- drivers/pmods/Makefile | 2 +- drivers/pmods/pmodoled-gpio.c | 848 ++++++++++++++++++++++++ drivers/pmods/pmodoled.c | 775 ---------------------- 5 files changed, 916 insertions(+), 811 deletions(-) create mode 100644 drivers/pmods/pmodoled-gpio.c delete mode 100644 drivers/pmods/pmodoled.c diff --git a/arch/arm/boot/dts/digilent-zed.dts b/arch/arm/boot/dts/digilent-zed.dts index cef01c170c7c9..5e1755e6e988c 100644 --- a/arch/arm/boot/dts/digilent-zed.dts +++ b/arch/arm/boot/dts/digilent-zed.dts @@ -7,21 +7,55 @@ #size-cells = <0x1>; interrupt-parent = <&gic>; - memory { + ps7_ddr_0: memory@0 { device_type = "memory"; reg = <0x0 0x20000000>; }; chosen { bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0"; - linux,stdout-path = "/amba@0/uart@E0001000"; + linux,stdout-path = "/axi@0/uart@E0001000"; }; + + cpus { + #address-cells = <1>; + #cpus = <0x2>; + #size-cells = <0>; + ps7_cortexa9_0: cpu@0 { + clock-frequency = <666666687>; + compatible = "xlnx,ps7-cortexa9-1.00.a"; + d-cache-line-size = <0x20>; + d-cache-size = <0x8000>; + device_type = "cpu"; + i-cache-line-size = <0x20>; + i-cache-size = <0x8000>; + model = "ps7_cortexa9,1.00.a"; + reg = <0>; + timebase-frequency = <333333343>; + xlnx,cpu-1x-clk-freq-hz = <0x69f6bcb>; + xlnx,cpu-clk-freq-hz = <0x27bc86bf>; + } ; + ps7_cortexa9_1: cpu@1 { + clock-frequency = <666666687>; + compatible = "xlnx,ps7-cortexa9-1.00.a"; + d-cache-line-size = <0x20>; + d-cache-size = <0x8000>; + device_type = "cpu"; + i-cache-line-size = <0x20>; + i-cache-size = <0x8000>; + model = "ps7_cortexa9,1.00.a"; + reg = <1>; + timebase-frequency = <333333343>; + xlnx,cpu-1x-clk-freq-hz = <0x69f6bcb>; + xlnx,cpu-clk-freq-hz = <0x27bc86bf>; + } ; + } ; - amba@0 { - compatible = "simple-bus"; - #address-cells = <0x1>; - #size-cells = <0x1>; - ranges; + ps7_axi_interconnect_0: axi@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,ps7-axi-interconnect-1.00.a", "simple-bus"; + ranges ; gic: intc@f8f01000 { interrupt-controller; @@ -66,7 +100,7 @@ clock-frequency = <111111111>; }; - eth@e000b000 { + ps7_ethernet_0: eth@e000b000 { compatible = "xlnx,ps7-ethernet-1.00.a"; reg = <0xe000b000 0x1000>; interrupts = <0x0 0x16 0x0>; @@ -81,12 +115,16 @@ xlnx,slcr-div1-1000Mbps = <1>; xlnx,slcr-div1-100Mbps = <5>; xlnx,slcr-div1-10Mbps = <50>; + mdio { + #address-cells = <1>; + #size-cells = <0>; - phy0: phy@0 { - compatible = "marvell,88e1510"; - device_type = "ethernet-phy"; - reg = <0x0>; - marvell,reg-init = <0x3 0x10 0xff00 0x1e 0x3 0x11 0xfff0 0xa>; + phy0: phy@0 { + compatible = "marvell,88e1510"; + device_type = "ethernet-phy"; + reg = <0x0>; + marvell,reg-init = <0x3 0x10 0xff00 0x1e 0x3 0x11 0xfff0 0xa>; + }; }; }; @@ -104,7 +142,7 @@ reg = <0xe0100000 0x1000>; interrupts = <0x0 0x18 0x0>; interrupt-parent = <&gic>; - xlnx,has-cd = <0x1>; + /*xlnx,has-cd = <0x1>;*/ clock-frequency = <0x1fc9f08>; }; @@ -124,26 +162,6 @@ interrupts = <0x0 0x14 0x0>; interrupt-parent = <&gic>; gpio-controller; - - zed_oled { - compatible = "dglnt,pmodoled-1.00.a"; - spi-bus-num = <2>; - spi-speed-hz = <4000000>; - gpio-width = <0x6>; - gpio-pins = <0x37 0x38 0x39 0x3a 0x3b 0x3c>; - }; - - zed_sw { - compatible = "dglnt,sw-gpio-1.00.a"; - gpio-width = <0x8>; - gpio-pins = <69 70 71 72 73 74 75 76>; - }; - - zed_led { - compatible = "dglnt,led-gpio-1.00.a"; - gpio-width = <0x8>; - gpio-pins = <61 62 63 64 65 66 67 68>; - }; }; qspi@e000d000 { @@ -231,5 +249,19 @@ linux,default-trigger = "mmc0"; }; }; + + zed_oled { + compatible = "dglnt,pmodoled-gpio"; + /* GPIO Pins */ + vbat-gpio = <&gpiops 55 0>; + vdd-gpio = <&gpiops 56 0>; + res-gpio = <&gpiops 57 0>; + dc-gpio = <&gpiops 58 0>; + /* SPI-GPIOs */ + spi-bus-num = <2>; + spi-speed-hz = <4000000>; + spi-sclk-gpio = <&gpiops 59 0>; + spi-sdin-gpio = <&gpiops 60 0>; + }; }; }; diff --git a/arch/arm/configs/digilent_zed_defconfig b/arch/arm/configs/digilent_zed_defconfig index a49c1fbce12c9..7f1fdd0e93ade 100755 --- a/arch/arm/configs/digilent_zed_defconfig +++ b/arch/arm/configs/digilent_zed_defconfig @@ -1918,7 +1918,7 @@ CONFIG_COMMON_CLK=y # CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set CONFIG_PMODS=y -CONFIG_PMODS_DEBUG=y +# CONFIG_PMODS_DEBUG is not set CONFIG_PMODOLED=y # diff --git a/drivers/pmods/Makefile b/drivers/pmods/Makefile index 40031dbaada77..a1bcc1d3367e7 100644 --- a/drivers/pmods/Makefile +++ b/drivers/pmods/Makefile @@ -1,5 +1,5 @@ ccflags-$(CONFIG_PMODS_DEBUG) += -DDEBUG -obj-$(CONFIG_PMODOLED) += pmodoled.o +obj-$(CONFIG_PMODOLED) += pmodoled-gpio.o diff --git a/drivers/pmods/pmodoled-gpio.c b/drivers/pmods/pmodoled-gpio.c new file mode 100644 index 0000000000000..6c03c0c2a8e39 --- /dev/null +++ b/drivers/pmods/pmodoled-gpio.c @@ -0,0 +1,848 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "pmodoled-gpio" +#define SPI_DRIVER_NAME "pmodoled-gpio-spi" +#define MAX_PMODOLED_GPIO_DEV_NUM 16 +#define DISPLAY_BUF_SZ 512 /* 32 x 128 bit monochrome == 512 bytes */ +#define MAX_LINE_LEN 16 /* 128 bits wide and current char width is 8 bit */ +#define MAX_ROW 4 +#define OLED_MAX_PG_CNT 4 /* number of display pages in OLED controller */ +#define OLED_CONTROLLER_PG_SZ 128 +#define OLED_CONTROLLER_CMD 0 +#define OLED_CONTROLLER_DATA 1 + +/* commands for the OLED display controller */ +#define OLED_SET_PG_ADDR 0x22 +#define OLED_DISPLAY_OFF 0xAE +#define OLED_DISPLAY_ON 0xAF +#define OLED_CONTRAST_CTRL 0x81 +#define OLED_SET_PRECHARGE_PERIOD 0xD9 +#define OLED_SET_SEGMENT_REMAP 0xA1 +#define OLED_SET_COM_DIR 0xC8 +#define OLED_SET_COM_PINS 0xDA + +dev_t gpio_pmodoled_dev_id = 0; +static unsigned int device_num = 0; +static unsigned int cur_minor = 0; +static unsigned int spi_drv_registered = 0; +struct mutex minor_mutex; +static struct class *gpio_pmodoled_class = NULL; + +struct gpio_pmodoled_device { + char *name; + /* R/W Mutex Lock */ + struct mutex mutex; + /* Display Buffers */ + uint8_t disp_on; + uint8_t *disp_buf; + /* Pin Assignment */ + unsigned long iVBAT; + unsigned long iVDD; + unsigned long iRES; + unsigned long iDC; + unsigned long iSCLK; + unsigned long iSDIN; + unsigned long iCS; + /* SPI Info */ + uint32_t spi_id; + /* platform device structures */ + struct platform_device *pdev; + /* Char Device */ + struct cdev cdev; + struct spi_device *spi; + dev_t dev_id; +}; + +/** + * screen_buf_to_display - + * @screen_buf - + * @dev - + * + */ +static int screen_buf_to_display(uint8_t *screen_buf, struct gpio_pmodoled_device *dev) +{ + uint32_t pg; + int status; + uint8_t lower_start_column = 0x00; + uint8_t upper_start_column = 0x10; + uint8_t wr_buf[10]; + + for(pg = 0; pg < OLED_MAX_PG_CNT; pg++) { + wr_buf[0] = OLED_SET_PG_ADDR; + wr_buf[1] = pg; + wr_buf[2] = lower_start_column; + wr_buf[3] = upper_start_column; + gpio_set_value(dev->iDC, OLED_CONTROLLER_CMD); + status = spi_write(dev->spi, wr_buf, 4); + if(status) { + dev_err(&dev->spi->dev, "screen_buf_to_display: Error writing to SPI\n"); + break; + } + + gpio_set_value(dev->iDC, OLED_CONTROLLER_DATA); + status = spi_write(dev->spi, (uint8_t *) (screen_buf + + (pg*OLED_CONTROLLER_PG_SZ)), OLED_CONTROLLER_PG_SZ); + if(status) { + dev_err(&dev->spi->dev, "screen_buf_to_display: Error writing to SPI\n"); + break; + } + } + return status; +} + +/** + * A basic open function. It exists mainly to save the id of + * the OLED and some other basic information. + */ +static int gpio_pmodoled_open(struct inode *inode, struct file *fp) +{ + struct gpio_pmodoled_device *dev; + + dev = container_of(inode->i_cdev, struct gpio_pmodoled_device, cdev); + fp->private_data = dev; + + return 0; +} + +static int gpio_pmodoled_close(struct inode *inode, struct file *fp) +{ + return 0; +} + +/** + * Driver write function + * + * This function uses a generic SPI write to send values to the Pmod device + * It takes a raw data array from the app in the buffer, copied it into + * device dispay buffer, and finally sends the buffer to the OLED using SPI + */ +static ssize_t gpio_pmodoled_write(struct file *fp, const char __user *buffer, size_t length, loff_t *offset) +{ + ssize_t retval = 0; + struct gpio_pmodoled_device *dev; + unsigned int minor_id; + int cnt; + int status; + + dev = fp->private_data; + minor_id = MINOR(dev->dev_id); + + if(mutex_lock_interruptible(&dev->mutex)) { + retval = -ERESTARTSYS; + goto write_lock_err; + } + + if (buffer == NULL) { + dev_err(&dev->spi->dev, "oled_write: ERROR: invalid buffer address: 0x%08x\n", + (unsigned int) buffer); + retval = -EINVAL; + goto quit_write; + } + + if(length > DISPLAY_BUF_SZ) { + cnt = DISPLAY_BUF_SZ; + } + else { + cnt = length; + } + + if(copy_from_user(dev->disp_buf, buffer, cnt)) { + dev_err(&dev->spi->dev, "oled_write: copy_from_user failed\n"); + retval = -EFAULT; + goto quit_write; + } + else { + retval = cnt; + } + + status = screen_buf_to_display(dev->disp_buf, dev); + if(status) { + dev_err(&dev->spi->dev, "oled_write: Error sending string to display\n"); + retval = -EFAULT; + goto quit_write; + } + +quit_write: + mutex_unlock(&dev->mutex); +write_lock_err: + return retval; +} + +/** + * Driver Read Function + * + * This function does not actually read the Pmod as it is a write-only device. Instead + * It returns data in the buffer generated for the display that was used when the OLED + * was last programmed. + */ +static ssize_t gpio_pmodoled_read(struct file *fp, char __user *buffer, size_t length, loff_t *offset) +{ + ssize_t retval = 0; + struct gpio_pmodoled_device *dev; + unsigned int minor_id; + int cnt; + + dev = fp->private_data; + minor_id = MINOR(dev->dev_id); + + if(mutex_lock_interruptible(&dev->mutex)) { + retval = -ERESTARTSYS; + goto read_lock_err; + } + + if (buffer == NULL) { + dev_err(&dev->spi->dev, "OLED_read: ERROR: invalid buffer " + "address: 0x%08X\n", (unsigned int)buffer); + retval = -EINVAL; + goto quit_read; + } + + if (length > DISPLAY_BUF_SZ) + cnt = DISPLAY_BUF_SZ; + else + cnt = length; + retval = copy_to_user((void *)buffer, dev->disp_buf, cnt); + if (!retval) + retval = cnt; /* copy success, return amount in buffer */ + +quit_read: + mutex_unlock(&dev->mutex); +read_lock_err: + return(retval); +} + +struct file_operations gpio_pmodoled_cdev_fops = { + .owner = THIS_MODULE, + .write = gpio_pmodoled_write, + .read = gpio_pmodoled_read, + .open = gpio_pmodoled_open, + .release = gpio_pmodoled_close, +}; + +static int __init add_gpio_pmodoled_device_to_bus(struct gpio_pmodoled_device* dev) { + struct spi_master *spi_master; + struct spi_device *spi_device; + int status = 0; + + spi_master = spi_busnum_to_master(dev->spi_id); + if(!spi_master) { + dev_err(&dev->pdev->dev, "spi_busnum_to_master(%d) returned NULL\n", dev->spi_id); + return -ENOSYS; + } + + spi_device = spi_alloc_device(spi_master); + if(!spi_device) { + put_device(&spi_master->dev); + dev_err(&dev->pdev->dev, "spi_alloc_device() failed\n"); + return -ENOMEM; + } + + spi_device->chip_select = 0; + spi_device->max_speed_hz = 4000000; + spi_device->mode = SPI_MODE_0; + spi_device->bits_per_word = 8; + spi_device->controller_data = (void *) dev->iCS; + spi_device->dev.platform_data = dev; + strlcpy(spi_device->modalias, SPI_DRIVER_NAME, sizeof(SPI_DRIVER_NAME)); + + status = spi_add_device(spi_device); + if(status < 0) { + spi_dev_put(spi_device); + dev_err(&dev->pdev->dev, "spi_add_device() failed %d\n", status); + return status; + } + dev->spi = spi_device; + + put_device(&spi_master->dev); + + return status; +} + +/** + * gpio_pmodoled_setup_cdev - Setup Char Device for ZED on-board OLED device. + * @dev: pointer to device tree node + * @dev_id: pointer to device major and minor number + * @spi: pointer to spi_device structure + * + * This function initializes char device for OLED device, and add it into + * kernel device structure. It returns 0, if the cdev is successfully + * initialized, or a negative value if there is an error. + */ +static int gpio_pmodoled_setup_cdev(struct gpio_pmodoled_device *dev, dev_t *dev_id, struct spi_device *spi) +{ + int status = 0; + struct device *device; + + cdev_init(&dev->cdev, &gpio_pmodoled_cdev_fops); + dev->cdev.owner = THIS_MODULE; + dev->cdev.ops = &gpio_pmodoled_cdev_fops; + dev->spi = spi; + + *dev_id = MKDEV(MAJOR(gpio_pmodoled_dev_id), cur_minor++); + status = cdev_add(&dev->cdev, *dev_id, 1); + if(status < 0) { + return status; + } + + /* Add Device node in system */ + device = device_create(gpio_pmodoled_class, NULL, + *dev_id, NULL, + "%s", dev->name); + if(IS_ERR(device)) { + status = PTR_ERR(device); + dev_err(&spi->dev, "failed to create device node %s, err %d\n", + dev->name, status); + cdev_del(&dev->cdev); + } + + return status; +} + +/** + * gpio_pmodoled_init_gpio - Initialize GPIO for ZED Onboard OLED + * @dev - gpio_pmodoled_device + * + * Initializes OLED GPIO Control Pins. + * It returns 0, if the gpio pins are successfully + * initialized, or a negative value if there is an error. + */ +static int gpio_pmodoled_init_gpio(struct gpio_pmodoled_device *dev) +{ + struct gpio gpio_pmodoled_ctrl[] = { + {dev->iVBAT, GPIOF_OUT_INIT_HIGH, "OLED VBat"}, + {dev->iVDD, GPIOF_OUT_INIT_HIGH, "OLED VDD"}, + {dev->iRES, GPIOF_OUT_INIT_HIGH, "OLED_RESET"}, + {dev->iDC, GPIOF_OUT_INIT_HIGH, "OLED_D/C"}, + }; + int status; + int i; + + for (i = 0; i < ARRAY_SIZE(gpio_pmodoled_ctrl); i++) { + status = gpio_is_valid(gpio_pmodoled_ctrl[i].gpio); + if(!status) { + dev_err(&dev->spi->dev, "!! gpio_is_valid for GPIO %d, %s FAILED!, status: %d\n", + gpio_pmodoled_ctrl[i].gpio, gpio_pmodoled_ctrl[i].label, status); + goto gpio_invalid; + } + } + + status = gpio_request_array(gpio_pmodoled_ctrl, ARRAY_SIZE(gpio_pmodoled_ctrl)); + if(status) { + dev_err(&dev->spi->dev, "!! gpio_request_array FAILED!\n"); + dev_err(&dev->spi->dev, " status is: %d\n", status); + gpio_free_array(gpio_pmodoled_ctrl, 4); + goto gpio_invalid; + } + +gpio_invalid: + return status; +} + +/** + * gpio_pmodoled_disp_init - + * @dev: + * + */ +static void gpio_pmodoled_disp_init(struct gpio_pmodoled_device *dev) +{ + int status; + uint8_t wr_buf[20]; + + // We are going to be sending commands + // so clear the data/cmd bit + gpio_set_value(dev->iDC, OLED_CONTROLLER_CMD); + + // Start by turning VDD on and wait for the power to come up + gpio_set_value(dev->iVDD, 0); + msleep(1); + + // Display off Command + wr_buf[0] = OLED_DISPLAY_OFF; + status = spi_write(dev->spi, wr_buf, 1); + + /* Bring Reset Low and then High */ + gpio_set_value(dev->iRES, 1); + msleep(1); + gpio_set_value(dev->iRES, 0); + msleep(1); + gpio_set_value(dev->iRES, 1); + + // Send the set charge pump and set precharge period commands + wr_buf[0] = 0x8D; + wr_buf[1] = 0x14; + wr_buf[2] = OLED_SET_PRECHARGE_PERIOD; + wr_buf[3] = 0xF1; + + status = spi_write(dev->spi, wr_buf, 4); + + /* Turn on VCC and wait 100ms */ + gpio_set_value(dev->iVBAT, 0); + msleep(100); + + /* Set Display COntrast */ + wr_buf[0] = OLED_CONTRAST_CTRL; + wr_buf[1] = 0x0F; + + /* Invert the display */ + wr_buf[2] = OLED_SET_SEGMENT_REMAP; // Remap Columns + wr_buf[3] = OLED_SET_COM_DIR; // Remap Rows + + // Select sequential COM configuration + wr_buf[4] = OLED_SET_COM_PINS; + wr_buf[5] = 0x00; + wr_buf[6] = 0xC0; + wr_buf[7] = 0x20; + wr_buf[8] = 0x00; + + // Turn on Display + wr_buf[9] = OLED_DISPLAY_ON; + + status = spi_write(dev->spi, wr_buf, 10); +} + + +/** + * SPI hardware probe. Sets correct SPI mode, attempts + * to obtain memory needed by the driver, and performs + * a simple initialization of the device. + */ +static int gpio_pmodoled_spi_probe(struct spi_device *spi) { + int status = 0; + struct gpio_pmodoled_device *gpio_pmodoled_dev; + + /* We rely on full duplex transfers, mostly to reduce + * per transfer overheads (by making few transfers). + */ + if (spi->master->flags & SPI_MASTER_HALF_DUPLEX) { + status = -EINVAL; + dev_err(&spi->dev, "SPI settings incorrect: %d\n", status); + goto spi_err; + } + + /* We must use SPI_MODE_0 */ + spi->mode = SPI_MODE_0; + spi->bits_per_word = 8; + + status = spi_setup(spi); + if(status < 0) { + dev_err(&spi->dev, "needs SPI mode %02x, %d KHz; %d\n", + spi->mode, spi->max_speed_hz / 1000, + status); + goto spi_err; + } + + /* Get gpio_pmodoled_device structure */ + gpio_pmodoled_dev = (struct gpio_pmodoled_device*) spi->dev.platform_data; + if(gpio_pmodoled_dev == NULL) { + dev_err(&spi->dev, "Cannot get gpio_pmodoled_device.\n"); + status = -EINVAL; + goto spi_platform_data_err; + } + + printk(KERN_INFO SPI_DRIVER_NAME " [%s] SPI Probing\n", gpio_pmodoled_dev->name); + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO SPI_DRIVER_NAME " [%s] spi_probe: setup char device\n", gpio_pmodoled_dev->name); +#endif + + /* Setup char driver */ + status = gpio_pmodoled_setup_cdev(gpio_pmodoled_dev, &(gpio_pmodoled_dev->dev_id), spi); + if (status) { + dev_err(&spi->dev, "spi_probe: Error adding %s device: %d\n", SPI_DRIVER_NAME, status); + goto cdev_add_err; + } + + /* Initialize Mutex */ + mutex_init(&gpio_pmodoled_dev->mutex); + + /** + * It is important to the OLED's longevity that the lines that + * control it's power are carefully controlled. This is a good + * time to ensure that the device is ot turned on until it is + * instructed to do so. + */ +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO SPI_DRIVER_NAME " [%s] spi_probe: initialize device\n", gpio_pmodoled_dev->name); +#endif + + status = gpio_pmodoled_init_gpio(gpio_pmodoled_dev); + if(status) { + dev_err(&spi->dev, "spi_probe: Error initializing GPIO\n"); + goto oled_init_error; + } + + gpio_pmodoled_disp_init(gpio_pmodoled_dev); + + memset(gpio_pmodoled_dev->disp_buf, 0x00, DISPLAY_BUF_SZ); + + status = screen_buf_to_display(gpio_pmodoled_dev->disp_buf, gpio_pmodoled_dev); + if(status) { + dev_err(&spi->dev, "spi_probe: Error sending initial Display String\n"); + goto oled_init_error; + } + return status; + +oled_init_error: + if (&gpio_pmodoled_dev->cdev) + cdev_del(&gpio_pmodoled_dev->cdev); +cdev_add_err: +spi_platform_data_err: +spi_err: + return(status); +} + +static int __devexit gpio_pmodoled_spi_remove(struct spi_device *spi) +{ + int status; + struct gpio_pmodoled_device *dev; + uint8_t wr_buf[10]; + + dev = (struct gpio_pmodoled_device*) spi->dev.platform_data; + + if(dev == NULL) { + dev_err(&spi->dev, "spi_remove: Error fetch gpio_pmodoled_device struct\n"); + return -EINVAL; + } + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO SPI_DRIVER_NAME " [%s] spi_remove: Clearing Display\n", dev->name); +#endif + + /* Clear Display */ + memset(dev->disp_buf, 0, DISPLAY_BUF_SZ); + status = screen_buf_to_display(dev->disp_buf, dev); + + /* Turn off display */ + wr_buf[0] = OLED_DISPLAY_OFF; + status = spi_write(spi, wr_buf, 1); + if(status) { + dev_err(&spi->dev, "oled_spi_remove: Error writing to SPI device\n"); + } + + /* Turn off VCC (VBAT) */ + gpio_set_value(dev->iVBAT, 1); + msleep(100); + /* TUrn off VDD Power */ + gpio_set_value(dev->iVDD, 1); +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO SPI_DRIVER_NAME " [%s] spi_remove: Free GPIOs\n", dev->name); +#endif + +{ + struct gpio gpio_pmodoled_ctrl[] = { + {dev->iVBAT, GPIOF_OUT_INIT_HIGH, "OLED VBat"}, + {dev->iVDD, GPIOF_OUT_INIT_HIGH, "OLED VDD"}, + {dev->iRES, GPIOF_OUT_INIT_HIGH, "OLED_RESET"}, + {dev->iDC, GPIOF_OUT_INIT_HIGH, "OLED_D/C"}, + }; + + gpio_free_array(gpio_pmodoled_ctrl, 4); +} + + if(&dev->cdev) { +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO SPI_DRIVER_NAME " [%s] spi_remove: Destroy Char Device\n", dev->name); +#endif + device_destroy(gpio_pmodoled_class, dev->dev_id); + cdev_del(&dev->cdev); + } + + cur_minor--; + + printk(KERN_INFO SPI_DRIVER_NAME " [%s] spi_remove: Device Removed\n", dev->name); + + return status; +} + +static struct spi_driver gpio_pmodoled_spi_driver = { + .driver = { + .name = SPI_DRIVER_NAME, + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = gpio_pmodoled_spi_probe, + .remove = __devexit_p(gpio_pmodoled_spi_remove), +}; + +static const struct of_device_id gpio_pmodoled_of_match[] __devinitconst = { + { .compatible = "dglnt,pmodoled-gpio", }, + {}, +}; +MODULE_DEVICE_TABLE(of, gpio_pmodoled_of_match); + +/** + * gpio_pmodoled_of_probe - Probe method for PmodOLED device (over GPIO). + * @pdev: pointer to platform devices + * + * This function probes the OLED device in the device tree. It initializes the + * OLED driver data structure. It returns 0, if the driver is bound to the OLED + * device, or a negative value if there is an error. + */ +static int __devinit gpio_pmodoled_of_probe(struct platform_device *pdev) +{ + struct gpio_pmodoled_device *gpio_pmodoled_dev; + struct platform_device *gpio_pmodoled_pdev; + struct spi_gpio_platform_data *gpio_pmodoled_pdata; + + struct device_node *np = pdev->dev.of_node; + + const u32* tree_info; + int status = 0; + + /* Alloc Space for platform device structure */ + gpio_pmodoled_dev = (struct gpio_pmodoled_device*) kzalloc(sizeof(*gpio_pmodoled_dev), GFP_KERNEL); + if(!gpio_pmodoled_dev) { + status = -ENOMEM; + goto dev_alloc_err; + } + + /* Alloc Graphic Buffer for device */ + gpio_pmodoled_dev->disp_buf = (uint8_t*) kmalloc(DISPLAY_BUF_SZ, GFP_KERNEL); + if(!gpio_pmodoled_dev->disp_buf) { + status = -ENOMEM; + dev_err(&pdev->dev, "Device Display data buffer allocation failed: %d\n", status); + goto disp_buf_alloc_err; + } + + /* Get the GPIO Pins */ + gpio_pmodoled_dev->iVBAT = of_get_named_gpio(np, "vbat-gpio", 0); + gpio_pmodoled_dev->iVDD = of_get_named_gpio(np, "vdd-gpio", 0); + gpio_pmodoled_dev->iRES = of_get_named_gpio(np, "res-gpio", 0); + gpio_pmodoled_dev->iDC = of_get_named_gpio(np, "dc-gpio", 0); + gpio_pmodoled_dev->iSCLK = of_get_named_gpio(np, "spi-sclk-gpio", 0); + gpio_pmodoled_dev->iSDIN = of_get_named_gpio(np, "spi-sdin-gpio", 0); + status = of_get_named_gpio(np, "spi-cs-gpio", 0); + gpio_pmodoled_dev->iCS = (status < 0) ? SPI_GPIO_NO_CHIPSELECT : status; +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: iVBAT: 0x%lx\n", np->name, gpio_pmodoled_dev->iVBAT); + printk(KERN_INFO DRIVER_NAME " %s: iVDD : 0x%lx\n", np->name, gpio_pmodoled_dev->iVDD); + printk(KERN_INFO DRIVER_NAME " %s: iRES : 0x%lx\n", np->name, gpio_pmodoled_dev->iRES); + printk(KERN_INFO DRIVER_NAME " %s: iDC : 0x%lx\n", np->name, gpio_pmodoled_dev->iDC); + printk(KERN_INFO DRIVER_NAME " %s: iSCLK: 0x%lx\n", np->name, gpio_pmodoled_dev->iSCLK); + printk(KERN_INFO DRIVER_NAME " %s: iSDIN: 0x%lx\n", np->name, gpio_pmodoled_dev->iSDIN); + printk(KERN_INFO DRIVER_NAME " %s: iCS : 0x%lx\n", np->name, gpio_pmodoled_dev->iCS); +#endif + + /* Get SPI Related Params */ + tree_info = of_get_property(np, "spi-bus-num", NULL); + if(tree_info) { + gpio_pmodoled_dev->spi_id = be32_to_cpup((tree_info)); +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: BUS_ID\t%x\n", np->name, gpio_pmodoled_dev->spi_id); +#endif + } + + /* Alloc Space for platform data structure */ + gpio_pmodoled_pdata = (struct spi_gpio_platform_data*) kzalloc(sizeof(*gpio_pmodoled_pdata), GFP_KERNEL); + if(!gpio_pmodoled_pdata) { + status = -ENOMEM; + goto pdata_alloc_err; + } + + /* Fill up Platform Data Structure */ + gpio_pmodoled_pdata->sck = gpio_pmodoled_dev->iSCLK; + gpio_pmodoled_pdata->miso = SPI_GPIO_NO_MISO; + gpio_pmodoled_pdata->mosi = gpio_pmodoled_dev->iSDIN; + gpio_pmodoled_pdata->num_chipselect = 1; + + /* Alloc Space for platform data structure */ + gpio_pmodoled_pdev = (struct platform_device*) kzalloc(sizeof(*gpio_pmodoled_pdev), GFP_KERNEL); + if(!gpio_pmodoled_pdev) { + status = -ENOMEM; + goto pdev_alloc_err; + } + + /* Fill up Platform Device Structure */ + gpio_pmodoled_pdev->name = "spi_gpio"; + gpio_pmodoled_pdev->id = gpio_pmodoled_dev->spi_id; + gpio_pmodoled_pdev->dev.platform_data = gpio_pmodoled_pdata; + gpio_pmodoled_dev->pdev = gpio_pmodoled_pdev; + + /* Register spi_gpio master */ + status = platform_device_register(gpio_pmodoled_dev->pdev); + if(status < 0) { + dev_err(&pdev->dev, "platform_device_register failed: %d\n", status); + goto pdev_reg_err; + } + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: spi_gpio platform device registered.\n", np->name); +#endif + gpio_pmodoled_dev->name = np->name; + + /* Fill up Board Info for SPI device */ + status = add_gpio_pmodoled_device_to_bus(gpio_pmodoled_dev); + if(status < 0) { + dev_err(&pdev->dev, "add_gpio_pmodoled_device_to_bus failed: %d\n", status); + goto spi_add_err; + } + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: spi device registered.\n", np->name); +#endif + + /* Point device node data to gpio_pmodoled_device structure */ + if(np->data == NULL) + np->data = gpio_pmodoled_dev; + + if(gpio_pmodoled_dev_id == 0) { + /* Alloc Major & Minor number for char device */ + status = alloc_chrdev_region(&gpio_pmodoled_dev_id, 0, MAX_PMODOLED_GPIO_DEV_NUM, DRIVER_NAME); + if(status) { + dev_err(&pdev->dev, "Character device region not allocated correctly: %d\n", status); + goto err_alloc_chrdev_region; + } +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Char Device Region Registered, with Major: %d.\n", + MAJOR(gpio_pmodoled_dev_id)); +#endif + } + + if(gpio_pmodoled_class == NULL) { + /* Create Pmodoled-gpio Device Class */ + gpio_pmodoled_class = class_create(THIS_MODULE, DRIVER_NAME); + if (IS_ERR(gpio_pmodoled_class)) { + status = PTR_ERR(gpio_pmodoled_class); + goto err_create_class; + } +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : pmodoled_gpio device class registered.\n"); +#endif + } + + if(spi_drv_registered == 0) { + /* Register SPI Driver for Pmodoled Device */ + status = spi_register_driver(&gpio_pmodoled_spi_driver); + if (status < 0) { + dev_err(&pdev->dev, "gpio_pmodoled_spi_driver register failed: %d\n", status); + goto err_spi_register; + } + spi_drv_registered = 1; + } + + device_num ++; + + return status; + +err_spi_register: + class_destroy(gpio_pmodoled_class); + gpio_pmodoled_class = NULL; +err_create_class: + unregister_chrdev_region(gpio_pmodoled_dev_id, MAX_PMODOLED_GPIO_DEV_NUM); + gpio_pmodoled_dev_id = 0; +err_alloc_chrdev_region: + spi_unregister_device(gpio_pmodoled_dev->spi); +spi_add_err: + platform_device_unregister(gpio_pmodoled_dev->pdev); +pdev_reg_err: + kfree(gpio_pmodoled_pdev); +pdev_alloc_err: + kfree(gpio_pmodoled_pdata); +pdata_alloc_err: + kfree(gpio_pmodoled_dev->disp_buf); +disp_buf_alloc_err: + kfree(gpio_pmodoled_dev); +dev_alloc_err: + return status; +} + +/** + * gpio_pmodoled_of_remove - Remove method for ZED on-board OLED device. + * @np: pointer to device tree node + * + * This function removes the OLED device in the device tree. It frees the + * OLED driver data structure. It returns 0, if the driver is successfully + * removed, or a negative value if there is an error. + */ +static int gpio_pmodoled_of_remove(struct platform_device *pdev) +{ + struct gpio_pmodoled_device *gpio_pmodoled_dev; + struct device_node *np = pdev->dev.of_node; + + if(np->data == NULL) { + dev_err(&pdev->dev, "pmodoled %s: ERROR: No gpio_pmodoled_device structure found!\n", np->name); + return -ENOSYS; + } + gpio_pmodoled_dev = (struct gpio_pmodoled_device*) (np->data); + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s : Free display buffer.\n", np->name); +#endif + + if(gpio_pmodoled_dev->disp_buf != NULL) { + kfree(gpio_pmodoled_dev->disp_buf); + } + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s : Unregister gpio_spi Platform Devices.\n", np->name); +#endif + + if(gpio_pmodoled_dev->pdev != NULL) { + platform_device_unregister(gpio_pmodoled_dev->pdev); + } + + np->data = NULL; + device_num--; + + /* Unregister SPI Driver, Destroy pmodoled-gpio class, Release device id Region after + * all pmodoled-gpio devices have been removed. + */ + if(device_num == 0) { +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Unregister SPI Driver.\n"); +#endif + spi_unregister_driver(&gpio_pmodoled_spi_driver); + spi_drv_registered = 0; + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Destroy pmodoled_gpio Class.\n"); +#endif + + if(gpio_pmodoled_class) { + class_destroy(gpio_pmodoled_class); + } + gpio_pmodoled_class = NULL; + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Release Char Device Region.\n"); +#endif + + unregister_chrdev_region(gpio_pmodoled_dev_id, MAX_PMODOLED_GPIO_DEV_NUM); + gpio_pmodoled_dev_id = 0; + } + + return 0; +} + +static struct platform_driver gpio_pmodoled_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = gpio_pmodoled_of_match, + }, + .probe = gpio_pmodoled_of_probe, + .remove = __devexit_p(gpio_pmodoled_of_remove), +}; + +module_platform_driver(gpio_pmodoled_driver); + +MODULE_AUTHOR("Digilent, Inc."); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(DRIVER_NAME": PmodOLED display driver"); +MODULE_ALIAS(DRIVER_NAME); diff --git a/drivers/pmods/pmodoled.c b/drivers/pmods/pmodoled.c deleted file mode 100644 index 4b8708ef03806..0000000000000 --- a/drivers/pmods/pmodoled.c +++ /dev/null @@ -1,775 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_NAME "pmodoled" -#define DISPLAY_BUF_SZ 512 /* 32 x 128 bit monochrome == 512 bytes */ -#define MAX_LINE_LEN 16 /* 128 bits wide and current char width is 8 bit */ -#define MAX_ROW 4 -#define OLED_MAX_PG_CNT 4 /* number of display pages in OLED controller */ -#define OLED_CONTROLLER_PG_SZ 128 -#define OLED_CONTROLLER_CMD 0 -#define OLED_CONTROLLER_DATA 1 - -/* commands for the OLED display controller */ -#define OLED_SET_PG_ADDR 0x22 -#define OLED_DISPLAY_OFF 0xAE -#define OLED_DISPLAY_ON 0xAF -#define OLED_CONTRAST_CTRL 0x81 -#define OLED_SET_PRECHARGE_PERIOD 0xD9 -#define OLED_SET_SEGMENT_REMAP 0xA1 -#define OLED_SET_COM_DIR 0xC8 -#define OLED_SET_COM_PINS 0xDA - -dev_t pmodoled_dev_id = 0; -static unsigned int device_num = 0; -static unsigned int cur_minor = 0; -struct mutex minor_mutex; -static struct class *pmodoled_class = NULL; - -struct pmodoled_device { - char *name; - /* R/W Mutex Lock */ - struct mutex mutex; - /* Display Buffers */ - uint8_t disp_on; - uint8_t *disp_buf; - /* Pin Assignment */ - unsigned long iVBAT; - unsigned long iVDD; - unsigned long iRES; - unsigned long iDC; - unsigned long iCLK; - unsigned long iMOSI; - unsigned long iCS; - /* SPI Info */ - uint32_t spi_id; - /* platform device structures */ - struct platform_device *pdev; - /* Char Device */ - struct cdev cdev; - struct spi_device *spi; - dev_t dev_id; -}; - -/** - * screen_buf_to_display - - * @screen_buf - - * @dev - - * - */ -static int screen_buf_to_display(uint8_t *screen_buf, struct pmodoled_device *dev) -{ - uint32_t pg; - int status; - uint8_t lower_start_column = 0x00; - uint8_t upper_start_column = 0x10; - uint8_t wr_buf[10]; - - for(pg = 0; pg < OLED_MAX_PG_CNT; pg++) { - wr_buf[0] = OLED_SET_PG_ADDR; - wr_buf[1] = pg; - wr_buf[2] = lower_start_column; - wr_buf[3] = upper_start_column; - gpio_set_value(dev->iDC, OLED_CONTROLLER_CMD); - status = spi_write(dev->spi, wr_buf, 4); - if(status) { - printk(KERN_INFO DRIVER_NAME "screen_buf_to_display: Error writing to SPI\n"); - break; - } - - gpio_set_value(dev->iDC, OLED_CONTROLLER_DATA); - status = spi_write(dev->spi, (uint8_t *) (screen_buf + - (pg*OLED_CONTROLLER_PG_SZ)), OLED_CONTROLLER_PG_SZ); - if(status) { - printk(KERN_INFO DRIVER_NAME "screen_buf_to_display: Error writing to SPI\n"); - break; - } - } - return status; -} - -/** - * A basic open function. It exists mainly to save the id of - * the OLED and some other basic information. - */ -static int pmodoled_open(struct inode *inode, struct file *fp) -{ - struct pmodoled_device *dev; - - dev = container_of(inode->i_cdev, struct pmodoled_device, cdev); - fp->private_data = dev; - - return 0; -} - -static int pmodoled_close(struct inode *inode, struct file *fp) -{ - return 0; -} - -/** - * Driver write function - * - * This function uses a generic SPI write to send values to the Pmod device - * It takes a raw data array from the app in the buffer, copied it into - * device dispay buffer, and finally sends the buffer to the OLED using SPI - */ -static ssize_t pmodoled_write(struct file *fp, const char __user *buffer, size_t length, loff_t *offset) -{ - ssize_t retval = 0; - struct pmodoled_device *dev; - unsigned int minor_id; - int cnt; - int status; - - dev = fp->private_data; - minor_id = MINOR(dev->dev_id); - - if(mutex_lock_interruptible(&dev->mutex)) { - retval = -ERESTARTSYS; - goto write_lock_err; - } - - if (buffer == NULL) { - printk(KERN_ALERT "oled_write: ERROR: invalid buffer address: 0x%08x\n", - (unsigned int) buffer); - retval = -EINVAL; - goto quit_write; - } - - if(length > DISPLAY_BUF_SZ) { - cnt = DISPLAY_BUF_SZ; - } - else { - cnt = length; - } - - printk(KERN_INFO "oled_write: data length %d\n", cnt); - if(copy_from_user(dev->disp_buf, buffer, cnt)) { - printk(KERN_ALERT "oled_write: copy_from_user failed\n"); - retval = -EFAULT; - goto quit_write; - } - else { - retval = cnt; - } - - status = screen_buf_to_display(dev->disp_buf, dev); - if(status) { - printk(KERN_ALERT "oled_write: Error sending string to display\n"); - retval = -EFAULT; - goto quit_write; - } - -quit_write: - mutex_unlock(&dev->mutex); -write_lock_err: - return retval; -} - -/** - * Driver Read Function - * - * This function does not actually read the Pmod as it is a write-only device. Instead - * It returns data in the buffer generated for the display that was used when the OLED - * was last programmed. - */ -static ssize_t pmodoled_read(struct file *fp, char __user *buffer, size_t length, loff_t *offset) -{ - ssize_t retval = 0; - struct pmodoled_device *dev; - unsigned int minor_id; - int cnt; - - dev = fp->private_data; - minor_id = MINOR(dev->dev_id); - - if(mutex_lock_interruptible(&dev->mutex)) { - retval = -ERESTARTSYS; - goto read_lock_err; - } - - if (buffer == NULL) { - dev_err(&dev->spi->dev, "OLED_read: ERROR: invalid buffer " - "address: 0x%08X\n", (unsigned int)buffer); - retval = -EINVAL; - goto quit_read; - } - - if (length > DISPLAY_BUF_SZ) - cnt = DISPLAY_BUF_SZ; - else - cnt = length; - retval = copy_to_user((void *)buffer, dev->disp_buf, cnt); - if (!retval) - retval = cnt; /* copy success, return amount in buffer */ - -quit_read: - mutex_unlock(&dev->mutex); -read_lock_err: - return(retval); -} - -struct file_operations pmodoled_cdev_fops = { - .owner = THIS_MODULE, - .write = pmodoled_write, - .read = pmodoled_read, - .open = pmodoled_open, - .release = pmodoled_close, -}; - -static const struct of_device_id pmodoled_of_match[] = { - { .compatible = "dglnt,pmodoled-1.00.a", }, - {}, -}; - -static int __init add_pmodoled_device_to_bus(struct pmodoled_device* dev) { - struct spi_master *spi_master; - struct spi_device *spi_device; - int status = 0; - - spi_master = spi_busnum_to_master(dev->spi_id); - if(!spi_master) { - printk(KERN_ALERT "spi_busnum_to_master(%d) returned NULL\n", dev->spi_id); - return -ENOSYS; - } - - spi_device = spi_alloc_device(spi_master); - if(!spi_device) { - put_device(&spi_master->dev); - printk(KERN_ALERT "spi_alloc_device() failed\n"); - return -ENOMEM; - } - - spi_device->chip_select = 0; - spi_device->max_speed_hz = 4000000; - spi_device->mode = SPI_MODE_0; - spi_device->bits_per_word = 8; - spi_device->controller_data = (void *) dev->iCS; - spi_device->dev.platform_data = dev; - strlcpy(spi_device->modalias, DRIVER_NAME, sizeof(DRIVER_NAME)); - - status = spi_add_device(spi_device); - if(status < 0) { - spi_dev_put(spi_device); - printk(KERN_ALERT "spi_add_device() failed %d\n", status); - return status; - } - dev->spi = spi_device; - - put_device(&spi_master->dev); - - return status; -} - -/** - * pmodoled_of_probe - Probe method for ZED on-board OLED device. - * @np: pointer to device tree node - * - * This function probes the OLED device in the device tree. It initializes the - * OLED driver data structure. It returns 0, if the driver is bound to the OLED - * device, or a negative value if there is an error. - */ -static int __init pmodoled_of_probe(struct device_node *np) -{ - struct pmodoled_device *pmodoled_dev; - struct platform_device *pmodoled_pdev; - struct spi_gpio_platform_data *pmodoled_pdata; - const u32* tree_info; - int status = 0; - - /* Alloc Space for platform device structure */ - pmodoled_dev = (struct pmodoled_device*) kzalloc(sizeof(*pmodoled_dev), GFP_KERNEL); - if(!pmodoled_dev) { - status = -ENOMEM; - goto dev_alloc_err; - } - - /* Alloc Graphic Buffer for device */ - pmodoled_dev->disp_buf = (uint8_t*) kmalloc(DISPLAY_BUF_SZ, GFP_KERNEL); - if(!pmodoled_dev->disp_buf) { - status = -ENOMEM; - printk(KERN_INFO DRIVER_NAME "Device Display data buffer allocation failed: %d\n", status); - goto disp_buf_alloc_err; - } - - /* Get CS for SPI_GPIO */ - tree_info = of_get_property(np, "spi-chip-select", NULL); - if(tree_info) { - pmodoled_dev->iCS = be32_to_cpup((tree_info)); - } - else { - pmodoled_dev->iCS = SPI_GPIO_NO_CHIPSELECT; - } - - /* Get the Pin index */ - tree_info = of_get_property(np, "gpio-pins", NULL); - if(tree_info) { - pmodoled_dev->iVBAT = be32_to_cpup((tree_info)); - pmodoled_dev->iVDD = be32_to_cpup((tree_info + 1)); - pmodoled_dev->iRES = be32_to_cpup((tree_info + 2)); - pmodoled_dev->iDC = be32_to_cpup((tree_info + 3)); - pmodoled_dev->iCLK = be32_to_cpup((tree_info + 4)); - pmodoled_dev->iMOSI = be32_to_cpup((tree_info + 5)); - } - - /* Get SPI Related Params */ - tree_info = of_get_property(np, "spi-bus-num", NULL); - if(tree_info) { - pmodoled_dev->spi_id = be32_to_cpup((tree_info)); -#ifdef CONFIG_PMODS_DEBUG - printk(KERN_INFO "pmodoled: BUS_ID\t%x\n", pmodoled_dev->spi_id); -#endif - } - - /* Alloc Space for platform data structure */ - pmodoled_pdata = (struct spi_gpio_platform_data*) kzalloc(sizeof(*pmodoled_pdata), GFP_KERNEL); - if(!pmodoled_pdata) { - status = -ENOMEM; - goto pdata_alloc_err; - } - - /* Fill up Platform Data Structure */ - pmodoled_pdata->sck = pmodoled_dev->iCLK; - pmodoled_pdata->miso = SPI_GPIO_NO_MISO; - pmodoled_pdata->mosi = pmodoled_dev->iMOSI; - pmodoled_pdata->num_chipselect = 1; - - /* Alloc Space for platform data structure */ - pmodoled_pdev = (struct platform_device*) kzalloc(sizeof(*pmodoled_pdev), GFP_KERNEL); - if(!pmodoled_pdev) { - status = -ENOMEM; - goto pdev_alloc_err; - } - - /* Fill up Platform Device Structure */ - pmodoled_pdev->name = "spi_gpio"; - pmodoled_pdev->id = pmodoled_dev->spi_id; - pmodoled_pdev->dev.platform_data = pmodoled_pdata; - pmodoled_dev->pdev = pmodoled_pdev; - - /* Register spi_gpio master */ - status = platform_device_register(pmodoled_dev->pdev); - if(status < 0) { - printk(KERN_ALERT "platform_device_register failed: %d\n", status); - goto pdev_reg_err; - } - /* Fill up Board Info for SPI device */ - status = add_pmodoled_device_to_bus(pmodoled_dev); - if(status < 0) { - printk(KERN_ALERT "add_pmodoled_device_to_bus failed: %d\n", status); - goto spi_add_err; - } - - /* Point device node data to pmodoled_device structure */ - if(np->data == NULL) - np->data = pmodoled_dev; - - pmodoled_dev->name = np->name; - device_num ++; - return status; - -spi_add_err: - platform_device_unregister(pmodoled_dev->pdev); -pdev_reg_err: - kfree(pmodoled_pdev); -pdev_alloc_err: - kfree(pmodoled_pdata); -pdata_alloc_err: - kfree(pmodoled_dev->disp_buf); -disp_buf_alloc_err: - kfree(pmodoled_dev); -dev_alloc_err: - return status; -} - -/** - * pmodoled_of_remove - Remove method for ZED on-board OLED device. - * @np: pointer to device tree node - * - * This function removes the OLED device in the device tree. It frees the - * OLED driver data structure. It returns 0, if the driver is successfully - * removed, or a negative value if there is an error. - */ -static int __exit pmodoled_of_remove(struct device_node *np) -{ - struct pmodoled_device *pmodoled_dev; - - if(np->data == NULL) { - printk(KERN_ERR "pmodoled %s: ERROR: No pmodoled_device structure found!\n", np->name); - return -ENOSYS; - } - pmodoled_dev = (struct pmodoled_device*) (np->data); - - if(pmodoled_dev->disp_buf != NULL) { - kfree(pmodoled_dev->disp_buf); - } - - if(pmodoled_dev->pdev != NULL) { - platform_device_unregister(pmodoled_dev->pdev); - } - - np->data = NULL; - - return 0; -} - -/** - * pmodoled_setup_cdev - Setup Char Device for ZED on-board OLED device. - * @dev: pointer to device tree node - * @dev_id: pointer to device major and minor number - * @spi: pointer to spi_device structure - * - * This function initializes char device for OLED device, and add it into - * kernel device structure. It returns 0, if the cdev is successfully - * initialized, or a negative value if there is an error. - */ -static int pmodoled_setup_cdev(struct pmodoled_device *dev, dev_t *dev_id, struct spi_device *spi) -{ - int status = 0; - struct device *device; - - cdev_init(&dev->cdev, &pmodoled_cdev_fops); - dev->cdev.owner = THIS_MODULE; - dev->cdev.ops = &pmodoled_cdev_fops; - dev->spi = spi; - - *dev_id = MKDEV(MAJOR(pmodoled_dev_id), cur_minor++); - status = cdev_add(&dev->cdev, *dev_id, 1); - if(status < 0) { - return status; - } - - /* Add Device node in system */ - device = device_create(pmodoled_class, NULL, - *dev_id, NULL, - "%s.%d", dev->name, (cur_minor - 1)); - if(IS_ERR(device)) { - status = PTR_ERR(device); - printk(KERN_WARNING "failed to create device node %s.%d, err %d\n", - dev->name, (cur_minor-1), status); - cdev_del(&dev->cdev); - } - - return status; -} - -/** - * pmodoled_init_gpio - Initialize GPIO for ZED Onboard OLED - * @dev - pmodoled_device - * - * Initializes OLED GPIO Control Pins. - * It returns 0, if the gpio pins are successfully - * initialized, or a negative value if there is an error. - */ -static int pmodoled_init_gpio(struct pmodoled_device *dev) -{ - - struct gpio pmodoled_ctrl[] = { - {dev->iVBAT, GPIOF_OUT_INIT_HIGH, "OLED VBat"}, - {dev->iVDD, GPIOF_OUT_INIT_HIGH, "OLED VDD"}, - {dev->iRES, GPIOF_OUT_INIT_HIGH, "OLED_RESET"}, - {dev->iDC, GPIOF_OUT_INIT_HIGH, "OLED_D/C"}, - }; - int status; - int i; - - for (i = 0; i < ARRAY_SIZE(pmodoled_ctrl); i++) { - status = gpio_is_valid(pmodoled_ctrl[i].gpio); - if(!status) { - printk(KERN_INFO DRIVER_NAME "!! gpio_is_valid for GPIO %d, %s FAILED!, status: %d\n", - pmodoled_ctrl[i].gpio, pmodoled_ctrl[i].label, status); - goto gpio_invalid; - } - } - - status = gpio_request_array(pmodoled_ctrl, ARRAY_SIZE(pmodoled_ctrl)); - if(status) { - printk(KERN_INFO DRIVER_NAME "!! gpio_request_array FAILED!\n"); - printk(KERN_INFO DRIVER_NAME " status is: %d\n", status); - gpio_free_array(pmodoled_ctrl, 4); - goto gpio_invalid; - } - -gpio_invalid: - return status; -} - -/** - * pmodoled_disp_init - - * @dev: - * - */ -static void pmodoled_disp_init(struct pmodoled_device *dev) -{ - int status; - uint8_t wr_buf[20]; - - // We are going to be sending commands - // so clear the data/cmd bit - gpio_set_value(dev->iDC, OLED_CONTROLLER_CMD); - - // Start by turning VDD on and wait for the power to come up - gpio_set_value(dev->iVDD, 0); - msleep(1); - - // Display off Command - wr_buf[0] = OLED_DISPLAY_OFF; - status = spi_write(dev->spi, wr_buf, 1); - - /* Bring Reset Low and then High */ - gpio_set_value(dev->iRES, 1); - msleep(1); - gpio_set_value(dev->iRES, 0); - msleep(1); - gpio_set_value(dev->iRES, 1); - - // Send the set charge pump and set precharge period commands - wr_buf[0] = 0x8D; - wr_buf[1] = 0x14; - wr_buf[2] = OLED_SET_PRECHARGE_PERIOD; - wr_buf[3] = 0xF1; - - status = spi_write(dev->spi, wr_buf, 4); - - /* Turn on VCC and wait 100ms */ - gpio_set_value(dev->iVBAT, 0); - msleep(100); - - /* Set Display COntrast */ - wr_buf[0] = OLED_CONTRAST_CTRL; - wr_buf[1] = 0x0F; - - /* Invert the display */ - wr_buf[2] = OLED_SET_SEGMENT_REMAP; // Remap Columns - wr_buf[3] = OLED_SET_COM_DIR; // Remap Rows - - // Select sequential COM configuration - wr_buf[4] = OLED_SET_COM_PINS; - wr_buf[5] = 0x00; - wr_buf[6] = 0xC0; - wr_buf[7] = 0x20; - wr_buf[8] = 0x00; - - // Turn on Display - wr_buf[9] = OLED_DISPLAY_ON; - - status = spi_write(dev->spi, wr_buf, 10); -} - - -/** - * SPI hardware probe. Sets correct SPI mode, attempts - * to obtain memory needed by the driver, and performs - * a simple initialization of the device. - */ -static int pmodoled_spi_probe(struct spi_device *spi) { - int status = 0; - struct pmodoled_device *pmodoled_dev; - - printk(KERN_INFO DRIVER_NAME "oled_spi_probe: Probing %s ..........\n", DRIVER_NAME); - - /* We rely on full duplex transfers, mostly to reduce - * per transfer overheads (by making few transfers). - */ - if (spi->master->flags & SPI_MASTER_HALF_DUPLEX) { - status = -EINVAL; - printk(KERN_INFO DRIVER_NAME "SPI settings incorrect: %d\n", status); - goto spi_err; - } - - /* We must use SPI_MODE_0 */ - spi->mode = SPI_MODE_0; - spi->bits_per_word = 8; - - status = spi_setup(spi); - if(status < 0) { - printk(KERN_INFO DRIVER_NAME "needs SPI mode %02x, %d KHz; %d\n", - spi->mode, spi->max_speed_hz / 1000, - status); - goto spi_err; - } - - /* Get pmodoled_device structure */ - pmodoled_dev = (struct pmodoled_device*) spi->dev.platform_data; - if(pmodoled_dev == NULL) { - printk(KERN_INFO DRIVER_NAME "Cannot get pmodoled_device.\n"); - goto spi_platform_data_err; - } - - /* Setup char driver */ - status = pmodoled_setup_cdev(pmodoled_dev, &(pmodoled_dev->dev_id), spi); - if (status) { - printk(KERN_INFO DRIVER_NAME "oled_spi_probe: Error adding %s device: %d\n", DRIVER_NAME, status); - goto cdev_add_err; - } - - /* Initialize Mutex */ - mutex_init(&pmodoled_dev->mutex); - - /** - * It is important to the OLED's longevity that the lines that - * control it's power are carefully controlled. This is a good - * time to ensure that the device is ot turned on until it is - * instructed to do so. - */ - status = pmodoled_init_gpio(pmodoled_dev); - if(status) { - printk(KERN_INFO DRIVER_NAME "oled_spi_probe: Error initializing GPIO\n"); - goto oled_init_error; - } - - pmodoled_disp_init(pmodoled_dev); - - memset(pmodoled_dev->disp_buf, 0x00, DISPLAY_BUF_SZ); - - status = screen_buf_to_display(pmodoled_dev->disp_buf, pmodoled_dev); - if(status) { - printk(KERN_INFO DRIVER_NAME "oled_spi_probe: Error sending initial Display String\n"); - goto oled_init_error; - } - return status; - -oled_init_error: - if (&pmodoled_dev->cdev) - cdev_del(&pmodoled_dev->cdev); -cdev_add_err: -spi_platform_data_err: -spi_err: - return(status); -} - -static int __devexit pmodoled_spi_remove(struct spi_device *spi) -{ - int status; - struct pmodoled_device *dev; - uint8_t wr_buf[10]; - - dev = (struct pmodoled_device*) spi->dev.platform_data; - - /* Clear Display */ - memset(dev->disp_buf, 0, DISPLAY_BUF_SZ); - status = screen_buf_to_display(dev->disp_buf, dev); - - /* Turn off display */ - wr_buf[0] = OLED_DISPLAY_OFF; - status = spi_write(spi, wr_buf, 1); - if(status) { - dev_err(&spi->dev, "oled_spi_remove: Error writing to SPI device\n"); - } - - /* Turn off VCC (VBAT) */ - gpio_set_value(dev->iVBAT, 1); - msleep(100); - /* TUrn off VDD Power */ - gpio_set_value(dev->iVDD, 1); - -{ - struct gpio pmodoled_ctrl[] = { - {dev->iVBAT, GPIOF_OUT_INIT_HIGH, "OLED VBat"}, - {dev->iVDD, GPIOF_OUT_INIT_HIGH, "OLED VDD"}, - {dev->iRES, GPIOF_OUT_INIT_HIGH, "OLED_RESET"}, - {dev->iDC, GPIOF_OUT_INIT_HIGH, "OLED_D/C"}, - }; - - gpio_free_array(pmodoled_ctrl, 4); -} - - if(&dev->cdev) { - device_destroy(pmodoled_class, dev->dev_id); - cdev_del(&dev->cdev); - } - - return status; -} - -static struct spi_driver pmodoled_spi_driver = { - .driver = { - .name = DRIVER_NAME, - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = pmodoled_spi_probe, - .remove = __devexit_p(pmodoled_spi_remove), -}; - -/** - * pmodoled_init - Initial driver registration call - */ - -static int __init pmodoled_init(void) -{ - int status; -#ifdef CONFIG_OF - struct device_node *np; - - for_each_matching_node(np, pmodoled_of_match) - pmodoled_of_probe(np); -#else - printk(KERN_INFO "pmodoled: CONFIG_OF needs to be enabled!\n"); - return 0; -#endif - - /* Alloc Major & Minor number for char device */ - status = alloc_chrdev_region(&pmodoled_dev_id, 0, device_num, DRIVER_NAME); - if(status) { - printk(KERN_INFO DRIVER_NAME "Character device region not allocated correctly: %d\n", status); - return status; - } - - pmodoled_class = class_create(THIS_MODULE, DRIVER_NAME); - if (IS_ERR(pmodoled_class)) { - status = PTR_ERR(pmodoled_class); - return status; - } - - return spi_register_driver(&pmodoled_spi_driver); -} - -/** - * pmodoled_exit - Clean up function when module gets removed - */ - -static void __exit pmodoled_exit(void) -{ -#ifdef CONFIG_OF -{ - struct device_node *np; - - for_each_matching_node(np, pmodoled_of_match) - pmodoled_of_remove(np); -} -#endif - - spi_unregister_driver(&pmodoled_spi_driver); - - if(pmodoled_class) { - class_destroy(pmodoled_class); - } - - unregister_chrdev_region(pmodoled_dev_id, device_num); - - return; -} - -module_init(pmodoled_init); -module_exit(pmodoled_exit); - -MODULE_AUTHOR("Digilent, Inc."); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION(DRIVER_NAME": ZED On-board OLED display driver"); -MODULE_ALIAS("spi:"DRIVER_NAME); From b9483a941defe8a378f39e5e24c7fb4899b246af Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 12 Jul 2012 17:05:06 -0700 Subject: [PATCH 155/261] Xilinx: DMA: Use dev_dbg instead of printk to output debug message After the fix, the debug message will not appear on the console while booting with a ramdisk. --- drivers/dma/xilinx_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/xilinx_dma.c b/drivers/dma/xilinx_dma.c index 96c265d823a3c..b51d340860020 100644 --- a/drivers/dma/xilinx_dma.c +++ b/drivers/dma/xilinx_dma.c @@ -486,7 +486,7 @@ static int xilinx_dma_wait_status(struct xilinx_dma_chan *chan, uint32_t mask, do { status = DMA_IN(&chan->regs->cr); - printk("status: %x, mask: %x, value: %x\n", status, mask, value); + dev_dbg(chan->dev, "status: %x, mask: %x, value: %x\n", status, mask, value); if ((status & mask) == value) break; } while (--timeout); From 69d733d28917dafd3773b805559c8e7e727f6195 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 12 Jul 2012 17:07:22 -0700 Subject: [PATCH 156/261] DRM: Use dev_dbg instead of printk to output debug message After the fix, the debug message will not appear on the console while booting with a ramdisk. --- drivers/gpu/drm/i2c/adv7511_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i2c/adv7511_core.c b/drivers/gpu/drm/i2c/adv7511_core.c index a7fffb274d1f1..0fb5a7ea05724 100644 --- a/drivers/gpu/drm/i2c/adv7511_core.c +++ b/drivers/gpu/drm/i2c/adv7511_core.c @@ -450,7 +450,7 @@ static enum drm_connector_status adv7511_encoder_detect(struct drm_encoder *enco hpd = adv7511_hpd(adv7511); - printk("detect: %x %d %d %d\n", val, status, hpd, adv7511->dpms_mode); + dev_dbg(encoder->dev->dev, "detect: %x %d %d %d\n", val, status, hpd, adv7511->dpms_mode); /* The chip resets itself when the cable is disconnected, so in case there is * a pending HPD interrupt and the cable is connected there was at least on From 2c8edba4644bb311398b01af89b7e7b3598e1ce0 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 12 Jul 2012 20:37:07 -0700 Subject: [PATCH 157/261] Digilent: 12.07-zed-beta Release --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ce4f80573d97b..468c75960d191 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 3 SUBLEVEL = 0 -EXTRAVERSION = -14.2-build1 +EXTRAVERSION = -digilent-12.07-zed-beta NAME = Saber-toothed Squirrel # *DOCUMENTATION* From 6f2013fc2c5dabe7d301029dcad5b671157f6822 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 5 Apr 2012 14:25:09 -0700 Subject: [PATCH 158/261] libfs: add simple_open() debugfs and a few other drivers use an open-coded version of simple_open() to pass a pointer from the file to the read/write file ops. Add support for this simple case to libfs so that we can remove the many duplicate copies of this simple function. Signed-off-by: Stephen Boyd Cc: Al Viro Cc: Julia Lawall Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/libfs.c | 8 ++++++++ include/linux/fs.h | 1 + 2 files changed, 9 insertions(+) diff --git a/fs/libfs.c b/fs/libfs.c index 5b2dbb3ba4fca..2a897ee0f011f 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -264,6 +264,13 @@ struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name, return ERR_PTR(-ENOMEM); } +int simple_open(struct inode *inode, struct file *file) +{ + if (inode->i_private) + file->private_data = inode->i_private; + return 0; +} + int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; @@ -986,6 +993,7 @@ EXPORT_SYMBOL(simple_dir_operations); EXPORT_SYMBOL(simple_empty); EXPORT_SYMBOL(simple_fill_super); EXPORT_SYMBOL(simple_getattr); +EXPORT_SYMBOL(simple_open); EXPORT_SYMBOL(simple_link); EXPORT_SYMBOL(simple_lookup); EXPORT_SYMBOL(simple_pin_fs); diff --git a/include/linux/fs.h b/include/linux/fs.h index 69cd5bb640f5f..f1c797e25dada 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2510,6 +2510,7 @@ extern int dcache_readdir(struct file *, void *, filldir_t); extern int simple_setattr(struct dentry *, struct iattr *); extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *); extern int simple_statfs(struct dentry *, struct kstatfs *); +extern int simple_open(struct inode *inode, struct file *file); extern int simple_link(struct dentry *, struct inode *, struct dentry *); extern int simple_unlink(struct inode *, struct dentry *); extern int simple_rmdir(struct inode *, struct dentry *); From 6c26301d4b9f412994b90c3a80057e5b2b4d3089 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 23 Mar 2012 15:02:04 -0700 Subject: [PATCH 159/261] bitops: introduce for_each_clear_bit() Introduce for_each_clear_bit() and for_each_clear_bit_from(). They are similar to for_each_set_bit() and list_for_each_set_bit_from(), but they iterate over all the cleared bits in a memory region. Signed-off-by: Akinobu Mita Cc: Robert Richter Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: David Woodhouse Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: Stefano Panella Cc: David Vrabel Cc: Sergei Shtylyov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/bitops.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/linux/bitops.h b/include/linux/bitops.h index 94300fe46cced..c4e9b932efe0f 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -32,6 +32,17 @@ extern unsigned long __sw_hweight64(__u64 w); (bit) < (size); \ (bit) = find_next_bit((addr), (size), (bit) + 1)) +#define for_each_clear_bit(bit, addr, size) \ + for ((bit) = find_first_zero_bit((addr), (size)); \ + (bit) < (size); \ + (bit) = find_next_zero_bit((addr), (size), (bit) + 1)) + +/* same as for_each_clear_bit() but use bit as value to start with */ +#define for_each_clear_bit_from(bit, addr, size) \ + for ((bit) = find_next_zero_bit((addr), (size), (bit)); \ + (bit) < (size); \ + (bit) = find_next_zero_bit((addr), (size), (bit) + 1)) + static __inline__ int get_bitmask_order(unsigned int count) { int order; From bfe5d601151df90971cfb4f87aa943e1d5f82c99 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 13 Jul 2012 13:07:00 +0200 Subject: [PATCH 160/261] iio: disable staging iio Signed-off-by: Michael Hennerich --- drivers/staging/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 943e14830753e..8d3f1dab9d5b0 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -32,7 +32,7 @@ obj-$(CONFIG_VT6656) += vt6656/ obj-$(CONFIG_HYPERV) += hv/ obj-$(CONFIG_VME_BUS) += vme/ obj-$(CONFIG_DX_SEP) += sep/ -obj-$(CONFIG_IIO) += iio/ +#obj-$(CONFIG_IIO) += iio/ obj-$(CONFIG_ZRAM) += zram/ obj-$(CONFIG_XVMALLOC) += zram/ obj-$(CONFIG_ZCACHE) += zcache/ From ccf68ea481131425c32663522a46920dc5de346f Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 13 Jul 2012 13:11:27 +0200 Subject: [PATCH 161/261] iio: add out of staging iio and all xcomm drivers Signed-off-by: Michael Hennerich --- drivers/Kconfig | 1 + drivers/Makefile | 1 + drivers/iio/Kconfig | 63 + drivers/iio/Makefile | 17 + drivers/iio/adc/Kconfig | 41 + drivers/iio/adc/Makefile | 10 + drivers/iio/adc/ad7266.c | 536 +++++++++ drivers/iio/adc/ad9467.c | 115 ++ drivers/iio/adc/at91_adc.c | 761 ++++++++++++ drivers/iio/adc/cf_axi_adc.h | 202 ++++ drivers/iio/adc/cf_axi_adc_core.c | 773 ++++++++++++ drivers/iio/adc/cf_axi_adc_ring.c | 263 +++++ drivers/iio/adc/cf_axi_fft_core.c | 368 ++++++ drivers/iio/adc/cf_axi_fft_core.h | 17 + drivers/iio/adc/cf_fft_core.c | 368 ++++++ drivers/iio/adc/cf_fft_core.h | 17 + drivers/iio/amplifiers/Kconfig | 17 + drivers/iio/amplifiers/Makefile | 5 + drivers/iio/amplifiers/ad8366.c | 225 ++++ drivers/iio/dac/Kconfig | 132 +++ drivers/iio/dac/Makefile | 16 + drivers/iio/dac/ad5064.c | 676 +++++++++++ drivers/iio/dac/ad5360.c | 570 +++++++++ drivers/iio/dac/ad5380.c | 655 +++++++++++ drivers/iio/dac/ad5421.c | 544 +++++++++ drivers/iio/dac/ad5446.c | 393 +++++++ drivers/iio/dac/ad5446.h | 91 ++ drivers/iio/dac/ad5504.c | 393 +++++++ drivers/iio/dac/ad5624r.h | 79 ++ drivers/iio/dac/ad5624r_spi.c | 324 +++++ drivers/iio/dac/ad5686.c | 418 +++++++ drivers/iio/dac/ad5764.c | 382 ++++++ drivers/iio/dac/ad5791.c | 485 ++++++++ drivers/iio/dac/max517.c | 242 ++++ drivers/iio/dac/mcp4725.c | 227 ++++ drivers/iio/frequency/Kconfig | 69 ++ drivers/iio/frequency/Makefile | 9 + drivers/iio/frequency/ad9122.c | 471 ++++++++ drivers/iio/frequency/ad9523.c | 1059 +++++++++++++++++ drivers/iio/frequency/ad9548.c | 287 +++++ drivers/iio/frequency/adf4350.c | 480 ++++++++ drivers/iio/frequency/cf_axi_dds.c | 529 +++++++++ drivers/iio/frequency/cf_axi_dds.h | 1169 +++++++++++++++++++ drivers/iio/iio_core.h | 62 + drivers/iio/iio_core_trigger.h | 46 + drivers/iio/industrialio-buffer.c | 762 ++++++++++++ drivers/iio/industrialio-core.c | 980 ++++++++++++++++ drivers/iio/industrialio-event.c | 454 +++++++ drivers/iio/industrialio-trigger.c | 496 ++++++++ drivers/iio/industrialio-triggered-buffer.c | 110 ++ drivers/iio/inkern.c | 288 +++++ drivers/iio/kfifo_buf.c | 150 +++ drivers/iio/light/Kconfig | 33 + drivers/iio/light/Makefile | 6 + drivers/iio/light/lm3533-als.c | 932 +++++++++++++++ drivers/iio/light/vcnl4000.c | 217 ++++ include/linux/iio/buffer.h | 194 +++ include/linux/iio/consumer.h | 96 ++ include/linux/iio/dac/ad5421.h | 28 + include/linux/iio/dac/ad5504.h | 16 + include/linux/iio/dac/ad5791.h | 25 + include/linux/iio/dac/max517.h | 15 + include/linux/iio/dac/mcp4725.h | 16 + include/linux/iio/driver.h | 34 + include/linux/iio/events.h | 105 ++ include/linux/iio/frequency/ad9523.h | 195 ++++ include/linux/iio/frequency/adf4350.h | 126 ++ include/linux/iio/iio.h | 566 +++++++++ include/linux/iio/kfifo_buf.h | 8 + include/linux/iio/machine.h | 24 + include/linux/iio/sysfs.h | 117 ++ include/linux/iio/trigger.h | 119 ++ include/linux/iio/trigger_consumer.h | 52 + include/linux/iio/triggered_buffer.h | 15 + include/linux/iio/types.h | 56 + 75 files changed, 19843 insertions(+) create mode 100644 drivers/iio/Kconfig create mode 100644 drivers/iio/Makefile create mode 100644 drivers/iio/adc/Kconfig create mode 100644 drivers/iio/adc/Makefile create mode 100644 drivers/iio/adc/ad7266.c create mode 100644 drivers/iio/adc/ad9467.c create mode 100644 drivers/iio/adc/at91_adc.c create mode 100644 drivers/iio/adc/cf_axi_adc.h create mode 100644 drivers/iio/adc/cf_axi_adc_core.c create mode 100644 drivers/iio/adc/cf_axi_adc_ring.c create mode 100644 drivers/iio/adc/cf_axi_fft_core.c create mode 100644 drivers/iio/adc/cf_axi_fft_core.h create mode 100644 drivers/iio/adc/cf_fft_core.c create mode 100644 drivers/iio/adc/cf_fft_core.h create mode 100644 drivers/iio/amplifiers/Kconfig create mode 100644 drivers/iio/amplifiers/Makefile create mode 100644 drivers/iio/amplifiers/ad8366.c create mode 100644 drivers/iio/dac/Kconfig create mode 100644 drivers/iio/dac/Makefile create mode 100644 drivers/iio/dac/ad5064.c create mode 100644 drivers/iio/dac/ad5360.c create mode 100644 drivers/iio/dac/ad5380.c create mode 100644 drivers/iio/dac/ad5421.c create mode 100644 drivers/iio/dac/ad5446.c create mode 100644 drivers/iio/dac/ad5446.h create mode 100644 drivers/iio/dac/ad5504.c create mode 100644 drivers/iio/dac/ad5624r.h create mode 100644 drivers/iio/dac/ad5624r_spi.c create mode 100644 drivers/iio/dac/ad5686.c create mode 100644 drivers/iio/dac/ad5764.c create mode 100644 drivers/iio/dac/ad5791.c create mode 100644 drivers/iio/dac/max517.c create mode 100644 drivers/iio/dac/mcp4725.c create mode 100644 drivers/iio/frequency/Kconfig create mode 100644 drivers/iio/frequency/Makefile create mode 100644 drivers/iio/frequency/ad9122.c create mode 100644 drivers/iio/frequency/ad9523.c create mode 100644 drivers/iio/frequency/ad9548.c create mode 100644 drivers/iio/frequency/adf4350.c create mode 100644 drivers/iio/frequency/cf_axi_dds.c create mode 100644 drivers/iio/frequency/cf_axi_dds.h create mode 100644 drivers/iio/iio_core.h create mode 100644 drivers/iio/iio_core_trigger.h create mode 100644 drivers/iio/industrialio-buffer.c create mode 100644 drivers/iio/industrialio-core.c create mode 100644 drivers/iio/industrialio-event.c create mode 100644 drivers/iio/industrialio-trigger.c create mode 100644 drivers/iio/industrialio-triggered-buffer.c create mode 100644 drivers/iio/inkern.c create mode 100644 drivers/iio/kfifo_buf.c create mode 100644 drivers/iio/light/Kconfig create mode 100644 drivers/iio/light/Makefile create mode 100644 drivers/iio/light/lm3533-als.c create mode 100644 drivers/iio/light/vcnl4000.c create mode 100644 include/linux/iio/buffer.h create mode 100644 include/linux/iio/consumer.h create mode 100644 include/linux/iio/dac/ad5421.h create mode 100644 include/linux/iio/dac/ad5504.h create mode 100644 include/linux/iio/dac/ad5791.h create mode 100644 include/linux/iio/dac/max517.h create mode 100644 include/linux/iio/dac/mcp4725.h create mode 100644 include/linux/iio/driver.h create mode 100644 include/linux/iio/events.h create mode 100644 include/linux/iio/frequency/ad9523.h create mode 100644 include/linux/iio/frequency/adf4350.h create mode 100644 include/linux/iio/iio.h create mode 100644 include/linux/iio/kfifo_buf.h create mode 100644 include/linux/iio/machine.h create mode 100644 include/linux/iio/sysfs.h create mode 100644 include/linux/iio/trigger.h create mode 100644 include/linux/iio/trigger_consumer.h create mode 100644 include/linux/iio/triggered_buffer.h create mode 100644 include/linux/iio/types.h diff --git a/drivers/Kconfig b/drivers/Kconfig index fe2d57f705e9e..b7c0473abf4a2 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -138,4 +138,5 @@ source "drivers/virt/Kconfig" source "drivers/devfreq/Kconfig" +source "drivers/iio/Kconfig" endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 88f5627415b02..74aba7450531e 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -73,6 +73,7 @@ obj-$(CONFIG_USB_OTG_UTILS) += usb/ obj-$(CONFIG_USB) += usb/ obj-$(CONFIG_PCI) += usb/ obj-$(CONFIG_USB_GADGET) += usb/ +obj-$(CONFIG_IIO) += iio/ obj-$(CONFIG_SERIO) += input/serio/ obj-$(CONFIG_GAMEPORT) += input/gameport/ obj-$(CONFIG_INPUT) += input/ diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig new file mode 100644 index 0000000000000..d4984c8be9738 --- /dev/null +++ b/drivers/iio/Kconfig @@ -0,0 +1,63 @@ +# +# Industrial I/O subsytem configuration +# + +menuconfig IIO + tristate "Industrial I/O support" + depends on GENERIC_HARDIRQS + help + The industrial I/O subsystem provides a unified framework for + drivers for many different types of embedded sensors using a + number of different physical interfaces (i2c, spi, etc). + +if IIO + +config IIO_BUFFER + bool "Enable buffer support within IIO" + help + Provide core support for various buffer based data + acquisition methods. + +if IIO_BUFFER + +config IIO_KFIFO_BUF + select IIO_TRIGGER + tristate "Industrial I/O buffering based on kfifo" + help + A simple fifo based on kfifo. Use this if you want a fifo + rather than a ring buffer. Note that this currently provides + no buffer events so it is up to userspace to work out how + often to read from the buffer. + +config IIO_TRIGGERED_BUFFER + tristate + select IIO_TRIGGER + select IIO_KFIFO_BUF + help + Provides helper functions for setting up triggered buffers. + +endif # IIO_BUFFER + +config IIO_TRIGGER + boolean "Enable triggered sampling support" + help + Provides IIO core support for triggers. Currently these + are used to initialize capture of samples to push into + ring buffers. The triggers are effectively a 'capture + data now' interrupt. + +config IIO_CONSUMERS_PER_TRIGGER + int "Maximum number of consumers per trigger" + depends on IIO_TRIGGER + default "2" + help + This value controls the maximum number of consumers that a + given trigger may handle. Default is 2. + +source "drivers/iio/adc/Kconfig" +source "drivers/iio/amplifiers/Kconfig" +source "drivers/iio/light/Kconfig" +source "drivers/iio/frequency/Kconfig" +source "drivers/iio/dac/Kconfig" + +endif # IIO diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile new file mode 100644 index 0000000000000..34309abb79798 --- /dev/null +++ b/drivers/iio/Makefile @@ -0,0 +1,17 @@ +# +# Makefile for the industrial I/O core. +# + +obj-$(CONFIG_IIO) += industrialio.o +industrialio-y := industrialio-core.o industrialio-event.o inkern.o +industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o +industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o + +obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o +obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o + +obj-y += adc/ +obj-y += amplifiers/ +obj-y += light/ +obj-y += frequency/ +obj-y += dac/ diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig new file mode 100644 index 0000000000000..c8eb86326db53 --- /dev/null +++ b/drivers/iio/adc/Kconfig @@ -0,0 +1,41 @@ +# +# ADC drivers +# +menu "Analog to digital converters" + +config AD7266 + tristate "Analog Devices AD7265/AD7266 ADC driver" + depends on SPI_MASTER + select IIO_BUFFER + select IIO_TRIGGER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for Analog Devices AD7265 and AD7266 + ADCs. + +config AT91_ADC + tristate "Atmel AT91 ADC" + depends on ARCH_AT91 + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + select SYSFS + help + Say yes here to build support for Atmel AT91 ADC. + +config CF_AXI_ADC + tristate "Analog Devices AD9467 AD9643 High-Speed AXI ADC driver" + select IIO_BUFFER + help + Say yes here to build support for Analog Devices AD9467 and AD9643, + High-Speed LVDS analog to digital converters (ADC). + FPGA interface HDL is available here: + http://wiki.analog.com/resources/fpga/xilinx/fmc/ad9467 + If unsure, say N (but it's safe to say "Y"). + + To compile this driver as a module, choose M here: the + module will be called cf_axi_adc. + +config CF_AXI_FFT + tristate "Generic FFT driver" + +endmenu diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile new file mode 100644 index 0000000000000..a235b510a827f --- /dev/null +++ b/drivers/iio/adc/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for IIO ADC drivers +# + +obj-$(CONFIG_AD7266) += ad7266.o +obj-$(CONFIG_AT91_ADC) += at91_adc.o + +cf_axi_adc-y := cf_axi_adc_core.o cf_axi_adc_ring.o +obj-$(CONFIG_CF_AXI_ADC) += cf_axi_adc.o ad9467.o +obj-$(CONFIG_CF_AXI_FFT) += cf_axi_fft_core.o diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c new file mode 100644 index 0000000000000..5c3f1ba5a06dc --- /dev/null +++ b/drivers/iio/adc/ad7266.c @@ -0,0 +1,536 @@ +/* + * AD7266/65 SPI ADC driver + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +struct ad7266_state { + struct spi_device *spi; + struct regulator *reg; + unsigned long vref_uv; + + struct spi_transfer single_xfer[3]; + struct spi_message single_msg; + + enum ad7266_range range; + enum ad7266_mode mode; + bool fixed_addr; + struct gpio gpios[3]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + * The buffer needs to be large enough to hold two samples (4 bytes) and + * the naturally aligned timestamp (8 bytes). + */ + uint8_t data[ALIGN(4, sizeof(s64)) + sizeof(s64)] ____cacheline_aligned; +}; + +static int ad7266_wakeup(struct ad7266_state *st) +{ + /* Any read with >= 2 bytes will wake the device */ + return spi_read(st->spi, st->data, 2); +} + +static int ad7266_powerdown(struct ad7266_state *st) +{ + /* Any read with < 2 bytes will powerdown the device */ + return spi_read(st->spi, st->data, 1); +} + +static int ad7266_preenable(struct iio_dev *indio_dev) +{ + struct ad7266_state *st = iio_priv(indio_dev); + int ret; + + ret = ad7266_wakeup(st); + if (ret) + return ret; + + ret = iio_sw_buffer_preenable(indio_dev); + if (ret) + ad7266_powerdown(st); + + return ret; +} + +static int ad7266_postdisable(struct iio_dev *indio_dev) +{ + struct ad7266_state *st = iio_priv(indio_dev); + return ad7266_powerdown(st); +} + +static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = { + .preenable = &ad7266_preenable, + .postenable = &iio_triggered_buffer_postenable, + .predisable = &iio_triggered_buffer_predisable, + .postdisable = &ad7266_postdisable, +}; + +static irqreturn_t ad7266_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct iio_buffer *buffer = indio_dev->buffer; + struct ad7266_state *st = iio_priv(indio_dev); + int ret; + + ret = spi_read(st->spi, st->data, 4); + if (ret == 0) { + if (indio_dev->scan_timestamp) + ((s64 *)st->data)[1] = pf->timestamp; + iio_push_to_buffer(buffer, (u8 *)st->data, pf->timestamp); + } + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static void ad7266_select_input(struct ad7266_state *st, unsigned int nr) +{ + unsigned int i; + + if (st->fixed_addr) + return; + + switch (st->mode) { + case AD7266_MODE_SINGLE_ENDED: + nr >>= 1; + break; + case AD7266_MODE_PSEUDO_DIFF: + nr |= 1; + break; + case AD7266_MODE_DIFF: + nr &= ~1; + break; + } + + for (i = 0; i < 3; ++i) + gpio_set_value(st->gpios[i].gpio, (bool)(nr & BIT(i))); +} + +static int ad7266_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct ad7266_state *st = iio_priv(indio_dev); + unsigned int nr = find_first_bit(scan_mask, indio_dev->masklength); + + ad7266_select_input(st, nr); + + return 0; +} + +static int ad7266_read_single(struct ad7266_state *st, int *val, + unsigned int address) +{ + int ret; + + ad7266_select_input(st, address); + + ret = spi_sync(st->spi, &st->single_msg); + *val = be16_to_cpu(st->data[address % 2]); + + return ret; +} + +static int ad7266_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long m) +{ + struct ad7266_state *st = iio_priv(indio_dev); + unsigned long scale_uv; + int ret; + + switch (m) { + case IIO_CHAN_INFO_RAW: + if (iio_buffer_enabled(indio_dev)) + return -EBUSY; + + ret = ad7266_read_single(st, val, chan->address); + if (ret) + return ret; + + *val = (*val >> 2) & 0xfff; + if (chan->scan_type.sign == 's') + *val = sign_extend32(*val, 11); + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + scale_uv = (st->vref_uv * 100); + if (st->mode == AD7266_MODE_DIFF) + scale_uv *= 2; + if (st->range == AD7266_RANGE_2VREF) + scale_uv *= 2; + + scale_uv >>= chan->scan_type.realbits; + *val = scale_uv / 100000; + *val2 = (scale_uv % 100000) * 10; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_OFFSET: + if (st->range == AD7266_RANGE_2VREF && + st->mode != AD7266_MODE_DIFF) + *val = 2048; + else + *val = 0; + return IIO_VAL_INT; + } + return -EINVAL; +} + +#define AD7266_CHAN(_chan, _sign) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (_chan), \ + .address = (_chan), \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT \ + | IIO_CHAN_INFO_SCALE_SHARED_BIT \ + | IIO_CHAN_INFO_OFFSET_SHARED_BIT, \ + .scan_index = (_chan), \ + .scan_type = { \ + .sign = (_sign), \ + .realbits = 12, \ + .storagebits = 16, \ + .shift = 2, \ + .endianness = IIO_BE, \ + }, \ +} + +#define AD7266_DECLARE_SINGLE_ENDED_CHANNELS(_name, _sign) \ +const struct iio_chan_spec ad7266_channels_##_name[] = { \ + AD7266_CHAN(0, (_sign)), \ + AD7266_CHAN(1, (_sign)), \ + AD7266_CHAN(2, (_sign)), \ + AD7266_CHAN(3, (_sign)), \ + AD7266_CHAN(4, (_sign)), \ + AD7266_CHAN(5, (_sign)), \ + AD7266_CHAN(6, (_sign)), \ + AD7266_CHAN(7, (_sign)), \ + AD7266_CHAN(8, (_sign)), \ + AD7266_CHAN(9, (_sign)), \ + AD7266_CHAN(10, (_sign)), \ + AD7266_CHAN(11, (_sign)), \ + IIO_CHAN_SOFT_TIMESTAMP(13), \ +} + +#define AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(_name, _sign) \ +const struct iio_chan_spec ad7266_channels_##_name##_fixed[] = { \ + AD7266_CHAN(0, (_sign)), \ + AD7266_CHAN(1, (_sign)), \ + IIO_CHAN_SOFT_TIMESTAMP(2), \ +} + +static AD7266_DECLARE_SINGLE_ENDED_CHANNELS(u, 'u'); +static AD7266_DECLARE_SINGLE_ENDED_CHANNELS(s, 's'); +static AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(u, 'u'); +static AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(s, 's'); + +#define AD7266_CHAN_DIFF(_chan, _sign) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (_chan) * 2, \ + .channel2 = (_chan) * 2 + 1, \ + .address = (_chan), \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT \ + | IIO_CHAN_INFO_SCALE_SHARED_BIT \ + | IIO_CHAN_INFO_OFFSET_SHARED_BIT, \ + .scan_index = (_chan), \ + .scan_type = { \ + .sign = _sign, \ + .realbits = 12, \ + .storagebits = 16, \ + .shift = 2, \ + .endianness = IIO_BE, \ + }, \ + .differential = 1, \ +} + +#define AD7266_DECLARE_DIFF_CHANNELS(_name, _sign) \ +const struct iio_chan_spec ad7266_channels_diff_##_name[] = { \ + AD7266_CHAN_DIFF(0, (_sign)), \ + AD7266_CHAN_DIFF(1, (_sign)), \ + AD7266_CHAN_DIFF(2, (_sign)), \ + AD7266_CHAN_DIFF(3, (_sign)), \ + AD7266_CHAN_DIFF(4, (_sign)), \ + AD7266_CHAN_DIFF(5, (_sign)), \ + IIO_CHAN_SOFT_TIMESTAMP(6), \ +} + +static AD7266_DECLARE_DIFF_CHANNELS(s, 's'); +static AD7266_DECLARE_DIFF_CHANNELS(u, 'u'); + +#define AD7266_DECLARE_DIFF_CHANNELS_FIXED(_name, _sign) \ +const struct iio_chan_spec ad7266_channels_diff_fixed_##_name[] = { \ + AD7266_CHAN_DIFF(0, (_sign)), \ + AD7266_CHAN_DIFF(1, (_sign)), \ + IIO_CHAN_SOFT_TIMESTAMP(2), \ +} + +static AD7266_DECLARE_DIFF_CHANNELS_FIXED(s, 's'); +static AD7266_DECLARE_DIFF_CHANNELS_FIXED(u, 'u'); + +static const struct iio_info ad7266_info = { + .read_raw = &ad7266_read_raw, + .update_scan_mode = &ad7266_update_scan_mode, + .driver_module = THIS_MODULE, +}; + +static unsigned long ad7266_available_scan_masks[] = { + 0x003, + 0x00c, + 0x030, + 0x0c0, + 0x300, + 0xc00, + 0x000, +}; + +static unsigned long ad7266_available_scan_masks_diff[] = { + 0x003, + 0x00c, + 0x030, + 0x000, +}; + +static unsigned long ad7266_available_scan_masks_fixed[] = { + 0x003, + 0x000, +}; + +struct ad7266_chan_info { + const struct iio_chan_spec *channels; + unsigned int num_channels; + unsigned long *scan_masks; +}; + +#define AD7266_CHAN_INFO_INDEX(_differential, _signed, _fixed) \ + (((_differential) << 2) | ((_signed) << 1) | ((_fixed) << 0)) + +static const struct ad7266_chan_info ad7266_chan_infos[] = { + [AD7266_CHAN_INFO_INDEX(0, 0, 0)] = { + .channels = ad7266_channels_u, + .num_channels = ARRAY_SIZE(ad7266_channels_u), + .scan_masks = ad7266_available_scan_masks, + }, + [AD7266_CHAN_INFO_INDEX(0, 0, 1)] = { + .channels = ad7266_channels_u_fixed, + .num_channels = ARRAY_SIZE(ad7266_channels_u_fixed), + .scan_masks = ad7266_available_scan_masks_fixed, + }, + [AD7266_CHAN_INFO_INDEX(0, 1, 0)] = { + .channels = ad7266_channels_s, + .num_channels = ARRAY_SIZE(ad7266_channels_s), + .scan_masks = ad7266_available_scan_masks, + }, + [AD7266_CHAN_INFO_INDEX(0, 1, 1)] = { + .channels = ad7266_channels_s_fixed, + .num_channels = ARRAY_SIZE(ad7266_channels_s_fixed), + .scan_masks = ad7266_available_scan_masks_fixed, + }, + [AD7266_CHAN_INFO_INDEX(1, 0, 0)] = { + .channels = ad7266_channels_diff_u, + .num_channels = ARRAY_SIZE(ad7266_channels_diff_u), + .scan_masks = ad7266_available_scan_masks_diff, + }, + [AD7266_CHAN_INFO_INDEX(1, 0, 1)] = { + .channels = ad7266_channels_diff_fixed_u, + .num_channels = ARRAY_SIZE(ad7266_channels_diff_fixed_u), + .scan_masks = ad7266_available_scan_masks_fixed, + }, + [AD7266_CHAN_INFO_INDEX(1, 1, 0)] = { + .channels = ad7266_channels_diff_s, + .num_channels = ARRAY_SIZE(ad7266_channels_diff_s), + .scan_masks = ad7266_available_scan_masks_diff, + }, + [AD7266_CHAN_INFO_INDEX(1, 1, 1)] = { + .channels = ad7266_channels_diff_fixed_s, + .num_channels = ARRAY_SIZE(ad7266_channels_diff_fixed_s), + .scan_masks = ad7266_available_scan_masks_fixed, + }, +}; + +static void __devinit ad7266_init_channels(struct iio_dev *indio_dev) +{ + struct ad7266_state *st = iio_priv(indio_dev); + bool is_differential, is_signed; + const struct ad7266_chan_info *chan_info; + int i; + + is_differential = st->mode != AD7266_MODE_SINGLE_ENDED; + is_signed = (st->range == AD7266_RANGE_2VREF) | + (st->mode == AD7266_MODE_DIFF); + + i = AD7266_CHAN_INFO_INDEX(is_differential, is_signed, st->fixed_addr); + chan_info = &ad7266_chan_infos[i]; + + indio_dev->channels = chan_info->channels; + indio_dev->num_channels = chan_info->num_channels; + indio_dev->available_scan_masks = chan_info->scan_masks; + indio_dev->masklength = chan_info->num_channels - 1; +} + +static const char * const ad7266_gpio_labels[] = { + "AD0", "AD1", "AD2", +}; + +static int __devinit ad7266_probe(struct spi_device *spi) +{ + struct ad7266_platform_data *pdata = spi->dev.platform_data; + struct iio_dev *indio_dev; + struct ad7266_state *st; + unsigned int i; + int ret; + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + + st->reg = regulator_get(&spi->dev, "vref"); + if (!IS_ERR_OR_NULL(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) + goto error_put_reg; + + st->vref_uv = regulator_get_voltage(st->reg); + } else { + /* Use internal reference */ + st->vref_uv = 2500000; + } + + if (pdata) { + st->fixed_addr = pdata->fixed_addr; + st->mode = pdata->mode; + st->range = pdata->range; + + if (!st->fixed_addr) { + for (i = 0; i < ARRAY_SIZE(st->gpios); ++i) { + st->gpios[i].gpio = pdata->addr_gpios[i]; + st->gpios[i].flags = GPIOF_OUT_INIT_LOW; + st->gpios[i].label = ad7266_gpio_labels[i]; + } + ret = gpio_request_array(st->gpios, + ARRAY_SIZE(st->gpios)); + if (ret) + goto error_disable_reg; + } + } else { + st->fixed_addr = true; + st->range = AD7266_RANGE_VREF; + st->mode = AD7266_MODE_DIFF; + } + + spi_set_drvdata(spi, indio_dev); + st->spi = spi; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &ad7266_info; + + ad7266_init_channels(indio_dev); + + /* wakeup */ + st->single_xfer[0].rx_buf = &st->data; + st->single_xfer[0].len = 2; + st->single_xfer[0].cs_change = 1; + /* conversion */ + st->single_xfer[1].rx_buf = &st->data; + st->single_xfer[1].len = 4; + st->single_xfer[1].cs_change = 1; + /* powerdown */ + st->single_xfer[2].tx_buf = &st->data; + st->single_xfer[2].len = 1; + + spi_message_init(&st->single_msg); + spi_message_add_tail(&st->single_xfer[0], &st->single_msg); + spi_message_add_tail(&st->single_xfer[1], &st->single_msg); + spi_message_add_tail(&st->single_xfer[2], &st->single_msg); + + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + &ad7266_trigger_handler, &iio_triggered_buffer_setup_ops); + if (ret) + goto error_free_gpios; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_buffer_cleanup; + + return 0; + +error_buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); +error_free_gpios: + if (!st->fixed_addr) + gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios)); +error_disable_reg: + if (!IS_ERR_OR_NULL(st->reg)) + regulator_disable(st->reg); +error_put_reg: + if (!IS_ERR_OR_NULL(st->reg)) + regulator_put(st->reg); + + iio_device_free(indio_dev); + + return ret; +} + +static int __devexit ad7266_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad7266_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + if (!st->fixed_addr) + gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios)); + if (!IS_ERR_OR_NULL(st->reg)) { + regulator_disable(st->reg); + regulator_put(st->reg); + } + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id ad7266_id[] = { + {"ad7265", 0}, + {"ad7266", 0}, + { } +}; +MODULE_DEVICE_TABLE(spi, ad7266_id); + +static struct spi_driver ad7266_driver = { + .driver = { + .name = "ad7266", + .owner = THIS_MODULE, + }, + .probe = ad7266_probe, + .remove = __devexit_p(ad7266_remove), + .id_table = ad7266_id, +}; +module_spi_driver(ad7266_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("Analog Devices AD7266/65 ADC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c new file mode 100644 index 0000000000000..c8e7ad924b030 --- /dev/null +++ b/drivers/iio/adc/ad9467.c @@ -0,0 +1,115 @@ +/* + * AD9467 SPI DAC driver for DDS PCORE/COREFPGA Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "cf_axi_adc.h" + +static int ad9467_spi_read(struct spi_device *spi, unsigned reg) +{ + unsigned char buf[3]; + int ret; + + if (spi) { + buf[0] = 0x80 | (reg >> 8); + buf[1] = reg & 0xFF; + + ret = spi_write_then_read(spi, &buf[0], 2, &buf[2], 1); + if (ret < 0) + return ret; + + return buf[2]; + } + return -ENODEV; +} + +static int ad9467_spi_write(struct spi_device *spi, unsigned reg, unsigned val) +{ + unsigned char buf[3]; + int ret; + + if (spi) { + buf[0] = reg >> 8; + buf[1] = reg & 0xFF; + buf[2] = val; + ret = spi_write_then_read(spi, buf, 3, NULL, 0); + if (ret < 0) + return ret; + + return 0; + } + return -ENODEV; +} + + +static int __devinit ad9467_probe(struct spi_device *spi) +{ + struct axiadc_converter *conv; + int ret; + + conv = kzalloc(sizeof(*conv), GFP_KERNEL); + if (conv == NULL) + return -ENOMEM; + + spi->mode = SPI_MODE_0 | SPI_3WIRE; + + conv->id = ad9467_spi_read(spi, ADC_REG_CHIP_ID); + if (conv->id != spi_get_device_id(spi)->driver_data) { + dev_err(&spi->dev, "Unrecognized CHIP_ID 0x%X\n", conv->id); + ret = -ENODEV; + goto out; + } + + conv->write = ad9467_spi_write; + conv->read = ad9467_spi_read; + conv->spi = spi; + spi_set_drvdata(spi, conv); + + return 0; + +out: + kfree(conv); + return ret; +} + +static int ad9467_remove(struct spi_device *spi) +{ + spi_set_drvdata(spi, NULL); + + return 0; +} + +static const struct spi_device_id ad9467_id[] = { + {"ad9467", CHIPID_AD9467}, + {"ad9643", CHIPID_AD9643}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad9467_id); + +static struct spi_driver ad9467_driver = { + .driver = { + .name = "ad9467", + .owner = THIS_MODULE, + }, + .probe = ad9467_probe, + .remove = __devexit_p(ad9467_remove), + .id_table = ad9467_id, +}; +module_spi_driver(ad9467_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD9467 ADC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c new file mode 100644 index 0000000000000..f61780a02374d --- /dev/null +++ b/drivers/iio/adc/at91_adc.c @@ -0,0 +1,761 @@ +/* + * Driver for the ADC present in the Atmel AT91 evaluation boards. + * + * Copyright 2011 Free Electrons + * + * Licensed under the GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#define AT91_ADC_CHAN(st, ch) \ + (st->registers->channel_base + (ch * 4)) +#define at91_adc_readl(st, reg) \ + (readl_relaxed(st->reg_base + reg)) +#define at91_adc_writel(st, reg, val) \ + (writel_relaxed(val, st->reg_base + reg)) + +struct at91_adc_state { + struct clk *adc_clk; + u16 *buffer; + unsigned long channels_mask; + struct clk *clk; + bool done; + int irq; + bool irq_enabled; + u16 last_value; + struct mutex lock; + u8 num_channels; + void __iomem *reg_base; + struct at91_adc_reg_desc *registers; + u8 startup_time; + struct iio_trigger **trig; + struct at91_adc_trigger *trigger_list; + u32 trigger_number; + bool use_external; + u32 vref_mv; + wait_queue_head_t wq_data_avail; +}; + +static irqreturn_t at91_adc_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *idev = pf->indio_dev; + struct at91_adc_state *st = iio_priv(idev); + struct iio_buffer *buffer = idev->buffer; + int i, j = 0; + + for (i = 0; i < idev->masklength; i++) { + if (!test_bit(i, idev->active_scan_mask)) + continue; + st->buffer[j] = at91_adc_readl(st, AT91_ADC_CHAN(st, i)); + j++; + } + + if (idev->scan_timestamp) { + s64 *timestamp = (s64 *)((u8 *)st->buffer + + ALIGN(j, sizeof(s64))); + *timestamp = pf->timestamp; + } + + buffer->access->store_to(buffer, (u8 *)st->buffer, pf->timestamp); + + iio_trigger_notify_done(idev->trig); + st->irq_enabled = true; + + /* Needed to ACK the DRDY interruption */ + at91_adc_readl(st, AT91_ADC_LCDR); + + enable_irq(st->irq); + + return IRQ_HANDLED; +} + +static irqreturn_t at91_adc_eoc_trigger(int irq, void *private) +{ + struct iio_dev *idev = private; + struct at91_adc_state *st = iio_priv(idev); + u32 status = at91_adc_readl(st, st->registers->status_register); + + if (!(status & st->registers->drdy_mask)) + return IRQ_HANDLED; + + if (iio_buffer_enabled(idev)) { + disable_irq_nosync(irq); + st->irq_enabled = false; + iio_trigger_poll(idev->trig, iio_get_time_ns()); + } else { + st->last_value = at91_adc_readl(st, AT91_ADC_LCDR); + st->done = true; + wake_up_interruptible(&st->wq_data_avail); + } + + return IRQ_HANDLED; +} + +static int at91_adc_channel_init(struct iio_dev *idev) +{ + struct at91_adc_state *st = iio_priv(idev); + struct iio_chan_spec *chan_array, *timestamp; + int bit, idx = 0; + + idev->num_channels = bitmap_weight(&st->channels_mask, + st->num_channels) + 1; + + chan_array = devm_kzalloc(&idev->dev, + ((idev->num_channels + 1) * + sizeof(struct iio_chan_spec)), + GFP_KERNEL); + + if (!chan_array) + return -ENOMEM; + + for_each_set_bit(bit, &st->channels_mask, st->num_channels) { + struct iio_chan_spec *chan = chan_array + idx; + + chan->type = IIO_VOLTAGE; + chan->indexed = 1; + chan->channel = bit; + chan->scan_index = idx; + chan->scan_type.sign = 'u'; + chan->scan_type.realbits = 10; + chan->scan_type.storagebits = 16; + chan->info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_RAW_SEPARATE_BIT; + idx++; + } + timestamp = chan_array + idx; + + timestamp->type = IIO_TIMESTAMP; + timestamp->channel = -1; + timestamp->scan_index = idx; + timestamp->scan_type.sign = 's'; + timestamp->scan_type.realbits = 64; + timestamp->scan_type.storagebits = 64; + + idev->channels = chan_array; + return idev->num_channels; +} + +static u8 at91_adc_get_trigger_value_by_name(struct iio_dev *idev, + struct at91_adc_trigger *triggers, + const char *trigger_name) +{ + struct at91_adc_state *st = iio_priv(idev); + u8 value = 0; + int i; + + for (i = 0; i < st->trigger_number; i++) { + char *name = kasprintf(GFP_KERNEL, + "%s-dev%d-%s", + idev->name, + idev->id, + triggers[i].name); + if (!name) + return -ENOMEM; + + if (strcmp(trigger_name, name) == 0) { + value = triggers[i].value; + kfree(name); + break; + } + + kfree(name); + } + + return value; +} + +static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state) +{ + struct iio_dev *idev = trig->private_data; + struct at91_adc_state *st = iio_priv(idev); + struct iio_buffer *buffer = idev->buffer; + struct at91_adc_reg_desc *reg = st->registers; + u32 status = at91_adc_readl(st, reg->trigger_register); + u8 value; + u8 bit; + + value = at91_adc_get_trigger_value_by_name(idev, + st->trigger_list, + idev->trig->name); + if (value == 0) + return -EINVAL; + + if (state) { + st->buffer = kmalloc(idev->scan_bytes, GFP_KERNEL); + if (st->buffer == NULL) + return -ENOMEM; + + at91_adc_writel(st, reg->trigger_register, + status | value); + + for_each_set_bit(bit, buffer->scan_mask, + st->num_channels) { + struct iio_chan_spec const *chan = idev->channels + bit; + at91_adc_writel(st, AT91_ADC_CHER, + AT91_ADC_CH(chan->channel)); + } + + at91_adc_writel(st, AT91_ADC_IER, reg->drdy_mask); + + } else { + at91_adc_writel(st, AT91_ADC_IDR, reg->drdy_mask); + + at91_adc_writel(st, reg->trigger_register, + status & ~value); + + for_each_set_bit(bit, buffer->scan_mask, + st->num_channels) { + struct iio_chan_spec const *chan = idev->channels + bit; + at91_adc_writel(st, AT91_ADC_CHDR, + AT91_ADC_CH(chan->channel)); + } + kfree(st->buffer); + } + + return 0; +} + +static const struct iio_trigger_ops at91_adc_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = &at91_adc_configure_trigger, +}; + +static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *idev, + struct at91_adc_trigger *trigger) +{ + struct iio_trigger *trig; + int ret; + + trig = iio_trigger_alloc("%s-dev%d-%s", idev->name, + idev->id, trigger->name); + if (trig == NULL) + return NULL; + + trig->dev.parent = idev->dev.parent; + trig->private_data = idev; + trig->ops = &at91_adc_trigger_ops; + + ret = iio_trigger_register(trig); + if (ret) + return NULL; + + return trig; +} + +static int at91_adc_trigger_init(struct iio_dev *idev) +{ + struct at91_adc_state *st = iio_priv(idev); + int i, ret; + + st->trig = devm_kzalloc(&idev->dev, + st->trigger_number * sizeof(st->trig), + GFP_KERNEL); + + if (st->trig == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + for (i = 0; i < st->trigger_number; i++) { + if (st->trigger_list[i].is_external && !(st->use_external)) + continue; + + st->trig[i] = at91_adc_allocate_trigger(idev, + st->trigger_list + i); + if (st->trig[i] == NULL) { + dev_err(&idev->dev, + "Could not allocate trigger %d\n", i); + ret = -ENOMEM; + goto error_trigger; + } + } + + return 0; + +error_trigger: + for (i--; i >= 0; i--) { + iio_trigger_unregister(st->trig[i]); + iio_trigger_free(st->trig[i]); + } +error_ret: + return ret; +} + +static void at91_adc_trigger_remove(struct iio_dev *idev) +{ + struct at91_adc_state *st = iio_priv(idev); + int i; + + for (i = 0; i < st->trigger_number; i++) { + iio_trigger_unregister(st->trig[i]); + iio_trigger_free(st->trig[i]); + } +} + +static int at91_adc_buffer_init(struct iio_dev *idev) +{ + return iio_triggered_buffer_setup(idev, &iio_pollfunc_store_time, + &at91_adc_trigger_handler, NULL); +} + +static void at91_adc_buffer_remove(struct iio_dev *idev) +{ + iio_triggered_buffer_cleanup(idev); +} + +static int at91_adc_read_raw(struct iio_dev *idev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct at91_adc_state *st = iio_priv(idev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&st->lock); + + at91_adc_writel(st, AT91_ADC_CHER, + AT91_ADC_CH(chan->channel)); + at91_adc_writel(st, AT91_ADC_IER, st->registers->drdy_mask); + at91_adc_writel(st, AT91_ADC_CR, AT91_ADC_START); + + ret = wait_event_interruptible_timeout(st->wq_data_avail, + st->done, + msecs_to_jiffies(1000)); + if (ret == 0) + ret = -ETIMEDOUT; + if (ret < 0) { + mutex_unlock(&st->lock); + return ret; + } + + *val = st->last_value; + + at91_adc_writel(st, AT91_ADC_CHDR, + AT91_ADC_CH(chan->channel)); + at91_adc_writel(st, AT91_ADC_IDR, st->registers->drdy_mask); + + st->last_value = 0; + st->done = false; + mutex_unlock(&st->lock); + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + *val = (st->vref_mv * 1000) >> chan->scan_type.realbits; + *val2 = 0; + return IIO_VAL_INT_PLUS_MICRO; + default: + break; + } + return -EINVAL; +} + +static int at91_adc_probe_dt(struct at91_adc_state *st, + struct platform_device *pdev) +{ + struct iio_dev *idev = iio_priv_to_dev(st); + struct device_node *node = pdev->dev.of_node; + struct device_node *trig_node; + int i = 0, ret; + u32 prop; + + if (!node) + return -EINVAL; + + st->use_external = of_property_read_bool(node, "atmel,adc-use-external-triggers"); + + if (of_property_read_u32(node, "atmel,adc-channels-used", &prop)) { + dev_err(&idev->dev, "Missing adc-channels-used property in the DT.\n"); + ret = -EINVAL; + goto error_ret; + } + st->channels_mask = prop; + + if (of_property_read_u32(node, "atmel,adc-num-channels", &prop)) { + dev_err(&idev->dev, "Missing adc-num-channels property in the DT.\n"); + ret = -EINVAL; + goto error_ret; + } + st->num_channels = prop; + + if (of_property_read_u32(node, "atmel,adc-startup-time", &prop)) { + dev_err(&idev->dev, "Missing adc-startup-time property in the DT.\n"); + ret = -EINVAL; + goto error_ret; + } + st->startup_time = prop; + + + if (of_property_read_u32(node, "atmel,adc-vref", &prop)) { + dev_err(&idev->dev, "Missing adc-vref property in the DT.\n"); + ret = -EINVAL; + goto error_ret; + } + st->vref_mv = prop; + + st->registers = devm_kzalloc(&idev->dev, + sizeof(struct at91_adc_reg_desc), + GFP_KERNEL); + if (!st->registers) { + dev_err(&idev->dev, "Could not allocate register memory.\n"); + ret = -ENOMEM; + goto error_ret; + } + + if (of_property_read_u32(node, "atmel,adc-channel-base", &prop)) { + dev_err(&idev->dev, "Missing adc-channel-base property in the DT.\n"); + ret = -EINVAL; + goto error_ret; + } + st->registers->channel_base = prop; + + if (of_property_read_u32(node, "atmel,adc-drdy-mask", &prop)) { + dev_err(&idev->dev, "Missing adc-drdy-mask property in the DT.\n"); + ret = -EINVAL; + goto error_ret; + } + st->registers->drdy_mask = prop; + + if (of_property_read_u32(node, "atmel,adc-status-register", &prop)) { + dev_err(&idev->dev, "Missing adc-status-register property in the DT.\n"); + ret = -EINVAL; + goto error_ret; + } + st->registers->status_register = prop; + + if (of_property_read_u32(node, "atmel,adc-trigger-register", &prop)) { + dev_err(&idev->dev, "Missing adc-trigger-register property in the DT.\n"); + ret = -EINVAL; + goto error_ret; + } + st->registers->trigger_register = prop; + + st->trigger_number = of_get_child_count(node); + st->trigger_list = devm_kzalloc(&idev->dev, st->trigger_number * + sizeof(struct at91_adc_trigger), + GFP_KERNEL); + if (!st->trigger_list) { + dev_err(&idev->dev, "Could not allocate trigger list memory.\n"); + ret = -ENOMEM; + goto error_ret; + } + + for_each_child_of_node(node, trig_node) { + struct at91_adc_trigger *trig = st->trigger_list + i; + const char *name; + + if (of_property_read_string(trig_node, "trigger-name", &name)) { + dev_err(&idev->dev, "Missing trigger-name property in the DT.\n"); + ret = -EINVAL; + goto error_ret; + } + trig->name = name; + + if (of_property_read_u32(trig_node, "trigger-value", &prop)) { + dev_err(&idev->dev, "Missing trigger-value property in the DT.\n"); + ret = -EINVAL; + goto error_ret; + } + trig->value = prop; + trig->is_external = of_property_read_bool(trig_node, "trigger-external"); + i++; + } + + return 0; + +error_ret: + return ret; +} + +static int at91_adc_probe_pdata(struct at91_adc_state *st, + struct platform_device *pdev) +{ + struct at91_adc_data *pdata = pdev->dev.platform_data; + + if (!pdata) + return -EINVAL; + + st->use_external = pdata->use_external_triggers; + st->vref_mv = pdata->vref; + st->channels_mask = pdata->channels_used; + st->num_channels = pdata->num_channels; + st->startup_time = pdata->startup_time; + st->trigger_number = pdata->trigger_number; + st->trigger_list = pdata->trigger_list; + st->registers = pdata->registers; + + return 0; +} + +static const struct iio_info at91_adc_info = { + .driver_module = THIS_MODULE, + .read_raw = &at91_adc_read_raw, +}; + +static int __devinit at91_adc_probe(struct platform_device *pdev) +{ + unsigned int prsc, mstrclk, ticks, adc_clk; + int ret; + struct iio_dev *idev; + struct at91_adc_state *st; + struct resource *res; + + idev = iio_device_alloc(sizeof(struct at91_adc_state)); + if (idev == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + st = iio_priv(idev); + + if (pdev->dev.of_node) + ret = at91_adc_probe_dt(st, pdev); + else + ret = at91_adc_probe_pdata(st, pdev); + + if (ret) { + dev_err(&pdev->dev, "No platform data available.\n"); + ret = -EINVAL; + goto error_free_device; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "No resource defined\n"); + ret = -ENXIO; + goto error_ret; + } + + platform_set_drvdata(pdev, idev); + + idev->dev.parent = &pdev->dev; + idev->name = dev_name(&pdev->dev); + idev->modes = INDIO_DIRECT_MODE; + idev->info = &at91_adc_info; + + st->irq = platform_get_irq(pdev, 0); + if (st->irq < 0) { + dev_err(&pdev->dev, "No IRQ ID is designated\n"); + ret = -ENODEV; + goto error_free_device; + } + + if (!request_mem_region(res->start, resource_size(res), + "AT91 adc registers")) { + dev_err(&pdev->dev, "Resources are unavailable.\n"); + ret = -EBUSY; + goto error_free_device; + } + + st->reg_base = ioremap(res->start, resource_size(res)); + if (!st->reg_base) { + dev_err(&pdev->dev, "Failed to map registers.\n"); + ret = -ENOMEM; + goto error_release_mem; + } + + /* + * Disable all IRQs before setting up the handler + */ + at91_adc_writel(st, AT91_ADC_CR, AT91_ADC_SWRST); + at91_adc_writel(st, AT91_ADC_IDR, 0xFFFFFFFF); + ret = request_irq(st->irq, + at91_adc_eoc_trigger, + 0, + pdev->dev.driver->name, + idev); + if (ret) { + dev_err(&pdev->dev, "Failed to allocate IRQ.\n"); + goto error_unmap_reg; + } + + st->clk = clk_get(&pdev->dev, "adc_clk"); + if (IS_ERR(st->clk)) { + dev_err(&pdev->dev, "Failed to get the clock.\n"); + ret = PTR_ERR(st->clk); + goto error_free_irq; + } + + ret = clk_prepare(st->clk); + if (ret) { + dev_err(&pdev->dev, "Could not prepare the clock.\n"); + goto error_free_clk; + } + + ret = clk_enable(st->clk); + if (ret) { + dev_err(&pdev->dev, "Could not enable the clock.\n"); + goto error_unprepare_clk; + } + + st->adc_clk = clk_get(&pdev->dev, "adc_op_clk"); + if (IS_ERR(st->adc_clk)) { + dev_err(&pdev->dev, "Failed to get the ADC clock.\n"); + ret = PTR_ERR(st->clk); + goto error_disable_clk; + } + + ret = clk_prepare(st->adc_clk); + if (ret) { + dev_err(&pdev->dev, "Could not prepare the ADC clock.\n"); + goto error_free_adc_clk; + } + + ret = clk_enable(st->adc_clk); + if (ret) { + dev_err(&pdev->dev, "Could not enable the ADC clock.\n"); + goto error_unprepare_adc_clk; + } + + /* + * Prescaler rate computation using the formula from the Atmel's + * datasheet : ADC Clock = MCK / ((Prescaler + 1) * 2), ADC Clock being + * specified by the electrical characteristics of the board. + */ + mstrclk = clk_get_rate(st->clk); + adc_clk = clk_get_rate(st->adc_clk); + prsc = (mstrclk / (2 * adc_clk)) - 1; + + if (!st->startup_time) { + dev_err(&pdev->dev, "No startup time available.\n"); + ret = -EINVAL; + goto error_disable_adc_clk; + } + + /* + * Number of ticks needed to cover the startup time of the ADC as + * defined in the electrical characteristics of the board, divided by 8. + * The formula thus is : Startup Time = (ticks + 1) * 8 / ADC Clock + */ + ticks = round_up((st->startup_time * adc_clk / + 1000000) - 1, 8) / 8; + at91_adc_writel(st, AT91_ADC_MR, + (AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) | + (AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP)); + + /* Setup the ADC channels available on the board */ + ret = at91_adc_channel_init(idev); + if (ret < 0) { + dev_err(&pdev->dev, "Couldn't initialize the channels.\n"); + goto error_disable_adc_clk; + } + + init_waitqueue_head(&st->wq_data_avail); + mutex_init(&st->lock); + + ret = at91_adc_buffer_init(idev); + if (ret < 0) { + dev_err(&pdev->dev, "Couldn't initialize the buffer.\n"); + goto error_disable_adc_clk; + } + + ret = at91_adc_trigger_init(idev); + if (ret < 0) { + dev_err(&pdev->dev, "Couldn't setup the triggers.\n"); + goto error_unregister_buffer; + } + + ret = iio_device_register(idev); + if (ret < 0) { + dev_err(&pdev->dev, "Couldn't register the device.\n"); + goto error_remove_triggers; + } + + return 0; + +error_remove_triggers: + at91_adc_trigger_remove(idev); +error_unregister_buffer: + at91_adc_buffer_remove(idev); +error_disable_adc_clk: + clk_disable(st->adc_clk); +error_unprepare_adc_clk: + clk_unprepare(st->adc_clk); +error_free_adc_clk: + clk_put(st->adc_clk); +error_disable_clk: + clk_disable(st->clk); +error_unprepare_clk: + clk_unprepare(st->clk); +error_free_clk: + clk_put(st->clk); +error_free_irq: + free_irq(st->irq, idev); +error_unmap_reg: + iounmap(st->reg_base); +error_release_mem: + release_mem_region(res->start, resource_size(res)); +error_free_device: + iio_device_free(idev); +error_ret: + return ret; +} + +static int __devexit at91_adc_remove(struct platform_device *pdev) +{ + struct iio_dev *idev = platform_get_drvdata(pdev); + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + struct at91_adc_state *st = iio_priv(idev); + + iio_device_unregister(idev); + at91_adc_trigger_remove(idev); + at91_adc_buffer_remove(idev); + clk_disable_unprepare(st->adc_clk); + clk_put(st->adc_clk); + clk_disable(st->clk); + clk_unprepare(st->clk); + clk_put(st->clk); + free_irq(st->irq, idev); + iounmap(st->reg_base); + release_mem_region(res->start, resource_size(res)); + iio_device_free(idev); + + return 0; +} + +static const struct of_device_id at91_adc_dt_ids[] = { + { .compatible = "atmel,at91sam9260-adc" }, + {}, +}; +MODULE_DEVICE_TABLE(of, at91_adc_dt_ids); + +static struct platform_driver at91_adc_driver = { + .probe = at91_adc_probe, + .remove = __devexit_p(at91_adc_remove), + .driver = { + .name = "at91_adc", + .of_match_table = of_match_ptr(at91_adc_dt_ids), + }, +}; + +module_platform_driver(at91_adc_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Atmel AT91 ADC Driver"); +MODULE_AUTHOR("Maxime Ripard "); diff --git a/drivers/iio/adc/cf_axi_adc.h b/drivers/iio/adc/cf_axi_adc.h new file mode 100644 index 0000000000000..3fd2768afa053 --- /dev/null +++ b/drivers/iio/adc/cf_axi_adc.h @@ -0,0 +1,202 @@ +/* + * ADI-AIM ADI ADC Interface Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + * + * http://wiki.analog.com/resources/fpga/xilinx/fmc/ad9467 + */ + +#ifndef ADI_AXI_ADC_H_ +#define ADI_AXI_ADC_H_ + +/* PCORE CoreFPGA register map */ + +#define AXIADC_PCORE_VERSION 0x00 +#define AXIADC_PCORE_SPI_CTRL 0x04 +#define AXIADC_PCORE_SPI_RDSTAT 0x08 +#define AXIADC_PCORE_DMA_CTRL 0x0C +#define AXIADC_PCORE_DMA_STAT 0x10 +#define AXIADC_PCORE_ADC_STAT 0x14 +#define AXIADC_PCORE_PN_ERR_CTRL 0x24 +#define AXIADC_PCORE_IDENT 0x28 +#define AXIADC_PCORE_ADC_CTRL 0x2C + +/* AXIADC_PCORE_SPI_CTRL */ +#define AXIADC_SPI_START (1 << 25) +#define AXIADC_SPI_SEL(x) (((x) & 0x1) << 24) +#define AXIADC_SPI_READ (1 << 23) +#define AXIADC_SPI_WRITE (0 << 23) +#define AXIADC_SPI_ADDR(x) (((x) & 0x1FFF) << 8) +#define AXIADC_SPI_DATA(x) (((x) & 0xFF) << 0) + +/* AXIADC_PCORE_SPI_RDSTAT */ +#define AXIADC_SPI_IDLE (1 << 8) +#define AXIADC_SPI_READVAL(x) ((x) & 0xFF) + +/* AXIADC_PCORE_DMA_CTRL */ +#define AXIADC_DMA_CAP_EN (1 << 16) +#define AXIADC_DMA_CNT(x) (((x) & 0xFFFF) << 0) + +/* AXIADC_PCORE_DMA_STAT */ +#define AXIADC_DMA_STAT_BUSY (1 << 0) +#define AXIADC_DMA_STAT_OVF (1 << 1) +#define AXIADC_DMA_STAT_UNF (1 << 2) + +/* AXIADC_PCORE_ADC_STAT */ +#define AXIADC_PCORE_ADC_STAT_OVR0 (1 << 0) /* W1C */ +#define AXIADC_PCORE_ADC_STAT_OVR1 (1 << 1) /* W1C */ +#define AXIADC_PCORE_ADC_STAT_PN_OOS0 (1 << 2) /* W1C */ +#define AXIADC_PCORE_ADC_STAT_PN_OOS1 (1 << 3) /* W1C */ +#define AXIADC_PCORE_ADC_STAT_PN_ERR0 (1 << 4) /* W1C */ +#define AXIADC_PCORE_ADC_STAT_PN_ERR1 (1 << 5) /* W1C */ +#define AXIADC_PCORE_ADC_STAT_MASK 0x3F + +/* AXIADC_PCORE_PN_ERR_CTRL */ +#define AXIADC_PN23_1_EN (1 << 1) +#define AXIADC_PN23_0_EN (1 << 0) +#define AXIADC_PN9_1_EN (0 << 1) +#define AXIADC_PN9_0_EN (0 << 0) +#define AXIADC_PN23_EN (AXIADC_PN23_0_EN | AXIADC_PN23_1_EN) +#define AXIADC_PN9_EN (AXIADC_PN9_0_EN | AXIADC_PN9_1_EN) + +/* AXIADC_PCORE_ADC_CTRL */ +#define AXIADC_SIGNEXTEND (1 << 1) +#define AXIADC_STATUS_EN (1 << 0) + +/* AXIADC_PCORE_IDENT */ +#define AXIADC_PCORE_IDENT_SLAVE 0x1 + +/* + * ADI High-Speed ADC common spi interface registers + * See Application-Note AN-877 + */ + +#define ADC_REG_CHIP_PORT_CONF 0x00 +#define ADC_REG_CHIP_ID 0x01 +#define ADC_REG_CHIP_GRADE 0x02 +#define ADC_REG_CHAN_INDEX 0x05 +#define ADC_REG_TRANSFER 0xFF +#define ADC_REG_MODES 0x08 +#define ADC_REG_TEST_IO 0x0D +#define ADC_REG_ADC_INPUT 0x0F +#define ADC_REG_OFFSET 0x10 +#define ADC_REG_OUTPUT_MODE 0x14 +#define ADC_REG_OUTPUT_ADJUST 0x15 +#define ADC_REG_OUTPUT_PHASE 0x16 +#define ADC_REG_OUTPUT_DELAY 0x17 +#define ADC_REG_VREF 0x18 +#define ADC_REG_ANALOG_INPUT 0x2C + +/* ADC_REG_TRANSFER */ +#define TRANSFER_SYNC 0x1 + +/* ADC_REG_TEST_IO */ +#define TESTMODE_OFF 0x0 +#define TESTMODE_MIDSCALE_SHORT 0x1 +#define TESTMODE_POS_FULLSCALE 0x2 +#define TESTMODE_NEG_FULLSCALE 0x3 +#define TESTMODE_ALT_CHECKERBOARD 0x4 +#define TESTMODE_PN23_SEQ 0x5 +#define TESTMODE_PN9_SEQ 0x6 +#define TESTMODE_ONE_ZERO_TOGGLE 0x7 + +/* ADC_REG_OUTPUT_MODE */ +#define OUTPUT_MODE_OFFSET_BINARY 0x0 +#define OUTPUT_MODE_TWOS_COMPLEMENT 0x1 +#define OUTPUT_MODE_GRAY_CODE 0x2 + +/* + * Analog Devices AD9467 16-Bit, 200/250 MSPS ADC + */ + +#define CHIPID_AD9467 0x50 +#define AD9467_DEF_OUTPUT_MODE 0x08 +#define AD9467_REG_VREF_MASK 0x0F + +/* + * Analog Devices AD9643 Dual 14-Bit, 170/210/250 MSPS ADC + */ + +#define CHIPID_AD9643 0x82 +#define AD9643_REG_VREF_MASK 0x1F +#define AD9643_DEF_OUTPUT_MODE 0x00 + +#include + +enum { + ID_AD9467, + ID_AD9643, +}; + +struct axiadc_chip_info { + char name[8]; + unsigned num_channels; + unsigned long available_scan_masks[2]; + const int (*scale_table)[2]; + int num_scales; + struct iio_chan_spec channel[4]; +}; + +struct axiadc_state { + struct device *dev_spi; + struct mutex lock; + struct completion dma_complete; + struct dma_chan *rx_chan; + const struct axiadc_chip_info *chip_info; + void __iomem *regs; + void *buf_virt; + dma_addr_t buf_phys; + int compl_stat; + unsigned adc_def_output_mode; + unsigned ring_lenght; + unsigned rcount; + unsigned fftcount; +// unsigned bytes_per_datum; + unsigned id; + unsigned char testmode[2]; +}; + +struct axiadc_converter { + struct spi_device *spi; + unsigned id; + int (*read)(struct spi_device *spi, unsigned reg); + int (*write)(struct spi_device *spi, + unsigned reg, unsigned val); + int (*setup)(struct spi_device *spi, unsigned mode); +}; + +static inline struct axiadc_converter *to_converter(struct device *dev) +{ + struct axiadc_converter *conv = spi_get_drvdata(to_spi_device(dev)); + + if (conv) + return conv; + + return ERR_PTR(-ENODEV); +}; + +struct axiadc_spidev { + struct device_node *of_nspi; + struct device *dev_spi; +}; + +/* + * IO accessors + */ + +static inline void axiadc_write(struct axiadc_state *st, unsigned reg, unsigned val) +{ + iowrite32(val, st->regs + reg); +} + +static inline unsigned int axiadc_read(struct axiadc_state *st, unsigned reg) +{ + return ioread32(st->regs + reg); +} + +int axiadc_configure_ring(struct iio_dev *indio_dev); +void axiadc_unconfigure_ring(struct iio_dev *indio_dev); + +#endif /* ADI_AXI_ADC_H_ */ diff --git a/drivers/iio/adc/cf_axi_adc_core.c b/drivers/iio/adc/cf_axi_adc_core.c new file mode 100644 index 0000000000000..867354926043f --- /dev/null +++ b/drivers/iio/adc/cf_axi_adc_core.c @@ -0,0 +1,773 @@ +/* + * AXI_ADC ADI ADC Interface Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + * + * http://wiki.analog.com/resources/fpga/xilinx/fmc/ad9467 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "cf_axi_adc.h" +#define DCO_DEBUG + +static int axiadc_spi_read(struct axiadc_state *st, unsigned reg) +{ + struct axiadc_converter *conv = to_converter(st->dev_spi); + + if (IS_ERR(conv)) + return PTR_ERR(conv); + + return conv->read(conv->spi, reg); +} + +static int axiadc_spi_write(struct axiadc_state *st, unsigned reg, unsigned val) +{ + struct axiadc_converter *conv = to_converter(st->dev_spi); + + if (IS_ERR(conv)) + return PTR_ERR(conv); + + return conv->write(conv->spi, reg, val); +} + +static int axiadc_testmode_set(struct iio_dev *indio_dev, + unsigned chan_mask, unsigned mode) +{ + struct axiadc_state *st = iio_priv(indio_dev); + + switch (mode) { + case TESTMODE_PN23_SEQ: + case TESTMODE_PN9_SEQ: + case TESTMODE_ALT_CHECKERBOARD: + axiadc_write(st, AXIADC_PCORE_ADC_CTRL, 0); + axiadc_spi_write(st, ADC_REG_OUTPUT_MODE, + st->adc_def_output_mode & + ~OUTPUT_MODE_TWOS_COMPLEMENT); + break; + default: + axiadc_write(st, AXIADC_PCORE_ADC_CTRL, + (st->id == CHIPID_AD9643) ? AXIADC_SIGNEXTEND : 0); + axiadc_spi_write(st, ADC_REG_OUTPUT_MODE, st->adc_def_output_mode); + }; + + axiadc_spi_write(st, ADC_REG_CHAN_INDEX, chan_mask); + axiadc_spi_write(st, ADC_REG_TEST_IO, mode); + axiadc_spi_write(st, ADC_REG_CHAN_INDEX, 0x3); + axiadc_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); + + if (chan_mask & BIT(0)) + st->testmode[0] = mode; + if (chan_mask & BIT(1)) + st->testmode[1] = mode; + + return 0; +} + +static int axiadc_debugfs_open(struct inode *inode, struct file *file) +{ + if (inode->i_private) + file->private_data = inode->i_private; + + return 0; +} + +static int axiadc_dco_calibrate(struct iio_dev *indio_dev) +{ + struct axiadc_state *st = iio_priv(indio_dev); + int dco, ret, cnt, start, max_start, max_cnt; + unsigned stat; + unsigned char err_field[33]; + + axiadc_testmode_set(indio_dev, 0x2, TESTMODE_PN23_SEQ); + axiadc_testmode_set(indio_dev, 0x1, TESTMODE_PN9_SEQ); + + axiadc_write(st, AXIADC_PCORE_PN_ERR_CTRL, AXIADC_PN23_1_EN | + AXIADC_PN9_0_EN); + + for(dco = 0; dco <= 32; dco++) { + ret = 0; + axiadc_spi_write(st, ADC_REG_OUTPUT_DELAY, + dco > 0 ? ((dco - 1) | 0x80) : 0); + axiadc_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); + axiadc_write(st, AXIADC_PCORE_ADC_STAT, AXIADC_PCORE_ADC_STAT_MASK); + + cnt = 4; + + do { + mdelay(8); + stat = axiadc_read(st, AXIADC_PCORE_ADC_STAT); + if ((cnt-- < 0) | (stat & (AXIADC_PCORE_ADC_STAT_PN_ERR0 | + AXIADC_PCORE_ADC_STAT_PN_ERR1))) { + ret = -EIO; + break; + } + } while (stat & (AXIADC_PCORE_ADC_STAT_PN_OOS0 | + AXIADC_PCORE_ADC_STAT_PN_OOS1)); + + cnt = 4; + + if (!ret) + do { + mdelay(4); + stat = axiadc_read(st, AXIADC_PCORE_ADC_STAT); + if (stat & (AXIADC_PCORE_ADC_STAT_PN_ERR0 | + AXIADC_PCORE_ADC_STAT_PN_ERR1)) { + ret = -EIO; + break; + } + } while (cnt--); + + err_field[dco] = !!ret; + } + + for(dco = 0, cnt = 0, max_cnt = 0, start = -1, max_start = 0; + dco <= 32; dco++) { + if (err_field[dco] == 0) { + if (start == -1) + start = dco; + cnt++; + } else { + if (cnt > max_cnt) { + max_cnt = cnt; + max_start = start; + } + start = -1; + cnt = 0; + } + } + + dco = max_start + (max_cnt / 2); + + axiadc_testmode_set(indio_dev, 0x3, TESTMODE_OFF); + axiadc_spi_write(st, ADC_REG_OUTPUT_DELAY, + dco > 0 ? ((dco - 1) | 0x80) : 0); + axiadc_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); + +#ifdef DCO_DEBUG + for(cnt = 0; cnt <= 32; cnt++) + if (cnt == dco) + printk("|"); + else + printk("%c", err_field[cnt] ? '-' : 'o'); + printk(" DCO 0x%X\n", dco > 0 ? ((dco - 1) | 0x80) : 0); +#endif + + return 0; +} + +static ssize_t axiadc_debugfs_pncheck_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct iio_dev *indio_dev = file->private_data; + struct axiadc_state *st = iio_priv(indio_dev); + char buf[80]; + ssize_t len; + unsigned stat; + + stat = axiadc_read(st, AXIADC_PCORE_ADC_STAT); + + switch (st->id) { + case CHIPID_AD9467: + len = sprintf(buf, "%s %s\n", (stat & AXIADC_PCORE_ADC_STAT_PN_OOS0) ? + "Out of Sync :" : "In Sync :", + (stat & AXIADC_PCORE_ADC_STAT_PN_ERR0) ? + "PN Error" : "No Error"); + break; + case CHIPID_AD9643: + len = sprintf(buf, "CH0 %s %s\nCH1 %s %s\n", (stat & AXIADC_PCORE_ADC_STAT_PN_OOS0) ? + "Out of Sync :" : "In Sync :", + (stat & AXIADC_PCORE_ADC_STAT_PN_ERR0) ? + "PN Error" : "No Error", + (stat & AXIADC_PCORE_ADC_STAT_PN_OOS1) ? + "Out of Sync :" : "In Sync :", + (stat & AXIADC_PCORE_ADC_STAT_PN_ERR1) ? + "PN Error" : "No Error"); + break; + default: + len = 0; + } + + axiadc_write(st, AXIADC_PCORE_ADC_STAT, AXIADC_PCORE_ADC_STAT_MASK); + + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} + +static ssize_t axiadc_debugfs_pncheck_write(struct file *file, + const char __user *userbuf, size_t count, loff_t *ppos) +{ + struct iio_dev *indio_dev = file->private_data; + struct axiadc_state *st = iio_priv(indio_dev); + unsigned mode = TESTMODE_OFF; + char buf[80], *p = buf; + + count = min_t(size_t, count, (sizeof(buf)-1)); + if (copy_from_user(p, userbuf, count)) + return -EFAULT; + + p[count] = 0; + + if (sysfs_streq(p, "PN9")) + mode = TESTMODE_PN9_SEQ; + else if (sysfs_streq(p, "PN23")) + mode = TESTMODE_PN23_SEQ; + else if (sysfs_streq(p, "CALIB")) + axiadc_dco_calibrate(indio_dev); + else + mode = TESTMODE_OFF; + + mutex_lock(&indio_dev->mlock); + axiadc_testmode_set(indio_dev, 0x3, mode); + + axiadc_write(st, AXIADC_PCORE_PN_ERR_CTRL, (mode == TESTMODE_PN23_SEQ) ? + AXIADC_PN23_EN : AXIADC_PN9_EN); + + mdelay(1); /* FIXME */ + + axiadc_write(st, AXIADC_PCORE_ADC_STAT, AXIADC_PCORE_ADC_STAT_MASK); + mutex_unlock(&indio_dev->mlock); + + return count; +} + +static const struct file_operations axiadc_debugfs_pncheck_fops = { + .open = axiadc_debugfs_open, + .read = axiadc_debugfs_pncheck_read, + .write = axiadc_debugfs_pncheck_write, +}; + +static int axiadc_reg_access(struct iio_dev *indio_dev, + unsigned reg, unsigned writeval, + unsigned *readval) +{ + struct axiadc_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&indio_dev->mlock); + if (readval == NULL) { + ret = axiadc_spi_write(st, reg, writeval); + axiadc_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); + } else { + ret = axiadc_spi_read(st, reg); + if (ret < 0) + return ret; + *readval = ret; + + ret = 0; + } + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int axiadc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct axiadc_state *st = iio_priv(indio_dev); + int i; + unsigned vref_val; + + switch (m) { + case IIO_CHAN_INFO_SCALE: + vref_val = axiadc_spi_read(st, ADC_REG_VREF) & + (st->id == CHIPID_AD9643 ? AD9643_REG_VREF_MASK : + AD9467_REG_VREF_MASK); + + for (i = 0; i < st->chip_info->num_scales; i++) + if (vref_val == st->chip_info->scale_table[i][1]) + break; + + *val = 0; + *val2 = st->chip_info->scale_table[i][0]; + + return IIO_VAL_INT_PLUS_MICRO; + } + return -EINVAL; +} + + +static int axiadc_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct axiadc_state *st = iio_priv(indio_dev); + int i; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + if (val != 0) + return -EINVAL; + + for (i = 0; i < st->chip_info->num_scales; i++) + if (val2 == st->chip_info->scale_table[i][0]) { + axiadc_spi_write(st, ADC_REG_VREF, + st->chip_info->scale_table[i][1]); + axiadc_spi_write(st, ADC_REG_TRANSFER, + TRANSFER_SYNC); + return 0; + } + + return -EINVAL; + default: + return -EINVAL; + } +} + +static ssize_t axiadc_show_scale_available(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct axiadc_state *st = iio_priv(indio_dev); + int i, len = 0; + + for (i = 0; i < st->chip_info->num_scales; i++) + len += sprintf(buf + len, "0.%06u ", + st->chip_info->scale_table[i][0]); + + len += sprintf(buf + len, "\n"); + + return len; +} + +static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO, + axiadc_show_scale_available, NULL, 0); + +static struct attribute *axiadc_attributes[] = { + &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group axiadc_attribute_group = { + .attrs = axiadc_attributes, +}; + +static const int ad9467_scale_table[][2] = { + {30517, 0}, {32043, 6}, {33569, 7}, + {35095, 8}, {36621, 9}, {38146, 10}, +}; + +static const int ad9643_scale_table[][2] = { + {31738, 0xF}, {31403, 0xE}, {31067, 0xD}, {30731, 0xC}, {30396, 0xB}, + {30060, 0xA}, {29724, 0x9}, {29388, 0x8}, {29053, 0x7}, {28717, 0x6}, + {28381, 0x5}, {28046, 0x4}, {27710, 0x3}, {27374, 0x2}, {27039, 0x1}, + {26703, 0x0}, {26367, 0x1F}, {26031, 0x1E}, {25696, 0x1D}, + {25360, 0x1C}, {25024, 0x1B}, {24689, 0x1A}, {24353, 0x19}, + {24017, 0x18}, {23682, 0x17}, {23346, 0x16}, {23010, 0x15}, + {22675, 0x14}, {22339, 0x13}, {22003, 0x12}, {21667, 0x11}, + {21332, 0x10}, +}; + +static const char testmodes[][16] = { + [TESTMODE_OFF] = "off", + [TESTMODE_MIDSCALE_SHORT] = "midscale_short", + [TESTMODE_POS_FULLSCALE] = "pos_fullscale", + [TESTMODE_NEG_FULLSCALE] = "neg_fullscale", + [TESTMODE_ALT_CHECKERBOARD] = "checkerboard", + [TESTMODE_PN23_SEQ] = "pn_long", + [TESTMODE_PN9_SEQ] = "pn_short", + [TESTMODE_ONE_ZERO_TOGGLE] = "one_zero_toggle", +}; + +static ssize_t axiadc_testmode_mode_available(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + char *buf) +{ + size_t len = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(testmodes); ++i) { + len += sprintf(buf + len, "%s ", testmodes[i]); + } + len += sprintf(buf + len, "\n"); + return len; +} + +static ssize_t axiadc_testmode_read(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, char *buf) +{ + struct axiadc_state *st = iio_priv(indio_dev); + + return sprintf(buf, "%s\n", + testmodes[st->testmode[chan->channel]]); +} + +static ssize_t axiadc_testmode_write(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + const char *buf, size_t len) +{ + unsigned int mode, i; + int ret; + + mode = 0; + + for (i = 0; i < ARRAY_SIZE(testmodes); ++i) { + if (sysfs_streq(buf, testmodes[i])) { + mode = i; + break; + } + } + + mutex_lock(&indio_dev->mlock); + ret = axiadc_testmode_set(indio_dev, 1 << chan->channel, mode); + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static struct iio_chan_spec_ext_info axiadc_ext_info[] = { + { + .name = "test_mode", + .read = axiadc_testmode_read, + .write = axiadc_testmode_write, + }, + { + .name = "test_mode_available", + .read = axiadc_testmode_mode_available, + .shared = true, + }, + { }, +}; + +#define AIM_CHAN(_chan, _si, _bits, _sign) \ + { .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = _chan, \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .ext_info = axiadc_ext_info, \ + .scan_index = _si, \ + .scan_type = IIO_ST(_sign, _bits, 16, 0)} + +#define AIM_CHAN_FD(_chan, _si, _bits, _sign) \ + { .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = _chan, \ + .extend_name = "frequency_domain", \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .scan_index = _si, \ + .scan_type = IIO_ST(_sign, _bits, 16, 0)} + +static const struct axiadc_chip_info axiadc_chip_info_tbl[] = { + [ID_AD9467] = { + .name = "AD9467", + .scale_table = ad9467_scale_table, + .num_scales = ARRAY_SIZE(ad9467_scale_table), + .num_channels = 1, + .available_scan_masks[0] = BIT(0), + .channel[0] = AIM_CHAN(0, 0, 16, 's'), + }, + [ID_AD9643] = { + .name = "AD9643", + .scale_table = ad9643_scale_table, + .num_scales = ARRAY_SIZE(ad9643_scale_table), + .num_channels = 4, + .available_scan_masks[0] = BIT(0) | BIT(1), + .available_scan_masks[1] = BIT(2) | BIT(3), + .channel[0] = AIM_CHAN(0, 0, 14, 'u'), + .channel[1] = AIM_CHAN(1, 1, 14, 'u'), + .channel[2] = AIM_CHAN_FD(0, 2, 14, 'u'), + .channel[3] = AIM_CHAN_FD(1, 3, 14, 'u'), + }, +}; + +static const struct iio_info axiadc_info = { + .driver_module = THIS_MODULE, + .read_raw = &axiadc_read_raw, + .write_raw = &axiadc_write_raw, + .attrs = &axiadc_attribute_group, + .debugfs_reg_access = &axiadc_reg_access, +}; + +struct axiadc_dma_params { + struct device_node *of_node; + int chan_id; +}; + +static bool axiadc_dma_filter(struct dma_chan *chan, void *param) +{ + struct axiadc_dma_params *p = param; + + return chan->device->dev->of_node == p->of_node && + chan->chan_id == p->chan_id; +} + +static int axiadc_attach_spi_client(struct device *dev, void *data) +{ + struct axiadc_spidev *axiadc_spidev = data; + + if ((axiadc_spidev->of_nspi == dev->of_node) && dev->driver) { + axiadc_spidev->dev_spi = dev; + return 1; + } + + return 0; +} + +/** + * axiadc_of_probe - probe method for the AIM device. + * @of_dev: pointer to OF device structure + * @match: pointer to the structure used for matching a device + * + * This function probes the AIM device in the device tree. + * It initializes the driver data structure and the hardware. + * It returns 0, if the driver is bound to the AIM device, or a negative + * value if there is an error. + */ +static int __devinit axiadc_of_probe(struct platform_device *op) +{ + struct iio_dev *indio_dev; + struct device *dev = &op->dev; + struct axiadc_state *st; + struct resource r_mem; /* IO mem resources */ + struct axiadc_dma_params dma_params; + struct of_phandle_args dma_spec; + struct axiadc_spidev axiadc_spidev; + dma_cap_mask_t mask; + resource_size_t remap_size, phys_addr; + unsigned def_mode; + int ret; + + dev_info(dev, "Device Tree Probing \'%s\'\n", + op->dev.of_node->name); + + /* Defer driver probe until matching spi + * converter driver is registered + */ + axiadc_spidev.of_nspi = of_parse_phandle(op->dev.of_node, + "spibus-connected", 0); + if (!axiadc_spidev.of_nspi) { + dev_err(&op->dev, "could not find spi node\n"); + return -ENODEV; + } + + ret = bus_for_each_dev(&spi_bus_type, NULL, &axiadc_spidev, + axiadc_attach_spi_client); + if (ret == 0) + return -EPROBE_DEFER; + + if (!try_module_get(axiadc_spidev.dev_spi->driver->owner)) + return -ENODEV; + + get_device(axiadc_spidev.dev_spi); + + /* Get iospace for the device */ + ret = of_address_to_resource(op->dev.of_node, 0, &r_mem); + if (ret) { + dev_err(dev, "invalid address\n"); + return ret; + } + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + st->dev_spi = axiadc_spidev.dev_spi; + + dev_set_drvdata(dev, indio_dev); + mutex_init(&st->lock); + + phys_addr = r_mem.start; + remap_size = resource_size(&r_mem); + if (!request_mem_region(phys_addr, remap_size, KBUILD_MODNAME)) { + dev_err(dev, "Couldn't lock memory region at 0x%08llX\n", + (unsigned long long)phys_addr); + ret = -EBUSY; + goto failed1; + } + + st->regs = ioremap(phys_addr, remap_size); + if (st->regs == NULL) { + dev_err(dev, "Couldn't ioremap memory at 0x%08llX\n", + (unsigned long long)phys_addr); + ret = -EFAULT; + goto failed2; + } + /* Get dma channel for the device */ + ret = of_parse_phandle_with_args(op->dev.of_node, "dma-request", + "#dma-cells", 0, &dma_spec); + if (ret) { + dev_err(dev, "Couldn't parse dma-request\n"); + goto failed2; + } + + dma_params.of_node = dma_spec.np; + dma_params.chan_id = dma_spec.args[0]; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE | DMA_PRIVATE, mask); + + st->rx_chan = dma_request_channel(mask, axiadc_dma_filter, &dma_params); + if (!st->rx_chan) { + dev_err(dev, "failed to find rx dma device\n"); + goto failed2; + } + + /* Probe device */ + st->id = axiadc_spi_read(st, ADC_REG_CHIP_ID); + + switch (st->id) { + case CHIPID_AD9467: + st->chip_info = &axiadc_chip_info_tbl[ID_AD9467]; + st->adc_def_output_mode = AD9467_DEF_OUTPUT_MODE | OUTPUT_MODE_TWOS_COMPLEMENT; + break; + case CHIPID_AD9643: + st->chip_info = &axiadc_chip_info_tbl[ID_AD9643]; + st->adc_def_output_mode = AD9643_DEF_OUTPUT_MODE | OUTPUT_MODE_TWOS_COMPLEMENT; + axiadc_write(st, AXIADC_PCORE_ADC_CTRL, AXIADC_SIGNEXTEND); + break; + default: + dev_err(dev, "Unrecognized CHIP_ID 0x%X\n", st->id); + ret = -ENODEV; + goto failed3; + } + + indio_dev->dev.parent = dev; + indio_dev->name = op->dev.of_node->name; + indio_dev->channels = st->chip_info->channel; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->num_channels = st->chip_info->num_channels; + indio_dev->available_scan_masks = st->chip_info->available_scan_masks; + indio_dev->info = &axiadc_info; + + init_completion(&st->dma_complete); + + axiadc_spi_write(st, ADC_REG_OUTPUT_MODE, st->adc_def_output_mode); + axiadc_spi_write(st, ADC_REG_TEST_IO, TESTMODE_OFF); + axiadc_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); + + axiadc_dco_calibrate(indio_dev); + + axiadc_configure_ring(indio_dev); + ret = iio_buffer_register(indio_dev, + st->chip_info->channel, + ARRAY_SIZE(st->chip_info->channel)); + if (ret) + goto failed4; + + ret = iio_device_register(indio_dev); + if (ret) + goto failed4; + + dev_info(dev, "ADI AIM (0x%X) at 0x%08llX mapped to 0x%p," + " DMA-%d probed ADC %s as %s\n", + axiadc_read(st, AXIADC_PCORE_VERSION), + (unsigned long long)phys_addr, st->regs, + st->rx_chan->chan_id, st->chip_info->name, + (axiadc_read(st, AXIADC_PCORE_IDENT) & + AXIADC_PCORE_IDENT_SLAVE) ? "SLAVE" : "MASTER"); + + if (iio_get_debugfs_dentry(indio_dev)) + debugfs_create_file("pseudorandom_err_check", 0644, + iio_get_debugfs_dentry(indio_dev), + indio_dev, &axiadc_debugfs_pncheck_fops); + + return 0; + +failed4: + axiadc_unconfigure_ring(indio_dev); +failed3: + dma_release_channel(st->rx_chan); +failed2: + release_mem_region(phys_addr, remap_size); +failed1: + put_device(st->dev_spi); + module_put(st->dev_spi->driver->owner); + iio_device_free(indio_dev); + dev_set_drvdata(dev, NULL); + + return ret; +} + +/** + * axiadc_of_remove - unbinds the driver from the AIM device. + * @of_dev: pointer to OF device structure + * + * This function is called if a device is physically removed from the system or + * if the driver module is being unloaded. It frees any resources allocated to + * the device. + */ +static int __devexit axiadc_of_remove(struct platform_device *op) +{ + struct device *dev = &op->dev; + struct resource r_mem; /* IO mem resources */ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct axiadc_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_buffer_unregister(indio_dev); + axiadc_unconfigure_ring(indio_dev); + + dma_release_channel(st->rx_chan); + + put_device(st->dev_spi); + module_put(st->dev_spi->driver->owner); + + iounmap(st->regs); + + /* Get iospace of the device */ + if (of_address_to_resource(op->dev.of_node, 0, &r_mem)) + dev_err(dev, "invalid address\n"); + else + release_mem_region(r_mem.start, resource_size(&r_mem)); + + iio_device_free(indio_dev); + + dev_set_drvdata(dev, NULL); + + return 0; +} + +/* Match table for of_platform binding */ +static const struct of_device_id axiadc_of_match[] __devinitconst = { + { .compatible = "xlnx,cf-ad9467-core-1.00.a", }, + { .compatible = "xlnx,cf-ad9643-core-1.00.a", }, + { .compatible = "xlnx,axi-adc-2c-1.00.a", }, +{ /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, axiadc_of_match); + +static struct platform_driver axiadc_of_driver = { + .driver = { + .name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .of_match_table = axiadc_of_match, + }, + .probe = axiadc_of_probe, + .remove = __devexit_p(axiadc_of_remove), +}; + +module_platform_driver(axiadc_of_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices ADI-AIM"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/cf_axi_adc_ring.c b/drivers/iio/adc/cf_axi_adc_ring.c new file mode 100644 index 0000000000000..8e304f22da4cb --- /dev/null +++ b/drivers/iio/adc/cf_axi_adc_ring.c @@ -0,0 +1,263 @@ +/* + * ADI-AIM ADC Interface Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "../../staging/iio/ring_hw.h" +#include "cf_axi_adc.h" +#include "cf_axi_fft_core.h" + +static int axiadc_read_first_n_hw_rb(struct iio_buffer *r, + size_t count, char __user *buf) +{ + struct iio_hw_buffer *hw_ring = iio_to_hw_buf(r); + struct iio_dev *indio_dev = hw_ring->private; + struct axiadc_state *st = iio_priv(indio_dev); + int ret; + unsigned stat, dma_stat; + + mutex_lock(&st->lock); + + ret = wait_for_completion_interruptible_timeout(&st->dma_complete, + 4 * HZ); + + stat = axiadc_read(st, AXIADC_PCORE_ADC_STAT); + dma_stat = axiadc_read(st, AXIADC_PCORE_DMA_STAT); + + if (st->compl_stat < 0) { + ret = st->compl_stat; + goto error_ret; + } else if (ret == 0) { + ret = -ETIMEDOUT; + dev_err(indio_dev->dev.parent, + "timeout: DMA_STAT 0x%X, ADC_STAT 0x%X\n", + dma_stat, stat); + goto error_ret; + } else if (ret < 0) { + goto error_ret; + } + +#if defined(CONFIG_CF_AXI_FFT) + if (st->fftcount) { + ret = fft_calculate(st->buf_phys, st->buf_phys + st->fftcount, + st->fftcount / 4, *r->scan_mask >> 2); + } +#endif + if (copy_to_user(buf, st->buf_virt + st->fftcount, count)) + ret = -EFAULT; + + if ((stat & (AXIADC_PCORE_ADC_STAT_OVR0 | AXIADC_PCORE_ADC_STAT_OVR1)) + || dma_stat) + dev_warn(indio_dev->dev.parent, + "STATUS: DMA_STAT 0x%X, ADC_STAT 0x%X\n", + dma_stat, stat); + +error_ret: + r->stufftoread = 0; + + mutex_unlock(&st->lock); + + return ret < 0 ? ret : count; +} + +static int axiadc_ring_get_length(struct iio_buffer *r) +{ + struct iio_hw_buffer *hw_ring = iio_to_hw_buf(r); + struct iio_dev *indio_dev = hw_ring->private; + struct axiadc_state *st = iio_priv(indio_dev); + + return st->ring_lenght; +} + +static int axiadc_ring_set_length(struct iio_buffer *r, int lenght) +{ + struct iio_hw_buffer *hw_ring = iio_to_hw_buf(r); + struct axiadc_state *st = iio_priv(hw_ring->private); + + st->ring_lenght = lenght; + + return 0; +} + +static int axiadc_ring_get_bytes_per_datum(struct iio_buffer *r) +{ + struct iio_hw_buffer *hw_ring = iio_to_hw_buf(r); + + return r->bytes_per_datum; +} + +static IIO_BUFFER_ENABLE_ATTR; +static IIO_BUFFER_LENGTH_ATTR; + +static struct attribute *axiadc_ring_attributes[] = { + &dev_attr_length.attr, + &dev_attr_enable.attr, + NULL, +}; + +static struct attribute_group axiadc_ring_attr = { + .attrs = axiadc_ring_attributes, + .name = "buffer", +}; + +static struct iio_buffer *axiadc_rb_allocate(struct iio_dev *indio_dev) +{ + struct iio_buffer *buf; + struct iio_hw_buffer *ring; + + ring = kzalloc(sizeof *ring, GFP_KERNEL); + if (!ring) + return NULL; + + ring->private = indio_dev; + buf = &ring->buf; + buf->attrs = &axiadc_ring_attr; + iio_buffer_init(buf); + + return buf; +} + +static inline void axiadc_rb_free(struct iio_buffer *r) +{ + kfree(iio_to_hw_buf(r)); +} + +static const struct iio_buffer_access_funcs axiadc_ring_access_funcs = { + .read_first_n = &axiadc_read_first_n_hw_rb, + .get_length = &axiadc_ring_get_length, + .set_length = &axiadc_ring_set_length, + .get_bytes_per_datum = &axiadc_ring_get_bytes_per_datum, +}; + +static int __axiadc_hw_ring_state_set(struct iio_dev *indio_dev, bool state) +{ + struct axiadc_state *st = iio_priv(indio_dev); + struct iio_buffer *buffer = indio_dev->buffer; + struct dma_async_tx_descriptor *desc; + dma_cookie_t cookie; + int ret = 0; + + if (!state) { + if (!completion_done(&st->dma_complete)) { + st->compl_stat = -EPERM; + dmaengine_terminate_all(st->rx_chan); + complete(&st->dma_complete); + } + + dma_free_coherent(indio_dev->dev.parent, + PAGE_ALIGN(st->rcount + st->fftcount), + st->buf_virt, st->buf_phys); + return 0; + } + + st->compl_stat = 0; + + if (st->ring_lenght == 0) { + ret = -EINVAL; + goto error_ret; + } + + if (st->ring_lenght % 8) + st->rcount = (st->ring_lenght + 8) & 0xFFFFFFF8; + else + st->rcount = st->ring_lenght; + +#if defined(CONFIG_CF_AXI_FFT) + if (*buffer->scan_mask & 0xC) + st->fftcount = st->rcount; + else + st->fftcount = 0; +#else + st->fftcount = 0; +#endif + + st->buf_virt = dma_alloc_coherent(indio_dev->dev.parent, + PAGE_ALIGN(st->rcount + st->fftcount), &st->buf_phys, + GFP_KERNEL); + if (st->buf_virt == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + desc = dmaengine_prep_slave_single(st->rx_chan, st->buf_phys, st->rcount, + DMA_FROM_DEVICE, DMA_PREP_INTERRUPT); + if (!desc) { + dev_err(indio_dev->dev.parent, + "Failed to allocate a dma descriptor\n"); + ret = -ENOMEM; + goto error_free; + } + + desc->callback = (dma_async_tx_callback) complete; + desc->callback_param = &st->dma_complete; + + cookie = dmaengine_submit(desc); + if (cookie < 0) { + dev_err(indio_dev->dev.parent, + "Failed to submit a dma transfer\n"); + ret = cookie; + goto error_free; + } + INIT_COMPLETION(st->dma_complete); + dma_async_issue_pending(st->rx_chan); + + axiadc_write(st, AXIADC_PCORE_DMA_CTRL, 0); + axiadc_write(st, AXIADC_PCORE_ADC_STAT, 0xFF); + axiadc_write(st, AXIADC_PCORE_DMA_STAT, 0xFF); + axiadc_write(st, AXIADC_PCORE_DMA_CTRL, + AXIADC_DMA_CAP_EN | AXIADC_DMA_CNT((st->rcount / 8) - 1)); + + return 0; + +error_free: + dma_free_coherent(indio_dev->dev.parent, PAGE_ALIGN(st->rcount), + st->buf_virt, st->buf_phys); +error_ret: + return ret; +} + +static int axiadc_hw_ring_preenable(struct iio_dev *indio_dev) +{ + return __axiadc_hw_ring_state_set(indio_dev, 1); +} + +static int axiadc_hw_ring_postdisable(struct iio_dev *indio_dev) +{ + return __axiadc_hw_ring_state_set(indio_dev, 0); +} + +static const struct iio_buffer_setup_ops axiadc_ring_setup_ops = { + .preenable = &axiadc_hw_ring_preenable, + .postdisable = &axiadc_hw_ring_postdisable, +}; + +int axiadc_configure_ring(struct iio_dev *indio_dev) +{ + indio_dev->buffer = axiadc_rb_allocate(indio_dev); + if (indio_dev->buffer == NULL) + return -ENOMEM; + + indio_dev->modes |= INDIO_BUFFER_HARDWARE; + indio_dev->buffer->access = &axiadc_ring_access_funcs; + indio_dev->setup_ops = &axiadc_ring_setup_ops; + + return 0; +} + +void axiadc_unconfigure_ring(struct iio_dev *indio_dev) +{ + axiadc_rb_free(indio_dev->buffer); +} diff --git a/drivers/iio/adc/cf_axi_fft_core.c b/drivers/iio/adc/cf_axi_fft_core.c new file mode 100644 index 0000000000000..e45d1a9a53165 --- /dev/null +++ b/drivers/iio/adc/cf_axi_fft_core.c @@ -0,0 +1,368 @@ +/* + * ADI-FFT Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + * + * http://wiki.analog.com/resources/fpga/xilinx/ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/*************************************************************************** + * register definitions (fft) + * 5'h00: + * [31: 0]: version(32'h00010061) + * 5'h01: + * [31: 0]: up_cfg_data, fft cfg data (refer Xilinx fft core for details). + * 5'h02: + * [ 3: 3]: up_status_ovf, fft overflow (mapped to Xilinx fft core outputs). + * [ 2: 2]: up_status_lm, fft tlast missing (mapped to core). + * [ 1: 1]: up_status_lu, fft tlast unexpected (mapped to core). + * [ 0: 0]: up_status_fs, fft frame start (mapped to core). + ***************************************************************************/ + +#define FFT_PCORE_VERSION 0x0 +#define FFT_PCORE_CFG 0x4 +#define FFT_PCORE_STAT 0x8 +#define FFT_PCORE_POSTPROC 0xC +#define FFT_PCORE_IRSEL 0x10 +#define FFT_PCORE_WINCFG 0x14 + +#define FFT_PCORE_CFG_DEFAULT 0xD5700 +#define FFT_PCORE_CFG_FW_FFT (1 << 8) +#define FFT_PCORE_CFG_INV_FFT (0 << 8) + +#define FFT_PCORE_POSTPROC_EN 0x1 + +#define FFT_PCORE_IRSEL_I(x) ((x) << 2) +#define FFT_PCORE_IRSEL_R(x) ((x) << 0) +#define FFT_PCORE_IRSEL_ZERO 0 +#define FFT_PCORE_IRSEL_CH0 1 +#define FFT_PCORE_IRSEL_CH1 2 + + +#define FFT_PCORE_WINCFG_INC(x) ((x) & 0xFFFF) +#define FFT_PCORE_WINCFG_ENB (1 << 16) + +struct fft_state { + struct device *dev; + struct mutex lock; + struct completion dma_complete; + struct dma_chan *rx_chan; + struct dma_chan *tx_chan; + void __iomem *regs; + int compl_stat; +}; + +struct fft_dma_params { + struct device_node *of_node; + enum dma_transfer_direction direction; + int chan_id; +}; + +struct fft_state *fft_state_glob; + +/* + * IO accessors + */ + +static inline void fft_write(struct fft_state *st, unsigned reg, unsigned val) +{ + iowrite32(val, st->regs + reg); +} + +static inline unsigned int fft_read(struct fft_state *st, unsigned reg) +{ + return ioread32(st->regs + reg); +} + +static bool fft_dma_filter(struct dma_chan *chan, void *param) +{ + struct fft_dma_params *p = param; + + return chan->device->dev->of_node == p->of_node && + chan->chan_id == p->chan_id; +} + +int fft_calculate(dma_addr_t src, dma_addr_t dest, unsigned int size, unsigned irsel) +{ + struct fft_state *st = fft_state_glob; + struct dma_async_tx_descriptor *tx_desc, *rx_desc; + dma_cookie_t tx_cookie, rx_cookie; + unsigned nfft = ilog2(size); + int ret = 0; + + if (st == NULL) + return -ENODEV; + + if (((1 << nfft) != size) || !src || !dest || !irsel) + return -EINVAL; + + switch (irsel) { + case FFT_PCORE_IRSEL_CH0: + case FFT_PCORE_IRSEL_CH1: + irsel = FFT_PCORE_IRSEL_R(irsel); + break; + case FFT_PCORE_IRSEL_CH0 | FFT_PCORE_IRSEL_CH1: + irsel = FFT_PCORE_IRSEL_R(FFT_PCORE_IRSEL_CH0) | + FFT_PCORE_IRSEL_I(FFT_PCORE_IRSEL_CH1); + break; + } + + mutex_lock(&st->lock); +// printk("%s: %d::: %d %x\n",__func__,__LINE__, size, irsel); + fft_write(st, FFT_PCORE_WINCFG, 0); + fft_write(st, FFT_PCORE_WINCFG, BIT(16) | (0x10000 >> nfft)); + fft_write(st, FFT_PCORE_POSTPROC, FFT_PCORE_POSTPROC_EN); + fft_write(st, FFT_PCORE_IRSEL, irsel); + fft_write(st, FFT_PCORE_STAT, 0xFF); + fft_write(st, FFT_PCORE_CFG, FFT_PCORE_CFG_DEFAULT | nfft); + + tx_desc = dmaengine_prep_slave_single(st->tx_chan, src, size * 4, + DMA_TO_DEVICE, 0); + if (!tx_desc) { + dev_err(st->dev, + "Failed to allocate a dma descriptor\n"); + ret = -ENOMEM; + goto error_ret; + } + + tx_cookie = dmaengine_submit(tx_desc); + if (tx_cookie < 0) { + dev_err(st->dev, + "Failed to submit a dma transfer\n"); + ret = tx_cookie; + goto error_ret; + } + + rx_desc = dmaengine_prep_slave_single(st->rx_chan, dest, size * 4, + DMA_FROM_DEVICE, DMA_PREP_INTERRUPT); + if (!rx_desc) { + dev_err(st->dev, + "Failed to allocate a dma descriptor\n"); + ret = -ENOMEM; + goto error_ret; + } + + rx_desc->callback = (dma_async_tx_callback) complete; + rx_desc->callback_param = &st->dma_complete; + + rx_cookie = dmaengine_submit(rx_desc); + if (rx_cookie < 0) { + dev_err(st->dev, + "Failed to submit a dma transfer\n"); + ret = rx_cookie; + goto error_ret; + } + + dma_async_issue_pending(st->tx_chan); + dma_async_issue_pending(st->rx_chan); + + ret = wait_for_completion_interruptible_timeout(&st->dma_complete, + 4 * HZ); + if (ret == 0) { + ret = -ETIMEDOUT; + goto error_ret; + } else if (ret < 0) { + goto error_ret; + } + + ret = 0; + +error_ret: + mutex_unlock(&st->lock); + return ret; +} +EXPORT_SYMBOL_GPL(fft_calculate); + +/** + * fft_of_probe - probe method for the AIM device. + * @of_dev: pointer to OF device structure + * @match: pointer to the structure used for matching a device + * + * This function probes the AIM device in the device tree. + * It initializes the driver data structure and the hardware. + * It returns 0, if the driver is bound to the AIM device, or a negative + * value if there is an error. + */ +static int __devinit fft_of_probe(struct platform_device *op) +{ + struct device *dev = &op->dev; + struct fft_state *st; + struct resource r_mem; /* IO mem resources */ + struct fft_dma_params dma_params; + struct of_phandle_args dma_spec; + dma_cap_mask_t mask; + resource_size_t remap_size, phys_addr; + int ret; + + dev_info(dev, "Device Tree Probing \'%s\'\n", + op->dev.of_node->name); + + st = devm_kzalloc(&op->dev, sizeof(*st), GFP_KERNEL); + if (!st) { + dev_err(dev, "Not enough memory for device\n"); + return -ENOMEM; + } + + st->dev = dev; + dev_set_drvdata(dev, st); + mutex_init(&st->lock); + + /* Get iospace for the device */ + ret = of_address_to_resource(op->dev.of_node, 0, &r_mem); + if (ret) { + dev_err(dev, "invalid address\n"); + return ret; + } + + phys_addr = r_mem.start; + remap_size = resource_size(&r_mem); + if (!request_mem_region(phys_addr, remap_size, KBUILD_MODNAME)) { + dev_err(dev, "Couldn't lock memory region at 0x%08llX\n", + (unsigned long long)phys_addr); + ret = -EBUSY; + goto failed1; + } + + st->regs = ioremap(phys_addr, remap_size); + if (st->regs == NULL) { + dev_err(dev, "Couldn't ioremap memory at 0x%08llX\n", + (unsigned long long)phys_addr); + ret = -EFAULT; + goto failed2; + } + + /* Get dma channel for the device */ + ret = of_parse_phandle_with_args(op->dev.of_node, "dma-request", + "#dma-cells", 0, &dma_spec); + if (ret) { + dev_err(dev, "Couldn't parse dma-request\n"); + goto failed2; + } + + dma_params.of_node = dma_spec.np; + dma_params.chan_id = dma_spec.args[0]; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE | DMA_PRIVATE, mask); + + st->tx_chan = dma_request_channel(mask, fft_dma_filter, &dma_params); + if (!st->tx_chan) { + dev_err(dev, "failed to find tx dma device\n"); + goto failed2; + } + + /* Get dma channel for the device */ + ret = of_parse_phandle_with_args(op->dev.of_node, "dma-request", + "#dma-cells", 1, &dma_spec); + if (ret) { + dev_err(dev, "Couldn't parse dma-request\n"); + goto failed2; + } + + dma_params.of_node = dma_spec.np; + dma_params.chan_id = dma_spec.args[0]; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE | DMA_PRIVATE, mask); + + st->rx_chan = dma_request_channel(mask, fft_dma_filter, &dma_params); + if (!st->rx_chan) { + dev_err(dev, "failed to find rx dma device\n"); + goto failed2; + } + + init_completion(&st->dma_complete); + + dev_info(dev, "ADI-FFT (0x%X) at 0x%08llX mapped to 0x%p," + " DMA-%d, DMA-%d probed\n", + fft_read(st, FFT_PCORE_VERSION), + (unsigned long long)phys_addr, st->regs, + st->rx_chan->chan_id, st->tx_chan->chan_id); + + fft_state_glob = st; + + return 0; + +failed2: + release_mem_region(phys_addr, remap_size); +failed1: + dev_set_drvdata(dev, NULL); + + return ret; +} + +/** + * fft_of_remove - unbinds the driver from the AIM device. + * @of_dev: pointer to OF device structure + * + * This function is called if a device is physically removed from the system or + * if the driver module is being unloaded. It frees any resources allocated to + * the device. + */ +static int __devexit fft_of_remove(struct platform_device *op) +{ + struct device *dev = &op->dev; + struct resource r_mem; /* IO mem resources */ + struct fft_state *st = dev_get_drvdata(dev); + + dma_release_channel(st->rx_chan); + dma_release_channel(st->tx_chan); + + iounmap(st->regs); + + /* Get iospace of the device */ + if (of_address_to_resource(op->dev.of_node, 0, &r_mem)) + dev_err(dev, "invalid address\n"); + else + release_mem_region(r_mem.start, resource_size(&r_mem)); + + dev_set_drvdata(dev, NULL); + fft_state_glob = NULL; + + return 0; +} + +/* Match table for of_platform binding */ +static const struct of_device_id fft_of_match[] __devinitconst = { + { .compatible = "xlnx,cf-fft-core-1.00.a", }, + { .compatible = "xlnx,axi-fft-1.00.a", }, + { /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, fft_of_match); + +static struct platform_driver fft_of_driver = { + .driver = { + .name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .of_match_table = fft_of_match, + }, + .probe = fft_of_probe, + .remove = __devexit_p(fft_of_remove), +}; + +module_platform_driver(fft_of_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices CF FFT"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/cf_axi_fft_core.h b/drivers/iio/adc/cf_axi_fft_core.h new file mode 100644 index 0000000000000..7437dcc2a6f91 --- /dev/null +++ b/drivers/iio/adc/cf_axi_fft_core.h @@ -0,0 +1,17 @@ +/* + * ADI-FFT Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + * + * http://wiki.analog.com/resources/fpga/xilinx/ + */ + +#ifndef ADI_FFT_H_ +#define ADI_FFT_H_ + +int fft_calculate(dma_addr_t src, dma_addr_t dest, + unsigned int size, unsigned irsel); + +#endif /* ADI_FFT_H_ */ diff --git a/drivers/iio/adc/cf_fft_core.c b/drivers/iio/adc/cf_fft_core.c new file mode 100644 index 0000000000000..17861136193ad --- /dev/null +++ b/drivers/iio/adc/cf_fft_core.c @@ -0,0 +1,368 @@ +/* + * ADI-FFT Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + * + * http://wiki.analog.com/resources/fpga/xilinx/ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/*************************************************************************** + * register definitions (fft) + * 5'h00: + * [31: 0]: version(32'h00010061) + * 5'h01: + * [31: 0]: up_cfg_data, fft cfg data (refer Xilinx fft core for details). + * 5'h02: + * [ 3: 3]: up_status_ovf, fft overflow (mapped to Xilinx fft core outputs). + * [ 2: 2]: up_status_lm, fft tlast missing (mapped to core). + * [ 1: 1]: up_status_lu, fft tlast unexpected (mapped to core). + * [ 0: 0]: up_status_fs, fft frame start (mapped to core). + ***************************************************************************/ + +#define FFT_PCORE_VERSION 0x0 +#define FFT_PCORE_CFG 0x4 +#define FFT_PCORE_STAT 0x8 +#define FFT_PCORE_POSTPROC 0xC +#define FFT_PCORE_IRSEL 0x10 +#define FFT_PCORE_WINCFG 0x14 + +#define FFT_PCORE_CFG_DEFAULT 0xD5700 +#define FFT_PCORE_CFG_FW_FFT (1 << 8) +#define FFT_PCORE_CFG_INV_FFT (0 << 8) + +#define FFT_PCORE_POSTPROC_EN 0x1 + +#define FFT_PCORE_IRSEL_I(x) ((x) << 2) +#define FFT_PCORE_IRSEL_R(x) ((x) << 0) +#define FFT_PCORE_IRSEL_ZERO 0 +#define FFT_PCORE_IRSEL_CH0 1 +#define FFT_PCORE_IRSEL_CH1 2 + + +#define FFT_PCORE_WINCFG_INC(x) ((x) & 0xFFFF) +#define FFT_PCORE_WINCFG_ENB (1 << 16) + +struct fft_state { + struct device *dev; + struct mutex lock; + struct completion dma_complete; + struct dma_chan *rx_chan; + struct dma_chan *tx_chan; + void __iomem *regs; + int compl_stat; +}; + +struct fft_dma_params { + struct device_node *of_node; + enum dma_transfer_direction direction; + int chan_id; +}; + +struct fft_state *fft_state_glob; + +/* + * IO accessors + */ + +static inline void fft_write(struct fft_state *st, unsigned reg, unsigned val) +{ + iowrite32(val, st->regs + reg); +} + +static inline unsigned int fft_read(struct fft_state *st, unsigned reg) +{ + return ioread32(st->regs + reg); +} + +static bool fft_dma_filter(struct dma_chan *chan, void *param) +{ + struct fft_dma_params *p = param; + + return chan->device->dev->of_node == p->of_node && + chan->chan_id == p->chan_id; +} + +int fft_calculate(dma_addr_t src, dma_addr_t dest, unsigned int size, unsigned irsel) +{ + struct fft_state *st = fft_state_glob; + struct dma_async_tx_descriptor *tx_desc, *rx_desc; + dma_cookie_t tx_cookie, rx_cookie; + unsigned nfft = ilog2(size); + int ret = 0; + + if (st == NULL) + return -ENODEV; + + if (((1 << nfft) != size) || !src || !dest || !irsel) + return -EINVAL; + + switch (irsel) { + case FFT_PCORE_IRSEL_CH0: + case FFT_PCORE_IRSEL_CH1: + irsel = FFT_PCORE_IRSEL_R(irsel); + break; + case FFT_PCORE_IRSEL_CH0 | FFT_PCORE_IRSEL_CH1: + irsel = FFT_PCORE_IRSEL_R(FFT_PCORE_IRSEL_CH0) | + FFT_PCORE_IRSEL_I(FFT_PCORE_IRSEL_CH1); + break; + } + + mutex_lock(&st->lock); + + fft_write(st, FFT_PCORE_WINCFG, 0); + fft_write(st, FFT_PCORE_WINCFG, BIT(16) | (0x10000 >> nfft)); + fft_write(st, FFT_PCORE_POSTPROC, 0);//FFT_PCORE_POSTPROC_EN); + fft_write(st, FFT_PCORE_IRSEL, irsel); + fft_write(st, FFT_PCORE_STAT, 0xFF); + fft_write(st, FFT_PCORE_CFG, FFT_PCORE_CFG_DEFAULT | nfft); + + tx_desc = dmaengine_prep_slave_single(st->tx_chan, src, size * 4, + DMA_TO_DEVICE, 0); + if (!tx_desc) { + dev_err(st->dev, + "Failed to allocate a dma descriptor\n"); + ret = -ENOMEM; + goto error_ret; + } + + tx_cookie = dmaengine_submit(tx_desc); + if (tx_cookie < 0) { + dev_err(st->dev, + "Failed to submit a dma transfer\n"); + ret = tx_cookie; + goto error_ret; + } + + rx_desc = dmaengine_prep_slave_single(st->rx_chan, dest, size * 4, + DMA_FROM_DEVICE, DMA_PREP_INTERRUPT); + if (!rx_desc) { + dev_err(st->dev, + "Failed to allocate a dma descriptor\n"); + ret = -ENOMEM; + goto error_ret; + } + + rx_desc->callback = (dma_async_tx_callback) complete; + rx_desc->callback_param = &st->dma_complete; + + rx_cookie = dmaengine_submit(rx_desc); + if (rx_cookie < 0) { + dev_err(st->dev, + "Failed to submit a dma transfer\n"); + ret = rx_cookie; + goto error_ret; + } + + dma_async_issue_pending(st->tx_chan); + dma_async_issue_pending(st->rx_chan); + + ret = wait_for_completion_interruptible_timeout(&st->dma_complete, + 4 * HZ); + if (ret == 0) { + ret = -ETIMEDOUT; + goto error_ret; + } else if (ret < 0) { + goto error_ret; + } + + ret = 0; + +error_ret: + mutex_unlock(&st->lock); + return ret; +} +EXPORT_SYMBOL_GPL(fft_calculate); + +/** + * fft_of_probe - probe method for the AIM device. + * @of_dev: pointer to OF device structure + * @match: pointer to the structure used for matching a device + * + * This function probes the AIM device in the device tree. + * It initializes the driver data structure and the hardware. + * It returns 0, if the driver is bound to the AIM device, or a negative + * value if there is an error. + */ +static int __devinit fft_of_probe(struct platform_device *op) +{ + struct device *dev = &op->dev; + struct fft_state *st; + struct resource r_mem; /* IO mem resources */ + struct fft_dma_params dma_params; + struct of_phandle_args dma_spec; + dma_cap_mask_t mask; + resource_size_t remap_size, phys_addr; + int ret; + + dev_info(dev, "Device Tree Probing \'%s\'\n", + op->dev.of_node->name); + + st = devm_kzalloc(&op->dev, sizeof(*st), GFP_KERNEL); + if (!st) { + dev_err(dev, "Not enough memory for device\n"); + return -ENOMEM; + } + + st->dev = dev; + dev_set_drvdata(dev, st); + mutex_init(&st->lock); + + /* Get iospace for the device */ + ret = of_address_to_resource(op->dev.of_node, 0, &r_mem); + if (ret) { + dev_err(dev, "invalid address\n"); + return ret; + } + + phys_addr = r_mem.start; + remap_size = resource_size(&r_mem); + if (!request_mem_region(phys_addr, remap_size, KBUILD_MODNAME)) { + dev_err(dev, "Couldn't lock memory region at 0x%08llX\n", + (unsigned long long)phys_addr); + ret = -EBUSY; + goto failed1; + } + + st->regs = ioremap(phys_addr, remap_size); + if (st->regs == NULL) { + dev_err(dev, "Couldn't ioremap memory at 0x%08llX\n", + (unsigned long long)phys_addr); + ret = -EFAULT; + goto failed2; + } + + /* Get dma channel for the device */ + ret = of_parse_phandle_with_args(op->dev.of_node, "dma-request", + "#dma-cells", 0, &dma_spec); + if (ret) { + dev_err(dev, "Couldn't parse dma-request\n"); + goto failed2; + } + + dma_params.of_node = dma_spec.np; + dma_params.chan_id = dma_spec.args[0]; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE | DMA_PRIVATE, mask); + + st->tx_chan = dma_request_channel(mask, fft_dma_filter, &dma_params); + if (!st->tx_chan) { + dev_err(dev, "failed to find tx dma device\n"); + goto failed2; + } + + /* Get dma channel for the device */ + ret = of_parse_phandle_with_args(op->dev.of_node, "dma-request", + "#dma-cells", 1, &dma_spec); + if (ret) { + dev_err(dev, "Couldn't parse dma-request\n"); + goto failed2; + } + + dma_params.of_node = dma_spec.np; + dma_params.chan_id = dma_spec.args[0]; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE | DMA_PRIVATE, mask); + + st->rx_chan = dma_request_channel(mask, fft_dma_filter, &dma_params); + if (!st->rx_chan) { + dev_err(dev, "failed to find rx dma device\n"); + goto failed2; + } + + init_completion(&st->dma_complete); + + dev_info(dev, "ADI-FFT (0x%X) at 0x%08llX mapped to 0x%p," + " DMA-%d, DMA-%d probed\n", + fft_read(st, FFT_PCORE_VERSION), + (unsigned long long)phys_addr, st->regs, + st->rx_chan->chan_id, st->tx_chan->chan_id); + + fft_state_glob = st; + + return 0; + +failed2: + release_mem_region(phys_addr, remap_size); +failed1: + dev_set_drvdata(dev, NULL); + + return ret; +} + +/** + * fft_of_remove - unbinds the driver from the AIM device. + * @of_dev: pointer to OF device structure + * + * This function is called if a device is physically removed from the system or + * if the driver module is being unloaded. It frees any resources allocated to + * the device. + */ +static int __devexit fft_of_remove(struct platform_device *op) +{ + struct device *dev = &op->dev; + struct resource r_mem; /* IO mem resources */ + struct fft_state *st = dev_get_drvdata(dev); + + dma_release_channel(st->rx_chan); + dma_release_channel(st->tx_chan); + + iounmap(st->regs); + + /* Get iospace of the device */ + if (of_address_to_resource(op->dev.of_node, 0, &r_mem)) + dev_err(dev, "invalid address\n"); + else + release_mem_region(r_mem.start, resource_size(&r_mem)); + + dev_set_drvdata(dev, NULL); + fft_state_glob = NULL; + + return 0; +} + +/* Match table for of_platform binding */ +static const struct of_device_id fft_of_match[] __devinitconst = { + { .compatible = "xlnx,cf-fft-core-1.00.a", }, + { .compatible = "xlnx,axi-fft-1.00.a", }, + { /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, fft_of_match); + +static struct platform_driver fft_of_driver = { + .driver = { + .name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .of_match_table = fft_of_match, + }, + .probe = fft_of_probe, + .remove = __devexit_p(fft_of_remove), +}; + +module_platform_driver(fft_of_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices CF FFT"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/cf_fft_core.h b/drivers/iio/adc/cf_fft_core.h new file mode 100644 index 0000000000000..7437dcc2a6f91 --- /dev/null +++ b/drivers/iio/adc/cf_fft_core.h @@ -0,0 +1,17 @@ +/* + * ADI-FFT Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + * + * http://wiki.analog.com/resources/fpga/xilinx/ + */ + +#ifndef ADI_FFT_H_ +#define ADI_FFT_H_ + +int fft_calculate(dma_addr_t src, dma_addr_t dest, + unsigned int size, unsigned irsel); + +#endif /* ADI_FFT_H_ */ diff --git a/drivers/iio/amplifiers/Kconfig b/drivers/iio/amplifiers/Kconfig new file mode 100644 index 0000000000000..05d707ed7d4f9 --- /dev/null +++ b/drivers/iio/amplifiers/Kconfig @@ -0,0 +1,17 @@ +# +# Gain Amplifiers, etc. +# +menu "Amplifiers" + +config AD8366 + tristate "Analog Devices AD8366 VGA" + depends on SPI + select BITREVERSE + help + Say yes here to build support for Analog Devices AD8366 + SPI Dual-Digital Variable Gain Amplifier (VGA). + + To compile this driver as a module, choose M here: the + module will be called ad8366. + +endmenu diff --git a/drivers/iio/amplifiers/Makefile b/drivers/iio/amplifiers/Makefile new file mode 100644 index 0000000000000..a6ca366908e07 --- /dev/null +++ b/drivers/iio/amplifiers/Makefile @@ -0,0 +1,5 @@ +# +# Makefile iio/amplifiers +# + +obj-$(CONFIG_AD8366) += ad8366.o diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c new file mode 100644 index 0000000000000..9dd4114856f40 --- /dev/null +++ b/drivers/iio/amplifiers/ad8366.c @@ -0,0 +1,225 @@ +/* + * AD8366 SPI Dual-Digital Variable Gain Amplifier (VGA) + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +struct ad8366_state { + struct spi_device *spi; + struct regulator *reg; + unsigned char ch[2]; + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + unsigned char data[2] ____cacheline_aligned; +}; + +static int ad8366_write(struct iio_dev *indio_dev, + unsigned char ch_a, char unsigned ch_b) +{ + struct ad8366_state *st = iio_priv(indio_dev); + int ret; + + ch_a = bitrev8(ch_a & 0x3F); + ch_b = bitrev8(ch_b & 0x3F); + + st->data[0] = ch_b >> 4; + st->data[1] = (ch_b << 4) | (ch_a >> 2); + + ret = spi_write(st->spi, st->data, ARRAY_SIZE(st->data)); + if (ret < 0) + dev_err(&indio_dev->dev, "write failed (%d)", ret); + + return ret; +} + +static int ad8366_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad8366_state *st = iio_priv(indio_dev); + int ret; + unsigned code; + + mutex_lock(&indio_dev->mlock); + switch (m) { + case IIO_CHAN_INFO_HARDWAREGAIN: + code = st->ch[chan->channel]; + + /* Values in dB */ + code = code * 253 + 4500; + *val = code / 1000; + *val2 = (code % 1000) * 1000; + + ret = IIO_VAL_INT_PLUS_MICRO_DB; + break; + default: + ret = -EINVAL; + } + mutex_unlock(&indio_dev->mlock); + + return ret; +}; + +static int ad8366_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad8366_state *st = iio_priv(indio_dev); + unsigned code; + int ret; + + if (val < 0 || val2 < 0) + return -EINVAL; + + /* Values in dB */ + code = (((u8)val * 1000) + ((u32)val2 / 1000)); + + if (code > 20500 || code < 4500) + return -EINVAL; + + code = (code - 4500) / 253; + + mutex_lock(&indio_dev->mlock); + switch (mask) { + case IIO_CHAN_INFO_HARDWAREGAIN: + st->ch[chan->channel] = code; + ret = ad8366_write(indio_dev, st->ch[0], st->ch[1]); + break; + default: + ret = -EINVAL; + } + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static const struct iio_info ad8366_info = { + .read_raw = &ad8366_read_raw, + .write_raw = &ad8366_write_raw, + .driver_module = THIS_MODULE, +}; + +#define AD8366_CHAN(_channel) { \ + .type = IIO_VOLTAGE, \ + .output = 1, \ + .indexed = 1, \ + .channel = _channel, \ + .info_mask = IIO_CHAN_INFO_HARDWAREGAIN_SEPARATE_BIT,\ +} + +static const struct iio_chan_spec ad8366_channels[] = { + AD8366_CHAN(0), + AD8366_CHAN(1), +}; + +static int __devinit ad8366_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct ad8366_state *st; + int ret; + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + + st->reg = regulator_get(&spi->dev, "vcc"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) + goto error_put_reg; + } + + spi_set_drvdata(spi, indio_dev); + st->spi = spi; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi->dev.platform_data ? spi->dev.platform_data : + spi_get_device_id(spi)->name; + indio_dev->info = &ad8366_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ad8366_channels; + indio_dev->num_channels = ARRAY_SIZE(ad8366_channels); + + ret = ad8366_write(indio_dev, 0 , 0); + if (ret < 0) + goto error_disable_reg; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_disable_reg; + + return 0; + +error_disable_reg: + if (!IS_ERR(st->reg)) + regulator_disable(st->reg); +error_put_reg: + if (!IS_ERR(st->reg)) + regulator_put(st->reg); + + iio_device_free(indio_dev); + + return ret; +} + +static int __devexit ad8366_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad8366_state *st = iio_priv(indio_dev); + struct regulator *reg = st->reg; + + iio_device_unregister(indio_dev); + + if (!IS_ERR(reg)) { + regulator_disable(reg); + regulator_put(reg); + } + + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id ad8366_id[] = { + {"ad8366", 0}, + {} +}; + +static struct spi_driver ad8366_driver = { + .driver = { + .name = KBUILD_MODNAME, + .owner = THIS_MODULE, + }, + .probe = ad8366_probe, + .remove = __devexit_p(ad8366_remove), + .id_table = ad8366_id, +}; + +module_spi_driver(ad8366_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD8366 VGA"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig new file mode 100644 index 0000000000000..1be15fa9d6182 --- /dev/null +++ b/drivers/iio/dac/Kconfig @@ -0,0 +1,132 @@ +# +# DAC drivers +# +menu "Digital to analog converters" + +config AD5064 + tristate "Analog Devices AD5064 and similar multi-channel DAC driver" + depends on (SPI_MASTER || I2C) + help + Say yes here to build support for Analog Devices AD5024, AD5025, AD5044, + AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5629R, AD5648, AD5666, AD5668, + AD5669R Digital to Analog Converter. + + To compile this driver as a module, choose M here: the + module will be called ad5064. + +config AD5360 + tristate "Analog Devices Analog Devices AD5360/61/62/63/70/71/73 DAC driver" + depends on SPI + help + Say yes here to build support for Analog Devices AD5360, AD5361, + AD5362, AD5363, AD5370, AD5371, AD5373 multi-channel + Digital to Analog Converters (DAC). + + To compile this driver as module choose M here: the module will be called + ad5360. + +config AD5380 + tristate "Analog Devices AD5380/81/82/83/84/90/91/92 DAC driver" + depends on (SPI_MASTER || I2C) + select REGMAP_I2C if I2C + select REGMAP_SPI if SPI_MASTER + help + Say yes here to build support for Analog Devices AD5380, AD5381, + AD5382, AD5383, AD5384, AD5390, AD5391, AD5392 multi-channel + Digital to Analog Converters (DAC). + + To compile this driver as module choose M here: the module will be called + ad5380. + +config AD5421 + tristate "Analog Devices AD5421 DAC driver" + depends on SPI + help + Say yes here to build support for Analog Devices AD5421 loop-powered + digital-to-analog convertors (DAC). + + To compile this driver as module choose M here: the module will be called + ad5421. + +config AD5624R_SPI + tristate "Analog Devices AD5624/44/64R DAC spi driver" + depends on SPI + help + Say yes here to build support for Analog Devices AD5624R, AD5644R and + AD5664R converters (DAC). This driver uses the common SPI interface. + +config AD5446 + tristate "Analog Devices AD5446 and similar single channel DACs driver" + depends on SPI + help + Say yes here to build support for Analog Devices AD5444, AD5446, AD5450, + AD5451, AD5452, AD5453, AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5601, + AD5611, AD5620, AD5621, AD5640, AD5660, AD5662 DACs. + + To compile this driver as a module, choose M here: the + module will be called ad5446. + +config AD5504 + tristate "Analog Devices AD5504/AD5501 DAC SPI driver" + depends on SPI + help + Say yes here to build support for Analog Devices AD5504, AD5501, + High Voltage Digital to Analog Converter. + + To compile this driver as a module, choose M here: the + module will be called ad5504. + +config AD5764 + tristate "Analog Devices AD5764/64R/44/44R DAC driver" + depends on SPI_MASTER + help + Say yes here to build support for Analog Devices AD5764, AD5764R, AD5744, + AD5744R Digital to Analog Converter. + + To compile this driver as a module, choose M here: the + module will be called ad5764. + +config AD5791 + tristate "Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC SPI driver" + depends on SPI + help + Say yes here to build support for Analog Devices AD5760, AD5780, + AD5781, AD5790, AD5791 High Resolution Voltage Output Digital to + Analog Converter. + + To compile this driver as a module, choose M here: the + module will be called ad5791. + +config AD5686 + tristate "Analog Devices AD5686R/AD5685R/AD5684R DAC SPI driver" + depends on SPI + help + Say yes here to build support for Analog Devices AD5686R, AD5685R, + AD5684R, AD5791 Voltage Output Digital to + Analog Converter. + + To compile this driver as a module, choose M here: the + module will be called ad5686. + +config MAX517 + tristate "Maxim MAX517/518/519 DAC driver" + depends on I2C && EXPERIMENTAL + help + If you say yes here you get support for the Maxim chips MAX517, + MAX518 and MAX519 (I2C 8-Bit DACs with rail-to-rail outputs). + + This driver can also be built as a module. If so, the module + will be called max517. + +config MCP4725 + tristate "MCP4725 DAC driver" + depends on I2C + ---help--- + Say Y here if you want to build a driver for the Microchip + MCP 4725 12-bit digital-to-analog converter (DAC) with I2C + interface. + + To compile this driver as a module, choose M here: the module + will be called mcp4725. + +endmenu diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile new file mode 100644 index 0000000000000..9ea3ceeefc074 --- /dev/null +++ b/drivers/iio/dac/Makefile @@ -0,0 +1,16 @@ +# +# Makefile for industrial I/O DAC drivers +# + +obj-$(CONFIG_AD5360) += ad5360.o +obj-$(CONFIG_AD5380) += ad5380.o +obj-$(CONFIG_AD5421) += ad5421.o +obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o +obj-$(CONFIG_AD5064) += ad5064.o +obj-$(CONFIG_AD5504) += ad5504.o +obj-$(CONFIG_AD5446) += ad5446.o +obj-$(CONFIG_AD5764) += ad5764.o +obj-$(CONFIG_AD5791) += ad5791.o +obj-$(CONFIG_AD5686) += ad5686.o +obj-$(CONFIG_MAX517) += max517.o +obj-$(CONFIG_MCP4725) += mcp4725.o diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c new file mode 100644 index 0000000000000..aa739c497f2bc --- /dev/null +++ b/drivers/iio/dac/ad5064.c @@ -0,0 +1,676 @@ +/* + * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5629R, + * AD5648, AD5666, AD5668, AD5669R Digital to analog converters driver + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define AD5064_MAX_DAC_CHANNELS 8 +#define AD5064_MAX_VREFS 4 + +#define AD5064_ADDR(x) ((x) << 20) +#define AD5064_CMD(x) ((x) << 24) + +#define AD5064_ADDR_DAC(chan) (chan) +#define AD5064_ADDR_ALL_DAC 0xF + +#define AD5064_CMD_WRITE_INPUT_N 0x0 +#define AD5064_CMD_UPDATE_DAC_N 0x1 +#define AD5064_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 +#define AD5064_CMD_WRITE_INPUT_N_UPDATE_N 0x3 +#define AD5064_CMD_POWERDOWN_DAC 0x4 +#define AD5064_CMD_CLEAR 0x5 +#define AD5064_CMD_LDAC_MASK 0x6 +#define AD5064_CMD_RESET 0x7 +#define AD5064_CMD_CONFIG 0x8 + +#define AD5064_CONFIG_DAISY_CHAIN_ENABLE BIT(1) +#define AD5064_CONFIG_INT_VREF_ENABLE BIT(0) + +#define AD5064_LDAC_PWRDN_NONE 0x0 +#define AD5064_LDAC_PWRDN_1K 0x1 +#define AD5064_LDAC_PWRDN_100K 0x2 +#define AD5064_LDAC_PWRDN_3STATE 0x3 + +/** + * struct ad5064_chip_info - chip specific information + * @shared_vref: whether the vref supply is shared between channels + * @internal_vref: internal reference voltage. 0 if the chip has no internal + * vref. + * @channel: channel specification + * @num_channels: number of channels + */ + +struct ad5064_chip_info { + bool shared_vref; + unsigned long internal_vref; + const struct iio_chan_spec *channels; + unsigned int num_channels; +}; + +struct ad5064_state; + +typedef int (*ad5064_write_func)(struct ad5064_state *st, unsigned int cmd, + unsigned int addr, unsigned int val); + +/** + * struct ad5064_state - driver instance specific data + * @dev: the device for this driver instance + * @chip_info: chip model specific constants, available modes etc + * @vref_reg: vref supply regulators + * @pwr_down: whether channel is powered down + * @pwr_down_mode: channel's current power down mode + * @dac_cache: current DAC raw value (chip does not support readback) + * @use_internal_vref: set to true if the internal reference voltage should be + * used. + * @write: register write callback + * @data: i2c/spi transfer buffers + */ + +struct ad5064_state { + struct device *dev; + const struct ad5064_chip_info *chip_info; + struct regulator_bulk_data vref_reg[AD5064_MAX_VREFS]; + bool pwr_down[AD5064_MAX_DAC_CHANNELS]; + u8 pwr_down_mode[AD5064_MAX_DAC_CHANNELS]; + unsigned int dac_cache[AD5064_MAX_DAC_CHANNELS]; + bool use_internal_vref; + + ad5064_write_func write; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + union { + u8 i2c[3]; + __be32 spi; + } data ____cacheline_aligned; +}; + +enum ad5064_type { + ID_AD5024, + ID_AD5025, + ID_AD5044, + ID_AD5045, + ID_AD5064, + ID_AD5064_1, + ID_AD5065, + ID_AD5628_1, + ID_AD5628_2, + ID_AD5648_1, + ID_AD5648_2, + ID_AD5666_1, + ID_AD5666_2, + ID_AD5668_1, + ID_AD5668_2, +}; + +static int ad5064_i2c_write(struct ad5064_state *st, unsigned int cmd, + unsigned int addr, unsigned int val) +{ + struct i2c_client *i2c = to_i2c_client(st->dev); + + st->data.i2c[0] = (cmd << 4) | addr; + put_unaligned_be16(val, &st->data.i2c[1]); + return i2c_master_send(i2c, st->data.i2c, 3); +} + +static int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd, + unsigned int addr, unsigned int val) +{ + struct spi_device *spi = to_spi_device(st->dev); + + st->data.spi = cpu_to_be32(AD5064_CMD(cmd) | AD5064_ADDR(addr) | val); + return spi_write(spi, &st->data.spi, sizeof(st->data.spi)); +} + +static int ad5064_write(struct ad5064_state *st, unsigned int cmd, + unsigned int addr, unsigned int val, unsigned int shift) +{ + val <<= shift; + + return st->write(st, cmd, addr, val); +} + +static int ad5064_sync_powerdown_mode(struct ad5064_state *st, + unsigned int channel) +{ + unsigned int val; + int ret; + + val = (0x1 << channel); + + if (st->pwr_down[channel]) + val |= st->pwr_down_mode[channel] << 8; + + ret = ad5064_write(st, AD5064_CMD_POWERDOWN_DAC, 0, val, 0); + + return ret; +} + +static const char * const ad5064_powerdown_modes[] = { + "1kohm_to_gnd", + "100kohm_to_gnd", + "three_state", +}; + +static int ad5064_get_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct ad5064_state *st = iio_priv(indio_dev); + + return st->pwr_down_mode[chan->channel] - 1; +} + +static int ad5064_set_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int mode) +{ + struct ad5064_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&indio_dev->mlock); + st->pwr_down_mode[chan->channel] = mode + 1; + + ret = ad5064_sync_powerdown_mode(st, chan->channel); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static const struct iio_enum ad5064_powerdown_mode_enum = { + .items = ad5064_powerdown_modes, + .num_items = ARRAY_SIZE(ad5064_powerdown_modes), + .get = ad5064_get_powerdown_mode, + .set = ad5064_set_powerdown_mode, +}; + +static ssize_t ad5064_read_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, char *buf) +{ + struct ad5064_state *st = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", st->pwr_down[chan->channel]); +} + +static ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, + size_t len) +{ + struct ad5064_state *st = iio_priv(indio_dev); + bool pwr_down; + int ret; + + ret = strtobool(buf, &pwr_down); + if (ret) + return ret; + + mutex_lock(&indio_dev->mlock); + st->pwr_down[chan->channel] = pwr_down; + + ret = ad5064_sync_powerdown_mode(st, chan->channel); + mutex_unlock(&indio_dev->mlock); + return ret ? ret : len; +} + +static int ad5064_get_vref(struct ad5064_state *st, + struct iio_chan_spec const *chan) +{ + unsigned int i; + + if (st->use_internal_vref) + return st->chip_info->internal_vref; + + i = st->chip_info->shared_vref ? 0 : chan->channel; + return regulator_get_voltage(st->vref_reg[i].consumer); +} + +static int ad5064_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad5064_state *st = iio_priv(indio_dev); + int scale_uv; + + switch (m) { + case IIO_CHAN_INFO_RAW: + *val = st->dac_cache[chan->channel]; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + scale_uv = ad5064_get_vref(st, chan); + if (scale_uv < 0) + return scale_uv; + + scale_uv = (scale_uv * 100) >> chan->scan_type.realbits; + *val = scale_uv / 100000; + *val2 = (scale_uv % 100000) * 10; + return IIO_VAL_INT_PLUS_MICRO; + default: + break; + } + return -EINVAL; +} + +static int ad5064_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long mask) +{ + struct ad5064_state *st = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val > (1 << chan->scan_type.realbits) || val < 0) + return -EINVAL; + + mutex_lock(&indio_dev->mlock); + ret = ad5064_write(st, AD5064_CMD_WRITE_INPUT_N_UPDATE_N, + chan->address, val, chan->scan_type.shift); + if (ret == 0) + st->dac_cache[chan->channel] = val; + mutex_unlock(&indio_dev->mlock); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static const struct iio_info ad5064_info = { + .read_raw = ad5064_read_raw, + .write_raw = ad5064_write_raw, + .driver_module = THIS_MODULE, +}; + +static const struct iio_chan_spec_ext_info ad5064_ext_info[] = { + { + .name = "powerdown", + .read = ad5064_read_dac_powerdown, + .write = ad5064_write_dac_powerdown, + }, + IIO_ENUM("powerdown_mode", false, &ad5064_powerdown_mode_enum), + IIO_ENUM_AVAILABLE("powerdown_mode", &ad5064_powerdown_mode_enum), + { }, +}; + +#define AD5064_CHANNEL(chan, bits) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (chan), \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ + .address = AD5064_ADDR_DAC(chan), \ + .scan_type = IIO_ST('u', (bits), 16, 20 - (bits)), \ + .ext_info = ad5064_ext_info, \ +} + +#define DECLARE_AD5064_CHANNELS(name, bits) \ +const struct iio_chan_spec name[] = { \ + AD5064_CHANNEL(0, bits), \ + AD5064_CHANNEL(1, bits), \ + AD5064_CHANNEL(2, bits), \ + AD5064_CHANNEL(3, bits), \ + AD5064_CHANNEL(4, bits), \ + AD5064_CHANNEL(5, bits), \ + AD5064_CHANNEL(6, bits), \ + AD5064_CHANNEL(7, bits), \ +} + +static DECLARE_AD5064_CHANNELS(ad5024_channels, 12); +static DECLARE_AD5064_CHANNELS(ad5044_channels, 14); +static DECLARE_AD5064_CHANNELS(ad5064_channels, 16); + +static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { + [ID_AD5024] = { + .shared_vref = false, + .channels = ad5024_channels, + .num_channels = 4, + }, + [ID_AD5025] = { + .shared_vref = false, + .channels = ad5024_channels, + .num_channels = 2, + }, + [ID_AD5044] = { + .shared_vref = false, + .channels = ad5044_channels, + .num_channels = 4, + }, + [ID_AD5045] = { + .shared_vref = false, + .channels = ad5044_channels, + .num_channels = 2, + }, + [ID_AD5064] = { + .shared_vref = false, + .channels = ad5064_channels, + .num_channels = 4, + }, + [ID_AD5064_1] = { + .shared_vref = true, + .channels = ad5064_channels, + .num_channels = 4, + }, + [ID_AD5065] = { + .shared_vref = false, + .channels = ad5064_channels, + .num_channels = 2, + }, + [ID_AD5628_1] = { + .shared_vref = true, + .internal_vref = 2500000, + .channels = ad5024_channels, + .num_channels = 8, + }, + [ID_AD5628_2] = { + .shared_vref = true, + .internal_vref = 5000000, + .channels = ad5024_channels, + .num_channels = 8, + }, + [ID_AD5648_1] = { + .shared_vref = true, + .internal_vref = 2500000, + .channels = ad5044_channels, + .num_channels = 8, + }, + [ID_AD5648_2] = { + .shared_vref = true, + .internal_vref = 5000000, + .channels = ad5044_channels, + .num_channels = 8, + }, + [ID_AD5666_1] = { + .shared_vref = true, + .internal_vref = 2500000, + .channels = ad5064_channels, + .num_channels = 4, + }, + [ID_AD5666_2] = { + .shared_vref = true, + .internal_vref = 5000000, + .channels = ad5064_channels, + .num_channels = 4, + }, + [ID_AD5668_1] = { + .shared_vref = true, + .internal_vref = 2500000, + .channels = ad5064_channels, + .num_channels = 8, + }, + [ID_AD5668_2] = { + .shared_vref = true, + .internal_vref = 5000000, + .channels = ad5064_channels, + .num_channels = 8, + }, +}; + +static inline unsigned int ad5064_num_vref(struct ad5064_state *st) +{ + return st->chip_info->shared_vref ? 1 : st->chip_info->num_channels; +} + +static const char * const ad5064_vref_names[] = { + "vrefA", + "vrefB", + "vrefC", + "vrefD", +}; + +static const char * const ad5064_vref_name(struct ad5064_state *st, + unsigned int vref) +{ + return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref]; +} + +static int __devinit ad5064_probe(struct device *dev, enum ad5064_type type, + const char *name, ad5064_write_func write) +{ + struct iio_dev *indio_dev; + struct ad5064_state *st; + unsigned int i; + int ret; + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + dev_set_drvdata(dev, indio_dev); + + st->chip_info = &ad5064_chip_info_tbl[type]; + st->dev = dev; + st->write = write; + + for (i = 0; i < ad5064_num_vref(st); ++i) + st->vref_reg[i].supply = ad5064_vref_name(st, i); + + ret = regulator_bulk_get(dev, ad5064_num_vref(st), + st->vref_reg); + if (ret) { + if (!st->chip_info->internal_vref) + goto error_free; + st->use_internal_vref = true; + ret = ad5064_write(st, AD5064_CMD_CONFIG, 0, + AD5064_CONFIG_INT_VREF_ENABLE, 0); + if (ret) { + dev_err(dev, "Failed to enable internal vref: %d\n", + ret); + goto error_free; + } + } else { + ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg); + if (ret) + goto error_free_reg; + } + + for (i = 0; i < st->chip_info->num_channels; ++i) { + st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K; + st->dac_cache[i] = 0x8000; + } + + indio_dev->dev.parent = dev; + indio_dev->name = name; + indio_dev->info = &ad5064_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = st->chip_info->num_channels; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_disable_reg; + + return 0; + +error_disable_reg: + if (!st->use_internal_vref) + regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); +error_free_reg: + if (!st->use_internal_vref) + regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); +error_free: + iio_device_free(indio_dev); + + return ret; +} + +static int __devexit ad5064_remove(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad5064_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + if (!st->use_internal_vref) { + regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); + regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); + } + + iio_device_free(indio_dev); + + return 0; +} + +#if IS_ENABLED(CONFIG_SPI_MASTER) + +static int __devinit ad5064_spi_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + + return ad5064_probe(&spi->dev, id->driver_data, id->name, + ad5064_spi_write); +} + +static int __devexit ad5064_spi_remove(struct spi_device *spi) +{ + return ad5064_remove(&spi->dev); +} + +static const struct spi_device_id ad5064_spi_ids[] = { + {"ad5024", ID_AD5024}, + {"ad5025", ID_AD5025}, + {"ad5044", ID_AD5044}, + {"ad5045", ID_AD5045}, + {"ad5064", ID_AD5064}, + {"ad5064-1", ID_AD5064_1}, + {"ad5065", ID_AD5065}, + {"ad5628-1", ID_AD5628_1}, + {"ad5628-2", ID_AD5628_2}, + {"ad5648-1", ID_AD5648_1}, + {"ad5648-2", ID_AD5648_2}, + {"ad5666-1", ID_AD5666_1}, + {"ad5666-2", ID_AD5666_2}, + {"ad5668-1", ID_AD5668_1}, + {"ad5668-2", ID_AD5668_2}, + {"ad5668-3", ID_AD5668_2}, /* similar enough to ad5668-2 */ + {} +}; +MODULE_DEVICE_TABLE(spi, ad5064_spi_ids); + +static struct spi_driver ad5064_spi_driver = { + .driver = { + .name = "ad5064", + .owner = THIS_MODULE, + }, + .probe = ad5064_spi_probe, + .remove = __devexit_p(ad5064_spi_remove), + .id_table = ad5064_spi_ids, +}; + +static int __init ad5064_spi_register_driver(void) +{ + return spi_register_driver(&ad5064_spi_driver); +} + +static void __exit ad5064_spi_unregister_driver(void) +{ + spi_unregister_driver(&ad5064_spi_driver); +} + +#else + +static inline int ad5064_spi_register_driver(void) { return 0; } +static inline void ad5064_spi_unregister_driver(void) { } + +#endif + +#if IS_ENABLED(CONFIG_I2C) + +static int __devinit ad5064_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + return ad5064_probe(&i2c->dev, id->driver_data, id->name, + ad5064_i2c_write); +} + +static int __devexit ad5064_i2c_remove(struct i2c_client *i2c) +{ + return ad5064_remove(&i2c->dev); +} + +static const struct i2c_device_id ad5064_i2c_ids[] = { + {"ad5629-1", ID_AD5628_1}, + {"ad5629-2", ID_AD5628_2}, + {"ad5629-3", ID_AD5628_2}, /* similar enough to ad5629-2 */ + {"ad5669-1", ID_AD5668_1}, + {"ad5669-2", ID_AD5668_2}, + {"ad5669-3", ID_AD5668_2}, /* similar enough to ad5669-2 */ + {} +}; +MODULE_DEVICE_TABLE(i2c, ad5064_i2c_ids); + +static struct i2c_driver ad5064_i2c_driver = { + .driver = { + .name = "ad5064", + .owner = THIS_MODULE, + }, + .probe = ad5064_i2c_probe, + .remove = __devexit_p(ad5064_i2c_remove), + .id_table = ad5064_i2c_ids, +}; + +static int __init ad5064_i2c_register_driver(void) +{ + return i2c_add_driver(&ad5064_i2c_driver); +} + +static void __exit ad5064_i2c_unregister_driver(void) +{ + i2c_del_driver(&ad5064_i2c_driver); +} + +#else + +static inline int ad5064_i2c_register_driver(void) { return 0; } +static inline void ad5064_i2c_unregister_driver(void) { } + +#endif + +static int __init ad5064_init(void) +{ + int ret; + + ret = ad5064_spi_register_driver(); + if (ret) + return ret; + + ret = ad5064_i2c_register_driver(); + if (ret) { + ad5064_spi_unregister_driver(); + return ret; + } + + return 0; +} +module_init(ad5064_init); + +static void __exit ad5064_exit(void) +{ + ad5064_i2c_unregister_driver(); + ad5064_spi_unregister_driver(); +} +module_exit(ad5064_exit); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("Analog Devices AD5024 and similar multi-channel DACs"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c new file mode 100644 index 0000000000000..8fce84fe70b1e --- /dev/null +++ b/drivers/iio/dac/ad5360.c @@ -0,0 +1,570 @@ +/* + * Analog devices AD5360, AD5361, AD5362, AD5363, AD5370, AD5371, AD5373 + * multi-channel Digital to Analog Converters driver + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define AD5360_CMD(x) ((x) << 22) +#define AD5360_ADDR(x) ((x) << 16) + +#define AD5360_READBACK_TYPE(x) ((x) << 13) +#define AD5360_READBACK_ADDR(x) ((x) << 7) + +#define AD5360_CHAN_ADDR(chan) ((chan) + 0x8) + +#define AD5360_CMD_WRITE_DATA 0x3 +#define AD5360_CMD_WRITE_OFFSET 0x2 +#define AD5360_CMD_WRITE_GAIN 0x1 +#define AD5360_CMD_SPECIAL_FUNCTION 0x0 + +/* Special function register addresses */ +#define AD5360_REG_SF_NOP 0x0 +#define AD5360_REG_SF_CTRL 0x1 +#define AD5360_REG_SF_OFS(x) (0x2 + (x)) +#define AD5360_REG_SF_READBACK 0x5 + +#define AD5360_SF_CTRL_PWR_DOWN BIT(0) + +#define AD5360_READBACK_X1A 0x0 +#define AD5360_READBACK_X1B 0x1 +#define AD5360_READBACK_OFFSET 0x2 +#define AD5360_READBACK_GAIN 0x3 +#define AD5360_READBACK_SF 0x4 + + +/** + * struct ad5360_chip_info - chip specific information + * @channel_template: channel specification template + * @num_channels: number of channels + * @channels_per_group: number of channels per group + * @num_vrefs: number of vref supplies for the chip +*/ + +struct ad5360_chip_info { + struct iio_chan_spec channel_template; + unsigned int num_channels; + unsigned int channels_per_group; + unsigned int num_vrefs; +}; + +/** + * struct ad5360_state - driver instance specific data + * @spi: spi_device + * @chip_info: chip model specific constants, available modes etc + * @vref_reg: vref supply regulators + * @ctrl: control register cache + * @data: spi transfer buffers + */ + +struct ad5360_state { + struct spi_device *spi; + const struct ad5360_chip_info *chip_info; + struct regulator_bulk_data vref_reg[3]; + unsigned int ctrl; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + union { + __be32 d32; + u8 d8[4]; + } data[2] ____cacheline_aligned; +}; + +enum ad5360_type { + ID_AD5360, + ID_AD5361, + ID_AD5362, + ID_AD5363, + ID_AD5370, + ID_AD5371, + ID_AD5372, + ID_AD5373, +}; + +#define AD5360_CHANNEL(bits) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \ + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \ + IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \ + .scan_type = IIO_ST('u', (bits), 16, 16 - (bits)) \ +} + +static const struct ad5360_chip_info ad5360_chip_info_tbl[] = { + [ID_AD5360] = { + .channel_template = AD5360_CHANNEL(16), + .num_channels = 16, + .channels_per_group = 8, + .num_vrefs = 2, + }, + [ID_AD5361] = { + .channel_template = AD5360_CHANNEL(14), + .num_channels = 16, + .channels_per_group = 8, + .num_vrefs = 2, + }, + [ID_AD5362] = { + .channel_template = AD5360_CHANNEL(16), + .num_channels = 8, + .channels_per_group = 4, + .num_vrefs = 2, + }, + [ID_AD5363] = { + .channel_template = AD5360_CHANNEL(14), + .num_channels = 8, + .channels_per_group = 4, + .num_vrefs = 2, + }, + [ID_AD5370] = { + .channel_template = AD5360_CHANNEL(16), + .num_channels = 40, + .channels_per_group = 8, + .num_vrefs = 2, + }, + [ID_AD5371] = { + .channel_template = AD5360_CHANNEL(14), + .num_channels = 40, + .channels_per_group = 8, + .num_vrefs = 3, + }, + [ID_AD5372] = { + .channel_template = AD5360_CHANNEL(16), + .num_channels = 32, + .channels_per_group = 8, + .num_vrefs = 2, + }, + [ID_AD5373] = { + .channel_template = AD5360_CHANNEL(14), + .num_channels = 32, + .channels_per_group = 8, + .num_vrefs = 2, + }, +}; + +static unsigned int ad5360_get_channel_vref_index(struct ad5360_state *st, + unsigned int channel) +{ + unsigned int i; + + /* The first groups have their own vref, while the remaining groups + * share the last vref */ + i = channel / st->chip_info->channels_per_group; + if (i >= st->chip_info->num_vrefs) + i = st->chip_info->num_vrefs - 1; + + return i; +} + +static int ad5360_get_channel_vref(struct ad5360_state *st, + unsigned int channel) +{ + unsigned int i = ad5360_get_channel_vref_index(st, channel); + + return regulator_get_voltage(st->vref_reg[i].consumer); +} + + +static int ad5360_write_unlocked(struct iio_dev *indio_dev, + unsigned int cmd, unsigned int addr, unsigned int val, + unsigned int shift) +{ + struct ad5360_state *st = iio_priv(indio_dev); + + val <<= shift; + val |= AD5360_CMD(cmd) | AD5360_ADDR(addr); + st->data[0].d32 = cpu_to_be32(val); + + return spi_write(st->spi, &st->data[0].d8[1], 3); +} + +static int ad5360_write(struct iio_dev *indio_dev, unsigned int cmd, + unsigned int addr, unsigned int val, unsigned int shift) +{ + int ret; + + mutex_lock(&indio_dev->mlock); + ret = ad5360_write_unlocked(indio_dev, cmd, addr, val, shift); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int ad5360_read(struct iio_dev *indio_dev, unsigned int type, + unsigned int addr) +{ + struct ad5360_state *st = iio_priv(indio_dev); + struct spi_message m; + int ret; + struct spi_transfer t[] = { + { + .tx_buf = &st->data[0].d8[1], + .len = 3, + .cs_change = 1, + }, { + .rx_buf = &st->data[1].d8[1], + .len = 3, + }, + }; + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + mutex_lock(&indio_dev->mlock); + + st->data[0].d32 = cpu_to_be32(AD5360_CMD(AD5360_CMD_SPECIAL_FUNCTION) | + AD5360_ADDR(AD5360_REG_SF_READBACK) | + AD5360_READBACK_TYPE(type) | + AD5360_READBACK_ADDR(addr)); + + ret = spi_sync(st->spi, &m); + if (ret >= 0) + ret = be32_to_cpu(st->data[1].d32) & 0xffff; + + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static ssize_t ad5360_read_dac_powerdown(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad5360_state *st = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", (bool)(st->ctrl & AD5360_SF_CTRL_PWR_DOWN)); +} + +static int ad5360_update_ctrl(struct iio_dev *indio_dev, unsigned int set, + unsigned int clr) +{ + struct ad5360_state *st = iio_priv(indio_dev); + unsigned int ret; + + mutex_lock(&indio_dev->mlock); + + st->ctrl |= set; + st->ctrl &= ~clr; + + ret = ad5360_write_unlocked(indio_dev, AD5360_CMD_SPECIAL_FUNCTION, + AD5360_REG_SF_CTRL, st->ctrl, 0); + + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static ssize_t ad5360_write_dac_powerdown(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + bool pwr_down; + int ret; + + ret = strtobool(buf, &pwr_down); + if (ret) + return ret; + + if (pwr_down) + ret = ad5360_update_ctrl(indio_dev, AD5360_SF_CTRL_PWR_DOWN, 0); + else + ret = ad5360_update_ctrl(indio_dev, 0, AD5360_SF_CTRL_PWR_DOWN); + + return ret ? ret : len; +} + +static IIO_DEVICE_ATTR(out_voltage_powerdown, + S_IRUGO | S_IWUSR, + ad5360_read_dac_powerdown, + ad5360_write_dac_powerdown, 0); + +static struct attribute *ad5360_attributes[] = { + &iio_dev_attr_out_voltage_powerdown.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad5360_attribute_group = { + .attrs = ad5360_attributes, +}; + +static int ad5360_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad5360_state *st = iio_priv(indio_dev); + int max_val = (1 << chan->scan_type.realbits); + unsigned int ofs_index; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val >= max_val || val < 0) + return -EINVAL; + + return ad5360_write(indio_dev, AD5360_CMD_WRITE_DATA, + chan->address, val, chan->scan_type.shift); + + case IIO_CHAN_INFO_CALIBBIAS: + if (val >= max_val || val < 0) + return -EINVAL; + + return ad5360_write(indio_dev, AD5360_CMD_WRITE_OFFSET, + chan->address, val, chan->scan_type.shift); + + case IIO_CHAN_INFO_CALIBSCALE: + if (val >= max_val || val < 0) + return -EINVAL; + + return ad5360_write(indio_dev, AD5360_CMD_WRITE_GAIN, + chan->address, val, chan->scan_type.shift); + + case IIO_CHAN_INFO_OFFSET: + if (val <= -max_val || val > 0) + return -EINVAL; + + val = -val; + + /* offset is supposed to have the same scale as raw, but it + * is always 14bits wide, so on a chip where the raw value has + * more bits, we need to shift offset. */ + val >>= (chan->scan_type.realbits - 14); + + /* There is one DAC offset register per vref. Changing one + * channels offset will also change the offset for all other + * channels which share the same vref supply. */ + ofs_index = ad5360_get_channel_vref_index(st, chan->channel); + return ad5360_write(indio_dev, AD5360_CMD_SPECIAL_FUNCTION, + AD5360_REG_SF_OFS(ofs_index), val, 0); + default: + break; + } + + return -EINVAL; +} + +static int ad5360_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad5360_state *st = iio_priv(indio_dev); + unsigned int ofs_index; + int scale_uv; + int ret; + + switch (m) { + case IIO_CHAN_INFO_RAW: + ret = ad5360_read(indio_dev, AD5360_READBACK_X1A, + chan->address); + if (ret < 0) + return ret; + *val = ret >> chan->scan_type.shift; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + /* vout = 4 * vref * dac_code */ + scale_uv = ad5360_get_channel_vref(st, chan->channel) * 4 * 100; + if (scale_uv < 0) + return scale_uv; + + scale_uv >>= (chan->scan_type.realbits); + *val = scale_uv / 100000; + *val2 = (scale_uv % 100000) * 10; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_CALIBBIAS: + ret = ad5360_read(indio_dev, AD5360_READBACK_OFFSET, + chan->address); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_CALIBSCALE: + ret = ad5360_read(indio_dev, AD5360_READBACK_GAIN, + chan->address); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_OFFSET: + ofs_index = ad5360_get_channel_vref_index(st, chan->channel); + ret = ad5360_read(indio_dev, AD5360_READBACK_SF, + AD5360_REG_SF_OFS(ofs_index)); + if (ret < 0) + return ret; + + ret <<= (chan->scan_type.realbits - 14); + *val = -ret; + return IIO_VAL_INT; + } + + return -EINVAL; +} + +static const struct iio_info ad5360_info = { + .read_raw = ad5360_read_raw, + .write_raw = ad5360_write_raw, + .attrs = &ad5360_attribute_group, + .driver_module = THIS_MODULE, +}; + +static const char * const ad5360_vref_name[] = { + "vref0", "vref1", "vref2" +}; + +static int __devinit ad5360_alloc_channels(struct iio_dev *indio_dev) +{ + struct ad5360_state *st = iio_priv(indio_dev); + struct iio_chan_spec *channels; + unsigned int i; + + channels = kcalloc(st->chip_info->num_channels, + sizeof(struct iio_chan_spec), GFP_KERNEL); + + if (!channels) + return -ENOMEM; + + for (i = 0; i < st->chip_info->num_channels; ++i) { + channels[i] = st->chip_info->channel_template; + channels[i].channel = i; + channels[i].address = AD5360_CHAN_ADDR(i); + } + + indio_dev->channels = channels; + + return 0; +} + +static int __devinit ad5360_probe(struct spi_device *spi) +{ + enum ad5360_type type = spi_get_device_id(spi)->driver_data; + struct iio_dev *indio_dev; + struct ad5360_state *st; + unsigned int i; + int ret; + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) { + dev_err(&spi->dev, "Failed to allocate iio device\n"); + return -ENOMEM; + } + + st = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + + st->chip_info = &ad5360_chip_info_tbl[type]; + st->spi = spi; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->info = &ad5360_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->num_channels = st->chip_info->num_channels; + + ret = ad5360_alloc_channels(indio_dev); + if (ret) { + dev_err(&spi->dev, "Failed to allocate channel spec: %d\n", ret); + goto error_free; + } + + for (i = 0; i < st->chip_info->num_vrefs; ++i) + st->vref_reg[i].supply = ad5360_vref_name[i]; + + ret = regulator_bulk_get(&st->spi->dev, st->chip_info->num_vrefs, + st->vref_reg); + if (ret) { + dev_err(&spi->dev, "Failed to request vref regulators: %d\n", ret); + goto error_free_channels; + } + + ret = regulator_bulk_enable(st->chip_info->num_vrefs, st->vref_reg); + if (ret) { + dev_err(&spi->dev, "Failed to enable vref regulators: %d\n", ret); + goto error_free_reg; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&spi->dev, "Failed to register iio device: %d\n", ret); + goto error_disable_reg; + } + + return 0; + +error_disable_reg: + regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg); +error_free_reg: + regulator_bulk_free(st->chip_info->num_vrefs, st->vref_reg); +error_free_channels: + kfree(indio_dev->channels); +error_free: + iio_device_free(indio_dev); + + return ret; +} + +static int __devexit ad5360_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad5360_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + kfree(indio_dev->channels); + + regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg); + regulator_bulk_free(st->chip_info->num_vrefs, st->vref_reg); + + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id ad5360_ids[] = { + { "ad5360", ID_AD5360 }, + { "ad5361", ID_AD5361 }, + { "ad5362", ID_AD5362 }, + { "ad5363", ID_AD5363 }, + { "ad5370", ID_AD5370 }, + { "ad5371", ID_AD5371 }, + { "ad5372", ID_AD5372 }, + { "ad5373", ID_AD5373 }, + {} +}; +MODULE_DEVICE_TABLE(spi, ad5360_ids); + +static struct spi_driver ad5360_driver = { + .driver = { + .name = "ad5360", + .owner = THIS_MODULE, + }, + .probe = ad5360_probe, + .remove = __devexit_p(ad5360_remove), + .id_table = ad5360_ids, +}; +module_spi_driver(ad5360_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("Analog Devices AD5360/61/62/63/70/71/72/73 DAC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c new file mode 100644 index 0000000000000..14991ac55f268 --- /dev/null +++ b/drivers/iio/dac/ad5380.c @@ -0,0 +1,655 @@ +/* + * Analog devices AD5380, AD5381, AD5382, AD5383, AD5390, AD5391, AD5392 + * multi-channel Digital to Analog Converters driver + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define AD5380_REG_DATA(x) (((x) << 2) | 3) +#define AD5380_REG_OFFSET(x) (((x) << 2) | 2) +#define AD5380_REG_GAIN(x) (((x) << 2) | 1) +#define AD5380_REG_SF_PWR_DOWN (8 << 2) +#define AD5380_REG_SF_PWR_UP (9 << 2) +#define AD5380_REG_SF_CTRL (12 << 2) + +#define AD5380_CTRL_PWR_DOWN_MODE_OFFSET 13 +#define AD5380_CTRL_INT_VREF_2V5 BIT(12) +#define AD5380_CTRL_INT_VREF_EN BIT(10) + +/** + * struct ad5380_chip_info - chip specific information + * @channel_template: channel specification template + * @num_channels: number of channels + * @int_vref: internal vref in uV +*/ + +struct ad5380_chip_info { + struct iio_chan_spec channel_template; + unsigned int num_channels; + unsigned int int_vref; +}; + +/** + * struct ad5380_state - driver instance specific data + * @regmap: regmap instance used by the device + * @chip_info: chip model specific constants, available modes etc + * @vref_reg: vref supply regulator + * @vref: actual reference voltage used in uA + * @pwr_down: whether the chip is currently in power down mode + */ + +struct ad5380_state { + struct regmap *regmap; + const struct ad5380_chip_info *chip_info; + struct regulator *vref_reg; + int vref; + bool pwr_down; +}; + +enum ad5380_type { + ID_AD5380_3, + ID_AD5380_5, + ID_AD5381_3, + ID_AD5381_5, + ID_AD5382_3, + ID_AD5382_5, + ID_AD5383_3, + ID_AD5383_5, + ID_AD5390_3, + ID_AD5390_5, + ID_AD5391_3, + ID_AD5391_5, + ID_AD5392_3, + ID_AD5392_5, +}; + +static ssize_t ad5380_read_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, char *buf) +{ + struct ad5380_state *st = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", st->pwr_down); +} + +static ssize_t ad5380_write_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, + size_t len) +{ + struct ad5380_state *st = iio_priv(indio_dev); + bool pwr_down; + int ret; + + ret = strtobool(buf, &pwr_down); + if (ret) + return ret; + + mutex_lock(&indio_dev->mlock); + + if (pwr_down) + ret = regmap_write(st->regmap, AD5380_REG_SF_PWR_DOWN, 0); + else + ret = regmap_write(st->regmap, AD5380_REG_SF_PWR_UP, 0); + + st->pwr_down = pwr_down; + + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static const char * const ad5380_powerdown_modes[] = { + "100kohm_to_gnd", + "three_state", +}; + +static int ad5380_get_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct ad5380_state *st = iio_priv(indio_dev); + unsigned int mode; + int ret; + + ret = regmap_read(st->regmap, AD5380_REG_SF_CTRL, &mode); + if (ret) + return ret; + + mode = (mode >> AD5380_CTRL_PWR_DOWN_MODE_OFFSET) & 1; + + return mode; +} + +static int ad5380_set_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int mode) +{ + struct ad5380_state *st = iio_priv(indio_dev); + int ret; + + ret = regmap_update_bits(st->regmap, AD5380_REG_SF_CTRL, + 1 << AD5380_CTRL_PWR_DOWN_MODE_OFFSET, + mode << AD5380_CTRL_PWR_DOWN_MODE_OFFSET); + + return ret; +} + +static const struct iio_enum ad5380_powerdown_mode_enum = { + .items = ad5380_powerdown_modes, + .num_items = ARRAY_SIZE(ad5380_powerdown_modes), + .get = ad5380_get_powerdown_mode, + .set = ad5380_set_powerdown_mode, +}; + +static unsigned int ad5380_info_to_reg(struct iio_chan_spec const *chan, + long info) +{ + switch (info) { + case 0: + return AD5380_REG_DATA(chan->address); + case IIO_CHAN_INFO_CALIBBIAS: + return AD5380_REG_OFFSET(chan->address); + case IIO_CHAN_INFO_CALIBSCALE: + return AD5380_REG_GAIN(chan->address); + default: + break; + } + + return 0; +} + +static int ad5380_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long info) +{ + const unsigned int max_val = (1 << chan->scan_type.realbits); + struct ad5380_state *st = iio_priv(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_CALIBSCALE: + if (val >= max_val || val < 0) + return -EINVAL; + + return regmap_write(st->regmap, + ad5380_info_to_reg(chan, info), + val << chan->scan_type.shift); + case IIO_CHAN_INFO_CALIBBIAS: + val += (1 << chan->scan_type.realbits) / 2; + if (val >= max_val || val < 0) + return -EINVAL; + + return regmap_write(st->regmap, + AD5380_REG_OFFSET(chan->address), + val << chan->scan_type.shift); + default: + break; + } + return -EINVAL; +} + +static int ad5380_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long info) +{ + struct ad5380_state *st = iio_priv(indio_dev); + unsigned long scale_uv; + int ret; + + switch (info) { + case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_CALIBSCALE: + ret = regmap_read(st->regmap, ad5380_info_to_reg(chan, info), + val); + if (ret) + return ret; + *val >>= chan->scan_type.shift; + return IIO_VAL_INT; + case IIO_CHAN_INFO_CALIBBIAS: + ret = regmap_read(st->regmap, AD5380_REG_OFFSET(chan->address), + val); + if (ret) + return ret; + *val >>= chan->scan_type.shift; + val -= (1 << chan->scan_type.realbits) / 2; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + scale_uv = ((2 * st->vref) >> chan->scan_type.realbits) * 100; + *val = scale_uv / 100000; + *val2 = (scale_uv % 100000) * 10; + return IIO_VAL_INT_PLUS_MICRO; + default: + break; + } + + return -EINVAL; +} + +static const struct iio_info ad5380_info = { + .read_raw = ad5380_read_raw, + .write_raw = ad5380_write_raw, + .driver_module = THIS_MODULE, +}; + +static struct iio_chan_spec_ext_info ad5380_ext_info[] = { + { + .name = "powerdown", + .read = ad5380_read_dac_powerdown, + .write = ad5380_write_dac_powerdown, + }, + IIO_ENUM("powerdown_mode", true, &ad5380_powerdown_mode_enum), + IIO_ENUM_AVAILABLE("powerdown_mode", &ad5380_powerdown_mode_enum), + { }, +}; + +#define AD5380_CHANNEL(_bits) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SHARED_BIT | \ + IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \ + .scan_type = IIO_ST('u', (_bits), 16, 14 - (_bits)), \ + .ext_info = ad5380_ext_info, \ +} + +static const struct ad5380_chip_info ad5380_chip_info_tbl[] = { + [ID_AD5380_3] = { + .channel_template = AD5380_CHANNEL(14), + .num_channels = 40, + .int_vref = 1250000, + }, + [ID_AD5380_5] = { + .channel_template = AD5380_CHANNEL(14), + .num_channels = 40, + .int_vref = 2500000, + }, + [ID_AD5381_3] = { + .channel_template = AD5380_CHANNEL(12), + .num_channels = 16, + .int_vref = 1250000, + }, + [ID_AD5381_5] = { + .channel_template = AD5380_CHANNEL(12), + .num_channels = 16, + .int_vref = 2500000, + }, + [ID_AD5382_3] = { + .channel_template = AD5380_CHANNEL(14), + .num_channels = 32, + .int_vref = 1250000, + }, + [ID_AD5382_5] = { + .channel_template = AD5380_CHANNEL(14), + .num_channels = 32, + .int_vref = 2500000, + }, + [ID_AD5383_3] = { + .channel_template = AD5380_CHANNEL(12), + .num_channels = 32, + .int_vref = 1250000, + }, + [ID_AD5383_5] = { + .channel_template = AD5380_CHANNEL(12), + .num_channels = 32, + .int_vref = 2500000, + }, + [ID_AD5390_3] = { + .channel_template = AD5380_CHANNEL(14), + .num_channels = 16, + .int_vref = 1250000, + }, + [ID_AD5390_5] = { + .channel_template = AD5380_CHANNEL(14), + .num_channels = 16, + .int_vref = 2500000, + }, + [ID_AD5391_3] = { + .channel_template = AD5380_CHANNEL(12), + .num_channels = 16, + .int_vref = 1250000, + }, + [ID_AD5391_5] = { + .channel_template = AD5380_CHANNEL(12), + .num_channels = 16, + .int_vref = 2500000, + }, + [ID_AD5392_3] = { + .channel_template = AD5380_CHANNEL(14), + .num_channels = 8, + .int_vref = 1250000, + }, + [ID_AD5392_5] = { + .channel_template = AD5380_CHANNEL(14), + .num_channels = 8, + .int_vref = 2500000, + }, +}; + +static int __devinit ad5380_alloc_channels(struct iio_dev *indio_dev) +{ + struct ad5380_state *st = iio_priv(indio_dev); + struct iio_chan_spec *channels; + unsigned int i; + + channels = kcalloc(st->chip_info->num_channels, + sizeof(struct iio_chan_spec), GFP_KERNEL); + + if (!channels) + return -ENOMEM; + + for (i = 0; i < st->chip_info->num_channels; ++i) { + channels[i] = st->chip_info->channel_template; + channels[i].channel = i; + channels[i].address = i; + } + + indio_dev->channels = channels; + + return 0; +} + +static int __devinit ad5380_probe(struct device *dev, struct regmap *regmap, + enum ad5380_type type, const char *name) +{ + struct iio_dev *indio_dev; + struct ad5380_state *st; + unsigned int ctrl = 0; + int ret; + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) { + dev_err(dev, "Failed to allocate iio device\n"); + ret = -ENOMEM; + goto error_out; + } + + st = iio_priv(indio_dev); + dev_set_drvdata(dev, indio_dev); + + st->chip_info = &ad5380_chip_info_tbl[type]; + st->regmap = regmap; + + indio_dev->dev.parent = dev; + indio_dev->name = name; + indio_dev->info = &ad5380_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->num_channels = st->chip_info->num_channels; + + ret = ad5380_alloc_channels(indio_dev); + if (ret) { + dev_err(dev, "Failed to allocate channel spec: %d\n", ret); + goto error_free; + } + + if (st->chip_info->int_vref == 2500000) + ctrl |= AD5380_CTRL_INT_VREF_2V5; + + st->vref_reg = regulator_get(dev, "vref"); + if (!IS_ERR(st->vref_reg)) { + ret = regulator_enable(st->vref_reg); + if (ret) { + dev_err(dev, "Failed to enable vref regulators: %d\n", + ret); + goto error_free_reg; + } + + st->vref = regulator_get_voltage(st->vref_reg); + } else { + st->vref = st->chip_info->int_vref; + ctrl |= AD5380_CTRL_INT_VREF_EN; + } + + ret = regmap_write(st->regmap, AD5380_REG_SF_CTRL, ctrl); + if (ret) { + dev_err(dev, "Failed to write to device: %d\n", ret); + goto error_disable_reg; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(dev, "Failed to register iio device: %d\n", ret); + goto error_disable_reg; + } + + return 0; + +error_disable_reg: + if (!IS_ERR(st->vref_reg)) + regulator_disable(st->vref_reg); +error_free_reg: + if (!IS_ERR(st->vref_reg)) + regulator_put(st->vref_reg); + + kfree(indio_dev->channels); +error_free: + iio_device_free(indio_dev); +error_out: + + return ret; +} + +static int __devexit ad5380_remove(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad5380_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + kfree(indio_dev->channels); + + if (!IS_ERR(st->vref_reg)) { + regulator_disable(st->vref_reg); + regulator_put(st->vref_reg); + } + + iio_device_free(indio_dev); + + return 0; +} + +static bool ad5380_reg_false(struct device *dev, unsigned int reg) +{ + return false; +} + +static const struct regmap_config ad5380_regmap_config = { + .reg_bits = 10, + .val_bits = 14, + + .max_register = AD5380_REG_DATA(40), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = ad5380_reg_false, + .readable_reg = ad5380_reg_false, +}; + +#if IS_ENABLED(CONFIG_SPI_MASTER) + +static int __devinit ad5380_spi_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + struct regmap *regmap; + + regmap = devm_regmap_init_spi(spi, &ad5380_regmap_config); + + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return ad5380_probe(&spi->dev, regmap, id->driver_data, id->name); +} + +static int __devexit ad5380_spi_remove(struct spi_device *spi) +{ + return ad5380_remove(&spi->dev); +} + +static const struct spi_device_id ad5380_spi_ids[] = { + { "ad5380-3", ID_AD5380_3 }, + { "ad5380-5", ID_AD5380_5 }, + { "ad5381-3", ID_AD5381_3 }, + { "ad5381-5", ID_AD5381_5 }, + { "ad5382-3", ID_AD5382_3 }, + { "ad5382-5", ID_AD5382_5 }, + { "ad5383-3", ID_AD5383_3 }, + { "ad5383-5", ID_AD5383_5 }, + { "ad5384-3", ID_AD5380_3 }, + { "ad5384-5", ID_AD5380_5 }, + { "ad5390-3", ID_AD5390_3 }, + { "ad5390-5", ID_AD5390_5 }, + { "ad5391-3", ID_AD5391_3 }, + { "ad5391-5", ID_AD5391_5 }, + { "ad5392-3", ID_AD5392_3 }, + { "ad5392-5", ID_AD5392_5 }, + { } +}; +MODULE_DEVICE_TABLE(spi, ad5380_spi_ids); + +static struct spi_driver ad5380_spi_driver = { + .driver = { + .name = "ad5380", + .owner = THIS_MODULE, + }, + .probe = ad5380_spi_probe, + .remove = __devexit_p(ad5380_spi_remove), + .id_table = ad5380_spi_ids, +}; + +static inline int ad5380_spi_register_driver(void) +{ + return spi_register_driver(&ad5380_spi_driver); +} + +static inline void ad5380_spi_unregister_driver(void) +{ + spi_unregister_driver(&ad5380_spi_driver); +} + +#else + +static inline int ad5380_spi_register_driver(void) +{ + return 0; +} + +static inline void ad5380_spi_unregister_driver(void) +{ +} + +#endif + +#if IS_ENABLED(CONFIG_I2C) + +static int __devinit ad5380_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_i2c(i2c, &ad5380_regmap_config); + + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return ad5380_probe(&i2c->dev, regmap, id->driver_data, id->name); +} + +static int __devexit ad5380_i2c_remove(struct i2c_client *i2c) +{ + return ad5380_remove(&i2c->dev); +} + +static const struct i2c_device_id ad5380_i2c_ids[] = { + { "ad5380-3", ID_AD5380_3 }, + { "ad5380-5", ID_AD5380_5 }, + { "ad5381-3", ID_AD5381_3 }, + { "ad5381-5", ID_AD5381_5 }, + { "ad5382-3", ID_AD5382_3 }, + { "ad5382-5", ID_AD5382_5 }, + { "ad5383-3", ID_AD5383_3 }, + { "ad5383-5", ID_AD5383_5 }, + { "ad5384-3", ID_AD5380_3 }, + { "ad5384-5", ID_AD5380_5 }, + { "ad5390-3", ID_AD5390_3 }, + { "ad5390-5", ID_AD5390_5 }, + { "ad5391-3", ID_AD5391_3 }, + { "ad5391-5", ID_AD5391_5 }, + { "ad5392-3", ID_AD5392_3 }, + { "ad5392-5", ID_AD5392_5 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ad5380_i2c_ids); + +static struct i2c_driver ad5380_i2c_driver = { + .driver = { + .name = "ad5380", + .owner = THIS_MODULE, + }, + .probe = ad5380_i2c_probe, + .remove = __devexit_p(ad5380_i2c_remove), + .id_table = ad5380_i2c_ids, +}; + +static inline int ad5380_i2c_register_driver(void) +{ + return i2c_add_driver(&ad5380_i2c_driver); +} + +static inline void ad5380_i2c_unregister_driver(void) +{ + i2c_del_driver(&ad5380_i2c_driver); +} + +#else + +static inline int ad5380_i2c_register_driver(void) +{ + return 0; +} + +static inline void ad5380_i2c_unregister_driver(void) +{ +} + +#endif + +static int __init ad5380_spi_init(void) +{ + int ret; + + ret = ad5380_spi_register_driver(); + if (ret) + return ret; + + ret = ad5380_i2c_register_driver(); + if (ret) { + ad5380_spi_unregister_driver(); + return ret; + } + + return 0; +} +module_init(ad5380_spi_init); + +static void __exit ad5380_spi_exit(void) +{ + ad5380_i2c_unregister_driver(); + ad5380_spi_unregister_driver(); + +} +module_exit(ad5380_spi_exit); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("Analog Devices AD5380/81/82/83/84/90/91/92 DAC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c new file mode 100644 index 0000000000000..cdbc5bf25c31f --- /dev/null +++ b/drivers/iio/dac/ad5421.c @@ -0,0 +1,544 @@ +/* + * AD5421 Digital to analog converters driver + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +#define AD5421_REG_DAC_DATA 0x1 +#define AD5421_REG_CTRL 0x2 +#define AD5421_REG_OFFSET 0x3 +#define AD5421_REG_GAIN 0x4 +/* load dac and fault shared the same register number. Writing to it will cause + * a dac load command, reading from it will return the fault status register */ +#define AD5421_REG_LOAD_DAC 0x5 +#define AD5421_REG_FAULT 0x5 +#define AD5421_REG_FORCE_ALARM_CURRENT 0x6 +#define AD5421_REG_RESET 0x7 +#define AD5421_REG_START_CONVERSION 0x8 +#define AD5421_REG_NOOP 0x9 + +#define AD5421_CTRL_WATCHDOG_DISABLE BIT(12) +#define AD5421_CTRL_AUTO_FAULT_READBACK BIT(11) +#define AD5421_CTRL_MIN_CURRENT BIT(9) +#define AD5421_CTRL_ADC_SOURCE_TEMP BIT(8) +#define AD5421_CTRL_ADC_ENABLE BIT(7) +#define AD5421_CTRL_PWR_DOWN_INT_VREF BIT(6) + +#define AD5421_FAULT_SPI BIT(15) +#define AD5421_FAULT_PEC BIT(14) +#define AD5421_FAULT_OVER_CURRENT BIT(13) +#define AD5421_FAULT_UNDER_CURRENT BIT(12) +#define AD5421_FAULT_TEMP_OVER_140 BIT(11) +#define AD5421_FAULT_TEMP_OVER_100 BIT(10) +#define AD5421_FAULT_UNDER_VOLTAGE_6V BIT(9) +#define AD5421_FAULT_UNDER_VOLTAGE_12V BIT(8) + +/* These bits will cause the fault pin to go high */ +#define AD5421_FAULT_TRIGGER_IRQ \ + (AD5421_FAULT_SPI | AD5421_FAULT_PEC | AD5421_FAULT_OVER_CURRENT | \ + AD5421_FAULT_UNDER_CURRENT | AD5421_FAULT_TEMP_OVER_140) + +/** + * struct ad5421_state - driver instance specific data + * @spi: spi_device + * @ctrl: control register cache + * @current_range: current range which the device is configured for + * @data: spi transfer buffers + * @fault_mask: software masking of events + */ +struct ad5421_state { + struct spi_device *spi; + unsigned int ctrl; + enum ad5421_current_range current_range; + unsigned int fault_mask; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + union { + u32 d32; + u8 d8[4]; + } data[2] ____cacheline_aligned; +}; + +static const struct iio_chan_spec ad5421_channels[] = { + { + .type = IIO_CURRENT, + .indexed = 1, + .output = 1, + .channel = 0, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_OFFSET_SHARED_BIT | + IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, + .scan_type = IIO_ST('u', 16, 16, 0), + .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | + IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), + }, + { + .type = IIO_TEMP, + .channel = -1, + .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), + }, +}; + +static int ad5421_write_unlocked(struct iio_dev *indio_dev, + unsigned int reg, unsigned int val) +{ + struct ad5421_state *st = iio_priv(indio_dev); + + st->data[0].d32 = cpu_to_be32((reg << 16) | val); + + return spi_write(st->spi, &st->data[0].d8[1], 3); +} + +static int ad5421_write(struct iio_dev *indio_dev, unsigned int reg, + unsigned int val) +{ + int ret; + + mutex_lock(&indio_dev->mlock); + ret = ad5421_write_unlocked(indio_dev, reg, val); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int ad5421_read(struct iio_dev *indio_dev, unsigned int reg) +{ + struct ad5421_state *st = iio_priv(indio_dev); + struct spi_message m; + int ret; + struct spi_transfer t[] = { + { + .tx_buf = &st->data[0].d8[1], + .len = 3, + .cs_change = 1, + }, { + .rx_buf = &st->data[1].d8[1], + .len = 3, + }, + }; + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + mutex_lock(&indio_dev->mlock); + + st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16)); + + ret = spi_sync(st->spi, &m); + if (ret >= 0) + ret = be32_to_cpu(st->data[1].d32) & 0xffff; + + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int ad5421_update_ctrl(struct iio_dev *indio_dev, unsigned int set, + unsigned int clr) +{ + struct ad5421_state *st = iio_priv(indio_dev); + unsigned int ret; + + mutex_lock(&indio_dev->mlock); + + st->ctrl &= ~clr; + st->ctrl |= set; + + ret = ad5421_write_unlocked(indio_dev, AD5421_REG_CTRL, st->ctrl); + + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static irqreturn_t ad5421_fault_handler(int irq, void *data) +{ + struct iio_dev *indio_dev = data; + struct ad5421_state *st = iio_priv(indio_dev); + unsigned int fault; + unsigned int old_fault = 0; + unsigned int events; + + fault = ad5421_read(indio_dev, AD5421_REG_FAULT); + if (!fault) + return IRQ_NONE; + + /* If we had a fault, this might mean that the DAC has lost its state + * and has been reset. Make sure that the control register actually + * contains what we expect it to contain. Otherwise the watchdog might + * be enabled and we get watchdog timeout faults, which will render the + * DAC unusable. */ + ad5421_update_ctrl(indio_dev, 0, 0); + + + /* The fault pin stays high as long as a fault condition is present and + * it is not possible to mask fault conditions. For certain fault + * conditions for example like over-temperature it takes some time + * until the fault condition disappears. If we would exit the interrupt + * handler immediately after handling the event it would be entered + * again instantly. Thus we fall back to polling in case we detect that + * a interrupt condition is still present. + */ + do { + /* 0xffff is a invalid value for the register and will only be + * read if there has been a communication error */ + if (fault == 0xffff) + fault = 0; + + /* we are only interested in new events */ + events = (old_fault ^ fault) & fault; + events &= st->fault_mask; + + if (events & AD5421_FAULT_OVER_CURRENT) { + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_CURRENT, + 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + iio_get_time_ns()); + } + + if (events & AD5421_FAULT_UNDER_CURRENT) { + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_CURRENT, + 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + iio_get_time_ns()); + } + + if (events & AD5421_FAULT_TEMP_OVER_140) { + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_TEMP, + 0, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_RISING), + iio_get_time_ns()); + } + + old_fault = fault; + fault = ad5421_read(indio_dev, AD5421_REG_FAULT); + + /* still active? go to sleep for some time */ + if (fault & AD5421_FAULT_TRIGGER_IRQ) + msleep(1000); + + } while (fault & AD5421_FAULT_TRIGGER_IRQ); + + + return IRQ_HANDLED; +} + +static void ad5421_get_current_min_max(struct ad5421_state *st, + unsigned int *min, unsigned int *max) +{ + /* The current range is configured using external pins, which are + * usually hard-wired and not run-time switchable. */ + switch (st->current_range) { + case AD5421_CURRENT_RANGE_4mA_20mA: + *min = 4000; + *max = 20000; + break; + case AD5421_CURRENT_RANGE_3mA8_21mA: + *min = 3800; + *max = 21000; + break; + case AD5421_CURRENT_RANGE_3mA2_24mA: + *min = 3200; + *max = 24000; + break; + default: + *min = 0; + *max = 1; + break; + } +} + +static inline unsigned int ad5421_get_offset(struct ad5421_state *st) +{ + unsigned int min, max; + + ad5421_get_current_min_max(st, &min, &max); + return (min * (1 << 16)) / (max - min); +} + +static inline unsigned int ad5421_get_scale(struct ad5421_state *st) +{ + unsigned int min, max; + + ad5421_get_current_min_max(st, &min, &max); + return ((max - min) * 1000) / (1 << 16); +} + +static int ad5421_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long m) +{ + struct ad5421_state *st = iio_priv(indio_dev); + int ret; + + if (chan->type != IIO_CURRENT) + return -EINVAL; + + switch (m) { + case IIO_CHAN_INFO_RAW: + ret = ad5421_read(indio_dev, AD5421_REG_DAC_DATA); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = ad5421_get_scale(st); + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_OFFSET: + *val = ad5421_get_offset(st); + return IIO_VAL_INT; + case IIO_CHAN_INFO_CALIBBIAS: + ret = ad5421_read(indio_dev, AD5421_REG_OFFSET); + if (ret < 0) + return ret; + *val = ret - 32768; + return IIO_VAL_INT; + case IIO_CHAN_INFO_CALIBSCALE: + ret = ad5421_read(indio_dev, AD5421_REG_GAIN); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + } + + return -EINVAL; +} + +static int ad5421_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long mask) +{ + const unsigned int max_val = 1 << 16; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val >= max_val || val < 0) + return -EINVAL; + + return ad5421_write(indio_dev, AD5421_REG_DAC_DATA, val); + case IIO_CHAN_INFO_CALIBBIAS: + val += 32768; + if (val >= max_val || val < 0) + return -EINVAL; + + return ad5421_write(indio_dev, AD5421_REG_OFFSET, val); + case IIO_CHAN_INFO_CALIBSCALE: + if (val >= max_val || val < 0) + return -EINVAL; + + return ad5421_write(indio_dev, AD5421_REG_GAIN, val); + default: + break; + } + + return -EINVAL; +} + +static int ad5421_write_event_config(struct iio_dev *indio_dev, + u64 event_code, int state) +{ + struct ad5421_state *st = iio_priv(indio_dev); + unsigned int mask; + + switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { + case IIO_CURRENT: + if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == + IIO_EV_DIR_RISING) + mask = AD5421_FAULT_OVER_CURRENT; + else + mask = AD5421_FAULT_UNDER_CURRENT; + break; + case IIO_TEMP: + mask = AD5421_FAULT_TEMP_OVER_140; + break; + default: + return -EINVAL; + } + + mutex_lock(&indio_dev->mlock); + if (state) + st->fault_mask |= mask; + else + st->fault_mask &= ~mask; + mutex_unlock(&indio_dev->mlock); + + return 0; +} + +static int ad5421_read_event_config(struct iio_dev *indio_dev, + u64 event_code) +{ + struct ad5421_state *st = iio_priv(indio_dev); + unsigned int mask; + + switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { + case IIO_CURRENT: + if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == + IIO_EV_DIR_RISING) + mask = AD5421_FAULT_OVER_CURRENT; + else + mask = AD5421_FAULT_UNDER_CURRENT; + break; + case IIO_TEMP: + mask = AD5421_FAULT_TEMP_OVER_140; + break; + default: + return -EINVAL; + } + + return (bool)(st->fault_mask & mask); +} + +static int ad5421_read_event_value(struct iio_dev *indio_dev, u64 event_code, + int *val) +{ + int ret; + + switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { + case IIO_CURRENT: + ret = ad5421_read(indio_dev, AD5421_REG_DAC_DATA); + if (ret < 0) + return ret; + *val = ret; + break; + case IIO_TEMP: + *val = 140000; + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct iio_info ad5421_info = { + .read_raw = ad5421_read_raw, + .write_raw = ad5421_write_raw, + .read_event_config = ad5421_read_event_config, + .write_event_config = ad5421_write_event_config, + .read_event_value = ad5421_read_event_value, + .driver_module = THIS_MODULE, +}; + +static int __devinit ad5421_probe(struct spi_device *spi) +{ + struct ad5421_platform_data *pdata = dev_get_platdata(&spi->dev); + struct iio_dev *indio_dev; + struct ad5421_state *st; + int ret; + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) { + dev_err(&spi->dev, "Failed to allocate iio device\n"); + return -ENOMEM; + } + + st = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + + st->spi = spi; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = "ad5421"; + indio_dev->info = &ad5421_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ad5421_channels; + indio_dev->num_channels = ARRAY_SIZE(ad5421_channels); + + st->ctrl = AD5421_CTRL_WATCHDOG_DISABLE | + AD5421_CTRL_AUTO_FAULT_READBACK; + + if (pdata) { + st->current_range = pdata->current_range; + if (pdata->external_vref) + st->ctrl |= AD5421_CTRL_PWR_DOWN_INT_VREF; + } else { + st->current_range = AD5421_CURRENT_RANGE_4mA_20mA; + } + + /* write initial ctrl register value */ + ad5421_update_ctrl(indio_dev, 0, 0); + + if (spi->irq) { + ret = request_threaded_irq(spi->irq, + NULL, + ad5421_fault_handler, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "ad5421 fault", + indio_dev); + if (ret) + goto error_free; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&spi->dev, "Failed to register iio device: %d\n", ret); + goto error_free_irq; + } + + return 0; + +error_free_irq: + if (spi->irq) + free_irq(spi->irq, indio_dev); +error_free: + iio_device_free(indio_dev); + + return ret; +} + +static int __devexit ad5421_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + + iio_device_unregister(indio_dev); + if (spi->irq) + free_irq(spi->irq, indio_dev); + iio_device_free(indio_dev); + + return 0; +} + +static struct spi_driver ad5421_driver = { + .driver = { + .name = "ad5421", + .owner = THIS_MODULE, + }, + .probe = ad5421_probe, + .remove = __devexit_p(ad5421_remove), +}; +module_spi_driver(ad5421_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("Analog Devices AD5421 DAC"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:ad5421"); diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c new file mode 100644 index 0000000000000..2ca5059ef89ef --- /dev/null +++ b/drivers/iio/dac/ad5446.c @@ -0,0 +1,393 @@ +/* + * AD5446 SPI DAC driver + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ad5446.h" + +static int ad5446_write(struct ad5446_state *st, unsigned val) +{ + __be16 data = cpu_to_be16(val); + return spi_write(st->spi, &data, sizeof(data)); +} + +static int ad5660_write(struct ad5446_state *st, unsigned val) +{ + uint8_t data[3]; + + data[0] = (val >> 16) & 0xFF; + data[1] = (val >> 8) & 0xFF; + data[2] = val & 0xFF; + + return spi_write(st->spi, data, sizeof(data)); +} + +static const char * const ad5446_powerdown_modes[] = { + "1kohm_to_gnd", "100kohm_to_gnd", "three_state" +}; + +static int ad5446_set_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int mode) +{ + struct ad5446_state *st = iio_priv(indio_dev); + + st->pwr_down_mode = mode + 1; + + return 0; +} + +static int ad5446_get_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct ad5446_state *st = iio_priv(indio_dev); + + return st->pwr_down_mode - 1; +} + +static const struct iio_enum ad5446_powerdown_mode_enum = { + .items = ad5446_powerdown_modes, + .num_items = ARRAY_SIZE(ad5446_powerdown_modes), + .get = ad5446_get_powerdown_mode, + .set = ad5446_set_powerdown_mode, +}; + +static ssize_t ad5446_read_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + char *buf) +{ + struct ad5446_state *st = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", st->pwr_down); +} + +static ssize_t ad5446_write_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + const char *buf, size_t len) +{ + struct ad5446_state *st = iio_priv(indio_dev); + unsigned int shift; + unsigned int val; + bool powerdown; + int ret; + + ret = strtobool(buf, &powerdown); + if (ret) + return ret; + + mutex_lock(&indio_dev->mlock); + st->pwr_down = powerdown; + + if (st->pwr_down) { + shift = chan->scan_type.realbits + chan->scan_type.shift; + val = st->pwr_down_mode << shift; + } else { + val = st->cached_val; + } + + ret = st->chip_info->write(st, val); + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static const struct iio_chan_spec_ext_info ad5064_ext_info_powerdown[] = { + { + .name = "powerdown", + .read = ad5446_read_dac_powerdown, + .write = ad5446_write_dac_powerdown, + }, + IIO_ENUM("powerdown_mode", false, &ad5446_powerdown_mode_enum), + IIO_ENUM_AVAILABLE("powerdown_mode", &ad5446_powerdown_mode_enum), + { }, +}; + +#define _AD5446_CHANNEL(bits, storage, shift, ext) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = 0, \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .scan_type = IIO_ST('u', (bits), (storage), (shift)), \ + .ext_info = (ext), \ +} + +#define AD5446_CHANNEL(bits, storage, shift) \ + _AD5446_CHANNEL(bits, storage, shift, NULL) + +#define AD5446_CHANNEL_POWERDOWN(bits, storage, shift) \ + _AD5446_CHANNEL(bits, storage, shift, ad5064_ext_info_powerdown) + +static const struct ad5446_chip_info ad5446_chip_info_tbl[] = { + [ID_AD5444] = { + .channel = AD5446_CHANNEL(12, 16, 2), + .write = ad5446_write, + }, + [ID_AD5446] = { + .channel = AD5446_CHANNEL(14, 16, 0), + .write = ad5446_write, + }, + [ID_AD5450] = { + .channel = AD5446_CHANNEL(8, 16, 6), + .write = ad5446_write, + }, + [ID_AD5451] = { + .channel = AD5446_CHANNEL(10, 16, 4), + .write = ad5446_write, + }, + [ID_AD5541A] = { + .channel = AD5446_CHANNEL(16, 16, 0), + .write = ad5446_write, + }, + [ID_AD5512A] = { + .channel = AD5446_CHANNEL(12, 16, 4), + .write = ad5446_write, + }, + [ID_AD5553] = { + .channel = AD5446_CHANNEL(14, 16, 0), + .write = ad5446_write, + }, + [ID_AD5601] = { + .channel = AD5446_CHANNEL_POWERDOWN(8, 16, 6), + .write = ad5446_write, + }, + [ID_AD5611] = { + .channel = AD5446_CHANNEL_POWERDOWN(10, 16, 4), + .write = ad5446_write, + }, + [ID_AD5621] = { + .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2), + .write = ad5446_write, + }, + [ID_AD5620_2500] = { + .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2), + .int_vref_mv = 2500, + .write = ad5446_write, + }, + [ID_AD5620_1250] = { + .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2), + .int_vref_mv = 1250, + .write = ad5446_write, + }, + [ID_AD5640_2500] = { + .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0), + .int_vref_mv = 2500, + .write = ad5446_write, + }, + [ID_AD5640_1250] = { + .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0), + .int_vref_mv = 1250, + .write = ad5446_write, + }, + [ID_AD5660_2500] = { + .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0), + .int_vref_mv = 2500, + .write = ad5660_write, + }, + [ID_AD5660_1250] = { + .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0), + .int_vref_mv = 1250, + .write = ad5660_write, + }, + [ID_AD5662] = { + .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0), + .write = ad5660_write, + }, +}; + +static int ad5446_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad5446_state *st = iio_priv(indio_dev); + unsigned long scale_uv; + + switch (m) { + case IIO_CHAN_INFO_RAW: + *val = st->cached_val; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits; + *val = scale_uv / 1000; + *val2 = (scale_uv % 1000) * 1000; + return IIO_VAL_INT_PLUS_MICRO; + + } + return -EINVAL; +} + +static int ad5446_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad5446_state *st = iio_priv(indio_dev); + int ret = 0; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val >= (1 << chan->scan_type.realbits) || val < 0) + return -EINVAL; + + val <<= chan->scan_type.shift; + mutex_lock(&indio_dev->mlock); + st->cached_val = val; + if (!st->pwr_down) + ret = st->chip_info->write(st, val); + mutex_unlock(&indio_dev->mlock); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static const struct iio_info ad5446_info = { + .read_raw = ad5446_read_raw, + .write_raw = ad5446_write_raw, + .driver_module = THIS_MODULE, +}; + +static int __devinit ad5446_probe(struct spi_device *spi) +{ + struct ad5446_state *st; + struct iio_dev *indio_dev; + struct regulator *reg; + int ret, voltage_uv = 0; + + reg = regulator_get(&spi->dev, "vcc"); + if (!IS_ERR(reg)) { + ret = regulator_enable(reg); + if (ret) + goto error_put_reg; + + voltage_uv = regulator_get_voltage(reg); + } + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) { + ret = -ENOMEM; + goto error_disable_reg; + } + st = iio_priv(indio_dev); + st->chip_info = + &ad5446_chip_info_tbl[spi_get_device_id(spi)->driver_data]; + + spi_set_drvdata(spi, indio_dev); + st->reg = reg; + st->spi = spi; + + /* Establish that the iio_dev is a child of the spi device */ + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->info = &ad5446_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = &st->chip_info->channel; + indio_dev->num_channels = 1; + + st->pwr_down_mode = MODE_PWRDWN_1k; + + if (st->chip_info->int_vref_mv) + st->vref_mv = st->chip_info->int_vref_mv; + else if (voltage_uv) + st->vref_mv = voltage_uv / 1000; + else + dev_warn(&spi->dev, "reference voltage unspecified\n"); + + ret = iio_device_register(indio_dev); + if (ret) + goto error_free_device; + + return 0; + +error_free_device: + iio_device_free(indio_dev); +error_disable_reg: + if (!IS_ERR(reg)) + regulator_disable(reg); +error_put_reg: + if (!IS_ERR(reg)) + regulator_put(reg); + + return ret; +} + +static int ad5446_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad5446_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + if (!IS_ERR(st->reg)) { + regulator_disable(st->reg); + regulator_put(st->reg); + } + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id ad5446_id[] = { + {"ad5444", ID_AD5444}, + {"ad5446", ID_AD5446}, + {"ad5450", ID_AD5450}, + {"ad5451", ID_AD5451}, + {"ad5452", ID_AD5444}, /* ad5452 is compatible to the ad5444 */ + {"ad5453", ID_AD5446}, /* ad5453 is compatible to the ad5446 */ + {"ad5512a", ID_AD5512A}, + {"ad5541a", ID_AD5541A}, + {"ad5542a", ID_AD5541A}, /* ad5541a and ad5542a are compatible */ + {"ad5543", ID_AD5541A}, /* ad5541a and ad5543 are compatible */ + {"ad5553", ID_AD5553}, + {"ad5601", ID_AD5601}, + {"ad5611", ID_AD5611}, + {"ad5621", ID_AD5621}, + {"ad5620-2500", ID_AD5620_2500}, /* AD5620/40/60: */ + {"ad5620-1250", ID_AD5620_1250}, /* part numbers may look differently */ + {"ad5640-2500", ID_AD5640_2500}, + {"ad5640-1250", ID_AD5640_1250}, + {"ad5660-2500", ID_AD5660_2500}, + {"ad5660-1250", ID_AD5660_1250}, + {"ad5662", ID_AD5662}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad5446_id); + +static struct spi_driver ad5446_driver = { + .driver = { + .name = "ad5446", + .owner = THIS_MODULE, + }, + .probe = ad5446_probe, + .remove = __devexit_p(ad5446_remove), + .id_table = ad5446_id, +}; +module_spi_driver(ad5446_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/ad5446.h b/drivers/iio/dac/ad5446.h new file mode 100644 index 0000000000000..2934269a56d5e --- /dev/null +++ b/drivers/iio/dac/ad5446.h @@ -0,0 +1,91 @@ +/* + * AD5446 SPI DAC driver + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ +#ifndef IIO_DAC_AD5446_H_ +#define IIO_DAC_AD5446_H_ + +/* DAC Control Bits */ + +#define AD5446_LOAD (0x0 << 14) /* Load and update */ +#define AD5446_SDO_DIS (0x1 << 14) /* Disable SDO */ +#define AD5446_NOP (0x2 << 14) /* No operation */ +#define AD5446_CLK_RISING (0x3 << 14) /* Clock data on rising edge */ + +#define AD5620_LOAD (0x0 << 14) /* Load and update Norm Operation*/ +#define AD5620_PWRDWN_1k (0x1 << 14) /* Power-down: 1kOhm to GND */ +#define AD5620_PWRDWN_100k (0x2 << 14) /* Power-down: 100kOhm to GND */ +#define AD5620_PWRDWN_TRISTATE (0x3 << 14) /* Power-down: Three-state */ + +#define AD5660_LOAD (0x0 << 16) /* Load and update Norm Operation*/ +#define AD5660_PWRDWN_1k (0x1 << 16) /* Power-down: 1kOhm to GND */ +#define AD5660_PWRDWN_100k (0x2 << 16) /* Power-down: 100kOhm to GND */ +#define AD5660_PWRDWN_TRISTATE (0x3 << 16) /* Power-down: Three-state */ + +#define MODE_PWRDWN_1k 0x1 +#define MODE_PWRDWN_100k 0x2 +#define MODE_PWRDWN_TRISTATE 0x3 + +/** + * struct ad5446_state - driver instance specific data + * @spi: spi_device + * @chip_info: chip model specific constants, available modes etc + * @reg: supply regulator + * @vref_mv: actual reference voltage used + */ + +struct ad5446_state { + struct spi_device *spi; + const struct ad5446_chip_info *chip_info; + struct regulator *reg; + unsigned short vref_mv; + unsigned cached_val; + unsigned pwr_down_mode; + unsigned pwr_down; +}; + +/** + * struct ad5446_chip_info - chip specific information + * @channel: channel spec for the DAC + * @int_vref_mv: AD5620/40/60: the internal reference voltage + * @write: chip specific helper function to write to the register + */ + +struct ad5446_chip_info { + struct iio_chan_spec channel; + u16 int_vref_mv; + int (*write)(struct ad5446_state *st, unsigned val); +}; + +/** + * ad5446_supported_device_ids: + * The AD5620/40/60 parts are available in different fixed internal reference + * voltage options. The actual part numbers may look differently + * (and a bit cryptic), however this style is used to make clear which + * parts are supported here. + */ + +enum ad5446_supported_device_ids { + ID_AD5444, + ID_AD5446, + ID_AD5450, + ID_AD5451, + ID_AD5541A, + ID_AD5512A, + ID_AD5553, + ID_AD5601, + ID_AD5611, + ID_AD5621, + ID_AD5620_2500, + ID_AD5620_1250, + ID_AD5640_2500, + ID_AD5640_1250, + ID_AD5660_2500, + ID_AD5660_1250, + ID_AD5662, +}; + +#endif /* IIO_DAC_AD5446_H_ */ diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c new file mode 100644 index 0000000000000..242bdc7d00449 --- /dev/null +++ b/drivers/iio/dac/ad5504.c @@ -0,0 +1,393 @@ +/* + * AD5504, AD5501 High Voltage Digital to Analog Converter + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define AD5505_BITS 12 +#define AD5504_RES_MASK ((1 << (AD5505_BITS)) - 1) + +#define AD5504_CMD_READ (1 << 15) +#define AD5504_CMD_WRITE (0 << 15) +#define AD5504_ADDR(addr) ((addr) << 12) + +/* Registers */ +#define AD5504_ADDR_NOOP 0 +#define AD5504_ADDR_DAC(x) ((x) + 1) +#define AD5504_ADDR_ALL_DAC 5 +#define AD5504_ADDR_CTRL 7 + +/* Control Register */ +#define AD5504_DAC_PWR(ch) ((ch) << 2) +#define AD5504_DAC_PWRDWN_MODE(mode) ((mode) << 6) +#define AD5504_DAC_PWRDN_20K 0 +#define AD5504_DAC_PWRDN_3STATE 1 + +/** + * struct ad5446_state - driver instance specific data + * @us: spi_device + * @reg: supply regulator + * @vref_mv: actual reference voltage used + * @pwr_down_mask power down mask + * @pwr_down_mode current power down mode + */ + +struct ad5504_state { + struct spi_device *spi; + struct regulator *reg; + unsigned short vref_mv; + unsigned pwr_down_mask; + unsigned pwr_down_mode; +}; + +/** + * ad5504_supported_device_ids: + */ + +enum ad5504_supported_device_ids { + ID_AD5504, + ID_AD5501, +}; + +static int ad5504_spi_write(struct spi_device *spi, u8 addr, u16 val) +{ + u16 tmp = cpu_to_be16(AD5504_CMD_WRITE | + AD5504_ADDR(addr) | + (val & AD5504_RES_MASK)); + + return spi_write(spi, (u8 *)&tmp, 2); +} + +static int ad5504_spi_read(struct spi_device *spi, u8 addr) +{ + u16 tmp = cpu_to_be16(AD5504_CMD_READ | AD5504_ADDR(addr)); + u16 val; + int ret; + struct spi_transfer t = { + .tx_buf = &tmp, + .rx_buf = &val, + .len = 2, + }; + struct spi_message m; + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + ret = spi_sync(spi, &m); + + if (ret < 0) + return ret; + + return be16_to_cpu(val) & AD5504_RES_MASK; +} + +static int ad5504_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad5504_state *st = iio_priv(indio_dev); + unsigned long scale_uv; + int ret; + + switch (m) { + case IIO_CHAN_INFO_RAW: + ret = ad5504_spi_read(st->spi, chan->address); + if (ret < 0) + return ret; + + *val = ret; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits; + *val = scale_uv / 1000; + *val2 = (scale_uv % 1000) * 1000; + return IIO_VAL_INT_PLUS_MICRO; + + } + return -EINVAL; +} + +static int ad5504_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad5504_state *st = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val >= (1 << chan->scan_type.realbits) || val < 0) + return -EINVAL; + + return ad5504_spi_write(st->spi, chan->address, val); + default: + ret = -EINVAL; + } + + return -EINVAL; +} + +static const char * const ad5504_powerdown_modes[] = { + "20kohm_to_gnd", + "three_state", +}; + +static int ad5504_get_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct ad5504_state *st = iio_priv(indio_dev); + + return st->pwr_down_mode; +} + +static int ad5504_set_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int mode) +{ + struct ad5504_state *st = iio_priv(indio_dev); + + st->pwr_down_mode = mode; + + return 0; +} + +static const struct iio_enum ad5504_powerdown_mode_enum = { + .items = ad5504_powerdown_modes, + .num_items = ARRAY_SIZE(ad5504_powerdown_modes), + .get = ad5504_get_powerdown_mode, + .set = ad5504_set_powerdown_mode, +}; + +static ssize_t ad5504_read_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, char *buf) +{ + struct ad5504_state *st = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", + !(st->pwr_down_mask & (1 << chan->channel))); +} + +static ssize_t ad5504_write_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, + size_t len) +{ + bool pwr_down; + int ret; + struct ad5504_state *st = iio_priv(indio_dev); + + ret = strtobool(buf, &pwr_down); + if (ret) + return ret; + + if (pwr_down) + st->pwr_down_mask |= (1 << chan->channel); + else + st->pwr_down_mask &= ~(1 << chan->channel); + + ret = ad5504_spi_write(st->spi, AD5504_ADDR_CTRL, + AD5504_DAC_PWRDWN_MODE(st->pwr_down_mode) | + AD5504_DAC_PWR(st->pwr_down_mask)); + + /* writes to the CTRL register must be followed by a NOOP */ + ad5504_spi_write(st->spi, AD5504_ADDR_NOOP, 0); + + return ret ? ret : len; +} + +static IIO_CONST_ATTR(temp0_thresh_rising_value, "110000"); +static IIO_CONST_ATTR(temp0_thresh_rising_en, "1"); + +static struct attribute *ad5504_ev_attributes[] = { + &iio_const_attr_temp0_thresh_rising_value.dev_attr.attr, + &iio_const_attr_temp0_thresh_rising_en.dev_attr.attr, + NULL, +}; + +static struct attribute_group ad5504_ev_attribute_group = { + .attrs = ad5504_ev_attributes, + .name = "events", +}; + +static irqreturn_t ad5504_event_handler(int irq, void *private) +{ + iio_push_event(private, + IIO_UNMOD_EVENT_CODE(IIO_TEMP, + 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + iio_get_time_ns()); + + return IRQ_HANDLED; +} + +static const struct iio_info ad5504_info = { + .write_raw = ad5504_write_raw, + .read_raw = ad5504_read_raw, + .event_attrs = &ad5504_ev_attribute_group, + .driver_module = THIS_MODULE, +}; + +static const struct iio_chan_spec_ext_info ad5504_ext_info[] = { + { + .name = "powerdown", + .read = ad5504_read_dac_powerdown, + .write = ad5504_write_dac_powerdown, + }, + IIO_ENUM("powerdown_mode", true, &ad5504_powerdown_mode_enum), + IIO_ENUM_AVAILABLE("powerdown_mode", &ad5504_powerdown_mode_enum), + { }, +}; + +#define AD5504_CHANNEL(_chan) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (_chan), \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .address = AD5504_ADDR_DAC(_chan), \ + .scan_type = IIO_ST('u', 12, 16, 0), \ + .ext_info = ad5504_ext_info, \ +} + +static const struct iio_chan_spec ad5504_channels[] = { + AD5504_CHANNEL(0), + AD5504_CHANNEL(1), + AD5504_CHANNEL(2), + AD5504_CHANNEL(3), +}; + +static int __devinit ad5504_probe(struct spi_device *spi) +{ + struct ad5504_platform_data *pdata = spi->dev.platform_data; + struct iio_dev *indio_dev; + struct ad5504_state *st; + struct regulator *reg; + int ret, voltage_uv = 0; + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) { + ret = -ENOMEM; + goto error_ret; + } + reg = regulator_get(&spi->dev, "vcc"); + if (!IS_ERR(reg)) { + ret = regulator_enable(reg); + if (ret) + goto error_put_reg; + + voltage_uv = regulator_get_voltage(reg); + } + + spi_set_drvdata(spi, indio_dev); + st = iio_priv(indio_dev); + if (voltage_uv) + st->vref_mv = voltage_uv / 1000; + else if (pdata) + st->vref_mv = pdata->vref_mv; + else + dev_warn(&spi->dev, "reference voltage unspecified\n"); + + st->reg = reg; + st->spi = spi; + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(st->spi)->name; + indio_dev->info = &ad5504_info; + if (spi_get_device_id(st->spi)->driver_data == ID_AD5501) + indio_dev->num_channels = 1; + else + indio_dev->num_channels = 4; + indio_dev->channels = ad5504_channels; + indio_dev->modes = INDIO_DIRECT_MODE; + + if (spi->irq) { + ret = request_threaded_irq(spi->irq, + NULL, + &ad5504_event_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + spi_get_device_id(st->spi)->name, + indio_dev); + if (ret) + goto error_disable_reg; + } + + ret = iio_device_register(indio_dev); + if (ret) + goto error_free_irq; + + return 0; + +error_free_irq: + if (spi->irq) + free_irq(spi->irq, indio_dev); +error_disable_reg: + if (!IS_ERR(reg)) + regulator_disable(reg); +error_put_reg: + if (!IS_ERR(reg)) + regulator_put(reg); + + iio_device_free(indio_dev); +error_ret: + return ret; +} + +static int __devexit ad5504_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad5504_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + if (spi->irq) + free_irq(spi->irq, indio_dev); + + if (!IS_ERR(st->reg)) { + regulator_disable(st->reg); + regulator_put(st->reg); + } + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id ad5504_id[] = { + {"ad5504", ID_AD5504}, + {"ad5501", ID_AD5501}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad5504_id); + +static struct spi_driver ad5504_driver = { + .driver = { + .name = "ad5504", + .owner = THIS_MODULE, + }, + .probe = ad5504_probe, + .remove = __devexit_p(ad5504_remove), + .id_table = ad5504_id, +}; +module_spi_driver(ad5504_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD5501/AD5501 DAC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/ad5624r.h b/drivers/iio/dac/ad5624r.h new file mode 100644 index 0000000000000..5dca3028cdfd7 --- /dev/null +++ b/drivers/iio/dac/ad5624r.h @@ -0,0 +1,79 @@ +/* + * AD5624R SPI DAC driver + * + * Copyright 2010-2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ +#ifndef SPI_AD5624R_H_ +#define SPI_AD5624R_H_ + +#define AD5624R_DAC_CHANNELS 4 + +#define AD5624R_ADDR_DAC0 0x0 +#define AD5624R_ADDR_DAC1 0x1 +#define AD5624R_ADDR_DAC2 0x2 +#define AD5624R_ADDR_DAC3 0x3 +#define AD5624R_ADDR_ALL_DAC 0x7 + +#define AD5624R_CMD_WRITE_INPUT_N 0x0 +#define AD5624R_CMD_UPDATE_DAC_N 0x1 +#define AD5624R_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 +#define AD5624R_CMD_WRITE_INPUT_N_UPDATE_N 0x3 +#define AD5624R_CMD_POWERDOWN_DAC 0x4 +#define AD5624R_CMD_RESET 0x5 +#define AD5624R_CMD_LDAC_SETUP 0x6 +#define AD5624R_CMD_INTERNAL_REFER_SETUP 0x7 + +#define AD5624R_LDAC_PWRDN_NONE 0x0 +#define AD5624R_LDAC_PWRDN_1K 0x1 +#define AD5624R_LDAC_PWRDN_100K 0x2 +#define AD5624R_LDAC_PWRDN_3STATE 0x3 + +/** + * struct ad5624r_chip_info - chip specific information + * @channels: channel spec for the DAC + * @int_vref_mv: AD5620/40/60: the internal reference voltage + */ + +struct ad5624r_chip_info { + const struct iio_chan_spec *channels; + u16 int_vref_mv; +}; + +/** + * struct ad5446_state - driver instance specific data + * @indio_dev: the industrial I/O device + * @us: spi_device + * @chip_info: chip model specific constants, available modes etc + * @reg: supply regulator + * @vref_mv: actual reference voltage used + * @pwr_down_mask power down mask + * @pwr_down_mode current power down mode + */ + +struct ad5624r_state { + struct spi_device *us; + const struct ad5624r_chip_info *chip_info; + struct regulator *reg; + unsigned short vref_mv; + unsigned pwr_down_mask; + unsigned pwr_down_mode; +}; + +/** + * ad5624r_supported_device_ids: + * The AD5624/44/64 parts are available in different + * fixed internal reference voltage options. + */ + +enum ad5624r_supported_device_ids { + ID_AD5624R3, + ID_AD5644R3, + ID_AD5664R3, + ID_AD5624R5, + ID_AD5644R5, + ID_AD5664R5, +}; + +#endif /* SPI_AD5624R_H_ */ diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c new file mode 100644 index 0000000000000..6a7d6a48cc6dd --- /dev/null +++ b/drivers/iio/dac/ad5624r_spi.c @@ -0,0 +1,324 @@ +/* + * AD5624R, AD5644R, AD5664R Digital to analog convertors spi driver + * + * Copyright 2010-2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ad5624r.h" + +static int ad5624r_spi_write(struct spi_device *spi, + u8 cmd, u8 addr, u16 val, u8 len) +{ + u32 data; + u8 msg[3]; + + /* + * The input shift register is 24 bits wide. The first two bits are + * don't care bits. The next three are the command bits, C2 to C0, + * followed by the 3-bit DAC address, A2 to A0, and then the + * 16-, 14-, 12-bit data-word. The data-word comprises the 16-, + * 14-, 12-bit input code followed by 0, 2, or 4 don't care bits, + * for the AD5664R, AD5644R, and AD5624R, respectively. + */ + data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << (16 - len)); + msg[0] = data >> 16; + msg[1] = data >> 8; + msg[2] = data; + + return spi_write(spi, msg, 3); +} + +static int ad5624r_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad5624r_state *st = iio_priv(indio_dev); + unsigned long scale_uv; + + switch (m) { + case IIO_CHAN_INFO_SCALE: + scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits; + *val = scale_uv / 1000; + *val2 = (scale_uv % 1000) * 1000; + return IIO_VAL_INT_PLUS_MICRO; + + } + return -EINVAL; +} + +static int ad5624r_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad5624r_state *st = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val >= (1 << chan->scan_type.realbits) || val < 0) + return -EINVAL; + + return ad5624r_spi_write(st->us, + AD5624R_CMD_WRITE_INPUT_N_UPDATE_N, + chan->address, val, + chan->scan_type.shift); + default: + ret = -EINVAL; + } + + return -EINVAL; +} + +static const char * const ad5624r_powerdown_modes[] = { + "1kohm_to_gnd", + "100kohm_to_gnd", + "three_state" +}; + +static int ad5624r_get_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct ad5624r_state *st = iio_priv(indio_dev); + + return st->pwr_down_mode; +} + +static int ad5624r_set_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int mode) +{ + struct ad5624r_state *st = iio_priv(indio_dev); + + st->pwr_down_mode = mode; + + return 0; +} + +static const struct iio_enum ad5624r_powerdown_mode_enum = { + .items = ad5624r_powerdown_modes, + .num_items = ARRAY_SIZE(ad5624r_powerdown_modes), + .get = ad5624r_get_powerdown_mode, + .set = ad5624r_set_powerdown_mode, +}; + +static ssize_t ad5624r_read_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, char *buf) +{ + struct ad5624r_state *st = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", + !!(st->pwr_down_mask & (1 << chan->channel))); +} + +static ssize_t ad5624r_write_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, + size_t len) +{ + bool pwr_down; + int ret; + struct ad5624r_state *st = iio_priv(indio_dev); + + ret = strtobool(buf, &pwr_down); + if (ret) + return ret; + + if (pwr_down) + st->pwr_down_mask |= (1 << chan->channel); + else + st->pwr_down_mask &= ~(1 << chan->channel); + + ret = ad5624r_spi_write(st->us, AD5624R_CMD_POWERDOWN_DAC, 0, + (st->pwr_down_mode << 4) | + st->pwr_down_mask, 16); + + return ret ? ret : len; +} + +static const struct iio_info ad5624r_info = { + .write_raw = ad5624r_write_raw, + .read_raw = ad5624r_read_raw, + .driver_module = THIS_MODULE, +}; + +static const struct iio_chan_spec_ext_info ad5624r_ext_info[] = { + { + .name = "powerdown", + .read = ad5624r_read_dac_powerdown, + .write = ad5624r_write_dac_powerdown, + }, + IIO_ENUM("powerdown_mode", true, &ad5624r_powerdown_mode_enum), + IIO_ENUM_AVAILABLE("powerdown_mode", &ad5624r_powerdown_mode_enum), + { }, +}; + +#define AD5624R_CHANNEL(_chan, _bits) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (_chan), \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .address = (_chan), \ + .scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)), \ + .ext_info = ad5624r_ext_info, \ +} + +#define DECLARE_AD5624R_CHANNELS(_name, _bits) \ + const struct iio_chan_spec _name##_channels[] = { \ + AD5624R_CHANNEL(0, _bits), \ + AD5624R_CHANNEL(1, _bits), \ + AD5624R_CHANNEL(2, _bits), \ + AD5624R_CHANNEL(3, _bits), \ +} + +static DECLARE_AD5624R_CHANNELS(ad5624r, 12); +static DECLARE_AD5624R_CHANNELS(ad5644r, 14); +static DECLARE_AD5624R_CHANNELS(ad5664r, 16); + +static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = { + [ID_AD5624R3] = { + .channels = ad5624r_channels, + .int_vref_mv = 1250, + }, + [ID_AD5624R5] = { + .channels = ad5624r_channels, + .int_vref_mv = 2500, + }, + [ID_AD5644R3] = { + .channels = ad5644r_channels, + .int_vref_mv = 1250, + }, + [ID_AD5644R5] = { + .channels = ad5644r_channels, + .int_vref_mv = 2500, + }, + [ID_AD5664R3] = { + .channels = ad5664r_channels, + .int_vref_mv = 1250, + }, + [ID_AD5664R5] = { + .channels = ad5664r_channels, + .int_vref_mv = 2500, + }, +}; + +static int __devinit ad5624r_probe(struct spi_device *spi) +{ + struct ad5624r_state *st; + struct iio_dev *indio_dev; + int ret, voltage_uv = 0; + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) { + ret = -ENOMEM; + goto error_ret; + } + st = iio_priv(indio_dev); + st->reg = regulator_get(&spi->dev, "vcc"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) + goto error_put_reg; + + voltage_uv = regulator_get_voltage(st->reg); + } + + spi_set_drvdata(spi, indio_dev); + st->chip_info = + &ad5624r_chip_info_tbl[spi_get_device_id(spi)->driver_data]; + + if (voltage_uv) + st->vref_mv = voltage_uv / 1000; + else + st->vref_mv = st->chip_info->int_vref_mv; + + st->us = spi; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->info = &ad5624r_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = AD5624R_DAC_CHANNELS; + + ret = ad5624r_spi_write(spi, AD5624R_CMD_INTERNAL_REFER_SETUP, 0, + !!voltage_uv, 16); + if (ret) + goto error_disable_reg; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_disable_reg; + + return 0; + +error_disable_reg: + if (!IS_ERR(st->reg)) + regulator_disable(st->reg); +error_put_reg: + if (!IS_ERR(st->reg)) + regulator_put(st->reg); + iio_device_free(indio_dev); +error_ret: + + return ret; +} + +static int __devexit ad5624r_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad5624r_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + if (!IS_ERR(st->reg)) { + regulator_disable(st->reg); + regulator_put(st->reg); + } + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id ad5624r_id[] = { + {"ad5624r3", ID_AD5624R3}, + {"ad5644r3", ID_AD5644R3}, + {"ad5664r3", ID_AD5664R3}, + {"ad5624r5", ID_AD5624R5}, + {"ad5644r5", ID_AD5644R5}, + {"ad5664r5", ID_AD5664R5}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad5624r_id); + +static struct spi_driver ad5624r_driver = { + .driver = { + .name = "ad5624r", + .owner = THIS_MODULE, + }, + .probe = ad5624r_probe, + .remove = __devexit_p(ad5624r_remove), + .id_table = ad5624r_id, +}; +module_spi_driver(ad5624r_driver); + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices AD5624/44/64R DAC spi driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c new file mode 100644 index 0000000000000..6948d75e1036c --- /dev/null +++ b/drivers/iio/dac/ad5686.c @@ -0,0 +1,418 @@ +/* + * AD5686R, AD5685R, AD5684R Digital to analog converters driver + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define AD5686_DAC_CHANNELS 4 + +#define AD5686_ADDR(x) ((x) << 16) +#define AD5686_CMD(x) ((x) << 20) + +#define AD5686_ADDR_DAC(chan) (0x1 << (chan)) +#define AD5686_ADDR_ALL_DAC 0xF + +#define AD5686_CMD_NOOP 0x0 +#define AD5686_CMD_WRITE_INPUT_N 0x1 +#define AD5686_CMD_UPDATE_DAC_N 0x2 +#define AD5686_CMD_WRITE_INPUT_N_UPDATE_N 0x3 +#define AD5686_CMD_POWERDOWN_DAC 0x4 +#define AD5686_CMD_LDAC_MASK 0x5 +#define AD5686_CMD_RESET 0x6 +#define AD5686_CMD_INTERNAL_REFER_SETUP 0x7 +#define AD5686_CMD_DAISY_CHAIN_ENABLE 0x8 +#define AD5686_CMD_READBACK_ENABLE 0x9 + +#define AD5686_LDAC_PWRDN_NONE 0x0 +#define AD5686_LDAC_PWRDN_1K 0x1 +#define AD5686_LDAC_PWRDN_100K 0x2 +#define AD5686_LDAC_PWRDN_3STATE 0x3 + +/** + * struct ad5686_chip_info - chip specific information + * @int_vref_mv: AD5620/40/60: the internal reference voltage + * @channel: channel specification +*/ + +struct ad5686_chip_info { + u16 int_vref_mv; + struct iio_chan_spec channel[AD5686_DAC_CHANNELS]; +}; + +/** + * struct ad5446_state - driver instance specific data + * @spi: spi_device + * @chip_info: chip model specific constants, available modes etc + * @reg: supply regulator + * @vref_mv: actual reference voltage used + * @pwr_down_mask: power down mask + * @pwr_down_mode: current power down mode + * @data: spi transfer buffers + */ + +struct ad5686_state { + struct spi_device *spi; + const struct ad5686_chip_info *chip_info; + struct regulator *reg; + unsigned short vref_mv; + unsigned pwr_down_mask; + unsigned pwr_down_mode; + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + + union { + u32 d32; + u8 d8[4]; + } data[3] ____cacheline_aligned; +}; + +/** + * ad5686_supported_device_ids: + */ + +enum ad5686_supported_device_ids { + ID_AD5684, + ID_AD5685, + ID_AD5686, +}; +static int ad5686_spi_write(struct ad5686_state *st, + u8 cmd, u8 addr, u16 val, u8 shift) +{ + val <<= shift; + + st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) | + AD5686_ADDR(addr) | + val); + + return spi_write(st->spi, &st->data[0].d8[1], 3); +} + +static int ad5686_spi_read(struct ad5686_state *st, u8 addr) +{ + struct spi_transfer t[] = { + { + .tx_buf = &st->data[0].d8[1], + .len = 3, + .cs_change = 1, + }, { + .tx_buf = &st->data[1].d8[1], + .rx_buf = &st->data[2].d8[1], + .len = 3, + }, + }; + struct spi_message m; + int ret; + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + st->data[0].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_READBACK_ENABLE) | + AD5686_ADDR(addr)); + st->data[1].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP)); + + ret = spi_sync(st->spi, &m); + if (ret < 0) + return ret; + + return be32_to_cpu(st->data[2].d32); +} + +static const char * const ad5686_powerdown_modes[] = { + "1kohm_to_gnd", + "100kohm_to_gnd", + "three_state" +}; + +static int ad5686_get_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct ad5686_state *st = iio_priv(indio_dev); + + return ((st->pwr_down_mode >> (chan->channel * 2)) & 0x3) - 1; +} + +static int ad5686_set_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int mode) +{ + struct ad5686_state *st = iio_priv(indio_dev); + + st->pwr_down_mode &= ~(0x3 << (chan->channel * 2)); + st->pwr_down_mode |= ((mode + 1) << (chan->channel * 2)); + + return 0; +} + +static const struct iio_enum ad5686_powerdown_mode_enum = { + .items = ad5686_powerdown_modes, + .num_items = ARRAY_SIZE(ad5686_powerdown_modes), + .get = ad5686_get_powerdown_mode, + .set = ad5686_set_powerdown_mode, +}; + +static ssize_t ad5686_read_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, char *buf) +{ + struct ad5686_state *st = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", !!(st->pwr_down_mask & + (0x3 << (chan->channel * 2)))); +} + +static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, + size_t len) +{ + bool readin; + int ret; + struct ad5686_state *st = iio_priv(indio_dev); + + ret = strtobool(buf, &readin); + if (ret) + return ret; + + if (readin == true) + st->pwr_down_mask |= (0x3 << (chan->channel * 2)); + else + st->pwr_down_mask &= ~(0x3 << (chan->channel * 2)); + + ret = ad5686_spi_write(st, AD5686_CMD_POWERDOWN_DAC, 0, + st->pwr_down_mask & st->pwr_down_mode, 0); + + return ret ? ret : len; +} + +static int ad5686_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad5686_state *st = iio_priv(indio_dev); + unsigned long scale_uv; + int ret; + + switch (m) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&indio_dev->mlock); + ret = ad5686_spi_read(st, chan->address); + mutex_unlock(&indio_dev->mlock); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + break; + case IIO_CHAN_INFO_SCALE: + scale_uv = (st->vref_mv * 100000) + >> (chan->scan_type.realbits); + *val = scale_uv / 100000; + *val2 = (scale_uv % 100000) * 10; + return IIO_VAL_INT_PLUS_MICRO; + + } + return -EINVAL; +} + +static int ad5686_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad5686_state *st = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val > (1 << chan->scan_type.realbits) || val < 0) + return -EINVAL; + + mutex_lock(&indio_dev->mlock); + ret = ad5686_spi_write(st, + AD5686_CMD_WRITE_INPUT_N_UPDATE_N, + chan->address, + val, + chan->scan_type.shift); + mutex_unlock(&indio_dev->mlock); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static const struct iio_info ad5686_info = { + .read_raw = ad5686_read_raw, + .write_raw = ad5686_write_raw, + .driver_module = THIS_MODULE, +}; + +static const struct iio_chan_spec_ext_info ad5686_ext_info[] = { + { + .name = "powerdown", + .read = ad5686_read_dac_powerdown, + .write = ad5686_write_dac_powerdown, + }, + IIO_ENUM("powerdown_mode", false, &ad5686_powerdown_mode_enum), + IIO_ENUM_AVAILABLE("powerdown_mode", &ad5686_powerdown_mode_enum), + { }, +}; + +#define AD5868_CHANNEL(chan, bits, shift) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = chan, \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .address = AD5686_ADDR_DAC(chan), \ + .scan_type = IIO_ST('u', bits, 16, shift), \ + .ext_info = ad5686_ext_info, \ +} + +static const struct ad5686_chip_info ad5686_chip_info_tbl[] = { + [ID_AD5684] = { + .channel[0] = AD5868_CHANNEL(0, 12, 4), + .channel[1] = AD5868_CHANNEL(1, 12, 4), + .channel[2] = AD5868_CHANNEL(2, 12, 4), + .channel[3] = AD5868_CHANNEL(3, 12, 4), + .int_vref_mv = 2500, + }, + [ID_AD5685] = { + .channel[0] = AD5868_CHANNEL(0, 14, 2), + .channel[1] = AD5868_CHANNEL(1, 14, 2), + .channel[2] = AD5868_CHANNEL(2, 14, 2), + .channel[3] = AD5868_CHANNEL(3, 14, 2), + .int_vref_mv = 2500, + }, + [ID_AD5686] = { + .channel[0] = AD5868_CHANNEL(0, 16, 0), + .channel[1] = AD5868_CHANNEL(1, 16, 0), + .channel[2] = AD5868_CHANNEL(2, 16, 0), + .channel[3] = AD5868_CHANNEL(3, 16, 0), + .int_vref_mv = 2500, + }, +}; + + +static int __devinit ad5686_probe(struct spi_device *spi) +{ + struct ad5686_state *st; + struct iio_dev *indio_dev; + int ret, regdone = 0, voltage_uv = 0; + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + + st->reg = regulator_get(&spi->dev, "vcc"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) + goto error_put_reg; + + voltage_uv = regulator_get_voltage(st->reg); + } + + st->chip_info = + &ad5686_chip_info_tbl[spi_get_device_id(spi)->driver_data]; + + if (voltage_uv) + st->vref_mv = voltage_uv / 1000; + else + st->vref_mv = st->chip_info->int_vref_mv; + + st->spi = spi; + + /* Set all the power down mode for all channels to 1K pulldown */ + st->pwr_down_mode = 0x55; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->info = &ad5686_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = st->chip_info->channel; + indio_dev->num_channels = AD5686_DAC_CHANNELS; + + regdone = 1; + ret = ad5686_spi_write(st, AD5686_CMD_INTERNAL_REFER_SETUP, 0, + !!voltage_uv, 0); + if (ret) + goto error_disable_reg; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_disable_reg; + + return 0; + +error_disable_reg: + if (!IS_ERR(st->reg)) + regulator_disable(st->reg); +error_put_reg: + if (!IS_ERR(st->reg)) + regulator_put(st->reg); + + iio_device_free(indio_dev); + + return ret; +} + +static int __devexit ad5686_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad5686_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + if (!IS_ERR(st->reg)) { + regulator_disable(st->reg); + regulator_put(st->reg); + } + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id ad5686_id[] = { + {"ad5684", ID_AD5684}, + {"ad5685", ID_AD5685}, + {"ad5686", ID_AD5686}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad5686_id); + +static struct spi_driver ad5686_driver = { + .driver = { + .name = "ad5686", + .owner = THIS_MODULE, + }, + .probe = ad5686_probe, + .remove = __devexit_p(ad5686_remove), + .id_table = ad5686_id, +}; +module_spi_driver(ad5686_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD5686/85/84 DAC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/ad5764.c b/drivers/iio/dac/ad5764.c new file mode 100644 index 0000000000000..ffce30447445d --- /dev/null +++ b/drivers/iio/dac/ad5764.c @@ -0,0 +1,382 @@ +/* + * Analog devices AD5764, AD5764R, AD5744, AD5744R quad-channel + * Digital to Analog Converters driver + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define AD5764_REG_SF_NOP 0x0 +#define AD5764_REG_SF_CONFIG 0x1 +#define AD5764_REG_SF_CLEAR 0x4 +#define AD5764_REG_SF_LOAD 0x5 +#define AD5764_REG_DATA(x) ((2 << 3) | (x)) +#define AD5764_REG_COARSE_GAIN(x) ((3 << 3) | (x)) +#define AD5764_REG_FINE_GAIN(x) ((4 << 3) | (x)) +#define AD5764_REG_OFFSET(x) ((5 << 3) | (x)) + +#define AD5764_NUM_CHANNELS 4 + +/** + * struct ad5764_chip_info - chip specific information + * @int_vref: Value of the internal reference voltage in uV - 0 if external + * reference voltage is used + * @channel channel specification +*/ + +struct ad5764_chip_info { + unsigned long int_vref; + const struct iio_chan_spec *channels; +}; + +/** + * struct ad5764_state - driver instance specific data + * @spi: spi_device + * @chip_info: chip info + * @vref_reg: vref supply regulators + * @data: spi transfer buffers + */ + +struct ad5764_state { + struct spi_device *spi; + const struct ad5764_chip_info *chip_info; + struct regulator_bulk_data vref_reg[2]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + union { + __be32 d32; + u8 d8[4]; + } data[2] ____cacheline_aligned; +}; + +enum ad5764_type { + ID_AD5744, + ID_AD5744R, + ID_AD5764, + ID_AD5764R, +}; + +#define AD5764_CHANNEL(_chan, _bits) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (_chan), \ + .address = (_chan), \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_OFFSET_SHARED_BIT | \ + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \ + IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \ + .scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)) \ +} + +#define DECLARE_AD5764_CHANNELS(_name, _bits) \ +const struct iio_chan_spec _name##_channels[] = { \ + AD5764_CHANNEL(0, (_bits)), \ + AD5764_CHANNEL(1, (_bits)), \ + AD5764_CHANNEL(2, (_bits)), \ + AD5764_CHANNEL(3, (_bits)), \ +}; + +static DECLARE_AD5764_CHANNELS(ad5764, 16); +static DECLARE_AD5764_CHANNELS(ad5744, 14); + +static const struct ad5764_chip_info ad5764_chip_infos[] = { + [ID_AD5744] = { + .int_vref = 0, + .channels = ad5744_channels, + }, + [ID_AD5744R] = { + .int_vref = 5000000, + .channels = ad5744_channels, + }, + [ID_AD5764] = { + .int_vref = 0, + .channels = ad5764_channels, + }, + [ID_AD5764R] = { + .int_vref = 5000000, + .channels = ad5764_channels, + }, +}; + +static int ad5764_write(struct iio_dev *indio_dev, unsigned int reg, + unsigned int val) +{ + struct ad5764_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&indio_dev->mlock); + st->data[0].d32 = cpu_to_be32((reg << 16) | val); + + ret = spi_write(st->spi, &st->data[0].d8[1], 3); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int ad5764_read(struct iio_dev *indio_dev, unsigned int reg, + unsigned int *val) +{ + struct ad5764_state *st = iio_priv(indio_dev); + struct spi_message m; + int ret; + struct spi_transfer t[] = { + { + .tx_buf = &st->data[0].d8[1], + .len = 3, + .cs_change = 1, + }, { + .rx_buf = &st->data[1].d8[1], + .len = 3, + }, + }; + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + mutex_lock(&indio_dev->mlock); + + st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16)); + + ret = spi_sync(st->spi, &m); + if (ret >= 0) + *val = be32_to_cpu(st->data[1].d32) & 0xffff; + + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int ad5764_chan_info_to_reg(struct iio_chan_spec const *chan, long info) +{ + switch (info) { + case 0: + return AD5764_REG_DATA(chan->address); + case IIO_CHAN_INFO_CALIBBIAS: + return AD5764_REG_OFFSET(chan->address); + case IIO_CHAN_INFO_CALIBSCALE: + return AD5764_REG_FINE_GAIN(chan->address); + default: + break; + } + + return 0; +} + +static int ad5764_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long info) +{ + const int max_val = (1 << chan->scan_type.realbits); + unsigned int reg; + + switch (info) { + case IIO_CHAN_INFO_RAW: + if (val >= max_val || val < 0) + return -EINVAL; + val <<= chan->scan_type.shift; + break; + case IIO_CHAN_INFO_CALIBBIAS: + if (val >= 128 || val < -128) + return -EINVAL; + break; + case IIO_CHAN_INFO_CALIBSCALE: + if (val >= 32 || val < -32) + return -EINVAL; + break; + default: + return -EINVAL; + } + + reg = ad5764_chan_info_to_reg(chan, info); + return ad5764_write(indio_dev, reg, (u16)val); +} + +static int ad5764_get_channel_vref(struct ad5764_state *st, + unsigned int channel) +{ + if (st->chip_info->int_vref) + return st->chip_info->int_vref; + else + return regulator_get_voltage(st->vref_reg[channel / 2].consumer); +} + +static int ad5764_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long info) +{ + struct ad5764_state *st = iio_priv(indio_dev); + unsigned long scale_uv; + unsigned int reg; + int vref; + int ret; + + switch (info) { + case IIO_CHAN_INFO_RAW: + reg = AD5764_REG_DATA(chan->address); + ret = ad5764_read(indio_dev, reg, val); + if (ret < 0) + return ret; + *val >>= chan->scan_type.shift; + return IIO_VAL_INT; + case IIO_CHAN_INFO_CALIBBIAS: + reg = AD5764_REG_OFFSET(chan->address); + ret = ad5764_read(indio_dev, reg, val); + if (ret < 0) + return ret; + *val = sign_extend32(*val, 7); + return IIO_VAL_INT; + case IIO_CHAN_INFO_CALIBSCALE: + reg = AD5764_REG_FINE_GAIN(chan->address); + ret = ad5764_read(indio_dev, reg, val); + if (ret < 0) + return ret; + *val = sign_extend32(*val, 5); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + /* vout = 4 * vref + ((dac_code / 65535) - 0.5) */ + vref = ad5764_get_channel_vref(st, chan->channel); + if (vref < 0) + return vref; + + scale_uv = (vref * 4 * 100) >> chan->scan_type.realbits; + *val = scale_uv / 100000; + *val2 = (scale_uv % 100000) * 10; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_OFFSET: + *val = -(1 << chan->scan_type.realbits) / 2; + return IIO_VAL_INT; + } + + return -EINVAL; +} + +static const struct iio_info ad5764_info = { + .read_raw = ad5764_read_raw, + .write_raw = ad5764_write_raw, + .driver_module = THIS_MODULE, +}; + +static int __devinit ad5764_probe(struct spi_device *spi) +{ + enum ad5764_type type = spi_get_device_id(spi)->driver_data; + struct iio_dev *indio_dev; + struct ad5764_state *st; + int ret; + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) { + dev_err(&spi->dev, "Failed to allocate iio device\n"); + return -ENOMEM; + } + + st = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + + st->spi = spi; + st->chip_info = &ad5764_chip_infos[type]; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->info = &ad5764_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->num_channels = AD5764_NUM_CHANNELS; + indio_dev->channels = st->chip_info->channels; + + if (st->chip_info->int_vref == 0) { + st->vref_reg[0].supply = "vrefAB"; + st->vref_reg[1].supply = "vrefCD"; + + ret = regulator_bulk_get(&st->spi->dev, + ARRAY_SIZE(st->vref_reg), st->vref_reg); + if (ret) { + dev_err(&spi->dev, "Failed to request vref regulators: %d\n", + ret); + goto error_free; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(st->vref_reg), + st->vref_reg); + if (ret) { + dev_err(&spi->dev, "Failed to enable vref regulators: %d\n", + ret); + goto error_free_reg; + } + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&spi->dev, "Failed to register iio device: %d\n", ret); + goto error_disable_reg; + } + + return 0; + +error_disable_reg: + if (st->chip_info->int_vref == 0) + regulator_bulk_disable(ARRAY_SIZE(st->vref_reg), st->vref_reg); +error_free_reg: + if (st->chip_info->int_vref == 0) + regulator_bulk_free(ARRAY_SIZE(st->vref_reg), st->vref_reg); +error_free: + iio_device_free(indio_dev); + + return ret; +} + +static int __devexit ad5764_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad5764_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + if (st->chip_info->int_vref == 0) { + regulator_bulk_disable(ARRAY_SIZE(st->vref_reg), st->vref_reg); + regulator_bulk_free(ARRAY_SIZE(st->vref_reg), st->vref_reg); + } + + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id ad5764_ids[] = { + { "ad5744", ID_AD5744 }, + { "ad5744r", ID_AD5744R }, + { "ad5764", ID_AD5764 }, + { "ad5764r", ID_AD5764R }, + { } +}; +MODULE_DEVICE_TABLE(spi, ad5764_ids); + +static struct spi_driver ad5764_driver = { + .driver = { + .name = "ad5764", + .owner = THIS_MODULE, + }, + .probe = ad5764_probe, + .remove = __devexit_p(ad5764_remove), + .id_table = ad5764_ids, +}; +module_spi_driver(ad5764_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("Analog Devices AD5744/AD5744R/AD5764/AD5764R DAC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c new file mode 100644 index 0000000000000..2bd2e37280ff8 --- /dev/null +++ b/drivers/iio/dac/ad5791.c @@ -0,0 +1,485 @@ +/* + * AD5760, AD5780, AD5781, AD5790, AD5791 Voltage Output Digital to Analog + * Converter + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define AD5791_RES_MASK(x) ((1 << (x)) - 1) +#define AD5791_DAC_MASK AD5791_RES_MASK(20) +#define AD5791_DAC_MSB (1 << 19) + +#define AD5791_CMD_READ (1 << 23) +#define AD5791_CMD_WRITE (0 << 23) +#define AD5791_ADDR(addr) ((addr) << 20) + +/* Registers */ +#define AD5791_ADDR_NOOP 0 +#define AD5791_ADDR_DAC0 1 +#define AD5791_ADDR_CTRL 2 +#define AD5791_ADDR_CLRCODE 3 +#define AD5791_ADDR_SW_CTRL 4 + +/* Control Register */ +#define AD5791_CTRL_RBUF (1 << 1) +#define AD5791_CTRL_OPGND (1 << 2) +#define AD5791_CTRL_DACTRI (1 << 3) +#define AD5791_CTRL_BIN2SC (1 << 4) +#define AD5791_CTRL_SDODIS (1 << 5) +#define AD5761_CTRL_LINCOMP(x) ((x) << 6) + +#define AD5791_LINCOMP_0_10 0 +#define AD5791_LINCOMP_10_12 1 +#define AD5791_LINCOMP_12_16 2 +#define AD5791_LINCOMP_16_19 3 +#define AD5791_LINCOMP_19_20 12 + +#define AD5780_LINCOMP_0_10 0 +#define AD5780_LINCOMP_10_20 12 + +/* Software Control Register */ +#define AD5791_SWCTRL_LDAC (1 << 0) +#define AD5791_SWCTRL_CLR (1 << 1) +#define AD5791_SWCTRL_RESET (1 << 2) + +#define AD5791_DAC_PWRDN_6K 0 +#define AD5791_DAC_PWRDN_3STATE 1 + +/** + * struct ad5791_chip_info - chip specific information + * @get_lin_comp: function pointer to the device specific function + */ + +struct ad5791_chip_info { + int (*get_lin_comp) (unsigned int span); +}; + +/** + * struct ad5791_state - driver instance specific data + * @us: spi_device + * @reg_vdd: positive supply regulator + * @reg_vss: negative supply regulator + * @chip_info: chip model specific constants + * @vref_mv: actual reference voltage used + * @vref_neg_mv: voltage of the negative supply + * @pwr_down_mode current power down mode + */ + +struct ad5791_state { + struct spi_device *spi; + struct regulator *reg_vdd; + struct regulator *reg_vss; + const struct ad5791_chip_info *chip_info; + unsigned short vref_mv; + unsigned int vref_neg_mv; + unsigned ctrl; + unsigned pwr_down_mode; + bool pwr_down; +}; + +/** + * ad5791_supported_device_ids: + */ + +enum ad5791_supported_device_ids { + ID_AD5760, + ID_AD5780, + ID_AD5781, + ID_AD5791, +}; + +static int ad5791_spi_write(struct spi_device *spi, u8 addr, u32 val) +{ + union { + u32 d32; + u8 d8[4]; + } data; + + data.d32 = cpu_to_be32(AD5791_CMD_WRITE | + AD5791_ADDR(addr) | + (val & AD5791_DAC_MASK)); + + return spi_write(spi, &data.d8[1], 3); +} + +static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val) +{ + union { + u32 d32; + u8 d8[4]; + } data[3]; + int ret; + struct spi_message msg; + struct spi_transfer xfers[] = { + { + .tx_buf = &data[0].d8[1], + .bits_per_word = 8, + .len = 3, + .cs_change = 1, + }, { + .tx_buf = &data[1].d8[1], + .rx_buf = &data[2].d8[1], + .bits_per_word = 8, + .len = 3, + }, + }; + + data[0].d32 = cpu_to_be32(AD5791_CMD_READ | + AD5791_ADDR(addr)); + data[1].d32 = cpu_to_be32(AD5791_ADDR(AD5791_ADDR_NOOP)); + + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(spi, &msg); + + *val = be32_to_cpu(data[2].d32); + + return ret; +} + +static const char * const ad5791_powerdown_modes[] = { + "6kohm_to_gnd", + "three_state", +}; + +static int ad5791_get_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct ad5791_state *st = iio_priv(indio_dev); + + return st->pwr_down_mode; +} + +static int ad5791_set_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, unsigned int mode) +{ + struct ad5791_state *st = iio_priv(indio_dev); + + st->pwr_down_mode = mode; + + return 0; +} + +static const struct iio_enum ad5791_powerdown_mode_enum = { + .items = ad5791_powerdown_modes, + .num_items = ARRAY_SIZE(ad5791_powerdown_modes), + .get = ad5791_get_powerdown_mode, + .set = ad5791_set_powerdown_mode, +}; + +static ssize_t ad5791_read_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, char *buf) +{ + struct ad5791_state *st = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", st->pwr_down); +} + +static ssize_t ad5791_write_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, + size_t len) +{ + bool pwr_down; + int ret; + struct ad5791_state *st = iio_priv(indio_dev); + + ret = strtobool(buf, &pwr_down); + if (ret) + return ret; + + if (!pwr_down) { + st->ctrl &= ~(AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI); + } else { + if (st->pwr_down_mode == AD5791_DAC_PWRDN_6K) + st->ctrl |= AD5791_CTRL_OPGND; + else if (st->pwr_down_mode == AD5791_DAC_PWRDN_3STATE) + st->ctrl |= AD5791_CTRL_DACTRI; + } + st->pwr_down = pwr_down; + + ret = ad5791_spi_write(st->spi, AD5791_ADDR_CTRL, st->ctrl); + + return ret ? ret : len; +} + +static int ad5791_get_lin_comp(unsigned int span) +{ + if (span <= 10000) + return AD5791_LINCOMP_0_10; + else if (span <= 12000) + return AD5791_LINCOMP_10_12; + else if (span <= 16000) + return AD5791_LINCOMP_12_16; + else if (span <= 19000) + return AD5791_LINCOMP_16_19; + else + return AD5791_LINCOMP_19_20; +} + +static int ad5780_get_lin_comp(unsigned int span) +{ + if (span <= 10000) + return AD5780_LINCOMP_0_10; + else + return AD5780_LINCOMP_10_20; +} +static const struct ad5791_chip_info ad5791_chip_info_tbl[] = { + [ID_AD5760] = { + .get_lin_comp = ad5780_get_lin_comp, + }, + [ID_AD5780] = { + .get_lin_comp = ad5780_get_lin_comp, + }, + [ID_AD5781] = { + .get_lin_comp = ad5791_get_lin_comp, + }, + [ID_AD5791] = { + .get_lin_comp = ad5791_get_lin_comp, + }, +}; + +static int ad5791_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad5791_state *st = iio_priv(indio_dev); + u64 val64; + int ret; + + switch (m) { + case IIO_CHAN_INFO_RAW: + ret = ad5791_spi_read(st->spi, chan->address, val); + if (ret) + return ret; + *val &= AD5791_DAC_MASK; + *val >>= chan->scan_type.shift; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = (((u64)st->vref_mv) * 1000000ULL) >> chan->scan_type.realbits; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_OFFSET: + val64 = (((u64)st->vref_neg_mv) << chan->scan_type.realbits); + do_div(val64, st->vref_mv); + *val = -val64; + return IIO_VAL_INT; + default: + return -EINVAL; + } + +}; + +static const struct iio_chan_spec_ext_info ad5791_ext_info[] = { + { + .name = "powerdown", + .shared = true, + .read = ad5791_read_dac_powerdown, + .write = ad5791_write_dac_powerdown, + }, + IIO_ENUM("powerdown_mode", true, &ad5791_powerdown_mode_enum), + IIO_ENUM_AVAILABLE("powerdown_mode", &ad5791_powerdown_mode_enum), + { }, +}; + +#define AD5791_CHAN(bits, shift) { \ + .type = IIO_VOLTAGE, \ + .output = 1, \ + .indexed = 1, \ + .address = AD5791_ADDR_DAC0, \ + .channel = 0, \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SHARED_BIT | \ + IIO_CHAN_INFO_OFFSET_SHARED_BIT, \ + .scan_type = IIO_ST('u', bits, 24, shift), \ + .ext_info = ad5791_ext_info, \ +} + +static const struct iio_chan_spec ad5791_channels[] = { + [ID_AD5760] = AD5791_CHAN(16, 4), + [ID_AD5780] = AD5791_CHAN(18, 2), + [ID_AD5781] = AD5791_CHAN(18, 2), + [ID_AD5791] = AD5791_CHAN(20, 0) +}; + +static int ad5791_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad5791_state *st = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + val &= AD5791_RES_MASK(chan->scan_type.realbits); + val <<= chan->scan_type.shift; + + return ad5791_spi_write(st->spi, chan->address, val); + + default: + return -EINVAL; + } +} + +static const struct iio_info ad5791_info = { + .read_raw = &ad5791_read_raw, + .write_raw = &ad5791_write_raw, + .driver_module = THIS_MODULE, +}; + +static int __devinit ad5791_probe(struct spi_device *spi) +{ + struct ad5791_platform_data *pdata = spi->dev.platform_data; + struct iio_dev *indio_dev; + struct ad5791_state *st; + int ret, pos_voltage_uv = 0, neg_voltage_uv = 0; + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) { + ret = -ENOMEM; + goto error_ret; + } + st = iio_priv(indio_dev); + st->reg_vdd = regulator_get(&spi->dev, "vdd"); + if (!IS_ERR(st->reg_vdd)) { + ret = regulator_enable(st->reg_vdd); + if (ret) + goto error_put_reg_pos; + + pos_voltage_uv = regulator_get_voltage(st->reg_vdd); + } + + st->reg_vss = regulator_get(&spi->dev, "vss"); + if (!IS_ERR(st->reg_vss)) { + ret = regulator_enable(st->reg_vss); + if (ret) + goto error_put_reg_neg; + + neg_voltage_uv = regulator_get_voltage(st->reg_vss); + } + + st->pwr_down = true; + st->spi = spi; + + if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd)) { + st->vref_mv = (pos_voltage_uv + neg_voltage_uv) / 1000; + st->vref_neg_mv = neg_voltage_uv / 1000; + } else if (pdata) { + st->vref_mv = pdata->vref_pos_mv + pdata->vref_neg_mv; + st->vref_neg_mv = pdata->vref_neg_mv; + } else { + dev_warn(&spi->dev, "reference voltage unspecified\n"); + } + + ret = ad5791_spi_write(spi, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET); + if (ret) + goto error_disable_reg_neg; + + st->chip_info = &ad5791_chip_info_tbl[spi_get_device_id(spi) + ->driver_data]; + + + st->ctrl = AD5761_CTRL_LINCOMP(st->chip_info->get_lin_comp(st->vref_mv)) + | ((pdata && pdata->use_rbuf_gain2) ? 0 : AD5791_CTRL_RBUF) | + AD5791_CTRL_BIN2SC; + + ret = ad5791_spi_write(spi, AD5791_ADDR_CTRL, st->ctrl | + AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI); + if (ret) + goto error_disable_reg_neg; + + spi_set_drvdata(spi, indio_dev); + indio_dev->dev.parent = &spi->dev; + indio_dev->info = &ad5791_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels + = &ad5791_channels[spi_get_device_id(spi)->driver_data]; + indio_dev->num_channels = 1; + indio_dev->name = spi_get_device_id(st->spi)->name; + ret = iio_device_register(indio_dev); + if (ret) + goto error_disable_reg_neg; + + return 0; + +error_disable_reg_neg: + if (!IS_ERR(st->reg_vss)) + regulator_disable(st->reg_vss); +error_put_reg_neg: + if (!IS_ERR(st->reg_vss)) + regulator_put(st->reg_vss); + + if (!IS_ERR(st->reg_vdd)) + regulator_disable(st->reg_vdd); +error_put_reg_pos: + if (!IS_ERR(st->reg_vdd)) + regulator_put(st->reg_vdd); + iio_device_free(indio_dev); +error_ret: + + return ret; +} + +static int __devexit ad5791_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad5791_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + if (!IS_ERR(st->reg_vdd)) { + regulator_disable(st->reg_vdd); + regulator_put(st->reg_vdd); + } + + if (!IS_ERR(st->reg_vss)) { + regulator_disable(st->reg_vss); + regulator_put(st->reg_vss); + } + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id ad5791_id[] = { + {"ad5760", ID_AD5760}, + {"ad5780", ID_AD5780}, + {"ad5781", ID_AD5781}, + {"ad5790", ID_AD5791}, + {"ad5791", ID_AD5791}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad5791_id); + +static struct spi_driver ad5791_driver = { + .driver = { + .name = "ad5791", + .owner = THIS_MODULE, + }, + .probe = ad5791_probe, + .remove = __devexit_p(ad5791_remove), + .id_table = ad5791_id, +}; +module_spi_driver(ad5791_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c new file mode 100644 index 0000000000000..c3d748c25939c --- /dev/null +++ b/drivers/iio/dac/max517.c @@ -0,0 +1,242 @@ +/* + * max517.c - Support for Maxim MAX517, MAX518 and MAX519 + * + * Copyright (C) 2010, 2011 Roland Stigge + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define MAX517_DRV_NAME "max517" + +/* Commands */ +#define COMMAND_CHANNEL0 0x00 +#define COMMAND_CHANNEL1 0x01 /* for MAX518 and MAX519 */ +#define COMMAND_PD 0x08 /* Power Down */ + +enum max517_device_ids { + ID_MAX517, + ID_MAX518, + ID_MAX519, +}; + +struct max517_data { + struct i2c_client *client; + unsigned short vref_mv[2]; +}; + +/* + * channel: bit 0: channel 1 + * bit 1: channel 2 + * (this way, it's possible to set both channels at once) + */ +static int max517_set_value(struct iio_dev *indio_dev, + long val, int channel) +{ + struct max517_data *data = iio_priv(indio_dev); + struct i2c_client *client = data->client; + u8 outbuf[2]; + int res; + + if (val < 0 || val > 255) + return -EINVAL; + + outbuf[0] = channel; + outbuf[1] = val; + + res = i2c_master_send(client, outbuf, 2); + if (res < 0) + return res; + else if (res != 2) + return -EIO; + else + return 0; +} + +static int max517_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct max517_data *data = iio_priv(indio_dev); + unsigned int scale_uv; + + switch (m) { + case IIO_CHAN_INFO_SCALE: + /* Corresponds to Vref / 2^(bits) */ + scale_uv = (data->vref_mv[chan->channel] * 1000) >> 8; + *val = scale_uv / 1000000; + *val2 = scale_uv % 1000000; + return IIO_VAL_INT_PLUS_MICRO; + default: + break; + } + return -EINVAL; +} + +static int max517_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long mask) +{ + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = max517_set_value(indio_dev, val, chan->channel); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +#ifdef CONFIG_PM_SLEEP +static int max517_suspend(struct device *dev) +{ + u8 outbuf = COMMAND_PD; + + return i2c_master_send(to_i2c_client(dev), &outbuf, 1); +} + +static int max517_resume(struct device *dev) +{ + u8 outbuf = 0; + + return i2c_master_send(to_i2c_client(dev), &outbuf, 1); +} + +static SIMPLE_DEV_PM_OPS(max517_pm_ops, max517_suspend, max517_resume); +#define MAX517_PM_OPS (&max517_pm_ops) +#else +#define MAX517_PM_OPS NULL +#endif + +static const struct iio_info max517_info = { + .read_raw = max517_read_raw, + .write_raw = max517_write_raw, + .driver_module = THIS_MODULE, +}; + +#define MAX517_CHANNEL(chan) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (chan), \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ + .scan_type = IIO_ST('u', 8, 8, 0), \ +} + +static const struct iio_chan_spec max517_channels[] = { + MAX517_CHANNEL(0), + MAX517_CHANNEL(1) +}; + +static int __devinit max517_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct max517_data *data; + struct iio_dev *indio_dev; + struct max517_platform_data *platform_data = client->dev.platform_data; + int err; + + indio_dev = iio_device_alloc(sizeof(*data)); + if (indio_dev == NULL) { + err = -ENOMEM; + goto exit; + } + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + + /* establish that the iio_dev is a child of the i2c device */ + indio_dev->dev.parent = &client->dev; + + /* reduced channel set for MAX517 */ + if (id->driver_data == ID_MAX517) + indio_dev->num_channels = 1; + else + indio_dev->num_channels = 2; + indio_dev->channels = max517_channels; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &max517_info; + + /* + * Reference voltage on MAX518 and default is 5V, else take vref_mv + * from platform_data + */ + if (id->driver_data == ID_MAX518 || !platform_data) { + data->vref_mv[0] = data->vref_mv[1] = 5000; /* mV */ + } else { + data->vref_mv[0] = platform_data->vref_mv[0]; + data->vref_mv[1] = platform_data->vref_mv[1]; + } + + err = iio_device_register(indio_dev); + if (err) + goto exit_free_device; + + dev_info(&client->dev, "DAC registered\n"); + + return 0; + +exit_free_device: + iio_device_free(indio_dev); +exit: + return err; +} + +static int __devexit max517_remove(struct i2c_client *client) +{ + iio_device_unregister(i2c_get_clientdata(client)); + iio_device_free(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id max517_id[] = { + { "max517", ID_MAX517 }, + { "max518", ID_MAX518 }, + { "max519", ID_MAX519 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max517_id); + +static struct i2c_driver max517_driver = { + .driver = { + .name = MAX517_DRV_NAME, + .pm = MAX517_PM_OPS, + }, + .probe = max517_probe, + .remove = __devexit_p(max517_remove), + .id_table = max517_id, +}; +module_i2c_driver(max517_driver); + +MODULE_AUTHOR("Roland Stigge "); +MODULE_DESCRIPTION("MAX517/MAX518/MAX519 8-bit DAC"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c new file mode 100644 index 0000000000000..e0e168bd5b459 --- /dev/null +++ b/drivers/iio/dac/mcp4725.c @@ -0,0 +1,227 @@ +/* + * mcp4725.c - Support for Microchip MCP4725 + * + * Copyright (C) 2012 Peter Meerwald + * + * Based on max517 by Roland Stigge + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * driver for the Microchip I2C 12-bit digital-to-analog converter (DAC) + * (7-bit I2C slave address 0x60, the three LSBs can be configured in + * hardware) + * + * writing the DAC value to EEPROM is not supported + */ + +#include +#include +#include +#include + +#include +#include + +#include + +#define MCP4725_DRV_NAME "mcp4725" + +struct mcp4725_data { + struct i2c_client *client; + u16 vref_mv; + u16 dac_value; +}; + +#ifdef CONFIG_PM_SLEEP +static int mcp4725_suspend(struct device *dev) +{ + u8 outbuf[2]; + + outbuf[0] = 0x3 << 4; /* power-down bits, 500 kOhm resistor */ + outbuf[1] = 0; + + return i2c_master_send(to_i2c_client(dev), outbuf, 2); +} + +static int mcp4725_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct mcp4725_data *data = iio_priv(indio_dev); + u8 outbuf[2]; + + /* restore previous DAC value */ + outbuf[0] = (data->dac_value >> 8) & 0xf; + outbuf[1] = data->dac_value & 0xff; + + return i2c_master_send(to_i2c_client(dev), outbuf, 2); +} + +static SIMPLE_DEV_PM_OPS(mcp4725_pm_ops, mcp4725_suspend, mcp4725_resume); +#define MCP4725_PM_OPS (&mcp4725_pm_ops) +#else +#define MCP4725_PM_OPS NULL +#endif + +static const struct iio_chan_spec mcp4725_channel = { + .type = IIO_VOLTAGE, + .indexed = 1, + .output = 1, + .channel = 0, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, + .scan_type = IIO_ST('u', 12, 16, 0), +}; + +static int mcp4725_set_value(struct iio_dev *indio_dev, int val) +{ + struct mcp4725_data *data = iio_priv(indio_dev); + u8 outbuf[2]; + int ret; + + if (val >= (1 << 12) || val < 0) + return -EINVAL; + + outbuf[0] = (val >> 8) & 0xf; + outbuf[1] = val & 0xff; + + ret = i2c_master_send(data->client, outbuf, 2); + if (ret < 0) + return ret; + else if (ret != 2) + return -EIO; + else + return 0; +} + +static int mcp4725_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct mcp4725_data *data = iio_priv(indio_dev); + unsigned long scale_uv; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + *val = data->dac_value; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + scale_uv = (data->vref_mv * 1000) >> 12; + *val = scale_uv / 1000000; + *val2 = scale_uv % 1000000; + return IIO_VAL_INT_PLUS_MICRO; + } + return -EINVAL; +} + +static int mcp4725_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct mcp4725_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = mcp4725_set_value(indio_dev, val); + data->dac_value = val; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static const struct iio_info mcp4725_info = { + .read_raw = mcp4725_read_raw, + .write_raw = mcp4725_write_raw, + .driver_module = THIS_MODULE, +}; + +static int __devinit mcp4725_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct mcp4725_data *data; + struct iio_dev *indio_dev; + struct mcp4725_platform_data *platform_data = client->dev.platform_data; + u8 inbuf[3]; + int err; + + if (!platform_data || !platform_data->vref_mv) { + dev_err(&client->dev, "invalid platform data"); + err = -EINVAL; + goto exit; + } + + indio_dev = iio_device_alloc(sizeof(*data)); + if (indio_dev == NULL) { + err = -ENOMEM; + goto exit; + } + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &mcp4725_info; + indio_dev->channels = &mcp4725_channel; + indio_dev->num_channels = 1; + indio_dev->modes = INDIO_DIRECT_MODE; + + data->vref_mv = platform_data->vref_mv; + + /* read current DAC value */ + err = i2c_master_recv(client, inbuf, 3); + if (err < 0) { + dev_err(&client->dev, "failed to read DAC value"); + goto exit_free_device; + } + data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4); + + err = iio_device_register(indio_dev); + if (err) + goto exit_free_device; + + dev_info(&client->dev, "MCP4725 DAC registered\n"); + + return 0; + +exit_free_device: + iio_device_free(indio_dev); +exit: + return err; +} + +static int __devexit mcp4725_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + iio_device_free(indio_dev); + + return 0; +} + +static const struct i2c_device_id mcp4725_id[] = { + { "mcp4725", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mcp4725_id); + +static struct i2c_driver mcp4725_driver = { + .driver = { + .name = MCP4725_DRV_NAME, + .pm = MCP4725_PM_OPS, + }, + .probe = mcp4725_probe, + .remove = __devexit_p(mcp4725_remove), + .id_table = mcp4725_id, +}; +module_i2c_driver(mcp4725_driver); + +MODULE_AUTHOR("Peter Meerwald "); +MODULE_DESCRIPTION("MCP4725 12-bit DAC"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/frequency/Kconfig b/drivers/iio/frequency/Kconfig new file mode 100644 index 0000000000000..51292bd080cba --- /dev/null +++ b/drivers/iio/frequency/Kconfig @@ -0,0 +1,69 @@ +# +# Frequency +# Direct Digital Synthesis drivers (DDS) +# Clock Distribution device drivers +# Phase-Locked Loop (PLL) frequency synthesizers +# + +menu "Frequency Synthesizers DDS/PLL" + +menu "Clock Generator/Distribution" + +config AD9523 + tristate "Analog Devices AD9523 Low Jitter Clock Generator" + depends on SPI + help + Say yes here to build support for Analog Devices AD9523 Low Jitter + Clock Generator. The driver provides direct access via sysfs. + + To compile this driver as a module, choose M here: the + module will be called ad9523. + +config AD9548 + tristate "Analog Devices AD9548 Network Clock Generator/Synchronizer" + depends on SPI + help + Say yes here to build support for Analog Devices AD9548 + Quad/Octal Input Network Clock Generator/Synchronizer. + + To compile this driver as a module, choose M here: the + module will be called ad9548. + +endmenu + +menu "Direct Digital Synthesis" + +config CF_AXI_DDS + tristate "Analog Devices CoreFPGA AXI DDS driver" + depends on SPI + help + Say yes here to build support for Analog Devices DDS chip + AD9122, provides direct access via sysfs. + +config CF_AXI_DDS_AD9122 + tristate "Analog Devices AD9122 DAC" + depends on CF_AXI_DDS + help + Say yes here to build support for Analog Devices AD9122 DAC chip + ad9122, provides direct access via sysfs. + +endmenu + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# + +menu "Phase-Locked Loop (PLL) frequency synthesizers" + +config ADF4350 + tristate "Analog Devices ADF4350/ADF4351 Wideband Synthesizers" + depends on SPI + help + Say yes here to build support for Analog Devices ADF4350/ADF4351 + Wideband Synthesizers. The driver provides direct access via sysfs. + + To compile this driver as a module, choose M here: the + module will be called adf4350. + +endmenu +endmenu diff --git a/drivers/iio/frequency/Makefile b/drivers/iio/frequency/Makefile new file mode 100644 index 0000000000000..1e6fa5b9229be --- /dev/null +++ b/drivers/iio/frequency/Makefile @@ -0,0 +1,9 @@ +# +# Makefile iio/frequency +# + +obj-$(CONFIG_AD9548) += ad9548.o +obj-$(CONFIG_AD9523) += ad9523.o +obj-$(CONFIG_ADF4350) += adf4350.o +obj-$(CONFIG_CF_AXI_DDS) += cf_axi_dds.o +obj-$(CONFIG_CF_AXI_DDS_AD9122) += ad9122.o diff --git a/drivers/iio/frequency/ad9122.c b/drivers/iio/frequency/ad9122.c new file mode 100644 index 0000000000000..2faa9ad66ce89 --- /dev/null +++ b/drivers/iio/frequency/ad9122.c @@ -0,0 +1,471 @@ +/* + * AD9122 SPI DAC driver for AXI DDS PCORE/COREFPGA Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "cf_axi_dds.h" + +/* Registers */ +#define AD9122_REG_COMM 0x00 +#define AD9122_REG_POWER_CTRL 0x01 +#define AD9122_REG_DATA_FORMAT 0x03 +#define AD9122_REG_INTERRUPT_EN_1 0x04 +#define AD9122_REG_INTERRUPT_EN_2 0x05 +#define AD9122_REG_EVENT_FLAG_1 0x06 +#define AD9122_REG_EVENT_FLAG_2 0x07 +#define AD9122_REG_CLK_REC_CTRL 0x08 +#define AD9122_REG_PLL_CTRL_1 0x0A +#define AD9122_REG_PLL_CTRL_2 0x0C +#define AD9122_REG_PLL_CTRL_3 0x0D +#define AD9122_REG_PLL_STATUS_1 0x0E +#define AD9122_REG_PLL_STATUS_2 0x0F +#define AD9122_REG_SYNC_CTRL_1 0x10 +#define AD9122_REG_SYNC_CTRL_2 0x11 +#define AD9122_REG_SYNC_STATUS_1 0x12 +#define AD9122_REG_SYNC_STATUS_2 0x13 +#define AD9122_REG_DATA_REC_STATUS 0x15 +#define AD9122_REG_DCI_DELAY 0x16 +#define AD9122_REG_FIFO_CTRL 0x17 +#define AD9122_REG_FIFO_STATUS_1 0x18 +#define AD9122_REG_FIFO_STATUS_2 0x19 +#define AD9122_REG_DATAPATH_CTRL 0x1B +#define AD9122_REG_HB1_CTRL 0x1C +#define AD9122_REG_HB2_CTRL 0x1D +#define AD9122_REG_HB3_CTRL 0x1E +#define AD9122_REG_CHIP_ID 0x1F +#define AD9122_REG_FTW_7_0 0x30 +#define AD9122_REG_FTW_15_8 0x31 +#define AD9122_REG_FTW_23_16 0x32 +#define AD9122_REG_FTW_31_24 0x33 +#define AD9122_REG_NCO_PHA_OFFSET_LSB 0x34 +#define AD9122_REG_NCO_PHA_OFFSET_MSB 0x35 +#define AD9122_REG_NCO_FTW_UPDATE 0x36 +#define AD9122_REG_I_PHA_ADJ_LSB 0x38 +#define AD9122_REG_I_PHA_ADJ_MSB 0x39 +#define AD9122_REG_Q_PHA_ADJ_LSB 0x3A +#define AD9122_REG_Q_PHA_ADJ_MSB 0x3B +#define AD9122_REG_I_DAC_OFFSET_LSB 0x3C +#define AD9122_REG_I_DAC_OFFSET_MSB 0x3D +#define AD9122_REG_Q_DAC_OFFSET_LSB 0x3E +#define AD9122_REG_Q_DAC_OFFSET_MSB 0x3F +#define AD9122_REG_I_DAC_FS_ADJ 0x40 +#define AD9122_REG_I_DAC_CTRL 0x41 +#define AD9122_REG_I_AUX_DAC_DATA 0x42 +#define AD9122_REG_I_AUX_DAC_CTRL 0x43 +#define AD9122_REG_Q_DAC_FS_ADJ 0x44 +#define AD9122_REG_Q_DAC_CTRL 0x45 +#define AD9122_REG_Q_AUX_DAC_DATA 0x46 +#define AD9122_REG_Q_AUX_DAC_CTRL 0x47 +#define AD9122_REG_DIE_TEMP_RANGE_CTRL 0x48 +#define AD9122_REG_DIE_TEMP_LSB 0x49 +#define AD9122_REG_DIE_TEMP_MSB 0x4A +#define AD9122_REG_SED_CTRL 0x67 +#define AD9122_REG_COMPARE_I0_LSBS 0x68 +#define AD9122_REG_COMPARE_I0_MSBS 0x69 +#define AD9122_REG_COMPARE_Q0_LSBS 0x6A +#define AD9122_REG_COMPARE_Q0_MSBS 0x6B +#define AD9122_REG_COMPARE_I1_LSBS 0x6C +#define AD9122_REG_COMPARE_I1_MSBS 0x6D +#define AD9122_REG_COMPARE_Q1_LSBS 0x6E +#define AD9122_REG_COMPARE_Q1_MSBS 0x6F +#define AD9122_REG_SED_I_LSBS 0x70 +#define AD9122_REG_SED_I_MSBS 0x71 +#define AD9122_REG_SED_Q_LSBS 0x72 +#define AD9122_REG_SED_Q_MSBS 0x73 +#define AD9122_REG_REVISION 0x7F + +/* AD9122_REG_COMM definitions */ +#define AD9122_COMM_SDIO (1 << 7) +#define AD9122_COMM_LSB_FIRST (1 << 6) +#define AD9122_COMM_RESET (1 << 5) + +/* AD9122_REG_POWER_CTRL definitions */ +#define AD9122_POWER_CTRL_PD_I_DAC (1 << 7) +#define AD9122_POWER_CTRL_PD_Q_DAC (1 << 6) +#define AD9122_POWER_CTRL_PD_DATA_REC (1 << 5) +#define AD9122_POWER_CTRL_PD_AUX_ADC (1 << 4) + +/* AD9122_REG_DATA_FORMAT definitions */ +#define AD9122_DATA_FORMAT_BINARY (1 << 7) +#define AD9122_DATA_FORMAT_Q_DATA_FIRST (1 << 6) +#define AD9122_DATA_FORMAT_MSB_SWAP (1 << 5) +#define AD9122_DATA_FORMAT_BUS_WIDTH(x) (((x) & 0x3) << 0) + +/* AD9122_REG_INTERRUPT_EN_1 definitions */ +#define AD9122_INTERRUPT_EN_1_EN_PLL_LOCK_LOST (1 << 7) +#define AD9122_INTERRUPT_EN_1_EN_PLL_LOCKED (1 << 6) +#define AD9122_INTERRUPT_EN_1_EN_SYNC_SIGNAL_LOST (1 << 5) +#define AD9122_INTERRUPT_EN_1_EN_SYNC_SIGNAL_LOCKED (1 << 4) +#define AD9122_INTERRUPT_EN_1_EN_FIFO_WARNING_1 (1 << 1) +#define AD9122_INTERRUPT_EN_1_EN_FIFO_WARNING_2 (1 << 0) + +/* AD9122_REG_INTERRUPT_EN_2 definitions */ +#define AD9122_INTERRUPT_EN_2_EN_AED_COMPARE_PASS (1 << 4) +#define AD9122_INTERRUPT_EN_2_EN_AED_COMPARE_FAIL (1 << 3) +#define AD9122_INTERRUPT_EN_2_EN_SED_COMPARE_FAIL (1 << 2) + +/* AD9122_REG_EVENT_FLAG_1 definitions */ +#define AD9122_EVENT_FLAG_1_PLL_LOCK_LOST (1 << 7) +#define AD9122_EVENT_FLAG_1_PLL_LOCKED (1 << 6) +#define AD9122_EVENT_FLAG_1_SYNC_SIGNAL_LOST (1 << 5) +#define AD9122_EVENT_FLAG_1_SYNC_SIGNAL_LOCKED (1 << 4) +#define AD9122_EVENT_FLAG_1_FIFO_WARNING_1 (1 << 1) +#define AD9122_EVENT_FLAG_1_FIFO_WARNING_2 (1 << 0) + +/* AD9122_REG_EVENT_FLAG_2 definitions */ +#define AD9122_EVENT_FLAG_2_AED_COMPARE_PASS (1 << 4) +#define AD9122_EVENT_FLAG_2_AED_COMPARE_FAIL (1 << 3) +#define AD9122_EVENT_FLAG_2_SED_COMPARE_FAIL (1 << 2) + +/* AD9122_REG_CLK_REC_CTRL definitions */ +#define AD9122_CLK_REC_CTRL_DACCLK_DUTY_CORRECTION (1 << 7) +#define AD9122_CLK_REC_CTRL_REFCLK_DUTY_CORRECTION (1 << 6) +#define AD9122_CLK_REC_CTRL_DACCLK_CROSS_CORRECTION (1 << 5) +#define AD9122_CLK_REC_CTRL_REFCLK_CROSS_CORRECTION (1 << 4) + +/* AD9122_REG_PLL_CTRL_1 definitions */ +#define AD9122_PLL_CTRL_1_PLL_EN (1 << 7) +#define AD9122_PLL_CTRL_1_PLL_MANUAL_EN (1 << 6) +#define AD9122_PLL_CTRL_1_MANUAL_VCO_BAND(x) ((x) & 0x3F) << 0) + +/* AD9122_REG_PLL_CTRL_2 definitions */ +#define AD9122_PLL_CTRL_2_PLL_LOOP_BANDWIDTH(x) (((x) & 0x3) << 6) +#define AD9122_PLL_CTRL_2_PLL_CHARGE_PUMP_CURRENT(x) (((x) & 0x1F) << 0) + +/* AD9122_REG_PLL_CTRL_3 definitions */ +#define AD9122_PLL_CTRL_3_N2(x) (((x) & 0x3) << 6) +#define AD9122_PLL_CTRL_3_PLL_CROSS_CTRL_EN (1 << 4) +#define AD9122_PLL_CTRL_3_N0(x) (((x) & 0x3) << 2) +#define AD9122_PLL_CTRL_3_N1(x) (((x) & 0x3) << 0) + +/* AD9122_REG_PLL_STATUS_1 definitions */ +#define AD9122_PLL_STATUS_1_PLL_LOCKED (1 << 7) +#define AD9122_PLL_STATUS_1_VCO_CTRL_VOLTAGE(x) (((x) & 0xF) << 0) + +/* AD9122_REG_PLL_STATUS_2 definitions */ +#define AD9122_PLL_STATUS_2_VCO_BAND_READBACK(x) (((x) & 0x3F) << 0) + +/* AD9122_REG_SYNC_CTRL_1 definitions */ +#define AD9122_SYNC_CTRL_1_SYNC_EN (1 << 7) +#define AD9122_SYNC_CTRL_1_DATA_FIFO_RATE_TOGGLE (1 << 6) +#define AD9122_SYNC_CTRL_1_RISING_EDGE_SYNC (1 << 3) +#define AD9122_SYNC_CTRL_1_SYNC_AVERAGING(x) (((x) & 0x7) << 0) + +/* AD9122_REG_SYNC_CTRL_2 definitions */ +#define AD9122_SYNC_CTRL_2_SYNC_PHA_REQUEST(x) (((x) & 0x3F) << 0) + +/* AD9122_REG_SYNC_STATUS_1 definitions */ +#define AD9122_SYNC_STATUS_1_SYNC_LOST (1 << 7) +#define AD9122_SYNC_STATUS_1_SYNC_LOCKED (1 << 6) + +/* AD9122_REG_SYNC_STATUS_2 definitions */ +#define AD9122_SYNC_STATUS_2_SYNC_PHA_READBACK (((x) & 0xFF) << 0) + +/* AD9122_REG_DATA_REC_STATUS definitions */ +#define AD9122_DATA_REC_STATUS_LVDS_FRAME_LEVEL_H (1 << 5) +#define AD9122_DATA_REC_STATUS_LVDS_FRAME_LEVEL_L (1 << 4) +#define AD9122_DATA_REC_STATUS_LVDS_DCI_LEVEL_H (1 << 3) +#define AD9122_DATA_REC_STATUS_LVDS_DCI_LEVEL_L (1 << 2) +#define AD9122_DATA_REC_STATUS_LVDS_DATA_LEVEL_H (1 << 1) +#define AD9122_DATA_REC_STATUS_LVDS_DATA_LEVEL_L (1 << 0) + +/* AD9122_REG_DCI_DELAY definitions */ +#define AD9122_DCI_DELAY_DCI_DELAY(x) (((x) & 0x3) << 0) + +/* AD9122_REG_FIFO_CTRL definitions */ +#define AD9122_FIFO_CTRL_FIFO_PHA_OFFSET(x) (((x) & 0x7) << 0) + +/* AD9122_REG_FIFO_STATUS_1 definitions */ +#define AD9122_FIFO_STATUS_1_FIFO_WARNING_1 (1 << 7) +#define AD9122_FIFO_STATUS_1_FIFO_WARNING_2 (1 << 6) +#define AD9122_FIFO_STATUS_1_FIFO_SOFT_ALIGN_ACK (1 << 2) +#define AD9122_FIFO_STATUS_1_FIFO_SOFT_ALIGN_REQ (1 << 1) + +/* AD9122_REG_FIFO_STATUS_2 definitions */ +#define AD9122_FIFO_STATUS_2_FIFO_LEVEL (((x) & 0xFF) << 0) + +/* AD9122_REG_DATAPATH_CTRL definitions */ +#define AD9122_DATAPATH_CTRL_BYPASS_PREMOD (1 << 7) +#define AD9122_DATAPATH_CTRL_BYPASS_INV_SINC (1 << 6) +#define AD9122_DATAPATH_CTRL_BYPASS_NCO (1 << 5) +#define AD9122_DATAPATH_CTRL_NCO_GAIN (1 << 3) +#define AD9122_DATAPATH_CTRL_BYPASS_PHA_COMP_DC_OFFSET (1 << 2) +#define AD9122_DATAPATH_CTRL_SELECT_SIDEBAND (1 << 1) +#define AD9122_DATAPATH_CTRL_SEND_I_DATA_TO_Q_DATA (1 << 0) + +/* AD9122_REG_HB1_CTRL definitions */ +#define AD9122_HB1_CTRL_HB1(x) (((x) & 0x3) << 1) +#define AD9122_HB1_CTRL_BYPASS_HB1 (1 << 0) + +/* AD9122_REG_HB2_CTRL definitions */ +#define AD9122_HB2_CTRL_HB2(x) (((x) & 0x3F) << 1) +#define AD9122_HB2_CTRL_BYPASS_HB2 (1 << 0) + +/* AD9122_REG_HB3_CTRL definitions */ +#define AD9122_HB3_CTRL_HB3(x) (((x) & 0x3F) << 1) +#define AD9122_HB3_CTRL_BYPASS_HB3 (1 << 0) + +/* Value of AD9122_REG_CHIP_ID */ +#define AD9122_CHIP_ID 0x08 + +/* AD9122_REG_NCO_FTW_UPDATE definitions */ +#define AD9122_NCO_FTW_UPDATE_FRAME_FTW_ACK (1 << 5) +#define AD9122_NCO_FTW_UPDATE_FRAME_FTW_REQ (1 << 4) +#define AD9122_NCO_FTW_UPDATE_UPDATE_FTW_ACK (1 << 1) +#define AD9122_NCO_FTW_UPDATE_UPDATE_FTW_REQ (1 << 0) + +/* AD9122_REG_I_PHA_ADJ_LSB definitions */ +#define AD9122_REG_I_PHA_ADJ_7_0(x) (((x) & 0xFF) << 0) + +/* AD9122_REG_I_PHA_ADJ_MSB definitions */ +#define AD9122_REG_I_PHA_ADJ_9_8(x) (((x) & 0x3) << 0) + +/* AD9122_REG_Q_PHA_ADJ_LSB definitions */ +#define AD9122_REG_Q_PHA_ADJ_7_0(x) (((x) & 0xFF) << 0) + +/* AD9122_REG_Q_PHA_ADJ_MSB definitions */ +#define AD9122_REG_Q_PHA_ADJ_9_8(x) (((x) & 0x3) << 0) + +/* AD9122_REG_I_DAC_FS_ADJ definitions */ +#define AD9122_I_DAC_FS_ADJ_I_DAC_FS_ADJ_7_0(x) (((x) & 0xFF) << 0) + +/* AD9122_I_DAC_CTRL definitions */ +#define AD9122_I_DAC_CTRL_I_DAC_SLEEP (1 << 7) +#define AD9122_I_DAC_CTRL_I_DAC_FS_ADJ_9_8(x) (((x) & 0x3) << 0) + +/* AD9122_REG_I_AUX_DAC_DATA definitions */ +#define AD9122_I_AUX_DAC_DATA_I_AUX_DAC_7_0 (((x) & 0xFF) << 0) + +/* AD9122_REG_I_AUX_DAC_CTRL definitions */ +#define AD9122_I_AUX_DAC_CTRL_I_AUX_DAC_SIGN (1 << 7) +#define AD9122_I_AUX_DAC_CTRL_I_AUX_DAC_CURRENT_DIR (1 << 6) +#define AD9122_I_AUX_DAC_CTRL_I_AUX_DAC_SLEEP (1 << 5) +#define AD9122_I_AUX_DAC_CTRL_I_AUX_DAC_9_8(x) (((x) & 0x3) << 0) + +/* AD9122_REG_Q_DAC_FS_ADJ definitions */ +#define AD9122_Q_DAC_FS_ADJ_Q_DAC_FS_ADJ_7_0(x) (((x) & 0xFF) << 0) + +/* AD9122_Q_DAC_CTRL definitions */ +#define AD9122_Q_DAC_CTRL_Q_DAC_SLEEP (1 << 7) +#define AD9122_Q_DAC_CTRL_Q_DAC_FS_ADJ_9_8(x) (((x) & 0x3) << 0) + +/* AD9122_REG_Q_AUX_DAC_DATA definitions */ +#define AD9122_Q_AUX_DAC_DATA_Q_AUX_DAC_7_0 (((x) & 0xFF) << 0) + +/* AD9122_REG_Q_AUX_DAC_CTRL definitions */ +#define AD9122_Q_AUX_DAC_CTRL_Q_AUX_DAC_SIGN (1 << 7) +#define AD9122_Q_AUX_DAC_CTRL_Q_AUX_DAC_CURRENT_DIR (1 << 6) +#define AD9122_Q_AUX_DAC_CTRL_Q_AUX_DAC_SLEEP (1 << 5) +#define AD9122_Q_AUX_DAC_CTRL_Q_AUX_DAC_9_8(x) (((x) & 0x3) << 0) + +/* AD9122_REG_DIE_TEMP_RANGE_CTRL definitions */ +#define AD9122_DIE_TEMP_RANGE_CTRL_FS_CURRENT(x) (((x) & 0x7) << 4) +#define AD9122_DIE_TEMP_RANGE_CTRL_REF_CURRENT(x) (((x) & 0x7) << 1) +#define AD9122_DIE_TEMP_RANGE_CTRL_CAP_VALUE (1 << 0) + +/* AD9122_REG_SED_CTRL definitions */ +#define AD9122_SED_CTRL_SED_COMPARE_EN (1 << 7) +#define AD9122_SED_CTRL_SAMPLE_ERR_DETECTED (1 << 5) +#define AD9122_SED_CTRL_AUTOCLEAR_EN (1 << 3) +#define AD9122_SED_CTRL_COMPARE_FAIL (1 << 1) +#define AD9122_SED_CTRL_COMPARE_PASS (1 << 0) + +/* Values of AD9122_REG_REVISION */ +#define AD9122_DIE_REV_1 0x1 +#define AD9122_DIE_REV_2 0x3 + +#define CHIPID_AD9122 0x8 + +static const unsigned char ad9122_reg_defaults[][2] = { + {AD9122_REG_COMM, 0x00}, + {AD9122_REG_COMM, AD9122_COMM_RESET}, + {AD9122_REG_COMM, 0x00}, + {AD9122_REG_POWER_CTRL, AD9122_POWER_CTRL_PD_AUX_ADC}, + {AD9122_REG_DATA_FORMAT, AD9122_DATA_FORMAT_BINARY}, + {AD9122_REG_INTERRUPT_EN_1, 0x00}, + {AD9122_REG_INTERRUPT_EN_2, 0x00}, + {AD9122_REG_CLK_REC_CTRL, AD9122_CLK_REC_CTRL_DACCLK_CROSS_CORRECTION | + AD9122_CLK_REC_CTRL_REFCLK_CROSS_CORRECTION | + 0xF}, + {AD9122_REG_PLL_CTRL_1, AD9122_PLL_CTRL_1_PLL_MANUAL_EN}, + {AD9122_REG_PLL_CTRL_2, AD9122_PLL_CTRL_2_PLL_LOOP_BANDWIDTH(3) | + AD9122_PLL_CTRL_2_PLL_CHARGE_PUMP_CURRENT(0x11)}, + {AD9122_REG_PLL_CTRL_3, AD9122_PLL_CTRL_3_N2(3) | + AD9122_PLL_CTRL_3_PLL_CROSS_CTRL_EN | + AD9122_PLL_CTRL_3_N0(1) | + AD9122_PLL_CTRL_3_N1(2)}, + {AD9122_REG_SYNC_CTRL_1, AD9122_SYNC_CTRL_1_DATA_FIFO_RATE_TOGGLE | + AD9122_SYNC_CTRL_1_RISING_EDGE_SYNC}, + {AD9122_REG_SYNC_CTRL_2, 0x00}, + {AD9122_REG_DCI_DELAY, 0x00}, + {AD9122_REG_FIFO_CTRL, AD9122_FIFO_CTRL_FIFO_PHA_OFFSET(4)}, + {AD9122_REG_FIFO_STATUS_1, 0x00}, + {AD9122_REG_DATAPATH_CTRL, AD9122_DATAPATH_CTRL_BYPASS_PREMOD | + AD9122_DATAPATH_CTRL_BYPASS_INV_SINC | + AD9122_DATAPATH_CTRL_BYPASS_NCO}, + {AD9122_REG_HB1_CTRL, AD9122_HB1_CTRL_BYPASS_HB1}, + {AD9122_REG_HB2_CTRL, AD9122_HB2_CTRL_BYPASS_HB2}, + {AD9122_REG_HB3_CTRL, AD9122_HB3_CTRL_BYPASS_HB3}, + {AD9122_REG_FTW_7_0, 0x00}, + {AD9122_REG_FTW_15_8, 0x00}, + {AD9122_REG_FTW_23_16, 0x00}, + {AD9122_REG_FTW_31_24, 0x00}, + {AD9122_REG_NCO_PHA_OFFSET_LSB, 0x00}, + {AD9122_REG_NCO_PHA_OFFSET_MSB, 0x00}, + {AD9122_REG_NCO_FTW_UPDATE, 0x00}, + {AD9122_REG_I_PHA_ADJ_LSB, 0x00}, + {AD9122_REG_I_PHA_ADJ_MSB, 0x00}, + {AD9122_REG_Q_PHA_ADJ_LSB, 0x00}, + {AD9122_REG_Q_PHA_ADJ_MSB, 0x00}, + {AD9122_REG_I_DAC_OFFSET_LSB, 0x00}, + {AD9122_REG_I_DAC_OFFSET_MSB, 0x00}, + {AD9122_REG_Q_DAC_OFFSET_LSB, 0x00}, + {AD9122_REG_Q_DAC_OFFSET_MSB, 0x00}, + {AD9122_REG_I_DAC_FS_ADJ, 0xF9}, + {AD9122_REG_I_DAC_CTRL, 0x01}, + {AD9122_REG_I_AUX_DAC_DATA, 0x00}, + {AD9122_REG_I_AUX_DAC_CTRL, 0x00}, + {AD9122_REG_Q_DAC_FS_ADJ, 0xF9}, + {AD9122_REG_Q_DAC_CTRL, 0x01}, + {AD9122_REG_Q_AUX_DAC_DATA, 0x00}, + {AD9122_REG_Q_AUX_DAC_CTRL, 0x00}, + {AD9122_REG_DIE_TEMP_RANGE_CTRL, AD9122_DIE_TEMP_RANGE_CTRL_REF_CURRENT(1)}, + {AD9122_REG_FIFO_STATUS_1, AD9122_FIFO_STATUS_1_FIFO_SOFT_ALIGN_REQ}, +}; + +static int ad9122_read(struct spi_device *spi, unsigned reg) +{ + unsigned char buf[2]; + int ret; + + buf[0] = 0x80 | reg; + + ret = spi_write_then_read(spi, &buf[0], 1, &buf[1], 1); + if (ret < 0) + return ret; + + return buf[1]; +} + +static int ad9122_write(struct spi_device *spi, + unsigned reg, unsigned val) +{ + unsigned char buf[2]; + int ret; + + buf[0] = reg; + buf[1] = val; + ret = spi_write_then_read(spi, buf, 2, NULL, 0); + if (ret < 0) + return ret; + + return 0; +} + +static int ad9122_setup(struct spi_device *spi, unsigned mode) +{ + int ret, timeout, i; + + for (i = 0; i < ARRAY_SIZE(ad9122_reg_defaults); i++) + ad9122_write(spi, ad9122_reg_defaults[i][0], + ad9122_reg_defaults[i][1]); + timeout = 255; + do { + mdelay(1); + ret = ad9122_read(spi, AD9122_REG_FIFO_STATUS_1); + if (ret < 0) + return ret; + + } while (timeout-- && !(ret & AD9122_FIFO_STATUS_1_FIFO_SOFT_ALIGN_ACK)); + + ad9122_write(spi, AD9122_REG_FIFO_STATUS_1, 0x0); + ad9122_write(spi, AD9122_REG_SYNC_CTRL_1, + AD9122_SYNC_CTRL_1_SYNC_EN | + AD9122_SYNC_CTRL_1_RISING_EDGE_SYNC); + + timeout = 255; + do { + mdelay(1); + ret = ad9122_read(spi, AD9122_REG_SYNC_STATUS_1); + if (ret < 0) + return ret; + + } while (timeout-- && !(ret & AD9122_SYNC_STATUS_1_SYNC_LOCKED)); + + return 0; +} + +static int __devinit ad9122_probe(struct spi_device *spi) +{ + struct cf_axi_dds_converter *conv; + unsigned id; + int ret; + + conv = kzalloc(sizeof(*conv), GFP_KERNEL); + if (conv == NULL) + return -ENOMEM; + + + id = ad9122_read(spi, AD9122_REG_CHIP_ID); + if (id != CHIPID_AD9122) { + dev_err(&spi->dev, "Unrecognized CHIP_ID 0x%X\n", id); + ret = -ENODEV; + goto out; + } + + conv->write = ad9122_write; + conv->read = ad9122_read; + conv->setup = ad9122_setup; + conv->spi = spi; + conv->id = ID_AD9122; + spi_set_drvdata(spi, conv); + + return 0; +out: + kfree(conv); + return ret; +} + +static int ad9122_remove(struct spi_device *spi) +{ + struct cf_axi_dds_converter *conv = spi_get_drvdata(spi); + + spi_set_drvdata(spi, NULL); + kfree(conv); + + return 0; +} + +static const struct spi_device_id ad9122_id[] = { + {"ad9122", 0}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad9122_id); + +static struct spi_driver ad9122_driver = { + .driver = { + .name = "ad9122", + .owner = THIS_MODULE, + }, + .probe = ad9122_probe, + .remove = __devexit_p(ad9122_remove), + .id_table = ad9122_id, +}; +module_spi_driver(ad9122_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD9122 ADC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c new file mode 100644 index 0000000000000..b737c64a402da --- /dev/null +++ b/drivers/iio/frequency/ad9523.c @@ -0,0 +1,1059 @@ +/* + * AD9523 SPI Low Jitter Clock Generator + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define AD9523_READ (1 << 15) +#define AD9523_WRITE (0 << 15) +#define AD9523_CNT(x) (((x) - 1) << 13) +#define AD9523_ADDR(x) ((x) & 0xFFF) + +#define AD9523_R1B (1 << 16) +#define AD9523_R2B (2 << 16) +#define AD9523_R3B (3 << 16) +#define AD9523_TRANSF_LEN(x) ((x) >> 16) + +#define AD9523_SERIAL_PORT_CONFIG (AD9523_R1B | 0x0) +#define AD9523_VERSION_REGISTER (AD9523_R1B | 0x2) +#define AD9523_PART_REGISTER (AD9523_R1B | 0x3) +#define AD9523_READBACK_CTRL (AD9523_R1B | 0x4) + +#define AD9523_EEPROM_CUSTOMER_VERSION_ID (AD9523_R2B | 0x6) + +#define AD9523_PLL1_REF_A_DIVIDER (AD9523_R2B | 0x11) +#define AD9523_PLL1_REF_B_DIVIDER (AD9523_R2B | 0x13) +#define AD9523_PLL1_REF_TEST_DIVIDER (AD9523_R1B | 0x14) +#define AD9523_PLL1_FEEDBACK_DIVIDER (AD9523_R2B | 0x17) +#define AD9523_PLL1_CHARGE_PUMP_CTRL (AD9523_R2B | 0x19) +#define AD9523_PLL1_INPUT_RECEIVERS_CTRL (AD9523_R1B | 0x1A) +#define AD9523_PLL1_REF_CTRL (AD9523_R1B | 0x1B) +#define AD9523_PLL1_MISC_CTRL (AD9523_R1B | 0x1C) +#define AD9523_PLL1_LOOP_FILTER_CTRL (AD9523_R1B | 0x1D) + +#define AD9523_PLL2_CHARGE_PUMP (AD9523_R1B | 0xF0) +#define AD9523_PLL2_FEEDBACK_DIVIDER_AB (AD9523_R1B | 0xF1) +#define AD9523_PLL2_CTRL (AD9523_R1B | 0xF2) +#define AD9523_PLL2_VCO_CTRL (AD9523_R1B | 0xF3) +#define AD9523_PLL2_VCO_DIVIDER (AD9523_R1B | 0xF4) +#define AD9523_PLL2_LOOP_FILTER_CTRL (AD9523_R2B | 0xF6) +#define AD9523_PLL2_R2_DIVIDER (AD9523_R1B | 0xF7) + +#define AD9523_CHANNEL_CLOCK_DIST(ch) (AD9523_R3B | (0x192 + 3 * ch)) + +#define AD9523_PLL1_OUTPUT_CTRL (AD9523_R1B | 0x1BA) +#define AD9523_PLL1_OUTPUT_CHANNEL_CTRL (AD9523_R1B | 0x1BB) + +#define AD9523_READBACK_0 (AD9523_R1B | 0x22C) +#define AD9523_READBACK_1 (AD9523_R1B | 0x22D) + +#define AD9523_STATUS_SIGNALS (AD9523_R3B | 0x232) +#define AD9523_POWER_DOWN_CTRL (AD9523_R1B | 0x233) +#define AD9523_IO_UPDATE (AD9523_R1B | 0x234) + +#define AD9523_EEPROM_DATA_XFER_STATUS (AD9523_R1B | 0xB00) +#define AD9523_EEPROM_ERROR_READBACK (AD9523_R1B | 0xB01) +#define AD9523_EEPROM_CTRL1 (AD9523_R1B | 0xB02) +#define AD9523_EEPROM_CTRL2 (AD9523_R1B | 0xB03) + +/* AD9523_SERIAL_PORT_CONFIG */ + +#define AD9523_SER_CONF_SDO_ACTIVE (1 << 7) +#define AD9523_SER_CONF_SOFT_RESET (1 << 5) + +/* AD9523_READBACK_CTRL */ +#define AD9523_READBACK_CTRL_READ_BUFFERED (1 << 0) + +/* AD9523_PLL1_CHARGE_PUMP_CTRL */ +#define AD9523_PLL1_CHARGE_PUMP_CURRENT_nA(x) (((x) / 500) & 0x7F) +#define AD9523_PLL1_CHARGE_PUMP_TRISTATE (1 << 7) +#define AD9523_PLL1_CHARGE_PUMP_MODE_NORMAL (3 << 8) +#define AD9523_PLL1_CHARGE_PUMP_MODE_PUMP_DOWN (2 << 8) +#define AD9523_PLL1_CHARGE_PUMP_MODE_PUMP_UP (1 << 8) +#define AD9523_PLL1_CHARGE_PUMP_MODE_TRISTATE (0 << 8) +#define AD9523_PLL1_BACKLASH_PW_MIN (0 << 10) +#define AD9523_PLL1_BACKLASH_PW_LOW (1 << 10) +#define AD9523_PLL1_BACKLASH_PW_HIGH (2 << 10) +#define AD9523_PLL1_BACKLASH_PW_MAX (3 << 10) + +/* AD9523_PLL1_INPUT_RECEIVERS_CTRL */ +#define AD9523_PLL1_REF_TEST_RCV_EN (1 << 7) +#define AD9523_PLL1_REFB_DIFF_RCV_EN (1 << 6) +#define AD9523_PLL1_REFA_DIFF_RCV_EN (1 << 5) +#define AD9523_PLL1_REFB_RCV_EN (1 << 4) +#define AD9523_PLL1_REFA_RCV_EN (1 << 3) +#define AD9523_PLL1_REFA_REFB_PWR_CTRL_EN (1 << 2) +#define AD9523_PLL1_OSC_IN_CMOS_NEG_INP_EN (1 << 1) +#define AD9523_PLL1_OSC_IN_DIFF_EN (1 << 0) + +/* AD9523_PLL1_REF_CTRL */ +#define AD9523_PLL1_BYPASS_REF_TEST_DIV_EN (1 << 7) +#define AD9523_PLL1_BYPASS_FEEDBACK_DIV_EN (1 << 6) +#define AD9523_PLL1_ZERO_DELAY_MODE_INT (1 << 5) +#define AD9523_PLL1_ZERO_DELAY_MODE_EXT (0 << 5) +#define AD9523_PLL1_OSC_IN_PLL_FEEDBACK_EN (1 << 4) +#define AD9523_PLL1_ZD_IN_CMOS_NEG_INP_EN (1 << 3) +#define AD9523_PLL1_ZD_IN_DIFF_EN (1 << 2) +#define AD9523_PLL1_REFB_CMOS_NEG_INP_EN (1 << 1) +#define AD9523_PLL1_REFA_CMOS_NEG_INP_EN (1 << 0) + +/* AD9523_PLL1_MISC_CTRL */ +#define AD9523_PLL1_REFB_INDEP_DIV_CTRL_EN (1 << 7) +#define AD9523_PLL1_OSC_CTRL_FAIL_VCC_BY2_EN (1 << 6) +#define AD9523_PLL1_REF_MODE(x) ((x) << 2) +#define AD9523_PLL1_BYPASS_REFB_DIV (1 << 1) +#define AD9523_PLL1_BYPASS_REFA_DIV (1 << 0) + +/* AD9523_PLL1_LOOP_FILTER_CTRL */ +#define AD9523_PLL1_LOOP_FILTER_RZERO(x) ((x) & 0xF) + +/* AD9523_PLL2_CHARGE_PUMP */ +#define AD9523_PLL2_CHARGE_PUMP_CURRENT_nA(x) ((x) / 3500) + +/* AD9523_PLL2_FEEDBACK_DIVIDER_AB */ +#define AD9523_PLL2_FB_NDIV_A_CNT(x) (((x) & 0x3) << 6) +#define AD9523_PLL2_FB_NDIV_B_CNT(x) (((x) & 0x3F) << 0) +#define AD9523_PLL2_FB_NDIV(a, b) (4 * (b) + (a)) + +/* AD9523_PLL2_CTRL */ +#define AD9523_PLL2_CHARGE_PUMP_MODE_NORMAL (3 << 0) +#define AD9523_PLL2_CHARGE_PUMP_MODE_PUMP_DOWN (2 << 0) +#define AD9523_PLL2_CHARGE_PUMP_MODE_PUMP_UP (1 << 0) +#define AD9523_PLL2_CHARGE_PUMP_MODE_TRISTATE (0 << 0) +#define AD9523_PLL2_BACKLASH_PW_MIN (0 << 2) +#define AD9523_PLL2_BACKLASH_PW_LOW (1 << 2) +#define AD9523_PLL2_BACKLASH_PW_HIGH (2 << 2) +#define AD9523_PLL2_BACKLASH_PW_MAX (3 << 1) +#define AD9523_PLL2_BACKLASH_CTRL_EN (1 << 4) +#define AD9523_PLL2_FREQ_DOUBLER_EN (1 << 5) +#define AD9523_PLL2_LOCK_DETECT_PWR_DOWN_EN (1 << 7) + +/* AD9523_PLL2_VCO_CTRL */ +#define AD9523_PLL2_VCO_CALIBRATE (1 << 1) +#define AD9523_PLL2_FORCE_VCO_MIDSCALE (1 << 2) +#define AD9523_PLL2_FORCE_REFERENCE_VALID (1 << 3) +#define AD9523_PLL2_FORCE_RELEASE_SYNC (1 << 4) + +/* AD9523_PLL2_VCO_DIVIDER */ +#define AD9523_PLL2_VCO_DIV_M1(x) ((((x) - 3) & 0x3) << 0) +#define AD9523_PLL2_VCO_DIV_M2(x) ((((x) - 3) & 0x3) << 4) +#define AD9523_PLL2_VCO_DIV_M1_PWR_DOWN_EN (1 << 2) +#define AD9523_PLL2_VCO_DIV_M2_PWR_DOWN_EN (1 << 6) + +/* AD9523_PLL2_LOOP_FILTER_CTRL */ +#define AD9523_PLL2_LOOP_FILTER_CPOLE1(x) (((x) & 0x7) << 0) +#define AD9523_PLL2_LOOP_FILTER_RZERO(x) (((x) & 0x7) << 3) +#define AD9523_PLL2_LOOP_FILTER_RPOLE2(x) (((x) & 0x7) << 6) +#define AD9523_PLL2_LOOP_FILTER_RZERO_BYPASS_EN (1 << 8) + +/* AD9523_PLL2_R2_DIVIDER */ +#define AD9523_PLL2_R2_DIVIDER_VAL(x) (((x) & 0x1F) << 0) + +/* AD9523_CHANNEL_CLOCK_DIST */ +#define AD9523_CLK_DIST_DIV_PHASE(x) (((x) & 0x3F) << 18) +#define AD9523_CLK_DIST_DIV_PHASE_REV(x) ((ret >> 18) & 0x3F) +#define AD9523_CLK_DIST_DIV(x) ((((x) - 1) & 0x3FF) << 8) +#define AD9523_CLK_DIST_DIV_REV(x) (((ret >> 8) & 0x3FF) + 1) +#define AD9523_CLK_DIST_INV_DIV_OUTPUT_EN (1 << 7) +#define AD9523_CLK_DIST_IGNORE_SYNC_EN (1 << 6) +#define AD9523_CLK_DIST_PWR_DOWN_EN (1 << 5) +#define AD9523_CLK_DIST_LOW_PWR_MODE_EN (1 << 4) +#define AD9523_CLK_DIST_DRIVER_MODE(x) (((x) & 0xF) << 0) + +/* AD9523_PLL1_OUTPUT_CTRL */ +#define AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH6_M2 (1 << 7) +#define AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH5_M2 (1 << 6) +#define AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH4_M2 (1 << 5) +#define AD9523_PLL1_OUTP_CTRL_CMOS_DRV_WEAK (1 << 4) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_1 (0 << 0) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_2 (1 << 0) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_4 (2 << 0) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_8 (4 << 0) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_16 (8 << 0) + +/* AD9523_PLL1_OUTPUT_CHANNEL_CTRL */ +#define AD9523_PLL1_OUTP_CH_CTRL_OUTPUT_PWR_DOWN_EN (1 << 7) +#define AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH9_M2 (1 << 6) +#define AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH8_M2 (1 << 5) +#define AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH7_M2 (1 << 4) +#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH3 (1 << 3) +#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH2 (1 << 2) +#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH1 (1 << 1) +#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH0 (1 << 0) + +/* AD9523_READBACK_0 */ +#define AD9523_READBACK_0_STAT_PLL2_REF_CLK (1 << 7) +#define AD9523_READBACK_0_STAT_PLL2_FB_CLK (1 << 6) +#define AD9523_READBACK_0_STAT_VCXO (1 << 5) +#define AD9523_READBACK_0_STAT_REF_TEST (1 << 4) +#define AD9523_READBACK_0_STAT_REFB (1 << 3) +#define AD9523_READBACK_0_STAT_REFA (1 << 2) +#define AD9523_READBACK_0_STAT_PLL2_LD (1 << 1) +#define AD9523_READBACK_0_STAT_PLL1_LD (1 << 0) + +/* AD9523_READBACK_1 */ +#define AD9523_READBACK_1_HOLDOVER_ACTIVE (1 << 3) +#define AD9523_READBACK_1_AUTOMODE_SEL_REFB (1 << 2) +#define AD9523_READBACK_1_VCO_CALIB_IN_PROGRESS (1 << 0) + +/* AD9523_STATUS_SIGNALS */ +#define AD9523_STATUS_SIGNALS_SYNC_MAN_CTRL (1 << 16) +#define AD9523_STATUS_MONITOR_01_PLL12_LOCKED (0x302) +/* AD9523_POWER_DOWN_CTRL */ +#define AD9523_POWER_DOWN_CTRL_PLL1_PWR_DOWN (1 << 2) +#define AD9523_POWER_DOWN_CTRL_PLL2_PWR_DOWN (1 << 1) +#define AD9523_POWER_DOWN_CTRL_DIST_PWR_DOWN (1 << 0) + +/* AD9523_IO_UPDATE */ +#define AD9523_IO_UPDATE_EN (1 << 0) + +/* AD9523_EEPROM_DATA_XFER_STATUS */ +#define AD9523_EEPROM_DATA_XFER_IN_PROGRESS (1 << 0) + +/* AD9523_EEPROM_ERROR_READBACK */ +#define AD9523_EEPROM_ERROR_READBACK_FAIL (1 << 0) + +/* AD9523_EEPROM_CTRL1 */ +#define AD9523_EEPROM_CTRL1_SOFT_EEPROM (1 << 1) +#define AD9523_EEPROM_CTRL1_EEPROM_WRITE_PROT_DIS (1 << 0) + +/* AD9523_EEPROM_CTRL2 */ +#define AD9523_EEPROM_CTRL2_REG2EEPROM (1 << 0) + +#define AD9523_NUM_CHAN 14 +#define AD9523_NUM_CHAN_ALT_CLK_SRC 10 + +/* Helpers to avoid excess line breaks */ +#define AD_IFE(_pde, _a, _b) ((pdata->_pde) ? _a : _b) +#define AD_IF(_pde, _a) AD_IFE(_pde, _a, 0) + +enum { + AD9523_STAT_PLL1_LD, + AD9523_STAT_PLL2_LD, + AD9523_STAT_REFA, + AD9523_STAT_REFB, + AD9523_STAT_REF_TEST, + AD9523_STAT_VCXO, + AD9523_STAT_PLL2_FB_CLK, + AD9523_STAT_PLL2_REF_CLK, + AD9523_SYNC, + AD9523_EEPROM, +}; + +enum { + AD9523_VCO1, + AD9523_VCO2, + AD9523_VCXO, + AD9523_NUM_CLK_SRC, +}; + +struct ad9523_state { + struct spi_device *spi; + struct regulator *reg; + struct ad9523_platform_data *pdata; + struct iio_chan_spec ad9523_channels[AD9523_NUM_CHAN]; + + unsigned long vcxo_freq; + unsigned long vco_freq; + unsigned long vco_out_freq[AD9523_NUM_CLK_SRC]; + unsigned char vco_out_map[AD9523_NUM_CHAN_ALT_CLK_SRC]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + union { + __be32 d32; + u8 d8[4]; + } data[2] ____cacheline_aligned; +}; + +static int ad9523_read(struct iio_dev *indio_dev, unsigned addr) +{ + struct ad9523_state *st = iio_priv(indio_dev); + struct spi_message m; + int ret; + + /* We encode the register size 1..3 bytes into the register address. + * On transfer we get the size from the register datum, and make sure + * the result is properly aligned. + */ + + struct spi_transfer t[] = { + { + .tx_buf = &st->data[0].d8[2], + .len = 2, + }, { + .rx_buf = &st->data[1].d8[4 - AD9523_TRANSF_LEN(addr)], + .len = AD9523_TRANSF_LEN(addr), + }, + }; + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + st->data[0].d32 = cpu_to_be32(AD9523_READ | + AD9523_CNT(AD9523_TRANSF_LEN(addr)) | + AD9523_ADDR(addr)); + + ret = spi_sync(st->spi, &m); + if (ret < 0) + dev_err(&indio_dev->dev, "read failed (%d)", ret); + else + ret = be32_to_cpu(st->data[1].d32) & (0xFFFFFF >> + (8 * (3 - AD9523_TRANSF_LEN(addr)))); + + return ret; +}; + +static int ad9523_write(struct iio_dev *indio_dev, unsigned addr, unsigned val) +{ + struct ad9523_state *st = iio_priv(indio_dev); + struct spi_message m; + int ret; + struct spi_transfer t[] = { + { + .tx_buf = &st->data[0].d8[2], + .len = 2, + }, { + .tx_buf = &st->data[1].d8[4 - AD9523_TRANSF_LEN(addr)], + .len = AD9523_TRANSF_LEN(addr), + }, + }; + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + st->data[0].d32 = cpu_to_be32(AD9523_WRITE | + AD9523_CNT(AD9523_TRANSF_LEN(addr)) | + AD9523_ADDR(addr)); + st->data[1].d32 = cpu_to_be32(val); + + ret = spi_sync(st->spi, &m); + + if (ret < 0) + dev_err(&indio_dev->dev, "write failed (%d)", ret); + + return ret; +} + +static int ad9523_io_update(struct iio_dev *indio_dev) +{ + return ad9523_write(indio_dev, AD9523_IO_UPDATE, AD9523_IO_UPDATE_EN); +} + +static int ad9523_vco_out_map(struct iio_dev *indio_dev, + unsigned ch, unsigned out) +{ + struct ad9523_state *st = iio_priv(indio_dev); + int ret; + unsigned mask; + + switch (ch) { + case 0 ... 3: + ret = ad9523_read(indio_dev, AD9523_PLL1_OUTPUT_CHANNEL_CTRL); + if (ret < 0) + break; + mask = AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH0 << ch; + if (out) { + ret |= mask; + out = 2; + } else { + ret &= ~mask; + } + ret = ad9523_write(indio_dev, + AD9523_PLL1_OUTPUT_CHANNEL_CTRL, ret); + break; + case 4 ... 6: + ret = ad9523_read(indio_dev, AD9523_PLL1_OUTPUT_CTRL); + if (ret < 0) + break; + mask = AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH4_M2 << (ch - 4); + if (out) + ret |= mask; + else + ret &= ~mask; + ret = ad9523_write(indio_dev, AD9523_PLL1_OUTPUT_CTRL, ret); + break; + case 7 ... 9: + ret = ad9523_read(indio_dev, AD9523_PLL1_OUTPUT_CHANNEL_CTRL); + if (ret < 0) + break; + mask = AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH7_M2 << (ch - 7); + if (out) + ret |= mask; + else + ret &= ~mask; + ret = ad9523_write(indio_dev, + AD9523_PLL1_OUTPUT_CHANNEL_CTRL, ret); + break; + default: + return 0; + } + + st->vco_out_map[ch] = out; + + return ret; +} + +static int ad9523_set_clock_provider(struct iio_dev *indio_dev, + unsigned ch, unsigned long freq) +{ + struct ad9523_state *st = iio_priv(indio_dev); + long tmp1, tmp2; + bool use_alt_clk_src; + + switch (ch) { + case 0 ... 3: + use_alt_clk_src = (freq == st->vco_out_freq[AD9523_VCXO]); + break; + case 4 ... 9: + tmp1 = st->vco_out_freq[AD9523_VCO1] / freq; + tmp2 = st->vco_out_freq[AD9523_VCO2] / freq; + tmp1 *= freq; + tmp2 *= freq; + use_alt_clk_src = (abs(tmp1 - freq) > abs(tmp2 - freq)); + break; + default: + /* Ch 10..14: No action required, return success */ + return 0; + } + + return ad9523_vco_out_map(indio_dev, ch, use_alt_clk_src); +} + +static int ad9523_store_eeprom(struct iio_dev *indio_dev) +{ + int ret, tmp; + + ret = ad9523_write(indio_dev, AD9523_EEPROM_CTRL1, + AD9523_EEPROM_CTRL1_EEPROM_WRITE_PROT_DIS); + if (ret < 0) + return ret; + ret = ad9523_write(indio_dev, AD9523_EEPROM_CTRL2, + AD9523_EEPROM_CTRL2_REG2EEPROM); + if (ret < 0) + return ret; + + tmp = 4; + do { + msleep(16); + ret = ad9523_read(indio_dev, + AD9523_EEPROM_DATA_XFER_STATUS); + if (ret < 0) + return ret; + } while ((ret & AD9523_EEPROM_DATA_XFER_IN_PROGRESS) && tmp--); + + ret = ad9523_write(indio_dev, AD9523_EEPROM_CTRL1, 0); + if (ret < 0) + return ret; + + ret = ad9523_read(indio_dev, AD9523_EEPROM_ERROR_READBACK); + if (ret < 0) + return ret; + + if (ret & AD9523_EEPROM_ERROR_READBACK_FAIL) { + dev_err(&indio_dev->dev, "Verify EEPROM failed"); + ret = -EIO; + } + + return ret; +} + +static int ad9523_sync(struct iio_dev *indio_dev) +{ + int ret, tmp; + + ret = ad9523_read(indio_dev, AD9523_STATUS_SIGNALS); + if (ret < 0) + return ret; + + tmp = ret; + tmp |= AD9523_STATUS_SIGNALS_SYNC_MAN_CTRL; + + ret = ad9523_write(indio_dev, AD9523_STATUS_SIGNALS, tmp); + if (ret < 0) + return ret; + + ad9523_io_update(indio_dev); + tmp &= ~AD9523_STATUS_SIGNALS_SYNC_MAN_CTRL; + + ret = ad9523_write(indio_dev, AD9523_STATUS_SIGNALS, tmp); + if (ret < 0) + return ret; + + return ad9523_io_update(indio_dev); +} + +static ssize_t ad9523_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + bool state; + int ret; + + ret = strtobool(buf, &state); + if (ret < 0) + return ret; + + if (!state) + return 0; + + mutex_lock(&indio_dev->mlock); + switch ((u32)this_attr->address) { + case AD9523_SYNC: + ret = ad9523_sync(indio_dev); + break; + case AD9523_EEPROM: + ret = ad9523_store_eeprom(indio_dev); + break; + default: + ret = -ENODEV; + } + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static ssize_t ad9523_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + + mutex_lock(&indio_dev->mlock); + ret = ad9523_read(indio_dev, AD9523_READBACK_0); + if (ret >= 0) { + ret = sprintf(buf, "%d\n", !!(ret & (1 << + (u32)this_attr->address))); + } + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static IIO_DEVICE_ATTR(pll1_locked, S_IRUGO, + ad9523_show, + NULL, + AD9523_STAT_PLL1_LD); + +static IIO_DEVICE_ATTR(pll2_locked, S_IRUGO, + ad9523_show, + NULL, + AD9523_STAT_PLL2_LD); + +static IIO_DEVICE_ATTR(pll1_reference_clk_a_present, S_IRUGO, + ad9523_show, + NULL, + AD9523_STAT_REFA); + +static IIO_DEVICE_ATTR(pll1_reference_clk_b_present, S_IRUGO, + ad9523_show, + NULL, + AD9523_STAT_REFB); + +static IIO_DEVICE_ATTR(pll1_reference_clk_test_present, S_IRUGO, + ad9523_show, + NULL, + AD9523_STAT_REF_TEST); + +static IIO_DEVICE_ATTR(vcxo_clk_present, S_IRUGO, + ad9523_show, + NULL, + AD9523_STAT_VCXO); + +static IIO_DEVICE_ATTR(pll2_feedback_clk_present, S_IRUGO, + ad9523_show, + NULL, + AD9523_STAT_PLL2_FB_CLK); + +static IIO_DEVICE_ATTR(pll2_reference_clk_present, S_IRUGO, + ad9523_show, + NULL, + AD9523_STAT_PLL2_REF_CLK); + +static IIO_DEVICE_ATTR(sync_dividers, S_IWUSR, + NULL, + ad9523_store, + AD9523_SYNC); + +static IIO_DEVICE_ATTR(store_eeprom, S_IWUSR, + NULL, + ad9523_store, + AD9523_EEPROM); + +static struct attribute *ad9523_attributes[] = { + &iio_dev_attr_sync_dividers.dev_attr.attr, + &iio_dev_attr_store_eeprom.dev_attr.attr, + &iio_dev_attr_pll2_feedback_clk_present.dev_attr.attr, + &iio_dev_attr_pll2_reference_clk_present.dev_attr.attr, + &iio_dev_attr_pll1_reference_clk_a_present.dev_attr.attr, + &iio_dev_attr_pll1_reference_clk_b_present.dev_attr.attr, + &iio_dev_attr_pll1_reference_clk_test_present.dev_attr.attr, + &iio_dev_attr_vcxo_clk_present.dev_attr.attr, + &iio_dev_attr_pll1_locked.dev_attr.attr, + &iio_dev_attr_pll2_locked.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad9523_attribute_group = { + .attrs = ad9523_attributes, +}; + +static int ad9523_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad9523_state *st = iio_priv(indio_dev); + unsigned code; + int ret; + + mutex_lock(&indio_dev->mlock); + ret = ad9523_read(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel)); + mutex_unlock(&indio_dev->mlock); + + if (ret < 0) + return ret; + + switch (m) { + case IIO_CHAN_INFO_RAW: + *val = !(ret & AD9523_CLK_DIST_PWR_DOWN_EN); + return IIO_VAL_INT; + case IIO_CHAN_INFO_FREQUENCY: + *val = st->vco_out_freq[st->vco_out_map[chan->channel]] / + AD9523_CLK_DIST_DIV_REV(ret); + return IIO_VAL_INT; + case IIO_CHAN_INFO_PHASE: + code = (AD9523_CLK_DIST_DIV_PHASE_REV(ret) * 3141592) / + AD9523_CLK_DIST_DIV_REV(ret); + *val = code / 1000000; + *val2 = (code % 1000000) * 10; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +}; + +static int ad9523_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad9523_state *st = iio_priv(indio_dev); + unsigned reg; + int ret, tmp, code; + + mutex_lock(&indio_dev->mlock); + ret = ad9523_read(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel)); + if (ret < 0) + goto out; + + reg = ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val) + reg &= ~AD9523_CLK_DIST_PWR_DOWN_EN; + else + reg |= AD9523_CLK_DIST_PWR_DOWN_EN; + break; + case IIO_CHAN_INFO_FREQUENCY: + if (val <= 0) { + ret = -EINVAL; + goto out; + } + ret = ad9523_set_clock_provider(indio_dev, chan->channel, val); + if (ret < 0) + goto out; + tmp = st->vco_out_freq[st->vco_out_map[chan->channel]] / val; + tmp = clamp(tmp, 1, 1024); + reg &= ~(0x3FF << 8); + reg |= AD9523_CLK_DIST_DIV(tmp); + break; + case IIO_CHAN_INFO_PHASE: + code = val * 1000000 + val2 % 1000000; + tmp = (code * AD9523_CLK_DIST_DIV_REV(ret)) / 3141592; + tmp = clamp(tmp, 0, 63); + reg &= ~AD9523_CLK_DIST_DIV_PHASE(~0); + reg |= AD9523_CLK_DIST_DIV_PHASE(tmp); + break; + default: + ret = -EINVAL; + goto out; + } + + ret = ad9523_write(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel), + reg); + if (ret < 0) + goto out; + + ad9523_io_update(indio_dev); +out: + mutex_unlock(&indio_dev->mlock); + return ret; +} + +static int ad9523_reg_access(struct iio_dev *indio_dev, + unsigned reg, unsigned writeval, + unsigned *readval) +{ + int ret; + + mutex_lock(&indio_dev->mlock); + if (readval == NULL) { + ret = ad9523_write(indio_dev, reg | AD9523_R1B, writeval); + ad9523_io_update(indio_dev); + } else { + ret = ad9523_read(indio_dev, reg | AD9523_R1B); + if (ret < 0) + goto out_unlock; + *readval = ret; + ret = 0; + } + +out_unlock: + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static const struct iio_info ad9523_info = { + .read_raw = &ad9523_read_raw, + .write_raw = &ad9523_write_raw, + .debugfs_reg_access = &ad9523_reg_access, + .attrs = &ad9523_attribute_group, + .driver_module = THIS_MODULE, +}; + +static int ad9523_setup(struct iio_dev *indio_dev) +{ + struct ad9523_state *st = iio_priv(indio_dev); + struct ad9523_platform_data *pdata = st->pdata; + struct ad9523_channel_spec *chan; + unsigned long active_mask = 0; + int ret, i; + + ret = ad9523_write(indio_dev, AD9523_SERIAL_PORT_CONFIG, + AD9523_SER_CONF_SOFT_RESET | + (st->spi->mode & SPI_3WIRE ? 0 : + AD9523_SER_CONF_SDO_ACTIVE)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_READBACK_CTRL, + AD9523_READBACK_CTRL_READ_BUFFERED); + if (ret < 0) + return ret; + + ret = ad9523_io_update(indio_dev); + if (ret < 0) + return ret; + + /* + * PLL1 Setup + */ + ret = ad9523_write(indio_dev, AD9523_PLL1_REF_A_DIVIDER, + pdata->refa_r_div); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_REF_B_DIVIDER, + pdata->refb_r_div); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_FEEDBACK_DIVIDER, + pdata->pll1_feedback_div); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_CHARGE_PUMP_CTRL, + AD9523_PLL1_CHARGE_PUMP_CURRENT_nA(pdata-> + pll1_charge_pump_current_nA) | + AD9523_PLL1_CHARGE_PUMP_MODE_NORMAL | + AD9523_PLL1_BACKLASH_PW_MIN); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_INPUT_RECEIVERS_CTRL, + AD_IF(refa_diff_rcv_en, AD9523_PLL1_REFA_RCV_EN) | + AD_IF(refb_diff_rcv_en, AD9523_PLL1_REFB_RCV_EN) | + AD_IF(osc_in_diff_en, AD9523_PLL1_OSC_IN_DIFF_EN) | + AD_IF(osc_in_cmos_neg_inp_en, + AD9523_PLL1_OSC_IN_CMOS_NEG_INP_EN) | + AD_IF(refa_diff_rcv_en, AD9523_PLL1_REFA_DIFF_RCV_EN) | + AD_IF(refb_diff_rcv_en, AD9523_PLL1_REFB_DIFF_RCV_EN)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_REF_CTRL, + AD_IF(zd_in_diff_en, AD9523_PLL1_ZD_IN_DIFF_EN) | + AD_IF(zd_in_cmos_neg_inp_en, + AD9523_PLL1_ZD_IN_CMOS_NEG_INP_EN) | + AD_IF(zero_delay_mode_internal_en, + AD9523_PLL1_ZERO_DELAY_MODE_INT) | + AD_IF(osc_in_feedback_en, AD9523_PLL1_OSC_IN_PLL_FEEDBACK_EN) | + AD_IF(refa_cmos_neg_inp_en, AD9523_PLL1_REFA_CMOS_NEG_INP_EN) | + AD_IF(refb_cmos_neg_inp_en, AD9523_PLL1_REFB_CMOS_NEG_INP_EN)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_MISC_CTRL, + AD9523_PLL1_REFB_INDEP_DIV_CTRL_EN | + AD9523_PLL1_REF_MODE(pdata->ref_mode)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL1_LOOP_FILTER_CTRL, + AD9523_PLL1_LOOP_FILTER_RZERO(pdata->pll1_loop_filter_rzero)); + if (ret < 0) + return ret; + /* + * PLL2 Setup + */ + + ret = ad9523_write(indio_dev, AD9523_PLL2_CHARGE_PUMP, + AD9523_PLL2_CHARGE_PUMP_CURRENT_nA(pdata-> + pll2_charge_pump_current_nA)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL2_FEEDBACK_DIVIDER_AB, + AD9523_PLL2_FB_NDIV_A_CNT(pdata->pll2_ndiv_a_cnt) | + AD9523_PLL2_FB_NDIV_B_CNT(pdata->pll2_ndiv_b_cnt)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL2_CTRL, + AD9523_PLL2_CHARGE_PUMP_MODE_NORMAL | + AD9523_PLL2_BACKLASH_CTRL_EN | + AD_IF(pll2_freq_doubler_en, AD9523_PLL2_FREQ_DOUBLER_EN)); + if (ret < 0) + return ret; + + st->vco_freq = (pdata->vcxo_freq * (pdata->pll2_freq_doubler_en ? 2 : 1) + / pdata->pll2_r2_div) * AD9523_PLL2_FB_NDIV(pdata-> + pll2_ndiv_a_cnt, pdata->pll2_ndiv_b_cnt); + + ret = ad9523_write(indio_dev, AD9523_PLL2_VCO_CTRL, + AD9523_PLL2_VCO_CALIBRATE); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL2_VCO_DIVIDER, + AD9523_PLL2_VCO_DIV_M1(pdata->pll2_vco_diff_m1) | + AD9523_PLL2_VCO_DIV_M2(pdata->pll2_vco_diff_m2) | + AD_IFE(pll2_vco_diff_m1, 0, + AD9523_PLL2_VCO_DIV_M1_PWR_DOWN_EN) | + AD_IFE(pll2_vco_diff_m2, 0, + AD9523_PLL2_VCO_DIV_M2_PWR_DOWN_EN)); + if (ret < 0) + return ret; + + if (pdata->pll2_vco_diff_m1) + st->vco_out_freq[AD9523_VCO1] = + st->vco_freq / pdata->pll2_vco_diff_m1; + + if (pdata->pll2_vco_diff_m2) + st->vco_out_freq[AD9523_VCO2] = + st->vco_freq / pdata->pll2_vco_diff_m2; + + st->vco_out_freq[AD9523_VCXO] = pdata->vcxo_freq; + + ret = ad9523_write(indio_dev, AD9523_PLL2_R2_DIVIDER, + AD9523_PLL2_R2_DIVIDER_VAL(pdata->pll2_r2_div)); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_PLL2_LOOP_FILTER_CTRL, + AD9523_PLL2_LOOP_FILTER_CPOLE1(pdata->cpole1) | + AD9523_PLL2_LOOP_FILTER_RZERO(pdata->rzero) | + AD9523_PLL2_LOOP_FILTER_RPOLE2(pdata->rpole2) | + AD_IF(rzero_bypass_en, + AD9523_PLL2_LOOP_FILTER_RZERO_BYPASS_EN)); + if (ret < 0) + return ret; + + for (i = 0; i < pdata->num_channels; i++) { + chan = &pdata->channels[i]; + if (chan->channel_num < AD9523_NUM_CHAN) { + __set_bit(chan->channel_num, &active_mask); + ret = ad9523_write(indio_dev, + AD9523_CHANNEL_CLOCK_DIST(chan->channel_num), + AD9523_CLK_DIST_DRIVER_MODE(chan->driver_mode) | + AD9523_CLK_DIST_DIV(chan->channel_divider) | + AD9523_CLK_DIST_DIV_PHASE(chan->divider_phase) | + (chan->sync_ignore_en ? + AD9523_CLK_DIST_IGNORE_SYNC_EN : 0) | + (chan->divider_output_invert_en ? + AD9523_CLK_DIST_INV_DIV_OUTPUT_EN : 0) | + (chan->low_power_mode_en ? + AD9523_CLK_DIST_LOW_PWR_MODE_EN : 0) | + (chan->output_dis ? + AD9523_CLK_DIST_PWR_DOWN_EN : 0)); + if (ret < 0) + return ret; + + ret = ad9523_vco_out_map(indio_dev, chan->channel_num, + chan->use_alt_clock_src); + if (ret < 0) + return ret; + + st->ad9523_channels[i].type = IIO_ALTVOLTAGE; + st->ad9523_channels[i].output = 1; + st->ad9523_channels[i].indexed = 1; + st->ad9523_channels[i].channel = chan->channel_num; + st->ad9523_channels[i].extend_name = + chan->extended_name; + st->ad9523_channels[i].info_mask = + IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_PHASE_SEPARATE_BIT | + IIO_CHAN_INFO_FREQUENCY_SEPARATE_BIT; + } + } + + for_each_clear_bit(i, &active_mask, AD9523_NUM_CHAN) + ad9523_write(indio_dev, + AD9523_CHANNEL_CLOCK_DIST(i), + AD9523_CLK_DIST_DRIVER_MODE(TRISTATE) | + AD9523_CLK_DIST_PWR_DOWN_EN); + + ret = ad9523_write(indio_dev, AD9523_POWER_DOWN_CTRL, 0); + if (ret < 0) + return ret; + + ret = ad9523_write(indio_dev, AD9523_STATUS_SIGNALS, + AD9523_STATUS_MONITOR_01_PLL12_LOCKED); + if (ret < 0) + return ret; + + ret = ad9523_io_update(indio_dev); + if (ret < 0) + return ret; + + return 0; +} + +static int __devinit ad9523_probe(struct spi_device *spi) +{ + struct ad9523_platform_data *pdata = spi->dev.platform_data; + struct iio_dev *indio_dev; + struct ad9523_state *st; + int ret; + + if (!pdata) { + dev_err(&spi->dev, "no platform data?\n"); + return -EINVAL; + } + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + + st->reg = regulator_get(&spi->dev, "vcc"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) + goto error_put_reg; + } + + spi_set_drvdata(spi, indio_dev); + st->spi = spi; + st->pdata = pdata; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = (pdata->name[0] != 0) ? pdata->name : + spi_get_device_id(spi)->name; + indio_dev->info = &ad9523_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = st->ad9523_channels; + indio_dev->num_channels = pdata->num_channels; + + ret = ad9523_setup(indio_dev); + if (ret < 0) + goto error_disable_reg; + + ret = iio_device_register(indio_dev); + if (ret) + goto error_disable_reg; + + dev_info(&spi->dev, "probed %s\n", indio_dev->name); + + return 0; + +error_disable_reg: + if (!IS_ERR(st->reg)) + regulator_disable(st->reg); +error_put_reg: + if (!IS_ERR(st->reg)) + regulator_put(st->reg); + + iio_device_free(indio_dev); + + return ret; +} + +static int __devexit ad9523_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ad9523_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + if (!IS_ERR(st->reg)) { + regulator_disable(st->reg); + regulator_put(st->reg); + } + + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id ad9523_id[] = { + {"ad9523-1", 9523}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad9523_id); + +static struct spi_driver ad9523_driver = { + .driver = { + .name = "ad9523", + .owner = THIS_MODULE, + }, + .probe = ad9523_probe, + .remove = __devexit_p(ad9523_remove), + .id_table = ad9523_id, +}; +module_spi_driver(ad9523_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD9523 CLOCKDIST/PLL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/frequency/ad9548.c b/drivers/iio/frequency/ad9548.c new file mode 100644 index 0000000000000..9b985d7b0f500 --- /dev/null +++ b/drivers/iio/frequency/ad9548.c @@ -0,0 +1,287 @@ +/* + * AD9548 SPI Network Clock Generator/Synchronizer + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define AD_READ (1 << 15) +#define AD_WRITE (0 << 15) +#define AD_CNT(x) (((x) - 1) << 13) +#define AD_ADDR(x) ((x) & 0xFFF) +#define WAIT_B 0xFFFF +#define CHIPID_AD9548 0x48 + +static const unsigned short ad9548_regs[][2] = { + {0x0000, 0x30}, /* Reset */ + {0x0000, 0x10}, + {0x0000, 0x10}, + {0x0000, 0x10}, + {0x0000, 0x10}, + {0x0000, 0x10}, + {0x0100, 0x18}, /* System clock */ + {0x0101, 0x28}, + {0x0102, 0x45}, + {0x0103, 0x43}, + {0x0104, 0xDE}, + {0x0105, 0x13}, + {0x0106, 0x01}, + {0x0107, 0x00}, + {0x0108, 0x00}, + {0x0005, 0x01}, /* I/O Update */ + {0x0A02, 0x01}, /* Calibrate sysem clock */ + {0x0005, 0x01}, + {WAIT_B, 0x00}, + {0x0A02, 0x00}, + {0x0005, 0x01}, + {0x0208, 0x00}, /* IRQ Pin Output Mode */ + {0x0209, 0x00}, /* IRQ Masks */ + {0x020A, 0x00}, + {0x020B, 0x00}, + {0x020C, 0x00}, + {0x020D, 0x00}, + {0x020E, 0x00}, + {0x020F, 0x00}, + {0x0210, 0x00}, + {0x0211, 0x00}, /* Watchdog timer */ + {0x0212, 0x00}, + {0x0213, 0xFF}, /* Auxiliary DAC */ + {0x0214, 0x01}, + {0x0300, 0x29}, /* DPLL */ + {0x0301, 0x5C}, + {0x0302, 0x8F}, + {0x0303, 0xC2}, + {0x0304, 0xF5}, + {0x0305, 0x28}, + {0x0307, 0x00}, + {0x0308, 0x00}, + {0x0309, 0x00}, + {0x030A, 0xFF}, + {0x030B, 0xFF}, + {0x030C, 0xFF}, + {0x030D, 0x00}, + {0x030E, 0x00}, + {0x030F, 0x00}, + {0x0310, 0x00}, + {0x0311, 0x00}, + {0x0312, 0x00}, + {0x0313, 0x00}, + {0x0314, 0xE8}, + {0x0315, 0x03}, + {0x0316, 0x00}, + {0x0317, 0x00}, + {0x0318, 0x30}, + {0x0319, 0x75}, + {0x031A, 0x00}, + {0x031B, 0x00}, + {0x0306, 0x01}, /* Update TW */ + {0x0400, 0x0C}, /* Clock distribution output */ + {0x0401, 0x03}, + {0x0402, 0x00}, + {0x0403, 0x02}, + {0x0404, 0x04}, + {0x0405, 0x08}, + {0x0406, 0x03}, + {0x0407, 0x03}, + {0x0408, 0x03}, + {0x0409, 0x00}, + {0x040A, 0x00}, + {0x040B, 0x00}, + {0x040C, 0x03}, + {0x040D, 0x00}, + {0x040E, 0x00}, + {0x040F, 0x00}, + {0x0410, 0x00}, + {0x0411, 0x00}, + {0x0412, 0x00}, + {0x0413, 0x00}, + {0x0414, 0x00}, + {0x0415, 0x00}, + {0x0416, 0x00}, + {0x0417, 0x00}, + {0x0500, 0xFE}, /* Reference inputs */ + {0x0501, 0x00}, + {0x0502, 0x00}, + {0x0503, 0x08}, + {0x0504, 0x00}, + {0x0505, 0x00}, + {0x0506, 0x00}, + {0x0507, 0x00}, + {0x0600, 0x00}, /* Profiles are 0x0600-0x07FF */ + {0x0601, 0x55}, /* Profile 0 */ + {0x0602, 0xA0}, /* 30MHz input from FPGA, 122.880MHz output clock */ + {0x0603, 0xFC}, + {0x0604, 0x01}, + {0x0605, 0x00}, + {0x0606, 0x00}, + {0x0607, 0x00}, + {0x0608, 0xE8}, + {0x0609, 0x03}, + {0x060A, 0x00}, + {0x060B, 0xE8}, + {0x060C, 0x03}, + {0x060D, 0x00}, + {0x060E, 0x88}, + {0x060F, 0x13}, + {0x0610, 0x88}, + {0x0611, 0x13}, + {0x0612, 0x0E}, + {0x0613, 0xB2}, + {0x0614, 0x08}, + {0x0615, 0x82}, + {0x0616, 0x62}, + {0x0617, 0x42}, + {0x0618, 0xD8}, + {0x0619, 0x47}, + {0x061A, 0x21}, + {0x061B, 0xCB}, + {0x061C, 0xC4}, + {0x061D, 0x05}, + {0x061E, 0x7F}, + {0x061F, 0x00}, + {0x0620, 0x00}, + {0x0621, 0x00}, + {0x0622, 0x0B}, + {0x0623, 0x02}, + {0x0624, 0x00}, + {0x0625, 0x00}, + {0x0626, 0x26}, + {0x0627, 0xB0}, + {0x0628, 0x00}, + {0x0629, 0x10}, + {0x062A, 0x27}, + {0x062B, 0x20}, + {0x062C, 0x44}, + {0x062D, 0xF4}, + {0x062E, 0x01}, + {0x062F, 0x00}, + {0x0630, 0x20}, + {0x0631, 0x44}, + {0x0005, 0x01}, /* I/O Update */ + {0x0A0E, 0x01}, /* Force validation timeout */ + {0x0005, 0x01}, /* I/O Update */ + {0x0A02, 0x02}, /* Sync distribution */ + {0x0005, 0x01}, + {0x0A02, 0x00}, + {0x0005, 0x01}, +}; + +static int ad9548_read(struct spi_device *spi, unsigned reg) +{ + unsigned char buf[3]; + int ret; + u16 cmd; + + cmd = AD_READ | AD_CNT(1) | AD_ADDR(reg); + buf[0] = cmd >> 8; + buf[1] = cmd & 0xFF; + + + ret = spi_write_then_read(spi, &buf[0], 2, &buf[2], 1); + if (ret < 0) + return ret; + + return buf[2]; +} + +static int ad9548_write(struct spi_device *spi, + unsigned reg, unsigned val) +{ + unsigned char buf[3]; + int ret; + u16 cmd; + + cmd = AD_WRITE | AD_CNT(1) | AD_ADDR(reg); + buf[0] = cmd >> 8; + buf[1] = cmd & 0xFF; + buf[2] = val; + + ret = spi_write(spi, buf, 3); + if (ret < 0) + return ret; + + return 0; +} + +static int __devinit ad9548_probe(struct spi_device *spi) +{ + int i, ret, timeout; + + ret = ad9548_read(spi, 0x3); + if (ret < 0) + return ret; + if (ret != CHIPID_AD9548) { + dev_err(&spi->dev, "Unrecognized CHIP_ID 0x%X\n", ret); + return -ENODEV; + } + + for (i = 0; i < ARRAY_SIZE(ad9548_regs); i++) + switch (ad9548_regs[i][0]) { + case WAIT_B: + timeout = 100; + do { + ret = ad9548_read(spi, 0xD01); + if (ret < 0) + return ret; + if (ret & BIT(0)) + break; + mdelay(1); + } while (timeout--); + + if (timeout <= 0) + return -ETIMEDOUT; + break; + default: + ret = ad9548_write(spi, ad9548_regs[i][0], + ad9548_regs[i][1]); + if (ret < 0) + return ret; + break; + } + + spi_set_drvdata(spi, NULL); + dev_info(&spi->dev, "Rev. 0x%X probed\n", ad9548_read(spi, 0x2)); + + return 0; +} + +static int ad9548_remove(struct spi_device *spi) +{ + spi_set_drvdata(spi, NULL); + + return 0; +} + +static const struct spi_device_id ad9548_id[] = { + {"ad9548", 0}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad9548_id); + +static struct spi_driver ad9548_driver = { + .driver = { + .name = "ad9548", + .owner = THIS_MODULE, + }, + .probe = ad9548_probe, + .remove = __devexit_p(ad9548_remove), + .id_table = ad9548_id, +}; +module_spi_driver(ad9548_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD9548"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c new file mode 100644 index 0000000000000..59fbb3ae40e7f --- /dev/null +++ b/drivers/iio/frequency/adf4350.c @@ -0,0 +1,480 @@ +/* + * ADF4350/ADF4351 SPI Wideband Synthesizer driver + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +enum { + ADF4350_FREQ, + ADF4350_FREQ_REFIN, + ADF4350_FREQ_RESOLUTION, + ADF4350_PWRDOWN, +}; + +struct adf4350_state { + struct spi_device *spi; + struct regulator *reg; + struct adf4350_platform_data *pdata; + unsigned long clkin; + unsigned long chspc; /* Channel Spacing */ + unsigned long fpfd; /* Phase Frequency Detector */ + unsigned long min_out_freq; + unsigned r0_fract; + unsigned r0_int; + unsigned r1_mod; + unsigned r4_rf_div_sel; + unsigned long regs[6]; + unsigned long regs_hw[6]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + __be32 val ____cacheline_aligned; +}; + +static struct adf4350_platform_data default_pdata = { + .clkin = 122880000, + .channel_spacing = 10000, + .r2_user_settings = ADF4350_REG2_PD_POLARITY_POS | + ADF4350_REG2_CHARGE_PUMP_CURR_uA(2500), + .r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0), + .r4_user_settings = ADF4350_REG4_OUTPUT_PWR(3) | + ADF4350_REG4_MUTE_TILL_LOCK_EN, + .gpio_lock_detect = -1, +}; + +static int adf4350_sync_config(struct adf4350_state *st) +{ + int ret, i, doublebuf = 0; + + for (i = ADF4350_REG5; i >= ADF4350_REG0; i--) { + if ((st->regs_hw[i] != st->regs[i]) || + ((i == ADF4350_REG0) && doublebuf)) { + + switch (i) { + case ADF4350_REG1: + case ADF4350_REG4: + doublebuf = 1; + break; + } + + st->val = cpu_to_be32(st->regs[i] | i); + ret = spi_write(st->spi, &st->val, 4); + if (ret < 0) + return ret; + st->regs_hw[i] = st->regs[i]; + dev_dbg(&st->spi->dev, "[%d] 0x%X\n", + i, (u32)st->regs[i] | i); + } + } + return 0; +} + +static int adf4350_reg_access(struct iio_dev *indio_dev, + unsigned reg, unsigned writeval, + unsigned *readval) +{ + struct adf4350_state *st = iio_priv(indio_dev); + int ret; + + if (reg > ADF4350_REG5) + return -EINVAL; + + mutex_lock(&indio_dev->mlock); + if (readval == NULL) { + st->regs[reg] = writeval & ~(BIT(0) | BIT(1) | BIT(2)); + ret = adf4350_sync_config(st); + } else { + *readval = st->regs_hw[reg]; + ret = 0; + } + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int adf4350_tune_r_cnt(struct adf4350_state *st, unsigned short r_cnt) +{ + struct adf4350_platform_data *pdata = st->pdata; + + do { + r_cnt++; + st->fpfd = (st->clkin * (pdata->ref_doubler_en ? 2 : 1)) / + (r_cnt * (pdata->ref_div2_en ? 2 : 1)); + } while (st->fpfd > ADF4350_MAX_FREQ_PFD); + + return r_cnt; +} + +static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) +{ + struct adf4350_platform_data *pdata = st->pdata; + u64 tmp; + u32 div_gcd, prescaler; + u16 mdiv, r_cnt = 0; + u8 band_sel_div; + + if (freq > ADF4350_MAX_OUT_FREQ || freq < st->min_out_freq) + return -EINVAL; + + if (freq > ADF4350_MAX_FREQ_45_PRESC) { + prescaler = ADF4350_REG1_PRESCALER; + mdiv = 75; + } else { + prescaler = 0; + mdiv = 23; + } + + st->r4_rf_div_sel = 0; + + while (freq < ADF4350_MIN_VCO_FREQ) { + freq <<= 1; + st->r4_rf_div_sel++; + } + + /* + * Allow a predefined reference division factor + * if not set, compute our own + */ + if (pdata->ref_div_factor) + r_cnt = pdata->ref_div_factor - 1; + + do { + r_cnt = adf4350_tune_r_cnt(st, r_cnt); + + st->r1_mod = st->fpfd / st->chspc; + while (st->r1_mod > ADF4350_MAX_MODULUS) { + r_cnt = adf4350_tune_r_cnt(st, r_cnt); + st->r1_mod = st->fpfd / st->chspc; + } + + tmp = freq * (u64)st->r1_mod + (st->fpfd > 1); + do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */ + st->r0_fract = do_div(tmp, st->r1_mod); + st->r0_int = tmp; + } while (mdiv > st->r0_int); + + band_sel_div = DIV_ROUND_UP(st->fpfd, ADF4350_MAX_BANDSEL_CLK); + + if (st->r0_fract && st->r1_mod) { + div_gcd = gcd(st->r1_mod, st->r0_fract); + st->r1_mod /= div_gcd; + st->r0_fract /= div_gcd; + } else { + st->r0_fract = 0; + st->r1_mod = 1; + } + + dev_dbg(&st->spi->dev, "VCO: %llu Hz, PFD %lu Hz\n" + "REF_DIV %d, R0_INT %d, R0_FRACT %d\n" + "R1_MOD %d, RF_DIV %d\nPRESCALER %s, BAND_SEL_DIV %d\n", + freq, st->fpfd, r_cnt, st->r0_int, st->r0_fract, st->r1_mod, + 1 << st->r4_rf_div_sel, prescaler ? "8/9" : "4/5", + band_sel_div); + + st->regs[ADF4350_REG0] = ADF4350_REG0_INT(st->r0_int) | + ADF4350_REG0_FRACT(st->r0_fract); + + st->regs[ADF4350_REG1] = ADF4350_REG1_PHASE(0) | + ADF4350_REG1_MOD(st->r1_mod) | + prescaler; + + st->regs[ADF4350_REG2] = + ADF4350_REG2_10BIT_R_CNT(r_cnt) | + ADF4350_REG2_DOUBLE_BUFF_EN | + (pdata->ref_doubler_en ? ADF4350_REG2_RMULT2_EN : 0) | + (pdata->ref_div2_en ? ADF4350_REG2_RDIV2_EN : 0) | + (pdata->r2_user_settings & (ADF4350_REG2_PD_POLARITY_POS | + ADF4350_REG2_LDP_6ns | ADF4350_REG2_LDF_INT_N | + ADF4350_REG2_CHARGE_PUMP_CURR_uA(5000) | + ADF4350_REG2_MUXOUT(0x7) | ADF4350_REG2_NOISE_MODE(0x9))); + + st->regs[ADF4350_REG3] = pdata->r3_user_settings & + (ADF4350_REG3_12BIT_CLKDIV(0xFFF) | + ADF4350_REG3_12BIT_CLKDIV_MODE(0x3) | + ADF4350_REG3_12BIT_CSR_EN | + ADF4351_REG3_CHARGE_CANCELLATION_EN | + ADF4351_REG3_ANTI_BACKLASH_3ns_EN | + ADF4351_REG3_BAND_SEL_CLOCK_MODE_HIGH); + + st->regs[ADF4350_REG4] = + ADF4350_REG4_FEEDBACK_FUND | + ADF4350_REG4_RF_DIV_SEL(st->r4_rf_div_sel) | + ADF4350_REG4_8BIT_BAND_SEL_CLKDIV(band_sel_div) | + ADF4350_REG4_RF_OUT_EN | + (pdata->r4_user_settings & + (ADF4350_REG4_OUTPUT_PWR(0x3) | + ADF4350_REG4_AUX_OUTPUT_PWR(0x3) | + ADF4350_REG4_AUX_OUTPUT_EN | + ADF4350_REG4_AUX_OUTPUT_FUND | + ADF4350_REG4_MUTE_TILL_LOCK_EN)); + + st->regs[ADF4350_REG5] = ADF4350_REG5_LD_PIN_MODE_DIGITAL; + + return adf4350_sync_config(st); +} + +static ssize_t adf4350_write(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + const char *buf, size_t len) +{ + struct adf4350_state *st = iio_priv(indio_dev); + unsigned long long readin; + int ret; + + ret = kstrtoull(buf, 10, &readin); + if (ret) + return ret; + + mutex_lock(&indio_dev->mlock); + switch ((u32)private) { + case ADF4350_FREQ: + ret = adf4350_set_freq(st, readin); + break; + case ADF4350_FREQ_REFIN: + if (readin > ADF4350_MAX_FREQ_REFIN) + ret = -EINVAL; + else + st->clkin = readin; + break; + case ADF4350_FREQ_RESOLUTION: + if (readin == 0) + ret = -EINVAL; + else + st->chspc = readin; + break; + case ADF4350_PWRDOWN: + if (readin) + st->regs[ADF4350_REG2] |= ADF4350_REG2_POWER_DOWN_EN; + else + st->regs[ADF4350_REG2] &= ~ADF4350_REG2_POWER_DOWN_EN; + + adf4350_sync_config(st); + break; + default: + ret = -EINVAL; + } + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static ssize_t adf4350_read(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + char *buf) +{ + struct adf4350_state *st = iio_priv(indio_dev); + unsigned long long val; + int ret = 0; + + mutex_lock(&indio_dev->mlock); + switch ((u32)private) { + case ADF4350_FREQ: + val = (u64)((st->r0_int * st->r1_mod) + st->r0_fract) * + (u64)st->fpfd; + do_div(val, st->r1_mod * (1 << st->r4_rf_div_sel)); + /* PLL unlocked? return error */ + if (gpio_is_valid(st->pdata->gpio_lock_detect)) + if (!gpio_get_value(st->pdata->gpio_lock_detect)) { + dev_dbg(&st->spi->dev, "PLL un-locked\n"); + ret = -EBUSY; + } + break; + case ADF4350_FREQ_REFIN: + val = st->clkin; + break; + case ADF4350_FREQ_RESOLUTION: + val = st->chspc; + break; + case ADF4350_PWRDOWN: + val = !!(st->regs[ADF4350_REG2] & ADF4350_REG2_POWER_DOWN_EN); + break; + default: + ret = -EINVAL; + } + mutex_unlock(&indio_dev->mlock); + + return ret < 0 ? ret : sprintf(buf, "%llu\n", val); +} + +#define _ADF4350_EXT_INFO(_name, _ident) { \ + .name = _name, \ + .read = adf4350_read, \ + .write = adf4350_write, \ + .private = _ident, \ +} + +static const struct iio_chan_spec_ext_info adf4350_ext_info[] = { + /* Ideally we use IIO_CHAN_INFO_FREQUENCY, but there are + * values > 2^32 in order to support the entire frequency range + * in Hz. Using scale is a bit ugly. + */ + _ADF4350_EXT_INFO("frequency", ADF4350_FREQ), + _ADF4350_EXT_INFO("frequency_resolution", ADF4350_FREQ_RESOLUTION), + _ADF4350_EXT_INFO("refin_frequency", ADF4350_FREQ_REFIN), + _ADF4350_EXT_INFO("powerdown", ADF4350_PWRDOWN), + { }, +}; + +static const struct iio_chan_spec adf4350_chan = { + .type = IIO_ALTVOLTAGE, + .indexed = 1, + .output = 1, + .ext_info = adf4350_ext_info, +}; + +static const struct iio_info adf4350_info = { + .debugfs_reg_access = &adf4350_reg_access, + .driver_module = THIS_MODULE, +}; + +static int __devinit adf4350_probe(struct spi_device *spi) +{ + struct adf4350_platform_data *pdata = spi->dev.platform_data; + struct iio_dev *indio_dev; + struct adf4350_state *st; + int ret; + + if (!pdata) { + dev_warn(&spi->dev, "no platform data? using default\n"); + + pdata = &default_pdata; + } + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + + st->reg = regulator_get(&spi->dev, "vcc"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) + goto error_put_reg; + } + + spi_set_drvdata(spi, indio_dev); + st->spi = spi; + st->pdata = pdata; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = (pdata->name[0] != 0) ? pdata->name : + spi_get_device_id(spi)->name; + + indio_dev->info = &adf4350_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = &adf4350_chan; + indio_dev->num_channels = 1; + + st->chspc = pdata->channel_spacing; + st->clkin = pdata->clkin; + + st->min_out_freq = spi_get_device_id(spi)->driver_data == 4351 ? + ADF4351_MIN_OUT_FREQ : ADF4350_MIN_OUT_FREQ; + + memset(st->regs_hw, 0xFF, sizeof(st->regs_hw)); + + if (gpio_is_valid(pdata->gpio_lock_detect)) { + ret = gpio_request(pdata->gpio_lock_detect, indio_dev->name); + if (ret) { + dev_err(&spi->dev, "fail to request lock detect GPIO-%d", + pdata->gpio_lock_detect); + goto error_disable_reg; + } + gpio_direction_input(pdata->gpio_lock_detect); + } + + if (pdata->power_up_frequency) { + ret = adf4350_set_freq(st, pdata->power_up_frequency); + if (ret) + goto error_free_gpio; + } + + ret = iio_device_register(indio_dev); + if (ret) + goto error_free_gpio; + + return 0; + +error_free_gpio: + if (gpio_is_valid(pdata->gpio_lock_detect)) + gpio_free(pdata->gpio_lock_detect); + +error_disable_reg: + if (!IS_ERR(st->reg)) + regulator_disable(st->reg); +error_put_reg: + if (!IS_ERR(st->reg)) + regulator_put(st->reg); + + iio_device_free(indio_dev); + + return ret; +} + +static int __devexit adf4350_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct adf4350_state *st = iio_priv(indio_dev); + struct regulator *reg = st->reg; + + st->regs[ADF4350_REG2] |= ADF4350_REG2_POWER_DOWN_EN; + adf4350_sync_config(st); + + iio_device_unregister(indio_dev); + + if (!IS_ERR(reg)) { + regulator_disable(reg); + regulator_put(reg); + } + + if (gpio_is_valid(st->pdata->gpio_lock_detect)) + gpio_free(st->pdata->gpio_lock_detect); + + iio_device_free(indio_dev); + + return 0; +} + +static const struct spi_device_id adf4350_id[] = { + {"adf4350", 4350}, + {"adf4351", 4351}, + {} +}; + +static struct spi_driver adf4350_driver = { + .driver = { + .name = "adf4350", + .owner = THIS_MODULE, + }, + .probe = adf4350_probe, + .remove = __devexit_p(adf4350_remove), + .id_table = adf4350_id, +}; +module_spi_driver(adf4350_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices ADF4350/ADF4351 PLL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/frequency/cf_axi_dds.c b/drivers/iio/frequency/cf_axi_dds.c new file mode 100644 index 0000000000000..0c5a527ee9bf0 --- /dev/null +++ b/drivers/iio/frequency/cf_axi_dds.c @@ -0,0 +1,529 @@ +/* + * DDS PCORE/COREFPGA Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#define CF_AXI_DDS_WAVDATA +#include "cf_axi_dds.h" + +#define DRIVER_NAME "cf_axi_dds" + +struct dds_spidev { + struct device_node *of_nspi; + struct device *dev_spi; +}; + +static void cf_axi_dds_sync_frame(struct cf_axi_dds_state *st) { + dds_write(st, CF_AXI_DDS_DDS_FRAME, 0); + dds_write(st, CF_AXI_DDS_DDS_FRAME, CF_AXI_DDS_DDS_FRAME_SYNC); +} + +static void cf_axi_dds_stop(struct cf_axi_dds_state *st) { + dds_write(st, CF_AXI_DDS_DDS_CTRL, (st->vers_id > 1) ? + CF_AXI_DDS_DDS_CTRL_DDS_CLK_EN_V2 : CF_AXI_DDS_DDS_CTRL_DDS_CLK_EN_V1); +} + +static u32 cf_axi_dds_calc(u32 phase, u32 freq, u32 dac_clk) { + + unsigned long long val64; + u32 val; + + val64 = (u64) freq * 0xFFFFULL; + do_div(val64, dac_clk); + val = ((val64 & 0xFFFF) | 1); + + val64 = (u64) phase * 0xFFFFULL; + do_div(val64, 360000); + val |= val64 << 16; + + return val; +} + +static void cf_axi_dds_mem_init(struct cf_axi_dds_state *st) { + + u32 i, sample, addr, data; + + sample = 0; + addr = 0; + + for (i = 0; i < ARRAY_SIZE(cf_axi_dds_ia_data); i++) { + data = (sample << 24) | (addr << 16); + dds_write(st, CF_AXI_DDS_DDS_MEM_CTRL, ((0 << 26) | data | cf_axi_dds_ia_data[i])); + dds_write(st, CF_AXI_DDS_DDS_MEM_CTRL, ((1 << 26) | data | cf_axi_dds_ib_data[i])); + dds_write(st, CF_AXI_DDS_DDS_MEM_CTRL, ((2 << 26) | data | cf_axi_dds_qa_data[i])); + dds_write(st, CF_AXI_DDS_DDS_MEM_CTRL, ((3 << 26) | data | cf_axi_dds_qb_data[i])); + sample++; + if (sample >= 3) { + addr++; + sample = 0; + } + } +} + +static const int cf_axi_dds_scale_table[16] = { + 10000, 5000, 2500, 1250, 625, 313, 156, +}; + +static int cf_axi_dds_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct cf_axi_dds_state *st = iio_priv(indio_dev); + unsigned long long val64; + unsigned reg; + + switch (m) { + case 0: + if (!chan->output) { + return -EINVAL; + } + reg = dds_read(st, CF_AXI_DDS_DDS_CTRL); + if (st->vers_id > 1) { + if (reg & 0x2) + *val = 1; + else + *val = 0; + + } else { + if (reg & (1 << (chan->channel * 2))) + *val = 1; + else + *val = 0; + } + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + reg = dds_read(st, CF_AXI_DDS_DDS_SCALE); + reg = (reg >> (chan->channel * 4)) & 0xF; + if (!reg) { + *val = 1; + *val2 = 0; + } else { + *val = 0; + *val2 = 1000000 >> reg; + } + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_FREQUENCY: + if (!chan->output) { + *val = st->dac_clk; + return IIO_VAL_INT; + } + reg = dds_read(st, chan->address); + val64 = (u64)(reg & 0xFFFF) * (u64)st->dac_clk; + do_div(val64, 0xFFFF); + *val = val64; + return IIO_VAL_INT; + case IIO_CHAN_INFO_PHASE: + reg = dds_read(st, chan->address); + val64 = (u64)(reg >> 16) * 360000ULL; + do_div(val64, 0xFFFF); + *val = val64; + return IIO_VAL_INT; + } + return -EINVAL; +} + +static int cf_axi_dds_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct cf_axi_dds_state *st = iio_priv(indio_dev); + unsigned long long val64; + unsigned reg, ctrl_reg; + int i; + + ctrl_reg = dds_read(st, CF_AXI_DDS_DDS_CTRL); + + switch (mask) { + case 0: + if (!chan->output) { + return -EINVAL; + } + + if (st->vers_id > 1) { + if (val) + ctrl_reg |= 0x3; + else + ctrl_reg &= ~(0x2); + } else { + if (val) + ctrl_reg |= 1 << (chan->channel * 2); + else + ctrl_reg &= ~(1 << (chan->channel * 2)); + } + + dds_write(st, CF_AXI_DDS_DDS_CTRL, ctrl_reg); + break; + case IIO_CHAN_INFO_SCALE: + if (val == 1) { + i = 0; + } else { + for (i = 1; i < 16; i++) + if (val2 == (1000000 >> i)) + break; + } + cf_axi_dds_stop(st); + reg = dds_read(st, CF_AXI_DDS_DDS_SCALE); + + reg &= ~(0xF << (chan->channel * 4)); + reg |= (i << (chan->channel * 4)); + dds_write(st, CF_AXI_DDS_DDS_SCALE, reg); + dds_write(st, CF_AXI_DDS_DDS_CTRL, ctrl_reg); + break; + case IIO_CHAN_INFO_FREQUENCY: + if (!chan->output) { + st->dac_clk = val; + break; + } + if (val > (st->dac_clk / 2)) + return -EINVAL; + cf_axi_dds_stop(st); + reg = dds_read(st, chan->address); + reg &= 0xFFFF0000; + val64 = (u64) val * 0xFFFFULL; + do_div(val64, st->dac_clk); + reg |= (val64 & 0xFFFF) | 1; + dds_write(st, chan->address, reg); + dds_write(st, CF_AXI_DDS_DDS_CTRL, ctrl_reg); + break; + case IIO_CHAN_INFO_PHASE: + if (val < 0 || val > 360000) + return -EINVAL; + cf_axi_dds_stop(st); + reg = dds_read(st, chan->address); + reg &= 0x0000FFFF; + val64 = (u64) val * 0xFFFFULL; + do_div(val64, 360000); + reg |= val64 << 16; + dds_write(st, chan->address, reg); + dds_write(st, CF_AXI_DDS_DDS_CTRL, ctrl_reg); + break; + default: + return -EINVAL; + } + + cf_axi_dds_sync_frame(st); + + return 0; +} + +static int cf_axi_dds_reg_access(struct iio_dev *indio_dev, + unsigned reg, unsigned writeval, + unsigned *readval) +{ + struct cf_axi_dds_state *st = iio_priv(indio_dev); + struct cf_axi_dds_converter *conv = to_converter(st->dev_spi); + int ret; + + if (IS_ERR(conv)) + return PTR_ERR(conv); + + if (reg > 0xFF) + return -EINVAL; + + mutex_lock(&indio_dev->mlock); + if (readval == NULL) { + ret = conv->write(conv->spi, reg, writeval & 0xFF); + } else { + ret = conv->read(conv->spi, reg); + if (ret < 0) + return ret; + *readval = ret; + ret = 0; + } + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static IIO_CONST_ATTR(out_altvoltage_scale_available, + "1.000000 0.500000 0.250000 0.125000 ..."); + +static struct attribute *cf_axi_dds_attributes[] = { + &iio_const_attr_out_altvoltage_scale_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group cf_axi_dds_attribute_group = { + .attrs = cf_axi_dds_attributes, +}; + +#define CF_AXI_DDS_DDS_CHAN(_chan, _address, _extend_name) \ + { .type = IIO_ALTVOLTAGE, \ + .indexed = 1, \ + .channel = _chan, \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \ + IIO_CHAN_INFO_PHASE_SEPARATE_BIT | \ + IIO_CHAN_INFO_FREQUENCY_SEPARATE_BIT, \ + .address = _address, \ + .output = 1, \ + .extend_name = _extend_name, \ + } + +#define CF_AXI_DDS_DDS_CHAN_CLK_IN(_chan, _extend_name) \ + { .type = IIO_ALTVOLTAGE, \ + .indexed = 1, \ + .channel = _chan, \ + .info_mask = IIO_CHAN_INFO_FREQUENCY_SEPARATE_BIT, \ + .extend_name = _extend_name, \ + } + +static const struct cf_axi_dds_chip_info cf_axi_dds_chip_info_tbl[] = { + [ID_AD9122] = { + .name = "AD9122", + .channel[0] = CF_AXI_DDS_DDS_CHAN(0, CF_AXI_DDS_DDS_1A_OUTPUT_CTRL, "1A"), + .channel[1] = CF_AXI_DDS_DDS_CHAN(1, CF_AXI_DDS_DDS_1B_OUTPUT_CTRL, "1B"), + .channel[2] = CF_AXI_DDS_DDS_CHAN(2, CF_AXI_DDS_DDS_2A_OUTPUT_CTRL, "2A"), + .channel[3] = CF_AXI_DDS_DDS_CHAN(3, CF_AXI_DDS_DDS_2B_OUTPUT_CTRL, "2B"), + .channel[4] = CF_AXI_DDS_DDS_CHAN_CLK_IN(0, "DAC_CLK"), + }, + [ID_AD9739A] = { + .name = "AD9739A", + .channel[0] = CF_AXI_DDS_DDS_CHAN(0, CF_AXI_DDS_DDS_1A_OUTPUT_CTRL, "1A"), + .channel[1] = CF_AXI_DDS_DDS_CHAN(1, CF_AXI_DDS_DDS_1B_OUTPUT_CTRL, "1B"), + .channel[2] = CF_AXI_DDS_DDS_CHAN(2, CF_AXI_DDS_DDS_2A_OUTPUT_CTRL, "2A"), + .channel[3] = CF_AXI_DDS_DDS_CHAN(3, CF_AXI_DDS_DDS_2B_OUTPUT_CTRL, "2B"), + .channel[4] = CF_AXI_DDS_DDS_CHAN_CLK_IN(0, "DAC_CLK"), + }, +}; + +static const struct iio_info cf_axi_dds_info = { + .driver_module = THIS_MODULE, + .read_raw = &cf_axi_dds_read_raw, + .write_raw = &cf_axi_dds_write_raw, + .debugfs_reg_access = &cf_axi_dds_reg_access, + .attrs = &cf_axi_dds_attribute_group, +}; + +static int dds_attach_spi_client(struct device *dev, void *data) +{ + struct dds_spidev *dds_spidev = data; + + if ((dds_spidev->of_nspi == dev->of_node) && dev->driver) { + dds_spidev->dev_spi = dev; + return 1; + } + + return 0; +} + +/* Match table for of_platform binding */ +static const struct of_device_id cf_axi_dds_of_match[] __devinitconst = { + { .compatible = "xlnx,cf-ad9122-core-1.00.a", .data = (void*) 1}, + { .compatible = "xlnx,cf-ad9739a-core-1.00.a", .data = (void*) 1}, + { .compatible = "xlnx,cf-ad9122x2-core-1.00.a", .data = (void*) 1}, + { .compatible = "xlnx,cf-ad9122-core-2.00.a", .data = (void*) 2}, + { .compatible = "xlnx,axi-dac-4d-2c-1.00.a", .data = (void*) 2}, +{ /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, cf_axi_dds_of_match); + +static int __devinit cf_axi_dds_of_probe(struct platform_device *op) +{ + struct cf_axi_dds_state *st; + struct iio_dev *indio_dev; + struct device *dev = &op->dev; + resource_size_t remap_size, phys_addr; + struct dds_spidev dds_spidev; + struct cf_axi_dds_converter *conv; + int ret; + + const struct of_device_id *of_id = + of_match_device(cf_axi_dds_of_match, &op->dev); + + dev_info(dev, "Device Tree Probing \'%s\'\n", + op->dev.of_node->name); + + /* Defer driver probe until matching spi + * converter driver is registered + */ + dds_spidev.of_nspi = of_parse_phandle(op->dev.of_node, + "spibus-connected", 0); + if (!dds_spidev.of_nspi) { + dev_err(&op->dev, "could not find spi node\n"); + return -ENODEV; + } + + ret = bus_for_each_dev(&spi_bus_type, NULL, &dds_spidev, + dds_attach_spi_client); + if (ret == 0) + return -EPROBE_DEFER; + + if (!try_module_get(dds_spidev.dev_spi->driver->owner)) + return -ENODEV; + get_device(dds_spidev.dev_spi); + + indio_dev = iio_device_alloc(sizeof(*st)); + if (indio_dev == NULL) + return -ENOMEM; + + st = iio_priv(indio_dev); + st->dev_spi = dds_spidev.dev_spi; + + dev_set_drvdata(dev, indio_dev); + + if (of_id && of_id->data) + st->vers_id = (unsigned) of_id->data; + else + goto failed1; + + /* Get iospace for the device */ + ret = of_address_to_resource(op->dev.of_node, 0, &st->r_mem); + if (ret) { + dev_err(dev, "invalid address\n"); + goto failed1; + } + + phys_addr = st->r_mem.start; + remap_size = resource_size(&st->r_mem); + if (!request_mem_region(phys_addr, remap_size, DRIVER_NAME)) { + dev_err(dev, "Couldn't lock memory region at 0x%08llX\n", + (unsigned long long)phys_addr); + ret = -EBUSY; + goto failed1; + } + + /* Fill in configuration data and add them to the list */ + st->regs = ioremap(phys_addr, remap_size); + if (st->regs == NULL) { + dev_err(dev, "Couldn't ioremap memory at 0x%08llX\n", + (unsigned long long)phys_addr); + ret = -EFAULT; + goto failed2; + } + + ret = of_property_read_u32(op->dev.of_node, + "dac-sample-frequency", + &st->dac_clk); + if (ret) + st->dac_clk = 491520000; + + conv = to_converter(st->dev_spi); + if (IS_ERR(conv)) { + ret = PTR_ERR(conv); + goto failed3; + } + + ret = conv->setup(conv->spi, 0); + if (ret) { + dev_err(&op->dev, "failed to setup spi device\n"); + goto failed3; + } + + st->chip_info = &cf_axi_dds_chip_info_tbl[conv->id]; + + indio_dev->dev.parent = dev; + indio_dev->name = op->dev.of_node->name; + indio_dev->channels = st->chip_info->channel; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->num_channels = 5; + indio_dev->info = &cf_axi_dds_info; + + cf_axi_dds_mem_init(st); + + dds_write(st, CF_AXI_DDS_DDS_CTRL, 0x0); + dds_write(st, CF_AXI_DDS_DDS_SCALE, 0x1111); /* divide by 4 */ + dds_write(st, CF_AXI_DDS_DDS_1A_OUTPUT_CTRL, + cf_axi_dds_calc(90000, 40000000, st->dac_clk)); + dds_write(st, CF_AXI_DDS_DDS_1B_OUTPUT_CTRL, + cf_axi_dds_calc(90000, 40000000, st->dac_clk)); + dds_write(st, CF_AXI_DDS_DDS_2A_OUTPUT_CTRL, + cf_axi_dds_calc( 0, 40000000, st->dac_clk)); + dds_write(st, CF_AXI_DDS_DDS_2B_OUTPUT_CTRL, + cf_axi_dds_calc( 0, 40000000, st->dac_clk)); + + if (st->vers_id > 1) + dds_write(st, CF_AXI_DDS_DDS_CTRL, 0x3); /* clk, dds enable & ddsx select */ + else + dds_write(st, CF_AXI_DDS_DDS_CTRL, 0x1ff); /* clk, dds enable & ddsx select */ + + cf_axi_dds_sync_frame(st); + + ret = iio_device_register(indio_dev); + if (ret) + goto failed3; + + dev_info(dev, "Analog Devices CF_AXI_DDS_DDS %s (0x%X) at 0x%08llX mapped" + " to 0x%p, probed DDS %s\n", + (dds_read(st, CF_AXI_DDS_DDS_PCORE_IDENT) & + CF_AXI_DDS_DDS_PCORE_IDENT_SLAVE) ? "SLAVE" : "MASTER", + dds_read(st, CF_AXI_DDS_DDS_VERSION_ID), + (unsigned long long)phys_addr, st->regs, st->chip_info->name); + + return 0; /* success */ + +failed3: + iounmap(st->regs); +failed2: + release_mem_region(phys_addr, remap_size); +failed1: + put_device(st->dev_spi); + module_put(st->dev_spi->driver->owner); + dev_set_drvdata(dev, NULL); + iio_device_free(indio_dev); + + return ret; +} + +static int __devexit cf_axi_dds_of_remove(struct platform_device *op) +{ + struct device *dev = &op->dev; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct cf_axi_dds_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + put_device(st->dev_spi); + module_put(st->dev_spi->driver->owner); + iounmap(st->regs); + release_mem_region(st->r_mem.start, resource_size(&st->r_mem)); + + iio_device_free(indio_dev); + dev_set_drvdata(dev, NULL); + + return 0; +} + +static struct platform_driver cf_axi_dds_of_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = cf_axi_dds_of_match, + }, + .probe = cf_axi_dds_of_probe, + .remove = __devexit_p(cf_axi_dds_of_remove), +}; + +module_platform_driver(cf_axi_dds_of_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices DDS"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/frequency/cf_axi_dds.h b/drivers/iio/frequency/cf_axi_dds.h new file mode 100644 index 0000000000000..ce9015928f4f1 --- /dev/null +++ b/drivers/iio/frequency/cf_axi_dds.h @@ -0,0 +1,1169 @@ +/**************************************************************************** +* *************************************************************************** +* Rejeesh.Kutty@Analog.com (c) Analog Devices Inc. +* *************************************************************************** +* *************************************************************************** +* Address Map (AD9122) +* Address offset 0x00 +* [31: 0]: 0x00_01_00_61 +* Address offset 0x04 +* [ 8: 8]: dds clock enable (0x1) or disable (0x0). +* [ 7: 7]: dds-2b select dds-Xilinx(0x1) or dds-mem (0x0). +* [ 6: 6]: dds-2b enable (0x1) or disable (0x0). +* [ 5: 5]: dds-2a select dds-Xilinx(0x1) or dds-mem (0x0). +* [ 4: 4]: dds-2a enable (0x1) or disable (0x0). +* [ 3: 3]: dds-1b select dds-Xilinx(0x1) or dds-mem (0x0). +* [ 2: 2]: dds-1b enable (0x1) or disable (0x0). +* [ 1: 1]: dds-1a select dds-Xilinx(0x1) or dds-mem (0x0). +* [ 0: 0]: dds-1a enable (0x1) or disable (0x0). +* Address offset 0x08 +* [31:16]: dds-1a init (phase offset) count +* [15: 0]: dds-1a increment count +* Address offset 0x0c +* [31:16]: dds-1b init (phase offset) count +* [15: 0]: dds-1b increment count +* Address offset 0x10 +* [31:16]: dds-2a init (phase offset) count +* [15: 0]: dds-2a increment count +* Address offset 0x14 +* [31:16]: dds-2b init (phase offset) count +* [15: 0]: dds-2b increment count +* Address offset 0x18 +* [27:27]: dds mem select i/q (0 to 1). +* [26:26]: dds mem select a/b (0 to 1). +* [25:24]: dds mem sample select (0 to 2). +* [23:16]: dds mem write address +* [15: 0]: dds mem write data +* Address offset 0x20 (data = data >> scale) +* [15:12]: dds scale 2b +* [11: 8]: dds scale 2a +* [ 7: 4]: dds scale 1b +* [ 3: 0]: dds scale 1a +* ***************************************************************************/ + +#define CF_AXI_DDS_DDS_VERSION_ID 0x00 +#define CF_AXI_DDS_DDS_CTRL 0x04 +#define CF_AXI_DDS_DDS_1A_OUTPUT_CTRL 0x08 +#define CF_AXI_DDS_DDS_1B_OUTPUT_CTRL 0x0C +#define CF_AXI_DDS_DDS_2A_OUTPUT_CTRL 0x10 +#define CF_AXI_DDS_DDS_2B_OUTPUT_CTRL 0x14 +#define CF_AXI_DDS_DDS_MEM_CTRL 0x18 +#define CF_AXI_DDS_DDS_SCALE 0x20 +#define CF_AXI_DDS_DDS_FRAME 0x24 +#define CF_AXI_DDS_DDS_PCORE_IDENT 0x48 + +#define CF_AXI_DDS_DDS_CTRL_DDS_CLK_EN_V1 (1 << 8) +#define CF_AXI_DDS_DDS_CTRL_DDS_CLK_EN_V2 (1 << 0) + +/* CF_AXI_DDS_DDS_FRAME */ +#define CF_AXI_DDS_DDS_FRAME_SYNC 0x1 + +/* CF_AXI_DDS_DDS_PCORE_IDENT */ +#define CF_AXI_DDS_DDS_PCORE_IDENT_SLAVE 0x1 + +/* AD9122 internal registers */ + +#define AD9122_I_PHASE_ADJ 0x39 +#define AD9122_Q_PHASE_ADJ 0x3B + +#define AD9122_I_DAC_OFFS 0x3D +#define AD9122_Q_DAC_OFFS 0x3F + +#define AD9122_I_DAC_FS_ADJ 0x41 +#define AD9122_Q_DAC_FS_ADJ 0x45 +#define AD9122_I_AUX_DAC 0x43 + +enum { + ID_AD9122, + ID_AD9739A, +}; + +struct cf_axi_dds_chip_info { + char name[8]; + struct iio_chan_spec channel[5]; +}; + +struct cf_axi_dds_state { + struct list_head list; + struct device *dev_spi; + struct resource r_mem; /* IO mem resources */ + const struct cf_axi_dds_chip_info *chip_info; + u16 int_vref_mv; + int irq; + void __iomem *regs; + unsigned int flags; + u32 dac_clk; + unsigned vers_id; +}; + +struct cf_axi_dds_converter { + struct spi_device *spi; + unsigned id; + int (*read)(struct spi_device *spi, unsigned reg); + int (*write)(struct spi_device *spi, + unsigned reg, unsigned val); + int (*setup)(struct spi_device *spi, unsigned mode); +}; + +static inline struct cf_axi_dds_converter *to_converter(struct device *dev) +{ + struct cf_axi_dds_converter *conv = spi_get_drvdata(to_spi_device(dev)); + + if (conv) + return conv; + + return ERR_PTR(-ENODEV); +}; + +/* + * IO accessors + */ + +static inline void dds_write(struct cf_axi_dds_state *st, + unsigned reg, unsigned val) +{ + iowrite32(val, st->regs + reg); +} + +static inline unsigned int dds_read(struct cf_axi_dds_state *st, unsigned reg) +{ + return ioread32(st->regs + reg); +} + +#if defined(CF_AXI_DDS_WAVDATA) +static const u32 cf_axi_dds_ia_data[] = { + 0x7fff, 0xbf16, 0xedc8, + 0xfff4, 0xf0e1, 0xc479, + 0x8647, 0x4673, 0x1592, + 0x0059, 0x0c4a, 0x364b, + 0x7373, 0xb3de, 0xe6ce, + 0xff08, 0xf640, 0xcebe, + 0x92c7, 0x51ee, 0x1d0e, + 0x01e2, 0x077b, 0x2c64, + 0x6706, 0xa825, 0xded6, + 0xfce2, 0xfa7b, 0xd841, + 0x9f19, 0x5ddc, 0x257d, + 0x04a3, 0x03d6, 0x234c, + 0x5ad7, 0x9c0a, 0xd5f4, + 0xf988, 0xfd88, 0xe0ea, + 0xab1e, 0x6a1d, 0x2ecc, + 0x0894, 0x0163, 0x1b17, + 0x4f04, 0x8faa, 0xcc3e, + 0xf503, 0xff60, 0xe8a5, + 0xb6b9, 0x7695, 0x38e3, + 0x0dab, 0x0027, 0x13dc, + 0x43a9, 0x8323, 0xc1cd, + 0xef5d, 0xfffe, 0xef5d, + 0xc1cd, 0x8323, 0x43a9, + 0x13dc, 0x0027, 0x0dab, + 0x38e3, 0x7695, 0xb6b9, + 0xe8a5, 0xff60, 0xf503, + 0xcc3e, 0x8faa, 0x4f04, + 0x1b17, 0x0163, 0x0894, + 0x2ecc, 0x6a1d, 0xab1e, + 0xe0ea, 0xfd88, 0xf988, + 0xd5f4, 0x9c0a, 0x5ad7, + 0x234c, 0x03d6, 0x04a3, + 0x257d, 0x5ddc, 0x9f19, + 0xd841, 0xfa7b, 0xfce2, + 0xded6, 0xa825, 0x6706, + 0x2c64, 0x077b, 0x01e2, + 0x1d0e, 0x51ee, 0x92c7, + 0xcebe, 0xf640, 0xff08, + 0xe6ce, 0xb3de, 0x7373, + 0x364b, 0x0c4a, 0x0059, + 0x1592, 0x4673, 0x8647, + 0xc479, 0xf0e1, 0xfff4, + 0xedc8, 0xbf16, 0x7fff, + 0x40e8, 0x1236, 0x000a, + 0x0f1d, 0x3b85, 0x79b7, + 0xb98b, 0xea6c, 0xffa5, + 0xf3b4, 0xc9b3, 0x8c8b, + 0x4c20, 0x1930, 0x00f6, + 0x09be, 0x3140, 0x6d37, + 0xae10, 0xe2f0, 0xfe1c, + 0xf883, 0xd39a, 0x98f8, + 0x57d9, 0x2128, 0x031c, + 0x0583, 0x27bd, 0x60e5, + 0xa222, 0xda81, 0xfb5b, + 0xfc28, 0xdcb2, 0xa527, + 0x63f4, 0x2a0a, 0x0676, + 0x0276, 0x1f14, 0x54e0, + 0x95e1, 0xd132, 0xf76a, + 0xfe9b, 0xe4e7, 0xb0fa, + 0x7054, 0x33c0, 0x0afb, + 0x009e, 0x1759, 0x4945, + 0x8969, 0xc71b, 0xf253, + 0xffd7, 0xec22, 0xbc55, + 0x7cdb, 0x3e31, 0x10a1, + 0x0000, 0x10a1, 0x3e31, + 0x7cdb, 0xbc55, 0xec22, + 0xffd7, 0xf253, 0xc71b, + 0x8969, 0x4945, 0x1759, + 0x009e, 0x0afb, 0x33c0, + 0x7054, 0xb0fa, 0xe4e7, + 0xfe9b, 0xf76a, 0xd132, + 0x95e1, 0x54e0, 0x1f14, + 0x0276, 0x0676, 0x2a0a, + 0x63f4, 0xa527, 0xdcb2, + 0xfc28, 0xfb5b, 0xda81, + 0xa222, 0x60e5, 0x27bd, + 0x0583, 0x031c, 0x2128, + 0x57d9, 0x98f8, 0xd39a, + 0xf883, 0xfe1c, 0xe2f0, + 0xae10, 0x6d37, 0x3140, + 0x09be, 0x00f6, 0x1930, + 0x4c20, 0x8c8b, 0xc9b3, + 0xf3b4, 0xffa5, 0xea6c, + 0xb98b, 0x79b7, 0x3b85, + 0x0f1d, 0x000a, 0x1236, + 0x40e8, 0x7fff, 0xbf16, + 0xedc8, 0xfff4, 0xf0e1, + 0xc479, 0x8647, 0x4673, + 0x1592, 0x0059, 0x0c4a, + 0x364b, 0x7373, 0xb3de, + 0xe6ce, 0xff08, 0xf640, + 0xcebe, 0x92c7, 0x51ee, + 0x1d0e, 0x01e2, 0x077b, + 0x2c64, 0x6706, 0xa825, + 0xded6, 0xfce2, 0xfa7b, + 0xd841, 0x9f19, 0x5ddc, + 0x257d, 0x04a3, 0x03d6, + 0x234c, 0x5ad7, 0x9c0a, + 0xd5f4, 0xf988, 0xfd88, + 0xe0ea, 0xab1e, 0x6a1d, + 0x2ecc, 0x0894, 0x0163, + 0x1b17, 0x4f04, 0x8faa, + 0xcc3e, 0xf503, 0xff60, + 0xe8a5, 0xb6b9, 0x7695, + 0x38e3, 0x0dab, 0x0027, + 0x13dc, 0x43a9, 0x8323, + 0xc1cd, 0xef5d, 0xfffe, + 0xef5d, 0xc1cd, 0x8323, + 0x43a9, 0x13dc, 0x0027, + 0x0dab, 0x38e3, 0x7695, + 0xb6b9, 0xe8a5, 0xff60, + 0xf503, 0xcc3e, 0x8faa, + 0x4f04, 0x1b17, 0x0163, + 0x0894, 0x2ecc, 0x6a1d, + 0xab1e, 0xe0ea, 0xfd88, + 0xf988, 0xd5f4, 0x9c0a, + 0x5ad7, 0x234c, 0x03d6, + 0x04a3, 0x257d, 0x5ddc, + 0x9f19, 0xd841, 0xfa7b, + 0xfce2, 0xded6, 0xa825, + 0x6706, 0x2c64, 0x077b, + 0x01e2, 0x1d0e, 0x51ee, + 0x92c7, 0xcebe, 0xf640, + 0xff08, 0xe6ce, 0xb3de, + 0x7373, 0x364b, 0x0c4a, + 0x0059, 0x1592, 0x4673, + 0x8647, 0xc479, 0xf0e1, + 0xfff4, 0xedc8, 0xbf16, + 0x7fff, 0x40e8, 0x1236, + 0x000a, 0x0f1d, 0x3b85, + 0x79b7, 0xb98b, 0xea6c, + 0xffa5, 0xf3b4, 0xc9b3, + 0x8c8b, 0x4c20, 0x1930, + 0x00f6, 0x09be, 0x3140, + 0x6d37, 0xae10, 0xe2f0, + 0xfe1c, 0xf883, 0xd39a, + 0x98f8, 0x57d9, 0x2128, + 0x031c, 0x0583, 0x27bd, + 0x60e5, 0xa222, 0xda81, + 0xfb5b, 0xfc28, 0xdcb2, + 0xa527, 0x63f4, 0x2a0a, + 0x0676, 0x0276, 0x1f14, + 0x54e0, 0x95e1, 0xd132, + 0xf76a, 0xfe9b, 0xe4e7, + 0xb0fa, 0x7054, 0x33c0, + 0x0afb, 0x009e, 0x1759, + 0x4945, 0x8969, 0xc71b, + 0xf253, 0xffd7, 0xec22, + 0xbc55, 0x7cdb, 0x3e31, + 0x10a1, 0x0000, 0x10a1, + 0x3e31, 0x7cdb, 0xbc55, + 0xec22, 0xffd7, 0xf253, + 0xc71b, 0x8969, 0x4945, + 0x1759, 0x009e, 0x0afb, + 0x33c0, 0x7054, 0xb0fa, + 0xe4e7, 0xfe9b, 0xf76a, + 0xd132, 0x95e1, 0x54e0, + 0x1f14, 0x0276, 0x0676, + 0x2a0a, 0x63f4, 0xa527, + 0xdcb2, 0xfc28, 0xfb5b, + 0xda81, 0xa222, 0x60e5, + 0x27bd, 0x0583, 0x031c, + 0x2128, 0x57d9, 0x98f8, + 0xd39a, 0xf883, 0xfe1c, + 0xe2f0, 0xae10, 0x6d37, + 0x3140, 0x09be, 0x00f6, + 0x1930, 0x4c20, 0x8c8b, + 0xc9b3, 0xf3b4, 0xffa5, + 0xea6c, 0xb98b, 0x79b7, + 0x3b85, 0x0f1d, 0x000a, + 0x1236, 0x40e8, 0x7fff, + 0xbf16, 0xedc8, 0xfff4, + 0xf0e1, 0xc479, 0x8647, + 0x4673, 0x1592, 0x0059, + 0x0c4a, 0x364b, 0x7373, + 0xb3de, 0xe6ce, 0xff08, + 0xf640, 0xcebe, 0x92c7, + 0x51ee, 0x1d0e, 0x01e2, + 0x077b, 0x2c64, 0x6706, + 0xa825, 0xded6, 0xfce2, + 0xfa7b, 0xd841, 0x9f19, + 0x5ddc, 0x257d, 0x04a3, + 0x03d6, 0x234c, 0x5ad7, + 0x9c0a, 0xd5f4, 0xf988, + 0xfd88, 0xe0ea, 0xab1e, + 0x6a1d, 0x2ecc, 0x0894, + 0x0163, 0x1b17, 0x4f04, + 0x8faa, 0xcc3e, 0xf503, + 0xff60, 0xe8a5, 0xb6b9, + 0x7695, 0x38e3, 0x0dab, + 0x0027, 0x13dc, 0x43a9, + 0x8323, 0xc1cd, 0xef5d, + 0xfffe, 0xef5d, 0xc1cd, + 0x8323, 0x43a9, 0x13dc, + 0x0027, 0x0dab, 0x38e3, + 0x7695, 0xb6b9, 0xe8a5, + 0xff60, 0xf503, 0xcc3e, + 0x8faa, 0x4f04, 0x1b17, + 0x0163, 0x0894, 0x2ecc, + 0x6a1d, 0xab1e, 0xe0ea, + 0xfd88, 0xf988, 0xd5f4, + 0x9c0a, 0x5ad7, 0x234c, + 0x03d6, 0x04a3, 0x257d, + 0x5ddc, 0x9f19, 0xd841, + 0xfa7b, 0xfce2, 0xded6, + 0xa825, 0x6706, 0x2c64, + 0x077b, 0x01e2, 0x1d0e, + 0x51ee, 0x92c7, 0xcebe, + 0xf640, 0xff08, 0xe6ce, + 0xb3de, 0x7373, 0x364b, + 0x0c4a, 0x0059, 0x1592, + 0x4673, 0x8647, 0xc479, + 0xf0e1, 0xfff4, 0xedc8, + 0xbf16, 0x7fff, 0x40e8, + 0x1236, 0x000a, 0x0f1d, + 0x3b85, 0x79b7, 0xb98b, + 0xea6c, 0xffa5, 0xf3b4, + 0xc9b3, 0x8c8b, 0x4c20, + 0x1930, 0x00f6, 0x09be, + 0x3140, 0x6d37, 0xae10, + 0xe2f0, 0xfe1c, 0xf883, + 0xd39a, 0x98f8, 0x57d9, + 0x2128, 0x031c, 0x0583, + 0x27bd, 0x60e5, 0xa222, + 0xda81, 0xfb5b, 0xfc28, + 0xdcb2, 0xa527, 0x63f4, + 0x2a0a, 0x0676, 0x0276, + 0x1f14, 0x54e0, 0x95e1, + 0xd132, 0xf76a, 0xfe9b, + 0xe4e7, 0xb0fa, 0x7054, + 0x33c0, 0x0afb, 0x009e, + 0x1759, 0x4945, 0x8969, + 0xc71b, 0xf253, 0xffd7, + 0xec22, 0xbc55, 0x7cdb, + 0x3e31, 0x10a1, 0x0000, + 0x10a1, 0x3e31, 0x7cdb, + 0xbc55, 0xec22, 0xffd7, + 0xf253, 0xc71b, 0x8969, + 0x4945, 0x1759, 0x009e, + 0x0afb, 0x33c0, 0x7054, + 0xb0fa, 0xe4e7, 0xfe9b, + 0xf76a, 0xd132, 0x95e1, + 0x54e0, 0x1f14, 0x0276, + 0x0676, 0x2a0a, 0x63f4, + 0xa527, 0xdcb2, 0xfc28, + 0xfb5b, 0xda81, 0xa222, + 0x60e5, 0x27bd, 0x0583, + 0x031c, 0x2128, 0x57d9, + 0x98f8, 0xd39a, 0xf883, + 0xfe1c, 0xe2f0, 0xae10, + 0x6d37, 0x3140, 0x09be, + 0x00f6, 0x1930, 0x4c20, + 0x8c8b, 0xc9b3, 0xf3b4, + 0xffa5, 0xea6c, 0xb98b, + 0x79b7, 0x3b85, 0x0f1d, + 0x000a, 0x1236, 0x40e8 +}; + +static u32 cf_axi_dds_ib_data[] = { + 0x7fff, 0xbf16, 0xedc8, + 0xfff4, 0xf0e1, 0xc479, + 0x8647, 0x4673, 0x1592, + 0x0059, 0x0c4a, 0x364b, + 0x7373, 0xb3de, 0xe6ce, + 0xff08, 0xf640, 0xcebe, + 0x92c7, 0x51ee, 0x1d0e, + 0x01e2, 0x077b, 0x2c64, + 0x6706, 0xa825, 0xded6, + 0xfce2, 0xfa7b, 0xd841, + 0x9f19, 0x5ddc, 0x257d, + 0x04a3, 0x03d6, 0x234c, + 0x5ad7, 0x9c0a, 0xd5f4, + 0xf988, 0xfd88, 0xe0ea, + 0xab1e, 0x6a1d, 0x2ecc, + 0x0894, 0x0163, 0x1b17, + 0x4f04, 0x8faa, 0xcc3e, + 0xf503, 0xff60, 0xe8a5, + 0xb6b9, 0x7695, 0x38e3, + 0x0dab, 0x0027, 0x13dc, + 0x43a9, 0x8323, 0xc1cd, + 0xef5d, 0xfffe, 0xef5d, + 0xc1cd, 0x8323, 0x43a9, + 0x13dc, 0x0027, 0x0dab, + 0x38e3, 0x7695, 0xb6b9, + 0xe8a5, 0xff60, 0xf503, + 0xcc3e, 0x8faa, 0x4f04, + 0x1b17, 0x0163, 0x0894, + 0x2ecc, 0x6a1d, 0xab1e, + 0xe0ea, 0xfd88, 0xf988, + 0xd5f4, 0x9c0a, 0x5ad7, + 0x234c, 0x03d6, 0x04a3, + 0x257d, 0x5ddc, 0x9f19, + 0xd841, 0xfa7b, 0xfce2, + 0xded6, 0xa825, 0x6706, + 0x2c64, 0x077b, 0x01e2, + 0x1d0e, 0x51ee, 0x92c7, + 0xcebe, 0xf640, 0xff08, + 0xe6ce, 0xb3de, 0x7373, + 0x364b, 0x0c4a, 0x0059, + 0x1592, 0x4673, 0x8647, + 0xc479, 0xf0e1, 0xfff4, + 0xedc8, 0xbf16, 0x7fff, + 0x40e8, 0x1236, 0x000a, + 0x0f1d, 0x3b85, 0x79b7, + 0xb98b, 0xea6c, 0xffa5, + 0xf3b4, 0xc9b3, 0x8c8b, + 0x4c20, 0x1930, 0x00f6, + 0x09be, 0x3140, 0x6d37, + 0xae10, 0xe2f0, 0xfe1c, + 0xf883, 0xd39a, 0x98f8, + 0x57d9, 0x2128, 0x031c, + 0x0583, 0x27bd, 0x60e5, + 0xa222, 0xda81, 0xfb5b, + 0xfc28, 0xdcb2, 0xa527, + 0x63f4, 0x2a0a, 0x0676, + 0x0276, 0x1f14, 0x54e0, + 0x95e1, 0xd132, 0xf76a, + 0xfe9b, 0xe4e7, 0xb0fa, + 0x7054, 0x33c0, 0x0afb, + 0x009e, 0x1759, 0x4945, + 0x8969, 0xc71b, 0xf253, + 0xffd7, 0xec22, 0xbc55, + 0x7cdb, 0x3e31, 0x10a1, + 0x0000, 0x10a1, 0x3e31, + 0x7cdb, 0xbc55, 0xec22, + 0xffd7, 0xf253, 0xc71b, + 0x8969, 0x4945, 0x1759, + 0x009e, 0x0afb, 0x33c0, + 0x7054, 0xb0fa, 0xe4e7, + 0xfe9b, 0xf76a, 0xd132, + 0x95e1, 0x54e0, 0x1f14, + 0x0276, 0x0676, 0x2a0a, + 0x63f4, 0xa527, 0xdcb2, + 0xfc28, 0xfb5b, 0xda81, + 0xa222, 0x60e5, 0x27bd, + 0x0583, 0x031c, 0x2128, + 0x57d9, 0x98f8, 0xd39a, + 0xf883, 0xfe1c, 0xe2f0, + 0xae10, 0x6d37, 0x3140, + 0x09be, 0x00f6, 0x1930, + 0x4c20, 0x8c8b, 0xc9b3, + 0xf3b4, 0xffa5, 0xea6c, + 0xb98b, 0x79b7, 0x3b85, + 0x0f1d, 0x000a, 0x1236, + 0x40e8, 0x7fff, 0xbf16, + 0xedc8, 0xfff4, 0xf0e1, + 0xc479, 0x8647, 0x4673, + 0x1592, 0x0059, 0x0c4a, + 0x364b, 0x7373, 0xb3de, + 0xe6ce, 0xff08, 0xf640, + 0xcebe, 0x92c7, 0x51ee, + 0x1d0e, 0x01e2, 0x077b, + 0x2c64, 0x6706, 0xa825, + 0xded6, 0xfce2, 0xfa7b, + 0xd841, 0x9f19, 0x5ddc, + 0x257d, 0x04a3, 0x03d6, + 0x234c, 0x5ad7, 0x9c0a, + 0xd5f4, 0xf988, 0xfd88, + 0xe0ea, 0xab1e, 0x6a1d, + 0x2ecc, 0x0894, 0x0163, + 0x1b17, 0x4f04, 0x8faa, + 0xcc3e, 0xf503, 0xff60, + 0xe8a5, 0xb6b9, 0x7695, + 0x38e3, 0x0dab, 0x0027, + 0x13dc, 0x43a9, 0x8323, + 0xc1cd, 0xef5d, 0xfffe, + 0xef5d, 0xc1cd, 0x8323, + 0x43a9, 0x13dc, 0x0027, + 0x0dab, 0x38e3, 0x7695, + 0xb6b9, 0xe8a5, 0xff60, + 0xf503, 0xcc3e, 0x8faa, + 0x4f04, 0x1b17, 0x0163, + 0x0894, 0x2ecc, 0x6a1d, + 0xab1e, 0xe0ea, 0xfd88, + 0xf988, 0xd5f4, 0x9c0a, + 0x5ad7, 0x234c, 0x03d6, + 0x04a3, 0x257d, 0x5ddc, + 0x9f19, 0xd841, 0xfa7b, + 0xfce2, 0xded6, 0xa825, + 0x6706, 0x2c64, 0x077b, + 0x01e2, 0x1d0e, 0x51ee, + 0x92c7, 0xcebe, 0xf640, + 0xff08, 0xe6ce, 0xb3de, + 0x7373, 0x364b, 0x0c4a, + 0x0059, 0x1592, 0x4673, + 0x8647, 0xc479, 0xf0e1, + 0xfff4, 0xedc8, 0xbf16, + 0x7fff, 0x40e8, 0x1236, + 0x000a, 0x0f1d, 0x3b85, + 0x79b7, 0xb98b, 0xea6c, + 0xffa5, 0xf3b4, 0xc9b3, + 0x8c8b, 0x4c20, 0x1930, + 0x00f6, 0x09be, 0x3140, + 0x6d37, 0xae10, 0xe2f0, + 0xfe1c, 0xf883, 0xd39a, + 0x98f8, 0x57d9, 0x2128, + 0x031c, 0x0583, 0x27bd, + 0x60e5, 0xa222, 0xda81, + 0xfb5b, 0xfc28, 0xdcb2, + 0xa527, 0x63f4, 0x2a0a, + 0x0676, 0x0276, 0x1f14, + 0x54e0, 0x95e1, 0xd132, + 0xf76a, 0xfe9b, 0xe4e7, + 0xb0fa, 0x7054, 0x33c0, + 0x0afb, 0x009e, 0x1759, + 0x4945, 0x8969, 0xc71b, + 0xf253, 0xffd7, 0xec22, + 0xbc55, 0x7cdb, 0x3e31, + 0x10a1, 0x0000, 0x10a1, + 0x3e31, 0x7cdb, 0xbc55, + 0xec22, 0xffd7, 0xf253, + 0xc71b, 0x8969, 0x4945, + 0x1759, 0x009e, 0x0afb, + 0x33c0, 0x7054, 0xb0fa, + 0xe4e7, 0xfe9b, 0xf76a, + 0xd132, 0x95e1, 0x54e0, + 0x1f14, 0x0276, 0x0676, + 0x2a0a, 0x63f4, 0xa527, + 0xdcb2, 0xfc28, 0xfb5b, + 0xda81, 0xa222, 0x60e5, + 0x27bd, 0x0583, 0x031c, + 0x2128, 0x57d9, 0x98f8, + 0xd39a, 0xf883, 0xfe1c, + 0xe2f0, 0xae10, 0x6d37, + 0x3140, 0x09be, 0x00f6, + 0x1930, 0x4c20, 0x8c8b, + 0xc9b3, 0xf3b4, 0xffa5, + 0xea6c, 0xb98b, 0x79b7, + 0x3b85, 0x0f1d, 0x000a, + 0x1236, 0x40e8, 0x7fff, + 0xbf16, 0xedc8, 0xfff4, + 0xf0e1, 0xc479, 0x8647, + 0x4673, 0x1592, 0x0059, + 0x0c4a, 0x364b, 0x7373, + 0xb3de, 0xe6ce, 0xff08, + 0xf640, 0xcebe, 0x92c7, + 0x51ee, 0x1d0e, 0x01e2, + 0x077b, 0x2c64, 0x6706, + 0xa825, 0xded6, 0xfce2, + 0xfa7b, 0xd841, 0x9f19, + 0x5ddc, 0x257d, 0x04a3, + 0x03d6, 0x234c, 0x5ad7, + 0x9c0a, 0xd5f4, 0xf988, + 0xfd88, 0xe0ea, 0xab1e, + 0x6a1d, 0x2ecc, 0x0894, + 0x0163, 0x1b17, 0x4f04, + 0x8faa, 0xcc3e, 0xf503, + 0xff60, 0xe8a5, 0xb6b9, + 0x7695, 0x38e3, 0x0dab, + 0x0027, 0x13dc, 0x43a9, + 0x8323, 0xc1cd, 0xef5d, + 0xfffe, 0xef5d, 0xc1cd, + 0x8323, 0x43a9, 0x13dc, + 0x0027, 0x0dab, 0x38e3, + 0x7695, 0xb6b9, 0xe8a5, + 0xff60, 0xf503, 0xcc3e, + 0x8faa, 0x4f04, 0x1b17, + 0x0163, 0x0894, 0x2ecc, + 0x6a1d, 0xab1e, 0xe0ea, + 0xfd88, 0xf988, 0xd5f4, + 0x9c0a, 0x5ad7, 0x234c, + 0x03d6, 0x04a3, 0x257d, + 0x5ddc, 0x9f19, 0xd841, + 0xfa7b, 0xfce2, 0xded6, + 0xa825, 0x6706, 0x2c64, + 0x077b, 0x01e2, 0x1d0e, + 0x51ee, 0x92c7, 0xcebe, + 0xf640, 0xff08, 0xe6ce, + 0xb3de, 0x7373, 0x364b, + 0x0c4a, 0x0059, 0x1592, + 0x4673, 0x8647, 0xc479, + 0xf0e1, 0xfff4, 0xedc8, + 0xbf16, 0x7fff, 0x40e8, + 0x1236, 0x000a, 0x0f1d, + 0x3b85, 0x79b7, 0xb98b, + 0xea6c, 0xffa5, 0xf3b4, + 0xc9b3, 0x8c8b, 0x4c20, + 0x1930, 0x00f6, 0x09be, + 0x3140, 0x6d37, 0xae10, + 0xe2f0, 0xfe1c, 0xf883, + 0xd39a, 0x98f8, 0x57d9, + 0x2128, 0x031c, 0x0583, + 0x27bd, 0x60e5, 0xa222, + 0xda81, 0xfb5b, 0xfc28, + 0xdcb2, 0xa527, 0x63f4, + 0x2a0a, 0x0676, 0x0276, + 0x1f14, 0x54e0, 0x95e1, + 0xd132, 0xf76a, 0xfe9b, + 0xe4e7, 0xb0fa, 0x7054, + 0x33c0, 0x0afb, 0x009e, + 0x1759, 0x4945, 0x8969, + 0xc71b, 0xf253, 0xffd7, + 0xec22, 0xbc55, 0x7cdb, + 0x3e31, 0x10a1, 0x0000, + 0x10a1, 0x3e31, 0x7cdb, + 0xbc55, 0xec22, 0xffd7, + 0xf253, 0xc71b, 0x8969, + 0x4945, 0x1759, 0x009e, + 0x0afb, 0x33c0, 0x7054, + 0xb0fa, 0xe4e7, 0xfe9b, + 0xf76a, 0xd132, 0x95e1, + 0x54e0, 0x1f14, 0x0276, + 0x0676, 0x2a0a, 0x63f4, + 0xa527, 0xdcb2, 0xfc28, + 0xfb5b, 0xda81, 0xa222, + 0x60e5, 0x27bd, 0x0583, + 0x031c, 0x2128, 0x57d9, + 0x98f8, 0xd39a, 0xf883, + 0xfe1c, 0xe2f0, 0xae10, + 0x6d37, 0x3140, 0x09be, + 0x00f6, 0x1930, 0x4c20, + 0x8c8b, 0xc9b3, 0xf3b4, + 0xffa5, 0xea6c, 0xb98b, + 0x79b7, 0x3b85, 0x0f1d, + 0x000a, 0x1236, 0x40e8 +}; + +static u32 cf_axi_dds_qa_data[] = { + 0x0000, 0x10a1, 0x3e31, + 0x7cdb, 0xbc55, 0xec22, + 0xffd7, 0xf253, 0xc71b, + 0x8969, 0x4945, 0x1759, + 0x009e, 0x0afb, 0x33c0, + 0x7054, 0xb0fa, 0xe4e7, + 0xfe9b, 0xf76a, 0xd132, + 0x95e1, 0x54e0, 0x1f14, + 0x0276, 0x0676, 0x2a0a, + 0x63f4, 0xa527, 0xdcb2, + 0xfc28, 0xfb5b, 0xda81, + 0xa222, 0x60e5, 0x27bd, + 0x0583, 0x031c, 0x2128, + 0x57d9, 0x98f8, 0xd39a, + 0xf883, 0xfe1c, 0xe2f0, + 0xae10, 0x6d37, 0x3140, + 0x09be, 0x00f6, 0x1930, + 0x4c20, 0x8c8b, 0xc9b3, + 0xf3b4, 0xffa5, 0xea6c, + 0xb98b, 0x79b7, 0x3b85, + 0x0f1d, 0x000a, 0x1236, + 0x40e8, 0x7fff, 0xbf16, + 0xedc8, 0xfff4, 0xf0e1, + 0xc479, 0x8647, 0x4673, + 0x1592, 0x0059, 0x0c4a, + 0x364b, 0x7373, 0xb3de, + 0xe6ce, 0xff08, 0xf640, + 0xcebe, 0x92c7, 0x51ee, + 0x1d0e, 0x01e2, 0x077b, + 0x2c64, 0x6706, 0xa825, + 0xded6, 0xfce2, 0xfa7b, + 0xd841, 0x9f19, 0x5ddc, + 0x257d, 0x04a3, 0x03d6, + 0x234c, 0x5ad7, 0x9c0a, + 0xd5f4, 0xf988, 0xfd88, + 0xe0ea, 0xab1e, 0x6a1d, + 0x2ecc, 0x0894, 0x0163, + 0x1b17, 0x4f04, 0x8faa, + 0xcc3e, 0xf503, 0xff60, + 0xe8a5, 0xb6b9, 0x7695, + 0x38e3, 0x0dab, 0x0027, + 0x13dc, 0x43a9, 0x8323, + 0xc1cd, 0xef5d, 0xfffe, + 0xef5d, 0xc1cd, 0x8323, + 0x43a9, 0x13dc, 0x0027, + 0x0dab, 0x38e3, 0x7695, + 0xb6b9, 0xe8a5, 0xff60, + 0xf503, 0xcc3e, 0x8faa, + 0x4f04, 0x1b17, 0x0163, + 0x0894, 0x2ecc, 0x6a1d, + 0xab1e, 0xe0ea, 0xfd88, + 0xf988, 0xd5f4, 0x9c0a, + 0x5ad7, 0x234c, 0x03d6, + 0x04a3, 0x257d, 0x5ddc, + 0x9f19, 0xd841, 0xfa7b, + 0xfce2, 0xded6, 0xa825, + 0x6706, 0x2c64, 0x077b, + 0x01e2, 0x1d0e, 0x51ee, + 0x92c7, 0xcebe, 0xf640, + 0xff08, 0xe6ce, 0xb3de, + 0x7373, 0x364b, 0x0c4a, + 0x0059, 0x1592, 0x4673, + 0x8647, 0xc479, 0xf0e1, + 0xfff4, 0xedc8, 0xbf16, + 0x7fff, 0x40e8, 0x1236, + 0x000a, 0x0f1d, 0x3b85, + 0x79b7, 0xb98b, 0xea6c, + 0xffa5, 0xf3b4, 0xc9b3, + 0x8c8b, 0x4c20, 0x1930, + 0x00f6, 0x09be, 0x3140, + 0x6d37, 0xae10, 0xe2f0, + 0xfe1c, 0xf883, 0xd39a, + 0x98f8, 0x57d9, 0x2128, + 0x031c, 0x0583, 0x27bd, + 0x60e5, 0xa222, 0xda81, + 0xfb5b, 0xfc28, 0xdcb2, + 0xa527, 0x63f4, 0x2a0a, + 0x0676, 0x0276, 0x1f14, + 0x54e0, 0x95e1, 0xd132, + 0xf76a, 0xfe9b, 0xe4e7, + 0xb0fa, 0x7054, 0x33c0, + 0x0afb, 0x009e, 0x1759, + 0x4945, 0x8969, 0xc71b, + 0xf253, 0xffd7, 0xec22, + 0xbc55, 0x7cdb, 0x3e31, + 0x10a1, 0x0000, 0x10a1, + 0x3e31, 0x7cdb, 0xbc55, + 0xec22, 0xffd7, 0xf253, + 0xc71b, 0x8969, 0x4945, + 0x1759, 0x009e, 0x0afb, + 0x33c0, 0x7054, 0xb0fa, + 0xe4e7, 0xfe9b, 0xf76a, + 0xd132, 0x95e1, 0x54e0, + 0x1f14, 0x0276, 0x0676, + 0x2a0a, 0x63f4, 0xa527, + 0xdcb2, 0xfc28, 0xfb5b, + 0xda81, 0xa222, 0x60e5, + 0x27bd, 0x0583, 0x031c, + 0x2128, 0x57d9, 0x98f8, + 0xd39a, 0xf883, 0xfe1c, + 0xe2f0, 0xae10, 0x6d37, + 0x3140, 0x09be, 0x00f6, + 0x1930, 0x4c20, 0x8c8b, + 0xc9b3, 0xf3b4, 0xffa5, + 0xea6c, 0xb98b, 0x79b7, + 0x3b85, 0x0f1d, 0x000a, + 0x1236, 0x40e8, 0x7fff, + 0xbf16, 0xedc8, 0xfff4, + 0xf0e1, 0xc479, 0x8647, + 0x4673, 0x1592, 0x0059, + 0x0c4a, 0x364b, 0x7373, + 0xb3de, 0xe6ce, 0xff08, + 0xf640, 0xcebe, 0x92c7, + 0x51ee, 0x1d0e, 0x01e2, + 0x077b, 0x2c64, 0x6706, + 0xa825, 0xded6, 0xfce2, + 0xfa7b, 0xd841, 0x9f19, + 0x5ddc, 0x257d, 0x04a3, + 0x03d6, 0x234c, 0x5ad7, + 0x9c0a, 0xd5f4, 0xf988, + 0xfd88, 0xe0ea, 0xab1e, + 0x6a1d, 0x2ecc, 0x0894, + 0x0163, 0x1b17, 0x4f04, + 0x8faa, 0xcc3e, 0xf503, + 0xff60, 0xe8a5, 0xb6b9, + 0x7695, 0x38e3, 0x0dab, + 0x0027, 0x13dc, 0x43a9, + 0x8323, 0xc1cd, 0xef5d, + 0xfffe, 0xef5d, 0xc1cd, + 0x8323, 0x43a9, 0x13dc, + 0x0027, 0x0dab, 0x38e3, + 0x7695, 0xb6b9, 0xe8a5, + 0xff60, 0xf503, 0xcc3e, + 0x8faa, 0x4f04, 0x1b17, + 0x0163, 0x0894, 0x2ecc, + 0x6a1d, 0xab1e, 0xe0ea, + 0xfd88, 0xf988, 0xd5f4, + 0x9c0a, 0x5ad7, 0x234c, + 0x03d6, 0x04a3, 0x257d, + 0x5ddc, 0x9f19, 0xd841, + 0xfa7b, 0xfce2, 0xded6, + 0xa825, 0x6706, 0x2c64, + 0x077b, 0x01e2, 0x1d0e, + 0x51ee, 0x92c7, 0xcebe, + 0xf640, 0xff08, 0xe6ce, + 0xb3de, 0x7373, 0x364b, + 0x0c4a, 0x0059, 0x1592, + 0x4673, 0x8647, 0xc479, + 0xf0e1, 0xfff4, 0xedc8, + 0xbf16, 0x7fff, 0x40e8, + 0x1236, 0x000a, 0x0f1d, + 0x3b85, 0x79b7, 0xb98b, + 0xea6c, 0xffa5, 0xf3b4, + 0xc9b3, 0x8c8b, 0x4c20, + 0x1930, 0x00f6, 0x09be, + 0x3140, 0x6d37, 0xae10, + 0xe2f0, 0xfe1c, 0xf883, + 0xd39a, 0x98f8, 0x57d9, + 0x2128, 0x031c, 0x0583, + 0x27bd, 0x60e5, 0xa222, + 0xda81, 0xfb5b, 0xfc28, + 0xdcb2, 0xa527, 0x63f4, + 0x2a0a, 0x0676, 0x0276, + 0x1f14, 0x54e0, 0x95e1, + 0xd132, 0xf76a, 0xfe9b, + 0xe4e7, 0xb0fa, 0x7054, + 0x33c0, 0x0afb, 0x009e, + 0x1759, 0x4945, 0x8969, + 0xc71b, 0xf253, 0xffd7, + 0xec22, 0xbc55, 0x7cdb, + 0x3e31, 0x10a1, 0x0000, + 0x10a1, 0x3e31, 0x7cdb, + 0xbc55, 0xec22, 0xffd7, + 0xf253, 0xc71b, 0x8969, + 0x4945, 0x1759, 0x009e, + 0x0afb, 0x33c0, 0x7054, + 0xb0fa, 0xe4e7, 0xfe9b, + 0xf76a, 0xd132, 0x95e1, + 0x54e0, 0x1f14, 0x0276, + 0x0676, 0x2a0a, 0x63f4, + 0xa527, 0xdcb2, 0xfc28, + 0xfb5b, 0xda81, 0xa222, + 0x60e5, 0x27bd, 0x0583, + 0x031c, 0x2128, 0x57d9, + 0x98f8, 0xd39a, 0xf883, + 0xfe1c, 0xe2f0, 0xae10, + 0x6d37, 0x3140, 0x09be, + 0x00f6, 0x1930, 0x4c20, + 0x8c8b, 0xc9b3, 0xf3b4, + 0xffa5, 0xea6c, 0xb98b, + 0x79b7, 0x3b85, 0x0f1d, + 0x000a, 0x1236, 0x40e8, + 0x7fff, 0xbf16, 0xedc8, + 0xfff4, 0xf0e1, 0xc479, + 0x8647, 0x4673, 0x1592, + 0x0059, 0x0c4a, 0x364b, + 0x7373, 0xb3de, 0xe6ce, + 0xff08, 0xf640, 0xcebe, + 0x92c7, 0x51ee, 0x1d0e, + 0x01e2, 0x077b, 0x2c64, + 0x6706, 0xa825, 0xded6, + 0xfce2, 0xfa7b, 0xd841, + 0x9f19, 0x5ddc, 0x257d, + 0x04a3, 0x03d6, 0x234c, + 0x5ad7, 0x9c0a, 0xd5f4, + 0xf988, 0xfd88, 0xe0ea, + 0xab1e, 0x6a1d, 0x2ecc, + 0x0894, 0x0163, 0x1b17, + 0x4f04, 0x8faa, 0xcc3e, + 0xf503, 0xff60, 0xe8a5, + 0xb6b9, 0x7695, 0x38e3, + 0x0dab, 0x0027, 0x13dc, + 0x43a9, 0x8323, 0xc1cd, + 0xef5d, 0xfffe, 0xef5d, + 0xc1cd, 0x8323, 0x43a9, + 0x13dc, 0x0027, 0x0dab, + 0x38e3, 0x7695, 0xb6b9, + 0xe8a5, 0xff60, 0xf503, + 0xcc3e, 0x8faa, 0x4f04, + 0x1b17, 0x0163, 0x0894, + 0x2ecc, 0x6a1d, 0xab1e, + 0xe0ea, 0xfd88, 0xf988, + 0xd5f4, 0x9c0a, 0x5ad7, + 0x234c, 0x03d6, 0x04a3, + 0x257d, 0x5ddc, 0x9f19, + 0xd841, 0xfa7b, 0xfce2, + 0xded6, 0xa825, 0x6706, + 0x2c64, 0x077b, 0x01e2, + 0x1d0e, 0x51ee, 0x92c7, + 0xcebe, 0xf640, 0xff08, + 0xe6ce, 0xb3de, 0x7373, + 0x364b, 0x0c4a, 0x0059, + 0x1592, 0x4673, 0x8647, + 0xc479, 0xf0e1, 0xfff4, + 0xedc8, 0xbf16, 0x7fff, + 0x40e8, 0x1236, 0x000a, + 0x0f1d, 0x3b85, 0x79b7, + 0xb98b, 0xea6c, 0xffa5, + 0xf3b4, 0xc9b3, 0x8c8b, + 0x4c20, 0x1930, 0x00f6, + 0x09be, 0x3140, 0x6d37, + 0xae10, 0xe2f0, 0xfe1c, + 0xf883, 0xd39a, 0x98f8, + 0x57d9, 0x2128, 0x031c, + 0x0583, 0x27bd, 0x60e5, + 0xa222, 0xda81, 0xfb5b, + 0xfc28, 0xdcb2, 0xa527, + 0x63f4, 0x2a0a, 0x0676, + 0x0276, 0x1f14, 0x54e0, + 0x95e1, 0xd132, 0xf76a, + 0xfe9b, 0xe4e7, 0xb0fa, + 0x7054, 0x33c0, 0x0afb, + 0x009e, 0x1759, 0x4945, + 0x8969, 0xc71b, 0xf253, + 0xffd7, 0xec22, 0xbc55, + 0x7cdb, 0x3e31, 0x10a1 +}; + +static u32 cf_axi_dds_qb_data[] = { + 0x0000, 0x10a1, 0x3e31, + 0x7cdb, 0xbc55, 0xec22, + 0xffd7, 0xf253, 0xc71b, + 0x8969, 0x4945, 0x1759, + 0x009e, 0x0afb, 0x33c0, + 0x7054, 0xb0fa, 0xe4e7, + 0xfe9b, 0xf76a, 0xd132, + 0x95e1, 0x54e0, 0x1f14, + 0x0276, 0x0676, 0x2a0a, + 0x63f4, 0xa527, 0xdcb2, + 0xfc28, 0xfb5b, 0xda81, + 0xa222, 0x60e5, 0x27bd, + 0x0583, 0x031c, 0x2128, + 0x57d9, 0x98f8, 0xd39a, + 0xf883, 0xfe1c, 0xe2f0, + 0xae10, 0x6d37, 0x3140, + 0x09be, 0x00f6, 0x1930, + 0x4c20, 0x8c8b, 0xc9b3, + 0xf3b4, 0xffa5, 0xea6c, + 0xb98b, 0x79b7, 0x3b85, + 0x0f1d, 0x000a, 0x1236, + 0x40e8, 0x7fff, 0xbf16, + 0xedc8, 0xfff4, 0xf0e1, + 0xc479, 0x8647, 0x4673, + 0x1592, 0x0059, 0x0c4a, + 0x364b, 0x7373, 0xb3de, + 0xe6ce, 0xff08, 0xf640, + 0xcebe, 0x92c7, 0x51ee, + 0x1d0e, 0x01e2, 0x077b, + 0x2c64, 0x6706, 0xa825, + 0xded6, 0xfce2, 0xfa7b, + 0xd841, 0x9f19, 0x5ddc, + 0x257d, 0x04a3, 0x03d6, + 0x234c, 0x5ad7, 0x9c0a, + 0xd5f4, 0xf988, 0xfd88, + 0xe0ea, 0xab1e, 0x6a1d, + 0x2ecc, 0x0894, 0x0163, + 0x1b17, 0x4f04, 0x8faa, + 0xcc3e, 0xf503, 0xff60, + 0xe8a5, 0xb6b9, 0x7695, + 0x38e3, 0x0dab, 0x0027, + 0x13dc, 0x43a9, 0x8323, + 0xc1cd, 0xef5d, 0xfffe, + 0xef5d, 0xc1cd, 0x8323, + 0x43a9, 0x13dc, 0x0027, + 0x0dab, 0x38e3, 0x7695, + 0xb6b9, 0xe8a5, 0xff60, + 0xf503, 0xcc3e, 0x8faa, + 0x4f04, 0x1b17, 0x0163, + 0x0894, 0x2ecc, 0x6a1d, + 0xab1e, 0xe0ea, 0xfd88, + 0xf988, 0xd5f4, 0x9c0a, + 0x5ad7, 0x234c, 0x03d6, + 0x04a3, 0x257d, 0x5ddc, + 0x9f19, 0xd841, 0xfa7b, + 0xfce2, 0xded6, 0xa825, + 0x6706, 0x2c64, 0x077b, + 0x01e2, 0x1d0e, 0x51ee, + 0x92c7, 0xcebe, 0xf640, + 0xff08, 0xe6ce, 0xb3de, + 0x7373, 0x364b, 0x0c4a, + 0x0059, 0x1592, 0x4673, + 0x8647, 0xc479, 0xf0e1, + 0xfff4, 0xedc8, 0xbf16, + 0x7fff, 0x40e8, 0x1236, + 0x000a, 0x0f1d, 0x3b85, + 0x79b7, 0xb98b, 0xea6c, + 0xffa5, 0xf3b4, 0xc9b3, + 0x8c8b, 0x4c20, 0x1930, + 0x00f6, 0x09be, 0x3140, + 0x6d37, 0xae10, 0xe2f0, + 0xfe1c, 0xf883, 0xd39a, + 0x98f8, 0x57d9, 0x2128, + 0x031c, 0x0583, 0x27bd, + 0x60e5, 0xa222, 0xda81, + 0xfb5b, 0xfc28, 0xdcb2, + 0xa527, 0x63f4, 0x2a0a, + 0x0676, 0x0276, 0x1f14, + 0x54e0, 0x95e1, 0xd132, + 0xf76a, 0xfe9b, 0xe4e7, + 0xb0fa, 0x7054, 0x33c0, + 0x0afb, 0x009e, 0x1759, + 0x4945, 0x8969, 0xc71b, + 0xf253, 0xffd7, 0xec22, + 0xbc55, 0x7cdb, 0x3e31, + 0x10a1, 0x0000, 0x10a1, + 0x3e31, 0x7cdb, 0xbc55, + 0xec22, 0xffd7, 0xf253, + 0xc71b, 0x8969, 0x4945, + 0x1759, 0x009e, 0x0afb, + 0x33c0, 0x7054, 0xb0fa, + 0xe4e7, 0xfe9b, 0xf76a, + 0xd132, 0x95e1, 0x54e0, + 0x1f14, 0x0276, 0x0676, + 0x2a0a, 0x63f4, 0xa527, + 0xdcb2, 0xfc28, 0xfb5b, + 0xda81, 0xa222, 0x60e5, + 0x27bd, 0x0583, 0x031c, + 0x2128, 0x57d9, 0x98f8, + 0xd39a, 0xf883, 0xfe1c, + 0xe2f0, 0xae10, 0x6d37, + 0x3140, 0x09be, 0x00f6, + 0x1930, 0x4c20, 0x8c8b, + 0xc9b3, 0xf3b4, 0xffa5, + 0xea6c, 0xb98b, 0x79b7, + 0x3b85, 0x0f1d, 0x000a, + 0x1236, 0x40e8, 0x7fff, + 0xbf16, 0xedc8, 0xfff4, + 0xf0e1, 0xc479, 0x8647, + 0x4673, 0x1592, 0x0059, + 0x0c4a, 0x364b, 0x7373, + 0xb3de, 0xe6ce, 0xff08, + 0xf640, 0xcebe, 0x92c7, + 0x51ee, 0x1d0e, 0x01e2, + 0x077b, 0x2c64, 0x6706, + 0xa825, 0xded6, 0xfce2, + 0xfa7b, 0xd841, 0x9f19, + 0x5ddc, 0x257d, 0x04a3, + 0x03d6, 0x234c, 0x5ad7, + 0x9c0a, 0xd5f4, 0xf988, + 0xfd88, 0xe0ea, 0xab1e, + 0x6a1d, 0x2ecc, 0x0894, + 0x0163, 0x1b17, 0x4f04, + 0x8faa, 0xcc3e, 0xf503, + 0xff60, 0xe8a5, 0xb6b9, + 0x7695, 0x38e3, 0x0dab, + 0x0027, 0x13dc, 0x43a9, + 0x8323, 0xc1cd, 0xef5d, + 0xfffe, 0xef5d, 0xc1cd, + 0x8323, 0x43a9, 0x13dc, + 0x0027, 0x0dab, 0x38e3, + 0x7695, 0xb6b9, 0xe8a5, + 0xff60, 0xf503, 0xcc3e, + 0x8faa, 0x4f04, 0x1b17, + 0x0163, 0x0894, 0x2ecc, + 0x6a1d, 0xab1e, 0xe0ea, + 0xfd88, 0xf988, 0xd5f4, + 0x9c0a, 0x5ad7, 0x234c, + 0x03d6, 0x04a3, 0x257d, + 0x5ddc, 0x9f19, 0xd841, + 0xfa7b, 0xfce2, 0xded6, + 0xa825, 0x6706, 0x2c64, + 0x077b, 0x01e2, 0x1d0e, + 0x51ee, 0x92c7, 0xcebe, + 0xf640, 0xff08, 0xe6ce, + 0xb3de, 0x7373, 0x364b, + 0x0c4a, 0x0059, 0x1592, + 0x4673, 0x8647, 0xc479, + 0xf0e1, 0xfff4, 0xedc8, + 0xbf16, 0x7fff, 0x40e8, + 0x1236, 0x000a, 0x0f1d, + 0x3b85, 0x79b7, 0xb98b, + 0xea6c, 0xffa5, 0xf3b4, + 0xc9b3, 0x8c8b, 0x4c20, + 0x1930, 0x00f6, 0x09be, + 0x3140, 0x6d37, 0xae10, + 0xe2f0, 0xfe1c, 0xf883, + 0xd39a, 0x98f8, 0x57d9, + 0x2128, 0x031c, 0x0583, + 0x27bd, 0x60e5, 0xa222, + 0xda81, 0xfb5b, 0xfc28, + 0xdcb2, 0xa527, 0x63f4, + 0x2a0a, 0x0676, 0x0276, + 0x1f14, 0x54e0, 0x95e1, + 0xd132, 0xf76a, 0xfe9b, + 0xe4e7, 0xb0fa, 0x7054, + 0x33c0, 0x0afb, 0x009e, + 0x1759, 0x4945, 0x8969, + 0xc71b, 0xf253, 0xffd7, + 0xec22, 0xbc55, 0x7cdb, + 0x3e31, 0x10a1, 0x0000, + 0x10a1, 0x3e31, 0x7cdb, + 0xbc55, 0xec22, 0xffd7, + 0xf253, 0xc71b, 0x8969, + 0x4945, 0x1759, 0x009e, + 0x0afb, 0x33c0, 0x7054, + 0xb0fa, 0xe4e7, 0xfe9b, + 0xf76a, 0xd132, 0x95e1, + 0x54e0, 0x1f14, 0x0276, + 0x0676, 0x2a0a, 0x63f4, + 0xa527, 0xdcb2, 0xfc28, + 0xfb5b, 0xda81, 0xa222, + 0x60e5, 0x27bd, 0x0583, + 0x031c, 0x2128, 0x57d9, + 0x98f8, 0xd39a, 0xf883, + 0xfe1c, 0xe2f0, 0xae10, + 0x6d37, 0x3140, 0x09be, + 0x00f6, 0x1930, 0x4c20, + 0x8c8b, 0xc9b3, 0xf3b4, + 0xffa5, 0xea6c, 0xb98b, + 0x79b7, 0x3b85, 0x0f1d, + 0x000a, 0x1236, 0x40e8, + 0x7fff, 0xbf16, 0xedc8, + 0xfff4, 0xf0e1, 0xc479, + 0x8647, 0x4673, 0x1592, + 0x0059, 0x0c4a, 0x364b, + 0x7373, 0xb3de, 0xe6ce, + 0xff08, 0xf640, 0xcebe, + 0x92c7, 0x51ee, 0x1d0e, + 0x01e2, 0x077b, 0x2c64, + 0x6706, 0xa825, 0xded6, + 0xfce2, 0xfa7b, 0xd841, + 0x9f19, 0x5ddc, 0x257d, + 0x04a3, 0x03d6, 0x234c, + 0x5ad7, 0x9c0a, 0xd5f4, + 0xf988, 0xfd88, 0xe0ea, + 0xab1e, 0x6a1d, 0x2ecc, + 0x0894, 0x0163, 0x1b17, + 0x4f04, 0x8faa, 0xcc3e, + 0xf503, 0xff60, 0xe8a5, + 0xb6b9, 0x7695, 0x38e3, + 0x0dab, 0x0027, 0x13dc, + 0x43a9, 0x8323, 0xc1cd, + 0xef5d, 0xfffe, 0xef5d, + 0xc1cd, 0x8323, 0x43a9, + 0x13dc, 0x0027, 0x0dab, + 0x38e3, 0x7695, 0xb6b9, + 0xe8a5, 0xff60, 0xf503, + 0xcc3e, 0x8faa, 0x4f04, + 0x1b17, 0x0163, 0x0894, + 0x2ecc, 0x6a1d, 0xab1e, + 0xe0ea, 0xfd88, 0xf988, + 0xd5f4, 0x9c0a, 0x5ad7, + 0x234c, 0x03d6, 0x04a3, + 0x257d, 0x5ddc, 0x9f19, + 0xd841, 0xfa7b, 0xfce2, + 0xded6, 0xa825, 0x6706, + 0x2c64, 0x077b, 0x01e2, + 0x1d0e, 0x51ee, 0x92c7, + 0xcebe, 0xf640, 0xff08, + 0xe6ce, 0xb3de, 0x7373, + 0x364b, 0x0c4a, 0x0059, + 0x1592, 0x4673, 0x8647, + 0xc479, 0xf0e1, 0xfff4, + 0xedc8, 0xbf16, 0x7fff, + 0x40e8, 0x1236, 0x000a, + 0x0f1d, 0x3b85, 0x79b7, + 0xb98b, 0xea6c, 0xffa5, + 0xf3b4, 0xc9b3, 0x8c8b, + 0x4c20, 0x1930, 0x00f6, + 0x09be, 0x3140, 0x6d37, + 0xae10, 0xe2f0, 0xfe1c, + 0xf883, 0xd39a, 0x98f8, + 0x57d9, 0x2128, 0x031c, + 0x0583, 0x27bd, 0x60e5, + 0xa222, 0xda81, 0xfb5b, + 0xfc28, 0xdcb2, 0xa527, + 0x63f4, 0x2a0a, 0x0676, + 0x0276, 0x1f14, 0x54e0, + 0x95e1, 0xd132, 0xf76a, + 0xfe9b, 0xe4e7, 0xb0fa, + 0x7054, 0x33c0, 0x0afb, + 0x009e, 0x1759, 0x4945, + 0x8969, 0xc71b, 0xf253, + 0xffd7, 0xec22, 0xbc55, + 0x7cdb, 0x3e31, 0x10a1 +}; +#endif /* CF_AXI_DDS_WAVDATA */ diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h new file mode 100644 index 0000000000000..f652e6ae5a359 --- /dev/null +++ b/drivers/iio/iio_core.h @@ -0,0 +1,62 @@ +/* The industrial I/O core function defs. + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * These definitions are meant for use only within the IIO core, not individual + * drivers. + */ + +#ifndef _IIO_CORE_H_ +#define _IIO_CORE_H_ +#include +#include + +struct iio_chan_spec; +struct iio_dev; + + +int __iio_add_chan_devattr(const char *postfix, + struct iio_chan_spec const *chan, + ssize_t (*func)(struct device *dev, + struct device_attribute *attr, + char *buf), + ssize_t (*writefunc)(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len), + u64 mask, + bool generic, + struct device *dev, + struct list_head *attr_list); + +/* Event interface flags */ +#define IIO_BUSY_BIT_POS 1 + +#ifdef CONFIG_IIO_BUFFER +struct poll_table_struct; + +unsigned int iio_buffer_poll(struct file *filp, + struct poll_table_struct *wait); +ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, + size_t n, loff_t *f_ps); + + +#define iio_buffer_poll_addr (&iio_buffer_poll) +#define iio_buffer_read_first_n_outer_addr (&iio_buffer_read_first_n_outer) + +#else + +#define iio_buffer_poll_addr NULL +#define iio_buffer_read_first_n_outer_addr NULL + +#endif + +int iio_device_register_eventset(struct iio_dev *indio_dev); +void iio_device_unregister_eventset(struct iio_dev *indio_dev); +int iio_event_getfd(struct iio_dev *indio_dev); + +#endif diff --git a/drivers/iio/iio_core_trigger.h b/drivers/iio/iio_core_trigger.h new file mode 100644 index 0000000000000..6f7c56fcbe785 --- /dev/null +++ b/drivers/iio/iio_core_trigger.h @@ -0,0 +1,46 @@ + +/* The industrial I/O core, trigger consumer handling functions + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#ifdef CONFIG_IIO_TRIGGER +/** + * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers + * @indio_dev: iio_dev associated with the device that will consume the trigger + **/ +void iio_device_register_trigger_consumer(struct iio_dev *indio_dev); + +/** + * iio_device_unregister_trigger_consumer() - reverse the registration process + * @indio_dev: iio_dev associated with the device that consumed the trigger + **/ +void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev); + +#else + +/** + * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers + * @indio_dev: iio_dev associated with the device that will consume the trigger + **/ +static int iio_device_register_trigger_consumer(struct iio_dev *indio_dev) +{ + return 0; +}; + +/** + * iio_device_unregister_trigger_consumer() - reverse the registration process + * @indio_dev: iio_dev associated with the device that consumed the trigger + **/ +static void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev) +{ +}; + +#endif /* CONFIG_TRIGGER_CONSUMER */ + + + diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c new file mode 100644 index 0000000000000..096a6bfe0cdfa --- /dev/null +++ b/drivers/iio/industrialio-buffer.c @@ -0,0 +1,762 @@ +/* The industrial I/O core + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * Handling of buffer allocation / resizing. + * + * + * Things to look at here. + * - Better memory allocation techniques? + * - Alternative access techniques? + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include "iio_core.h" +#include +#include + +static const char * const iio_endian_prefix[] = { + [IIO_BE] = "be", + [IIO_LE] = "le", +}; + +/** + * iio_buffer_read_first_n_outer() - chrdev read for buffer access + * + * This function relies on all buffer implementations having an + * iio_buffer as their first element. + **/ +ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, + size_t n, loff_t *f_ps) +{ + struct iio_dev *indio_dev = filp->private_data; + struct iio_buffer *rb = indio_dev->buffer; + + if (!rb || !rb->access->read_first_n) + return -EINVAL; + return rb->access->read_first_n(rb, n, buf); +} + +/** + * iio_buffer_poll() - poll the buffer to find out if it has data + */ +unsigned int iio_buffer_poll(struct file *filp, + struct poll_table_struct *wait) +{ + struct iio_dev *indio_dev = filp->private_data; + struct iio_buffer *rb = indio_dev->buffer; + + poll_wait(filp, &rb->pollq, wait); + if (rb->stufftoread) + return POLLIN | POLLRDNORM; + /* need a way of knowing if there may be enough data... */ + return 0; +} + +void iio_buffer_init(struct iio_buffer *buffer) +{ + INIT_LIST_HEAD(&buffer->demux_list); + init_waitqueue_head(&buffer->pollq); +} +EXPORT_SYMBOL(iio_buffer_init); + +static ssize_t iio_show_scan_index(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", to_iio_dev_attr(attr)->c->scan_index); +} + +static ssize_t iio_show_fixed_type(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + u8 type = this_attr->c->scan_type.endianness; + + if (type == IIO_CPU) { +#ifdef __LITTLE_ENDIAN + type = IIO_LE; +#else + type = IIO_BE; +#endif + } + return sprintf(buf, "%s:%c%d/%d>>%u\n", + iio_endian_prefix[type], + this_attr->c->scan_type.sign, + this_attr->c->scan_type.realbits, + this_attr->c->scan_type.storagebits, + this_attr->c->scan_type.shift); +} + +static ssize_t iio_scan_el_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + + ret = test_bit(to_iio_dev_attr(attr)->address, + indio_dev->buffer->scan_mask); + + return sprintf(buf, "%d\n", ret); +} + +static int iio_scan_mask_clear(struct iio_buffer *buffer, int bit) +{ + clear_bit(bit, buffer->scan_mask); + return 0; +} + +static ssize_t iio_scan_el_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + int ret; + bool state; + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_buffer *buffer = indio_dev->buffer; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = strtobool(buf, &state); + if (ret < 0) + return ret; + mutex_lock(&indio_dev->mlock); + if (iio_buffer_enabled(indio_dev)) { + ret = -EBUSY; + goto error_ret; + } + ret = iio_scan_mask_query(indio_dev, buffer, this_attr->address); + if (ret < 0) + goto error_ret; + if (!state && ret) { + ret = iio_scan_mask_clear(buffer, this_attr->address); + if (ret) + goto error_ret; + } else if (state && !ret) { + ret = iio_scan_mask_set(indio_dev, buffer, this_attr->address); + if (ret) + goto error_ret; + } + +error_ret: + mutex_unlock(&indio_dev->mlock); + + return ret < 0 ? ret : len; + +} + +static ssize_t iio_scan_el_ts_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + return sprintf(buf, "%d\n", indio_dev->buffer->scan_timestamp); +} + +static ssize_t iio_scan_el_ts_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + int ret; + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + bool state; + + ret = strtobool(buf, &state); + if (ret < 0) + return ret; + + mutex_lock(&indio_dev->mlock); + if (iio_buffer_enabled(indio_dev)) { + ret = -EBUSY; + goto error_ret; + } + indio_dev->buffer->scan_timestamp = state; + indio_dev->scan_timestamp = state; +error_ret: + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + int ret, attrcount = 0; + struct iio_buffer *buffer = indio_dev->buffer; + + ret = __iio_add_chan_devattr("index", + chan, + &iio_show_scan_index, + NULL, + 0, + 0, + &indio_dev->dev, + &buffer->scan_el_dev_attr_list); + if (ret) + goto error_ret; + attrcount++; + ret = __iio_add_chan_devattr("type", + chan, + &iio_show_fixed_type, + NULL, + 0, + 0, + &indio_dev->dev, + &buffer->scan_el_dev_attr_list); + if (ret) + goto error_ret; + attrcount++; + if (chan->type != IIO_TIMESTAMP) + ret = __iio_add_chan_devattr("en", + chan, + &iio_scan_el_show, + &iio_scan_el_store, + chan->scan_index, + 0, + &indio_dev->dev, + &buffer->scan_el_dev_attr_list); + else + ret = __iio_add_chan_devattr("en", + chan, + &iio_scan_el_ts_show, + &iio_scan_el_ts_store, + chan->scan_index, + 0, + &indio_dev->dev, + &buffer->scan_el_dev_attr_list); + attrcount++; + ret = attrcount; +error_ret: + return ret; +} + +static void iio_buffer_remove_and_free_scan_dev_attr(struct iio_dev *indio_dev, + struct iio_dev_attr *p) +{ + kfree(p->dev_attr.attr.name); + kfree(p); +} + +static void __iio_buffer_attr_cleanup(struct iio_dev *indio_dev) +{ + struct iio_dev_attr *p, *n; + struct iio_buffer *buffer = indio_dev->buffer; + + list_for_each_entry_safe(p, n, + &buffer->scan_el_dev_attr_list, l) + iio_buffer_remove_and_free_scan_dev_attr(indio_dev, p); +} + +static const char * const iio_scan_elements_group_name = "scan_elements"; + +int iio_buffer_register(struct iio_dev *indio_dev, + const struct iio_chan_spec *channels, + int num_channels) +{ + struct iio_dev_attr *p; + struct attribute **attr; + struct iio_buffer *buffer = indio_dev->buffer; + int ret, i, attrn, attrcount, attrcount_orig = 0; + + if (buffer->attrs) + indio_dev->groups[indio_dev->groupcounter++] = buffer->attrs; + + if (buffer->scan_el_attrs != NULL) { + attr = buffer->scan_el_attrs->attrs; + while (*attr++ != NULL) + attrcount_orig++; + } + attrcount = attrcount_orig; + INIT_LIST_HEAD(&buffer->scan_el_dev_attr_list); + if (channels) { + /* new magic */ + for (i = 0; i < num_channels; i++) { + if (channels[i].scan_index < 0) + continue; + + /* Establish necessary mask length */ + if (channels[i].scan_index > + (int)indio_dev->masklength - 1) + indio_dev->masklength + = channels[i].scan_index + 1; + + ret = iio_buffer_add_channel_sysfs(indio_dev, + &channels[i]); + if (ret < 0) + goto error_cleanup_dynamic; + attrcount += ret; + if (channels[i].type == IIO_TIMESTAMP) + indio_dev->scan_index_timestamp = + channels[i].scan_index; + } + if (indio_dev->masklength && buffer->scan_mask == NULL) { + buffer->scan_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength), + sizeof(*buffer->scan_mask), + GFP_KERNEL); + if (buffer->scan_mask == NULL) { + ret = -ENOMEM; + goto error_cleanup_dynamic; + } + } + } + + buffer->scan_el_group.name = iio_scan_elements_group_name; + + buffer->scan_el_group.attrs = kcalloc(attrcount + 1, + sizeof(buffer->scan_el_group.attrs[0]), + GFP_KERNEL); + if (buffer->scan_el_group.attrs == NULL) { + ret = -ENOMEM; + goto error_free_scan_mask; + } + if (buffer->scan_el_attrs) + memcpy(buffer->scan_el_group.attrs, buffer->scan_el_attrs, + sizeof(buffer->scan_el_group.attrs[0])*attrcount_orig); + attrn = attrcount_orig; + + list_for_each_entry(p, &buffer->scan_el_dev_attr_list, l) + buffer->scan_el_group.attrs[attrn++] = &p->dev_attr.attr; + indio_dev->groups[indio_dev->groupcounter++] = &buffer->scan_el_group; + + return 0; + +error_free_scan_mask: + kfree(buffer->scan_mask); +error_cleanup_dynamic: + __iio_buffer_attr_cleanup(indio_dev); + + return ret; +} +EXPORT_SYMBOL(iio_buffer_register); + +void iio_buffer_unregister(struct iio_dev *indio_dev) +{ + kfree(indio_dev->buffer->scan_mask); + kfree(indio_dev->buffer->scan_el_group.attrs); + __iio_buffer_attr_cleanup(indio_dev); +} +EXPORT_SYMBOL(iio_buffer_unregister); + +ssize_t iio_buffer_read_length(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_buffer *buffer = indio_dev->buffer; + + if (buffer->access->get_length) + return sprintf(buf, "%d\n", + buffer->access->get_length(buffer)); + + return 0; +} +EXPORT_SYMBOL(iio_buffer_read_length); + +ssize_t iio_buffer_write_length(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + int ret; + ulong val; + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_buffer *buffer = indio_dev->buffer; + + ret = strict_strtoul(buf, 10, &val); + if (ret) + return ret; + + if (buffer->access->get_length) + if (val == buffer->access->get_length(buffer)) + return len; + + mutex_lock(&indio_dev->mlock); + if (iio_buffer_enabled(indio_dev)) { + ret = -EBUSY; + } else { + if (buffer->access->set_length) + buffer->access->set_length(buffer, val); + ret = 0; + } + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} +EXPORT_SYMBOL(iio_buffer_write_length); + +ssize_t iio_buffer_store_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + int ret; + bool requested_state, current_state; + int previous_mode; + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_buffer *buffer = indio_dev->buffer; + + mutex_lock(&indio_dev->mlock); + previous_mode = indio_dev->currentmode; + requested_state = !(buf[0] == '0'); + current_state = iio_buffer_enabled(indio_dev); + if (current_state == requested_state) { + printk(KERN_INFO "iio-buffer, current state requested again\n"); + goto done; + } + if (requested_state) { + if (indio_dev->setup_ops->preenable) { + ret = indio_dev->setup_ops->preenable(indio_dev); + if (ret) { + printk(KERN_ERR + "Buffer not started:" + "buffer preenable failed\n"); + goto error_ret; + } + } + if (buffer->access->request_update) { + ret = buffer->access->request_update(buffer); + if (ret) { + printk(KERN_INFO + "Buffer not started:" + "buffer parameter update failed\n"); + goto error_ret; + } + } + /* Definitely possible for devices to support both of these.*/ + if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) { + if (!indio_dev->trig) { + printk(KERN_INFO + "Buffer not started: no trigger\n"); + ret = -EINVAL; + goto error_ret; + } + indio_dev->currentmode = INDIO_BUFFER_TRIGGERED; + } else if (indio_dev->modes & INDIO_BUFFER_HARDWARE) + indio_dev->currentmode = INDIO_BUFFER_HARDWARE; + else { /* should never be reached */ + ret = -EINVAL; + goto error_ret; + } + + if (indio_dev->setup_ops->postenable) { + ret = indio_dev->setup_ops->postenable(indio_dev); + if (ret) { + printk(KERN_INFO + "Buffer not started:" + "postenable failed\n"); + indio_dev->currentmode = previous_mode; + if (indio_dev->setup_ops->postdisable) + indio_dev->setup_ops-> + postdisable(indio_dev); + goto error_ret; + } + } + } else { + if (indio_dev->setup_ops->predisable) { + ret = indio_dev->setup_ops->predisable(indio_dev); + if (ret) + goto error_ret; + } + indio_dev->currentmode = INDIO_DIRECT_MODE; + if (indio_dev->setup_ops->postdisable) { + ret = indio_dev->setup_ops->postdisable(indio_dev); + if (ret) + goto error_ret; + } + } +done: + mutex_unlock(&indio_dev->mlock); + return len; + +error_ret: + mutex_unlock(&indio_dev->mlock); + return ret; +} +EXPORT_SYMBOL(iio_buffer_store_enable); + +ssize_t iio_buffer_show_enable(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + return sprintf(buf, "%d\n", iio_buffer_enabled(indio_dev)); +} +EXPORT_SYMBOL(iio_buffer_show_enable); + +/* note NULL used as error indicator as it doesn't make sense. */ +static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks, + unsigned int masklength, + const unsigned long *mask) +{ + if (bitmap_empty(mask, masklength)) + return NULL; + while (*av_masks) { + if (bitmap_subset(mask, av_masks, masklength)) + return av_masks; + av_masks += BITS_TO_LONGS(masklength); + } + return NULL; +} + +static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask, + bool timestamp) +{ + const struct iio_chan_spec *ch; + unsigned bytes = 0; + int length, i; + + /* How much space will the demuxed element take? */ + for_each_set_bit(i, mask, + indio_dev->masklength) { + ch = iio_find_channel_from_si(indio_dev, i); + length = ch->scan_type.storagebits / 8; + bytes = ALIGN(bytes, length); + bytes += length; + } + if (timestamp) { + ch = iio_find_channel_from_si(indio_dev, + indio_dev->scan_index_timestamp); + length = ch->scan_type.storagebits / 8; + bytes = ALIGN(bytes, length); + bytes += length; + } + return bytes; +} + +int iio_sw_buffer_preenable(struct iio_dev *indio_dev) +{ + struct iio_buffer *buffer = indio_dev->buffer; + dev_dbg(&indio_dev->dev, "%s\n", __func__); + + /* How much space will the demuxed element take? */ + indio_dev->scan_bytes = + iio_compute_scan_bytes(indio_dev, buffer->scan_mask, + buffer->scan_timestamp); + buffer->access->set_bytes_per_datum(buffer, indio_dev->scan_bytes); + + /* What scan mask do we actually have ?*/ + if (indio_dev->available_scan_masks) + indio_dev->active_scan_mask = + iio_scan_mask_match(indio_dev->available_scan_masks, + indio_dev->masklength, + buffer->scan_mask); + else + indio_dev->active_scan_mask = buffer->scan_mask; + + if (indio_dev->active_scan_mask == NULL) + return -EINVAL; + + iio_update_demux(indio_dev); + + if (indio_dev->info->update_scan_mode) + return indio_dev->info + ->update_scan_mode(indio_dev, + indio_dev->active_scan_mask); + return 0; +} +EXPORT_SYMBOL(iio_sw_buffer_preenable); + +/** + * iio_scan_mask_set() - set particular bit in the scan mask + * @buffer: the buffer whose scan mask we are interested in + * @bit: the bit to be set. + **/ +int iio_scan_mask_set(struct iio_dev *indio_dev, + struct iio_buffer *buffer, int bit) +{ + const unsigned long *mask; + unsigned long *trialmask; + + trialmask = kmalloc(sizeof(*trialmask)* + BITS_TO_LONGS(indio_dev->masklength), + GFP_KERNEL); + + if (trialmask == NULL) + return -ENOMEM; + if (!indio_dev->masklength) { + WARN_ON("trying to set scanmask prior to registering buffer\n"); + kfree(trialmask); + return -EINVAL; + } + bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength); + set_bit(bit, trialmask); + + if (indio_dev->available_scan_masks) { + mask = iio_scan_mask_match(indio_dev->available_scan_masks, + indio_dev->masklength, + trialmask); + if (!mask) { + kfree(trialmask); + return -EINVAL; + } + } + bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength); + + kfree(trialmask); + + return 0; +}; +EXPORT_SYMBOL_GPL(iio_scan_mask_set); + +int iio_scan_mask_query(struct iio_dev *indio_dev, + struct iio_buffer *buffer, int bit) +{ + if (bit > indio_dev->masklength) + return -EINVAL; + + if (!buffer->scan_mask) + return 0; + + return test_bit(bit, buffer->scan_mask); +}; +EXPORT_SYMBOL_GPL(iio_scan_mask_query); + +/** + * struct iio_demux_table() - table describing demux memcpy ops + * @from: index to copy from + * @to: index to copy to + * @length: how many bytes to copy + * @l: list head used for management + */ +struct iio_demux_table { + unsigned from; + unsigned to; + unsigned length; + struct list_head l; +}; + +static unsigned char *iio_demux(struct iio_buffer *buffer, + unsigned char *datain) +{ + struct iio_demux_table *t; + + if (list_empty(&buffer->demux_list)) + return datain; + list_for_each_entry(t, &buffer->demux_list, l) + memcpy(buffer->demux_bounce + t->to, + datain + t->from, t->length); + + return buffer->demux_bounce; +} + +int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data, + s64 timestamp) +{ + unsigned char *dataout = iio_demux(buffer, data); + + return buffer->access->store_to(buffer, dataout, timestamp); +} +EXPORT_SYMBOL_GPL(iio_push_to_buffer); + +static void iio_buffer_demux_free(struct iio_buffer *buffer) +{ + struct iio_demux_table *p, *q; + list_for_each_entry_safe(p, q, &buffer->demux_list, l) { + list_del(&p->l); + kfree(p); + } +} + +int iio_update_demux(struct iio_dev *indio_dev) +{ + const struct iio_chan_spec *ch; + struct iio_buffer *buffer = indio_dev->buffer; + int ret, in_ind = -1, out_ind, length; + unsigned in_loc = 0, out_loc = 0; + struct iio_demux_table *p; + + /* Clear out any old demux */ + iio_buffer_demux_free(buffer); + kfree(buffer->demux_bounce); + buffer->demux_bounce = NULL; + + /* First work out which scan mode we will actually have */ + if (bitmap_equal(indio_dev->active_scan_mask, + buffer->scan_mask, + indio_dev->masklength)) + return 0; + + /* Now we have the two masks, work from least sig and build up sizes */ + for_each_set_bit(out_ind, + indio_dev->active_scan_mask, + indio_dev->masklength) { + in_ind = find_next_bit(indio_dev->active_scan_mask, + indio_dev->masklength, + in_ind + 1); + while (in_ind != out_ind) { + in_ind = find_next_bit(indio_dev->active_scan_mask, + indio_dev->masklength, + in_ind + 1); + ch = iio_find_channel_from_si(indio_dev, in_ind); + length = ch->scan_type.storagebits/8; + /* Make sure we are aligned */ + in_loc += length; + if (in_loc % length) + in_loc += length - in_loc % length; + } + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (p == NULL) { + ret = -ENOMEM; + goto error_clear_mux_table; + } + ch = iio_find_channel_from_si(indio_dev, in_ind); + length = ch->scan_type.storagebits/8; + if (out_loc % length) + out_loc += length - out_loc % length; + if (in_loc % length) + in_loc += length - in_loc % length; + p->from = in_loc; + p->to = out_loc; + p->length = length; + list_add_tail(&p->l, &buffer->demux_list); + out_loc += length; + in_loc += length; + } + /* Relies on scan_timestamp being last */ + if (buffer->scan_timestamp) { + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (p == NULL) { + ret = -ENOMEM; + goto error_clear_mux_table; + } + ch = iio_find_channel_from_si(indio_dev, + indio_dev->scan_index_timestamp); + length = ch->scan_type.storagebits/8; + if (out_loc % length) + out_loc += length - out_loc % length; + if (in_loc % length) + in_loc += length - in_loc % length; + p->from = in_loc; + p->to = out_loc; + p->length = length; + list_add_tail(&p->l, &buffer->demux_list); + out_loc += length; + in_loc += length; + } + buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL); + if (buffer->demux_bounce == NULL) { + ret = -ENOMEM; + goto error_clear_mux_table; + } + return 0; + +error_clear_mux_table: + iio_buffer_demux_free(buffer); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_update_demux); diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c new file mode 100644 index 0000000000000..bb3c692e49b88 --- /dev/null +++ b/drivers/iio/industrialio-core.c @@ -0,0 +1,980 @@ +/* The industrial I/O core + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * Based on elements of hwmon and input subsystems. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "iio_core.h" +#include "iio_core_trigger.h" +#include +#include + +/* IDA to assign each registered device a unique id*/ +static DEFINE_IDA(iio_ida); + +static dev_t iio_devt; + +#define IIO_DEV_MAX 256 +struct bus_type iio_bus_type = { + .name = "iio", +}; +EXPORT_SYMBOL(iio_bus_type); + +static struct dentry *iio_debugfs_dentry; + +static const char * const iio_direction[] = { + [0] = "in", + [1] = "out", +}; + +static const char * const iio_chan_type_name_spec[] = { + [IIO_VOLTAGE] = "voltage", + [IIO_CURRENT] = "current", + [IIO_POWER] = "power", + [IIO_ACCEL] = "accel", + [IIO_ANGL_VEL] = "anglvel", + [IIO_MAGN] = "magn", + [IIO_LIGHT] = "illuminance", + [IIO_INTENSITY] = "intensity", + [IIO_PROXIMITY] = "proximity", + [IIO_TEMP] = "temp", + [IIO_INCLI] = "incli", + [IIO_ROT] = "rot", + [IIO_ANGL] = "angl", + [IIO_TIMESTAMP] = "timestamp", + [IIO_CAPACITANCE] = "capacitance", + [IIO_ALTVOLTAGE] = "altvoltage", +}; + +static const char * const iio_modifier_names[] = { + [IIO_MOD_X] = "x", + [IIO_MOD_Y] = "y", + [IIO_MOD_Z] = "z", + [IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)", + [IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2", + [IIO_MOD_LIGHT_BOTH] = "both", + [IIO_MOD_LIGHT_IR] = "ir", +}; + +/* relies on pairs of these shared then separate */ +static const char * const iio_chan_info_postfix[] = { + [IIO_CHAN_INFO_RAW] = "raw", + [IIO_CHAN_INFO_PROCESSED] = "input", + [IIO_CHAN_INFO_SCALE] = "scale", + [IIO_CHAN_INFO_OFFSET] = "offset", + [IIO_CHAN_INFO_CALIBSCALE] = "calibscale", + [IIO_CHAN_INFO_CALIBBIAS] = "calibbias", + [IIO_CHAN_INFO_PEAK] = "peak_raw", + [IIO_CHAN_INFO_PEAK_SCALE] = "peak_scale", + [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW] = "quadrature_correction_raw", + [IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw", + [IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY] + = "filter_low_pass_3db_frequency", + [IIO_CHAN_INFO_SAMP_FREQ] = "sampling_frequency", + [IIO_CHAN_INFO_FREQUENCY] = "frequency", + [IIO_CHAN_INFO_PHASE] = "phase", + [IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain", +}; + +const struct iio_chan_spec +*iio_find_channel_from_si(struct iio_dev *indio_dev, int si) +{ + int i; + + for (i = 0; i < indio_dev->num_channels; i++) + if (indio_dev->channels[i].scan_index == si) + return &indio_dev->channels[i]; + return NULL; +} + +/* This turns up an awful lot */ +ssize_t iio_read_const_attr(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string); +} +EXPORT_SYMBOL(iio_read_const_attr); + +static int __init iio_init(void) +{ + int ret; + + /* Register sysfs bus */ + ret = bus_register(&iio_bus_type); + if (ret < 0) { + printk(KERN_ERR + "%s could not register bus type\n", + __FILE__); + goto error_nothing; + } + + ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio"); + if (ret < 0) { + printk(KERN_ERR "%s: failed to allocate char dev region\n", + __FILE__); + goto error_unregister_bus_type; + } + + iio_debugfs_dentry = debugfs_create_dir("iio", NULL); + + return 0; + +error_unregister_bus_type: + bus_unregister(&iio_bus_type); +error_nothing: + return ret; +} + +static void __exit iio_exit(void) +{ + if (iio_devt) + unregister_chrdev_region(iio_devt, IIO_DEV_MAX); + bus_unregister(&iio_bus_type); + debugfs_remove(iio_debugfs_dentry); +} + +#if defined(CONFIG_DEBUG_FS) +static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct iio_dev *indio_dev = file->private_data; + char buf[20]; + unsigned val = 0; + ssize_t len; + int ret; + + ret = indio_dev->info->debugfs_reg_access(indio_dev, + indio_dev->cached_reg_addr, + 0, &val); + if (ret) + dev_err(indio_dev->dev.parent, "%s: read failed\n", __func__); + + len = snprintf(buf, sizeof(buf), "0x%X\n", val); + + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} + +static ssize_t iio_debugfs_write_reg(struct file *file, + const char __user *userbuf, size_t count, loff_t *ppos) +{ + struct iio_dev *indio_dev = file->private_data; + unsigned reg, val; + char buf[80]; + int ret; + + count = min_t(size_t, count, (sizeof(buf)-1)); + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + buf[count] = 0; + + ret = sscanf(buf, "%i %i", ®, &val); + + switch (ret) { + case 1: + indio_dev->cached_reg_addr = reg; + break; + case 2: + indio_dev->cached_reg_addr = reg; + ret = indio_dev->info->debugfs_reg_access(indio_dev, reg, + val, NULL); + if (ret) { + dev_err(indio_dev->dev.parent, "%s: write failed\n", + __func__); + return ret; + } + break; + default: + return -EINVAL; + } + + return count; +} + +static const struct file_operations iio_debugfs_reg_fops = { + .open = simple_open, + .read = iio_debugfs_read_reg, + .write = iio_debugfs_write_reg, +}; + +static void iio_device_unregister_debugfs(struct iio_dev *indio_dev) +{ + debugfs_remove_recursive(indio_dev->debugfs_dentry); +} + +static int iio_device_register_debugfs(struct iio_dev *indio_dev) +{ + struct dentry *d; + + if (indio_dev->info->debugfs_reg_access == NULL) + return 0; + + if (!iio_debugfs_dentry) + return 0; + + indio_dev->debugfs_dentry = + debugfs_create_dir(dev_name(&indio_dev->dev), + iio_debugfs_dentry); + if (indio_dev->debugfs_dentry == NULL) { + dev_warn(indio_dev->dev.parent, + "Failed to create debugfs directory\n"); + return -EFAULT; + } + + d = debugfs_create_file("direct_reg_access", 0644, + indio_dev->debugfs_dentry, + indio_dev, &iio_debugfs_reg_fops); + if (!d) { + iio_device_unregister_debugfs(indio_dev); + return -ENOMEM; + } + + return 0; +} +#else +static int iio_device_register_debugfs(struct iio_dev *indio_dev) +{ + return 0; +} + +static void iio_device_unregister_debugfs(struct iio_dev *indio_dev) +{ +} +#endif /* CONFIG_DEBUG_FS */ + +static ssize_t iio_read_channel_ext_info(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + const struct iio_chan_spec_ext_info *ext_info; + + ext_info = &this_attr->c->ext_info[this_attr->address]; + + return ext_info->read(indio_dev, ext_info->private, this_attr->c, buf); +} + +static ssize_t iio_write_channel_ext_info(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + const struct iio_chan_spec_ext_info *ext_info; + + ext_info = &this_attr->c->ext_info[this_attr->address]; + + return ext_info->write(indio_dev, ext_info->private, + this_attr->c, buf, len); +} + +ssize_t iio_enum_available_read(struct iio_dev *indio_dev, + uintptr_t priv, const struct iio_chan_spec *chan, char *buf) +{ + const struct iio_enum *e = (const struct iio_enum *)priv; + unsigned int i; + size_t len = 0; + + if (!e->num_items) + return 0; + + for (i = 0; i < e->num_items; ++i) + len += scnprintf(buf + len, PAGE_SIZE - len, "%s ", e->items[i]); + + /* replace last space with a newline */ + buf[len - 1] = '\n'; + + return len; +} +EXPORT_SYMBOL_GPL(iio_enum_available_read); + +ssize_t iio_enum_read(struct iio_dev *indio_dev, + uintptr_t priv, const struct iio_chan_spec *chan, char *buf) +{ + const struct iio_enum *e = (const struct iio_enum *)priv; + int i; + + if (!e->get) + return -EINVAL; + + i = e->get(indio_dev, chan); + if (i < 0) + return i; + else if (i >= e->num_items) + return -EINVAL; + + return sprintf(buf, "%s\n", e->items[i]); +} +EXPORT_SYMBOL_GPL(iio_enum_read); + +ssize_t iio_enum_write(struct iio_dev *indio_dev, + uintptr_t priv, const struct iio_chan_spec *chan, const char *buf, + size_t len) +{ + const struct iio_enum *e = (const struct iio_enum *)priv; + unsigned int i; + int ret; + + if (!e->set) + return -EINVAL; + + for (i = 0; i < e->num_items; i++) { + if (sysfs_streq(buf, e->items[i])) + break; + } + + if (i == e->num_items) + return -EINVAL; + + ret = e->set(indio_dev, chan, i); + return ret ? ret : len; +} +EXPORT_SYMBOL_GPL(iio_enum_write); + +static ssize_t iio_read_channel_info(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int val, val2; + bool scale_db = false; + int ret = indio_dev->info->read_raw(indio_dev, this_attr->c, + &val, &val2, this_attr->address); + + if (ret < 0) + return ret; + + switch (ret) { + case IIO_VAL_INT: + return sprintf(buf, "%d\n", val); + case IIO_VAL_INT_PLUS_MICRO_DB: + scale_db = true; + case IIO_VAL_INT_PLUS_MICRO: + if (val2 < 0) + return sprintf(buf, "-%d.%06u%s\n", val, -val2, + scale_db ? " dB" : ""); + else + return sprintf(buf, "%d.%06u%s\n", val, val2, + scale_db ? " dB" : ""); + case IIO_VAL_INT_PLUS_NANO: + if (val2 < 0) + return sprintf(buf, "-%d.%09u\n", val, -val2); + else + return sprintf(buf, "%d.%09u\n", val, val2); + default: + return 0; + } +} + +static ssize_t iio_write_channel_info(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret, integer = 0, fract = 0, fract_mult = 100000; + bool integer_part = true, negative = false; + + /* Assumes decimal - precision based on number of digits */ + if (!indio_dev->info->write_raw) + return -EINVAL; + + if (indio_dev->info->write_raw_get_fmt) + switch (indio_dev->info->write_raw_get_fmt(indio_dev, + this_attr->c, this_attr->address)) { + case IIO_VAL_INT_PLUS_MICRO: + fract_mult = 100000; + break; + case IIO_VAL_INT_PLUS_NANO: + fract_mult = 100000000; + break; + default: + return -EINVAL; + } + + if (buf[0] == '-') { + negative = true; + buf++; + } + + while (*buf) { + if ('0' <= *buf && *buf <= '9') { + if (integer_part) + integer = integer*10 + *buf - '0'; + else { + fract += fract_mult*(*buf - '0'); + if (fract_mult == 1) + break; + fract_mult /= 10; + } + } else if (*buf == '\n') { + if (*(buf + 1) == '\0') + break; + else + return -EINVAL; + } else if (*buf == '.') { + integer_part = false; + } else { + return -EINVAL; + } + buf++; + } + if (negative) { + if (integer) + integer = -integer; + else + fract = -fract; + } + + ret = indio_dev->info->write_raw(indio_dev, this_attr->c, + integer, fract, this_attr->address); + if (ret) + return ret; + + return len; +} + +static +int __iio_device_attr_init(struct device_attribute *dev_attr, + const char *postfix, + struct iio_chan_spec const *chan, + ssize_t (*readfunc)(struct device *dev, + struct device_attribute *attr, + char *buf), + ssize_t (*writefunc)(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len), + bool generic) +{ + int ret; + char *name_format, *full_postfix; + sysfs_attr_init(&dev_attr->attr); + + /* Build up postfix of __postfix */ + if (chan->modified && !generic) { + if (chan->extend_name) + full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", + iio_modifier_names[chan + ->channel2], + chan->extend_name, + postfix); + else + full_postfix = kasprintf(GFP_KERNEL, "%s_%s", + iio_modifier_names[chan + ->channel2], + postfix); + } else { + if (chan->extend_name == NULL) + full_postfix = kstrdup(postfix, GFP_KERNEL); + else + full_postfix = kasprintf(GFP_KERNEL, + "%s_%s", + chan->extend_name, + postfix); + } + if (full_postfix == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + if (chan->differential) { /* Differential can not have modifier */ + if (generic) + name_format + = kasprintf(GFP_KERNEL, "%s_%s-%s_%s", + iio_direction[chan->output], + iio_chan_type_name_spec[chan->type], + iio_chan_type_name_spec[chan->type], + full_postfix); + else if (chan->indexed) + name_format + = kasprintf(GFP_KERNEL, "%s_%s%d-%s%d_%s", + iio_direction[chan->output], + iio_chan_type_name_spec[chan->type], + chan->channel, + iio_chan_type_name_spec[chan->type], + chan->channel2, + full_postfix); + else { + WARN_ON("Differential channels must be indexed\n"); + ret = -EINVAL; + goto error_free_full_postfix; + } + } else { /* Single ended */ + if (generic) + name_format + = kasprintf(GFP_KERNEL, "%s_%s_%s", + iio_direction[chan->output], + iio_chan_type_name_spec[chan->type], + full_postfix); + else if (chan->indexed) + name_format + = kasprintf(GFP_KERNEL, "%s_%s%d_%s", + iio_direction[chan->output], + iio_chan_type_name_spec[chan->type], + chan->channel, + full_postfix); + else + name_format + = kasprintf(GFP_KERNEL, "%s_%s_%s", + iio_direction[chan->output], + iio_chan_type_name_spec[chan->type], + full_postfix); + } + if (name_format == NULL) { + ret = -ENOMEM; + goto error_free_full_postfix; + } + dev_attr->attr.name = kasprintf(GFP_KERNEL, + name_format, + chan->channel, + chan->channel2); + if (dev_attr->attr.name == NULL) { + ret = -ENOMEM; + goto error_free_name_format; + } + + if (readfunc) { + dev_attr->attr.mode |= S_IRUGO; + dev_attr->show = readfunc; + } + + if (writefunc) { + dev_attr->attr.mode |= S_IWUSR; + dev_attr->store = writefunc; + } + kfree(name_format); + kfree(full_postfix); + + return 0; + +error_free_name_format: + kfree(name_format); +error_free_full_postfix: + kfree(full_postfix); +error_ret: + return ret; +} + +static void __iio_device_attr_deinit(struct device_attribute *dev_attr) +{ + kfree(dev_attr->attr.name); +} + +int __iio_add_chan_devattr(const char *postfix, + struct iio_chan_spec const *chan, + ssize_t (*readfunc)(struct device *dev, + struct device_attribute *attr, + char *buf), + ssize_t (*writefunc)(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len), + u64 mask, + bool generic, + struct device *dev, + struct list_head *attr_list) +{ + int ret; + struct iio_dev_attr *iio_attr, *t; + + iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL); + if (iio_attr == NULL) { + ret = -ENOMEM; + goto error_ret; + } + ret = __iio_device_attr_init(&iio_attr->dev_attr, + postfix, chan, + readfunc, writefunc, generic); + if (ret) + goto error_iio_dev_attr_free; + iio_attr->c = chan; + iio_attr->address = mask; + list_for_each_entry(t, attr_list, l) + if (strcmp(t->dev_attr.attr.name, + iio_attr->dev_attr.attr.name) == 0) { + if (!generic) + dev_err(dev, "tried to double register : %s\n", + t->dev_attr.attr.name); + ret = -EBUSY; + goto error_device_attr_deinit; + } + list_add(&iio_attr->l, attr_list); + + return 0; + +error_device_attr_deinit: + __iio_device_attr_deinit(&iio_attr->dev_attr); +error_iio_dev_attr_free: + kfree(iio_attr); +error_ret: + return ret; +} + +static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + int ret, attrcount = 0; + int i; + const struct iio_chan_spec_ext_info *ext_info; + + if (chan->channel < 0) + return 0; + for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) { + ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2], + chan, + &iio_read_channel_info, + &iio_write_channel_info, + i/2, + !(i%2), + &indio_dev->dev, + &indio_dev->channel_attr_list); + if (ret == -EBUSY && (i%2 == 0)) { + ret = 0; + continue; + } + if (ret < 0) + goto error_ret; + attrcount++; + } + + if (chan->ext_info) { + unsigned int i = 0; + for (ext_info = chan->ext_info; ext_info->name; ext_info++) { + ret = __iio_add_chan_devattr(ext_info->name, + chan, + ext_info->read ? + &iio_read_channel_ext_info : NULL, + ext_info->write ? + &iio_write_channel_ext_info : NULL, + i, + ext_info->shared, + &indio_dev->dev, + &indio_dev->channel_attr_list); + i++; + if (ret == -EBUSY && ext_info->shared) + continue; + + if (ret) + goto error_ret; + + attrcount++; + } + } + + ret = attrcount; +error_ret: + return ret; +} + +static void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev, + struct iio_dev_attr *p) +{ + kfree(p->dev_attr.attr.name); + kfree(p); +} + +static ssize_t iio_show_dev_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + return sprintf(buf, "%s\n", indio_dev->name); +} + +static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL); + +static int iio_device_register_sysfs(struct iio_dev *indio_dev) +{ + int i, ret = 0, attrcount, attrn, attrcount_orig = 0; + struct iio_dev_attr *p, *n; + struct attribute **attr; + + /* First count elements in any existing group */ + if (indio_dev->info->attrs) { + attr = indio_dev->info->attrs->attrs; + while (*attr++ != NULL) + attrcount_orig++; + } + attrcount = attrcount_orig; + /* + * New channel registration method - relies on the fact a group does + * not need to be initialized if it is name is NULL. + */ + if (indio_dev->channels) + for (i = 0; i < indio_dev->num_channels; i++) { + ret = iio_device_add_channel_sysfs(indio_dev, + &indio_dev + ->channels[i]); + if (ret < 0) + goto error_clear_attrs; + attrcount += ret; + } + + if (indio_dev->name) + attrcount++; + + indio_dev->chan_attr_group.attrs = kcalloc(attrcount + 1, + sizeof(indio_dev->chan_attr_group.attrs[0]), + GFP_KERNEL); + if (indio_dev->chan_attr_group.attrs == NULL) { + ret = -ENOMEM; + goto error_clear_attrs; + } + /* Copy across original attributes */ + if (indio_dev->info->attrs) + memcpy(indio_dev->chan_attr_group.attrs, + indio_dev->info->attrs->attrs, + sizeof(indio_dev->chan_attr_group.attrs[0]) + *attrcount_orig); + attrn = attrcount_orig; + /* Add all elements from the list. */ + list_for_each_entry(p, &indio_dev->channel_attr_list, l) + indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr; + if (indio_dev->name) + indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr; + + indio_dev->groups[indio_dev->groupcounter++] = + &indio_dev->chan_attr_group; + + return 0; + +error_clear_attrs: + list_for_each_entry_safe(p, n, + &indio_dev->channel_attr_list, l) { + list_del(&p->l); + iio_device_remove_and_free_read_attr(indio_dev, p); + } + + return ret; +} + +static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) +{ + + struct iio_dev_attr *p, *n; + + list_for_each_entry_safe(p, n, &indio_dev->channel_attr_list, l) { + list_del(&p->l); + iio_device_remove_and_free_read_attr(indio_dev, p); + } + kfree(indio_dev->chan_attr_group.attrs); +} + +static void iio_dev_release(struct device *device) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(device); + if (indio_dev->chrdev.dev) + cdev_del(&indio_dev->chrdev); + if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) + iio_device_unregister_trigger_consumer(indio_dev); + iio_device_unregister_eventset(indio_dev); + iio_device_unregister_sysfs(indio_dev); + iio_device_unregister_debugfs(indio_dev); + + ida_simple_remove(&iio_ida, indio_dev->id); + kfree(indio_dev); +} + +static struct device_type iio_dev_type = { + .name = "iio_device", + .release = iio_dev_release, +}; + +struct iio_dev *iio_device_alloc(int sizeof_priv) +{ + struct iio_dev *dev; + size_t alloc_size; + + alloc_size = sizeof(struct iio_dev); + if (sizeof_priv) { + alloc_size = ALIGN(alloc_size, IIO_ALIGN); + alloc_size += sizeof_priv; + } + /* ensure 32-byte alignment of whole construct ? */ + alloc_size += IIO_ALIGN - 1; + + dev = kzalloc(alloc_size, GFP_KERNEL); + + if (dev) { + dev->dev.groups = dev->groups; + dev->dev.type = &iio_dev_type; + dev->dev.bus = &iio_bus_type; + device_initialize(&dev->dev); + dev_set_drvdata(&dev->dev, (void *)dev); + mutex_init(&dev->mlock); + mutex_init(&dev->info_exist_lock); + INIT_LIST_HEAD(&dev->channel_attr_list); + + dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); + if (dev->id < 0) { + /* cannot use a dev_err as the name isn't available */ + printk(KERN_ERR "Failed to get id\n"); + kfree(dev); + return NULL; + } + dev_set_name(&dev->dev, "iio:device%d", dev->id); + } + + return dev; +} +EXPORT_SYMBOL(iio_device_alloc); + +void iio_device_free(struct iio_dev *dev) +{ + if (dev) + put_device(&dev->dev); +} +EXPORT_SYMBOL(iio_device_free); + +/** + * iio_chrdev_open() - chrdev file open for buffer access and ioctls + **/ +static int iio_chrdev_open(struct inode *inode, struct file *filp) +{ + struct iio_dev *indio_dev = container_of(inode->i_cdev, + struct iio_dev, chrdev); + + if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags)) + return -EBUSY; + + filp->private_data = indio_dev; + + return 0; +} + +/** + * iio_chrdev_release() - chrdev file close buffer access and ioctls + **/ +static int iio_chrdev_release(struct inode *inode, struct file *filp) +{ + struct iio_dev *indio_dev = container_of(inode->i_cdev, + struct iio_dev, chrdev); + clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags); + return 0; +} + +/* Somewhat of a cross file organization violation - ioctls here are actually + * event related */ +static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct iio_dev *indio_dev = filp->private_data; + int __user *ip = (int __user *)arg; + int fd; + + if (cmd == IIO_GET_EVENT_FD_IOCTL) { + fd = iio_event_getfd(indio_dev); + if (copy_to_user(ip, &fd, sizeof(fd))) + return -EFAULT; + return 0; + } + return -EINVAL; +} + +static const struct file_operations iio_buffer_fileops = { + .read = iio_buffer_read_first_n_outer_addr, + .release = iio_chrdev_release, + .open = iio_chrdev_open, + .poll = iio_buffer_poll_addr, + .owner = THIS_MODULE, + .llseek = noop_llseek, + .unlocked_ioctl = iio_ioctl, + .compat_ioctl = iio_ioctl, +}; + +static const struct iio_buffer_setup_ops noop_ring_setup_ops; + +int iio_device_register(struct iio_dev *indio_dev) +{ + int ret; + + /* configure elements for the chrdev */ + indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); + + ret = iio_device_register_debugfs(indio_dev); + if (ret) { + dev_err(indio_dev->dev.parent, + "Failed to register debugfs interfaces\n"); + goto error_ret; + } + ret = iio_device_register_sysfs(indio_dev); + if (ret) { + dev_err(indio_dev->dev.parent, + "Failed to register sysfs interfaces\n"); + goto error_unreg_debugfs; + } + ret = iio_device_register_eventset(indio_dev); + if (ret) { + dev_err(indio_dev->dev.parent, + "Failed to register event set\n"); + goto error_free_sysfs; + } + if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) + iio_device_register_trigger_consumer(indio_dev); + + if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) && + indio_dev->setup_ops == NULL) + indio_dev->setup_ops = &noop_ring_setup_ops; + + ret = device_add(&indio_dev->dev); + if (ret < 0) + goto error_unreg_eventset; + cdev_init(&indio_dev->chrdev, &iio_buffer_fileops); + indio_dev->chrdev.owner = indio_dev->info->driver_module; + ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1); + if (ret < 0) + goto error_del_device; + return 0; + +error_del_device: + device_del(&indio_dev->dev); +error_unreg_eventset: + iio_device_unregister_eventset(indio_dev); +error_free_sysfs: + iio_device_unregister_sysfs(indio_dev); +error_unreg_debugfs: + iio_device_unregister_debugfs(indio_dev); +error_ret: + return ret; +} +EXPORT_SYMBOL(iio_device_register); + +void iio_device_unregister(struct iio_dev *indio_dev) +{ + mutex_lock(&indio_dev->info_exist_lock); + indio_dev->info = NULL; + mutex_unlock(&indio_dev->info_exist_lock); + device_del(&indio_dev->dev); +} +EXPORT_SYMBOL(iio_device_unregister); +subsys_initcall(iio_init); +module_exit(iio_exit); + +MODULE_AUTHOR("Jonathan Cameron "); +MODULE_DESCRIPTION("Industrial I/O core"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c new file mode 100644 index 0000000000000..fa6543bf67312 --- /dev/null +++ b/drivers/iio/industrialio-event.c @@ -0,0 +1,454 @@ +/* Industrial I/O event handling + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * Based on elements of hwmon and input subsystems. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "iio_core.h" +#include +#include + +/** + * struct iio_event_interface - chrdev interface for an event line + * @wait: wait queue to allow blocking reads of events + * @det_events: list of detected events + * @dev_attr_list: list of event interface sysfs attribute + * @flags: file operations related flags including busy flag. + * @group: event interface sysfs attribute group + */ +struct iio_event_interface { + wait_queue_head_t wait; + DECLARE_KFIFO(det_events, struct iio_event_data, 16); + + struct list_head dev_attr_list; + unsigned long flags; + struct attribute_group group; +}; + +int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) +{ + struct iio_event_interface *ev_int = indio_dev->event_interface; + struct iio_event_data ev; + int copied; + + /* Does anyone care? */ + spin_lock(&ev_int->wait.lock); + if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { + + ev.id = ev_code; + ev.timestamp = timestamp; + + copied = kfifo_put(&ev_int->det_events, &ev); + if (copied != 0) + wake_up_locked_poll(&ev_int->wait, POLLIN); + } + spin_unlock(&ev_int->wait.lock); + + return 0; +} +EXPORT_SYMBOL(iio_push_event); + +/** + * iio_event_poll() - poll the event queue to find out if it has data + */ +static unsigned int iio_event_poll(struct file *filep, + struct poll_table_struct *wait) +{ + struct iio_event_interface *ev_int = filep->private_data; + unsigned int events = 0; + + poll_wait(filep, &ev_int->wait, wait); + + spin_lock(&ev_int->wait.lock); + if (!kfifo_is_empty(&ev_int->det_events)) + events = POLLIN | POLLRDNORM; + spin_unlock(&ev_int->wait.lock); + + return events; +} + +static ssize_t iio_event_chrdev_read(struct file *filep, + char __user *buf, + size_t count, + loff_t *f_ps) +{ + struct iio_event_interface *ev_int = filep->private_data; + unsigned int copied; + int ret; + + if (count < sizeof(struct iio_event_data)) + return -EINVAL; + + spin_lock(&ev_int->wait.lock); + if (kfifo_is_empty(&ev_int->det_events)) { + if (filep->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + goto error_unlock; + } + /* Blocking on device; waiting for something to be there */ + ret = wait_event_interruptible_locked(ev_int->wait, + !kfifo_is_empty(&ev_int->det_events)); + if (ret) + goto error_unlock; + /* Single access device so no one else can get the data */ + } + + ret = kfifo_to_user(&ev_int->det_events, buf, count, &copied); + +error_unlock: + spin_unlock(&ev_int->wait.lock); + + return ret ? ret : copied; +} + +static int iio_event_chrdev_release(struct inode *inode, struct file *filep) +{ + struct iio_event_interface *ev_int = filep->private_data; + + spin_lock(&ev_int->wait.lock); + __clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); + /* + * In order to maintain a clean state for reopening, + * clear out any awaiting events. The mask will prevent + * any new __iio_push_event calls running. + */ + kfifo_reset_out(&ev_int->det_events); + spin_unlock(&ev_int->wait.lock); + + return 0; +} + +static const struct file_operations iio_event_chrdev_fileops = { + .read = iio_event_chrdev_read, + .poll = iio_event_poll, + .release = iio_event_chrdev_release, + .owner = THIS_MODULE, + .llseek = noop_llseek, +}; + +int iio_event_getfd(struct iio_dev *indio_dev) +{ + struct iio_event_interface *ev_int = indio_dev->event_interface; + int fd; + + if (ev_int == NULL) + return -ENODEV; + + spin_lock(&ev_int->wait.lock); + if (__test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) { + spin_unlock(&ev_int->wait.lock); + return -EBUSY; + } + spin_unlock(&ev_int->wait.lock); + fd = anon_inode_getfd("iio:event", + &iio_event_chrdev_fileops, ev_int, O_RDONLY); + if (fd < 0) { + spin_lock(&ev_int->wait.lock); + __clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); + spin_unlock(&ev_int->wait.lock); + } + return fd; +} + +static const char * const iio_ev_type_text[] = { + [IIO_EV_TYPE_THRESH] = "thresh", + [IIO_EV_TYPE_MAG] = "mag", + [IIO_EV_TYPE_ROC] = "roc", + [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", + [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", +}; + +static const char * const iio_ev_dir_text[] = { + [IIO_EV_DIR_EITHER] = "either", + [IIO_EV_DIR_RISING] = "rising", + [IIO_EV_DIR_FALLING] = "falling" +}; + +static ssize_t iio_ev_state_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + bool val; + + ret = strtobool(buf, &val); + if (ret < 0) + return ret; + + ret = indio_dev->info->write_event_config(indio_dev, + this_attr->address, + val); + return (ret < 0) ? ret : len; +} + +static ssize_t iio_ev_state_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int val = indio_dev->info->read_event_config(indio_dev, + this_attr->address); + + if (val < 0) + return val; + else + return sprintf(buf, "%d\n", val); +} + +static ssize_t iio_ev_value_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int val, ret; + + ret = indio_dev->info->read_event_value(indio_dev, + this_attr->address, &val); + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", val); +} + +static ssize_t iio_ev_value_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + unsigned long val; + int ret; + + if (!indio_dev->info->write_event_value) + return -EINVAL; + + ret = strict_strtoul(buf, 10, &val); + if (ret) + return ret; + + ret = indio_dev->info->write_event_value(indio_dev, this_attr->address, + val); + if (ret < 0) + return ret; + + return len; +} + +static int iio_device_add_event_sysfs(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + int ret = 0, i, attrcount = 0; + u64 mask = 0; + char *postfix; + if (!chan->event_mask) + return 0; + + for_each_set_bit(i, &chan->event_mask, sizeof(chan->event_mask)*8) { + postfix = kasprintf(GFP_KERNEL, "%s_%s_en", + iio_ev_type_text[i/IIO_EV_DIR_MAX], + iio_ev_dir_text[i%IIO_EV_DIR_MAX]); + if (postfix == NULL) { + ret = -ENOMEM; + goto error_ret; + } + if (chan->modified) + mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel, + i/IIO_EV_DIR_MAX, + i%IIO_EV_DIR_MAX); + else if (chan->differential) + mask = IIO_EVENT_CODE(chan->type, + 0, 0, + i%IIO_EV_DIR_MAX, + i/IIO_EV_DIR_MAX, + 0, + chan->channel, + chan->channel2); + else + mask = IIO_UNMOD_EVENT_CODE(chan->type, + chan->channel, + i/IIO_EV_DIR_MAX, + i%IIO_EV_DIR_MAX); + + ret = __iio_add_chan_devattr(postfix, + chan, + &iio_ev_state_show, + iio_ev_state_store, + mask, + 0, + &indio_dev->dev, + &indio_dev->event_interface-> + dev_attr_list); + kfree(postfix); + if (ret) + goto error_ret; + attrcount++; + postfix = kasprintf(GFP_KERNEL, "%s_%s_value", + iio_ev_type_text[i/IIO_EV_DIR_MAX], + iio_ev_dir_text[i%IIO_EV_DIR_MAX]); + if (postfix == NULL) { + ret = -ENOMEM; + goto error_ret; + } + ret = __iio_add_chan_devattr(postfix, chan, + iio_ev_value_show, + iio_ev_value_store, + mask, + 0, + &indio_dev->dev, + &indio_dev->event_interface-> + dev_attr_list); + kfree(postfix); + if (ret) + goto error_ret; + attrcount++; + } + ret = attrcount; +error_ret: + return ret; +} + +static inline void __iio_remove_event_config_attrs(struct iio_dev *indio_dev) +{ + struct iio_dev_attr *p, *n; + list_for_each_entry_safe(p, n, + &indio_dev->event_interface-> + dev_attr_list, l) { + kfree(p->dev_attr.attr.name); + kfree(p); + } +} + +static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev) +{ + int j, ret, attrcount = 0; + + /* Dynically created from the channels array */ + for (j = 0; j < indio_dev->num_channels; j++) { + ret = iio_device_add_event_sysfs(indio_dev, + &indio_dev->channels[j]); + if (ret < 0) + goto error_clear_attrs; + attrcount += ret; + } + return attrcount; + +error_clear_attrs: + __iio_remove_event_config_attrs(indio_dev); + + return ret; +} + +static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev) +{ + int j; + + for (j = 0; j < indio_dev->num_channels; j++) + if (indio_dev->channels[j].event_mask != 0) + return true; + return false; +} + +static void iio_setup_ev_int(struct iio_event_interface *ev_int) +{ + INIT_KFIFO(ev_int->det_events); + init_waitqueue_head(&ev_int->wait); +} + +static const char *iio_event_group_name = "events"; +int iio_device_register_eventset(struct iio_dev *indio_dev) +{ + struct iio_dev_attr *p; + int ret = 0, attrcount_orig = 0, attrcount, attrn; + struct attribute **attr; + + if (!(indio_dev->info->event_attrs || + iio_check_for_dynamic_events(indio_dev))) + return 0; + + indio_dev->event_interface = + kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL); + if (indio_dev->event_interface == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list); + + iio_setup_ev_int(indio_dev->event_interface); + if (indio_dev->info->event_attrs != NULL) { + attr = indio_dev->info->event_attrs->attrs; + while (*attr++ != NULL) + attrcount_orig++; + } + attrcount = attrcount_orig; + if (indio_dev->channels) { + ret = __iio_add_event_config_attrs(indio_dev); + if (ret < 0) + goto error_free_setup_event_lines; + attrcount += ret; + } + + indio_dev->event_interface->group.name = iio_event_group_name; + indio_dev->event_interface->group.attrs = kcalloc(attrcount + 1, + sizeof(indio_dev->event_interface->group.attrs[0]), + GFP_KERNEL); + if (indio_dev->event_interface->group.attrs == NULL) { + ret = -ENOMEM; + goto error_free_setup_event_lines; + } + if (indio_dev->info->event_attrs) + memcpy(indio_dev->event_interface->group.attrs, + indio_dev->info->event_attrs->attrs, + sizeof(indio_dev->event_interface->group.attrs[0]) + *attrcount_orig); + attrn = attrcount_orig; + /* Add all elements from the list. */ + list_for_each_entry(p, + &indio_dev->event_interface->dev_attr_list, + l) + indio_dev->event_interface->group.attrs[attrn++] = + &p->dev_attr.attr; + indio_dev->groups[indio_dev->groupcounter++] = + &indio_dev->event_interface->group; + + return 0; + +error_free_setup_event_lines: + __iio_remove_event_config_attrs(indio_dev); + kfree(indio_dev->event_interface); +error_ret: + + return ret; +} + +void iio_device_unregister_eventset(struct iio_dev *indio_dev) +{ + if (indio_dev->event_interface == NULL) + return; + __iio_remove_event_config_attrs(indio_dev); + kfree(indio_dev->event_interface->group.attrs); + kfree(indio_dev->event_interface); +} diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c new file mode 100644 index 0000000000000..4fe0ead84213e --- /dev/null +++ b/drivers/iio/industrialio-trigger.c @@ -0,0 +1,496 @@ +/* The industrial I/O core, trigger handling functions + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "iio_core.h" +#include "iio_core_trigger.h" +#include + +/* RFC - Question of approach + * Make the common case (single sensor single trigger) + * simple by starting trigger capture from when first sensors + * is added. + * + * Complex simultaneous start requires use of 'hold' functionality + * of the trigger. (not implemented) + * + * Any other suggestions? + */ + +static DEFINE_IDA(iio_trigger_ida); + +/* Single list of all available triggers */ +static LIST_HEAD(iio_trigger_list); +static DEFINE_MUTEX(iio_trigger_list_lock); + +/** + * iio_trigger_read_name() - retrieve useful identifying name + **/ +static ssize_t iio_trigger_read_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_trigger *trig = to_iio_trigger(dev); + return sprintf(buf, "%s\n", trig->name); +} + +static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL); + +static struct attribute *iio_trig_dev_attrs[] = { + &dev_attr_name.attr, + NULL, +}; + +static struct attribute_group iio_trig_attr_group = { + .attrs = iio_trig_dev_attrs, +}; + +static const struct attribute_group *iio_trig_attr_groups[] = { + &iio_trig_attr_group, + NULL +}; + +int iio_trigger_register(struct iio_trigger *trig_info) +{ + int ret; + + trig_info->id = ida_simple_get(&iio_trigger_ida, 0, 0, GFP_KERNEL); + if (trig_info->id < 0) { + ret = trig_info->id; + goto error_ret; + } + /* Set the name used for the sysfs directory etc */ + dev_set_name(&trig_info->dev, "trigger%ld", + (unsigned long) trig_info->id); + + ret = device_add(&trig_info->dev); + if (ret) + goto error_unregister_id; + + /* Add to list of available triggers held by the IIO core */ + mutex_lock(&iio_trigger_list_lock); + list_add_tail(&trig_info->list, &iio_trigger_list); + mutex_unlock(&iio_trigger_list_lock); + + return 0; + +error_unregister_id: + ida_simple_remove(&iio_trigger_ida, trig_info->id); +error_ret: + return ret; +} +EXPORT_SYMBOL(iio_trigger_register); + +void iio_trigger_unregister(struct iio_trigger *trig_info) +{ + mutex_lock(&iio_trigger_list_lock); + list_del(&trig_info->list); + mutex_unlock(&iio_trigger_list_lock); + + ida_simple_remove(&iio_trigger_ida, trig_info->id); + /* Possible issue in here */ + device_unregister(&trig_info->dev); +} +EXPORT_SYMBOL(iio_trigger_unregister); + +static struct iio_trigger *iio_trigger_find_by_name(const char *name, + size_t len) +{ + struct iio_trigger *trig = NULL, *iter; + + mutex_lock(&iio_trigger_list_lock); + list_for_each_entry(iter, &iio_trigger_list, list) + if (sysfs_streq(iter->name, name)) { + trig = iter; + break; + } + mutex_unlock(&iio_trigger_list_lock); + + return trig; +} + +void iio_trigger_poll(struct iio_trigger *trig, s64 time) +{ + int i; + if (!trig->use_count) + for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) + if (trig->subirqs[i].enabled) { + trig->use_count++; + generic_handle_irq(trig->subirq_base + i); + } +} +EXPORT_SYMBOL(iio_trigger_poll); + +irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private) +{ + iio_trigger_poll(private, iio_get_time_ns()); + return IRQ_HANDLED; +} +EXPORT_SYMBOL(iio_trigger_generic_data_rdy_poll); + +void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time) +{ + int i; + if (!trig->use_count) + for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) + if (trig->subirqs[i].enabled) { + trig->use_count++; + handle_nested_irq(trig->subirq_base + i); + } +} +EXPORT_SYMBOL(iio_trigger_poll_chained); + +void iio_trigger_notify_done(struct iio_trigger *trig) +{ + trig->use_count--; + if (trig->use_count == 0 && trig->ops && trig->ops->try_reenable) + if (trig->ops->try_reenable(trig)) + /* Missed and interrupt so launch new poll now */ + iio_trigger_poll(trig, 0); +} +EXPORT_SYMBOL(iio_trigger_notify_done); + +/* Trigger Consumer related functions */ +static int iio_trigger_get_irq(struct iio_trigger *trig) +{ + int ret; + mutex_lock(&trig->pool_lock); + ret = bitmap_find_free_region(trig->pool, + CONFIG_IIO_CONSUMERS_PER_TRIGGER, + ilog2(1)); + mutex_unlock(&trig->pool_lock); + if (ret >= 0) + ret += trig->subirq_base; + + return ret; +} + +static void iio_trigger_put_irq(struct iio_trigger *trig, int irq) +{ + mutex_lock(&trig->pool_lock); + clear_bit(irq - trig->subirq_base, trig->pool); + mutex_unlock(&trig->pool_lock); +} + +/* Complexity in here. With certain triggers (datardy) an acknowledgement + * may be needed if the pollfuncs do not include the data read for the + * triggering device. + * This is not currently handled. Alternative of not enabling trigger unless + * the relevant function is in there may be the best option. + */ +/* Worth protecting against double additions?*/ +static int iio_trigger_attach_poll_func(struct iio_trigger *trig, + struct iio_poll_func *pf) +{ + int ret = 0; + bool notinuse + = bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER); + + /* Prevent the module being removed whilst attached to a trigger */ + __module_get(pf->indio_dev->info->driver_module); + pf->irq = iio_trigger_get_irq(trig); + ret = request_threaded_irq(pf->irq, pf->h, pf->thread, + pf->type, pf->name, + pf); + if (ret < 0) { + module_put(pf->indio_dev->info->driver_module); + return ret; + } + + if (trig->ops && trig->ops->set_trigger_state && notinuse) { + ret = trig->ops->set_trigger_state(trig, true); + if (ret < 0) + module_put(pf->indio_dev->info->driver_module); + } + + return ret; +} + +static int iio_trigger_detach_poll_func(struct iio_trigger *trig, + struct iio_poll_func *pf) +{ + int ret = 0; + bool no_other_users + = (bitmap_weight(trig->pool, + CONFIG_IIO_CONSUMERS_PER_TRIGGER) + == 1); + if (trig->ops && trig->ops->set_trigger_state && no_other_users) { + ret = trig->ops->set_trigger_state(trig, false); + if (ret) + goto error_ret; + } + iio_trigger_put_irq(trig, pf->irq); + free_irq(pf->irq, pf); + module_put(pf->indio_dev->info->driver_module); + +error_ret: + return ret; +} + +irqreturn_t iio_pollfunc_store_time(int irq, void *p) +{ + struct iio_poll_func *pf = p; + pf->timestamp = iio_get_time_ns(); + return IRQ_WAKE_THREAD; +} +EXPORT_SYMBOL(iio_pollfunc_store_time); + +struct iio_poll_func +*iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), + irqreturn_t (*thread)(int irq, void *p), + int type, + struct iio_dev *indio_dev, + const char *fmt, + ...) +{ + va_list vargs; + struct iio_poll_func *pf; + + pf = kmalloc(sizeof *pf, GFP_KERNEL); + if (pf == NULL) + return NULL; + va_start(vargs, fmt); + pf->name = kvasprintf(GFP_KERNEL, fmt, vargs); + va_end(vargs); + if (pf->name == NULL) { + kfree(pf); + return NULL; + } + pf->h = h; + pf->thread = thread; + pf->type = type; + pf->indio_dev = indio_dev; + + return pf; +} +EXPORT_SYMBOL_GPL(iio_alloc_pollfunc); + +void iio_dealloc_pollfunc(struct iio_poll_func *pf) +{ + kfree(pf->name); + kfree(pf); +} +EXPORT_SYMBOL_GPL(iio_dealloc_pollfunc); + +/** + * iio_trigger_read_current() - trigger consumer sysfs query which trigger + * + * For trigger consumers the current_trigger interface allows the trigger + * used by the device to be queried. + **/ +static ssize_t iio_trigger_read_current(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + + if (indio_dev->trig) + return sprintf(buf, "%s\n", indio_dev->trig->name); + return 0; +} + +/** + * iio_trigger_write_current() trigger consumer sysfs set current trigger + * + * For trigger consumers the current_trigger interface allows the trigger + * used for this device to be specified at run time based on the triggers + * name. + **/ +static ssize_t iio_trigger_write_current(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_trigger *oldtrig = indio_dev->trig; + struct iio_trigger *trig; + int ret; + + mutex_lock(&indio_dev->mlock); + if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { + mutex_unlock(&indio_dev->mlock); + return -EBUSY; + } + mutex_unlock(&indio_dev->mlock); + + trig = iio_trigger_find_by_name(buf, len); + if (oldtrig == trig) + return len; + + if (trig && indio_dev->info->validate_trigger) { + ret = indio_dev->info->validate_trigger(indio_dev, trig); + if (ret) + return ret; + } + + if (trig && trig->ops && trig->ops->validate_device) { + ret = trig->ops->validate_device(trig, indio_dev); + if (ret) + return ret; + } + + indio_dev->trig = trig; + + if (oldtrig && indio_dev->trig != oldtrig) + iio_trigger_put(oldtrig); + if (indio_dev->trig) + iio_trigger_get(indio_dev->trig); + + return len; +} + +static DEVICE_ATTR(current_trigger, S_IRUGO | S_IWUSR, + iio_trigger_read_current, + iio_trigger_write_current); + +static struct attribute *iio_trigger_consumer_attrs[] = { + &dev_attr_current_trigger.attr, + NULL, +}; + +static const struct attribute_group iio_trigger_consumer_attr_group = { + .name = "trigger", + .attrs = iio_trigger_consumer_attrs, +}; + +static void iio_trig_release(struct device *device) +{ + struct iio_trigger *trig = to_iio_trigger(device); + int i; + + if (trig->subirq_base) { + for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) { + irq_modify_status(trig->subirq_base + i, + IRQ_NOAUTOEN, + IRQ_NOREQUEST | IRQ_NOPROBE); + irq_set_chip(trig->subirq_base + i, + NULL); + irq_set_handler(trig->subirq_base + i, + NULL); + } + + irq_free_descs(trig->subirq_base, + CONFIG_IIO_CONSUMERS_PER_TRIGGER); + } + kfree(trig->name); + kfree(trig); +} + +static struct device_type iio_trig_type = { + .release = iio_trig_release, + .groups = iio_trig_attr_groups, +}; + +static void iio_trig_subirqmask(struct irq_data *d) +{ + struct irq_chip *chip = irq_data_get_irq_chip(d); + struct iio_trigger *trig + = container_of(chip, + struct iio_trigger, subirq_chip); + trig->subirqs[d->irq - trig->subirq_base].enabled = false; +} + +static void iio_trig_subirqunmask(struct irq_data *d) +{ + struct irq_chip *chip = irq_data_get_irq_chip(d); + struct iio_trigger *trig + = container_of(chip, + struct iio_trigger, subirq_chip); + trig->subirqs[d->irq - trig->subirq_base].enabled = true; +} + +struct iio_trigger *iio_trigger_alloc(const char *fmt, ...) +{ + va_list vargs; + struct iio_trigger *trig; + trig = kzalloc(sizeof *trig, GFP_KERNEL); + if (trig) { + int i; + trig->dev.type = &iio_trig_type; + trig->dev.bus = &iio_bus_type; + device_initialize(&trig->dev); + + mutex_init(&trig->pool_lock); + trig->subirq_base + = irq_alloc_descs(-1, 0, + CONFIG_IIO_CONSUMERS_PER_TRIGGER, + 0); + if (trig->subirq_base < 0) { + kfree(trig); + return NULL; + } + va_start(vargs, fmt); + trig->name = kvasprintf(GFP_KERNEL, fmt, vargs); + va_end(vargs); + if (trig->name == NULL) { + irq_free_descs(trig->subirq_base, + CONFIG_IIO_CONSUMERS_PER_TRIGGER); + kfree(trig); + return NULL; + } + trig->subirq_chip.name = trig->name; + trig->subirq_chip.irq_mask = &iio_trig_subirqmask; + trig->subirq_chip.irq_unmask = &iio_trig_subirqunmask; + for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) { + irq_set_chip(trig->subirq_base + i, + &trig->subirq_chip); + irq_set_handler(trig->subirq_base + i, + &handle_simple_irq); + irq_modify_status(trig->subirq_base + i, + IRQ_NOREQUEST | IRQ_NOAUTOEN, + IRQ_NOPROBE); + } + get_device(&trig->dev); + } + return trig; +} +EXPORT_SYMBOL(iio_trigger_alloc); + +void iio_trigger_free(struct iio_trigger *trig) +{ + if (trig) + put_device(&trig->dev); +} +EXPORT_SYMBOL(iio_trigger_free); + +void iio_device_register_trigger_consumer(struct iio_dev *indio_dev) +{ + indio_dev->groups[indio_dev->groupcounter++] = + &iio_trigger_consumer_attr_group; +} + +void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev) +{ + /* Clean up and associated but not attached triggers references */ + if (indio_dev->trig) + iio_trigger_put(indio_dev->trig); +} + +int iio_triggered_buffer_postenable(struct iio_dev *indio_dev) +{ + return iio_trigger_attach_poll_func(indio_dev->trig, + indio_dev->pollfunc); +} +EXPORT_SYMBOL(iio_triggered_buffer_postenable); + +int iio_triggered_buffer_predisable(struct iio_dev *indio_dev) +{ + return iio_trigger_detach_poll_func(indio_dev->trig, + indio_dev->pollfunc); +} +EXPORT_SYMBOL(iio_triggered_buffer_predisable); diff --git a/drivers/iio/industrialio-triggered-buffer.c b/drivers/iio/industrialio-triggered-buffer.c new file mode 100644 index 0000000000000..46c619b0d8c51 --- /dev/null +++ b/drivers/iio/industrialio-triggered-buffer.c @@ -0,0 +1,110 @@ + /* + * Copyright (c) 2012 Analog Devices, Inc. + * Author: Lars-Peter Clausen + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = { + .preenable = &iio_sw_buffer_preenable, + .postenable = &iio_triggered_buffer_postenable, + .predisable = &iio_triggered_buffer_predisable, +}; + +/** + * iio_triggered_buffer_setup() - Setup triggered buffer and pollfunc + * @indio_dev: IIO device structure + * @pollfunc_bh: Function which will be used as pollfunc bottom half + * @pollfunc_th: Function which will be used as pollfunc top half + * @setup_ops: Buffer setup functions to use for this device. + * If NULL the default setup functions for triggered + * buffers will be used. + * + * This function combines some common tasks which will normally be performed + * when setting up a triggered buffer. It will allocate the buffer and the + * pollfunc, as well as register the buffer with the IIO core. + * + * Before calling this function the indio_dev structure should already be + * completely initialized, but not yet registered. In practice this means that + * this function should be called right before iio_device_register(). + * + * To free the resources allocated by this function call + * iio_triggered_buffer_cleanup(). + */ +int iio_triggered_buffer_setup(struct iio_dev *indio_dev, + irqreturn_t (*pollfunc_bh)(int irq, void *p), + irqreturn_t (*pollfunc_th)(int irq, void *p), + const struct iio_buffer_setup_ops *setup_ops) +{ + int ret; + + indio_dev->buffer = iio_kfifo_allocate(indio_dev); + if (!indio_dev->buffer) { + ret = -ENOMEM; + goto error_ret; + } + + indio_dev->pollfunc = iio_alloc_pollfunc(pollfunc_bh, + pollfunc_th, + IRQF_ONESHOT, + indio_dev, + "%s_consumer%d", + indio_dev->name, + indio_dev->id); + if (indio_dev->pollfunc == NULL) { + ret = -ENOMEM; + goto error_kfifo_free; + } + + /* Ring buffer functions - here trigger setup related */ + if (setup_ops) + indio_dev->setup_ops = setup_ops; + else + indio_dev->setup_ops = &iio_triggered_buffer_setup_ops; + + /* Flag that polled ring buffering is possible */ + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; + + ret = iio_buffer_register(indio_dev, + indio_dev->channels, + indio_dev->num_channels); + if (ret) + goto error_dealloc_pollfunc; + + return 0; + +error_dealloc_pollfunc: + iio_dealloc_pollfunc(indio_dev->pollfunc); +error_kfifo_free: + iio_kfifo_free(indio_dev->buffer); +error_ret: + return ret; +} +EXPORT_SYMBOL(iio_triggered_buffer_setup); + +/** + * iio_triggered_buffer_cleanup() - Free resources allocated by iio_triggered_buffer_setup() + * @indio_dev: IIO device structure + */ +void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev) +{ + iio_buffer_unregister(indio_dev); + iio_dealloc_pollfunc(indio_dev->pollfunc); + iio_kfifo_free(indio_dev->buffer); +} +EXPORT_SYMBOL(iio_triggered_buffer_cleanup); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("IIO helper functions for setting up triggered buffers"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c new file mode 100644 index 0000000000000..e2aded04996bb --- /dev/null +++ b/drivers/iio/inkern.c @@ -0,0 +1,288 @@ +/* The industrial I/O core in kernel channel mapping + * + * Copyright (c) 2011 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#include +#include +#include +#include + +#include +#include "iio_core.h" +#include +#include +#include + +struct iio_map_internal { + struct iio_dev *indio_dev; + struct iio_map *map; + struct list_head l; +}; + +static LIST_HEAD(iio_map_list); +static DEFINE_MUTEX(iio_map_list_lock); + +int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps) +{ + int i = 0, ret = 0; + struct iio_map_internal *mapi; + + if (maps == NULL) + return 0; + + mutex_lock(&iio_map_list_lock); + while (maps[i].consumer_dev_name != NULL) { + mapi = kzalloc(sizeof(*mapi), GFP_KERNEL); + if (mapi == NULL) { + ret = -ENOMEM; + goto error_ret; + } + mapi->map = &maps[i]; + mapi->indio_dev = indio_dev; + list_add(&mapi->l, &iio_map_list); + i++; + } +error_ret: + mutex_unlock(&iio_map_list_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_map_array_register); + + +/* Assumes the exact same array (e.g. memory locations) + * used at unregistration as used at registration rather than + * more complex checking of contents. + */ +int iio_map_array_unregister(struct iio_dev *indio_dev, + struct iio_map *maps) +{ + int i = 0, ret = 0; + bool found_it; + struct iio_map_internal *mapi; + + if (maps == NULL) + return 0; + + mutex_lock(&iio_map_list_lock); + while (maps[i].consumer_dev_name != NULL) { + found_it = false; + list_for_each_entry(mapi, &iio_map_list, l) + if (&maps[i] == mapi->map) { + list_del(&mapi->l); + kfree(mapi); + found_it = true; + break; + } + if (found_it == false) { + ret = -ENODEV; + goto error_ret; + } + i++; + } +error_ret: + mutex_unlock(&iio_map_list_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_map_array_unregister); + +static const struct iio_chan_spec +*iio_chan_spec_from_name(const struct iio_dev *indio_dev, const char *name) +{ + int i; + const struct iio_chan_spec *chan = NULL; + + for (i = 0; i < indio_dev->num_channels; i++) + if (indio_dev->channels[i].datasheet_name && + strcmp(name, indio_dev->channels[i].datasheet_name) == 0) { + chan = &indio_dev->channels[i]; + break; + } + return chan; +} + + +struct iio_channel *iio_channel_get(const char *name, const char *channel_name) +{ + struct iio_map_internal *c_i = NULL, *c = NULL; + struct iio_channel *channel; + + if (name == NULL && channel_name == NULL) + return ERR_PTR(-ENODEV); + + /* first find matching entry the channel map */ + mutex_lock(&iio_map_list_lock); + list_for_each_entry(c_i, &iio_map_list, l) { + if ((name && strcmp(name, c_i->map->consumer_dev_name) != 0) || + (channel_name && + strcmp(channel_name, c_i->map->consumer_channel) != 0)) + continue; + c = c_i; + iio_device_get(c->indio_dev); + break; + } + mutex_unlock(&iio_map_list_lock); + if (c == NULL) + return ERR_PTR(-ENODEV); + + channel = kmalloc(sizeof(*channel), GFP_KERNEL); + if (channel == NULL) + return ERR_PTR(-ENOMEM); + + channel->indio_dev = c->indio_dev; + + if (c->map->adc_channel_label) + channel->channel = + iio_chan_spec_from_name(channel->indio_dev, + c->map->adc_channel_label); + + return channel; +} +EXPORT_SYMBOL_GPL(iio_channel_get); + +void iio_channel_release(struct iio_channel *channel) +{ + iio_device_put(channel->indio_dev); + kfree(channel); +} +EXPORT_SYMBOL_GPL(iio_channel_release); + +struct iio_channel *iio_channel_get_all(const char *name) +{ + struct iio_channel *chans; + struct iio_map_internal *c = NULL; + int nummaps = 0; + int mapind = 0; + int i, ret; + + if (name == NULL) + return ERR_PTR(-EINVAL); + + mutex_lock(&iio_map_list_lock); + /* first count the matching maps */ + list_for_each_entry(c, &iio_map_list, l) + if (name && strcmp(name, c->map->consumer_dev_name) != 0) + continue; + else + nummaps++; + + if (nummaps == 0) { + ret = -ENODEV; + goto error_ret; + } + + /* NULL terminated array to save passing size */ + chans = kzalloc(sizeof(*chans)*(nummaps + 1), GFP_KERNEL); + if (chans == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + /* for each map fill in the chans element */ + list_for_each_entry(c, &iio_map_list, l) { + if (name && strcmp(name, c->map->consumer_dev_name) != 0) + continue; + chans[mapind].indio_dev = c->indio_dev; + chans[mapind].channel = + iio_chan_spec_from_name(chans[mapind].indio_dev, + c->map->adc_channel_label); + if (chans[mapind].channel == NULL) { + ret = -EINVAL; + goto error_free_chans; + } + iio_device_get(chans[mapind].indio_dev); + mapind++; + } + mutex_unlock(&iio_map_list_lock); + if (mapind == 0) { + ret = -ENODEV; + goto error_free_chans; + } + return chans; + +error_free_chans: + for (i = 0; i < nummaps; i++) + iio_device_put(chans[i].indio_dev); + kfree(chans); +error_ret: + mutex_unlock(&iio_map_list_lock); + + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(iio_channel_get_all); + +void iio_channel_release_all(struct iio_channel *channels) +{ + struct iio_channel *chan = &channels[0]; + + while (chan->indio_dev) { + iio_device_put(chan->indio_dev); + chan++; + } + kfree(channels); +} +EXPORT_SYMBOL_GPL(iio_channel_release_all); + +int iio_read_channel_raw(struct iio_channel *chan, int *val) +{ + int val2, ret; + + mutex_lock(&chan->indio_dev->info_exist_lock); + if (chan->indio_dev->info == NULL) { + ret = -ENODEV; + goto err_unlock; + } + + ret = chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel, + val, &val2, 0); +err_unlock: + mutex_unlock(&chan->indio_dev->info_exist_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_read_channel_raw); + +int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2) +{ + int ret; + + mutex_lock(&chan->indio_dev->info_exist_lock); + if (chan->indio_dev->info == NULL) { + ret = -ENODEV; + goto err_unlock; + } + + ret = chan->indio_dev->info->read_raw(chan->indio_dev, + chan->channel, + val, val2, + IIO_CHAN_INFO_SCALE); +err_unlock: + mutex_unlock(&chan->indio_dev->info_exist_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_read_channel_scale); + +int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type) +{ + int ret = 0; + /* Need to verify underlying driver has not gone away */ + + mutex_lock(&chan->indio_dev->info_exist_lock); + if (chan->indio_dev->info == NULL) { + ret = -ENODEV; + goto err_unlock; + } + + *type = chan->channel->type; +err_unlock: + mutex_unlock(&chan->indio_dev->info_exist_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_get_channel_type); diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c new file mode 100644 index 0000000000000..6bf9d05f48411 --- /dev/null +++ b/drivers/iio/kfifo_buf.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +struct iio_kfifo { + struct iio_buffer buffer; + struct kfifo kf; + int update_needed; +}; + +#define iio_to_kfifo(r) container_of(r, struct iio_kfifo, buffer) + +static inline int __iio_allocate_kfifo(struct iio_kfifo *buf, + int bytes_per_datum, int length) +{ + if ((length == 0) || (bytes_per_datum == 0)) + return -EINVAL; + + __iio_update_buffer(&buf->buffer, bytes_per_datum, length); + return kfifo_alloc(&buf->kf, bytes_per_datum*length, GFP_KERNEL); +} + +static int iio_request_update_kfifo(struct iio_buffer *r) +{ + int ret = 0; + struct iio_kfifo *buf = iio_to_kfifo(r); + + if (!buf->update_needed) + goto error_ret; + kfifo_free(&buf->kf); + ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum, + buf->buffer.length); +error_ret: + return ret; +} + +static int iio_get_length_kfifo(struct iio_buffer *r) +{ + return r->length; +} + +static IIO_BUFFER_ENABLE_ATTR; +static IIO_BUFFER_LENGTH_ATTR; + +static struct attribute *iio_kfifo_attributes[] = { + &dev_attr_length.attr, + &dev_attr_enable.attr, + NULL, +}; + +static struct attribute_group iio_kfifo_attribute_group = { + .attrs = iio_kfifo_attributes, + .name = "buffer", +}; + +static int iio_get_bytes_per_datum_kfifo(struct iio_buffer *r) +{ + return r->bytes_per_datum; +} + +static int iio_mark_update_needed_kfifo(struct iio_buffer *r) +{ + struct iio_kfifo *kf = iio_to_kfifo(r); + kf->update_needed = true; + return 0; +} + +static int iio_set_bytes_per_datum_kfifo(struct iio_buffer *r, size_t bpd) +{ + if (r->bytes_per_datum != bpd) { + r->bytes_per_datum = bpd; + iio_mark_update_needed_kfifo(r); + } + return 0; +} + +static int iio_set_length_kfifo(struct iio_buffer *r, int length) +{ + if (r->length != length) { + r->length = length; + iio_mark_update_needed_kfifo(r); + } + return 0; +} + +static int iio_store_to_kfifo(struct iio_buffer *r, + u8 *data, + s64 timestamp) +{ + int ret; + struct iio_kfifo *kf = iio_to_kfifo(r); + ret = kfifo_in(&kf->kf, data, r->bytes_per_datum); + if (ret != r->bytes_per_datum) + return -EBUSY; + return 0; +} + +static int iio_read_first_n_kfifo(struct iio_buffer *r, + size_t n, char __user *buf) +{ + int ret, copied; + struct iio_kfifo *kf = iio_to_kfifo(r); + + if (n < r->bytes_per_datum) + return -EINVAL; + + n = rounddown(n, r->bytes_per_datum); + ret = kfifo_to_user(&kf->kf, buf, n, &copied); + + return copied; +} + +static const struct iio_buffer_access_funcs kfifo_access_funcs = { + .store_to = &iio_store_to_kfifo, + .read_first_n = &iio_read_first_n_kfifo, + .request_update = &iio_request_update_kfifo, + .get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo, + .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, + .get_length = &iio_get_length_kfifo, + .set_length = &iio_set_length_kfifo, +}; + +struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) +{ + struct iio_kfifo *kf; + + kf = kzalloc(sizeof *kf, GFP_KERNEL); + if (!kf) + return NULL; + kf->update_needed = true; + iio_buffer_init(&kf->buffer); + kf->buffer.attrs = &iio_kfifo_attribute_group; + kf->buffer.access = &kfifo_access_funcs; + + return &kf->buffer; +} +EXPORT_SYMBOL(iio_kfifo_allocate); + +void iio_kfifo_free(struct iio_buffer *r) +{ + kfree(iio_to_kfifo(r)); +} +EXPORT_SYMBOL(iio_kfifo_free); + +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig new file mode 100644 index 0000000000000..f3ea90d735b8c --- /dev/null +++ b/drivers/iio/light/Kconfig @@ -0,0 +1,33 @@ +# +# Light sensors +# +menu "Light sensors" + +config SENSORS_LM3533 + tristate "LM3533 ambient light sensor" + depends on MFD_LM3533 + help + If you say yes here you get support for the ambient light sensor + interface on National Semiconductor / TI LM3533 Lighting Power + chips. + + The sensor interface can be used to control the LEDs and backlights + of the chip through defining five light zones and three sets of + corresponding output-current values. + + The driver provides raw and mean adc readings along with the current + light zone through sysfs. A threshold event can be generated on zone + changes. The ALS-control output values can be set per zone for the + three current output channels. + +config VCNL4000 + tristate "VCNL4000 combined ALS and proximity sensor" + depends on I2C + help + Say Y here if you want to build a driver for the Vishay VCNL4000 + combined ambient light and proximity sensor. + + To compile this driver as a module, choose M here: the + module will be called vcnl4000. + +endmenu diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile new file mode 100644 index 0000000000000..06fa4d3f33ec1 --- /dev/null +++ b/drivers/iio/light/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for IIO Light sensors +# + +obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o +obj-$(CONFIG_VCNL4000) += vcnl4000.o diff --git a/drivers/iio/light/lm3533-als.c b/drivers/iio/light/lm3533-als.c new file mode 100644 index 0000000000000..c3e7bac131231 --- /dev/null +++ b/drivers/iio/light/lm3533-als.c @@ -0,0 +1,932 @@ +/* + * lm3533-als.c -- LM3533 Ambient Light Sensor driver + * + * Copyright (C) 2011-2012 Texas Instruments + * + * Author: Johan Hovold + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#define LM3533_ALS_RESISTOR_MIN 1 +#define LM3533_ALS_RESISTOR_MAX 127 +#define LM3533_ALS_CHANNEL_CURRENT_MAX 2 +#define LM3533_ALS_THRESH_MAX 3 +#define LM3533_ALS_ZONE_MAX 4 + +#define LM3533_REG_ALS_RESISTOR_SELECT 0x30 +#define LM3533_REG_ALS_CONF 0x31 +#define LM3533_REG_ALS_ZONE_INFO 0x34 +#define LM3533_REG_ALS_READ_ADC_RAW 0x37 +#define LM3533_REG_ALS_READ_ADC_AVERAGE 0x38 +#define LM3533_REG_ALS_BOUNDARY_BASE 0x50 +#define LM3533_REG_ALS_TARGET_BASE 0x60 + +#define LM3533_ALS_ENABLE_MASK 0x01 +#define LM3533_ALS_INPUT_MODE_MASK 0x02 +#define LM3533_ALS_INT_ENABLE_MASK 0x01 + +#define LM3533_ALS_ZONE_SHIFT 2 +#define LM3533_ALS_ZONE_MASK 0x1c + +#define LM3533_ALS_FLAG_INT_ENABLED 1 + + +struct lm3533_als { + struct lm3533 *lm3533; + struct platform_device *pdev; + + unsigned long flags; + int irq; + + atomic_t zone; + struct mutex thresh_mutex; +}; + + +static int lm3533_als_get_adc(struct iio_dev *indio_dev, bool average, + int *adc) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 reg; + u8 val; + int ret; + + if (average) + reg = LM3533_REG_ALS_READ_ADC_AVERAGE; + else + reg = LM3533_REG_ALS_READ_ADC_RAW; + + ret = lm3533_read(als->lm3533, reg, &val); + if (ret) { + dev_err(&indio_dev->dev, "failed to read adc\n"); + return ret; + } + + *adc = val; + + return 0; +} + +static int _lm3533_als_get_zone(struct iio_dev *indio_dev, u8 *zone) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 val; + int ret; + + ret = lm3533_read(als->lm3533, LM3533_REG_ALS_ZONE_INFO, &val); + if (ret) { + dev_err(&indio_dev->dev, "failed to read zone\n"); + return ret; + } + + val = (val & LM3533_ALS_ZONE_MASK) >> LM3533_ALS_ZONE_SHIFT; + *zone = min_t(u8, val, LM3533_ALS_ZONE_MAX); + + return 0; +} + +static int lm3533_als_get_zone(struct iio_dev *indio_dev, u8 *zone) +{ + struct lm3533_als *als = iio_priv(indio_dev); + int ret; + + if (test_bit(LM3533_ALS_FLAG_INT_ENABLED, &als->flags)) { + *zone = atomic_read(&als->zone); + } else { + ret = _lm3533_als_get_zone(indio_dev, zone); + if (ret) + return ret; + } + + return 0; +} + +/* + * channel output channel 0..2 + * zone zone 0..4 + */ +static inline u8 lm3533_als_get_target_reg(unsigned channel, unsigned zone) +{ + return LM3533_REG_ALS_TARGET_BASE + 5 * channel + zone; +} + +static int lm3533_als_get_target(struct iio_dev *indio_dev, unsigned channel, + unsigned zone, u8 *val) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 reg; + int ret; + + if (channel > LM3533_ALS_CHANNEL_CURRENT_MAX) + return -EINVAL; + + if (zone > LM3533_ALS_ZONE_MAX) + return -EINVAL; + + reg = lm3533_als_get_target_reg(channel, zone); + ret = lm3533_read(als->lm3533, reg, val); + if (ret) + dev_err(&indio_dev->dev, "failed to get target current\n"); + + return ret; +} + +static int lm3533_als_set_target(struct iio_dev *indio_dev, unsigned channel, + unsigned zone, u8 val) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 reg; + int ret; + + if (channel > LM3533_ALS_CHANNEL_CURRENT_MAX) + return -EINVAL; + + if (zone > LM3533_ALS_ZONE_MAX) + return -EINVAL; + + reg = lm3533_als_get_target_reg(channel, zone); + ret = lm3533_write(als->lm3533, reg, val); + if (ret) + dev_err(&indio_dev->dev, "failed to set target current\n"); + + return ret; +} + +static int lm3533_als_get_current(struct iio_dev *indio_dev, unsigned channel, + int *val) +{ + u8 zone; + u8 target; + int ret; + + ret = lm3533_als_get_zone(indio_dev, &zone); + if (ret) + return ret; + + ret = lm3533_als_get_target(indio_dev, channel, zone, &target); + if (ret) + return ret; + + *val = target; + + return 0; +} + +static int lm3533_als_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + int ret; + + switch (mask) { + case 0: + switch (chan->type) { + case IIO_LIGHT: + ret = lm3533_als_get_adc(indio_dev, false, val); + break; + case IIO_CURRENT: + ret = lm3533_als_get_current(indio_dev, chan->channel, + val); + break; + default: + return -EINVAL; + } + break; + case IIO_CHAN_INFO_AVERAGE_RAW: + ret = lm3533_als_get_adc(indio_dev, true, val); + break; + default: + return -EINVAL; + } + + if (ret) + return ret; + + return IIO_VAL_INT; +} + +#define CHANNEL_CURRENT(_channel) \ + { \ + .type = IIO_CURRENT, \ + .channel = _channel, \ + .indexed = true, \ + .output = true, \ + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, \ + } + +static const struct iio_chan_spec lm3533_als_channels[] = { + { + .type = IIO_LIGHT, + .channel = 0, + .indexed = true, + .info_mask = (IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_RAW_SEPARATE_BIT), + }, + CHANNEL_CURRENT(0), + CHANNEL_CURRENT(1), + CHANNEL_CURRENT(2), +}; + +static irqreturn_t lm3533_als_isr(int irq, void *dev_id) +{ + + struct iio_dev *indio_dev = dev_id; + struct lm3533_als *als = iio_priv(indio_dev); + u8 zone; + int ret; + + /* Clear interrupt by reading the ALS zone register. */ + ret = _lm3533_als_get_zone(indio_dev, &zone); + if (ret) + goto out; + + atomic_set(&als->zone, zone); + + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_LIGHT, + 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_EITHER), + iio_get_time_ns()); +out: + return IRQ_HANDLED; +} + +static int lm3533_als_set_int_mode(struct iio_dev *indio_dev, int enable) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 mask = LM3533_ALS_INT_ENABLE_MASK; + u8 val; + int ret; + + if (enable) + val = mask; + else + val = 0; + + ret = lm3533_update(als->lm3533, LM3533_REG_ALS_ZONE_INFO, val, mask); + if (ret) { + dev_err(&indio_dev->dev, "failed to set int mode %d\n", + enable); + return ret; + } + + return 0; +} + +static int lm3533_als_get_int_mode(struct iio_dev *indio_dev, int *enable) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 mask = LM3533_ALS_INT_ENABLE_MASK; + u8 val; + int ret; + + ret = lm3533_read(als->lm3533, LM3533_REG_ALS_ZONE_INFO, &val); + if (ret) { + dev_err(&indio_dev->dev, "failed to get int mode\n"); + return ret; + } + + *enable = !!(val & mask); + + return 0; +} + +static inline u8 lm3533_als_get_threshold_reg(unsigned nr, bool raising) +{ + u8 offset = !raising; + + return LM3533_REG_ALS_BOUNDARY_BASE + 2 * nr + offset; +} + +static int lm3533_als_get_threshold(struct iio_dev *indio_dev, unsigned nr, + bool raising, u8 *val) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 reg; + int ret; + + if (nr > LM3533_ALS_THRESH_MAX) + return -EINVAL; + + reg = lm3533_als_get_threshold_reg(nr, raising); + ret = lm3533_read(als->lm3533, reg, val); + if (ret) + dev_err(&indio_dev->dev, "failed to get threshold\n"); + + return ret; +} + +static int lm3533_als_set_threshold(struct iio_dev *indio_dev, unsigned nr, + bool raising, u8 val) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 val2; + u8 reg, reg2; + int ret; + + if (nr > LM3533_ALS_THRESH_MAX) + return -EINVAL; + + reg = lm3533_als_get_threshold_reg(nr, raising); + reg2 = lm3533_als_get_threshold_reg(nr, !raising); + + mutex_lock(&als->thresh_mutex); + ret = lm3533_read(als->lm3533, reg2, &val2); + if (ret) { + dev_err(&indio_dev->dev, "failed to get threshold\n"); + goto out; + } + /* + * This device does not allow negative hysteresis (in fact, it uses + * whichever value is smaller as the lower bound) so we need to make + * sure that thresh_falling <= thresh_raising. + */ + if ((raising && (val < val2)) || (!raising && (val > val2))) { + ret = -EINVAL; + goto out; + } + + ret = lm3533_write(als->lm3533, reg, val); + if (ret) { + dev_err(&indio_dev->dev, "failed to set threshold\n"); + goto out; + } +out: + mutex_unlock(&als->thresh_mutex); + + return ret; +} + +static int lm3533_als_get_hysteresis(struct iio_dev *indio_dev, unsigned nr, + u8 *val) +{ + struct lm3533_als *als = iio_priv(indio_dev); + u8 falling; + u8 raising; + int ret; + + if (nr > LM3533_ALS_THRESH_MAX) + return -EINVAL; + + mutex_lock(&als->thresh_mutex); + ret = lm3533_als_get_threshold(indio_dev, nr, false, &falling); + if (ret) + goto out; + ret = lm3533_als_get_threshold(indio_dev, nr, true, &raising); + if (ret) + goto out; + + *val = raising - falling; +out: + mutex_unlock(&als->thresh_mutex); + + return ret; +} + +static int show_thresh_either_en(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct lm3533_als *als = iio_priv(indio_dev); + int enable; + int ret; + + if (als->irq) { + ret = lm3533_als_get_int_mode(indio_dev, &enable); + if (ret) + return ret; + } else { + enable = 0; + } + + return scnprintf(buf, PAGE_SIZE, "%u\n", enable); +} + +static int store_thresh_either_en(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct lm3533_als *als = iio_priv(indio_dev); + unsigned long enable; + bool int_enabled; + u8 zone; + int ret; + + if (!als->irq) + return -EBUSY; + + if (kstrtoul(buf, 0, &enable)) + return -EINVAL; + + int_enabled = test_bit(LM3533_ALS_FLAG_INT_ENABLED, &als->flags); + + if (enable && !int_enabled) { + ret = lm3533_als_get_zone(indio_dev, &zone); + if (ret) + return ret; + + atomic_set(&als->zone, zone); + + set_bit(LM3533_ALS_FLAG_INT_ENABLED, &als->flags); + } + + ret = lm3533_als_set_int_mode(indio_dev, enable); + if (ret) { + if (!int_enabled) + clear_bit(LM3533_ALS_FLAG_INT_ENABLED, &als->flags); + + return ret; + } + + if (!enable) + clear_bit(LM3533_ALS_FLAG_INT_ENABLED, &als->flags); + + return len; +} + +static ssize_t show_zone(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + u8 zone; + int ret; + + ret = lm3533_als_get_zone(indio_dev, &zone); + if (ret) + return ret; + + return scnprintf(buf, PAGE_SIZE, "%u\n", zone); +} + +enum lm3533_als_attribute_type { + LM3533_ATTR_TYPE_HYSTERESIS, + LM3533_ATTR_TYPE_TARGET, + LM3533_ATTR_TYPE_THRESH_FALLING, + LM3533_ATTR_TYPE_THRESH_RAISING, +}; + +struct lm3533_als_attribute { + struct device_attribute dev_attr; + enum lm3533_als_attribute_type type; + u8 val1; + u8 val2; +}; + +static inline struct lm3533_als_attribute * +to_lm3533_als_attr(struct device_attribute *attr) +{ + return container_of(attr, struct lm3533_als_attribute, dev_attr); +} + +static ssize_t show_als_attr(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct lm3533_als_attribute *als_attr = to_lm3533_als_attr(attr); + u8 val; + int ret; + + switch (als_attr->type) { + case LM3533_ATTR_TYPE_HYSTERESIS: + ret = lm3533_als_get_hysteresis(indio_dev, als_attr->val1, + &val); + break; + case LM3533_ATTR_TYPE_TARGET: + ret = lm3533_als_get_target(indio_dev, als_attr->val1, + als_attr->val2, &val); + break; + case LM3533_ATTR_TYPE_THRESH_FALLING: + ret = lm3533_als_get_threshold(indio_dev, als_attr->val1, + false, &val); + break; + case LM3533_ATTR_TYPE_THRESH_RAISING: + ret = lm3533_als_get_threshold(indio_dev, als_attr->val1, + true, &val); + break; + default: + ret = -ENXIO; + } + + if (ret) + return ret; + + return scnprintf(buf, PAGE_SIZE, "%u\n", val); +} + +static ssize_t store_als_attr(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct lm3533_als_attribute *als_attr = to_lm3533_als_attr(attr); + u8 val; + int ret; + + if (kstrtou8(buf, 0, &val)) + return -EINVAL; + + switch (als_attr->type) { + case LM3533_ATTR_TYPE_TARGET: + ret = lm3533_als_set_target(indio_dev, als_attr->val1, + als_attr->val2, val); + break; + case LM3533_ATTR_TYPE_THRESH_FALLING: + ret = lm3533_als_set_threshold(indio_dev, als_attr->val1, + false, val); + break; + case LM3533_ATTR_TYPE_THRESH_RAISING: + ret = lm3533_als_set_threshold(indio_dev, als_attr->val1, + true, val); + break; + default: + ret = -ENXIO; + } + + if (ret) + return ret; + + return len; +} + +#define ALS_ATTR(_name, _mode, _show, _store, _type, _val1, _val2) \ + { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .type = _type, \ + .val1 = _val1, \ + .val2 = _val2 } + +#define LM3533_ALS_ATTR(_name, _mode, _show, _store, _type, _val1, _val2) \ + struct lm3533_als_attribute lm3533_als_attr_##_name = \ + ALS_ATTR(_name, _mode, _show, _store, _type, _val1, _val2) + +#define ALS_TARGET_ATTR_RW(_channel, _zone) \ + LM3533_ALS_ATTR(out_current##_channel##_current##_zone##_raw, \ + S_IRUGO | S_IWUSR, \ + show_als_attr, store_als_attr, \ + LM3533_ATTR_TYPE_TARGET, _channel, _zone) +/* + * ALS output current values (ALS mapper targets) + * + * out_current[0-2]_current[0-4]_raw 0-255 + */ +static ALS_TARGET_ATTR_RW(0, 0); +static ALS_TARGET_ATTR_RW(0, 1); +static ALS_TARGET_ATTR_RW(0, 2); +static ALS_TARGET_ATTR_RW(0, 3); +static ALS_TARGET_ATTR_RW(0, 4); + +static ALS_TARGET_ATTR_RW(1, 0); +static ALS_TARGET_ATTR_RW(1, 1); +static ALS_TARGET_ATTR_RW(1, 2); +static ALS_TARGET_ATTR_RW(1, 3); +static ALS_TARGET_ATTR_RW(1, 4); + +static ALS_TARGET_ATTR_RW(2, 0); +static ALS_TARGET_ATTR_RW(2, 1); +static ALS_TARGET_ATTR_RW(2, 2); +static ALS_TARGET_ATTR_RW(2, 3); +static ALS_TARGET_ATTR_RW(2, 4); + +#define ALS_THRESH_FALLING_ATTR_RW(_nr) \ + LM3533_ALS_ATTR(in_illuminance0_thresh##_nr##_falling_value, \ + S_IRUGO | S_IWUSR, \ + show_als_attr, store_als_attr, \ + LM3533_ATTR_TYPE_THRESH_FALLING, _nr, 0) + +#define ALS_THRESH_RAISING_ATTR_RW(_nr) \ + LM3533_ALS_ATTR(in_illuminance0_thresh##_nr##_raising_value, \ + S_IRUGO | S_IWUSR, \ + show_als_attr, store_als_attr, \ + LM3533_ATTR_TYPE_THRESH_RAISING, _nr, 0) +/* + * ALS Zone thresholds (boundaries) + * + * in_illuminance0_thresh[0-3]_falling_value 0-255 + * in_illuminance0_thresh[0-3]_raising_value 0-255 + */ +static ALS_THRESH_FALLING_ATTR_RW(0); +static ALS_THRESH_FALLING_ATTR_RW(1); +static ALS_THRESH_FALLING_ATTR_RW(2); +static ALS_THRESH_FALLING_ATTR_RW(3); + +static ALS_THRESH_RAISING_ATTR_RW(0); +static ALS_THRESH_RAISING_ATTR_RW(1); +static ALS_THRESH_RAISING_ATTR_RW(2); +static ALS_THRESH_RAISING_ATTR_RW(3); + +#define ALS_HYSTERESIS_ATTR_RO(_nr) \ + LM3533_ALS_ATTR(in_illuminance0_thresh##_nr##_hysteresis, \ + S_IRUGO, show_als_attr, NULL, \ + LM3533_ATTR_TYPE_HYSTERESIS, _nr, 0) +/* + * ALS Zone threshold hysteresis + * + * threshY_hysteresis = threshY_raising - threshY_falling + * + * in_illuminance0_thresh[0-3]_hysteresis 0-255 + * in_illuminance0_thresh[0-3]_hysteresis 0-255 + */ +static ALS_HYSTERESIS_ATTR_RO(0); +static ALS_HYSTERESIS_ATTR_RO(1); +static ALS_HYSTERESIS_ATTR_RO(2); +static ALS_HYSTERESIS_ATTR_RO(3); + +#define ILLUMINANCE_ATTR_RO(_name) \ + DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO, show_##_name, NULL) +#define ILLUMINANCE_ATTR_RW(_name) \ + DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO | S_IWUSR , \ + show_##_name, store_##_name) +/* + * ALS Zone threshold-event enable + * + * in_illuminance0_thresh_either_en 0,1 + */ +static ILLUMINANCE_ATTR_RW(thresh_either_en); + +/* + * ALS Current Zone + * + * in_illuminance0_zone 0-4 + */ +static ILLUMINANCE_ATTR_RO(zone); + +static struct attribute *lm3533_als_event_attributes[] = { + &dev_attr_in_illuminance0_thresh_either_en.attr, + &lm3533_als_attr_in_illuminance0_thresh0_falling_value.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh0_hysteresis.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh0_raising_value.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh1_falling_value.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh1_hysteresis.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh1_raising_value.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh2_falling_value.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh2_hysteresis.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh2_raising_value.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh3_falling_value.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh3_hysteresis.dev_attr.attr, + &lm3533_als_attr_in_illuminance0_thresh3_raising_value.dev_attr.attr, + NULL +}; + +static struct attribute_group lm3533_als_event_attribute_group = { + .attrs = lm3533_als_event_attributes +}; + +static struct attribute *lm3533_als_attributes[] = { + &dev_attr_in_illuminance0_zone.attr, + &lm3533_als_attr_out_current0_current0_raw.dev_attr.attr, + &lm3533_als_attr_out_current0_current1_raw.dev_attr.attr, + &lm3533_als_attr_out_current0_current2_raw.dev_attr.attr, + &lm3533_als_attr_out_current0_current3_raw.dev_attr.attr, + &lm3533_als_attr_out_current0_current4_raw.dev_attr.attr, + &lm3533_als_attr_out_current1_current0_raw.dev_attr.attr, + &lm3533_als_attr_out_current1_current1_raw.dev_attr.attr, + &lm3533_als_attr_out_current1_current2_raw.dev_attr.attr, + &lm3533_als_attr_out_current1_current3_raw.dev_attr.attr, + &lm3533_als_attr_out_current1_current4_raw.dev_attr.attr, + &lm3533_als_attr_out_current2_current0_raw.dev_attr.attr, + &lm3533_als_attr_out_current2_current1_raw.dev_attr.attr, + &lm3533_als_attr_out_current2_current2_raw.dev_attr.attr, + &lm3533_als_attr_out_current2_current3_raw.dev_attr.attr, + &lm3533_als_attr_out_current2_current4_raw.dev_attr.attr, + NULL +}; + +static struct attribute_group lm3533_als_attribute_group = { + .attrs = lm3533_als_attributes +}; + +static int __devinit lm3533_als_set_input_mode(struct lm3533_als *als, + bool pwm_mode) +{ + u8 mask = LM3533_ALS_INPUT_MODE_MASK; + u8 val; + int ret; + + if (pwm_mode) + val = mask; /* pwm input */ + else + val = 0; /* analog input */ + + ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, val, mask); + if (ret) { + dev_err(&als->pdev->dev, "failed to set input mode %d\n", + pwm_mode); + return ret; + } + + return 0; +} + +static int __devinit lm3533_als_set_resistor(struct lm3533_als *als, u8 val) +{ + int ret; + + if (val < LM3533_ALS_RESISTOR_MIN || val > LM3533_ALS_RESISTOR_MAX) + return -EINVAL; + + ret = lm3533_write(als->lm3533, LM3533_REG_ALS_RESISTOR_SELECT, val); + if (ret) { + dev_err(&als->pdev->dev, "failed to set resistor\n"); + return ret; + } + + return 0; +} + +static int __devinit lm3533_als_setup(struct lm3533_als *als, + struct lm3533_als_platform_data *pdata) +{ + int ret; + + ret = lm3533_als_set_input_mode(als, pdata->pwm_mode); + if (ret) + return ret; + + /* ALS input is always high impedance in PWM-mode. */ + if (!pdata->pwm_mode) { + ret = lm3533_als_set_resistor(als, pdata->r_select); + if (ret) + return ret; + } + + return 0; +} + +static int __devinit lm3533_als_setup_irq(struct lm3533_als *als, void *dev) +{ + u8 mask = LM3533_ALS_INT_ENABLE_MASK; + int ret; + + /* Make sure interrupts are disabled. */ + ret = lm3533_update(als->lm3533, LM3533_REG_ALS_ZONE_INFO, 0, mask); + if (ret) { + dev_err(&als->pdev->dev, "failed to disable interrupts\n"); + return ret; + } + + ret = request_threaded_irq(als->irq, NULL, lm3533_als_isr, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + dev_name(&als->pdev->dev), dev); + if (ret) { + dev_err(&als->pdev->dev, "failed to request irq %d\n", + als->irq); + return ret; + } + + return 0; +} + +static int __devinit lm3533_als_enable(struct lm3533_als *als) +{ + u8 mask = LM3533_ALS_ENABLE_MASK; + int ret; + + ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, mask, mask); + if (ret) + dev_err(&als->pdev->dev, "failed to enable ALS\n"); + + return ret; +} + +static int lm3533_als_disable(struct lm3533_als *als) +{ + u8 mask = LM3533_ALS_ENABLE_MASK; + int ret; + + ret = lm3533_update(als->lm3533, LM3533_REG_ALS_CONF, 0, mask); + if (ret) + dev_err(&als->pdev->dev, "failed to disable ALS\n"); + + return ret; +} + +static const struct iio_info lm3533_als_info = { + .attrs = &lm3533_als_attribute_group, + .event_attrs = &lm3533_als_event_attribute_group, + .driver_module = THIS_MODULE, + .read_raw = &lm3533_als_read_raw, +}; + +static int __devinit lm3533_als_probe(struct platform_device *pdev) +{ + struct lm3533 *lm3533; + struct lm3533_als_platform_data *pdata; + struct lm3533_als *als; + struct iio_dev *indio_dev; + int ret; + + lm3533 = dev_get_drvdata(pdev->dev.parent); + if (!lm3533) + return -EINVAL; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "no platform data\n"); + return -EINVAL; + } + + indio_dev = iio_device_alloc(sizeof(*als)); + if (!indio_dev) + return -ENOMEM; + + indio_dev->info = &lm3533_als_info; + indio_dev->channels = lm3533_als_channels; + indio_dev->num_channels = ARRAY_SIZE(lm3533_als_channels); + indio_dev->name = dev_name(&pdev->dev); + indio_dev->dev.parent = pdev->dev.parent; + indio_dev->modes = INDIO_DIRECT_MODE; + + als = iio_priv(indio_dev); + als->lm3533 = lm3533; + als->pdev = pdev; + als->irq = lm3533->irq; + atomic_set(&als->zone, 0); + mutex_init(&als->thresh_mutex); + + platform_set_drvdata(pdev, indio_dev); + + if (als->irq) { + ret = lm3533_als_setup_irq(als, indio_dev); + if (ret) + goto err_free_dev; + } + + ret = lm3533_als_setup(als, pdata); + if (ret) + goto err_free_irq; + + ret = lm3533_als_enable(als); + if (ret) + goto err_free_irq; + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&pdev->dev, "failed to register ALS\n"); + goto err_disable; + } + + return 0; + +err_disable: + lm3533_als_disable(als); +err_free_irq: + if (als->irq) + free_irq(als->irq, indio_dev); +err_free_dev: + iio_device_free(indio_dev); + + return ret; +} + +static int __devexit lm3533_als_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct lm3533_als *als = iio_priv(indio_dev); + + lm3533_als_set_int_mode(indio_dev, false); + iio_device_unregister(indio_dev); + lm3533_als_disable(als); + if (als->irq) + free_irq(als->irq, indio_dev); + iio_device_free(indio_dev); + + return 0; +} + +static struct platform_driver lm3533_als_driver = { + .driver = { + .name = "lm3533-als", + .owner = THIS_MODULE, + }, + .probe = lm3533_als_probe, + .remove = __devexit_p(lm3533_als_remove), +}; +module_platform_driver(lm3533_als_driver); + +MODULE_AUTHOR("Johan Hovold "); +MODULE_DESCRIPTION("LM3533 Ambient Light Sensor driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:lm3533-als"); diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c new file mode 100644 index 0000000000000..e49cb9784a6ff --- /dev/null +++ b/drivers/iio/light/vcnl4000.c @@ -0,0 +1,217 @@ +/* + * vcnl4000.c - Support for Vishay VCNL4000 combined ambient light and + * proximity sensor + * + * Copyright 2012 Peter Meerwald + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * IIO driver for VCNL4000 (7-bit I2C slave address 0x13) + * + * TODO: + * allow to adjust IR current + * proximity threshold and event handling + */ + +#include +#include +#include +#include + +#include +#include + +#define VCNL4000_DRV_NAME "vcnl4000" + +#define VCNL4000_COMMAND 0x80 /* Command register */ +#define VCNL4000_PROD_REV 0x81 /* Product ID and Revision ID */ +#define VCNL4000_LED_CURRENT 0x83 /* IR LED current for proximity mode */ +#define VCNL4000_AL_PARAM 0x84 /* Ambient light parameter register */ +#define VCNL4000_AL_RESULT_HI 0x85 /* Ambient light result register, MSB */ +#define VCNL4000_AL_RESULT_LO 0x86 /* Ambient light result register, LSB */ +#define VCNL4000_PS_RESULT_HI 0x87 /* Proximity result register, MSB */ +#define VCNL4000_PS_RESULT_LO 0x88 /* Proximity result register, LSB */ +#define VCNL4000_PS_MEAS_FREQ 0x89 /* Proximity test signal frequency */ +#define VCNL4000_PS_MOD_ADJ 0x8a /* Proximity modulator timing adjustment */ + +/* Bit masks for COMMAND register */ +#define VCNL4000_AL_RDY 0x40 /* ALS data ready? */ +#define VCNL4000_PS_RDY 0x20 /* proximity data ready? */ +#define VCNL4000_AL_OD 0x10 /* start on-demand ALS measurement */ +#define VCNL4000_PS_OD 0x08 /* start on-demand proximity measurement */ + +struct vcnl4000_data { + struct i2c_client *client; +}; + +static const struct i2c_device_id vcnl4000_id[] = { + { "vcnl4000", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, vcnl4000_id); + +static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, + u8 rdy_mask, u8 data_reg, int *val) +{ + int tries = 20; + u16 buf; + int ret; + + ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, + req_mask); + if (ret < 0) + return ret; + + /* wait for data to become ready */ + while (tries--) { + ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND); + if (ret < 0) + return ret; + if (ret & rdy_mask) + break; + msleep(20); /* measurement takes up to 100 ms */ + } + + if (tries < 0) { + dev_err(&data->client->dev, + "vcnl4000_measure() failed, data not ready\n"); + return -EIO; + } + + ret = i2c_smbus_read_i2c_block_data(data->client, + data_reg, sizeof(buf), (u8 *) &buf); + if (ret < 0) + return ret; + + *val = be16_to_cpu(buf); + + return 0; +} + +static const struct iio_chan_spec vcnl4000_channels[] = { + { + .type = IIO_LIGHT, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, + }, { + .type = IIO_PROXIMITY, + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, + } +}; + +static int vcnl4000_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + int ret = -EINVAL; + struct vcnl4000_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_LIGHT: + ret = vcnl4000_measure(data, + VCNL4000_AL_OD, VCNL4000_AL_RDY, + VCNL4000_AL_RESULT_HI, val); + if (ret < 0) + return ret; + ret = IIO_VAL_INT; + break; + case IIO_PROXIMITY: + ret = vcnl4000_measure(data, + VCNL4000_PS_OD, VCNL4000_PS_RDY, + VCNL4000_PS_RESULT_HI, val); + if (ret < 0) + return ret; + ret = IIO_VAL_INT; + break; + default: + break; + } + break; + case IIO_CHAN_INFO_SCALE: + if (chan->type == IIO_LIGHT) { + *val = 0; + *val2 = 250000; + ret = IIO_VAL_INT_PLUS_MICRO; + } + break; + default: + break; + } + + return ret; +} + +static const struct iio_info vcnl4000_info = { + .read_raw = vcnl4000_read_raw, + .driver_module = THIS_MODULE, +}; + +static int __devinit vcnl4000_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct vcnl4000_data *data; + struct iio_dev *indio_dev; + int ret; + + indio_dev = iio_device_alloc(sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + + ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV); + if (ret < 0) + goto error_free_dev; + + dev_info(&client->dev, "VCNL4000 Ambient light/proximity sensor, Prod %02x, Rev: %02x\n", + ret >> 4, ret & 0xf); + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &vcnl4000_info; + indio_dev->channels = vcnl4000_channels; + indio_dev->num_channels = ARRAY_SIZE(vcnl4000_channels); + indio_dev->name = VCNL4000_DRV_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto error_free_dev; + + return 0; + +error_free_dev: + iio_device_free(indio_dev); + return ret; +} + +static int __devexit vcnl4000_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + iio_device_free(indio_dev); + + return 0; +} + +static struct i2c_driver vcnl4000_driver = { + .driver = { + .name = VCNL4000_DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = vcnl4000_probe, + .remove = __devexit_p(vcnl4000_remove), + .id_table = vcnl4000_id, +}; + +module_i2c_driver(vcnl4000_driver); + +MODULE_AUTHOR("Peter Meerwald "); +MODULE_DESCRIPTION("Vishay VCNL4000 proximity/ambient light sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h new file mode 100644 index 0000000000000..2a2b6b4d8d055 --- /dev/null +++ b/include/linux/iio/buffer.h @@ -0,0 +1,194 @@ +/* The industrial I/O core - generic buffer interfaces. + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#ifndef _IIO_BUFFER_GENERIC_H_ +#define _IIO_BUFFER_GENERIC_H_ +#include +#include + +#ifdef CONFIG_IIO_BUFFER + +struct iio_buffer; + +/** + * struct iio_buffer_access_funcs - access functions for buffers. + * @store_to: actually store stuff to the buffer + * @read_first_n: try to get a specified number of bytes (must exist) + * @request_update: if a parameter change has been marked, update underlying + * storage. + * @get_bytes_per_datum:get current bytes per datum + * @set_bytes_per_datum:set number of bytes per datum + * @get_length: get number of datums in buffer + * @set_length: set number of datums in buffer + * + * The purpose of this structure is to make the buffer element + * modular as event for a given driver, different usecases may require + * different buffer designs (space efficiency vs speed for example). + * + * It is worth noting that a given buffer implementation may only support a + * small proportion of these functions. The core code 'should' cope fine with + * any of them not existing. + **/ +struct iio_buffer_access_funcs { + int (*store_to)(struct iio_buffer *buffer, u8 *data, s64 timestamp); + int (*read_first_n)(struct iio_buffer *buffer, + size_t n, + char __user *buf); + + int (*request_update)(struct iio_buffer *buffer); + + int (*get_bytes_per_datum)(struct iio_buffer *buffer); + int (*set_bytes_per_datum)(struct iio_buffer *buffer, size_t bpd); + int (*get_length)(struct iio_buffer *buffer); + int (*set_length)(struct iio_buffer *buffer, int length); +}; + +/** + * struct iio_buffer - general buffer structure + * @length: [DEVICE] number of datums in buffer + * @bytes_per_datum: [DEVICE] size of individual datum including timestamp + * @scan_el_attrs: [DRIVER] control of scan elements if that scan mode + * control method is used + * @scan_mask: [INTERN] bitmask used in masking scan mode elements + * @scan_timestamp: [INTERN] does the scan mode include a timestamp + * @access: [DRIVER] buffer access functions associated with the + * implementation. + * @scan_el_dev_attr_list:[INTERN] list of scan element related attributes. + * @scan_el_group: [DRIVER] attribute group for those attributes not + * created from the iio_chan_info array. + * @pollq: [INTERN] wait queue to allow for polling on the buffer. + * @stufftoread: [INTERN] flag to indicate new data. + * @demux_list: [INTERN] list of operations required to demux the scan. + * @demux_bounce: [INTERN] buffer for doing gather from incoming scan. + **/ +struct iio_buffer { + int length; + int bytes_per_datum; + struct attribute_group *scan_el_attrs; + long *scan_mask; + bool scan_timestamp; + const struct iio_buffer_access_funcs *access; + struct list_head scan_el_dev_attr_list; + struct attribute_group scan_el_group; + wait_queue_head_t pollq; + bool stufftoread; + const struct attribute_group *attrs; + struct list_head demux_list; + unsigned char *demux_bounce; +}; + +/** + * iio_buffer_init() - Initialize the buffer structure + * @buffer: buffer to be initialized + **/ +void iio_buffer_init(struct iio_buffer *buffer); + +/** + * __iio_update_buffer() - update common elements of buffers + * @buffer: buffer that is the event source + * @bytes_per_datum: size of individual datum including timestamp + * @length: number of datums in buffer + **/ +static inline void __iio_update_buffer(struct iio_buffer *buffer, + int bytes_per_datum, int length) +{ + buffer->bytes_per_datum = bytes_per_datum; + buffer->length = length; +} + +int iio_scan_mask_query(struct iio_dev *indio_dev, + struct iio_buffer *buffer, int bit); + +/** + * iio_scan_mask_set() - set particular bit in the scan mask + * @indio_dev IIO device structure + * @buffer: the buffer whose scan mask we are interested in + * @bit: the bit to be set. + **/ +int iio_scan_mask_set(struct iio_dev *indio_dev, + struct iio_buffer *buffer, int bit); + +/** + * iio_push_to_buffer() - push to a registered buffer. + * @buffer: IIO buffer structure for device + * @data: the data to push to the buffer + * @timestamp: timestamp to associate with the data + */ +int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data, + s64 timestamp); + +int iio_update_demux(struct iio_dev *indio_dev); + +/** + * iio_buffer_register() - register the buffer with IIO core + * @indio_dev: device with the buffer to be registered + * @channels: the channel descriptions used to construct buffer + * @num_channels: the number of channels + **/ +int iio_buffer_register(struct iio_dev *indio_dev, + const struct iio_chan_spec *channels, + int num_channels); + +/** + * iio_buffer_unregister() - unregister the buffer from IIO core + * @indio_dev: the device with the buffer to be unregistered + **/ +void iio_buffer_unregister(struct iio_dev *indio_dev); + +/** + * iio_buffer_read_length() - attr func to get number of datums in the buffer + **/ +ssize_t iio_buffer_read_length(struct device *dev, + struct device_attribute *attr, + char *buf); +/** + * iio_buffer_write_length() - attr func to set number of datums in the buffer + **/ +ssize_t iio_buffer_write_length(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len); +/** + * iio_buffer_store_enable() - attr to turn the buffer on + **/ +ssize_t iio_buffer_store_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len); +/** + * iio_buffer_show_enable() - attr to see if the buffer is on + **/ +ssize_t iio_buffer_show_enable(struct device *dev, + struct device_attribute *attr, + char *buf); +#define IIO_BUFFER_LENGTH_ATTR DEVICE_ATTR(length, S_IRUGO | S_IWUSR, \ + iio_buffer_read_length, \ + iio_buffer_write_length) + +#define IIO_BUFFER_ENABLE_ATTR DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, \ + iio_buffer_show_enable, \ + iio_buffer_store_enable) + +int iio_sw_buffer_preenable(struct iio_dev *indio_dev); + +#else /* CONFIG_IIO_BUFFER */ + +static inline int iio_buffer_register(struct iio_dev *indio_dev, + struct iio_chan_spec *channels, + int num_channels) +{ + return 0; +} + +static inline void iio_buffer_unregister(struct iio_dev *indio_dev) +{} + +#endif /* CONFIG_IIO_BUFFER */ + +#endif /* _IIO_BUFFER_GENERIC_H_ */ diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h new file mode 100644 index 0000000000000..e2657e6d4d26c --- /dev/null +++ b/include/linux/iio/consumer.h @@ -0,0 +1,96 @@ +/* + * Industrial I/O in kernel consumer interface + * + * Copyright (c) 2011 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#ifndef _IIO_INKERN_CONSUMER_H_ +#define _IIO_INKERN_CONSUMER_H +#include + +struct iio_dev; +struct iio_chan_spec; + +/** + * struct iio_channel - everything needed for a consumer to use a channel + * @indio_dev: Device on which the channel exists. + * @channel: Full description of the channel. + */ +struct iio_channel { + struct iio_dev *indio_dev; + const struct iio_chan_spec *channel; +}; + +/** + * iio_channel_get() - get description of all that is needed to access channel. + * @name: Unique name of the device as provided in the iio_map + * with which the desired provider to consumer mapping + * was registered. + * @consumer_channel: Unique name to identify the channel on the consumer + * side. This typically describes the channels use within + * the consumer. E.g. 'battery_voltage' + */ +struct iio_channel *iio_channel_get(const char *name, + const char *consumer_channel); + +/** + * iio_channel_release() - release channels obtained via iio_channel_get + * @chan: The channel to be released. + */ +void iio_channel_release(struct iio_channel *chan); + +/** + * iio_channel_get_all() - get all channels associated with a client + * @name: name of consumer device. + * + * Returns an array of iio_channel structures terminated with one with + * null iio_dev pointer. + * This function is used by fairly generic consumers to get all the + * channels registered as having this consumer. + */ +struct iio_channel *iio_channel_get_all(const char *name); + +/** + * iio_channel_release_all() - reverse iio_channel_get_all + * @chan: Array of channels to be released. + */ +void iio_channel_release_all(struct iio_channel *chan); + +/** + * iio_read_channel_raw() - read from a given channel + * @channel: The channel being queried. + * @val: Value read back. + * + * Note raw reads from iio channels are in adc counts and hence + * scale will need to be applied if standard units required. + */ +int iio_read_channel_raw(struct iio_channel *chan, + int *val); + +/** + * iio_get_channel_type() - get the type of a channel + * @channel: The channel being queried. + * @type: The type of the channel. + * + * returns the enum iio_chan_type of the channel + */ +int iio_get_channel_type(struct iio_channel *channel, + enum iio_chan_type *type); + +/** + * iio_read_channel_scale() - read the scale value for a channel + * @channel: The channel being queried. + * @val: First part of value read back. + * @val2: Second part of value read back. + * + * Note returns a description of what is in val and val2, such + * as IIO_VAL_INT_PLUS_MICRO telling us we have a value of val + * + val2/1e6 + */ +int iio_read_channel_scale(struct iio_channel *chan, int *val, + int *val2); + +#endif diff --git a/include/linux/iio/dac/ad5421.h b/include/linux/iio/dac/ad5421.h new file mode 100644 index 0000000000000..8fd8f057a890b --- /dev/null +++ b/include/linux/iio/dac/ad5421.h @@ -0,0 +1,28 @@ +#ifndef __IIO_DAC_AD5421_H__ +#define __IIO_DAC_AD5421_H__ + +/** + * enum ad5421_current_range - Current range the AD5421 is configured for. + * @AD5421_CURRENT_RANGE_4mA_20mA: 4 mA to 20 mA (RANGE1,0 pins = 00) + * @AD5421_CURRENT_RANGE_3mA8_21mA: 3.8 mA to 21 mA (RANGE1,0 pins = x1) + * @AD5421_CURRENT_RANGE_3mA2_24mA: 3.2 mA to 24 mA (RANGE1,0 pins = 10) + */ + +enum ad5421_current_range { + AD5421_CURRENT_RANGE_4mA_20mA, + AD5421_CURRENT_RANGE_3mA8_21mA, + AD5421_CURRENT_RANGE_3mA2_24mA, +}; + +/** + * struct ad5421_platform_data - AD5421 DAC driver platform data + * @external_vref: whether an external reference voltage is used or not + * @current_range: Current range the AD5421 is configured for + */ + +struct ad5421_platform_data { + bool external_vref; + enum ad5421_current_range current_range; +}; + +#endif diff --git a/include/linux/iio/dac/ad5504.h b/include/linux/iio/dac/ad5504.h new file mode 100644 index 0000000000000..43895376a9cab --- /dev/null +++ b/include/linux/iio/dac/ad5504.h @@ -0,0 +1,16 @@ +/* + * AD5504 SPI DAC driver + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#ifndef SPI_AD5504_H_ +#define SPI_AD5504_H_ + +struct ad5504_platform_data { + u16 vref_mv; +}; + +#endif /* SPI_AD5504_H_ */ diff --git a/include/linux/iio/dac/ad5791.h b/include/linux/iio/dac/ad5791.h new file mode 100644 index 0000000000000..45ee281c6660b --- /dev/null +++ b/include/linux/iio/dac/ad5791.h @@ -0,0 +1,25 @@ +/* + * AD5791 SPI DAC driver + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#ifndef SPI_AD5791_H_ +#define SPI_AD5791_H_ + +/** + * struct ad5791_platform_data - platform specific information + * @vref_pos_mv: Vdd Positive Analog Supply Volatge (mV) + * @vref_neg_mv: Vdd Negative Analog Supply Volatge (mV) + * @use_rbuf_gain2: ext. amplifier connected in gain of two configuration + */ + +struct ad5791_platform_data { + u16 vref_pos_mv; + u16 vref_neg_mv; + bool use_rbuf_gain2; +}; + +#endif /* SPI_AD5791_H_ */ diff --git a/include/linux/iio/dac/max517.h b/include/linux/iio/dac/max517.h new file mode 100644 index 0000000000000..f6d1d252f08d3 --- /dev/null +++ b/include/linux/iio/dac/max517.h @@ -0,0 +1,15 @@ +/* + * MAX517 DAC driver + * + * Copyright 2011 Roland Stigge + * + * Licensed under the GPL-2 or later. + */ +#ifndef IIO_DAC_MAX517_H_ +#define IIO_DAC_MAX517_H_ + +struct max517_platform_data { + u16 vref_mv[2]; +}; + +#endif /* IIO_DAC_MAX517_H_ */ diff --git a/include/linux/iio/dac/mcp4725.h b/include/linux/iio/dac/mcp4725.h new file mode 100644 index 0000000000000..91530e6611e9c --- /dev/null +++ b/include/linux/iio/dac/mcp4725.h @@ -0,0 +1,16 @@ +/* + * MCP4725 DAC driver + * + * Copyright (C) 2012 Peter Meerwald + * + * Licensed under the GPL-2 or later. + */ + +#ifndef IIO_DAC_MCP4725_H_ +#define IIO_DAC_MCP4725_H_ + +struct mcp4725_platform_data { + u16 vref_mv; +}; + +#endif /* IIO_DAC_MCP4725_H_ */ diff --git a/include/linux/iio/driver.h b/include/linux/iio/driver.h new file mode 100644 index 0000000000000..a4f8b2e05af5e --- /dev/null +++ b/include/linux/iio/driver.h @@ -0,0 +1,34 @@ +/* + * Industrial I/O in kernel access map interface. + * + * Copyright (c) 2011 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#ifndef _IIO_INKERN_H_ +#define _IIO_INKERN_H_ + +struct iio_map; + +/** + * iio_map_array_register() - tell the core about inkernel consumers + * @indio_dev: provider device + * @map: array of mappings specifying association of channel with client + */ +int iio_map_array_register(struct iio_dev *indio_dev, + struct iio_map *map); + +/** + * iio_map_array_unregister() - tell the core to remove consumer mappings + * @indio_dev: provider device + * @map: array of mappings to remove. Note these must have same memory + * addresses as those originally added not just equal parameter + * values. + */ +int iio_map_array_unregister(struct iio_dev *indio_dev, + struct iio_map *map); + +#endif diff --git a/include/linux/iio/events.h b/include/linux/iio/events.h new file mode 100644 index 0000000000000..13ce220c70036 --- /dev/null +++ b/include/linux/iio/events.h @@ -0,0 +1,105 @@ +/* The industrial I/O - event passing to userspace + * + * Copyright (c) 2008-2011 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#ifndef _IIO_EVENTS_H_ +#define _IIO_EVENTS_H_ + +#include +#include +#include + +/** + * struct iio_event_data - The actual event being pushed to userspace + * @id: event identifier + * @timestamp: best estimate of time of event occurrence (often from + * the interrupt handler) + */ +struct iio_event_data { + __u64 id; + __s64 timestamp; +}; + +#define IIO_GET_EVENT_FD_IOCTL _IOR('i', 0x90, int) + +enum iio_event_type { + IIO_EV_TYPE_THRESH, + IIO_EV_TYPE_MAG, + IIO_EV_TYPE_ROC, + IIO_EV_TYPE_THRESH_ADAPTIVE, + IIO_EV_TYPE_MAG_ADAPTIVE, +}; + +enum iio_event_direction { + IIO_EV_DIR_EITHER, + IIO_EV_DIR_RISING, + IIO_EV_DIR_FALLING, +}; + +/** + * IIO_EVENT_CODE() - create event identifier + * @chan_type: Type of the channel. Should be one of enum iio_chan_type. + * @diff: Whether the event is for an differential channel or not. + * @modifier: Modifier for the channel. Should be one of enum iio_modifier. + * @direction: Direction of the event. One of enum iio_event_direction. + * @type: Type of the event. Should be one of enum iio_event_type. + * @chan: Channel number for non-differential channels. + * @chan1: First channel number for differential channels. + * @chan2: Second channel number for differential channels. + */ + +#define IIO_EVENT_CODE(chan_type, diff, modifier, direction, \ + type, chan, chan1, chan2) \ + (((u64)type << 56) | ((u64)diff << 55) | \ + ((u64)direction << 48) | ((u64)modifier << 40) | \ + ((u64)chan_type << 32) | (((u16)chan2) << 16) | ((u16)chan1) | \ + ((u16)chan)) + + +#define IIO_EV_DIR_MAX 4 +#define IIO_EV_BIT(type, direction) \ + (1 << (type*IIO_EV_DIR_MAX + direction)) + +/** + * IIO_MOD_EVENT_CODE() - create event identifier for modified channels + * @chan_type: Type of the channel. Should be one of enum iio_chan_type. + * @number: Channel number. + * @modifier: Modifier for the channel. Should be one of enum iio_modifier. + * @type: Type of the event. Should be one of enum iio_event_type. + * @direction: Direction of the event. One of enum iio_event_direction. + */ + +#define IIO_MOD_EVENT_CODE(chan_type, number, modifier, \ + type, direction) \ + IIO_EVENT_CODE(chan_type, 0, modifier, direction, type, number, 0, 0) + +/** + * IIO_UNMOD_EVENT_CODE() - create event identifier for unmodified channels + * @chan_type: Type of the channel. Should be one of enum iio_chan_type. + * @number: Channel number. + * @type: Type of the event. Should be one of enum iio_event_type. + * @direction: Direction of the event. One of enum iio_event_direction. + */ + +#define IIO_UNMOD_EVENT_CODE(chan_type, number, type, direction) \ + IIO_EVENT_CODE(chan_type, 0, 0, direction, type, number, 0, 0) + +#define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF) + +#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0xCF) + +#define IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(mask) ((mask >> 32) & 0xFF) + +/* Event code number extraction depends on which type of event we have. + * Perhaps review this function in the future*/ +#define IIO_EVENT_CODE_EXTRACT_CHAN(mask) ((__s16)(mask & 0xFFFF)) +#define IIO_EVENT_CODE_EXTRACT_CHAN2(mask) ((__s16)(((mask) >> 16) & 0xFFFF)) + +#define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 40) & 0xFF) +#define IIO_EVENT_CODE_EXTRACT_DIFF(mask) (((mask) >> 55) & 0x1) + +#endif diff --git a/include/linux/iio/frequency/ad9523.h b/include/linux/iio/frequency/ad9523.h new file mode 100644 index 0000000000000..12ce3ee427fdd --- /dev/null +++ b/include/linux/iio/frequency/ad9523.h @@ -0,0 +1,195 @@ +/* + * AD9523 SPI Low Jitter Clock Generator + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#ifndef IIO_FREQUENCY_AD9523_H_ +#define IIO_FREQUENCY_AD9523_H_ + +enum outp_drv_mode { + TRISTATE, + LVPECL_8mA, + LVDS_4mA, + LVDS_7mA, + HSTL0_16mA, + HSTL1_8mA, + CMOS_CONF1, + CMOS_CONF2, + CMOS_CONF3, + CMOS_CONF4, + CMOS_CONF5, + CMOS_CONF6, + CMOS_CONF7, + CMOS_CONF8, + CMOS_CONF9 +}; + +enum ref_sel_mode { + NONEREVERTIVE_STAY_ON_REFB, + REVERT_TO_REFA, + SELECT_REFA, + SELECT_REFB, + EXT_REF_SEL +}; + +/** + * struct ad9523_channel_spec - Output channel configuration + * + * @channel_num: Output channel number. + * @divider_output_invert_en: Invert the polarity of the output clock. + * @sync_ignore_en: Ignore chip-level SYNC signal. + * @low_power_mode_en: Reduce power used in the differential output modes. + * @use_alt_clock_src: Channel divider uses alternative clk source. + * @output_dis: Disables, powers down the entire channel. + * @driver_mode: Output driver mode (logic level family). + * @divider_phase: Divider initial phase after a SYNC. Range 0..63 + LSB = 1/2 of a period of the divider input clock. + * @channel_divider: 10-bit channel divider. + * @extended_name: Optional descriptive channel name. + */ + +struct ad9523_channel_spec { + unsigned channel_num; + bool divider_output_invert_en; + bool sync_ignore_en; + bool low_power_mode_en; + /* CH0..CH3 VCXO, CH4..CH9 VCO2 */ + bool use_alt_clock_src; + bool output_dis; + enum outp_drv_mode driver_mode; + unsigned char divider_phase; + unsigned short channel_divider; + char extended_name[16]; +}; + +enum pll1_rzero_resistor { + RZERO_883_OHM, + RZERO_677_OHM, + RZERO_341_OHM, + RZERO_135_OHM, + RZERO_10_OHM, + RZERO_USE_EXT_RES = 8, +}; + +enum rpole2_resistor { + RPOLE2_900_OHM, + RPOLE2_450_OHM, + RPOLE2_300_OHM, + RPOLE2_225_OHM, +}; + +enum rzero_resistor { + RZERO_3250_OHM, + RZERO_2750_OHM, + RZERO_2250_OHM, + RZERO_2100_OHM, + RZERO_3000_OHM, + RZERO_2500_OHM, + RZERO_2000_OHM, + RZERO_1850_OHM, +}; + +enum cpole1_capacitor { + CPOLE1_0_PF, + CPOLE1_8_PF, + CPOLE1_16_PF, + CPOLE1_24_PF, + _CPOLE1_24_PF, /* place holder */ + CPOLE1_32_PF, + CPOLE1_40_PF, + CPOLE1_48_PF, +}; + +/** + * struct ad9523_platform_data - platform specific information + * + * @vcxo_freq: External VCXO frequency in Hz + * @refa_diff_rcv_en: REFA differential/single-ended input selection. + * @refb_diff_rcv_en: REFB differential/single-ended input selection. + * @zd_in_diff_en: Zero Delay differential/single-ended input selection. + * @osc_in_diff_en: OSC differential/ single-ended input selection. + * @refa_cmos_neg_inp_en: REFA single-ended neg./pos. input enable. + * @refb_cmos_neg_inp_en: REFB single-ended neg./pos. input enable. + * @zd_in_cmos_neg_inp_en: Zero Delay single-ended neg./pos. input enable. + * @osc_in_cmos_neg_inp_en: OSC single-ended neg./pos. input enable. + * @refa_r_div: PLL1 10-bit REFA R divider. + * @refb_r_div: PLL1 10-bit REFB R divider. + * @pll1_feedback_div: PLL1 10-bit Feedback N divider. + * @pll1_charge_pump_current_nA: Magnitude of PLL1 charge pump current (nA). + * @zero_delay_mode_internal_en: Internal, external Zero Delay mode selection. + * @osc_in_feedback_en: PLL1 feedback path, local feedback from + * the OSC_IN receiver or zero delay mode + * @pll1_loop_filter_rzero: PLL1 Loop Filter Zero Resistor selection. + * @ref_mode: Reference selection mode. + * @pll2_charge_pump_current_nA: Magnitude of PLL2 charge pump current (nA). + * @pll2_ndiv_a_cnt: PLL2 Feedback N-divider, A Counter, range 0..4. + * @pll2_ndiv_b_cnt: PLL2 Feedback N-divider, B Counter, range 0..63. + * @pll2_freq_doubler_en: PLL2 frequency doubler enable. + * @pll2_r2_div: PLL2 R2 divider, range 0..31. + * @pll2_vco_diff_m1: VCO1 divider, range 3..5. + * @pll2_vco_diff_m2: VCO2 divider, range 3..5. + * @rpole2: PLL2 loop filter Rpole resistor value. + * @rzero: PLL2 loop filter Rzero resistor value. + * @cpole1: PLL2 loop filter Cpole capacitor value. + * @rzero_bypass_en: PLL2 loop filter Rzero bypass enable. + * @num_channels: Array size of struct ad9523_channel_spec. + * @channels: Pointer to channel array. + * @name: Optional alternative iio device name. + */ + +struct ad9523_platform_data { + unsigned long vcxo_freq; + + /* Differential/ Single-Ended Input Configuration */ + bool refa_diff_rcv_en; + bool refb_diff_rcv_en; + bool zd_in_diff_en; + bool osc_in_diff_en; + + /* + * Valid if differential input disabled + * if false defaults to pos input + */ + bool refa_cmos_neg_inp_en; + bool refb_cmos_neg_inp_en; + bool zd_in_cmos_neg_inp_en; + bool osc_in_cmos_neg_inp_en; + + /* PLL1 Setting */ + unsigned short refa_r_div; + unsigned short refb_r_div; + unsigned short pll1_feedback_div; + unsigned short pll1_charge_pump_current_nA; + bool zero_delay_mode_internal_en; + bool osc_in_feedback_en; + enum pll1_rzero_resistor pll1_loop_filter_rzero; + + /* Reference */ + enum ref_sel_mode ref_mode; + + /* PLL2 Setting */ + unsigned int pll2_charge_pump_current_nA; + unsigned char pll2_ndiv_a_cnt; + unsigned char pll2_ndiv_b_cnt; + bool pll2_freq_doubler_en; + unsigned char pll2_r2_div; + unsigned char pll2_vco_diff_m1; /* 3..5 */ + unsigned char pll2_vco_diff_m2; /* 3..5 */ + + /* Loop Filter PLL2 */ + enum rpole2_resistor rpole2; + enum rzero_resistor rzero; + enum cpole1_capacitor cpole1; + bool rzero_bypass_en; + + /* Output Channel Configuration */ + int num_channels; + struct ad9523_channel_spec *channels; + + char name[SPI_NAME_SIZE]; +}; + +#endif /* IIO_FREQUENCY_AD9523_H_ */ diff --git a/include/linux/iio/frequency/adf4350.h b/include/linux/iio/frequency/adf4350.h new file mode 100644 index 0000000000000..b76b4a87065e3 --- /dev/null +++ b/include/linux/iio/frequency/adf4350.h @@ -0,0 +1,126 @@ +/* + * ADF4350/ADF4351 SPI PLL driver + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#ifndef IIO_PLL_ADF4350_H_ +#define IIO_PLL_ADF4350_H_ + +/* Registers */ +#define ADF4350_REG0 0 +#define ADF4350_REG1 1 +#define ADF4350_REG2 2 +#define ADF4350_REG3 3 +#define ADF4350_REG4 4 +#define ADF4350_REG5 5 + +/* REG0 Bit Definitions */ +#define ADF4350_REG0_FRACT(x) (((x) & 0xFFF) << 3) +#define ADF4350_REG0_INT(x) (((x) & 0xFFFF) << 15) + +/* REG1 Bit Definitions */ +#define ADF4350_REG1_MOD(x) (((x) & 0xFFF) << 3) +#define ADF4350_REG1_PHASE(x) (((x) & 0xFFF) << 15) +#define ADF4350_REG1_PRESCALER (1 << 27) + +/* REG2 Bit Definitions */ +#define ADF4350_REG2_COUNTER_RESET_EN (1 << 3) +#define ADF4350_REG2_CP_THREESTATE_EN (1 << 4) +#define ADF4350_REG2_POWER_DOWN_EN (1 << 5) +#define ADF4350_REG2_PD_POLARITY_POS (1 << 6) +#define ADF4350_REG2_LDP_6ns (1 << 7) +#define ADF4350_REG2_LDP_10ns (0 << 7) +#define ADF4350_REG2_LDF_FRACT_N (0 << 8) +#define ADF4350_REG2_LDF_INT_N (1 << 8) +#define ADF4350_REG2_CHARGE_PUMP_CURR_uA(x) (((((x)-312) / 312) & 0xF) << 9) +#define ADF4350_REG2_DOUBLE_BUFF_EN (1 << 13) +#define ADF4350_REG2_10BIT_R_CNT(x) ((x) << 14) +#define ADF4350_REG2_RDIV2_EN (1 << 24) +#define ADF4350_REG2_RMULT2_EN (1 << 25) +#define ADF4350_REG2_MUXOUT(x) ((x) << 26) +#define ADF4350_REG2_NOISE_MODE(x) ((x) << 29) +#define ADF4350_MUXOUT_THREESTATE 0 +#define ADF4350_MUXOUT_DVDD 1 +#define ADF4350_MUXOUT_GND 2 +#define ADF4350_MUXOUT_R_DIV_OUT 3 +#define ADF4350_MUXOUT_N_DIV_OUT 4 +#define ADF4350_MUXOUT_ANALOG_LOCK_DETECT 5 +#define ADF4350_MUXOUT_DIGITAL_LOCK_DETECT 6 + +/* REG3 Bit Definitions */ +#define ADF4350_REG3_12BIT_CLKDIV(x) ((x) << 3) +#define ADF4350_REG3_12BIT_CLKDIV_MODE(x) ((x) << 16) +#define ADF4350_REG3_12BIT_CSR_EN (1 << 18) +#define ADF4351_REG3_CHARGE_CANCELLATION_EN (1 << 21) +#define ADF4351_REG3_ANTI_BACKLASH_3ns_EN (1 << 22) +#define ADF4351_REG3_BAND_SEL_CLOCK_MODE_HIGH (1 << 23) + +/* REG4 Bit Definitions */ +#define ADF4350_REG4_OUTPUT_PWR(x) ((x) << 3) +#define ADF4350_REG4_RF_OUT_EN (1 << 5) +#define ADF4350_REG4_AUX_OUTPUT_PWR(x) ((x) << 6) +#define ADF4350_REG4_AUX_OUTPUT_EN (1 << 8) +#define ADF4350_REG4_AUX_OUTPUT_FUND (1 << 9) +#define ADF4350_REG4_AUX_OUTPUT_DIV (0 << 9) +#define ADF4350_REG4_MUTE_TILL_LOCK_EN (1 << 10) +#define ADF4350_REG4_VCO_PWRDOWN_EN (1 << 11) +#define ADF4350_REG4_8BIT_BAND_SEL_CLKDIV(x) ((x) << 12) +#define ADF4350_REG4_RF_DIV_SEL(x) ((x) << 20) +#define ADF4350_REG4_FEEDBACK_DIVIDED (0 << 23) +#define ADF4350_REG4_FEEDBACK_FUND (1 << 23) + +/* REG5 Bit Definitions */ +#define ADF4350_REG5_LD_PIN_MODE_LOW (0 << 22) +#define ADF4350_REG5_LD_PIN_MODE_DIGITAL (1 << 22) +#define ADF4350_REG5_LD_PIN_MODE_HIGH (3 << 22) + +/* Specifications */ +#define ADF4350_MAX_OUT_FREQ 4400000000ULL /* Hz */ +#define ADF4350_MIN_OUT_FREQ 137500000 /* Hz */ +#define ADF4351_MIN_OUT_FREQ 34375000 /* Hz */ +#define ADF4350_MIN_VCO_FREQ 2200000000ULL /* Hz */ +#define ADF4350_MAX_FREQ_45_PRESC 3000000000ULL /* Hz */ +#define ADF4350_MAX_FREQ_PFD 32000000 /* Hz */ +#define ADF4350_MAX_BANDSEL_CLK 125000 /* Hz */ +#define ADF4350_MAX_FREQ_REFIN 250000000 /* Hz */ +#define ADF4350_MAX_MODULUS 4095 + +/** + * struct adf4350_platform_data - platform specific information + * @name: Optional device name. + * @clkin: REFin frequency in Hz. + * @channel_spacing: Channel spacing in Hz (influences MODULUS). + * @power_up_frequency: Optional, If set in Hz the PLL tunes to the desired + * frequency on probe. + * @ref_div_factor: Optional, if set the driver skips dynamic calculation + * and uses this default value instead. + * @ref_doubler_en: Enables reference doubler. + * @ref_div2_en: Enables reference divider. + * @r2_user_settings: User defined settings for ADF4350/1 REGISTER_2. + * @r3_user_settings: User defined settings for ADF4350/1 REGISTER_3. + * @r4_user_settings: User defined settings for ADF4350/1 REGISTER_4. + * @gpio_lock_detect: Optional, if set with a valid GPIO number, + * pll lock state is tested upon read. + * If not used - set to -1. + */ + +struct adf4350_platform_data { + char name[32]; + unsigned long clkin; + unsigned long channel_spacing; + unsigned long long power_up_frequency; + + unsigned short ref_div_factor; /* 10-bit R counter */ + bool ref_doubler_en; + bool ref_div2_en; + + unsigned r2_user_settings; + unsigned r3_user_settings; + unsigned r4_user_settings; + int gpio_lock_detect; +}; + +#endif /* IIO_PLL_ADF4350_H_ */ diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h new file mode 100644 index 0000000000000..2afbb6f01afc1 --- /dev/null +++ b/include/linux/iio/iio.h @@ -0,0 +1,566 @@ + +/* The industrial I/O core + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#ifndef _INDUSTRIAL_IO_H_ +#define _INDUSTRIAL_IO_H_ + +#include +#include +#include +/* IIO TODO LIST */ +/* + * Provide means of adjusting timer accuracy. + * Currently assumes nano seconds. + */ + +enum iio_chan_info_enum { + IIO_CHAN_INFO_RAW = 0, + IIO_CHAN_INFO_PROCESSED, + IIO_CHAN_INFO_SCALE, + IIO_CHAN_INFO_OFFSET, + IIO_CHAN_INFO_CALIBSCALE, + IIO_CHAN_INFO_CALIBBIAS, + IIO_CHAN_INFO_PEAK, + IIO_CHAN_INFO_PEAK_SCALE, + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW, + IIO_CHAN_INFO_AVERAGE_RAW, + IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY, + IIO_CHAN_INFO_SAMP_FREQ, + IIO_CHAN_INFO_FREQUENCY, + IIO_CHAN_INFO_PHASE, + IIO_CHAN_INFO_HARDWAREGAIN, +}; + +#define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2) +#define IIO_CHAN_INFO_SEPARATE_BIT(type) BIT(type*2 + 1) + +#define IIO_CHAN_INFO_RAW_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_RAW) +#define IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PROCESSED) +#define IIO_CHAN_INFO_SCALE_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_SCALE) +#define IIO_CHAN_INFO_SCALE_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_SCALE) +#define IIO_CHAN_INFO_OFFSET_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_OFFSET) +#define IIO_CHAN_INFO_OFFSET_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_OFFSET) +#define IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_CALIBSCALE) +#define IIO_CHAN_INFO_CALIBSCALE_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_CALIBSCALE) +#define IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_CALIBBIAS) +#define IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_CALIBBIAS) +#define IIO_CHAN_INFO_PEAK_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PEAK) +#define IIO_CHAN_INFO_PEAK_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PEAK) +#define IIO_CHAN_INFO_PEAKSCALE_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PEAKSCALE) +#define IIO_CHAN_INFO_PEAKSCALE_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PEAKSCALE) +#define IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT( \ + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW) +#define IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT( \ + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW) +#define IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_AVERAGE_RAW) +#define IIO_CHAN_INFO_AVERAGE_RAW_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_AVERAGE_RAW) +#define IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT( \ + IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) +#define IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT( \ + IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) +#define IIO_CHAN_INFO_SAMP_FREQ_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_SAMP_FREQ) +#define IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_SAMP_FREQ) +#define IIO_CHAN_INFO_FREQUENCY_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_FREQUENCY) +#define IIO_CHAN_INFO_FREQUENCY_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_FREQUENCY) +#define IIO_CHAN_INFO_PHASE_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PHASE) +#define IIO_CHAN_INFO_PHASE_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PHASE) +#define IIO_CHAN_INFO_HARDWAREGAIN_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_HARDWAREGAIN) +#define IIO_CHAN_INFO_HARDWAREGAIN_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_HARDWAREGAIN) + +enum iio_endian { + IIO_CPU, + IIO_BE, + IIO_LE, +}; + +struct iio_chan_spec; +struct iio_dev; + +/** + * struct iio_chan_spec_ext_info - Extended channel info attribute + * @name: Info attribute name + * @shared: Whether this attribute is shared between all channels. + * @read: Read callback for this info attribute, may be NULL. + * @write: Write callback for this info attribute, may be NULL. + * @private: Data private to the driver. + */ +struct iio_chan_spec_ext_info { + const char *name; + bool shared; + ssize_t (*read)(struct iio_dev *, uintptr_t private, + struct iio_chan_spec const *, char *buf); + ssize_t (*write)(struct iio_dev *, uintptr_t private, + struct iio_chan_spec const *, const char *buf, + size_t len); + uintptr_t private; +}; + +/** + * struct iio_enum - Enum channel info attribute + * @items: An array of strings. + * @num_items: Length of the item array. + * @set: Set callback function, may be NULL. + * @get: Get callback function, may be NULL. + * + * The iio_enum struct can be used to implement enum style channel attributes. + * Enum style attributes are those which have a set of strings which map to + * unsigned integer values. The IIO enum helper code takes care of mapping + * between value and string as well as generating a "_available" file which + * contains a list of all available items. The set callback will be called when + * the attribute is updated. The last parameter is the index to the newly + * activated item. The get callback will be used to query the currently active + * item and is supposed to return the index for it. + */ +struct iio_enum { + const char * const *items; + unsigned int num_items; + int (*set)(struct iio_dev *, const struct iio_chan_spec *, unsigned int); + int (*get)(struct iio_dev *, const struct iio_chan_spec *); +}; + +ssize_t iio_enum_available_read(struct iio_dev *indio_dev, + uintptr_t priv, const struct iio_chan_spec *chan, char *buf); +ssize_t iio_enum_read(struct iio_dev *indio_dev, + uintptr_t priv, const struct iio_chan_spec *chan, char *buf); +ssize_t iio_enum_write(struct iio_dev *indio_dev, + uintptr_t priv, const struct iio_chan_spec *chan, const char *buf, + size_t len); + +/** + * IIO_ENUM() - Initialize enum extended channel attribute + * @_name: Attribute name + * @_shared: Whether the attribute is shared between all channels + * @_e: Pointer to a iio_enum struct + * + * This should usually be used together with IIO_ENUM_AVAILABLE() + */ +#define IIO_ENUM(_name, _shared, _e) \ +{ \ + .name = (_name), \ + .shared = (_shared), \ + .read = iio_enum_read, \ + .write = iio_enum_write, \ + .private = (uintptr_t)(_e), \ +} + +/** + * IIO_ENUM_AVAILABLE() - Initialize enum available extended channel attribute + * @_name: Attribute name ("_available" will be appended to the name) + * @_e: Pointer to a iio_enum struct + * + * Creates a read only attribute which list all the available enum items in a + * space separated list. This should usually be used together with IIO_ENUM() + */ +#define IIO_ENUM_AVAILABLE(_name, _e) \ +{ \ + .name = (_name "_available"), \ + .shared = true, \ + .read = iio_enum_available_read, \ + .private = (uintptr_t)(_e), \ +} + +/** + * struct iio_chan_spec - specification of a single channel + * @type: What type of measurement is the channel making. + * @channel: What number do we wish to assign the channel. + * @channel2: If there is a second number for a differential + * channel then this is it. If modified is set then the + * value here specifies the modifier. + * @address: Driver specific identifier. + * @scan_index: Monotonic index to give ordering in scans when read + * from a buffer. + * @scan_type: Sign: 's' or 'u' to specify signed or unsigned + * realbits: Number of valid bits of data + * storage_bits: Realbits + padding + * shift: Shift right by this before masking out + * realbits. + * endianness: little or big endian + * @info_mask: What information is to be exported about this channel. + * This includes calibbias, scale etc. + * @event_mask: What events can this channel produce. + * @ext_info: Array of extended info attributes for this channel. + * The array is NULL terminated, the last element should + * have its name field set to NULL. + * @extend_name: Allows labeling of channel attributes with an + * informative name. Note this has no effect codes etc, + * unlike modifiers. + * @datasheet_name: A name used in in-kernel mapping of channels. It should + * correspond to the first name that the channel is referred + * to by in the datasheet (e.g. IND), or the nearest + * possible compound name (e.g. IND-INC). + * @modified: Does a modifier apply to this channel. What these are + * depends on the channel type. Modifier is set in + * channel2. Examples are IIO_MOD_X for axial sensors about + * the 'x' axis. + * @indexed: Specify the channel has a numerical index. If not, + * the channel index number will be suppressed for sysfs + * attributes but not for event codes. + * @differential: Channel is differential. + */ +struct iio_chan_spec { + enum iio_chan_type type; + int channel; + int channel2; + unsigned long address; + int scan_index; + struct { + char sign; + u8 realbits; + u8 storagebits; + u8 shift; + enum iio_endian endianness; + } scan_type; + long info_mask; + long event_mask; + const struct iio_chan_spec_ext_info *ext_info; + const char *extend_name; + const char *datasheet_name; + unsigned modified:1; + unsigned indexed:1; + unsigned output:1; + unsigned differential:1; +}; + +#define IIO_ST(si, rb, sb, sh) \ + { .sign = si, .realbits = rb, .storagebits = sb, .shift = sh } + +#define IIO_CHAN_SOFT_TIMESTAMP(_si) \ + { .type = IIO_TIMESTAMP, .channel = -1, \ + .scan_index = _si, .scan_type = IIO_ST('s', 64, 64, 0) } + +/** + * iio_get_time_ns() - utility function to get a time stamp for events etc + **/ +static inline s64 iio_get_time_ns(void) +{ + struct timespec ts; + /* + * calls getnstimeofday. + * If hrtimers then up to ns accurate, if not microsecond. + */ + ktime_get_real_ts(&ts); + + return timespec_to_ns(&ts); +} + +/* Device operating modes */ +#define INDIO_DIRECT_MODE 0x01 +#define INDIO_BUFFER_TRIGGERED 0x02 +#define INDIO_BUFFER_HARDWARE 0x08 + +#define INDIO_ALL_BUFFER_MODES \ + (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE) + +struct iio_trigger; /* forward declaration */ +struct iio_dev; + +/** + * struct iio_info - constant information about device + * @driver_module: module structure used to ensure correct + * ownership of chrdevs etc + * @event_attrs: event control attributes + * @attrs: general purpose device attributes + * @read_raw: function to request a value from the device. + * mask specifies which value. Note 0 means a reading of + * the channel in question. Return value will specify the + * type of value returned by the device. val and val2 will + * contain the elements making up the returned value. + * @write_raw: function to write a value to the device. + * Parameters are the same as for read_raw. + * @write_raw_get_fmt: callback function to query the expected + * format/precision. If not set by the driver, write_raw + * returns IIO_VAL_INT_PLUS_MICRO. + * @read_event_config: find out if the event is enabled. + * @write_event_config: set if the event is enabled. + * @read_event_value: read a value associated with the event. Meaning + * is event dependant. event_code specifies which event. + * @write_event_value: write the value associated with the event. + * Meaning is event dependent. + * @validate_trigger: function to validate the trigger when the + * current trigger gets changed. + **/ +struct iio_info { + struct module *driver_module; + struct attribute_group *event_attrs; + const struct attribute_group *attrs; + + int (*read_raw)(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask); + + int (*write_raw)(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask); + + int (*write_raw_get_fmt)(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask); + + int (*read_event_config)(struct iio_dev *indio_dev, + u64 event_code); + + int (*write_event_config)(struct iio_dev *indio_dev, + u64 event_code, + int state); + + int (*read_event_value)(struct iio_dev *indio_dev, + u64 event_code, + int *val); + int (*write_event_value)(struct iio_dev *indio_dev, + u64 event_code, + int val); + int (*validate_trigger)(struct iio_dev *indio_dev, + struct iio_trigger *trig); + int (*update_scan_mode)(struct iio_dev *indio_dev, + const unsigned long *scan_mask); + int (*debugfs_reg_access)(struct iio_dev *indio_dev, + unsigned reg, unsigned writeval, + unsigned *readval); +}; + +/** + * struct iio_buffer_setup_ops - buffer setup related callbacks + * @preenable: [DRIVER] function to run prior to marking buffer enabled + * @postenable: [DRIVER] function to run after marking buffer enabled + * @predisable: [DRIVER] function to run prior to marking buffer + * disabled + * @postdisable: [DRIVER] function to run after marking buffer disabled + */ +struct iio_buffer_setup_ops { + int (*preenable)(struct iio_dev *); + int (*postenable)(struct iio_dev *); + int (*predisable)(struct iio_dev *); + int (*postdisable)(struct iio_dev *); +}; + +/** + * struct iio_dev - industrial I/O device + * @id: [INTERN] used to identify device internally + * @modes: [DRIVER] operating modes supported by device + * @currentmode: [DRIVER] current operating mode + * @dev: [DRIVER] device structure, should be assigned a parent + * and owner + * @event_interface: [INTERN] event chrdevs associated with interrupt lines + * @buffer: [DRIVER] any buffer present + * @scan_bytes: [INTERN] num bytes captured to be fed to buffer demux + * @mlock: [INTERN] lock used to prevent simultaneous device state + * changes + * @available_scan_masks: [DRIVER] optional array of allowed bitmasks + * @masklength: [INTERN] the length of the mask established from + * channels + * @active_scan_mask: [INTERN] union of all scan masks requested by buffers + * @scan_timestamp: [INTERN] set if any buffers have requested timestamp + * @scan_index_timestamp:[INTERN] cache of the index to the timestamp + * @trig: [INTERN] current device trigger (buffer modes) + * @pollfunc: [DRIVER] function run on trigger being received + * @channels: [DRIVER] channel specification structure table + * @num_channels: [DRIVER] number of channels specified in @channels. + * @channel_attr_list: [INTERN] keep track of automatically created channel + * attributes + * @chan_attr_group: [INTERN] group for all attrs in base directory + * @name: [DRIVER] name of the device. + * @info: [DRIVER] callbacks and constant info from driver + * @info_exist_lock: [INTERN] lock to prevent use during removal + * @setup_ops: [DRIVER] callbacks to call before and after buffer + * enable/disable + * @chrdev: [INTERN] associated character device + * @groups: [INTERN] attribute groups + * @groupcounter: [INTERN] index of next attribute group + * @flags: [INTERN] file ops related flags including busy flag. + * @debugfs_dentry: [INTERN] device specific debugfs dentry. + * @cached_reg_addr: [INTERN] cached register address for debugfs reads. + */ +struct iio_dev { + int id; + + int modes; + int currentmode; + struct device dev; + + struct iio_event_interface *event_interface; + + struct iio_buffer *buffer; + int scan_bytes; + struct mutex mlock; + + const unsigned long *available_scan_masks; + unsigned masklength; + const unsigned long *active_scan_mask; + bool scan_timestamp; + unsigned scan_index_timestamp; + struct iio_trigger *trig; + struct iio_poll_func *pollfunc; + + struct iio_chan_spec const *channels; + int num_channels; + + struct list_head channel_attr_list; + struct attribute_group chan_attr_group; + const char *name; + const struct iio_info *info; + struct mutex info_exist_lock; + const struct iio_buffer_setup_ops *setup_ops; + struct cdev chrdev; +#define IIO_MAX_GROUPS 6 + const struct attribute_group *groups[IIO_MAX_GROUPS + 1]; + int groupcounter; + + unsigned long flags; +#if defined(CONFIG_DEBUG_FS) + struct dentry *debugfs_dentry; + unsigned cached_reg_addr; +#endif +}; + +/** + * iio_find_channel_from_si() - get channel from its scan index + * @indio_dev: device + * @si: scan index to match + */ +const struct iio_chan_spec +*iio_find_channel_from_si(struct iio_dev *indio_dev, int si); + +/** + * iio_device_register() - register a device with the IIO subsystem + * @indio_dev: Device structure filled by the device driver + **/ +int iio_device_register(struct iio_dev *indio_dev); + +/** + * iio_device_unregister() - unregister a device from the IIO subsystem + * @indio_dev: Device structure representing the device. + **/ +void iio_device_unregister(struct iio_dev *indio_dev); + +/** + * iio_push_event() - try to add event to the list for userspace reading + * @indio_dev: IIO device structure + * @ev_code: What event + * @timestamp: When the event occurred + **/ +int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp); + +extern struct bus_type iio_bus_type; + +/** + * iio_device_put() - reference counted deallocation of struct device + * @indio_dev: IIO device structure containing the device + **/ +static inline void iio_device_put(struct iio_dev *indio_dev) +{ + if (indio_dev) + put_device(&indio_dev->dev); +}; + +/** + * dev_to_iio_dev() - Get IIO device struct from a device struct + * @dev: The device embedded in the IIO device + * + * Note: The device must be a IIO device, otherwise the result is undefined. + */ +static inline struct iio_dev *dev_to_iio_dev(struct device *dev) +{ + return container_of(dev, struct iio_dev, dev); +} + +/** + * iio_device_get() - increment reference count for the device + * @indio_dev: IIO device structure + * + * Returns: The passed IIO device + **/ +static inline struct iio_dev *iio_device_get(struct iio_dev *indio_dev) +{ + return indio_dev ? dev_to_iio_dev(get_device(&indio_dev->dev)) : NULL; +} + +/* Can we make this smaller? */ +#define IIO_ALIGN L1_CACHE_BYTES +/** + * iio_device_alloc() - allocate an iio_dev from a driver + * @sizeof_priv: Space to allocate for private structure. + **/ +struct iio_dev *iio_device_alloc(int sizeof_priv); + +static inline void *iio_priv(const struct iio_dev *indio_dev) +{ + return (char *)indio_dev + ALIGN(sizeof(struct iio_dev), IIO_ALIGN); +} + +static inline struct iio_dev *iio_priv_to_dev(void *priv) +{ + return (struct iio_dev *)((char *)priv - + ALIGN(sizeof(struct iio_dev), IIO_ALIGN)); +} + +/** + * iio_device_free() - free an iio_dev from a driver + * @indio_dev: the iio_dev associated with the device + **/ +void iio_device_free(struct iio_dev *indio_dev); + +/** + * iio_buffer_enabled() - helper function to test if the buffer is enabled + * @indio_dev: IIO device structure for device + **/ +static inline bool iio_buffer_enabled(struct iio_dev *indio_dev) +{ + return indio_dev->currentmode + & (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE); +}; + +/** + * iio_get_debugfs_dentry() - helper function to get the debugfs_dentry + * @indio_dev: IIO device structure for device + **/ +#if defined(CONFIG_DEBUG_FS) +static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) +{ + return indio_dev->debugfs_dentry; +}; +#else +static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) +{ + return NULL; +}; +#endif + +#endif /* _INDUSTRIAL_IO_H_ */ diff --git a/include/linux/iio/kfifo_buf.h b/include/linux/iio/kfifo_buf.h new file mode 100644 index 0000000000000..014d5a13b32b5 --- /dev/null +++ b/include/linux/iio/kfifo_buf.h @@ -0,0 +1,8 @@ + +#include +#include +#include + +struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev); +void iio_kfifo_free(struct iio_buffer *r); + diff --git a/include/linux/iio/machine.h b/include/linux/iio/machine.h new file mode 100644 index 0000000000000..400a453ff67be --- /dev/null +++ b/include/linux/iio/machine.h @@ -0,0 +1,24 @@ +/* + * Industrial I/O in kernel access map definitions for board files. + * + * Copyright (c) 2011 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +/** + * struct iio_map - description of link between consumer and device channels + * @adc_channel_label: Label used to identify the channel on the provider. + * This is matched against the datasheet_name element + * of struct iio_chan_spec. + * @consumer_dev_name: Name to uniquely identify the consumer device. + * @consumer_channel: Unique name used to identify the channel on the + * consumer side. + */ +struct iio_map { + const char *adc_channel_label; + const char *consumer_dev_name; + const char *consumer_channel; +}; diff --git a/include/linux/iio/sysfs.h b/include/linux/iio/sysfs.h new file mode 100644 index 0000000000000..b7a934b9431b5 --- /dev/null +++ b/include/linux/iio/sysfs.h @@ -0,0 +1,117 @@ +/* The industrial I/O core + * + *Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * General attributes + */ + +#ifndef _INDUSTRIAL_IO_SYSFS_H_ +#define _INDUSTRIAL_IO_SYSFS_H_ + +struct iio_chan_spec; + +/** + * struct iio_dev_attr - iio specific device attribute + * @dev_attr: underlying device attribute + * @address: associated register address + * @l: list head for maintaining list of dynamically created attrs. + */ +struct iio_dev_attr { + struct device_attribute dev_attr; + u64 address; + struct list_head l; + struct iio_chan_spec const *c; +}; + +#define to_iio_dev_attr(_dev_attr) \ + container_of(_dev_attr, struct iio_dev_attr, dev_attr) + +ssize_t iio_read_const_attr(struct device *dev, + struct device_attribute *attr, + char *len); + +/** + * struct iio_const_attr - constant device specific attribute + * often used for things like available modes + * @string: attribute string + * @dev_attr: underlying device attribute + */ +struct iio_const_attr { + const char *string; + struct device_attribute dev_attr; +}; + +#define to_iio_const_attr(_dev_attr) \ + container_of(_dev_attr, struct iio_const_attr, dev_attr) + +/* Some attributes will be hard coded (device dependent) and not require an + address, in these cases pass a negative */ +#define IIO_ATTR(_name, _mode, _show, _store, _addr) \ + { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .address = _addr } + +#define IIO_DEVICE_ATTR(_name, _mode, _show, _store, _addr) \ + struct iio_dev_attr iio_dev_attr_##_name \ + = IIO_ATTR(_name, _mode, _show, _store, _addr) + +#define IIO_DEVICE_ATTR_NAMED(_vname, _name, _mode, _show, _store, _addr) \ + struct iio_dev_attr iio_dev_attr_##_vname \ + = IIO_ATTR(_name, _mode, _show, _store, _addr) + +#define IIO_CONST_ATTR(_name, _string) \ + struct iio_const_attr iio_const_attr_##_name \ + = { .string = _string, \ + .dev_attr = __ATTR(_name, S_IRUGO, iio_read_const_attr, NULL)} + +#define IIO_CONST_ATTR_NAMED(_vname, _name, _string) \ + struct iio_const_attr iio_const_attr_##_vname \ + = { .string = _string, \ + .dev_attr = __ATTR(_name, S_IRUGO, iio_read_const_attr, NULL)} + +/* Generic attributes of onetype or another */ +/** + * IIO_DEV_ATTR_RESET: resets the device + **/ +#define IIO_DEV_ATTR_RESET(_store) \ + IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, _store, 0) + +/** + * IIO_DEV_ATTR_SAMP_FREQ - sets any internal clock frequency + * @_mode: sysfs file mode/permissions + * @_show: output method for the attribute + * @_store: input method for the attribute + **/ +#define IIO_DEV_ATTR_SAMP_FREQ(_mode, _show, _store) \ + IIO_DEVICE_ATTR(sampling_frequency, _mode, _show, _store, 0) + +/** + * IIO_DEV_ATTR_SAMP_FREQ_AVAIL - list available sampling frequencies + * @_show: output method for the attribute + * + * May be mode dependent on some devices + **/ +#define IIO_DEV_ATTR_SAMP_FREQ_AVAIL(_show) \ + IIO_DEVICE_ATTR(sampling_frequency_available, S_IRUGO, _show, NULL, 0) +/** + * IIO_CONST_ATTR_SAMP_FREQ_AVAIL - list available sampling frequencies + * @_string: frequency string for the attribute + * + * Constant version + **/ +#define IIO_CONST_ATTR_SAMP_FREQ_AVAIL(_string) \ + IIO_CONST_ATTR(sampling_frequency_available, _string) + +#define IIO_DEV_ATTR_TEMP_RAW(_show) \ + IIO_DEVICE_ATTR(in_temp_raw, S_IRUGO, _show, NULL, 0) + +#define IIO_CONST_ATTR_TEMP_OFFSET(_string) \ + IIO_CONST_ATTR(in_temp_offset, _string) + +#define IIO_CONST_ATTR_TEMP_SCALE(_string) \ + IIO_CONST_ATTR(in_temp_scale, _string) + +#endif /* _INDUSTRIAL_IO_SYSFS_H_ */ diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h new file mode 100644 index 0000000000000..a9819940a84c6 --- /dev/null +++ b/include/linux/iio/trigger.h @@ -0,0 +1,119 @@ +/* The industrial I/O core, trigger handling functions + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#include +#include + +#ifndef _IIO_TRIGGER_H_ +#define _IIO_TRIGGER_H_ + +struct iio_subirq { + bool enabled; +}; + +/** + * struct iio_trigger_ops - operations structure for an iio_trigger. + * @owner: used to monitor usage count of the trigger. + * @set_trigger_state: switch on/off the trigger on demand + * @try_reenable: function to reenable the trigger when the + * use count is zero (may be NULL) + * @validate_device: function to validate the device when the + * current trigger gets changed. + * + * This is typically static const within a driver and shared by + * instances of a given device. + **/ +struct iio_trigger_ops { + struct module *owner; + int (*set_trigger_state)(struct iio_trigger *trig, bool state); + int (*try_reenable)(struct iio_trigger *trig); + int (*validate_device)(struct iio_trigger *trig, + struct iio_dev *indio_dev); +}; + + +/** + * struct iio_trigger - industrial I/O trigger device + * + * @id: [INTERN] unique id number + * @name: [DRIVER] unique name + * @dev: [DRIVER] associated device (if relevant) + * @private_data: [DRIVER] device specific data + * @list: [INTERN] used in maintenance of global trigger list + * @alloc_list: [DRIVER] used for driver specific trigger list + * @use_count: use count for the trigger + * @subirq_chip: [INTERN] associate 'virtual' irq chip. + * @subirq_base: [INTERN] base number for irqs provided by trigger. + * @subirqs: [INTERN] information about the 'child' irqs. + * @pool: [INTERN] bitmap of irqs currently in use. + * @pool_lock: [INTERN] protection of the irq pool. + **/ +struct iio_trigger { + const struct iio_trigger_ops *ops; + int id; + const char *name; + struct device dev; + + void *private_data; + struct list_head list; + struct list_head alloc_list; + int use_count; + + struct irq_chip subirq_chip; + int subirq_base; + + struct iio_subirq subirqs[CONFIG_IIO_CONSUMERS_PER_TRIGGER]; + unsigned long pool[BITS_TO_LONGS(CONFIG_IIO_CONSUMERS_PER_TRIGGER)]; + struct mutex pool_lock; +}; + + +static inline struct iio_trigger *to_iio_trigger(struct device *d) +{ + return container_of(d, struct iio_trigger, dev); +}; + +static inline void iio_trigger_put(struct iio_trigger *trig) +{ + module_put(trig->ops->owner); + put_device(&trig->dev); +}; + +static inline void iio_trigger_get(struct iio_trigger *trig) +{ + get_device(&trig->dev); + __module_get(trig->ops->owner); +}; + +/** + * iio_trigger_register() - register a trigger with the IIO core + * @trig_info: trigger to be registered + **/ +int iio_trigger_register(struct iio_trigger *trig_info); + +/** + * iio_trigger_unregister() - unregister a trigger from the core + * @trig_info: trigger to be unregistered + **/ +void iio_trigger_unregister(struct iio_trigger *trig_info); + +/** + * iio_trigger_poll() - called on a trigger occurring + * @trig: trigger which occurred + * + * Typically called in relevant hardware interrupt handler. + **/ +void iio_trigger_poll(struct iio_trigger *trig, s64 time); +void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time); + +irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private); + +__printf(1, 2) struct iio_trigger *iio_trigger_alloc(const char *fmt, ...); +void iio_trigger_free(struct iio_trigger *trig); + +#endif /* _IIO_TRIGGER_H_ */ diff --git a/include/linux/iio/trigger_consumer.h b/include/linux/iio/trigger_consumer.h new file mode 100644 index 0000000000000..60d64b3569458 --- /dev/null +++ b/include/linux/iio/trigger_consumer.h @@ -0,0 +1,52 @@ +/* The industrial I/O core, trigger consumer functions + * + * Copyright (c) 2008-2011 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +/** + * struct iio_poll_func - poll function pair + * + * @indio_dev: data specific to device (passed into poll func) + * @h: the function that is actually run on trigger + * @thread: threaded interrupt part + * @type: the type of interrupt (basically if oneshot) + * @name: name used to identify the trigger consumer. + * @irq: the corresponding irq as allocated from the + * trigger pool + * @timestamp: some devices need a timestamp grabbed as soon + * as possible after the trigger - hence handler + * passes it via here. + **/ +struct iio_poll_func { + struct iio_dev *indio_dev; + irqreturn_t (*h)(int irq, void *p); + irqreturn_t (*thread)(int irq, void *p); + int type; + char *name; + int irq; + s64 timestamp; +}; + + +struct iio_poll_func +*iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), + irqreturn_t (*thread)(int irq, void *p), + int type, + struct iio_dev *indio_dev, + const char *fmt, + ...); +void iio_dealloc_pollfunc(struct iio_poll_func *pf); +irqreturn_t iio_pollfunc_store_time(int irq, void *p); + +void iio_trigger_notify_done(struct iio_trigger *trig); + +/* + * Two functions for common case where all that happens is a pollfunc + * is attached and detached from a trigger + */ +int iio_triggered_buffer_postenable(struct iio_dev *indio_dev); +int iio_triggered_buffer_predisable(struct iio_dev *indio_dev); diff --git a/include/linux/iio/triggered_buffer.h b/include/linux/iio/triggered_buffer.h new file mode 100644 index 0000000000000..c378ebec605ec --- /dev/null +++ b/include/linux/iio/triggered_buffer.h @@ -0,0 +1,15 @@ +#ifndef _LINUX_IIO_TRIGGERED_BUFFER_H_ +#define _LINUX_IIO_TRIGGERED_BUFFER_H_ + +#include + +struct iio_dev; +struct iio_buffer_setup_ops; + +int iio_triggered_buffer_setup(struct iio_dev *indio_dev, + irqreturn_t (*pollfunc_bh)(int irq, void *p), + irqreturn_t (*pollfunc_th)(int irq, void *p), + const struct iio_buffer_setup_ops *setup_ops); +void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev); + +#endif diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h new file mode 100644 index 0000000000000..e25040173346c --- /dev/null +++ b/include/linux/iio/types.h @@ -0,0 +1,56 @@ +/* industrial I/O data types needed both in and out of kernel + * + * Copyright (c) 2008 Jonathan Cameron + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#ifndef _IIO_TYPES_H_ +#define _IIO_TYPES_H_ + +enum iio_chan_type { + IIO_VOLTAGE, + IIO_CURRENT, + IIO_POWER, + IIO_ACCEL, + IIO_ANGL_VEL, + IIO_MAGN, + IIO_LIGHT, + IIO_INTENSITY, + IIO_PROXIMITY, + IIO_TEMP, + IIO_INCLI, + IIO_ROT, + IIO_ANGL, + IIO_TIMESTAMP, + IIO_CAPACITANCE, + IIO_ALTVOLTAGE, +}; + +enum iio_modifier { + IIO_NO_MOD, + IIO_MOD_X, + IIO_MOD_Y, + IIO_MOD_Z, + IIO_MOD_X_AND_Y, + IIO_MOD_X_AND_Z, + IIO_MOD_Y_AND_Z, + IIO_MOD_X_AND_Y_AND_Z, + IIO_MOD_X_OR_Y, + IIO_MOD_X_OR_Z, + IIO_MOD_Y_OR_Z, + IIO_MOD_X_OR_Y_OR_Z, + IIO_MOD_LIGHT_BOTH, + IIO_MOD_LIGHT_IR, + IIO_MOD_ROOT_SUM_SQUARED_X_Y, + IIO_MOD_SUM_SQUARED_X_Y_Z, +}; + +#define IIO_VAL_INT 1 +#define IIO_VAL_INT_PLUS_MICRO 2 +#define IIO_VAL_INT_PLUS_NANO 3 +#define IIO_VAL_INT_PLUS_MICRO_DB 4 + +#endif /* _IIO_TYPES_H_ */ From 13df5b7ddc9984a27ced6861d9b0960fd3cde800 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 13 Jul 2012 13:24:41 +0200 Subject: [PATCH 162/261] xcomm: update settings for XCOMM Rev.B Signed-off-by: Michael Hennerich --- arch/arm/mach-zynq/board_zc702.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-zynq/board_zc702.c b/arch/arm/mach-zynq/board_zc702.c index 681a741538113..c6c0156322ee2 100644 --- a/arch/arm/mach-zynq/board_zc702.c +++ b/arch/arm/mach-zynq/board_zc702.c @@ -173,8 +173,7 @@ static struct i2c_board_info __initdata m24c08_board_info[] = { #define SPIBUS_NUM_LPC 0 #if defined(CONFIG_AD9523) || defined(CONFIG_AD9523_MODULE) -#include "../../../../drivers/staging/iio/frequency/ad9523.h" - +#include struct ad9523_channel_spec ad9523_channels[] = { { /* ZD output */ .channel_num = 0, @@ -189,7 +188,7 @@ struct ad9523_channel_spec ad9523_channels[] = { .output_dis = false, }, { /* DAC CLK */ - .channel_num = 1, + .channel_num = 12, .extended_name = "DAC_CLK", .divider_output_invert_en = false, .sync_ignore_en = false, @@ -209,7 +208,7 @@ struct ad9523_channel_spec ad9523_channels[] = { .channel_divider = 4, }, { /* DAC REF CLK */ - .channel_num = 4, + .channel_num = 10, .extended_name = "DAC_REF_CLK", .divider_output_invert_en = false, .sync_ignore_en = false, @@ -239,7 +238,7 @@ struct ad9523_channel_spec ad9523_channels[] = { .channel_divider = 2, }, { /* ADC SYNC */ - .channel_num = 8, + .channel_num = 7, .extended_name = "ADC_SYNC_CLK", .divider_output_invert_en = false, .sync_ignore_en = false, @@ -265,8 +264,8 @@ struct ad9523_platform_data ad9523_pdata_lpc = { .vcxo_freq = 122880000, /* Single-Ended Input Configuration */ - .refa_diff_rcv_en = true, - .refb_diff_rcv_en = false, + .refa_diff_rcv_en = false, + .refb_diff_rcv_en = true, .zd_in_diff_en = true, .osc_in_diff_en = false, .osc_in_cmos_neg_inp_en = true, @@ -281,13 +280,13 @@ struct ad9523_platform_data ad9523_pdata_lpc = { .zero_delay_mode_internal_en = true, #endif .osc_in_feedback_en = false, - .refb_cmos_neg_inp_en = true, + .refa_cmos_neg_inp_en = true, .pll1_loop_filter_rzero = 3, #if defined(CONFIG_ADIXCOMM_SYNC) - .ref_mode = 3, /* 3 ?*/ + .ref_mode = 2, /* 3 ?*/ #else - .ref_mode = 1, /* 3 ?*/ + .ref_mode = 3, /* 3 ?*/ #endif .pll2_charge_pump_current_nA = 420000, @@ -311,7 +310,7 @@ struct ad9523_platform_data ad9523_pdata_lpc = { #endif #if defined(CONFIG_ADF4350) || defined(CONFIG_ADF4350_MODULE) -#include "../../../../drivers/staging/iio/frequency/adf4350.h" +#include static struct adf4350_platform_data adf4350_tx_pdata_lpc = { .name = "adf4351-tx-lpc", .clkin = 122880000, @@ -351,7 +350,7 @@ static struct spi_board_info __initdata xilinx_spipss_0_boardinfo[] = { #endif #if defined(CONFIG_AD9523) || defined(CONFIG_AD9523_MODULE) { - .modalias = "ad9523", + .modalias = "ad9523-1", .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ .bus_num = SPIBUS_NUM_LPC, .chip_select = 3, /* GPIO controlled SSEL */ From 136c9293a08732ef360be0c9c4ca28157bdc22f0 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 13 Jul 2012 13:31:26 +0200 Subject: [PATCH 163/261] zed: xcomm: add config and device tree for Rev.B Signed-off-by: Michael Hennerich --- .../arm/boot/dts/zynq-zc702-adv7511-xcomm.dts | 314 +++ .../arm/configs/xcomm_adv7511_zc702_defconfig | 2456 +++++++++++++++++ 2 files changed, 2770 insertions(+) create mode 100644 arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts create mode 100644 arch/arm/configs/xcomm_adv7511_zc702_defconfig diff --git a/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts b/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts new file mode 100644 index 0000000000000..527f348e68c7d --- /dev/null +++ b/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts @@ -0,0 +1,314 @@ +/dts-v1/; + +/ { + model = "Xilinx Zynq ZC702"; + compatible = "xlnx,zynq-zc702"; + #address-cells = <0x1>; + #size-cells = <0x1>; + interrupt-parent = <0x1>; + + memory { + device_type = "memory"; + reg = <0x000000000 0x40000000>; + }; + chosen { +// bootargs = "console=ttyPS0,115200 root=/dev/ram rw initrd=0x1100000,33M ip=:::::eth0:dhcp earlyprintk"; + bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0 --no-log"; + linux,stdout-path = "/amba@0/uart@E0001000"; + }; + + amba@0 { + compatible = "simple-bus"; + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + + gic: intc@f8f01000 { + interrupt-controller; + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + reg = < 0xf8f01000 0x1000 >, + < 0xf8f00100 0x0100 >; + }; + + uart@e0001000 { + compatible = "xlnx,ps7-uart-1.00.a"; + reg = <0xe0001000 0x1000>; + interrupts = < 0 50 0 >; + interrupt-parent = <&gic>; + clock = <50000000>; + }; + + timer@0xf8001000 { + compatible = "xlnx,ps7-ttc-1.00.a"; + reg = <0xf8001000 0x1000>; + interrupts = <0 10 0>,<0 11 0>,<0 12 0>; + interrupt-parent = <&gic>; +/* clock-frequency = <111111111>;*/ + clock-frequency-timer0 = <133000000>; + clock-frequency-timer1 = <133000000>; + clock-frequency-timer2 = <133000000>; + }; + + swdt@f8005000 { + device_type = "watchdog"; + compatible = "xlnx,ps7-wdt-1.00.a"; + reg = <0xf8005000 0x100>; + }; + + eth@e000b000 { + compatible = "xlnx,ps7-ethernet-1.00.a"; + reg = <0xe000b000 0x1000>; + interrupts = <0 22 0>; + interrupt-parent = <&gic>; + phy-handle = <&phy0>; + #address-cells = <0x1>; + #size-cells = <0x0>; + + phy0: phy@7 { + compatible = "marvell,88e1116r"; + device_type = "ethernet-phy"; + reg = <0x7>; + }; + }; + + gpio: gpio@e000a000 { + compatible = "xlnx,ps7-gpio-1.00.a"; + reg = <0xe000a000 0x1000>; + interrupts = <0 20 0>; + interrupt-parent = <&gic>; + gpio-controller; + #gpio-cells = <2>; + }; + +/* + i2c0: i2c@e0004000 { + compatible = "xlnx,ps7-i2c-1.00.a"; + reg = <0xe0004000 0x1000>; + interrupts = <0 25 0>; + interrupt-parent = <&gic>; + bus-id = <0>; + input-clk = <111111111>; + i2c-clk = <100000>; +*/ + + i2c0: i2c@0 { + compatible = "i2c-gpio"; + gpios = <&gpio 51 0 &gpio 50 0>; + i2c-gpio,delay-us = <5>; + #address-cells = <1>; + #size-cells = <0>; + + mux@74 { + compatible = "pca9548"; + reg = <0x74>; + #address-cells = <1>; + #size-cells = <0>; + i2c_adv7511: i2c@1 { + #size-cells = <0>; + #address-cells = <1>; + reg = <1>; + }; + + i2c@4 { + #size-cells = <0>; + #address-cells = <1>; + reg = <4>; + rtc@51 { + compatible = "rtc8564"; + reg = <0x51>; + }; + }; + i2c@5 { + #size-cells = <0>; + #address-cells = <1>; + reg = <5>; + spi_xcomm0: spi_xcomm0@58 { + #size-cells = <0>; + #address-cells = <1>; + compatible = "spi-xcomm"; + reg = <0x58>; + dac0_ad9122: ad9122@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ad9122"; + reg = <0>; + spi-max-frequency = <10000000>; + }; + adc0_ad9467: ad9467@1 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ad9643"; + reg = <1>; + spi-max-frequency = <10000000>; + }; + + }; + eeprom@50 { + compatible = "at24,24c02"; + reg = <0x50>; + }; + }; + }; + + }; + + sdhci@e0100000 { + compatible = "xlnx,ps7-sdhci-1.00.a"; + reg = <0xe0100000 0x1000>; + interrupts = <0 24 0>; + interrupt-parent = <&gic>; + clock-frequency = <50000000>; + }; + + usb@e0002000 { + compatible = "xlnx,ps7-usb-1.00.a"; + reg = <0xe0002000 0x1000>; + interrupts = <0 21 0>; + interrupt-parent = <&gic>; + dr_mode = "host"; + phy_type = "ulpi"; + }; + + devcfg@f8007000 { + compatible = "xlnx,ps7-dev-cfg-1.00.a"; + reg = <0xf8007000 0x1000>; + interrupts = <0 8 0>; + interrupt-parent = <&gic>; + }; + + axi_dma_0: axidma@40440000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + reg = < 0x40440000 0x1000 >; + xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@40440000 { + compatible = "xlnx,axi-dma-mm2s-channel"; + interrupts = < 0 54 0x4 >; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + }; + }; + + axi_spdif_tx_0: axi-spdif-tx@0x75c00000 { + compatible = "adi,axi-spdif-tx-1.00.a"; + reg = < 0x75c00000 0x1000 >; + clock-frequency = <12288000>; + }; + + axi_vdma_0: axivdma@43000000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-vdma"; + reg = <0x43020000 0x1000>; + xlnx,include-sg = <0x0>; + xlnx,num-fstores = <0x3>; + dma-channel@43000000 { + compatible = "xlnx,axi-vdma-mm2s-channel"; + interrupts = <0 55 0x4>; + xlnx,datawidth = <0x40>; + xlnx,genlock-mode = <0x0>; + xlnx,include-dre = <0x0>; + }; + }; + + cf_adv7x11_core_0: cf-adv7x11-core@6c000000 { + compatible = "adi,cf-adv7x11-core-1.00.a"; + reg = <0x70e00000 0x10000 + 0x79000000 0x10000>; + slave_adapter = <&i2c_adv7511>; + dma-request = <&axi_vdma_0 0>; + }; + + xilinx_pcm_audio: xilinx_pcm_audio { + compatible = "xilinx-pcm-audio"; + dma-request = <&axi_dma_0 0>; + }; + + adv7511_hdmi_snd: adv7511_hdmi_snd { + compatible = "adv7511-hdmi-snd"; + audio-codec = <&i2c_adv7511>; + cpu-dai = <&axi_spdif_tx_0>; + pcm = <&xilinx_pcm_audio>; + }; + + axi_dma_1: axidma@40420000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + reg = < 0x40420000 0x10000 >; + dma-channel@40420000 { + compatible = "xlnx,axi-dma-s2mm-channel"; + interrupts = < 0 56 0x4 >; + xlnx,datawidth = <0x40>; + xlnx,include-dre = <0x0>; + } ; + } ; + + cf_ad9643_core_0: cf-ad9643-core-lpc@79020000 { + compatible = "xlnx,cf-ad9643-core-1.00.a"; + reg = < 0x79020000 0x10000 >; + dma-request = <&axi_dma_1 0>; + spibus-connected = <&adc0_ad9467>; + xlnx,dphase-timeout = <0x8>; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + + axi_dma_2: axidma@40400000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + reg = < 0x40400000 0x10000 >; + dma-channel@40400000 { + compatible = "xlnx,axi-dma-mm2s-channel"; + interrupts = < 0 58 0x4 >; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + } ; + dma-channel@40400030 { + compatible = "xlnx,axi-dma-s2mm-channel"; + interrupts = < 0 59 0x4 >; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + } ; + } ; + + cf_fft_core_0: cf-fft-core@7de00000 { + compatible = "xlnx,cf-fft-core-1.00.a"; + reg = < 0x7de00000 0x10000 >; + dma-request = <&axi_dma_2 0 + &axi_dma_2 1>; + xlnx,dphase-timeout = <0x8>; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + + cf_ad9122_core_0: cf-ad9122-core-lpc@74200000 { + compatible = "xlnx,cf-ad9122-core-2.00.a"; + reg = < 0x74200000 0x10000 >; + spibus-connected = <&dac0_ad9122>; + dac-sample-frequency = <491520000>; + xlnx,dphase-timeout = <0x8>; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + }; +}; diff --git a/arch/arm/configs/xcomm_adv7511_zc702_defconfig b/arch/arm/configs/xcomm_adv7511_zc702_defconfig new file mode 100644 index 0000000000000..f487907c5faca --- /dev/null +++ b/arch/arm/configs/xcomm_adv7511_zc702_defconfig @@ -0,0 +1,2456 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.3.0 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_KTIME_SCALAR=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_LOCKBREAK=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0xffff0000 +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0x0 +CONFIG_GENERIC_BUG=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_HAVE_IRQ_WORK=y +CONFIG_IRQ_WORK=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_HAVE_SPARSE_IRQ=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_IRQ_DOMAIN=y +# CONFIG_SPARSE_IRQ is not set + +# +# RCU Subsystem +# +CONFIG_TREE_PREEMPT_RCU=y +CONFIG_PREEMPT_RCU=y +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_BOOST is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +# CONFIG_INLINE_SPIN_UNLOCK is not set +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +# CONFIG_INLINE_READ_UNLOCK is not set +# CONFIG_INLINE_READ_UNLOCK_BH is not set +# CONFIG_INLINE_READ_UNLOCK_IRQ is not set +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +# CONFIG_INLINE_WRITE_UNLOCK is not set +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_FREEZER is not set + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_PRIMA2 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_PICOXCELL is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_VT8500 is not set +CONFIG_ARCH_ZYNQ=y +# CONFIG_GPIO_PCA953X is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set + +# +# System MMU +# + +# +# Xilinx Specific Options +# +CONFIG_ZYNQ_EARLY_UART1=y +# CONFIG_ZYNQ_EARLY_UART_EP107 is not set +CONFIG_XILINX_FIXED_DEVTREE_ADDR=y +CONFIG_XILINX_L1_PREFETCH=y +CONFIG_XILINX_L2_PREFETCH=y +CONFIG_XILINX_ZED=y +# CONFIG_XILINX_TEST is not set +CONFIG_ZYNQ_DEFAULT_KERNEL=y +# CONFIG_ZYNQ_AMP_CPU0_MASTER is not set +# CONFIG_ZYNQ_AMP_CPU1_SLAVE is not set +# CONFIG_ZYNQ_CPU1_TEST is not set + +# +# Processor Type +# +CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_LPAE is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_ARM_NR_BANKS=8 +CONFIG_CPU_HAS_PMU=y +CONFIG_MULTI_IRQ_HANDLER=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_742230 is not set +# CONFIG_ARM_ERRATA_742231 is not set +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_PL310_ERRATA_753970 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_764369 is not set +# CONFIG_PL310_ERRATA_769419 is not set +CONFIG_ARM_GIC=y +CONFIG_ICST=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y +CONFIG_ISA_DMA_API=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_HAVE_SMP=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_ARM_CPU_TOPOLOGY=y +# CONFIG_SCHED_MC is not set +# CONFIG_SCHED_SMT is not set +CONFIG_HAVE_ARM_SCU=y +CONFIG_HAVE_ARM_TWD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_NR_CPUS=4 +# CONFIG_HOTPLUG_CPU is not set +CONFIG_LOCAL_TIMERS=y +CONFIG_ARCH_NR_GPIO=0 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +CONFIG_HZ=100 +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HW_PERF_EVENTS=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=999999 +# CONFIG_COMPACTION is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_CLEANCACHE is not set +CONFIG_FORCE_MAX_ZONEORDER=15 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +# CONFIG_CC_STACKPROTECTOR is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set + +# +# Boot options +# +CONFIG_USE_OF=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_ARM_APPENDED_DTB is not set +CONFIG_CMDLINE="console=ttyPS0,115200n8 root=/dev/ram rw initrd=0x00800000,16M earlyprintk mtdparts=physmap-flash.0:512K(nor-fsbl),512K(nor-u-boot),5M(nor-linux),9M(nor-user),1M(nor-scratch),-(nor-rootfs)" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_CMDLINE_EXTEND is not set +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_XIP_KERNEL is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_AUTO_ZRELADDR is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_SUSPEND is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_PM_CLK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_ARM_CPU_SUSPEND is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=m +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +CONFIG_VLAN_8021Q=m +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +CONFIG_BQL=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=m +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +# CONFIG_DMA_SHARED_BUFFER is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +# CONFIG_M25PXX_USE_FAST_READ is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_DOCG3 is not set +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +CONFIG_MTD_NAND_XILINX_PSS=y +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_DEVICE=y +CONFIG_OF_GPIO=y +CONFIG_OF_I2C=y +CONFIG_OF_NET=y +CONFIG_OF_SPI=y +CONFIG_OF_MDIO=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=35384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set + +# +# Misc devices +# +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_ATMEL_PWM is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085 is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SI570 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_MII is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set + +# +# CAIF transport drivers +# +CONFIG_ETHERNET=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_ETHOC is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +CONFIG_NET_VENDOR_XILINX=y +CONFIG_XILINX_PS_EMAC=y +CONFIG_XILINX_PS_EMAC_HWTSTAMP=y +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=y +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +CONFIG_MDIO_BITBANG=y +# CONFIG_MDIO_GPIO is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_WLAN is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +CONFIG_INPUT_SPARSEKMAP=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +CONFIG_SERIAL_XILINX_PS_UART=y +CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +CONFIG_XILINX_DEVCFG=y +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_RAMOOPS is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +CONFIG_I2C_MUX_PCA954x=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX_PS is not set +CONFIG_I2C_XILINX=y + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=y +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX_PCI is not set +CONFIG_SPI_XCOMM=y +# CONFIG_SPI_XILINX is not set +CONFIG_SPI_XILINX_PS_QSPI=y +# CONFIG_XILINX_PS_QSPI_USE_DUAL_FLASH is not set +CONFIG_SPI_XILINX_PS_SPI=y +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_XILINX is not set +CONFIG_GPIO_XILINX_PS=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_CORE is not set +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_MPCORE_WATCHDOG is not set +# CONFIG_XILINX_PS_WATCHDOG is not set +# CONFIG_XILINX_SCU_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_S5M_CORE is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_REGULATOR is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +# CONFIG_MEDIA_CONTROLLER is not set +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_COMMON=y +# CONFIG_DVB_CORE is not set +CONFIG_VIDEO_MEDIA=y + +# +# Multimedia drivers +# +# CONFIG_RC_CORE is not set +# CONFIG_MEDIA_ATTACH is not set +CONFIG_MEDIA_TUNER=y +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA827X=y +CONFIG_MEDIA_TUNER_TDA18271=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=y +CONFIG_MEDIA_TUNER_TEA5767=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_XC4000=y +CONFIG_MEDIA_TUNER_MC44S803=y +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_VMALLOC=y +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set + +# +# Encoders, decoders, sensors and other helper chips +# + +# +# Audio decoders, processors and mixers +# +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS5345 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_VP27SMPX is not set + +# +# RDS decoders +# +# CONFIG_VIDEO_SAA6588 is not set + +# +# Video decoders +# +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_SAA7110 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA7191 is not set +# CONFIG_VIDEO_TVP514X is not set +# CONFIG_VIDEO_TVP5150 is not set +# CONFIG_VIDEO_TVP7002 is not set +# CONFIG_VIDEO_VPX3220 is not set + +# +# Video and audio decoders +# +# CONFIG_VIDEO_SAA717X is not set +# CONFIG_VIDEO_CX25840 is not set + +# +# MPEG video encoders +# +# CONFIG_VIDEO_CX2341X is not set + +# +# Video encoders +# +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_ADV7343 is not set +# CONFIG_VIDEO_AK881X is not set + +# +# Camera sensor devices +# +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_TCM825X is not set +# CONFIG_VIDEO_SR030PC30 is not set + +# +# Flash devices +# + +# +# Video improvement chips +# +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set + +# +# Miscelaneous helper chips +# +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_M52790 is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_V4L_USB_DRIVERS=y +CONFIG_USB_VIDEO_CLASS=y +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=y +# CONFIG_USB_M5602 is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GSPCA_BENQ is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_JL2005BCD is not set +# CONFIG_USB_GSPCA_KINECT is not set +# CONFIG_USB_GSPCA_KONICA is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_NW80X is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7302 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SE401 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +# CONFIG_USB_GSPCA_SPCA500 is not set +# CONFIG_USB_GSPCA_SPCA501 is not set +# CONFIG_USB_GSPCA_SPCA505 is not set +# CONFIG_USB_GSPCA_SPCA506 is not set +# CONFIG_USB_GSPCA_SPCA508 is not set +# CONFIG_USB_GSPCA_SPCA561 is not set +# CONFIG_USB_GSPCA_SPCA1528 is not set +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_SQ930X is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_STV0680 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TOPRO is not set +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_VICAM is not set +# CONFIG_USB_GSPCA_XIRLINK_CIT is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_VIDEO_PVRUSB2 is not set +# CONFIG_VIDEO_HDPVR is not set +# CONFIG_VIDEO_EM28XX is not set +# CONFIG_VIDEO_USBVISION is not set +# CONFIG_USB_ET61X251 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_PWC is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +# CONFIG_V4L_PLATFORM_DRIVERS is not set +# CONFIG_V4L_MEM2MEM_DRIVERS is not set +# CONFIG_RADIO_ADAPTERS is not set + +# +# Graphics support +# +CONFIG_DRM=y +CONFIG_DRM_KMS_HELPER=y +CONFIG_DRM_ENCODER_ADV7511=y +CONFIG_DRM_ANALOG=y +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_WMT_GE_ROPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_XILINX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_XYLON is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +# CONFIG_SND_SUPPORT_OLD_API is not set +# CONFIG_SND_VERBOSE_PROCFS is not set +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +# CONFIG_SND_USB is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_DMAENGINE_PCM=y +CONFIG_SND_SOC_XILINX=y +CONFIG_SND_SOC_AXI_SPDIF=y +CONFIG_SND_SOC_ADV7511_HDMI=y +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACRUX is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LOGITECH is not set +CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB_ARCH_HAS_XHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_SUSPEND=y +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_XUSBPS_DR_OF=y +CONFIG_USB_EHCI_XUSBPS=y +# CONFIG_USB_EHCI_MV is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_RENESAS_USBHS is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +CONFIG_USB_GADGET_XUSBPS=y +CONFIG_USB_XUSBPS=y +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +CONFIG_USB_ZERO=m +# CONFIG_USB_ZERO_HNPTEST is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_GPIO_VBUS is not set +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_USB_XUSBPS_OTG=y +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF_XILINX_PS=y +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_WBSD is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +CONFIG_RTC_DRV_PCF8563=y +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_XILINX_DMA=y +# CONFIG_AMBA_PL08X is not set +# CONFIG_DW_DMAC is not set +# CONFIG_TIMB_DMA is not set +# CONFIG_PL330_DMA is not set +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_BALLOON is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_USBIP_CORE is not set +# CONFIG_ECHO is not set +# CONFIG_ASUS_OLED is not set +# CONFIG_RTS5139 is not set +# CONFIG_TRANZPORT is not set +# CONFIG_LINE6_USB is not set + +# +# I2C encoder or helper chips +# +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_SIL164 is not set +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +# CONFIG_IIO_SW_RING is not set +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16204 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_KXSD9 is not set +# CONFIG_LIS3L02DQ is not set +# CONFIG_SCA3000 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7291 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7606 is not set +# CONFIG_AD799X is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_ADT7310 is not set +# CONFIG_ADT7410 is not set +# CONFIG_AD7280 is not set +# CONFIG_CF_AD9467 is not set +# CONFIG_MAX1363 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Amplifiers +# +CONFIG_AD8366=y + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD5686 is not set +# CONFIG_MAX517 is not set + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +CONFIG_AD9523=y +CONFIG_AD9548=y + +# +# Direct Digital Synthesis +# +# CONFIG_AD5930 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_AD9850 is not set +# CONFIG_AD9852 is not set +# CONFIG_AD9910 is not set +# CONFIG_AD9951 is not set +# CONFIG_AD9122_CF is not set + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +CONFIG_ADF4350=y + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16060 is not set +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set + +# +# Light sensors +# +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_TSL2563 is not set +# CONFIG_TSL2583 is not set + +# +# Magnetometer sensors +# +# CONFIG_SENSORS_AK8975 is not set +# CONFIG_SENSORS_HMC5843 is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7753 is not set +# CONFIG_ADE7754 is not set +# CONFIG_ADE7758 is not set +# CONFIG_ADE7759 is not set +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set +# CONFIG_IIO_GPIO_TRIGGER is not set +# CONFIG_IIO_SYSFS_TRIGGER is not set +# CONFIG_IIO_SIMPLE_DUMMY is not set +# CONFIG_XVMALLOC is not set +# CONFIG_ZRAM is not set +# CONFIG_FB_SM7XX is not set +# CONFIG_USB_ENESTORAGE is not set +# CONFIG_BCM_WIMAX is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +# CONFIG_ANDROID is not set +CONFIG_CLKDEV_LOOKUP=y + +# +# Hardware Spinlock drivers +# +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set + +# +# Analog to digital converters +# +# CONFIG_AD7266 is not set +CONFIG_CF_AXI_ADC=y +CONFIG_CF_AXI_FFT=y + +# +# Amplifiers +# + +# +# Light sensors +# +# CONFIG_VCNL4000 is not set + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# + +# +# Direct Digital Synthesis +# +CONFIG_CF_AXI_DDS=y +CONFIG_CF_AXI_DDS_AD9122=y + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# + +# +# Digital to analog converters +# +# CONFIG_MCP4725 is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT23=y +CONFIG_EXT4_FS_XATTR=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=20 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +# CONFIG_PROVE_RCU_REPEATEDLY is not set +# CONFIG_SPARSE_RCU_POINTER is not set +CONFIG_LOCKDEP=y +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_LOCKDEP is not set +CONFIG_TRACE_IRQFLAGS=y +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_CPU_STALL_VERBOSE is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_LKDTM is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +CONFIG_DEBUG_LL=y +CONFIG_DEBUG_LL_UART_NONE=y +# CONFIG_DEBUG_ICEDCC is not set +CONFIG_EARLY_PRINTK=y +# CONFIG_OC_ETM is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_RNG=m +CONFIG_CRYPTO_RNG2=m +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_PCI_IOMAP=y +# CONFIG_CRC_CCITT is not set +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +# CONFIG_CRC8 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set From ece11d773a43223c84c925dd55cce1c81d5a86cc Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 13 Jul 2012 14:36:06 +0200 Subject: [PATCH 164/261] of_spi: add spi-3wire Signed-off-by: Michael Hennerich --- arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts | 1 + drivers/of/of_spi.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts b/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts index 527f348e68c7d..f2659018a9f44 100644 --- a/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts +++ b/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts @@ -140,6 +140,7 @@ #size-cells = <0>; compatible = "ad9643"; reg = <1>; + spi-3wire; spi-max-frequency = <10000000>; }; diff --git a/drivers/of/of_spi.c b/drivers/of/of_spi.c index f3dee01dcd4c0..d9bfaac6f848f 100644 --- a/drivers/of/of_spi.c +++ b/drivers/of/of_spi.c @@ -67,6 +67,9 @@ void of_register_spi_devices(struct spi_master *master) spi->mode |= SPI_CPOL; if (of_find_property(nc, "spi-cs-high", NULL)) spi->mode |= SPI_CS_HIGH; + if (of_find_property(nc, "spi-3wire", NULL)) + spi->mode |= SPI_3WIRE; + /* Device speed */ prop = of_get_property(nc, "spi-max-frequency", &len); From cb2d93906ab1706a4538de9b8943e725899e6f02 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 31 May 2012 10:08:54 +0200 Subject: [PATCH 165/261] DRM: add drm gem cma helper Many embedded drm devices do not have a IOMMU and no dedicated memory for graphics. These devices use cma (Contiguous Memory Allocator) backed graphics memory. This patch provides helper functions to be able to share the code. Signed-off-by: Sascha Hauer --- drivers/gpu/drm/Kconfig | 6 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/drm_gem_cma_helper.c | 251 +++++++++++++++++++++++++++ include/drm/drm_gem_cma_helper.h | 44 +++++ 4 files changed, 302 insertions(+) create mode 100644 drivers/gpu/drm/drm_gem_cma_helper.c create mode 100644 include/drm/drm_gem_cma_helper.h diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 86f3f72125b97..41bbd95e5ae59 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -35,6 +35,12 @@ config DRM_TTM GPU memory types. Will be enabled automatically if a device driver uses it. +config DRM_GEM_CMA_HELPER + tristate + depends on DRM + help + Choose this if you need the GEM CMA helper functions + config DRM_TDFX tristate "3dfx Banshee/Voodoo3+" depends on DRM && PCI diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 4cb65096c9d13..6e9e948c3f304 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -15,6 +15,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ drm_trace_points.o drm_global.o drm_usb.o drm-$(CONFIG_COMPAT) += drm_ioc32.o +drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_i2c_helper.o diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c new file mode 100644 index 0000000000000..1aa8fee1e8658 --- /dev/null +++ b/drivers/gpu/drm/drm_gem_cma_helper.c @@ -0,0 +1,251 @@ +/* + * drm gem CMA (contiguous memory allocator) helper functions + * + * Copyright (C) 2012 Sascha Hauer, Pengutronix + * + * Based on Samsung Exynos code + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj) +{ + return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT; +} + +static void drm_gem_cma_buf_destroy(struct drm_device *drm, + struct drm_gem_cma_object *cma_obj) +{ + dma_free_writecombine(drm->dev, cma_obj->base.size, cma_obj->vaddr, + cma_obj->paddr); +} + +/* + * drm_gem_cma_create - allocate an object with the given size + * + * returns a struct drm_gem_cma_object* on success or ERR_PTR values + * on failure. + */ +struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, + unsigned int size) +{ + struct drm_gem_cma_object *cma_obj; + struct drm_gem_object *gem_obj; + int ret; + + size = round_up(size, PAGE_SIZE); + + cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL); + if (!cma_obj) + return ERR_PTR(-ENOMEM); + + cma_obj->vaddr = dma_alloc_writecombine(drm->dev, size, + &cma_obj->paddr, GFP_KERNEL | __GFP_NOWARN); + if (!cma_obj->vaddr) { + dev_err(drm->dev, "failed to allocate buffer with size %d\n", size); + ret = -ENOMEM; + goto err_dma_alloc; + } + + gem_obj = &cma_obj->base; + + ret = drm_gem_object_init(drm, gem_obj, size); + if (ret) + goto err_obj_init; + + ret = drm_gem_create_mmap_offset(gem_obj); + if (ret) + goto err_create_mmap_offset; + + return cma_obj; + +err_create_mmap_offset: + drm_gem_object_release(gem_obj); + +err_obj_init: + drm_gem_cma_buf_destroy(drm, cma_obj); + +err_dma_alloc: + kfree(cma_obj); + + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(drm_gem_cma_create); + +/* + * drm_gem_cma_create_with_handle - allocate an object with the given + * size and create a gem handle on it + * + * returns a struct drm_gem_cma_object* on success or ERR_PTR values + * on failure. + */ +static struct drm_gem_cma_object *drm_gem_cma_create_with_handle( + struct drm_file *file_priv, + struct drm_device *drm, unsigned int size, + unsigned int *handle) +{ + struct drm_gem_cma_object *cma_obj; + struct drm_gem_object *gem_obj; + int ret; + + cma_obj = drm_gem_cma_create(drm, size); + if (IS_ERR(cma_obj)) + return cma_obj; + + gem_obj = &cma_obj->base; + + /* + * allocate a id of idr table where the obj is registered + * and handle has the id what user can see. + */ + ret = drm_gem_handle_create(file_priv, gem_obj, handle); + if (ret) + goto err_handle_create; + + /* drop reference from allocate - handle holds it now. */ + drm_gem_object_unreference_unlocked(gem_obj); + + return cma_obj; + +err_handle_create: + drm_gem_cma_free_object(gem_obj); + + return ERR_PTR(ret); +} + +/* + * drm_gem_cma_free_object - (struct drm_driver)->gem_free_object callback + * function + */ +void drm_gem_cma_free_object(struct drm_gem_object *gem_obj) +{ + struct drm_gem_cma_object *cma_obj; + + if (gem_obj->map_list.map) + drm_gem_free_mmap_offset(gem_obj); + + drm_gem_object_release(gem_obj); + + cma_obj = to_drm_gem_cma_obj(gem_obj); + + drm_gem_cma_buf_destroy(gem_obj->dev, cma_obj); + + kfree(cma_obj); +} +EXPORT_SYMBOL_GPL(drm_gem_cma_free_object); + +/* + * drm_gem_cma_dumb_create - (struct drm_driver)->dumb_create callback + * function + * + * This aligns the pitch and size arguments to the minimum required. wrap + * this into your own function if you need bigger alignment. + */ +int drm_gem_cma_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, struct drm_mode_create_dumb *args) +{ + struct drm_gem_cma_object *cma_obj; + int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); + + if (args->pitch < min_pitch) + args->pitch = min_pitch; + + if (args->size < args->pitch * args->height) + args->size = args->pitch * args->height; + + cma_obj = drm_gem_cma_create_with_handle(file_priv, dev, + args->size, &args->handle); + if (IS_ERR(cma_obj)) + return PTR_ERR(cma_obj); + + return 0; +} +EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create); + +/* + * drm_gem_cma_dumb_map_offset - (struct drm_driver)->dumb_map_offset callback + * function + */ +int drm_gem_cma_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *drm, uint32_t handle, uint64_t *offset) +{ + struct drm_gem_object *gem_obj; + + mutex_lock(&drm->struct_mutex); + + gem_obj = drm_gem_object_lookup(drm, file_priv, handle); + if (!gem_obj) { + dev_err(drm->dev, "failed to lookup gem object\n"); + mutex_unlock(&drm->struct_mutex); + return -EINVAL; + } + + *offset = get_gem_mmap_offset(gem_obj); + + drm_gem_object_unreference(gem_obj); + + mutex_unlock(&drm->struct_mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_map_offset); + +const struct vm_operations_struct drm_gem_cma_vm_ops = { + .open = drm_gem_vm_open, + .close = drm_gem_vm_close, +}; +EXPORT_SYMBOL_GPL(drm_gem_cma_vm_ops); + +/* + * drm_gem_cma_mmap - (struct file_operation)->mmap callback function + */ +int drm_gem_cma_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct drm_gem_object *gem_obj; + struct drm_gem_cma_object *cma_obj; + int ret; + + ret = drm_gem_mmap(filp, vma); + if (ret) + return ret; + + gem_obj = vma->vm_private_data; + cma_obj = to_drm_gem_cma_obj(gem_obj); + + ret = remap_pfn_range(vma, vma->vm_start, cma_obj->paddr >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot); + if (ret) + drm_gem_vm_close(vma); + + return ret; +} +EXPORT_SYMBOL_GPL(drm_gem_cma_mmap); + +/* + * drm_gem_cma_dumb_destroy - (struct drm_driver)->dumb_destroy callback function + */ +int drm_gem_cma_dumb_destroy(struct drm_file *file_priv, + struct drm_device *drm, unsigned int handle) +{ + return drm_gem_handle_delete(file_priv, handle); +} +EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_destroy); diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h new file mode 100644 index 0000000000000..f0f6b1af25adf --- /dev/null +++ b/include/drm/drm_gem_cma_helper.h @@ -0,0 +1,44 @@ +#ifndef __DRM_GEM_CMA_HELPER_H__ +#define __DRM_GEM_CMA_HELPER_H__ + +struct drm_gem_cma_object { + struct drm_gem_object base; + dma_addr_t paddr; + void *vaddr; +}; + +static inline struct drm_gem_cma_object * +to_drm_gem_cma_obj(struct drm_gem_object *gem_obj) +{ + return container_of(gem_obj, struct drm_gem_cma_object, base); +} + +/* free gem object. */ +void drm_gem_cma_free_object(struct drm_gem_object *gem_obj); + +/* create memory region for drm framebuffer. */ +int drm_gem_cma_dumb_create(struct drm_file *file_priv, + struct drm_device *drm, struct drm_mode_create_dumb *args); + +/* map memory region for drm framebuffer to user space. */ +int drm_gem_cma_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *drm, uint32_t handle, uint64_t *offset); + +/* set vm_flags and we can change the vm attribute to other one at here. */ +int drm_gem_cma_mmap(struct file *filp, struct vm_area_struct *vma); + +/* + * destroy memory region allocated. + * - a gem handle and physical memory region pointed by a gem object + * would be released by drm_gem_handle_delete(). + */ +int drm_gem_cma_dumb_destroy(struct drm_file *file_priv, + struct drm_device *drm, unsigned int handle); + +/* allocate physical memory. */ +struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, + unsigned int size); + +extern const struct vm_operations_struct drm_gem_cma_vm_ops; + +#endif /* __DRM_GEM_CMA_HELPER_H__ */ From bc12f24f60df7b53c2b78046721339951a764c58 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 29 May 2012 19:37:08 +0200 Subject: [PATCH 166/261] DRM: Add DRM kms/fb cma helper This patchset introduces a set of helper function for implementing the KMS framebuffer layer for drivers which use the drm gem CMA helper function. Signed-off-by: Lars-Peter Clausen --- Changes since v1: * Some spelling fixes * Add missing kfree in drm_fb_cma_alloc error path * Add multi-plane support --- drivers/gpu/drm/Kconfig | 10 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/drm_fb_cma_helper.c | 396 ++++++++++++++++++++++++++++ include/drm/drm_fb_cma_helper.h | 27 ++ 4 files changed, 434 insertions(+) create mode 100644 drivers/gpu/drm/drm_fb_cma_helper.c create mode 100644 include/drm/drm_fb_cma_helper.h diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 41bbd95e5ae59..e511c9a90eebb 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -41,6 +41,16 @@ config DRM_GEM_CMA_HELPER help Choose this if you need the GEM CMA helper functions +config DRM_KMS_CMA_HELPER + tristate + select DRM_GEM_CMA_HELPER + select DRM_KMS_HELPER + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + help + Choose this if you need the KMS cma helper functions + config DRM_TDFX tristate "3dfx Banshee/Voodoo3+" depends on DRM && PCI diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 6e9e948c3f304..5dcb1a5dbc8a3 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -18,6 +18,7 @@ drm-$(CONFIG_COMPAT) += drm_ioc32.o drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_i2c_helper.o +drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c new file mode 100644 index 0000000000000..453ad6a803353 --- /dev/null +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -0,0 +1,396 @@ +/* + * drm kms/fb cma (contiguous memory allocator) helper functions + * + * Copyright (C) 2012 Analog Device Inc. + * Author: Lars-Peter Clausen + * + * Based on udl_fbdev.c + * Copyright (C) 2012 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +struct drm_fb_cma { + struct drm_framebuffer fb; + struct drm_gem_cma_object *obj[4]; +}; + +struct drm_fbdev_cma { + struct drm_fb_helper fb_helper; + struct drm_fb_cma *fb; +}; + +static inline struct drm_fbdev_cma *to_fbdev_cma(struct drm_fb_helper *helper) +{ + return container_of(helper, struct drm_fbdev_cma, fb_helper); +} + +static inline struct drm_fb_cma *to_fb_cma(struct drm_framebuffer *fb) +{ + return container_of(fb, struct drm_fb_cma, fb); +} + +static void drm_fb_cma_destroy(struct drm_framebuffer *fb) +{ + struct drm_fb_cma *fb_cma = to_fb_cma(fb); + int i; + + for (i = 0; i < 4; i++) { + if (fb_cma->obj[i]) + drm_gem_object_unreference_unlocked(&fb_cma->obj[i]->base); + } + + drm_framebuffer_cleanup(fb); + kfree(fb_cma); +} + +static int drm_fb_cma_create_handle(struct drm_framebuffer *fb, + struct drm_file *file_priv, unsigned int *handle) +{ + struct drm_fb_cma *fb_cma = to_fb_cma(fb); + + return drm_gem_handle_create(file_priv, + &fb_cma->obj[0]->base, handle); +} + +static struct drm_framebuffer_funcs drm_fb_cma_funcs = { + .destroy = drm_fb_cma_destroy, + .create_handle = drm_fb_cma_create_handle, +}; + +static struct drm_fb_cma *drm_fb_cma_alloc(struct drm_device *dev, + struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_cma_object **obj, + unsigned int num_planes) +{ + struct drm_fb_cma *fb_cma; + int ret; + int i; + + fb_cma = kzalloc(sizeof(*fb_cma), GFP_KERNEL); + if (!fb_cma) + return ERR_PTR(-ENOMEM); + + ret = drm_framebuffer_init(dev, &fb_cma->fb, &drm_fb_cma_funcs); + if (ret) { + dev_err(dev->dev, "Failed to initalize framebuffer: %d\n", ret); + kfree(fb_cma); + return ERR_PTR(ret); + } + + drm_helper_mode_fill_fb_struct(&fb_cma->fb, mode_cmd); + + for (i = 0; i < num_planes; i++) + fb_cma->obj[i] = obj[i]; + + return fb_cma; +} + +/** + * drm_fb_cma_create() - (struct drm_mode_config_funcs *)->fb_create callback function + * + * If your hardware has special alignment or pitch requirements these should be + * checked before calling this function. + */ +struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev, + struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd) +{ + struct drm_fb_cma *fb_cma; + struct drm_gem_cma_object *objs[4]; + struct drm_gem_object *obj; + unsigned int min_size; + int ret; + int i; + + for (i = 0; i < drm_format_num_planes(mode_cmd->pixel_format); i++) { + obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[i]); + if (!obj) { + dev_err(dev->dev, "Failed to lookup GEM object\n"); + ret = -ENXIO; + goto err_gem_object_unreference; + } + + min_size = mode_cmd->height * mode_cmd->pitches[i]; + + if (obj->size < min_size) { + drm_gem_object_unreference_unlocked(obj); + ret = -EINVAL; + goto err_gem_object_unreference; + } + objs[i] = to_drm_gem_cma_obj(obj); + } + + fb_cma = drm_fb_cma_alloc(dev, mode_cmd, objs, i); + if (IS_ERR(fb_cma)) { + ret = PTR_ERR(fb_cma); + goto err_gem_object_unreference; + } + + return &fb_cma->fb; + +err_gem_object_unreference: + for (i--; i >= 0; i--) + drm_gem_object_unreference_unlocked(&objs[i]->base); + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(drm_fb_cma_create); + +/** + * drm_fb_cma_get_gem_obj() - Get CMA GEM object for framebuffer + * @fb: The framebuffer + * @plane: Which plane + * + * Return the CMA GEM object for given framebuffer. + * + * This function will usually be called from the CRTC callback functions. + */ +struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb, + unsigned int plane) +{ + struct drm_fb_cma *fb_cma = to_fb_cma(fb); + + if (plane >= 4) + return NULL; + + return fb_cma->obj[plane]; +} +EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj); + +static struct fb_ops drm_fbdev_cma_ops = { + .owner = THIS_MODULE, + .fb_fillrect = sys_fillrect, + .fb_copyarea = sys_copyarea, + .fb_imageblit = sys_imageblit, + .fb_check_var = drm_fb_helper_check_var, + .fb_set_par = drm_fb_helper_set_par, + .fb_blank = drm_fb_helper_blank, + .fb_pan_display = drm_fb_helper_pan_display, + .fb_setcmap = drm_fb_helper_setcmap, +}; + +static int drm_fbdev_cma_create(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + struct drm_fbdev_cma *fbdev_cma = to_fbdev_cma(helper); + struct drm_mode_fb_cmd2 mode_cmd = { 0 }; + struct drm_device *dev = helper->dev; + struct drm_gem_cma_object *obj; + struct drm_framebuffer *fb; + unsigned int bytes_per_pixel; + unsigned long offset; + struct fb_info *fbi; + size_t size; + int ret; + + DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n", + sizes->surface_width, sizes->surface_height, + sizes->surface_bpp); + + bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8); + + mode_cmd.width = sizes->surface_width; + mode_cmd.height = sizes->surface_height; + mode_cmd.pitches[0] = sizes->surface_width * bytes_per_pixel; + mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, + sizes->surface_depth); + + size = mode_cmd.pitches[0] * mode_cmd.height; + obj = drm_gem_cma_create(dev, size); + if (!obj) + return -ENOMEM; + + fbi = framebuffer_alloc(0, dev->dev); + if (!fbi) { + dev_err(dev->dev, "Failed to allocate framebuffer info.\n"); + ret = -ENOMEM; + goto err_drm_gem_cma_free_object; + } + + fbdev_cma->fb = drm_fb_cma_alloc(dev, &mode_cmd, &obj, 1); + if (IS_ERR(fbdev_cma->fb)) { + dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n"); + ret = PTR_ERR(fbdev_cma->fb); + goto err_framebuffer_release; + } + + fb = &fbdev_cma->fb->fb; + helper->fb = fb; + helper->fbdev = fbi; + + fbi->par = helper; + fbi->flags = FBINFO_FLAG_DEFAULT; + fbi->fbops = &drm_fbdev_cma_ops; + + ret = fb_alloc_cmap(&fbi->cmap, 256, 0); + if (ret) { + dev_err(dev->dev, "Failed to allocate color map.\n"); + goto err_drm_fb_cma_destroy; + } + + drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); + drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height); + + offset = fbi->var.xoffset * bytes_per_pixel; + offset += fbi->var.yoffset * fb->pitches[0]; + + dev->mode_config.fb_base = (resource_size_t)obj->paddr; + fbi->screen_base = obj->vaddr + offset; + fbi->fix.smem_start = (unsigned long)(obj->paddr + offset); + fbi->screen_size = size; + fbi->fix.smem_len = size; + + return 0; + +err_drm_fb_cma_destroy: + drm_fb_cma_destroy(fb); +err_framebuffer_release: + framebuffer_release(fbi); +err_drm_gem_cma_free_object: + drm_gem_cma_free_object(&obj->base); + return ret; +} + +static int drm_fbdev_cma_probe(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + int ret = 0; + + if (!helper->fb) { + ret = drm_fbdev_cma_create(helper, sizes); + if (ret < 0) + return ret; + ret = 1; + } + + return ret; +} + +static struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = { + .fb_probe = drm_fbdev_cma_probe, +}; + +/** + * drm_fbdev_cma_init() - Allocate and initializes a drm_fbdev_cma struct + * @dev: DRM device + * @preferred_bpp: Preferred bits per pixel for the device + * @num_crtc: Number of CRTCs + * @max_conn_count: Maximum number of connectors + * + * Returns a newly allocated drm_fbdev_cma struct or a ERR_PTR. + */ +struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev, + unsigned int preferred_bpp, unsigned int num_crtc, + unsigned int max_conn_count) +{ + struct drm_fbdev_cma *fbdev_cma; + struct drm_fb_helper *helper; + int ret; + + fbdev_cma = kzalloc(sizeof(*fbdev_cma), GFP_KERNEL); + if (!fbdev_cma) { + dev_err(dev->dev, "Failed to allocate drm fbdev.\n"); + return ERR_PTR(-ENOMEM); + } + + fbdev_cma->fb_helper.funcs = &drm_fb_cma_helper_funcs; + helper = &fbdev_cma->fb_helper; + + ret = drm_fb_helper_init(dev, helper, num_crtc, max_conn_count); + if (ret < 0) { + dev_err(dev->dev, "Failed to initialize drm fb helper.\n"); + goto err_free; + } + + ret = drm_fb_helper_single_add_all_connectors(helper); + if (ret < 0) { + dev_err(dev->dev, "Failed to add connectors.\n"); + goto err_drm_fb_helper_fini; + + } + + ret = drm_fb_helper_initial_config(helper, preferred_bpp); + if (ret < 0) { + dev_err(dev->dev, "Failed to set inital hw configuration.\n"); + goto err_drm_fb_helper_fini; + } + + return fbdev_cma; + +err_drm_fb_helper_fini: + drm_fb_helper_fini(helper); +err_free: + kfree(fbdev_cma); + + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(drm_fbdev_cma_init); + +/** + * drm_fbdev_cma_fini() - Free drm_fbdev_cma struct + * @fbdev_cma: The drm_fbdev_cma struct + */ +void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma) +{ + if (fbdev_cma->fb_helper.fbdev) { + struct fb_info *info; + int ret; + + info = fbdev_cma->fb_helper.fbdev; + ret = unregister_framebuffer(info); + if (ret < 0) + DRM_DEBUG_KMS("failed unregister_framebuffer()\n"); + + if (info->cmap.len) + fb_dealloc_cmap(&info->cmap); + + framebuffer_release(info); + } + + if (fbdev_cma->fb) + drm_fb_cma_destroy(&fbdev_cma->fb->fb); + + drm_fb_helper_fini(&fbdev_cma->fb_helper); + kfree(fbdev_cma); +} +EXPORT_SYMBOL_GPL(drm_fbdev_cma_fini); + +/** + * drm_fbdev_cma_restore_mode() - Restores initial framebuffer mode + * @fbdev_cma: The drm_fbdev_cma struct, may be NULL + * + * This function is usually called from the DRM drivers lastclose callback. + */ +void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma) +{ + if (fbdev_cma) + drm_fb_helper_restore_fbdev_mode(&fbdev_cma->fb_helper); +} +EXPORT_SYMBOL_GPL(drm_fbdev_cma_restore_mode); + +/** + * drm_fbdev_cma_hotplug_event() - Poll for hotpulug events + * @fbdev_cma: The drm_fbdev_cma struct, may be NULL + * + * This function is usually called from the DRM drivers output_poll_changed + * callback. + */ +void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma) +{ + if (fbdev_cma) + drm_fb_helper_hotplug_event(&fbdev_cma->fb_helper); +} +EXPORT_SYMBOL_GPL(drm_fbdev_cma_hotplug_event); diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h new file mode 100644 index 0000000000000..76c709837543f --- /dev/null +++ b/include/drm/drm_fb_cma_helper.h @@ -0,0 +1,27 @@ +#ifndef __DRM_FB_CMA_HELPER_H__ +#define __DRM_FB_CMA_HELPER_H__ + +struct drm_fbdev_cma; +struct drm_gem_cma_object; + +struct drm_framebuffer; +struct drm_device; +struct drm_file; +struct drm_mode_fb_cmd2; + +struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev, + unsigned int preferred_bpp, unsigned int num_crtc, + unsigned int max_conn_count); +void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma); + +void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma); +void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma); + +struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev, + struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd); + +struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb, + unsigned int plane); + +#endif + From 9a1760dab0fe421285a38dd7aee7c88263352b63 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 5 Jun 2012 16:39:56 +0200 Subject: [PATCH 167/261] DRM: Add quirk for broken YCrCb support During testing we have come across one device which claims to have YCrCb input format support, but mixes up the red and the blue channel. This new quirk allows to disable YCrCb support for certain monitors. Signed-off-by: Lars-Peter Clausen --- drivers/gpu/drm/drm_edid.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 8500a882f8882..a0feac1efcc1a 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -66,6 +66,8 @@ #define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5) /* use +hsync +vsync for detailed mode */ #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) +/* No or broken YCrCb input support */ +#define EDID_QUIRK_NO_YCRCB (1 << 7) struct detailed_mode_closure { struct drm_connector *connector; @@ -120,6 +122,9 @@ static struct edid_quirk { /* Samsung SyncMaster 22[5-6]BW */ { "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 }, { "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 }, + + /* Denon AVR */ + { "DON", 25, EDID_QUIRK_NO_YCRCB }, }; /*** DDC fetch and block validation ***/ @@ -1771,6 +1776,11 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) drm_add_display_info(edid, &connector->display_info); + if (quirks & EDID_QUIRK_NO_YCRCB) { + connector->display_info.color_formats &= + ~(DRM_COLOR_FORMAT_YCRCB444 | DRM_COLOR_FORMAT_YCRCB422); + } + return num_modes; } EXPORT_SYMBOL(drm_add_edid_modes); From 2ad59a65dd27aad07d491b8d2b7f6887ce4444c4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 30 Jan 2012 19:56:52 +0000 Subject: [PATCH 168/261] regmap: Implement managed regmap_init() Save error handling and unwinding code in drivers by providing managed versions of the regmap init functions, simplifying usage. Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-i2c.c | 17 ++++++++++++++ drivers/base/regmap/regmap-spi.c | 17 ++++++++++++++ drivers/base/regmap/regmap.c | 39 ++++++++++++++++++++++++++++++++ include/linux/regmap.h | 8 +++++++ 4 files changed, 81 insertions(+) diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c index 38621ec87c05b..9a3a8c5643892 100644 --- a/drivers/base/regmap/regmap-i2c.c +++ b/drivers/base/regmap/regmap-i2c.c @@ -111,4 +111,21 @@ struct regmap *regmap_init_i2c(struct i2c_client *i2c, } EXPORT_SYMBOL_GPL(regmap_init_i2c); +/** + * devm_regmap_init_i2c(): Initialise managed register map + * + * @i2c: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c, + const struct regmap_config *config) +{ + return devm_regmap_init(&i2c->dev, ®map_i2c, config); +} +EXPORT_SYMBOL_GPL(devm_regmap_init_i2c); + MODULE_LICENSE("GPL"); diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c index 2560658de344d..7c0c35a39c331 100644 --- a/drivers/base/regmap/regmap-spi.c +++ b/drivers/base/regmap/regmap-spi.c @@ -70,4 +70,21 @@ struct regmap *regmap_init_spi(struct spi_device *spi, } EXPORT_SYMBOL_GPL(regmap_init_spi); +/** + * devm_regmap_init_spi(): Initialise register map + * + * @spi: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The map will be automatically freed by the + * device management code. + */ +struct regmap *devm_regmap_init_spi(struct spi_device *spi, + const struct regmap_config *config) +{ + return devm_regmap_init(&spi->dev, ®map_spi, config); +} +EXPORT_SYMBOL_GPL(devm_regmap_init_spi); + MODULE_LICENSE("GPL"); diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 65558034318f3..677aeab24f750 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -258,6 +258,45 @@ struct regmap *regmap_init(struct device *dev, } EXPORT_SYMBOL_GPL(regmap_init); +static void devm_regmap_release(struct device *dev, void *res) +{ + regmap_exit(*(struct regmap **)res); +} + +/** + * devm_regmap_init(): Initialise managed register map + * + * @dev: Device that will be interacted with + * @bus: Bus-specific callbacks to use with device + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. This function should generally not be called + * directly, it should be called by bus-specific init functions. The + * map will be automatically freed by the device management code. + */ +struct regmap *devm_regmap_init(struct device *dev, + const struct regmap_bus *bus, + const struct regmap_config *config) +{ + struct regmap **ptr, *regmap; + + ptr = devres_alloc(devm_regmap_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + regmap = regmap_init(dev, bus, config); + if (!IS_ERR(regmap)) { + *ptr = regmap; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return regmap; +} +EXPORT_SYMBOL_GPL(devm_regmap_init); + /** * regmap_reinit_cache(): Reinitialise the current register cache * diff --git a/include/linux/regmap.h b/include/linux/regmap.h index eb93921cdd302..195db51ec79bc 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -127,6 +127,14 @@ struct regmap *regmap_init_i2c(struct i2c_client *i2c, struct regmap *regmap_init_spi(struct spi_device *dev, const struct regmap_config *config); +struct regmap *devm_regmap_init(struct device *dev, + const struct regmap_bus *bus, + const struct regmap_config *config); +struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c, + const struct regmap_config *config); +struct regmap *devm_regmap_init_spi(struct spi_device *dev, + const struct regmap_config *config); + void regmap_exit(struct regmap *map); int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config); From 7d307a6481f99972f4b7dd871b9421aeb5322e42 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 13 Jul 2012 15:35:38 +0200 Subject: [PATCH 169/261] DRM: adv7511: Sync to latest version --- drivers/gpu/drm/Kconfig | 2 - drivers/gpu/drm/i2c/adv7511.h | 75 ++++++++++++++++++++++------- drivers/gpu/drm/i2c/adv7511_audio.c | 47 +++++++++--------- drivers/gpu/drm/i2c/adv7511_core.c | 74 ++++++++++++++++------------ 4 files changed, 123 insertions(+), 75 deletions(-) diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index e511c9a90eebb..95bdf20ad8420 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -184,8 +184,6 @@ config DRM_ENCODER_ADV7511 select FB_SYS_COPYAREA select FB_SYS_IMAGEBLIT -source "drivers/gpu/drm/analog/Kconfig" - source "drivers/gpu/drm/exynos/Kconfig" source "drivers/gpu/drm/vmwgfx/Kconfig" diff --git a/drivers/gpu/drm/i2c/adv7511.h b/drivers/gpu/drm/i2c/adv7511.h index a80916add627e..ebfc05340f46a 100644 --- a/drivers/gpu/drm/i2c/adv7511.h +++ b/drivers/gpu/drm/i2c/adv7511.h @@ -1,3 +1,11 @@ +/** + * Analog Devices ADV7511 HDMI transmitter driver + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + #ifndef __ADV7511_H__ #define __ADV7511_H__ @@ -15,6 +23,14 @@ #define ADV7511_REG_AUDIO_CONFIG 0x0b #define ADV7511_REG_I2S_CONFIG 0x0c #define ADV7511_REG_I2S_WIDTH 0x0d +#define ADV7511_REG_AUDIO_SUB_SRC0 0x0e +#define ADV7511_REG_AUDIO_SUB_SRC1 0x0f +#define ADV7511_REG_AUDIO_SUB_SRC2 0x10 +#define ADV7511_REG_AUDIO_SUB_SRC3 0x11 +#define ADV7511_REG_AUDIO_CFG1 0x12 +#define ADV7511_REG_AUDIO_CFG2 0x13 +#define ADV7511_REG_AUDIO_CFG3 0x14 +#define ADV7511_REG_I2C_FREQ_ID_CFG 0x15 #define ADV7511_REG_VIDEO_INPUT_CFG1 0x16 #define ADV7511_REG_CSC_UPPER(x) (0x18 + (x) * 2) #define ADV7511_REG_CSC_LOWER(x) (0x19 + (x) * 2) @@ -46,17 +62,18 @@ #define ADV7511_REG_INT(x) (0x96 + (x)) #define ADV7511_REG_INPUT_CLK_DIV 0x9d #define ADV7511_REG_PLL_STATUS 0x9e -#define ADV7511_REG_POWER_DOWN 0xa1 +#define ADV7511_REG_HDMI_POWER 0xa1 #define ADV7511_REG_HDCP_HDMI_CFG 0xaf #define ADV7511_REG_AN(x) (0xb0 + (x)) /* 0xb0 - 0xb7 */ #define ADV7511_REG_HDCP_STATUS 0xb8 #define ADV7511_REG_BCAPS 0xbe #define ADV7511_REG_BKSV(x) (0xc0 + (x)) /* 0xc0 - 0xc3 */ #define ADV7511_REG_EDID_SEGMENT 0xc4 -#define ADV7511_REG_DDC_CONTROLLER_STATUS 0xc8 +#define ADV7511_REG_DDC_STATUS 0xc8 #define ADV7511_REG_EDID_READ_CTRL 0xc9 #define ADV7511_REG_BSTATUS(x) (0xca + (x)) /* 0xca - 0xcb */ #define ADV7511_REG_TIMING_GEN_SEQ 0xd0 +#define ADV7511_REG_POWER2 0xd6 #define ADV7511_REG_HSYNC_PLACEMENT_MSB 0xfa #define ADV7511_REG_SYNC_ADJUSTMENT(x) (0xd7 + (x)) /* 0xd7 - 0xdc */ @@ -133,6 +150,14 @@ #define ADV7511_PACKET_ENABLE_SPARE2 BIT(1) #define ADV7511_PACKET_ENABLE_SPARE1 BIT(0) +#define ADV7511_REG_POWER2_HDP_SRC_MASK 0xc0 +#define ADV7511_REG_POWER2_HDP_SRC_BOTH 0x00 +#define ADV7511_REG_POWER2_HDP_SRC_HDP 0x40 +#define ADV7511_REG_POWER2_HDP_SRC_CEC 0x80 +#define ADV7511_REG_POWER2_HDP_SRC_NONE 0xc0 +#define ADV7511_REG_POWER2_TDMS_ENABLE BIT(4) +#define ADV7511_REG_POWER2_GATE_INPUT_CLK BIT(0) + #define ADV7511_LOW_REFRESH_RATE_NONE 0x0 #define ADV7511_LOW_REFRESH_RATE_24HZ 0x1 #define ADV7511_LOW_REFRESH_RATE_25HZ 0x2 @@ -212,17 +237,6 @@ enum adv7511_input_clock_delay { ADV7511_INPUT_CLOCK_DELAY_PLUS_1600PS = 7, }; -enum adv7511_input_adjust_delay { - ADV7511_INPUT_ADJUST_DELAY_MINUS_1200PS = 0, - ADV7511_INPUT_ADJUST_DELAY_MINUS_800PS = 1, - ADV7511_INPUT_ADJUST_DELAY_MINUS_400PS = 2, - ADV7511_INPUT_ADJUST_DELAY_NONE = 3, - ADV7511_INPUT_ADJUST_DELAY_PLUS_400PS = 4, - ADV7511_INPUT_ADJUST_DELAY_PLUS_800PS = 5, - ADV7511_INPUT_ADJUST_DELAY_PLUS_1200PS = 6, - ADV7511_INPUT_ADJUST_DELAY_INVERT_CLK = 7, -}; - enum adv7511_input_bit_justifiction { ADV7511_INPUT_BIT_JUSTIFICATION_EVENLY = 0, ADV7511_INPUT_BIT_JUSTIFICATION_RIGHT = 1, @@ -235,6 +249,32 @@ enum adv7511_output_format { ADV7511_OUTPUT_FORMAT_YCBCR_444 = 2, }; +enum adv7511_csc_scaling { + ADV7511_CSC_SCALING_1 = 0, + ADV7511_CSC_SCALING_2 = 1, + ADV7511_CSC_SCALING_4 = 2, +}; + +/** + * struct adv7511_video_input_config - Describes adv7511 hardware configuration + * @id: Video input format id + * @input_style: Video input format style + * @sync_pulse: Select the sync pulse + * @clock_delay: Clock delay for the input clock + * @reverse_bitorder: Reverse video input signal bitorder + * @bit_justification: Video input format bit justification + * @up_conversion_first_order_interpolation: + * @input_color_depth: Input video format color depth + * @tmds_clock_inversion: Whether to invert the TDMS clock + * @vsync_polartity_low: Whether the vsync polarity is low + * @hsync_polartity_low: Whether the hsync polarity is low + * @csc_enable: Whether to enable color space conversion + * @csc_scaling_factor: Color space conversion scaling factor + * @csc_coefficents: Color space conversion coefficents + * @output_format: Video output format + * @timing_gen_sequence: + * @hdmi_mode: Whether to use HDMI or DVI output mode + **/ struct adv7511_video_input_config { enum adv7511_input_id id; enum adv7511_input_style input_style; @@ -242,18 +282,19 @@ struct adv7511_video_input_config { enum adv7511_input_clock_delay clock_delay; bool reverse_bitorder; enum adv7511_input_bit_justifiction bit_justification; - bool vsync_polartity_low; - bool hsync_polartity_low; bool up_conversion_first_order_interpolation; enum adv7511_input_color_depth input_color_depth; bool tmds_clock_inversion; + bool vsync_polartity_low; + bool hsync_polartity_low; + bool csc_enable; - int csc_scaling_factor; + enum adv7511_csc_scaling csc_scaling_factor; uint16_t *csc_coefficents; enum adv7511_output_format output_format; - int timing_generation_sequence; + int timing_gen_sequence; bool hdmi_mode; }; diff --git a/drivers/gpu/drm/i2c/adv7511_audio.c b/drivers/gpu/drm/i2c/adv7511_audio.c index 9fb99487ac998..6ca4e7cbe4eb2 100644 --- a/drivers/gpu/drm/i2c/adv7511_audio.c +++ b/drivers/gpu/drm/i2c/adv7511_audio.c @@ -1,3 +1,11 @@ +/** + * Analog Devices ADV7511 HDMI transmitter driver + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + #include #include #include @@ -15,12 +23,8 @@ #include "adv7511.h" -static const DECLARE_TLV_DB_SCALE(adv7511_levelshift_tlv, 0, 100, 0); - static const struct snd_kcontrol_new adv7511_controls[] = { SOC_SINGLE("Master Playback Switch", 0, 0, 0, 0), - SOC_SINGLE_TLV("Master Playback Volume", 0, 0, 45, 0, - adv7511_levelshift_tlv), }; static const struct snd_soc_dapm_widget adv7511_dapm_widgets[] = { @@ -122,10 +126,12 @@ static int adv7511_hw_params(struct snd_pcm_substream *substream, adv7511->f_audio = params_rate(params); adv7511_update_cts_n(adv7511); - - regmap_update_bits(adv7511->regmap, 0x14, 0x0f, len); - regmap_update_bits(adv7511->regmap, 0x15, 0xf0, rate << 4); - +/* + regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG3, + ADV7511_REG_AUDIO_CFG3_LEN_MASK, len); + regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG4, + ADV7511_REG_AUDIO_CFG4_RATE_MASK, rate << 4); +*/ return 0; } @@ -171,7 +177,6 @@ static int adv7511_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - /* clock inversion */ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: invert_clock = 0; @@ -183,9 +188,9 @@ static int adv7511_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - regmap_update_bits(adv7511->regmap, 0x0a, 0x70, audio_source << 4); - regmap_update_bits(adv7511->regmap, 0x0b, BIT(6), invert_clock << 6); - regmap_update_bits(adv7511->regmap, 0x0c, 0x03, i2s_format); + regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_SOURCE, 0x70, audio_source << 4); + regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG, BIT(6), invert_clock << 6); + regmap_update_bits(adv7511->regmap, ADV7511_REG_I2S_CONFIG, 0x03, i2s_format); adv7511->audio_source = audio_source; @@ -203,7 +208,7 @@ static int adv7511_set_bias_level(struct snd_soc_codec *codec, case ADV7511_AUDIO_SOURCE_I2S: break; case ADV7511_AUDIO_SOURCE_SPDIF: - regmap_update_bits(adv7511->regmap, 0x0b, BIT(7), BIT(7)); + regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG, BIT(7), BIT(7)); break; } break; @@ -219,7 +224,7 @@ static int adv7511_set_bias_level(struct snd_soc_codec *codec, } break; case SND_SOC_BIAS_STANDBY: - regmap_update_bits(adv7511->regmap, 0x0b, BIT(7), 0); + regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG, BIT(7), 0); break; case SND_SOC_BIAS_OFF: break; @@ -256,15 +261,12 @@ static struct snd_soc_dai_driver adv7511_dai = { static int adv7511_suspend(struct snd_soc_codec *codec) { - adv7511_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; + return adv7511_set_bias_level(codec, SND_SOC_BIAS_OFF); } static int adv7511_resume(struct snd_soc_codec *codec) { - adv7511_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; + return adv7511_set_bias_level(codec, SND_SOC_BIAS_STANDBY); } static int adv7511_probe(struct snd_soc_codec *codec) @@ -279,9 +281,7 @@ static int adv7511_probe(struct snd_soc_codec *codec) return ret; } - adv7511_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; + return adv7511_set_bias_level(codec, SND_SOC_BIAS_STANDBY); } static int adv7511_remove(struct snd_soc_codec *codec) @@ -297,9 +297,6 @@ static struct snd_soc_codec_driver adv7511_codec_driver = { .resume = adv7511_resume, .set_bias_level = adv7511_set_bias_level, -/* - .controls = adv7511_controls, - .num_controls = ARRAY_SIZE(adv7511_controls),*/ .dapm_widgets = adv7511_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(adv7511_dapm_widgets), .dapm_routes = adv7511_routes, diff --git a/drivers/gpu/drm/i2c/adv7511_core.c b/drivers/gpu/drm/i2c/adv7511_core.c index 096ff90a82df0..d67ec22bfaf7d 100644 --- a/drivers/gpu/drm/i2c/adv7511_core.c +++ b/drivers/gpu/drm/i2c/adv7511_core.c @@ -1,3 +1,10 @@ +/** + * Analog Devices ADV7511 HDMI transmitter driver + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ #include #include @@ -90,6 +97,7 @@ static void adv7511_set_colormap(struct adv7511 *adv7511, bool enable, ADV7511_CSC_UPDATE_MODE, 0); } +#define ADV7511_HDMI_CFG_MODE_MASK 0x2 #define ADV7511_HDMI_CFG_MODE_DVI 0x0 #define ADV7511_HDMI_CFG_MODE_HDMI 0x2 @@ -101,8 +109,8 @@ static void adv7511_set_config(struct drm_encoder *encoder, void *c) bool output_format_422, output_format_ycbcr; unsigned int mode; - adv7511_set_colormap(adv7511, config->csc_enable, config->csc_coefficents, - config->csc_scaling_factor); + adv7511_set_colormap(adv7511, config->csc_enable, + config->csc_coefficents, config->csc_scaling_factor); switch (config->output_format) { case ADV7511_OUTPUT_FORMAT_YCBCR_444: @@ -138,7 +146,8 @@ static void adv7511_set_config(struct drm_encoder *encoder, void *c) break; } - regmap_update_bits(adv7511->regmap, 0x15, 0xf, config->id); + regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG, + 0xf, config->id); regmap_write(adv7511->regmap, ADV7511_REG_VIDEO_INPUT_CFG1, (output_format_422 << 7) | (config->input_color_depth << 4) | @@ -149,9 +158,9 @@ static void adv7511_set_config(struct drm_encoder *encoder, void *c) (config->bit_justification << 3)); regmap_write(adv7511->regmap, ADV7511_REG_TIMING_GEN_SEQ, (sync_pulse << 2) | - (config->timing_generation_sequence << 1)); -/* regmap_write(adv7511->regmap, 0xba, - (config->clock_delay << 5));*/ + (config->timing_gen_sequence << 1)); + regmap_write(adv7511->regmap, 0xba, + (config->clock_delay << 5)); regmap_update_bits(adv7511->regmap, ADV7511_REG_TMDS_CLOCK_INV, 0x08, config->tmds_clock_inversion << 3); @@ -229,7 +238,7 @@ static bool adv7511_register_volatile(struct device *dev, unsigned int reg) case ADV7511_REG_BKSV(2): case ADV7511_REG_BKSV(3): case ADV7511_REG_BKSV(4): - case ADV7511_REG_DDC_CONTROLLER_STATUS: + case ADV7511_REG_DDC_STATUS: case ADV7511_REG_BSTATUS(0): case ADV7511_REG_BSTATUS(1): case ADV7511_REG_CHIP_ID_HIGH: @@ -315,8 +324,8 @@ static int adv7511_wait_for_interrupt(struct adv7511 *adv7511, int irq, int time return pending; } -int adv7511_get_edid_block(void *data, - unsigned char *buf, int block, int len) +static int adv7511_get_edid_block(void *data, unsigned char *buf, + int block, int len) { struct drm_encoder *encoder = data; struct adv7511 *adv7511 = encoder_to_adv7511(encoder); @@ -330,7 +339,10 @@ int adv7511_get_edid_block(void *data, if (adv7511->current_edid_segment != block / 2) { unsigned int status; - regmap_read(adv7511->regmap, 0xc8, &status); + + ret = regmap_read(adv7511->regmap, ADV7511_REG_DDC_STATUS, &status); + if (ret < 0) + return ret; printk("edid status: %x\n", status); if (status != 2) { @@ -437,7 +449,9 @@ static void adv7511_encoder_dpms(struct drm_encoder *encoder, int mode) * avoid this we ignore the HDP pin for the first few seconds * after enabeling the output. */ - regmap_update_bits(adv7511->regmap, 0xd6, 0xc0, 0xc0); + regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2, + ADV7511_REG_POWER2_HDP_SRC_MASK, + ADV7511_REG_POWER2_HDP_SRC_NONE); /* Most of the registers are reset during power down or when HPD is low */ regcache_sync(adv7511->regmap); break; @@ -480,10 +494,12 @@ static enum drm_connector_status adv7511_encoder_detect(struct drm_encoder *enco adv7511->dpms_mode == DRM_MODE_DPMS_ON) { regcache_mark_dirty(adv7511->regmap); adv7511_encoder_dpms(encoder, adv7511->dpms_mode); -/* adv7511_get_modes(encoder, connector);*/ + adv7511_get_modes(encoder, connector); } else { /* Renable HDP sensing */ - regmap_update_bits(adv7511->regmap, 0xd6, 0xc0, 0x0); + regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2, + ADV7511_REG_POWER2_HDP_SRC_MASK, + ADV7511_REG_POWER2_HDP_SRC_BOTH); } adv7511->status = status; @@ -536,16 +552,16 @@ static void adv7511_encoder_mode_set(struct drm_encoder *encoder, /* switch (adv7511->color_mode) { - case COLOR_MODE_30BIT: + case ADV7511_COLOR_MODE_30BIT: adv7511->f_tmds = adv7511->f_tmds * 5 / 4; break; - case COLOR_MODE_36BIT: + case ADV7511_COLOR_MODE_36BIT: adv7511->f_tmds = adv7511->f_tmds * 3 / 2; break; - case COLOR_MODE_48BIT: + case ADV7511_COLOR_MODE_48BIT: adv7511->f_tmds = adv7511->f_tmds * 2; break; - case COLOR_MODE_24BIT: + case ADV7511_COLOR_MODE_24BIT: break; } */ @@ -588,7 +604,7 @@ static int __devinit adv7511_probe(struct i2c_client *i2c, if (!adv7511) return -ENOMEM; - adv7511->regmap = regmap_init_i2c(i2c, &adv7511_regmap_config); + adv7511->regmap = devm_regmap_init_i2c(i2c, &adv7511_regmap_config); if (IS_ERR(adv7511->regmap)) return PTR_ERR(adv7511->regmap); @@ -601,8 +617,8 @@ static int __devinit adv7511_probe(struct i2c_client *i2c, adv7511->i2c_main = i2c; adv7511->i2c_edid = i2c_new_dummy(i2c->adapter, edid_i2c_addr >> 1); - adv7511->i2c_packet = i2c_new_dummy(i2c->adapter, packet_i2c_addr >> 1); - adv7511->i2c_cec = i2c_new_dummy(i2c->adapter, cec_i2c_addr >> 1); + if (!adv7511->i2c_edid) + return -ENOMEM; for (i = 0; i < ARRAY_SIZE(adv7511_fixed_registers); ++i) { regmap_write(adv7511->regmap, adv7511_fixed_registers[i][0], @@ -610,10 +626,10 @@ static int __devinit adv7511_probe(struct i2c_client *i2c, } if (i2c->irq) { - ret = request_threaded_irq(i2c->irq, NULL, adv7511_irq_handler, 0, - dev_name(&i2c->dev), adv7511); + ret = request_threaded_irq(i2c->irq, NULL, adv7511_irq_handler, + IRQF_ONESHOT, dev_name(&i2c->dev), adv7511); if (ret) - goto err_regmap_exit; + goto err_i2c_unregister_device; init_waitqueue_head(&adv7511->wq); } @@ -632,8 +648,8 @@ static int __devinit adv7511_probe(struct i2c_client *i2c, return 0; -err_regmap_exit: - regmap_exit(adv7511->regmap); +err_i2c_unregister_device: + i2c_unregister_device(adv7511->i2c_edid); return ret; } @@ -642,15 +658,11 @@ static int __devexit adv7511_remove(struct i2c_client *i2c) { struct adv7511 *adv7511 = i2c_get_clientdata(i2c); + i2c_unregister_device(adv7511->i2c_edid); + if (i2c->irq) free_irq(i2c->irq, adv7511); - regmap_exit(adv7511->regmap); - - i2c_unregister_device(adv7511->i2c_edid); - i2c_unregister_device(adv7511->i2c_packet); - i2c_unregister_device(adv7511->i2c_cec); - return 0; } From e371ec9e77307c173acda33b049832a68449462f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 13 Jul 2012 15:35:13 +0200 Subject: [PATCH 170/261] DRM: Analog: Sync to latest version --- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/analog/Kconfig | 5 +- drivers/gpu/drm/analog/Makefile | 3 +- drivers/gpu/drm/analog/analog_drm_buf.c | 76 ----- drivers/gpu/drm/analog/analog_drm_crtc.c | 27 +- drivers/gpu/drm/analog/analog_drm_drv.c | 66 ++-- drivers/gpu/drm/analog/analog_drm_drv.h | 4 +- drivers/gpu/drm/analog/analog_drm_encoder.c | 29 +- drivers/gpu/drm/analog/analog_drm_fbdev.c | 338 -------------------- drivers/gpu/drm/analog/analog_drm_fbdev.h | 12 - drivers/gpu/drm/analog/analog_drm_gem.c | 242 -------------- drivers/gpu/drm/analog/analog_drm_gem.h | 52 --- 12 files changed, 80 insertions(+), 776 deletions(-) delete mode 100644 drivers/gpu/drm/analog/analog_drm_buf.c delete mode 100644 drivers/gpu/drm/analog/analog_drm_fbdev.c delete mode 100644 drivers/gpu/drm/analog/analog_drm_fbdev.h delete mode 100644 drivers/gpu/drm/analog/analog_drm_gem.c delete mode 100644 drivers/gpu/drm/analog/analog_drm_gem.h diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 95bdf20ad8420..e511c9a90eebb 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -184,6 +184,8 @@ config DRM_ENCODER_ADV7511 select FB_SYS_COPYAREA select FB_SYS_IMAGEBLIT +source "drivers/gpu/drm/analog/Kconfig" + source "drivers/gpu/drm/exynos/Kconfig" source "drivers/gpu/drm/vmwgfx/Kconfig" diff --git a/drivers/gpu/drm/analog/Kconfig b/drivers/gpu/drm/analog/Kconfig index e70391744ddd1..6f2f8c9eb3873 100644 --- a/drivers/gpu/drm/analog/Kconfig +++ b/drivers/gpu/drm/analog/Kconfig @@ -2,8 +2,5 @@ config DRM_ANALOG tristate "DRM Support for Analog FPGA platforms" depends on DRM default n - select DRM_KMS_HELPER - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT + select DRM_KMS_CMA_HELPER select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE diff --git a/drivers/gpu/drm/analog/Makefile b/drivers/gpu/drm/analog/Makefile index 147ce59d69ab3..25375e88d2548 100644 --- a/drivers/gpu/drm/analog/Makefile +++ b/drivers/gpu/drm/analog/Makefile @@ -2,7 +2,6 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -analogdrm-y := analog_drm_encoder.o analog_drm_crtc.o analog_drm_drv.o \ - analog_drm_gem.o analog_drm_fbdev.o +analogdrm-y := analog_drm_encoder.o analog_drm_crtc.o analog_drm_drv.o obj-y += analogdrm.o diff --git a/drivers/gpu/drm/analog/analog_drm_buf.c b/drivers/gpu/drm/analog/analog_drm_buf.c deleted file mode 100644 index 4e8092519fb8d..0000000000000 --- a/drivers/gpu/drm/analog/analog_drm_buf.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include - -#include "analog_drm_drv.h" -#include "analog_drm_gem.h" -#include "analog_drm_buf.h" - -static int lowlevel_buffer_allocate(struct drm_device *dev, - struct analog_drm_gem_buf *buffer) -{ - - buffer->kvaddr = dma_alloc_writecombine(dev->dev, buffer->size, - &buffer->dma_addr, GFP_KERNEL); - if (!buffer->kvaddr) { - DRM_ERROR("failed to allocate buffer. %ld\n", buffer->size); - return -ENOMEM; - } - - DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n", - (unsigned long)buffer->kvaddr, - (unsigned long)buffer->dma_addr, - buffer->size); - - return 0; -} - -static void lowlevel_buffer_deallocate(struct drm_device *dev, - struct analog_drm_gem_buf *buffer) -{ - - if (buffer->dma_addr && buffer->size) - dma_free_coherent(dev->dev, buffer->size, buffer->kvaddr, - (dma_addr_t)buffer->dma_addr); - else - DRM_DEBUG_KMS("buffer data are invalid.\n"); -} - -struct analog_drm_gem_buf *analog_drm_buf_create(struct drm_device *dev, - unsigned int size) -{ - struct analog_drm_gem_buf *buffer; - - buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); - if (!buffer) { - DRM_ERROR("failed to allocate analog_drm_gem_buf.\n"); - return ERR_PTR(-ENOMEM); - } - - buffer->size = size; - - /* - * allocate memory region with size and set the memory information - * to vaddr and dma_addr of a buffer object. - */ - if (lowlevel_buffer_allocate(dev, buffer) < 0) { - kfree(buffer); - buffer = NULL; - return ERR_PTR(-ENOMEM); - } - - return buffer; -} - -void analog_drm_buf_destroy(struct drm_device *dev, - struct analog_drm_gem_buf *buffer) -{ - if (!buffer) { - DRM_DEBUG_KMS("buffer is null.\n"); - return; - } - - lowlevel_buffer_deallocate(dev, buffer); - - kfree(buffer); - buffer = NULL; -} diff --git a/drivers/gpu/drm/analog/analog_drm_crtc.c b/drivers/gpu/drm/analog/analog_drm_crtc.c index 9536e0bb4d655..4b8459dbe4bf5 100644 --- a/drivers/gpu/drm/analog/analog_drm_crtc.c +++ b/drivers/gpu/drm/analog/analog_drm_crtc.c @@ -1,38 +1,39 @@ #include #include +#include #include #include #include "analog_drm_crtc.h" -#include "analog_drm_fbdev.h" #include "analog_drm_drv.h" #include "analog_drm_encoder.h" -#include "analog_drm_gem.h" - -#define to_analog_crtc(x) container_of(x, struct analog_drm_crtc,\ - drm_crtc) struct analog_drm_crtc { - struct drm_crtc drm_crtc; - struct dma_chan *dma; + struct drm_crtc drm_crtc; + struct dma_chan *dma; struct xilinx_dma_config dma_config; int mode; }; +static inline struct analog_drm_crtc *to_analog_crtc(struct drm_crtc *crtc) +{ + return container_of(crtc, struct analog_drm_crtc, drm_crtc); +} + static int analog_drm_crtc_update(struct drm_crtc *crtc) { struct analog_drm_crtc *analog_crtc = to_analog_crtc(crtc); struct drm_display_mode *mode = &crtc->mode; struct drm_framebuffer *fb = crtc->fb; struct dma_async_tx_descriptor *desc; - struct analog_drm_gem_obj *obj; + struct drm_gem_cma_object *obj; size_t offset; if (!mode || !fb) return -EINVAL; if (analog_crtc->mode == DRM_MODE_DPMS_ON) { - obj = analog_drm_fb_get_gem_obj(fb); + obj = drm_fb_cma_get_gem_obj(fb, 0); if (!obj) return -EINVAL; @@ -46,7 +47,8 @@ static int analog_drm_crtc_update(struct drm_crtc *crtc) offset = crtc->x * fb->bits_per_pixel / 8 + crtc->y * fb->pitches[0]; desc = dmaengine_prep_slave_single(analog_crtc->dma, - obj->dma_addr + offset, mode->vdisplay * fb->pitches[0], + obj->paddr + offset, + mode->vdisplay * fb->pitches[0], DMA_MEM_TO_DEV, 0); if (!desc) { pr_err("Failed to prepare DMA descriptor\n"); @@ -112,7 +114,6 @@ static int analog_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, static void analog_drm_crtc_load_lut(struct drm_crtc *crtc) { - /* drm framework doesn't check NULL */ } static struct drm_crtc_helper_funcs analog_crtc_helper_funcs = { @@ -130,6 +131,7 @@ static void analog_drm_crtc_destroy(struct drm_crtc *crtc) struct analog_drm_crtc *analog_crtc = to_analog_crtc(crtc); drm_crtc_cleanup(crtc); + dma_release_channel(analog_crtc->dma); kfree(analog_crtc); } @@ -165,7 +167,8 @@ struct drm_crtc *analog_drm_crtc_create(struct drm_device *dev) dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_PRIVATE, mask); - analog_crtc->dma = dma_request_channel(mask, xlnx_pcm_filter, &p->dma_params); + analog_crtc->dma = dma_request_channel(mask, xlnx_pcm_filter, + &p->dma_params); drm_crtc_init(dev, crtc, &analog_crtc_funcs); drm_crtc_helper_add(crtc, &analog_crtc_helper_funcs); diff --git a/drivers/gpu/drm/analog/analog_drm_drv.c b/drivers/gpu/drm/analog/analog_drm_drv.c index 5406ccc291a51..49e4ff981ec32 100644 --- a/drivers/gpu/drm/analog/analog_drm_drv.c +++ b/drivers/gpu/drm/analog/analog_drm_drv.c @@ -8,12 +8,11 @@ #include #include #include +#include #include "analog_drm_drv.h" #include "analog_drm_crtc.h" #include "analog_drm_encoder.h" -#include "analog_drm_fbdev.h" -#include "analog_drm_gem.h" #define DRIVER_NAME "analog_drm" #define DRIVER_DESC "ANALOG DRM" @@ -25,6 +24,28 @@ static struct platform_device *analog_drm_pdev; static struct i2c_adapter *slave_adapter; static struct i2c_adapter *ddc_adapter; +static void analog_drm_output_poll_changed(struct drm_device *dev) +{ + struct analog_drm_private *private = dev->dev_private; + drm_fbdev_cma_hotplug_event(private->fbdev); +} + +static struct drm_mode_config_funcs analog_drm_mode_config_funcs = { + .fb_create = drm_fb_cma_create, + .output_poll_changed = analog_drm_output_poll_changed, +}; + +static void analog_drm_mode_config_init(struct drm_device *dev) +{ + dev->mode_config.min_width = 0; + dev->mode_config.min_height = 0; + + dev->mode_config.max_width = 4096; + dev->mode_config.max_height = 4096; + + dev->mode_config.funcs = &analog_drm_mode_config_funcs; +} + static int analog_drm_load(struct drm_device *dev, unsigned long flags) { struct analog_drm_private *private; @@ -32,11 +53,10 @@ static int analog_drm_load(struct drm_device *dev, unsigned long flags) struct device_node *of_node; int ret; - ret = of_parse_phandle_with_args(analog_drm_pdev->dev.of_node, "dma-request", "#dma-cells", - 0, &dma_spec); - if (ret) { + ret = of_parse_phandle_with_args(analog_drm_pdev->dev.of_node, "dma-request", + "#dma-cells", 0, &dma_spec); + if (ret) return ret; - } private = kzalloc(sizeof(struct analog_drm_private), GFP_KERNEL); if (!private) @@ -68,9 +88,10 @@ static int analog_drm_load(struct drm_device *dev, unsigned long flags) private->slave_adapter = slave_adapter; analog_drm_encoder_create(dev); - ret = analog_drm_fbdev_init(dev); - if (ret) { + private->fbdev = drm_fbdev_cma_init(dev, 32, 1, 1); + if (IS_ERR(private->fbdev)) { DRM_ERROR("failed to initialize drm fbdev\n"); + ret = PTR_ERR(private->fbdev); goto err_drm_device; } @@ -87,10 +108,16 @@ static int analog_drm_load(struct drm_device *dev, unsigned long flags) static int analog_drm_unload(struct drm_device *dev) { - analog_drm_fbdev_fini(dev); + struct analog_drm_private *private = dev->dev_private; + + drm_fbdev_cma_fini(private->fbdev); /*analog_drm_device_unregister(dev);*/ drm_kms_helper_poll_fini(dev); drm_mode_config_cleanup(dev); + + iounmap(private->base); + iounmap(private->base_clock); + kfree(dev->dev_private); return 0; @@ -98,19 +125,14 @@ static int analog_drm_unload(struct drm_device *dev) static void analog_drm_lastclose(struct drm_device *dev) { - analog_drm_fbdev_restore_mode(dev); + struct analog_drm_private *private = dev->dev_private; + drm_fbdev_cma_restore_mode(private->fbdev); } -static struct vm_operations_struct analog_drm_gem_vm_ops = { - .fault = analog_drm_gem_fault, - .open = drm_gem_vm_open, - .close = drm_gem_vm_close, -}; - static const struct file_operations analog_drm_driver_fops = { .owner = THIS_MODULE, .open = drm_open, - .mmap = analog_drm_gem_mmap, + .mmap = drm_gem_cma_mmap, .poll = drm_poll, .read = drm_read, .unlocked_ioctl = drm_ioctl, @@ -123,11 +145,11 @@ static struct drm_driver analog_drm_driver = { .load = analog_drm_load, .unload = analog_drm_unload, .lastclose = analog_drm_lastclose, - .gem_free_object = analog_drm_gem_free_object, - .gem_vm_ops = &analog_drm_gem_vm_ops, - .dumb_create = analog_drm_gem_dumb_create, - .dumb_map_offset = analog_drm_gem_dumb_map_offset, - .dumb_destroy = analog_drm_gem_dumb_destroy, + .gem_free_object = drm_gem_cma_free_object, + .gem_vm_ops = &drm_gem_cma_vm_ops, + .dumb_create = drm_gem_cma_dumb_create, + .dumb_map_offset = drm_gem_cma_dumb_map_offset, + .dumb_destroy = drm_gem_cma_dumb_destroy, .fops = &analog_drm_driver_fops, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/analog/analog_drm_drv.h b/drivers/gpu/drm/analog/analog_drm_drv.h index 89cc9e59f5256..c0b1fc686c21b 100644 --- a/drivers/gpu/drm/analog/analog_drm_drv.h +++ b/drivers/gpu/drm/analog/analog_drm_drv.h @@ -2,6 +2,7 @@ #define _ANALOG_DRM_DRV_H_ #include +#include #include struct xlnx_pcm_dma_params { @@ -9,11 +10,10 @@ struct xlnx_pcm_dma_params { int chan_id; }; -struct analog_drm_fbdev; struct analog_drm_encoder; struct analog_drm_private { - struct analog_drm_fbdev *fbdev; + struct drm_fbdev_cma *fbdev; struct drm_crtc *crtc; struct analog_drm_encoder *encoder; struct i2c_adapter *ddc_adapter; diff --git a/drivers/gpu/drm/analog/analog_drm_encoder.c b/drivers/gpu/drm/analog/analog_drm_encoder.c index da7b781ac40a9..3a3bd31c3b350 100644 --- a/drivers/gpu/drm/analog/analog_drm_encoder.c +++ b/drivers/gpu/drm/analog/analog_drm_encoder.c @@ -38,12 +38,12 @@ #define ANALOG_COLOR_PATTERN_ENABLE BIT(24) static struct debugfs_reg32 analog_drm_encoder_debugfs_regs[] = { - { "Control", ANALOG_REG_CTRL }, - { "HTiming1", ANALOG_REG_HTIMING1 }, - { "HTiming2", ANALOG_REG_HTIMING2 }, - { "VTiming1", ANALOG_REG_VTIMING1 }, - { "VTiming2", ANALOG_REG_VTIMING2 }, - { "Status", ANALOG_REG_STATUS }, + { "Control", ANALOG_REG_CTRL }, + { "HTiming1", ANALOG_REG_HTIMING1 }, + { "HTiming2", ANALOG_REG_HTIMING2 }, + { "VTiming1", ANALOG_REG_VTIMING1 }, + { "VTiming2", ANALOG_REG_VTIMING2 }, + { "Status", ANALOG_REG_STATUS }, }; static uint16_t adv7511_csc_ycbcr_to_rgb[] = { @@ -85,7 +85,7 @@ static struct adv7511_video_input_config adv7511_config_zc702 = { .output_format = ADV7511_OUTPUT_FORMAT_RGB_444, .csc_enable = true, .csc_coefficents = adv7511_csc_ycbcr_to_rgb, - .csc_scaling_factor = 3, + .csc_scaling_factor = ADV7511_CSC_SCALING_4, .bit_justification = ADV7511_INPUT_BIT_JUSTIFICATION_RIGHT, .tmds_clock_inversion = true, }; @@ -97,8 +97,11 @@ struct analog_drm_encoder { struct debugfs_regset32 regset; }; -#define to_analog_encoder(x) container_of(x, struct analog_drm_encoder,\ - encoder.base) + +static inline struct analog_drm_encoder *to_analog_encoder(struct drm_encoder *enc) +{ + return container_of(enc, struct analog_drm_encoder, encoder.base); +} static inline struct drm_encoder *connector_to_encoder(struct drm_connector *connector) { @@ -124,11 +127,12 @@ static int debugfs_cp_get(void *data, u64 *val) *val = ioread32(private->base + ANALOG_REG_COLOR_PATTERN); return 0; } + static int debugfs_cp_set(void *data, u64 val) { struct analog_drm_private *private = data; - iowrite32(0x0000000, private-> base + ANALOG_REG_COLOR_PATTERN); - iowrite32(0x1000000 | val, private-> base + ANALOG_REG_COLOR_PATTERN); + iowrite32(0x0000000, private->base + ANALOG_REG_COLOR_PATTERN); + iowrite32(0x1000000 | val, private->base + ANALOG_REG_COLOR_PATTERN); return 0; } DEFINE_SIMPLE_ATTRIBUTE(fops_cp, debugfs_cp_get, debugfs_cp_set, "0x%08llx\n"); @@ -551,7 +555,6 @@ static int analog_drm_connector_get_modes(struct drm_connector *connector) struct edid *edid; int count = 0; - kfree(connector->display_info.raw_edid); connector->display_info.raw_edid = NULL; @@ -571,8 +574,6 @@ static int analog_drm_connector_get_modes(struct drm_connector *connector) static int analog_drm_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - const struct analog_drm_crtc_clock_setting *best_setting; - if (mode->clock > 165000) return MODE_CLOCK_HIGH; diff --git a/drivers/gpu/drm/analog/analog_drm_fbdev.c b/drivers/gpu/drm/analog/analog_drm_fbdev.c deleted file mode 100644 index bf15d03b3532f..0000000000000 --- a/drivers/gpu/drm/analog/analog_drm_fbdev.c +++ /dev/null @@ -1,338 +0,0 @@ -#include -#include -#include -#include -#include - -#include "analog_drm_drv.h" -#include "analog_drm_gem.h" - -#define MAX_CONNECTOR 1 -#define PREFERRED_BPP 32 - -#define to_analog_fbdev(x) container_of(x, struct analog_drm_fbdev,\ - fb_helper) - -#define to_analog_fb(x) container_of(x, struct analog_drm_fb,\ - fb) - -struct analog_drm_fb { - struct drm_framebuffer fb; - struct analog_drm_gem_obj *obj; -}; - -struct analog_drm_fbdev { - struct drm_fb_helper fb_helper; - struct analog_drm_fb *fb; -}; - -static void analog_drm_fb_destroy(struct drm_framebuffer *fb) -{ - struct analog_drm_fb *afb = to_analog_fb(fb); - - if (afb->obj) - drm_gem_object_unreference_unlocked(&afb->obj->base); - - drm_framebuffer_cleanup(fb); - kfree(afb); -} - -static int analog_drm_fb_create_handle(struct drm_framebuffer *fb, - struct drm_file *file_priv, unsigned int *handle) -{ - struct analog_drm_fb *afb = to_analog_fb(fb); - - return drm_gem_handle_create(file_priv, - &afb->obj->base, handle); -} - -static struct drm_framebuffer_funcs analog_drm_fb_funcs = { - .destroy = analog_drm_fb_destroy, - .create_handle = analog_drm_fb_create_handle, -}; - -static struct analog_drm_fb *analog_drm_fb_alloc(struct drm_device *dev, - struct drm_mode_fb_cmd2 *mode_cmd, struct analog_drm_gem_obj *obj) -{ - struct analog_drm_fb *afb; - int ret; - - afb = kzalloc(sizeof(*afb), GFP_KERNEL); - if (!afb) - return ERR_PTR(-ENOMEM); - - afb->obj = obj; - ret = drm_framebuffer_init(dev, &afb->fb, &analog_drm_fb_funcs); - if (ret) { - DRM_ERROR("failed to initialize framebuffer.\n"); - return ERR_PTR(ret); - } - - drm_helper_mode_fill_fb_struct(&afb->fb, mode_cmd); - - return afb; -} - -static struct drm_framebuffer *analog_drm_fb_create(struct drm_device *dev, - struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd) -{ - struct analog_drm_fb *afb; - struct drm_gem_object *obj; - - obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - return ERR_PTR(-ENXIO); - } - - afb = analog_drm_fb_alloc(dev, mode_cmd, to_analog_gem_obj(obj)); - if (IS_ERR(afb)) - return ERR_CAST(afb); - - return &afb->fb; -} - -struct analog_drm_gem_obj *analog_drm_fb_get_gem_obj(struct drm_framebuffer *fb) -{ - struct analog_drm_fb *afb = to_analog_fb(fb); - - return afb->obj; -} - -static void analog_drm_output_poll_changed(struct drm_device *dev) -{ - struct analog_drm_private *private = dev->dev_private; - - if (private->fbdev) - drm_fb_helper_hotplug_event(&private->fbdev->fb_helper); -} - -static struct drm_mode_config_funcs analog_drm_mode_config_funcs = { - .fb_create = analog_drm_fb_create, - .output_poll_changed = analog_drm_output_poll_changed, -}; - -void analog_drm_mode_config_init(struct drm_device *dev) -{ - dev->mode_config.min_width = 0; - dev->mode_config.min_height = 0; - - /* - * set max width and height as default value(4096x4096). - * this value would be used to check framebuffer size limitation - * at drm_mode_addfb(). - */ - dev->mode_config.max_width = 4096; - dev->mode_config.max_height = 4096; - - dev->mode_config.funcs = &analog_drm_mode_config_funcs; -} - -static struct fb_ops analog_drm_fb_ops = { - .owner = THIS_MODULE, - .fb_fillrect = sys_fillrect, - .fb_copyarea = sys_copyarea, - .fb_imageblit = sys_imageblit, - .fb_check_var = drm_fb_helper_check_var, - .fb_set_par = drm_fb_helper_set_par, - .fb_blank = drm_fb_helper_blank, - .fb_pan_display = drm_fb_helper_pan_display, - .fb_setcmap = drm_fb_helper_setcmap, -}; - -static int analog_drm_fbdev_create(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - struct analog_drm_fbdev *afbdev = to_analog_fbdev(helper); - struct drm_mode_fb_cmd2 mode_cmd = { 0 }; - struct drm_device *dev = helper->dev; - struct analog_drm_gem_obj *obj; - struct drm_framebuffer *fb; - unsigned long offset; - struct fb_info *fbi; - size_t size; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n", - sizes->surface_width, sizes->surface_height, - sizes->surface_bpp); - - sizes->surface_bpp = 32; - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->surface_height; - mode_cmd.pitches[0] = sizes->surface_width * (sizes->surface_bpp >> 3); - mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, - sizes->surface_depth); - - size = mode_cmd.pitches[0] * mode_cmd.height; - obj = analog_drm_gem_alloc(dev, size); - if (!obj) - return -ENOMEM; - - fbi = framebuffer_alloc(0, dev->dev); - if (!fbi) { - DRM_ERROR("failed to allocate fb info.\n"); - ret = -ENOMEM; - goto out; - } - - afbdev->fb = analog_drm_fb_alloc(dev, &mode_cmd, obj); - if (IS_ERR(afbdev->fb)) { - DRM_ERROR("failed to create drm framebuffer.\n"); - ret = PTR_ERR(afbdev->fb); - goto out; - } - - fb = &afbdev->fb->fb; - helper->fb = fb; - helper->fbdev = fbi; - - fbi->par = helper; - fbi->flags = FBINFO_FLAG_DEFAULT; - fbi->fbops = &analog_drm_fb_ops; - - ret = fb_alloc_cmap(&fbi->cmap, 256, 0); - if (ret) { - DRM_ERROR("failed to allocate cmap.\n"); - goto out; - } - - drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); - drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height); - - offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3); - offset += fbi->var.yoffset * fb->pitches[0]; - - dev->mode_config.fb_base = (resource_size_t)obj->dma_addr; - fbi->screen_base = obj->addr + offset; - fbi->fix.smem_start = (unsigned long)(obj->dma_addr + offset); - fbi->screen_size = size; - fbi->fix.smem_len = size; - - return 0; - -/* TODO: gem obj, free fb */ -out: - return ret; -} - -static int analog_drm_fbdev_probe(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - int ret = 0; - - if (!helper->fb) { - ret = analog_drm_fbdev_create(helper, sizes); - if (ret < 0) { - DRM_ERROR("failed to create fbdev.\n"); - return ret; - } - - /* - * fb_helper expects a value more than 1 if succeed - * because register_framebuffer() should be called. - */ - ret = 1; - } - - - printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__); - return ret; -} - -static struct drm_fb_helper_funcs analog_drm_fb_helper_funcs = { - .fb_probe = analog_drm_fbdev_probe, -}; - -int analog_drm_fbdev_init(struct drm_device *dev) -{ - struct analog_drm_fbdev *afbdev; - struct analog_drm_private *private = dev->dev_private; - struct drm_fb_helper *helper; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - afbdev = kzalloc(sizeof(*afbdev), GFP_KERNEL); - if (!afbdev) { - DRM_ERROR("failed to allocate drm fbdev.\n"); - return -ENOMEM; - } - - afbdev->fb_helper.funcs = &analog_drm_fb_helper_funcs; - private->fbdev = afbdev; - helper = &afbdev->fb_helper; - - ret = drm_fb_helper_init(dev, helper, 1, 1); - if (ret < 0) { - DRM_ERROR("failed to initialize drm fb helper.\n"); - goto err_init; - } - - ret = drm_fb_helper_single_add_all_connectors(helper); - if (ret < 0) { - DRM_ERROR("failed to register drm_fb_helper_connector.\n"); - goto err_setup; - - } - - ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP); - if (ret < 0) { - DRM_ERROR("failed to set up hw configuration.\n"); - goto err_setup; - } - - return 0; - -err_setup: - drm_fb_helper_fini(helper); - -err_init: - private->fbdev = NULL; - kfree(afbdev); - - return ret; -} - -void analog_drm_fbdev_fini(struct drm_device *dev) -{ - struct analog_drm_private *private = dev->dev_private; - struct analog_drm_fbdev *afbdev; - - if (!private || !private->fbdev) - return; - - afbdev = private->fbdev; - - private->fbdev = NULL; - - if (afbdev->fb_helper.fbdev) { - struct fb_info *info; - int ret; - - info = afbdev->fb_helper.fbdev; - ret = unregister_framebuffer(info); - if (ret < 0) - DRM_DEBUG_KMS("failed unregister_framebuffer()\n"); - - if (info->cmap.len) - fb_dealloc_cmap(&info->cmap); - - framebuffer_release(info); - } - - drm_fb_helper_fini(&afbdev->fb_helper); - kfree(afbdev); -} - -void analog_drm_fbdev_restore_mode(struct drm_device *dev) -{ - struct analog_drm_private *private = dev->dev_private; - - if (!private || !private->fbdev) - return; - - drm_fb_helper_restore_fbdev_mode(&private->fbdev->fb_helper); -} diff --git a/drivers/gpu/drm/analog/analog_drm_fbdev.h b/drivers/gpu/drm/analog/analog_drm_fbdev.h deleted file mode 100644 index 4732524c199b5..0000000000000 --- a/drivers/gpu/drm/analog/analog_drm_fbdev.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _ANALOG_DRM_FBDEV_H_ -#define _ANALOG_DRM_FBDEV_H_ - -int analog_drm_fbdev_init(struct drm_device *dev); -void analog_drm_fbdev_fini(struct drm_device *dev); -void analog_drm_fbdev_restore_mode(struct drm_device *dev); - -void analog_drm_mode_config_init(struct drm_device *dev); - -struct analog_drm_gem_obj *analog_drm_fb_get_gem_obj(struct drm_framebuffer *fb); - -#endif diff --git a/drivers/gpu/drm/analog/analog_drm_gem.c b/drivers/gpu/drm/analog/analog_drm_gem.c deleted file mode 100644 index ed7cd929f03d9..0000000000000 --- a/drivers/gpu/drm/analog/analog_drm_gem.c +++ /dev/null @@ -1,242 +0,0 @@ -#include -#include - -#include - -#include "analog_drm_drv.h" -#include "analog_drm_gem.h" - -static unsigned int convert_to_vm_err_msg(int msg) -{ - unsigned int out_msg; - - switch (msg) { - case 0: - case -ERESTARTSYS: - case -EINTR: - out_msg = VM_FAULT_NOPAGE; - break; - - case -ENOMEM: - out_msg = VM_FAULT_OOM; - break; - - default: - out_msg = VM_FAULT_SIGBUS; - break; - } - - return out_msg; -} - -static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT; -} - -struct analog_drm_gem_obj *analog_drm_gem_alloc(struct drm_device *dev, - size_t size) -{ - struct analog_drm_gem_obj *analog_gem_obj; - struct drm_gem_object *obj; - dma_addr_t dma_addr; - void *addr; - int ret; - - size = roundup(size, PAGE_SIZE); - - addr = dma_alloc_writecombine(dev->dev, size, &dma_addr, GFP_KERNEL); - if (!addr) - return ERR_PTR(-ENOMEM); - - analog_gem_obj = kzalloc(sizeof(*analog_gem_obj), GFP_KERNEL); - if (!analog_gem_obj) { - DRM_ERROR("failed to allocate analog gem object.\n"); - ret = -ENOMEM; - goto err_alloc; - } - - analog_gem_obj->addr = addr; - analog_gem_obj->dma_addr = dma_addr; - - obj = &analog_gem_obj->base; - - ret = drm_gem_object_init(dev, obj, size); - if (ret < 0) { - DRM_ERROR("failed to initialize gem object.\n"); - ret = -EINVAL; - goto err_object_init; - } - - return analog_gem_obj; - -err_object_init: - kfree(analog_gem_obj); -err_alloc: - dma_free_coherent(dev->dev, size, addr, dma_addr); - - return ERR_PTR(ret); -} - -static struct analog_drm_gem_obj *analog_drm_gem_create(struct drm_device *dev, - struct drm_file *file, unsigned int *handle, unsigned long size) -{ - struct analog_drm_gem_obj *obj; - int ret; - - obj = analog_drm_gem_alloc(dev, size); - if (IS_ERR(obj)) - return obj; - - ret = drm_gem_handle_create(file, &obj->base, handle); - if (ret) { - drm_gem_object_release(&obj->base); - kfree(obj); - return ERR_PTR(ret); - } - - drm_gem_object_unreference(&obj->base); - return 0; -} - -void analog_drm_gem_free_object(struct drm_gem_object *gem_obj) -{ - struct analog_drm_gem_obj *analog_gem_obj = to_analog_gem_obj(gem_obj); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - DRM_DEBUG_KMS("handle count = %d\n", - atomic_read(&gem_obj->handle_count)); - - if (gem_obj->map_list.map) - drm_gem_free_mmap_offset(gem_obj); - - /* release file pointer to gem object. */ - drm_gem_object_release(gem_obj); - - - dma_free_coherent(gem_obj->dev->dev, analog_gem_obj->base.size, - analog_gem_obj->addr, analog_gem_obj->dma_addr); - - kfree(analog_gem_obj); -} - -int analog_drm_gem_dumb_create(struct drm_file *file_priv, - struct drm_device *dev, struct drm_mode_create_dumb *args) -{ - struct analog_drm_gem_obj *analog_gem_obj; - - args->pitch = args->width * args->bpp >> 3; - args->size = args->pitch * args->height; - - analog_gem_obj = analog_drm_gem_create(dev, file_priv, &args->handle, - args->size); - if (IS_ERR(analog_gem_obj)) - return PTR_ERR(analog_gem_obj); - - return 0; -} - -int analog_drm_gem_dumb_map_offset(struct drm_file *file_priv, - struct drm_device *dev, uint32_t handle, uint64_t *offset) -{ - struct analog_drm_gem_obj *analog_gem_obj; - struct drm_gem_object *obj; - int ret = 0; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - mutex_lock(&dev->struct_mutex); - - obj = drm_gem_object_lookup(dev, file_priv, handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - mutex_unlock(&dev->struct_mutex); - return -EINVAL; - } - - if (!obj->map_list.map) { - ret = drm_gem_create_mmap_offset(obj); - if (ret) - goto out; - } - - analog_gem_obj = to_analog_gem_obj(obj); - - *offset = get_gem_mmap_offset(&analog_gem_obj->base); - DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset); - -out: - drm_gem_object_unreference(obj); - - - mutex_unlock(&dev->struct_mutex); - - return ret; -} - -int analog_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - struct drm_gem_object *obj = vma->vm_private_data; - struct analog_drm_gem_obj *analog_gem_obj = to_analog_gem_obj(obj); - struct drm_device *dev = obj->dev; - unsigned int i, page_num; - unsigned long address; - unsigned long pfn; - pgoff_t page_offset; - int ret = 0; - - page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; - page_offset = ((unsigned long)vmf->virtual_address - - vma->vm_start) >> PAGE_SHIFT; - - mutex_lock(&dev->struct_mutex); - - pfn = (((unsigned long)analog_gem_obj->dma_addr) >> - PAGE_SHIFT) + page_offset; - - address = (unsigned long)vmf->virtual_address; - - for (i = 0; i < page_num; i++) { - ret = vm_insert_mixed(vma, address, pfn); - if (ret == -EBUSY || (ret != 0 && i > 0)) - break; - else if (ret) - return (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS; - address += PAGE_SIZE; - pfn++; - } - - mutex_unlock(&dev->struct_mutex); - - return convert_to_vm_err_msg(ret); -} - -int analog_drm_gem_dumb_destroy(struct drm_file *file_priv, - struct drm_device *dev, unsigned int handle) -{ - return drm_gem_handle_delete(file_priv, handle); -} - -int analog_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) -{ - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* set vm_area_struct. */ - ret = drm_gem_mmap(filp, vma); - if (ret < 0) { - DRM_ERROR("failed to mmap.\n"); - return ret; - } - - vma->vm_flags &= ~VM_PFNMAP; - vma->vm_flags |= VM_MIXEDMAP; - - return ret; -} - -MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/analog/analog_drm_gem.h b/drivers/gpu/drm/analog/analog_drm_gem.h deleted file mode 100644 index 68a0b26063ae1..0000000000000 --- a/drivers/gpu/drm/analog/analog_drm_gem.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _ANALOG_DRM_GEM_H_ -#define _ANALOG_DRM_GEM_H_ - -#define to_analog_gem_obj(x) container_of(x,\ - struct analog_drm_gem_obj, base) - -/* - * analog drm buffer structure. - * - * @base: a gem object. - * - a new handle to this gem object would be created - * by drm_gem_handle_create(). - * @addr: kernel virtual address to allocated memory region. - * @dma_addr: bus address(accessed by dma) to allocated memory region. - * - this address could be physical address without IOMMU and - * device address with IOMMU. - * - */ -struct analog_drm_gem_obj { - struct drm_gem_object base; - void *addr; - dma_addr_t dma_addr; -}; - -struct analog_drm_gem_obj *analog_drm_gem_alloc(struct drm_device *dev, - size_t size); - -/* free gem object. */ -void analog_drm_gem_free_object(struct drm_gem_object *gem_obj); - -/* create memory region for drm framebuffer. */ -int analog_drm_gem_dumb_create(struct drm_file *file_priv, - struct drm_device *dev, struct drm_mode_create_dumb *args); - -/* map memory region for drm framebuffer to user space. */ -int analog_drm_gem_dumb_map_offset(struct drm_file *file_priv, - struct drm_device *dev, uint32_t handle, uint64_t *offset); - -/* page fault handler and mmap fault address(virtual) to physical memory. */ -int analog_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); - -/* - * destroy memory region allocated. - * - a gem handle and physical memory region pointed by a gem object - * would be released by drm_gem_handle_delete(). - */ -int analog_drm_gem_dumb_destroy(struct drm_file *file_priv, - struct drm_device *dev, unsigned int handle); - -int analog_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); - -#endif From 7f8e908de02b03dcc43341d64f18fa6c34258abf Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Mon, 16 Jul 2012 16:07:19 -0700 Subject: [PATCH 171/261] Pmods: Add Documentation for PmodOLED The documentation of pmodoled can be found at Documentation/pmods/pmodoled.txt --- Documentation/pmods/00-INDEX | 8 ++ Documentation/pmods/pmodoled.txt | 137 +++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 Documentation/pmods/00-INDEX create mode 100644 Documentation/pmods/pmodoled.txt diff --git a/Documentation/pmods/00-INDEX b/Documentation/pmods/00-INDEX new file mode 100644 index 0000000000000..813f5b4af325f --- /dev/null +++ b/Documentation/pmods/00-INDEX @@ -0,0 +1,8 @@ +Documentation for pmods, a set of peripheral modules provided by Digilent Inc., +which can be plugged to various development boards to add additional functionalities. +These drivers are maintained by Digilent Inc. + +00-INDEX + - this file +pmodoled.txt + - PmodOLED: 128 by 32 pixel 0.9" Organic LED Graphic Display diff --git a/Documentation/pmods/pmodoled.txt b/Documentation/pmods/pmodoled.txt new file mode 100644 index 0000000000000..160be98aba191 --- /dev/null +++ b/Documentation/pmods/pmodoled.txt @@ -0,0 +1,137 @@ +PmodOLED +======== + +Copyright 2012, Digilent Inc. + + +Description +----------- + +The PmodOLED features an SPI-controlled monochrome OLED display, +perfect for embedded applications requiring small, complex visual output. + +The PmodOLED uses a standard 12-pin connector to display output on +a 128x32 pixel organic LED (OLED) panel. The graphic display panel uses +the Solomon Systech SSD1306 display controller. + +An SPI interface is used to configure the display, +as well as to send the bitmap data to the device. + +The PmodOLED displays the last image drawn on the screen until it is +powered down or a new image is drawn to the display. Refreshing and +updating is handled internally. + +The Reference Manual for PmodOLED display is available online at +Digilent Inc. Website (www.digilentinc.com) + +For more information on the OLED display interface, see the +UG-2832HSWEG04 datasheet available online or from Univisio. + +The OLED display uses a compatible command set from the SSD1306 device. +For more information, see the SSD1306 datasheet available at +www.solomon-systech.com. + + +Interface +--------- + +Signal Description + +CS SPI Chip Select (Slave Select) +SDIN SPI Data In (MOSI) +SCLK SPI Clock +D/C Data/Command Control +RES Power Reset +VBATC VBAT Battery Voltage Control +VDDC VDD Logic Voltage Control + + +Devicetree +---------- + +Required Properties: +- compatible : Should be "dlgnt,pmodoled-gpio" +- vbat-gpio : Should specify the GPIO for VBATC, see "gpios property" in + Documentation/devicetree/gpio.txt. +- vdd-gpio : Should specify the GPIO for VDDC, see "gpios property" in + Documentation/devicetree/gpio.txt. +- res-gpio : Should specify the GPIO for RES, see "gpios property" in + Documentation/devicetree/gpio.txt. +- dc-gpio : Should specify the GPIO for D/C, see "gpios property" in + Documentation/devicetree/gpio.txt. +- spi-bus-num : Should specify the bus number for PmodOLED SPI controller. + This value cannot be shared by any other SPI controller present in the + device tree. +- spi-sclk-gpio : Should specify the GPIO for SCLK, see "gpios property" in + Documentation/devicetree/gpio.txt. +- spi-sdin-gpio : Should specify the GPIO for SDIN, see "gpios property" in + Documentation/devicetree/gpio.txt. + +Optional Properties: +- spi-cs-gpio : Should specify the GPIO for CS, see "gpios property" in + Documentation/devicetree/gpio.txt. If unspecified, CS is assumed to be + tied to ground. + +Examples: + +zed_oled { + compatible = "dglnt,pmodoled-gpio"; + /* GPIO Pins */ + vbat-gpio = <&gpiops 55 0>; + vdd-gpio = <&gpiops 56 0>; + res-gpio = <&gpiops 57 0>; + dc-gpio = <&gpiops 58 0>; + /* SPI-GPIOs */ + spi-bus-num = <2>; + spi-sclk-gpio = <&gpiops 59 0>; + spi-sdin-gpio = <&gpiops 60 0>; +}; + +pmodoled_A { + compatible = "dglnt,pmodoled-gpio"; + vbat-gpio = <&gpiops 88 0>; + vdd-gpio = <&gpiops 89 0>; + res-gpio = <&gpiops 87 0>; + dc-gpio = <&gpiops 86 0>; + spi-bus-num = <3>; + spi-sclk-gpio = <&gpiops 85 0>; + spi-sdin-gpio = <&gpiops 83 0>; + spi-cs-gpio = <&gpiops 82 0>; +}; + + +Configuration +------------- + +The PmodOLED is located in the kernel configuration menu at +Device Drivers -> Pmods -> PmodOLED. The driver can be built into the kernel +by selecting (*) for it, or loadable module by selecting (M) for it. + + +Device Nodes +------------ + +A char device node will be created for each PmodOLED device automatically. +The name of the node is default to the one declared in the device tree. + + +Read/Writes +----------- + +The driver provides a 512 Byte display buffer for the display of PmodOLED. +The Whole screen is divided into four lines, each of them is 128 bits wide +and 8 bits high, as shown in the figure below. + + +--------------------------...----------------------------+ + + Line 4 + + +--------------------------...----------------------------+ + + Line 3 + + +--------------------------...----------------------------+ + + Line 2 + + +--------------------------...----------------------------+ MSB (bit 7) + + Line 1 + + +--------------------------...----------------------------+ LSB (bit 0) +byte 127 byte 0 + +Users can perform read and write functions to the device node to access the data +inside the display buffer. From e4a26fac47da8b9982b0358c3ed25fba8e740f2d Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 19 Jul 2012 14:06:05 +0200 Subject: [PATCH 172/261] XCOMM: ZED: Update device tree Signed-off-by: Michael Hennerich --- arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts index 900e50e791087..0e7153660d5aa 100644 --- a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts +++ b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts @@ -114,6 +114,19 @@ reg = <0>; spi-max-frequency = <10000000>; }; + adc0_ad9467: ad9467@1 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ad9643"; + reg = <1>; + spi-3wire; + spi-max-frequency = <10000000>; + }; + + }; + eeprom@50 { + compatible = "at24,24c02"; + reg = <0x50>; }; }; @@ -238,9 +251,7 @@ compatible = "xlnx,cf-ad9643-core-1.00.a"; reg = < 0x79020000 0x10000 >; dma-request = <&axi_dma_1 0>; - spibus-connected = <&spi_xcomm0>; - spibus-slaveselect-connected = <0x1>; - dco-output-delay = <0x8c>; + spibus-connected = <&adc0_ad9467>; xlnx,dphase-timeout = <0x8>; xlnx,num-mem = <0x1>; xlnx,num-reg = <0x1>; @@ -254,6 +265,7 @@ compatible = "xlnx,cf-ad9122-core-2.00.a"; reg = < 0x74200000 0x10000 >; spibus-connected = <&dac0_ad9122>; + dac-sample-frequency = <491520000>; xlnx,dphase-timeout = <0x8>; xlnx,num-mem = <0x1>; xlnx,num-reg = <0x1>; From 934262f7a3e3bf614c772656e5a38696c137bc37 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 22 Feb 2012 10:05:38 +0100 Subject: [PATCH 173/261] spi: create a message queueing infrastructure This rips the message queue in the PL022 driver out and pushes it into (optional) common infrastructure. Drivers that want to use the message pumping thread will need to define the new per-messags transfer methods and leave the deprecated transfer() method as NULL. Most of the design is described in the documentation changes that are included in this patch. Since there is a queue that need to be stopped when the system is suspending/resuming, two new calls are implemented for the device drivers to call in their suspend()/resume() functions: spi_master_suspend() and spi_master_resume(). ChangeLog v1->v2: - Remove Kconfig entry and do not make the queue support optional at all, instead be more agressive and have it as part of the compulsory infrastructure. - If the .transfer() method is implemented, delete print a small deprecation notice and do not start the transfer pump. - Fix a bitrotted comment. ChangeLog v2->v3: - Fix up a problematic sequence courtesy of Chris Blair. - Stop rather than destroy the queue on suspend() courtesy of Chris Blair. Signed-off-by: Chris Blair Signed-off-by: Linus Walleij Tested-by: Mark Brown Reviewed-by: Mark Brown Signed-off-by: Grant Likely Conflicts: drivers/spi/spi-pl022.c --- Documentation/spi/spi-summary | 58 ++++-- drivers/spi/spi.c | 339 +++++++++++++++++++++++++++++++++- include/linux/spi/spi.h | 51 +++++ 3 files changed, 435 insertions(+), 13 deletions(-) diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary index 4884cb33845d7..7312ec14dd898 100644 --- a/Documentation/spi/spi-summary +++ b/Documentation/spi/spi-summary @@ -1,7 +1,7 @@ Overview of Linux kernel SPI support ==================================== -21-May-2007 +02-Feb-2012 What is SPI? ------------ @@ -483,9 +483,9 @@ also initialize its own internal state. (See below about bus numbering and those methods.) After you initialize the spi_master, then use spi_register_master() to -publish it to the rest of the system. At that time, device nodes for -the controller and any predeclared spi devices will be made available, -and the driver model core will take care of binding them to drivers. +publish it to the rest of the system. At that time, device nodes for the +controller and any predeclared spi devices will be made available, and +the driver model core will take care of binding them to drivers. If you need to remove your SPI controller driver, spi_unregister_master() will reverse the effect of spi_register_master(). @@ -521,21 +521,53 @@ SPI MASTER METHODS ** When you code setup(), ASSUME that the controller ** is actively processing transfers for another device. - master->transfer(struct spi_device *spi, struct spi_message *message) - This must not sleep. Its responsibility is arrange that the - transfer happens and its complete() callback is issued. The two - will normally happen later, after other transfers complete, and - if the controller is idle it will need to be kickstarted. - master->cleanup(struct spi_device *spi) Your controller driver may use spi_device.controller_state to hold state it dynamically associates with that device. If you do that, be sure to provide the cleanup() method to free that state. + master->prepare_transfer_hardware(struct spi_master *master) + This will be called by the queue mechanism to signal to the driver + that a message is coming in soon, so the subsystem requests the + driver to prepare the transfer hardware by issuing this call. + This may sleep. + + master->unprepare_transfer_hardware(struct spi_master *master) + This will be called by the queue mechanism to signal to the driver + that there are no more messages pending in the queue and it may + relax the hardware (e.g. by power management calls). This may sleep. + + master->transfer_one_message(struct spi_master *master, + struct spi_message *mesg) + The subsystem calls the driver to transfer a single message while + queuing transfers that arrive in the meantime. When the driver is + finished with this message, it must call + spi_finalize_current_message() so the subsystem can issue the next + transfer. This may sleep. + + DEPRECATED METHODS + + master->transfer(struct spi_device *spi, struct spi_message *message) + This must not sleep. Its responsibility is arrange that the + transfer happens and its complete() callback is issued. The two + will normally happen later, after other transfers complete, and + if the controller is idle it will need to be kickstarted. This + method is not used on queued controllers and must be NULL if + transfer_one_message() and (un)prepare_transfer_hardware() are + implemented. + SPI MESSAGE QUEUE -The bulk of the driver will be managing the I/O queue fed by transfer(). +If you are happy with the standard queueing mechanism provided by the +SPI subsystem, just implement the queued methods specified above. Using +the message queue has the upside of centralizing a lot of code and +providing pure process-context execution of methods. The message queue +can also be elevated to realtime priority on high-priority SPI traffic. + +Unless the queueing mechanism in the SPI subsystem is selected, the bulk +of the driver will be managing the I/O queue fed by the now deprecated +function transfer(). That queue could be purely conceptual. For example, a driver used only for low-frequency sensor access might be fine using synchronous PIO. @@ -561,4 +593,6 @@ Stephen Street Mark Underwood Andrew Victor Vitaly Wool - +Grant Likely +Mark Brown +Linus Walleij diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 6f63a8ee4b3bf..41402344166d1 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -30,6 +30,9 @@ #include #include #include +#include +#include +#include static void spidev_release(struct device *dev) { @@ -507,6 +510,293 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n) /*-------------------------------------------------------------------------*/ +/** + * spi_pump_messages - kthread work function which processes spi message queue + * @work: pointer to kthread work struct contained in the master struct + * + * This function checks if there is any spi message in the queue that + * needs processing and if so call out to the driver to initialize hardware + * and transfer each message. + * + */ +static void spi_pump_messages(struct kthread_work *work) +{ + struct spi_master *master = + container_of(work, struct spi_master, pump_messages); + unsigned long flags; + bool was_busy = false; + int ret; + + /* Lock queue and check for queue work */ + spin_lock_irqsave(&master->queue_lock, flags); + if (list_empty(&master->queue) || !master->running) { + if (master->busy) { + ret = master->unprepare_transfer_hardware(master); + if (ret) { + dev_err(&master->dev, + "failed to unprepare transfer hardware\n"); + return; + } + } + master->busy = false; + spin_unlock_irqrestore(&master->queue_lock, flags); + return; + } + + /* Make sure we are not already running a message */ + if (master->cur_msg) { + spin_unlock_irqrestore(&master->queue_lock, flags); + return; + } + /* Extract head of queue */ + master->cur_msg = + list_entry(master->queue.next, struct spi_message, queue); + + list_del_init(&master->cur_msg->queue); + if (master->busy) + was_busy = true; + else + master->busy = true; + spin_unlock_irqrestore(&master->queue_lock, flags); + + if (!was_busy) { + ret = master->prepare_transfer_hardware(master); + if (ret) { + dev_err(&master->dev, + "failed to prepare transfer hardware\n"); + return; + } + } + + ret = master->transfer_one_message(master, master->cur_msg); + if (ret) { + dev_err(&master->dev, + "failed to transfer one message from queue\n"); + return; + } +} + +static int spi_init_queue(struct spi_master *master) +{ + struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; + + INIT_LIST_HEAD(&master->queue); + spin_lock_init(&master->queue_lock); + + master->running = false; + master->busy = false; + + init_kthread_worker(&master->kworker); + master->kworker_task = kthread_run(kthread_worker_fn, + &master->kworker, + dev_name(&master->dev)); + if (IS_ERR(master->kworker_task)) { + dev_err(&master->dev, "failed to create message pump task\n"); + return -ENOMEM; + } + init_kthread_work(&master->pump_messages, spi_pump_messages); + + /* + * Master config will indicate if this controller should run the + * message pump with high (realtime) priority to reduce the transfer + * latency on the bus by minimising the delay between a transfer + * request and the scheduling of the message pump thread. Without this + * setting the message pump thread will remain at default priority. + */ + if (master->rt) { + dev_info(&master->dev, + "will run message pump with realtime priority\n"); + sched_setscheduler(master->kworker_task, SCHED_FIFO, ¶m); + } + + return 0; +} + +/** + * spi_get_next_queued_message() - called by driver to check for queued + * messages + * @master: the master to check for queued messages + * + * If there are more messages in the queue, the next message is returned from + * this call. + */ +struct spi_message *spi_get_next_queued_message(struct spi_master *master) +{ + struct spi_message *next; + unsigned long flags; + + /* get a pointer to the next message, if any */ + spin_lock_irqsave(&master->queue_lock, flags); + if (list_empty(&master->queue)) + next = NULL; + else + next = list_entry(master->queue.next, + struct spi_message, queue); + spin_unlock_irqrestore(&master->queue_lock, flags); + + return next; +} +EXPORT_SYMBOL_GPL(spi_get_next_queued_message); + +/** + * spi_finalize_current_message() - the current message is complete + * @master: the master to return the message to + * + * Called by the driver to notify the core that the message in the front of the + * queue is complete and can be removed from the queue. + */ +void spi_finalize_current_message(struct spi_master *master) +{ + struct spi_message *mesg; + unsigned long flags; + + spin_lock_irqsave(&master->queue_lock, flags); + mesg = master->cur_msg; + master->cur_msg = NULL; + + queue_kthread_work(&master->kworker, &master->pump_messages); + spin_unlock_irqrestore(&master->queue_lock, flags); + + mesg->state = NULL; + if (mesg->complete) + mesg->complete(mesg->context); +} +EXPORT_SYMBOL_GPL(spi_finalize_current_message); + +static int spi_start_queue(struct spi_master *master) +{ + unsigned long flags; + + spin_lock_irqsave(&master->queue_lock, flags); + + if (master->running || master->busy) { + spin_unlock_irqrestore(&master->queue_lock, flags); + return -EBUSY; + } + + master->running = true; + master->cur_msg = NULL; + spin_unlock_irqrestore(&master->queue_lock, flags); + + queue_kthread_work(&master->kworker, &master->pump_messages); + + return 0; +} + +static int spi_stop_queue(struct spi_master *master) +{ + unsigned long flags; + unsigned limit = 500; + int ret = 0; + + spin_lock_irqsave(&master->queue_lock, flags); + + /* + * This is a bit lame, but is optimized for the common execution path. + * A wait_queue on the master->busy could be used, but then the common + * execution path (pump_messages) would be required to call wake_up or + * friends on every SPI message. Do this instead. + */ + while ((!list_empty(&master->queue) || master->busy) && limit--) { + spin_unlock_irqrestore(&master->queue_lock, flags); + msleep(10); + spin_lock_irqsave(&master->queue_lock, flags); + } + + if (!list_empty(&master->queue) || master->busy) + ret = -EBUSY; + else + master->running = false; + + spin_unlock_irqrestore(&master->queue_lock, flags); + + if (ret) { + dev_warn(&master->dev, + "could not stop message queue\n"); + return ret; + } + return ret; +} + +static int spi_destroy_queue(struct spi_master *master) +{ + int ret; + + ret = spi_stop_queue(master); + + /* + * flush_kthread_worker will block until all work is done. + * If the reason that stop_queue timed out is that the work will never + * finish, then it does no good to call flush/stop thread, so + * return anyway. + */ + if (ret) { + dev_err(&master->dev, "problem destroying queue\n"); + return ret; + } + + flush_kthread_worker(&master->kworker); + kthread_stop(master->kworker_task); + + return 0; +} + +/** + * spi_queued_transfer - transfer function for queued transfers + * @spi: spi device which is requesting transfer + * @msg: spi message which is to handled is queued to driver queue + */ +static int spi_queued_transfer(struct spi_device *spi, struct spi_message *msg) +{ + struct spi_master *master = spi->master; + unsigned long flags; + + spin_lock_irqsave(&master->queue_lock, flags); + + if (!master->running) { + spin_unlock_irqrestore(&master->queue_lock, flags); + return -ESHUTDOWN; + } + msg->actual_length = 0; + msg->status = -EINPROGRESS; + + list_add_tail(&msg->queue, &master->queue); + if (master->running && !master->busy) + queue_kthread_work(&master->kworker, &master->pump_messages); + + spin_unlock_irqrestore(&master->queue_lock, flags); + return 0; +} + +static int spi_master_initialize_queue(struct spi_master *master) +{ + int ret; + + master->queued = true; + master->transfer = spi_queued_transfer; + + /* Initialize and start queue */ + ret = spi_init_queue(master); + if (ret) { + dev_err(&master->dev, "problem initializing queue\n"); + goto err_init_queue; + } + ret = spi_start_queue(master); + if (ret) { + dev_err(&master->dev, "problem starting queue\n"); + goto err_start_queue; + } + + return 0; + +err_start_queue: +err_init_queue: + spi_destroy_queue(master); + return ret; +} + +/*-------------------------------------------------------------------------*/ + static void spi_master_release(struct device *dev) { struct spi_master *master; @@ -522,6 +812,7 @@ struct class spi_master_class = { }; EXPORT_SYMBOL_GPL(spi_master_class); + /** * spi_alloc_master - allocate SPI master controller * @dev: the controller, possibly using the platform_bus @@ -621,6 +912,17 @@ int spi_register_master(struct spi_master *master) dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev), dynamic ? " (dynamic)" : ""); + /* If we're using a queued driver, start the queue */ + if (master->transfer) + dev_info(dev, "master is unqueued, this is deprecated\n"); + else { + status = spi_master_initialize_queue(master); + if (status) { + device_unregister(&master->dev); + goto done; + } + } + mutex_lock(&board_lock); list_add_tail(&master->list, &spi_master_list); list_for_each_entry(bi, &board_list, list) @@ -636,7 +938,6 @@ int spi_register_master(struct spi_master *master) } EXPORT_SYMBOL_GPL(spi_register_master); - static int __unregister(struct device *dev, void *null) { spi_unregister_device(to_spi_device(dev)); @@ -657,6 +958,11 @@ void spi_unregister_master(struct spi_master *master) { int dummy; + if (master->queued) { + if (spi_destroy_queue(master)) + dev_err(&master->dev, "queue remove failed\n"); + } + mutex_lock(&board_lock); list_del(&master->list); mutex_unlock(&board_lock); @@ -666,6 +972,37 @@ void spi_unregister_master(struct spi_master *master) } EXPORT_SYMBOL_GPL(spi_unregister_master); +int spi_master_suspend(struct spi_master *master) +{ + int ret; + + /* Basically no-ops for non-queued masters */ + if (!master->queued) + return 0; + + ret = spi_stop_queue(master); + if (ret) + dev_err(&master->dev, "queue stop failed\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(spi_master_suspend); + +int spi_master_resume(struct spi_master *master) +{ + int ret; + + if (!master->queued) + return 0; + + ret = spi_start_queue(master); + if (ret) + dev_err(&master->dev, "queue restart failed\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(spi_master_resume); + static int __spi_master_match(struct device *dev, void *data) { struct spi_master *m; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 62e566e2abb84..1d92916fc9f24 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -22,6 +22,7 @@ #include #include #include +#include /* * INTERFACES between SPI master-side drivers and SPI infrastructure. @@ -235,6 +236,27 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * the device whose settings are being modified. * @transfer: adds a message to the controller's transfer queue. * @cleanup: frees controller-specific state + * @queued: whether this master is providing an internal message queue + * @kworker: thread struct for message pump + * @kworker_task: pointer to task for message pump kworker thread + * @pump_messages: work struct for scheduling work to the message pump + * @queue_lock: spinlock to syncronise access to message queue + * @queue: message queue + * @cur_msg: the currently in-flight message + * @busy: message pump is busy + * @running: message pump is running + * @rt: whether this queue is set to run as a realtime task + * @prepare_transfer_hardware: a message will soon arrive from the queue + * so the subsystem requests the driver to prepare the transfer hardware + * by issuing this call + * @transfer_one_message: the subsystem calls the driver to transfer a single + * message while queuing transfers that arrive in the meantime. When the + * driver is finished with this message, it must call + * spi_finalize_current_message() so the subsystem can issue the next + * transfer + * @prepare_transfer_hardware: there are currently no more messages on the + * queue so the subsystem notifies the driver that it may relax the + * hardware by issuing this call * * Each SPI master controller can communicate with one or more @spi_device * children. These make a small bus, sharing MOSI, MISO and SCK signals @@ -318,6 +340,28 @@ struct spi_master { /* called on release() to free memory provided by spi_master */ void (*cleanup)(struct spi_device *spi); + + /* + * These hooks are for drivers that want to use the generic + * master transfer queueing mechanism. If these are used, the + * transfer() function above must NOT be specified by the driver. + * Over time we expect SPI drivers to be phased over to this API. + */ + bool queued; + struct kthread_worker kworker; + struct task_struct *kworker_task; + struct kthread_work pump_messages; + spinlock_t queue_lock; + struct list_head queue; + struct spi_message *cur_msg; + bool busy; + bool running; + bool rt; + + int (*prepare_transfer_hardware)(struct spi_master *master); + int (*transfer_one_message)(struct spi_master *master, + struct spi_message *mesg); + int (*unprepare_transfer_hardware)(struct spi_master *master); }; static inline void *spi_master_get_devdata(struct spi_master *master) @@ -343,6 +387,13 @@ static inline void spi_master_put(struct spi_master *master) put_device(&master->dev); } +/* PM calls that need to be issued by the driver */ +extern int spi_master_suspend(struct spi_master *master); +extern int spi_master_resume(struct spi_master *master); + +/* Calls the driver make to interact with the message queue */ +extern struct spi_message *spi_get_next_queued_message(struct spi_master *master); +extern void spi_finalize_current_message(struct spi_master *master); /* the spi driver core manages memory for the spi_master classdev */ extern struct spi_master * From 5cd8649bb365175b44ff99140790c0b6e7472f2f Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Thu, 10 May 2012 19:20:41 +0530 Subject: [PATCH 174/261] spi: Dont call prepare/unprepare transfer if not populated Currently the prepare/unprepare transfer are called unconditionally. The assumption is that every driver using the spi core queue infrastructure has to populate the prepare and unprepare functions. This encourages drivers to populate empty functions to prevent crashing. This patch prevents the call to prepare/unprepare if not populated. Signed-off-by: Shubhrajyoti D Acked-by: Linus Walleij [grant.likely: fix whitespace defect] Signed-off-by: Grant Likely --- drivers/spi/spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 41402344166d1..c063f07a5dc27 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -530,7 +530,7 @@ static void spi_pump_messages(struct kthread_work *work) /* Lock queue and check for queue work */ spin_lock_irqsave(&master->queue_lock, flags); if (list_empty(&master->queue) || !master->running) { - if (master->busy) { + if (master->busy && master->unprepare_transfer_hardware) { ret = master->unprepare_transfer_hardware(master); if (ret) { dev_err(&master->dev, @@ -559,7 +559,7 @@ static void spi_pump_messages(struct kthread_work *work) master->busy = true; spin_unlock_irqrestore(&master->queue_lock, flags); - if (!was_busy) { + if (!was_busy && master->prepare_transfer_hardware) { ret = master->prepare_transfer_hardware(master); if (ret) { dev_err(&master->dev, From 9c9beb517bdddd11021891880baffe1dfc878db6 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 19 Jul 2012 13:27:52 +0200 Subject: [PATCH 175/261] spi: Sync spi-xcomm to the latest version Signed-off-by: Lars-Peter Clausen --- drivers/spi/Kconfig | 1 - drivers/spi/spi-xcomm.c | 279 ++++++++++++++++++++++------------------ 2 files changed, 152 insertions(+), 128 deletions(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 8f35d0ffaf0f7..762b495cb857a 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -362,7 +362,6 @@ config SPI_TXX9 config SPI_XCOMM tristate "SPI-I2C-bridge driver for the ADI Xcomm board" depends on I2C - select SPI_BITBANG help Support for the SPI-I2C-bridge IC found on the ADI Xcomm board. diff --git a/drivers/spi/spi-xcomm.c b/drivers/spi/spi-xcomm.c index 2996621a2a788..788c413c66e92 100644 --- a/drivers/spi/spi-xcomm.c +++ b/drivers/spi/spi-xcomm.c @@ -1,86 +1,80 @@ +/* + * Analog Devices AD-FMCOMMS1-EBZ board I2C-SPI bridge driver + * + * Copyright 2012 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2 or later. + */ + #include #include #include #include #include - - #include #include -#include +#include +#define SPI_XCOMM_SETTINGS_LEN_OFFSET 10 #define SPI_XCOMM_SETTINGS_3WIRE BIT(6) -#define SPI_XCOMM_SETTINGS_CS_HIGH BIT(5) -#define SPI_XCOMM_SETTINGS_SAMPLE_END BIT(4) -#define SPI_XCOMM_SETTINGS_CPHA BIT(3) -#define SPI_XCOMM_SETTINGS_CPOL BIT(2) -#define SPI_XCOMM_SETTINGS_CLOCK_DIV_MASK 0x3 -#define SPI_XCOMM_SETTINGS_CLOCK_DIV_64 0x2 -#define SPI_XCOMM_SETTINGS_CLOCK_DIV_16 0x1 -#define SPI_XCOMM_SETTINGS_CLOCK_DIV_4 0x0 +#define SPI_XCOMM_SETTINGS_CS_HIGH BIT(5) +#define SPI_XCOMM_SETTINGS_SAMPLE_END BIT(4) +#define SPI_XCOMM_SETTINGS_CPHA BIT(3) +#define SPI_XCOMM_SETTINGS_CPOL BIT(2) +#define SPI_XCOMM_SETTINGS_CLOCK_DIV_MASK 0x3 +#define SPI_XCOMM_SETTINGS_CLOCK_DIV_64 0x2 +#define SPI_XCOMM_SETTINGS_CLOCK_DIV_16 0x1 +#define SPI_XCOMM_SETTINGS_CLOCK_DIV_4 0x0 #define SPI_XCOMM_CMD_UPDATE_CONFIG 0x03 #define SPI_XCOMM_CMD_WRITE 0x04 -unsigned bus_num = 0; +#define SPI_XCOMM_CLOCK 48000000 struct spi_xcomm { - struct spi_bitbang bitbang; /* keep this one here !!! */ struct i2c_client *i2c; + uint16_t settings; uint16_t chipselect; - unsigned int clock; unsigned int current_speed; + + uint8_t buf[63]; }; -static int spi_xcomm_sync_config(struct spi_xcomm *spi_xcomm) +static int spi_xcomm_sync_config(struct spi_xcomm *spi_xcomm, unsigned int len) { - uint8_t buf[5]; + uint16_t settings; + uint8_t *buf = spi_xcomm->buf; + + settings = spi_xcomm->settings; + settings |= len << SPI_XCOMM_SETTINGS_LEN_OFFSET; buf[0] = SPI_XCOMM_CMD_UPDATE_CONFIG; - buf[1] = spi_xcomm->settings >> 8; - buf[2] = spi_xcomm->settings & 0xff; - buf[3] = spi_xcomm->chipselect >> 8; - buf[4] = spi_xcomm->chipselect & 0xff; + put_unaligned_be16(settings, &buf[1]); + put_unaligned_be16(spi_xcomm->chipselect, &buf[3]); return i2c_master_send(spi_xcomm->i2c, buf, 5); } - - -static void spi_xcomm_chipselect(struct spi_device *spi, int is_active) +static void spi_xcomm_chipselect(struct spi_xcomm *spi_xcomm, + struct spi_device *spi, int is_active) { - struct spi_xcomm *spi_xcomm = spi_master_get_devdata(spi->master); unsigned long cs = spi->chip_select; uint16_t chipselect = spi_xcomm->chipselect; - uint16_t settings = spi_xcomm->settings; -// static int cs = 0; - if (is_active) { - settings &= ~BIT(5); + if (is_active) chipselect |= BIT(cs); - } else { - settings |= BIT(5); + else chipselect &= ~BIT(cs); - } - - if (chipselect != spi_xcomm->chipselect || settings != spi_xcomm->settings) { - spi_xcomm->chipselect = chipselect; - spi_xcomm->settings = settings; - spi_xcomm_sync_config(spi_xcomm); - } -// if (!is_active) { -// printk("cs: %d\n", cs); -// cs = (cs + 1) % 16; -// } + spi_xcomm->chipselect = chipselect; } -static int spi_xcomm_setup_transfer(struct spi_device *spi, - struct spi_transfer *t) + +static int spi_xcomm_setup_transfer(struct spi_xcomm *spi_xcomm, + struct spi_device *spi, struct spi_transfer *t, unsigned int *settings) { - struct spi_xcomm *spi_xcomm = spi_master_get_devdata(spi->master); - unsigned int settings = spi_xcomm->settings; unsigned int speed; if ((t->bits_per_word && t->bits_per_word != 8) || t->len > 62) @@ -89,83 +83,133 @@ static int spi_xcomm_setup_transfer(struct spi_device *spi, speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz; if (speed != spi_xcomm->current_speed) { - unsigned int divider = spi_xcomm->clock / speed; - if (divider >= 64 || 1) - settings |= SPI_XCOMM_SETTINGS_CLOCK_DIV_64; + unsigned int divider = DIV_ROUND_UP(SPI_XCOMM_CLOCK, speed); + if (divider >= 64) + *settings |= SPI_XCOMM_SETTINGS_CLOCK_DIV_64; else if (divider >= 16) - settings |= SPI_XCOMM_SETTINGS_CLOCK_DIV_16; + *settings |= SPI_XCOMM_SETTINGS_CLOCK_DIV_16; else - settings |= SPI_XCOMM_SETTINGS_CLOCK_DIV_4; + *settings |= SPI_XCOMM_SETTINGS_CLOCK_DIV_4; spi_xcomm->current_speed = speed; } if (spi->mode & SPI_CPOL) - settings |= SPI_XCOMM_SETTINGS_CPOL; + *settings |= SPI_XCOMM_SETTINGS_CPOL; else - settings &= ~SPI_XCOMM_SETTINGS_CPOL; + *settings &= ~SPI_XCOMM_SETTINGS_CPOL; - if (!(spi->mode & SPI_CPHA)) - settings |= SPI_XCOMM_SETTINGS_CPHA; + if (spi->mode & SPI_CPHA) + *settings &= ~SPI_XCOMM_SETTINGS_CPHA; else - settings &= ~SPI_XCOMM_SETTINGS_CPHA; + *settings |= SPI_XCOMM_SETTINGS_CPHA; if (spi->mode & SPI_3WIRE) - settings |= SPI_XCOMM_SETTINGS_3WIRE; + *settings |= SPI_XCOMM_SETTINGS_3WIRE; else - settings &= ~SPI_XCOMM_SETTINGS_3WIRE; - - if (settings != spi_xcomm->settings) { - spi_xcomm->settings = settings; - spi_xcomm_sync_config(spi_xcomm); - } + *settings &= ~SPI_XCOMM_SETTINGS_3WIRE; return 0; } -static int spi_xcomm_txrx_bufs(struct spi_device *spi, struct spi_transfer *t, bool is_last) +static int spi_xcomm_txrx_bufs(struct spi_xcomm *spi_xcomm, + struct spi_device *spi, struct spi_transfer *t) { - struct spi_xcomm *spi_xcomm = spi_master_get_devdata(spi->master); int ret; - unsigned int settings = spi_xcomm->settings; - - if (is_last) - settings |= BIT(5); - else - settings &= ~BIT(5); if (t->tx_buf) { - uint8_t buf[63]; - if (settings != spi_xcomm->settings) { - spi_xcomm->settings = settings; - spi_xcomm_sync_config(spi_xcomm); - } - buf[0] = SPI_XCOMM_CMD_WRITE; - memcpy(buf + 1, t->tx_buf, t->len); + spi_xcomm->buf[0] = SPI_XCOMM_CMD_WRITE; + memcpy(spi_xcomm->buf + 1, t->tx_buf, t->len); - ret = i2c_master_send(spi_xcomm->i2c, buf, t->len + 1); + ret = i2c_master_send(spi_xcomm->i2c, spi_xcomm->buf, t->len + 1); if (ret < 0) return ret; else if (ret != t->len + 1) return -EIO; } else if (t->rx_buf) { - uint8_t rx_buf[t->len + 1]; - spi_xcomm->settings = settings & ~(0x3f << 10); - spi_xcomm->settings |= /*(t->len == 1 ? 2 :*/ t->len/*)*/ << 10; - spi_xcomm_sync_config(spi_xcomm); - spi_xcomm->settings &= ~(0x3f << 10); - - ret = i2c_master_recv(spi_xcomm->i2c, rx_buf, /*t->len == 1 ? 2 : */t->len); + ret = i2c_master_recv(spi_xcomm->i2c, t->rx_buf, t->len); if (ret < 0) return ret; - else if (ret != /*(t->len == 1 ? 2 : */t->len/*)*/) + else if (ret != t->len) return -EIO; - memcpy(t->rx_buf, rx_buf, t->len); } -// msleep(3); + return t->len; } +static int spi_xcomm_transfer_one(struct spi_master *master, + struct spi_message *msg) +{ + struct spi_xcomm *spi_xcomm = spi_master_get_devdata(master); + unsigned int settings = spi_xcomm->settings; + struct spi_device *spi = msg->spi; + unsigned cs_change = 0; + struct spi_transfer *t; + bool is_first = true; + int status = 0; + bool is_last; + + is_first = true; + + spi_xcomm_chipselect(spi_xcomm, spi, true); + + list_for_each_entry(t, &msg->transfers, transfer_list) { + + if (!t->tx_buf && !t->rx_buf && t->len) { + status = -EINVAL; + break; + } + + status = spi_xcomm_setup_transfer(spi_xcomm, spi, t, &settings); + if (status < 0) + break; + + is_last = list_is_last(&t->transfer_list, &msg->transfers); + cs_change = t->cs_change; + + if (cs_change ^ is_last) + settings |= BIT(5); + else + settings &= ~BIT(5); + + if (t->rx_buf) { + spi_xcomm->settings = settings; + status = spi_xcomm_sync_config(spi_xcomm, t->len); + if (status < 0) + break; + } else if (settings != spi_xcomm->settings || is_first) { + spi_xcomm->settings = settings; + status = spi_xcomm_sync_config(spi_xcomm, 0); + if (status < 0) + break; + } + + if (t->len) { + status = spi_xcomm_txrx_bufs(spi_xcomm, spi, t); + + if (status < 0) + break; + + if (status > 0) + msg->actual_length += status; + } + status = 0; + + if (t->delay_usecs) + udelay(t->delay_usecs); + + is_first = false; + } + + if (status != 0 || !cs_change) + spi_xcomm_chipselect(spi_xcomm, spi, false); + + msg->status = status; + spi_finalize_current_message(master); + + return status; +} + static int spi_xcomm_setup(struct spi_device *spi) { if (spi->bits_per_word != 8) @@ -177,58 +221,49 @@ static int spi_xcomm_setup(struct spi_device *spi) static int __devinit spi_xcomm_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { - uint8_t buf[] = {0x2}; - int ret; - struct spi_master *master; + static unsigned int bus_num; struct spi_xcomm *spi_xcomm; + struct spi_master *master; + int ret; master = spi_alloc_master(&i2c->dev, sizeof(*spi_xcomm)); if (!master) return -ENOMEM; spi_xcomm = spi_master_get_devdata(master); - i2c_set_clientdata(i2c, spi_xcomm); spi_xcomm->i2c = i2c; - master->dev.of_node = i2c->dev.of_node; master->num_chipselect = 16; - master->setup = spi_xcomm_setup; - master->cleanup = spi_bitbang_cleanup; - - spi_xcomm->bitbang.master = spi_master_get(master); - spi_xcomm->bitbang.master->bus_num = bus_num++; - spi_xcomm->bitbang.chipselect = spi_xcomm_chipselect; - - spi_xcomm->bitbang.setup_transfer = spi_xcomm_setup_transfer; - spi_xcomm->bitbang.txrx_bufs = spi_xcomm_txrx_bufs; - master->flags = SPI_MASTER_HALF_DUPLEX; - master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_3WIRE; + master->flags = SPI_MASTER_HALF_DUPLEX; + master->setup = spi_xcomm_setup; + master->transfer_one_message = spi_xcomm_transfer_one; + master->bus_num = bus_num++; + master->dev.of_node = i2c->dev.of_node; + i2c_set_clientdata(i2c, master); - spi_xcomm->clock = 48000000; - - ret = spi_bitbang_start(&spi_xcomm->bitbang); + ret = spi_register_master(master); if (ret < 0) spi_master_put(master); - i2c_master_send(i2c, buf, 1); + /* Let the LED blink */ + spi_xcomm->buf[0] = 0x2; + i2c_master_send(i2c, spi_xcomm->buf, 1); return ret; } static int __devexit spi_xcomm_remove(struct i2c_client *i2c) { - struct spi_xcomm *spi_xcomm = i2c_get_clientdata(i2c); - int ret; + struct spi_master *master = i2c_get_clientdata(i2c); - ret = spi_bitbang_stop(&spi_xcomm->bitbang); - spi_master_put(spi_xcomm->bitbang.master); + spi_unregister_master(master); - return ret; + return 0; } static const struct i2c_device_id spi_xcomm_ids[] = { - { "spi-xcomm", 0 }, + { "spi-xcomm" }, { }, }; @@ -241,18 +276,8 @@ static struct i2c_driver spi_xcomm_driver = { .probe = spi_xcomm_probe, .remove = __devexit_p(spi_xcomm_remove), }; -/*module_i2c_driver(spi_xcomm_driver);*/ - -static int __init spi_xcomm_init(void) -{ - return i2c_add_driver(&spi_xcomm_driver); -} -module_init(spi_xcomm_init); - -static void __exit spi_xcomm_exit(void) -{ - i2c_del_driver(&spi_xcomm_driver); -} -module_exit(spi_xcomm_exit); +module_i2c_driver(spi_xcomm_driver); MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("Analog Devices AD-FMCOMMS1-EBZ board I2C-SPI bridge driver"); From 5bdca7e26a07158ae9fba7e98f63effafbf2bcfa Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 19 Jul 2012 19:04:24 +0200 Subject: [PATCH 176/261] zynq-zed-adv7511.dts: Fix memory size Signed-off-by: Lars-Peter Clausen --- arch/arm/boot/dts/zynq-zed-adv7511.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/zynq-zed-adv7511.dts b/arch/arm/boot/dts/zynq-zed-adv7511.dts index d09e58656672c..10ee4be89e4b2 100644 --- a/arch/arm/boot/dts/zynq-zed-adv7511.dts +++ b/arch/arm/boot/dts/zynq-zed-adv7511.dts @@ -9,7 +9,7 @@ memory { device_type = "memory"; - reg = <0x000000000 0x40000000>; + reg = <0x000000000 0x20000000>; }; chosen { // bootargs = "console=ttyPS0,115200 root=/dev/ram rw initrd=0x1100000,33M ip=:::::eth0:dhcp earlyprintk"; From 189a9790ba8a6fc480a25e94c4e91814f48a23b8 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 19 Jul 2012 13:58:16 +0200 Subject: [PATCH 177/261] iio: adc: cf_axi_adc: adjust register layout for latest HDL version Signed-off-by: Michael Hennerich --- drivers/iio/adc/cf_axi_adc.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/iio/adc/cf_axi_adc.h b/drivers/iio/adc/cf_axi_adc.h index 3fd2768afa053..a66c2a3b0ad52 100644 --- a/drivers/iio/adc/cf_axi_adc.h +++ b/drivers/iio/adc/cf_axi_adc.h @@ -14,14 +14,12 @@ /* PCORE CoreFPGA register map */ #define AXIADC_PCORE_VERSION 0x00 -#define AXIADC_PCORE_SPI_CTRL 0x04 -#define AXIADC_PCORE_SPI_RDSTAT 0x08 #define AXIADC_PCORE_DMA_CTRL 0x0C #define AXIADC_PCORE_DMA_STAT 0x10 #define AXIADC_PCORE_ADC_STAT 0x14 #define AXIADC_PCORE_PN_ERR_CTRL 0x24 -#define AXIADC_PCORE_IDENT 0x28 #define AXIADC_PCORE_ADC_CTRL 0x2C +#define AXIADC_PCORE_IDENT 0x30 /* AXIADC_PCORE_SPI_CTRL */ #define AXIADC_SPI_START (1 << 25) From 32ac6decacf4e8f03792498b39d895a9365eaa28 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 20 Jul 2012 10:16:20 +0200 Subject: [PATCH 178/261] iio: frequency: ADF4350: Fix potential reference div factor overflow. With small channel spacing values and high reference frequencies it is possible to exceed the range of the 10-bit counter. Workaround by checking the range and widening some constrains. We don't use the REG1_PHASE value in this case the datasheet recommends to set it to 1 if not used. Signed-off-by: Michael Hennerich --- drivers/iio/frequency/adf4350.c | 24 +++++++++++++++--------- include/linux/iio/frequency/adf4350.h | 2 ++ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 59fbb3ae40e7f..e35bb8f6fe759 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -129,7 +129,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) { struct adf4350_platform_data *pdata = st->pdata; u64 tmp; - u32 div_gcd, prescaler; + u32 div_gcd, prescaler, chspc; u16 mdiv, r_cnt = 0; u8 band_sel_div; @@ -158,14 +158,20 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) if (pdata->ref_div_factor) r_cnt = pdata->ref_div_factor - 1; - do { - r_cnt = adf4350_tune_r_cnt(st, r_cnt); + chspc = st->chspc; - st->r1_mod = st->fpfd / st->chspc; - while (st->r1_mod > ADF4350_MAX_MODULUS) { - r_cnt = adf4350_tune_r_cnt(st, r_cnt); - st->r1_mod = st->fpfd / st->chspc; - } + do { + do { + do { + r_cnt = adf4350_tune_r_cnt(st, r_cnt); + st->r1_mod = st->fpfd / chspc; + if (r_cnt > ADF4350_MAX_R_CNT) { + /* try higher spacing values */ + chspc++; + r_cnt = 0; + } + } while ((st->r1_mod > ADF4350_MAX_MODULUS) && r_cnt); + } while (r_cnt == 0); tmp = freq * (u64)st->r1_mod + (st->fpfd > 1); do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */ @@ -194,7 +200,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) st->regs[ADF4350_REG0] = ADF4350_REG0_INT(st->r0_int) | ADF4350_REG0_FRACT(st->r0_fract); - st->regs[ADF4350_REG1] = ADF4350_REG1_PHASE(0) | + st->regs[ADF4350_REG1] = ADF4350_REG1_PHASE(1) | ADF4350_REG1_MOD(st->r1_mod) | prescaler; diff --git a/include/linux/iio/frequency/adf4350.h b/include/linux/iio/frequency/adf4350.h index b76b4a87065e3..be91f344d5fce 100644 --- a/include/linux/iio/frequency/adf4350.h +++ b/include/linux/iio/frequency/adf4350.h @@ -87,6 +87,8 @@ #define ADF4350_MAX_BANDSEL_CLK 125000 /* Hz */ #define ADF4350_MAX_FREQ_REFIN 250000000 /* Hz */ #define ADF4350_MAX_MODULUS 4095 +#define ADF4350_MAX_R_CNT 1023 + /** * struct adf4350_platform_data - platform specific information From a0c085d4cad474190252333a9b3a27c8feef52c7 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 26 Jul 2012 09:12:43 +0200 Subject: [PATCH 179/261] iio: frequency: adf4350: fix typo - this should be a divide by 2 Signed-off-by: Michael Hennerich --- drivers/iio/frequency/adf4350.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index e35bb8f6fe759..ec427c6980dc2 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -166,14 +166,14 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) r_cnt = adf4350_tune_r_cnt(st, r_cnt); st->r1_mod = st->fpfd / chspc; if (r_cnt > ADF4350_MAX_R_CNT) { - /* try higher spacing values */ + /* dtry higher spacing values */ chspc++; r_cnt = 0; } } while ((st->r1_mod > ADF4350_MAX_MODULUS) && r_cnt); } while (r_cnt == 0); - tmp = freq * (u64)st->r1_mod + (st->fpfd > 1); + tmp = freq * (u64)st->r1_mod + (st->fpfd >> 1); do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */ st->r0_fract = do_div(tmp, st->r1_mod); st->r0_int = tmp; From 83f58d2c122ec641467ad234cc05334a1a13f5d0 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 26 Jul 2012 09:23:25 +0200 Subject: [PATCH 180/261] iio: adc: add CALBISCALE and CALIBBIAS attributes Remove SPI PCORE support Signed-off-by: Michael Hennerich --- drivers/iio/adc/cf_axi_adc.h | 21 +++---- drivers/iio/adc/cf_axi_adc_core.c | 96 +++++++++++++++++++++++++++++-- 2 files changed, 100 insertions(+), 17 deletions(-) diff --git a/drivers/iio/adc/cf_axi_adc.h b/drivers/iio/adc/cf_axi_adc.h index a66c2a3b0ad52..4af9ce2539d23 100644 --- a/drivers/iio/adc/cf_axi_adc.h +++ b/drivers/iio/adc/cf_axi_adc.h @@ -20,18 +20,8 @@ #define AXIADC_PCORE_PN_ERR_CTRL 0x24 #define AXIADC_PCORE_ADC_CTRL 0x2C #define AXIADC_PCORE_IDENT 0x30 - -/* AXIADC_PCORE_SPI_CTRL */ -#define AXIADC_SPI_START (1 << 25) -#define AXIADC_SPI_SEL(x) (((x) & 0x1) << 24) -#define AXIADC_SPI_READ (1 << 23) -#define AXIADC_SPI_WRITE (0 << 23) -#define AXIADC_SPI_ADDR(x) (((x) & 0x1FFF) << 8) -#define AXIADC_SPI_DATA(x) (((x) & 0xFF) << 0) - -/* AXIADC_PCORE_SPI_RDSTAT */ -#define AXIADC_SPI_IDLE (1 << 8) -#define AXIADC_SPI_READVAL(x) ((x) & 0xFF) +#define AXIADC_PCORE_CA_OFFS_SCALE 0x40 +#define AXIADC_PCORE_CB_OFFS_SCALE 0x44 /* AXIADC_PCORE_DMA_CTRL */ #define AXIADC_DMA_CAP_EN (1 << 16) @@ -60,12 +50,19 @@ #define AXIADC_PN9_EN (AXIADC_PN9_0_EN | AXIADC_PN9_1_EN) /* AXIADC_PCORE_ADC_CTRL */ +#define AXIADC_INPUT_FMT_OFFSET_BIN (1 << 3) +#define AXIADC_INPUT_FMT_TWOS_COMPL (0 << 3) +#define AXIADC_SCALE_OFFSET_EN (1 << 2) #define AXIADC_SIGNEXTEND (1 << 1) #define AXIADC_STATUS_EN (1 << 0) /* AXIADC_PCORE_IDENT */ #define AXIADC_PCORE_IDENT_SLAVE 0x1 +/* AXIADC_PCORE_C[A|B]_OFFS_SCALE */ +#define AXIADC_OFFSET(x) (((x) & 0xFFFF) << 16) +#define AXIADC_SCALE(x) ((x) & 0xFFFF) + /* * ADI High-Speed ADC common spi interface registers * See Application-Note AN-877 diff --git a/drivers/iio/adc/cf_axi_adc_core.c b/drivers/iio/adc/cf_axi_adc_core.c index 867354926043f..4a8923d947ebd 100644 --- a/drivers/iio/adc/cf_axi_adc_core.c +++ b/drivers/iio/adc/cf_axi_adc_core.c @@ -86,6 +86,14 @@ static int axiadc_testmode_set(struct iio_dev *indio_dev, return 0; } +static void axiadc_toggle_scale_offset_en(struct axiadc_state *st) +{ + unsigned val = axiadc_read(st, AXIADC_PCORE_ADC_CTRL); + val &= ~AXIADC_SCALE_OFFSET_EN; + axiadc_write(st, AXIADC_PCORE_ADC_CTRL, val); + axiadc_write(st, AXIADC_PCORE_ADC_CTRL, val | AXIADC_SCALE_OFFSET_EN); +} + static int axiadc_debugfs_open(struct inode *inode, struct file *file) { if (inode->i_private) @@ -159,6 +167,11 @@ static int axiadc_dco_calibrate(struct iio_dev *indio_dev) } } + if (cnt > max_cnt) { + max_cnt = cnt; + max_start = start; + } + dco = max_start + (max_cnt / 2); axiadc_testmode_set(indio_dev, 0x3, TESTMODE_OFF); @@ -290,7 +303,8 @@ static int axiadc_read_raw(struct iio_dev *indio_dev, { struct axiadc_state *st = iio_priv(indio_dev); int i; - unsigned vref_val; + unsigned vref_val, tmp; + unsigned long long llval; switch (m) { case IIO_CHAN_INFO_SCALE: @@ -306,7 +320,34 @@ static int axiadc_read_raw(struct iio_dev *indio_dev, *val2 = st->chip_info->scale_table[i][0]; return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_CALIBSCALE: + tmp = axiadc_read(st, (chan->channel == 0) ? + AXIADC_PCORE_CA_OFFS_SCALE : + AXIADC_PCORE_CB_OFFS_SCALE); + + tmp = AXIADC_SCALE(tmp); + if (tmp & 0x8000) + *val = 1; + else + *val = 0; + + tmp &= ~0x8000; + + llval = tmp * 1000000ULL; + do_div(llval, 0x8000); + *val2 = llval; + + return IIO_VAL_INT_PLUS_MICRO; + + case IIO_CHAN_INFO_CALIBBIAS: + tmp = axiadc_read(st, (chan->channel == 0) ? AXIADC_PCORE_CA_OFFS_SCALE : AXIADC_PCORE_CB_OFFS_SCALE); + tmp >>= 16; + *val = sign_extend32(tmp, 14); + + return IIO_VAL_INT; } + + return -EINVAL; } @@ -318,6 +359,8 @@ static int axiadc_write_raw(struct iio_dev *indio_dev, long mask) { struct axiadc_state *st = iio_priv(indio_dev); + unsigned fract, tmp; + unsigned long long llval; int i; switch (mask) { @@ -335,6 +378,38 @@ static int axiadc_write_raw(struct iio_dev *indio_dev, } return -EINVAL; + case IIO_CHAN_INFO_CALIBSCALE: + if (val == 0) + fract = 0; + else if (val == 1) + fract = 0x8000; + else + return -EINVAL; + + llval = (unsigned long long)val2 * 0x8000UL; + do_div(llval, 1000000); + fract |= llval; + tmp = axiadc_read(st, (chan->channel == 0) ? AXIADC_PCORE_CA_OFFS_SCALE : AXIADC_PCORE_CB_OFFS_SCALE); + tmp &= ~AXIADC_SCALE(~0); + tmp |= AXIADC_SCALE(fract); + axiadc_write(st, (chan->channel == 0) ? + AXIADC_PCORE_CA_OFFS_SCALE : + AXIADC_PCORE_CB_OFFS_SCALE, tmp); + axiadc_toggle_scale_offset_en(st); + + return 0; + + case IIO_CHAN_INFO_CALIBBIAS: + tmp = axiadc_read(st, (chan->channel == 0) ? AXIADC_PCORE_CA_OFFS_SCALE : AXIADC_PCORE_CB_OFFS_SCALE); + tmp &= ~AXIADC_OFFSET(~0); + tmp |= AXIADC_OFFSET((short)val); + + axiadc_write(st, (chan->channel == 0) ? + AXIADC_PCORE_CA_OFFS_SCALE : + AXIADC_PCORE_CB_OFFS_SCALE, tmp); + axiadc_toggle_scale_offset_en(st); + return 0; + default: return -EINVAL; } @@ -462,7 +537,9 @@ static struct iio_chan_spec_ext_info axiadc_ext_info[] = { { .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = _chan, \ - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | \ + IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \ .ext_info = axiadc_ext_info, \ .scan_index = _si, \ .scan_type = IIO_ST(_sign, _bits, 16, 0)} @@ -472,7 +549,9 @@ static struct iio_chan_spec_ext_info axiadc_ext_info[] = { .indexed = 1, \ .channel = _chan, \ .extend_name = "frequency_domain", \ - .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | \ + IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \ .scan_index = _si, \ .scan_type = IIO_ST(_sign, _bits, 16, 0)} @@ -553,7 +632,6 @@ static int __devinit axiadc_of_probe(struct platform_device *op) struct axiadc_spidev axiadc_spidev; dma_cap_mask_t mask; resource_size_t remap_size, phys_addr; - unsigned def_mode; int ret; dev_info(dev, "Device Tree Probing \'%s\'\n", @@ -639,11 +717,19 @@ static int __devinit axiadc_of_probe(struct platform_device *op) case CHIPID_AD9467: st->chip_info = &axiadc_chip_info_tbl[ID_AD9467]; st->adc_def_output_mode = AD9467_DEF_OUTPUT_MODE | OUTPUT_MODE_TWOS_COMPLEMENT; + axiadc_write(st, AXIADC_PCORE_ADC_CTRL, AXIADC_SCALE_OFFSET_EN); + axiadc_write(st, AXIADC_PCORE_CA_OFFS_SCALE, + AXIADC_OFFSET(0) | AXIADC_SCALE(0x8000)); break; case CHIPID_AD9643: st->chip_info = &axiadc_chip_info_tbl[ID_AD9643]; st->adc_def_output_mode = AD9643_DEF_OUTPUT_MODE | OUTPUT_MODE_TWOS_COMPLEMENT; - axiadc_write(st, AXIADC_PCORE_ADC_CTRL, AXIADC_SIGNEXTEND); + axiadc_write(st, AXIADC_PCORE_ADC_CTRL, AXIADC_SIGNEXTEND | AXIADC_SCALE_OFFSET_EN); + axiadc_write(st, AXIADC_PCORE_CA_OFFS_SCALE, + AXIADC_OFFSET(0) | AXIADC_SCALE(0x8000)); + axiadc_write(st, AXIADC_PCORE_CB_OFFS_SCALE, + AXIADC_OFFSET(0) | AXIADC_SCALE(0x8000)); + break; default: dev_err(dev, "Unrecognized CHIP_ID 0x%X\n", st->id); From f578cea4bd40203aac027f3d9354dff3681691c4 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 26 Jul 2012 09:26:56 +0200 Subject: [PATCH 181/261] iio: frequency: cf_axi_dds: Miscellaneous changes Add DCI tuning support. Split AD9122 defines into separate header. Restore IQ tuning parameter attributes. Rename some defines. Signed-off-by: Michael Hennerich --- drivers/iio/frequency/ad9122.c | 272 +---------------------- drivers/iio/frequency/ad9122.h | 282 ++++++++++++++++++++++++ drivers/iio/frequency/cf_axi_dds.c | 341 +++++++++++++++++++++++++---- drivers/iio/frequency/cf_axi_dds.h | 51 ++--- 4 files changed, 603 insertions(+), 343 deletions(-) create mode 100644 drivers/iio/frequency/ad9122.h diff --git a/drivers/iio/frequency/ad9122.c b/drivers/iio/frequency/ad9122.c index 2faa9ad66ce89..2913bb1468088 100644 --- a/drivers/iio/frequency/ad9122.c +++ b/drivers/iio/frequency/ad9122.c @@ -16,279 +16,9 @@ #include #include +#include "ad9122.h" #include "cf_axi_dds.h" -/* Registers */ -#define AD9122_REG_COMM 0x00 -#define AD9122_REG_POWER_CTRL 0x01 -#define AD9122_REG_DATA_FORMAT 0x03 -#define AD9122_REG_INTERRUPT_EN_1 0x04 -#define AD9122_REG_INTERRUPT_EN_2 0x05 -#define AD9122_REG_EVENT_FLAG_1 0x06 -#define AD9122_REG_EVENT_FLAG_2 0x07 -#define AD9122_REG_CLK_REC_CTRL 0x08 -#define AD9122_REG_PLL_CTRL_1 0x0A -#define AD9122_REG_PLL_CTRL_2 0x0C -#define AD9122_REG_PLL_CTRL_3 0x0D -#define AD9122_REG_PLL_STATUS_1 0x0E -#define AD9122_REG_PLL_STATUS_2 0x0F -#define AD9122_REG_SYNC_CTRL_1 0x10 -#define AD9122_REG_SYNC_CTRL_2 0x11 -#define AD9122_REG_SYNC_STATUS_1 0x12 -#define AD9122_REG_SYNC_STATUS_2 0x13 -#define AD9122_REG_DATA_REC_STATUS 0x15 -#define AD9122_REG_DCI_DELAY 0x16 -#define AD9122_REG_FIFO_CTRL 0x17 -#define AD9122_REG_FIFO_STATUS_1 0x18 -#define AD9122_REG_FIFO_STATUS_2 0x19 -#define AD9122_REG_DATAPATH_CTRL 0x1B -#define AD9122_REG_HB1_CTRL 0x1C -#define AD9122_REG_HB2_CTRL 0x1D -#define AD9122_REG_HB3_CTRL 0x1E -#define AD9122_REG_CHIP_ID 0x1F -#define AD9122_REG_FTW_7_0 0x30 -#define AD9122_REG_FTW_15_8 0x31 -#define AD9122_REG_FTW_23_16 0x32 -#define AD9122_REG_FTW_31_24 0x33 -#define AD9122_REG_NCO_PHA_OFFSET_LSB 0x34 -#define AD9122_REG_NCO_PHA_OFFSET_MSB 0x35 -#define AD9122_REG_NCO_FTW_UPDATE 0x36 -#define AD9122_REG_I_PHA_ADJ_LSB 0x38 -#define AD9122_REG_I_PHA_ADJ_MSB 0x39 -#define AD9122_REG_Q_PHA_ADJ_LSB 0x3A -#define AD9122_REG_Q_PHA_ADJ_MSB 0x3B -#define AD9122_REG_I_DAC_OFFSET_LSB 0x3C -#define AD9122_REG_I_DAC_OFFSET_MSB 0x3D -#define AD9122_REG_Q_DAC_OFFSET_LSB 0x3E -#define AD9122_REG_Q_DAC_OFFSET_MSB 0x3F -#define AD9122_REG_I_DAC_FS_ADJ 0x40 -#define AD9122_REG_I_DAC_CTRL 0x41 -#define AD9122_REG_I_AUX_DAC_DATA 0x42 -#define AD9122_REG_I_AUX_DAC_CTRL 0x43 -#define AD9122_REG_Q_DAC_FS_ADJ 0x44 -#define AD9122_REG_Q_DAC_CTRL 0x45 -#define AD9122_REG_Q_AUX_DAC_DATA 0x46 -#define AD9122_REG_Q_AUX_DAC_CTRL 0x47 -#define AD9122_REG_DIE_TEMP_RANGE_CTRL 0x48 -#define AD9122_REG_DIE_TEMP_LSB 0x49 -#define AD9122_REG_DIE_TEMP_MSB 0x4A -#define AD9122_REG_SED_CTRL 0x67 -#define AD9122_REG_COMPARE_I0_LSBS 0x68 -#define AD9122_REG_COMPARE_I0_MSBS 0x69 -#define AD9122_REG_COMPARE_Q0_LSBS 0x6A -#define AD9122_REG_COMPARE_Q0_MSBS 0x6B -#define AD9122_REG_COMPARE_I1_LSBS 0x6C -#define AD9122_REG_COMPARE_I1_MSBS 0x6D -#define AD9122_REG_COMPARE_Q1_LSBS 0x6E -#define AD9122_REG_COMPARE_Q1_MSBS 0x6F -#define AD9122_REG_SED_I_LSBS 0x70 -#define AD9122_REG_SED_I_MSBS 0x71 -#define AD9122_REG_SED_Q_LSBS 0x72 -#define AD9122_REG_SED_Q_MSBS 0x73 -#define AD9122_REG_REVISION 0x7F - -/* AD9122_REG_COMM definitions */ -#define AD9122_COMM_SDIO (1 << 7) -#define AD9122_COMM_LSB_FIRST (1 << 6) -#define AD9122_COMM_RESET (1 << 5) - -/* AD9122_REG_POWER_CTRL definitions */ -#define AD9122_POWER_CTRL_PD_I_DAC (1 << 7) -#define AD9122_POWER_CTRL_PD_Q_DAC (1 << 6) -#define AD9122_POWER_CTRL_PD_DATA_REC (1 << 5) -#define AD9122_POWER_CTRL_PD_AUX_ADC (1 << 4) - -/* AD9122_REG_DATA_FORMAT definitions */ -#define AD9122_DATA_FORMAT_BINARY (1 << 7) -#define AD9122_DATA_FORMAT_Q_DATA_FIRST (1 << 6) -#define AD9122_DATA_FORMAT_MSB_SWAP (1 << 5) -#define AD9122_DATA_FORMAT_BUS_WIDTH(x) (((x) & 0x3) << 0) - -/* AD9122_REG_INTERRUPT_EN_1 definitions */ -#define AD9122_INTERRUPT_EN_1_EN_PLL_LOCK_LOST (1 << 7) -#define AD9122_INTERRUPT_EN_1_EN_PLL_LOCKED (1 << 6) -#define AD9122_INTERRUPT_EN_1_EN_SYNC_SIGNAL_LOST (1 << 5) -#define AD9122_INTERRUPT_EN_1_EN_SYNC_SIGNAL_LOCKED (1 << 4) -#define AD9122_INTERRUPT_EN_1_EN_FIFO_WARNING_1 (1 << 1) -#define AD9122_INTERRUPT_EN_1_EN_FIFO_WARNING_2 (1 << 0) - -/* AD9122_REG_INTERRUPT_EN_2 definitions */ -#define AD9122_INTERRUPT_EN_2_EN_AED_COMPARE_PASS (1 << 4) -#define AD9122_INTERRUPT_EN_2_EN_AED_COMPARE_FAIL (1 << 3) -#define AD9122_INTERRUPT_EN_2_EN_SED_COMPARE_FAIL (1 << 2) - -/* AD9122_REG_EVENT_FLAG_1 definitions */ -#define AD9122_EVENT_FLAG_1_PLL_LOCK_LOST (1 << 7) -#define AD9122_EVENT_FLAG_1_PLL_LOCKED (1 << 6) -#define AD9122_EVENT_FLAG_1_SYNC_SIGNAL_LOST (1 << 5) -#define AD9122_EVENT_FLAG_1_SYNC_SIGNAL_LOCKED (1 << 4) -#define AD9122_EVENT_FLAG_1_FIFO_WARNING_1 (1 << 1) -#define AD9122_EVENT_FLAG_1_FIFO_WARNING_2 (1 << 0) - -/* AD9122_REG_EVENT_FLAG_2 definitions */ -#define AD9122_EVENT_FLAG_2_AED_COMPARE_PASS (1 << 4) -#define AD9122_EVENT_FLAG_2_AED_COMPARE_FAIL (1 << 3) -#define AD9122_EVENT_FLAG_2_SED_COMPARE_FAIL (1 << 2) - -/* AD9122_REG_CLK_REC_CTRL definitions */ -#define AD9122_CLK_REC_CTRL_DACCLK_DUTY_CORRECTION (1 << 7) -#define AD9122_CLK_REC_CTRL_REFCLK_DUTY_CORRECTION (1 << 6) -#define AD9122_CLK_REC_CTRL_DACCLK_CROSS_CORRECTION (1 << 5) -#define AD9122_CLK_REC_CTRL_REFCLK_CROSS_CORRECTION (1 << 4) - -/* AD9122_REG_PLL_CTRL_1 definitions */ -#define AD9122_PLL_CTRL_1_PLL_EN (1 << 7) -#define AD9122_PLL_CTRL_1_PLL_MANUAL_EN (1 << 6) -#define AD9122_PLL_CTRL_1_MANUAL_VCO_BAND(x) ((x) & 0x3F) << 0) - -/* AD9122_REG_PLL_CTRL_2 definitions */ -#define AD9122_PLL_CTRL_2_PLL_LOOP_BANDWIDTH(x) (((x) & 0x3) << 6) -#define AD9122_PLL_CTRL_2_PLL_CHARGE_PUMP_CURRENT(x) (((x) & 0x1F) << 0) - -/* AD9122_REG_PLL_CTRL_3 definitions */ -#define AD9122_PLL_CTRL_3_N2(x) (((x) & 0x3) << 6) -#define AD9122_PLL_CTRL_3_PLL_CROSS_CTRL_EN (1 << 4) -#define AD9122_PLL_CTRL_3_N0(x) (((x) & 0x3) << 2) -#define AD9122_PLL_CTRL_3_N1(x) (((x) & 0x3) << 0) - -/* AD9122_REG_PLL_STATUS_1 definitions */ -#define AD9122_PLL_STATUS_1_PLL_LOCKED (1 << 7) -#define AD9122_PLL_STATUS_1_VCO_CTRL_VOLTAGE(x) (((x) & 0xF) << 0) - -/* AD9122_REG_PLL_STATUS_2 definitions */ -#define AD9122_PLL_STATUS_2_VCO_BAND_READBACK(x) (((x) & 0x3F) << 0) - -/* AD9122_REG_SYNC_CTRL_1 definitions */ -#define AD9122_SYNC_CTRL_1_SYNC_EN (1 << 7) -#define AD9122_SYNC_CTRL_1_DATA_FIFO_RATE_TOGGLE (1 << 6) -#define AD9122_SYNC_CTRL_1_RISING_EDGE_SYNC (1 << 3) -#define AD9122_SYNC_CTRL_1_SYNC_AVERAGING(x) (((x) & 0x7) << 0) - -/* AD9122_REG_SYNC_CTRL_2 definitions */ -#define AD9122_SYNC_CTRL_2_SYNC_PHA_REQUEST(x) (((x) & 0x3F) << 0) - -/* AD9122_REG_SYNC_STATUS_1 definitions */ -#define AD9122_SYNC_STATUS_1_SYNC_LOST (1 << 7) -#define AD9122_SYNC_STATUS_1_SYNC_LOCKED (1 << 6) - -/* AD9122_REG_SYNC_STATUS_2 definitions */ -#define AD9122_SYNC_STATUS_2_SYNC_PHA_READBACK (((x) & 0xFF) << 0) - -/* AD9122_REG_DATA_REC_STATUS definitions */ -#define AD9122_DATA_REC_STATUS_LVDS_FRAME_LEVEL_H (1 << 5) -#define AD9122_DATA_REC_STATUS_LVDS_FRAME_LEVEL_L (1 << 4) -#define AD9122_DATA_REC_STATUS_LVDS_DCI_LEVEL_H (1 << 3) -#define AD9122_DATA_REC_STATUS_LVDS_DCI_LEVEL_L (1 << 2) -#define AD9122_DATA_REC_STATUS_LVDS_DATA_LEVEL_H (1 << 1) -#define AD9122_DATA_REC_STATUS_LVDS_DATA_LEVEL_L (1 << 0) - -/* AD9122_REG_DCI_DELAY definitions */ -#define AD9122_DCI_DELAY_DCI_DELAY(x) (((x) & 0x3) << 0) - -/* AD9122_REG_FIFO_CTRL definitions */ -#define AD9122_FIFO_CTRL_FIFO_PHA_OFFSET(x) (((x) & 0x7) << 0) - -/* AD9122_REG_FIFO_STATUS_1 definitions */ -#define AD9122_FIFO_STATUS_1_FIFO_WARNING_1 (1 << 7) -#define AD9122_FIFO_STATUS_1_FIFO_WARNING_2 (1 << 6) -#define AD9122_FIFO_STATUS_1_FIFO_SOFT_ALIGN_ACK (1 << 2) -#define AD9122_FIFO_STATUS_1_FIFO_SOFT_ALIGN_REQ (1 << 1) - -/* AD9122_REG_FIFO_STATUS_2 definitions */ -#define AD9122_FIFO_STATUS_2_FIFO_LEVEL (((x) & 0xFF) << 0) - -/* AD9122_REG_DATAPATH_CTRL definitions */ -#define AD9122_DATAPATH_CTRL_BYPASS_PREMOD (1 << 7) -#define AD9122_DATAPATH_CTRL_BYPASS_INV_SINC (1 << 6) -#define AD9122_DATAPATH_CTRL_BYPASS_NCO (1 << 5) -#define AD9122_DATAPATH_CTRL_NCO_GAIN (1 << 3) -#define AD9122_DATAPATH_CTRL_BYPASS_PHA_COMP_DC_OFFSET (1 << 2) -#define AD9122_DATAPATH_CTRL_SELECT_SIDEBAND (1 << 1) -#define AD9122_DATAPATH_CTRL_SEND_I_DATA_TO_Q_DATA (1 << 0) - -/* AD9122_REG_HB1_CTRL definitions */ -#define AD9122_HB1_CTRL_HB1(x) (((x) & 0x3) << 1) -#define AD9122_HB1_CTRL_BYPASS_HB1 (1 << 0) - -/* AD9122_REG_HB2_CTRL definitions */ -#define AD9122_HB2_CTRL_HB2(x) (((x) & 0x3F) << 1) -#define AD9122_HB2_CTRL_BYPASS_HB2 (1 << 0) - -/* AD9122_REG_HB3_CTRL definitions */ -#define AD9122_HB3_CTRL_HB3(x) (((x) & 0x3F) << 1) -#define AD9122_HB3_CTRL_BYPASS_HB3 (1 << 0) - -/* Value of AD9122_REG_CHIP_ID */ -#define AD9122_CHIP_ID 0x08 - -/* AD9122_REG_NCO_FTW_UPDATE definitions */ -#define AD9122_NCO_FTW_UPDATE_FRAME_FTW_ACK (1 << 5) -#define AD9122_NCO_FTW_UPDATE_FRAME_FTW_REQ (1 << 4) -#define AD9122_NCO_FTW_UPDATE_UPDATE_FTW_ACK (1 << 1) -#define AD9122_NCO_FTW_UPDATE_UPDATE_FTW_REQ (1 << 0) - -/* AD9122_REG_I_PHA_ADJ_LSB definitions */ -#define AD9122_REG_I_PHA_ADJ_7_0(x) (((x) & 0xFF) << 0) - -/* AD9122_REG_I_PHA_ADJ_MSB definitions */ -#define AD9122_REG_I_PHA_ADJ_9_8(x) (((x) & 0x3) << 0) - -/* AD9122_REG_Q_PHA_ADJ_LSB definitions */ -#define AD9122_REG_Q_PHA_ADJ_7_0(x) (((x) & 0xFF) << 0) - -/* AD9122_REG_Q_PHA_ADJ_MSB definitions */ -#define AD9122_REG_Q_PHA_ADJ_9_8(x) (((x) & 0x3) << 0) - -/* AD9122_REG_I_DAC_FS_ADJ definitions */ -#define AD9122_I_DAC_FS_ADJ_I_DAC_FS_ADJ_7_0(x) (((x) & 0xFF) << 0) - -/* AD9122_I_DAC_CTRL definitions */ -#define AD9122_I_DAC_CTRL_I_DAC_SLEEP (1 << 7) -#define AD9122_I_DAC_CTRL_I_DAC_FS_ADJ_9_8(x) (((x) & 0x3) << 0) - -/* AD9122_REG_I_AUX_DAC_DATA definitions */ -#define AD9122_I_AUX_DAC_DATA_I_AUX_DAC_7_0 (((x) & 0xFF) << 0) - -/* AD9122_REG_I_AUX_DAC_CTRL definitions */ -#define AD9122_I_AUX_DAC_CTRL_I_AUX_DAC_SIGN (1 << 7) -#define AD9122_I_AUX_DAC_CTRL_I_AUX_DAC_CURRENT_DIR (1 << 6) -#define AD9122_I_AUX_DAC_CTRL_I_AUX_DAC_SLEEP (1 << 5) -#define AD9122_I_AUX_DAC_CTRL_I_AUX_DAC_9_8(x) (((x) & 0x3) << 0) - -/* AD9122_REG_Q_DAC_FS_ADJ definitions */ -#define AD9122_Q_DAC_FS_ADJ_Q_DAC_FS_ADJ_7_0(x) (((x) & 0xFF) << 0) - -/* AD9122_Q_DAC_CTRL definitions */ -#define AD9122_Q_DAC_CTRL_Q_DAC_SLEEP (1 << 7) -#define AD9122_Q_DAC_CTRL_Q_DAC_FS_ADJ_9_8(x) (((x) & 0x3) << 0) - -/* AD9122_REG_Q_AUX_DAC_DATA definitions */ -#define AD9122_Q_AUX_DAC_DATA_Q_AUX_DAC_7_0 (((x) & 0xFF) << 0) - -/* AD9122_REG_Q_AUX_DAC_CTRL definitions */ -#define AD9122_Q_AUX_DAC_CTRL_Q_AUX_DAC_SIGN (1 << 7) -#define AD9122_Q_AUX_DAC_CTRL_Q_AUX_DAC_CURRENT_DIR (1 << 6) -#define AD9122_Q_AUX_DAC_CTRL_Q_AUX_DAC_SLEEP (1 << 5) -#define AD9122_Q_AUX_DAC_CTRL_Q_AUX_DAC_9_8(x) (((x) & 0x3) << 0) - -/* AD9122_REG_DIE_TEMP_RANGE_CTRL definitions */ -#define AD9122_DIE_TEMP_RANGE_CTRL_FS_CURRENT(x) (((x) & 0x7) << 4) -#define AD9122_DIE_TEMP_RANGE_CTRL_REF_CURRENT(x) (((x) & 0x7) << 1) -#define AD9122_DIE_TEMP_RANGE_CTRL_CAP_VALUE (1 << 0) - -/* AD9122_REG_SED_CTRL definitions */ -#define AD9122_SED_CTRL_SED_COMPARE_EN (1 << 7) -#define AD9122_SED_CTRL_SAMPLE_ERR_DETECTED (1 << 5) -#define AD9122_SED_CTRL_AUTOCLEAR_EN (1 << 3) -#define AD9122_SED_CTRL_COMPARE_FAIL (1 << 1) -#define AD9122_SED_CTRL_COMPARE_PASS (1 << 0) - -/* Values of AD9122_REG_REVISION */ -#define AD9122_DIE_REV_1 0x1 -#define AD9122_DIE_REV_2 0x3 - -#define CHIPID_AD9122 0x8 - static const unsigned char ad9122_reg_defaults[][2] = { {AD9122_REG_COMM, 0x00}, {AD9122_REG_COMM, AD9122_COMM_RESET}, diff --git a/drivers/iio/frequency/ad9122.h b/drivers/iio/frequency/ad9122.h new file mode 100644 index 0000000000000..281bc06c7458b --- /dev/null +++ b/drivers/iio/frequency/ad9122.h @@ -0,0 +1,282 @@ +/* + * AD9122 SPI DAC driver for AXI DDS PCORE/COREFPGA Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#ifndef IIO_FREQUENCY_AD9122_H_ +#define IIO_FREQUENCY_AD9122_H_ + +/* Registers */ +#define AD9122_REG_COMM 0x00 +#define AD9122_REG_POWER_CTRL 0x01 +#define AD9122_REG_DATA_FORMAT 0x03 +#define AD9122_REG_INTERRUPT_EN_1 0x04 +#define AD9122_REG_INTERRUPT_EN_2 0x05 +#define AD9122_REG_EVENT_FLAG_1 0x06 +#define AD9122_REG_EVENT_FLAG_2 0x07 +#define AD9122_REG_CLK_REC_CTRL 0x08 +#define AD9122_REG_PLL_CTRL_1 0x0A +#define AD9122_REG_PLL_CTRL_2 0x0C +#define AD9122_REG_PLL_CTRL_3 0x0D +#define AD9122_REG_PLL_STATUS_1 0x0E +#define AD9122_REG_PLL_STATUS_2 0x0F +#define AD9122_REG_SYNC_CTRL_1 0x10 +#define AD9122_REG_SYNC_CTRL_2 0x11 +#define AD9122_REG_SYNC_STATUS_1 0x12 +#define AD9122_REG_SYNC_STATUS_2 0x13 +#define AD9122_REG_DATA_REC_STATUS 0x15 +#define AD9122_REG_DCI_DELAY 0x16 +#define AD9122_REG_FIFO_CTRL 0x17 +#define AD9122_REG_FIFO_STATUS_1 0x18 +#define AD9122_REG_FIFO_STATUS_2 0x19 +#define AD9122_REG_DATAPATH_CTRL 0x1B +#define AD9122_REG_HB1_CTRL 0x1C +#define AD9122_REG_HB2_CTRL 0x1D +#define AD9122_REG_HB3_CTRL 0x1E +#define AD9122_REG_CHIP_ID 0x1F +#define AD9122_REG_FTW_7_0 0x30 +#define AD9122_REG_FTW_15_8 0x31 +#define AD9122_REG_FTW_23_16 0x32 +#define AD9122_REG_FTW_31_24 0x33 +#define AD9122_REG_NCO_PHA_OFFSET_LSB 0x34 +#define AD9122_REG_NCO_PHA_OFFSET_MSB 0x35 +#define AD9122_REG_NCO_FTW_UPDATE 0x36 +#define AD9122_REG_I_PHA_ADJ_LSB 0x38 +#define AD9122_REG_I_PHA_ADJ_MSB 0x39 +#define AD9122_REG_Q_PHA_ADJ_LSB 0x3A +#define AD9122_REG_Q_PHA_ADJ_MSB 0x3B +#define AD9122_REG_I_DAC_OFFSET_LSB 0x3C +#define AD9122_REG_I_DAC_OFFSET_MSB 0x3D +#define AD9122_REG_Q_DAC_OFFSET_LSB 0x3E +#define AD9122_REG_Q_DAC_OFFSET_MSB 0x3F +#define AD9122_REG_I_DAC_FS_ADJ 0x40 +#define AD9122_REG_I_DAC_CTRL 0x41 +#define AD9122_REG_I_AUX_DAC_DATA 0x42 +#define AD9122_REG_I_AUX_DAC_CTRL 0x43 +#define AD9122_REG_Q_DAC_FS_ADJ 0x44 +#define AD9122_REG_Q_DAC_CTRL 0x45 +#define AD9122_REG_Q_AUX_DAC_DATA 0x46 +#define AD9122_REG_Q_AUX_DAC_CTRL 0x47 +#define AD9122_REG_DIE_TEMP_RANGE_CTRL 0x48 +#define AD9122_REG_DIE_TEMP_LSB 0x49 +#define AD9122_REG_DIE_TEMP_MSB 0x4A +#define AD9122_REG_SED_CTRL 0x67 +#define AD9122_REG_COMPARE_I0_LSBS 0x68 +#define AD9122_REG_COMPARE_I0_MSBS 0x69 +#define AD9122_REG_COMPARE_Q0_LSBS 0x6A +#define AD9122_REG_COMPARE_Q0_MSBS 0x6B +#define AD9122_REG_COMPARE_I1_LSBS 0x6C +#define AD9122_REG_COMPARE_I1_MSBS 0x6D +#define AD9122_REG_COMPARE_Q1_LSBS 0x6E +#define AD9122_REG_COMPARE_Q1_MSBS 0x6F +#define AD9122_REG_SED_I_LSBS 0x70 +#define AD9122_REG_SED_I_MSBS 0x71 +#define AD9122_REG_SED_Q_LSBS 0x72 +#define AD9122_REG_SED_Q_MSBS 0x73 +#define AD9122_REG_REVISION 0x7F + +/* AD9122_REG_COMM definitions */ +#define AD9122_COMM_SDIO (1 << 7) +#define AD9122_COMM_LSB_FIRST (1 << 6) +#define AD9122_COMM_RESET (1 << 5) + +/* AD9122_REG_POWER_CTRL definitions */ +#define AD9122_POWER_CTRL_PD_I_DAC (1 << 7) +#define AD9122_POWER_CTRL_PD_Q_DAC (1 << 6) +#define AD9122_POWER_CTRL_PD_DATA_REC (1 << 5) +#define AD9122_POWER_CTRL_PD_AUX_ADC (1 << 4) + +/* AD9122_REG_DATA_FORMAT definitions */ +#define AD9122_DATA_FORMAT_BINARY (1 << 7) +#define AD9122_DATA_FORMAT_Q_DATA_FIRST (1 << 6) +#define AD9122_DATA_FORMAT_MSB_SWAP (1 << 5) +#define AD9122_DATA_FORMAT_BUS_WIDTH(x) (((x) & 0x3) << 0) + +/* AD9122_REG_INTERRUPT_EN_1 definitions */ +#define AD9122_INTERRUPT_EN_1_EN_PLL_LOCK_LOST (1 << 7) +#define AD9122_INTERRUPT_EN_1_EN_PLL_LOCKED (1 << 6) +#define AD9122_INTERRUPT_EN_1_EN_SYNC_SIGNAL_LOST (1 << 5) +#define AD9122_INTERRUPT_EN_1_EN_SYNC_SIGNAL_LOCKED (1 << 4) +#define AD9122_INTERRUPT_EN_1_EN_FIFO_WARNING_1 (1 << 1) +#define AD9122_INTERRUPT_EN_1_EN_FIFO_WARNING_2 (1 << 0) + +/* AD9122_REG_INTERRUPT_EN_2 definitions */ +#define AD9122_INTERRUPT_EN_2_EN_AED_COMPARE_PASS (1 << 4) +#define AD9122_INTERRUPT_EN_2_EN_AED_COMPARE_FAIL (1 << 3) +#define AD9122_INTERRUPT_EN_2_EN_SED_COMPARE_FAIL (1 << 2) + +/* AD9122_REG_EVENT_FLAG_1 definitions */ +#define AD9122_EVENT_FLAG_1_PLL_LOCK_LOST (1 << 7) +#define AD9122_EVENT_FLAG_1_PLL_LOCKED (1 << 6) +#define AD9122_EVENT_FLAG_1_SYNC_SIGNAL_LOST (1 << 5) +#define AD9122_EVENT_FLAG_1_SYNC_SIGNAL_LOCKED (1 << 4) +#define AD9122_EVENT_FLAG_1_FIFO_WARNING_1 (1 << 1) +#define AD9122_EVENT_FLAG_1_FIFO_WARNING_2 (1 << 0) + +/* AD9122_REG_EVENT_FLAG_2 definitions */ +#define AD9122_EVENT_FLAG_2_AED_COMPARE_PASS (1 << 4) +#define AD9122_EVENT_FLAG_2_AED_COMPARE_FAIL (1 << 3) +#define AD9122_EVENT_FLAG_2_SED_COMPARE_FAIL (1 << 2) + +/* AD9122_REG_CLK_REC_CTRL definitions */ +#define AD9122_CLK_REC_CTRL_DACCLK_DUTY_CORRECTION (1 << 7) +#define AD9122_CLK_REC_CTRL_REFCLK_DUTY_CORRECTION (1 << 6) +#define AD9122_CLK_REC_CTRL_DACCLK_CROSS_CORRECTION (1 << 5) +#define AD9122_CLK_REC_CTRL_REFCLK_CROSS_CORRECTION (1 << 4) + +/* AD9122_REG_PLL_CTRL_1 definitions */ +#define AD9122_PLL_CTRL_1_PLL_EN (1 << 7) +#define AD9122_PLL_CTRL_1_PLL_MANUAL_EN (1 << 6) +#define AD9122_PLL_CTRL_1_MANUAL_VCO_BAND(x) ((x) & 0x3F) << 0) + +/* AD9122_REG_PLL_CTRL_2 definitions */ +#define AD9122_PLL_CTRL_2_PLL_LOOP_BANDWIDTH(x) (((x) & 0x3) << 6) +#define AD9122_PLL_CTRL_2_PLL_CHARGE_PUMP_CURRENT(x) (((x) & 0x1F) << 0) + +/* AD9122_REG_PLL_CTRL_3 definitions */ +#define AD9122_PLL_CTRL_3_N2(x) (((x) & 0x3) << 6) +#define AD9122_PLL_CTRL_3_PLL_CROSS_CTRL_EN (1 << 4) +#define AD9122_PLL_CTRL_3_N0(x) (((x) & 0x3) << 2) +#define AD9122_PLL_CTRL_3_N1(x) (((x) & 0x3) << 0) + +/* AD9122_REG_PLL_STATUS_1 definitions */ +#define AD9122_PLL_STATUS_1_PLL_LOCKED (1 << 7) +#define AD9122_PLL_STATUS_1_VCO_CTRL_VOLTAGE(x) (((x) & 0xF) << 0) + +/* AD9122_REG_PLL_STATUS_2 definitions */ +#define AD9122_PLL_STATUS_2_VCO_BAND_READBACK(x) (((x) & 0x3F) << 0) + +/* AD9122_REG_SYNC_CTRL_1 definitions */ +#define AD9122_SYNC_CTRL_1_SYNC_EN (1 << 7) +#define AD9122_SYNC_CTRL_1_DATA_FIFO_RATE_TOGGLE (1 << 6) +#define AD9122_SYNC_CTRL_1_RISING_EDGE_SYNC (1 << 3) +#define AD9122_SYNC_CTRL_1_SYNC_AVERAGING(x) (((x) & 0x7) << 0) + +/* AD9122_REG_SYNC_CTRL_2 definitions */ +#define AD9122_SYNC_CTRL_2_SYNC_PHA_REQUEST(x) (((x) & 0x3F) << 0) + +/* AD9122_REG_SYNC_STATUS_1 definitions */ +#define AD9122_SYNC_STATUS_1_SYNC_LOST (1 << 7) +#define AD9122_SYNC_STATUS_1_SYNC_LOCKED (1 << 6) + +/* AD9122_REG_SYNC_STATUS_2 definitions */ +#define AD9122_SYNC_STATUS_2_SYNC_PHA_READBACK (((x) & 0xFF) << 0) + +/* AD9122_REG_DATA_REC_STATUS definitions */ +#define AD9122_DATA_REC_STATUS_LVDS_FRAME_LEVEL_H (1 << 5) +#define AD9122_DATA_REC_STATUS_LVDS_FRAME_LEVEL_L (1 << 4) +#define AD9122_DATA_REC_STATUS_LVDS_DCI_LEVEL_H (1 << 3) +#define AD9122_DATA_REC_STATUS_LVDS_DCI_LEVEL_L (1 << 2) +#define AD9122_DATA_REC_STATUS_LVDS_DATA_LEVEL_H (1 << 1) +#define AD9122_DATA_REC_STATUS_LVDS_DATA_LEVEL_L (1 << 0) + +/* AD9122_REG_DCI_DELAY definitions */ +#define AD9122_DCI_DELAY_DCI_DELAY(x) (((x) & 0x3) << 0) + +/* AD9122_REG_FIFO_CTRL definitions */ +#define AD9122_FIFO_CTRL_FIFO_PHA_OFFSET(x) (((x) & 0x7) << 0) + +/* AD9122_REG_FIFO_STATUS_1 definitions */ +#define AD9122_FIFO_STATUS_1_FIFO_WARNING_1 (1 << 7) +#define AD9122_FIFO_STATUS_1_FIFO_WARNING_2 (1 << 6) +#define AD9122_FIFO_STATUS_1_FIFO_SOFT_ALIGN_ACK (1 << 2) +#define AD9122_FIFO_STATUS_1_FIFO_SOFT_ALIGN_REQ (1 << 1) + +/* AD9122_REG_FIFO_STATUS_2 definitions */ +#define AD9122_FIFO_STATUS_2_FIFO_LEVEL (((x) & 0xFF) << 0) + +/* AD9122_REG_DATAPATH_CTRL definitions */ +#define AD9122_DATAPATH_CTRL_BYPASS_PREMOD (1 << 7) +#define AD9122_DATAPATH_CTRL_BYPASS_INV_SINC (1 << 6) +#define AD9122_DATAPATH_CTRL_BYPASS_NCO (1 << 5) +#define AD9122_DATAPATH_CTRL_NCO_GAIN (1 << 3) +#define AD9122_DATAPATH_CTRL_BYPASS_PHA_COMP_DC_OFFSET (1 << 2) +#define AD9122_DATAPATH_CTRL_SELECT_SIDEBAND (1 << 1) +#define AD9122_DATAPATH_CTRL_SEND_I_DATA_TO_Q_DATA (1 << 0) + +/* AD9122_REG_HB1_CTRL definitions */ +#define AD9122_HB1_CTRL_HB1(x) (((x) & 0x3) << 1) +#define AD9122_HB1_CTRL_BYPASS_HB1 (1 << 0) + +/* AD9122_REG_HB2_CTRL definitions */ +#define AD9122_HB2_CTRL_HB2(x) (((x) & 0x3F) << 1) +#define AD9122_HB2_CTRL_BYPASS_HB2 (1 << 0) + +/* AD9122_REG_HB3_CTRL definitions */ +#define AD9122_HB3_CTRL_HB3(x) (((x) & 0x3F) << 1) +#define AD9122_HB3_CTRL_BYPASS_HB3 (1 << 0) + +/* Value of AD9122_REG_CHIP_ID */ +#define AD9122_CHIP_ID 0x08 + +/* AD9122_REG_NCO_FTW_UPDATE definitions */ +#define AD9122_NCO_FTW_UPDATE_FRAME_FTW_ACK (1 << 5) +#define AD9122_NCO_FTW_UPDATE_FRAME_FTW_REQ (1 << 4) +#define AD9122_NCO_FTW_UPDATE_UPDATE_FTW_ACK (1 << 1) +#define AD9122_NCO_FTW_UPDATE_UPDATE_FTW_REQ (1 << 0) + +/* AD9122_REG_I_PHA_ADJ_LSB definitions */ +#define AD9122_REG_I_PHA_ADJ_7_0(x) (((x) & 0xFF) << 0) + +/* AD9122_REG_I_PHA_ADJ_MSB definitions */ +#define AD9122_REG_I_PHA_ADJ_9_8(x) (((x) & 0x3) << 0) + +/* AD9122_REG_Q_PHA_ADJ_LSB definitions */ +#define AD9122_REG_Q_PHA_ADJ_7_0(x) (((x) & 0xFF) << 0) + +/* AD9122_REG_Q_PHA_ADJ_MSB definitions */ +#define AD9122_REG_Q_PHA_ADJ_9_8(x) (((x) & 0x3) << 0) + +/* AD9122_REG_I_DAC_FS_ADJ definitions */ +#define AD9122_I_DAC_FS_ADJ_I_DAC_FS_ADJ_7_0(x) (((x) & 0xFF) << 0) + +/* AD9122_I_DAC_CTRL definitions */ +#define AD9122_I_DAC_CTRL_I_DAC_SLEEP (1 << 7) +#define AD9122_I_DAC_CTRL_I_DAC_FS_ADJ_9_8(x) (((x) & 0x3) << 0) + +/* AD9122_REG_I_AUX_DAC_DATA definitions */ +#define AD9122_I_AUX_DAC_DATA_I_AUX_DAC_7_0 (((x) & 0xFF) << 0) + +/* AD9122_REG_I_AUX_DAC_CTRL definitions */ +#define AD9122_I_AUX_DAC_CTRL_I_AUX_DAC_SIGN (1 << 7) +#define AD9122_I_AUX_DAC_CTRL_I_AUX_DAC_CURRENT_DIR (1 << 6) +#define AD9122_I_AUX_DAC_CTRL_I_AUX_DAC_SLEEP (1 << 5) +#define AD9122_I_AUX_DAC_CTRL_I_AUX_DAC_9_8(x) (((x) & 0x3) << 0) + +/* AD9122_REG_Q_DAC_FS_ADJ definitions */ +#define AD9122_Q_DAC_FS_ADJ_Q_DAC_FS_ADJ_7_0(x) (((x) & 0xFF) << 0) + +/* AD9122_Q_DAC_CTRL definitions */ +#define AD9122_Q_DAC_CTRL_Q_DAC_SLEEP (1 << 7) +#define AD9122_Q_DAC_CTRL_Q_DAC_FS_ADJ_9_8(x) (((x) & 0x3) << 0) + +/* AD9122_REG_Q_AUX_DAC_DATA definitions */ +#define AD9122_Q_AUX_DAC_DATA_Q_AUX_DAC_7_0 (((x) & 0xFF) << 0) + +/* AD9122_REG_Q_AUX_DAC_CTRL definitions */ +#define AD9122_Q_AUX_DAC_CTRL_Q_AUX_DAC_SIGN (1 << 7) +#define AD9122_Q_AUX_DAC_CTRL_Q_AUX_DAC_CURRENT_DIR (1 << 6) +#define AD9122_Q_AUX_DAC_CTRL_Q_AUX_DAC_SLEEP (1 << 5) +#define AD9122_Q_AUX_DAC_CTRL_Q_AUX_DAC_9_8(x) (((x) & 0x3) << 0) + +/* AD9122_REG_DIE_TEMP_RANGE_CTRL definitions */ +#define AD9122_DIE_TEMP_RANGE_CTRL_FS_CURRENT(x) (((x) & 0x7) << 4) +#define AD9122_DIE_TEMP_RANGE_CTRL_REF_CURRENT(x) (((x) & 0x7) << 1) +#define AD9122_DIE_TEMP_RANGE_CTRL_CAP_VALUE (1 << 0) + +/* AD9122_REG_SED_CTRL definitions */ +#define AD9122_SED_CTRL_SED_COMPARE_EN (1 << 7) +#define AD9122_SED_CTRL_SAMPLE_ERR_DETECTED (1 << 5) +#define AD9122_SED_CTRL_AUTOCLEAR_EN (1 << 3) +#define AD9122_SED_CTRL_COMPARE_FAIL (1 << 1) +#define AD9122_SED_CTRL_COMPARE_PASS (1 << 0) + +/* Values of AD9122_REG_REVISION */ +#define AD9122_DIE_REV_1 0x1 +#define AD9122_DIE_REV_2 0x3 + +#define CHIPID_AD9122 0x8 +#endif /* IIO_FREQUENCY_AD9122_H_ */ diff --git a/drivers/iio/frequency/cf_axi_dds.c b/drivers/iio/frequency/cf_axi_dds.c index 0c5a527ee9bf0..6c6c41bfa4802 100644 --- a/drivers/iio/frequency/cf_axi_dds.c +++ b/drivers/iio/frequency/cf_axi_dds.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,7 @@ #define CF_AXI_DDS_WAVDATA #include "cf_axi_dds.h" +#include "ad9122.h" #define DRIVER_NAME "cf_axi_dds" @@ -39,13 +41,13 @@ struct dds_spidev { }; static void cf_axi_dds_sync_frame(struct cf_axi_dds_state *st) { - dds_write(st, CF_AXI_DDS_DDS_FRAME, 0); - dds_write(st, CF_AXI_DDS_DDS_FRAME, CF_AXI_DDS_DDS_FRAME_SYNC); + dds_write(st, CF_AXI_DDS_FRAME, 0); + dds_write(st, CF_AXI_DDS_FRAME, CF_AXI_DDS_FRAME_SYNC); } static void cf_axi_dds_stop(struct cf_axi_dds_state *st) { - dds_write(st, CF_AXI_DDS_DDS_CTRL, (st->vers_id > 1) ? - CF_AXI_DDS_DDS_CTRL_DDS_CLK_EN_V2 : CF_AXI_DDS_DDS_CTRL_DDS_CLK_EN_V1); + dds_write(st, CF_AXI_DDS_CTRL, (st->vers_id > 1) ? + CF_AXI_DDS_CTRL_DDS_CLK_EN_V2 : CF_AXI_DDS_CTRL_DDS_CLK_EN_V1); } static u32 cf_axi_dds_calc(u32 phase, u32 freq, u32 dac_clk) { @@ -64,7 +66,139 @@ static u32 cf_axi_dds_calc(u32 phase, u32 freq, u32 dac_clk) { return val; } -static void cf_axi_dds_mem_init(struct cf_axi_dds_state *st) { +struct cf_axi_dds_sed { + unsigned short i0; + unsigned short q0; + unsigned short i1; + unsigned short q1; +}; + +static struct cf_axi_dds_sed dac_sed_pattern[2] = { + { + .i0 = 0x5555, + .q0 = 0xAAAA, + .i1 = 0xAAAA, + .q1 = 0x5555, + }, + { + .i0 = 0x1248, + .q0 = 0xEDC7, + .i1 = 0xEDC7, + .q1 = 0x1248, + } +}; + +static int cf_axi_dds_find_dci(unsigned long *err_field, unsigned entries) +{ + int dci, cnt, start, max_start, max_cnt; + char str[33]; + int ret; + + for(dci = 0, cnt = 0, max_cnt = 0, start = -1, max_start = 0; + dci < entries; dci++) { + if (test_bit(dci, err_field) == 0) { + if (start == -1) + start = dci; + cnt++; + str[dci] = 'o'; + } else { + if (cnt > max_cnt) { + max_cnt = cnt; + max_start = start; + } + start = -1; + cnt = 0; + str[dci] = '-'; + } + } + str[dci] = 0; + + if (cnt > max_cnt) { + max_cnt = cnt; + max_start = start; + } + + + ret = max_start + (max_cnt / 2); + + str[ret] = '|'; + + printk("%s DCI %d\n",str, ret); + + return ret; +} + +static int cf_axi_dds_tune_dci(struct cf_axi_dds_state *st) +{ + struct cf_axi_dds_converter *conv = to_converter(st->dev_spi); + unsigned reg, err_mask; + int i = 0, dci; + unsigned long err_bfield = 0; + + for (dci = 0; dci < 4; dci++) + for (i = 0; i < ARRAY_SIZE(dac_sed_pattern); i++) { + dds_write(st, CF_AXI_DDS_PAT_DATA1, + (dac_sed_pattern[i].i1 << 16) | + dac_sed_pattern[i].i0); + dds_write(st, CF_AXI_DDS_PAT_DATA2, + (dac_sed_pattern[i].q1 << 16) | + dac_sed_pattern[i].q0); + + dds_write(st, CF_AXI_DDS_CTRL, 0); + dds_write(st, CF_AXI_DDS_CTRL, CF_AXI_DDS_CTRL_DDS_CLK_EN_V2 | + CF_AXI_DDS_CTRL_PATTERN_EN); + dds_write(st, CF_AXI_DDS_CTRL, CF_AXI_DDS_CTRL_DDS_CLK_EN_V2 | + CF_AXI_DDS_CTRL_PATTERN_EN | CF_AXI_DDS_CTRL_DATA_EN); + + conv->write(conv->spi, AD9122_REG_DCI_DELAY, dci); + + conv->write(conv->spi, AD9122_REG_COMPARE_I0_LSBS, + dac_sed_pattern[i].i0 & 0xFF); + conv->write(conv->spi, AD9122_REG_COMPARE_I0_MSBS, + dac_sed_pattern[i].i0 >> 8); + + conv->write(conv->spi, AD9122_REG_COMPARE_Q0_LSBS, + dac_sed_pattern[i].q0 & 0xFF); + conv->write(conv->spi, AD9122_REG_COMPARE_Q0_MSBS, + dac_sed_pattern[i].q0 >> 8); + + conv->write(conv->spi, AD9122_REG_COMPARE_I1_LSBS, + dac_sed_pattern[i].i1 & 0xFF); + conv->write(conv->spi, AD9122_REG_COMPARE_I1_MSBS, + dac_sed_pattern[i].i1 >> 8); + + conv->write(conv->spi, AD9122_REG_COMPARE_Q1_LSBS, + dac_sed_pattern[i].q1 & 0xFF); + conv->write(conv->spi, AD9122_REG_COMPARE_Q1_MSBS, + dac_sed_pattern[i].q1 >> 8); + + + conv->write(conv->spi, AD9122_REG_SED_CTRL, + AD9122_SED_CTRL_SED_COMPARE_EN); + conv->write(conv->spi, AD9122_REG_SED_CTRL, + AD9122_SED_CTRL_SED_COMPARE_EN); + + msleep(50); + reg = conv->read(conv->spi, AD9122_REG_SED_CTRL); + err_mask = conv->read(conv->spi, AD9122_REG_SED_I_LSBS); + err_mask |= conv->read(conv->spi, AD9122_REG_SED_I_MSBS); + err_mask |= conv->read(conv->spi, AD9122_REG_SED_Q_LSBS); + err_mask |= conv->read(conv->spi, AD9122_REG_SED_Q_MSBS); + + if (err_mask || (reg & AD9122_SED_CTRL_SAMPLE_ERR_DETECTED)) + set_bit(dci, &err_bfield); + } + + conv->write(conv->spi, AD9122_REG_DCI_DELAY, + cf_axi_dds_find_dci(&err_bfield, 4)); + conv->write(conv->spi, AD9122_REG_SED_CTRL, 0); + dds_write(st, CF_AXI_DDS_CTRL, 0); + + return 0; +} + +static void cf_axi_dds_mem_init(struct cf_axi_dds_state *st) +{ u32 i, sample, addr, data; @@ -73,10 +207,10 @@ static void cf_axi_dds_mem_init(struct cf_axi_dds_state *st) { for (i = 0; i < ARRAY_SIZE(cf_axi_dds_ia_data); i++) { data = (sample << 24) | (addr << 16); - dds_write(st, CF_AXI_DDS_DDS_MEM_CTRL, ((0 << 26) | data | cf_axi_dds_ia_data[i])); - dds_write(st, CF_AXI_DDS_DDS_MEM_CTRL, ((1 << 26) | data | cf_axi_dds_ib_data[i])); - dds_write(st, CF_AXI_DDS_DDS_MEM_CTRL, ((2 << 26) | data | cf_axi_dds_qa_data[i])); - dds_write(st, CF_AXI_DDS_DDS_MEM_CTRL, ((3 << 26) | data | cf_axi_dds_qb_data[i])); + dds_write(st, CF_AXI_DDS_MEM_CTRL, ((0 << 26) | data | cf_axi_dds_ia_data[i])); + dds_write(st, CF_AXI_DDS_MEM_CTRL, ((1 << 26) | data | cf_axi_dds_ib_data[i])); + dds_write(st, CF_AXI_DDS_MEM_CTRL, ((2 << 26) | data | cf_axi_dds_qa_data[i])); + dds_write(st, CF_AXI_DDS_MEM_CTRL, ((3 << 26) | data | cf_axi_dds_qb_data[i])); sample++; if (sample >= 3) { addr++; @@ -104,9 +238,9 @@ static int cf_axi_dds_read_raw(struct iio_dev *indio_dev, if (!chan->output) { return -EINVAL; } - reg = dds_read(st, CF_AXI_DDS_DDS_CTRL); + reg = dds_read(st, CF_AXI_DDS_CTRL); if (st->vers_id > 1) { - if (reg & 0x2) + if (reg & CF_AXI_DDS_CTRL_DATA_EN) *val = 1; else *val = 0; @@ -119,7 +253,7 @@ static int cf_axi_dds_read_raw(struct iio_dev *indio_dev, } return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - reg = dds_read(st, CF_AXI_DDS_DDS_SCALE); + reg = dds_read(st, CF_AXI_DDS_SCALE); reg = (reg >> (chan->channel * 4)) & 0xF; if (!reg) { *val = 1; @@ -160,7 +294,7 @@ static int cf_axi_dds_write_raw(struct iio_dev *indio_dev, unsigned reg, ctrl_reg; int i; - ctrl_reg = dds_read(st, CF_AXI_DDS_DDS_CTRL); + ctrl_reg = dds_read(st, CF_AXI_DDS_CTRL); switch (mask) { case 0: @@ -170,9 +304,10 @@ static int cf_axi_dds_write_raw(struct iio_dev *indio_dev, if (st->vers_id > 1) { if (val) - ctrl_reg |= 0x3; + ctrl_reg |= (CF_AXI_DDS_CTRL_DATA_EN | + CF_AXI_DDS_CTRL_DDS_CLK_EN_V2); else - ctrl_reg &= ~(0x2); + ctrl_reg &= ~(CF_AXI_DDS_CTRL_DATA_EN); } else { if (val) ctrl_reg |= 1 << (chan->channel * 2); @@ -180,7 +315,7 @@ static int cf_axi_dds_write_raw(struct iio_dev *indio_dev, ctrl_reg &= ~(1 << (chan->channel * 2)); } - dds_write(st, CF_AXI_DDS_DDS_CTRL, ctrl_reg); + dds_write(st, CF_AXI_DDS_CTRL, ctrl_reg); break; case IIO_CHAN_INFO_SCALE: if (val == 1) { @@ -191,12 +326,12 @@ static int cf_axi_dds_write_raw(struct iio_dev *indio_dev, break; } cf_axi_dds_stop(st); - reg = dds_read(st, CF_AXI_DDS_DDS_SCALE); + reg = dds_read(st, CF_AXI_DDS_SCALE); reg &= ~(0xF << (chan->channel * 4)); reg |= (i << (chan->channel * 4)); - dds_write(st, CF_AXI_DDS_DDS_SCALE, reg); - dds_write(st, CF_AXI_DDS_DDS_CTRL, ctrl_reg); + dds_write(st, CF_AXI_DDS_SCALE, reg); + dds_write(st, CF_AXI_DDS_CTRL, ctrl_reg); break; case IIO_CHAN_INFO_FREQUENCY: if (!chan->output) { @@ -212,7 +347,7 @@ static int cf_axi_dds_write_raw(struct iio_dev *indio_dev, do_div(val64, st->dac_clk); reg |= (val64 & 0xFFFF) | 1; dds_write(st, chan->address, reg); - dds_write(st, CF_AXI_DDS_DDS_CTRL, ctrl_reg); + dds_write(st, CF_AXI_DDS_CTRL, ctrl_reg); break; case IIO_CHAN_INFO_PHASE: if (val < 0 || val > 360000) @@ -224,7 +359,7 @@ static int cf_axi_dds_write_raw(struct iio_dev *indio_dev, do_div(val64, 360000); reg |= val64 << 16; dds_write(st, chan->address, reg); - dds_write(st, CF_AXI_DDS_DDS_CTRL, ctrl_reg); + dds_write(st, CF_AXI_DDS_CTRL, ctrl_reg); break; default: return -EINVAL; @@ -264,10 +399,125 @@ static int cf_axi_dds_reg_access(struct iio_dev *indio_dev, return ret; } +static ssize_t ad9122_dds_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct cf_axi_dds_state *st = iio_priv(indio_dev); + struct cf_axi_dds_converter *conv = to_converter(st->dev_spi); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + unsigned long readin; + int ret; + + ret = kstrtoul(buf, 10, &readin); + if (ret) + return ret; + + mutex_lock(&indio_dev->mlock); + + switch ((u32)this_attr->address) { + case AD9122_REG_I_DAC_OFFSET_MSB: + case AD9122_REG_Q_DAC_OFFSET_MSB: + if (readin > 0xFFFF) { + ret = -EINVAL; + goto out; + } + break; + default: + if (readin > 0x3FF) { + ret = -EINVAL; + goto out; + } + break; + } + + ret = conv->write(conv->spi, (u32)this_attr->address, readin >> 8); + if (ret < 0) + goto out; + + ret = conv->write(conv->spi, (u32)this_attr->address - 1, readin & 0xFF); + if (ret < 0) + goto out; + +out: + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static ssize_t ad9122_dds_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct cf_axi_dds_state *st = iio_priv(indio_dev); + struct cf_axi_dds_converter *conv = to_converter(st->dev_spi); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret = 0; + unsigned val; + + mutex_lock(&indio_dev->mlock); + ret = conv->read(conv->spi, (u32)this_attr->address); + if (ret < 0) + goto out; + val = ret << 8; + + ret = conv->read(conv->spi, (u32)this_attr->address - 1); + if (ret < 0) + goto out; + val |= ret & 0xFF; + + ret = sprintf(buf, "%d\n", val); + +out: + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static IIO_DEVICE_ATTR(i_phase_adj, S_IRUGO | S_IWUSR, + ad9122_dds_show, + ad9122_dds_store, + AD9122_REG_I_PHA_ADJ_MSB); + +static IIO_DEVICE_ATTR(q_phase_adj, S_IRUGO | S_IWUSR, + ad9122_dds_show, + ad9122_dds_store, + AD9122_REG_Q_PHA_ADJ_MSB); + +static IIO_DEVICE_ATTR(i_dac_offset, S_IRUGO | S_IWUSR, + ad9122_dds_show, + ad9122_dds_store, + AD9122_REG_I_DAC_OFFSET_MSB); + +static IIO_DEVICE_ATTR(q_dac_offset, S_IRUGO | S_IWUSR, + ad9122_dds_show, + ad9122_dds_store, + AD9122_REG_Q_DAC_OFFSET_MSB); + +static IIO_DEVICE_ATTR(i_dac_fs_adj, S_IRUGO | S_IWUSR, + ad9122_dds_show, + ad9122_dds_store, + AD9122_REG_I_DAC_CTRL); + +static IIO_DEVICE_ATTR(q_dac_fs_adj, S_IRUGO | S_IWUSR, + ad9122_dds_show, + ad9122_dds_store, + AD9122_REG_Q_DAC_CTRL); + + + static IIO_CONST_ATTR(out_altvoltage_scale_available, "1.000000 0.500000 0.250000 0.125000 ..."); static struct attribute *cf_axi_dds_attributes[] = { + &iio_dev_attr_i_phase_adj.dev_attr.attr, + &iio_dev_attr_q_phase_adj.dev_attr.attr, + &iio_dev_attr_i_dac_offset.dev_attr.attr, + &iio_dev_attr_q_dac_offset.dev_attr.attr, + &iio_dev_attr_i_dac_fs_adj.dev_attr.attr, + &iio_dev_attr_q_dac_fs_adj.dev_attr.attr, &iio_const_attr_out_altvoltage_scale_available.dev_attr.attr, NULL, }; @@ -276,7 +526,7 @@ static const struct attribute_group cf_axi_dds_attribute_group = { .attrs = cf_axi_dds_attributes, }; -#define CF_AXI_DDS_DDS_CHAN(_chan, _address, _extend_name) \ +#define CF_AXI_DDS_CHAN(_chan, _address, _extend_name) \ { .type = IIO_ALTVOLTAGE, \ .indexed = 1, \ .channel = _chan, \ @@ -289,7 +539,7 @@ static const struct attribute_group cf_axi_dds_attribute_group = { .extend_name = _extend_name, \ } -#define CF_AXI_DDS_DDS_CHAN_CLK_IN(_chan, _extend_name) \ +#define CF_AXI_DDS_CHAN_CLK_IN(_chan, _extend_name) \ { .type = IIO_ALTVOLTAGE, \ .indexed = 1, \ .channel = _chan, \ @@ -300,19 +550,19 @@ static const struct attribute_group cf_axi_dds_attribute_group = { static const struct cf_axi_dds_chip_info cf_axi_dds_chip_info_tbl[] = { [ID_AD9122] = { .name = "AD9122", - .channel[0] = CF_AXI_DDS_DDS_CHAN(0, CF_AXI_DDS_DDS_1A_OUTPUT_CTRL, "1A"), - .channel[1] = CF_AXI_DDS_DDS_CHAN(1, CF_AXI_DDS_DDS_1B_OUTPUT_CTRL, "1B"), - .channel[2] = CF_AXI_DDS_DDS_CHAN(2, CF_AXI_DDS_DDS_2A_OUTPUT_CTRL, "2A"), - .channel[3] = CF_AXI_DDS_DDS_CHAN(3, CF_AXI_DDS_DDS_2B_OUTPUT_CTRL, "2B"), - .channel[4] = CF_AXI_DDS_DDS_CHAN_CLK_IN(0, "DAC_CLK"), + .channel[0] = CF_AXI_DDS_CHAN(0, CF_AXI_DDS_1A_OUTPUT_CTRL, "1A"), + .channel[1] = CF_AXI_DDS_CHAN(1, CF_AXI_DDS_1B_OUTPUT_CTRL, "1B"), + .channel[2] = CF_AXI_DDS_CHAN(2, CF_AXI_DDS_2A_OUTPUT_CTRL, "2A"), + .channel[3] = CF_AXI_DDS_CHAN(3, CF_AXI_DDS_2B_OUTPUT_CTRL, "2B"), + .channel[4] = CF_AXI_DDS_CHAN_CLK_IN(0, "DAC_CLK"), }, [ID_AD9739A] = { .name = "AD9739A", - .channel[0] = CF_AXI_DDS_DDS_CHAN(0, CF_AXI_DDS_DDS_1A_OUTPUT_CTRL, "1A"), - .channel[1] = CF_AXI_DDS_DDS_CHAN(1, CF_AXI_DDS_DDS_1B_OUTPUT_CTRL, "1B"), - .channel[2] = CF_AXI_DDS_DDS_CHAN(2, CF_AXI_DDS_DDS_2A_OUTPUT_CTRL, "2A"), - .channel[3] = CF_AXI_DDS_DDS_CHAN(3, CF_AXI_DDS_DDS_2B_OUTPUT_CTRL, "2B"), - .channel[4] = CF_AXI_DDS_DDS_CHAN_CLK_IN(0, "DAC_CLK"), + .channel[0] = CF_AXI_DDS_CHAN(0, CF_AXI_DDS_1A_OUTPUT_CTRL, "1A"), + .channel[1] = CF_AXI_DDS_CHAN(1, CF_AXI_DDS_1B_OUTPUT_CTRL, "1B"), + .channel[2] = CF_AXI_DDS_CHAN(2, CF_AXI_DDS_2A_OUTPUT_CTRL, "2A"), + .channel[3] = CF_AXI_DDS_CHAN(3, CF_AXI_DDS_2B_OUTPUT_CTRL, "2B"), + .channel[4] = CF_AXI_DDS_CHAN_CLK_IN(0, "DAC_CLK"), }, }; @@ -448,23 +698,26 @@ static int __devinit cf_axi_dds_of_probe(struct platform_device *op) indio_dev->num_channels = 5; indio_dev->info = &cf_axi_dds_info; + cf_axi_dds_tune_dci(st); + cf_axi_dds_mem_init(st); - dds_write(st, CF_AXI_DDS_DDS_CTRL, 0x0); - dds_write(st, CF_AXI_DDS_DDS_SCALE, 0x1111); /* divide by 4 */ - dds_write(st, CF_AXI_DDS_DDS_1A_OUTPUT_CTRL, + dds_write(st, CF_AXI_DDS_CTRL, 0x0); + dds_write(st, CF_AXI_DDS_SCALE, 0x1111); /* divide by 4 */ + dds_write(st, CF_AXI_DDS_1A_OUTPUT_CTRL, cf_axi_dds_calc(90000, 40000000, st->dac_clk)); - dds_write(st, CF_AXI_DDS_DDS_1B_OUTPUT_CTRL, + dds_write(st, CF_AXI_DDS_1B_OUTPUT_CTRL, cf_axi_dds_calc(90000, 40000000, st->dac_clk)); - dds_write(st, CF_AXI_DDS_DDS_2A_OUTPUT_CTRL, + dds_write(st, CF_AXI_DDS_2A_OUTPUT_CTRL, cf_axi_dds_calc( 0, 40000000, st->dac_clk)); - dds_write(st, CF_AXI_DDS_DDS_2B_OUTPUT_CTRL, + dds_write(st, CF_AXI_DDS_2B_OUTPUT_CTRL, cf_axi_dds_calc( 0, 40000000, st->dac_clk)); if (st->vers_id > 1) - dds_write(st, CF_AXI_DDS_DDS_CTRL, 0x3); /* clk, dds enable & ddsx select */ + dds_write(st, CF_AXI_DDS_CTRL, CF_AXI_DDS_CTRL_DATA_EN | + CF_AXI_DDS_CTRL_DDS_CLK_EN_V2); /* clk, dds enable & ddsx select */ else - dds_write(st, CF_AXI_DDS_DDS_CTRL, 0x1ff); /* clk, dds enable & ddsx select */ + dds_write(st, CF_AXI_DDS_CTRL, 0x1ff); /* clk, dds enable & ddsx select */ cf_axi_dds_sync_frame(st); @@ -474,9 +727,9 @@ static int __devinit cf_axi_dds_of_probe(struct platform_device *op) dev_info(dev, "Analog Devices CF_AXI_DDS_DDS %s (0x%X) at 0x%08llX mapped" " to 0x%p, probed DDS %s\n", - (dds_read(st, CF_AXI_DDS_DDS_PCORE_IDENT) & - CF_AXI_DDS_DDS_PCORE_IDENT_SLAVE) ? "SLAVE" : "MASTER", - dds_read(st, CF_AXI_DDS_DDS_VERSION_ID), + (dds_read(st, CF_AXI_DDS_PCORE_IDENT) & + CF_AXI_DDS_PCORE_IDENT_SLAVE) ? "SLAVE" : "MASTER", + dds_read(st, CF_AXI_DDS_VERSION_ID), (unsigned long long)phys_addr, st->regs, st->chip_info->name); return 0; /* success */ diff --git a/drivers/iio/frequency/cf_axi_dds.h b/drivers/iio/frequency/cf_axi_dds.h index ce9015928f4f1..66e4a6293097b 100644 --- a/drivers/iio/frequency/cf_axi_dds.h +++ b/drivers/iio/frequency/cf_axi_dds.h @@ -41,37 +41,32 @@ * [ 3: 0]: dds scale 1a * ***************************************************************************/ -#define CF_AXI_DDS_DDS_VERSION_ID 0x00 -#define CF_AXI_DDS_DDS_CTRL 0x04 -#define CF_AXI_DDS_DDS_1A_OUTPUT_CTRL 0x08 -#define CF_AXI_DDS_DDS_1B_OUTPUT_CTRL 0x0C -#define CF_AXI_DDS_DDS_2A_OUTPUT_CTRL 0x10 -#define CF_AXI_DDS_DDS_2B_OUTPUT_CTRL 0x14 -#define CF_AXI_DDS_DDS_MEM_CTRL 0x18 -#define CF_AXI_DDS_DDS_SCALE 0x20 -#define CF_AXI_DDS_DDS_FRAME 0x24 -#define CF_AXI_DDS_DDS_PCORE_IDENT 0x48 +#define CF_AXI_DDS_VERSION_ID 0x00 +#define CF_AXI_DDS_CTRL 0x04 +#define CF_AXI_DDS_1A_OUTPUT_CTRL 0x08 +#define CF_AXI_DDS_1B_OUTPUT_CTRL 0x0C +#define CF_AXI_DDS_2A_OUTPUT_CTRL 0x10 +#define CF_AXI_DDS_2B_OUTPUT_CTRL 0x14 +#define CF_AXI_DDS_MEM_CTRL 0x18 +#define CF_AXI_DDS_SCALE 0x20 +#define CF_AXI_DDS_FRAME 0x24 +#define CF_AXI_DDS_PCORE_IDENT 0x30 +#define CF_AXI_DDS_PAT_DATA1 0x40 +#define CF_AXI_DDS_PAT_DATA2 0x44 -#define CF_AXI_DDS_DDS_CTRL_DDS_CLK_EN_V1 (1 << 8) -#define CF_AXI_DDS_DDS_CTRL_DDS_CLK_EN_V2 (1 << 0) +/* CF_AXI_DDS_CTRL */ +#define CF_AXI_DDS_CTRL_PATTERN_EN (1 << 4) +#define CF_AXI_DDS_CTRL_INTERPOLATE (1 << 3) +#define CF_AXI_DDS_CTRL_DDS_SEL (1 << 2) +#define CF_AXI_DDS_CTRL_DATA_EN (1 << 1) +#define CF_AXI_DDS_CTRL_DDS_CLK_EN_V1 (1 << 8) +#define CF_AXI_DDS_CTRL_DDS_CLK_EN_V2 (1 << 0) -/* CF_AXI_DDS_DDS_FRAME */ -#define CF_AXI_DDS_DDS_FRAME_SYNC 0x1 +/* CF_AXI_DDS_FRAME */ +#define CF_AXI_DDS_FRAME_SYNC 0x1 -/* CF_AXI_DDS_DDS_PCORE_IDENT */ -#define CF_AXI_DDS_DDS_PCORE_IDENT_SLAVE 0x1 - -/* AD9122 internal registers */ - -#define AD9122_I_PHASE_ADJ 0x39 -#define AD9122_Q_PHASE_ADJ 0x3B - -#define AD9122_I_DAC_OFFS 0x3D -#define AD9122_Q_DAC_OFFS 0x3F - -#define AD9122_I_DAC_FS_ADJ 0x41 -#define AD9122_Q_DAC_FS_ADJ 0x45 -#define AD9122_I_AUX_DAC 0x43 +/* CF_AXI_DDS_PCORE_IDENT */ +#define CF_AXI_DDS_PCORE_IDENT_SLAVE 0x1 enum { ID_AD9122, From 649b31ed5844a510853e085ad136f07e0f6b33d6 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 27 Jul 2012 10:59:11 +0200 Subject: [PATCH 182/261] Add common config for xcomm on zynq We can use the same kernel for ZED and ZC702, so there is no need to have two different config files. Signed-off-by: Lars-Peter Clausen --- .../arm/configs/xcomm_adv7511_zc702_defconfig | 2456 ----------------- arch/arm/configs/xcomm_adv7511_zed_defconfig | 2418 ---------------- arch/arm/configs/zync_xcomm_adv7511_defconfig | 240 ++ 3 files changed, 240 insertions(+), 4874 deletions(-) delete mode 100644 arch/arm/configs/xcomm_adv7511_zc702_defconfig delete mode 100644 arch/arm/configs/xcomm_adv7511_zed_defconfig create mode 100644 arch/arm/configs/zync_xcomm_adv7511_defconfig diff --git a/arch/arm/configs/xcomm_adv7511_zc702_defconfig b/arch/arm/configs/xcomm_adv7511_zc702_defconfig deleted file mode 100644 index f487907c5faca..0000000000000 --- a/arch/arm/configs/xcomm_adv7511_zc702_defconfig +++ /dev/null @@ -1,2456 +0,0 @@ -# -# Automatically generated file; DO NOT EDIT. -# Linux/arm 3.3.0 Kernel Configuration -# -CONFIG_ARM=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_GENERIC_GPIO=y -# CONFIG_ARCH_USES_GETTIMEOFFSET is not set -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_KTIME_SCALAR=y -CONFIG_HAVE_PROC_CPU=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_TRACE_IRQFLAGS_SUPPORT=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_GENERIC_LOCKBREAK=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_VECTORS_BASE=0xffff0000 -# CONFIG_ARM_PATCH_PHYS_VIRT is not set -CONFIG_PHYS_OFFSET=0x0 -CONFIG_GENERIC_BUG=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -CONFIG_HAVE_IRQ_WORK=y -CONFIG_IRQ_WORK=y - -# -# General setup -# -CONFIG_EXPERIMENTAL=y -CONFIG_INIT_ENV_ARG_LIMIT=32 -CONFIG_CROSS_COMPILE="" -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -CONFIG_HAVE_KERNEL_GZIP=y -CONFIG_HAVE_KERNEL_LZMA=y -CONFIG_HAVE_KERNEL_LZO=y -CONFIG_KERNEL_GZIP=y -# CONFIG_KERNEL_LZMA is not set -# CONFIG_KERNEL_LZO is not set -CONFIG_DEFAULT_HOSTNAME="(none)" -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -CONFIG_SYSVIPC_SYSCTL=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_FHANDLE is not set -# CONFIG_TASKSTATS is not set -# CONFIG_AUDIT is not set -CONFIG_HAVE_GENERIC_HARDIRQS=y - -# -# IRQ subsystem -# -CONFIG_GENERIC_HARDIRQS=y -CONFIG_HAVE_SPARSE_IRQ=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_IRQ_DOMAIN=y -# CONFIG_SPARSE_IRQ is not set - -# -# RCU Subsystem -# -CONFIG_TREE_PREEMPT_RCU=y -CONFIG_PREEMPT_RCU=y -# CONFIG_RCU_TRACE is not set -CONFIG_RCU_FANOUT=32 -# CONFIG_RCU_FANOUT_EXACT is not set -# CONFIG_TREE_RCU_TRACE is not set -# CONFIG_RCU_BOOST is not set -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set -# CONFIG_CHECKPOINT_RESTORE is not set -# CONFIG_NAMESPACES is not set -# CONFIG_SCHED_AUTOGROUP is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y -# CONFIG_RELAY is not set -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_RD_GZIP=y -# CONFIG_RD_BZIP2 is not set -# CONFIG_RD_LZMA is not set -# CONFIG_RD_XZ is not set -# CONFIG_RD_LZO is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SYSCTL=y -CONFIG_ANON_INODES=y -CONFIG_EXPERT=y -CONFIG_UID16=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS=y -CONFIG_KALLSYMS_ALL=y -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_AIO=y -CONFIG_EMBEDDED=y -CONFIG_HAVE_PERF_EVENTS=y -CONFIG_PERF_USE_VMALLOC=y - -# -# Kernel Performance Events And Counters -# -CONFIG_PERF_EVENTS=y -# CONFIG_PERF_COUNTERS is not set -# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_COMPAT_BRK=y -CONFIG_SLAB=y -# CONFIG_SLUB is not set -# CONFIG_SLOB is not set -# CONFIG_PROFILING is not set -CONFIG_HAVE_OPROFILE=y -# CONFIG_KPROBES is not set -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_USE_GENERIC_SMP_HELPERS=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_CLK=y -CONFIG_HAVE_DMA_API_DEBUG=y -CONFIG_HAVE_HW_BREAKPOINT=y - -# -# GCOV-based kernel profiling -# -# CONFIG_GCOV_KERNEL is not set -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_SLABINFO=y -CONFIG_RT_MUTEXES=y -CONFIG_BASE_SMALL=0 -CONFIG_MODULES=y -# CONFIG_MODULE_FORCE_LOAD is not set -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MODVERSIONS=y -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_STOP_MACHINE=y -CONFIG_BLOCK=y -CONFIG_LBDAF=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_BLK_DEV_BSGLIB is not set -# CONFIG_BLK_DEV_INTEGRITY is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_CFQ=y -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" -# CONFIG_INLINE_SPIN_TRYLOCK is not set -# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK is not set -# CONFIG_INLINE_SPIN_LOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK_IRQ is not set -# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set -# CONFIG_INLINE_SPIN_UNLOCK is not set -# CONFIG_INLINE_SPIN_UNLOCK_BH is not set -# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set -# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_READ_TRYLOCK is not set -# CONFIG_INLINE_READ_LOCK is not set -# CONFIG_INLINE_READ_LOCK_BH is not set -# CONFIG_INLINE_READ_LOCK_IRQ is not set -# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set -# CONFIG_INLINE_READ_UNLOCK is not set -# CONFIG_INLINE_READ_UNLOCK_BH is not set -# CONFIG_INLINE_READ_UNLOCK_IRQ is not set -# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_WRITE_TRYLOCK is not set -# CONFIG_INLINE_WRITE_LOCK is not set -# CONFIG_INLINE_WRITE_LOCK_BH is not set -# CONFIG_INLINE_WRITE_LOCK_IRQ is not set -# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set -# CONFIG_INLINE_WRITE_UNLOCK is not set -# CONFIG_INLINE_WRITE_UNLOCK_BH is not set -# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set -# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set -# CONFIG_MUTEX_SPIN_ON_OWNER is not set -# CONFIG_FREEZER is not set - -# -# System Type -# -CONFIG_MMU=y -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_REALVIEW is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_VEXPRESS is not set -# CONFIG_ARCH_AT91 is not set -# CONFIG_ARCH_BCMRING is not set -# CONFIG_ARCH_HIGHBANK is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CNS3XXX is not set -# CONFIG_ARCH_GEMINI is not set -# CONFIG_ARCH_PRIMA2 is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_EP93XX is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_MXC is not set -# CONFIG_ARCH_MXS is not set -# CONFIG_ARCH_NETX is not set -# CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_IOP13XX is not set -# CONFIG_ARCH_IOP32X is not set -# CONFIG_ARCH_IOP33X is not set -# CONFIG_ARCH_IXP23XX is not set -# CONFIG_ARCH_IXP2000 is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_DOVE is not set -# CONFIG_ARCH_KIRKWOOD is not set -# CONFIG_ARCH_LPC32XX is not set -# CONFIG_ARCH_MV78XX0 is not set -# CONFIG_ARCH_ORION5X is not set -# CONFIG_ARCH_MMP is not set -# CONFIG_ARCH_KS8695 is not set -# CONFIG_ARCH_W90X900 is not set -# CONFIG_ARCH_TEGRA is not set -# CONFIG_ARCH_PICOXCELL is not set -# CONFIG_ARCH_PNX4008 is not set -# CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_MSM is not set -# CONFIG_ARCH_SHMOBILE is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_S3C64XX is not set -# CONFIG_ARCH_S5P64X0 is not set -# CONFIG_ARCH_S5PC100 is not set -# CONFIG_ARCH_S5PV210 is not set -# CONFIG_ARCH_EXYNOS is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_U300 is not set -# CONFIG_ARCH_U8500 is not set -# CONFIG_ARCH_NOMADIK is not set -# CONFIG_ARCH_DAVINCI is not set -# CONFIG_ARCH_OMAP is not set -# CONFIG_PLAT_SPEAR is not set -# CONFIG_ARCH_VT8500 is not set -CONFIG_ARCH_ZYNQ=y -# CONFIG_GPIO_PCA953X is not set -# CONFIG_KEYBOARD_GPIO_POLLED is not set - -# -# System MMU -# - -# -# Xilinx Specific Options -# -CONFIG_ZYNQ_EARLY_UART1=y -# CONFIG_ZYNQ_EARLY_UART_EP107 is not set -CONFIG_XILINX_FIXED_DEVTREE_ADDR=y -CONFIG_XILINX_L1_PREFETCH=y -CONFIG_XILINX_L2_PREFETCH=y -CONFIG_XILINX_ZED=y -# CONFIG_XILINX_TEST is not set -CONFIG_ZYNQ_DEFAULT_KERNEL=y -# CONFIG_ZYNQ_AMP_CPU0_MASTER is not set -# CONFIG_ZYNQ_AMP_CPU1_SLAVE is not set -# CONFIG_ZYNQ_CPU1_TEST is not set - -# -# Processor Type -# -CONFIG_CPU_V7=y -CONFIG_CPU_32v6K=y -CONFIG_CPU_32v7=y -CONFIG_CPU_ABRT_EV7=y -CONFIG_CPU_PABRT_V7=y -CONFIG_CPU_CACHE_V7=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_TLB_V7=y -CONFIG_CPU_HAS_ASID=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y - -# -# Processor Features -# -# CONFIG_ARM_LPAE is not set -# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set -CONFIG_ARM_THUMB=y -# CONFIG_ARM_THUMBEE is not set -CONFIG_SWP_EMULATE=y -# CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set -# CONFIG_CPU_BPREDICT_DISABLE is not set -CONFIG_OUTER_CACHE=y -CONFIG_OUTER_CACHE_SYNC=y -CONFIG_CACHE_L2X0=y -CONFIG_CACHE_PL310=y -CONFIG_ARM_L1_CACHE_SHIFT_6=y -CONFIG_ARM_L1_CACHE_SHIFT=6 -CONFIG_ARM_DMA_MEM_BUFFERABLE=y -CONFIG_ARM_NR_BANKS=8 -CONFIG_CPU_HAS_PMU=y -CONFIG_MULTI_IRQ_HANDLER=y -# CONFIG_ARM_ERRATA_430973 is not set -# CONFIG_ARM_ERRATA_458693 is not set -# CONFIG_ARM_ERRATA_460075 is not set -# CONFIG_ARM_ERRATA_742230 is not set -# CONFIG_ARM_ERRATA_742231 is not set -# CONFIG_PL310_ERRATA_588369 is not set -# CONFIG_ARM_ERRATA_720789 is not set -# CONFIG_PL310_ERRATA_727915 is not set -# CONFIG_ARM_ERRATA_743622 is not set -# CONFIG_ARM_ERRATA_751472 is not set -# CONFIG_PL310_ERRATA_753970 is not set -# CONFIG_ARM_ERRATA_754322 is not set -# CONFIG_ARM_ERRATA_754327 is not set -# CONFIG_ARM_ERRATA_764369 is not set -# CONFIG_PL310_ERRATA_769419 is not set -CONFIG_ARM_GIC=y -CONFIG_ICST=y - -# -# Bus support -# -CONFIG_ARM_AMBA=y -CONFIG_ISA_DMA_API=y -# CONFIG_PCI_SYSCALL is not set -# CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCCARD is not set - -# -# Kernel Features -# -CONFIG_TICK_ONESHOT=y -# CONFIG_NO_HZ is not set -CONFIG_HIGH_RES_TIMERS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -CONFIG_HAVE_SMP=y -CONFIG_SMP=y -CONFIG_SMP_ON_UP=y -CONFIG_ARM_CPU_TOPOLOGY=y -# CONFIG_SCHED_MC is not set -# CONFIG_SCHED_SMT is not set -CONFIG_HAVE_ARM_SCU=y -CONFIG_HAVE_ARM_TWD=y -CONFIG_VMSPLIT_3G=y -# CONFIG_VMSPLIT_2G is not set -# CONFIG_VMSPLIT_1G is not set -CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_NR_CPUS=4 -# CONFIG_HOTPLUG_CPU is not set -CONFIG_LOCAL_TIMERS=y -CONFIG_ARCH_NR_GPIO=0 -# CONFIG_PREEMPT_NONE is not set -# CONFIG_PREEMPT_VOLUNTARY is not set -CONFIG_PREEMPT=y -CONFIG_PREEMPT_COUNT=y -CONFIG_HZ=100 -# CONFIG_THUMB2_KERNEL is not set -CONFIG_AEABI=y -# CONFIG_OABI_COMPAT is not set -# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set -# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set -CONFIG_HAVE_ARCH_PFN_VALID=y -CONFIG_HIGHMEM=y -# CONFIG_HIGHPTE is not set -CONFIG_HW_PERF_EVENTS=y -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -CONFIG_HAVE_MEMBLOCK=y -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_SPLIT_PTLOCK_CPUS=999999 -# CONFIG_COMPACTION is not set -# CONFIG_PHYS_ADDR_T_64BIT is not set -CONFIG_ZONE_DMA_FLAG=0 -CONFIG_BOUNCE=y -CONFIG_VIRT_TO_BUS=y -# CONFIG_KSM is not set -CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 -# CONFIG_CLEANCACHE is not set -CONFIG_FORCE_MAX_ZONEORDER=15 -CONFIG_ALIGNMENT_TRAP=y -# CONFIG_UACCESS_WITH_MEMCPY is not set -# CONFIG_SECCOMP is not set -# CONFIG_CC_STACKPROTECTOR is not set -# CONFIG_DEPRECATED_PARAM_STRUCT is not set - -# -# Boot options -# -CONFIG_USE_OF=y -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -# CONFIG_ARM_APPENDED_DTB is not set -CONFIG_CMDLINE="console=ttyPS0,115200n8 root=/dev/ram rw initrd=0x00800000,16M earlyprintk mtdparts=physmap-flash.0:512K(nor-fsbl),512K(nor-u-boot),5M(nor-linux),9M(nor-user),1M(nor-scratch),-(nor-rootfs)" -CONFIG_CMDLINE_FROM_BOOTLOADER=y -# CONFIG_CMDLINE_EXTEND is not set -# CONFIG_CMDLINE_FORCE is not set -# CONFIG_XIP_KERNEL is not set -# CONFIG_CRASH_DUMP is not set -# CONFIG_AUTO_ZRELADDR is not set - -# -# CPU Power Management -# -# CONFIG_CPU_IDLE is not set - -# -# Floating point emulation -# - -# -# At least one emulation must be selected -# -CONFIG_VFP=y -CONFIG_VFPv3=y -CONFIG_NEON=y - -# -# Userspace binary formats -# -CONFIG_BINFMT_ELF=y -CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_HAVE_AOUT=y -# CONFIG_BINFMT_AOUT is not set -# CONFIG_BINFMT_MISC is not set - -# -# Power management options -# -# CONFIG_SUSPEND is not set -CONFIG_PM_RUNTIME=y -CONFIG_PM=y -# CONFIG_PM_DEBUG is not set -# CONFIG_APM_EMULATION is not set -CONFIG_PM_CLK=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -# CONFIG_ARM_CPU_SUSPEND is not set -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_UNIX=y -# CONFIG_UNIX_DIAG is not set -CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set -# CONFIG_XFRM_SUB_POLICY is not set -# CONFIG_XFRM_MIGRATE is not set -# CONFIG_XFRM_STATISTICS is not set -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_IP_PNP_RARP=y -CONFIG_NET_IPIP=m -# CONFIG_NET_IPGRE_DEMUX is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_XFRM_TUNNEL is not set -CONFIG_INET_TUNNEL=m -CONFIG_INET_XFRM_MODE_TRANSPORT=y -CONFIG_INET_XFRM_MODE_TUNNEL=y -CONFIG_INET_XFRM_MODE_BEET=y -CONFIG_INET_LRO=y -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_INET_UDP_DIAG is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set -CONFIG_IPV6=m -# CONFIG_IPV6_PRIVACY is not set -# CONFIG_IPV6_ROUTER_PREF is not set -# CONFIG_IPV6_OPTIMISTIC_DAD is not set -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_IPV6_MIP6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set -CONFIG_INET6_XFRM_MODE_TRANSPORT=m -CONFIG_INET6_XFRM_MODE_TUNNEL=m -CONFIG_INET6_XFRM_MODE_BEET=m -# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set -CONFIG_IPV6_SIT=m -# CONFIG_IPV6_SIT_6RD is not set -CONFIG_IPV6_NDISC_NODETYPE=y -# CONFIG_IPV6_TUNNEL is not set -# CONFIG_IPV6_MULTIPLE_TABLES is not set -# CONFIG_IPV6_MROUTE is not set -# CONFIG_NETWORK_SECMARK is not set -# CONFIG_NETWORK_PHY_TIMESTAMPING is not set -# CONFIG_NETFILTER is not set -# CONFIG_IP_DCCP is not set -# CONFIG_IP_SCTP is not set -# CONFIG_RDS is not set -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -# CONFIG_L2TP is not set -# CONFIG_BRIDGE is not set -# CONFIG_NET_DSA is not set -CONFIG_VLAN_8021Q=m -# CONFIG_VLAN_8021Q_GVRP is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_PHONET is not set -# CONFIG_IEEE802154 is not set -# CONFIG_NET_SCHED is not set -# CONFIG_DCB is not set -# CONFIG_BATMAN_ADV is not set -# CONFIG_OPENVSWITCH is not set -CONFIG_RPS=y -CONFIG_RFS_ACCEL=y -CONFIG_XPS=y -CONFIG_BQL=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_HAMRADIO is not set -# CONFIG_CAN is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_AF_RXRPC is not set -CONFIG_WIRELESS=y -# CONFIG_CFG80211 is not set -# CONFIG_LIB80211 is not set - -# -# CFG80211 needs to be enabled for MAC80211 -# -# CONFIG_WIMAX is not set -# CONFIG_RFKILL is not set -# CONFIG_NET_9P is not set -# CONFIG_CAIF is not set -# CONFIG_CEPH_LIB is not set -# CONFIG_NFC is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m -CONFIG_FIRMWARE_IN_KERNEL=y -CONFIG_EXTRA_FIRMWARE="" -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_SYS_HYPERVISOR is not set -# CONFIG_GENERIC_CPU_DEVICES is not set -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -CONFIG_REGMAP_SPI=y -# CONFIG_DMA_SHARED_BUFFER is not set -CONFIG_CONNECTOR=y -CONFIG_PROC_EVENTS=y -CONFIG_MTD=y -# CONFIG_MTD_TESTS is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set -CONFIG_MTD_OF_PARTS=y -# CONFIG_MTD_AR7_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLKDEVS=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set -# CONFIG_RFD_FTL is not set -# CONFIG_SSFDC is not set -# CONFIG_SM_FTL is not set -# CONFIG_MTD_OOPS is not set -# CONFIG_MTD_SWAP is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -CONFIG_MTD_MAP_BANK_WIDTH_4=y -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CFI_AMDSTD=y -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=y -# CONFIG_MTD_PHYSMAP_COMPAT is not set -CONFIG_MTD_PHYSMAP_OF=y -# CONFIG_MTD_PLATRAM is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_DATAFLASH is not set -CONFIG_MTD_M25P80=y -# CONFIG_M25PXX_USE_FAST_READ is not set -# CONFIG_MTD_SST25L is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLOCK2MTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set -# CONFIG_MTD_DOCG3 is not set -CONFIG_MTD_NAND_ECC=y -# CONFIG_MTD_NAND_ECC_SMC is not set -CONFIG_MTD_NAND=y -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -# CONFIG_MTD_NAND_ECC_BCH is not set -# CONFIG_MTD_SM_COMMON is not set -# CONFIG_MTD_NAND_MUSEUM_IDS is not set -# CONFIG_MTD_NAND_GPIO is not set -CONFIG_MTD_NAND_IDS=y -# CONFIG_MTD_NAND_DISKONCHIP is not set -# CONFIG_MTD_NAND_NANDSIM is not set -# CONFIG_MTD_NAND_PLATFORM is not set -# CONFIG_MTD_ALAUDA is not set -CONFIG_MTD_NAND_XILINX_PSS=y -# CONFIG_MTD_ONENAND is not set - -# -# LPDDR flash memory drivers -# -# CONFIG_MTD_LPDDR is not set -# CONFIG_MTD_UBI is not set -CONFIG_DTC=y -CONFIG_OF=y - -# -# Device Tree and Open Firmware support -# -CONFIG_PROC_DEVICETREE=y -# CONFIG_OF_SELFTEST is not set -CONFIG_OF_FLATTREE=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_IRQ=y -CONFIG_OF_DEVICE=y -CONFIG_OF_GPIO=y -CONFIG_OF_I2C=y -CONFIG_OF_NET=y -CONFIG_OF_SPI=y -CONFIG_OF_MDIO=y -# CONFIG_PARPORT is not set -CONFIG_BLK_DEV=y -# CONFIG_BLK_DEV_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_DRBD is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_UB is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=35384 -# CONFIG_BLK_DEV_XIP is not set -# CONFIG_CDROM_PKTCDVD is not set -# CONFIG_ATA_OVER_ETH is not set -# CONFIG_MG_DISK is not set -# CONFIG_BLK_DEV_RBD is not set - -# -# Misc devices -# -# CONFIG_SENSORS_LIS3LV02D is not set -# CONFIG_AD525X_DPOT is not set -# CONFIG_ATMEL_PWM is not set -# CONFIG_ICS932S401 is not set -# CONFIG_ENCLOSURE_SERVICES is not set -# CONFIG_APDS9802ALS is not set -# CONFIG_ISL29003 is not set -# CONFIG_ISL29020 is not set -# CONFIG_SENSORS_TSL2550 is not set -# CONFIG_SENSORS_BH1780 is not set -# CONFIG_SENSORS_BH1770 is not set -# CONFIG_SENSORS_APDS990X is not set -# CONFIG_HMC6352 is not set -# CONFIG_DS1682 is not set -# CONFIG_TI_DAC7512 is not set -# CONFIG_BMP085 is not set -# CONFIG_USB_SWITCH_FSA9480 is not set -# CONFIG_SI570 is not set -# CONFIG_C2PORT is not set - -# -# EEPROM support -# -CONFIG_EEPROM_AT24=y -CONFIG_EEPROM_AT25=y -# CONFIG_EEPROM_LEGACY is not set -# CONFIG_EEPROM_MAX6875 is not set -# CONFIG_EEPROM_93CX6 is not set -# CONFIG_EEPROM_93XX46 is not set -# CONFIG_IWMC3200TOP is not set - -# -# Texas Instruments shared transport line discipline -# -# CONFIG_TI_ST is not set -# CONFIG_SENSORS_LIS3_SPI is not set -# CONFIG_SENSORS_LIS3_I2C is not set - -# -# Altera FPGA firmware download module -# -# CONFIG_ALTERA_STAPL is not set - -# -# SCSI device support -# -CONFIG_SCSI_MOD=y -# CONFIG_RAID_ATTRS is not set -CONFIG_SCSI=y -CONFIG_SCSI_DMA=y -# CONFIG_SCSI_TGT is not set -# CONFIG_SCSI_NETLINK is not set -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -# CONFIG_BLK_DEV_SR is not set -CONFIG_CHR_DEV_SG=y -# CONFIG_CHR_DEV_SCH is not set -CONFIG_SCSI_MULTI_LUN=y -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set -# CONFIG_SCSI_SCAN_ASYNC is not set -CONFIG_SCSI_WAIT_SCAN=m - -# -# SCSI Transports -# -# CONFIG_SCSI_SPI_ATTRS is not set -# CONFIG_SCSI_FC_ATTRS is not set -# CONFIG_SCSI_ISCSI_ATTRS is not set -# CONFIG_SCSI_SAS_ATTRS is not set -# CONFIG_SCSI_SAS_LIBSAS is not set -# CONFIG_SCSI_SRP_ATTRS is not set -CONFIG_SCSI_LOWLEVEL=y -# CONFIG_ISCSI_TCP is not set -# CONFIG_ISCSI_BOOT_SYSFS is not set -# CONFIG_LIBFC is not set -# CONFIG_LIBFCOE is not set -# CONFIG_SCSI_DEBUG is not set -# CONFIG_SCSI_DH is not set -# CONFIG_SCSI_OSD_INITIATOR is not set -# CONFIG_ATA is not set -# CONFIG_MD is not set -# CONFIG_TARGET_CORE is not set -CONFIG_NETDEVICES=y -CONFIG_NET_CORE=y -# CONFIG_BONDING is not set -# CONFIG_DUMMY is not set -# CONFIG_EQUALIZER is not set -# CONFIG_MII is not set -# CONFIG_NET_TEAM is not set -# CONFIG_MACVLAN is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_TUN is not set -# CONFIG_VETH is not set - -# -# CAIF transport drivers -# -CONFIG_ETHERNET=y -# CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_NET_CALXEDA_XGMAC is not set -# CONFIG_NET_VENDOR_CHELSIO is not set -# CONFIG_DM9000 is not set -# CONFIG_DNET is not set -# CONFIG_NET_VENDOR_FARADAY is not set -# CONFIG_NET_VENDOR_INTEL is not set -# CONFIG_NET_VENDOR_MARVELL is not set -# CONFIG_NET_VENDOR_MICREL is not set -# CONFIG_NET_VENDOR_MICROCHIP is not set -# CONFIG_NET_VENDOR_NATSEMI is not set -# CONFIG_ETHOC is not set -# CONFIG_NET_VENDOR_SEEQ is not set -# CONFIG_NET_VENDOR_SMSC is not set -# CONFIG_NET_VENDOR_STMICRO is not set -CONFIG_NET_VENDOR_XILINX=y -CONFIG_XILINX_PS_EMAC=y -CONFIG_XILINX_PS_EMAC_HWTSTAMP=y -CONFIG_PHYLIB=y - -# -# MII PHY device drivers -# -CONFIG_MARVELL_PHY=y -# CONFIG_DAVICOM_PHY is not set -# CONFIG_QSEMI_PHY is not set -# CONFIG_LXT_PHY is not set -# CONFIG_CICADA_PHY is not set -# CONFIG_VITESSE_PHY is not set -# CONFIG_SMSC_PHY is not set -# CONFIG_BROADCOM_PHY is not set -# CONFIG_ICPLUS_PHY is not set -# CONFIG_REALTEK_PHY is not set -# CONFIG_NATIONAL_PHY is not set -# CONFIG_STE10XP is not set -# CONFIG_LSI_ET1011C_PHY is not set -# CONFIG_MICREL_PHY is not set -# CONFIG_FIXED_PHY is not set -CONFIG_MDIO_BITBANG=y -# CONFIG_MDIO_GPIO is not set -# CONFIG_MICREL_KS8995MA is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# USB Network Adapters -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set -# CONFIG_USB_IPHETH is not set -# CONFIG_WLAN is not set - -# -# Enable WiMAX (Networking options) to see the WiMAX drivers -# -# CONFIG_WAN is not set -# CONFIG_ISDN is not set -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set -# CONFIG_INPUT_POLLDEV is not set -CONFIG_INPUT_SPARSEKMAP=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -# CONFIG_KEYBOARD_ADP5588 is not set -# CONFIG_KEYBOARD_ADP5589 is not set -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_QT1070 is not set -# CONFIG_KEYBOARD_QT2160 is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_GPIO is not set -# CONFIG_KEYBOARD_TCA6416 is not set -# CONFIG_KEYBOARD_TCA8418 is not set -# CONFIG_KEYBOARD_MATRIX is not set -# CONFIG_KEYBOARD_MAX7359 is not set -# CONFIG_KEYBOARD_MCS is not set -# CONFIG_KEYBOARD_MPR121 is not set -# CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_KEYBOARD_OPENCORES is not set -# CONFIG_KEYBOARD_SAMSUNG is not set -# CONFIG_KEYBOARD_STOWAWAY is not set -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=y -CONFIG_MOUSE_PS2_ALPS=y -CONFIG_MOUSE_PS2_LOGIPS2PP=y -CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_TRACKPOINT=y -# CONFIG_MOUSE_PS2_ELANTECH is not set -# CONFIG_MOUSE_PS2_SENTELIC is not set -# CONFIG_MOUSE_PS2_TOUCHKIT is not set -# CONFIG_MOUSE_SERIAL is not set -# CONFIG_MOUSE_APPLETOUCH is not set -# CONFIG_MOUSE_BCM5974 is not set -# CONFIG_MOUSE_VSXXXAA is not set -# CONFIG_MOUSE_GPIO is not set -# CONFIG_MOUSE_SYNAPTICS_I2C is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TABLET is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_AMBAKMI is not set -CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set -# CONFIG_SERIO_ALTERA_PS2 is not set -# CONFIG_SERIO_PS2MULT is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -CONFIG_VT_HW_CONSOLE_BINDING=y -CONFIG_UNIX98_PTYS=y -# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_N_GSM is not set -# CONFIG_TRACE_SINK is not set -# CONFIG_DEVKMEM is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -# CONFIG_SERIAL_AMBA_PL010 is not set -# CONFIG_SERIAL_AMBA_PL011 is not set -# CONFIG_SERIAL_MAX3100 is not set -# CONFIG_SERIAL_MAX3107 is not set -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_TIMBERDALE is not set -# CONFIG_SERIAL_ALTERA_JTAGUART is not set -# CONFIG_SERIAL_ALTERA_UART is not set -# CONFIG_SERIAL_IFX6X60 is not set -CONFIG_SERIAL_XILINX_PS_UART=y -CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y -# CONFIG_TTY_PRINTK is not set -# CONFIG_HVC_DCC is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_HW_RANDOM is not set -CONFIG_XILINX_DEVCFG=y -# CONFIG_R3964 is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set -# CONFIG_RAMOOPS is not set -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_COMPAT=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_MUX=y - -# -# Multiplexer I2C Chip support -# -# CONFIG_I2C_MUX_GPIO is not set -# CONFIG_I2C_MUX_PCA9541 is not set -CONFIG_I2C_MUX_PCA954x=y -CONFIG_I2C_HELPER_AUTO=y -CONFIG_I2C_ALGOBIT=y - -# -# I2C Hardware Bus support -# - -# -# I2C system bus drivers (mostly embedded / system-on-chip) -# -# CONFIG_I2C_DESIGNWARE_PLATFORM is not set -CONFIG_I2C_GPIO=y -# CONFIG_I2C_OCORES is not set -# CONFIG_I2C_PCA_PLATFORM is not set -# CONFIG_I2C_PXA_PCI is not set -# CONFIG_I2C_SIMTEC is not set -# CONFIG_I2C_XILINX_PS is not set -CONFIG_I2C_XILINX=y - -# -# External I2C/SMBus adapter drivers -# -# CONFIG_I2C_DIOLAN_U2C is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_TAOS_EVM is not set -# CONFIG_I2C_TINY_USB is not set - -# -# Other I2C/SMBus bus drivers -# -# CONFIG_I2C_STUB is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -CONFIG_SPI=y -# CONFIG_SPI_DEBUG is not set -CONFIG_SPI_MASTER=y - -# -# SPI Master Controller Drivers -# -# CONFIG_SPI_ALTERA is not set -CONFIG_SPI_BITBANG=y -# CONFIG_SPI_GPIO is not set -# CONFIG_SPI_OC_TINY is not set -# CONFIG_SPI_PL022 is not set -# CONFIG_SPI_PXA2XX_PCI is not set -CONFIG_SPI_XCOMM=y -# CONFIG_SPI_XILINX is not set -CONFIG_SPI_XILINX_PS_QSPI=y -# CONFIG_XILINX_PS_QSPI_USE_DUAL_FLASH is not set -CONFIG_SPI_XILINX_PS_SPI=y -# CONFIG_SPI_DESIGNWARE is not set - -# -# SPI Protocol Masters -# -# CONFIG_SPI_SPIDEV is not set -# CONFIG_SPI_TLE62X0 is not set - -# -# PPS support -# -# CONFIG_PPS is not set - -# -# PPS generators support -# - -# -# PTP clock support -# - -# -# Enable Device Drivers -> PPS to see the PTP clock options. -# -CONFIG_ARCH_REQUIRE_GPIOLIB=y -CONFIG_GPIOLIB=y -# CONFIG_DEBUG_GPIO is not set -CONFIG_GPIO_SYSFS=y - -# -# Memory mapped GPIO drivers: -# -# CONFIG_GPIO_GENERIC_PLATFORM is not set -# CONFIG_GPIO_PL061 is not set -# CONFIG_GPIO_XILINX is not set -CONFIG_GPIO_XILINX_PS=y - -# -# I2C GPIO expanders: -# -# CONFIG_GPIO_MAX7300 is not set -# CONFIG_GPIO_MAX732X is not set -# CONFIG_GPIO_PCF857X is not set -# CONFIG_GPIO_SX150X is not set -# CONFIG_GPIO_ADP5588 is not set - -# -# PCI GPIO expanders: -# - -# -# SPI GPIO expanders: -# -# CONFIG_GPIO_MAX7301 is not set -# CONFIG_GPIO_MCP23S08 is not set -# CONFIG_GPIO_MC33880 is not set -# CONFIG_GPIO_74X164 is not set - -# -# AC97 GPIO expanders: -# - -# -# MODULbus GPIO expanders: -# -# CONFIG_W1 is not set -# CONFIG_POWER_SUPPLY is not set -# CONFIG_HWMON is not set -# CONFIG_THERMAL is not set -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_CORE is not set -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_ARM_SP805_WATCHDOG is not set -# CONFIG_DW_WATCHDOG is not set -# CONFIG_MPCORE_WATCHDOG is not set -# CONFIG_XILINX_PS_WATCHDOG is not set -# CONFIG_XILINX_SCU_WATCHDOG is not set -# CONFIG_MAX63XX_WATCHDOG is not set - -# -# USB-based Watchdog Cards -# -# CONFIG_USBPCWATCHDOG is not set -CONFIG_SSB_POSSIBLE=y - -# -# Sonics Silicon Backplane -# -# CONFIG_SSB is not set -CONFIG_BCMA_POSSIBLE=y - -# -# Broadcom specific AMBA -# -# CONFIG_BCMA is not set - -# -# Multifunction device drivers -# -# CONFIG_MFD_CORE is not set -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_MFD_ASIC3 is not set -# CONFIG_HTC_EGPIO is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_HTC_I2CPLD is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS65010 is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS65910 is not set -# CONFIG_MFD_TPS65912_I2C is not set -# CONFIG_MFD_TPS65912_SPI is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MFD_TC6387XB is not set -# CONFIG_MFD_TC6393XB is not set -# CONFIG_PMIC_DA903X is not set -# CONFIG_MFD_DA9052_SPI is not set -# CONFIG_MFD_DA9052_I2C is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_MAX8925 is not set -# CONFIG_MFD_MAX8997 is not set -# CONFIG_MFD_MAX8998 is not set -# CONFIG_MFD_S5M_CORE is not set -# CONFIG_MFD_WM8400 is not set -# CONFIG_MFD_WM831X_I2C is not set -# CONFIG_MFD_WM831X_SPI is not set -# CONFIG_MFD_WM8350_I2C is not set -# CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_EZX_PCAP is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_AAT2870_CORE is not set -# CONFIG_REGULATOR is not set -CONFIG_MEDIA_SUPPORT=y - -# -# Multimedia core support -# -# CONFIG_MEDIA_CONTROLLER is not set -CONFIG_VIDEO_DEV=y -CONFIG_VIDEO_V4L2_COMMON=y -# CONFIG_DVB_CORE is not set -CONFIG_VIDEO_MEDIA=y - -# -# Multimedia drivers -# -# CONFIG_RC_CORE is not set -# CONFIG_MEDIA_ATTACH is not set -CONFIG_MEDIA_TUNER=y -# CONFIG_MEDIA_TUNER_CUSTOMISE is not set -CONFIG_MEDIA_TUNER_SIMPLE=y -CONFIG_MEDIA_TUNER_TDA8290=y -CONFIG_MEDIA_TUNER_TDA827X=y -CONFIG_MEDIA_TUNER_TDA18271=y -CONFIG_MEDIA_TUNER_TDA9887=y -CONFIG_MEDIA_TUNER_TEA5761=y -CONFIG_MEDIA_TUNER_TEA5767=y -CONFIG_MEDIA_TUNER_MT20XX=y -CONFIG_MEDIA_TUNER_XC2028=y -CONFIG_MEDIA_TUNER_XC5000=y -CONFIG_MEDIA_TUNER_XC4000=y -CONFIG_MEDIA_TUNER_MC44S803=y -CONFIG_VIDEO_V4L2=y -CONFIG_VIDEOBUF2_CORE=y -CONFIG_VIDEOBUF2_MEMOPS=y -CONFIG_VIDEOBUF2_VMALLOC=y -CONFIG_VIDEO_CAPTURE_DRIVERS=y -# CONFIG_VIDEO_ADV_DEBUG is not set -# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set -# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set - -# -# Encoders, decoders, sensors and other helper chips -# - -# -# Audio decoders, processors and mixers -# -# CONFIG_VIDEO_TVAUDIO is not set -# CONFIG_VIDEO_TDA7432 is not set -# CONFIG_VIDEO_TDA9840 is not set -# CONFIG_VIDEO_TEA6415C is not set -# CONFIG_VIDEO_TEA6420 is not set -# CONFIG_VIDEO_MSP3400 is not set -# CONFIG_VIDEO_CS5345 is not set -# CONFIG_VIDEO_CS53L32A is not set -# CONFIG_VIDEO_TLV320AIC23B is not set -# CONFIG_VIDEO_WM8775 is not set -# CONFIG_VIDEO_WM8739 is not set -# CONFIG_VIDEO_VP27SMPX is not set - -# -# RDS decoders -# -# CONFIG_VIDEO_SAA6588 is not set - -# -# Video decoders -# -# CONFIG_VIDEO_ADV7180 is not set -# CONFIG_VIDEO_BT819 is not set -# CONFIG_VIDEO_BT856 is not set -# CONFIG_VIDEO_BT866 is not set -# CONFIG_VIDEO_KS0127 is not set -# CONFIG_VIDEO_SAA7110 is not set -# CONFIG_VIDEO_SAA711X is not set -# CONFIG_VIDEO_SAA7191 is not set -# CONFIG_VIDEO_TVP514X is not set -# CONFIG_VIDEO_TVP5150 is not set -# CONFIG_VIDEO_TVP7002 is not set -# CONFIG_VIDEO_VPX3220 is not set - -# -# Video and audio decoders -# -# CONFIG_VIDEO_SAA717X is not set -# CONFIG_VIDEO_CX25840 is not set - -# -# MPEG video encoders -# -# CONFIG_VIDEO_CX2341X is not set - -# -# Video encoders -# -# CONFIG_VIDEO_SAA7127 is not set -# CONFIG_VIDEO_SAA7185 is not set -# CONFIG_VIDEO_ADV7170 is not set -# CONFIG_VIDEO_ADV7175 is not set -# CONFIG_VIDEO_ADV7343 is not set -# CONFIG_VIDEO_AK881X is not set - -# -# Camera sensor devices -# -# CONFIG_VIDEO_OV7670 is not set -# CONFIG_VIDEO_MT9V011 is not set -# CONFIG_VIDEO_TCM825X is not set -# CONFIG_VIDEO_SR030PC30 is not set - -# -# Flash devices -# - -# -# Video improvement chips -# -# CONFIG_VIDEO_UPD64031A is not set -# CONFIG_VIDEO_UPD64083 is not set - -# -# Miscelaneous helper chips -# -# CONFIG_VIDEO_THS7303 is not set -# CONFIG_VIDEO_M52790 is not set -# CONFIG_VIDEO_VIVI is not set -CONFIG_V4L_USB_DRIVERS=y -CONFIG_USB_VIDEO_CLASS=y -CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y -CONFIG_USB_GSPCA=y -# CONFIG_USB_M5602 is not set -# CONFIG_USB_STV06XX is not set -# CONFIG_USB_GL860 is not set -# CONFIG_USB_GSPCA_BENQ is not set -# CONFIG_USB_GSPCA_CONEX is not set -# CONFIG_USB_GSPCA_CPIA1 is not set -# CONFIG_USB_GSPCA_ETOMS is not set -# CONFIG_USB_GSPCA_FINEPIX is not set -# CONFIG_USB_GSPCA_JEILINJ is not set -# CONFIG_USB_GSPCA_JL2005BCD is not set -# CONFIG_USB_GSPCA_KINECT is not set -# CONFIG_USB_GSPCA_KONICA is not set -# CONFIG_USB_GSPCA_MARS is not set -# CONFIG_USB_GSPCA_MR97310A is not set -# CONFIG_USB_GSPCA_NW80X is not set -# CONFIG_USB_GSPCA_OV519 is not set -# CONFIG_USB_GSPCA_OV534 is not set -# CONFIG_USB_GSPCA_OV534_9 is not set -# CONFIG_USB_GSPCA_PAC207 is not set -# CONFIG_USB_GSPCA_PAC7302 is not set -# CONFIG_USB_GSPCA_PAC7311 is not set -# CONFIG_USB_GSPCA_SE401 is not set -# CONFIG_USB_GSPCA_SN9C2028 is not set -# CONFIG_USB_GSPCA_SN9C20X is not set -# CONFIG_USB_GSPCA_SONIXB is not set -# CONFIG_USB_GSPCA_SONIXJ is not set -# CONFIG_USB_GSPCA_SPCA500 is not set -# CONFIG_USB_GSPCA_SPCA501 is not set -# CONFIG_USB_GSPCA_SPCA505 is not set -# CONFIG_USB_GSPCA_SPCA506 is not set -# CONFIG_USB_GSPCA_SPCA508 is not set -# CONFIG_USB_GSPCA_SPCA561 is not set -# CONFIG_USB_GSPCA_SPCA1528 is not set -# CONFIG_USB_GSPCA_SQ905 is not set -# CONFIG_USB_GSPCA_SQ905C is not set -# CONFIG_USB_GSPCA_SQ930X is not set -# CONFIG_USB_GSPCA_STK014 is not set -# CONFIG_USB_GSPCA_STV0680 is not set -# CONFIG_USB_GSPCA_SUNPLUS is not set -# CONFIG_USB_GSPCA_T613 is not set -# CONFIG_USB_GSPCA_TOPRO is not set -# CONFIG_USB_GSPCA_TV8532 is not set -# CONFIG_USB_GSPCA_VC032X is not set -# CONFIG_USB_GSPCA_VICAM is not set -# CONFIG_USB_GSPCA_XIRLINK_CIT is not set -# CONFIG_USB_GSPCA_ZC3XX is not set -# CONFIG_VIDEO_PVRUSB2 is not set -# CONFIG_VIDEO_HDPVR is not set -# CONFIG_VIDEO_EM28XX is not set -# CONFIG_VIDEO_USBVISION is not set -# CONFIG_USB_ET61X251 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_PWC is not set -# CONFIG_VIDEO_CPIA2 is not set -# CONFIG_USB_ZR364XX is not set -# CONFIG_USB_STKWEBCAM is not set -# CONFIG_USB_S2255 is not set -# CONFIG_V4L_PLATFORM_DRIVERS is not set -# CONFIG_V4L_MEM2MEM_DRIVERS is not set -# CONFIG_RADIO_ADAPTERS is not set - -# -# Graphics support -# -CONFIG_DRM=y -CONFIG_DRM_KMS_HELPER=y -CONFIG_DRM_ENCODER_ADV7511=y -CONFIG_DRM_ANALOG=y -# CONFIG_VGASTATE is not set -# CONFIG_VIDEO_OUTPUT_CONTROL is not set -CONFIG_FB=y -# CONFIG_FIRMWARE_EDID is not set -# CONFIG_FB_BOOT_VESA_SUPPORT is not set -# CONFIG_FB_CFB_FILLRECT is not set -# CONFIG_FB_CFB_COPYAREA is not set -# CONFIG_FB_CFB_IMAGEBLIT is not set -# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -CONFIG_FB_SYS_FILLRECT=y -CONFIG_FB_SYS_COPYAREA=y -CONFIG_FB_SYS_IMAGEBLIT=y -# CONFIG_FB_FOREIGN_ENDIAN is not set -# CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set -# CONFIG_FB_SVGALIB is not set -# CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set -# CONFIG_FB_MODE_HELPERS is not set -# CONFIG_FB_TILEBLITTING is not set - -# -# Frame buffer hardware drivers -# -# CONFIG_FB_ARMCLCD is not set -# CONFIG_FB_UVESA is not set -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_SMSCUFX is not set -# CONFIG_FB_UDL is not set -# CONFIG_FB_XILINX is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FB_METRONOME is not set -# CONFIG_FB_BROADSHEET is not set -# CONFIG_FB_XYLON is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Console display driver support -# -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -CONFIG_FONTS=y -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_7x14 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set -# CONFIG_FONT_MINI_4x6 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_10x18 is not set -CONFIG_LOGO=y -CONFIG_LOGO_LINUX_MONO=y -CONFIG_LOGO_LINUX_VGA16=y -CONFIG_LOGO_LINUX_CLUT224=y -CONFIG_SOUND=y -# CONFIG_SOUND_OSS_CORE is not set -CONFIG_SND=y -CONFIG_SND_TIMER=y -CONFIG_SND_PCM=y -CONFIG_SND_JACK=y -# CONFIG_SND_SEQUENCER is not set -# CONFIG_SND_MIXER_OSS is not set -# CONFIG_SND_PCM_OSS is not set -# CONFIG_SND_HRTIMER is not set -# CONFIG_SND_DYNAMIC_MINORS is not set -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_VERBOSE_PROCFS is not set -# CONFIG_SND_VERBOSE_PRINTK is not set -# CONFIG_SND_DEBUG is not set -# CONFIG_SND_RAWMIDI_SEQ is not set -# CONFIG_SND_OPL3_LIB_SEQ is not set -# CONFIG_SND_OPL4_LIB_SEQ is not set -# CONFIG_SND_SBAWE_SEQ is not set -# CONFIG_SND_EMU10K1_SEQ is not set -# CONFIG_SND_DRIVERS is not set -# CONFIG_SND_ARM is not set -# CONFIG_SND_SPI is not set -# CONFIG_SND_USB is not set -CONFIG_SND_SOC=y -CONFIG_SND_SOC_DMAENGINE_PCM=y -CONFIG_SND_SOC_XILINX=y -CONFIG_SND_SOC_AXI_SPDIF=y -CONFIG_SND_SOC_ADV7511_HDMI=y -CONFIG_SND_SOC_I2C_AND_SPI=y -# CONFIG_SND_SOC_ALL_CODECS is not set -# CONFIG_SOUND_PRIME is not set -CONFIG_HID_SUPPORT=y -CONFIG_HID=y -# CONFIG_HIDRAW is not set - -# -# USB Input Devices -# -CONFIG_USB_HID=y -# CONFIG_HID_PID is not set -# CONFIG_USB_HIDDEV is not set - -# -# Special HID drivers -# -# CONFIG_HID_A4TECH is not set -# CONFIG_HID_ACRUX is not set -# CONFIG_HID_APPLE is not set -# CONFIG_HID_BELKIN is not set -# CONFIG_HID_CHERRY is not set -# CONFIG_HID_CHICONY is not set -# CONFIG_HID_PRODIKEYS is not set -# CONFIG_HID_CYPRESS is not set -# CONFIG_HID_DRAGONRISE is not set -# CONFIG_HID_EMS_FF is not set -# CONFIG_HID_EZKEY is not set -# CONFIG_HID_HOLTEK is not set -# CONFIG_HID_KEYTOUCH is not set -# CONFIG_HID_KYE is not set -# CONFIG_HID_UCLOGIC is not set -# CONFIG_HID_WALTOP is not set -# CONFIG_HID_GYRATION is not set -# CONFIG_HID_TWINHAN is not set -# CONFIG_HID_KENSINGTON is not set -# CONFIG_HID_LCPOWER is not set -# CONFIG_HID_LOGITECH is not set -CONFIG_HID_MICROSOFT=y -# CONFIG_HID_MONTEREY is not set -# CONFIG_HID_MULTITOUCH is not set -# CONFIG_HID_NTRIG is not set -# CONFIG_HID_ORTEK is not set -# CONFIG_HID_PANTHERLORD is not set -# CONFIG_HID_PETALYNX is not set -# CONFIG_HID_PICOLCD is not set -# CONFIG_HID_PRIMAX is not set -# CONFIG_HID_ROCCAT is not set -# CONFIG_HID_SAMSUNG is not set -# CONFIG_HID_SONY is not set -# CONFIG_HID_SPEEDLINK is not set -# CONFIG_HID_SUNPLUS is not set -# CONFIG_HID_GREENASIA is not set -# CONFIG_HID_SMARTJOYPLUS is not set -# CONFIG_HID_TOPSEED is not set -# CONFIG_HID_THRUSTMASTER is not set -# CONFIG_HID_ZEROPLUS is not set -# CONFIG_HID_ZYDACRON is not set -CONFIG_USB_SUPPORT=y -CONFIG_USB_COMMON=y -CONFIG_USB_ARCH_HAS_HCD=y -# CONFIG_USB_ARCH_HAS_OHCI is not set -CONFIG_USB_ARCH_HAS_EHCI=y -# CONFIG_USB_ARCH_HAS_XHCI is not set -CONFIG_USB=y -# CONFIG_USB_DEBUG is not set -# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -CONFIG_USB_DEVICE_CLASS=y -# CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y -CONFIG_USB_OTG=y -# CONFIG_USB_OTG_WHITELIST is not set -# CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set -# CONFIG_USB_MON is not set -# CONFIG_USB_WUSB_CBAF is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_C67X00_HCD is not set -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_ROOT_HUB_TT=y -# CONFIG_USB_EHCI_TT_NEWSCHED is not set -CONFIG_USB_XUSBPS_DR_OF=y -CONFIG_USB_EHCI_XUSBPS=y -# CONFIG_USB_EHCI_MV is not set -# CONFIG_USB_OXU210HP_HCD is not set -# CONFIG_USB_ISP116X_HCD is not set -# CONFIG_USB_ISP1760_HCD is not set -# CONFIG_USB_ISP1362_HCD is not set -# CONFIG_USB_SL811_HCD is not set -# CONFIG_USB_R8A66597_HCD is not set -# CONFIG_USB_MUSB_HDRC is not set -# CONFIG_USB_RENESAS_USBHS is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_WDM is not set -# CONFIG_USB_TMC is not set - -# -# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may -# - -# -# also be needed; see USB_STORAGE Help for more info -# -CONFIG_USB_STORAGE=y -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_REALTEK is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_USBAT is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_SDDR55 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_ALAUDA is not set -# CONFIG_USB_STORAGE_ONETOUCH is not set -# CONFIG_USB_STORAGE_KARMA is not set -# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set -# CONFIG_USB_STORAGE_ENE_UB6250 is not set -# CONFIG_USB_UAS is not set -# CONFIG_USB_LIBUSUAL is not set - -# -# USB Imaging devices -# -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set - -# -# USB port drivers -# -# CONFIG_USB_SERIAL is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_ADUTUX is not set -# CONFIG_USB_SEVSEG is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYPRESS_CY7C63 is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_IDMOUSE is not set -# CONFIG_USB_FTDI_ELAN is not set -# CONFIG_USB_APPLEDISPLAY is not set -# CONFIG_USB_SISUSBVGA is not set -# CONFIG_USB_LD is not set -# CONFIG_USB_TRANCEVIBRATOR is not set -# CONFIG_USB_IOWARRIOR is not set -# CONFIG_USB_TEST is not set -# CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_YUREX is not set -CONFIG_USB_GADGET=y -# CONFIG_USB_GADGET_DEBUG is not set -# CONFIG_USB_GADGET_DEBUG_FILES is not set -# CONFIG_USB_GADGET_DEBUG_FS is not set -CONFIG_USB_GADGET_VBUS_DRAW=2 -CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 -CONFIG_USB_GADGET_XUSBPS=y -CONFIG_USB_XUSBPS=y -# CONFIG_USB_FUSB300 is not set -# CONFIG_USB_R8A66597 is not set -# CONFIG_USB_GADGET_XILINX is not set -# CONFIG_USB_MV_UDC is not set -# CONFIG_USB_M66592 is not set -# CONFIG_USB_NET2272 is not set -# CONFIG_USB_DUMMY_HCD is not set -CONFIG_USB_GADGET_DUALSPEED=y -CONFIG_USB_ZERO=m -# CONFIG_USB_ZERO_HNPTEST is not set -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_ETH is not set -# CONFIG_USB_G_NCM is not set -# CONFIG_USB_GADGETFS is not set -# CONFIG_USB_FUNCTIONFS is not set -CONFIG_USB_FILE_STORAGE=m -# CONFIG_USB_FILE_STORAGE_TEST is not set -# CONFIG_USB_MASS_STORAGE is not set -# CONFIG_USB_G_SERIAL is not set -# CONFIG_USB_MIDI_GADGET is not set -# CONFIG_USB_G_PRINTER is not set -# CONFIG_USB_CDC_COMPOSITE is not set -# CONFIG_USB_G_ACM_MS is not set -# CONFIG_USB_G_MULTI is not set -# CONFIG_USB_G_HID is not set -# CONFIG_USB_G_DBGP is not set -# CONFIG_USB_G_WEBCAM is not set - -# -# OTG and related infrastructure -# -CONFIG_USB_OTG_UTILS=y -# CONFIG_USB_GPIO_VBUS is not set -CONFIG_USB_ULPI=y -CONFIG_USB_ULPI_VIEWPORT=y -# CONFIG_NOP_USB_XCEIV is not set -CONFIG_USB_XUSBPS_OTG=y -CONFIG_MMC=y -# CONFIG_MMC_DEBUG is not set -# CONFIG_MMC_UNSAFE_RESUME is not set -# CONFIG_MMC_CLKGATE is not set - -# -# MMC/SD/SDIO Card Drivers -# -CONFIG_MMC_BLOCK=y -CONFIG_MMC_BLOCK_MINORS=8 -CONFIG_MMC_BLOCK_BOUNCE=y -# CONFIG_SDIO_UART is not set -# CONFIG_MMC_TEST is not set - -# -# MMC/SD/SDIO Host Controller Drivers -# -# CONFIG_MMC_ARMMMCI is not set -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMC_SDHCI_OF_XILINX_PS=y -# CONFIG_MMC_SDHCI_PXAV3 is not set -# CONFIG_MMC_SDHCI_PXAV2 is not set -# CONFIG_MMC_WBSD is not set -# CONFIG_MMC_DW is not set -# CONFIG_MMC_VUB300 is not set -# CONFIG_MMC_USHC is not set -# CONFIG_MEMSTICK is not set -# CONFIG_NEW_LEDS is not set -# CONFIG_ACCESSIBILITY is not set -CONFIG_RTC_LIB=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_HCTOSYS=y -CONFIG_RTC_HCTOSYS_DEVICE="rtc0" -# CONFIG_RTC_DEBUG is not set - -# -# RTC interfaces -# -CONFIG_RTC_INTF_SYSFS=y -CONFIG_RTC_INTF_PROC=y -CONFIG_RTC_INTF_DEV=y -# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set -# CONFIG_RTC_DRV_TEST is not set - -# -# I2C RTC drivers -# -# CONFIG_RTC_DRV_DS1307 is not set -# CONFIG_RTC_DRV_DS1374 is not set -# CONFIG_RTC_DRV_DS1672 is not set -# CONFIG_RTC_DRV_DS3232 is not set -# CONFIG_RTC_DRV_MAX6900 is not set -# CONFIG_RTC_DRV_RS5C372 is not set -# CONFIG_RTC_DRV_ISL1208 is not set -# CONFIG_RTC_DRV_ISL12022 is not set -# CONFIG_RTC_DRV_X1205 is not set -CONFIG_RTC_DRV_PCF8563=y -# CONFIG_RTC_DRV_PCF8583 is not set -# CONFIG_RTC_DRV_M41T80 is not set -# CONFIG_RTC_DRV_BQ32K is not set -# CONFIG_RTC_DRV_S35390A is not set -# CONFIG_RTC_DRV_FM3130 is not set -# CONFIG_RTC_DRV_RX8581 is not set -# CONFIG_RTC_DRV_RX8025 is not set -# CONFIG_RTC_DRV_EM3027 is not set -# CONFIG_RTC_DRV_RV3029C2 is not set - -# -# SPI RTC drivers -# -# CONFIG_RTC_DRV_M41T93 is not set -# CONFIG_RTC_DRV_M41T94 is not set -# CONFIG_RTC_DRV_DS1305 is not set -# CONFIG_RTC_DRV_DS1390 is not set -# CONFIG_RTC_DRV_MAX6902 is not set -# CONFIG_RTC_DRV_R9701 is not set -# CONFIG_RTC_DRV_RS5C348 is not set -# CONFIG_RTC_DRV_DS3234 is not set -# CONFIG_RTC_DRV_PCF2123 is not set - -# -# Platform RTC drivers -# -# CONFIG_RTC_DRV_CMOS is not set -# CONFIG_RTC_DRV_DS1286 is not set -# CONFIG_RTC_DRV_DS1511 is not set -# CONFIG_RTC_DRV_DS1553 is not set -# CONFIG_RTC_DRV_DS1742 is not set -# CONFIG_RTC_DRV_STK17TA8 is not set -# CONFIG_RTC_DRV_M48T86 is not set -# CONFIG_RTC_DRV_M48T35 is not set -# CONFIG_RTC_DRV_M48T59 is not set -# CONFIG_RTC_DRV_MSM6242 is not set -# CONFIG_RTC_DRV_BQ4802 is not set -# CONFIG_RTC_DRV_RP5C01 is not set -# CONFIG_RTC_DRV_V3020 is not set - -# -# on-CPU RTC drivers -# -# CONFIG_RTC_DRV_PL030 is not set -# CONFIG_RTC_DRV_PL031 is not set -CONFIG_DMADEVICES=y -# CONFIG_DMADEVICES_DEBUG is not set - -# -# DMA Devices -# -CONFIG_XILINX_DMA=y -# CONFIG_AMBA_PL08X is not set -# CONFIG_DW_DMAC is not set -# CONFIG_TIMB_DMA is not set -# CONFIG_PL330_DMA is not set -CONFIG_DMA_ENGINE=y - -# -# DMA Clients -# -# CONFIG_NET_DMA is not set -# CONFIG_ASYNC_TX_DMA is not set -# CONFIG_DMATEST is not set -# CONFIG_AUXDISPLAY is not set -# CONFIG_UIO is not set - -# -# Virtio drivers -# -# CONFIG_VIRTIO_BALLOON is not set -# CONFIG_VIRTIO_MMIO is not set - -# -# Microsoft Hyper-V guest support -# -CONFIG_STAGING=y -# CONFIG_USBIP_CORE is not set -# CONFIG_ECHO is not set -# CONFIG_ASUS_OLED is not set -# CONFIG_RTS5139 is not set -# CONFIG_TRANZPORT is not set -# CONFIG_LINE6_USB is not set - -# -# I2C encoder or helper chips -# -# CONFIG_DRM_I2C_CH7006 is not set -# CONFIG_DRM_I2C_SIL164 is not set -CONFIG_IIO=y -CONFIG_IIO_BUFFER=y -# CONFIG_IIO_SW_RING is not set -CONFIG_IIO_KFIFO_BUF=y -CONFIG_IIO_TRIGGER=y -CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 - -# -# Accelerometers -# -# CONFIG_ADIS16201 is not set -# CONFIG_ADIS16203 is not set -# CONFIG_ADIS16204 is not set -# CONFIG_ADIS16209 is not set -# CONFIG_ADIS16220 is not set -# CONFIG_ADIS16240 is not set -# CONFIG_KXSD9 is not set -# CONFIG_LIS3L02DQ is not set -# CONFIG_SCA3000 is not set - -# -# Analog to digital converters -# -# CONFIG_AD7291 is not set -# CONFIG_AD7298 is not set -# CONFIG_AD7606 is not set -# CONFIG_AD799X is not set -# CONFIG_AD7476 is not set -# CONFIG_AD7887 is not set -# CONFIG_AD7780 is not set -# CONFIG_AD7793 is not set -# CONFIG_AD7816 is not set -# CONFIG_AD7192 is not set -# CONFIG_ADT7310 is not set -# CONFIG_ADT7410 is not set -# CONFIG_AD7280 is not set -# CONFIG_CF_AD9467 is not set -# CONFIG_MAX1363 is not set - -# -# Analog digital bi-direction converters -# -# CONFIG_ADT7316 is not set - -# -# Amplifiers -# -CONFIG_AD8366=y - -# -# Capacitance to digital converters -# -# CONFIG_AD7150 is not set -# CONFIG_AD7152 is not set -# CONFIG_AD7746 is not set - -# -# Digital to analog converters -# -# CONFIG_AD5064 is not set -# CONFIG_AD5360 is not set -# CONFIG_AD5380 is not set -# CONFIG_AD5421 is not set -# CONFIG_AD5624R_SPI is not set -# CONFIG_AD5446 is not set -# CONFIG_AD5504 is not set -# CONFIG_AD5764 is not set -# CONFIG_AD5791 is not set -# CONFIG_AD5686 is not set -# CONFIG_MAX517 is not set - -# -# Frequency Synthesizers DDS/PLL -# - -# -# Clock Generator/Distribution -# -CONFIG_AD9523=y -CONFIG_AD9548=y - -# -# Direct Digital Synthesis -# -# CONFIG_AD5930 is not set -# CONFIG_AD9832 is not set -# CONFIG_AD9834 is not set -# CONFIG_AD9850 is not set -# CONFIG_AD9852 is not set -# CONFIG_AD9910 is not set -# CONFIG_AD9951 is not set -# CONFIG_AD9122_CF is not set - -# -# Phase-Locked Loop (PLL) frequency synthesizers -# -CONFIG_ADF4350=y - -# -# Digital gyroscope sensors -# -# CONFIG_ADIS16060 is not set -# CONFIG_ADIS16080 is not set -# CONFIG_ADIS16130 is not set -# CONFIG_ADIS16260 is not set -# CONFIG_ADXRS450 is not set - -# -# Network Analyzer, Impedance Converters -# -# CONFIG_AD5933 is not set - -# -# Inertial measurement units -# -# CONFIG_ADIS16400 is not set - -# -# Light sensors -# -# CONFIG_SENSORS_ISL29018 is not set -# CONFIG_SENSORS_TSL2563 is not set -# CONFIG_TSL2583 is not set - -# -# Magnetometer sensors -# -# CONFIG_SENSORS_AK8975 is not set -# CONFIG_SENSORS_HMC5843 is not set - -# -# Active energy metering IC -# -# CONFIG_ADE7753 is not set -# CONFIG_ADE7754 is not set -# CONFIG_ADE7758 is not set -# CONFIG_ADE7759 is not set -# CONFIG_ADE7854 is not set - -# -# Resolver to digital converters -# -# CONFIG_AD2S90 is not set -# CONFIG_AD2S1200 is not set -# CONFIG_AD2S1210 is not set - -# -# Triggers - standalone -# -# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set -# CONFIG_IIO_GPIO_TRIGGER is not set -# CONFIG_IIO_SYSFS_TRIGGER is not set -# CONFIG_IIO_SIMPLE_DUMMY is not set -# CONFIG_XVMALLOC is not set -# CONFIG_ZRAM is not set -# CONFIG_FB_SM7XX is not set -# CONFIG_USB_ENESTORAGE is not set -# CONFIG_BCM_WIMAX is not set -# CONFIG_FT1000 is not set - -# -# Speakup console speech -# -# CONFIG_SPEAKUP is not set -# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set -# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set -# CONFIG_STAGING_MEDIA is not set - -# -# Android -# -# CONFIG_ANDROID is not set -CONFIG_CLKDEV_LOOKUP=y - -# -# Hardware Spinlock drivers -# -# CONFIG_IOMMU_SUPPORT is not set -# CONFIG_VIRT_DRIVERS is not set -# CONFIG_PM_DEVFREQ is not set - -# -# Analog to digital converters -# -# CONFIG_AD7266 is not set -CONFIG_CF_AXI_ADC=y -CONFIG_CF_AXI_FFT=y - -# -# Amplifiers -# - -# -# Light sensors -# -# CONFIG_VCNL4000 is not set - -# -# Frequency Synthesizers DDS/PLL -# - -# -# Clock Generator/Distribution -# - -# -# Direct Digital Synthesis -# -CONFIG_CF_AXI_DDS=y -CONFIG_CF_AXI_DDS_AD9122=y - -# -# Phase-Locked Loop (PLL) frequency synthesizers -# - -# -# Digital to analog converters -# -# CONFIG_MCP4725 is not set - -# -# File systems -# -# CONFIG_EXT2_FS is not set -# CONFIG_EXT3_FS is not set -CONFIG_EXT4_FS=y -CONFIG_EXT4_USE_FOR_EXT23=y -CONFIG_EXT4_FS_XATTR=y -# CONFIG_EXT4_FS_POSIX_ACL is not set -# CONFIG_EXT4_FS_SECURITY is not set -# CONFIG_EXT4_DEBUG is not set -CONFIG_JBD2=y -# CONFIG_JBD2_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set -# CONFIG_BTRFS_FS is not set -# CONFIG_NILFS2_FS is not set -# CONFIG_FS_POSIX_ACL is not set -CONFIG_FILE_LOCKING=y -CONFIG_FSNOTIFY=y -# CONFIG_DNOTIFY is not set -CONFIG_INOTIFY_USER=y -# CONFIG_FANOTIFY is not set -# CONFIG_QUOTA is not set -# CONFIG_QUOTACTL is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set - -# -# Caches -# -# CONFIG_FSCACHE is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_SYSCTL=y -CONFIG_PROC_PAGE_MONITOR=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -# CONFIG_TMPFS_POSIX_ACL is not set -# CONFIG_TMPFS_XATTR is not set -# CONFIG_HUGETLB_PAGE is not set -# CONFIG_CONFIGFS_FS is not set -CONFIG_MISC_FILESYSTEMS=y -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS2_FS is not set -# CONFIG_LOGFS is not set -# CONFIG_CRAMFS is not set -# CONFIG_SQUASHFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_OMFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_PSTORE is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set -# CONFIG_NETWORK_FILESYSTEMS is not set -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=y -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -CONFIG_NLS_ASCII=y -CONFIG_NLS_ISO8859_1=y -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set -CONFIG_FRAME_WARN=1024 -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_STRIP_ASM_SYMS is not set -# CONFIG_UNUSED_SYMBOLS is not set -CONFIG_DEBUG_FS=y -# CONFIG_HEADERS_CHECK is not set -# CONFIG_DEBUG_SECTION_MISMATCH is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SHIRQ is not set -# CONFIG_LOCKUP_DETECTOR is not set -# CONFIG_HARDLOCKUP_DETECTOR is not set -CONFIG_DETECT_HUNG_TASK=y -CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=20 -# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 -# CONFIG_SCHED_DEBUG is not set -# CONFIG_SCHEDSTATS is not set -# CONFIG_TIMER_STATS is not set -# CONFIG_DEBUG_OBJECTS is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_KMEMLEAK is not set -# CONFIG_DEBUG_PREEMPT is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set -CONFIG_DEBUG_SPINLOCK=y -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_LOCK_ALLOC=y -CONFIG_PROVE_LOCKING=y -CONFIG_PROVE_RCU=y -# CONFIG_PROVE_RCU_REPEATEDLY is not set -# CONFIG_SPARSE_RCU_POINTER is not set -CONFIG_LOCKDEP=y -# CONFIG_LOCK_STAT is not set -# CONFIG_DEBUG_LOCKDEP is not set -CONFIG_TRACE_IRQFLAGS=y -# CONFIG_DEBUG_ATOMIC_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -CONFIG_STACKTRACE=y -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_KOBJECT is not set -# CONFIG_DEBUG_HIGHMEM is not set -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_INFO=y -# CONFIG_DEBUG_INFO_REDUCED is not set -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_WRITECOUNT is not set -# CONFIG_DEBUG_MEMORY_INIT is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_TEST_LIST_SORT is not set -# CONFIG_DEBUG_SG is not set -# CONFIG_DEBUG_NOTIFIERS is not set -# CONFIG_DEBUG_CREDENTIALS is not set -# CONFIG_BOOT_PRINTK_DELAY is not set -# CONFIG_RCU_TORTURE_TEST is not set -CONFIG_RCU_CPU_STALL_TIMEOUT=60 -# CONFIG_RCU_CPU_STALL_VERBOSE is not set -# CONFIG_BACKTRACE_SELF_TEST is not set -# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set -# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set -# CONFIG_DEBUG_PER_CPU_MAPS is not set -# CONFIG_LKDTM is not set -# CONFIG_FAULT_INJECTION is not set -# CONFIG_SYSCTL_SYSCALL_CHECK is not set -# CONFIG_DEBUG_PAGEALLOC is not set -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -CONFIG_HAVE_C_RECORDMCOUNT=y -CONFIG_TRACING_SUPPORT=y -# CONFIG_FTRACE is not set -# CONFIG_DYNAMIC_DEBUG is not set -# CONFIG_DMA_API_DEBUG is not set -# CONFIG_ATOMIC64_SELFTEST is not set -# CONFIG_SAMPLES is not set -CONFIG_HAVE_ARCH_KGDB=y -# CONFIG_KGDB is not set -# CONFIG_TEST_KSTRTOX is not set -# CONFIG_STRICT_DEVMEM is not set -CONFIG_ARM_UNWIND=y -# CONFIG_DEBUG_USER is not set -CONFIG_DEBUG_LL=y -CONFIG_DEBUG_LL_UART_NONE=y -# CONFIG_DEBUG_ICEDCC is not set -CONFIG_EARLY_PRINTK=y -# CONFIG_OC_ETM is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY_DMESG_RESTRICT is not set -# CONFIG_SECURITY is not set -# CONFIG_SECURITYFS is not set -CONFIG_DEFAULT_SECURITY_DAC=y -CONFIG_DEFAULT_SECURITY="" -CONFIG_CRYPTO=y - -# -# Crypto core or helper -# -# CONFIG_CRYPTO_FIPS is not set -CONFIG_CRYPTO_ALGAPI=m -CONFIG_CRYPTO_ALGAPI2=m -CONFIG_CRYPTO_RNG=m -CONFIG_CRYPTO_RNG2=m -# CONFIG_CRYPTO_MANAGER is not set -# CONFIG_CRYPTO_MANAGER2 is not set -# CONFIG_CRYPTO_USER is not set -# CONFIG_CRYPTO_GF128MUL is not set -# CONFIG_CRYPTO_NULL is not set -# CONFIG_CRYPTO_PCRYPT is not set -# CONFIG_CRYPTO_CRYPTD is not set -# CONFIG_CRYPTO_AUTHENC is not set -# CONFIG_CRYPTO_TEST is not set - -# -# Authenticated Encryption with Associated Data -# -# CONFIG_CRYPTO_CCM is not set -# CONFIG_CRYPTO_GCM is not set -# CONFIG_CRYPTO_SEQIV is not set - -# -# Block modes -# -# CONFIG_CRYPTO_CBC is not set -# CONFIG_CRYPTO_CTR is not set -# CONFIG_CRYPTO_CTS is not set -# CONFIG_CRYPTO_ECB is not set -# CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_PCBC is not set -# CONFIG_CRYPTO_XTS is not set - -# -# Hash modes -# -# CONFIG_CRYPTO_HMAC is not set -# CONFIG_CRYPTO_XCBC is not set -# CONFIG_CRYPTO_VMAC is not set - -# -# Digest -# -# CONFIG_CRYPTO_CRC32C is not set -# CONFIG_CRYPTO_GHASH is not set -# CONFIG_CRYPTO_MD4 is not set -# CONFIG_CRYPTO_MD5 is not set -# CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_RMD128 is not set -# CONFIG_CRYPTO_RMD160 is not set -# CONFIG_CRYPTO_RMD256 is not set -# CONFIG_CRYPTO_RMD320 is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_WP512 is not set - -# -# Ciphers -# -CONFIG_CRYPTO_AES=m -# CONFIG_CRYPTO_ANUBIS is not set -# CONFIG_CRYPTO_ARC4 is not set -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_CAMELLIA is not set -# CONFIG_CRYPTO_CAST5 is not set -# CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_FCRYPT is not set -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_SALSA20 is not set -# CONFIG_CRYPTO_SEED is not set -# CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_TEA is not set -# CONFIG_CRYPTO_TWOFISH is not set - -# -# Compression -# -# CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_ZLIB is not set -# CONFIG_CRYPTO_LZO is not set - -# -# Random Number Generation -# -CONFIG_CRYPTO_ANSI_CPRNG=m -# CONFIG_CRYPTO_USER_API_HASH is not set -# CONFIG_CRYPTO_USER_API_SKCIPHER is not set -CONFIG_CRYPTO_HW=y -# CONFIG_BINARY_PRINTF is not set - -# -# Library routines -# -CONFIG_BITREVERSE=y -CONFIG_GENERIC_PCI_IOMAP=y -# CONFIG_CRC_CCITT is not set -CONFIG_CRC16=y -# CONFIG_CRC_T10DIF is not set -# CONFIG_CRC_ITU_T is not set -CONFIG_CRC32=y -# CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set -# CONFIG_CRC8 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -# CONFIG_XZ_DEC is not set -# CONFIG_XZ_DEC_BCJ is not set -CONFIG_DECOMPRESS_GZIP=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y -CONFIG_CPU_RMAP=y -CONFIG_DQL=y -CONFIG_NLATTR=y -# CONFIG_AVERAGE is not set -# CONFIG_CORDIC is not set diff --git a/arch/arm/configs/xcomm_adv7511_zed_defconfig b/arch/arm/configs/xcomm_adv7511_zed_defconfig deleted file mode 100644 index 62abc73a942f2..0000000000000 --- a/arch/arm/configs/xcomm_adv7511_zed_defconfig +++ /dev/null @@ -1,2418 +0,0 @@ -# -# Automatically generated file; DO NOT EDIT. -# Linux/arm 3.3.0 Kernel Configuration -# -CONFIG_ARM=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_GENERIC_GPIO=y -# CONFIG_ARCH_USES_GETTIMEOFFSET is not set -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_KTIME_SCALAR=y -CONFIG_HAVE_PROC_CPU=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_TRACE_IRQFLAGS_SUPPORT=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_GENERIC_LOCKBREAK=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_VECTORS_BASE=0xffff0000 -# CONFIG_ARM_PATCH_PHYS_VIRT is not set -CONFIG_PHYS_OFFSET=0x0 -CONFIG_GENERIC_BUG=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -CONFIG_HAVE_IRQ_WORK=y -CONFIG_IRQ_WORK=y - -# -# General setup -# -CONFIG_EXPERIMENTAL=y -CONFIG_INIT_ENV_ARG_LIMIT=32 -CONFIG_CROSS_COMPILE="" -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -CONFIG_HAVE_KERNEL_GZIP=y -CONFIG_HAVE_KERNEL_LZMA=y -CONFIG_HAVE_KERNEL_LZO=y -CONFIG_KERNEL_GZIP=y -# CONFIG_KERNEL_LZMA is not set -# CONFIG_KERNEL_LZO is not set -CONFIG_DEFAULT_HOSTNAME="(none)" -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -CONFIG_SYSVIPC_SYSCTL=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_FHANDLE is not set -# CONFIG_TASKSTATS is not set -# CONFIG_AUDIT is not set -CONFIG_HAVE_GENERIC_HARDIRQS=y - -# -# IRQ subsystem -# -CONFIG_GENERIC_HARDIRQS=y -CONFIG_HAVE_SPARSE_IRQ=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_IRQ_DOMAIN=y -# CONFIG_SPARSE_IRQ is not set - -# -# RCU Subsystem -# -CONFIG_TREE_PREEMPT_RCU=y -CONFIG_PREEMPT_RCU=y -# CONFIG_RCU_TRACE is not set -CONFIG_RCU_FANOUT=32 -# CONFIG_RCU_FANOUT_EXACT is not set -# CONFIG_TREE_RCU_TRACE is not set -# CONFIG_RCU_BOOST is not set -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set -# CONFIG_CHECKPOINT_RESTORE is not set -# CONFIG_NAMESPACES is not set -# CONFIG_SCHED_AUTOGROUP is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y -# CONFIG_RELAY is not set -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_RD_GZIP=y -# CONFIG_RD_BZIP2 is not set -# CONFIG_RD_LZMA is not set -# CONFIG_RD_XZ is not set -# CONFIG_RD_LZO is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SYSCTL=y -CONFIG_ANON_INODES=y -CONFIG_EXPERT=y -CONFIG_UID16=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS=y -CONFIG_KALLSYMS_ALL=y -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_AIO=y -CONFIG_EMBEDDED=y -CONFIG_HAVE_PERF_EVENTS=y -CONFIG_PERF_USE_VMALLOC=y - -# -# Kernel Performance Events And Counters -# -CONFIG_PERF_EVENTS=y -# CONFIG_PERF_COUNTERS is not set -# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_COMPAT_BRK=y -CONFIG_SLAB=y -# CONFIG_SLUB is not set -# CONFIG_SLOB is not set -# CONFIG_PROFILING is not set -CONFIG_HAVE_OPROFILE=y -# CONFIG_KPROBES is not set -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_USE_GENERIC_SMP_HELPERS=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_CLK=y -CONFIG_HAVE_DMA_API_DEBUG=y -CONFIG_HAVE_HW_BREAKPOINT=y - -# -# GCOV-based kernel profiling -# -# CONFIG_GCOV_KERNEL is not set -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_SLABINFO=y -CONFIG_RT_MUTEXES=y -CONFIG_BASE_SMALL=0 -CONFIG_MODULES=y -# CONFIG_MODULE_FORCE_LOAD is not set -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MODVERSIONS=y -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_STOP_MACHINE=y -CONFIG_BLOCK=y -CONFIG_LBDAF=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_BLK_DEV_BSGLIB is not set -# CONFIG_BLK_DEV_INTEGRITY is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_CFQ=y -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" -# CONFIG_INLINE_SPIN_TRYLOCK is not set -# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK is not set -# CONFIG_INLINE_SPIN_LOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK_IRQ is not set -# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set -# CONFIG_INLINE_SPIN_UNLOCK is not set -# CONFIG_INLINE_SPIN_UNLOCK_BH is not set -# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set -# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_READ_TRYLOCK is not set -# CONFIG_INLINE_READ_LOCK is not set -# CONFIG_INLINE_READ_LOCK_BH is not set -# CONFIG_INLINE_READ_LOCK_IRQ is not set -# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set -# CONFIG_INLINE_READ_UNLOCK is not set -# CONFIG_INLINE_READ_UNLOCK_BH is not set -# CONFIG_INLINE_READ_UNLOCK_IRQ is not set -# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_WRITE_TRYLOCK is not set -# CONFIG_INLINE_WRITE_LOCK is not set -# CONFIG_INLINE_WRITE_LOCK_BH is not set -# CONFIG_INLINE_WRITE_LOCK_IRQ is not set -# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set -# CONFIG_INLINE_WRITE_UNLOCK is not set -# CONFIG_INLINE_WRITE_UNLOCK_BH is not set -# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set -# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set -# CONFIG_MUTEX_SPIN_ON_OWNER is not set -# CONFIG_FREEZER is not set - -# -# System Type -# -CONFIG_MMU=y -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_REALVIEW is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_VEXPRESS is not set -# CONFIG_ARCH_AT91 is not set -# CONFIG_ARCH_BCMRING is not set -# CONFIG_ARCH_HIGHBANK is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CNS3XXX is not set -# CONFIG_ARCH_GEMINI is not set -# CONFIG_ARCH_PRIMA2 is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_EP93XX is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_MXC is not set -# CONFIG_ARCH_MXS is not set -# CONFIG_ARCH_NETX is not set -# CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_IOP13XX is not set -# CONFIG_ARCH_IOP32X is not set -# CONFIG_ARCH_IOP33X is not set -# CONFIG_ARCH_IXP23XX is not set -# CONFIG_ARCH_IXP2000 is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_DOVE is not set -# CONFIG_ARCH_KIRKWOOD is not set -# CONFIG_ARCH_LPC32XX is not set -# CONFIG_ARCH_MV78XX0 is not set -# CONFIG_ARCH_ORION5X is not set -# CONFIG_ARCH_MMP is not set -# CONFIG_ARCH_KS8695 is not set -# CONFIG_ARCH_W90X900 is not set -# CONFIG_ARCH_TEGRA is not set -# CONFIG_ARCH_PICOXCELL is not set -# CONFIG_ARCH_PNX4008 is not set -# CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_MSM is not set -# CONFIG_ARCH_SHMOBILE is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_S3C64XX is not set -# CONFIG_ARCH_S5P64X0 is not set -# CONFIG_ARCH_S5PC100 is not set -# CONFIG_ARCH_S5PV210 is not set -# CONFIG_ARCH_EXYNOS is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_U300 is not set -# CONFIG_ARCH_U8500 is not set -# CONFIG_ARCH_NOMADIK is not set -# CONFIG_ARCH_DAVINCI is not set -# CONFIG_ARCH_OMAP is not set -# CONFIG_PLAT_SPEAR is not set -# CONFIG_ARCH_VT8500 is not set -CONFIG_ARCH_ZYNQ=y -# CONFIG_GPIO_PCA953X is not set -# CONFIG_KEYBOARD_GPIO_POLLED is not set - -# -# System MMU -# - -# -# Xilinx Specific Options -# -CONFIG_ZYNQ_EARLY_UART1=y -# CONFIG_ZYNQ_EARLY_UART_EP107 is not set -CONFIG_XILINX_FIXED_DEVTREE_ADDR=y -CONFIG_XILINX_L1_PREFETCH=y -CONFIG_XILINX_L2_PREFETCH=y -CONFIG_XILINX_ZED=y -# CONFIG_XILINX_TEST is not set -CONFIG_ZYNQ_DEFAULT_KERNEL=y -# CONFIG_ZYNQ_AMP_CPU0_MASTER is not set -# CONFIG_ZYNQ_AMP_CPU1_SLAVE is not set -# CONFIG_ZYNQ_CPU1_TEST is not set - -# -# Processor Type -# -CONFIG_CPU_V7=y -CONFIG_CPU_32v6K=y -CONFIG_CPU_32v7=y -CONFIG_CPU_ABRT_EV7=y -CONFIG_CPU_PABRT_V7=y -CONFIG_CPU_CACHE_V7=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_TLB_V7=y -CONFIG_CPU_HAS_ASID=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y - -# -# Processor Features -# -# CONFIG_ARM_LPAE is not set -# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set -CONFIG_ARM_THUMB=y -# CONFIG_ARM_THUMBEE is not set -CONFIG_SWP_EMULATE=y -# CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set -# CONFIG_CPU_BPREDICT_DISABLE is not set -CONFIG_OUTER_CACHE=y -CONFIG_OUTER_CACHE_SYNC=y -CONFIG_CACHE_L2X0=y -CONFIG_CACHE_PL310=y -CONFIG_ARM_L1_CACHE_SHIFT_6=y -CONFIG_ARM_L1_CACHE_SHIFT=6 -CONFIG_ARM_DMA_MEM_BUFFERABLE=y -CONFIG_ARM_NR_BANKS=8 -CONFIG_CPU_HAS_PMU=y -CONFIG_MULTI_IRQ_HANDLER=y -# CONFIG_ARM_ERRATA_430973 is not set -# CONFIG_ARM_ERRATA_458693 is not set -# CONFIG_ARM_ERRATA_460075 is not set -# CONFIG_ARM_ERRATA_742230 is not set -# CONFIG_ARM_ERRATA_742231 is not set -# CONFIG_PL310_ERRATA_588369 is not set -# CONFIG_ARM_ERRATA_720789 is not set -# CONFIG_PL310_ERRATA_727915 is not set -# CONFIG_ARM_ERRATA_743622 is not set -# CONFIG_ARM_ERRATA_751472 is not set -# CONFIG_PL310_ERRATA_753970 is not set -# CONFIG_ARM_ERRATA_754322 is not set -# CONFIG_ARM_ERRATA_754327 is not set -# CONFIG_ARM_ERRATA_764369 is not set -# CONFIG_PL310_ERRATA_769419 is not set -CONFIG_ARM_GIC=y -CONFIG_ICST=y - -# -# Bus support -# -CONFIG_ARM_AMBA=y -CONFIG_ISA_DMA_API=y -# CONFIG_PCI_SYSCALL is not set -# CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCCARD is not set - -# -# Kernel Features -# -CONFIG_TICK_ONESHOT=y -# CONFIG_NO_HZ is not set -CONFIG_HIGH_RES_TIMERS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -CONFIG_HAVE_SMP=y -CONFIG_SMP=y -CONFIG_SMP_ON_UP=y -CONFIG_ARM_CPU_TOPOLOGY=y -# CONFIG_SCHED_MC is not set -# CONFIG_SCHED_SMT is not set -CONFIG_HAVE_ARM_SCU=y -CONFIG_HAVE_ARM_TWD=y -CONFIG_VMSPLIT_3G=y -# CONFIG_VMSPLIT_2G is not set -# CONFIG_VMSPLIT_1G is not set -CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_NR_CPUS=4 -# CONFIG_HOTPLUG_CPU is not set -CONFIG_LOCAL_TIMERS=y -CONFIG_ARCH_NR_GPIO=0 -# CONFIG_PREEMPT_NONE is not set -# CONFIG_PREEMPT_VOLUNTARY is not set -CONFIG_PREEMPT=y -CONFIG_PREEMPT_COUNT=y -CONFIG_HZ=100 -# CONFIG_THUMB2_KERNEL is not set -CONFIG_AEABI=y -# CONFIG_OABI_COMPAT is not set -# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set -# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set -CONFIG_HAVE_ARCH_PFN_VALID=y -CONFIG_HIGHMEM=y -# CONFIG_HIGHPTE is not set -CONFIG_HW_PERF_EVENTS=y -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -CONFIG_HAVE_MEMBLOCK=y -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_SPLIT_PTLOCK_CPUS=999999 -# CONFIG_COMPACTION is not set -# CONFIG_PHYS_ADDR_T_64BIT is not set -CONFIG_ZONE_DMA_FLAG=0 -CONFIG_BOUNCE=y -CONFIG_VIRT_TO_BUS=y -# CONFIG_KSM is not set -CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 -# CONFIG_CLEANCACHE is not set -CONFIG_FORCE_MAX_ZONEORDER=15 -CONFIG_ALIGNMENT_TRAP=y -# CONFIG_UACCESS_WITH_MEMCPY is not set -# CONFIG_SECCOMP is not set -# CONFIG_CC_STACKPROTECTOR is not set -# CONFIG_DEPRECATED_PARAM_STRUCT is not set - -# -# Boot options -# -CONFIG_USE_OF=y -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -# CONFIG_ARM_APPENDED_DTB is not set -CONFIG_CMDLINE="console=ttyPS0,115200n8 root=/dev/ram rw initrd=0x00800000,16M earlyprintk mtdparts=physmap-flash.0:512K(nor-fsbl),512K(nor-u-boot),5M(nor-linux),9M(nor-user),1M(nor-scratch),-(nor-rootfs)" -CONFIG_CMDLINE_FROM_BOOTLOADER=y -# CONFIG_CMDLINE_EXTEND is not set -# CONFIG_CMDLINE_FORCE is not set -# CONFIG_XIP_KERNEL is not set -# CONFIG_CRASH_DUMP is not set -# CONFIG_AUTO_ZRELADDR is not set - -# -# CPU Power Management -# -# CONFIG_CPU_IDLE is not set - -# -# Floating point emulation -# - -# -# At least one emulation must be selected -# -CONFIG_VFP=y -CONFIG_VFPv3=y -CONFIG_NEON=y - -# -# Userspace binary formats -# -CONFIG_BINFMT_ELF=y -CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_HAVE_AOUT=y -# CONFIG_BINFMT_AOUT is not set -# CONFIG_BINFMT_MISC is not set - -# -# Power management options -# -# CONFIG_SUSPEND is not set -CONFIG_PM_RUNTIME=y -CONFIG_PM=y -# CONFIG_PM_DEBUG is not set -# CONFIG_APM_EMULATION is not set -CONFIG_PM_CLK=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -# CONFIG_ARM_CPU_SUSPEND is not set -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_UNIX=y -# CONFIG_UNIX_DIAG is not set -CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set -# CONFIG_XFRM_SUB_POLICY is not set -# CONFIG_XFRM_MIGRATE is not set -# CONFIG_XFRM_STATISTICS is not set -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_IP_PNP_RARP=y -CONFIG_NET_IPIP=m -# CONFIG_NET_IPGRE_DEMUX is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_XFRM_TUNNEL is not set -CONFIG_INET_TUNNEL=m -CONFIG_INET_XFRM_MODE_TRANSPORT=y -CONFIG_INET_XFRM_MODE_TUNNEL=y -CONFIG_INET_XFRM_MODE_BEET=y -CONFIG_INET_LRO=y -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_INET_UDP_DIAG is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set -CONFIG_IPV6=m -# CONFIG_IPV6_PRIVACY is not set -# CONFIG_IPV6_ROUTER_PREF is not set -# CONFIG_IPV6_OPTIMISTIC_DAD is not set -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_IPV6_MIP6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set -CONFIG_INET6_XFRM_MODE_TRANSPORT=m -CONFIG_INET6_XFRM_MODE_TUNNEL=m -CONFIG_INET6_XFRM_MODE_BEET=m -# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set -CONFIG_IPV6_SIT=m -# CONFIG_IPV6_SIT_6RD is not set -CONFIG_IPV6_NDISC_NODETYPE=y -# CONFIG_IPV6_TUNNEL is not set -# CONFIG_IPV6_MULTIPLE_TABLES is not set -# CONFIG_IPV6_MROUTE is not set -# CONFIG_NETWORK_SECMARK is not set -# CONFIG_NETWORK_PHY_TIMESTAMPING is not set -# CONFIG_NETFILTER is not set -# CONFIG_IP_DCCP is not set -# CONFIG_IP_SCTP is not set -# CONFIG_RDS is not set -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -# CONFIG_L2TP is not set -# CONFIG_BRIDGE is not set -# CONFIG_NET_DSA is not set -CONFIG_VLAN_8021Q=m -# CONFIG_VLAN_8021Q_GVRP is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_PHONET is not set -# CONFIG_IEEE802154 is not set -# CONFIG_NET_SCHED is not set -# CONFIG_DCB is not set -# CONFIG_BATMAN_ADV is not set -# CONFIG_OPENVSWITCH is not set -CONFIG_RPS=y -CONFIG_RFS_ACCEL=y -CONFIG_XPS=y -CONFIG_BQL=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_HAMRADIO is not set -# CONFIG_CAN is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_AF_RXRPC is not set -CONFIG_WIRELESS=y -# CONFIG_CFG80211 is not set -# CONFIG_LIB80211 is not set - -# -# CFG80211 needs to be enabled for MAC80211 -# -# CONFIG_WIMAX is not set -# CONFIG_RFKILL is not set -# CONFIG_NET_9P is not set -# CONFIG_CAIF is not set -# CONFIG_CEPH_LIB is not set -# CONFIG_NFC is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m -CONFIG_FIRMWARE_IN_KERNEL=y -CONFIG_EXTRA_FIRMWARE="" -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_SYS_HYPERVISOR is not set -# CONFIG_GENERIC_CPU_DEVICES is not set -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -CONFIG_REGMAP_SPI=y -# CONFIG_DMA_SHARED_BUFFER is not set -CONFIG_CONNECTOR=y -CONFIG_PROC_EVENTS=y -CONFIG_MTD=y -# CONFIG_MTD_TESTS is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set -CONFIG_MTD_OF_PARTS=y -# CONFIG_MTD_AR7_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLKDEVS=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set -# CONFIG_RFD_FTL is not set -# CONFIG_SSFDC is not set -# CONFIG_SM_FTL is not set -# CONFIG_MTD_OOPS is not set -# CONFIG_MTD_SWAP is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -CONFIG_MTD_MAP_BANK_WIDTH_4=y -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CFI_AMDSTD=y -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=y -# CONFIG_MTD_PHYSMAP_COMPAT is not set -CONFIG_MTD_PHYSMAP_OF=y -# CONFIG_MTD_PLATRAM is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_DATAFLASH is not set -CONFIG_MTD_M25P80=y -# CONFIG_M25PXX_USE_FAST_READ is not set -# CONFIG_MTD_SST25L is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLOCK2MTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set -# CONFIG_MTD_DOCG3 is not set -CONFIG_MTD_NAND_ECC=y -# CONFIG_MTD_NAND_ECC_SMC is not set -CONFIG_MTD_NAND=y -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -# CONFIG_MTD_NAND_ECC_BCH is not set -# CONFIG_MTD_SM_COMMON is not set -# CONFIG_MTD_NAND_MUSEUM_IDS is not set -# CONFIG_MTD_NAND_GPIO is not set -CONFIG_MTD_NAND_IDS=y -# CONFIG_MTD_NAND_DISKONCHIP is not set -# CONFIG_MTD_NAND_NANDSIM is not set -# CONFIG_MTD_NAND_PLATFORM is not set -# CONFIG_MTD_ALAUDA is not set -CONFIG_MTD_NAND_XILINX_PSS=y -# CONFIG_MTD_ONENAND is not set - -# -# LPDDR flash memory drivers -# -# CONFIG_MTD_LPDDR is not set -# CONFIG_MTD_UBI is not set -CONFIG_DTC=y -CONFIG_OF=y - -# -# Device Tree and Open Firmware support -# -CONFIG_PROC_DEVICETREE=y -# CONFIG_OF_SELFTEST is not set -CONFIG_OF_FLATTREE=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_IRQ=y -CONFIG_OF_DEVICE=y -CONFIG_OF_GPIO=y -CONFIG_OF_I2C=y -CONFIG_OF_NET=y -CONFIG_OF_SPI=y -CONFIG_OF_MDIO=y -# CONFIG_PARPORT is not set -CONFIG_BLK_DEV=y -# CONFIG_BLK_DEV_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_DRBD is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_UB is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=35384 -# CONFIG_BLK_DEV_XIP is not set -# CONFIG_CDROM_PKTCDVD is not set -# CONFIG_ATA_OVER_ETH is not set -# CONFIG_MG_DISK is not set -# CONFIG_BLK_DEV_RBD is not set - -# -# Misc devices -# -# CONFIG_SENSORS_LIS3LV02D is not set -# CONFIG_AD525X_DPOT is not set -# CONFIG_ATMEL_PWM is not set -# CONFIG_ICS932S401 is not set -# CONFIG_ENCLOSURE_SERVICES is not set -# CONFIG_APDS9802ALS is not set -# CONFIG_ISL29003 is not set -# CONFIG_ISL29020 is not set -# CONFIG_SENSORS_TSL2550 is not set -# CONFIG_SENSORS_BH1780 is not set -# CONFIG_SENSORS_BH1770 is not set -# CONFIG_SENSORS_APDS990X is not set -# CONFIG_HMC6352 is not set -# CONFIG_DS1682 is not set -# CONFIG_TI_DAC7512 is not set -# CONFIG_BMP085 is not set -# CONFIG_USB_SWITCH_FSA9480 is not set -# CONFIG_SI570 is not set -# CONFIG_C2PORT is not set - -# -# EEPROM support -# -CONFIG_EEPROM_AT24=y -CONFIG_EEPROM_AT25=y -# CONFIG_EEPROM_LEGACY is not set -# CONFIG_EEPROM_MAX6875 is not set -# CONFIG_EEPROM_93CX6 is not set -# CONFIG_EEPROM_93XX46 is not set -# CONFIG_IWMC3200TOP is not set - -# -# Texas Instruments shared transport line discipline -# -# CONFIG_TI_ST is not set -# CONFIG_SENSORS_LIS3_SPI is not set -# CONFIG_SENSORS_LIS3_I2C is not set - -# -# Altera FPGA firmware download module -# -# CONFIG_ALTERA_STAPL is not set - -# -# SCSI device support -# -CONFIG_SCSI_MOD=y -# CONFIG_RAID_ATTRS is not set -CONFIG_SCSI=y -CONFIG_SCSI_DMA=y -# CONFIG_SCSI_TGT is not set -# CONFIG_SCSI_NETLINK is not set -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -# CONFIG_BLK_DEV_SR is not set -CONFIG_CHR_DEV_SG=y -# CONFIG_CHR_DEV_SCH is not set -CONFIG_SCSI_MULTI_LUN=y -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set -# CONFIG_SCSI_SCAN_ASYNC is not set -CONFIG_SCSI_WAIT_SCAN=m - -# -# SCSI Transports -# -# CONFIG_SCSI_SPI_ATTRS is not set -# CONFIG_SCSI_FC_ATTRS is not set -# CONFIG_SCSI_ISCSI_ATTRS is not set -# CONFIG_SCSI_SAS_ATTRS is not set -# CONFIG_SCSI_SAS_LIBSAS is not set -# CONFIG_SCSI_SRP_ATTRS is not set -CONFIG_SCSI_LOWLEVEL=y -# CONFIG_ISCSI_TCP is not set -# CONFIG_ISCSI_BOOT_SYSFS is not set -# CONFIG_LIBFC is not set -# CONFIG_LIBFCOE is not set -# CONFIG_SCSI_DEBUG is not set -# CONFIG_SCSI_DH is not set -# CONFIG_SCSI_OSD_INITIATOR is not set -# CONFIG_ATA is not set -# CONFIG_MD is not set -# CONFIG_TARGET_CORE is not set -CONFIG_NETDEVICES=y -CONFIG_NET_CORE=y -# CONFIG_BONDING is not set -# CONFIG_DUMMY is not set -# CONFIG_EQUALIZER is not set -# CONFIG_MII is not set -# CONFIG_NET_TEAM is not set -# CONFIG_MACVLAN is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_TUN is not set -# CONFIG_VETH is not set - -# -# CAIF transport drivers -# -CONFIG_ETHERNET=y -# CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_NET_CALXEDA_XGMAC is not set -# CONFIG_NET_VENDOR_CHELSIO is not set -# CONFIG_DM9000 is not set -# CONFIG_DNET is not set -# CONFIG_NET_VENDOR_FARADAY is not set -# CONFIG_NET_VENDOR_INTEL is not set -# CONFIG_NET_VENDOR_MARVELL is not set -# CONFIG_NET_VENDOR_MICREL is not set -# CONFIG_NET_VENDOR_MICROCHIP is not set -# CONFIG_NET_VENDOR_NATSEMI is not set -# CONFIG_ETHOC is not set -# CONFIG_NET_VENDOR_SEEQ is not set -# CONFIG_NET_VENDOR_SMSC is not set -# CONFIG_NET_VENDOR_STMICRO is not set -CONFIG_NET_VENDOR_XILINX=y -CONFIG_XILINX_PS_EMAC=y -CONFIG_XILINX_PS_EMAC_HWTSTAMP=y -CONFIG_PHYLIB=y - -# -# MII PHY device drivers -# -CONFIG_MARVELL_PHY=y -# CONFIG_DAVICOM_PHY is not set -# CONFIG_QSEMI_PHY is not set -# CONFIG_LXT_PHY is not set -# CONFIG_CICADA_PHY is not set -# CONFIG_VITESSE_PHY is not set -# CONFIG_SMSC_PHY is not set -# CONFIG_BROADCOM_PHY is not set -# CONFIG_ICPLUS_PHY is not set -# CONFIG_REALTEK_PHY is not set -# CONFIG_NATIONAL_PHY is not set -# CONFIG_STE10XP is not set -# CONFIG_LSI_ET1011C_PHY is not set -# CONFIG_MICREL_PHY is not set -# CONFIG_FIXED_PHY is not set -CONFIG_MDIO_BITBANG=y -# CONFIG_MDIO_GPIO is not set -# CONFIG_MICREL_KS8995MA is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# USB Network Adapters -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set -# CONFIG_USB_IPHETH is not set -# CONFIG_WLAN is not set - -# -# Enable WiMAX (Networking options) to see the WiMAX drivers -# -# CONFIG_WAN is not set -# CONFIG_ISDN is not set -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set -# CONFIG_INPUT_POLLDEV is not set -CONFIG_INPUT_SPARSEKMAP=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -# CONFIG_KEYBOARD_ADP5588 is not set -# CONFIG_KEYBOARD_ADP5589 is not set -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_QT1070 is not set -# CONFIG_KEYBOARD_QT2160 is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_GPIO is not set -# CONFIG_KEYBOARD_TCA6416 is not set -# CONFIG_KEYBOARD_TCA8418 is not set -# CONFIG_KEYBOARD_MATRIX is not set -# CONFIG_KEYBOARD_MAX7359 is not set -# CONFIG_KEYBOARD_MCS is not set -# CONFIG_KEYBOARD_MPR121 is not set -# CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_KEYBOARD_OPENCORES is not set -# CONFIG_KEYBOARD_SAMSUNG is not set -# CONFIG_KEYBOARD_STOWAWAY is not set -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=y -CONFIG_MOUSE_PS2_ALPS=y -CONFIG_MOUSE_PS2_LOGIPS2PP=y -CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_TRACKPOINT=y -# CONFIG_MOUSE_PS2_ELANTECH is not set -# CONFIG_MOUSE_PS2_SENTELIC is not set -# CONFIG_MOUSE_PS2_TOUCHKIT is not set -# CONFIG_MOUSE_SERIAL is not set -# CONFIG_MOUSE_APPLETOUCH is not set -# CONFIG_MOUSE_BCM5974 is not set -# CONFIG_MOUSE_VSXXXAA is not set -# CONFIG_MOUSE_GPIO is not set -# CONFIG_MOUSE_SYNAPTICS_I2C is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TABLET is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_AMBAKMI is not set -CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set -# CONFIG_SERIO_ALTERA_PS2 is not set -# CONFIG_SERIO_PS2MULT is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -CONFIG_VT_HW_CONSOLE_BINDING=y -CONFIG_UNIX98_PTYS=y -# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_N_GSM is not set -# CONFIG_TRACE_SINK is not set -# CONFIG_DEVKMEM is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -# CONFIG_SERIAL_AMBA_PL010 is not set -# CONFIG_SERIAL_AMBA_PL011 is not set -# CONFIG_SERIAL_MAX3100 is not set -# CONFIG_SERIAL_MAX3107 is not set -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_TIMBERDALE is not set -# CONFIG_SERIAL_ALTERA_JTAGUART is not set -# CONFIG_SERIAL_ALTERA_UART is not set -# CONFIG_SERIAL_IFX6X60 is not set -CONFIG_SERIAL_XILINX_PS_UART=y -CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y -# CONFIG_TTY_PRINTK is not set -# CONFIG_HVC_DCC is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_HW_RANDOM is not set -CONFIG_XILINX_DEVCFG=y -# CONFIG_R3964 is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set -# CONFIG_RAMOOPS is not set -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_COMPAT=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_MUX=y - -# -# Multiplexer I2C Chip support -# -# CONFIG_I2C_MUX_GPIO is not set -# CONFIG_I2C_MUX_PCA9541 is not set -CONFIG_I2C_MUX_PCA954x=y -CONFIG_I2C_HELPER_AUTO=y -CONFIG_I2C_ALGOBIT=y - -# -# I2C Hardware Bus support -# - -# -# I2C system bus drivers (mostly embedded / system-on-chip) -# -# CONFIG_I2C_DESIGNWARE_PLATFORM is not set -CONFIG_I2C_GPIO=y -# CONFIG_I2C_OCORES is not set -# CONFIG_I2C_PCA_PLATFORM is not set -# CONFIG_I2C_PXA_PCI is not set -# CONFIG_I2C_SIMTEC is not set -# CONFIG_I2C_XILINX_PS is not set -CONFIG_I2C_XILINX=y - -# -# External I2C/SMBus adapter drivers -# -# CONFIG_I2C_DIOLAN_U2C is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_TAOS_EVM is not set -# CONFIG_I2C_TINY_USB is not set - -# -# Other I2C/SMBus bus drivers -# -# CONFIG_I2C_STUB is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -CONFIG_SPI=y -# CONFIG_SPI_DEBUG is not set -CONFIG_SPI_MASTER=y - -# -# SPI Master Controller Drivers -# -# CONFIG_SPI_ALTERA is not set -CONFIG_SPI_BITBANG=y -# CONFIG_SPI_GPIO is not set -# CONFIG_SPI_OC_TINY is not set -# CONFIG_SPI_PL022 is not set -# CONFIG_SPI_PXA2XX_PCI is not set -CONFIG_SPI_XCOMM=y -# CONFIG_SPI_XILINX is not set -CONFIG_SPI_XILINX_PS_QSPI=y -# CONFIG_XILINX_PS_QSPI_USE_DUAL_FLASH is not set -CONFIG_SPI_XILINX_PS_SPI=y -# CONFIG_SPI_DESIGNWARE is not set - -# -# SPI Protocol Masters -# -# CONFIG_SPI_SPIDEV is not set -# CONFIG_SPI_TLE62X0 is not set - -# -# PPS support -# -# CONFIG_PPS is not set - -# -# PPS generators support -# - -# -# PTP clock support -# - -# -# Enable Device Drivers -> PPS to see the PTP clock options. -# -CONFIG_ARCH_REQUIRE_GPIOLIB=y -CONFIG_GPIOLIB=y -# CONFIG_DEBUG_GPIO is not set -CONFIG_GPIO_SYSFS=y - -# -# Memory mapped GPIO drivers: -# -# CONFIG_GPIO_GENERIC_PLATFORM is not set -# CONFIG_GPIO_PL061 is not set -# CONFIG_GPIO_XILINX is not set -CONFIG_GPIO_XILINX_PS=y - -# -# I2C GPIO expanders: -# -# CONFIG_GPIO_MAX7300 is not set -# CONFIG_GPIO_MAX732X is not set -# CONFIG_GPIO_PCF857X is not set -# CONFIG_GPIO_SX150X is not set -# CONFIG_GPIO_ADP5588 is not set - -# -# PCI GPIO expanders: -# - -# -# SPI GPIO expanders: -# -# CONFIG_GPIO_MAX7301 is not set -# CONFIG_GPIO_MCP23S08 is not set -# CONFIG_GPIO_MC33880 is not set -# CONFIG_GPIO_74X164 is not set - -# -# AC97 GPIO expanders: -# - -# -# MODULbus GPIO expanders: -# -# CONFIG_W1 is not set -# CONFIG_POWER_SUPPLY is not set -# CONFIG_HWMON is not set -# CONFIG_THERMAL is not set -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_CORE is not set -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_ARM_SP805_WATCHDOG is not set -# CONFIG_DW_WATCHDOG is not set -# CONFIG_MPCORE_WATCHDOG is not set -# CONFIG_XILINX_PS_WATCHDOG is not set -# CONFIG_XILINX_SCU_WATCHDOG is not set -# CONFIG_MAX63XX_WATCHDOG is not set - -# -# USB-based Watchdog Cards -# -# CONFIG_USBPCWATCHDOG is not set -CONFIG_SSB_POSSIBLE=y - -# -# Sonics Silicon Backplane -# -# CONFIG_SSB is not set -CONFIG_BCMA_POSSIBLE=y - -# -# Broadcom specific AMBA -# -# CONFIG_BCMA is not set - -# -# Multifunction device drivers -# -# CONFIG_MFD_CORE is not set -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_MFD_ASIC3 is not set -# CONFIG_HTC_EGPIO is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_HTC_I2CPLD is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS65010 is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS65910 is not set -# CONFIG_MFD_TPS65912_I2C is not set -# CONFIG_MFD_TPS65912_SPI is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MFD_TC6387XB is not set -# CONFIG_MFD_TC6393XB is not set -# CONFIG_PMIC_DA903X is not set -# CONFIG_MFD_DA9052_SPI is not set -# CONFIG_MFD_DA9052_I2C is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_MAX8925 is not set -# CONFIG_MFD_MAX8997 is not set -# CONFIG_MFD_MAX8998 is not set -# CONFIG_MFD_S5M_CORE is not set -# CONFIG_MFD_WM8400 is not set -# CONFIG_MFD_WM831X_I2C is not set -# CONFIG_MFD_WM831X_SPI is not set -# CONFIG_MFD_WM8350_I2C is not set -# CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_EZX_PCAP is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_AAT2870_CORE is not set -# CONFIG_REGULATOR is not set -CONFIG_MEDIA_SUPPORT=y - -# -# Multimedia core support -# -# CONFIG_MEDIA_CONTROLLER is not set -CONFIG_VIDEO_DEV=y -CONFIG_VIDEO_V4L2_COMMON=y -# CONFIG_DVB_CORE is not set -CONFIG_VIDEO_MEDIA=y - -# -# Multimedia drivers -# -# CONFIG_RC_CORE is not set -# CONFIG_MEDIA_ATTACH is not set -CONFIG_MEDIA_TUNER=y -# CONFIG_MEDIA_TUNER_CUSTOMISE is not set -CONFIG_MEDIA_TUNER_SIMPLE=y -CONFIG_MEDIA_TUNER_TDA8290=y -CONFIG_MEDIA_TUNER_TDA827X=y -CONFIG_MEDIA_TUNER_TDA18271=y -CONFIG_MEDIA_TUNER_TDA9887=y -CONFIG_MEDIA_TUNER_TEA5761=y -CONFIG_MEDIA_TUNER_TEA5767=y -CONFIG_MEDIA_TUNER_MT20XX=y -CONFIG_MEDIA_TUNER_XC2028=y -CONFIG_MEDIA_TUNER_XC5000=y -CONFIG_MEDIA_TUNER_XC4000=y -CONFIG_MEDIA_TUNER_MC44S803=y -CONFIG_VIDEO_V4L2=y -CONFIG_VIDEOBUF2_CORE=y -CONFIG_VIDEOBUF2_MEMOPS=y -CONFIG_VIDEOBUF2_VMALLOC=y -CONFIG_VIDEO_CAPTURE_DRIVERS=y -# CONFIG_VIDEO_ADV_DEBUG is not set -# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set -# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set - -# -# Encoders, decoders, sensors and other helper chips -# - -# -# Audio decoders, processors and mixers -# -# CONFIG_VIDEO_TVAUDIO is not set -# CONFIG_VIDEO_TDA7432 is not set -# CONFIG_VIDEO_TDA9840 is not set -# CONFIG_VIDEO_TEA6415C is not set -# CONFIG_VIDEO_TEA6420 is not set -# CONFIG_VIDEO_MSP3400 is not set -# CONFIG_VIDEO_CS5345 is not set -# CONFIG_VIDEO_CS53L32A is not set -# CONFIG_VIDEO_TLV320AIC23B is not set -# CONFIG_VIDEO_WM8775 is not set -# CONFIG_VIDEO_WM8739 is not set -# CONFIG_VIDEO_VP27SMPX is not set - -# -# RDS decoders -# -# CONFIG_VIDEO_SAA6588 is not set - -# -# Video decoders -# -# CONFIG_VIDEO_ADV7180 is not set -# CONFIG_VIDEO_BT819 is not set -# CONFIG_VIDEO_BT856 is not set -# CONFIG_VIDEO_BT866 is not set -# CONFIG_VIDEO_KS0127 is not set -# CONFIG_VIDEO_SAA7110 is not set -# CONFIG_VIDEO_SAA711X is not set -# CONFIG_VIDEO_SAA7191 is not set -# CONFIG_VIDEO_TVP514X is not set -# CONFIG_VIDEO_TVP5150 is not set -# CONFIG_VIDEO_TVP7002 is not set -# CONFIG_VIDEO_VPX3220 is not set - -# -# Video and audio decoders -# -# CONFIG_VIDEO_SAA717X is not set -# CONFIG_VIDEO_CX25840 is not set - -# -# MPEG video encoders -# -# CONFIG_VIDEO_CX2341X is not set - -# -# Video encoders -# -# CONFIG_VIDEO_SAA7127 is not set -# CONFIG_VIDEO_SAA7185 is not set -# CONFIG_VIDEO_ADV7170 is not set -# CONFIG_VIDEO_ADV7175 is not set -# CONFIG_VIDEO_ADV7343 is not set -# CONFIG_VIDEO_AK881X is not set - -# -# Camera sensor devices -# -# CONFIG_VIDEO_OV7670 is not set -# CONFIG_VIDEO_MT9V011 is not set -# CONFIG_VIDEO_TCM825X is not set -# CONFIG_VIDEO_SR030PC30 is not set - -# -# Flash devices -# - -# -# Video improvement chips -# -# CONFIG_VIDEO_UPD64031A is not set -# CONFIG_VIDEO_UPD64083 is not set - -# -# Miscelaneous helper chips -# -# CONFIG_VIDEO_THS7303 is not set -# CONFIG_VIDEO_M52790 is not set -# CONFIG_VIDEO_VIVI is not set -CONFIG_V4L_USB_DRIVERS=y -CONFIG_USB_VIDEO_CLASS=y -CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y -CONFIG_USB_GSPCA=y -# CONFIG_USB_M5602 is not set -# CONFIG_USB_STV06XX is not set -# CONFIG_USB_GL860 is not set -# CONFIG_USB_GSPCA_BENQ is not set -# CONFIG_USB_GSPCA_CONEX is not set -# CONFIG_USB_GSPCA_CPIA1 is not set -# CONFIG_USB_GSPCA_ETOMS is not set -# CONFIG_USB_GSPCA_FINEPIX is not set -# CONFIG_USB_GSPCA_JEILINJ is not set -# CONFIG_USB_GSPCA_JL2005BCD is not set -# CONFIG_USB_GSPCA_KINECT is not set -# CONFIG_USB_GSPCA_KONICA is not set -# CONFIG_USB_GSPCA_MARS is not set -# CONFIG_USB_GSPCA_MR97310A is not set -# CONFIG_USB_GSPCA_NW80X is not set -# CONFIG_USB_GSPCA_OV519 is not set -# CONFIG_USB_GSPCA_OV534 is not set -# CONFIG_USB_GSPCA_OV534_9 is not set -# CONFIG_USB_GSPCA_PAC207 is not set -# CONFIG_USB_GSPCA_PAC7302 is not set -# CONFIG_USB_GSPCA_PAC7311 is not set -# CONFIG_USB_GSPCA_SE401 is not set -# CONFIG_USB_GSPCA_SN9C2028 is not set -# CONFIG_USB_GSPCA_SN9C20X is not set -# CONFIG_USB_GSPCA_SONIXB is not set -# CONFIG_USB_GSPCA_SONIXJ is not set -# CONFIG_USB_GSPCA_SPCA500 is not set -# CONFIG_USB_GSPCA_SPCA501 is not set -# CONFIG_USB_GSPCA_SPCA505 is not set -# CONFIG_USB_GSPCA_SPCA506 is not set -# CONFIG_USB_GSPCA_SPCA508 is not set -# CONFIG_USB_GSPCA_SPCA561 is not set -# CONFIG_USB_GSPCA_SPCA1528 is not set -# CONFIG_USB_GSPCA_SQ905 is not set -# CONFIG_USB_GSPCA_SQ905C is not set -# CONFIG_USB_GSPCA_SQ930X is not set -# CONFIG_USB_GSPCA_STK014 is not set -# CONFIG_USB_GSPCA_STV0680 is not set -# CONFIG_USB_GSPCA_SUNPLUS is not set -# CONFIG_USB_GSPCA_T613 is not set -# CONFIG_USB_GSPCA_TOPRO is not set -# CONFIG_USB_GSPCA_TV8532 is not set -# CONFIG_USB_GSPCA_VC032X is not set -# CONFIG_USB_GSPCA_VICAM is not set -# CONFIG_USB_GSPCA_XIRLINK_CIT is not set -# CONFIG_USB_GSPCA_ZC3XX is not set -# CONFIG_VIDEO_PVRUSB2 is not set -# CONFIG_VIDEO_HDPVR is not set -# CONFIG_VIDEO_EM28XX is not set -# CONFIG_VIDEO_USBVISION is not set -# CONFIG_USB_ET61X251 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_PWC is not set -# CONFIG_VIDEO_CPIA2 is not set -# CONFIG_USB_ZR364XX is not set -# CONFIG_USB_STKWEBCAM is not set -# CONFIG_USB_S2255 is not set -# CONFIG_V4L_PLATFORM_DRIVERS is not set -# CONFIG_V4L_MEM2MEM_DRIVERS is not set -# CONFIG_RADIO_ADAPTERS is not set - -# -# Graphics support -# -CONFIG_DRM=y -CONFIG_DRM_KMS_HELPER=y -CONFIG_DRM_ENCODER_ADV7511=y -CONFIG_DRM_ANALOG=y -# CONFIG_VGASTATE is not set -# CONFIG_VIDEO_OUTPUT_CONTROL is not set -CONFIG_FB=y -# CONFIG_FIRMWARE_EDID is not set -# CONFIG_FB_BOOT_VESA_SUPPORT is not set -# CONFIG_FB_CFB_FILLRECT is not set -# CONFIG_FB_CFB_COPYAREA is not set -# CONFIG_FB_CFB_IMAGEBLIT is not set -# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -CONFIG_FB_SYS_FILLRECT=y -CONFIG_FB_SYS_COPYAREA=y -CONFIG_FB_SYS_IMAGEBLIT=y -# CONFIG_FB_FOREIGN_ENDIAN is not set -# CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set -# CONFIG_FB_SVGALIB is not set -# CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set -# CONFIG_FB_MODE_HELPERS is not set -# CONFIG_FB_TILEBLITTING is not set - -# -# Frame buffer hardware drivers -# -# CONFIG_FB_ARMCLCD is not set -# CONFIG_FB_UVESA is not set -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_SMSCUFX is not set -# CONFIG_FB_UDL is not set -# CONFIG_FB_XILINX is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FB_METRONOME is not set -# CONFIG_FB_BROADSHEET is not set -# CONFIG_FB_XYLON is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Console display driver support -# -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -CONFIG_FONTS=y -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_7x14 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set -# CONFIG_FONT_MINI_4x6 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_10x18 is not set -CONFIG_LOGO=y -CONFIG_LOGO_LINUX_MONO=y -CONFIG_LOGO_LINUX_VGA16=y -CONFIG_LOGO_LINUX_CLUT224=y -CONFIG_SOUND=y -# CONFIG_SOUND_OSS_CORE is not set -CONFIG_SND=y -CONFIG_SND_TIMER=y -CONFIG_SND_PCM=y -CONFIG_SND_JACK=y -# CONFIG_SND_SEQUENCER is not set -# CONFIG_SND_MIXER_OSS is not set -# CONFIG_SND_PCM_OSS is not set -# CONFIG_SND_HRTIMER is not set -# CONFIG_SND_DYNAMIC_MINORS is not set -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_VERBOSE_PROCFS is not set -# CONFIG_SND_VERBOSE_PRINTK is not set -# CONFIG_SND_DEBUG is not set -# CONFIG_SND_RAWMIDI_SEQ is not set -# CONFIG_SND_OPL3_LIB_SEQ is not set -# CONFIG_SND_OPL4_LIB_SEQ is not set -# CONFIG_SND_SBAWE_SEQ is not set -# CONFIG_SND_EMU10K1_SEQ is not set -# CONFIG_SND_DRIVERS is not set -# CONFIG_SND_ARM is not set -# CONFIG_SND_SPI is not set -# CONFIG_SND_USB is not set -CONFIG_SND_SOC=y -CONFIG_SND_SOC_DMAENGINE_PCM=y -CONFIG_SND_SOC_XILINX=y -CONFIG_SND_SOC_AXI_SPDIF=y -CONFIG_SND_SOC_ADV7511_HDMI=y -CONFIG_SND_SOC_I2C_AND_SPI=y -# CONFIG_SND_SOC_ALL_CODECS is not set -# CONFIG_SOUND_PRIME is not set -CONFIG_HID_SUPPORT=y -CONFIG_HID=y -# CONFIG_HIDRAW is not set - -# -# USB Input Devices -# -CONFIG_USB_HID=y -# CONFIG_HID_PID is not set -# CONFIG_USB_HIDDEV is not set - -# -# Special HID drivers -# -# CONFIG_HID_A4TECH is not set -# CONFIG_HID_ACRUX is not set -# CONFIG_HID_APPLE is not set -# CONFIG_HID_BELKIN is not set -# CONFIG_HID_CHERRY is not set -# CONFIG_HID_CHICONY is not set -# CONFIG_HID_PRODIKEYS is not set -# CONFIG_HID_CYPRESS is not set -# CONFIG_HID_DRAGONRISE is not set -# CONFIG_HID_EMS_FF is not set -# CONFIG_HID_EZKEY is not set -# CONFIG_HID_HOLTEK is not set -# CONFIG_HID_KEYTOUCH is not set -# CONFIG_HID_KYE is not set -# CONFIG_HID_UCLOGIC is not set -# CONFIG_HID_WALTOP is not set -# CONFIG_HID_GYRATION is not set -# CONFIG_HID_TWINHAN is not set -# CONFIG_HID_KENSINGTON is not set -# CONFIG_HID_LCPOWER is not set -# CONFIG_HID_LOGITECH is not set -CONFIG_HID_MICROSOFT=y -# CONFIG_HID_MONTEREY is not set -# CONFIG_HID_MULTITOUCH is not set -# CONFIG_HID_NTRIG is not set -# CONFIG_HID_ORTEK is not set -# CONFIG_HID_PANTHERLORD is not set -# CONFIG_HID_PETALYNX is not set -# CONFIG_HID_PICOLCD is not set -# CONFIG_HID_PRIMAX is not set -# CONFIG_HID_ROCCAT is not set -# CONFIG_HID_SAMSUNG is not set -# CONFIG_HID_SONY is not set -# CONFIG_HID_SPEEDLINK is not set -# CONFIG_HID_SUNPLUS is not set -# CONFIG_HID_GREENASIA is not set -# CONFIG_HID_SMARTJOYPLUS is not set -# CONFIG_HID_TOPSEED is not set -# CONFIG_HID_THRUSTMASTER is not set -# CONFIG_HID_ZEROPLUS is not set -# CONFIG_HID_ZYDACRON is not set -CONFIG_USB_SUPPORT=y -CONFIG_USB_COMMON=y -CONFIG_USB_ARCH_HAS_HCD=y -# CONFIG_USB_ARCH_HAS_OHCI is not set -CONFIG_USB_ARCH_HAS_EHCI=y -# CONFIG_USB_ARCH_HAS_XHCI is not set -CONFIG_USB=y -# CONFIG_USB_DEBUG is not set -# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -CONFIG_USB_DEVICE_CLASS=y -# CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y -CONFIG_USB_OTG=y -# CONFIG_USB_OTG_WHITELIST is not set -# CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set -# CONFIG_USB_MON is not set -# CONFIG_USB_WUSB_CBAF is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_C67X00_HCD is not set -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_ROOT_HUB_TT=y -# CONFIG_USB_EHCI_TT_NEWSCHED is not set -CONFIG_USB_XUSBPS_DR_OF=y -CONFIG_USB_EHCI_XUSBPS=y -# CONFIG_USB_EHCI_MV is not set -# CONFIG_USB_OXU210HP_HCD is not set -# CONFIG_USB_ISP116X_HCD is not set -# CONFIG_USB_ISP1760_HCD is not set -# CONFIG_USB_ISP1362_HCD is not set -# CONFIG_USB_SL811_HCD is not set -# CONFIG_USB_R8A66597_HCD is not set -# CONFIG_USB_MUSB_HDRC is not set -# CONFIG_USB_RENESAS_USBHS is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_WDM is not set -# CONFIG_USB_TMC is not set - -# -# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may -# - -# -# also be needed; see USB_STORAGE Help for more info -# -CONFIG_USB_STORAGE=y -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_REALTEK is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_USBAT is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_SDDR55 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_ALAUDA is not set -# CONFIG_USB_STORAGE_ONETOUCH is not set -# CONFIG_USB_STORAGE_KARMA is not set -# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set -# CONFIG_USB_STORAGE_ENE_UB6250 is not set -# CONFIG_USB_UAS is not set -# CONFIG_USB_LIBUSUAL is not set - -# -# USB Imaging devices -# -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set - -# -# USB port drivers -# -# CONFIG_USB_SERIAL is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_ADUTUX is not set -# CONFIG_USB_SEVSEG is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYPRESS_CY7C63 is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_IDMOUSE is not set -# CONFIG_USB_FTDI_ELAN is not set -# CONFIG_USB_APPLEDISPLAY is not set -# CONFIG_USB_SISUSBVGA is not set -# CONFIG_USB_LD is not set -# CONFIG_USB_TRANCEVIBRATOR is not set -# CONFIG_USB_IOWARRIOR is not set -# CONFIG_USB_TEST is not set -# CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_YUREX is not set -CONFIG_USB_GADGET=y -# CONFIG_USB_GADGET_DEBUG is not set -# CONFIG_USB_GADGET_DEBUG_FILES is not set -# CONFIG_USB_GADGET_DEBUG_FS is not set -CONFIG_USB_GADGET_VBUS_DRAW=2 -CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 -CONFIG_USB_GADGET_XUSBPS=y -CONFIG_USB_XUSBPS=y -# CONFIG_USB_FUSB300 is not set -# CONFIG_USB_R8A66597 is not set -# CONFIG_USB_GADGET_XILINX is not set -# CONFIG_USB_MV_UDC is not set -# CONFIG_USB_M66592 is not set -# CONFIG_USB_NET2272 is not set -# CONFIG_USB_DUMMY_HCD is not set -CONFIG_USB_GADGET_DUALSPEED=y -CONFIG_USB_ZERO=m -# CONFIG_USB_ZERO_HNPTEST is not set -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_ETH is not set -# CONFIG_USB_G_NCM is not set -# CONFIG_USB_GADGETFS is not set -# CONFIG_USB_FUNCTIONFS is not set -CONFIG_USB_FILE_STORAGE=m -# CONFIG_USB_FILE_STORAGE_TEST is not set -# CONFIG_USB_MASS_STORAGE is not set -# CONFIG_USB_G_SERIAL is not set -# CONFIG_USB_MIDI_GADGET is not set -# CONFIG_USB_G_PRINTER is not set -# CONFIG_USB_CDC_COMPOSITE is not set -# CONFIG_USB_G_ACM_MS is not set -# CONFIG_USB_G_MULTI is not set -# CONFIG_USB_G_HID is not set -# CONFIG_USB_G_DBGP is not set -# CONFIG_USB_G_WEBCAM is not set - -# -# OTG and related infrastructure -# -CONFIG_USB_OTG_UTILS=y -# CONFIG_USB_GPIO_VBUS is not set -CONFIG_USB_ULPI=y -CONFIG_USB_ULPI_VIEWPORT=y -# CONFIG_NOP_USB_XCEIV is not set -CONFIG_USB_XUSBPS_OTG=y -CONFIG_MMC=y -# CONFIG_MMC_DEBUG is not set -# CONFIG_MMC_UNSAFE_RESUME is not set -# CONFIG_MMC_CLKGATE is not set - -# -# MMC/SD/SDIO Card Drivers -# -CONFIG_MMC_BLOCK=y -CONFIG_MMC_BLOCK_MINORS=8 -CONFIG_MMC_BLOCK_BOUNCE=y -# CONFIG_SDIO_UART is not set -# CONFIG_MMC_TEST is not set - -# -# MMC/SD/SDIO Host Controller Drivers -# -# CONFIG_MMC_ARMMMCI is not set -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMC_SDHCI_OF_XILINX_PS=y -# CONFIG_MMC_SDHCI_PXAV3 is not set -# CONFIG_MMC_SDHCI_PXAV2 is not set -# CONFIG_MMC_WBSD is not set -# CONFIG_MMC_DW is not set -# CONFIG_MMC_VUB300 is not set -# CONFIG_MMC_USHC is not set -# CONFIG_MEMSTICK is not set -# CONFIG_NEW_LEDS is not set -# CONFIG_ACCESSIBILITY is not set -CONFIG_RTC_LIB=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_HCTOSYS=y -CONFIG_RTC_HCTOSYS_DEVICE="rtc0" -# CONFIG_RTC_DEBUG is not set - -# -# RTC interfaces -# -CONFIG_RTC_INTF_SYSFS=y -CONFIG_RTC_INTF_PROC=y -CONFIG_RTC_INTF_DEV=y -# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set -# CONFIG_RTC_DRV_TEST is not set - -# -# I2C RTC drivers -# -# CONFIG_RTC_DRV_DS1307 is not set -# CONFIG_RTC_DRV_DS1374 is not set -# CONFIG_RTC_DRV_DS1672 is not set -# CONFIG_RTC_DRV_DS3232 is not set -# CONFIG_RTC_DRV_MAX6900 is not set -# CONFIG_RTC_DRV_RS5C372 is not set -# CONFIG_RTC_DRV_ISL1208 is not set -# CONFIG_RTC_DRV_ISL12022 is not set -# CONFIG_RTC_DRV_X1205 is not set -CONFIG_RTC_DRV_PCF8563=y -# CONFIG_RTC_DRV_PCF8583 is not set -# CONFIG_RTC_DRV_M41T80 is not set -# CONFIG_RTC_DRV_BQ32K is not set -# CONFIG_RTC_DRV_S35390A is not set -# CONFIG_RTC_DRV_FM3130 is not set -# CONFIG_RTC_DRV_RX8581 is not set -# CONFIG_RTC_DRV_RX8025 is not set -# CONFIG_RTC_DRV_EM3027 is not set -# CONFIG_RTC_DRV_RV3029C2 is not set - -# -# SPI RTC drivers -# -# CONFIG_RTC_DRV_M41T93 is not set -# CONFIG_RTC_DRV_M41T94 is not set -# CONFIG_RTC_DRV_DS1305 is not set -# CONFIG_RTC_DRV_DS1390 is not set -# CONFIG_RTC_DRV_MAX6902 is not set -# CONFIG_RTC_DRV_R9701 is not set -# CONFIG_RTC_DRV_RS5C348 is not set -# CONFIG_RTC_DRV_DS3234 is not set -# CONFIG_RTC_DRV_PCF2123 is not set - -# -# Platform RTC drivers -# -# CONFIG_RTC_DRV_CMOS is not set -# CONFIG_RTC_DRV_DS1286 is not set -# CONFIG_RTC_DRV_DS1511 is not set -# CONFIG_RTC_DRV_DS1553 is not set -# CONFIG_RTC_DRV_DS1742 is not set -# CONFIG_RTC_DRV_STK17TA8 is not set -# CONFIG_RTC_DRV_M48T86 is not set -# CONFIG_RTC_DRV_M48T35 is not set -# CONFIG_RTC_DRV_M48T59 is not set -# CONFIG_RTC_DRV_MSM6242 is not set -# CONFIG_RTC_DRV_BQ4802 is not set -# CONFIG_RTC_DRV_RP5C01 is not set -# CONFIG_RTC_DRV_V3020 is not set - -# -# on-CPU RTC drivers -# -# CONFIG_RTC_DRV_PL030 is not set -# CONFIG_RTC_DRV_PL031 is not set -CONFIG_DMADEVICES=y -# CONFIG_DMADEVICES_DEBUG is not set - -# -# DMA Devices -# -CONFIG_XILINX_DMA=y -# CONFIG_AMBA_PL08X is not set -# CONFIG_DW_DMAC is not set -# CONFIG_TIMB_DMA is not set -# CONFIG_PL330_DMA is not set -CONFIG_DMA_ENGINE=y - -# -# DMA Clients -# -# CONFIG_NET_DMA is not set -# CONFIG_ASYNC_TX_DMA is not set -# CONFIG_DMATEST is not set -# CONFIG_AUXDISPLAY is not set -# CONFIG_UIO is not set - -# -# Virtio drivers -# -# CONFIG_VIRTIO_BALLOON is not set -# CONFIG_VIRTIO_MMIO is not set - -# -# Microsoft Hyper-V guest support -# -CONFIG_STAGING=y -# CONFIG_USBIP_CORE is not set -# CONFIG_ECHO is not set -# CONFIG_ASUS_OLED is not set -# CONFIG_RTS5139 is not set -# CONFIG_TRANZPORT is not set -# CONFIG_LINE6_USB is not set - -# -# I2C encoder or helper chips -# -# CONFIG_DRM_I2C_CH7006 is not set -# CONFIG_DRM_I2C_SIL164 is not set -CONFIG_IIO=y -CONFIG_IIO_BUFFER=y -CONFIG_IIO_SW_RING=y -CONFIG_IIO_KFIFO_BUF=y -CONFIG_IIO_TRIGGER=y -CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 - -# -# Accelerometers -# -# CONFIG_ADIS16201 is not set -# CONFIG_ADIS16203 is not set -# CONFIG_ADIS16204 is not set -# CONFIG_ADIS16209 is not set -# CONFIG_ADIS16220 is not set -# CONFIG_ADIS16240 is not set -# CONFIG_KXSD9 is not set -# CONFIG_LIS3L02DQ is not set -# CONFIG_SCA3000 is not set - -# -# Analog to digital converters -# -# CONFIG_AD7291 is not set -# CONFIG_AD7298 is not set -# CONFIG_AD7606 is not set -# CONFIG_AD799X is not set -# CONFIG_AD7476 is not set -# CONFIG_AD7887 is not set -# CONFIG_AD7780 is not set -# CONFIG_AD7793 is not set -# CONFIG_AD7816 is not set -# CONFIG_AD7192 is not set -# CONFIG_ADT7310 is not set -# CONFIG_ADT7410 is not set -# CONFIG_AD7280 is not set -CONFIG_CF_AD9467=y -# CONFIG_MAX1363 is not set - -# -# Analog digital bi-direction converters -# -# CONFIG_ADT7316 is not set - -# -# Amplifiers -# -CONFIG_AD8366=y - -# -# Capacitance to digital converters -# -# CONFIG_AD7150 is not set -# CONFIG_AD7152 is not set -# CONFIG_AD7746 is not set - -# -# Digital to analog converters -# -# CONFIG_AD5064 is not set -# CONFIG_AD5360 is not set -# CONFIG_AD5380 is not set -# CONFIG_AD5421 is not set -# CONFIG_AD5624R_SPI is not set -# CONFIG_AD5446 is not set -# CONFIG_AD5504 is not set -# CONFIG_AD5764 is not set -# CONFIG_AD5791 is not set -# CONFIG_AD5686 is not set -# CONFIG_MAX517 is not set - -# -# Frequency Synthesizers DDS/PLL -# - -# -# Clock Generator/Distribution -# -CONFIG_AD9523=y -CONFIG_AD9548=y - -# -# Direct Digital Synthesis -# -# CONFIG_AD5930 is not set -# CONFIG_AD9832 is not set -# CONFIG_AD9834 is not set -# CONFIG_AD9850 is not set -# CONFIG_AD9852 is not set -# CONFIG_AD9910 is not set -# CONFIG_AD9951 is not set -CONFIG_AD9122_CF=y -CONFIG_AD9122_CF_DAC=y - -# -# Phase-Locked Loop (PLL) frequency synthesizers -# -CONFIG_ADF4350=y - -# -# Digital gyroscope sensors -# -# CONFIG_ADIS16060 is not set -# CONFIG_ADIS16080 is not set -# CONFIG_ADIS16130 is not set -# CONFIG_ADIS16260 is not set -# CONFIG_ADXRS450 is not set - -# -# Network Analyzer, Impedance Converters -# -# CONFIG_AD5933 is not set - -# -# Inertial measurement units -# -# CONFIG_ADIS16400 is not set - -# -# Light sensors -# -# CONFIG_SENSORS_ISL29018 is not set -# CONFIG_SENSORS_TSL2563 is not set -# CONFIG_TSL2583 is not set - -# -# Magnetometer sensors -# -# CONFIG_SENSORS_AK8975 is not set -# CONFIG_SENSORS_HMC5843 is not set - -# -# Active energy metering IC -# -# CONFIG_ADE7753 is not set -# CONFIG_ADE7754 is not set -# CONFIG_ADE7758 is not set -# CONFIG_ADE7759 is not set -# CONFIG_ADE7854 is not set - -# -# Resolver to digital converters -# -# CONFIG_AD2S90 is not set -# CONFIG_AD2S1200 is not set -# CONFIG_AD2S1210 is not set - -# -# Triggers - standalone -# -# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set -# CONFIG_IIO_GPIO_TRIGGER is not set -# CONFIG_IIO_SYSFS_TRIGGER is not set -# CONFIG_IIO_SIMPLE_DUMMY is not set -# CONFIG_XVMALLOC is not set -# CONFIG_ZRAM is not set -# CONFIG_FB_SM7XX is not set -# CONFIG_USB_ENESTORAGE is not set -# CONFIG_BCM_WIMAX is not set -# CONFIG_FT1000 is not set - -# -# Speakup console speech -# -# CONFIG_SPEAKUP is not set -# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set -# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set -# CONFIG_STAGING_MEDIA is not set - -# -# Android -# -# CONFIG_ANDROID is not set -CONFIG_CLKDEV_LOOKUP=y - -# -# Hardware Spinlock drivers -# -# CONFIG_IOMMU_SUPPORT is not set -# CONFIG_VIRT_DRIVERS is not set -# CONFIG_PM_DEVFREQ is not set - -# -# File systems -# -# CONFIG_EXT2_FS is not set -# CONFIG_EXT3_FS is not set -CONFIG_EXT4_FS=y -CONFIG_EXT4_USE_FOR_EXT23=y -CONFIG_EXT4_FS_XATTR=y -# CONFIG_EXT4_FS_POSIX_ACL is not set -# CONFIG_EXT4_FS_SECURITY is not set -# CONFIG_EXT4_DEBUG is not set -CONFIG_JBD2=y -# CONFIG_JBD2_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set -# CONFIG_BTRFS_FS is not set -# CONFIG_NILFS2_FS is not set -# CONFIG_FS_POSIX_ACL is not set -CONFIG_FILE_LOCKING=y -CONFIG_FSNOTIFY=y -# CONFIG_DNOTIFY is not set -CONFIG_INOTIFY_USER=y -# CONFIG_FANOTIFY is not set -# CONFIG_QUOTA is not set -# CONFIG_QUOTACTL is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set - -# -# Caches -# -# CONFIG_FSCACHE is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_SYSCTL=y -CONFIG_PROC_PAGE_MONITOR=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -# CONFIG_TMPFS_POSIX_ACL is not set -# CONFIG_TMPFS_XATTR is not set -# CONFIG_HUGETLB_PAGE is not set -# CONFIG_CONFIGFS_FS is not set -CONFIG_MISC_FILESYSTEMS=y -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS2_FS is not set -# CONFIG_LOGFS is not set -# CONFIG_CRAMFS is not set -# CONFIG_SQUASHFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_OMFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_PSTORE is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set -# CONFIG_NETWORK_FILESYSTEMS is not set -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=y -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -CONFIG_NLS_ASCII=y -CONFIG_NLS_ISO8859_1=y -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set -CONFIG_FRAME_WARN=1024 -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_STRIP_ASM_SYMS is not set -# CONFIG_UNUSED_SYMBOLS is not set -CONFIG_DEBUG_FS=y -# CONFIG_HEADERS_CHECK is not set -# CONFIG_DEBUG_SECTION_MISMATCH is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SHIRQ is not set -# CONFIG_LOCKUP_DETECTOR is not set -# CONFIG_HARDLOCKUP_DETECTOR is not set -CONFIG_DETECT_HUNG_TASK=y -CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=20 -# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 -# CONFIG_SCHED_DEBUG is not set -# CONFIG_SCHEDSTATS is not set -# CONFIG_TIMER_STATS is not set -# CONFIG_DEBUG_OBJECTS is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_KMEMLEAK is not set -# CONFIG_DEBUG_PREEMPT is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set -CONFIG_DEBUG_SPINLOCK=y -CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_LOCK_ALLOC=y -CONFIG_PROVE_LOCKING=y -CONFIG_PROVE_RCU=y -# CONFIG_PROVE_RCU_REPEATEDLY is not set -# CONFIG_SPARSE_RCU_POINTER is not set -CONFIG_LOCKDEP=y -# CONFIG_LOCK_STAT is not set -# CONFIG_DEBUG_LOCKDEP is not set -CONFIG_TRACE_IRQFLAGS=y -# CONFIG_DEBUG_ATOMIC_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -CONFIG_STACKTRACE=y -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_KOBJECT is not set -# CONFIG_DEBUG_HIGHMEM is not set -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_INFO=y -# CONFIG_DEBUG_INFO_REDUCED is not set -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_WRITECOUNT is not set -# CONFIG_DEBUG_MEMORY_INIT is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_TEST_LIST_SORT is not set -# CONFIG_DEBUG_SG is not set -# CONFIG_DEBUG_NOTIFIERS is not set -# CONFIG_DEBUG_CREDENTIALS is not set -# CONFIG_BOOT_PRINTK_DELAY is not set -# CONFIG_RCU_TORTURE_TEST is not set -CONFIG_RCU_CPU_STALL_TIMEOUT=60 -# CONFIG_RCU_CPU_STALL_VERBOSE is not set -# CONFIG_BACKTRACE_SELF_TEST is not set -# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set -# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set -# CONFIG_DEBUG_PER_CPU_MAPS is not set -# CONFIG_LKDTM is not set -# CONFIG_FAULT_INJECTION is not set -# CONFIG_SYSCTL_SYSCALL_CHECK is not set -# CONFIG_DEBUG_PAGEALLOC is not set -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -CONFIG_HAVE_C_RECORDMCOUNT=y -CONFIG_TRACING_SUPPORT=y -# CONFIG_FTRACE is not set -# CONFIG_DYNAMIC_DEBUG is not set -# CONFIG_DMA_API_DEBUG is not set -# CONFIG_ATOMIC64_SELFTEST is not set -# CONFIG_SAMPLES is not set -CONFIG_HAVE_ARCH_KGDB=y -# CONFIG_KGDB is not set -# CONFIG_TEST_KSTRTOX is not set -# CONFIG_STRICT_DEVMEM is not set -CONFIG_ARM_UNWIND=y -# CONFIG_DEBUG_USER is not set -CONFIG_DEBUG_LL=y -CONFIG_DEBUG_LL_UART_NONE=y -# CONFIG_DEBUG_ICEDCC is not set -CONFIG_EARLY_PRINTK=y -# CONFIG_OC_ETM is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY_DMESG_RESTRICT is not set -# CONFIG_SECURITY is not set -# CONFIG_SECURITYFS is not set -CONFIG_DEFAULT_SECURITY_DAC=y -CONFIG_DEFAULT_SECURITY="" -CONFIG_CRYPTO=y - -# -# Crypto core or helper -# -# CONFIG_CRYPTO_FIPS is not set -CONFIG_CRYPTO_ALGAPI=m -CONFIG_CRYPTO_ALGAPI2=m -CONFIG_CRYPTO_RNG=m -CONFIG_CRYPTO_RNG2=m -# CONFIG_CRYPTO_MANAGER is not set -# CONFIG_CRYPTO_MANAGER2 is not set -# CONFIG_CRYPTO_USER is not set -# CONFIG_CRYPTO_GF128MUL is not set -# CONFIG_CRYPTO_NULL is not set -# CONFIG_CRYPTO_PCRYPT is not set -# CONFIG_CRYPTO_CRYPTD is not set -# CONFIG_CRYPTO_AUTHENC is not set -# CONFIG_CRYPTO_TEST is not set - -# -# Authenticated Encryption with Associated Data -# -# CONFIG_CRYPTO_CCM is not set -# CONFIG_CRYPTO_GCM is not set -# CONFIG_CRYPTO_SEQIV is not set - -# -# Block modes -# -# CONFIG_CRYPTO_CBC is not set -# CONFIG_CRYPTO_CTR is not set -# CONFIG_CRYPTO_CTS is not set -# CONFIG_CRYPTO_ECB is not set -# CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_PCBC is not set -# CONFIG_CRYPTO_XTS is not set - -# -# Hash modes -# -# CONFIG_CRYPTO_HMAC is not set -# CONFIG_CRYPTO_XCBC is not set -# CONFIG_CRYPTO_VMAC is not set - -# -# Digest -# -# CONFIG_CRYPTO_CRC32C is not set -# CONFIG_CRYPTO_GHASH is not set -# CONFIG_CRYPTO_MD4 is not set -# CONFIG_CRYPTO_MD5 is not set -# CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_RMD128 is not set -# CONFIG_CRYPTO_RMD160 is not set -# CONFIG_CRYPTO_RMD256 is not set -# CONFIG_CRYPTO_RMD320 is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_WP512 is not set - -# -# Ciphers -# -CONFIG_CRYPTO_AES=m -# CONFIG_CRYPTO_ANUBIS is not set -# CONFIG_CRYPTO_ARC4 is not set -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_CAMELLIA is not set -# CONFIG_CRYPTO_CAST5 is not set -# CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_FCRYPT is not set -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_SALSA20 is not set -# CONFIG_CRYPTO_SEED is not set -# CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_TEA is not set -# CONFIG_CRYPTO_TWOFISH is not set - -# -# Compression -# -# CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_ZLIB is not set -# CONFIG_CRYPTO_LZO is not set - -# -# Random Number Generation -# -CONFIG_CRYPTO_ANSI_CPRNG=m -# CONFIG_CRYPTO_USER_API_HASH is not set -# CONFIG_CRYPTO_USER_API_SKCIPHER is not set -CONFIG_CRYPTO_HW=y -# CONFIG_BINARY_PRINTF is not set - -# -# Library routines -# -CONFIG_BITREVERSE=y -CONFIG_GENERIC_PCI_IOMAP=y -# CONFIG_CRC_CCITT is not set -CONFIG_CRC16=y -# CONFIG_CRC_T10DIF is not set -# CONFIG_CRC_ITU_T is not set -CONFIG_CRC32=y -# CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set -# CONFIG_CRC8 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -# CONFIG_XZ_DEC is not set -# CONFIG_XZ_DEC_BCJ is not set -CONFIG_DECOMPRESS_GZIP=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y -CONFIG_CPU_RMAP=y -CONFIG_DQL=y -CONFIG_NLATTR=y -# CONFIG_AVERAGE is not set -# CONFIG_CORDIC is not set diff --git a/arch/arm/configs/zync_xcomm_adv7511_defconfig b/arch/arm/configs/zync_xcomm_adv7511_defconfig new file mode 100644 index 0000000000000..eb1ae1353a95c --- /dev/null +++ b/arch/arm/configs/zync_xcomm_adv7511_defconfig @@ -0,0 +1,240 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0x0 +CONFIG_EXPERIMENTAL=y +CONFIG_SYSVIPC=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +CONFIG_PERF_EVENTS=y +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_ZYNQ=y +CONFIG_ZYNQ_EARLY_UART1=y +# CONFIG_ZYNQ_EARLY_UART_EP107 is not set +CONFIG_XILINX_ZED=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_SMP=y +CONFIG_PREEMPT=y +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +CONFIG_HIGHMEM=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttyPS0,115200n8 root=/dev/ram rw initrd=0x00800000,16M earlyprintk mtdparts=physmap-flash.0:512K(nor-fsbl),512K(nor-u-boot),5M(nor-linux),9M(nor-user),1M(nor-scratch),-(nor-rootfs)" +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_SUSPEND is not set +CONFIG_PM_RUNTIME=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +CONFIG_VLAN_8021Q=m +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_FW_LOADER=m +CONFIG_CONNECTOR=y +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_OF_PARTS=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_OF=y +CONFIG_MTD_M25P80=y +# CONFIG_M25PXX_USE_FAST_READ is not set +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_XILINX_PSS=y +CONFIG_PROC_DEVICETREE=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=35384 +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_SCSI_MULTI_LUN=y +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +CONFIG_XILINX_PS_EMAC=y +CONFIG_XILINX_PS_EMAC_HWTSTAMP=y +CONFIG_MARVELL_PHY=y +CONFIG_MDIO_BITBANG=y +# CONFIG_WLAN is not set +CONFIG_INPUT_SPARSEKMAP=y +CONFIG_INPUT_EVDEV=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_XILINX_PS_UART=y +CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +# CONFIG_HW_RANDOM is not set +CONFIG_XILINX_DEVCFG=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y +CONFIG_I2C_MUX_PCA954x=y +CONFIG_I2C_GPIO=y +CONFIG_I2C_XILINX=y +CONFIG_SPI=y +CONFIG_SPI_BITBANG=y +CONFIG_SPI_XCOMM=y +CONFIG_SPI_XILINX_PS_QSPI=y +# CONFIG_XILINX_PS_QSPI_USE_DUAL_FLASH is not set +CONFIG_SPI_XILINX_PS_SPI=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_XILINX_PS=y +# CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_VIDEO_DEV=y +# CONFIG_RC_CORE is not set +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_USB_VIDEO_CLASS=y +CONFIG_USB_GSPCA=y +# CONFIG_RADIO_ADAPTERS is not set +CONFIG_DRM=y +CONFIG_DRM_ENCODER_ADV7511=y +CONFIG_DRM_ANALOG=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_LOGO=y +CONFIG_SOUND=y +CONFIG_SND=y +# CONFIG_SND_SUPPORT_OLD_API is not set +# CONFIG_SND_VERBOSE_PROCFS is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +# CONFIG_SND_USB is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_XILINX=y +CONFIG_SND_SOC_ADV7511_HDMI=y +CONFIG_HID_MICROSOFT=y +CONFIG_USB=y +CONFIG_USB_DEVICEFS=y +CONFIG_USB_SUSPEND=y +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_EHCI_XUSBPS=y +CONFIG_USB_STORAGE=y + +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +CONFIG_USB_GADGET_XUSBPS=y +CONFIG_USB_XUSBPS=y +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_GPIO_VBUS is not set +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_USB_XUSBPS_OTG=y +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF_XILINX_PS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_PCF8563=y +CONFIG_DMADEVICES=y +CONFIG_XILINX_DMA=y +CONFIG_STAGING=y +CONFIG_IIO=y +CONFIG_IIO_KFIFO_BUF=y +CONFIG_AD8366=y +CONFIG_AD9523=y +CONFIG_AD9548=y +CONFIG_ADF4350=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_CF_AXI_ADC=y +CONFIG_CF_AXI_FFT=y +CONFIG_CF_AXI_DDS=y +CONFIG_CF_AXI_DDS_AD9122=y +CONFIG_EXT4_FS=y +# CONFIG_DNOTIFY is not set +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_DEBUG_FS=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=20 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_PROVE_LOCKING=y +CONFIG_PROVE_RCU=y +CONFIG_DEBUG_INFO=y +# CONFIG_RCU_CPU_STALL_VERBOSE is not set +# CONFIG_FTRACE is not set +CONFIG_DEBUG_LL=y +CONFIG_EARLY_PRINTK=y From e3fc9322ea0f0343e514aa5d640045f05d352971 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 6 Aug 2012 11:35:24 +0200 Subject: [PATCH 183/261] DRM: adv7511: Fix calculation and setting of CTS The value calculated for cts is of by a factor of 1000 and also the value for n is written to the cts register. This problem is not critical since the driver configues the device to use the automatic cts value. Signed-off-by: Lars-Peter Clausen --- drivers/gpu/drm/i2c/adv7511_audio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i2c/adv7511_audio.c b/drivers/gpu/drm/i2c/adv7511_audio.c index 6ca4e7cbe4eb2..f24fe47b48a20 100644 --- a/drivers/gpu/drm/i2c/adv7511_audio.c +++ b/drivers/gpu/drm/i2c/adv7511_audio.c @@ -49,7 +49,7 @@ static void adv7511_calc_cts_n(unsigned int f_tmds, unsigned int fs, break; } - *cts = (f_tmds * *n) / (128 * fs); + *cts = ((f_tmds * *n) / (128 * fs)) * 1000; } static int adv7511_update_cts_n(struct adv7511 *adv7511) @@ -63,9 +63,9 @@ static int adv7511_update_cts_n(struct adv7511 *adv7511) regmap_write(adv7511->regmap, ADV7511_REG_N1, (n >> 8) & 0xff); regmap_write(adv7511->regmap, ADV7511_REG_N2, n & 0xff); - regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL0, (n >> 16) & 0xf); - regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL1, (n >> 8) & 0xff); - regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL2, n & 0xff); + regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL0, (cts >> 16) & 0xf); + regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL1, (cts >> 8) & 0xff); + regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL2, cts & 0xff); return 0; } From eefcbc4cc86138c4bfa5270165aa3ac8a226dd07 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 7 Aug 2012 15:05:23 +0200 Subject: [PATCH 184/261] ASoC: axi-spdif: Set frequency in SPDIF status word The the sampling frequency in the SPDIF status word. Signed-off-by: Lars-Peter Clausen --- sound/soc/xlnx/axi-spdif.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/sound/soc/xlnx/axi-spdif.c b/sound/soc/xlnx/axi-spdif.c index 78d2a8ab28b49..02e41c1682979 100644 --- a/sound/soc/xlnx/axi-spdif.c +++ b/sound/soc/xlnx/axi-spdif.c @@ -46,6 +46,11 @@ struct axi_spdif { #define AXI_SPDIF_CTRL_RATIO_OFFSET 8 #define AXI_SPDIF_CTRL_RATIO_MASK (0xff << 8) +#define AXI_SPDIF_FREQ_44100 (0x0 << 6) +#define AXI_SPDIF_FREQ_48000 (0x1 << 6) +#define AXI_SPDIF_FREQ_32000 (0x2 << 6) +#define AXI_SPDIF_FREQ_NA (0x3 << 6) + static struct debugfs_reg32 axi_spdif_debugfs_regs[] = { { "Control", AXI_SPDIF_REG_CTRL }, { "Status", AXI_SPDIF_REG_STAT }, @@ -94,13 +99,29 @@ static int axi_spdif_hw_params(struct snd_pcm_substream *substream, { struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai); uint32_t ctrl = axi_spdif_read(spdif, AXI_SPDIF_REG_CTRL); - unsigned int ratio; + unsigned int ratio, stat; + + switch (params_rate(params)) { + case 32000: + stat = AXI_SPDIF_FREQ_32000; + break; + case 44100: + stat = AXI_SPDIF_FREQ_44100; + break; + case 48000: + stat = AXI_SPDIF_FREQ_48000; + break; + default: + stat = AXI_SPDIF_FREQ_NA; + break; + } ratio = DIV_ROUND_CLOSEST(spdif->clock, (params_rate(params) * 64 * 2)) - 1; ctrl &= ~AXI_SPDIF_CTRL_RATIO_MASK; ctrl |= ratio << AXI_SPDIF_CTRL_RATIO_OFFSET; + axi_spdif_write(spdif, AXI_SPDIF_REG_STAT, stat); axi_spdif_write(spdif, AXI_SPDIF_REG_CTRL, ctrl); return 0; From 877856bd2b32e60fa0a7d9d11315e1a5de039072 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 7 Aug 2012 15:54:35 +0200 Subject: [PATCH 185/261] DRM: adv7511: Write status word frequency and word len registers These were commented out for no obvious reason. Make the work again. Signed-off-by: Lars-Peter Clausen --- drivers/gpu/drm/i2c/adv7511.h | 18 ++++++++++++++---- drivers/gpu/drm/i2c/adv7511_audio.c | 17 +++++------------ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i2c/adv7511.h b/drivers/gpu/drm/i2c/adv7511.h index ebfc05340f46a..40a860ea43e2c 100644 --- a/drivers/gpu/drm/i2c/adv7511.h +++ b/drivers/gpu/drm/i2c/adv7511.h @@ -158,10 +158,20 @@ #define ADV7511_REG_POWER2_TDMS_ENABLE BIT(4) #define ADV7511_REG_POWER2_GATE_INPUT_CLK BIT(0) -#define ADV7511_LOW_REFRESH_RATE_NONE 0x0 -#define ADV7511_LOW_REFRESH_RATE_24HZ 0x1 -#define ADV7511_LOW_REFRESH_RATE_25HZ 0x2 -#define ADV7511_LOW_REFRESH_RATE_30HZ 0x3 +#define ADV7511_LOW_REFRESH_RATE_NONE 0x0 +#define ADV7511_LOW_REFRESH_RATE_24HZ 0x1 +#define ADV7511_LOW_REFRESH_RATE_25HZ 0x2 +#define ADV7511_LOW_REFRESH_RATE_30HZ 0x3 + +#define ADV7511_AUDIO_CFG3_LEN_MASK 0x0f +#define ADV7511_I2C_FREQ_ID_CFG_RATE_MASK 0xf0 + +#define ADV7511_AUDIO_SOURCE_I2S 0 +#define ADV7511_AUDIO_SOURCE_SPDIF 1 + +#define ADV7511_I2S_FORMAT_I2S 0 +#define ADV7511_I2S_FORMAT_RIGHT_J 1 +#define ADV7511_I2S_FORMAT_LEFT_J 2 #include diff --git a/drivers/gpu/drm/i2c/adv7511_audio.c b/drivers/gpu/drm/i2c/adv7511_audio.c index f24fe47b48a20..c7f65a75a2e10 100644 --- a/drivers/gpu/drm/i2c/adv7511_audio.c +++ b/drivers/gpu/drm/i2c/adv7511_audio.c @@ -126,22 +126,15 @@ static int adv7511_hw_params(struct snd_pcm_substream *substream, adv7511->f_audio = params_rate(params); adv7511_update_cts_n(adv7511); -/* + regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG3, - ADV7511_REG_AUDIO_CFG3_LEN_MASK, len); - regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG4, - ADV7511_REG_AUDIO_CFG4_RATE_MASK, rate << 4); -*/ + ADV7511_AUDIO_CFG3_LEN_MASK, len); + regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG, + ADV7511_I2C_FREQ_ID_CFG_RATE_MASK, rate << 4); + return 0; } -#define ADV7511_AUDIO_SOURCE_I2S 0 -#define ADV7511_AUDIO_SOURCE_SPDIF 1 - -#define ADV7511_I2S_FORMAT_I2S 0 -#define ADV7511_I2S_FORMAT_RIGHT_J 1 -#define ADV7511_I2S_FORMAT_LEFT_J 2 - static int adv7511_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { From 86b3b7186734f0e0cf5c1268ce4127f27a2b9acd Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 8 Aug 2012 15:05:55 +0200 Subject: [PATCH 186/261] iio: cf_axi_dds: rename IQ imbalance correction attributes fix AD9122_REG_I_PHA_ADJ_MSB to accespt negative values disable frame pulsing Signed-off-by: Michael Hennerich --- drivers/iio/frequency/cf_axi_dds.c | 51 +++++++++++++++++++----------- drivers/iio/frequency/cf_axi_dds.h | 2 +- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/iio/frequency/cf_axi_dds.c b/drivers/iio/frequency/cf_axi_dds.c index 6c6c41bfa4802..efdb365b6ada7 100644 --- a/drivers/iio/frequency/cf_axi_dds.c +++ b/drivers/iio/frequency/cf_axi_dds.c @@ -364,8 +364,7 @@ static int cf_axi_dds_write_raw(struct iio_dev *indio_dev, default: return -EINVAL; } - - cf_axi_dds_sync_frame(st); +// cf_axi_dds_sync_frame(st); return 0; } @@ -407,10 +406,10 @@ static ssize_t ad9122_dds_store(struct device *dev, struct cf_axi_dds_state *st = iio_priv(indio_dev); struct cf_axi_dds_converter *conv = to_converter(st->dev_spi); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - unsigned long readin; + long readin; int ret; - ret = kstrtoul(buf, 10, &readin); + ret = kstrtol(buf, 10, &readin); if (ret) return ret; @@ -419,13 +418,20 @@ static ssize_t ad9122_dds_store(struct device *dev, switch ((u32)this_attr->address) { case AD9122_REG_I_DAC_OFFSET_MSB: case AD9122_REG_Q_DAC_OFFSET_MSB: - if (readin > 0xFFFF) { + if (readin < 0 || readin > 0xFFFF) { + ret = -EINVAL; + goto out; + } + break; + case AD9122_REG_I_PHA_ADJ_MSB: + case AD9122_REG_Q_PHA_ADJ_MSB: + if (readin < -512 || readin > 511) { ret = -EINVAL; goto out; } break; default: - if (readin > 0x3FF) { + if (readin < 0 || readin > 0x3FF) { ret = -EINVAL; goto out; } @@ -468,40 +474,46 @@ static ssize_t ad9122_dds_show(struct device *dev, goto out; val |= ret & 0xFF; - ret = sprintf(buf, "%d\n", val); + switch ((u32)this_attr->address) { + case AD9122_REG_I_PHA_ADJ_MSB: + case AD9122_REG_Q_PHA_ADJ_MSB: + val = sign_extend32(val, 9); + break; + } + ret = sprintf(buf, "%d\n", val); out: mutex_unlock(&indio_dev->mlock); return ret; } -static IIO_DEVICE_ATTR(i_phase_adj, S_IRUGO | S_IWUSR, +static IIO_DEVICE_ATTR(out_voltage0_phase, S_IRUGO | S_IWUSR, ad9122_dds_show, ad9122_dds_store, AD9122_REG_I_PHA_ADJ_MSB); -static IIO_DEVICE_ATTR(q_phase_adj, S_IRUGO | S_IWUSR, +static IIO_DEVICE_ATTR(out_voltage1_phase, S_IRUGO | S_IWUSR, ad9122_dds_show, ad9122_dds_store, AD9122_REG_Q_PHA_ADJ_MSB); -static IIO_DEVICE_ATTR(i_dac_offset, S_IRUGO | S_IWUSR, +static IIO_DEVICE_ATTR(out_voltage0_calibbias, S_IRUGO | S_IWUSR, ad9122_dds_show, ad9122_dds_store, AD9122_REG_I_DAC_OFFSET_MSB); -static IIO_DEVICE_ATTR(q_dac_offset, S_IRUGO | S_IWUSR, +static IIO_DEVICE_ATTR(out_voltage1_calibbias, S_IRUGO | S_IWUSR, ad9122_dds_show, ad9122_dds_store, AD9122_REG_Q_DAC_OFFSET_MSB); -static IIO_DEVICE_ATTR(i_dac_fs_adj, S_IRUGO | S_IWUSR, +static IIO_DEVICE_ATTR(out_voltage0_calibscale, S_IRUGO | S_IWUSR, ad9122_dds_show, ad9122_dds_store, AD9122_REG_I_DAC_CTRL); -static IIO_DEVICE_ATTR(q_dac_fs_adj, S_IRUGO | S_IWUSR, +static IIO_DEVICE_ATTR(out_voltage1_calibscale, S_IRUGO | S_IWUSR, ad9122_dds_show, ad9122_dds_store, AD9122_REG_Q_DAC_CTRL); @@ -511,13 +523,14 @@ static IIO_DEVICE_ATTR(q_dac_fs_adj, S_IRUGO | S_IWUSR, static IIO_CONST_ATTR(out_altvoltage_scale_available, "1.000000 0.500000 0.250000 0.125000 ..."); + static struct attribute *cf_axi_dds_attributes[] = { - &iio_dev_attr_i_phase_adj.dev_attr.attr, - &iio_dev_attr_q_phase_adj.dev_attr.attr, - &iio_dev_attr_i_dac_offset.dev_attr.attr, - &iio_dev_attr_q_dac_offset.dev_attr.attr, - &iio_dev_attr_i_dac_fs_adj.dev_attr.attr, - &iio_dev_attr_q_dac_fs_adj.dev_attr.attr, + &iio_dev_attr_out_voltage0_phase.dev_attr.attr, /* I */ + &iio_dev_attr_out_voltage0_calibscale.dev_attr.attr, + &iio_dev_attr_out_voltage0_calibbias.dev_attr.attr, + &iio_dev_attr_out_voltage1_phase.dev_attr.attr, /* Q */ + &iio_dev_attr_out_voltage1_calibscale.dev_attr.attr, + &iio_dev_attr_out_voltage1_calibbias.dev_attr.attr, &iio_const_attr_out_altvoltage_scale_available.dev_attr.attr, NULL, }; diff --git a/drivers/iio/frequency/cf_axi_dds.h b/drivers/iio/frequency/cf_axi_dds.h index 66e4a6293097b..c3f897b960fd0 100644 --- a/drivers/iio/frequency/cf_axi_dds.h +++ b/drivers/iio/frequency/cf_axi_dds.h @@ -50,9 +50,9 @@ #define CF_AXI_DDS_MEM_CTRL 0x18 #define CF_AXI_DDS_SCALE 0x20 #define CF_AXI_DDS_FRAME 0x24 -#define CF_AXI_DDS_PCORE_IDENT 0x30 #define CF_AXI_DDS_PAT_DATA1 0x40 #define CF_AXI_DDS_PAT_DATA2 0x44 +#define CF_AXI_DDS_PCORE_IDENT 0x48 /* CF_AXI_DDS_CTRL */ #define CF_AXI_DDS_CTRL_PATTERN_EN (1 << 4) From 8ee55aa1a3a509e4943fc6fd28b90b4ef277b13d Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 8 Aug 2012 15:07:49 +0200 Subject: [PATCH 187/261] iio: cf_axi_adc: AD9467 use ODD/EVEN mode Signed-off-by: Michael Hennerich --- drivers/iio/adc/cf_axi_adc.h | 3 +++ drivers/iio/adc/cf_axi_adc_core.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/iio/adc/cf_axi_adc.h b/drivers/iio/adc/cf_axi_adc.h index 4af9ce2539d23..06f2d30c916f9 100644 --- a/drivers/iio/adc/cf_axi_adc.h +++ b/drivers/iio/adc/cf_axi_adc.h @@ -102,6 +102,9 @@ #define OUTPUT_MODE_TWOS_COMPLEMENT 0x1 #define OUTPUT_MODE_GRAY_CODE 0x2 +/* ADC_REG_OUTPUT_PHASE */ +#define OUTPUT_EVEN_ODD_MODE_EN 0x20 + /* * Analog Devices AD9467 16-Bit, 200/250 MSPS ADC */ diff --git a/drivers/iio/adc/cf_axi_adc_core.c b/drivers/iio/adc/cf_axi_adc_core.c index 4a8923d947ebd..5a01a91cf97be 100644 --- a/drivers/iio/adc/cf_axi_adc_core.c +++ b/drivers/iio/adc/cf_axi_adc_core.c @@ -724,6 +724,7 @@ static int __devinit axiadc_of_probe(struct platform_device *op) case CHIPID_AD9643: st->chip_info = &axiadc_chip_info_tbl[ID_AD9643]; st->adc_def_output_mode = AD9643_DEF_OUTPUT_MODE | OUTPUT_MODE_TWOS_COMPLEMENT; + axiadc_spi_write(st, ADC_REG_OUTPUT_PHASE, OUTPUT_EVEN_ODD_MODE_EN); axiadc_write(st, AXIADC_PCORE_ADC_CTRL, AXIADC_SIGNEXTEND | AXIADC_SCALE_OFFSET_EN); axiadc_write(st, AXIADC_PCORE_CA_OFFS_SCALE, AXIADC_OFFSET(0) | AXIADC_SCALE(0x8000)); @@ -737,6 +738,8 @@ static int __devinit axiadc_of_probe(struct platform_device *op) goto failed3; } + axiadc_spi_write(st, ADC_REG_OUTPUT_PHASE, OUTPUT_EVEN_ODD_MODE_EN); + indio_dev->dev.parent = dev; indio_dev->name = op->dev.of_node->name; indio_dev->channels = st->chip_info->channel; From 0af253bbc5a71650a4e2be5d4fe000ac76cbfb02 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 8 Aug 2012 15:05:55 +0200 Subject: [PATCH 188/261] iio: cf_axi_dds: rename IQ imbalance correction attributes fix AD9122_REG_I_PHA_ADJ_MSB to accespt negative values disable frame pulsing Signed-off-by: Michael Hennerich --- drivers/iio/frequency/cf_axi_dds.c | 51 +++++++++++++++++++----------- drivers/iio/frequency/cf_axi_dds.h | 2 +- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/iio/frequency/cf_axi_dds.c b/drivers/iio/frequency/cf_axi_dds.c index 6c6c41bfa4802..efdb365b6ada7 100644 --- a/drivers/iio/frequency/cf_axi_dds.c +++ b/drivers/iio/frequency/cf_axi_dds.c @@ -364,8 +364,7 @@ static int cf_axi_dds_write_raw(struct iio_dev *indio_dev, default: return -EINVAL; } - - cf_axi_dds_sync_frame(st); +// cf_axi_dds_sync_frame(st); return 0; } @@ -407,10 +406,10 @@ static ssize_t ad9122_dds_store(struct device *dev, struct cf_axi_dds_state *st = iio_priv(indio_dev); struct cf_axi_dds_converter *conv = to_converter(st->dev_spi); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - unsigned long readin; + long readin; int ret; - ret = kstrtoul(buf, 10, &readin); + ret = kstrtol(buf, 10, &readin); if (ret) return ret; @@ -419,13 +418,20 @@ static ssize_t ad9122_dds_store(struct device *dev, switch ((u32)this_attr->address) { case AD9122_REG_I_DAC_OFFSET_MSB: case AD9122_REG_Q_DAC_OFFSET_MSB: - if (readin > 0xFFFF) { + if (readin < 0 || readin > 0xFFFF) { + ret = -EINVAL; + goto out; + } + break; + case AD9122_REG_I_PHA_ADJ_MSB: + case AD9122_REG_Q_PHA_ADJ_MSB: + if (readin < -512 || readin > 511) { ret = -EINVAL; goto out; } break; default: - if (readin > 0x3FF) { + if (readin < 0 || readin > 0x3FF) { ret = -EINVAL; goto out; } @@ -468,40 +474,46 @@ static ssize_t ad9122_dds_show(struct device *dev, goto out; val |= ret & 0xFF; - ret = sprintf(buf, "%d\n", val); + switch ((u32)this_attr->address) { + case AD9122_REG_I_PHA_ADJ_MSB: + case AD9122_REG_Q_PHA_ADJ_MSB: + val = sign_extend32(val, 9); + break; + } + ret = sprintf(buf, "%d\n", val); out: mutex_unlock(&indio_dev->mlock); return ret; } -static IIO_DEVICE_ATTR(i_phase_adj, S_IRUGO | S_IWUSR, +static IIO_DEVICE_ATTR(out_voltage0_phase, S_IRUGO | S_IWUSR, ad9122_dds_show, ad9122_dds_store, AD9122_REG_I_PHA_ADJ_MSB); -static IIO_DEVICE_ATTR(q_phase_adj, S_IRUGO | S_IWUSR, +static IIO_DEVICE_ATTR(out_voltage1_phase, S_IRUGO | S_IWUSR, ad9122_dds_show, ad9122_dds_store, AD9122_REG_Q_PHA_ADJ_MSB); -static IIO_DEVICE_ATTR(i_dac_offset, S_IRUGO | S_IWUSR, +static IIO_DEVICE_ATTR(out_voltage0_calibbias, S_IRUGO | S_IWUSR, ad9122_dds_show, ad9122_dds_store, AD9122_REG_I_DAC_OFFSET_MSB); -static IIO_DEVICE_ATTR(q_dac_offset, S_IRUGO | S_IWUSR, +static IIO_DEVICE_ATTR(out_voltage1_calibbias, S_IRUGO | S_IWUSR, ad9122_dds_show, ad9122_dds_store, AD9122_REG_Q_DAC_OFFSET_MSB); -static IIO_DEVICE_ATTR(i_dac_fs_adj, S_IRUGO | S_IWUSR, +static IIO_DEVICE_ATTR(out_voltage0_calibscale, S_IRUGO | S_IWUSR, ad9122_dds_show, ad9122_dds_store, AD9122_REG_I_DAC_CTRL); -static IIO_DEVICE_ATTR(q_dac_fs_adj, S_IRUGO | S_IWUSR, +static IIO_DEVICE_ATTR(out_voltage1_calibscale, S_IRUGO | S_IWUSR, ad9122_dds_show, ad9122_dds_store, AD9122_REG_Q_DAC_CTRL); @@ -511,13 +523,14 @@ static IIO_DEVICE_ATTR(q_dac_fs_adj, S_IRUGO | S_IWUSR, static IIO_CONST_ATTR(out_altvoltage_scale_available, "1.000000 0.500000 0.250000 0.125000 ..."); + static struct attribute *cf_axi_dds_attributes[] = { - &iio_dev_attr_i_phase_adj.dev_attr.attr, - &iio_dev_attr_q_phase_adj.dev_attr.attr, - &iio_dev_attr_i_dac_offset.dev_attr.attr, - &iio_dev_attr_q_dac_offset.dev_attr.attr, - &iio_dev_attr_i_dac_fs_adj.dev_attr.attr, - &iio_dev_attr_q_dac_fs_adj.dev_attr.attr, + &iio_dev_attr_out_voltage0_phase.dev_attr.attr, /* I */ + &iio_dev_attr_out_voltage0_calibscale.dev_attr.attr, + &iio_dev_attr_out_voltage0_calibbias.dev_attr.attr, + &iio_dev_attr_out_voltage1_phase.dev_attr.attr, /* Q */ + &iio_dev_attr_out_voltage1_calibscale.dev_attr.attr, + &iio_dev_attr_out_voltage1_calibbias.dev_attr.attr, &iio_const_attr_out_altvoltage_scale_available.dev_attr.attr, NULL, }; diff --git a/drivers/iio/frequency/cf_axi_dds.h b/drivers/iio/frequency/cf_axi_dds.h index 66e4a6293097b..c3f897b960fd0 100644 --- a/drivers/iio/frequency/cf_axi_dds.h +++ b/drivers/iio/frequency/cf_axi_dds.h @@ -50,9 +50,9 @@ #define CF_AXI_DDS_MEM_CTRL 0x18 #define CF_AXI_DDS_SCALE 0x20 #define CF_AXI_DDS_FRAME 0x24 -#define CF_AXI_DDS_PCORE_IDENT 0x30 #define CF_AXI_DDS_PAT_DATA1 0x40 #define CF_AXI_DDS_PAT_DATA2 0x44 +#define CF_AXI_DDS_PCORE_IDENT 0x48 /* CF_AXI_DDS_CTRL */ #define CF_AXI_DDS_CTRL_PATTERN_EN (1 << 4) From 30f31f8dd58a087647bdea506268c9fc569858e5 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 8 Aug 2012 15:07:49 +0200 Subject: [PATCH 189/261] iio: cf_axi_adc: AD9467 use ODD/EVEN mode Signed-off-by: Michael Hennerich --- drivers/iio/adc/cf_axi_adc.h | 3 +++ drivers/iio/adc/cf_axi_adc_core.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/iio/adc/cf_axi_adc.h b/drivers/iio/adc/cf_axi_adc.h index 4af9ce2539d23..06f2d30c916f9 100644 --- a/drivers/iio/adc/cf_axi_adc.h +++ b/drivers/iio/adc/cf_axi_adc.h @@ -102,6 +102,9 @@ #define OUTPUT_MODE_TWOS_COMPLEMENT 0x1 #define OUTPUT_MODE_GRAY_CODE 0x2 +/* ADC_REG_OUTPUT_PHASE */ +#define OUTPUT_EVEN_ODD_MODE_EN 0x20 + /* * Analog Devices AD9467 16-Bit, 200/250 MSPS ADC */ diff --git a/drivers/iio/adc/cf_axi_adc_core.c b/drivers/iio/adc/cf_axi_adc_core.c index 4a8923d947ebd..5a01a91cf97be 100644 --- a/drivers/iio/adc/cf_axi_adc_core.c +++ b/drivers/iio/adc/cf_axi_adc_core.c @@ -724,6 +724,7 @@ static int __devinit axiadc_of_probe(struct platform_device *op) case CHIPID_AD9643: st->chip_info = &axiadc_chip_info_tbl[ID_AD9643]; st->adc_def_output_mode = AD9643_DEF_OUTPUT_MODE | OUTPUT_MODE_TWOS_COMPLEMENT; + axiadc_spi_write(st, ADC_REG_OUTPUT_PHASE, OUTPUT_EVEN_ODD_MODE_EN); axiadc_write(st, AXIADC_PCORE_ADC_CTRL, AXIADC_SIGNEXTEND | AXIADC_SCALE_OFFSET_EN); axiadc_write(st, AXIADC_PCORE_CA_OFFS_SCALE, AXIADC_OFFSET(0) | AXIADC_SCALE(0x8000)); @@ -737,6 +738,8 @@ static int __devinit axiadc_of_probe(struct platform_device *op) goto failed3; } + axiadc_spi_write(st, ADC_REG_OUTPUT_PHASE, OUTPUT_EVEN_ODD_MODE_EN); + indio_dev->dev.parent = dev; indio_dev->name = op->dev.of_node->name; indio_dev->channels = st->chip_info->channel; From 3068bb09014cd4f461a3c5022b37c96868d2157c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 9 Aug 2012 15:11:00 +0200 Subject: [PATCH 190/261] zed xcomm dts: Fix IRQ number for the video DMA core --- arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts index 0e7153660d5aa..a8a8735225ae2 100644 --- a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts +++ b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts @@ -185,7 +185,7 @@ xlnx,num-fstores = <0x3>; dma-channel@43000000 { compatible = "xlnx,axi-vdma-mm2s-channel"; - interrupts = <0 59 0x4>; + interrupts = <0 55 0x4>; xlnx,datawidth = <0x40>; xlnx,genlock-mode = <0x0>; xlnx,include-dre = <0x0>; From ff093954c50c013fc2157bd2778f80d0db88d604 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 16 Aug 2012 14:37:19 +0200 Subject: [PATCH 191/261] ARM: Fix timer frequency in ZED XCOMM devicetree Signed-off-by: Lars-Peter Clausen --- arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts index a8a8735225ae2..0f94344266cfc 100644 --- a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts +++ b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts @@ -45,9 +45,9 @@ interrupts = <0 10 0>,<0 11 0>,<0 12 0>; interrupt-parent = <&gic>; /* clock-frequency = <111111111>;*/ - clock-frequency-timer0 = <133000000>; - clock-frequency-timer1 = <133000000>; - clock-frequency-timer2 = <133000000>; + clock-frequency-timer0 = <111111111>; + clock-frequency-timer1 = <111111111>; + clock-frequency-timer2 = <111111111>; }; swdt@f8005000 { From 71b0a06f15ded6059e83ce1c65dbab50c758586b Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 21 Aug 2012 09:56:21 +0200 Subject: [PATCH 192/261] zynq xcomm: update device tree Signed-off-by: Michael Hennerich --- arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts | 8 ++++++-- arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts | 16 ++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts b/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts index f2659018a9f44..d760af9e3073d 100644 --- a/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts +++ b/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts @@ -149,6 +149,10 @@ compatible = "at24,24c02"; reg = <0x50>; }; + eeprom@55 { + compatible = "at24,24c02"; + reg = <0x55>; + }; }; }; @@ -251,7 +255,7 @@ } ; cf_ad9643_core_0: cf-ad9643-core-lpc@79020000 { - compatible = "xlnx,cf-ad9643-core-1.00.a"; + compatible = "xlnx,axi-adc-2c-1.00.a"; reg = < 0x79020000 0x10000 >; dma-request = <&axi_dma_1 0>; spibus-connected = <&adc0_ad9467>; @@ -299,7 +303,7 @@ } ; cf_ad9122_core_0: cf-ad9122-core-lpc@74200000 { - compatible = "xlnx,cf-ad9122-core-2.00.a"; + compatible = "xlnx,axi-dac-4d-2c-1.00.a"; reg = < 0x74200000 0x10000 >; spibus-connected = <&dac0_ad9122>; dac-sample-frequency = <491520000>; diff --git a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts index 0e7153660d5aa..15068b82a44df 100644 --- a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts +++ b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts @@ -45,9 +45,9 @@ interrupts = <0 10 0>,<0 11 0>,<0 12 0>; interrupt-parent = <&gic>; /* clock-frequency = <111111111>;*/ - clock-frequency-timer0 = <133000000>; - clock-frequency-timer1 = <133000000>; - clock-frequency-timer2 = <133000000>; + clock-frequency-timer0 = <111111111>; + clock-frequency-timer1 = <111111111>; + clock-frequency-timer2 = <111111111>; }; swdt@f8005000 { @@ -128,6 +128,10 @@ compatible = "at24,24c02"; reg = <0x50>; }; + eeprom@55 { + compatible = "at24,24c02"; + reg = <0x55>; + }; }; sdhci@e0100000 { @@ -185,7 +189,7 @@ xlnx,num-fstores = <0x3>; dma-channel@43000000 { compatible = "xlnx,axi-vdma-mm2s-channel"; - interrupts = <0 59 0x4>; + interrupts = <0 55 0x4>; xlnx,datawidth = <0x40>; xlnx,genlock-mode = <0x0>; xlnx,include-dre = <0x0>; @@ -248,7 +252,7 @@ } ; cf_ad9643_core_0: cf-ad9643-core-lpc@79020000 { - compatible = "xlnx,cf-ad9643-core-1.00.a"; + compatible = "xlnx,axi-adc-2c-1.00.a"; reg = < 0x79020000 0x10000 >; dma-request = <&axi_dma_1 0>; spibus-connected = <&adc0_ad9467>; @@ -262,7 +266,7 @@ } ; cf_ad9122_core_0: cf-ad9122-core-lpc@74200000 { - compatible = "xlnx,cf-ad9122-core-2.00.a"; + compatible = "xlnx,axi-dac-4d-2c-1.00.a"; reg = < 0x74200000 0x10000 >; spibus-connected = <&dac0_ad9122>; dac-sample-frequency = <491520000>; From 5e6114e73691b50ed2d267b1f9afd50e19be04ce Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 24 Aug 2012 10:37:35 +0200 Subject: [PATCH 193/261] iio: adc: cf_axi_adc: extend support for AD9467 Signed-off-by: Michael Hennerich --- drivers/iio/adc/cf_axi_adc.h | 6 ++ drivers/iio/adc/cf_axi_adc_core.c | 113 ++++++++++++++++++++++++++---- drivers/iio/adc/cf_axi_adc_ring.c | 2 +- 3 files changed, 107 insertions(+), 14 deletions(-) diff --git a/drivers/iio/adc/cf_axi_adc.h b/drivers/iio/adc/cf_axi_adc.h index 06f2d30c916f9..e11c277ec0382 100644 --- a/drivers/iio/adc/cf_axi_adc.h +++ b/drivers/iio/adc/cf_axi_adc.h @@ -41,6 +41,12 @@ #define AXIADC_PCORE_ADC_STAT_PN_ERR1 (1 << 5) /* W1C */ #define AXIADC_PCORE_ADC_STAT_MASK 0x3F +/* AXIADC_PCORE_ADC_STAT */ +#define AXIADC_PCORE_ADC_STAT_OVR (1 << 0) /* W1C */ +#define AXIADC_PCORE_ADC_STAT_PN_OOS (1 << 1) /* W1C */ +#define AXIADC_PCORE_ADC_STAT_PN_ERR (1 << 2) /* W1C */ +#define AXIADC_PCORE_ADC_1C_STAT_MASK 0x7 + /* AXIADC_PCORE_PN_ERR_CTRL */ #define AXIADC_PN23_1_EN (1 << 1) #define AXIADC_PN23_0_EN (1 << 0) diff --git a/drivers/iio/adc/cf_axi_adc_core.c b/drivers/iio/adc/cf_axi_adc_core.c index 5a01a91cf97be..510a7794d5cb0 100644 --- a/drivers/iio/adc/cf_axi_adc_core.c +++ b/drivers/iio/adc/cf_axi_adc_core.c @@ -102,7 +102,7 @@ static int axiadc_debugfs_open(struct inode *inode, struct file *file) return 0; } -static int axiadc_dco_calibrate(struct iio_dev *indio_dev) +static int axiadc_dco_calibrate_2c(struct iio_dev *indio_dev) { struct axiadc_state *st = iio_priv(indio_dev); int dco, ret, cnt, start, max_start, max_cnt; @@ -191,6 +191,90 @@ static int axiadc_dco_calibrate(struct iio_dev *indio_dev) return 0; } +static int axiadc_dco_calibrate_1c(struct iio_dev *indio_dev) +{ + struct axiadc_state *st = iio_priv(indio_dev); + int dco, ret, cnt, start, max_start, max_cnt; + unsigned stat; + unsigned char err_field[33]; + + axiadc_testmode_set(indio_dev, 0x1, TESTMODE_PN9_SEQ); + + axiadc_write(st, AXIADC_PCORE_PN_ERR_CTRL, AXIADC_PN9_0_EN); + + for(dco = 0; dco <= 32; dco++) { + ret = 0; + axiadc_spi_write(st, ADC_REG_OUTPUT_DELAY, + dco > 0 ? ((dco - 1) | 0x80) : 0); + axiadc_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); + axiadc_write(st, AXIADC_PCORE_ADC_STAT, AXIADC_PCORE_ADC_STAT_MASK); + + cnt = 4; + + do { + mdelay(8); + stat = axiadc_read(st, AXIADC_PCORE_ADC_STAT); + if ((cnt-- < 0) | (stat & AXIADC_PCORE_ADC_STAT_PN_ERR)) { + ret = -EIO; + break; + } + } while (stat & AXIADC_PCORE_ADC_STAT_PN_OOS); + + cnt = 4; + + if (!ret) + do { + mdelay(4); + stat = axiadc_read(st, AXIADC_PCORE_ADC_STAT); + if (stat & AXIADC_PCORE_ADC_STAT_PN_ERR) { + ret = -EIO; + break; + } + } while (cnt--); + + err_field[dco] = !!ret; + } + + for(dco = 0, cnt = 0, max_cnt = 0, start = -1, max_start = 0; + dco <= 32; dco++) { + if (err_field[dco] == 0) { + if (start == -1) + start = dco; + cnt++; + } else { + if (cnt > max_cnt) { + max_cnt = cnt; + max_start = start; + } + start = -1; + cnt = 0; + } + } + + if (cnt > max_cnt) { + max_cnt = cnt; + max_start = start; + } + + dco = max_start + (max_cnt / 2); + + axiadc_testmode_set(indio_dev, 0x3, TESTMODE_OFF); + axiadc_spi_write(st, ADC_REG_OUTPUT_DELAY, + dco > 0 ? ((dco - 1) | 0x80) : 0); + axiadc_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); + +#ifdef DCO_DEBUG + for(cnt = 0; cnt <= 32; cnt++) + if (cnt == dco) + printk("|"); + else + printk("%c", err_field[cnt] ? '-' : 'o'); + printk(" DCO 0x%X\n", dco > 0 ? ((dco - 1) | 0x80) : 0); +#endif + + return 0; +} + static ssize_t axiadc_debugfs_pncheck_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { @@ -204,9 +288,9 @@ static ssize_t axiadc_debugfs_pncheck_read(struct file *file, char __user *userb switch (st->id) { case CHIPID_AD9467: - len = sprintf(buf, "%s %s\n", (stat & AXIADC_PCORE_ADC_STAT_PN_OOS0) ? + len = sprintf(buf, "%s %s\n", (stat & AXIADC_PCORE_ADC_STAT_PN_OOS) ? "Out of Sync :" : "In Sync :", - (stat & AXIADC_PCORE_ADC_STAT_PN_ERR0) ? + (stat & AXIADC_PCORE_ADC_STAT_PN_ERR) ? "PN Error" : "No Error"); break; case CHIPID_AD9643: @@ -247,7 +331,8 @@ static ssize_t axiadc_debugfs_pncheck_write(struct file *file, else if (sysfs_streq(p, "PN23")) mode = TESTMODE_PN23_SEQ; else if (sysfs_streq(p, "CALIB")) - axiadc_dco_calibrate(indio_dev); + (st->id == CHIPID_AD9467) ? axiadc_dco_calibrate_1c(indio_dev) : + axiadc_dco_calibrate_2c(indio_dev); else mode = TESTMODE_OFF; @@ -720,6 +805,10 @@ static int __devinit axiadc_of_probe(struct platform_device *op) axiadc_write(st, AXIADC_PCORE_ADC_CTRL, AXIADC_SCALE_OFFSET_EN); axiadc_write(st, AXIADC_PCORE_CA_OFFS_SCALE, AXIADC_OFFSET(0) | AXIADC_SCALE(0x8000)); + axiadc_spi_write(st, ADC_REG_OUTPUT_MODE, st->adc_def_output_mode); + axiadc_spi_write(st, ADC_REG_TEST_IO, TESTMODE_OFF); + axiadc_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); + axiadc_dco_calibrate_1c(indio_dev); break; case CHIPID_AD9643: st->chip_info = &axiadc_chip_info_tbl[ID_AD9643]; @@ -730,6 +819,10 @@ static int __devinit axiadc_of_probe(struct platform_device *op) AXIADC_OFFSET(0) | AXIADC_SCALE(0x8000)); axiadc_write(st, AXIADC_PCORE_CB_OFFS_SCALE, AXIADC_OFFSET(0) | AXIADC_SCALE(0x8000)); + axiadc_spi_write(st, ADC_REG_OUTPUT_MODE, st->adc_def_output_mode); + axiadc_spi_write(st, ADC_REG_TEST_IO, TESTMODE_OFF); + axiadc_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); + axiadc_dco_calibrate_2c(indio_dev); break; default: @@ -738,8 +831,6 @@ static int __devinit axiadc_of_probe(struct platform_device *op) goto failed3; } - axiadc_spi_write(st, ADC_REG_OUTPUT_PHASE, OUTPUT_EVEN_ODD_MODE_EN); - indio_dev->dev.parent = dev; indio_dev->name = op->dev.of_node->name; indio_dev->channels = st->chip_info->channel; @@ -750,16 +841,11 @@ static int __devinit axiadc_of_probe(struct platform_device *op) init_completion(&st->dma_complete); - axiadc_spi_write(st, ADC_REG_OUTPUT_MODE, st->adc_def_output_mode); - axiadc_spi_write(st, ADC_REG_TEST_IO, TESTMODE_OFF); - axiadc_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); - - axiadc_dco_calibrate(indio_dev); - axiadc_configure_ring(indio_dev); + ret = iio_buffer_register(indio_dev, st->chip_info->channel, - ARRAY_SIZE(st->chip_info->channel)); + st->chip_info->num_channels); if (ret) goto failed4; @@ -841,6 +927,7 @@ static const struct of_device_id axiadc_of_match[] __devinitconst = { { .compatible = "xlnx,cf-ad9467-core-1.00.a", }, { .compatible = "xlnx,cf-ad9643-core-1.00.a", }, { .compatible = "xlnx,axi-adc-2c-1.00.a", }, + { .compatible = "xlnx,axi-adc-1c-1.00.a", }, { /* end of list */ }, }; MODULE_DEVICE_TABLE(of, axiadc_of_match); diff --git a/drivers/iio/adc/cf_axi_adc_ring.c b/drivers/iio/adc/cf_axi_adc_ring.c index 8e304f22da4cb..ba7ac035177e8 100644 --- a/drivers/iio/adc/cf_axi_adc_ring.c +++ b/drivers/iio/adc/cf_axi_adc_ring.c @@ -59,7 +59,7 @@ static int axiadc_read_first_n_hw_rb(struct iio_buffer *r, if (copy_to_user(buf, st->buf_virt + st->fftcount, count)) ret = -EFAULT; - if ((stat & (AXIADC_PCORE_ADC_STAT_OVR0 | AXIADC_PCORE_ADC_STAT_OVR1)) + if ((stat & (AXIADC_PCORE_ADC_STAT_OVR0 | ((st->id == CHIPID_AD9467) ? 0 : AXIADC_PCORE_ADC_STAT_OVR1))) || dma_stat) dev_warn(indio_dev->dev.parent, "STATUS: DMA_STAT 0x%X, ADC_STAT 0x%X\n", From 862049219049040fdbda859240138084b90ade63 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 30 Aug 2012 08:47:58 +0200 Subject: [PATCH 194/261] iio: adc: cf_axi_adc: alloc and free coherent dma memory only once Signed-off-by: Michael Hennerich --- drivers/iio/adc/cf_axi_adc.h | 2 ++ drivers/iio/adc/cf_axi_adc_ring.c | 34 ++++++++++++++++--------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/iio/adc/cf_axi_adc.h b/drivers/iio/adc/cf_axi_adc.h index e11c277ec0382..2bb390a0fd475 100644 --- a/drivers/iio/adc/cf_axi_adc.h +++ b/drivers/iio/adc/cf_axi_adc.h @@ -129,6 +129,8 @@ #include +#define AXIADC_MAX_DMA_SIZE (4 * 1024 * 1024) /* Randomly picked */ + enum { ID_AD9467, ID_AD9643, diff --git a/drivers/iio/adc/cf_axi_adc_ring.c b/drivers/iio/adc/cf_axi_adc_ring.c index ba7ac035177e8..6f6f68b2d16d7 100644 --- a/drivers/iio/adc/cf_axi_adc_ring.c +++ b/drivers/iio/adc/cf_axi_adc_ring.c @@ -94,8 +94,6 @@ static int axiadc_ring_set_length(struct iio_buffer *r, int lenght) static int axiadc_ring_get_bytes_per_datum(struct iio_buffer *r) { - struct iio_hw_buffer *hw_ring = iio_to_hw_buf(r); - return r->bytes_per_datum; } @@ -157,14 +155,10 @@ static int __axiadc_hw_ring_state_set(struct iio_dev *indio_dev, bool state) complete(&st->dma_complete); } - dma_free_coherent(indio_dev->dev.parent, - PAGE_ALIGN(st->rcount + st->fftcount), - st->buf_virt, st->buf_phys); return 0; } st->compl_stat = 0; - if (st->ring_lenght == 0) { ret = -EINVAL; goto error_ret; @@ -184,11 +178,8 @@ static int __axiadc_hw_ring_state_set(struct iio_dev *indio_dev, bool state) st->fftcount = 0; #endif - st->buf_virt = dma_alloc_coherent(indio_dev->dev.parent, - PAGE_ALIGN(st->rcount + st->fftcount), &st->buf_phys, - GFP_KERNEL); - if (st->buf_virt == NULL) { - ret = -ENOMEM; + if (PAGE_ALIGN(st->rcount + st->fftcount) > AXIADC_MAX_DMA_SIZE) { + ret = -EINVAL; goto error_ret; } @@ -198,7 +189,7 @@ static int __axiadc_hw_ring_state_set(struct iio_dev *indio_dev, bool state) dev_err(indio_dev->dev.parent, "Failed to allocate a dma descriptor\n"); ret = -ENOMEM; - goto error_free; + goto error_ret; } desc->callback = (dma_async_tx_callback) complete; @@ -209,7 +200,7 @@ static int __axiadc_hw_ring_state_set(struct iio_dev *indio_dev, bool state) dev_err(indio_dev->dev.parent, "Failed to submit a dma transfer\n"); ret = cookie; - goto error_free; + goto error_ret; } INIT_COMPLETION(st->dma_complete); dma_async_issue_pending(st->rx_chan); @@ -222,9 +213,6 @@ static int __axiadc_hw_ring_state_set(struct iio_dev *indio_dev, bool state) return 0; -error_free: - dma_free_coherent(indio_dev->dev.parent, PAGE_ALIGN(st->rcount), - st->buf_virt, st->buf_phys); error_ret: return ret; } @@ -246,6 +234,7 @@ static const struct iio_buffer_setup_ops axiadc_ring_setup_ops = { int axiadc_configure_ring(struct iio_dev *indio_dev) { + struct axiadc_state *st = iio_priv(indio_dev); indio_dev->buffer = axiadc_rb_allocate(indio_dev); if (indio_dev->buffer == NULL) return -ENOMEM; @@ -254,10 +243,23 @@ int axiadc_configure_ring(struct iio_dev *indio_dev) indio_dev->buffer->access = &axiadc_ring_access_funcs; indio_dev->setup_ops = &axiadc_ring_setup_ops; + st->buf_virt = dma_alloc_coherent(indio_dev->dev.parent, + PAGE_ALIGN(AXIADC_MAX_DMA_SIZE), &st->buf_phys, + GFP_KERNEL); + if (st->buf_virt == NULL) { + dev_err(indio_dev->dev.parent, + "Failed to allocate a dma memory\n"); + return -ENOMEM; + } + return 0; } void axiadc_unconfigure_ring(struct iio_dev *indio_dev) { + struct axiadc_state *st = iio_priv(indio_dev); + + dma_free_coherent(indio_dev->dev.parent, PAGE_ALIGN(AXIADC_MAX_DMA_SIZE), + st->buf_virt, st->buf_phys); axiadc_rb_free(indio_dev->buffer); } From 18365dc1d2b13b8c8d862024a8387ba840fdaf7c Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 9 Oct 2012 10:31:04 +0200 Subject: [PATCH 195/261] iio: frequency: cf_axi_dds: add more sed test patterns Signed-off-by: Michael Hennerich --- drivers/iio/frequency/cf_axi_dds.c | 39 +++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/drivers/iio/frequency/cf_axi_dds.c b/drivers/iio/frequency/cf_axi_dds.c index efdb365b6ada7..d97a6ef8ff20d 100644 --- a/drivers/iio/frequency/cf_axi_dds.c +++ b/drivers/iio/frequency/cf_axi_dds.c @@ -73,13 +73,31 @@ struct cf_axi_dds_sed { unsigned short q1; }; -static struct cf_axi_dds_sed dac_sed_pattern[2] = { +static struct cf_axi_dds_sed dac_sed_pattern[5] = { { .i0 = 0x5555, .q0 = 0xAAAA, .i1 = 0xAAAA, .q1 = 0x5555, }, + { + .i0 = 0, + .q0 = 0, + .i1 = 0xFFFF, + .q1 = 0xFFFF, + }, + { + .i0 = 0, + .q0 = 0, + .i1 = 0, + .q1 = 0, + }, + { + .i0 = 0xFFFF, + .q0 = 0xFFFF, + .i1 = 0xFFFF, + .q1 = 0xFFFF, + }, { .i0 = 0x1248, .q0 = 0xEDC7, @@ -119,7 +137,7 @@ static int cf_axi_dds_find_dci(unsigned long *err_field, unsigned entries) } - ret = max_start + (max_cnt / 2); + ret = max_start + ((max_cnt - 1) / 2); str[ret] = '|'; @@ -135,8 +153,12 @@ static int cf_axi_dds_tune_dci(struct cf_axi_dds_state *st) int i = 0, dci; unsigned long err_bfield = 0; - for (dci = 0; dci < 4; dci++) + for (dci = 0; dci < 4; dci++) { + conv->write(conv->spi, AD9122_REG_DCI_DELAY, dci); for (i = 0; i < ARRAY_SIZE(dac_sed_pattern); i++) { + + conv->write(conv->spi, AD9122_REG_SED_CTRL, 0); + dds_write(st, CF_AXI_DDS_PAT_DATA1, (dac_sed_pattern[i].i1 << 16) | dac_sed_pattern[i].i0); @@ -150,8 +172,6 @@ static int cf_axi_dds_tune_dci(struct cf_axi_dds_state *st) dds_write(st, CF_AXI_DDS_CTRL, CF_AXI_DDS_CTRL_DDS_CLK_EN_V2 | CF_AXI_DDS_CTRL_PATTERN_EN | CF_AXI_DDS_CTRL_DATA_EN); - conv->write(conv->spi, AD9122_REG_DCI_DELAY, dci); - conv->write(conv->spi, AD9122_REG_COMPARE_I0_LSBS, dac_sed_pattern[i].i0 & 0xFF); conv->write(conv->spi, AD9122_REG_COMPARE_I0_MSBS, @@ -175,10 +195,16 @@ static int cf_axi_dds_tune_dci(struct cf_axi_dds_state *st) conv->write(conv->spi, AD9122_REG_SED_CTRL, AD9122_SED_CTRL_SED_COMPARE_EN); + + conv->write(conv->spi, AD9122_REG_EVENT_FLAG_2, + AD9122_EVENT_FLAG_2_AED_COMPARE_PASS | + AD9122_EVENT_FLAG_2_AED_COMPARE_FAIL | + AD9122_EVENT_FLAG_2_SED_COMPARE_FAIL); + conv->write(conv->spi, AD9122_REG_SED_CTRL, AD9122_SED_CTRL_SED_COMPARE_EN); - msleep(50); + msleep(100); reg = conv->read(conv->spi, AD9122_REG_SED_CTRL); err_mask = conv->read(conv->spi, AD9122_REG_SED_I_LSBS); err_mask |= conv->read(conv->spi, AD9122_REG_SED_I_MSBS); @@ -188,6 +214,7 @@ static int cf_axi_dds_tune_dci(struct cf_axi_dds_state *st) if (err_mask || (reg & AD9122_SED_CTRL_SAMPLE_ERR_DETECTED)) set_bit(dci, &err_bfield); } + } conv->write(conv->spi, AD9122_REG_DCI_DELAY, cf_axi_dds_find_dci(&err_bfield, 4)); From 1baa6eaf3ccc87af419e4aff8effb72d493cc92e Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 9 Oct 2012 10:33:58 +0200 Subject: [PATCH 196/261] iio: adc: cf_axi_adc: add support for the AD9250 JESD204B converter. Signed-off-by: Michael Hennerich --- drivers/iio/adc/ad9467.c | 45 +++++++++++++++++++++++++++++++ drivers/iio/adc/cf_axi_adc.h | 9 +++++++ drivers/iio/adc/cf_axi_adc_core.c | 21 +++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c index c8e7ad924b030..9774bf6b83a43 100644 --- a/drivers/iio/adc/ad9467.c +++ b/drivers/iio/adc/ad9467.c @@ -51,9 +51,44 @@ static int ad9467_spi_write(struct spi_device *spi, unsigned reg, unsigned val) return 0; } + + if (val != ad9467_spi_read(spi, reg)) + dev_err(&spi->dev, "Verify REG 0x%X Failed (0x%X)\n", reg, ad9467_spi_read(spi, reg)); + + return -ENODEV; } +static int __devinit ad9250_setup(struct spi_device *spi) +{ + int ret; + + msleep(500); + + ret = ad9467_spi_write(spi, 0x18, 0x0f); // max vref + ret |= ad9467_spi_write(spi, 0x64, 0xf0); // did + ret |= ad9467_spi_write(spi, 0x80, 0x0f); // powerdown + ret |= ad9467_spi_write(spi, 0x5f, 0x15); // char repl & ilas + ret |= ad9467_spi_write(spi, 0x09, 0x01); // clock control + ret |= ad9467_spi_write(spi, 0x82, 0x02); // lane b = 0, lane a = 2 + ret |= ad9467_spi_write(spi, 0x83, 0x31); // lane c = 1, lane d = 3 + ret |= ad9467_spi_write(spi, 0x6e, 0x81); // scr, 2-lane + ret |= ad9467_spi_write(spi, 0x70, 0x1f); // no. of frames per multi frame + ret |= ad9467_spi_write(spi, 0x5e, 0x22); // m=2, l=2 + ret |= ad9467_spi_write(spi, 0x5f, 0x14); // char repl & ilas + ret |= ad9467_spi_write(spi, 0x80, 0x09); // powerdown + ret |= ad9467_spi_write(spi, 0x3a, 0x10); // sysref ctrl + ret |= ad9467_spi_write(spi, 0x14, 0x00); // offset binary + ret |= ad9467_spi_write(spi, 0x0d, 0x00); // test patterns + ret |= ad9467_spi_write(spi, 0xff, 0x01); + ret |= ad9467_spi_write(spi, 0xff, 0x00); + + dev_info(&spi->dev, "PLL STATUS 0x%X\n", ad9467_spi_read(spi, 0x0A)); + + msleep(500); + + return ret; +} static int __devinit ad9467_probe(struct spi_device *spi) { @@ -73,6 +108,15 @@ static int __devinit ad9467_probe(struct spi_device *spi) goto out; } + if (conv->id == CHIPID_AD9250) { + ret = ad9250_setup(spi); + if (ret) { + dev_err(&spi->dev, "Failed to initialize\n"); + ret = -EIO; + goto out; + } + } + conv->write = ad9467_spi_write; conv->read = ad9467_spi_read; conv->spi = spi; @@ -95,6 +139,7 @@ static int ad9467_remove(struct spi_device *spi) static const struct spi_device_id ad9467_id[] = { {"ad9467", CHIPID_AD9467}, {"ad9643", CHIPID_AD9643}, + {"ad9250", CHIPID_AD9250}, {} }; MODULE_DEVICE_TABLE(spi, ad9467_id); diff --git a/drivers/iio/adc/cf_axi_adc.h b/drivers/iio/adc/cf_axi_adc.h index 2bb390a0fd475..5c8ec61a814b7 100644 --- a/drivers/iio/adc/cf_axi_adc.h +++ b/drivers/iio/adc/cf_axi_adc.h @@ -127,6 +127,14 @@ #define AD9643_REG_VREF_MASK 0x1F #define AD9643_DEF_OUTPUT_MODE 0x00 +/* + * Analog Devices AD9250 Dual 14-Bit, 170/250 MSPS ADC, JESD204B + */ + +#define CHIPID_AD9250 0xB9 +#define AD9250_REG_VREF_MASK 0x1F +#define AD9250_DEF_OUTPUT_MODE 0x00 + #include #define AXIADC_MAX_DMA_SIZE (4 * 1024 * 1024) /* Randomly picked */ @@ -134,6 +142,7 @@ enum { ID_AD9467, ID_AD9643, + ID_AD9250, }; struct axiadc_chip_info { diff --git a/drivers/iio/adc/cf_axi_adc_core.c b/drivers/iio/adc/cf_axi_adc_core.c index 510a7794d5cb0..b4a213740fb35 100644 --- a/drivers/iio/adc/cf_axi_adc_core.c +++ b/drivers/iio/adc/cf_axi_adc_core.c @@ -661,6 +661,18 @@ static const struct axiadc_chip_info axiadc_chip_info_tbl[] = { .channel[2] = AIM_CHAN_FD(0, 2, 14, 'u'), .channel[3] = AIM_CHAN_FD(1, 3, 14, 'u'), }, + [ID_AD9250] = { + .name = "AD9250", + .scale_table = ad9643_scale_table, + .num_scales = ARRAY_SIZE(ad9643_scale_table), + .num_channels = 4, + .available_scan_masks[0] = BIT(0) | BIT(1), + .available_scan_masks[1] = BIT(2) | BIT(3), + .channel[0] = AIM_CHAN(0, 0, 14, 'u'), + .channel[1] = AIM_CHAN(1, 1, 14, 'u'), + .channel[2] = AIM_CHAN_FD(0, 2, 14, 'u'), + .channel[3] = AIM_CHAN_FD(1, 3, 14, 'u'), + }, }; static const struct iio_info axiadc_info = { @@ -824,6 +836,12 @@ static int __devinit axiadc_of_probe(struct platform_device *op) axiadc_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); axiadc_dco_calibrate_2c(indio_dev); + break; + case CHIPID_AD9250: + st->chip_info = &axiadc_chip_info_tbl[ID_AD9250]; + st->adc_def_output_mode = AD9643_DEF_OUTPUT_MODE | OUTPUT_MODE_OFFSET_BINARY; + axiadc_spi_write(st, ADC_REG_OUTPUT_MODE, st->adc_def_output_mode); + axiadc_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); break; default: dev_err(dev, "Unrecognized CHIP_ID 0x%X\n", st->id); @@ -849,6 +867,8 @@ static int __devinit axiadc_of_probe(struct platform_device *op) if (ret) goto failed4; + *indio_dev->buffer->scan_mask = st->chip_info->available_scan_masks[0]; + ret = iio_device_register(indio_dev); if (ret) goto failed4; @@ -928,6 +948,7 @@ static const struct of_device_id axiadc_of_match[] __devinitconst = { { .compatible = "xlnx,cf-ad9643-core-1.00.a", }, { .compatible = "xlnx,axi-adc-2c-1.00.a", }, { .compatible = "xlnx,axi-adc-1c-1.00.a", }, + { .compatible = "xlnx,axi-ad9250-1.00.a", }, { /* end of list */ }, }; MODULE_DEVICE_TABLE(of, axiadc_of_match); From f618d2b760e08de6a51e94352d4c4255441bd6ee Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 9 Oct 2012 10:34:50 +0200 Subject: [PATCH 197/261] iio: Add generic AXI JESD204B configuration driver Signed-off-by: Michael Hennerich --- drivers/iio/adc/Kconfig | 4 + drivers/iio/adc/Makefile | 2 + drivers/iio/adc/cf_axi_jesd204b.c | 165 ++++++++++++++++++++++++++++++ drivers/iio/adc/cf_axi_jesd204b.h | 80 +++++++++++++++ 4 files changed, 251 insertions(+) create mode 100644 drivers/iio/adc/cf_axi_jesd204b.c create mode 100644 drivers/iio/adc/cf_axi_jesd204b.h diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index c8eb86326db53..1d5d19b62f1c3 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -38,4 +38,8 @@ config CF_AXI_ADC config CF_AXI_FFT tristate "Generic FFT driver" +config AXI_JESD204B + tristate "Generic AXI JESD204B configuration driver" + + endmenu diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index a235b510a827f..16ebb62aaa86f 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -8,3 +8,5 @@ obj-$(CONFIG_AT91_ADC) += at91_adc.o cf_axi_adc-y := cf_axi_adc_core.o cf_axi_adc_ring.o obj-$(CONFIG_CF_AXI_ADC) += cf_axi_adc.o ad9467.o obj-$(CONFIG_CF_AXI_FFT) += cf_axi_fft_core.o + +obj-$(CONFIG_AXI_JESD204B) += cf_axi_jesd204b.o diff --git a/drivers/iio/adc/cf_axi_jesd204b.c b/drivers/iio/adc/cf_axi_jesd204b.c new file mode 100644 index 0000000000000..1c751cd4f54e2 --- /dev/null +++ b/drivers/iio/adc/cf_axi_jesd204b.c @@ -0,0 +1,165 @@ +/* + * ADI AXI-JESD204B Interface Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + * + * http://wiki.analog.com/resources/fpga/xilinx/ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "cf_axi_jesd204b.h" + +struct jesd204b_state { + struct device *dev; + void __iomem *regs; +}; + +/* + * IO accessors + */ + +static inline void jesd204b_write(struct jesd204b_state *st, unsigned reg, unsigned val) +{ + iowrite32(val, st->regs + reg); +} + +static inline unsigned int jesd204b_read(struct jesd204b_state *st, unsigned reg) +{ + return ioread32(st->regs + reg); +} + + +static int __devinit jesd204b_of_probe(struct platform_device *op) +{ + struct device *dev = &op->dev; + struct jesd204b_state *st; + struct resource r_mem; /* IO mem resources */ + resource_size_t remap_size, phys_addr; + int ret; + + dev_info(dev, "Device Tree Probing \'%s\'\n", + op->dev.of_node->name); + + st = devm_kzalloc(&op->dev, sizeof(*st), GFP_KERNEL); + if (!st) { + dev_err(dev, "Not enough memory for device\n"); + return -ENOMEM; + } + + st->dev = dev; + dev_set_drvdata(dev, st); + + /* Get iospace for the device */ + ret = of_address_to_resource(op->dev.of_node, 0, &r_mem); + if (ret) { + dev_err(dev, "invalid address\n"); + return ret; + } + + phys_addr = r_mem.start; + remap_size = resource_size(&r_mem); + if (!request_mem_region(phys_addr, remap_size, KBUILD_MODNAME)) { + dev_err(dev, "Couldn't lock memory region at 0x%08llX\n", + (unsigned long long)phys_addr); + ret = -EBUSY; + goto failed1; + } + + st->regs = ioremap(phys_addr, remap_size); + if (st->regs == NULL) { + dev_err(dev, "Couldn't ioremap memory at 0x%08llX\n", + (unsigned long long)phys_addr); + ret = -EFAULT; + goto failed2; + } + + jesd204b_write(st, AXI_JESD204B_REG_CTRL, + AXI_JESD204B_CTRL_SCR_EN | + AXI_JESD204B_CTRL_LANESYNC_EN); + jesd204b_write(st, AXI_JESD204B_REG_FRMCTRL, + AXI_JESD204B_FRMCTRL_FRMCNT(0x1F) | + AXI_JESD204B_FRMCTRL_BYTECNT(1)); + + dev_info(dev, "AXI-JESD204B (0x%X) at 0x%08llX mapped to 0x%p,", + jesd204b_read(st, AXI_JESD204B_REG_VERSION), + (unsigned long long)phys_addr, st->regs); + + return 0; + +failed2: + release_mem_region(phys_addr, remap_size); +failed1: + dev_set_drvdata(dev, NULL); + + return ret; +} + +/** + * jesd204b_of_remove - unbinds the driver from the AIM device. + * @of_dev: pointer to OF device structure + * + * This function is called if a device is physically removed from the system or + * if the driver module is being unloaded. It frees any resources allocated to + * the device. + */ +static int __devexit jesd204b_of_remove(struct platform_device *op) +{ + struct device *dev = &op->dev; + struct resource r_mem; /* IO mem resources */ + struct jesd204b_state *st = dev_get_drvdata(dev); + + + iounmap(st->regs); + + /* Get iospace of the device */ + if (of_address_to_resource(op->dev.of_node, 0, &r_mem)) + dev_err(dev, "invalid address\n"); + else + release_mem_region(r_mem.start, resource_size(&r_mem)); + + dev_set_drvdata(dev, NULL); + + return 0; +} + +/* Match table for of_platform binding */ +static const struct of_device_id jesd204b_of_match[] __devinitconst = { + { .compatible = "xlnx,axi-jesd204b-rx2-1.00.a", }, + { /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, jesd204b_of_match); + +static struct platform_driver jesd204b_of_driver = { + .driver = { + .name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .of_match_table = jesd204b_of_match, + }, + .probe = jesd204b_of_probe, + .remove = __devexit_p(jesd204b_of_remove), +}; + +module_platform_driver(jesd204b_of_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices CF FFT"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/cf_axi_jesd204b.h b/drivers/iio/adc/cf_axi_jesd204b.h new file mode 100644 index 0000000000000..57ae49013df6c --- /dev/null +++ b/drivers/iio/adc/cf_axi_jesd204b.h @@ -0,0 +1,80 @@ +/* + * ADI AXI-JESD204B Interface Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + * + * http://wiki.analog.com/resources/fpga/xilinx/ + */ + +/* + * 0x00 0x00 [31: 0] version[31:0] 32'h00010061 (1.0a) + * --------------------------------------------------------------------------- + * 0x01 0x04 [ 4: 4] sysref_sel Select sw(0x1) or hw(0x0) sysref generation + * [ 3: 3] lanesync_enb Enable (0x1) lane synchronization + * [ 2: 2] scr_enb Enable (0x1) scrambling + * [ 1: 1] sysref_enb Enable (0x1) re-alignment at every sysref pulses + * [ 0: 0] err_disb Disable (0x1) error reporting via sync + * --------------------------------------------------------------------------- + * 0x02 0x08 [ 0: 0] sysref_int Software controlled sysref (0->1 transition) + * --------------------------------------------------------------------------- + * 0x03 0x0c [12: 8] frmcnt Number of frames per multi-frame (n-1) + * [ 7: 0] bytecnt Number of bytes (octets) per frame (n-1) + * --------------------------------------------------------------------------- + * 0x04 0x10 [12: 0] buffdelay Buffer delay from multi-frame + * --------------------------------------------------------------------------- + * 0x05 0x14 [ 3: 2] test_mode Test mode (?) + * [ 1: 0] lane_sel Select lanes (0, 1, 2 or 3) for reporting + * --------------------------------------------------------------------------- + * The following registers are based on lane_sel + * --------------------------------------------------------------------------- + * 0x06 0x18 [31: 0] bufcnt Buffer count (latency) + * 0x07 0x1c [31: 0] init_data0 ILS Data 0 + * 0x08 0x20 [31: 0] init_data1 ILS Data 1 + * 0x09 0x24 [31: 0] init_data2 ILS Data 2 + * 0x0a 0x28 [31: 0] init_data3 ILS Data 3 + * 0x0b 0x2c [31: 0] test_mfcnt Test MF count (?) + * 0x0c 0x30 [31: 0] test_ilacnt Test ILA count (?) + * 0x0d 0x34 [31: 0] test_errcnt Test ERROR count (?) + */ + +#ifndef ADI_JESD204B_H_ +#define ADI_JESD204B_H_ + +/* PCORE CoreFPGA register map */ + +#define AXI_JESD204B_REG_VERSION 0x00 +#define AXI_JESD204B_REG_CTRL 0x04 +#define AXI_JESD204B_REG_SYSREF_TRIG 0x08 +#define AXI_JESD204B_REG_FRMCTRL 0x0C +#define AXI_JESD204B_REG_BUFDELAY 0x10 +#define AXI_JESD204B_REG_TEST_MODE 0x14 +#define AXI_JESD204B_REG_BUFCNT 0x18 +#define AXI_JESD204B_REG_INIT_DATA0 0x1C +#define AXI_JESD204B_REG_INIT_DATA1 0x20 +#define AXI_JESD204B_REG_INIT_DATA2 0x24 +#define AXI_JESD204B_REG_INIT_DATA3 0x28 +#define AXI_JESD204B_REG_TEST_MFCNT 0x2C +#define AXI_JESD204B_REG_TEST_ILACNT 0x30 +#define AXI_JESD204B_REG_TEST_ERRCNT 0x34 + +/* AXI_JESD204B_REG_CTRL */ +#define AXI_JESD204B_CTRL_ERR_DIS (1 << 0) +#define AXI_JESD204B_CTRL_SYSREF_EN (1 << 1) +#define AXI_JESD204B_CTRL_SCR_EN (1 << 2) +#define AXI_JESD204B_CTRL_LANESYNC_EN (1 << 3) +#define AXI_JESD204B_CTRL_SYSREF_SW_EN (1 << 4) +#define AXI_JESD204B_CTRL_SYSREF_HW_EN (0 << 4) + +/* AXI_JESD204B_REG_SYSREF_TRIG */ +#define AXI_JESD204B_SYSREF_TRIG (1 << 0) + +/* AXI_JESD204B_REG_FRMCTRL */ +#define AXI_JESD204B_FRMCTRL_FRMCNT(x) ((x) << 8) +#define AXI_JESD204B_FRMCTRL_BYTECNT(x) (((x) & 0xFF) << 0) + +/* AXI_JESD204B_REG_BUFDELAY */ +#define AXI_JESD204B_BUFDELAY(x) ((x) << 0) + +#endif /* ADI_JESD204B_H_ */ From 0e02efeebc25364958b386ea9ac2ae4572874ee2 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 9 Oct 2012 10:37:38 +0200 Subject: [PATCH 198/261] platform: ml605: add support for AD9250_FMC Signed-off-by: Michael Hennerich --- .../boot/dts/cf_ad9250_fmc_kc705.dts | 419 +++++ .../microblaze/configs/kc705_ad9250_defconfig | 1381 +++++++++++++++++ 2 files changed, 1800 insertions(+) create mode 100644 arch/microblaze/boot/dts/cf_ad9250_fmc_kc705.dts create mode 100644 arch/microblaze/configs/kc705_ad9250_defconfig diff --git a/arch/microblaze/boot/dts/cf_ad9250_fmc_kc705.dts b/arch/microblaze/boot/dts/cf_ad9250_fmc_kc705.dts new file mode 100644 index 0000000000000..74736527574f1 --- /dev/null +++ b/arch/microblaze/boot/dts/cf_ad9250_fmc_kc705.dts @@ -0,0 +1,419 @@ +/* + * Device Tree Generator version: 1.3 + * + * (C) Copyright 2007-2008 Xilinx, Inc. + * (C) Copyright 2007-2009 Michal Simek + * + * Michal SIMEK + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * CAUTION: This file is automatically generated by libgen. + * Version: Xilinx EDK 14.1 EDK_P.15xf + * + * XPS project directory: device-tree_bsp_0 + */ + +/dts-v1/; +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,microblaze"; + model = "testing"; + DDR3_SDRAM: memory@c0000000 { + device_type = "memory"; + reg = < 0xc0000000 0x40000000 >; + } ; + aliases { + ethernet0 = &Ethernet_Lite; + serial0 = &RS232_Uart_1; + } ; + chosen { + bootargs = "console=ttyS0 root=/dev/ram"; + } ; + cpus { + #address-cells = <1>; + #cpus = <0x1>; + #size-cells = <0>; + microblaze_0: cpu@0 { + clock-frequency = <100000000>; + compatible = "xlnx,microblaze-8.30.a"; + d-cache-baseaddr = <0xc0000000>; + d-cache-highaddr = <0xffffffff>; + d-cache-line-size = <0x10>; + d-cache-size = <0x4000>; + device_type = "cpu"; + i-cache-baseaddr = <0xc0000000>; + i-cache-highaddr = <0xffffffff>; + i-cache-line-size = <0x20>; + i-cache-size = <0x4000>; + model = "microblaze,8.30.a"; + reg = <0>; + timebase-frequency = <100000000>; + xlnx,addr-tag-bits = <0x10>; + xlnx,allow-dcache-wr = <0x1>; + xlnx,allow-icache-wr = <0x1>; + xlnx,area-optimized = <0x0>; + xlnx,avoid-primitives = <0x0>; + xlnx,branch-target-cache-size = <0x0>; + xlnx,cache-byte-size = <0x4000>; + xlnx,d-axi = <0x1>; + xlnx,d-lmb = <0x1>; + xlnx,d-plb = <0x0>; + xlnx,data-size = <0x20>; + xlnx,dcache-addr-tag = <0x10>; + xlnx,dcache-always-used = <0x1>; + xlnx,dcache-byte-size = <0x4000>; + xlnx,dcache-data-width = <0x0>; + xlnx,dcache-force-tag-lutram = <0x0>; + xlnx,dcache-interface = <0x0>; + xlnx,dcache-line-len = <0x4>; + xlnx,dcache-use-fsl = <0x0>; + xlnx,dcache-use-writeback = <0x0>; + xlnx,dcache-victims = <0x0>; + xlnx,debug-enabled = <0x1>; + xlnx,div-zero-exception = <0x1>; + xlnx,dynamic-bus-sizing = <0x1>; + xlnx,ecc-use-ce-exception = <0x0>; + xlnx,edge-is-positive = <0x1>; + xlnx,endianness = <0x1>; + xlnx,family = "kintex7"; + xlnx,fault-tolerant = <0x0>; + xlnx,fpu-exception = <0x0>; + xlnx,freq = <0x5f5e100>; + xlnx,fsl-data-size = <0x20>; + xlnx,fsl-exception = <0x0>; + xlnx,fsl-links = <0x0>; + xlnx,i-axi = <0x0>; + xlnx,i-lmb = <0x1>; + xlnx,i-plb = <0x0>; + xlnx,icache-always-used = <0x1>; + xlnx,icache-data-width = <0x0>; + xlnx,icache-force-tag-lutram = <0x0>; + xlnx,icache-interface = <0x0>; + xlnx,icache-line-len = <0x8>; + xlnx,icache-streams = <0x1>; + xlnx,icache-use-fsl = <0x0>; + xlnx,icache-victims = <0x8>; + xlnx,ill-opcode-exception = <0x1>; + xlnx,instance = "microblaze_0"; + xlnx,interconnect = <0x2>; + xlnx,interconnect-m-axi-dc-read-issuing = <0x2>; + xlnx,interconnect-m-axi-dc-write-issuing = <0x20>; + xlnx,interconnect-m-axi-dp-read-issuing = <0x1>; + xlnx,interconnect-m-axi-dp-write-issuing = <0x1>; + xlnx,interconnect-m-axi-ic-read-issuing = <0x8>; + xlnx,interconnect-m-axi-ip-read-issuing = <0x1>; + xlnx,interrupt-is-edge = <0x0>; + xlnx,lockstep-slave = <0x0>; + xlnx,mmu-dtlb-size = <0x4>; + xlnx,mmu-itlb-size = <0x2>; + xlnx,mmu-privileged-instr = <0x0>; + xlnx,mmu-tlb-access = <0x3>; + xlnx,mmu-zones = <0x2>; + xlnx,number-of-pc-brk = <0x1>; + xlnx,number-of-rd-addr-brk = <0x0>; + xlnx,number-of-wr-addr-brk = <0x0>; + xlnx,opcode-0x0-illegal = <0x1>; + xlnx,optimization = <0x0>; + xlnx,pc-width = <0x20>; + xlnx,pvr = <0x2>; + xlnx,pvr-user1 = <0x0>; + xlnx,pvr-user2 = <0x0>; + xlnx,reset-msr = <0x0>; + xlnx,sco = <0x0>; + xlnx,stream-interconnect = <0x0>; + xlnx,unaligned-exceptions = <0x1>; + xlnx,use-barrel = <0x1>; + xlnx,use-branch-target-cache = <0x0>; + xlnx,use-dcache = <0x1>; + xlnx,use-div = <0x1>; + xlnx,use-ext-brk = <0x1>; + xlnx,use-ext-nm-brk = <0x1>; + xlnx,use-extended-fsl-instr = <0x0>; + xlnx,use-fpu = <0x0>; + xlnx,use-hw-mul = <0x2>; + xlnx,use-icache = <0x1>; + xlnx,use-interrupt = <0x1>; + xlnx,use-mmu = <0x3>; + xlnx,use-msr-instr = <0x1>; + xlnx,use-pcmp-instr = <0x1>; + xlnx,use-reorder-instr = <0x1>; + xlnx,use-stack-protection = <0x0>; + } ; + } ; + axi4lite_0: axi@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,axi-interconnect-1.06.a", "simple-bus"; + ranges ; + Ethernet_Lite: ethernet@40e00000 { + compatible = "xlnx,axi-ethernetlite-1.01.b", "xlnx,xps-ethernetlite-1.00.a"; + device_type = "network"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 4 0 >; + local-mac-address = [ 00 0a 35 b9 b5 00 ]; + phy-handle = <&phy0>; + reg = < 0x40e00000 0x10000 >; + xlnx,duplex = <0x1>; + xlnx,family = "kintex7"; + xlnx,include-global-buffers = <0x0>; + xlnx,include-internal-loopback = <0x0>; + xlnx,include-mdio = <0x1>; + xlnx,include-phy-constraints = <0x1>; + xlnx,instance = "Ethernet_Lite"; + xlnx,interconnect-s-axi-read-acceptance = <0x1>; + xlnx,interconnect-s-axi-write-acceptance = <0x1>; + xlnx,rx-ping-pong = <0x0>; + xlnx,s-axi-aclk-period-ps = <0x2710>; + xlnx,s-axi-id-width = <0x1>; + xlnx,s-axi-supports-narrow-burst = <0x0>; + xlnx,tx-ping-pong = <0x0>; + mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: phy@7 { + compatible = "marvell,88e1111"; + device_type = "ethernet-phy"; + reg = <7>; + } ; + } ; + } ; + RS232_Uart_1: serial@40600000 { + clock-frequency = <100000000>; + compatible = "xlnx,axi-uartlite-1.02.a", "xlnx,xps-uartlite-1.00.a"; + current-speed = <57600>; + device_type = "serial"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 5 0 >; + port-number = <0>; + reg = < 0x40600000 0x10000 >; + xlnx,baudrate = <0xe100>; + xlnx,data-bits = <0x8>; + xlnx,family = "kintex7"; + xlnx,instance = "RS232_Uart_1"; + xlnx,odd-parity = <0x1>; + xlnx,s-axi-aclk-freq-hz = <0x5f5e100>; + xlnx,use-parity = <0x0>; + } ; + axi_ad9250_0: cf-ad9250-1@7c820000 { + compatible = "xlnx,axi-ad9250-1.00.a"; + reg = < 0x7c820000 0x10000 >; + dma-request = <&axi_dma_0 0>; + spibus-connected = <&adc0_ad9250>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "kintex7"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + axi_ad9250_1: cf-ad9250-2@7c800000 { + compatible = "xlnx,axi-ad9250-1.00.a"; + reg = < 0x7c800000 0x10000 >; + dma-request = <&axi_dma_1 0>; + spibus-connected = <&adc1_ad9250>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "kintex7"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + axi_dma_0: axidma@41e20000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + ranges = < 0x41e20000 0x41e20000 0x10000 >; + reg = < 0x41e20000 0x10000 >; +// xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@41e20030 { + compatible = "xlnx,axi-dma-s2mm-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 2 2 >; + xlnx,datawidth = <0x40>; + xlnx,include-dre = <0x0>; + } ; + } ; + axi_dma_1: axidma@41e00000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + ranges = < 0x41e00000 0x41e00000 0x10000 >; + reg = < 0x41e00000 0x10000 >; +// xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@41e00030 { + compatible = "xlnx,axi-dma-s2mm-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 1 2 >; + xlnx,datawidth = <0x40>; + xlnx,include-dre = <0x0>; + } ; + } ; + + /* LCD Display */ + + axi_gpio_0: gpio@40000000 { + compatible = "xlnx,axi-xlnx-lcd-1.00.a"; + reg = < 0x40000000 0x8 >; + xlnx,all-inputs = <0x0>; + xlnx,dout-default = <0x0>; + xlnx,family = "kintex7"; + xlnx,gpio-width = <0x7>; + xlnx,instance = "axi_gpio_0"; + xlnx,interrupt-present = <0x0>; + xlnx,is-dual = <0x0>; + xlnx,tri-default = <0xffffffff>; + } ; + + /* util_jesdbufx2_0 mode */ + + axi_gpio_1: gpio@40000008 { + compatible = "xlnx,axi-gpio-1.01.b", "xlnx,xps-gpio-1.00.a"; + reg = < 0x40000008 0x8 >; + xlnx,all-inputs = <0x0>; + xlnx,dout-default = <0x1>; /* set mode ??? */ + xlnx,family = "kintex7"; + xlnx,gpio-width = <0x1>; + xlnx,instance = "axi_gpio_0"; + xlnx,interrupt-present = <0x0>; + xlnx,is-dual = <0x0>; + xlnx,tri-default = <0xfffffffe>; + } ; + + /* axi_gpio_1_ad8372_ctrl */ + + axi_gpio_2: gpio@40040000 { + compatible = "xlnx,axi-gpio-1.01.b", "xlnx,xps-gpio-1.00.a"; + reg = < 0x40040000 0x8 >; + xlnx,all-inputs = <0x0>; + xlnx,dout-default = <0x0>; + xlnx,family = "kintex7"; + xlnx,gpio-width = <0x8>; + xlnx,instance = "axi_gpio_1"; + xlnx,interrupt-present = <0x0>; + xlnx,is-dual = <0x0>; + xlnx,tri-default = <0xffffffff>; + } ; + + /* axi_gpio_1_rstb_pwdn */ + + axi_gpio_3: gpio@40040008 { + compatible = "xlnx,axi-gpio-1.01.b", "xlnx,xps-gpio-1.00.a"; + reg = < 0x40040008 0x8 >; + xlnx,all-inputs = <0x0>; + xlnx,dout-default = <0x3>; + xlnx,family = "kintex7"; + xlnx,gpio-width = <0x4>; + xlnx,instance = "axi_gpio_1"; + xlnx,interrupt-present = <0x0>; + xlnx,is-dual = <0x0>; + xlnx,tri-default = <0xfffffff0>; + } ; + + axi_intc_0: interrupt-controller@41200000 { + #interrupt-cells = <0x2>; + compatible = "xlnx,axi-intc-1.01.a", "xlnx,xps-intc-1.00.a"; + interrupt-controller ; + reg = < 0x41200000 0x10000 >; + xlnx,kind-of-intr = <0x30>; + xlnx,num-intr-inputs = <0x6>; + } ; + axi_jesd204b_rx2_0: axi-jesd204b-rx2@77a20000 { + compatible = "xlnx,axi-jesd204b-rx2-1.00.a"; + reg = < 0x77a20000 0x10000 >; + xlnx,cf-buftype = <0x1>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "kintex7"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + axi_jesd204b_rx2_1: axi-jesd204b-rx2@77a00000 { + compatible = "xlnx,axi-jesd204b-rx2-1.00.a"; + reg = < 0x77a00000 0x10000 >; + xlnx,cf-buftype = <0x0>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "kintex7"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + axi_spi_0: spi@40a00000 { + compatible = "xlnx,axi-spi-1.02.a", "xlnx,xps-spi-2.00.a"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 0 2 >; + reg = < 0x40a00000 0x10000 >; + xlnx,family = "kintex7"; + xlnx,fifo-exist = <0x1>; + xlnx,instance = "axi_spi_0"; + xlnx,num-ss-bits = <0x2>; + xlnx,num-transfer-bits = <0x8>; + xlnx,sck-ratio = <0x20>; + adc0_ad9250: ad9250@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ad9250"; + reg = <0>; + spi-max-frequency = <10000000>; + }; + adc1_ad9250: ad9250@1 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ad9250"; + reg = <1>; + spi-max-frequency = <10000000>; + }; + + } ; + axi_timer_0: timer@41c00000 { + clock-frequency = <100000000>; + compatible = "xlnx,axi-timer-1.03.a", "xlnx,xps-timer-1.00.a"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 3 2 >; + reg = < 0x41c00000 0x10000 >; + xlnx,count-width = <0x20>; + xlnx,family = "kintex7"; + xlnx,gen0-assert = <0x1>; + xlnx,gen1-assert = <0x1>; + xlnx,instance = "axi_timer_0"; + xlnx,one-timer-only = <0x0>; + xlnx,trig0-assert = <0x1>; + xlnx,trig1-assert = <0x1>; + } ; + debug_module: debug@41400000 { + compatible = "xlnx,mdm-2.00.b"; + reg = < 0x41400000 0x10000 >; + xlnx,family = "kintex7"; + xlnx,interconnect = <0x2>; + xlnx,jtag-chain = <0x2>; + xlnx,mb-dbg-ports = <0x1>; + xlnx,use-uart = <0x1>; + } ; + } ; +} ; diff --git a/arch/microblaze/configs/kc705_ad9250_defconfig b/arch/microblaze/configs/kc705_ad9250_defconfig new file mode 100644 index 0000000000000..82ad7d6acbba5 --- /dev/null +++ b/arch/microblaze/configs/kc705_ad9250_defconfig @@ -0,0 +1,1381 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/microblaze 3.5.0-rc4 Kernel Configuration +# +CONFIG_MICROBLAZE=y +# CONFIG_SWAP is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ZONE_DMA=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_CSUM=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_IRQ_DOMAIN=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y + +# +# RCU Subsystem +# +CONFIG_TINY_RCU=y +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="rootfs.cpio.gz" +CONFIG_INITRAMFS_ROOT_UID=0 +CONFIG_INITRAMFS_ROOT_GID=0 +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +CONFIG_INITRAMFS_COMPRESSION_NONE=y +# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_API_DEBUG=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_BLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_FREEZER is not set + +# +# Platform options +# +# CONFIG_PLATFORM_GENERIC is not set +CONFIG_PLATFORM_ML605_ADIXCOMM=y +# CONFIG_PLATFORM_KC705_ADIXCOMM is not set +# CONFIG_ADIXCOMM_SYNC is not set +CONFIG_OPT_LIB_FUNCTION=y +# CONFIG_OPT_LIB_ASM is not set + +# +# Definitions for MICROBLAZE0 +# +CONFIG_KERNEL_BASE_ADDR=0xc0000000 +CONFIG_XILINX_MICROBLAZE0_FAMILY="virtex6" +CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1 +CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1 +CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1 +CONFIG_XILINX_MICROBLAZE0_USE_DIV=1 +CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL=2 +CONFIG_XILINX_MICROBLAZE0_USE_FPU=0 +CONFIG_XILINX_MICROBLAZE0_HW_VER="8.20.a" + +# +# Processor type and features +# +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_SCHED_HRTICK=y +CONFIG_MMU=y + +# +# Boot options +# +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyUL0,57600 root=/dev/ram" +CONFIG_CMDLINE_FORCE=y +# CONFIG_SECCOMP is not set + +# +# Advanced setup +# +CONFIG_ADVANCED_OPTIONS=y +# CONFIG_HIGHMEM is not set +CONFIG_LOWMEM_SIZE_BOOL=y +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_MANUAL_RESET_VECTOR=0x0 +CONFIG_KERNEL_START_BOOL=y +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE_BOOL=y +CONFIG_TASK_SIZE=0x80000000 +CONFIG_KERNEL_PAD=0x80000 +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_NEED_PER_CPU_KM=y +# CONFIG_CLEANCACHE is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Bus Options +# +# CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS is not set +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +# CONFIG_DNS_RESOLVER is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +CONFIG_BQL=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +CONFIG_GENERIC_CPU_DEVICES=y +# CONFIG_DMA_SHARED_BUFFER is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=y +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_GPIO_ADDR is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_LATCH_ADDR is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_DEVICE=y +CONFIG_OF_I2C=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +# CONFIG_PARPORT is not set + +# +# Misc devices +# +CONFIG_AD525X_DPOT=y +CONFIG_AD525X_DPOT_I2C=y +CONFIG_AD525X_DPOT_SPI=y +# CONFIG_ICS932S401 is not set +CONFIG_XLNX_LCD=y +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_MII is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set + +# +# CAIF transport drivers +# +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_INTEL=y +CONFIG_NET_VENDOR_I825XX=y +CONFIG_NET_VENDOR_MARVELL=y +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +CONFIG_NET_VENDOR_NATSEMI=y +CONFIG_NET_VENDOR_8390=y +# CONFIG_ETHOC is not set +CONFIG_NET_VENDOR_SEEQ=y +# CONFIG_SEEQ8005 is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_WIZNET=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +CONFIG_NET_VENDOR_XILINX=y +CONFIG_XILINX_EMACLITE=y +# CONFIG_XILINX_AXI_EMAC is not set +# CONFIG_XILINX_LL_TEMAC is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_AMD_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_WLAN=y +# CONFIG_HOSTAP is not set +# CONFIG_WL_TI is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_DW is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_UARTLITE=y +CONFIG_SERIAL_UARTLITE_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_TTY_PRINTK is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_XILINX_HWICAP is not set +# CONFIG_R3964 is not set + +# +# PCMCIA character devices +# +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_MUX is not set +# CONFIG_I2C_HELPER_AUTO is not set +# CONFIG_I2C_SMBUS is not set + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +CONFIG_I2C_XILINX=y + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=y +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_XCOMM is not set +CONFIG_SPI_XILINX=y +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_HSI is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_OF_GPIO=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +CONFIG_GPIO_XILINX=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_S5M_CORE is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_EXYNOS_VIDEO is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_SOUND is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB_ARCH_HAS_XHCI is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_RTC_CLASS is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_XILINX_DMA=y +# CONFIG_TIMB_DMA is not set +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_BALLOON is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_ECHO is not set +# CONFIG_RTLLIB is not set + +# +# IIO staging drivers +# +CONFIG_IIO_SW_RING=y + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16204 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_KXSD9 is not set +# CONFIG_LIS3L02DQ is not set +# CONFIG_SCA3000 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7291 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7606 is not set +# CONFIG_AD799X is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_ADT7310 is not set +# CONFIG_ADT7410 is not set +# CONFIG_AD7280 is not set +# CONFIG_MAX1363 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Direct Digital Synthesis +# +# CONFIG_AD5930 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_AD9850 is not set +# CONFIG_AD9852 is not set +# CONFIG_AD9910 is not set +# CONFIG_AD9951 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16060 is not set +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set + +# +# Light sensors +# +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_ISL29028 is not set +# CONFIG_SENSORS_TSL2563 is not set +# CONFIG_TSL2583 is not set +# CONFIG_TSL2x7x is not set + +# +# Magnetometer sensors +# +# CONFIG_SENSORS_AK8975 is not set +# CONFIG_SENSORS_HMC5843 is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7753 is not set +# CONFIG_ADE7754 is not set +# CONFIG_ADE7758 is not set +# CONFIG_ADE7759 is not set +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_GPIO_TRIGGER is not set +# CONFIG_IIO_SYSFS_TRIGGER is not set +# CONFIG_IIO_SIMPLE_DUMMY is not set +# CONFIG_ZSMALLOC is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +# CONFIG_ANDROID is not set +# CONFIG_PHONE is not set +# CONFIG_IPACK_BUS is not set +# CONFIG_WIMAX_GDM72XX is not set + +# +# Hardware Spinlock drivers +# +CONFIG_IOMMU_SUPPORT=y + +# +# Remoteproc drivers (EXPERIMENTAL) +# + +# +# Rpmsg drivers (EXPERIMENTAL) +# +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 + +# +# Analog to digital converters +# +# CONFIG_AD7266 is not set +CONFIG_CF_AXI_ADC=y +CONFIG_CF_AXI_FFT=y +CONFIG_AXI_JESD204B=y + +# +# Amplifiers +# +# CONFIG_AD8366 is not set + +# +# Light sensors +# +# CONFIG_VCNL4000 is not set + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +# CONFIG_AD9523 is not set +# CONFIG_AD9548 is not set + +# +# Direct Digital Synthesis +# +CONFIG_CF_AXI_DDS=y +CONFIG_CF_AXI_DDS_AD9122=y + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +# CONFIG_ADF4350 is not set + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD5686 is not set +# CONFIG_MAX517 is not set +# CONFIG_MCP4725 is not set + +# +# File systems +# +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ECRYPT_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set +# CONFIG_MINIX_FS_NATIVE_ENDIAN is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V2=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_DEBUG is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +# CONFIG_DETECT_HUNG_TASK is not set +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_TEST_KSTRTOX is not set +CONFIG_EARLY_PRINTK=y +# CONFIG_HEART_BEAT is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_ENCRYPTED_KEYS is not set +CONFIG_KEYS_DEBUG_PROC_KEYS=y +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +# CONFIG_CRC8 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_GENERIC_ATOMIC64=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set From 23ec650f56c9d5a753a77e45be0b537467c7d8c4 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 17 Oct 2012 17:43:43 +0200 Subject: [PATCH 199/261] iio: core: add support for chardev write buffers Signed-off-by: Michael Hennerich --- drivers/iio/iio_core.h | 3 ++- drivers/iio/industrialio-buffer.c | 17 +++++++++++++++ drivers/iio/industrialio-core.c | 36 +++++++++++++++++++++++++++++-- include/linux/iio/buffer.h | 8 +++++++ 4 files changed, 61 insertions(+), 3 deletions(-) diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h index f652e6ae5a359..c54ee236639f0 100644 --- a/drivers/iio/iio_core.h +++ b/drivers/iio/iio_core.h @@ -43,7 +43,8 @@ unsigned int iio_buffer_poll(struct file *filp, struct poll_table_struct *wait); ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, size_t n, loff_t *f_ps); - +ssize_t iio_buffer_chrdev_write(struct file *filp, const char __user *buf, + size_t n, loff_t *f_ps); #define iio_buffer_poll_addr (&iio_buffer_poll) #define iio_buffer_read_first_n_outer_addr (&iio_buffer_read_first_n_outer) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 096a6bfe0cdfa..a819462c6fe02 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -48,6 +48,23 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, return rb->access->read_first_n(rb, n, buf); } +/** + * iio_buffer_read_first_n_outer() - chrdev read for buffer access + * + * This function relies on all buffer implementations having an + * iio_buffer as their first element. + **/ +ssize_t iio_buffer_chrdev_write(struct file *filp, const char __user *buf, + size_t n, loff_t *f_ps) +{ + struct iio_dev *indio_dev = filp->private_data; + struct iio_buffer *rb = indio_dev->buffer; + + if (!rb || !rb->access->write) + return -EINVAL; + return rb->access->write(rb, n, buf); +} + /** * iio_buffer_poll() - poll the buffer to find out if it has data */ diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index bb3c692e49b88..5a011a5c95ff8 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -28,6 +28,7 @@ #include "iio_core_trigger.h" #include #include +#include /* IDA to assign each registered device a unique id*/ static DEFINE_IDA(iio_ida); @@ -896,7 +897,7 @@ static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -EINVAL; } -static const struct file_operations iio_buffer_fileops = { +static const struct file_operations iio_buffer_in_fileops = { .read = iio_buffer_read_first_n_outer_addr, .release = iio_chrdev_release, .open = iio_chrdev_open, @@ -907,10 +908,31 @@ static const struct file_operations iio_buffer_fileops = { .compat_ioctl = iio_ioctl, }; +static const struct file_operations iio_buffer_none_fileops = { + .release = iio_chrdev_release, + .open = iio_chrdev_open, + .owner = THIS_MODULE, + .llseek = noop_llseek, + .unlocked_ioctl = iio_ioctl, + .compat_ioctl = iio_ioctl, +}; + +static const struct file_operations iio_buffer_out_fileops = { + .write = iio_buffer_chrdev_write, + .release = iio_chrdev_release, + .open = iio_chrdev_open, + .poll = iio_buffer_poll_addr, + .owner = THIS_MODULE, + .llseek = noop_llseek, + .unlocked_ioctl = iio_ioctl, + .compat_ioctl = iio_ioctl, +}; + static const struct iio_buffer_setup_ops noop_ring_setup_ops; int iio_device_register(struct iio_dev *indio_dev) { + const struct file_operations *fops; int ret; /* configure elements for the chrdev */ @@ -941,10 +963,20 @@ int iio_device_register(struct iio_dev *indio_dev) indio_dev->setup_ops == NULL) indio_dev->setup_ops = &noop_ring_setup_ops; + if (indio_dev->buffer) { + if (indio_dev->buffer->direction == IIO_BUFFER_DIRECTION_IN) + fops = &iio_buffer_in_fileops; + else + fops = &iio_buffer_out_fileops; + } else { + fops = &iio_buffer_none_fileops; + } + ret = device_add(&indio_dev->dev); if (ret < 0) goto error_unreg_eventset; - cdev_init(&indio_dev->chrdev, &iio_buffer_fileops); + + cdev_init(&indio_dev->chrdev, fops); indio_dev->chrdev.owner = indio_dev->info->driver_module; ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1); if (ret < 0) diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 2a2b6b4d8d055..e5e22ade79100 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -41,6 +41,7 @@ struct iio_buffer_access_funcs { size_t n, char __user *buf); + int (*write)(struct iio_buffer *buffer, size_t n, const char __user *buf); int (*request_update)(struct iio_buffer *buffer); int (*get_bytes_per_datum)(struct iio_buffer *buffer); @@ -49,6 +50,12 @@ struct iio_buffer_access_funcs { int (*set_length)(struct iio_buffer *buffer, int length); }; +enum iio_buffer_direction { + IIO_BUFFER_DIRECTION_IN, + IIO_BUFFER_DIRECTION_OUT, +}; + + /** * struct iio_buffer - general buffer structure * @length: [DEVICE] number of datums in buffer @@ -81,6 +88,7 @@ struct iio_buffer { const struct attribute_group *attrs; struct list_head demux_list; unsigned char *demux_bounce; + enum iio_buffer_direction direction; }; /** From 68d72361d01cda3d739621b9f38c75914ab26099 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 18 Oct 2012 10:16:00 +0200 Subject: [PATCH 200/261] iio: frequency: cf_axi_dds: add support for DMA buffers Signed-off-by: Michael Hennerich --- drivers/iio/frequency/Makefile | 2 +- drivers/iio/frequency/cf_axi_dds.c | 75 ++- drivers/iio/frequency/cf_axi_dds.h | 724 +++------------------- drivers/iio/frequency/cf_axi_dds_buffer.c | 249 ++++++++ 4 files changed, 417 insertions(+), 633 deletions(-) create mode 100644 drivers/iio/frequency/cf_axi_dds_buffer.c diff --git a/drivers/iio/frequency/Makefile b/drivers/iio/frequency/Makefile index 1e6fa5b9229be..f6f5e533529db 100644 --- a/drivers/iio/frequency/Makefile +++ b/drivers/iio/frequency/Makefile @@ -5,5 +5,5 @@ obj-$(CONFIG_AD9548) += ad9548.o obj-$(CONFIG_AD9523) += ad9523.o obj-$(CONFIG_ADF4350) += adf4350.o -obj-$(CONFIG_CF_AXI_DDS) += cf_axi_dds.o +obj-$(CONFIG_CF_AXI_DDS) += cf_axi_dds.o cf_axi_dds_buffer.o obj-$(CONFIG_CF_AXI_DDS_AD9122) += ad9122.o diff --git a/drivers/iio/frequency/cf_axi_dds.c b/drivers/iio/frequency/cf_axi_dds.c index d97a6ef8ff20d..9acbda9e3b3df 100644 --- a/drivers/iio/frequency/cf_axi_dds.c +++ b/drivers/iio/frequency/cf_axi_dds.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -40,12 +41,25 @@ struct dds_spidev { struct device *dev_spi; }; +struct axi_dds_dma_params { + struct device_node *of_node; + int chan_id; +}; + +static bool cf_axi_dds_dma_filter(struct dma_chan *chan, void *param) +{ + struct axi_dds_dma_params *p = param; + + return chan->device->dev->of_node == p->of_node && + chan->chan_id == p->chan_id; +} + static void cf_axi_dds_sync_frame(struct cf_axi_dds_state *st) { dds_write(st, CF_AXI_DDS_FRAME, 0); dds_write(st, CF_AXI_DDS_FRAME, CF_AXI_DDS_FRAME_SYNC); } -static void cf_axi_dds_stop(struct cf_axi_dds_state *st) { +void cf_axi_dds_stop(struct cf_axi_dds_state *st) { dds_write(st, CF_AXI_DDS_CTRL, (st->vers_id > 1) ? CF_AXI_DDS_CTRL_DDS_CLK_EN_V2 : CF_AXI_DDS_CTRL_DDS_CLK_EN_V1); } @@ -232,12 +246,12 @@ static void cf_axi_dds_mem_init(struct cf_axi_dds_state *st) sample = 0; addr = 0; - for (i = 0; i < ARRAY_SIZE(cf_axi_dds_ia_data); i++) { + for (i = 0; i < ARRAY_SIZE(cf_axi_dds_i_data); i++) { data = (sample << 24) | (addr << 16); - dds_write(st, CF_AXI_DDS_MEM_CTRL, ((0 << 26) | data | cf_axi_dds_ia_data[i])); - dds_write(st, CF_AXI_DDS_MEM_CTRL, ((1 << 26) | data | cf_axi_dds_ib_data[i])); - dds_write(st, CF_AXI_DDS_MEM_CTRL, ((2 << 26) | data | cf_axi_dds_qa_data[i])); - dds_write(st, CF_AXI_DDS_MEM_CTRL, ((3 << 26) | data | cf_axi_dds_qb_data[i])); + dds_write(st, CF_AXI_DDS_MEM_CTRL, ((0 << 26) | data | cf_axi_dds_i_data[i])); + dds_write(st, CF_AXI_DDS_MEM_CTRL, ((1 << 26) | data | cf_axi_dds_i_data[i])); + dds_write(st, CF_AXI_DDS_MEM_CTRL, ((2 << 26) | data | cf_axi_dds_q_data[i])); + dds_write(st, CF_AXI_DDS_MEM_CTRL, ((3 << 26) | data | cf_axi_dds_q_data[i])); sample++; if (sample >= 3) { addr++; @@ -587,6 +601,16 @@ static const struct attribute_group cf_axi_dds_attribute_group = { .extend_name = _extend_name, \ } +#define CF_AXI_DDS_CHAN_BUF(_chan) \ + { .type = IIO_ALTVOLTAGE, \ + .indexed = 1, \ + .channel = _chan, \ + .info_mask = 0, \ + .output = 1, \ + .scan_index = _chan, \ + .scan_type = IIO_ST('s', 16, 16, 0), \ +} + static const struct cf_axi_dds_chip_info cf_axi_dds_chip_info_tbl[] = { [ID_AD9122] = { .name = "AD9122", @@ -595,6 +619,8 @@ static const struct cf_axi_dds_chip_info cf_axi_dds_chip_info_tbl[] = { .channel[2] = CF_AXI_DDS_CHAN(2, CF_AXI_DDS_2A_OUTPUT_CTRL, "2A"), .channel[3] = CF_AXI_DDS_CHAN(3, CF_AXI_DDS_2B_OUTPUT_CTRL, "2B"), .channel[4] = CF_AXI_DDS_CHAN_CLK_IN(0, "DAC_CLK"), + .buf_channel[0] = CF_AXI_DDS_CHAN_BUF(0), + .buf_channel[1] = CF_AXI_DDS_CHAN_BUF(1), }, [ID_AD9739A] = { .name = "AD9739A", @@ -603,6 +629,8 @@ static const struct cf_axi_dds_chip_info cf_axi_dds_chip_info_tbl[] = { .channel[2] = CF_AXI_DDS_CHAN(2, CF_AXI_DDS_2A_OUTPUT_CTRL, "2A"), .channel[3] = CF_AXI_DDS_CHAN(3, CF_AXI_DDS_2B_OUTPUT_CTRL, "2B"), .channel[4] = CF_AXI_DDS_CHAN_CLK_IN(0, "DAC_CLK"), + .buf_channel[0] = CF_AXI_DDS_CHAN_BUF(0), + .buf_channel[1] = CF_AXI_DDS_CHAN_BUF(1), }, }; @@ -645,6 +673,9 @@ static int __devinit cf_axi_dds_of_probe(struct platform_device *op) resource_size_t remap_size, phys_addr; struct dds_spidev dds_spidev; struct cf_axi_dds_converter *conv; + struct axi_dds_dma_params dma_params; + struct of_phandle_args dma_spec; + dma_cap_mask_t mask; int ret; const struct of_device_id *of_id = @@ -761,6 +792,33 @@ static int __devinit cf_axi_dds_of_probe(struct platform_device *op) cf_axi_dds_sync_frame(st); + ret = of_parse_phandle_with_args(op->dev.of_node, "dma-request", + "#dma-cells", 0, &dma_spec); + if (ret) { + dev_warn(dev, "Couldn't parse dma-request\n"); + goto skip_writebuf; + } + + dma_params.of_node = dma_spec.np; + dma_params.chan_id = dma_spec.args[0]; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE | DMA_PRIVATE, mask); + + st->tx_chan = dma_request_channel(mask, cf_axi_dds_dma_filter, &dma_params); + if (!st->tx_chan) { + dev_err(dev, "failed to find vdma device\n"); + goto failed3; + } + + cf_axi_dds_configure_buffer(indio_dev); + + ret = iio_buffer_register(indio_dev, + st->chip_info->buf_channel, 2); + if (ret) + goto failed3; + +skip_writebuf: ret = iio_device_register(indio_dev); if (ret) goto failed3; @@ -799,6 +857,11 @@ static int __devexit cf_axi_dds_of_remove(struct platform_device *op) iounmap(st->regs); release_mem_region(st->r_mem.start, resource_size(&st->r_mem)); + if (st->tx_chan == NULL) { + cf_axi_dds_unconfigure_buffer(indio_dev); + dma_release_channel(st->tx_chan); + } + iio_device_free(indio_dev); dev_set_drvdata(dev, NULL); diff --git a/drivers/iio/frequency/cf_axi_dds.h b/drivers/iio/frequency/cf_axi_dds.h index c3f897b960fd0..5a32819fc9c39 100644 --- a/drivers/iio/frequency/cf_axi_dds.h +++ b/drivers/iio/frequency/cf_axi_dds.h @@ -1,45 +1,13 @@ -/**************************************************************************** -* *************************************************************************** -* Rejeesh.Kutty@Analog.com (c) Analog Devices Inc. -* *************************************************************************** -* *************************************************************************** -* Address Map (AD9122) -* Address offset 0x00 -* [31: 0]: 0x00_01_00_61 -* Address offset 0x04 -* [ 8: 8]: dds clock enable (0x1) or disable (0x0). -* [ 7: 7]: dds-2b select dds-Xilinx(0x1) or dds-mem (0x0). -* [ 6: 6]: dds-2b enable (0x1) or disable (0x0). -* [ 5: 5]: dds-2a select dds-Xilinx(0x1) or dds-mem (0x0). -* [ 4: 4]: dds-2a enable (0x1) or disable (0x0). -* [ 3: 3]: dds-1b select dds-Xilinx(0x1) or dds-mem (0x0). -* [ 2: 2]: dds-1b enable (0x1) or disable (0x0). -* [ 1: 1]: dds-1a select dds-Xilinx(0x1) or dds-mem (0x0). -* [ 0: 0]: dds-1a enable (0x1) or disable (0x0). -* Address offset 0x08 -* [31:16]: dds-1a init (phase offset) count -* [15: 0]: dds-1a increment count -* Address offset 0x0c -* [31:16]: dds-1b init (phase offset) count -* [15: 0]: dds-1b increment count -* Address offset 0x10 -* [31:16]: dds-2a init (phase offset) count -* [15: 0]: dds-2a increment count -* Address offset 0x14 -* [31:16]: dds-2b init (phase offset) count -* [15: 0]: dds-2b increment count -* Address offset 0x18 -* [27:27]: dds mem select i/q (0 to 1). -* [26:26]: dds mem select a/b (0 to 1). -* [25:24]: dds mem sample select (0 to 2). -* [23:16]: dds mem write address -* [15: 0]: dds mem write data -* Address offset 0x20 (data = data >> scale) -* [15:12]: dds scale 2b -* [11: 8]: dds scale 2a -* [ 7: 4]: dds scale 1b -* [ 3: 0]: dds scale 1a -* ***************************************************************************/ +/* + * DDS PCORE/COREFPGA Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#ifndef ADI_AXI_DDS_H_ +#define ADI_AXI_DDS_H_ #define CF_AXI_DDS_VERSION_ID 0x00 #define CF_AXI_DDS_CTRL 0x04 @@ -50,6 +18,7 @@ #define CF_AXI_DDS_MEM_CTRL 0x18 #define CF_AXI_DDS_SCALE 0x20 #define CF_AXI_DDS_FRAME 0x24 +#define CF_AXI_DDS_DMA_STAT 0x28 #define CF_AXI_DDS_PAT_DATA1 0x40 #define CF_AXI_DDS_PAT_DATA2 0x44 #define CF_AXI_DDS_PCORE_IDENT 0x48 @@ -68,6 +37,12 @@ /* CF_AXI_DDS_PCORE_IDENT */ #define CF_AXI_DDS_PCORE_IDENT_SLAVE 0x1 +/* CF_AXI_DDS_DMA_STAT W1C */ +#define CF_AXI_DDS_DMA_STAT_OVF (1 << 0) +#define CF_AXI_DDS_DMA_STAT_UNF (1 << 1) + +#define AXIDDS_MAX_DMA_SIZE (4 * 1024 * 1024) /* Randomly picked */ + enum { ID_AD9122, ID_AD9739A, @@ -76,19 +51,28 @@ enum { struct cf_axi_dds_chip_info { char name[8]; struct iio_chan_spec channel[5]; + struct iio_chan_spec buf_channel[2]; }; +#include + struct cf_axi_dds_state { struct list_head list; struct device *dev_spi; struct resource r_mem; /* IO mem resources */ const struct cf_axi_dds_chip_info *chip_info; + void *buf_virt; + dma_addr_t buf_phys; + struct dma_chan *tx_chan; + struct xilinx_dma_config dma_config; u16 int_vref_mv; int irq; void __iomem *regs; unsigned int flags; u32 dac_clk; unsigned vers_id; + unsigned buffer_lenght; + unsigned txcount; }; struct cf_axi_dds_converter { @@ -110,6 +94,10 @@ static inline struct cf_axi_dds_converter *to_converter(struct device *dev) return ERR_PTR(-ENODEV); }; +int cf_axi_dds_configure_buffer(struct iio_dev *indio_dev); +void cf_axi_dds_unconfigure_buffer(struct iio_dev *indio_dev); +void cf_axi_dds_stop(struct cf_axi_dds_state *st); + /* * IO accessors */ @@ -126,7 +114,7 @@ static inline unsigned int dds_read(struct cf_axi_dds_state *st, unsigned reg) } #if defined(CF_AXI_DDS_WAVDATA) -static const u32 cf_axi_dds_ia_data[] = { +static const u16 cf_axi_dds_i_data[] = { 0x7fff, 0xbf16, 0xedc8, 0xfff4, 0xf0e1, 0xc479, 0x8647, 0x4673, 0x1592, @@ -385,71 +373,7 @@ static const u32 cf_axi_dds_ia_data[] = { 0x000a, 0x1236, 0x40e8 }; -static u32 cf_axi_dds_ib_data[] = { - 0x7fff, 0xbf16, 0xedc8, - 0xfff4, 0xf0e1, 0xc479, - 0x8647, 0x4673, 0x1592, - 0x0059, 0x0c4a, 0x364b, - 0x7373, 0xb3de, 0xe6ce, - 0xff08, 0xf640, 0xcebe, - 0x92c7, 0x51ee, 0x1d0e, - 0x01e2, 0x077b, 0x2c64, - 0x6706, 0xa825, 0xded6, - 0xfce2, 0xfa7b, 0xd841, - 0x9f19, 0x5ddc, 0x257d, - 0x04a3, 0x03d6, 0x234c, - 0x5ad7, 0x9c0a, 0xd5f4, - 0xf988, 0xfd88, 0xe0ea, - 0xab1e, 0x6a1d, 0x2ecc, - 0x0894, 0x0163, 0x1b17, - 0x4f04, 0x8faa, 0xcc3e, - 0xf503, 0xff60, 0xe8a5, - 0xb6b9, 0x7695, 0x38e3, - 0x0dab, 0x0027, 0x13dc, - 0x43a9, 0x8323, 0xc1cd, - 0xef5d, 0xfffe, 0xef5d, - 0xc1cd, 0x8323, 0x43a9, - 0x13dc, 0x0027, 0x0dab, - 0x38e3, 0x7695, 0xb6b9, - 0xe8a5, 0xff60, 0xf503, - 0xcc3e, 0x8faa, 0x4f04, - 0x1b17, 0x0163, 0x0894, - 0x2ecc, 0x6a1d, 0xab1e, - 0xe0ea, 0xfd88, 0xf988, - 0xd5f4, 0x9c0a, 0x5ad7, - 0x234c, 0x03d6, 0x04a3, - 0x257d, 0x5ddc, 0x9f19, - 0xd841, 0xfa7b, 0xfce2, - 0xded6, 0xa825, 0x6706, - 0x2c64, 0x077b, 0x01e2, - 0x1d0e, 0x51ee, 0x92c7, - 0xcebe, 0xf640, 0xff08, - 0xe6ce, 0xb3de, 0x7373, - 0x364b, 0x0c4a, 0x0059, - 0x1592, 0x4673, 0x8647, - 0xc479, 0xf0e1, 0xfff4, - 0xedc8, 0xbf16, 0x7fff, - 0x40e8, 0x1236, 0x000a, - 0x0f1d, 0x3b85, 0x79b7, - 0xb98b, 0xea6c, 0xffa5, - 0xf3b4, 0xc9b3, 0x8c8b, - 0x4c20, 0x1930, 0x00f6, - 0x09be, 0x3140, 0x6d37, - 0xae10, 0xe2f0, 0xfe1c, - 0xf883, 0xd39a, 0x98f8, - 0x57d9, 0x2128, 0x031c, - 0x0583, 0x27bd, 0x60e5, - 0xa222, 0xda81, 0xfb5b, - 0xfc28, 0xdcb2, 0xa527, - 0x63f4, 0x2a0a, 0x0676, - 0x0276, 0x1f14, 0x54e0, - 0x95e1, 0xd132, 0xf76a, - 0xfe9b, 0xe4e7, 0xb0fa, - 0x7054, 0x33c0, 0x0afb, - 0x009e, 0x1759, 0x4945, - 0x8969, 0xc71b, 0xf253, - 0xffd7, 0xec22, 0xbc55, - 0x7cdb, 0x3e31, 0x10a1, +static const u16 cf_axi_dds_q_data[] = { 0x0000, 0x10a1, 0x3e31, 0x7cdb, 0xbc55, 0xec22, 0xffd7, 0xf253, 0xc71b, @@ -641,524 +565,72 @@ static u32 cf_axi_dds_ib_data[] = { 0x8c8b, 0xc9b3, 0xf3b4, 0xffa5, 0xea6c, 0xb98b, 0x79b7, 0x3b85, 0x0f1d, - 0x000a, 0x1236, 0x40e8 + 0x000a, 0x1236, 0x40e8, + 0x7fff, 0xbf16, 0xedc8, + 0xfff4, 0xf0e1, 0xc479, + 0x8647, 0x4673, 0x1592, + 0x0059, 0x0c4a, 0x364b, + 0x7373, 0xb3de, 0xe6ce, + 0xff08, 0xf640, 0xcebe, + 0x92c7, 0x51ee, 0x1d0e, + 0x01e2, 0x077b, 0x2c64, + 0x6706, 0xa825, 0xded6, + 0xfce2, 0xfa7b, 0xd841, + 0x9f19, 0x5ddc, 0x257d, + 0x04a3, 0x03d6, 0x234c, + 0x5ad7, 0x9c0a, 0xd5f4, + 0xf988, 0xfd88, 0xe0ea, + 0xab1e, 0x6a1d, 0x2ecc, + 0x0894, 0x0163, 0x1b17, + 0x4f04, 0x8faa, 0xcc3e, + 0xf503, 0xff60, 0xe8a5, + 0xb6b9, 0x7695, 0x38e3, + 0x0dab, 0x0027, 0x13dc, + 0x43a9, 0x8323, 0xc1cd, + 0xef5d, 0xfffe, 0xef5d, + 0xc1cd, 0x8323, 0x43a9, + 0x13dc, 0x0027, 0x0dab, + 0x38e3, 0x7695, 0xb6b9, + 0xe8a5, 0xff60, 0xf503, + 0xcc3e, 0x8faa, 0x4f04, + 0x1b17, 0x0163, 0x0894, + 0x2ecc, 0x6a1d, 0xab1e, + 0xe0ea, 0xfd88, 0xf988, + 0xd5f4, 0x9c0a, 0x5ad7, + 0x234c, 0x03d6, 0x04a3, + 0x257d, 0x5ddc, 0x9f19, + 0xd841, 0xfa7b, 0xfce2, + 0xded6, 0xa825, 0x6706, + 0x2c64, 0x077b, 0x01e2, + 0x1d0e, 0x51ee, 0x92c7, + 0xcebe, 0xf640, 0xff08, + 0xe6ce, 0xb3de, 0x7373, + 0x364b, 0x0c4a, 0x0059, + 0x1592, 0x4673, 0x8647, + 0xc479, 0xf0e1, 0xfff4, + 0xedc8, 0xbf16, 0x7fff, + 0x40e8, 0x1236, 0x000a, + 0x0f1d, 0x3b85, 0x79b7, + 0xb98b, 0xea6c, 0xffa5, + 0xf3b4, 0xc9b3, 0x8c8b, + 0x4c20, 0x1930, 0x00f6, + 0x09be, 0x3140, 0x6d37, + 0xae10, 0xe2f0, 0xfe1c, + 0xf883, 0xd39a, 0x98f8, + 0x57d9, 0x2128, 0x031c, + 0x0583, 0x27bd, 0x60e5, + 0xa222, 0xda81, 0xfb5b, + 0xfc28, 0xdcb2, 0xa527, + 0x63f4, 0x2a0a, 0x0676, + 0x0276, 0x1f14, 0x54e0, + 0x95e1, 0xd132, 0xf76a, + 0xfe9b, 0xe4e7, 0xb0fa, + 0x7054, 0x33c0, 0x0afb, + 0x009e, 0x1759, 0x4945, + 0x8969, 0xc71b, 0xf253, + 0xffd7, 0xec22, 0xbc55, + 0x7cdb, 0x3e31, 0x10a1 }; -static u32 cf_axi_dds_qa_data[] = { - 0x0000, 0x10a1, 0x3e31, - 0x7cdb, 0xbc55, 0xec22, - 0xffd7, 0xf253, 0xc71b, - 0x8969, 0x4945, 0x1759, - 0x009e, 0x0afb, 0x33c0, - 0x7054, 0xb0fa, 0xe4e7, - 0xfe9b, 0xf76a, 0xd132, - 0x95e1, 0x54e0, 0x1f14, - 0x0276, 0x0676, 0x2a0a, - 0x63f4, 0xa527, 0xdcb2, - 0xfc28, 0xfb5b, 0xda81, - 0xa222, 0x60e5, 0x27bd, - 0x0583, 0x031c, 0x2128, - 0x57d9, 0x98f8, 0xd39a, - 0xf883, 0xfe1c, 0xe2f0, - 0xae10, 0x6d37, 0x3140, - 0x09be, 0x00f6, 0x1930, - 0x4c20, 0x8c8b, 0xc9b3, - 0xf3b4, 0xffa5, 0xea6c, - 0xb98b, 0x79b7, 0x3b85, - 0x0f1d, 0x000a, 0x1236, - 0x40e8, 0x7fff, 0xbf16, - 0xedc8, 0xfff4, 0xf0e1, - 0xc479, 0x8647, 0x4673, - 0x1592, 0x0059, 0x0c4a, - 0x364b, 0x7373, 0xb3de, - 0xe6ce, 0xff08, 0xf640, - 0xcebe, 0x92c7, 0x51ee, - 0x1d0e, 0x01e2, 0x077b, - 0x2c64, 0x6706, 0xa825, - 0xded6, 0xfce2, 0xfa7b, - 0xd841, 0x9f19, 0x5ddc, - 0x257d, 0x04a3, 0x03d6, - 0x234c, 0x5ad7, 0x9c0a, - 0xd5f4, 0xf988, 0xfd88, - 0xe0ea, 0xab1e, 0x6a1d, - 0x2ecc, 0x0894, 0x0163, - 0x1b17, 0x4f04, 0x8faa, - 0xcc3e, 0xf503, 0xff60, - 0xe8a5, 0xb6b9, 0x7695, - 0x38e3, 0x0dab, 0x0027, - 0x13dc, 0x43a9, 0x8323, - 0xc1cd, 0xef5d, 0xfffe, - 0xef5d, 0xc1cd, 0x8323, - 0x43a9, 0x13dc, 0x0027, - 0x0dab, 0x38e3, 0x7695, - 0xb6b9, 0xe8a5, 0xff60, - 0xf503, 0xcc3e, 0x8faa, - 0x4f04, 0x1b17, 0x0163, - 0x0894, 0x2ecc, 0x6a1d, - 0xab1e, 0xe0ea, 0xfd88, - 0xf988, 0xd5f4, 0x9c0a, - 0x5ad7, 0x234c, 0x03d6, - 0x04a3, 0x257d, 0x5ddc, - 0x9f19, 0xd841, 0xfa7b, - 0xfce2, 0xded6, 0xa825, - 0x6706, 0x2c64, 0x077b, - 0x01e2, 0x1d0e, 0x51ee, - 0x92c7, 0xcebe, 0xf640, - 0xff08, 0xe6ce, 0xb3de, - 0x7373, 0x364b, 0x0c4a, - 0x0059, 0x1592, 0x4673, - 0x8647, 0xc479, 0xf0e1, - 0xfff4, 0xedc8, 0xbf16, - 0x7fff, 0x40e8, 0x1236, - 0x000a, 0x0f1d, 0x3b85, - 0x79b7, 0xb98b, 0xea6c, - 0xffa5, 0xf3b4, 0xc9b3, - 0x8c8b, 0x4c20, 0x1930, - 0x00f6, 0x09be, 0x3140, - 0x6d37, 0xae10, 0xe2f0, - 0xfe1c, 0xf883, 0xd39a, - 0x98f8, 0x57d9, 0x2128, - 0x031c, 0x0583, 0x27bd, - 0x60e5, 0xa222, 0xda81, - 0xfb5b, 0xfc28, 0xdcb2, - 0xa527, 0x63f4, 0x2a0a, - 0x0676, 0x0276, 0x1f14, - 0x54e0, 0x95e1, 0xd132, - 0xf76a, 0xfe9b, 0xe4e7, - 0xb0fa, 0x7054, 0x33c0, - 0x0afb, 0x009e, 0x1759, - 0x4945, 0x8969, 0xc71b, - 0xf253, 0xffd7, 0xec22, - 0xbc55, 0x7cdb, 0x3e31, - 0x10a1, 0x0000, 0x10a1, - 0x3e31, 0x7cdb, 0xbc55, - 0xec22, 0xffd7, 0xf253, - 0xc71b, 0x8969, 0x4945, - 0x1759, 0x009e, 0x0afb, - 0x33c0, 0x7054, 0xb0fa, - 0xe4e7, 0xfe9b, 0xf76a, - 0xd132, 0x95e1, 0x54e0, - 0x1f14, 0x0276, 0x0676, - 0x2a0a, 0x63f4, 0xa527, - 0xdcb2, 0xfc28, 0xfb5b, - 0xda81, 0xa222, 0x60e5, - 0x27bd, 0x0583, 0x031c, - 0x2128, 0x57d9, 0x98f8, - 0xd39a, 0xf883, 0xfe1c, - 0xe2f0, 0xae10, 0x6d37, - 0x3140, 0x09be, 0x00f6, - 0x1930, 0x4c20, 0x8c8b, - 0xc9b3, 0xf3b4, 0xffa5, - 0xea6c, 0xb98b, 0x79b7, - 0x3b85, 0x0f1d, 0x000a, - 0x1236, 0x40e8, 0x7fff, - 0xbf16, 0xedc8, 0xfff4, - 0xf0e1, 0xc479, 0x8647, - 0x4673, 0x1592, 0x0059, - 0x0c4a, 0x364b, 0x7373, - 0xb3de, 0xe6ce, 0xff08, - 0xf640, 0xcebe, 0x92c7, - 0x51ee, 0x1d0e, 0x01e2, - 0x077b, 0x2c64, 0x6706, - 0xa825, 0xded6, 0xfce2, - 0xfa7b, 0xd841, 0x9f19, - 0x5ddc, 0x257d, 0x04a3, - 0x03d6, 0x234c, 0x5ad7, - 0x9c0a, 0xd5f4, 0xf988, - 0xfd88, 0xe0ea, 0xab1e, - 0x6a1d, 0x2ecc, 0x0894, - 0x0163, 0x1b17, 0x4f04, - 0x8faa, 0xcc3e, 0xf503, - 0xff60, 0xe8a5, 0xb6b9, - 0x7695, 0x38e3, 0x0dab, - 0x0027, 0x13dc, 0x43a9, - 0x8323, 0xc1cd, 0xef5d, - 0xfffe, 0xef5d, 0xc1cd, - 0x8323, 0x43a9, 0x13dc, - 0x0027, 0x0dab, 0x38e3, - 0x7695, 0xb6b9, 0xe8a5, - 0xff60, 0xf503, 0xcc3e, - 0x8faa, 0x4f04, 0x1b17, - 0x0163, 0x0894, 0x2ecc, - 0x6a1d, 0xab1e, 0xe0ea, - 0xfd88, 0xf988, 0xd5f4, - 0x9c0a, 0x5ad7, 0x234c, - 0x03d6, 0x04a3, 0x257d, - 0x5ddc, 0x9f19, 0xd841, - 0xfa7b, 0xfce2, 0xded6, - 0xa825, 0x6706, 0x2c64, - 0x077b, 0x01e2, 0x1d0e, - 0x51ee, 0x92c7, 0xcebe, - 0xf640, 0xff08, 0xe6ce, - 0xb3de, 0x7373, 0x364b, - 0x0c4a, 0x0059, 0x1592, - 0x4673, 0x8647, 0xc479, - 0xf0e1, 0xfff4, 0xedc8, - 0xbf16, 0x7fff, 0x40e8, - 0x1236, 0x000a, 0x0f1d, - 0x3b85, 0x79b7, 0xb98b, - 0xea6c, 0xffa5, 0xf3b4, - 0xc9b3, 0x8c8b, 0x4c20, - 0x1930, 0x00f6, 0x09be, - 0x3140, 0x6d37, 0xae10, - 0xe2f0, 0xfe1c, 0xf883, - 0xd39a, 0x98f8, 0x57d9, - 0x2128, 0x031c, 0x0583, - 0x27bd, 0x60e5, 0xa222, - 0xda81, 0xfb5b, 0xfc28, - 0xdcb2, 0xa527, 0x63f4, - 0x2a0a, 0x0676, 0x0276, - 0x1f14, 0x54e0, 0x95e1, - 0xd132, 0xf76a, 0xfe9b, - 0xe4e7, 0xb0fa, 0x7054, - 0x33c0, 0x0afb, 0x009e, - 0x1759, 0x4945, 0x8969, - 0xc71b, 0xf253, 0xffd7, - 0xec22, 0xbc55, 0x7cdb, - 0x3e31, 0x10a1, 0x0000, - 0x10a1, 0x3e31, 0x7cdb, - 0xbc55, 0xec22, 0xffd7, - 0xf253, 0xc71b, 0x8969, - 0x4945, 0x1759, 0x009e, - 0x0afb, 0x33c0, 0x7054, - 0xb0fa, 0xe4e7, 0xfe9b, - 0xf76a, 0xd132, 0x95e1, - 0x54e0, 0x1f14, 0x0276, - 0x0676, 0x2a0a, 0x63f4, - 0xa527, 0xdcb2, 0xfc28, - 0xfb5b, 0xda81, 0xa222, - 0x60e5, 0x27bd, 0x0583, - 0x031c, 0x2128, 0x57d9, - 0x98f8, 0xd39a, 0xf883, - 0xfe1c, 0xe2f0, 0xae10, - 0x6d37, 0x3140, 0x09be, - 0x00f6, 0x1930, 0x4c20, - 0x8c8b, 0xc9b3, 0xf3b4, - 0xffa5, 0xea6c, 0xb98b, - 0x79b7, 0x3b85, 0x0f1d, - 0x000a, 0x1236, 0x40e8, - 0x7fff, 0xbf16, 0xedc8, - 0xfff4, 0xf0e1, 0xc479, - 0x8647, 0x4673, 0x1592, - 0x0059, 0x0c4a, 0x364b, - 0x7373, 0xb3de, 0xe6ce, - 0xff08, 0xf640, 0xcebe, - 0x92c7, 0x51ee, 0x1d0e, - 0x01e2, 0x077b, 0x2c64, - 0x6706, 0xa825, 0xded6, - 0xfce2, 0xfa7b, 0xd841, - 0x9f19, 0x5ddc, 0x257d, - 0x04a3, 0x03d6, 0x234c, - 0x5ad7, 0x9c0a, 0xd5f4, - 0xf988, 0xfd88, 0xe0ea, - 0xab1e, 0x6a1d, 0x2ecc, - 0x0894, 0x0163, 0x1b17, - 0x4f04, 0x8faa, 0xcc3e, - 0xf503, 0xff60, 0xe8a5, - 0xb6b9, 0x7695, 0x38e3, - 0x0dab, 0x0027, 0x13dc, - 0x43a9, 0x8323, 0xc1cd, - 0xef5d, 0xfffe, 0xef5d, - 0xc1cd, 0x8323, 0x43a9, - 0x13dc, 0x0027, 0x0dab, - 0x38e3, 0x7695, 0xb6b9, - 0xe8a5, 0xff60, 0xf503, - 0xcc3e, 0x8faa, 0x4f04, - 0x1b17, 0x0163, 0x0894, - 0x2ecc, 0x6a1d, 0xab1e, - 0xe0ea, 0xfd88, 0xf988, - 0xd5f4, 0x9c0a, 0x5ad7, - 0x234c, 0x03d6, 0x04a3, - 0x257d, 0x5ddc, 0x9f19, - 0xd841, 0xfa7b, 0xfce2, - 0xded6, 0xa825, 0x6706, - 0x2c64, 0x077b, 0x01e2, - 0x1d0e, 0x51ee, 0x92c7, - 0xcebe, 0xf640, 0xff08, - 0xe6ce, 0xb3de, 0x7373, - 0x364b, 0x0c4a, 0x0059, - 0x1592, 0x4673, 0x8647, - 0xc479, 0xf0e1, 0xfff4, - 0xedc8, 0xbf16, 0x7fff, - 0x40e8, 0x1236, 0x000a, - 0x0f1d, 0x3b85, 0x79b7, - 0xb98b, 0xea6c, 0xffa5, - 0xf3b4, 0xc9b3, 0x8c8b, - 0x4c20, 0x1930, 0x00f6, - 0x09be, 0x3140, 0x6d37, - 0xae10, 0xe2f0, 0xfe1c, - 0xf883, 0xd39a, 0x98f8, - 0x57d9, 0x2128, 0x031c, - 0x0583, 0x27bd, 0x60e5, - 0xa222, 0xda81, 0xfb5b, - 0xfc28, 0xdcb2, 0xa527, - 0x63f4, 0x2a0a, 0x0676, - 0x0276, 0x1f14, 0x54e0, - 0x95e1, 0xd132, 0xf76a, - 0xfe9b, 0xe4e7, 0xb0fa, - 0x7054, 0x33c0, 0x0afb, - 0x009e, 0x1759, 0x4945, - 0x8969, 0xc71b, 0xf253, - 0xffd7, 0xec22, 0xbc55, - 0x7cdb, 0x3e31, 0x10a1 -}; - -static u32 cf_axi_dds_qb_data[] = { - 0x0000, 0x10a1, 0x3e31, - 0x7cdb, 0xbc55, 0xec22, - 0xffd7, 0xf253, 0xc71b, - 0x8969, 0x4945, 0x1759, - 0x009e, 0x0afb, 0x33c0, - 0x7054, 0xb0fa, 0xe4e7, - 0xfe9b, 0xf76a, 0xd132, - 0x95e1, 0x54e0, 0x1f14, - 0x0276, 0x0676, 0x2a0a, - 0x63f4, 0xa527, 0xdcb2, - 0xfc28, 0xfb5b, 0xda81, - 0xa222, 0x60e5, 0x27bd, - 0x0583, 0x031c, 0x2128, - 0x57d9, 0x98f8, 0xd39a, - 0xf883, 0xfe1c, 0xe2f0, - 0xae10, 0x6d37, 0x3140, - 0x09be, 0x00f6, 0x1930, - 0x4c20, 0x8c8b, 0xc9b3, - 0xf3b4, 0xffa5, 0xea6c, - 0xb98b, 0x79b7, 0x3b85, - 0x0f1d, 0x000a, 0x1236, - 0x40e8, 0x7fff, 0xbf16, - 0xedc8, 0xfff4, 0xf0e1, - 0xc479, 0x8647, 0x4673, - 0x1592, 0x0059, 0x0c4a, - 0x364b, 0x7373, 0xb3de, - 0xe6ce, 0xff08, 0xf640, - 0xcebe, 0x92c7, 0x51ee, - 0x1d0e, 0x01e2, 0x077b, - 0x2c64, 0x6706, 0xa825, - 0xded6, 0xfce2, 0xfa7b, - 0xd841, 0x9f19, 0x5ddc, - 0x257d, 0x04a3, 0x03d6, - 0x234c, 0x5ad7, 0x9c0a, - 0xd5f4, 0xf988, 0xfd88, - 0xe0ea, 0xab1e, 0x6a1d, - 0x2ecc, 0x0894, 0x0163, - 0x1b17, 0x4f04, 0x8faa, - 0xcc3e, 0xf503, 0xff60, - 0xe8a5, 0xb6b9, 0x7695, - 0x38e3, 0x0dab, 0x0027, - 0x13dc, 0x43a9, 0x8323, - 0xc1cd, 0xef5d, 0xfffe, - 0xef5d, 0xc1cd, 0x8323, - 0x43a9, 0x13dc, 0x0027, - 0x0dab, 0x38e3, 0x7695, - 0xb6b9, 0xe8a5, 0xff60, - 0xf503, 0xcc3e, 0x8faa, - 0x4f04, 0x1b17, 0x0163, - 0x0894, 0x2ecc, 0x6a1d, - 0xab1e, 0xe0ea, 0xfd88, - 0xf988, 0xd5f4, 0x9c0a, - 0x5ad7, 0x234c, 0x03d6, - 0x04a3, 0x257d, 0x5ddc, - 0x9f19, 0xd841, 0xfa7b, - 0xfce2, 0xded6, 0xa825, - 0x6706, 0x2c64, 0x077b, - 0x01e2, 0x1d0e, 0x51ee, - 0x92c7, 0xcebe, 0xf640, - 0xff08, 0xe6ce, 0xb3de, - 0x7373, 0x364b, 0x0c4a, - 0x0059, 0x1592, 0x4673, - 0x8647, 0xc479, 0xf0e1, - 0xfff4, 0xedc8, 0xbf16, - 0x7fff, 0x40e8, 0x1236, - 0x000a, 0x0f1d, 0x3b85, - 0x79b7, 0xb98b, 0xea6c, - 0xffa5, 0xf3b4, 0xc9b3, - 0x8c8b, 0x4c20, 0x1930, - 0x00f6, 0x09be, 0x3140, - 0x6d37, 0xae10, 0xe2f0, - 0xfe1c, 0xf883, 0xd39a, - 0x98f8, 0x57d9, 0x2128, - 0x031c, 0x0583, 0x27bd, - 0x60e5, 0xa222, 0xda81, - 0xfb5b, 0xfc28, 0xdcb2, - 0xa527, 0x63f4, 0x2a0a, - 0x0676, 0x0276, 0x1f14, - 0x54e0, 0x95e1, 0xd132, - 0xf76a, 0xfe9b, 0xe4e7, - 0xb0fa, 0x7054, 0x33c0, - 0x0afb, 0x009e, 0x1759, - 0x4945, 0x8969, 0xc71b, - 0xf253, 0xffd7, 0xec22, - 0xbc55, 0x7cdb, 0x3e31, - 0x10a1, 0x0000, 0x10a1, - 0x3e31, 0x7cdb, 0xbc55, - 0xec22, 0xffd7, 0xf253, - 0xc71b, 0x8969, 0x4945, - 0x1759, 0x009e, 0x0afb, - 0x33c0, 0x7054, 0xb0fa, - 0xe4e7, 0xfe9b, 0xf76a, - 0xd132, 0x95e1, 0x54e0, - 0x1f14, 0x0276, 0x0676, - 0x2a0a, 0x63f4, 0xa527, - 0xdcb2, 0xfc28, 0xfb5b, - 0xda81, 0xa222, 0x60e5, - 0x27bd, 0x0583, 0x031c, - 0x2128, 0x57d9, 0x98f8, - 0xd39a, 0xf883, 0xfe1c, - 0xe2f0, 0xae10, 0x6d37, - 0x3140, 0x09be, 0x00f6, - 0x1930, 0x4c20, 0x8c8b, - 0xc9b3, 0xf3b4, 0xffa5, - 0xea6c, 0xb98b, 0x79b7, - 0x3b85, 0x0f1d, 0x000a, - 0x1236, 0x40e8, 0x7fff, - 0xbf16, 0xedc8, 0xfff4, - 0xf0e1, 0xc479, 0x8647, - 0x4673, 0x1592, 0x0059, - 0x0c4a, 0x364b, 0x7373, - 0xb3de, 0xe6ce, 0xff08, - 0xf640, 0xcebe, 0x92c7, - 0x51ee, 0x1d0e, 0x01e2, - 0x077b, 0x2c64, 0x6706, - 0xa825, 0xded6, 0xfce2, - 0xfa7b, 0xd841, 0x9f19, - 0x5ddc, 0x257d, 0x04a3, - 0x03d6, 0x234c, 0x5ad7, - 0x9c0a, 0xd5f4, 0xf988, - 0xfd88, 0xe0ea, 0xab1e, - 0x6a1d, 0x2ecc, 0x0894, - 0x0163, 0x1b17, 0x4f04, - 0x8faa, 0xcc3e, 0xf503, - 0xff60, 0xe8a5, 0xb6b9, - 0x7695, 0x38e3, 0x0dab, - 0x0027, 0x13dc, 0x43a9, - 0x8323, 0xc1cd, 0xef5d, - 0xfffe, 0xef5d, 0xc1cd, - 0x8323, 0x43a9, 0x13dc, - 0x0027, 0x0dab, 0x38e3, - 0x7695, 0xb6b9, 0xe8a5, - 0xff60, 0xf503, 0xcc3e, - 0x8faa, 0x4f04, 0x1b17, - 0x0163, 0x0894, 0x2ecc, - 0x6a1d, 0xab1e, 0xe0ea, - 0xfd88, 0xf988, 0xd5f4, - 0x9c0a, 0x5ad7, 0x234c, - 0x03d6, 0x04a3, 0x257d, - 0x5ddc, 0x9f19, 0xd841, - 0xfa7b, 0xfce2, 0xded6, - 0xa825, 0x6706, 0x2c64, - 0x077b, 0x01e2, 0x1d0e, - 0x51ee, 0x92c7, 0xcebe, - 0xf640, 0xff08, 0xe6ce, - 0xb3de, 0x7373, 0x364b, - 0x0c4a, 0x0059, 0x1592, - 0x4673, 0x8647, 0xc479, - 0xf0e1, 0xfff4, 0xedc8, - 0xbf16, 0x7fff, 0x40e8, - 0x1236, 0x000a, 0x0f1d, - 0x3b85, 0x79b7, 0xb98b, - 0xea6c, 0xffa5, 0xf3b4, - 0xc9b3, 0x8c8b, 0x4c20, - 0x1930, 0x00f6, 0x09be, - 0x3140, 0x6d37, 0xae10, - 0xe2f0, 0xfe1c, 0xf883, - 0xd39a, 0x98f8, 0x57d9, - 0x2128, 0x031c, 0x0583, - 0x27bd, 0x60e5, 0xa222, - 0xda81, 0xfb5b, 0xfc28, - 0xdcb2, 0xa527, 0x63f4, - 0x2a0a, 0x0676, 0x0276, - 0x1f14, 0x54e0, 0x95e1, - 0xd132, 0xf76a, 0xfe9b, - 0xe4e7, 0xb0fa, 0x7054, - 0x33c0, 0x0afb, 0x009e, - 0x1759, 0x4945, 0x8969, - 0xc71b, 0xf253, 0xffd7, - 0xec22, 0xbc55, 0x7cdb, - 0x3e31, 0x10a1, 0x0000, - 0x10a1, 0x3e31, 0x7cdb, - 0xbc55, 0xec22, 0xffd7, - 0xf253, 0xc71b, 0x8969, - 0x4945, 0x1759, 0x009e, - 0x0afb, 0x33c0, 0x7054, - 0xb0fa, 0xe4e7, 0xfe9b, - 0xf76a, 0xd132, 0x95e1, - 0x54e0, 0x1f14, 0x0276, - 0x0676, 0x2a0a, 0x63f4, - 0xa527, 0xdcb2, 0xfc28, - 0xfb5b, 0xda81, 0xa222, - 0x60e5, 0x27bd, 0x0583, - 0x031c, 0x2128, 0x57d9, - 0x98f8, 0xd39a, 0xf883, - 0xfe1c, 0xe2f0, 0xae10, - 0x6d37, 0x3140, 0x09be, - 0x00f6, 0x1930, 0x4c20, - 0x8c8b, 0xc9b3, 0xf3b4, - 0xffa5, 0xea6c, 0xb98b, - 0x79b7, 0x3b85, 0x0f1d, - 0x000a, 0x1236, 0x40e8, - 0x7fff, 0xbf16, 0xedc8, - 0xfff4, 0xf0e1, 0xc479, - 0x8647, 0x4673, 0x1592, - 0x0059, 0x0c4a, 0x364b, - 0x7373, 0xb3de, 0xe6ce, - 0xff08, 0xf640, 0xcebe, - 0x92c7, 0x51ee, 0x1d0e, - 0x01e2, 0x077b, 0x2c64, - 0x6706, 0xa825, 0xded6, - 0xfce2, 0xfa7b, 0xd841, - 0x9f19, 0x5ddc, 0x257d, - 0x04a3, 0x03d6, 0x234c, - 0x5ad7, 0x9c0a, 0xd5f4, - 0xf988, 0xfd88, 0xe0ea, - 0xab1e, 0x6a1d, 0x2ecc, - 0x0894, 0x0163, 0x1b17, - 0x4f04, 0x8faa, 0xcc3e, - 0xf503, 0xff60, 0xe8a5, - 0xb6b9, 0x7695, 0x38e3, - 0x0dab, 0x0027, 0x13dc, - 0x43a9, 0x8323, 0xc1cd, - 0xef5d, 0xfffe, 0xef5d, - 0xc1cd, 0x8323, 0x43a9, - 0x13dc, 0x0027, 0x0dab, - 0x38e3, 0x7695, 0xb6b9, - 0xe8a5, 0xff60, 0xf503, - 0xcc3e, 0x8faa, 0x4f04, - 0x1b17, 0x0163, 0x0894, - 0x2ecc, 0x6a1d, 0xab1e, - 0xe0ea, 0xfd88, 0xf988, - 0xd5f4, 0x9c0a, 0x5ad7, - 0x234c, 0x03d6, 0x04a3, - 0x257d, 0x5ddc, 0x9f19, - 0xd841, 0xfa7b, 0xfce2, - 0xded6, 0xa825, 0x6706, - 0x2c64, 0x077b, 0x01e2, - 0x1d0e, 0x51ee, 0x92c7, - 0xcebe, 0xf640, 0xff08, - 0xe6ce, 0xb3de, 0x7373, - 0x364b, 0x0c4a, 0x0059, - 0x1592, 0x4673, 0x8647, - 0xc479, 0xf0e1, 0xfff4, - 0xedc8, 0xbf16, 0x7fff, - 0x40e8, 0x1236, 0x000a, - 0x0f1d, 0x3b85, 0x79b7, - 0xb98b, 0xea6c, 0xffa5, - 0xf3b4, 0xc9b3, 0x8c8b, - 0x4c20, 0x1930, 0x00f6, - 0x09be, 0x3140, 0x6d37, - 0xae10, 0xe2f0, 0xfe1c, - 0xf883, 0xd39a, 0x98f8, - 0x57d9, 0x2128, 0x031c, - 0x0583, 0x27bd, 0x60e5, - 0xa222, 0xda81, 0xfb5b, - 0xfc28, 0xdcb2, 0xa527, - 0x63f4, 0x2a0a, 0x0676, - 0x0276, 0x1f14, 0x54e0, - 0x95e1, 0xd132, 0xf76a, - 0xfe9b, 0xe4e7, 0xb0fa, - 0x7054, 0x33c0, 0x0afb, - 0x009e, 0x1759, 0x4945, - 0x8969, 0xc71b, 0xf253, - 0xffd7, 0xec22, 0xbc55, - 0x7cdb, 0x3e31, 0x10a1 -}; #endif /* CF_AXI_DDS_WAVDATA */ +#endif /* ADI_AXI_DDS_H_ */ diff --git a/drivers/iio/frequency/cf_axi_dds_buffer.c b/drivers/iio/frequency/cf_axi_dds_buffer.c new file mode 100644 index 0000000000000..8adc085df819e --- /dev/null +++ b/drivers/iio/frequency/cf_axi_dds_buffer.c @@ -0,0 +1,249 @@ +/* + * DDS PCORE/COREFPGA Module + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "../../staging/iio/ring_hw.h" +#include "cf_axi_dds.h" + +#define VDMA_MAX_HSIZE 0xFFFF +#define VDMA_MAX_VSIZE 0xFFF + + +static int __cf_axi_dds_hw_buffer_state_set(struct iio_dev *indio_dev, bool state); + +static int cf_axi_dds_write_buffer(struct iio_buffer *r, + size_t count, const char __user *buf) +{ + struct iio_hw_buffer *hw_buffer = iio_to_hw_buf(r); + struct iio_dev *indio_dev = hw_buffer->private; + struct cf_axi_dds_state *st = iio_priv(indio_dev); + int ret = 0; + + if (PAGE_ALIGN(count) > AXIDDS_MAX_DMA_SIZE || count % 8) { + ret = -EINVAL; + goto error_ret; + } + + mutex_lock(&indio_dev->mlock); + + if (copy_from_user (st->buf_virt, buf, count)) + ret = -EFAULT; + + st->txcount = count; + st->buffer_lenght = count / 4; + + if (iio_buffer_enabled(indio_dev)) { + dmaengine_terminate_all(st->tx_chan); + __cf_axi_dds_hw_buffer_state_set(indio_dev, 1); + } + + mutex_unlock(&indio_dev->mlock); + +error_ret: + + return ret < 0 ? ret : count; +} + +static int cf_axi_dds_buffer_get_length(struct iio_buffer *r) +{ + struct iio_hw_buffer *hw_buffer = iio_to_hw_buf(r); + struct iio_dev *indio_dev = hw_buffer->private; + struct cf_axi_dds_state *st = iio_priv(indio_dev); + + return st->buffer_lenght; +} + +static int cf_axi_dds_buffer_set_length(struct iio_buffer *r, int lenght) +{ + struct iio_hw_buffer *hw_buffer = iio_to_hw_buf(r); + struct cf_axi_dds_state *st = iio_priv(hw_buffer->private); + + st->buffer_lenght = lenght; + + return 0; +} + +static int cf_axi_dds_buffer_get_bytes_per_datum(struct iio_buffer *r) +{ + return r->bytes_per_datum; +} + +static IIO_BUFFER_ENABLE_ATTR; +static IIO_BUFFER_LENGTH_ATTR; + +static struct attribute *cf_axi_dds_buffer_attributes[] = { + &dev_attr_length.attr, + &dev_attr_enable.attr, + NULL, +}; + +static struct attribute_group cf_axi_dds_buffer_attr = { + .attrs = cf_axi_dds_buffer_attributes, + .name = "buffer", +}; + +static struct iio_buffer *cf_axi_dds_rb_allocate(struct iio_dev *indio_dev) +{ + struct iio_buffer *buf; + struct iio_hw_buffer *ring; + + ring = kzalloc(sizeof *ring, GFP_KERNEL); + if (!ring) + return NULL; + + ring->private = indio_dev; + buf = &ring->buf; + buf->attrs = &cf_axi_dds_buffer_attr; + iio_buffer_init(buf); + + return buf; +} + +static inline void cf_axi_dds_rb_free(struct iio_buffer *r) +{ + kfree(iio_to_hw_buf(r)); +} + +static const struct iio_buffer_access_funcs cf_axi_dds_buffer_access_funcs = { + .write = &cf_axi_dds_write_buffer, + .get_length = &cf_axi_dds_buffer_get_length, + .set_length = &cf_axi_dds_buffer_set_length, + .get_bytes_per_datum = &cf_axi_dds_buffer_get_bytes_per_datum, +}; + +static int __cf_axi_dds_hw_buffer_state_set(struct iio_dev *indio_dev, bool state) +{ + struct cf_axi_dds_state *st = iio_priv(indio_dev); + struct dma_async_tx_descriptor *desc; + unsigned tmp_reg, x; + + tmp_reg = dds_read(st, CF_AXI_DDS_DMA_STAT); + if (tmp_reg & (CF_AXI_DDS_DMA_STAT_OVF | CF_AXI_DDS_DMA_STAT_UNF)) + dev_warn(indio_dev->dev.parent, "VDMA Status: %s %s\n", + (tmp_reg & CF_AXI_DDS_DMA_STAT_OVF) ? "overflow" : "", + (tmp_reg & CF_AXI_DDS_DMA_STAT_OVF) ? "underflow" : ""); + + tmp_reg = dds_read(st, CF_AXI_DDS_CTRL); + + if (!state) { + cf_axi_dds_stop(st); + tmp_reg = CF_AXI_DDS_CTRL_DATA_EN | CF_AXI_DDS_CTRL_DDS_CLK_EN_V2; + dds_write(st, CF_AXI_DDS_CTRL, tmp_reg); + dmaengine_terminate_all(st->tx_chan); + return 0; + } + + if (st->txcount == 0) { + return -EINVAL; + } + + tmp_reg = CF_AXI_DDS_CTRL_DDS_SEL | + CF_AXI_DDS_CTRL_DATA_EN | + CF_AXI_DDS_CTRL_DDS_CLK_EN_V2; + + + x = DIV_ROUND_UP(st->txcount, (VDMA_MAX_VSIZE + 1) * 8); + + do { + if (st->txcount % (x * 8)) + x++; + else + break; + } while (x <= 8192); + + if (x == 8192) { + return -EINVAL; + } + + cf_axi_dds_stop(st); + + st->dma_config.vsize = st->txcount / (x * 8); + st->dma_config.stride = st->dma_config.hsize = x * 8; + + dmaengine_device_control(st->tx_chan, DMA_SLAVE_CONFIG, + (unsigned long)&st->dma_config); + + desc = dmaengine_prep_slave_single(st->tx_chan, + st->buf_phys, + st->txcount, + DMA_MEM_TO_DEV, 0); + if (!desc) { + dev_err(indio_dev->dev.parent, "Failed to prepare DMA descriptor\n"); + return -ENOMEM; + } else { + dmaengine_submit(desc); + dma_async_issue_pending(st->tx_chan); + } + + dds_write(st, CF_AXI_DDS_CTRL, tmp_reg); + dds_write(st, CF_AXI_DDS_DMA_STAT, + CF_AXI_DDS_DMA_STAT_OVF | + CF_AXI_DDS_DMA_STAT_UNF); + + return 0; + +} + +static int cf_axi_dds_hw_buffer_preenable(struct iio_dev *indio_dev) +{ + return __cf_axi_dds_hw_buffer_state_set(indio_dev, 1); +} + +static int cf_axi_dds_hw_buffer_postdisable(struct iio_dev *indio_dev) +{ + return __cf_axi_dds_hw_buffer_state_set(indio_dev, 0); +} + +static const struct iio_buffer_setup_ops cf_axi_dds_buffer_setup_ops = { + .preenable = &cf_axi_dds_hw_buffer_preenable, + .postdisable = &cf_axi_dds_hw_buffer_postdisable, +}; + +int cf_axi_dds_configure_buffer(struct iio_dev *indio_dev) +{ + struct cf_axi_dds_state *st = iio_priv(indio_dev); + indio_dev->buffer = cf_axi_dds_rb_allocate(indio_dev); + if (indio_dev->buffer == NULL) + return -ENOMEM; + + indio_dev->modes |= INDIO_BUFFER_HARDWARE; + indio_dev->buffer->direction = IIO_BUFFER_DIRECTION_OUT; + indio_dev->buffer->access = &cf_axi_dds_buffer_access_funcs; + indio_dev->setup_ops = &cf_axi_dds_buffer_setup_ops; + + st->buf_virt = dma_alloc_coherent(indio_dev->dev.parent, + PAGE_ALIGN(AXIDDS_MAX_DMA_SIZE), &st->buf_phys, + GFP_KERNEL); + if (st->buf_virt == NULL) { + dev_err(indio_dev->dev.parent, + "Failed to allocate a dma memory\n"); + return -ENOMEM; + } + + return 0; +} + +void cf_axi_dds_unconfigure_buffer(struct iio_dev *indio_dev) +{ + struct cf_axi_dds_state *st = iio_priv(indio_dev); + + dma_free_coherent(indio_dev->dev.parent, PAGE_ALIGN(AXIDDS_MAX_DMA_SIZE), + st->buf_virt, st->buf_phys); + cf_axi_dds_rb_free(indio_dev->buffer); +} From 59349ef51f9f561ccf60a02cdb5234175cbe3d5f Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 18 Oct 2012 10:22:21 +0200 Subject: [PATCH 201/261] iio: adc: add support for Analog Devices AD9265 16-Bit, 125/105/80 MSPS ADC Signed-off-by: Michael Hennerich --- arch/microblaze/boot/dts/cf_ad9265_ml605.dts | 328 ++++ .../microblaze/configs/ml605_ad9265_defconfig | 1378 +++++++++++++++++ drivers/iio/adc/ad9467.c | 15 +- drivers/iio/adc/cf_axi_adc.h | 12 + drivers/iio/adc/cf_axi_adc_core.c | 94 +- 5 files changed, 1805 insertions(+), 22 deletions(-) create mode 100644 arch/microblaze/boot/dts/cf_ad9265_ml605.dts create mode 100644 arch/microblaze/configs/ml605_ad9265_defconfig diff --git a/arch/microblaze/boot/dts/cf_ad9265_ml605.dts b/arch/microblaze/boot/dts/cf_ad9265_ml605.dts new file mode 100644 index 0000000000000..b72c5c497dcc3 --- /dev/null +++ b/arch/microblaze/boot/dts/cf_ad9265_ml605.dts @@ -0,0 +1,328 @@ +/* + * Device Tree Generator version: 1.3 + * + * (C) Copyright 2007-2008 Xilinx, Inc. + * (C) Copyright 2007-2009 Michal Simek + * + * Michal SIMEK + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * CAUTION: This file is automatically generated by libgen. + * Version: Xilinx EDK 14.1 EDK_P.15xf + * + * XPS project directory: device-tree_bsp_0 + */ + +/dts-v1/; +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,microblaze"; + model = "testing"; + DDR3_SDRAM: memory@c0000000 { + device_type = "memory"; + reg = < 0xc0000000 0x20000000 >; + } ; + aliases { + ethernet0 = &Ethernet_Lite; + serial0 = &RS232_Uart_1; + } ; + chosen { + bootargs = "console=ttyS0 root=/dev/ram"; + } ; + cpus { + #address-cells = <1>; + #cpus = <0x1>; + #size-cells = <0>; + microblaze_0: cpu@0 { + clock-frequency = <100000000>; + compatible = "xlnx,microblaze-8.30.a"; + d-cache-baseaddr = <0xc0000000>; + d-cache-highaddr = <0xdfffffff>; + d-cache-line-size = <0x10>; + d-cache-size = <0x4000>; + device_type = "cpu"; + i-cache-baseaddr = <0xc0000000>; + i-cache-highaddr = <0xdfffffff>; + i-cache-line-size = <0x20>; + i-cache-size = <0x4000>; + model = "microblaze,8.30.a"; + reg = <0>; + timebase-frequency = <100000000>; + xlnx,addr-tag-bits = <0xf>; + xlnx,allow-dcache-wr = <0x1>; + xlnx,allow-icache-wr = <0x1>; + xlnx,area-optimized = <0x0>; + xlnx,avoid-primitives = <0x0>; + xlnx,branch-target-cache-size = <0x0>; + xlnx,cache-byte-size = <0x4000>; + xlnx,d-axi = <0x1>; + xlnx,d-lmb = <0x1>; + xlnx,d-plb = <0x0>; + xlnx,data-size = <0x20>; + xlnx,dcache-addr-tag = <0xf>; + xlnx,dcache-always-used = <0x1>; + xlnx,dcache-byte-size = <0x4000>; + xlnx,dcache-data-width = <0x0>; + xlnx,dcache-force-tag-lutram = <0x0>; + xlnx,dcache-interface = <0x0>; + xlnx,dcache-line-len = <0x4>; + xlnx,dcache-use-fsl = <0x0>; + xlnx,dcache-use-writeback = <0x0>; + xlnx,dcache-victims = <0x0>; + xlnx,debug-enabled = <0x1>; + xlnx,div-zero-exception = <0x1>; + xlnx,dynamic-bus-sizing = <0x1>; + xlnx,ecc-use-ce-exception = <0x0>; + xlnx,edge-is-positive = <0x1>; + xlnx,endianness = <0x1>; + xlnx,family = "virtex6"; + xlnx,fault-tolerant = <0x0>; + xlnx,fpu-exception = <0x0>; + xlnx,freq = <0x5f5e100>; + xlnx,fsl-data-size = <0x20>; + xlnx,fsl-exception = <0x0>; + xlnx,fsl-links = <0x0>; + xlnx,i-axi = <0x0>; + xlnx,i-lmb = <0x1>; + xlnx,i-plb = <0x0>; + xlnx,icache-always-used = <0x1>; + xlnx,icache-data-width = <0x0>; + xlnx,icache-force-tag-lutram = <0x0>; + xlnx,icache-interface = <0x0>; + xlnx,icache-line-len = <0x8>; + xlnx,icache-streams = <0x1>; + xlnx,icache-use-fsl = <0x0>; + xlnx,icache-victims = <0x8>; + xlnx,ill-opcode-exception = <0x1>; + xlnx,instance = "microblaze_0"; + xlnx,interconnect = <0x2>; + xlnx,interconnect-m-axi-dc-read-issuing = <0x2>; + xlnx,interconnect-m-axi-dc-write-issuing = <0x20>; + xlnx,interconnect-m-axi-dp-read-issuing = <0x1>; + xlnx,interconnect-m-axi-dp-write-issuing = <0x1>; + xlnx,interconnect-m-axi-ic-read-issuing = <0x8>; + xlnx,interconnect-m-axi-ip-read-issuing = <0x1>; + xlnx,interrupt-is-edge = <0x0>; + xlnx,lockstep-slave = <0x0>; + xlnx,mmu-dtlb-size = <0x4>; + xlnx,mmu-itlb-size = <0x2>; + xlnx,mmu-privileged-instr = <0x0>; + xlnx,mmu-tlb-access = <0x3>; + xlnx,mmu-zones = <0x2>; + xlnx,number-of-pc-brk = <0x1>; + xlnx,number-of-rd-addr-brk = <0x0>; + xlnx,number-of-wr-addr-brk = <0x0>; + xlnx,opcode-0x0-illegal = <0x1>; + xlnx,optimization = <0x0>; + xlnx,pc-width = <0x20>; + xlnx,pvr = <0x2>; + xlnx,pvr-user1 = <0x0>; + xlnx,pvr-user2 = <0x0>; + xlnx,reset-msr = <0x0>; + xlnx,sco = <0x0>; + xlnx,stream-interconnect = <0x0>; + xlnx,unaligned-exceptions = <0x1>; + xlnx,use-barrel = <0x1>; + xlnx,use-branch-target-cache = <0x0>; + xlnx,use-dcache = <0x1>; + xlnx,use-div = <0x1>; + xlnx,use-ext-brk = <0x1>; + xlnx,use-ext-nm-brk = <0x1>; + xlnx,use-extended-fsl-instr = <0x0>; + xlnx,use-fpu = <0x0>; + xlnx,use-hw-mul = <0x2>; + xlnx,use-icache = <0x1>; + xlnx,use-interrupt = <0x1>; + xlnx,use-mmu = <0x3>; + xlnx,use-msr-instr = <0x1>; + xlnx,use-pcmp-instr = <0x1>; + xlnx,use-reorder-instr = <0x1>; + xlnx,use-stack-protection = <0x0>; + } ; + } ; + axi4lite_0: axi@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,axi-interconnect-1.06.a", "simple-bus"; + ranges ; + Ethernet_Lite: ethernet@40e00000 { + compatible = "xlnx,axi-ethernetlite-1.01.b", "xlnx,xps-ethernetlite-1.00.a"; + device_type = "network"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 5 0 >; + local-mac-address = [ 00 0a 35 4d b4 00 ]; + phy-handle = <&phy0>; + reg = < 0x40e00000 0x10000 >; + xlnx,duplex = <0x1>; + xlnx,family = "virtex6"; + xlnx,include-global-buffers = <0x0>; + xlnx,include-internal-loopback = <0x0>; + xlnx,include-mdio = <0x1>; + xlnx,include-phy-constraints = <0x1>; + xlnx,instance = "Ethernet_Lite"; + xlnx,interconnect-s-axi-read-acceptance = <0x1>; + xlnx,interconnect-s-axi-write-acceptance = <0x1>; + xlnx,rx-ping-pong = <0x0>; + xlnx,s-axi-aclk-period-ps = <0x2710>; + xlnx,s-axi-id-width = <0x1>; + xlnx,s-axi-supports-narrow-burst = <0x0>; + xlnx,tx-ping-pong = <0x0>; + mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: phy@7 { + compatible = "marvell,88e1111"; + device_type = "ethernet-phy"; + reg = <7>; + } ; + } ; + } ; + RS232_Uart_1: serial@40600000 { + clock-frequency = <100000000>; + compatible = "xlnx,axi-uartlite-1.02.a", "xlnx,xps-uartlite-1.00.a"; + current-speed = <57600>; + device_type = "serial"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 6 0 >; + port-number = <0>; + reg = < 0x40600000 0x10000 >; + xlnx,baudrate = <0xe100>; + xlnx,data-bits = <0x8>; + xlnx,family = "virtex6"; + xlnx,instance = "RS232_Uart_1"; + xlnx,odd-parity = <0x1>; + xlnx,s-axi-aclk-freq-hz = <0x5f5e100>; + xlnx,use-parity = <0x0>; + } ; + axi_ad9265_0: cf-ad9265@73000000 { + compatible = "xlnx,axi-ad9265-1.00.a"; + reg = < 0x73000000 0x10000 >; + dma-request = <&axi_dma_0 0>; + spibus-connected = <&adc0_ad9265>; + xlnx,cf-buftype = <0x1>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "virtex6"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + axi_dma_0: axidma@41e00000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + ranges = < 0x41e00000 0x41e00000 0x10000 >; + reg = < 0x41e00000 0x10000 >; +// xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@41e00030 { + compatible = "xlnx,axi-dma-s2mm-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 3 2 >; + xlnx,datawidth = <0x40>; + xlnx,include-dre = <0x0>; + } ; + } ; + axi_gpio_0: gpio@40000000 { + compatible = "xlnx,axi-xlnx-lcd-1.00.a"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 1 2 >; + reg = < 0x40000000 0x10000 >; + xlnx,all-inputs = <0x0>; + xlnx,all-inputs-2 = <0x0>; + xlnx,dout-default = <0x0>; + xlnx,dout-default-2 = <0x0>; + xlnx,family = "virtex6"; + xlnx,gpio-width = <0x7>; + xlnx,gpio2-width = <0x20>; + xlnx,instance = "axi_gpio_0"; + xlnx,interrupt-present = <0x1>; + xlnx,is-dual = <0x0>; + xlnx,tri-default = <0xffffffff>; + xlnx,tri-default-2 = <0xffffffff>; + } ; + axi_iic_0: i2c@40800000 { + compatible = "xlnx,axi-iic-1.02.a", "xlnx,xps-iic-2.00.a"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 0 2 >; + reg = < 0x40800000 0x10000 >; + xlnx,family = "virtex6"; + xlnx,gpo-width = <0x1>; + xlnx,iic-freq = <0x186a0>; + xlnx,instance = "axi_iic_0"; + xlnx,s-axi-aclk-freq-hz = <0x5f5e100>; + xlnx,scl-inertial-delay = <0x5>; + xlnx,sda-inertial-delay = <0x5>; + xlnx,sda-level = <0x1>; + xlnx,ten-bit-adr = <0x0>; + } ; + axi_intc_0: interrupt-controller@41200000 { + #interrupt-cells = <0x2>; + compatible = "xlnx,axi-intc-1.02.a", "xlnx,xps-intc-1.00.a"; + interrupt-controller ; + reg = < 0x41200000 0x10000 >; + xlnx,kind-of-intr = <0x60>; + xlnx,num-intr-inputs = <0x7>; + } ; + axi_spi_0: spi@40a00000 { + compatible = "xlnx,axi-spi-1.02.a", "xlnx,xps-spi-2.00.a"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 2 2 >; + reg = < 0x40a00000 0x10000 >; + xlnx,family = "virtex6"; + xlnx,fifo-exist = <0x1>; + xlnx,instance = "axi_spi_0"; + xlnx,num-ss-bits = <0x2>; + xlnx,num-transfer-bits = <0x8>; + xlnx,sck-ratio = <0x20>; + adc0_ad9265: ad9265@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ad9265"; + reg = <0>; + spi-max-frequency = <10000000>; + }; + } ; + axi_timer_0: timer@41c00000 { + clock-frequency = <100000000>; + compatible = "xlnx,axi-timer-1.03.a", "xlnx,xps-timer-1.00.a"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 4 2 >; + reg = < 0x41c00000 0x10000 >; + xlnx,count-width = <0x20>; + xlnx,family = "virtex6"; + xlnx,gen0-assert = <0x1>; + xlnx,gen1-assert = <0x1>; + xlnx,instance = "axi_timer_0"; + xlnx,one-timer-only = <0x0>; + xlnx,trig0-assert = <0x1>; + xlnx,trig1-assert = <0x1>; + } ; + debug_module: debug@74800000 { + compatible = "xlnx,mdm-2.00.b"; + reg = < 0x74800000 0x10000 >; + xlnx,family = "virtex6"; + xlnx,interconnect = <0x2>; + xlnx,jtag-chain = <0x2>; + xlnx,mb-dbg-ports = <0x1>; + xlnx,use-uart = <0x1>; + } ; + } ; +} ; diff --git a/arch/microblaze/configs/ml605_ad9265_defconfig b/arch/microblaze/configs/ml605_ad9265_defconfig new file mode 100644 index 0000000000000..d291911e060fc --- /dev/null +++ b/arch/microblaze/configs/ml605_ad9265_defconfig @@ -0,0 +1,1378 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/microblaze 3.5.0-rc4 Kernel Configuration +# +CONFIG_MICROBLAZE=y +# CONFIG_SWAP is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ZONE_DMA=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_CSUM=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_IRQ_DOMAIN=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y + +# +# RCU Subsystem +# +CONFIG_TINY_RCU=y +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="rootfs.cpio.gz" +CONFIG_INITRAMFS_ROOT_UID=0 +CONFIG_INITRAMFS_ROOT_GID=0 +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +CONFIG_INITRAMFS_COMPRESSION_NONE=y +# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_API_DEBUG=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_BLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_FREEZER is not set + +# +# Platform options +# +# CONFIG_PLATFORM_GENERIC is not set +CONFIG_PLATFORM_ML605_ADIXCOMM=y +# CONFIG_PLATFORM_KC705_ADIXCOMM is not set +# CONFIG_ADIXCOMM_SYNC is not set +CONFIG_OPT_LIB_FUNCTION=y +# CONFIG_OPT_LIB_ASM is not set + +# +# Definitions for MICROBLAZE0 +# +CONFIG_KERNEL_BASE_ADDR=0xc0000000 +CONFIG_XILINX_MICROBLAZE0_FAMILY="virtex6" +CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1 +CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1 +CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1 +CONFIG_XILINX_MICROBLAZE0_USE_DIV=1 +CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL=2 +CONFIG_XILINX_MICROBLAZE0_USE_FPU=0 +CONFIG_XILINX_MICROBLAZE0_HW_VER="8.20.a" + +# +# Processor type and features +# +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_SCHED_HRTICK=y +CONFIG_MMU=y + +# +# Boot options +# +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyUL0,57600 root=/dev/ram" +CONFIG_CMDLINE_FORCE=y +# CONFIG_SECCOMP is not set + +# +# Advanced setup +# +CONFIG_ADVANCED_OPTIONS=y +# CONFIG_HIGHMEM is not set +CONFIG_LOWMEM_SIZE_BOOL=y +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_MANUAL_RESET_VECTOR=0x0 +CONFIG_KERNEL_START_BOOL=y +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE_BOOL=y +CONFIG_TASK_SIZE=0x80000000 +CONFIG_KERNEL_PAD=0x80000 +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_NEED_PER_CPU_KM=y +# CONFIG_CLEANCACHE is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Bus Options +# +# CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS is not set +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +# CONFIG_DNS_RESOLVER is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +CONFIG_BQL=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +CONFIG_GENERIC_CPU_DEVICES=y +# CONFIG_DMA_SHARED_BUFFER is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=y +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_GPIO_ADDR is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_LATCH_ADDR is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_DEVICE=y +CONFIG_OF_I2C=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +# CONFIG_PARPORT is not set + +# +# Misc devices +# +# CONFIG_AD525X_DPOT is not set +# CONFIG_ICS932S401 is not set +CONFIG_XLNX_LCD=y +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_MII is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set + +# +# CAIF transport drivers +# +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_INTEL=y +CONFIG_NET_VENDOR_I825XX=y +CONFIG_NET_VENDOR_MARVELL=y +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +CONFIG_NET_VENDOR_NATSEMI=y +CONFIG_NET_VENDOR_8390=y +# CONFIG_ETHOC is not set +CONFIG_NET_VENDOR_SEEQ=y +# CONFIG_SEEQ8005 is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_WIZNET=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +CONFIG_NET_VENDOR_XILINX=y +CONFIG_XILINX_EMACLITE=y +# CONFIG_XILINX_AXI_EMAC is not set +# CONFIG_XILINX_LL_TEMAC is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_AMD_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_WLAN=y +# CONFIG_HOSTAP is not set +# CONFIG_WL_TI is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_DW is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_UARTLITE=y +CONFIG_SERIAL_UARTLITE_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_TTY_PRINTK is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_XILINX_HWICAP is not set +# CONFIG_R3964 is not set + +# +# PCMCIA character devices +# +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_MUX is not set +# CONFIG_I2C_HELPER_AUTO is not set +# CONFIG_I2C_SMBUS is not set + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +CONFIG_I2C_XILINX=y + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=y +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_XCOMM is not set +CONFIG_SPI_XILINX=y +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_HSI is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_OF_GPIO=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +CONFIG_GPIO_XILINX=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_S5M_CORE is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_EXYNOS_VIDEO is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_SOUND is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB_ARCH_HAS_XHCI is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_RTC_CLASS is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_XILINX_DMA=y +# CONFIG_TIMB_DMA is not set +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_BALLOON is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_ECHO is not set +# CONFIG_RTLLIB is not set + +# +# IIO staging drivers +# +CONFIG_IIO_SW_RING=y + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16204 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_KXSD9 is not set +# CONFIG_LIS3L02DQ is not set +# CONFIG_SCA3000 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7291 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7606 is not set +# CONFIG_AD799X is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_ADT7310 is not set +# CONFIG_ADT7410 is not set +# CONFIG_AD7280 is not set +# CONFIG_MAX1363 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Direct Digital Synthesis +# +# CONFIG_AD5930 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_AD9850 is not set +# CONFIG_AD9852 is not set +# CONFIG_AD9910 is not set +# CONFIG_AD9951 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16060 is not set +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set + +# +# Light sensors +# +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_ISL29028 is not set +# CONFIG_SENSORS_TSL2563 is not set +# CONFIG_TSL2583 is not set +# CONFIG_TSL2x7x is not set + +# +# Magnetometer sensors +# +# CONFIG_SENSORS_AK8975 is not set +# CONFIG_SENSORS_HMC5843 is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7753 is not set +# CONFIG_ADE7754 is not set +# CONFIG_ADE7758 is not set +# CONFIG_ADE7759 is not set +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_GPIO_TRIGGER is not set +# CONFIG_IIO_SYSFS_TRIGGER is not set +# CONFIG_IIO_SIMPLE_DUMMY is not set +# CONFIG_ZSMALLOC is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +# CONFIG_ANDROID is not set +# CONFIG_PHONE is not set +# CONFIG_IPACK_BUS is not set +# CONFIG_WIMAX_GDM72XX is not set + +# +# Hardware Spinlock drivers +# +CONFIG_IOMMU_SUPPORT=y + +# +# Remoteproc drivers (EXPERIMENTAL) +# + +# +# Rpmsg drivers (EXPERIMENTAL) +# +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 + +# +# Analog to digital converters +# +# CONFIG_AD7266 is not set +CONFIG_CF_AXI_ADC=y +# CONFIG_CF_AXI_FFT is not set +# CONFIG_AXI_JESD204B is not set + +# +# Amplifiers +# +# CONFIG_AD8366 is not set + +# +# Light sensors +# +# CONFIG_VCNL4000 is not set + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +# CONFIG_AD9523 is not set +# CONFIG_AD9548 is not set + +# +# Direct Digital Synthesis +# +# CONFIG_CF_AXI_DDS is not set + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +# CONFIG_ADF4350 is not set + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD5686 is not set +# CONFIG_MAX517 is not set +# CONFIG_MCP4725 is not set + +# +# File systems +# +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ECRYPT_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set +# CONFIG_MINIX_FS_NATIVE_ENDIAN is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V2=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_DEBUG is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +# CONFIG_DETECT_HUNG_TASK is not set +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_TEST_KSTRTOX is not set +CONFIG_EARLY_PRINTK=y +# CONFIG_HEART_BEAT is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_ENCRYPTED_KEYS is not set +CONFIG_KEYS_DEBUG_PROC_KEYS=y +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +# CONFIG_CRC8 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_GENERIC_ATOMIC64=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c index 9774bf6b83a43..e412b1b1b58a0 100644 --- a/drivers/iio/adc/ad9467.c +++ b/drivers/iio/adc/ad9467.c @@ -49,13 +49,13 @@ static int ad9467_spi_write(struct spi_device *spi, unsigned reg, unsigned val) if (ret < 0) return ret; + if ((reg == ADC_REG_TRANSFER) && (val == TRANSFER_SYNC) && + (spi_get_device_id(spi)->driver_data == CHIPID_AD9265)) + ad9467_spi_write(spi, ADC_REG_TRANSFER, 0); + return 0; } - if (val != ad9467_spi_read(spi, reg)) - dev_err(&spi->dev, "Verify REG 0x%X Failed (0x%X)\n", reg, ad9467_spi_read(spi, reg)); - - return -ENODEV; } @@ -63,19 +63,19 @@ static int __devinit ad9250_setup(struct spi_device *spi) { int ret; - msleep(500); + msleep(10); ret = ad9467_spi_write(spi, 0x18, 0x0f); // max vref ret |= ad9467_spi_write(spi, 0x64, 0xf0); // did ret |= ad9467_spi_write(spi, 0x80, 0x0f); // powerdown - ret |= ad9467_spi_write(spi, 0x5f, 0x15); // char repl & ilas + ret |= ad9467_spi_write(spi, 0x5f, 0x17); // char repl & ilas ret |= ad9467_spi_write(spi, 0x09, 0x01); // clock control ret |= ad9467_spi_write(spi, 0x82, 0x02); // lane b = 0, lane a = 2 ret |= ad9467_spi_write(spi, 0x83, 0x31); // lane c = 1, lane d = 3 ret |= ad9467_spi_write(spi, 0x6e, 0x81); // scr, 2-lane ret |= ad9467_spi_write(spi, 0x70, 0x1f); // no. of frames per multi frame ret |= ad9467_spi_write(spi, 0x5e, 0x22); // m=2, l=2 - ret |= ad9467_spi_write(spi, 0x5f, 0x14); // char repl & ilas + ret |= ad9467_spi_write(spi, 0x5f, 0x16); // char repl & ilas ret |= ad9467_spi_write(spi, 0x80, 0x09); // powerdown ret |= ad9467_spi_write(spi, 0x3a, 0x10); // sysref ctrl ret |= ad9467_spi_write(spi, 0x14, 0x00); // offset binary @@ -140,6 +140,7 @@ static const struct spi_device_id ad9467_id[] = { {"ad9467", CHIPID_AD9467}, {"ad9643", CHIPID_AD9643}, {"ad9250", CHIPID_AD9250}, + {"ad9265", CHIPID_AD9265}, {} }; MODULE_DEVICE_TABLE(spi, ad9467_id); diff --git a/drivers/iio/adc/cf_axi_adc.h b/drivers/iio/adc/cf_axi_adc.h index 5c8ec61a814b7..5113696160096 100644 --- a/drivers/iio/adc/cf_axi_adc.h +++ b/drivers/iio/adc/cf_axi_adc.h @@ -135,6 +135,17 @@ #define AD9250_REG_VREF_MASK 0x1F #define AD9250_DEF_OUTPUT_MODE 0x00 +/* + * Analog Devices AD9265 16-Bit, 125/105/80 MSPS ADC + */ + +#define CHIPID_AD9265 0x64 +#define AD9265_DEF_OUTPUT_MODE 0x40 +#define AD9265_REG_VREF_MASK 0xC0 + +/* debugfs direct register access */ +#define DEBUGFS_DRA_PCORE_REG_MAGIC 0x80000000 + #include #define AXIADC_MAX_DMA_SIZE (4 * 1024 * 1024) /* Randomly picked */ @@ -143,6 +154,7 @@ enum { ID_AD9467, ID_AD9643, ID_AD9250, + ID_AD9265, }; struct axiadc_chip_info { diff --git a/drivers/iio/adc/cf_axi_adc_core.c b/drivers/iio/adc/cf_axi_adc_core.c index b4a213740fb35..eb0e09f517e0d 100644 --- a/drivers/iio/adc/cf_axi_adc_core.c +++ b/drivers/iio/adc/cf_axi_adc_core.c @@ -365,14 +365,22 @@ static int axiadc_reg_access(struct iio_dev *indio_dev, mutex_lock(&indio_dev->mlock); if (readval == NULL) { - ret = axiadc_spi_write(st, reg, writeval); - axiadc_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); + if (reg & DEBUGFS_DRA_PCORE_REG_MAGIC) { + axiadc_write(st, reg & 0xFFFF, writeval); + ret = 0; + } else { + ret = axiadc_spi_write(st, reg, writeval); + axiadc_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); + } } else { - ret = axiadc_spi_read(st, reg); - if (ret < 0) - return ret; - *readval = ret; - + if (reg & DEBUGFS_DRA_PCORE_REG_MAGIC) { + *readval = axiadc_read(st, reg & 0xFFFF); + } else { + ret = axiadc_spi_read(st, reg); + if (ret < 0) + return ret; + *readval = ret; + } ret = 0; } mutex_unlock(&indio_dev->mlock); @@ -388,14 +396,31 @@ static int axiadc_read_raw(struct iio_dev *indio_dev, { struct axiadc_state *st = iio_priv(indio_dev); int i; - unsigned vref_val, tmp; + unsigned vref_val, tmp, mask; unsigned long long llval; switch (m) { case IIO_CHAN_INFO_SCALE: - vref_val = axiadc_spi_read(st, ADC_REG_VREF) & - (st->id == CHIPID_AD9643 ? AD9643_REG_VREF_MASK : - AD9467_REG_VREF_MASK); + vref_val = axiadc_spi_read(st, ADC_REG_VREF); + + switch (st->id) { + case CHIPID_AD9467: + mask = AD9467_REG_VREF_MASK; + break; + case CHIPID_AD9643: + mask = AD9643_REG_VREF_MASK; + break; + case CHIPID_AD9250: + mask = AD9250_REG_VREF_MASK; + break; + case CHIPID_AD9265: + mask = AD9265_REG_VREF_MASK; + break; + default: + mask = 0xFFFF; + } + + vref_val &= mask; for (i = 0; i < st->chip_info->num_scales; i++) if (vref_val == st->chip_info->scale_table[i][1]) @@ -528,6 +553,10 @@ static const struct attribute_group axiadc_attribute_group = { .attrs = axiadc_attributes, }; +static const int ad9265_scale_table[][2] = { + {19073, 0x00}, {22888, 0x40}, {26703, 0x80}, {30518, 0xC0}, +}; + static const int ad9467_scale_table[][2] = { {30517, 0}, {32043, 6}, {33569, 7}, {35095, 8}, {36621, 9}, {38146, 10}, @@ -640,6 +669,24 @@ static struct iio_chan_spec_ext_info axiadc_ext_info[] = { .scan_index = _si, \ .scan_type = IIO_ST(_sign, _bits, 16, 0)} +#define AIM_CHAN_NOCALIB(_chan, _si, _bits, _sign) \ + { .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = _chan, \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .ext_info = axiadc_ext_info, \ + .scan_index = _si, \ + .scan_type = IIO_ST(_sign, _bits, 16, 0)} + +#define AIM_CHAN_FD_NOCALIB(_chan, _si, _bits, _sign) \ + { .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = _chan, \ + .extend_name = "frequency_domain", \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .scan_index = _si, \ + .scan_type = IIO_ST(_sign, _bits, 16, 0)} + static const struct axiadc_chip_info axiadc_chip_info_tbl[] = { [ID_AD9467] = { .name = "AD9467", @@ -668,10 +715,18 @@ static const struct axiadc_chip_info axiadc_chip_info_tbl[] = { .num_channels = 4, .available_scan_masks[0] = BIT(0) | BIT(1), .available_scan_masks[1] = BIT(2) | BIT(3), - .channel[0] = AIM_CHAN(0, 0, 14, 'u'), - .channel[1] = AIM_CHAN(1, 1, 14, 'u'), - .channel[2] = AIM_CHAN_FD(0, 2, 14, 'u'), - .channel[3] = AIM_CHAN_FD(1, 3, 14, 'u'), + .channel[0] = AIM_CHAN_NOCALIB(0, 0, 14, 'u'), + .channel[1] = AIM_CHAN_NOCALIB(1, 1, 14, 'u'), + .channel[2] = AIM_CHAN_FD_NOCALIB(0, 2, 14, 'u'), + .channel[3] = AIM_CHAN_FD_NOCALIB(1, 3, 14, 'u'), + }, + [ID_AD9265] = { + .name = "AD9265", + .scale_table = ad9265_scale_table, + .num_scales = ARRAY_SIZE(ad9265_scale_table), + .num_channels = 1, + .available_scan_masks[0] = BIT(0), + .channel[0] = AIM_CHAN_NOCALIB(0, 0, 16, 's'), }, }; @@ -843,6 +898,14 @@ static int __devinit axiadc_of_probe(struct platform_device *op) axiadc_spi_write(st, ADC_REG_OUTPUT_MODE, st->adc_def_output_mode); axiadc_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); break; + case CHIPID_AD9265: + st->chip_info = &axiadc_chip_info_tbl[ID_AD9265]; + st->adc_def_output_mode = AD9265_DEF_OUTPUT_MODE | OUTPUT_MODE_TWOS_COMPLEMENT; + axiadc_spi_write(st, ADC_REG_OUTPUT_MODE, st->adc_def_output_mode); + axiadc_spi_write(st, ADC_REG_TEST_IO, TESTMODE_OFF); + axiadc_spi_write(st, ADC_REG_TRANSFER, TRANSFER_SYNC); + axiadc_dco_calibrate_1c(indio_dev); + break; default: dev_err(dev, "Unrecognized CHIP_ID 0x%X\n", st->id); ret = -ENODEV; @@ -949,6 +1012,7 @@ static const struct of_device_id axiadc_of_match[] __devinitconst = { { .compatible = "xlnx,axi-adc-2c-1.00.a", }, { .compatible = "xlnx,axi-adc-1c-1.00.a", }, { .compatible = "xlnx,axi-ad9250-1.00.a", }, + { .compatible = "xlnx,axi-ad9265-1.00.a", }, { /* end of list */ }, }; MODULE_DEVICE_TABLE(of, axiadc_of_match); From 9a82e855199cd35d0517db6346267bf0f8012ca8 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 18 Oct 2012 10:23:22 +0200 Subject: [PATCH 202/261] iio: adc: cf_axi_adc: add support for PCORE channel select Signed-off-by: Michael Hennerich --- drivers/iio/adc/cf_axi_adc.h | 11 ++++++++--- drivers/iio/adc/cf_axi_adc_core.c | 3 +++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/cf_axi_adc.h b/drivers/iio/adc/cf_axi_adc.h index 5113696160096..c6e4878f5108f 100644 --- a/drivers/iio/adc/cf_axi_adc.h +++ b/drivers/iio/adc/cf_axi_adc.h @@ -14,6 +14,7 @@ /* PCORE CoreFPGA register map */ #define AXIADC_PCORE_VERSION 0x00 +#define AXIADC_PCORE_DMA_CHAN_SEL 0x04 #define AXIADC_PCORE_DMA_CTRL 0x0C #define AXIADC_PCORE_DMA_STAT 0x10 #define AXIADC_PCORE_ADC_STAT 0x14 @@ -23,14 +24,18 @@ #define AXIADC_PCORE_CA_OFFS_SCALE 0x40 #define AXIADC_PCORE_CB_OFFS_SCALE 0x44 +/* AXIADC_PCORE_DMA_CHAN_SEL */ +#define AXIADC_PCORE_DMA_CHAN_SEL0 (1 << 0) +#define AXIADC_PCORE_DMA_CHAN_SEL1 (1 << 1) + /* AXIADC_PCORE_DMA_CTRL */ #define AXIADC_DMA_CAP_EN (1 << 16) #define AXIADC_DMA_CNT(x) (((x) & 0xFFFF) << 0) /* AXIADC_PCORE_DMA_STAT */ -#define AXIADC_DMA_STAT_BUSY (1 << 0) -#define AXIADC_DMA_STAT_OVF (1 << 1) -#define AXIADC_DMA_STAT_UNF (1 << 2) +#define AXIADC_DMA_STAT_BUSY (1 << 0) /* W1C */ +#define AXIADC_DMA_STAT_OVF (1 << 1) /* W1C */ +#define AXIADC_DMA_STAT_UNF (1 << 2) /* W1C */ /* AXIADC_PCORE_ADC_STAT */ #define AXIADC_PCORE_ADC_STAT_OVR0 (1 << 0) /* W1C */ diff --git a/drivers/iio/adc/cf_axi_adc_core.c b/drivers/iio/adc/cf_axi_adc_core.c index eb0e09f517e0d..341d7b1f64019 100644 --- a/drivers/iio/adc/cf_axi_adc_core.c +++ b/drivers/iio/adc/cf_axi_adc_core.c @@ -932,6 +932,9 @@ static int __devinit axiadc_of_probe(struct platform_device *op) *indio_dev->buffer->scan_mask = st->chip_info->available_scan_masks[0]; + axiadc_write(st, AXIADC_PCORE_DMA_CHAN_SEL, + st->chip_info->available_scan_masks[0]); + ret = iio_device_register(indio_dev); if (ret) goto failed4; From ff8eec743e5ed281831939d2e47c3446a1f6e455 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 18 Oct 2012 10:25:24 +0200 Subject: [PATCH 203/261] iio: adc: update jesd204b inrerface block and adjust AD9250 support accordingly Signed-off-by: Michael Hennerich --- .../boot/dts/cf_ad9250_fmc_kc705.dts | 37 ++++--------------- drivers/iio/adc/cf_axi_jesd204b.c | 29 ++++++++++++--- drivers/iio/adc/cf_axi_jesd204b.h | 11 +++++- 3 files changed, 40 insertions(+), 37 deletions(-) diff --git a/arch/microblaze/boot/dts/cf_ad9250_fmc_kc705.dts b/arch/microblaze/boot/dts/cf_ad9250_fmc_kc705.dts index 74736527574f1..c8eb54f1c6d8a 100644 --- a/arch/microblaze/boot/dts/cf_ad9250_fmc_kc705.dts +++ b/arch/microblaze/boot/dts/cf_ad9250_fmc_kc705.dts @@ -285,21 +285,6 @@ xlnx,tri-default = <0xffffffff>; } ; - /* util_jesdbufx2_0 mode */ - - axi_gpio_1: gpio@40000008 { - compatible = "xlnx,axi-gpio-1.01.b", "xlnx,xps-gpio-1.00.a"; - reg = < 0x40000008 0x8 >; - xlnx,all-inputs = <0x0>; - xlnx,dout-default = <0x1>; /* set mode ??? */ - xlnx,family = "kintex7"; - xlnx,gpio-width = <0x1>; - xlnx,instance = "axi_gpio_0"; - xlnx,interrupt-present = <0x0>; - xlnx,is-dual = <0x0>; - xlnx,tri-default = <0xfffffffe>; - } ; - /* axi_gpio_1_ad8372_ctrl */ axi_gpio_2: gpio@40040000 { @@ -338,9 +323,13 @@ xlnx,kind-of-intr = <0x30>; xlnx,num-intr-inputs = <0x6>; } ; - axi_jesd204b_rx2_0: axi-jesd204b-rx2@77a20000 { - compatible = "xlnx,axi-jesd204b-rx2-1.00.a"; + axi_jesd204b_rx4_0: axi-jesd204b-rx4@77a20000 { + compatible = "xlnx,axi-jesd204b-rx4-1.00.a"; reg = < 0x77a20000 0x10000 >; + jesd,lanesync_en; + jesd,scramble_en; + jesd,frames-per-multiframe = <32>; + jesd,bytes-per-frame = <2>; xlnx,cf-buftype = <0x1>; xlnx,dphase-timeout = <0x8>; xlnx,family = "kintex7"; @@ -351,19 +340,7 @@ xlnx,slv-dwidth = <0x20>; xlnx,use-wstrb = <0x0>; } ; - axi_jesd204b_rx2_1: axi-jesd204b-rx2@77a00000 { - compatible = "xlnx,axi-jesd204b-rx2-1.00.a"; - reg = < 0x77a00000 0x10000 >; - xlnx,cf-buftype = <0x0>; - xlnx,dphase-timeout = <0x8>; - xlnx,family = "kintex7"; - xlnx,num-mem = <0x1>; - xlnx,num-reg = <0x1>; - xlnx,s-axi-min-size = <0x1ff>; - xlnx,slv-awidth = <0x20>; - xlnx,slv-dwidth = <0x20>; - xlnx,use-wstrb = <0x0>; - } ; + axi_spi_0: spi@40a00000 { compatible = "xlnx,axi-spi-1.02.a", "xlnx,xps-spi-2.00.a"; interrupt-parent = <&axi_intc_0>; diff --git a/drivers/iio/adc/cf_axi_jesd204b.c b/drivers/iio/adc/cf_axi_jesd204b.c index 1c751cd4f54e2..96b5a6be33243 100644 --- a/drivers/iio/adc/cf_axi_jesd204b.c +++ b/drivers/iio/adc/cf_axi_jesd204b.c @@ -54,6 +54,7 @@ static int __devinit jesd204b_of_probe(struct platform_device *op) struct jesd204b_state *st; struct resource r_mem; /* IO mem resources */ resource_size_t remap_size, phys_addr; + unsigned frmcnt, bytecnt; int ret; dev_info(dev, "Device Tree Probing \'%s\'\n", @@ -92,12 +93,29 @@ static int __devinit jesd204b_of_probe(struct platform_device *op) goto failed2; } + jesd204b_write(st, AXI_JESD204B_REG_TEST_MODE, + AXI_JESD204B_REG_TEST_MODE_JESD_RESET | + AXI_JESD204B_REG_TEST_MODE_GTX_RESET); + + ret = of_property_read_u32(op->dev.of_node, + "jesd,frames-per-multiframe", &frmcnt); + if (ret) + goto failed2; + + ret = of_property_read_u32(op->dev.of_node, + "jesd,bytes-per-frame", &bytecnt); + if (ret) + goto failed2; + jesd204b_write(st, AXI_JESD204B_REG_CTRL, - AXI_JESD204B_CTRL_SCR_EN | - AXI_JESD204B_CTRL_LANESYNC_EN); + (of_property_read_bool(op->dev.of_node, "jesd,scramble_en") ? + AXI_JESD204B_CTRL_SCR_EN : 0) | + (of_property_read_bool(op->dev.of_node, "jesd,lanesync_en") ? + AXI_JESD204B_CTRL_LANESYNC_EN : 0)); + jesd204b_write(st, AXI_JESD204B_REG_FRMCTRL, - AXI_JESD204B_FRMCTRL_FRMCNT(0x1F) | - AXI_JESD204B_FRMCTRL_BYTECNT(1)); + AXI_JESD204B_FRMCTRL_FRMCNT(frmcnt - 1) | + AXI_JESD204B_FRMCTRL_BYTECNT(bytecnt - 1)); dev_info(dev, "AXI-JESD204B (0x%X) at 0x%08llX mapped to 0x%p,", jesd204b_read(st, AXI_JESD204B_REG_VERSION), @@ -144,7 +162,8 @@ static int __devexit jesd204b_of_remove(struct platform_device *op) /* Match table for of_platform binding */ static const struct of_device_id jesd204b_of_match[] __devinitconst = { { .compatible = "xlnx,axi-jesd204b-rx2-1.00.a", }, - { /* end of list */ }, + { .compatible = "xlnx,axi-jesd204b-rx4-1.00.a", }, +{ /* end of list */ }, }; MODULE_DEVICE_TABLE(of, jesd204b_of_match); diff --git a/drivers/iio/adc/cf_axi_jesd204b.h b/drivers/iio/adc/cf_axi_jesd204b.h index 57ae49013df6c..51b4df564d021 100644 --- a/drivers/iio/adc/cf_axi_jesd204b.h +++ b/drivers/iio/adc/cf_axi_jesd204b.h @@ -27,7 +27,7 @@ * 0x05 0x14 [ 3: 2] test_mode Test mode (?) * [ 1: 0] lane_sel Select lanes (0, 1, 2 or 3) for reporting * --------------------------------------------------------------------------- - * The following registers are based on lane_sel + * The following registers are based on lane_sel * --------------------------------------------------------------------------- * 0x06 0x18 [31: 0] bufcnt Buffer count (latency) * 0x07 0x1c [31: 0] init_data0 ILS Data 0 @@ -50,7 +50,7 @@ #define AXI_JESD204B_REG_FRMCTRL 0x0C #define AXI_JESD204B_REG_BUFDELAY 0x10 #define AXI_JESD204B_REG_TEST_MODE 0x14 -#define AXI_JESD204B_REG_BUFCNT 0x18 +#define AXI_JESD204B_REG_BUFCNT 0x18 #define AXI_JESD204B_REG_INIT_DATA0 0x1C #define AXI_JESD204B_REG_INIT_DATA1 0x20 #define AXI_JESD204B_REG_INIT_DATA2 0x24 @@ -77,4 +77,11 @@ /* AXI_JESD204B_REG_BUFDELAY */ #define AXI_JESD204B_BUFDELAY(x) ((x) << 0) +/* AXI_JESD204B_REG_TEST_MODE */ +#define AXI_JESD204B_REG_TEST_MODE_LS(x) ((x) << 0) +#define AXI_JESD204B_REG_TEST_MODE_EN(x) ((x) << 2) +#define AXI_JESD204B_REG_TEST_MODE_JESD_RESET (1 << 4) +#define AXI_JESD204B_REG_TEST_MODE_GTX_RESET (1 << 5) + + #endif /* ADI_JESD204B_H_ */ From 4f6e103860ff9bae50ef4af15d434034294bd9a2 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 18 Oct 2012 11:48:39 +0200 Subject: [PATCH 204/261] sync platforms Signed-off-by: Michael Hennerich --- arch/microblaze/configs/ml605_xcomm_defconfig | 199 ++++++++++++------ arch/microblaze/platform/platform_xcomm.c | 46 ++-- 2 files changed, 152 insertions(+), 93 deletions(-) diff --git a/arch/microblaze/configs/ml605_xcomm_defconfig b/arch/microblaze/configs/ml605_xcomm_defconfig index 2170239baa90b..4728a16d111f1 100644 --- a/arch/microblaze/configs/ml605_xcomm_defconfig +++ b/arch/microblaze/configs/ml605_xcomm_defconfig @@ -1,16 +1,16 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/microblaze 3.3.0-rc3 Kernel Configuration +# Linux/microblaze 3.5.0-rc4 Kernel Configuration # CONFIG_MICROBLAZE=y # CONFIG_SWAP is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ZONE_DMA=y +CONFIG_ARCH_POPULATES_NODE_MAP=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y -# CONFIG_GENERIC_TIME_VSYSCALL is not set -CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_CSUM=y CONFIG_STACKTRACE_SUPPORT=y @@ -45,13 +45,23 @@ CONFIG_HAVE_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_IRQ_DOMAIN=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y # # RCU Subsystem # CONFIG_TINY_RCU=y # CONFIG_PREEMPT_RCU is not set -# CONFIG_RCU_TRACE is not set # CONFIG_TREE_RCU_TRACE is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y @@ -129,7 +139,6 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_INLINE_SPIN_LOCK_BH is not set # CONFIG_INLINE_SPIN_LOCK_IRQ is not set # CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set -CONFIG_INLINE_SPIN_UNLOCK=y # CONFIG_INLINE_SPIN_UNLOCK_BH is not set CONFIG_INLINE_SPIN_UNLOCK_IRQ=y # CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set @@ -180,10 +189,6 @@ CONFIG_XILINX_MICROBLAZE0_HW_VER="8.20.a" # # Processor type and features # -CONFIG_TICK_ONESHOT=y -# CONFIG_NO_HZ is not set -CONFIG_HIGH_RES_TIMERS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set @@ -207,7 +212,7 @@ CONFIG_CMDLINE_FORCE=y # Advanced setup # CONFIG_ADVANCED_OPTIONS=y -CONFIG_HIGHMEM_START=0xfe000000 +# CONFIG_HIGHMEM is not set CONFIG_LOWMEM_SIZE_BOOL=y CONFIG_LOWMEM_SIZE=0x30000000 CONFIG_MANUAL_RESET_VECTOR=0x0 @@ -215,19 +220,22 @@ CONFIG_KERNEL_START_BOOL=y CONFIG_KERNEL_START=0xc0000000 CONFIG_TASK_SIZE_BOOL=y CONFIG_TASK_SIZE=0x80000000 +CONFIG_KERNEL_PAD=0x80000 CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_COMPACTION is not set # CONFIG_PHYS_ADDR_T_64BIT is not set -CONFIG_ZONE_DMA_FLAG=0 +CONFIG_ZONE_DMA_FLAG=1 CONFIG_VIRT_TO_BUS=y # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_CROSS_MEMORY_ATTACH=y CONFIG_NEED_PER_CPU_KM=y # CONFIG_CLEANCACHE is not set @@ -303,7 +311,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_PHONET is not set # CONFIG_IEEE802154 is not set @@ -447,11 +454,10 @@ CONFIG_OF_EARLY_FLATTREE=y CONFIG_OF_ADDRESS=y CONFIG_OF_IRQ=y CONFIG_OF_DEVICE=y -CONFIG_OF_GPIO=y CONFIG_OF_I2C=y CONFIG_OF_NET=y -CONFIG_OF_SPI=y CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y # CONFIG_PARPORT is not set # @@ -461,6 +467,7 @@ CONFIG_AD525X_DPOT=y CONFIG_AD525X_DPOT_I2C=y CONFIG_AD525X_DPOT_SPI=y # CONFIG_ICS932S401 is not set +CONFIG_XLNX_LCD=y # CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_APDS9802ALS is not set # CONFIG_ISL29003 is not set @@ -472,7 +479,8 @@ CONFIG_AD525X_DPOT_SPI=y # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set # CONFIG_TI_DAC7512 is not set -# CONFIG_BMP085 is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set # CONFIG_USB_SWITCH_FSA9480 is not set # CONFIG_C2PORT is not set @@ -541,14 +549,19 @@ CONFIG_NET_VENDOR_SEEQ=y # CONFIG_SEEQ8005 is not set CONFIG_NET_VENDOR_STMICRO=y # CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_WIZNET=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set CONFIG_NET_VENDOR_XILINX=y CONFIG_XILINX_EMACLITE=y +# CONFIG_XILINX_AXI_EMAC is not set # CONFIG_XILINX_LL_TEMAC is not set CONFIG_PHYLIB=y # # MII PHY device drivers # +# CONFIG_AMD_PHY is not set # CONFIG_MARVELL_PHY is not set # CONFIG_DAVICOM_PHY is not set # CONFIG_QSEMI_PHY is not set @@ -565,11 +578,13 @@ CONFIG_PHYLIB=y # CONFIG_MICREL_PHY is not set # CONFIG_FIXED_PHY is not set # CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set # CONFIG_MICREL_KS8995MA is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set CONFIG_WLAN=y # CONFIG_HOSTAP is not set +# CONFIG_WL_TI is not set # # Enable WiMAX (Networking options) to see the WiMAX drivers @@ -638,7 +653,6 @@ CONFIG_SERIAL_OF_PLATFORM=y # PCMCIA character devices # # CONFIG_TCG_TPM is not set -# CONFIG_RAMOOPS is not set CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_COMPAT=y @@ -702,6 +716,7 @@ CONFIG_SPI_XCOMM=y # # CONFIG_SPI_SPIDEV is not set # CONFIG_SPI_TLE62X0 is not set +# CONFIG_HSI is not set # # PPS support @@ -721,6 +736,7 @@ CONFIG_SPI_XCOMM=y # CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y CONFIG_GPIOLIB=y +CONFIG_OF_GPIO=y # CONFIG_DEBUG_GPIO is not set CONFIG_GPIO_SYSFS=y @@ -785,13 +801,16 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_HTC_I2CPLD is not set +# CONFIG_MFD_LM3533 is not set # CONFIG_TPS6105X is not set # CONFIG_TPS65010 is not set # CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65217 is not set # CONFIG_MFD_TPS65910 is not set # CONFIG_MFD_TPS65912_I2C is not set # CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set # CONFIG_MFD_STMPE is not set # CONFIG_MFD_TC3589X is not set # CONFIG_MFD_TMIO is not set @@ -799,6 +818,7 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_DA9052_SPI is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set @@ -809,11 +829,15 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set # CONFIG_ABX500_CORE is not set # CONFIG_EZX_PCAP is not set # CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_TPS65090 is not set # CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_PALMAS is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -824,8 +848,12 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set # CONFIG_FB is not set +# CONFIG_EXYNOS_VIDEO is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # CONFIG_SOUND is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB_ARCH_HAS_XHCI is not set # CONFIG_USB_SUPPORT is not set # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set @@ -863,12 +891,11 @@ CONFIG_DMA_ENGINE=y CONFIG_STAGING=y # CONFIG_ECHO is not set # CONFIG_RTLLIB is not set -CONFIG_IIO=y -CONFIG_IIO_BUFFER=y + +# +# IIO staging drivers +# CONFIG_IIO_SW_RING=y -CONFIG_IIO_KFIFO_BUF=y -CONFIG_IIO_TRIGGER=y -CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # # Accelerometers @@ -899,7 +926,6 @@ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # CONFIG_ADT7310 is not set # CONFIG_ADT7410 is not set # CONFIG_AD7280 is not set -CONFIG_CF_AD9467=y # CONFIG_MAX1363 is not set # @@ -907,11 +933,6 @@ CONFIG_CF_AD9467=y # # CONFIG_ADT7316 is not set -# -# Amplifiers -# -CONFIG_AD8366=y - # # Capacitance to digital converters # @@ -919,31 +940,6 @@ CONFIG_AD8366=y # CONFIG_AD7152 is not set # CONFIG_AD7746 is not set -# -# Digital to analog converters -# -# CONFIG_AD5064 is not set -# CONFIG_AD5360 is not set -# CONFIG_AD5380 is not set -# CONFIG_AD5421 is not set -# CONFIG_AD5624R_SPI is not set -# CONFIG_AD5446 is not set -# CONFIG_AD5504 is not set -# CONFIG_AD5764 is not set -# CONFIG_AD5791 is not set -# CONFIG_AD5686 is not set -# CONFIG_MAX517 is not set - -# -# Frequency Synthesizers DDS/PLL -# - -# -# Clock Generator/Distribution -# -CONFIG_AD9523=y -CONFIG_AD9548=y - # # Direct Digital Synthesis # @@ -954,13 +950,6 @@ CONFIG_AD9548=y # CONFIG_AD9852 is not set # CONFIG_AD9910 is not set # CONFIG_AD9951 is not set -CONFIG_AD9122_CF=y -CONFIG_AD9122_CF_DAC=y - -# -# Phase-Locked Loop (PLL) frequency synthesizers -# -CONFIG_ADF4350=y # # Digital gyroscope sensors @@ -985,8 +974,10 @@ CONFIG_ADF4350=y # Light sensors # # CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_ISL29028 is not set # CONFIG_SENSORS_TSL2563 is not set # CONFIG_TSL2583 is not set +# CONFIG_TSL2x7x is not set # # Magnetometer sensors @@ -1016,6 +1007,7 @@ CONFIG_ADF4350=y # CONFIG_IIO_GPIO_TRIGGER is not set # CONFIG_IIO_SYSFS_TRIGGER is not set # CONFIG_IIO_SIMPLE_DUMMY is not set +# CONFIG_ZSMALLOC is not set # CONFIG_FT1000 is not set # @@ -1028,13 +1020,84 @@ CONFIG_ADF4350=y # # CONFIG_ANDROID is not set # CONFIG_PHONE is not set +# CONFIG_IPACK_BUS is not set +# CONFIG_WIMAX_GDM72XX is not set # # Hardware Spinlock drivers # CONFIG_IOMMU_SUPPORT=y + +# +# Remoteproc drivers (EXPERIMENTAL) +# + +# +# Rpmsg drivers (EXPERIMENTAL) +# # CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 + +# +# Analog to digital converters +# +# CONFIG_AD7266 is not set +CONFIG_CF_AXI_ADC=y +CONFIG_CF_AXI_FFT=y + +# +# Amplifiers +# +CONFIG_AD8366=y + +# +# Light sensors +# +# CONFIG_VCNL4000 is not set + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +CONFIG_AD9523=y +CONFIG_AD9548=y + +# +# Direct Digital Synthesis +# +CONFIG_CF_AXI_DDS=y +CONFIG_CF_AXI_DDS_AD9122=y + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +CONFIG_ADF4350=y + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD5686 is not set +# CONFIG_MAX517 is not set +# CONFIG_MCP4725 is not set # # File systems @@ -1087,6 +1150,7 @@ CONFIG_JFFS2_RTIME=y # CONFIG_PSTORE is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y +CONFIG_NFS_V2=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set @@ -1095,6 +1159,7 @@ CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y +# CONFIG_SUNRPC_DEBUG is not set # CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -1113,6 +1178,7 @@ CONFIG_ENABLE_MUST_CHECK=y CONFIG_FRAME_WARN=1024 # CONFIG_MAGIC_SYSRQ is not set # CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set @@ -1121,6 +1187,8 @@ CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set # CONFIG_LOCKUP_DETECTOR is not set # CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 # CONFIG_DETECT_HUNG_TASK is not set CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set @@ -1151,11 +1219,11 @@ CONFIG_SCHED_DEBUG=y # CONFIG_DEBUG_CREDENTIALS is not set # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_TRACE is not set # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set -# CONFIG_SYSCTL_SYSCALL_CHECK is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y @@ -1282,11 +1350,17 @@ CONFIG_CRYPTO_HW=y # CONFIG_BITREVERSE=y CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set # CONFIG_CRC_T10DIF is not set # CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set # CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set # CONFIG_CRC8 is not set @@ -1303,3 +1377,4 @@ CONFIG_NLATTR=y CONFIG_GENERIC_ATOMIC64=y # CONFIG_AVERAGE is not set # CONFIG_CORDIC is not set +# CONFIG_DDR is not set diff --git a/arch/microblaze/platform/platform_xcomm.c b/arch/microblaze/platform/platform_xcomm.c index 771411170e996..4d46067505c6e 100644 --- a/arch/microblaze/platform/platform_xcomm.c +++ b/arch/microblaze/platform/platform_xcomm.c @@ -18,7 +18,7 @@ #endif #if defined(CONFIG_AD9523) || defined(CONFIG_AD9523_MODULE) -#include "../../../../drivers/staging/iio/frequency/ad9523.h" +#include struct ad9523_channel_spec ad9523_channels[] = { { /* ZD output */ @@ -34,7 +34,7 @@ struct ad9523_channel_spec ad9523_channels[] = { .output_dis = false, }, { /* DAC CLK */ - .channel_num = 1, + .channel_num = 12, .extended_name = "DAC_CLK", .divider_output_invert_en = false, .sync_ignore_en = false, @@ -54,7 +54,7 @@ struct ad9523_channel_spec ad9523_channels[] = { .channel_divider = 4, }, { /* DAC REF CLK */ - .channel_num = 4, + .channel_num = 10, .extended_name = "DAC_REF_CLK", .divider_output_invert_en = false, .sync_ignore_en = false, @@ -84,7 +84,7 @@ struct ad9523_channel_spec ad9523_channels[] = { .channel_divider = 2, }, { /* ADC SYNC */ - .channel_num = 8, + .channel_num = 7, .extended_name = "ADC_SYNC_CLK", .divider_output_invert_en = false, .sync_ignore_en = false, @@ -110,8 +110,8 @@ struct ad9523_platform_data ad9523_pdata_lpc = { .vcxo_freq = 122880000, /* Single-Ended Input Configuration */ - .refa_diff_rcv_en = true, - .refb_diff_rcv_en = false, + .refa_diff_rcv_en = false, + .refb_diff_rcv_en = true, .zd_in_diff_en = true, .osc_in_diff_en = false, .osc_in_cmos_neg_inp_en = true, @@ -120,20 +120,12 @@ struct ad9523_platform_data ad9523_pdata_lpc = { .refb_r_div = 0, .pll1_feedback_div = 4, .pll1_charge_pump_current_nA = 2000, -#if defined(CONFIG_ADIXCOMM_SYNC) .zero_delay_mode_internal_en = false, -#else - .zero_delay_mode_internal_en = true, -#endif .osc_in_feedback_en = false, - .refb_cmos_neg_inp_en = true, + .refa_cmos_neg_inp_en = true, .pll1_loop_filter_rzero = 3, -#if defined(CONFIG_ADIXCOMM_SYNC) - .ref_mode = 3, /* 3 ?*/ -#else - .ref_mode = 1, /* 3 ?*/ -#endif + .ref_mode = SELECT_REFB, // REVERT_TO_REFA, /* 3 ?*/ .pll2_charge_pump_current_nA = 420000, .pll2_ndiv_a_cnt = 0, @@ -158,8 +150,8 @@ struct ad9523_platform_data ad9523_pdata_hpc = { .vcxo_freq = 122880000, /* Single-Ended Input Configuration */ - .refa_diff_rcv_en = true, - .refb_diff_rcv_en = false, + .refa_diff_rcv_en = false, + .refb_diff_rcv_en = true, .zd_in_diff_en = true, .osc_in_diff_en = false, .osc_in_cmos_neg_inp_en = true, @@ -168,20 +160,12 @@ struct ad9523_platform_data ad9523_pdata_hpc = { .refb_r_div = 0, .pll1_feedback_div = 4, .pll1_charge_pump_current_nA = 2000, -#if defined(CONFIG_ADIXCOMM_SYNC) .zero_delay_mode_internal_en = false, -#else - .zero_delay_mode_internal_en = true, -#endif .osc_in_feedback_en = false, - .refb_cmos_neg_inp_en = true, + .refa_cmos_neg_inp_en = true, .pll1_loop_filter_rzero = 3, -#if defined(CONFIG_ADIXCOMM_SYNC) - .ref_mode = 3, /* 3 ?*/ -#else - .ref_mode = 1, /* 3 ?*/ -#endif + .ref_mode = SELECT_REFB, // REVERT_TO_REFA, /* 3 ?*/ .pll2_charge_pump_current_nA = 420000, .pll2_ndiv_a_cnt = 0, @@ -204,7 +188,7 @@ struct ad9523_platform_data ad9523_pdata_hpc = { #endif #if defined(CONFIG_ADF4350) || defined(CONFIG_ADF4350_MODULE) -#include "../../../../drivers/staging/iio/frequency/adf4350.h" +#include static struct adf4350_platform_data adf4350_tx_pdata_lpc = { .name = "adf4351-tx-lpc", .clkin = 122880000, @@ -290,7 +274,7 @@ static struct spi_board_info xcomm_spi_board_info[] __initdata = { #endif #if defined(CONFIG_AD9523) || defined(CONFIG_AD9523_MODULE) { - .modalias = "ad9523", + .modalias = "ad9523-1", .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ .bus_num = SPIBUS_NUM_LPC, .chip_select = 3, /* GPIO controlled SSEL */ @@ -298,7 +282,7 @@ static struct spi_board_info xcomm_spi_board_info[] __initdata = { .mode = SPI_MODE_0 | SPI_3WIRE, }, { - .modalias = "ad9523", + .modalias = "ad9523-1", .max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */ .bus_num = SPIBUS_NUM_HPC, .chip_select = 3, /* GPIO controlled SSEL */ From 221e157ba384be55125db05ccdcf578eb576d45b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 26 Oct 2012 16:24:52 +0200 Subject: [PATCH 205/261] drm: Disable debuging --- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/drm_stub.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 5dcb1a5dbc8a3..e3a9bedb4a00d 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -2,7 +2,7 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -ccflags-y := -Iinclude/drm -DDEBUG +ccflags-y := -Iinclude/drm drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ drm_context.o drm_dma.o \ diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 85fc436187808..6d7b083c5b776 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -37,7 +37,7 @@ #include "drmP.h" #include "drm_core.h" -unsigned int drm_debug = 0xff; /* 1 to enable debug output */ +unsigned int drm_debug = 0; /* 1 to enable debug output */ EXPORT_SYMBOL(drm_debug); unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */ From 3b540e34536aa1f4ef60997c2cfa1c6672083367 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 26 Oct 2012 16:25:17 +0200 Subject: [PATCH 206/261] iio:axi_adc: Fix CHAN_SEL register address --- drivers/iio/adc/cf_axi_adc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/cf_axi_adc.h b/drivers/iio/adc/cf_axi_adc.h index c6e4878f5108f..fc2a976278059 100644 --- a/drivers/iio/adc/cf_axi_adc.h +++ b/drivers/iio/adc/cf_axi_adc.h @@ -14,7 +14,7 @@ /* PCORE CoreFPGA register map */ #define AXIADC_PCORE_VERSION 0x00 -#define AXIADC_PCORE_DMA_CHAN_SEL 0x04 +#define AXIADC_PCORE_DMA_CHAN_SEL 0x08 #define AXIADC_PCORE_DMA_CTRL 0x0C #define AXIADC_PCORE_DMA_STAT 0x10 #define AXIADC_PCORE_ADC_STAT 0x14 From b675d589242e4cb7da677d04590625bb11fcf24d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 26 Oct 2012 16:57:22 +0200 Subject: [PATCH 207/261] zynq-{zed,zc702}-adv7511-xcomm.dts: Add missing DDS DMA entry Signed-off-by: Lars-Peter Clausen --- .../arm/boot/dts/zynq-zc702-adv7511-xcomm.dts | 20 ++++++++++++++++++- arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts | 20 ++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts b/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts index d760af9e3073d..3a7f8762e3545 100644 --- a/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts +++ b/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts @@ -203,7 +203,7 @@ clock-frequency = <12288000>; }; - axi_vdma_0: axivdma@43000000 { + axi_vdma_0: axivdma@43200000 { #address-cells = <1>; #size-cells = <1>; #dma-cells = <1>; @@ -220,6 +220,23 @@ }; }; + axi_vdma_1: axivdma@43000000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-vdma"; + reg = <0x43000000 0x1000>; + xlnx,include-sg = <0x0>; + xlnx,num-fstores = <0x3>; + dma-channel@43000000 { + compatible = "xlnx,axi-vdma-mm2s-channel"; + interrupts = <0 57 0x4>; + xlnx,datawidth = <0x40>; + xlnx,genlock-mode = <0x0>; + xlnx,include-dre = <0x0>; + }; + }; + cf_adv7x11_core_0: cf-adv7x11-core@6c000000 { compatible = "adi,cf-adv7x11-core-1.00.a"; reg = <0x70e00000 0x10000 @@ -306,6 +323,7 @@ compatible = "xlnx,axi-dac-4d-2c-1.00.a"; reg = < 0x74200000 0x10000 >; spibus-connected = <&dac0_ad9122>; + dma-request = <&axi_vdma_1 0>; dac-sample-frequency = <491520000>; xlnx,dphase-timeout = <0x8>; xlnx,num-mem = <0x1>; diff --git a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts index 15068b82a44df..751a2f7f1e9b8 100644 --- a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts +++ b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts @@ -187,7 +187,7 @@ reg = <0x43020000 0x1000>; xlnx,include-sg = <0x0>; xlnx,num-fstores = <0x3>; - dma-channel@43000000 { + dma-channel@43020000 { compatible = "xlnx,axi-vdma-mm2s-channel"; interrupts = <0 55 0x4>; xlnx,datawidth = <0x40>; @@ -196,6 +196,23 @@ }; }; + axi_vdma_1: axivdma@43000000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-vdma"; + reg = <0x43000000 0x1000>; + xlnx,include-sg = <0x0>; + xlnx,num-fstores = <0x3>; + dma-channel@43000000 { + compatible = "xlnx,axi-vdma-mm2s-channel"; + interrupts = <0 57 0x4>; + xlnx,datawidth = <0x40>; + xlnx,genlock-mode = <0x0>; + xlnx,include-dre = <0x0>; + }; + }; + cf_adv7x11_core_0: cf-adv7x11-core@6c000000 { compatible = "adi,cf-adv7x11-core-1.00.a"; reg = <0x70e00000 0x10000 @@ -269,6 +286,7 @@ compatible = "xlnx,axi-dac-4d-2c-1.00.a"; reg = < 0x74200000 0x10000 >; spibus-connected = <&dac0_ad9122>; + dma-request = <&axi_vdma_1 0>; dac-sample-frequency = <491520000>; xlnx,dphase-timeout = <0x8>; xlnx,num-mem = <0x1>; From e92a588730e1734d6e9f14a1a34391cf395590f1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 29 Oct 2012 13:14:20 +0100 Subject: [PATCH 208/261] adv7511: Remove some debug printks Signed-off-by: Lars-Peter Clausen --- drivers/gpu/drm/i2c/adv7511_core.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/i2c/adv7511_core.c b/drivers/gpu/drm/i2c/adv7511_core.c index d67ec22bfaf7d..0693fd4e6625f 100644 --- a/drivers/gpu/drm/i2c/adv7511_core.c +++ b/drivers/gpu/drm/i2c/adv7511_core.c @@ -343,13 +343,11 @@ static int adv7511_get_edid_block(void *data, unsigned char *buf, ret = regmap_read(adv7511->regmap, ADV7511_REG_DDC_STATUS, &status); if (ret < 0) return ret; - printk("edid status: %x\n", status); if (status != 2) { regmap_write(adv7511->regmap, ADV7511_REG_EDID_SEGMENT, block); ret = adv7511_wait_for_interrupt(adv7511, ADV7511_INT0_EDID_READY | ADV7511_INT1_DDC_ERROR, 200); - printk("edid ret: %x\n", ret); if (!(ret & ADV7511_INT0_EDID_READY)) return -EIO; @@ -374,7 +372,6 @@ static int adv7511_get_edid_block(void *data, unsigned char *buf, for (i = 0; i < 4; ++i) { ret = i2c_transfer(adv7511->i2c_edid->adapter, xfer, ARRAY_SIZE(xfer)); - printk("i2c ret: %d\n", ret); if (ret < 0) return ret; else if (ret != 2) @@ -484,8 +481,6 @@ static enum drm_connector_status adv7511_encoder_detect(struct drm_encoder *enco hpd = adv7511_hpd(adv7511); - printk("detect: %x %d %d %d\n", val, status, hpd, adv7511->dpms_mode); - /* The chip resets itself when the cable is disconnected, so in case there is * a pending HPD interrupt and the cable is connected there was at least on * transition from disconnected to connected and the chip has to be From abdb1e4419a1b4d3ac4032491c9e7a522dab8acd Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 29 Oct 2012 13:06:50 +0100 Subject: [PATCH 209/261] ASoC: adv7511_hdmi: Get codec adapter from devicetree Get the I2C adapter on which the adv7511 is registered from the devicetree. This allows the code to run on both ZC702 and ZED without modification. Signed-off-by: Lars-Peter Clausen --- arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts | 2 +- arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts | 2 +- sound/soc/xlnx/adv7511_hdmi.c | 16 ++++++++++++++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts b/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts index 3a7f8762e3545..e03dc7a7ae532 100644 --- a/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts +++ b/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts @@ -252,7 +252,7 @@ adv7511_hdmi_snd: adv7511_hdmi_snd { compatible = "adv7511-hdmi-snd"; - audio-codec = <&i2c_adv7511>; + audio-codec-adapter = <&i2c_adv7511>; cpu-dai = <&axi_spdif_tx_0>; pcm = <&xilinx_pcm_audio>; }; diff --git a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts index 751a2f7f1e9b8..380b30b451888 100644 --- a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts +++ b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts @@ -228,7 +228,7 @@ adv7511_hdmi_snd: adv7511_hdmi_snd { compatible = "adv7511-hdmi-snd"; - audio-codec = <&i2c_adv7511>; + audio-codec-adapter = <&i2c_adv7511>; cpu-dai = <&axi_spdif_tx_0>; pcm = <&xilinx_pcm_audio>; }; diff --git a/sound/soc/xlnx/adv7511_hdmi.c b/sound/soc/xlnx/adv7511_hdmi.c index 79be998c40fd7..410ad19311dd8 100644 --- a/sound/soc/xlnx/adv7511_hdmi.c +++ b/sound/soc/xlnx/adv7511_hdmi.c @@ -18,16 +18,19 @@ #include #include #include +#include #include #include #include +static char adv7511_codec_name[] = "adv7511.2-0039"; + static struct snd_soc_dai_link hdmi_dai_link = { .name = "HDMI", .stream_name = "HDMI", /* .cpu_dai_name = "75c00000.axi-spdif-tx", .platform_name = "xilinx_pcm_audio.2",*/ - .codec_name = "adv7511.2-0039", + .codec_name = adv7511_codec_name, .codec_dai_name = "adv7511", .dai_fmt = SND_SOC_DAIFMT_SPDIF | SND_SOC_DAIFMT_NB_NF | @@ -41,20 +44,29 @@ static struct snd_soc_card hdmi_card = { .num_links = 1, }; + static int __devinit adv7511_hdmi_probe(struct platform_device *pdev) { struct snd_soc_card *card = &hdmi_card; struct device_node *of_node = pdev->dev.of_node; + struct device_node *adapter_node; + struct i2c_adapter *adapter; if (!of_node) return -ENXIO; card->dev = &pdev->dev; -/* hdmi_dai_link.codec_of_node = of_parse_phandle(of_node, "audio-codec", 0);*/ hdmi_dai_link.cpu_dai_of_node = of_parse_phandle(of_node, "cpu-dai", 0); hdmi_dai_link.platform_of_node = of_parse_phandle(of_node, "pcm", 0); + adapter_node = of_parse_phandle(of_node, "audio-codec-adapter", 0); + adapter = of_find_i2c_adapter_by_node(adapter_node); + if (adapter) { + snprintf(adv7511_codec_name, sizeof(adv7511_codec_name), + "adv7511.%d-0039", i2c_adapter_id(adapter)); + } + if (/*!hdmi_dai_link.codec_of_node || */!hdmi_dai_link.cpu_dai_of_node || !hdmi_dai_link.platform_of_node) return -ENXIO; From 0f8dd21d5a75da378066468228eba03333f2b4cf Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 29 Oct 2012 13:49:07 +0100 Subject: [PATCH 210/261] ASoC: xilinx-pcm: Reduce preallocated memory area We are running a little tight on DMAable memory otherwise if we have all three audio, video and xcomm running. Signed-off-by: Lars-Peter Clausen --- sound/soc/xlnx/xilinx-pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/xlnx/xilinx-pcm.c b/sound/soc/xlnx/xilinx-pcm.c index a9680aa471917..f304924da128b 100644 --- a/sound/soc/xlnx/xilinx-pcm.c +++ b/sound/soc/xlnx/xilinx-pcm.c @@ -83,7 +83,7 @@ static int xlnx_pcm_new(struct snd_soc_pcm_runtime *rtd) return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, - card->dev, 8 * 1024 * 1024, + card->dev, 1 * 1024 * 1024, xlnx_pcm_hardware.buffer_bytes_max); } From 6af53d3402cc73db7800b534007b8f2be2f13043 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 23 Nov 2012 14:48:42 +0100 Subject: [PATCH 211/261] Merge branch 'xcomm_zynq' into xcomm_zynq_3_5 Conflicts: drivers/gpu/drm/Makefile sound/soc/soc-core.c --- arch/arm/configs/zync_xcomm_adv7511_defconfig | 63 +++++++++++++++++++ arch/arm/mach-zynq/slcr.c | 2 +- drivers/gpu/drm/Kconfig | 6 +- drivers/gpu/drm/Makefile | 4 +- drivers/gpu/drm/analog/Makefile | 2 +- drivers/gpu/drm/analog/analog_drm_drv.c | 4 ++ drivers/gpu/drm/drm_fb_cma_helper.c | 2 + drivers/gpu/drm/i2c/adv7511_core.c | 4 ++ sound/soc/xlnx/adv7511_hdmi.c | 4 ++ 9 files changed, 83 insertions(+), 8 deletions(-) diff --git a/arch/arm/configs/zync_xcomm_adv7511_defconfig b/arch/arm/configs/zync_xcomm_adv7511_defconfig index eb1ae1353a95c..e8ce8998669df 100644 --- a/arch/arm/configs/zync_xcomm_adv7511_defconfig +++ b/arch/arm/configs/zync_xcomm_adv7511_defconfig @@ -141,7 +141,70 @@ CONFIG_SND=y CONFIG_SND_SOC=y CONFIG_SND_SOC_XILINX=y CONFIG_SND_SOC_ADV7511_HDMI=y +CONFIG_HIDRAW=y +CONFIG_USB_HIDDEV=y +CONFIG_HID_A4TECH=y +CONFIG_HID_ACRUX=y +CONFIG_HID_ACRUX_FF=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_PRODIKEYS=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_DRAGONRISE_FF=y +CONFIG_HID_EMS_FF=y +CONFIG_HID_EZKEY=y +CONFIG_HID_HOLTEK=y +CONFIG_HOLTEK_FF=y +CONFIG_HID_KEYTOUCH=y +CONFIG_HID_KYE=y +CONFIG_HID_UCLOGIC=y +CONFIG_HID_WALTOP=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LCPOWER=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_LOGITECH_DJ=y +CONFIG_LOGITECH_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_LOGIG940_FF=y +CONFIG_LOGIWHEELS_FF=y CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_MULTITOUCH=y +CONFIG_HID_NTRIG=y +CONFIG_HID_ORTEK=y +CONFIG_HID_PANTHERLORD=y +CONFIG_PANTHERLORD_FF=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_PICOLCD=y +CONFIG_HID_PICOLCD_FB=y +CONFIG_HID_PRIMAX=y +CONFIG_HID_ROCCAT=y +CONFIG_HID_ROCCAT_COMMON=y +CONFIG_HID_ROCCAT_ARVO=y +CONFIG_HID_ROCCAT_ISKU=y +CONFIG_HID_ROCCAT_KONE=y +CONFIG_HID_ROCCAT_KONEPLUS=y +CONFIG_HID_ROCCAT_KOVAPLUS=y +CONFIG_HID_ROCCAT_PYRA=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SONY=y +CONFIG_HID_SPEEDLINK=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_GREENASIA_FF=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_SMARTJOYPLUS_FF=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_HID_ZEROPLUS=y +CONFIG_ZEROPLUS_FF=y +CONFIG_HID_ZYDACRON=y CONFIG_USB=y CONFIG_USB_DEVICEFS=y CONFIG_USB_SUSPEND=y diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index 4e057437baeb4..e4da03e7bc384 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -2458,7 +2458,7 @@ static int __devinit xslcr_probe(struct platform_device *pdev) xslcr_writereg(slcr->regs + XSLCR_FPGA0_CLK_CTRL_OFFSET, 0x100a00); xslcr_writereg(slcr->regs + XSLCR_FPGA1_CLK_CTRL_OFFSET, 0x100500); xslcr_writereg(slcr->regs + XSLCR_FPGA2_CLK_CTRL_OFFSET, 0x100500); - xslcr_writereg(slcr->regs + XSLCR_FPGA3_CLK_CTRL_OFFSET, 0x102900); + xslcr_writereg(slcr->regs + XSLCR_FPGA3_CLK_CTRL_OFFSET, 0x102100); xslcr_writereg(slcr->regs + XSLCR_MIO_PIN(50), 0x200); xslcr_writereg(slcr->regs + XSLCR_MIO_PIN(51), 0x200); diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 624b409912402..0abeaa1703cf3 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -54,7 +54,7 @@ config DRM_TTM uses it. config DRM_GEM_CMA_HELPER - tristate + bool depends on DRM help Choose this if you need the GEM CMA helper functions @@ -199,10 +199,6 @@ config DRM_ENCODER_ADV7511 tristate "AV7511 encoder" depends on I2C && DRM select REGMAP_I2C - select DRM_KMS_HELPER - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT source "drivers/gpu/drm/analog/Kconfig" diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 759b60df62ae3..0839856deac87 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -20,10 +20,12 @@ drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o drm-usb-y := drm_usb.o drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_i2c_helper.o -drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o +drm_kms_cma_helper-y += drm_fb_cma_helper.o + obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o +obj-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_kms_cma_helper.o CFLAGS_drm_trace_points.o := -I$(src) diff --git a/drivers/gpu/drm/analog/Makefile b/drivers/gpu/drm/analog/Makefile index 25375e88d2548..01c8376cf9771 100644 --- a/drivers/gpu/drm/analog/Makefile +++ b/drivers/gpu/drm/analog/Makefile @@ -4,4 +4,4 @@ analogdrm-y := analog_drm_encoder.o analog_drm_crtc.o analog_drm_drv.o -obj-y += analogdrm.o +obj-$(CONFIG_DRM_ANALOG) += analogdrm.o diff --git a/drivers/gpu/drm/analog/analog_drm_drv.c b/drivers/gpu/drm/analog/analog_drm_drv.c index 49e4ff981ec32..27eae0196c7ea 100644 --- a/drivers/gpu/drm/analog/analog_drm_drv.c +++ b/drivers/gpu/drm/analog/analog_drm_drv.c @@ -239,3 +239,7 @@ static struct platform_driver adv7511_encoder_driver = { .remove = __devexit_p(analog_drm_platform_remove), }; module_platform_driver(adv7511_encoder_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("DRM support for Analog Devices FPGA platforms"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 453ad6a803353..0f8fd3b312810 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -394,3 +394,5 @@ void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma) drm_fb_helper_hotplug_event(&fbdev_cma->fb_helper); } EXPORT_SYMBOL_GPL(drm_fbdev_cma_hotplug_event); + +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/i2c/adv7511_core.c b/drivers/gpu/drm/i2c/adv7511_core.c index 0693fd4e6625f..76dc7b121c3aa 100644 --- a/drivers/gpu/drm/i2c/adv7511_core.c +++ b/drivers/gpu/drm/i2c/adv7511_core.c @@ -704,3 +704,7 @@ static void __exit adv7511_exit(void) drm_i2c_encoder_unregister(&adv7511_driver); } module_exit(adv7511_exit); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("ADV7511 HDMI transmitter driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/xlnx/adv7511_hdmi.c b/sound/soc/xlnx/adv7511_hdmi.c index 410ad19311dd8..f0093793a1968 100644 --- a/sound/soc/xlnx/adv7511_hdmi.c +++ b/sound/soc/xlnx/adv7511_hdmi.c @@ -100,3 +100,7 @@ static struct platform_driver hdmi_card_driver = { .remove = __devexit_p(adv7511_hdmi_remove), }; module_platform_driver(hdmi_card_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("ADV7511 HDMI sound driver"); +MODULE_LICENSE("GPL"); From ce2f3b7c7d7f530df74e300094c6c7fdeac06239 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 27 Nov 2012 17:02:43 +0100 Subject: [PATCH 212/261] gpio:xilinxps: Fix gpio_request() return value Commit bb1bff3c ("Xilinx: ARM: xgpiops: Adding PM support") added runtime power management for the gpio driver. The gpio chip's request callback calls pm_runtime_get() and passes the return value on, but pm_runtime_get() may either return 0 or 1 on success, but the gpio request callback should only ever return 0 on success. This patch modifies the code to return 0 if the return value of pm_runtime_get() is >= 0. Signed-off-by: Lars-Peter Clausen --- drivers/gpio/gpio-xilinxps.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-xilinxps.c b/drivers/gpio/gpio-xilinxps.c index b89739de403e8..a1c470866af06 100644 --- a/drivers/gpio/gpio-xilinxps.c +++ b/drivers/gpio/gpio-xilinxps.c @@ -460,7 +460,15 @@ static int xgpiops_idle(struct device *dev) static int xgpiops_request(struct gpio_chip *chip, unsigned offset) { - return pm_runtime_get(chip->dev); + int ret; + + ret = pm_runtime_get(chip->dev); + + /* + * If the device is already active pm_runtime_get() will return 1 on + * success, but gpio_request still needs to return 0. + */ + return ret < 0 ? ret : 0; } static void xgpiops_free(struct gpio_chip *chip, unsigned offset) From a97300abf508f4b5622a1d8b53fb454c57ea94e9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 30 Oct 2012 10:01:00 +0100 Subject: [PATCH 213/261] Sync devicetree to latest bitstream The hardware fft and it's dma have been removed from the bitstream. Signed-off-by: Lars-Peter Clausen --- .../arm/boot/dts/zynq-zc702-adv7511-xcomm.dts | 42 ++--------------- arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts | 46 +++---------------- 2 files changed, 11 insertions(+), 77 deletions(-) diff --git a/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts b/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts index e03dc7a7ae532..9c9a06b47e1ad 100644 --- a/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts +++ b/arch/arm/boot/dts/zynq-zc702-adv7511-xcomm.dts @@ -191,7 +191,7 @@ xlnx,sg-include-stscntrl-strm = <0x0>; dma-channel@40440000 { compatible = "xlnx,axi-dma-mm2s-channel"; - interrupts = < 0 54 0x4 >; + interrupts = < 0 56 0x4 >; xlnx,datawidth = <0x20>; xlnx,include-dre = <0x0>; }; @@ -213,7 +213,7 @@ xlnx,num-fstores = <0x3>; dma-channel@43000000 { compatible = "xlnx,axi-vdma-mm2s-channel"; - interrupts = <0 55 0x4>; + interrupts = <0 57 0x4>; xlnx,datawidth = <0x40>; xlnx,genlock-mode = <0x0>; xlnx,include-dre = <0x0>; @@ -230,7 +230,7 @@ xlnx,num-fstores = <0x3>; dma-channel@43000000 { compatible = "xlnx,axi-vdma-mm2s-channel"; - interrupts = <0 57 0x4>; + interrupts = <0 59 0x4>; xlnx,datawidth = <0x40>; xlnx,genlock-mode = <0x0>; xlnx,include-dre = <0x0>; @@ -265,7 +265,7 @@ reg = < 0x40420000 0x10000 >; dma-channel@40420000 { compatible = "xlnx,axi-dma-s2mm-channel"; - interrupts = < 0 56 0x4 >; + interrupts = < 0 58 0x4 >; xlnx,datawidth = <0x40>; xlnx,include-dre = <0x0>; } ; @@ -285,40 +285,6 @@ xlnx,use-wstrb = <0x0>; } ; - axi_dma_2: axidma@40400000 { - #address-cells = <1>; - #size-cells = <1>; - #dma-cells = <1>; - compatible = "xlnx,axi-dma"; - reg = < 0x40400000 0x10000 >; - dma-channel@40400000 { - compatible = "xlnx,axi-dma-mm2s-channel"; - interrupts = < 0 58 0x4 >; - xlnx,datawidth = <0x20>; - xlnx,include-dre = <0x0>; - } ; - dma-channel@40400030 { - compatible = "xlnx,axi-dma-s2mm-channel"; - interrupts = < 0 59 0x4 >; - xlnx,datawidth = <0x20>; - xlnx,include-dre = <0x0>; - } ; - } ; - - cf_fft_core_0: cf-fft-core@7de00000 { - compatible = "xlnx,cf-fft-core-1.00.a"; - reg = < 0x7de00000 0x10000 >; - dma-request = <&axi_dma_2 0 - &axi_dma_2 1>; - xlnx,dphase-timeout = <0x8>; - xlnx,num-mem = <0x1>; - xlnx,num-reg = <0x1>; - xlnx,s-axi-min-size = <0x1ff>; - xlnx,slv-awidth = <0x20>; - xlnx,slv-dwidth = <0x20>; - xlnx,use-wstrb = <0x0>; - } ; - cf_ad9122_core_0: cf-ad9122-core-lpc@74200000 { compatible = "xlnx,axi-dac-4d-2c-1.00.a"; reg = < 0x74200000 0x10000 >; diff --git a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts index 380b30b451888..976f7ca753f61 100644 --- a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts +++ b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts @@ -86,7 +86,7 @@ i2c_adv7511: i2c@41620000 { compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; interrupt-parent = <&gic>; - interrupts = < 0 52 0x4 >; + interrupts = < 0 54 0x4 >; reg = < 0x41620000 0x10000 >; #size-cells = <0>; @@ -96,7 +96,7 @@ axi_iic_1: i2c@41600000 { compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; interrupt-parent = <&gic>; - interrupts = < 0 36 0x4 >; + interrupts = < 0 53 0x4 >; reg = < 0x41600000 0x10000 >; #size-cells = <0>; @@ -167,7 +167,7 @@ xlnx,sg-include-stscntrl-strm = <0x0>; dma-channel@40440000 { compatible = "xlnx,axi-dma-mm2s-channel"; - interrupts = < 0 54 0x4 >; + interrupts = < 0 56 0x4 >; xlnx,datawidth = <0x20>; xlnx,include-dre = <0x0>; }; @@ -189,7 +189,7 @@ xlnx,num-fstores = <0x3>; dma-channel@43020000 { compatible = "xlnx,axi-vdma-mm2s-channel"; - interrupts = <0 55 0x4>; + interrupts = <0 57 0x4>; xlnx,datawidth = <0x40>; xlnx,genlock-mode = <0x0>; xlnx,include-dre = <0x0>; @@ -206,7 +206,7 @@ xlnx,num-fstores = <0x3>; dma-channel@43000000 { compatible = "xlnx,axi-vdma-mm2s-channel"; - interrupts = <0 57 0x4>; + interrupts = <0 59 0x4>; xlnx,datawidth = <0x40>; xlnx,genlock-mode = <0x0>; xlnx,include-dre = <0x0>; @@ -242,32 +242,12 @@ // xlnx,sg-include-stscntrl-strm = <0x0>; dma-channel@40420000 { compatible = "xlnx,axi-dma-s2mm-channel"; - interrupts = < 0 56 0x4 >; - xlnx,datawidth = <0x40>; - xlnx,include-dre = <0x0>; - } ; - } ; - - axi_dma_2: axidma@40400000 { - #address-cells = <1>; - #size-cells = <1>; - #dma-cells = <1>; - compatible = "xlnx,axi-dma"; - reg = < 0x40400000 0x10000 >; - dma-channel@40400000 { - compatible = "xlnx,axi-dma-mm2s-channel"; interrupts = < 0 58 0x4 >; - xlnx,datawidth = <0x20>; - xlnx,include-dre = <0x0>; - } ; - dma-channel@40400030 { - compatible = "xlnx,axi-dma-s2mm-channel"; - interrupts = < 0 59 0x4 >; - xlnx,datawidth = <0x20>; + xlnx,datawidth = <0x40>; xlnx,include-dre = <0x0>; } ; } ; - + cf_ad9643_core_0: cf-ad9643-core-lpc@79020000 { compatible = "xlnx,axi-adc-2c-1.00.a"; reg = < 0x79020000 0x10000 >; @@ -297,17 +277,5 @@ xlnx,use-wstrb = <0x0>; } ; - cf_fft_core_0: cf-fft-core@7de00000 { - compatible = "xlnx,cf-fft-core-1.00.a"; - reg = < 0x7de00000 0x10000 >; - xlnx,dphase-timeout = <0x8>; - xlnx,num-mem = <0x1>; - xlnx,num-reg = <0x1>; - xlnx,s-axi-min-size = <0x1ff>; - xlnx,slv-awidth = <0x20>; - xlnx,slv-dwidth = <0x20>; - xlnx,use-wstrb = <0x0>; - } ; - }; }; From cf92a14920bb160073777356398edb2300ad3133 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 3 Dec 2012 18:39:01 +0100 Subject: [PATCH 214/261] zync_xcomm_adv7511_defconfig: Enable CMA Enable CMA and reserve a memory region of 40MB. This allows us to allocate all the different DMA buffers we need for both XCOMM and HDMI. Signed-off-by: Lars-Peter Clausen --- arch/arm/configs/zync_xcomm_adv7511_defconfig | 68 +++---------------- 1 file changed, 9 insertions(+), 59 deletions(-) diff --git a/arch/arm/configs/zync_xcomm_adv7511_defconfig b/arch/arm/configs/zync_xcomm_adv7511_defconfig index e8ce8998669df..1e6baa7489da2 100644 --- a/arch/arm/configs/zync_xcomm_adv7511_defconfig +++ b/arch/arm/configs/zync_xcomm_adv7511_defconfig @@ -2,6 +2,7 @@ CONFIG_PHYS_OFFSET=0x0 CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y +CONFIG_HIGH_RES_TIMERS=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 @@ -22,7 +23,6 @@ CONFIG_ARCH_ZYNQ=y CONFIG_ZYNQ_EARLY_UART1=y # CONFIG_ZYNQ_EARLY_UART_EP107 is not set CONFIG_XILINX_ZED=y -CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y CONFIG_PREEMPT=y CONFIG_AEABI=y @@ -51,10 +51,11 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_FW_LOADER=m +CONFIG_CMA=y +CONFIG_CMA_SIZE_MBYTES=40 CONFIG_CONNECTOR=y CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_OF_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y @@ -109,7 +110,6 @@ CONFIG_SPI=y CONFIG_SPI_BITBANG=y CONFIG_SPI_XCOMM=y CONFIG_SPI_XILINX_PS_QSPI=y -# CONFIG_XILINX_PS_QSPI_USE_DUAL_FLASH is not set CONFIG_SPI_XILINX_PS_SPI=y CONFIG_GPIO_SYSFS=y CONFIG_GPIO_XILINX_PS=y @@ -142,7 +142,6 @@ CONFIG_SND_SOC=y CONFIG_SND_SOC_XILINX=y CONFIG_SND_SOC_ADV7511_HDMI=y CONFIG_HIDRAW=y -CONFIG_USB_HIDDEV=y CONFIG_HID_A4TECH=y CONFIG_HID_ACRUX=y CONFIG_HID_ACRUX_FF=y @@ -171,7 +170,6 @@ CONFIG_HID_LOGITECH_DJ=y CONFIG_LOGITECH_FF=y CONFIG_LOGIRUMBLEPAD2_FF=y CONFIG_LOGIG940_FF=y -CONFIG_LOGIWHEELS_FF=y CONFIG_HID_MICROSOFT=y CONFIG_HID_MONTEREY=y CONFIG_HID_MULTITOUCH=y @@ -184,13 +182,6 @@ CONFIG_HID_PICOLCD=y CONFIG_HID_PICOLCD_FB=y CONFIG_HID_PRIMAX=y CONFIG_HID_ROCCAT=y -CONFIG_HID_ROCCAT_COMMON=y -CONFIG_HID_ROCCAT_ARVO=y -CONFIG_HID_ROCCAT_ISKU=y -CONFIG_HID_ROCCAT_KONE=y -CONFIG_HID_ROCCAT_KONEPLUS=y -CONFIG_HID_ROCCAT_KOVAPLUS=y -CONFIG_HID_ROCCAT_PYRA=y CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y CONFIG_HID_SPEEDLINK=y @@ -205,8 +196,8 @@ CONFIG_THRUSTMASTER_FF=y CONFIG_HID_ZEROPLUS=y CONFIG_ZEROPLUS_FF=y CONFIG_HID_ZYDACRON=y +CONFIG_USB_HIDDEV=y CONFIG_USB=y -CONFIG_USB_DEVICEFS=y CONFIG_USB_SUSPEND=y CONFIG_USB_OTG=y # CONFIG_USB_OTG_WHITELIST is not set @@ -214,49 +205,8 @@ CONFIG_USB_EHCI_HCD=y # CONFIG_USB_EHCI_TT_NEWSCHED is not set CONFIG_USB_EHCI_XUSBPS=y CONFIG_USB_STORAGE=y - CONFIG_USB_GADGET=y -# CONFIG_USB_GADGET_DEBUG is not set -# CONFIG_USB_GADGET_DEBUG_FILES is not set -# CONFIG_USB_GADGET_DEBUG_FS is not set -CONFIG_USB_GADGET_VBUS_DRAW=2 -CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 CONFIG_USB_GADGET_XUSBPS=y -CONFIG_USB_XUSBPS=y -# CONFIG_USB_FUSB300 is not set -# CONFIG_USB_R8A66597 is not set -# CONFIG_USB_GADGET_XILINX is not set -# CONFIG_USB_MV_UDC is not set -# CONFIG_USB_M66592 is not set -# CONFIG_USB_NET2272 is not set -# CONFIG_USB_DUMMY_HCD is not set -CONFIG_USB_GADGET_DUALSPEED=y -# CONFIG_USB_ZERO is not set -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_ETH is not set -# CONFIG_USB_G_NCM is not set -# CONFIG_USB_GADGETFS is not set -# CONFIG_USB_FUNCTIONFS is not set -# CONFIG_USB_FILE_STORAGE is not set -# CONFIG_USB_MASS_STORAGE is not set -# CONFIG_USB_G_SERIAL is not set -# CONFIG_USB_MIDI_GADGET is not set -# CONFIG_USB_G_PRINTER is not set -# CONFIG_USB_CDC_COMPOSITE is not set -# CONFIG_USB_G_ACM_MS is not set -# CONFIG_USB_G_MULTI is not set -# CONFIG_USB_G_HID is not set -# CONFIG_USB_G_DBGP is not set -# CONFIG_USB_G_WEBCAM is not set - -# -# OTG and related infrastructure -# -CONFIG_USB_OTG_UTILS=y -# CONFIG_USB_GPIO_VBUS is not set -CONFIG_USB_ULPI=y -CONFIG_USB_ULPI_VIEWPORT=y -# CONFIG_NOP_USB_XCEIV is not set CONFIG_USB_XUSBPS_OTG=y CONFIG_MMC=y CONFIG_MMC_SDHCI=y @@ -267,17 +217,17 @@ CONFIG_RTC_DRV_PCF8563=y CONFIG_DMADEVICES=y CONFIG_XILINX_DMA=y CONFIG_STAGING=y -CONFIG_IIO=y -CONFIG_IIO_KFIFO_BUF=y CONFIG_AD8366=y -CONFIG_AD9523=y -CONFIG_AD9548=y -CONFIG_ADF4350=y # CONFIG_IOMMU_SUPPORT is not set +CONFIG_IIO=y +CONFIG_IIO_KFIFO_BUF=y CONFIG_CF_AXI_ADC=y CONFIG_CF_AXI_FFT=y +CONFIG_AD9523=y +CONFIG_AD9548=y CONFIG_CF_AXI_DDS=y CONFIG_CF_AXI_DDS_AD9122=y +CONFIG_ADF4350=y CONFIG_EXT4_FS=y # CONFIG_DNOTIFY is not set CONFIG_MSDOS_FS=y From 50857c8efbb1d658126b5a771348eb866be00dfc Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 3 Dec 2012 18:41:10 +0100 Subject: [PATCH 215/261] Revert "Increase DMA memory region" This reverts commit 8a797e461986eddfb15757a1f01284d4e63c5259. Now that we have CMA we do not need this anymore. Signed-off-by: Lars-Peter Clausen --- arch/arm/Kconfig | 2 +- arch/arm/include/asm/pgtable.h | 2 +- arch/arm/mach-zynq/common.c | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 1180cbcc0c41e..c4b2a0f25a622 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1736,7 +1736,7 @@ config FORCE_MAX_ZONEORDER int "Maximum zone order" if ARCH_SHMOBILE range 11 64 if ARCH_SHMOBILE default "9" if SA1111 - default "15" + default "11" help The kernel memory allocator divides physically contiguous memory blocks into "zones", where each zone is a power of two number of diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 48d9d1474f1c4..f66626d71e7d1 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -40,7 +40,7 @@ */ #define VMALLOC_OFFSET (8*1024*1024) #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) -#define VMALLOC_END 0xfd000000UL +#define VMALLOC_END 0xff000000UL #define LIBRARY_TEXT_START 0x0c000000 diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index ad86a2ed1f930..ed684d95dce17 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -100,7 +99,6 @@ struct map_desc io_desc[] __initdata = { void __init xilinx_map_io(void) { iotable_init(io_desc, ARRAY_SIZE(io_desc)); - init_consistent_dma_size(40 << 20); } /** From bdf0a65db3928346cc7a8814de162006aa6ade67 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 4 Dec 2012 14:40:50 +0100 Subject: [PATCH 216/261] arch: microblaze: update ML605 xcomm settings Signed-off-by: Michael Hennerich --- arch/microblaze/configs/ml605_xcomm_defconfig | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/microblaze/configs/ml605_xcomm_defconfig b/arch/microblaze/configs/ml605_xcomm_defconfig index 4728a16d111f1..828c67463d09a 100644 --- a/arch/microblaze/configs/ml605_xcomm_defconfig +++ b/arch/microblaze/configs/ml605_xcomm_defconfig @@ -116,6 +116,7 @@ CONFIG_SLAB=y # CONFIG_PROFILING is not set CONFIG_HAVE_OPROFILE=y CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y # @@ -466,6 +467,7 @@ CONFIG_OF_MTD=y CONFIG_AD525X_DPOT=y CONFIG_AD525X_DPOT_I2C=y CONFIG_AD525X_DPOT_SPI=y +# CONFIG_ATMEL_PWM is not set # CONFIG_ICS932S401 is not set CONFIG_XLNX_LCD=y # CONFIG_ENCLOSURE_SERVICES is not set @@ -675,6 +677,7 @@ CONFIG_I2C_CHARDEV=y # # I2C system bus drivers (mostly embedded / system-on-chip) # +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set # CONFIG_I2C_GPIO is not set # CONFIG_I2C_OCORES is not set # CONFIG_I2C_PCA_PLATFORM is not set @@ -708,6 +711,7 @@ CONFIG_SPI_BITBANG=y # CONFIG_SPI_OC_TINY is not set # CONFIG_SPI_PXA2XX_PCI is not set CONFIG_SPI_XCOMM=y +# CONFIG_SPI_AD9250FMC is not set # CONFIG_SPI_XILINX is not set # CONFIG_SPI_DESIGNWARE is not set @@ -867,6 +871,7 @@ CONFIG_DMADEVICES=y # DMA Devices # CONFIG_XILINX_DMA=y +# CONFIG_DW_DMAC is not set # CONFIG_TIMB_DMA is not set CONFIG_DMA_ENGINE=y @@ -1022,6 +1027,14 @@ CONFIG_IIO_SW_RING=y # CONFIG_PHONE is not set # CONFIG_IPACK_BUS is not set # CONFIG_WIMAX_GDM72XX is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Common Clock Framework +# +# CONFIG_COMMON_CLK_DEBUG is not set # # Hardware Spinlock drivers @@ -1051,6 +1064,7 @@ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # CONFIG_AD7266 is not set CONFIG_CF_AXI_ADC=y CONFIG_CF_AXI_FFT=y +# CONFIG_AXI_JESD204B is not set # # Amplifiers @@ -1071,6 +1085,7 @@ CONFIG_AD8366=y # CONFIG_AD9523=y CONFIG_AD9548=y +# CONFIG_AD9517 is not set # # Direct Digital Synthesis From f06f5300e9cbad19ba0d036eb1fe8a69eac8ae81 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 9 Apr 2012 14:50:06 -0500 Subject: [PATCH 217/261] clk: add DT clock binding support Based on work 1st by Ben Herrenschmidt and Jeremy Kerr, then by Grant Likely, this patch adds support to clk_get to allow drivers to retrieve clock data from the device tree. Platforms scan for clocks in DT with of_clk_init and a match table, and the register a provider through of_clk_add_provider. The provider's clk_src_get function will be called when a device references the provider's OF node for a clock reference. v6 (Rob Herring): - Return error values instead of NULL to match clock framework expectations v5 (Rob Herring): - Move from drivers/of into common clock subsystem - Squashed "dt/clock: add a simple provider get function" and "dt/clock: add function to get parent clock name" - Rebase to 3.4-rc1 - Drop CONFIG_OF_CLOCK and just use CONFIG_OF - Add missing EXPORT_SYMBOL to various functions - s/clock-output-name/clock-output-names/ - Define that fixed-clock binding is a single output v4 (Rob Herring): - Rework for common clk subsystem - Add of_clk_get_parent_name function v3: - Clarified documentation v2: - fixed errant ';' causing compile error - Editorial fixes from Shawn Guo - merged in adding lookup to clkdev - changed property names to match established convention. After working with the binding a bit it really made more sense to follow the lead of 'reg', 'gpios' and 'interrupts' by making the input simply 'clocks' & 'clock-names' instead of 'clock-input-*', and to only use clock-output* for the producer nodes. (Sorry Shawn, this will mean you need to change some code, but it should be trivial) - Add ability to inherit clocks from parent nodes by using an empty 'clock-ranges' property. Useful for busses. I could use some feedback on the new property name, 'clock-ranges' doesn't feel right to me. Signed-off-by: Grant Likely Signed-off-by: Rob Herring Reviewed-by: Shawn Guo Cc: Sascha Hauer Signed-off-by: Mike Turquette --- .../bindings/clock/clock-bindings.txt | 117 +++++++++++++++ .../devicetree/bindings/clock/fixed-clock.txt | 21 +++ drivers/clk/clk.c | 140 ++++++++++++++++++ drivers/clk/clkdev.c | 77 ++++++++++ include/linux/clk-provider.h | 14 ++ include/linux/clk.h | 19 +++ 6 files changed, 388 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/clock-bindings.txt create mode 100644 Documentation/devicetree/bindings/clock/fixed-clock.txt diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt new file mode 100644 index 0000000000000..eb65d417f8c41 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt @@ -0,0 +1,117 @@ +This binding is a work-in-progress, and are based on some experimental +work by benh[1]. + +Sources of clock signal can be represented by any node in the device +tree. Those nodes are designated as clock providers. Clock consumer +nodes use a phandle and clock specifier pair to connect clock provider +outputs to clock inputs. Similar to the gpio specifiers, a clock +specifier is an array of one more more cells identifying the clock +output on a device. The length of a clock specifier is defined by the +value of a #clock-cells property in the clock provider node. + +[1] http://patchwork.ozlabs.org/patch/31551/ + +==Clock providers== + +Required properties: +#clock-cells: Number of cells in a clock specifier; Typically 0 for nodes + with a single clock output and 1 for nodes with multiple + clock outputs. + +Optional properties: +clock-output-names: Recommended to be a list of strings of clock output signal + names indexed by the first cell in the clock specifier. + However, the meaning of clock-output-names is domain + specific to the clock provider, and is only provided to + encourage using the same meaning for the majority of clock + providers. This format may not work for clock providers + using a complex clock specifier format. In those cases it + is recommended to omit this property and create a binding + specific names property. + + Clock consumer nodes must never directly reference + the provider's clock-output-names property. + +For example: + + oscillator { + #clock-cells = <1>; + clock-output-names = "ckil", "ckih"; + }; + +- this node defines a device with two clock outputs, the first named + "ckil" and the second named "ckih". Consumer nodes always reference + clocks by index. The names should reflect the clock output signal + names for the device. + +==Clock consumers== + +Required properties: +clocks: List of phandle and clock specifier pairs, one pair + for each clock input to the device. Note: if the + clock provider specifies '0' for #clock-cells, then + only the phandle portion of the pair will appear. + +Optional properties: +clock-names: List of clock input name strings sorted in the same + order as the clocks property. Consumers drivers + will use clock-names to match clock input names + with clocks specifiers. +clock-ranges: Empty property indicating that child nodes can inherit named + clocks from this node. Useful for bus nodes to provide a + clock to their children. + +For example: + + device { + clocks = <&osc 1>, <&ref 0>; + clock-names = "baud", "register"; + }; + + +This represents a device with two clock inputs, named "baud" and "register". +The baud clock is connected to output 1 of the &osc device, and the register +clock is connected to output 0 of the &ref. + +==Example== + + /* external oscillator */ + osc: oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <32678>; + clock-output-names = "osc"; + }; + + /* phase-locked-loop device, generates a higher frequency clock + * from the external oscillator reference */ + pll: pll@4c000 { + compatible = "vendor,some-pll-interface" + #clock-cells = <1>; + clocks = <&osc 0>; + clock-names = "ref"; + reg = <0x4c000 0x1000>; + clock-output-names = "pll", "pll-switched"; + }; + + /* UART, using the low frequency oscillator for the baud clock, + * and the high frequency switched PLL output for register + * clocking */ + uart@a000 { + compatible = "fsl,imx-uart"; + reg = <0xa000 0x1000>; + interrupts = <33>; + clocks = <&osc 0>, <&pll 1>; + clock-names = "baud", "register"; + }; + +This DT fragment defines three devices: an external oscillator to provide a +low-frequency reference clock, a PLL device to generate a higher frequency +clock signal, and a UART. + +* The oscillator is fixed-frequency, and provides one clock output, named "osc". +* The PLL is both a clock provider and a clock consumer. It uses the clock + signal generated by the external oscillator, and provides two output signals + ("pll" and "pll-switched"). +* The UART has its baud clock connected the external oscillator and its + register clock connected to the PLL clock (the "pll-switched" signal) diff --git a/Documentation/devicetree/bindings/clock/fixed-clock.txt b/Documentation/devicetree/bindings/clock/fixed-clock.txt new file mode 100644 index 0000000000000..0b1fe7824093a --- /dev/null +++ b/Documentation/devicetree/bindings/clock/fixed-clock.txt @@ -0,0 +1,21 @@ +Binding for simple fixed-rate clock sources. + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +Required properties: +- compatible : shall be "fixed-clock". +- #clock-cells : from common clock binding; shall be set to 0. +- clock-frequency : frequency of clock in Hz. Should be a single cell. + +Optional properties: +- gpios : From common gpio binding; gpio connection to clock enable pin. +- clock-output-names : From common clock binding. + +Example: + clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1000000000>; + }; diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 9a1eb0cfa95f3..5d11e39d3c324 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -16,6 +16,7 @@ #include #include #include +#include static DEFINE_SPINLOCK(enable_lock); static DEFINE_MUTEX(prepare_lock); @@ -1550,3 +1551,142 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb) return ret; } EXPORT_SYMBOL_GPL(clk_notifier_unregister); + +#ifdef CONFIG_OF +/** + * struct of_clk_provider - Clock provider registration structure + * @link: Entry in global list of clock providers + * @node: Pointer to device tree node of clock provider + * @get: Get clock callback. Returns NULL or a struct clk for the + * given clock specifier + * @data: context pointer to be passed into @get callback + */ +struct of_clk_provider { + struct list_head link; + + struct device_node *node; + struct clk *(*get)(struct of_phandle_args *clkspec, void *data); + void *data; +}; + +static LIST_HEAD(of_clk_providers); +static DEFINE_MUTEX(of_clk_lock); + +struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, + void *data) +{ + return data; +} +EXPORT_SYMBOL_GPL(of_clk_src_simple_get); + +/** + * of_clk_add_provider() - Register a clock provider for a node + * @np: Device node pointer associated with clock provider + * @clk_src_get: callback for decoding clock + * @data: context pointer for @clk_src_get callback. + */ +int of_clk_add_provider(struct device_node *np, + struct clk *(*clk_src_get)(struct of_phandle_args *clkspec, + void *data), + void *data) +{ + struct of_clk_provider *cp; + + cp = kzalloc(sizeof(struct of_clk_provider), GFP_KERNEL); + if (!cp) + return -ENOMEM; + + cp->node = of_node_get(np); + cp->data = data; + cp->get = clk_src_get; + + mutex_lock(&of_clk_lock); + list_add(&cp->link, &of_clk_providers); + mutex_unlock(&of_clk_lock); + pr_debug("Added clock from %s\n", np->full_name); + + return 0; +} +EXPORT_SYMBOL_GPL(of_clk_add_provider); + +/** + * of_clk_del_provider() - Remove a previously registered clock provider + * @np: Device node pointer associated with clock provider + */ +void of_clk_del_provider(struct device_node *np) +{ + struct of_clk_provider *cp; + + mutex_lock(&of_clk_lock); + list_for_each_entry(cp, &of_clk_providers, link) { + if (cp->node == np) { + list_del(&cp->link); + of_node_put(cp->node); + kfree(cp); + break; + } + } + mutex_unlock(&of_clk_lock); +} +EXPORT_SYMBOL_GPL(of_clk_del_provider); + +struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec) +{ + struct of_clk_provider *provider; + struct clk *clk = ERR_PTR(-ENOENT); + + /* Check if we have such a provider in our array */ + mutex_lock(&of_clk_lock); + list_for_each_entry(provider, &of_clk_providers, link) { + if (provider->node == clkspec->np) + clk = provider->get(clkspec, provider->data); + if (!IS_ERR(clk)) + break; + } + mutex_unlock(&of_clk_lock); + + return clk; +} + +const char *of_clk_get_parent_name(struct device_node *np, int index) +{ + struct of_phandle_args clkspec; + const char *clk_name; + int rc; + + if (index < 0) + return NULL; + + rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index, + &clkspec); + if (rc) + return NULL; + + if (of_property_read_string_index(clkspec.np, "clock-output-names", + clkspec.args_count ? clkspec.args[0] : 0, + &clk_name) < 0) + clk_name = clkspec.np->name; + + of_node_put(clkspec.np); + return clk_name; +} +EXPORT_SYMBOL_GPL(of_clk_get_parent_name); + +/** + * of_clk_init() - Scan and init clock providers from the DT + * @matches: array of compatible values and init functions for providers. + * + * This function scans the device tree for matching clock providers and + * calls their initialization functions + */ +void __init of_clk_init(const struct of_device_id *matches) +{ + struct device_node *np; + + for_each_matching_node(np, matches) { + const struct of_device_id *match = of_match_node(matches, np); + of_clk_init_cb_t clk_init_cb = match->data; + clk_init_cb(np); + } +} +#endif diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index c535cf8c5770f..20649b3c88fe4 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -19,10 +19,80 @@ #include #include #include +#include static LIST_HEAD(clocks); static DEFINE_MUTEX(clocks_mutex); +#ifdef CONFIG_OF +struct clk *of_clk_get(struct device_node *np, int index) +{ + struct of_phandle_args clkspec; + struct clk *clk; + int rc; + + if (index < 0) + return ERR_PTR(-EINVAL); + + rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index, + &clkspec); + if (rc) + return ERR_PTR(rc); + + clk = of_clk_get_from_provider(&clkspec); + of_node_put(clkspec.np); + return clk; +} +EXPORT_SYMBOL(of_clk_get); + +/** + * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node + * @np: pointer to clock consumer node + * @name: name of consumer's clock input, or NULL for the first clock reference + * + * This function parses the clocks and clock-names properties, + * and uses them to look up the struct clk from the registered list of clock + * providers. + */ +struct clk *of_clk_get_by_name(struct device_node *np, const char *name) +{ + struct clk *clk = ERR_PTR(-ENOENT); + + /* Walk up the tree of devices looking for a clock that matches */ + while (np) { + int index = 0; + + /* + * For named clocks, first look up the name in the + * "clock-names" property. If it cannot be found, then + * index will be an error code, and of_clk_get() will fail. + */ + if (name) + index = of_property_match_string(np, "clock-names", name); + clk = of_clk_get(np, index); + if (!IS_ERR(clk)) + break; + else if (name && index >= 0) { + pr_err("ERROR: could not get clock %s:%s(%i)\n", + np->full_name, name ? name : "", index); + return clk; + } + + /* + * No matching clock found on this node. If the parent node + * has a "clock-ranges" property, then we can try one of its + * clocks. + */ + np = np->parent; + if (np && !of_get_property(np, "clock-ranges", NULL)) + break; + } + + return clk; +} +EXPORT_SYMBOL(of_clk_get_by_name); +#endif + /* * Find the correct struct clk for the device and connection ID. * We do slightly fuzzy matching here: @@ -83,6 +153,13 @@ EXPORT_SYMBOL(clk_get_sys); struct clk *clk_get(struct device *dev, const char *con_id) { const char *dev_id = dev ? dev_name(dev) : NULL; + struct clk *clk; + + if (dev) { + clk = of_clk_get_by_name(dev->of_node, con_id); + if (clk && __clk_get(clk)) + return clk; + } return clk_get_sys(dev_id, con_id); } diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 4a0b483986c3b..acfef4591a1ac 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -334,5 +334,19 @@ void __clk_unprepare(struct clk *clk); void __clk_reparent(struct clk *clk, struct clk *new_parent); unsigned long __clk_round_rate(struct clk *clk, unsigned long rate); +struct of_device_id; + +typedef void (*of_clk_init_cb_t)(struct device_node *); + +int of_clk_add_provider(struct device_node *np, + struct clk *(*clk_src_get)(struct of_phandle_args *args, + void *data), + void *data); +void of_clk_del_provider(struct device_node *np); +struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, + void *data); +const char *of_clk_get_parent_name(struct device_node *np, int index); +void of_clk_init(const struct of_device_id *matches); + #endif /* CONFIG_COMMON_CLK */ #endif /* CLK_PROVIDER_H */ diff --git a/include/linux/clk.h b/include/linux/clk.h index ad5c43e8ae8ae..8b70342e7e0b7 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -310,4 +310,23 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id); int clk_add_alias(const char *alias, const char *alias_dev_name, char *id, struct device *dev); +struct device_node; +struct of_phandle_args; + +#ifdef CONFIG_OF +struct clk *of_clk_get(struct device_node *np, int index); +struct clk *of_clk_get_by_name(struct device_node *np, const char *name); +struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec); +#else +static inline struct clk *of_clk_get(struct device_node *np, int index) +{ + return NULL; +} +static inline struct clk *of_clk_get_by_name(struct device_node *np, + const char *name) +{ + return NULL; +} +#endif + #endif From c4ca5a575627de2bea31db2dbcd56ba31fba4347 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 7 Apr 2012 21:39:39 -0500 Subject: [PATCH 218/261] clk: add DT fixed-clock binding support Add support for DT "fixed-clock" binding to the common fixed rate clock support. Signed-off-by: Grant Likely [Rob Herring] Rework and move into common clock infrastructure Signed-off-by: Rob Herring Signed-off-by: Mike Turquette --- drivers/clk/clk-fixed-rate.c | 23 +++++++++++++++++++++++ include/linux/clk-provider.h | 2 ++ 2 files changed, 25 insertions(+) diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index cbd2462297866..94493f1613b31 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c @@ -14,6 +14,7 @@ #include #include #include +#include /* * DOC: basic fixed-rate clock that cannot gate @@ -79,3 +80,25 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name, return clk; } + +#ifdef CONFIG_OF +/** + * of_fixed_clk_setup() - Setup function for simple fixed rate clock + */ +void __init of_fixed_clk_setup(struct device_node *node) +{ + struct clk *clk; + const char *clk_name = node->name; + u32 rate; + + if (of_property_read_u32(node, "clock-frequency", &rate)) + return; + + of_property_read_string(node, "clock-output-names", &clk_name); + + clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate); + if (clk) + of_clk_add_provider(node, of_clk_src_simple_get, clk); +} +EXPORT_SYMBOL_GPL(of_fixed_clk_setup); +#endif diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index acfef4591a1ac..b97f61ef3614d 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -171,6 +171,8 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name, const char *parent_name, unsigned long flags, unsigned long fixed_rate); +void of_fixed_clk_setup(struct device_node *np); + /** * struct clk_gate - gating clock * From 01d6f0dd24b3091ae02dc7d9187aaf5e686f3fdb Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 4 Dec 2012 15:16:41 +0100 Subject: [PATCH 219/261] arch: mb: enable COMMOM_CLK infrastructure Signed-off-by: Michael Hennerich --- arch/microblaze/Kconfig | 1 + arch/microblaze/platform/platform.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index e08bbcba94b4e..07836af07c1ff 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -23,6 +23,7 @@ config MICROBLAZE select GENERIC_CPU_DEVICES select GENERIC_ATOMIC64 select GENERIC_CLOCKEVENTS + select COMMON_CLK config SWAP def_bool n diff --git a/arch/microblaze/platform/platform.c b/arch/microblaze/platform/platform.c index 9b187a90ca658..01c84965ccff2 100644 --- a/arch/microblaze/platform/platform.c +++ b/arch/microblaze/platform/platform.c @@ -15,16 +15,25 @@ #include #include +#include + static struct of_device_id xilinx_of_bus_ids[] __initdata = { { .compatible = "simple-bus", }, { .compatible = "xlnx,compound", }, {} }; +static const __initconst struct of_device_id clk_match[] = { + { .compatible = "fixed-clock", .data = of_fixed_clk_setup, }, + { /* sentinel */ } +}; + + static int __init microblaze_device_probe(void) { of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL); of_platform_reset_gpio_probe(); + of_clk_init(clk_match); return 0; } From 9bae611eedbf43f12d20f6683dfae59fb17c6b92 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 4 Dec 2012 13:17:41 +0100 Subject: [PATCH 220/261] iio: adc: avoid possible false trigger and simplify dco calibrate routine Signed-off-by: Michael Hennerich --- drivers/iio/adc/cf_axi_adc_core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/cf_axi_adc_core.c b/drivers/iio/adc/cf_axi_adc_core.c index c402a430bfa70..e316bebda139d 100644 --- a/drivers/iio/adc/cf_axi_adc_core.c +++ b/drivers/iio/adc/cf_axi_adc_core.c @@ -127,8 +127,7 @@ static int axiadc_dco_calibrate_2c(struct iio_dev *indio_dev) do { mdelay(8); stat = axiadc_read(st, AXIADC_PCORE_ADC_STAT); - if ((cnt-- < 0) | (stat & (AXIADC_PCORE_ADC_STAT_PN_ERR0 | - AXIADC_PCORE_ADC_STAT_PN_ERR1))) { + if (cnt-- < 0) { ret = -EIO; break; } @@ -214,7 +213,7 @@ static int axiadc_dco_calibrate_1c(struct iio_dev *indio_dev) do { mdelay(8); stat = axiadc_read(st, AXIADC_PCORE_ADC_STAT); - if ((cnt-- < 0) | (stat & AXIADC_PCORE_ADC_STAT_PN_ERR)) { + if (cnt-- < 0) { ret = -EIO; break; } From 8359969ac2c70a928f26b605b01255576b6af57b Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 4 Dec 2012 13:21:43 +0100 Subject: [PATCH 221/261] iio: frequency: cf_axi_dds miscellaneous changes Remove mem init and wave data. (no longer supported by HDL) Add debugfs access to PCORE registers. Add support for 3x HW interpolation. Signed-off-by: Michael Hennerich --- drivers/iio/frequency/cf_axi_dds.c | 99 ++-- drivers/iio/frequency/cf_axi_dds.h | 531 +--------------------- drivers/iio/frequency/cf_axi_dds_buffer.c | 6 +- 3 files changed, 81 insertions(+), 555 deletions(-) diff --git a/drivers/iio/frequency/cf_axi_dds.c b/drivers/iio/frequency/cf_axi_dds.c index 9acbda9e3b3df..1200baa6f7a88 100644 --- a/drivers/iio/frequency/cf_axi_dds.c +++ b/drivers/iio/frequency/cf_axi_dds.c @@ -30,7 +30,6 @@ #include #include -#define CF_AXI_DDS_WAVDATA #include "cf_axi_dds.h" #include "ad9122.h" @@ -238,28 +237,6 @@ static int cf_axi_dds_tune_dci(struct cf_axi_dds_state *st) return 0; } -static void cf_axi_dds_mem_init(struct cf_axi_dds_state *st) -{ - - u32 i, sample, addr, data; - - sample = 0; - addr = 0; - - for (i = 0; i < ARRAY_SIZE(cf_axi_dds_i_data); i++) { - data = (sample << 24) | (addr << 16); - dds_write(st, CF_AXI_DDS_MEM_CTRL, ((0 << 26) | data | cf_axi_dds_i_data[i])); - dds_write(st, CF_AXI_DDS_MEM_CTRL, ((1 << 26) | data | cf_axi_dds_i_data[i])); - dds_write(st, CF_AXI_DDS_MEM_CTRL, ((2 << 26) | data | cf_axi_dds_q_data[i])); - dds_write(st, CF_AXI_DDS_MEM_CTRL, ((3 << 26) | data | cf_axi_dds_q_data[i])); - sample++; - if (sample >= 3) { - addr++; - sample = 0; - } - } -} - static const int cf_axi_dds_scale_table[16] = { 10000, 5000, 2500, 1250, 625, 313, 156, }; @@ -421,18 +398,28 @@ static int cf_axi_dds_reg_access(struct iio_dev *indio_dev, if (IS_ERR(conv)) return PTR_ERR(conv); - if (reg > 0xFF) + if ((reg & ~DEBUGFS_DRA_PCORE_REG_MAGIC) > 0xFF) return -EINVAL; mutex_lock(&indio_dev->mlock); if (readval == NULL) { - ret = conv->write(conv->spi, reg, writeval & 0xFF); + if (reg & DEBUGFS_DRA_PCORE_REG_MAGIC) { + dds_write(st, reg & 0xFFFF, writeval); + ret = 0; + } else { + ret = conv->write(conv->spi, reg, writeval & 0xFF); + } } else { - ret = conv->read(conv->spi, reg); - if (ret < 0) - return ret; + if (reg & DEBUGFS_DRA_PCORE_REG_MAGIC) { + ret = dds_read(st, reg & 0xFFFF); + } else { + ret = conv->read(conv->spi, reg); + if (ret < 0) + return ret; + } *readval = ret; ret = 0; + } mutex_unlock(&indio_dev->mlock); @@ -529,6 +516,52 @@ static ssize_t ad9122_dds_show(struct device *dev, return ret; } +static ssize_t ad9122_dds_interpolation_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct cf_axi_dds_state *st = iio_priv(indio_dev); + long readin; + int ret; + + ret = kstrtol(buf, 10, &readin); + if (ret) + return ret; + + mutex_lock(&indio_dev->mlock); + + switch (readin) { + case 1: + st->ddr_dds_interp_en = 0; + break; + case 3: + st->ddr_dds_interp_en = CF_AXI_DDS_CTRL_INTERPOLATE; + break; + default: + ret = -EINVAL; + } + + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static ssize_t ad9122_dds_interpolation_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct cf_axi_dds_state *st = iio_priv(indio_dev); + int ret = 0; + + mutex_lock(&indio_dev->mlock); + ret = sprintf(buf, "%d\n", st->ddr_dds_interp_en ? 3 : 1); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + static IIO_DEVICE_ATTR(out_voltage0_phase, S_IRUGO | S_IWUSR, ad9122_dds_show, ad9122_dds_store, @@ -559,11 +592,17 @@ static IIO_DEVICE_ATTR(out_voltage1_calibscale, S_IRUGO | S_IWUSR, ad9122_dds_store, AD9122_REG_Q_DAC_CTRL); +static IIO_DEVICE_ATTR(out_altvoltage_interpolation, S_IRUGO | S_IWUSR, + ad9122_dds_interpolation_show, + ad9122_dds_interpolation_store, + 0); static IIO_CONST_ATTR(out_altvoltage_scale_available, "1.000000 0.500000 0.250000 0.125000 ..."); +static IIO_CONST_ATTR(out_altvoltage_interpolation_available, + "1 3"); static struct attribute *cf_axi_dds_attributes[] = { &iio_dev_attr_out_voltage0_phase.dev_attr.attr, /* I */ @@ -573,6 +612,8 @@ static struct attribute *cf_axi_dds_attributes[] = { &iio_dev_attr_out_voltage1_calibscale.dev_attr.attr, &iio_dev_attr_out_voltage1_calibbias.dev_attr.attr, &iio_const_attr_out_altvoltage_scale_available.dev_attr.attr, + &iio_dev_attr_out_altvoltage_interpolation.dev_attr.attr, + &iio_const_attr_out_altvoltage_interpolation_available.dev_attr.attr, NULL, }; @@ -771,7 +812,7 @@ static int __devinit cf_axi_dds_of_probe(struct platform_device *op) cf_axi_dds_tune_dci(st); - cf_axi_dds_mem_init(st); + dds_write(st, CF_AXI_DDS_INTERPOL_CTRL, 0x2aaa5555); /* Lin. Interp. */ dds_write(st, CF_AXI_DDS_CTRL, 0x0); dds_write(st, CF_AXI_DDS_SCALE, 0x1111); /* divide by 4 */ diff --git a/drivers/iio/frequency/cf_axi_dds.h b/drivers/iio/frequency/cf_axi_dds.h index 5a32819fc9c39..78179ab68e8fe 100644 --- a/drivers/iio/frequency/cf_axi_dds.h +++ b/drivers/iio/frequency/cf_axi_dds.h @@ -15,9 +15,9 @@ #define CF_AXI_DDS_1B_OUTPUT_CTRL 0x0C #define CF_AXI_DDS_2A_OUTPUT_CTRL 0x10 #define CF_AXI_DDS_2B_OUTPUT_CTRL 0x14 -#define CF_AXI_DDS_MEM_CTRL 0x18 -#define CF_AXI_DDS_SCALE 0x20 -#define CF_AXI_DDS_FRAME 0x24 +#define CF_AXI_DDS_INTERPOL_CTRL 0x18 +#define CF_AXI_DDS_SCALE 0x20 +#define CF_AXI_DDS_FRAME 0x24 #define CF_AXI_DDS_DMA_STAT 0x28 #define CF_AXI_DDS_PAT_DATA1 0x40 #define CF_AXI_DDS_PAT_DATA2 0x44 @@ -43,6 +43,9 @@ #define AXIDDS_MAX_DMA_SIZE (4 * 1024 * 1024) /* Randomly picked */ +/* debugfs direct register access */ +#define DEBUGFS_DRA_PCORE_REG_MAGIC 0x80000000 + enum { ID_AD9122, ID_AD9739A, @@ -73,6 +76,7 @@ struct cf_axi_dds_state { unsigned vers_id; unsigned buffer_lenght; unsigned txcount; + unsigned ddr_dds_interp_en; }; struct cf_axi_dds_converter { @@ -112,525 +116,4 @@ static inline unsigned int dds_read(struct cf_axi_dds_state *st, unsigned reg) { return ioread32(st->regs + reg); } - -#if defined(CF_AXI_DDS_WAVDATA) -static const u16 cf_axi_dds_i_data[] = { - 0x7fff, 0xbf16, 0xedc8, - 0xfff4, 0xf0e1, 0xc479, - 0x8647, 0x4673, 0x1592, - 0x0059, 0x0c4a, 0x364b, - 0x7373, 0xb3de, 0xe6ce, - 0xff08, 0xf640, 0xcebe, - 0x92c7, 0x51ee, 0x1d0e, - 0x01e2, 0x077b, 0x2c64, - 0x6706, 0xa825, 0xded6, - 0xfce2, 0xfa7b, 0xd841, - 0x9f19, 0x5ddc, 0x257d, - 0x04a3, 0x03d6, 0x234c, - 0x5ad7, 0x9c0a, 0xd5f4, - 0xf988, 0xfd88, 0xe0ea, - 0xab1e, 0x6a1d, 0x2ecc, - 0x0894, 0x0163, 0x1b17, - 0x4f04, 0x8faa, 0xcc3e, - 0xf503, 0xff60, 0xe8a5, - 0xb6b9, 0x7695, 0x38e3, - 0x0dab, 0x0027, 0x13dc, - 0x43a9, 0x8323, 0xc1cd, - 0xef5d, 0xfffe, 0xef5d, - 0xc1cd, 0x8323, 0x43a9, - 0x13dc, 0x0027, 0x0dab, - 0x38e3, 0x7695, 0xb6b9, - 0xe8a5, 0xff60, 0xf503, - 0xcc3e, 0x8faa, 0x4f04, - 0x1b17, 0x0163, 0x0894, - 0x2ecc, 0x6a1d, 0xab1e, - 0xe0ea, 0xfd88, 0xf988, - 0xd5f4, 0x9c0a, 0x5ad7, - 0x234c, 0x03d6, 0x04a3, - 0x257d, 0x5ddc, 0x9f19, - 0xd841, 0xfa7b, 0xfce2, - 0xded6, 0xa825, 0x6706, - 0x2c64, 0x077b, 0x01e2, - 0x1d0e, 0x51ee, 0x92c7, - 0xcebe, 0xf640, 0xff08, - 0xe6ce, 0xb3de, 0x7373, - 0x364b, 0x0c4a, 0x0059, - 0x1592, 0x4673, 0x8647, - 0xc479, 0xf0e1, 0xfff4, - 0xedc8, 0xbf16, 0x7fff, - 0x40e8, 0x1236, 0x000a, - 0x0f1d, 0x3b85, 0x79b7, - 0xb98b, 0xea6c, 0xffa5, - 0xf3b4, 0xc9b3, 0x8c8b, - 0x4c20, 0x1930, 0x00f6, - 0x09be, 0x3140, 0x6d37, - 0xae10, 0xe2f0, 0xfe1c, - 0xf883, 0xd39a, 0x98f8, - 0x57d9, 0x2128, 0x031c, - 0x0583, 0x27bd, 0x60e5, - 0xa222, 0xda81, 0xfb5b, - 0xfc28, 0xdcb2, 0xa527, - 0x63f4, 0x2a0a, 0x0676, - 0x0276, 0x1f14, 0x54e0, - 0x95e1, 0xd132, 0xf76a, - 0xfe9b, 0xe4e7, 0xb0fa, - 0x7054, 0x33c0, 0x0afb, - 0x009e, 0x1759, 0x4945, - 0x8969, 0xc71b, 0xf253, - 0xffd7, 0xec22, 0xbc55, - 0x7cdb, 0x3e31, 0x10a1, - 0x0000, 0x10a1, 0x3e31, - 0x7cdb, 0xbc55, 0xec22, - 0xffd7, 0xf253, 0xc71b, - 0x8969, 0x4945, 0x1759, - 0x009e, 0x0afb, 0x33c0, - 0x7054, 0xb0fa, 0xe4e7, - 0xfe9b, 0xf76a, 0xd132, - 0x95e1, 0x54e0, 0x1f14, - 0x0276, 0x0676, 0x2a0a, - 0x63f4, 0xa527, 0xdcb2, - 0xfc28, 0xfb5b, 0xda81, - 0xa222, 0x60e5, 0x27bd, - 0x0583, 0x031c, 0x2128, - 0x57d9, 0x98f8, 0xd39a, - 0xf883, 0xfe1c, 0xe2f0, - 0xae10, 0x6d37, 0x3140, - 0x09be, 0x00f6, 0x1930, - 0x4c20, 0x8c8b, 0xc9b3, - 0xf3b4, 0xffa5, 0xea6c, - 0xb98b, 0x79b7, 0x3b85, - 0x0f1d, 0x000a, 0x1236, - 0x40e8, 0x7fff, 0xbf16, - 0xedc8, 0xfff4, 0xf0e1, - 0xc479, 0x8647, 0x4673, - 0x1592, 0x0059, 0x0c4a, - 0x364b, 0x7373, 0xb3de, - 0xe6ce, 0xff08, 0xf640, - 0xcebe, 0x92c7, 0x51ee, - 0x1d0e, 0x01e2, 0x077b, - 0x2c64, 0x6706, 0xa825, - 0xded6, 0xfce2, 0xfa7b, - 0xd841, 0x9f19, 0x5ddc, - 0x257d, 0x04a3, 0x03d6, - 0x234c, 0x5ad7, 0x9c0a, - 0xd5f4, 0xf988, 0xfd88, - 0xe0ea, 0xab1e, 0x6a1d, - 0x2ecc, 0x0894, 0x0163, - 0x1b17, 0x4f04, 0x8faa, - 0xcc3e, 0xf503, 0xff60, - 0xe8a5, 0xb6b9, 0x7695, - 0x38e3, 0x0dab, 0x0027, - 0x13dc, 0x43a9, 0x8323, - 0xc1cd, 0xef5d, 0xfffe, - 0xef5d, 0xc1cd, 0x8323, - 0x43a9, 0x13dc, 0x0027, - 0x0dab, 0x38e3, 0x7695, - 0xb6b9, 0xe8a5, 0xff60, - 0xf503, 0xcc3e, 0x8faa, - 0x4f04, 0x1b17, 0x0163, - 0x0894, 0x2ecc, 0x6a1d, - 0xab1e, 0xe0ea, 0xfd88, - 0xf988, 0xd5f4, 0x9c0a, - 0x5ad7, 0x234c, 0x03d6, - 0x04a3, 0x257d, 0x5ddc, - 0x9f19, 0xd841, 0xfa7b, - 0xfce2, 0xded6, 0xa825, - 0x6706, 0x2c64, 0x077b, - 0x01e2, 0x1d0e, 0x51ee, - 0x92c7, 0xcebe, 0xf640, - 0xff08, 0xe6ce, 0xb3de, - 0x7373, 0x364b, 0x0c4a, - 0x0059, 0x1592, 0x4673, - 0x8647, 0xc479, 0xf0e1, - 0xfff4, 0xedc8, 0xbf16, - 0x7fff, 0x40e8, 0x1236, - 0x000a, 0x0f1d, 0x3b85, - 0x79b7, 0xb98b, 0xea6c, - 0xffa5, 0xf3b4, 0xc9b3, - 0x8c8b, 0x4c20, 0x1930, - 0x00f6, 0x09be, 0x3140, - 0x6d37, 0xae10, 0xe2f0, - 0xfe1c, 0xf883, 0xd39a, - 0x98f8, 0x57d9, 0x2128, - 0x031c, 0x0583, 0x27bd, - 0x60e5, 0xa222, 0xda81, - 0xfb5b, 0xfc28, 0xdcb2, - 0xa527, 0x63f4, 0x2a0a, - 0x0676, 0x0276, 0x1f14, - 0x54e0, 0x95e1, 0xd132, - 0xf76a, 0xfe9b, 0xe4e7, - 0xb0fa, 0x7054, 0x33c0, - 0x0afb, 0x009e, 0x1759, - 0x4945, 0x8969, 0xc71b, - 0xf253, 0xffd7, 0xec22, - 0xbc55, 0x7cdb, 0x3e31, - 0x10a1, 0x0000, 0x10a1, - 0x3e31, 0x7cdb, 0xbc55, - 0xec22, 0xffd7, 0xf253, - 0xc71b, 0x8969, 0x4945, - 0x1759, 0x009e, 0x0afb, - 0x33c0, 0x7054, 0xb0fa, - 0xe4e7, 0xfe9b, 0xf76a, - 0xd132, 0x95e1, 0x54e0, - 0x1f14, 0x0276, 0x0676, - 0x2a0a, 0x63f4, 0xa527, - 0xdcb2, 0xfc28, 0xfb5b, - 0xda81, 0xa222, 0x60e5, - 0x27bd, 0x0583, 0x031c, - 0x2128, 0x57d9, 0x98f8, - 0xd39a, 0xf883, 0xfe1c, - 0xe2f0, 0xae10, 0x6d37, - 0x3140, 0x09be, 0x00f6, - 0x1930, 0x4c20, 0x8c8b, - 0xc9b3, 0xf3b4, 0xffa5, - 0xea6c, 0xb98b, 0x79b7, - 0x3b85, 0x0f1d, 0x000a, - 0x1236, 0x40e8, 0x7fff, - 0xbf16, 0xedc8, 0xfff4, - 0xf0e1, 0xc479, 0x8647, - 0x4673, 0x1592, 0x0059, - 0x0c4a, 0x364b, 0x7373, - 0xb3de, 0xe6ce, 0xff08, - 0xf640, 0xcebe, 0x92c7, - 0x51ee, 0x1d0e, 0x01e2, - 0x077b, 0x2c64, 0x6706, - 0xa825, 0xded6, 0xfce2, - 0xfa7b, 0xd841, 0x9f19, - 0x5ddc, 0x257d, 0x04a3, - 0x03d6, 0x234c, 0x5ad7, - 0x9c0a, 0xd5f4, 0xf988, - 0xfd88, 0xe0ea, 0xab1e, - 0x6a1d, 0x2ecc, 0x0894, - 0x0163, 0x1b17, 0x4f04, - 0x8faa, 0xcc3e, 0xf503, - 0xff60, 0xe8a5, 0xb6b9, - 0x7695, 0x38e3, 0x0dab, - 0x0027, 0x13dc, 0x43a9, - 0x8323, 0xc1cd, 0xef5d, - 0xfffe, 0xef5d, 0xc1cd, - 0x8323, 0x43a9, 0x13dc, - 0x0027, 0x0dab, 0x38e3, - 0x7695, 0xb6b9, 0xe8a5, - 0xff60, 0xf503, 0xcc3e, - 0x8faa, 0x4f04, 0x1b17, - 0x0163, 0x0894, 0x2ecc, - 0x6a1d, 0xab1e, 0xe0ea, - 0xfd88, 0xf988, 0xd5f4, - 0x9c0a, 0x5ad7, 0x234c, - 0x03d6, 0x04a3, 0x257d, - 0x5ddc, 0x9f19, 0xd841, - 0xfa7b, 0xfce2, 0xded6, - 0xa825, 0x6706, 0x2c64, - 0x077b, 0x01e2, 0x1d0e, - 0x51ee, 0x92c7, 0xcebe, - 0xf640, 0xff08, 0xe6ce, - 0xb3de, 0x7373, 0x364b, - 0x0c4a, 0x0059, 0x1592, - 0x4673, 0x8647, 0xc479, - 0xf0e1, 0xfff4, 0xedc8, - 0xbf16, 0x7fff, 0x40e8, - 0x1236, 0x000a, 0x0f1d, - 0x3b85, 0x79b7, 0xb98b, - 0xea6c, 0xffa5, 0xf3b4, - 0xc9b3, 0x8c8b, 0x4c20, - 0x1930, 0x00f6, 0x09be, - 0x3140, 0x6d37, 0xae10, - 0xe2f0, 0xfe1c, 0xf883, - 0xd39a, 0x98f8, 0x57d9, - 0x2128, 0x031c, 0x0583, - 0x27bd, 0x60e5, 0xa222, - 0xda81, 0xfb5b, 0xfc28, - 0xdcb2, 0xa527, 0x63f4, - 0x2a0a, 0x0676, 0x0276, - 0x1f14, 0x54e0, 0x95e1, - 0xd132, 0xf76a, 0xfe9b, - 0xe4e7, 0xb0fa, 0x7054, - 0x33c0, 0x0afb, 0x009e, - 0x1759, 0x4945, 0x8969, - 0xc71b, 0xf253, 0xffd7, - 0xec22, 0xbc55, 0x7cdb, - 0x3e31, 0x10a1, 0x0000, - 0x10a1, 0x3e31, 0x7cdb, - 0xbc55, 0xec22, 0xffd7, - 0xf253, 0xc71b, 0x8969, - 0x4945, 0x1759, 0x009e, - 0x0afb, 0x33c0, 0x7054, - 0xb0fa, 0xe4e7, 0xfe9b, - 0xf76a, 0xd132, 0x95e1, - 0x54e0, 0x1f14, 0x0276, - 0x0676, 0x2a0a, 0x63f4, - 0xa527, 0xdcb2, 0xfc28, - 0xfb5b, 0xda81, 0xa222, - 0x60e5, 0x27bd, 0x0583, - 0x031c, 0x2128, 0x57d9, - 0x98f8, 0xd39a, 0xf883, - 0xfe1c, 0xe2f0, 0xae10, - 0x6d37, 0x3140, 0x09be, - 0x00f6, 0x1930, 0x4c20, - 0x8c8b, 0xc9b3, 0xf3b4, - 0xffa5, 0xea6c, 0xb98b, - 0x79b7, 0x3b85, 0x0f1d, - 0x000a, 0x1236, 0x40e8 -}; - -static const u16 cf_axi_dds_q_data[] = { - 0x0000, 0x10a1, 0x3e31, - 0x7cdb, 0xbc55, 0xec22, - 0xffd7, 0xf253, 0xc71b, - 0x8969, 0x4945, 0x1759, - 0x009e, 0x0afb, 0x33c0, - 0x7054, 0xb0fa, 0xe4e7, - 0xfe9b, 0xf76a, 0xd132, - 0x95e1, 0x54e0, 0x1f14, - 0x0276, 0x0676, 0x2a0a, - 0x63f4, 0xa527, 0xdcb2, - 0xfc28, 0xfb5b, 0xda81, - 0xa222, 0x60e5, 0x27bd, - 0x0583, 0x031c, 0x2128, - 0x57d9, 0x98f8, 0xd39a, - 0xf883, 0xfe1c, 0xe2f0, - 0xae10, 0x6d37, 0x3140, - 0x09be, 0x00f6, 0x1930, - 0x4c20, 0x8c8b, 0xc9b3, - 0xf3b4, 0xffa5, 0xea6c, - 0xb98b, 0x79b7, 0x3b85, - 0x0f1d, 0x000a, 0x1236, - 0x40e8, 0x7fff, 0xbf16, - 0xedc8, 0xfff4, 0xf0e1, - 0xc479, 0x8647, 0x4673, - 0x1592, 0x0059, 0x0c4a, - 0x364b, 0x7373, 0xb3de, - 0xe6ce, 0xff08, 0xf640, - 0xcebe, 0x92c7, 0x51ee, - 0x1d0e, 0x01e2, 0x077b, - 0x2c64, 0x6706, 0xa825, - 0xded6, 0xfce2, 0xfa7b, - 0xd841, 0x9f19, 0x5ddc, - 0x257d, 0x04a3, 0x03d6, - 0x234c, 0x5ad7, 0x9c0a, - 0xd5f4, 0xf988, 0xfd88, - 0xe0ea, 0xab1e, 0x6a1d, - 0x2ecc, 0x0894, 0x0163, - 0x1b17, 0x4f04, 0x8faa, - 0xcc3e, 0xf503, 0xff60, - 0xe8a5, 0xb6b9, 0x7695, - 0x38e3, 0x0dab, 0x0027, - 0x13dc, 0x43a9, 0x8323, - 0xc1cd, 0xef5d, 0xfffe, - 0xef5d, 0xc1cd, 0x8323, - 0x43a9, 0x13dc, 0x0027, - 0x0dab, 0x38e3, 0x7695, - 0xb6b9, 0xe8a5, 0xff60, - 0xf503, 0xcc3e, 0x8faa, - 0x4f04, 0x1b17, 0x0163, - 0x0894, 0x2ecc, 0x6a1d, - 0xab1e, 0xe0ea, 0xfd88, - 0xf988, 0xd5f4, 0x9c0a, - 0x5ad7, 0x234c, 0x03d6, - 0x04a3, 0x257d, 0x5ddc, - 0x9f19, 0xd841, 0xfa7b, - 0xfce2, 0xded6, 0xa825, - 0x6706, 0x2c64, 0x077b, - 0x01e2, 0x1d0e, 0x51ee, - 0x92c7, 0xcebe, 0xf640, - 0xff08, 0xe6ce, 0xb3de, - 0x7373, 0x364b, 0x0c4a, - 0x0059, 0x1592, 0x4673, - 0x8647, 0xc479, 0xf0e1, - 0xfff4, 0xedc8, 0xbf16, - 0x7fff, 0x40e8, 0x1236, - 0x000a, 0x0f1d, 0x3b85, - 0x79b7, 0xb98b, 0xea6c, - 0xffa5, 0xf3b4, 0xc9b3, - 0x8c8b, 0x4c20, 0x1930, - 0x00f6, 0x09be, 0x3140, - 0x6d37, 0xae10, 0xe2f0, - 0xfe1c, 0xf883, 0xd39a, - 0x98f8, 0x57d9, 0x2128, - 0x031c, 0x0583, 0x27bd, - 0x60e5, 0xa222, 0xda81, - 0xfb5b, 0xfc28, 0xdcb2, - 0xa527, 0x63f4, 0x2a0a, - 0x0676, 0x0276, 0x1f14, - 0x54e0, 0x95e1, 0xd132, - 0xf76a, 0xfe9b, 0xe4e7, - 0xb0fa, 0x7054, 0x33c0, - 0x0afb, 0x009e, 0x1759, - 0x4945, 0x8969, 0xc71b, - 0xf253, 0xffd7, 0xec22, - 0xbc55, 0x7cdb, 0x3e31, - 0x10a1, 0x0000, 0x10a1, - 0x3e31, 0x7cdb, 0xbc55, - 0xec22, 0xffd7, 0xf253, - 0xc71b, 0x8969, 0x4945, - 0x1759, 0x009e, 0x0afb, - 0x33c0, 0x7054, 0xb0fa, - 0xe4e7, 0xfe9b, 0xf76a, - 0xd132, 0x95e1, 0x54e0, - 0x1f14, 0x0276, 0x0676, - 0x2a0a, 0x63f4, 0xa527, - 0xdcb2, 0xfc28, 0xfb5b, - 0xda81, 0xa222, 0x60e5, - 0x27bd, 0x0583, 0x031c, - 0x2128, 0x57d9, 0x98f8, - 0xd39a, 0xf883, 0xfe1c, - 0xe2f0, 0xae10, 0x6d37, - 0x3140, 0x09be, 0x00f6, - 0x1930, 0x4c20, 0x8c8b, - 0xc9b3, 0xf3b4, 0xffa5, - 0xea6c, 0xb98b, 0x79b7, - 0x3b85, 0x0f1d, 0x000a, - 0x1236, 0x40e8, 0x7fff, - 0xbf16, 0xedc8, 0xfff4, - 0xf0e1, 0xc479, 0x8647, - 0x4673, 0x1592, 0x0059, - 0x0c4a, 0x364b, 0x7373, - 0xb3de, 0xe6ce, 0xff08, - 0xf640, 0xcebe, 0x92c7, - 0x51ee, 0x1d0e, 0x01e2, - 0x077b, 0x2c64, 0x6706, - 0xa825, 0xded6, 0xfce2, - 0xfa7b, 0xd841, 0x9f19, - 0x5ddc, 0x257d, 0x04a3, - 0x03d6, 0x234c, 0x5ad7, - 0x9c0a, 0xd5f4, 0xf988, - 0xfd88, 0xe0ea, 0xab1e, - 0x6a1d, 0x2ecc, 0x0894, - 0x0163, 0x1b17, 0x4f04, - 0x8faa, 0xcc3e, 0xf503, - 0xff60, 0xe8a5, 0xb6b9, - 0x7695, 0x38e3, 0x0dab, - 0x0027, 0x13dc, 0x43a9, - 0x8323, 0xc1cd, 0xef5d, - 0xfffe, 0xef5d, 0xc1cd, - 0x8323, 0x43a9, 0x13dc, - 0x0027, 0x0dab, 0x38e3, - 0x7695, 0xb6b9, 0xe8a5, - 0xff60, 0xf503, 0xcc3e, - 0x8faa, 0x4f04, 0x1b17, - 0x0163, 0x0894, 0x2ecc, - 0x6a1d, 0xab1e, 0xe0ea, - 0xfd88, 0xf988, 0xd5f4, - 0x9c0a, 0x5ad7, 0x234c, - 0x03d6, 0x04a3, 0x257d, - 0x5ddc, 0x9f19, 0xd841, - 0xfa7b, 0xfce2, 0xded6, - 0xa825, 0x6706, 0x2c64, - 0x077b, 0x01e2, 0x1d0e, - 0x51ee, 0x92c7, 0xcebe, - 0xf640, 0xff08, 0xe6ce, - 0xb3de, 0x7373, 0x364b, - 0x0c4a, 0x0059, 0x1592, - 0x4673, 0x8647, 0xc479, - 0xf0e1, 0xfff4, 0xedc8, - 0xbf16, 0x7fff, 0x40e8, - 0x1236, 0x000a, 0x0f1d, - 0x3b85, 0x79b7, 0xb98b, - 0xea6c, 0xffa5, 0xf3b4, - 0xc9b3, 0x8c8b, 0x4c20, - 0x1930, 0x00f6, 0x09be, - 0x3140, 0x6d37, 0xae10, - 0xe2f0, 0xfe1c, 0xf883, - 0xd39a, 0x98f8, 0x57d9, - 0x2128, 0x031c, 0x0583, - 0x27bd, 0x60e5, 0xa222, - 0xda81, 0xfb5b, 0xfc28, - 0xdcb2, 0xa527, 0x63f4, - 0x2a0a, 0x0676, 0x0276, - 0x1f14, 0x54e0, 0x95e1, - 0xd132, 0xf76a, 0xfe9b, - 0xe4e7, 0xb0fa, 0x7054, - 0x33c0, 0x0afb, 0x009e, - 0x1759, 0x4945, 0x8969, - 0xc71b, 0xf253, 0xffd7, - 0xec22, 0xbc55, 0x7cdb, - 0x3e31, 0x10a1, 0x0000, - 0x10a1, 0x3e31, 0x7cdb, - 0xbc55, 0xec22, 0xffd7, - 0xf253, 0xc71b, 0x8969, - 0x4945, 0x1759, 0x009e, - 0x0afb, 0x33c0, 0x7054, - 0xb0fa, 0xe4e7, 0xfe9b, - 0xf76a, 0xd132, 0x95e1, - 0x54e0, 0x1f14, 0x0276, - 0x0676, 0x2a0a, 0x63f4, - 0xa527, 0xdcb2, 0xfc28, - 0xfb5b, 0xda81, 0xa222, - 0x60e5, 0x27bd, 0x0583, - 0x031c, 0x2128, 0x57d9, - 0x98f8, 0xd39a, 0xf883, - 0xfe1c, 0xe2f0, 0xae10, - 0x6d37, 0x3140, 0x09be, - 0x00f6, 0x1930, 0x4c20, - 0x8c8b, 0xc9b3, 0xf3b4, - 0xffa5, 0xea6c, 0xb98b, - 0x79b7, 0x3b85, 0x0f1d, - 0x000a, 0x1236, 0x40e8, - 0x7fff, 0xbf16, 0xedc8, - 0xfff4, 0xf0e1, 0xc479, - 0x8647, 0x4673, 0x1592, - 0x0059, 0x0c4a, 0x364b, - 0x7373, 0xb3de, 0xe6ce, - 0xff08, 0xf640, 0xcebe, - 0x92c7, 0x51ee, 0x1d0e, - 0x01e2, 0x077b, 0x2c64, - 0x6706, 0xa825, 0xded6, - 0xfce2, 0xfa7b, 0xd841, - 0x9f19, 0x5ddc, 0x257d, - 0x04a3, 0x03d6, 0x234c, - 0x5ad7, 0x9c0a, 0xd5f4, - 0xf988, 0xfd88, 0xe0ea, - 0xab1e, 0x6a1d, 0x2ecc, - 0x0894, 0x0163, 0x1b17, - 0x4f04, 0x8faa, 0xcc3e, - 0xf503, 0xff60, 0xe8a5, - 0xb6b9, 0x7695, 0x38e3, - 0x0dab, 0x0027, 0x13dc, - 0x43a9, 0x8323, 0xc1cd, - 0xef5d, 0xfffe, 0xef5d, - 0xc1cd, 0x8323, 0x43a9, - 0x13dc, 0x0027, 0x0dab, - 0x38e3, 0x7695, 0xb6b9, - 0xe8a5, 0xff60, 0xf503, - 0xcc3e, 0x8faa, 0x4f04, - 0x1b17, 0x0163, 0x0894, - 0x2ecc, 0x6a1d, 0xab1e, - 0xe0ea, 0xfd88, 0xf988, - 0xd5f4, 0x9c0a, 0x5ad7, - 0x234c, 0x03d6, 0x04a3, - 0x257d, 0x5ddc, 0x9f19, - 0xd841, 0xfa7b, 0xfce2, - 0xded6, 0xa825, 0x6706, - 0x2c64, 0x077b, 0x01e2, - 0x1d0e, 0x51ee, 0x92c7, - 0xcebe, 0xf640, 0xff08, - 0xe6ce, 0xb3de, 0x7373, - 0x364b, 0x0c4a, 0x0059, - 0x1592, 0x4673, 0x8647, - 0xc479, 0xf0e1, 0xfff4, - 0xedc8, 0xbf16, 0x7fff, - 0x40e8, 0x1236, 0x000a, - 0x0f1d, 0x3b85, 0x79b7, - 0xb98b, 0xea6c, 0xffa5, - 0xf3b4, 0xc9b3, 0x8c8b, - 0x4c20, 0x1930, 0x00f6, - 0x09be, 0x3140, 0x6d37, - 0xae10, 0xe2f0, 0xfe1c, - 0xf883, 0xd39a, 0x98f8, - 0x57d9, 0x2128, 0x031c, - 0x0583, 0x27bd, 0x60e5, - 0xa222, 0xda81, 0xfb5b, - 0xfc28, 0xdcb2, 0xa527, - 0x63f4, 0x2a0a, 0x0676, - 0x0276, 0x1f14, 0x54e0, - 0x95e1, 0xd132, 0xf76a, - 0xfe9b, 0xe4e7, 0xb0fa, - 0x7054, 0x33c0, 0x0afb, - 0x009e, 0x1759, 0x4945, - 0x8969, 0xc71b, 0xf253, - 0xffd7, 0xec22, 0xbc55, - 0x7cdb, 0x3e31, 0x10a1 -}; - -#endif /* CF_AXI_DDS_WAVDATA */ #endif /* ADI_AXI_DDS_H_ */ diff --git a/drivers/iio/frequency/cf_axi_dds_buffer.c b/drivers/iio/frequency/cf_axi_dds_buffer.c index 8adc085df819e..c978491ea7921 100644 --- a/drivers/iio/frequency/cf_axi_dds_buffer.c +++ b/drivers/iio/frequency/cf_axi_dds_buffer.c @@ -133,12 +133,13 @@ static int __cf_axi_dds_hw_buffer_state_set(struct iio_dev *indio_dev, bool stat struct dma_async_tx_descriptor *desc; unsigned tmp_reg, x; +#if 0 tmp_reg = dds_read(st, CF_AXI_DDS_DMA_STAT); if (tmp_reg & (CF_AXI_DDS_DMA_STAT_OVF | CF_AXI_DDS_DMA_STAT_UNF)) dev_warn(indio_dev->dev.parent, "VDMA Status: %s %s\n", (tmp_reg & CF_AXI_DDS_DMA_STAT_OVF) ? "overflow" : "", (tmp_reg & CF_AXI_DDS_DMA_STAT_OVF) ? "underflow" : ""); - +#endif tmp_reg = dds_read(st, CF_AXI_DDS_CTRL); if (!state) { @@ -155,7 +156,8 @@ static int __cf_axi_dds_hw_buffer_state_set(struct iio_dev *indio_dev, bool stat tmp_reg = CF_AXI_DDS_CTRL_DDS_SEL | CF_AXI_DDS_CTRL_DATA_EN | - CF_AXI_DDS_CTRL_DDS_CLK_EN_V2; + CF_AXI_DDS_CTRL_DDS_CLK_EN_V2 | + st->ddr_dds_interp_en; x = DIV_ROUND_UP(st->txcount, (VDMA_MAX_VSIZE + 1) * 8); From 8ea3495889173158b47dac9d0c3314e41849c307 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 4 Dec 2012 13:38:01 +0100 Subject: [PATCH 222/261] iio: frequency: New driver AD9517 SPI Clock Generator with integrated VCO Signed-off-by: Michael Hennerich --- drivers/iio/frequency/Kconfig | 10 + drivers/iio/frequency/Makefile | 1 + drivers/iio/frequency/ad9517.c | 676 +++++++++++++++++++++++++++++++++ 3 files changed, 687 insertions(+) create mode 100644 drivers/iio/frequency/ad9517.c diff --git a/drivers/iio/frequency/Kconfig b/drivers/iio/frequency/Kconfig index 51292bd080cba..58da849d45bf6 100644 --- a/drivers/iio/frequency/Kconfig +++ b/drivers/iio/frequency/Kconfig @@ -29,6 +29,16 @@ config AD9548 To compile this driver as a module, choose M here: the module will be called ad9548. +config AD9517 + tristate "Analog Devices AD9517 12-Output Clock Generator" + depends on SPI + help + Say yes here to build support for Analog Devices AD9517 + 12-Output Clock Generator. + + To compile this driver as a module, choose M here: the + module will be called ad9517. + endmenu menu "Direct Digital Synthesis" diff --git a/drivers/iio/frequency/Makefile b/drivers/iio/frequency/Makefile index f6f5e533529db..ec84635078d83 100644 --- a/drivers/iio/frequency/Makefile +++ b/drivers/iio/frequency/Makefile @@ -2,6 +2,7 @@ # Makefile iio/frequency # +obj-$(CONFIG_AD9517) += ad9517.o obj-$(CONFIG_AD9548) += ad9548.o obj-$(CONFIG_AD9523) += ad9523.o obj-$(CONFIG_ADF4350) += adf4350.o diff --git a/drivers/iio/frequency/ad9517.c b/drivers/iio/frequency/ad9517.c new file mode 100644 index 0000000000000..2d632bf148e89 --- /dev/null +++ b/drivers/iio/frequency/ad9517.c @@ -0,0 +1,676 @@ +/* + * AD9517 SPI Clock Generator with integrated VCO + * + * Copyright 2012 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#define FIRMWARE "ad9517.stp" + +#define AD_READ (1 << 15) +#define AD_WRITE (0 << 15) +#define AD_CNT(x) (((x) - 1) << 13) +#define AD_ADDR(x) ((x) & 0xFFF) + +/* +* AD9517-X Registers +*/ +#define AD9517_SERCONF 0x00 +#define AD9517_PARTID 0x03 +#define AD9517_RB_CTL 0x04 +#define AD9517_PFD_CP 0x10 +#define AD9517_RCNT_L 0x11 +#define AD9517_RCNT_H 0x12 +#define AD9517_ACNT 0x13 +#define AD9517_BCNT_L 0x14 +#define AD9517_BCNT_H 0x15 +#define AD9517_PLL1 0x16 +#define AD9517_PLL2 0x17 +#define AD9517_PLL3 0x18 +#define AD9517_PLL4 0x19 +#define AD9517_PLL5 0x1A +#define AD9517_PLL6 0x1B +#define AD9517_PLL7 0x1C +#define AD9517_PLL8 0x1D +#define AD9517_PLL9 0x1E +#define AD9517_PLL_RB 0x1F + +#define AD9517_OUT4_DELAY_BP 0xA0 +#define AD9517_OUT4_DELAY_FS 0xA1 +#define AD9517_OUT4_DELAY_FR 0xA2 +#define AD9517_OUT5_DELAY_BP 0xA3 +#define AD9517_OUT5_DELAY_FS 0xA4 +#define AD9517_OUT5_DELAY_FR 0xA5 +#define AD9517_OUT6_DELAY_BP 0xA6 +#define AD9517_OUT6_DELAY_FS 0xA7 +#define AD9517_OUT6_DELAY_FR 0xA8 +#define AD9517_OUT7_DELAY_BP 0xA9 +#define AD9517_OUT7_DELAY_FS 0xAA +#define AD9517_OUT7_DELAY_FR 0xAB + +#define AD9517_OUT0_LVPECL 0xF0 +#define AD9517_OUT1_LVPECL 0xF1 +#define AD9517_OUT2_LVPECL 0xF4 +#define AD9517_OUT3_LVPECL 0xF5 + +#define AD9517_OUT4_LVCMOS 0x140 +#define AD9517_OUT5_LVCMOS 0x141 +#define AD9517_OUT6_LVCMOS 0x142 +#define AD9517_OUT7_LVCMOS 0x143 + +/* LVPECL Channel Dividers */ +#define AD9517_PECLDIV0_1 0x190 +#define AD9517_PECLDIV0_2 0x191 +#define AD9517_PECLDIV0_3 0x192 +#define AD9517_PECLDIV1_1 0x196 +#define AD9517_PECLDIV1_2 0x197 +#define AD9517_PECLDIV1_3 0x198 + +/* LVDS/CMOS Channel Dividers */ +#define AD9517_CMOSDIV2_1 0x199 +#define AD9517_CMOSDIV2_1_PHO 0x19A +#define AD9517_CMOSDIV2_2 0x19B +#define AD9517_CMOSDIV2_BYPASS 0x19C +#define AD9517_CMOSDIV2_DCCOFF 0x19D +#define AD9517_CMOSDIV3_1 0x19E +#define AD9517_CMOSDIV3_PHO 0x19F +#define AD9517_CMOSDIV3_2 0x1A0 +#define AD9517_CMOSDIV3_BYPASS 0x1A1 +#define AD9517_CMOSDIV3_DCCOFF 0x1A2 + +/* VCO Divider and CLK Input */ +#define AD9517_VCO_DIVIDER 0x1E0 +#define AD9517_INPUT_CLKS 0x1E1 +#define AD9517_POWDOWN_SYNC 0x230 + +/* Update All Registers */ +#define AD9517_TRANSFER 0x232 + +#define AD9517_PLL3_VCO_CAL (1 << 0) +#define AD9517_TRANSFER_NOW (1 << 0) +#define AD9517_PLL1_BCNT_BP (1 << 3) +#define AD9517_VCO_DIVIDER_BP (1 << 0) +#define AD9517_VCO_DIVIDER_SEL (1 << 1) +#define AD9517_PECLDIV_VCO_SEL (1 << 1) +#define AD9517_PECLDIV_3_BP (1 << 7) +#define AD9517_CMOSDIV_BYPASS_2 (1 << 5) +#define AD9517_CMOSDIV_BYPASS_1 (1 << 4) +#define AD9517_SOFT_RESET (0x24) +#define AD9517_SDO_ACTIVE (0x81) +#define AD9517_LONG_INSTR (0x18) + +enum outputs { + OUT_0, + OUT_1, + OUT_2, + OUT_3, + OUT_4, + OUT_5, + OUT_6, + OUT_7, + NUM_OUTPUTS, +}; + +#define AD9517_REG(addr, val) ((addr << 16) | (val & 0xFF)) + +struct ad9517_platform_data { + unsigned long *regs; + unsigned num_regs; +}; + +struct ad9517_outputs { + struct ad9517_state *st; + struct clk_hw hw; + unsigned long freq; + const char *parent_name; + bool is_enabled; + unsigned char pwrdwn_reg; + unsigned char pwrdwn_bit; + +}; + +struct ad9517_state { + struct spi_device *spi; + unsigned char regs[AD9517_TRANSFER]; + struct ad9517_outputs output[NUM_OUTPUTS]; + unsigned long refin_freq; + unsigned long clkin_freq; + char *div0123_clk_parent_name; + char *vco_divin_clk_parent_name; +}; + +#define IS_FD (1 << 7) +#define AD9517_PLL1_PRESCALER_MASK 0x7 +static const unsigned char to_prescaler[] = { + 1 | IS_FD, + 2 | IS_FD, + 2, + 4, + 8, + 16, + 32, + 3 | IS_FD, +}; + +enum { + PWRDWN_REG, + PWRDWN_MASK, + PWRDWN_BIT, +}; + +static const unsigned short output_pwrdwn_lut[NUM_OUTPUTS][3] = { + {AD9517_OUT0_LVPECL, 0x3, 1}, + {AD9517_OUT1_LVPECL, 0x3, 1}, + {AD9517_OUT2_LVPECL, 0x3, 1}, + {AD9517_OUT3_LVPECL, 0x3, 1}, + {AD9517_OUT4_LVCMOS, 0x1, 0}, + {AD9517_OUT5_LVCMOS, 0x1, 0}, + {AD9517_OUT6_LVCMOS, 0x1, 0}, + {AD9517_OUT7_LVCMOS, 0x1, 0}, +}; + +#define to_ad9517_clk_output(_hw) container_of(_hw, struct ad9517_outputs, hw) + +static int ad9517_read(struct spi_device *spi, unsigned reg) +{ + unsigned char buf[3]; + int ret; + u16 cmd; + + cmd = AD_READ | AD_CNT(1) | AD_ADDR(reg); + buf[0] = cmd >> 8; + buf[1] = cmd & 0xFF; + + + ret = spi_write_then_read(spi, &buf[0], 2, &buf[2], 1); + if (ret < 0) + return ret; + + return buf[2]; +} + +static int ad9517_write(struct spi_device *spi, + unsigned reg, unsigned val) +{ + unsigned char buf[3]; + int ret; + u16 cmd; + + cmd = AD_WRITE | AD_CNT(1) | AD_ADDR(reg); + buf[0] = cmd >> 8; + buf[1] = cmd & 0xFF; + buf[2] = val; + + ret = spi_write(spi, buf, 3); + if (ret < 0) + return ret; + + return 0; +} + +static int ad9517_parse_firmware(struct ad9517_state *st, + char *data, unsigned size) +{ + char *line; + int ret; + unsigned addr, val1, val2; + + while ((line = strsep(&data, "\n"))) { + if (line >= data + size) + break; + + ret = sscanf(line, "\"%x\",\"%x\",\"%x\"", &addr, &val1, &val2); + if (ret == 3) { + if (addr > AD9517_TRANSFER) + return -EINVAL; + st->regs[addr] = val2 & 0xFF; + } + } + return 0; +} + +static int ad9517_parse_pdata(struct ad9517_state *st, + struct ad9517_platform_data *pdata) +{ + int i; + unsigned addr; + + if (!pdata->num_regs | (pdata->num_regs > AD9517_TRANSFER)) + return -EINVAL; + + for (i = 0; i < pdata->num_regs; i++) { + addr = pdata->regs[i] >> 16; + if (addr > AD9517_TRANSFER) + return -EINVAL; + st->regs[addr] = pdata->regs[i] & 0xFF; + } + return 0; +} + +static int ad9517_setup(struct ad9517_state *st) +{ + struct spi_device *spi = st->spi; + int ret, reg; + unsigned cal_delay_ms, d1, d2; + unsigned long pll_a_cnt, pll_b_cnt, pll_r_cnt, prescaler; + unsigned long vco_freq; + unsigned long vco_divin_freq; + unsigned long div0123_freq; + + /* Setup PLL */ + for (reg = AD9517_PFD_CP; reg <= AD9517_PLL8; reg++) { + ret = ad9517_write(spi, reg, st->regs[reg]); + if (ret < 0) + return ret; + } + + /* Setup fine delay adjust OUT4..OUT7 */ + for (reg = AD9517_OUT4_DELAY_BP; reg <= AD9517_OUT7_DELAY_FR; reg++) { + ret = ad9517_write(spi, reg, st->regs[reg]); + if (ret < 0) + return ret; + } + + /* Setup LVPECL outputs OUT0..OUT3 */ + for (reg = AD9517_OUT0_LVPECL; reg <= AD9517_OUT3_LVPECL; reg++) { + ret = ad9517_write(spi, reg, st->regs[reg]); + if (ret < 0) + return ret; + } + + /* Setup LVCMOS outputs OUT4..OUT7 */ + for (reg = AD9517_OUT4_LVCMOS; reg <= AD9517_OUT7_LVCMOS; reg++) { + ret = ad9517_write(spi, reg, st->regs[reg]); + if (ret < 0) + return ret; + } + + /* Setup PECL Channel Dividers */ + for (reg = AD9517_PECLDIV0_1; reg <= AD9517_PECLDIV1_3; reg++) { + ret = ad9517_write(spi, reg, st->regs[reg]); + if (ret < 0) + return ret; + } + + /* Setup LVDS/CMOS Channel Dividers */ + for (reg = AD9517_CMOSDIV2_1; reg <= AD9517_CMOSDIV3_DCCOFF; reg++) { + ret = ad9517_write(spi, reg, st->regs[reg]); + if (ret < 0) + return ret; + } + + /* Setup VCO Divier and CLK Input */ + ret = ad9517_write(spi, AD9517_VCO_DIVIDER, + st->regs[AD9517_VCO_DIVIDER]); + if (ret < 0) + return ret; + + ret = ad9517_write(spi, AD9517_INPUT_CLKS, st->regs[AD9517_INPUT_CLKS]); + if (ret < 0) + return ret; + + /* Setup System */ + ret = ad9517_write(spi, AD9517_POWDOWN_SYNC, + st->regs[AD9517_POWDOWN_SYNC]); + if (ret < 0) + return ret; + + ret = ad9517_write(spi, AD9517_PLL3, + st->regs[AD9517_PLL3] & ~AD9517_PLL3_VCO_CAL); + if (ret < 0) + return ret; + + /* Update all registers */ + ret = ad9517_write(spi, AD9517_TRANSFER, AD9517_TRANSFER_NOW); + if (ret < 0) + return ret; + + /* Calibrate VCO */ + ret = ad9517_write(spi, AD9517_PLL3, + st->regs[AD9517_PLL3] | AD9517_PLL3_VCO_CAL); + if (ret < 0) + return ret; + + /* Update all registers */ + ret = ad9517_write(spi, AD9517_TRANSFER, AD9517_TRANSFER_NOW); + if (ret < 0) + return ret; + + /* Get PLL settings */ + pll_r_cnt = st->regs[AD9517_RCNT_H] << 8 | st->regs[AD9517_RCNT_L]; + pll_a_cnt = st->regs[AD9517_ACNT]; + pll_b_cnt = st->regs[AD9517_BCNT_H] << 8 | st->regs[AD9517_BCNT_L]; + + if (st->regs[AD9517_PLL1] & AD9517_PLL1_BCNT_BP) + pll_b_cnt = 1; + + prescaler = to_prescaler[st->regs[AD9517_PLL1] & + AD9517_PLL1_PRESCALER_MASK]; + + if (prescaler & IS_FD) + pll_a_cnt = 0; + + prescaler &= ~IS_FD; + + vco_freq = (st->refin_freq * (prescaler * + pll_b_cnt + pll_a_cnt)) / pll_r_cnt; + + /* tcal = 4400 * Rdiv * cal_div / Refin */ + cal_delay_ms = (4400 * pll_r_cnt * + (2 << ((st->regs[AD9517_PLL3] >> 1) & 0x3))) / + (st->refin_freq / 1000); + + msleep(cal_delay_ms); + + /* Internal clock distribution */ + + if (st->regs[AD9517_INPUT_CLKS] & AD9517_VCO_DIVIDER_SEL) { + if (!vco_freq) + return -EINVAL; + vco_divin_freq = vco_freq; + st->vco_divin_clk_parent_name = "refclk"; + } else { + if (!st->clkin_freq) + return -EINVAL; + vco_divin_freq = st->clkin_freq; + st->vco_divin_clk_parent_name = "clkin"; + } + + if (st->regs[AD9517_INPUT_CLKS] & AD9517_VCO_DIVIDER_BP) { + if (!st->clkin_freq) + return -EINVAL; + div0123_freq = st->clkin_freq; + st->div0123_clk_parent_name = "clkin"; + } else { + div0123_freq = vco_divin_freq / + ((st->regs[AD9517_VCO_DIVIDER] & 0x7) + 2); + st->div0123_clk_parent_name = st->vco_divin_clk_parent_name; + } + + /* Outputs */ + /* 0..1 */ + + if (st->regs[AD9517_PECLDIV0_3] & AD9517_PECLDIV_VCO_SEL) { + st->output[OUT_0].freq = + st->output[OUT_1].freq = + vco_divin_freq; + st->output[OUT_0].parent_name = + st->output[OUT_1].parent_name = + st->vco_divin_clk_parent_name; + } else { + if (st->regs[AD9517_PECLDIV0_2] & AD9517_PECLDIV_3_BP) + d1 = 1; + else + d1 = (st->regs[AD9517_PECLDIV0_1] & 0xF) + + (st->regs[AD9517_PECLDIV0_1] >> 4) + 2; + + st->output[OUT_0].freq = + st->output[OUT_1].freq = + div0123_freq / d1; + + st->output[OUT_0].parent_name = + st->output[OUT_1].parent_name = + st->div0123_clk_parent_name; + } + + /* 2..3 */ + + if (st->regs[AD9517_PECLDIV1_3] & AD9517_PECLDIV_VCO_SEL) { + st->output[OUT_2].freq = + st->output[OUT_3].freq = + vco_divin_freq; + st->output[OUT_2].parent_name = + st->output[OUT_3].parent_name = + st->vco_divin_clk_parent_name; + } else { + if (st->regs[AD9517_PECLDIV1_2] & AD9517_PECLDIV_3_BP) + d1 = 1; + else + d1 = (st->regs[AD9517_PECLDIV1_1] & 0xF) + + (st->regs[AD9517_PECLDIV1_1] >> 4) + 2; + + st->output[OUT_2].freq = + st->output[OUT_3].freq = + div0123_freq / d1; + + st->output[OUT_2].parent_name = + st->output[OUT_3].parent_name = + st->div0123_clk_parent_name; + } + + /* 4..5 */ + + if (st->regs[AD9517_CMOSDIV2_BYPASS] & AD9517_CMOSDIV_BYPASS_1) + d1 = 1; + else + d1 = (st->regs[AD9517_CMOSDIV2_1] & 0xF) + + (st->regs[AD9517_CMOSDIV2_1] >> 4) + 2; + + if (st->regs[AD9517_CMOSDIV2_BYPASS] & AD9517_CMOSDIV_BYPASS_2) + d2 = 1; + else + d2 = (st->regs[AD9517_CMOSDIV2_2] & 0xF) + + (st->regs[AD9517_CMOSDIV2_2] >> 4) + 2; + + st->output[OUT_4].freq = + st->output[OUT_5].freq = + div0123_freq / (d1 * d2); + + st->output[OUT_4].parent_name = + st->output[OUT_5].parent_name = + st->div0123_clk_parent_name; + + /* 6..7 */ + + if (st->regs[AD9517_CMOSDIV3_BYPASS] & AD9517_CMOSDIV_BYPASS_1) + d1 = 1; + else + d1 = (st->regs[AD9517_CMOSDIV3_1] & 0xF) + + (st->regs[AD9517_CMOSDIV3_1] >> 4) + 2; + + if (st->regs[AD9517_CMOSDIV3_BYPASS] & AD9517_CMOSDIV_BYPASS_2) + d2 = 1; + else + d2 = (st->regs[AD9517_CMOSDIV3_2] & 0xF) + + (st->regs[AD9517_CMOSDIV3_2] >> 4) + 2; + + st->output[OUT_6].freq = + st->output[OUT_7].freq = + div0123_freq / (d1 * d2); + + st->output[OUT_6].parent_name = + st->output[OUT_7].parent_name = + st->div0123_clk_parent_name; + + return 0; +} + +static unsigned long ad9517_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return to_ad9517_clk_output(hw)->freq; +} + +static int ad9517_is_enabled(struct clk_hw *hw) +{ + return to_ad9517_clk_output(hw)->is_enabled; +} + +const struct clk_ops ad9517_clk_ops = { + .recalc_rate = ad9517_recalc_rate, + .is_enabled = ad9517_is_enabled, +}; + +struct clk *ad9517_clk_register(struct ad9517_state *st, unsigned num) +{ + struct clk_init_data init; + struct ad9517_outputs *output = &st->output[num]; + struct clk *clk; + char name[8]; + + sprintf(name, "out%d", num); + + init.name = name; + init.ops = &ad9517_clk_ops; + init.parent_names = &output->parent_name; + init.num_parents = 1; + + output->hw.init = &init; + output->st = st; + + /* register the clock */ + clk = clk_register(&st->spi->dev, &output->hw); + + if (!IS_ERR(clk)) + of_clk_add_provider(st->spi->dev.of_node, + of_clk_src_simple_get, clk); + + return clk; +} + +static int __devinit ad9517_probe(struct spi_device *spi) +{ + struct ad9517_platform_data *pdata = spi->dev.platform_data; + int out, ret, conf; + const struct firmware *fw; + struct ad9517_state *st; + struct clk *clk, *ref_clk, *clkin; + + st = devm_kzalloc(&spi->dev, sizeof(*st), GFP_KERNEL); + if (!st) { + dev_err(&spi->dev, "Not enough memory for device\n"); + return -ENOMEM; + } + + conf = AD9517_LONG_INSTR | + (spi->mode & SPI_3WIRE ? 0 : AD9517_SDO_ACTIVE); + + ret = ad9517_write(spi, AD9517_SERCONF, conf | AD9517_SOFT_RESET); + if (ret < 0) + return ret; + + ret = ad9517_write(spi, AD9517_SERCONF, conf); + if (ret < 0) + return ret; + + ret = ad9517_read(spi, AD9517_PARTID); + if (ret < 0) + return ret; + if (ret != spi_get_device_id(spi)->driver_data) { + dev_err(&spi->dev, "Unrecognized CHIP_ID 0x%X\n", ret); + return -ENODEV; + } + + if (!pdata) { + ret = request_firmware(&fw, FIRMWARE, &spi->dev); + if (ret) { + dev_err(&spi->dev, + "request_firmware() failed with %i\n", ret); + return ret; + } + ad9517_parse_firmware(st, (u8 *) fw->data, fw->size); + release_firmware(fw); + } else { + ret = ad9517_parse_pdata(st, pdata); + if (ret < 0) { + dev_err(&spi->dev, + "parse pdata failed with %i\n", ret); + return ret; + } + } + + st->spi = spi; + ref_clk = clk_get(&spi->dev, "refclk"); + clkin = clk_get(&spi->dev, "clkin"); + + if (IS_ERR(ref_clk) && IS_ERR(clkin)) { + ret = PTR_ERR(ref_clk); + dev_err(&spi->dev, "failed getting clock (%d)\n", ret); + goto out; + } + + + if (IS_ERR(ref_clk)) { + ret = PTR_ERR(ref_clk); + dev_warn(&spi->dev, "failed getting clock (%d)\n", ret); + } else { + st->refin_freq = clk_get_rate(ref_clk); + } + + if (IS_ERR(clkin)) { + ret = PTR_ERR(clkin); + dev_warn(&spi->dev, "failed getting clock (%d)\n", ret); + goto out; + } else { + st->clkin_freq = clk_get_rate(clkin); + } + + ret = ad9517_setup(st); + if (ret < 0) + return ret; + + for (out = 0; out < NUM_OUTPUTS; out++) { + st->output[out].is_enabled = + !(st->regs[output_pwrdwn_lut[out][PWRDWN_REG]] & + output_pwrdwn_lut[out][PWRDWN_MASK]); + clk = ad9517_clk_register(st, out); + if (IS_ERR(clk)) + return PTR_ERR(clk); + } + + spi_set_drvdata(spi, NULL); + dev_info(&spi->dev, "probed\n"); + +out: + return 0; +} + +static int ad9517_remove(struct spi_device *spi) +{ + spi_set_drvdata(spi, NULL); + + return 0; +} + +static const struct spi_device_id ad9517_id[] = { + {"ad9517-0", 0x11}, + {"ad9517-1", 0x51}, + {"ad9517-2", 0x91}, + {"ad9517-3", 0x53}, + {"ad9517-4", 0xD3}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad9517_id); + +static struct spi_driver ad9517_driver = { + .driver = { + .name = "ad9517", + .owner = THIS_MODULE, + }, + .probe = ad9517_probe, + .remove = __devexit_p(ad9517_remove), + .id_table = ad9517_id, +}; +module_spi_driver(ad9517_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD9517"); +MODULE_LICENSE("GPL v2"); From b2df6594a47fc0d5a254fbd71294dbdeaed9a727 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 4 Dec 2012 13:41:31 +0100 Subject: [PATCH 223/261] spi: New Analog Devices AD9250-FMC-250EBZ SPI-SPI-bridge driver This driver adds support for the SPI-SPI bridge CPLD found on the Analog Devices AD9250-FMC-250EBZ and 4DSP FMC176 and FMX230 FMC cards. Signed-off-by: Michael Hennerich --- drivers/spi/Kconfig | 6 ++ drivers/spi/Makefile | 1 + drivers/spi/spi-ad9250fmc.c | 162 ++++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 drivers/spi/spi-ad9250fmc.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index ab4f4e1f946e1..b076830833fbb 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -390,6 +390,12 @@ config SPI_XCOMM help Support for the SPI-I2C-bridge IC found on the ADI Xcomm board. +config SPI_AD9250FMC + tristate "Analog Devices AD9250-FMC-250EBZ SPI-SPI-bridge driver" + help + Support for the SPI-SPI bridge CPLD found on the Analog Devices + AD9250-FMC-250EBZ and 4DSP FMC176 and FMX230 FMC cards. + config SPI_XILINX tristate "Xilinx SPI controller common module" depends on HAS_IOMEM && EXPERIMENTAL diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index c345085f59018..8d4cc1233111a 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -62,6 +62,7 @@ obj-$(CONFIG_SPI_TLE62X0) += spi-tle62x0.o obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o obj-$(CONFIG_SPI_TXX9) += spi-txx9.o obj-$(CONFIG_SPI_XCOMM) += spi-xcomm.o +obj-$(CONFIG_SPI_AD9250FMC) += spi-ad9250fmc.o obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o obj-$(CONFIG_SPI_XILINX_PS_SPI) += spi-xilinx-ps.o obj-$(CONFIG_SPI_XILINX_PS_QSPI) += spi-xilinx-qps.o diff --git a/drivers/spi/spi-ad9250fmc.c b/drivers/spi/spi-ad9250fmc.c new file mode 100644 index 0000000000000..1d3f67aec49e0 --- /dev/null +++ b/drivers/spi/spi-ad9250fmc.c @@ -0,0 +1,162 @@ +/* + * Analog Devices AD9250-FMC-250EBZ board SPI-SPI CPLD demux driver + * + * Copyright 2012 Analog Devices Inc. + * Author: Michael Hennerich + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define FMC_CPLD 0x00 /* chip_select 0 */ +#define FMC_AD9517 0x84 /* chip_select 1 */ +#define FMC_AD9250_0 0x80 /* chip_select 2 */ +#define FMC_AD9250_1 0x81 /* chip_select 3 */ +#define FMC_AD9129_0 0x82 /* chip_select 4 */ +#define FMC_AD9129_1 0x83 /* chip_select 5 */ +#define FMC_NUM_SLAVES 6 + +static const unsigned char cs_lut[FMC_NUM_SLAVES] = { + FMC_CPLD, + FMC_AD9517, + FMC_AD9250_0, + FMC_AD9250_1, + FMC_AD9129_0, + FMC_AD9129_1, +}; + +struct spi_ad9250 { + struct spi_device *spi; + struct work_struct work; + uint8_t data[32] ____cacheline_aligned; +}; + +static inline unsigned cs_to_cpld (unsigned chip_select) +{ + return cs_lut[chip_select]; +} + +static int spi_ad9250_transfer_one(struct spi_master *master, + struct spi_message *msg) +{ + struct spi_ad9250 *spi_ad9250 = spi_master_get_devdata(master); + struct spi_device *spi = msg->spi; + int status = 0, i = 1; + + struct spi_transfer *tn; + struct spi_message m; + struct spi_transfer x[8]; + + spi_message_init(&m); + memset(x, 0, sizeof x); + + x[0].len = 1; + x[0].tx_buf = spi_ad9250->data; + x[0].delay_usecs = 10; + spi_ad9250->data[0] = cs_to_cpld(spi->chip_select); + spi_message_add_tail(&x[0], &m); + + list_for_each_entry(tn, &msg->transfers, transfer_list) { + x[i] = *tn; + spi_message_add_tail(&x[i], &m); + i++; + if (i > 7) + return -EIO; + } + + spi_ad9250->spi->mode = spi->mode & ~SPI_3WIRE; + spi_setup(spi_ad9250->spi); + + spi_sync(spi_ad9250->spi, &m); + + msg->status = m.status; + spi_finalize_current_message(master); + + return status; +} + +static int spi_ad9250_setup(struct spi_device *spi) +{ + if (spi->bits_per_word != 8) + return -EINVAL; + + return 0; +} + +static void spi_ad9250_work(struct work_struct *work) +{ + struct spi_ad9250 *spi_ad9250 = + container_of(work,struct spi_ad9250, work); + struct spi_master *master = spi_get_drvdata(spi_ad9250->spi); + + int ret = spi_register_master(master); + if (ret < 0) + spi_master_put(master); +} + +static int __devinit spi_ad9250_probe(struct spi_device *spi) +{ + struct spi_ad9250 *spi_ad9250; + struct spi_master *master; + static int bus_num = 0; + + master = spi_alloc_master(&spi->dev, sizeof(*spi_ad9250)); + if (!master) + return -ENOMEM; + + spi_ad9250 = spi_master_get_devdata(master); + spi_ad9250->spi = spi; + master->num_chipselect = FMC_NUM_SLAVES; + master->bus_num = bus_num++; + master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_3WIRE; + master->setup = spi_ad9250_setup; + master->transfer_one_message = spi_ad9250_transfer_one; + master->dev.of_node = spi->dev.of_node; + spi_set_drvdata(spi, master); + + /* spi_add_lock in spi_add_device() prevents registering + * the master in place so defer this to an work queue + */ + INIT_WORK(&spi_ad9250->work, spi_ad9250_work); + schedule_work(&spi_ad9250->work); + + return 0; +} + +static int __devexit spi_ad9250_remove(struct spi_device *spi) +{ + struct spi_master *master = spi_get_drvdata(spi); + + spi_unregister_master(master); + + return 0; +} + +static const struct spi_device_id spi_ad9250_ids[] = { + { "spi-ad9250", 0 }, + { }, +}; + +MODULE_DEVICE_TABLE(spi, spi_ad9250_ids); + +static struct spi_driver spi_ad9250_driver = { + .driver = { + .name = "spi-ad9250", + .owner = THIS_MODULE, + }, + .id_table = spi_ad9250_ids, + .probe = spi_ad9250_probe, + .remove = __devexit_p(spi_ad9250_remove), +}; +module_spi_driver(spi_ad9250_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD9250-FMC board SPI mux driver"); From d72ebf32e338f7f3fe218bb83b0915a542ae56d0 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 4 Dec 2012 13:42:06 +0100 Subject: [PATCH 224/261] spi: of_register_spi_devices: add support for SPI_3WIRE Signed-off-by: Michael Hennerich --- drivers/spi/spi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index fb66f3123f6ce..5fd75e39da230 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -870,6 +870,8 @@ static void of_register_spi_devices(struct spi_master *master) spi->mode |= SPI_CPOL; if (of_find_property(nc, "spi-cs-high", NULL)) spi->mode |= SPI_CS_HIGH; + if (of_find_property(nc, "spi-3wire", NULL)) + spi->mode |= SPI_3WIRE; /* Device speed */ prop = of_get_property(nc, "spi-max-frequency", &len); From 32f871ed25f1acb8d6370cee6e3cf78c8d64274e Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 4 Dec 2012 13:43:34 +0100 Subject: [PATCH 225/261] iio: adc: Analog Devices AXI-JESD204B Interface Module add clk support Clocks must be present and stable before the interface is setup. Signed-off-by: Michael Hennerich --- drivers/iio/adc/cf_axi_jesd204b.c | 47 +++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/drivers/iio/adc/cf_axi_jesd204b.c b/drivers/iio/adc/cf_axi_jesd204b.c index 96b5a6be33243..9e6cb5592ed64 100644 --- a/drivers/iio/adc/cf_axi_jesd204b.c +++ b/drivers/iio/adc/cf_axi_jesd204b.c @@ -26,11 +26,14 @@ #include #include +#include + #include "cf_axi_jesd204b.h" struct jesd204b_state { - struct device *dev; - void __iomem *regs; + struct device *dev; + void __iomem *regs; + struct clk *clk; }; /* @@ -53,6 +56,7 @@ static int __devinit jesd204b_of_probe(struct platform_device *op) struct device *dev = &op->dev; struct jesd204b_state *st; struct resource r_mem; /* IO mem resources */ + struct clk *clk; resource_size_t remap_size, phys_addr; unsigned frmcnt, bytecnt; int ret; @@ -60,6 +64,11 @@ static int __devinit jesd204b_of_probe(struct platform_device *op) dev_info(dev, "Device Tree Probing \'%s\'\n", op->dev.of_node->name); + clk = clk_get(&op->dev, NULL); + if (IS_ERR(clk)) { + return -EPROBE_DEFER; + } + st = devm_kzalloc(&op->dev, sizeof(*st), GFP_KERNEL); if (!st) { dev_err(dev, "Not enough memory for device\n"); @@ -67,13 +76,22 @@ static int __devinit jesd204b_of_probe(struct platform_device *op) } st->dev = dev; + st->clk = clk; dev_set_drvdata(dev, st); + ret = clk_prepare(clk); + if (ret < 0) + return ret; + + ret = clk_enable(clk); + if (ret < 0) + goto err_clk_unprepare; + /* Get iospace for the device */ ret = of_address_to_resource(op->dev.of_node, 0, &r_mem); if (ret) { dev_err(dev, "invalid address\n"); - return ret; + goto err_clk_disable; } phys_addr = r_mem.start; @@ -82,7 +100,7 @@ static int __devinit jesd204b_of_probe(struct platform_device *op) dev_err(dev, "Couldn't lock memory region at 0x%08llX\n", (unsigned long long)phys_addr); ret = -EBUSY; - goto failed1; + goto err_clk_disable; } st->regs = ioremap(phys_addr, remap_size); @@ -90,7 +108,7 @@ static int __devinit jesd204b_of_probe(struct platform_device *op) dev_err(dev, "Couldn't ioremap memory at 0x%08llX\n", (unsigned long long)phys_addr); ret = -EFAULT; - goto failed2; + goto err_release_mem_region; } jesd204b_write(st, AXI_JESD204B_REG_TEST_MODE, @@ -100,12 +118,12 @@ static int __devinit jesd204b_of_probe(struct platform_device *op) ret = of_property_read_u32(op->dev.of_node, "jesd,frames-per-multiframe", &frmcnt); if (ret) - goto failed2; + goto err_release_mem_region; ret = of_property_read_u32(op->dev.of_node, "jesd,bytes-per-frame", &bytecnt); if (ret) - goto failed2; + goto err_release_mem_region; jesd204b_write(st, AXI_JESD204B_REG_CTRL, (of_property_read_bool(op->dev.of_node, "jesd,scramble_en") ? @@ -123,9 +141,13 @@ static int __devinit jesd204b_of_probe(struct platform_device *op) return 0; -failed2: +err_release_mem_region: release_mem_region(phys_addr, remap_size); -failed1: +err_clk_disable: + clk_disable(clk); +err_clk_unprepare: + clk_unprepare(clk); + clk_put(clk); dev_set_drvdata(dev, NULL); return ret; @@ -145,7 +167,6 @@ static int __devexit jesd204b_of_remove(struct platform_device *op) struct resource r_mem; /* IO mem resources */ struct jesd204b_state *st = dev_get_drvdata(dev); - iounmap(st->regs); /* Get iospace of the device */ @@ -154,6 +175,10 @@ static int __devexit jesd204b_of_remove(struct platform_device *op) else release_mem_region(r_mem.start, resource_size(&r_mem)); + clk_disable(st->clk); + clk_unprepare(st->clk); + clk_put(st->clk); + dev_set_drvdata(dev, NULL); return 0; @@ -180,5 +205,5 @@ static struct platform_driver jesd204b_of_driver = { module_platform_driver(jesd204b_of_driver); MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("Analog Devices CF FFT"); +MODULE_DESCRIPTION("Analog Devices AXI-JESD204B Interface Module"); MODULE_LICENSE("GPL v2"); From 78dcb1558a9c85f02fdf0512a50fc12ebb0009ed Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 4 Dec 2012 13:44:40 +0100 Subject: [PATCH 226/261] iio: adc: AD9250: clocks must be present and stable before device init. Signed-off-by: Michael Hennerich --- drivers/iio/adc/ad9467.c | 46 ++++++++++++++++++++++++++++++++---- drivers/iio/adc/cf_axi_adc.h | 3 ++- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c index e412b1b1b58a0..e6b7a08e75edb 100644 --- a/drivers/iio/adc/ad9467.c +++ b/drivers/iio/adc/ad9467.c @@ -18,6 +18,9 @@ #include #include "cf_axi_adc.h" +#include +#include + static int ad9467_spi_read(struct spi_device *spi, unsigned reg) { unsigned char buf[3]; @@ -62,8 +65,7 @@ static int ad9467_spi_write(struct spi_device *spi, unsigned reg, unsigned val) static int __devinit ad9250_setup(struct spi_device *spi) { int ret; - - msleep(10); + unsigned pll_stat; ret = ad9467_spi_write(spi, 0x18, 0x0f); // max vref ret |= ad9467_spi_write(spi, 0x64, 0xf0); // did @@ -83,9 +85,11 @@ static int __devinit ad9250_setup(struct spi_device *spi) ret |= ad9467_spi_write(spi, 0xff, 0x01); ret |= ad9467_spi_write(spi, 0xff, 0x00); - dev_info(&spi->dev, "PLL STATUS 0x%X\n", ad9467_spi_read(spi, 0x0A)); + pll_stat = ad9467_spi_read(spi, 0x0A); - msleep(500); + dev_info(&spi->dev, "PLL %s, JESD204B Link %s\n", + pll_stat & 0x80 ? "LOCKED" : "UNLOCKED", + pll_stat & 0x01 ? "Ready" : "Fail"); return ret; } @@ -93,14 +97,35 @@ static int __devinit ad9250_setup(struct spi_device *spi) static int __devinit ad9467_probe(struct spi_device *spi) { struct axiadc_converter *conv; + struct clk *clk = NULL; int ret; + if (spi_get_device_id(spi)->driver_data == CHIPID_AD9250) { + clk = clk_get(&spi->dev, NULL); + if (IS_ERR(clk)) { + return -EPROBE_DEFER; + } + + ret = clk_prepare(clk); + if (ret < 0) + return ret; + + ret = clk_enable(clk); + if (ret < 0) { + clk_unprepare(clk); + return ret; + } + } + conv = kzalloc(sizeof(*conv), GFP_KERNEL); if (conv == NULL) return -ENOMEM; spi->mode = SPI_MODE_0 | SPI_3WIRE; + if (clk) + conv->clk = clk; + conv->id = ad9467_spi_read(spi, ADC_REG_CHIP_ID); if (conv->id != spi_get_device_id(spi)->driver_data) { dev_err(&spi->dev, "Unrecognized CHIP_ID 0x%X\n", conv->id); @@ -126,11 +151,24 @@ static int __devinit ad9467_probe(struct spi_device *spi) out: kfree(conv); + if (clk) { + clk_disable(clk); + clk_unprepare(clk); + clk_put(clk); + } + return ret; } static int ad9467_remove(struct spi_device *spi) { + struct axiadc_converter *conv = spi_get_drvdata(spi); + + if (conv->clk) { + clk_disable(conv->clk); + clk_unprepare(conv->clk); + clk_put(conv->clk); + } spi_set_drvdata(spi, NULL); return 0; diff --git a/drivers/iio/adc/cf_axi_adc.h b/drivers/iio/adc/cf_axi_adc.h index fc2a976278059..2627a702a8ee6 100644 --- a/drivers/iio/adc/cf_axi_adc.h +++ b/drivers/iio/adc/cf_axi_adc.h @@ -191,7 +191,8 @@ struct axiadc_state { }; struct axiadc_converter { - struct spi_device *spi; + struct spi_device *spi; + struct clk *clk; unsigned id; int (*read)(struct spi_device *spi, unsigned reg); int (*write)(struct spi_device *spi, From feae0a10b1fb03c9ec247f08bf83218a11231b3e Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 4 Dec 2012 14:19:47 +0100 Subject: [PATCH 227/261] arch: microblaze: add support for AD9250-FMC-250EBZ Signed-off-by: Michael Hennerich --- .../boot/dts/cf_ad9250_fmc_ebz_kc705.dts | 439 ++++++ .../configs/kc705_ad9250_fmc_ebz_defconfig | 1381 +++++++++++++++++ 2 files changed, 1820 insertions(+) create mode 100644 arch/microblaze/boot/dts/cf_ad9250_fmc_ebz_kc705.dts create mode 100644 arch/microblaze/configs/kc705_ad9250_fmc_ebz_defconfig diff --git a/arch/microblaze/boot/dts/cf_ad9250_fmc_ebz_kc705.dts b/arch/microblaze/boot/dts/cf_ad9250_fmc_ebz_kc705.dts new file mode 100644 index 0000000000000..9fb65c0b0aa3a --- /dev/null +++ b/arch/microblaze/boot/dts/cf_ad9250_fmc_ebz_kc705.dts @@ -0,0 +1,439 @@ +/* + * Device Tree Generator version: 1.3 + * + * (C) Copyright 2007-2008 Xilinx, Inc. + * (C) Copyright 2007-2009 Michal Simek + * + * Michal SIMEK + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * CAUTION: This file is automatically generated by libgen. + * Version: Xilinx EDK 14.1 EDK_P.15xf + * + * XPS project directory: device-tree_bsp_0 + */ + +/dts-v1/; +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,microblaze"; + model = "testing"; + DDR3_SDRAM: memory@c0000000 { + device_type = "memory"; + reg = < 0xc0000000 0x40000000 >; + } ; + aliases { + ethernet0 = &Ethernet_Lite; + serial0 = &RS232_Uart_1; + } ; + chosen { + bootargs = "console=ttyS0 root=/dev/ram"; + } ; + + clocks { + ad9517_ref_clk: clock@0 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <30720000>; + clock-output-names = "refclk"; + }; + ad9517_clkin: clock@1 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <250000000>; + clock-output-names = "clkin"; + }; + }; + + cpus { + #address-cells = <1>; + #cpus = <0x1>; + #size-cells = <0>; + microblaze_0: cpu@0 { + clock-frequency = <100000000>; + compatible = "xlnx,microblaze-8.30.a"; + d-cache-baseaddr = <0xc0000000>; + d-cache-highaddr = <0xffffffff>; + d-cache-line-size = <0x10>; + d-cache-size = <0x4000>; + device_type = "cpu"; + i-cache-baseaddr = <0xc0000000>; + i-cache-highaddr = <0xffffffff>; + i-cache-line-size = <0x20>; + i-cache-size = <0x4000>; + model = "microblaze,8.30.a"; + reg = <0>; + timebase-frequency = <100000000>; + xlnx,addr-tag-bits = <0x10>; + xlnx,allow-dcache-wr = <0x1>; + xlnx,allow-icache-wr = <0x1>; + xlnx,area-optimized = <0x0>; + xlnx,avoid-primitives = <0x0>; + xlnx,branch-target-cache-size = <0x0>; + xlnx,cache-byte-size = <0x4000>; + xlnx,d-axi = <0x1>; + xlnx,d-lmb = <0x1>; + xlnx,d-plb = <0x0>; + xlnx,data-size = <0x20>; + xlnx,dcache-addr-tag = <0x10>; + xlnx,dcache-always-used = <0x1>; + xlnx,dcache-byte-size = <0x4000>; + xlnx,dcache-data-width = <0x0>; + xlnx,dcache-force-tag-lutram = <0x0>; + xlnx,dcache-interface = <0x0>; + xlnx,dcache-line-len = <0x4>; + xlnx,dcache-use-fsl = <0x0>; + xlnx,dcache-use-writeback = <0x0>; + xlnx,dcache-victims = <0x0>; + xlnx,debug-enabled = <0x1>; + xlnx,div-zero-exception = <0x1>; + xlnx,dynamic-bus-sizing = <0x1>; + xlnx,ecc-use-ce-exception = <0x0>; + xlnx,edge-is-positive = <0x1>; + xlnx,endianness = <0x1>; + xlnx,family = "kintex7"; + xlnx,fault-tolerant = <0x0>; + xlnx,fpu-exception = <0x0>; + xlnx,freq = <0x5f5e100>; + xlnx,fsl-data-size = <0x20>; + xlnx,fsl-exception = <0x0>; + xlnx,fsl-links = <0x0>; + xlnx,i-axi = <0x0>; + xlnx,i-lmb = <0x1>; + xlnx,i-plb = <0x0>; + xlnx,icache-always-used = <0x1>; + xlnx,icache-data-width = <0x0>; + xlnx,icache-force-tag-lutram = <0x0>; + xlnx,icache-interface = <0x0>; + xlnx,icache-line-len = <0x8>; + xlnx,icache-streams = <0x1>; + xlnx,icache-use-fsl = <0x0>; + xlnx,icache-victims = <0x8>; + xlnx,ill-opcode-exception = <0x1>; + xlnx,instance = "microblaze_0"; + xlnx,interconnect = <0x2>; + xlnx,interconnect-m-axi-dc-read-issuing = <0x2>; + xlnx,interconnect-m-axi-dc-write-issuing = <0x20>; + xlnx,interconnect-m-axi-dp-read-issuing = <0x1>; + xlnx,interconnect-m-axi-dp-write-issuing = <0x1>; + xlnx,interconnect-m-axi-ic-read-issuing = <0x8>; + xlnx,interconnect-m-axi-ip-read-issuing = <0x1>; + xlnx,interrupt-is-edge = <0x0>; + xlnx,lockstep-slave = <0x0>; + xlnx,mmu-dtlb-size = <0x4>; + xlnx,mmu-itlb-size = <0x2>; + xlnx,mmu-privileged-instr = <0x0>; + xlnx,mmu-tlb-access = <0x3>; + xlnx,mmu-zones = <0x2>; + xlnx,number-of-pc-brk = <0x1>; + xlnx,number-of-rd-addr-brk = <0x0>; + xlnx,number-of-wr-addr-brk = <0x0>; + xlnx,opcode-0x0-illegal = <0x1>; + xlnx,optimization = <0x0>; + xlnx,pc-width = <0x20>; + xlnx,pvr = <0x2>; + xlnx,pvr-user1 = <0x0>; + xlnx,pvr-user2 = <0x0>; + xlnx,reset-msr = <0x0>; + xlnx,sco = <0x0>; + xlnx,stream-interconnect = <0x0>; + xlnx,unaligned-exceptions = <0x1>; + xlnx,use-barrel = <0x1>; + xlnx,use-branch-target-cache = <0x0>; + xlnx,use-dcache = <0x1>; + xlnx,use-div = <0x1>; + xlnx,use-ext-brk = <0x1>; + xlnx,use-ext-nm-brk = <0x1>; + xlnx,use-extended-fsl-instr = <0x0>; + xlnx,use-fpu = <0x0>; + xlnx,use-hw-mul = <0x2>; + xlnx,use-icache = <0x1>; + xlnx,use-interrupt = <0x1>; + xlnx,use-mmu = <0x3>; + xlnx,use-msr-instr = <0x1>; + xlnx,use-pcmp-instr = <0x1>; + xlnx,use-reorder-instr = <0x1>; + xlnx,use-stack-protection = <0x0>; + } ; + } ; + axi4lite_0: axi@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,axi-interconnect-1.06.a", "simple-bus"; + ranges ; + Ethernet_Lite: ethernet@40e00000 { + compatible = "xlnx,axi-ethernetlite-1.01.b", "xlnx,xps-ethernetlite-1.00.a"; + device_type = "network"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 6 0 >; + local-mac-address = [ 00 0a 35 fb 52 00 ]; + phy-handle = <&phy0>; + reg = < 0x40e00000 0x10000 >; + xlnx,duplex = <0x1>; + xlnx,family = "kintex7"; + xlnx,include-global-buffers = <0x0>; + xlnx,include-internal-loopback = <0x0>; + xlnx,include-mdio = <0x1>; + xlnx,include-phy-constraints = <0x1>; + xlnx,instance = "Ethernet_Lite"; + xlnx,interconnect-s-axi-read-acceptance = <0x1>; + xlnx,interconnect-s-axi-write-acceptance = <0x1>; + xlnx,rx-ping-pong = <0x0>; + xlnx,s-axi-aclk-period-ps = <0x2710>; + xlnx,s-axi-id-width = <0x1>; + xlnx,s-axi-supports-narrow-burst = <0x0>; + xlnx,tx-ping-pong = <0x0>; + mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: phy@7 { + compatible = "marvell,88e1111"; + device_type = "ethernet-phy"; + reg = <7>; + } ; + } ; + } ; + RS232_Uart_1: serial@40600000 { + clock-frequency = <100000000>; + compatible = "xlnx,axi-uartlite-1.02.a", "xlnx,xps-uartlite-1.00.a"; + current-speed = <57600>; + device_type = "serial"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 7 0 >; + port-number = <0>; + reg = < 0x40600000 0x10000 >; + xlnx,baudrate = <0xe100>; + xlnx,data-bits = <0x8>; + xlnx,family = "kintex7"; + xlnx,instance = "RS232_Uart_1"; + xlnx,odd-parity = <0x1>; + xlnx,s-axi-aclk-freq-hz = <0x5f5e100>; + xlnx,use-parity = <0x0>; + } ; + axi_dma_0: axidma@41e20000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + ranges = < 0x41e20000 0x41e20000 0x10000 >; + reg = < 0x41e20000 0x10000 >; +// xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@41e20030 { + compatible = "xlnx,axi-dma-s2mm-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 4 2 >; + xlnx,datawidth = <0x40>; + xlnx,include-dre = <0x0>; + } ; + } ; + axi_dma_1: axidma@41e00000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-dma"; + ranges = < 0x41e00000 0x41e00000 0x10000 >; + reg = < 0x41e00000 0x10000 >; +// xlnx,sg-include-stscntrl-strm = <0x0>; + dma-channel@41e00030 { + compatible = "xlnx,axi-dma-s2mm-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 3 2 >; + xlnx,datawidth = <0x40>; + xlnx,include-dre = <0x0>; + } ; + }; + axi_spi_0: spi@40a00000 { + compatible = "xlnx,axi-spi-1.02.a", "xlnx,xps-spi-2.00.a"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 2 2 >; + reg = < 0x40a00000 0x10000 >; + xlnx,family = "kintex7"; + xlnx,fifo-exist = <0x1>; + xlnx,instance = "axi_spi_0"; + xlnx,num-ss-bits = <0x1>; + xlnx,num-transfer-bits = <0x8>; + xlnx,sck-ratio = <0x10>; + spi_fmc176: spi-fmc176@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "spi-ad9250"; + reg = <0>; + spi-max-frequency = <10000000>; + clk_ad9517: ad9517@4 { + #address-cells = <1>; + #size-cells = <0>; + #clock-cells = <0>; + compatible = "ad9517-1"; + reg = <1>; + spi-max-frequency = <10000000>; + spi-3wire; + clocks = <&ad9517_ref_clk>, <&ad9517_clkin>; + clock-names = "refclk", "clkin"; + clock-output-names = "out0", "out1", "out2", "out3", "out4", "out5", "out6", "out7"; + + }; + adc0_ad9250: ad9250@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ad9250"; + reg = <2>; + spi-max-frequency = <10000000>; + clocks = <&clk_ad9517>; + clock-names = "out0"; + + }; + adc1_ad9250: ad9250@1 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ad9250"; + reg = <3>; + spi-max-frequency = <10000000>; + clocks = <&clk_ad9517>; + clock-names = "out1"; + + }; + }; + }; + axi_ad9129_0: axi-ad9129@7c840000 { + compatible = "xlnx,axi-ad9129-1.00.a"; + reg = < 0x7c840000 0x10000 >; + xlnx,cf-buftype = <0x0>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "kintex7"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + axi_ad9250_0: cf-ad9250-1@7c820000 { + compatible = "xlnx,axi-ad9250-1.00.a"; + reg = < 0x7c820000 0x10000 >; + dma-request = <&axi_dma_0 0>; + spibus-connected = <&adc0_ad9250>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "kintex7"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + axi_ad9250_1: cf-ad9250-2@7c800000 { + compatible = "xlnx,axi-ad9250-1.00.a"; + reg = < 0x7c800000 0x10000 >; + dma-request = <&axi_dma_1 0>; + spibus-connected = <&adc1_ad9250>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "kintex7"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + } ; + + /* LCD Display */ + + axi_gpio_0: gpio@40000000 { + compatible = "xlnx,axi-xlnx-lcd-1.00.a"; + reg = < 0x40000000 0x8 >; + xlnx,all-inputs = <0x0>; + xlnx,dout-default = <0x0>; + xlnx,family = "kintex7"; + xlnx,gpio-width = <0x7>; + xlnx,instance = "axi_gpio_0"; + xlnx,interrupt-present = <0x0>; + xlnx,is-dual = <0x0>; + xlnx,tri-default = <0xffffffff>; + } ; + + axi_intc_0: interrupt-controller@41200000 { + #interrupt-cells = <0x2>; + compatible = "xlnx,axi-intc-1.01.a", "xlnx,xps-intc-1.00.a"; + interrupt-controller ; + reg = < 0x41200000 0x10000 >; + xlnx,kind-of-intr = <0xc0>; + xlnx,num-intr-inputs = <0x8>; + } ; + axi_jesd204b_rx4_0: axi-jesd204b-rx4@77a00000 { + compatible = "xlnx,axi-jesd204b-rx4-1.00.a"; + reg = < 0x77a00000 0x10000 >; + jesd,lanesync_en; + jesd,scramble_en; + jesd,frames-per-multiframe = <32>; + jesd,bytes-per-frame = <2>; + xlnx,cf-buftype = <0x1>; + xlnx,dphase-timeout = <0x8>; + xlnx,family = "kintex7"; + xlnx,num-mem = <0x1>; + xlnx,num-reg = <0x1>; + xlnx,s-axi-min-size = <0x1ff>; + xlnx,slv-awidth = <0x20>; + xlnx,slv-dwidth = <0x20>; + xlnx,use-wstrb = <0x0>; + clocks = <&clk_ad9517>; + clock-names = "out0"; + + } ; + axi_timer_0: timer@41c00000 { + clock-frequency = <100000000>; + compatible = "xlnx,axi-timer-1.03.a", "xlnx,xps-timer-1.00.a"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 5 2 >; + reg = < 0x41c00000 0x10000 >; + xlnx,count-width = <0x20>; + xlnx,family = "kintex7"; + xlnx,gen0-assert = <0x1>; + xlnx,gen1-assert = <0x1>; + xlnx,instance = "axi_timer_0"; + xlnx,one-timer-only = <0x0>; + xlnx,trig0-assert = <0x1>; + xlnx,trig1-assert = <0x1>; + } ; + axi_vdma_0: axivdma@7e200000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,axi-vdma"; + ranges = < 0x7e200000 0x7e200000 0x10000 >; + reg = < 0x7e200000 0x10000 >; + xlnx,include-sg = <0x0>; + xlnx,num-fstores = <0x3>; + dma-channel@7e200000 { + compatible = "xlnx,axi-vdma-mm2s-channel"; + interrupt-parent = <&axi_intc_0>; + interrupts = < 1 2 >; + xlnx,datawidth = <0x40>; + xlnx,genlock-mode = <0x0>; + xlnx,include-dre = <0x0>; + } ; + } ; + debug_module: debug@41400000 { + compatible = "xlnx,mdm-2.00.b"; + reg = < 0x41400000 0x10000 >; + xlnx,family = "kintex7"; + xlnx,interconnect = <0x2>; + xlnx,jtag-chain = <0x2>; + xlnx,mb-dbg-ports = <0x1>; + xlnx,use-uart = <0x1>; + } ; + } ; +} ; diff --git a/arch/microblaze/configs/kc705_ad9250_fmc_ebz_defconfig b/arch/microblaze/configs/kc705_ad9250_fmc_ebz_defconfig new file mode 100644 index 0000000000000..82ad7d6acbba5 --- /dev/null +++ b/arch/microblaze/configs/kc705_ad9250_fmc_ebz_defconfig @@ -0,0 +1,1381 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/microblaze 3.5.0-rc4 Kernel Configuration +# +CONFIG_MICROBLAZE=y +# CONFIG_SWAP is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ZONE_DMA=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_CSUM=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_IRQ_DOMAIN=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y + +# +# RCU Subsystem +# +CONFIG_TINY_RCU=y +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="rootfs.cpio.gz" +CONFIG_INITRAMFS_ROOT_UID=0 +CONFIG_INITRAMFS_ROOT_GID=0 +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +CONFIG_INITRAMFS_COMPRESSION_NONE=y +# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_API_DEBUG=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_BLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_FREEZER is not set + +# +# Platform options +# +# CONFIG_PLATFORM_GENERIC is not set +CONFIG_PLATFORM_ML605_ADIXCOMM=y +# CONFIG_PLATFORM_KC705_ADIXCOMM is not set +# CONFIG_ADIXCOMM_SYNC is not set +CONFIG_OPT_LIB_FUNCTION=y +# CONFIG_OPT_LIB_ASM is not set + +# +# Definitions for MICROBLAZE0 +# +CONFIG_KERNEL_BASE_ADDR=0xc0000000 +CONFIG_XILINX_MICROBLAZE0_FAMILY="virtex6" +CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1 +CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1 +CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1 +CONFIG_XILINX_MICROBLAZE0_USE_DIV=1 +CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL=2 +CONFIG_XILINX_MICROBLAZE0_USE_FPU=0 +CONFIG_XILINX_MICROBLAZE0_HW_VER="8.20.a" + +# +# Processor type and features +# +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_SCHED_HRTICK=y +CONFIG_MMU=y + +# +# Boot options +# +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyUL0,57600 root=/dev/ram" +CONFIG_CMDLINE_FORCE=y +# CONFIG_SECCOMP is not set + +# +# Advanced setup +# +CONFIG_ADVANCED_OPTIONS=y +# CONFIG_HIGHMEM is not set +CONFIG_LOWMEM_SIZE_BOOL=y +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_MANUAL_RESET_VECTOR=0x0 +CONFIG_KERNEL_START_BOOL=y +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE_BOOL=y +CONFIG_TASK_SIZE=0x80000000 +CONFIG_KERNEL_PAD=0x80000 +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_NEED_PER_CPU_KM=y +# CONFIG_CLEANCACHE is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Bus Options +# +# CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS is not set +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +# CONFIG_DNS_RESOLVER is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +CONFIG_BQL=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +CONFIG_GENERIC_CPU_DEVICES=y +# CONFIG_DMA_SHARED_BUFFER is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=y +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_GPIO_ADDR is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_LATCH_ADDR is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_DEVICE=y +CONFIG_OF_I2C=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +# CONFIG_PARPORT is not set + +# +# Misc devices +# +CONFIG_AD525X_DPOT=y +CONFIG_AD525X_DPOT_I2C=y +CONFIG_AD525X_DPOT_SPI=y +# CONFIG_ICS932S401 is not set +CONFIG_XLNX_LCD=y +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_MII is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set + +# +# CAIF transport drivers +# +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_INTEL=y +CONFIG_NET_VENDOR_I825XX=y +CONFIG_NET_VENDOR_MARVELL=y +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +CONFIG_NET_VENDOR_NATSEMI=y +CONFIG_NET_VENDOR_8390=y +# CONFIG_ETHOC is not set +CONFIG_NET_VENDOR_SEEQ=y +# CONFIG_SEEQ8005 is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_WIZNET=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +CONFIG_NET_VENDOR_XILINX=y +CONFIG_XILINX_EMACLITE=y +# CONFIG_XILINX_AXI_EMAC is not set +# CONFIG_XILINX_LL_TEMAC is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_AMD_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_WLAN=y +# CONFIG_HOSTAP is not set +# CONFIG_WL_TI is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_DW is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_UARTLITE=y +CONFIG_SERIAL_UARTLITE_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_TTY_PRINTK is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_XILINX_HWICAP is not set +# CONFIG_R3964 is not set + +# +# PCMCIA character devices +# +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_MUX is not set +# CONFIG_I2C_HELPER_AUTO is not set +# CONFIG_I2C_SMBUS is not set + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +CONFIG_I2C_XILINX=y + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=y +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_XCOMM is not set +CONFIG_SPI_XILINX=y +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_HSI is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_OF_GPIO=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +CONFIG_GPIO_XILINX=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_S5M_CORE is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_EXYNOS_VIDEO is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_SOUND is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB_ARCH_HAS_XHCI is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_RTC_CLASS is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_XILINX_DMA=y +# CONFIG_TIMB_DMA is not set +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_BALLOON is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_ECHO is not set +# CONFIG_RTLLIB is not set + +# +# IIO staging drivers +# +CONFIG_IIO_SW_RING=y + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16204 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_KXSD9 is not set +# CONFIG_LIS3L02DQ is not set +# CONFIG_SCA3000 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7291 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7606 is not set +# CONFIG_AD799X is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_ADT7310 is not set +# CONFIG_ADT7410 is not set +# CONFIG_AD7280 is not set +# CONFIG_MAX1363 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Direct Digital Synthesis +# +# CONFIG_AD5930 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_AD9850 is not set +# CONFIG_AD9852 is not set +# CONFIG_AD9910 is not set +# CONFIG_AD9951 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16060 is not set +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set + +# +# Light sensors +# +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_ISL29028 is not set +# CONFIG_SENSORS_TSL2563 is not set +# CONFIG_TSL2583 is not set +# CONFIG_TSL2x7x is not set + +# +# Magnetometer sensors +# +# CONFIG_SENSORS_AK8975 is not set +# CONFIG_SENSORS_HMC5843 is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7753 is not set +# CONFIG_ADE7754 is not set +# CONFIG_ADE7758 is not set +# CONFIG_ADE7759 is not set +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_GPIO_TRIGGER is not set +# CONFIG_IIO_SYSFS_TRIGGER is not set +# CONFIG_IIO_SIMPLE_DUMMY is not set +# CONFIG_ZSMALLOC is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +# CONFIG_ANDROID is not set +# CONFIG_PHONE is not set +# CONFIG_IPACK_BUS is not set +# CONFIG_WIMAX_GDM72XX is not set + +# +# Hardware Spinlock drivers +# +CONFIG_IOMMU_SUPPORT=y + +# +# Remoteproc drivers (EXPERIMENTAL) +# + +# +# Rpmsg drivers (EXPERIMENTAL) +# +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 + +# +# Analog to digital converters +# +# CONFIG_AD7266 is not set +CONFIG_CF_AXI_ADC=y +CONFIG_CF_AXI_FFT=y +CONFIG_AXI_JESD204B=y + +# +# Amplifiers +# +# CONFIG_AD8366 is not set + +# +# Light sensors +# +# CONFIG_VCNL4000 is not set + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +# CONFIG_AD9523 is not set +# CONFIG_AD9548 is not set + +# +# Direct Digital Synthesis +# +CONFIG_CF_AXI_DDS=y +CONFIG_CF_AXI_DDS_AD9122=y + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +# CONFIG_ADF4350 is not set + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD5686 is not set +# CONFIG_MAX517 is not set +# CONFIG_MCP4725 is not set + +# +# File systems +# +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +# CONFIG_DNOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ECRYPT_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set +# CONFIG_MINIX_FS_NATIVE_ENDIAN is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V2=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_DEBUG is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +# CONFIG_DETECT_HUNG_TASK is not set +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_TEST_KSTRTOX is not set +CONFIG_EARLY_PRINTK=y +# CONFIG_HEART_BEAT is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_ENCRYPTED_KEYS is not set +CONFIG_KEYS_DEBUG_PROC_KEYS=y +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +# CONFIG_CRC8 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_GENERIC_ATOMIC64=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set From ad396429838ed22bf57940c0401b990ebb196ea7 Mon Sep 17 00:00:00 2001 From: Cristian Fatu Date: Wed, 5 Dec 2012 20:45:15 -0800 Subject: [PATCH 228/261] Digilent: Pmods: Added PmodCLS driver and documentation --- Documentation/pmods/pmodcls.txt | 174 +++++++ drivers/pmods/Kconfig | 6 + drivers/pmods/Makefile | 1 + drivers/pmods/pmodcls.c | 834 ++++++++++++++++++++++++++++++++ 4 files changed, 1015 insertions(+) create mode 100644 Documentation/pmods/pmodcls.txt create mode 100644 drivers/pmods/pmodcls.c diff --git a/Documentation/pmods/pmodcls.txt b/Documentation/pmods/pmodcls.txt new file mode 100644 index 0000000000000..6ca28fafed794 --- /dev/null +++ b/Documentation/pmods/pmodcls.txt @@ -0,0 +1,174 @@ +PmodCLS +======== + +Copyright 2012, Digilent Inc. + + +Description +----------- + +The PmodCLS features an SPI-controlled monochrome LCD 16x2 Character Display, +perfect for embedded applications requiring small, simple text output. + +The PmodCLS uses simple terminal-like display interface. It provides +flexible communications using UART, SPI or TWI interface. + +This Linux character driver uses an SPI interface in order to configure the device, +as well as to send the text to be displayed on the device. + +Commands are sent and characters are written to the display simply by sending +characters over the communication link. + + +The Reference Manual for PmodCLS display is available online at +Digilent Inc. Website (www.digilentinc.com). + + +Interface +--------- + +Signal Description + +SDIN SPI Data In (MOSI) +SCLK SPI Clock +SS Slave Select + + +Devicetree +---------- + +Required Properties: +- compatible : Should be "dlgnt,pmodcls" +- spi-bus-num : Should specify the bus number for PmodCLS SPI controller. + This value cannot be shared by any other SPI controller present in the + device tree. +- spi-sclk-gpio : Should specify the GPIO for SCLK, see "gpios property" in + Documentation/devicetree/gpio.txt. +- spi-sdin-gpio : Should specify the GPIO for SDIN, see "gpios property" in + Documentation/devicetree/gpio.txt. + +Optional Properties: +- spi-cs-gpio : Should specify the GPIO for CS, see "gpios property" in + Documentation/devicetree/gpio.txt. If unspecified, CS is assumed to be + tied to ground. +- spi-speed-hz : Should specify the spi speed (in Hz). If unspecified, spi + speed is assumed to be 625000 (625 kHz). + +Examples: + + pmodcls { + compatible = "dglnt,pmodcls"; + spi-bus-num = <0x3>; + spi-speed-hz = <625000>; + spi-sclk-gpio = <0x8 85 0>; + spi-sdin-gpio = <0x8 83 0>; + spi-cs-gpio = <0x8 82 0>; + }; + + +Configuration +------------- + +The PmodCLS is located in the kernel configuration menu at +Device Drivers -> Pmods -> PmodCLS. The driver can be built into the kernel +by selecting (*) for it, or as a loadable module by selecting (M) for it. + + +Device Nodes +------------ + +A char device node will be created for each PmodCLS device automatically. +The name of the node is default to the one declared in the device tree. + +Instruction set +----------- +Instructions are sent using escape sequences. An escape sequence +begins with ESC (character code 0x1B) followed by the left +square bracket ‘[‘ , followed by 0 or more parameters separated by +semicolons ‘;’ and ending with the command character. + +The commands are (as stated in the PmodCLS reference Manual): + +;H - set cursor position to row and col +s - save cursor position +u - restore saved cursor position +j - clear display and home cursor +K - erase within line + 0 = current position to end of line + 1 = start of line to current position + 2 = entire line +N erase field in current line + = number of chars starting at current position +@ - scroll left columns +A - scroll right columns +* - reset; equivalent to cycling power of PmodCLS +e - enable/disable display + 0 = display off, + backlight off + 1 = display on, + backlight off + 2 = display off, + backlight on + 3 = display on, + backlight on +h - set display mode + 0 = wrap line at 16 characters + 1 = wrap line at 40 characters +c - set cursor mode + 0 = cursor off + 1 = cursor on, + blink off + 2 = cursor on, + blink on +a - save TWI address in EEPROM to +b - save baud rate value in EEPROM to +p - program character table into LCD +t - save RAM character table to EEPROM +l - load EEPROM character table to RAM +;…;d- define user programmable character + Be aware that after defining a user character you must + program the character table into LCD (command 'p'). +m - save communication mode to EEPROM +w - enable write to EEPROM +n - save cursor mode to EEPROM +o - save display mode to EEPROM + +Notations: + row number (0 - 1) + column number (0 – 39) + numeric parameter + - decimal: 122 for ex. + - hex: 0x7A for ex. + - binary: 0b01111010 for ex. + decimal selection parameter + character table selector + (0 – 2 in EEPROM, 3 in RAM) + + +Example of commands +----------- + +- Set backlight on, display on +echo -n -e "\x1B[3e" > /dev/pmodcls + +- Clear screen, cursor home +echo -n -e "\x1B[j" > /dev/pmodcls + +- Position cursor (row 1, col 0) +echo -n -e "\x1B[1;0H" > /dev/pmodcls + +- Display string +echo -n -e "Digilent" > /dev/pmodcls + +- Display string on 2 rows (when current row is the first) +echo -n -e "Hello\nDigilent" > /dev/pmodcls + +- Define user character 1 (in RAM) +echo -n -e "\x1B[0;10;21;17;10;4;0;0;1d\x1B[3p" > /dev/pmodcls + +- Display user char 1 +echo -n -e "\x01" > /dev/pmodcls + + + + diff --git a/drivers/pmods/Kconfig b/drivers/pmods/Kconfig index 207dcaac2116b..a7d99dcd25536 100644 --- a/drivers/pmods/Kconfig +++ b/drivers/pmods/Kconfig @@ -17,4 +17,10 @@ config PMODOLED The Digilent PmodOLED1, as well as ZED on-board OLED. Uses SPI over GPIO. Configuration SPI_BITBANG and SPI_GPIO will be selected automatically. +config PMODCLS + tristate "pmodcls" + select SPI_BITBANG + help + This is the Digilent PmodCLS driver. Uses SPI over GPIO. + endif # PMODS diff --git a/drivers/pmods/Makefile b/drivers/pmods/Makefile index a1bcc1d3367e7..1fb3b4d4747f2 100644 --- a/drivers/pmods/Makefile +++ b/drivers/pmods/Makefile @@ -2,4 +2,5 @@ ccflags-$(CONFIG_PMODS_DEBUG) += -DDEBUG obj-$(CONFIG_PMODOLED) += pmodoled-gpio.o +obj-$(CONFIG_PMODCLS) += pmodcls.o diff --git a/drivers/pmods/pmodcls.c b/drivers/pmods/pmodcls.c new file mode 100644 index 0000000000000..8a812976c5eef --- /dev/null +++ b/drivers/pmods/pmodcls.c @@ -0,0 +1,834 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "pmodcls" +#define SPI_DRIVER_NAME "pmodcls-spi" + +#define DEFAULT_SPI_SPEED 625000 +#define MAX_PMODCLS_DEV_NUM 16 +#define TXT_BUF_SIZE 1024 +#define MAX_NO_ROWS 2 // The device has 2 rows + + + +dev_t pmodcls_dev_id = 0; +static unsigned int device_num = 0; +static unsigned int cur_minor = 0; +static unsigned int spi_drv_registered = 0; +static struct class *pmodcls_class = NULL; + +struct pmodcls_device { + char *name; + /* R/W Mutex Lock */ + struct mutex mutex; + /* Text Buffer */ + char *txt_buf; // Device Text buffer + int cur_row; // Maintain current row + int exceeded_rows; // Flag for situation where maximum number of rows is exceeded + /* Pin Assignment */ + + unsigned long iSCLK; + unsigned long iSDIN; + unsigned long iCS; + + /* SPI Info */ + uint32_t spi_speed; + uint32_t spi_id; + /* platform device structures */ + struct platform_device *pdev; + /* Char Device */ + struct cdev cdev; + struct spi_device *spi; + dev_t dev_id; +}; + +// Forward definitions +static int parse_text(char *txt_buf, int cnt, struct pmodcls_device *dev); +static int txt_buf_to_display(char *txt_buf, int cnt, struct pmodcls_device *dev); + +/** + * A basic open function. + */ +static int pmodcls_open(struct inode *inode, struct file *fp) +{ + struct pmodcls_device *dev; + + dev = container_of(inode->i_cdev, struct pmodcls_device, cdev); + fp->private_data = dev; + + return 0; +} + +/** + * A basic close function, do nothing. + */ +static int pmodcls_close(struct inode *inode, struct file *fp) +{ + return 0; +} + +/* + * Driver write function + * + * This function uses a generic SPI write to send values to the Pmod device. + * It takes a string from the app in the buffer. + * It sends the commands and the text to PmodCLS over the standard SPI interface. + * + */ +static ssize_t pmodcls_write(struct file *fp, const char __user *buffer, size_t length, loff_t *offset) +{ + ssize_t retval = 0; + int status; /* spi_write return value */ + int cnt; + struct pmodcls_device *dev; + + dev = fp->private_data; + + if (mutex_lock_interruptible(&dev->mutex)) { + retval = -ERESTARTSYS; + goto write_lock_err; + } + + + cnt = length; + + if(copy_from_user(dev->txt_buf, buffer, cnt)) + { + retval = -EFAULT; + goto quit_write; + } + retval = cnt; + + dev->txt_buf[cnt] = '\0'; + status = parse_text(dev->txt_buf, cnt, dev); + dev_dbg (&dev->spi->dev, "cls_write: Writing \"%s\" to display\n", + dev->txt_buf); + + if (status) { + dev_err(&dev->spi->dev, "cls_write: " + "Error writing text to SPI device\n"); + retval = -EFAULT; + goto quit_write; + } + dev_dbg (&dev->spi->dev, "cls_write: Writing to display complete\n"); + + +quit_write: + mutex_unlock(&dev->mutex); +write_lock_err: + return(retval); +} + +/** + * parse_text - This function builds the commands to be sent for each recognized escape sequence. + * + * Parameters + * @char *txt_buf: the text array to be parsed + * @int cnt the number of charcaters to be parsed in the text array + * @struct pmodclp_device *dev pointer to device structure + * + * + * This function parses a text array, containing a sequence of one or more text or commands to be sent to PmodCLS. Its purpose is: + * - recognize, interpret the commands: + * - maintain a shadow value of the current row (this is because PmodCLS is a "write only" device, the cursor position cannot be read) + * - split the separate commands / text and send individually to the device. + * - recognize LF character ('\n') inside a text to be sent to the device + * - if current line is the first, move the cursor to the beginning of the next line + * - if current line is the second, there is no room for new line. Text characters after LF are ignored, commands are still interpreted. + * + */ +static int parse_text(char *txt_buf, int cnt, struct pmodcls_device *dev) +{ + int status = 0; /* spi_write return value */ + int is_ignore_txt; + int is_par1 = 0; + int is_cmd = 0; + int par1 = 0, par2; + char txt_LF_cmd[10]; + char *parse_buf, *sent_buf; + + parse_buf = txt_buf; + sent_buf = txt_buf - 1; + is_par1 = 0; + is_cmd = 0; + is_ignore_txt = dev->exceeded_rows; + while((!status) && (parse_buf < (txt_buf + cnt))) + { + // recognize command - look for ESC code, followed by '[' + if((!is_cmd) && ((*parse_buf) == 0x1B) && (parse_buf[1] == '[')) + { + // enter command mode + is_cmd = 1; + is_par1 = 1; + par1 = 0; + // send previous text (before the ESC sequence) + if((parse_buf - sent_buf) > 1) + { + status = txt_buf_to_display(sent_buf + 1, parse_buf - 1 - sent_buf, dev); + sent_buf = parse_buf - 1; + } + parse_buf ++; // skip '[' char + + } + else + { + if(is_cmd) + { + if((*parse_buf) >= '0' && (*parse_buf) <= '9') + { // numeric char, build parameters values + if(is_par1) + { + par1 = 10 * par1 + (*parse_buf) - '0'; + } + else + { + par2 = 10 * par2 + (*parse_buf) - '0'; + } + } + else + { + if((*parse_buf) == ';') + { // parameters separator + is_par1 = 0; + par2 = 0; + } + else + { + // look for some commands + switch (*parse_buf) + { + case 'H': // set cursor position + dev->cur_row = par1; + if(dev->cur_row < MAX_NO_ROWS) + { + is_ignore_txt = 0; + } + else + { + is_ignore_txt = 1; + } + break; + case 'j': // clear display and home cursor + case '*': // reset + dev->cur_row = 0; + is_ignore_txt = 0; + break; + case 's': // save cursor position + case 'u': // restore saved cursor position + case 'K': // erase within line + case 'N': // erase field + case '@': // scroll left + case 'A': // scroll right + case 'h': // set display mode (wrap line) + case 'c': // set cursor mode + case 'p': // program char table into LCD + case 't': // save RAM character table to EEPROM + case 'l': // load EEPROM character table to RAM + case 'd': // define user programmable character + case 'm': // save communication mode to EEPROM + case 'w': // enable write to EEPROM + case 'n': // save cursor mode to EEPROM + case 'o': // save display mode to EEPROM + // cursor is not affected + break; + + default: + // no command was recognized + is_cmd = 0; // comand mode is abandonned + } + if(is_cmd) + { + // send text including the command char + if((parse_buf - sent_buf) > 1) + { + status = txt_buf_to_display(sent_buf + 1, parse_buf - sent_buf, dev); + sent_buf = parse_buf; + is_cmd = 0; // comand mode is abandonned + } + } + } + } + } + else + { + // free text, not inside a command + if(is_ignore_txt) + { + sent_buf = parse_buf; + } + else + { + if((*parse_buf) == '\n') + { // LF + // send text before the LF char + if((parse_buf - sent_buf) > 0) + { + txt_buf_to_display(sent_buf + 1, parse_buf - 1 - sent_buf, dev); + } + // position the cursor on the beginning of the next line + if(dev->cur_row < (MAX_NO_ROWS - 1)) + { + dev->cur_row++; + strcpy(txt_LF_cmd, "0[0;0H"); + txt_LF_cmd[0] = 0x1B;// ESC + txt_LF_cmd[2] = '0' + (unsigned char)dev->cur_row; + status = txt_buf_to_display(txt_LF_cmd, 6, dev); + } + else + { + // there is no room to place a third line. Ignore text (still look for the comands) + is_ignore_txt = 1; + } + + // advance the pointers so that LF char is skipped next time when chars are sent + sent_buf = parse_buf; + } + + } + } + + } + parse_buf ++; // advance one character + } + parse_buf--; + // send remaining chars + + if((!status) && ((parse_buf - sent_buf) > 0)) + { + status = txt_buf_to_display(sent_buf + 1, parse_buf - sent_buf, dev); + } + + dev->exceeded_rows = is_ignore_txt; + + return status; +} + +/** + * txt_buf_to_display - This function breaks sends the string to the PmodCLS device over the SPI. + prior to . + * + * Parameters + * @char *txt_buf: the text array to be parsed + * @int cnt the number of charcaters to be parsed in the text array + * @struct pmodclp_device *dev pointer to device structure + * + * + * This function breaks sends the string to the PmodCLS device over the SPI. It breaks the input string in chunks of 3 bytes in order to reduce the load on the receiving + * PmodCLS. + * + */ +static int txt_buf_to_display(char *txt_buf, int cnt, struct pmodcls_device *dev) +{ + int status; /* spi_write return value */ + int short_cnt; + + /* + * Break writes into three byte chunks so that the microcontroller on + * the PmodCLS can keep up. Prior to breaking up writes to these + * smaller chunks, every 4th character would not be displayed. + * + * NOTE: The usleep_range delay is not needed, but allows the driver + * to relinquish control to other tasks. + */ + status = 0; + while ((cnt > 0) && (!status)) { + short_cnt = (cnt > 3) ? 3 : cnt; + status = spi_write (dev->spi, txt_buf, short_cnt); + cnt -= short_cnt; + txt_buf += short_cnt; + usleep_range (10, 100); + } + return status; + +} + +/** + * Driver Read Function + * + * This function does not actually read the PmodCLP as it is a write-only device. + */ +static ssize_t pmodcls_read(struct file *fp, char __user *buffer, size_t length, loff_t *offset) +{ + ssize_t retval = 0; + return(retval); +} + + +struct file_operations pmodcls_cdev_fops = { + .owner = THIS_MODULE, + .write = pmodcls_write, + .read = pmodcls_read, + .open = pmodcls_open, + .release = pmodcls_close, +}; + + +/** + * add_pmodcls_device_to_bus - Add device to SPI bus, initialize SPI data. + * @dev: pointer to device tree node + * + * This function adds device to SPI bus, initialize SPI data. + */ +static int __init add_pmodcls_device_to_bus(struct pmodcls_device* dev) { + struct spi_master *spi_master; + struct spi_device *spi_device; + int status = 0; + + spi_master = spi_busnum_to_master(dev->spi_id); + if(!spi_master) { + dev_err(&dev->pdev->dev, "spi_busnum_to_master(%d) returned NULL\n", dev->spi_id); + return -ENOSYS; + } + + spi_device = spi_alloc_device(spi_master); + if(!spi_device) { + put_device(&spi_master->dev); + dev_err(&dev->pdev->dev, "spi_alloc_device() failed\n"); + return -ENOMEM; + } + + spi_device->chip_select = 0; + spi_device->max_speed_hz = dev->spi_speed; + spi_device->mode = SPI_MODE_0; + spi_device->bits_per_word = 8; + spi_device->controller_data = (void *) dev->iCS; + spi_device->dev.platform_data = dev; + strlcpy(spi_device->modalias, SPI_DRIVER_NAME, sizeof(SPI_DRIVER_NAME)); + + status = spi_add_device(spi_device); + if(status < 0) { + spi_dev_put(spi_device); + dev_err(&dev->pdev->dev, "spi_add_device() failed %d\n", status); + return status; + } + dev->spi = spi_device; + + put_device(&spi_master->dev); + printk(KERN_INFO DRIVER_NAME " SPI initialized, max_speed_hz\t%d\n", spi_device->max_speed_hz); + + return status; +} + +/** + * pmodcls_setup_cdev - Setup Char Device for ZED PmodCLP device. + * @dev: pointer to device tree node + * @dev_id: pointer to device major and minor number + * @spi: pointer to spi_device structure + * + * This function initializes char device for PmodCLS device, and add it into + * kernel device structure. It returns 0, if the cdev is successfully + * initialized, or a negative value if there is an error. + */ +static int pmodcls_setup_cdev(struct pmodcls_device *dev, dev_t *dev_id, struct spi_device *spi) +{ + int status = 0; + struct device *device; + + cdev_init(&dev->cdev, &pmodcls_cdev_fops); + dev->cdev.owner = THIS_MODULE; + dev->cdev.ops = &pmodcls_cdev_fops; + dev->spi = spi; + + *dev_id = MKDEV(MAJOR(pmodcls_dev_id), cur_minor++); + status = cdev_add(&dev->cdev, *dev_id, 1); + if(status < 0) { + return status; + } + + /* Add Device node in system */ + device = device_create(pmodcls_class, NULL, + *dev_id, NULL, + "%s", dev->name); + if(IS_ERR(device)) { + status = PTR_ERR(device); + dev_err(&spi->dev, "failed to create device node %s, err %d\n", + dev->name, status); + cdev_del(&dev->cdev); + } + + return status; +} + + + + +/** + * SPI hardware probe. Sets correct SPI mode, attempts + * to obtain memory needed by the driver, and performs + * a simple initialization of the device. + */ +static int pmodcls_spi_probe(struct spi_device *spi) { + int status = 0; + struct pmodcls_device *pmodcls_dev; + + /* We must use SPI_MODE_0 */ + spi->mode = SPI_MODE_0; + spi->bits_per_word = 8; + + status = spi_setup(spi); + if(status < 0) { + dev_err(&spi->dev, "needs SPI mode %02x, %d KHz; %d\n", + spi->mode, spi->max_speed_hz / 1000, + status); + goto spi_err; + } + + /* Get pmodcls_device structure */ + pmodcls_dev = (struct pmodcls_device*) spi->dev.platform_data; + if(pmodcls_dev == NULL) { + dev_err(&spi->dev, "Cannot get pmodcls_device.\n"); + status = -EINVAL; + goto spi_platform_data_err; + } + + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO SPI_DRIVER_NAME " [%s] spi_probe: setup char device\n", pmodcls_dev->name); +#endif + + /* Setup char driver */ + status = pmodcls_setup_cdev(pmodcls_dev, &(pmodcls_dev->dev_id), spi); + if (status) { + printk(KERN_INFO " spi_probe: Error adding %s device: %d\n", SPI_DRIVER_NAME, status); + dev_err(&spi->dev, "spi_probe: Error adding %s device: %d\n", SPI_DRIVER_NAME, status); + goto cdev_add_err; + } + + /* Initialize Mutex */ + mutex_init(&pmodcls_dev->mutex); + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO SPI_DRIVER_NAME " [%s] spi_probe: initialize device\n", pmodcls_dev->name); +#endif + + return status; + +cdev_add_err: +spi_platform_data_err: +spi_err: + return(status); +} + +static int __devexit pmodcls_spi_remove(struct spi_device *spi) +{ + int status; + struct pmodcls_device *dev; + + dev = (struct pmodcls_device*) spi->dev.platform_data; + + if(dev == NULL) { + dev_err(&spi->dev, "spi_remove: Error fetch pmodcls_device struct\n"); + return -EINVAL; + } + + + if(&dev->cdev) { +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO SPI_DRIVER_NAME " [%s] spi_remove: Destroy Char Device\n", dev->name); +#endif + device_destroy(pmodcls_class, dev->dev_id); + cdev_del(&dev->cdev); + } + + cur_minor--; + + return status; +} + +static struct spi_driver pmodcls_spi_driver = { + .driver = { + .name = SPI_DRIVER_NAME, + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = pmodcls_spi_probe, + .remove = __devexit_p(pmodcls_spi_remove), +}; + +static const struct of_device_id pmodcls_of_match[] __devinitconst = { + { .compatible = "dglnt,pmodcls", }, + {}, +}; +MODULE_DEVICE_TABLE(of, pmodcls_of_match); + +/** + * pmodcls_of_probe - Probe method for PmodCLS device (over GPIO). + * @pdev: pointer to platform devices + * + * This function probes the PmodCLS device in the device tree. It initializes the + * PmodCLS driver data structure. It returns 0, if the driver is bound to the PmodCLS + * device, or a negative value if there is an error. + */ +static int __devinit pmodcls_of_probe(struct platform_device *pdev) +{ + struct pmodcls_device *pmodcls_dev; + struct platform_device *pmodcls_pdev; + struct spi_gpio_platform_data *pmodcls_pdata; + + struct device_node *np = pdev->dev.of_node; + + const u32* tree_info; + const u32* spi_speed; + int status = 0; + + /* Alloc Space for platform device structure */ + pmodcls_dev = (struct pmodcls_device*) kzalloc(sizeof(*pmodcls_dev), GFP_KERNEL); + if(!pmodcls_dev) { + status = -ENOMEM; + goto dev_alloc_err; + } + + /* Alloc Text Buffer for device */ + pmodcls_dev->txt_buf = (uint8_t*) kmalloc(TXT_BUF_SIZE, GFP_KERNEL); + if(!pmodcls_dev->txt_buf) { + status = -ENOMEM; + dev_err(&pdev->dev, "Device Display data buffer allocation failed: %d\n", status); + goto txt_buf_alloc_err; + } + + /* Get the GPIO Pins */ + + pmodcls_dev->iSCLK = of_get_named_gpio(np, "spi-sclk-gpio", 0); + pmodcls_dev->iSDIN = of_get_named_gpio(np, "spi-sdin-gpio", 0); + status = of_get_named_gpio(np, "spi-cs-gpio", 0); + pmodcls_dev->iCS = (status < 0) ? SPI_GPIO_NO_CHIPSELECT : status; + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: iSCLK: 0x%lx\n", np->name, pmodcls_dev->iSCLK); + printk(KERN_INFO DRIVER_NAME " %s: iSDIN: 0x%lx\n", np->name, pmodcls_dev->iSDIN); + printk(KERN_INFO DRIVER_NAME " %s: iCS : 0x%lx\n", np->name, pmodcls_dev->iCS); +#endif + + /* Get SPI Related Params */ + tree_info = of_get_property(np, "spi-bus-num", NULL); + if(tree_info) { + pmodcls_dev->spi_id = be32_to_cpup((tree_info)); +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: BUS_ID\t%x\n", np->name, pmodcls_dev->spi_id); +#endif + } + + spi_speed = of_get_property(np, "spi-speed-hz", NULL); + if(spi_speed) { + pmodcls_dev->spi_speed = be32_to_cpup((spi_speed)); +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: SPI_SPEED\t%x\n", np->name, pmodcls_dev->spi_speed); +#endif + } + else + { + pmodcls_dev->spi_speed = DEFAULT_SPI_SPEED; + } + /* Alloc Space for platform data structure */ + pmodcls_pdata = (struct spi_gpio_platform_data*) kzalloc(sizeof(*pmodcls_pdata), GFP_KERNEL); + if(!pmodcls_pdata) { + status = -ENOMEM; + goto pdata_alloc_err; + } + + /* Fill up Platform Data Structure */ + pmodcls_pdata->sck = pmodcls_dev->iSCLK; + pmodcls_pdata->miso = SPI_GPIO_NO_MISO; + pmodcls_pdata->mosi = pmodcls_dev->iSDIN; + pmodcls_pdata->num_chipselect = 1; + + /* Alloc Space for platform data structure */ + pmodcls_pdev = (struct platform_device*) kzalloc(sizeof(*pmodcls_pdev), GFP_KERNEL); + if(!pmodcls_pdev) { + status = -ENOMEM; + goto pdev_alloc_err; + } + + /* Fill up Platform Device Structure */ + pmodcls_pdev->name = "spi_gpio"; + pmodcls_pdev->id = pmodcls_dev->spi_id; + pmodcls_pdev->dev.platform_data = pmodcls_pdata; + pmodcls_dev->pdev = pmodcls_pdev; + + /* Register spi_gpio master */ + status = platform_device_register(pmodcls_dev->pdev); + if(status < 0) { + dev_err(&pdev->dev, "platform_device_register failed: %d\n", status); + goto pdev_reg_err; + } + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: spi_gpio platform device registered.\n", np->name); +#endif + pmodcls_dev->name = (char *)np->name; + + /* Fill up Board Info for SPI device */ + status = add_pmodcls_device_to_bus(pmodcls_dev); + if(status < 0) { + dev_err(&pdev->dev, "add_pmodcls_device_to_bus failed: %d\n", status); + goto spi_add_err; + } + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: spi device registered.\n", np->name); +#endif + + /* Point device node data to pmodcls_device structure */ + if(np->data == NULL) + np->data = pmodcls_dev; + + if(pmodcls_dev_id == 0) { + /* Alloc Major & Minor number for char device */ + status = alloc_chrdev_region(&pmodcls_dev_id, 0, MAX_PMODCLS_DEV_NUM, DRIVER_NAME); + if(status) { + dev_err(&pdev->dev, "Character device region not allocated correctly: %d\n", status); + goto err_alloc_chrdev_region; + } +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Char Device Region Registered, with Major: %d.\n", + MAJOR(pmodcls_dev_id)); +#endif + } + + if(pmodcls_class == NULL) { + /* Create Pmodcls Device Class */ + pmodcls_class = class_create(THIS_MODULE, DRIVER_NAME); + if (IS_ERR(pmodcls_class)) { + status = PTR_ERR(pmodcls_class); + goto err_create_class; + } +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : pmodcls device class registered.\n"); +#endif + } + + if(spi_drv_registered == 0) { + /* Register SPI Driver for Pmodcls Device */ + status = spi_register_driver(&pmodcls_spi_driver); + if (status < 0) { + dev_err(&pdev->dev, "pmodcls_spi_driver register failed: %d\n", status); + goto err_spi_register; + } + spi_drv_registered = 1; + } + + device_num ++; + + return status; + +err_spi_register: + class_destroy(pmodcls_class); + pmodcls_class = NULL; +err_create_class: + unregister_chrdev_region(pmodcls_dev_id, MAX_PMODCLS_DEV_NUM); + pmodcls_dev_id = 0; +err_alloc_chrdev_region: + spi_unregister_device(pmodcls_dev->spi); +spi_add_err: + platform_device_unregister(pmodcls_dev->pdev); +pdev_reg_err: + kfree(pmodcls_pdev); +pdev_alloc_err: + kfree(pmodcls_pdata); +pdata_alloc_err: + kfree(pmodcls_dev->txt_buf); +txt_buf_alloc_err: + kfree(pmodcls_dev); +dev_alloc_err: + return status; +} + +/** + * pmodcls_of_remove - Remove method for ZED PmodCLS device. + * @np: pointer to device tree node + * + * This function removes the PmodCLS device in the device tree. It frees the + * PmodCLS driver data structure. It returns 0, if the driver is successfully + * removed, or a negative value if there is an error. + */ +static int pmodcls_of_remove(struct platform_device *pdev) +{ + struct pmodcls_device *pmodcls_dev; + struct device_node *np = pdev->dev.of_node; + + if(np->data == NULL) { + dev_err(&pdev->dev, "pmodcls %s: ERROR: No pmodcls_device structure found!\n", np->name); + return -ENOSYS; + } + pmodcls_dev = (struct pmodcls_device*) (np->data); + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s : Free display buffer.\n", np->name); +#endif + + if(pmodcls_dev->txt_buf != NULL) { + kfree(pmodcls_dev->txt_buf); + } + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s : Unregister gpio_spi Platform Devices.\n", np->name); +#endif + + if(pmodcls_dev->pdev != NULL) { + platform_device_unregister(pmodcls_dev->pdev); + } + + np->data = NULL; + device_num--; + + /* Unregister SPI Driver, Destroy pmodcls class, Release device id Region after + * all pmodcls devices have been removed. + */ + if(device_num == 0) { +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Unregister SPI Driver.\n"); +#endif + spi_unregister_driver(&pmodcls_spi_driver); + spi_drv_registered = 0; + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Destroy pmodcls_gpio Class.\n"); +#endif + + if(pmodcls_class) { + class_destroy(pmodcls_class); + } + pmodcls_class = NULL; + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Release Char Device Region.\n"); +#endif + + unregister_chrdev_region(pmodcls_dev_id, MAX_PMODCLS_DEV_NUM); + pmodcls_dev_id = 0; + } + + return 0; +} + +static struct platform_driver pmodcls_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = pmodcls_of_match, + }, + .probe = pmodcls_of_probe, + .remove = __devexit_p(pmodcls_of_remove), +}; + +module_platform_driver(pmodcls_driver); + +MODULE_AUTHOR("Digilent, Inc."); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(DRIVER_NAME": PmodCLS display driver"); +MODULE_ALIAS(DRIVER_NAME); From 89b3b50ce9b80c67dea60dd46c080daedc364c85 Mon Sep 17 00:00:00 2001 From: Cristian Fatu Date: Wed, 5 Dec 2012 20:58:07 -0800 Subject: [PATCH 229/261] Digilent: Pmods: Added PmodCLP driver and documentation --- Documentation/pmods/pmodclp.txt | 198 ++++++ drivers/pmods/Kconfig | 5 + drivers/pmods/Makefile | 1 + drivers/pmods/pmodclp.c | 1164 +++++++++++++++++++++++++++++++ 4 files changed, 1368 insertions(+) create mode 100644 Documentation/pmods/pmodclp.txt create mode 100644 drivers/pmods/pmodclp.c diff --git a/Documentation/pmods/pmodclp.txt b/Documentation/pmods/pmodclp.txt new file mode 100644 index 0000000000000..5ec04680fb61b --- /dev/null +++ b/Documentation/pmods/pmodclp.txt @@ -0,0 +1,198 @@ +PmodCLP +======== + +Copyright 2012, Digilent Inc. + + +Description +----------- + +The PmodCLP is a 16x2 character LCD module that uses two Pmod connectors to present a +8-bit parallel data interface to system boards. +The PmodCLP features an SPI-controlled monochrome LCD 16x2 Character Display, +perfect for embedded applications requiring small, simple text output. + +The PmodCLP uses simple terminal-like display interface. It provides +flexible communications using UART, SPI or TWI interface. + +Some of the PmodCLP implement a backlight feature. This is implemented by using the +optional bk-gpio in the Device Tree. + +This Linux character driver sends commands and data to the device using parallel access +to GPIOs. The set of commands is based on escape characters. + +The Reference Manual for PmodCLP device is available online at +Digilent Inc. Website (www.digilentinc.com). + + +Interface +--------- + +Signal Description + +RS RS (Register Select) signal of the parallel interface +RW RW (Read/Write) signal of the parallel interface +E E (Enable) signal of the parallel interface +BK (Optional) - BackLight signal +DATA0 Signal for Bit 0 of the parallel interface +DATA1 Signal for Bit 1 of the parallel interface +DATA2 Signal for Bit 2 of the parallel interface +DATA3 Signal for Bit 3 of the parallel interface +DATA4 Signal for Bit 4 of the parallel interface +DATA5 Signal for Bit 5 of the parallel interface +DATA6 Signal for Bit 6 of the parallel interface +DATA7 Signal for Bit 7 of the parallel interface + +Devicetree +---------- + +Required Properties: +- compatible : Should be "dlgnt,pmodclp" +- rs-gpio : Should specify the GPIO for RS, see "gpios property" in + Documentation/devicetree/gpio.txt. +- rw-gpio : Should specify the GPIO for RW, see "gpios property" in + Documentation/devicetree/gpio.txt. +- e-gpio : Should specify the GPIO for E, see "gpios property" in + Documentation/devicetree/gpio.txt. +- data0-gpio : Should specify the GPIO for DATA0, see "gpios property" in + Documentation/devicetree/gpio.txt. +- data1-gpio : Should specify the GPIO for DATA1, see "gpios property" in + Documentation/devicetree/gpio.txt. +- data2-gpio : Should specify the GPIO for DATA2, see "gpios property" in + Documentation/devicetree/gpio.txt. +- data3-gpio : Should specify the GPIO for DATA3, see "gpios property" in + Documentation/devicetree/gpio.txt. +- data4-gpio : Should specify the GPIO for DATA4, see "gpios property" in + Documentation/devicetree/gpio.txt. +- data5-gpio : Should specify the GPIO for DATA5, see "gpios property" in + Documentation/devicetree/gpio.txt. +- data6-gpio : Should specify the GPIO for DATA6, see "gpios property" in + Documentation/devicetree/gpio.txt. +- data7-gpio : Should specify the GPIO for DATA7, see "gpios property" in + Documentation/devicetree/gpio.txt. + +Optional Properties: +- bk-gpio : Should specify the GPIO for BK, see "gpios property" in + Documentation/devicetree/gpio.txt. + +Example: +(corresponds to +J1 connector of PmodCLP connected to JA connector of Zed +J2 connector of PmodCLP connected to Jb connector of Zed): + + pmodclp { + compatible = "dglnt,pmodclp"; + rs-gpio = <0x8 94 0>; + rw-gpio = <0x8 95 0>; + e-gpio = <0x8 96 0>; + bk-gpio = <0x8 97 0>; + data0-gpio = <0x8 82 0>; + data1-gpio = <0x8 83 0>; + data2-gpio = <0x8 84 0>; + data3-gpio = <0x8 85 0>; + data4-gpio = <0x8 86 0>; + data5-gpio = <0x8 87 0>; + data6-gpio = <0x8 88 0>; + data7-gpio = <0x8 89 0>; + }; + + +Configuration +------------- + +The PmodCLP is located in the kernel configuration menu at +Device Drivers -> Pmods -> PmodCLP. The driver can be built into the kernel +by selecting (*) for it, or loadable module by selecting (M) for it. + + +Device Nodes +------------ + +A char device node will be created for each PmodCLP device automatically. +The name of the node is default to the one declared in the device tree. + + +Instruction set +----------- +Instructions are sent using escape sequences. An escape sequence +begins with ESC (character code 0x1B) followed by the left +square bracket ‘[‘ , followed by 0 or more parameters separated by +semicolons ‘;’ and ending with the command character. + +The implemented commands are: + +;H - set cursor position to row and col + +@ - scroll left columns + +A - scroll right columns + +e - enable/disable display + 0 = display off, + backlight off + 1 = display on, + backlight off + 2 = display off, + backlight on + 3 = display on, + backlight on + +c - set cursor mode + 0 = cursor off + 1 = cursor on, + blink off + 2 = cursor on, + blink on + +j - clear display and home cursor + + +;…;d - define user programmable character +Be aware that after defining a user character you must issue a +set position command. + +Notations: + row number (0 - 1) + column number (0 – 39) + numeric parameter + - decimal: 122 for ex. + - hex: 0x7A for ex. + - binary: 0b01111010 for ex. + decimal selection parameter + + +Examples of commands +----------- + +- Set display on, backlight on +echo -n -e "\x1B[3e" > /dev/pmodclp + +- Clear screen, cursor home +echo -n -e "\x1B[j" > /dev/pmodclp + +- Position cursor (row 1, col 0) +echo -n -e "\x1B[1;0H" > /dev/pmodclp + +- Display string +echo -n -e "Digilent" > /dev/pmodclp + +- Display string on 2 rows (when current row is the first) +echo -n -e "Hello\nDigilent" > /dev/pmodclp + +- Scroll right 2 positions +echo -n -e "\x1B[2A" > /dev/pmodclp + +- Scroll left 2 positions +echo -n -e "\x1B[2@" > /dev/pmodclp + + +- Define user char 1 +echo -n -e "\x1B[0x00;0x0A;0x15;0x11;0x0A;0x04;0x00;0x00;1d" > /dev/pmodclp + +- Display user char 1 on row 1, col 3 +echo -n -e "\x1B[1;3H" > /dev/pmodclp +echo -n -e "\x01" > /dev/pmodclp + + + + diff --git a/drivers/pmods/Kconfig b/drivers/pmods/Kconfig index a7d99dcd25536..2e7e6a2785a26 100644 --- a/drivers/pmods/Kconfig +++ b/drivers/pmods/Kconfig @@ -23,4 +23,9 @@ config PMODCLS help This is the Digilent PmodCLS driver. Uses SPI over GPIO. +config PMODCLP + tristate "pmodclp" + help + This is the Digilent PmodCLP driver. Implements parallel access. + endif # PMODS diff --git a/drivers/pmods/Makefile b/drivers/pmods/Makefile index 1fb3b4d4747f2..7d9b98649194f 100644 --- a/drivers/pmods/Makefile +++ b/drivers/pmods/Makefile @@ -3,4 +3,5 @@ ccflags-$(CONFIG_PMODS_DEBUG) += -DDEBUG obj-$(CONFIG_PMODOLED) += pmodoled-gpio.o obj-$(CONFIG_PMODCLS) += pmodcls.o +obj-$(CONFIG_PMODCLP) += pmodclp.o diff --git a/drivers/pmods/pmodclp.c b/drivers/pmods/pmodclp.c new file mode 100644 index 0000000000000..5c87ad1145873 --- /dev/null +++ b/drivers/pmods/pmodclp.c @@ -0,0 +1,1164 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "pmodclp" +#define MAX_PMODCLP_DEV_NUM 16 +#define TXT_BUF_SIZE 1024 +#define MAX_NO_ROWS 2 // The device has 2 rows +#define MAX_NO_COLS 40 // The device has max 40 columns +#define CONFIG_PMODS_DEBUG + +#define CMD_LCDFNCINIT 0x38 // function set command, (8-bit interface, 2 lines, and 5x8 dots) +#define CMD_LCDCTLINIT 0x08 // display control set command +#define CMD_LCDCLEAR 0x01 // clear display command +#define CMD_LCDRETHOME 0x02 // return home command +#define CMD_LCDDISPLAYSHIFT 0x18// shift display command +#define CMD_LCDCURSORSHIFT 0x10 // shift cursor command +#define CMD_LCDSETDDRAMPOS 0x80 // set DDRAM position command +#define CMD_LCDSETCGRAMPOS 0x40 // set CGRAM position command + +#define MSK_BSTATUS 0x80 // bit busy +#define MSK_SHIFTRL 0x04 // shift direction mask +#define OPT_DISPLAYON 0x4 // Set Display On option +#define OPT_CURSORON 0x2 // Set Cursor On option +#define OPT_BLINKON 0x1 // Set Blink On option + +dev_t pmodclp_dev_id = 0; +static unsigned int device_num = 0; +static unsigned int cur_minor = 0; +static struct class *pmodclp_class = NULL; + +// structure that keeps the parallel port related information +struct par_device{ + /* Pin Assignment */ + + unsigned long iRS; + unsigned long iRW; + unsigned long iE; + unsigned long iBK; + unsigned long iData[8]; +}; + +struct pmodclp_device { + char *name; + /* R/W Mutex Lock */ + struct mutex mutex; + /* Text Buffer */ + char *txt_buf; // Device Text buffer + unsigned long cur_row; // Maintain current row + int exceeded_rows; // Flag for situation where maximum number of rows is exceeded + + int display_on; + int cursor_on; + int blink_on; + int bk_on; + + /* Pin Assignment */ + struct par_device par_dev; + + /* Char Device */ + struct cdev cdev; + dev_t dev_id; +}; + +// Forward definitions +void parse_text(char *txt_buf, int cnt, struct pmodclp_device *dev); +void pmodclp_write_command(struct par_device *par_dev, unsigned char cmd); +static int pmodclp_init_gpio(struct pmodclp_device *pmodclp_dev); + + +/** + * A basic open function. + */ +static int pmodclp_open(struct inode *inode, struct file *fp) +{ + struct pmodclp_device *dev; + + dev = container_of(inode->i_cdev, struct pmodclp_device, cdev); + fp->private_data = dev; + + return 0; +} + + +/** + * A basic close function, do nothing. + */ + +static int pmodclp_close(struct inode *inode, struct file *fp) +{ + return 0; +} + +/* + * Driver write function + * + * This function uses a generic SPI write to send values to the Pmod device. + * It takes a string from the app in the buffer. + * It interprets the string of characters, and sends the commands and the text to PmodCLP over the parallel interface. + */ + +static ssize_t pmodclp_write(struct file *fp, const char __user *buffer, size_t length, loff_t *offset) +{ + ssize_t retval = 0; + int cnt; + struct pmodclp_device *dev; + + dev = fp->private_data; + + if (mutex_lock_interruptible(&dev->mutex)) { + retval = -ERESTARTSYS; + goto write_lock_err; + } + + + cnt = length; + + if(copy_from_user(dev->txt_buf, buffer, cnt)) + { + retval = -EFAULT; + goto quit_write; + } + retval = cnt; + + dev->txt_buf[cnt] = '\0'; + + + parse_text(dev->txt_buf, cnt, dev); + +quit_write: + mutex_unlock(&dev->mutex); +write_lock_err: + return(retval); +} + + +void write_display_control_cmd(struct pmodclp_device *dev) +{ + unsigned char cmd = CMD_LCDCTLINIT + + (dev->display_on ? OPT_DISPLAYON : 0) + + (dev->cursor_on ? OPT_CURSORON : 0) + + (dev->blink_on ? OPT_BLINKON : 0); + pmodclp_write_command(&(dev->par_dev), cmd); + +} + +// Begin of parallel interface functions + + +/** + * gpio_par_define_data_direction - Configure the gpio data pins as input or output. + * + * Parameters: + * @struct par_device *par_dev: pointer to the structure containing parallel interface information + * @bool fOutput: true if the pins are configured as output + false if the pins are configured as input + * @unsigned char bOutputVal the 8 bit value corresponding to the initial value set for the 8 lines if they are defined as output + * + * + * This function configures the gpio data pins as input or output, as required by read or write operations. + */ +int gpio_par_define_data_direction(struct par_device *par_dev, bool fOutput, unsigned char bOutputVal) +{ + int i; + int status = 0; + for (i = 0; !status && (i < 8); i++) + { + if(fOutput) + { + status = gpio_direction_output(par_dev->iData[i], ((bOutputVal & (1<iData[i]); + } + } + udelay(20); + return status; +} + +/** + * gpio_par_read_byte - Read one byte function. + * + * Parameters: + * @struct par_device *par_dev: pointer to the structure containing parallel interface information + * + * Return value the byte read + * + * This function implements the parallel read cycle on the gpio pins. It is the basic read function. + */ +unsigned char gpio_par_read_byte(struct par_device *par_dev) +{ + int i; + unsigned char bData = 0; + // Set RW + gpio_set_value(par_dev->iRW, 1); + udelay(20); + // Set Enable + gpio_set_value(par_dev->iE, 1); + udelay(20); + for (i = 0; i < 8; i++) + { + bData += ((unsigned char)gpio_get_value(par_dev->iData[i]) << i); + } + + // Clear Enable + gpio_set_value(par_dev->iE, 0); + udelay(20); + // Clear RW + gpio_set_value(par_dev->iRW, 0); + udelay(20); + return bData; +} + +/** + * gpio_par_write_byte - Write one byte function. + * + * Parameters: + * @struct par_device *par_dev: pointer to the structure containing parallel interface information + * @unsigned char bData: the byte to be written over the parallel interface. + * + * + * This function implements the parallel write cycle on the gpio pins. It is the basic write function, + * it writes one byte over the parallel interface. + */ +void gpio_par_write_byte(struct par_device *par_dev, unsigned char bData) +{ + int i; + // Clear RW + gpio_set_value(par_dev->iRW, 0); + udelay(20); + // Set Enable + gpio_set_value(par_dev->iE, 1); + udelay(20); + for (i = 0; i < 8; i++) + { + gpio_set_value(par_dev->iData[i], (bData >> i) & 0x01); + } + + // Clear Enable + gpio_set_value(par_dev->iE, 0); + udelay(20); + // Set RW + gpio_set_value(par_dev->iRW, 1); + udelay(20); +} + + +/** + * pmodclp_read_status - Read Status function + * + * Parameters: + * @struct par_device *par_dev: pointer to the structure containing parallel interface information + * + * + * This function reads the status of the PmodCLP device. + */ +unsigned char pmodclp_read_status(struct par_device *par_dev) +{ + unsigned char bStatus; + // define data pins as input + gpio_par_define_data_direction(par_dev , false, 0); + + // clear RS, meaning instruction register + gpio_set_value(par_dev->iRS, 0); + udelay(20); + + bStatus = gpio_par_read_byte(par_dev); + + return bStatus; +} + +/** + * pmodclp_wait_until_not_busy - Wait until device is ready function + * + * Parameters: + * @struct par_device *par_dev: pointer to the structure containing parallel interface information + * + * + * This function loops until the device reports to be not busy. + */ +void pmodclp_wait_until_not_busy(struct par_device *par_dev) +{ + unsigned char bStatus; + + // read status + bStatus = pmodclp_read_status(par_dev); + while (bStatus & MSK_BSTATUS) + { + mdelay(10); + bStatus = pmodclp_read_status(par_dev); + } +} + +/** + * gpio_par_write_byte - Write one command byte function. + * + * Parameters: + * @struct par_device *par_dev: pointer to the structure containing parallel interface information + * @unsigned char bData: the byte containing the command to be written over the parallel interface. + * + * + * This function writes a command byte over the parallel interface. + */ +void pmodclp_write_command(struct par_device *par_dev, unsigned char cmd) +{ + // wait until LCD is not busy + pmodclp_wait_until_not_busy(par_dev); + + // clear RS, meaning instruction register + gpio_set_value(par_dev->iRS, 0); + udelay(20); + + // Write command byte + // define data pins as output, and provide initial output value + gpio_par_define_data_direction(par_dev , true, cmd); + + // implement write command + gpio_par_write_byte(par_dev, cmd); +} + +/** + * gpio_par_write_byte - Write array of caracters as data function. + * + * Parameters: + * @struct par_device *par_dev: pointer to the structure containing parallel interface information + * @char *txt_buf: the text array to be written + * @int cnt the number of charcaters in the text array + * + * This function writes a number of characters as data over the parallel interface. + */ +void pmodclp_write_data(struct par_device *par_dev, char *txt_buf, int cnt) +{ + int i; + // set RS, meaning data + gpio_set_value(par_dev->iRS, 1); + udelay(20); + + // define data pins as output, and provide initial output value + gpio_par_define_data_direction(par_dev , true, txt_buf[0]); + for(i = 0; i < cnt; i++) + { + // implement write command + gpio_par_write_byte(par_dev, txt_buf[i]); + } +} + +/** + * pmodclp_init - Required initialization sequence for PmodCLP. + * + * Parameters: + * @struct par_device *par_dev: pointer to the structure containing parallel interface information + * + * + * This function performs the required initialization sequence for PmodCLP. See the reference manual for more information. + */ +void pmodclp_init(struct par_device *par_dev) +{ + + // perform initialization sequence, according to datasheet + + // wait 20 ms + mdelay(20); + // Set function + pmodclp_write_command(par_dev, CMD_LCDFNCINIT); + // Wait 37 us + udelay(37); + + // display on, no cursor, no blinking + pmodclp_write_command(par_dev, CMD_LCDCTLINIT); + + // Wait 37 us + udelay(37); + + // Display Clear + pmodclp_write_command(par_dev, CMD_LCDCLEAR); + // Wait 1.52 ms + udelay(1520); + +} +// Begin of parse functions + +/** + * is_decimal_digit - This function returns true if the specified character is among decimal characters. + * + * Parameters + * @char c: character that is searched to be among decimal characters + * + * Return value + * true if the specified character is among decimal characters + * false if the character character is not among decimal characters + * + * This function returns true if the specified character is among hexa characters ('0', '1', ...'9'). + */ +bool is_decimal_digit(char c) +{ + return (c >= '0' && c <= '9'); +} + +/** + * is_hexa_digit - This function returns true if the specified character is among hexa characters. + * + * Parameters + * @char c: character that is searched to be among hexa characters + * + * Return value + * true if the specified character is among hexa characters + * false if the character character is not among hexa characters + * + * This function returns true if the specified character is among hexa characters ('0', '1', ...'9', 'A', 'B', ... , 'F', 'a', 'b', ..., 'f'). + */ +bool is_hexa_digit(char c) +{ + return (is_decimal_digit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')); +} + +/** + * is_binary_digit - This function returns true if the specified character is among binary characters. + * + * Parameters + * @char c: character that is searched to be among binary characters + * + * Return value + * true if the specified character is among binary characters + * false if the character character is not among binary characters + * + * This function returns true if the specified character is among binary characters ('0' and '1'). + */ +bool is_binary_digit(char c) +{ + return (c == '0' || c == '1'); +} + +/** + * parse_cmd - This function builds the commands to be sent for each recognized escape sequence. + * + * Parameters + * @char c: character that is searched to be among command codes + * @unsigned char *pars parameters array, built in parse_text function + * @int idx_par index of last parameter in parameters array, built in parse_text function + * @int par_typ the type of the last parameter + * 0 - decimal + * 1 - hexa + * 2 - binary + * @struct pmodclp_device *dev pointer to device structure + * + * Return value + * 1 if the character was recognized as a command code and the parameters configuration is correct for that command + * 0 if the character is not a command code + * + * This function tries to mach the specified character and the parameters configuration to a command. + * If it does, the command is built and sent to PmodCLP on parallel interface and 1 is returned. + * If no command is recognized for the character, 0 is returned. + */ + +int parse_cmd(char c, unsigned char *pars, int idx_par, int par_type, struct pmodclp_device *dev) +{ + int is_consumed_char = 0; // this will be returned + unsigned char cmd; + switch (c) + { + case 'e': + // enable/disable display + if(idx_par >= 0 && par_type == 0 && pars[0] >=0 && pars[0] <=3) + { + // set display + int display, bk; + display = (pars[0] & 1) != 0; + if(display != dev->display_on) + { + dev->display_on = display; + write_display_control_cmd(dev); + } + + + // set background light, if the pin is defined. + if(dev->par_dev.iBK != -1) + { + bk = (pars[0] & 2)>>1; + if(bk != dev->bk_on) + { + dev->bk_on = bk; + gpio_set_value(dev->par_dev.iBK, bk); + } + } + is_consumed_char = 1; // mark char as consumed. + } + break; + case 'H': // set cursor position + if(idx_par == 1 && pars[0] >= 0 && pars[0] < MAX_NO_ROWS && pars[1] >= 0 && pars[1] < MAX_NO_COLS) + { + // allow only decimal parameter + dev->cur_row = pars[0]; + dev->exceeded_rows = 0; + cmd = 0x40*pars[0] + pars[1]; + cmd |= CMD_LCDSETDDRAMPOS; + pmodclp_write_command(&(dev->par_dev), cmd); + is_consumed_char = 1; // mark char as consumed. + } + break; + case 'j': // clear display and home cursor + dev->cur_row = 0; + dev->exceeded_rows = 0; + pmodclp_write_command(&(dev->par_dev), CMD_LCDCLEAR); + is_consumed_char = 1; // mark char as consumed. + break; + case '@': // scroll left + if(idx_par == 0 && pars[0] >= 0 && pars[0] < MAX_NO_COLS) + { + // allow only decimal parameter + int i; + cmd = CMD_LCDDISPLAYSHIFT; + for(i = 0; i< pars[0]; i++) + { + // scroll one position + pmodclp_write_command(&(dev->par_dev), cmd); + } + is_consumed_char = 1; // mark char as consumed. + } + break; + case 'A': // scroll right + if(idx_par == 0 && pars[0] >= 0 && pars[0] < MAX_NO_COLS) + { + // allow only decimal parameter + int i; + cmd = CMD_LCDDISPLAYSHIFT | MSK_SHIFTRL; + for(i = 0; i< pars[0]; i++) + { + // scroll one position + pmodclp_write_command(&(dev->par_dev), cmd); + } + is_consumed_char = 1; // mark char as consumed. + } + break; + case 'c': // set cursor mode + if(idx_par == 0 && par_type == 0 && pars[0] >= 0 && pars[0] <= 2) + { + // allow only decimal parameter + int cursor, blink; + + // set cursor + cursor = pars[0] >= 1; // 1 and 2 + if(cursor != dev->cursor_on) + { + dev->cursor_on = cursor; + write_display_control_cmd(dev); + } + // set blink + blink = pars[0] <= 1; // 0 and 1 + + if(blink != dev->blink_on) + { + dev->blink_on = blink; + write_display_control_cmd(dev); + } + is_consumed_char = 1; // mark char as consumed. + } + break; + case 'd': // define user programmable character + { + // define user char + if(idx_par == 8 && par_type == 0) + { + /* 9 params + - first 8 definition bytes and + - last one is the character number, allow only ecimal character + */ + + // set CGRAM pos + unsigned char cmd = CMD_LCDSETCGRAMPOS | (pars[8] << 3); + pmodclp_write_command(&(dev->par_dev), cmd); + + // write 8 character definition bytes as data + pmodclp_write_data(&(dev->par_dev), pars, 8); + is_consumed_char = 1; // mark} char as consumed. + } + } + break; + default: ; + // no command was recognized + } + return is_consumed_char; +} + + +/** + * parse_text - This function builds the commands to be sent for each recognized escape sequence. + * + * Parameters + * @char *txt_buf: the text array to be parsed + * @int cnt the number of charcaters to be parsed in the text array + * @struct pmodclp_device *dev pointer to device structure + * + * + * This function parses a text array, containing a sequence of one or more text or commands sent to PmodCLP. Its purpose is: + * - recognize, interpret the text sent to the device: + * - split the separate commands / text and process them individually. + * - recognize escape code commands and translate them into PmodCLP commands on parallel interface + * - send text data to PmodCLP device on parallel interface + * - maintain a shadow value of the current row (this is because the cursor position cannot be read) + * - recognize LF character ('\n') inside a text to be sent to the device + * - if current line is the first, move the cursor to the beginning of the next line + * - if current line is the second, there is no room for new line. Text characters after LF are ignored, commands are still interpreted. + * + */ +void parse_text(char *txt_buf, int cnt, struct pmodclp_device *dev) +{ + int is_ignore_txt; + int is_cmd = 0; + int is_inside_par = -1; + int is_consumed_char; + int par_type = 0; + + char *parse_ptr, *processed_ptr, *par_ptr; + int idx_par = -1; + unsigned char pars[10]; + par_ptr = NULL; + parse_ptr = txt_buf; + processed_ptr = txt_buf - 1; + is_cmd = 0; + par_type = -1; + is_ignore_txt = dev->exceeded_rows; + while(parse_ptr < (txt_buf + cnt)) + { + is_consumed_char = 0; // waiting to be consumed + // recognize command - look for ESC code, followed by '[' + if((!is_cmd) && ((*parse_ptr) == 0x1B) && (parse_ptr[1] == '[')) + { + // enter command mode + is_cmd = 1; + is_inside_par = 0;// able to receive the parameter + // send previous text (before the ESC sequence) + if((parse_ptr - processed_ptr) > 1) + { + pmodclp_write_data(&(dev->par_dev), processed_ptr + 1, parse_ptr - 1 - processed_ptr); + } + parse_ptr ++; // skip '[' char + } + else + { + if(is_cmd) + { + // look for commands + if(!(par_type == 1 && (parse_ptr - par_ptr) <= 2)) + { + // do not look for commands when current parameter is hexa and less than 2 chars are parsed + is_consumed_char = parse_cmd(*parse_ptr, pars, idx_par, par_type, dev); + } + is_ignore_txt = dev->exceeded_rows;// because command parsing may change this parameter + if(is_consumed_char) + { + // mark text as processed including the command char + if((parse_ptr - processed_ptr) > 0) + { + processed_ptr = parse_ptr; + is_cmd = 0; // comand mode is abandonned + } + } + if(!is_inside_par) + { + // look for begining of a parameter + if(is_decimal_digit(*parse_ptr)){ + par_type = -1; + if(*parse_ptr == '0'){ + if(parse_ptr[1] == 'x' || parse_ptr[1] == 'X'){ + // 0x or 0X sequence detected, start a hexa parameter + par_type = 1; + is_consumed_char = 1; // char was consumed + parse_ptr ++; // skip 'x' or 'X' char + } + else{ + if(parse_ptr[1] == 'b' || parse_ptr[1] == 'B'){ + // 0B or 0b sequence detected, start a binary parameter + par_type = 2; + is_consumed_char = 1; // char was consumed + parse_ptr ++; // skip 'b' or 'B' char + } + } + } + idx_par ++; + if(!is_consumed_char){ + // 0x or 0b were not detected, start a decimal parameter + par_type = 0; + pars[idx_par] = (*parse_ptr - '0'); + is_consumed_char = 1; // char was consumed + } + else{ + pars[idx_par] = 0; + } + par_ptr = parse_ptr; + is_inside_par = 1; + } + } + else{ + // inside parameter, look for ';' separator and parameter digits + if(!is_consumed_char){ + if((*parse_ptr) == ';') + { // parameters separator + par_ptr = NULL; + is_inside_par = 0; // look for a new parameter + is_consumed_char = 1; // char was consumed + } + } + if(!is_consumed_char){ + switch(par_type) + { + // interpret parameter digit + case 0: // decimal + if(is_decimal_digit(*parse_ptr)) + { + pars[idx_par] = 10*pars[idx_par] + (*parse_ptr - '0'); + is_consumed_char = 1; // char was consumed + } + // else wrong char, expecting decimal digit, do not consume char + break; + case 1: // hexa + if(is_hexa_digit(*parse_ptr)) + { + pars[idx_par] = pars[idx_par] << 4; + if(*parse_ptr >= '0' && *parse_ptr <= '9'){ + pars[idx_par] += (*parse_ptr - '0'); + } + else{ + if(*parse_ptr >= 'A' && *parse_ptr <= 'F'){ + pars[idx_par] += 10 + (*parse_ptr - 'A'); + } + else{ + pars[idx_par] += 10 + (*parse_ptr - 'a'); + } + } + is_consumed_char = 1; // char was consumed + } + // else wrong char, expecting decimal digit, do not consume char + break; + case 2: // binary + if(is_binary_digit(*parse_ptr)) + { + pars[idx_par] = (pars[idx_par] << 1) + (*parse_ptr - '0'); + is_consumed_char = 1; // char was consumed + } + // else wrong char, expecting binary digit, leave command mode + break; + } + } // end of interpret parameter digit + }// end of parameter} + if(!is_consumed_char) + { + // inside command mode, if character is not consumed, leave command mode + is_cmd = 0; + // consume unrecongnized command characters, makes no sense to display them on LCD + printk(KERN_INFO " Wrong command: %.*s \n", (parse_ptr - processed_ptr + 1), processed_ptr); + processed_ptr = parse_ptr; + } + // end of inside command + } + else + { + // free text, not inside a command + if(is_ignore_txt) + { + // if text is ignored, processed_ptr advances together with parse_ptr + processed_ptr = parse_ptr; + } + else + { + if((*parse_ptr) == '\n') + { // LF + // mark processed before the LF char + if((parse_ptr - processed_ptr) > 0) + { + pmodclp_write_data(&(dev->par_dev), processed_ptr + 1, parse_ptr - 1 - processed_ptr); + } + // position the cursor on the beginning of the next line + if(dev->cur_row < (MAX_NO_ROWS - 1)) + { + dev->cur_row++; + pmodclp_write_command(&(dev->par_dev), CMD_LCDSETDDRAMPOS + 0x40*dev->cur_row); + } + else + { + // there is no room to place a third line. Enter ignore text (still look for the comands) + is_ignore_txt = 1; + } + + // advance the pointers so that LF char is skipped next time when chars are sent + processed_ptr = parse_ptr; + } + } + } + } + parse_ptr ++; // advance one character +} + parse_ptr--; + // send remaining chars + + if(((parse_ptr - processed_ptr) > 0)) + { + if(!is_cmd) + { + pmodclp_write_data(&(dev->par_dev), processed_ptr + 1, parse_ptr - processed_ptr); + } + else + { + printk(KERN_INFO " Wrong command: %.*s \n", (parse_ptr - processed_ptr + 2), processed_ptr + 1); + } + } + + dev->exceeded_rows = is_ignore_txt; +} + +/** + * Driver Read Function + * + * This function does not actually read the PmodCLP as it is a write-only device. + */ +static ssize_t pmodclp_read(struct file *fp, char __user *buffer, size_t length, loff_t *offset) +{ + ssize_t retval = 0; + return(retval); +} + + +struct file_operations pmodclp_cdev_fops = { + .owner = THIS_MODULE, + .write = pmodclp_write, + .read = pmodclp_read, + .open = pmodclp_open, + .release = pmodclp_close, +}; + + + +/** + * pmodclp_setup_cdev - Setup Char Device for ZED PmodCLP device. + * @dev: pointer to device tree node + * @dev_id: pointer to device major and minor number + * @spi: pointer to spi_device structure + * + * This function initializes char device for PmodCLP device, and add it into + * kernel device structure. It returns 0, if the cdev is successfully + * initialized, or a negative value if there is an error. + */ +static int pmodclp_setup_cdev(struct pmodclp_device *dev, dev_t *dev_id) +{ + int status = 0; + struct device *device; + cdev_init(&dev->cdev, &pmodclp_cdev_fops); + dev->cdev.owner = THIS_MODULE; + dev->cdev.ops = &pmodclp_cdev_fops; + + + *dev_id = MKDEV(MAJOR(pmodclp_dev_id), cur_minor++); + status = cdev_add(&dev->cdev, *dev_id, 1); + if(status < 0) { + printk(KERN_INFO " cdev_add failed ...\n"); + return status; + } + + /* Add Device node in system */ + device = device_create(pmodclp_class, NULL, + *dev_id, NULL, + "%s", dev->name); + if(IS_ERR(device)) { + status = PTR_ERR(device); + printk(KERN_INFO "failed to create device node %s, err %d\n", + dev->name, status); + cdev_del(&dev->cdev); + } + + return status; +} + + + + + + +static const struct of_device_id pmodclp_of_match[] __devinitconst = { + { .compatible = "dglnt,pmodclp", }, + {}, +}; +MODULE_DEVICE_TABLE(of, pmodclp_of_match); + +/** + * pmodclp_of_probe - Probe method for PmodCLP device (over GPIO). + * @pdev: pointer to platform devices + * + * This function probes the PmodCLP device in the device tree. It initializes the + * PmodCLP driver data structure. It returns 0, if the driver is bound to the PmodCLP + * device, or a negative value if there is an error. + */ +static int __devinit pmodclp_of_probe(struct platform_device *pdev) +{ + struct pmodclp_device *pmodclp_dev; + + + struct device_node *np = pdev->dev.of_node; + + int status = 0; + + + /* Alloc Space for platform device structure */ + pmodclp_dev = (struct pmodclp_device*) kzalloc(sizeof(*pmodclp_dev), GFP_KERNEL); + if(!pmodclp_dev) { + status = -ENOMEM; + goto dev_alloc_err; + } + + /* Alloc Text Buffer for device */ + pmodclp_dev->txt_buf = (unsigned char*) kmalloc(TXT_BUF_SIZE, GFP_KERNEL); + if(!pmodclp_dev->txt_buf) { + status = -ENOMEM; + dev_err(&pdev->dev, "Device Display data buffer allocation failed: %d\n", status); + goto txt_buf_alloc_err; + } + + /* Get the GPIO Pins */ + pmodclp_dev->par_dev.iRS = of_get_named_gpio(np, "rs-gpio", 0); + pmodclp_dev->par_dev.iRW = of_get_named_gpio(np, "rw-gpio", 0); + pmodclp_dev->par_dev.iE = of_get_named_gpio(np, "e-gpio", 0); + status = of_get_named_gpio(np, "bk-gpio", 0); + pmodclp_dev->par_dev.iBK = (status < 0) ? -1 : status; + + pmodclp_dev->par_dev.iData[0] = of_get_named_gpio(np, "data0-gpio", 0); + pmodclp_dev->par_dev.iData[1] = of_get_named_gpio(np, "data1-gpio", 0); + pmodclp_dev->par_dev.iData[2] = of_get_named_gpio(np, "data2-gpio", 0); + pmodclp_dev->par_dev.iData[3] = of_get_named_gpio(np, "data3-gpio", 0); + pmodclp_dev->par_dev.iData[4] = of_get_named_gpio(np, "data4-gpio", 0); + pmodclp_dev->par_dev.iData[5] = of_get_named_gpio(np, "data5-gpio", 0); + pmodclp_dev->par_dev.iData[6] = of_get_named_gpio(np, "data6-gpio", 0); + pmodclp_dev->par_dev.iData[7] = of_get_named_gpio(np, "data7-gpio", 0); + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: iRS: 0x%lx\n", np->name, pmodclp_dev->par_dev.iRS); + printk(KERN_INFO DRIVER_NAME " %s: iRW: 0x%lx\n", np->name, pmodclp_dev->par_dev.iRW); + printk(KERN_INFO DRIVER_NAME " %s: iE : 0x%lx\n", np->name, pmodclp_dev->par_dev.iE); + printk(KERN_INFO DRIVER_NAME " %s: iBK : 0x%lx\n", np->name, pmodclp_dev->par_dev.iBK); + + printk(KERN_INFO DRIVER_NAME " %s: iData[0] : 0x%lx\n", np->name, pmodclp_dev->par_dev.iData[0]); + printk(KERN_INFO DRIVER_NAME " %s: iData[1] : 0x%lx\n", np->name, pmodclp_dev->par_dev.iData[1]); + printk(KERN_INFO DRIVER_NAME " %s: iData[2] : 0x%lx\n", np->name, pmodclp_dev->par_dev.iData[2]); + printk(KERN_INFO DRIVER_NAME " %s: iData[3] : 0x%lx\n", np->name, pmodclp_dev->par_dev.iData[3]); + printk(KERN_INFO DRIVER_NAME " %s: iData[4] : 0x%lx\n", np->name, pmodclp_dev->par_dev.iData[4]); + printk(KERN_INFO DRIVER_NAME " %s: iData[5] : 0x%lx\n", np->name, pmodclp_dev->par_dev.iData[5]); + printk(KERN_INFO DRIVER_NAME " %s: iData[6] : 0x%lx\n", np->name, pmodclp_dev->par_dev.iData[6]); + printk(KERN_INFO DRIVER_NAME " %s: iData[7] : 0x%lx\n", np->name, pmodclp_dev->par_dev.iData[7]); +#endif + pmodclp_dev->name = (char *)np->name; + + // initialize device data + pmodclp_dev->cur_row = 0; + pmodclp_dev->exceeded_rows = 0; + + pmodclp_dev->display_on = 0; + pmodclp_dev->cursor_on = 0; + pmodclp_dev->blink_on = 0; + pmodclp_dev->bk_on = 0; + + /* Point device node data to pmodclp_device structure */ + if(np->data == NULL) + np->data = pmodclp_dev; + + if(pmodclp_dev_id == 0) { + /* Alloc Major & Minor number for char device */ + status = alloc_chrdev_region(&pmodclp_dev_id, 0, MAX_PMODCLP_DEV_NUM, DRIVER_NAME); + if(status) { + dev_err(&pdev->dev, "Character device region not allocated correctly: %d\n", status); + goto err_alloc_chrdev_region; + } +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Char Device Region Registered, with Major: %d.\n", + MAJOR(pmodclp_dev_id)); +#endif + } + + if(pmodclp_class == NULL) { + /* Create Pmodclp Device Class */ + pmodclp_class = class_create(THIS_MODULE, DRIVER_NAME); + if (IS_ERR(pmodclp_class)) { + status = PTR_ERR(pmodclp_class); + goto err_create_class; + } +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : pmodclp device class registered.\n"); +#endif + } + + /* Setup char driver */ + status = pmodclp_setup_cdev(pmodclp_dev, &(pmodclp_dev->dev_id)); + if (status) { + printk(KERN_INFO " pmodclp_probe: Error adding %s device: %d\n", DRIVER_NAME, status); + goto cdev_add_err; + } + + device_num ++; + + /* Initialize Mutex */ + mutex_init(&pmodclp_dev->mutex); + + + status = pmodclp_init_gpio(pmodclp_dev); + if (status) { + printk(KERN_INFO " spi_probe: Error init gpio: %d\n", status); + goto cdev_add_err; + } + + pmodclp_init(&pmodclp_dev->par_dev); + + return status; + +err_create_class: + unregister_chrdev_region(pmodclp_dev_id, MAX_PMODCLP_DEV_NUM); + pmodclp_dev_id = 0; +err_alloc_chrdev_region: +cdev_add_err: + + printk(KERN_INFO DRIVER_NAME " Free text buffer.\n"); + + kfree(pmodclp_dev->txt_buf); +txt_buf_alloc_err: + kfree(pmodclp_dev); +dev_alloc_err: + return status; +} + +/** + * pmodclp_init_gpio - Initialize GPIO for ZED PmodCLP device + * @dev - pmodclp_device + * + * Initializes PmodCLP GPIO Control Pins. + * It returns 0, if the gpio pins are successfully + * initialized, or a negative value if there is an error. + */ +static int pmodclp_init_gpio(struct pmodclp_device *pmodclp_dev) +{ + struct gpio pmodclp_ctrl[] = { + {pmodclp_dev->par_dev.iRS, GPIOF_OUT_INIT_HIGH, "CLP RS"}, + {pmodclp_dev->par_dev.iRW, GPIOF_OUT_INIT_HIGH, "CLP RW"}, + {pmodclp_dev->par_dev.iE, GPIOF_OUT_INIT_HIGH, "CLP E"}, + {pmodclp_dev->par_dev.iData[0], GPIOF_OUT_INIT_HIGH, "CLP DATA[0]"}, + {pmodclp_dev->par_dev.iData[1], GPIOF_OUT_INIT_HIGH, "CLP DATA[1]"}, + {pmodclp_dev->par_dev.iData[2], GPIOF_OUT_INIT_HIGH, "CLP DATA[2]"}, + {pmodclp_dev->par_dev.iData[3], GPIOF_OUT_INIT_HIGH, "CLP DATA[3]"}, + {pmodclp_dev->par_dev.iData[4], GPIOF_OUT_INIT_HIGH, "CLP DATA[4]"}, + {pmodclp_dev->par_dev.iData[5], GPIOF_OUT_INIT_HIGH, "CLP DATA[5]"}, + {pmodclp_dev->par_dev.iData[6], GPIOF_OUT_INIT_HIGH, "CLP DATA[6]"}, + {pmodclp_dev->par_dev.iData[7], GPIOF_OUT_INIT_HIGH, "CLP DATA[7]"}, + {pmodclp_dev->par_dev.iBK, GPIOF_OUT_INIT_HIGH, "CLP BK"} + }; + int status; + int i; + int array_size = pmodclp_dev->par_dev.iBK == -1 ? (ARRAY_SIZE(pmodclp_ctrl) - 1): ARRAY_SIZE(pmodclp_ctrl); + + for (i = 0; i < array_size; i++) { + status = gpio_is_valid(pmodclp_ctrl[i].gpio); + if(!status) { + printk(KERN_INFO "!! gpio_is_valid for GPIO %d, %s FAILED!, status: %d\n", + pmodclp_ctrl[i].gpio, pmodclp_ctrl[i].label, status); + goto gpio_invalid; + } + } + + printk(KERN_INFO "** gpio_request_array array_size = %d, ARRAY_SIZE = %d\n", array_size, ARRAY_SIZE(pmodclp_ctrl)); + + status = gpio_request_array(pmodclp_ctrl, ARRAY_SIZE(pmodclp_ctrl)); + if(status) { + printk(KERN_INFO "!! gpio_request_array FAILED!\n"); + printk(KERN_INFO " status is: %d, array_size = %d, ARRAY_SIZE = %d\n", status, array_size, ARRAY_SIZE(pmodclp_ctrl)); + gpio_free_array(pmodclp_ctrl, 4); + goto gpio_invalid; + } + + +gpio_invalid: +//gpio_direction_output_invalid: + return status; +} + +/** + * pmodclp_of_remove - Remove method for ZED PmodCLP device. + * @np: pointer to device tree node + * + * This function removes the PmodCLP device in the device tree. It frees the + * PmodCLP driver data structure. It returns 0, if the driver is successfully + * removed, or a negative value if there is an error. + */ +static int pmodclp_of_remove(struct platform_device *pdev) +{ + struct pmodclp_device *pmodclp_dev; + struct device_node *np = pdev->dev.of_node; + + if(np->data == NULL) { + dev_err(&pdev->dev, "pmodclp %s: ERROR: No pmodclp_device structure found!\n", np->name); + return -ENOSYS; + } + pmodclp_dev = (struct pmodclp_device*) (np->data); + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s : Free text buffer.\n", np->name); +#endif + + if(pmodclp_dev->txt_buf != NULL) { + kfree(pmodclp_dev->txt_buf); + } + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s : Unregister gpio_spi Platform Devices.\n", np->name); +#endif + + np->data = NULL; + device_num--; + + /* Destroy pmodclp class, Release device id Region after + * all pmodclp devices have been removed. + */ + if(device_num == 0) { +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Destroy pmodclp_gpio Class.\n"); +#endif + + if(pmodclp_class) { + class_destroy(pmodclp_class); + } + pmodclp_class = NULL; + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Release Char Device Region.\n"); +#endif + + unregister_chrdev_region(pmodclp_dev_id, MAX_PMODCLP_DEV_NUM); + pmodclp_dev_id = 0; + } + + return 0; +} + +static struct platform_driver pmodclp_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = pmodclp_of_match, + }, + .probe = pmodclp_of_probe, + .remove = __devexit_p(pmodclp_of_remove), +}; + +module_platform_driver(pmodclp_driver); + +MODULE_AUTHOR("Digilent, Inc."); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(DRIVER_NAME": PmodCLP display driver"); +MODULE_ALIAS(DRIVER_NAME); From 9ca7b9eda6473ec254c264bfd521cb91f1d34813 Mon Sep 17 00:00:00 2001 From: Cristian Fatu Date: Wed, 5 Dec 2012 21:04:03 -0800 Subject: [PATCH 230/261] Digilent: Pmods: Added PmodDA1 driver and documentation --- Documentation/pmods/pmodda1.txt | 120 +++++ drivers/pmods/Kconfig | 6 + drivers/pmods/Makefile | 1 + drivers/pmods/pmodda1.c | 840 ++++++++++++++++++++++++++++++++ 4 files changed, 967 insertions(+) create mode 100644 Documentation/pmods/pmodda1.txt create mode 100644 drivers/pmods/pmodda1.c diff --git a/Documentation/pmods/pmodda1.txt b/Documentation/pmods/pmodda1.txt new file mode 100644 index 0000000000000..82547d5c7d01a --- /dev/null +++ b/Documentation/pmods/pmodda1.txt @@ -0,0 +1,120 @@ +PmodDA1 +======== + +Copyright 2012, Digilent Inc. + + +Description +----------- + +The Digilent PmodDA1 Digital To Analog Module Converter Board (the DA1) converts +signals from digital to analog at up to one MSa per second. + +The Digilent PmodDA1 relies on two Analog Devices AD7303, thus implementing four +simultaneous D/A conversion channels, each with an 8-bit converter that can +process a separate digital signal. + +The PmodDA1 converts an 8 bit digital value to an analog output +ranging from 0-3.3 volts. + +This Linux driver is based on SPI. Because SPI can not write on Data Out line of +SPI, only the 2 channels corresponding to the first AD7303 (the channels corresponding +to A1 and B1 pins of J2 connector of PmodDA1) can be accessed using this driver. + +The driver is implemented as a character driver. Corresponding to each channel, +two separates nodes are created by the driver code, having different minor numbers. + +The basic action of the driver is write, when 8 bits data is outputted to each of the +two channels. Still, read function is also implemented, by providing the last written +value. + +The Reference Manual for PmodDA1 device is available online at +Digilent Inc. Website (www.digilentinc.com). + + +Interface +--------- + +Signal Description + +SDIN SPI Data Out (MOSI) +SCLK SPI Clock +SS Slave Select + + +Devicetree +---------- + +Required Properties: +- compatible : Should be "dlgnt,pmodda1" +- spi-bus-num : Should specify the bus number for PmodDA1 SPI controller. + This value cannot be shared by any other SPI controller present in the + device tree. +- spi-sclk-gpio : Should specify the GPIO for SCLK, see "gpios property" in + Documentation/devicetree/gpio.txt. +- spi-sdin-gpio : Should specify the GPIO for SDIN, see "gpios property" in + Documentation/devicetree/gpio.txt. + +Optional Properties: +- spi-cs-gpio : Should specify the GPIO for CS, see "gpios property" in + Documentation/devicetree/gpio.txt. If unspecified, CS is assumed to be + tied to ground. +- spi-speed-hz : Should specify the spi speed (in Hz). If unspecified, spi + speed is assumed to be 625000 (625 kHz). + +Examples: + + pmodda1 { + compatible = "dglnt,pmodda1"; + spi-bus-num = <0x4>; + spi-speed-hz = <625000>; + spi-sclk-gpio = <0x8 85 0>; + spi-sdin-gpio = <0x8 83 0>; + spi-cs-gpio = <0x8 82 0>; + }; + + +Configuration +------------- + +The PmodDA1 is located in the kernel configuration menu at +Device Drivers -> Pmods -> PmodDA1. The driver can be built into the kernel +by selecting (*) for it, or loadable module by selecting (M) for it. + + +Device Nodes +------------ + +Two char device nodes are created for each PmodDA1 device automatically, +having 0 and 1 as minor numbers. + +The name of the nodes is by default the one declared in the device tree, +postfixed with "_0" (for channel A1) and "_1" (for channel B1). + + +Writing to the device +----------- +Characters written to the device are used as 8 bits values sent to the appropriate +converter channel. While writing to a channel the other channel is not disabled, +allowing it to perform its current task. + + +Reading from the device +----------- +The PmodDA1 is a "write only" device. Still, the driver implements a shadow register +that also maintains the last value written to the converter. When read occurs, this +value is used to fill the read buffer. + + +Example of commands +----------- + +- Write 0x80 value to second channel (B1) of the device +echo -n -e "\x80" > /dev/pmodda1_1 + +- Read (repeatedly) first channel (A1) of the device +hexdump -C -v /dev/pmodda1_0 + + + + diff --git a/drivers/pmods/Kconfig b/drivers/pmods/Kconfig index 2e7e6a2785a26..df338863ed561 100644 --- a/drivers/pmods/Kconfig +++ b/drivers/pmods/Kconfig @@ -28,4 +28,10 @@ config PMODCLP help This is the Digilent PmodCLP driver. Implements parallel access. +config PMODDA1 + tristate "pmodda1" + select SPI_BITBANG + help + This is the Digilent PmodDA1 driver. Uses SPI over GPIO. + endif # PMODS diff --git a/drivers/pmods/Makefile b/drivers/pmods/Makefile index 7d9b98649194f..109cb652393b4 100644 --- a/drivers/pmods/Makefile +++ b/drivers/pmods/Makefile @@ -4,4 +4,5 @@ ccflags-$(CONFIG_PMODS_DEBUG) += -DDEBUG obj-$(CONFIG_PMODOLED) += pmodoled-gpio.o obj-$(CONFIG_PMODCLS) += pmodcls.o obj-$(CONFIG_PMODCLP) += pmodclp.o +obj-$(CONFIG_PMODDA1) += pmodda1.o diff --git a/drivers/pmods/pmodda1.c b/drivers/pmods/pmodda1.c new file mode 100644 index 0000000000000..1912c09cb2cdb --- /dev/null +++ b/drivers/pmods/pmodda1.c @@ -0,0 +1,840 @@ +/* + * Digilent PmodDA1 linux driver for Zed + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "pmodda1" +#define SPI_DRIVER_NAME "pmodda1-spi" + +#define DEFAULT_SPI_SPEED 625000 +#define PMODDA1_DEV_NUM 2 // only 2 channels as SPI does not allow write on Data In line. + +#define DEFAULT_BUF_SZ 512 +/* + * default size of the buffer for each DAC on the device. Can be + * changed from the default during insmod. + */ +int buf_sz = DEFAULT_BUF_SZ; +module_param(buf_sz, int, 0); + +dev_t pmodda1_first_dev_id = 0; +struct spi_device *spi_device; +static unsigned int spi_drv_registered = 0; +static struct class *pmodda1_class = NULL; + +struct pmodda1_device { + char *name; + + unsigned int minor_id; + /* Data Buffer */ + unsigned char *buf; // Device data buffer + /* Pin Assignment */ + + unsigned long iSCLK; + unsigned long iSDIN; + unsigned long iCS; + + /* SPI Info */ + uint32_t spi_speed; + uint32_t spi_id; + /* platform device structures */ + struct platform_device *pdev; + /* Char Device */ + struct cdev cdev; + struct spi_device *spi; + dev_t dev_id; +}; + +/* + * create a shadow register to configure the devices using a + * struct for the physical D to A parts used on the Pmod. + * this is intended to hold the state for each D to A such + * that a control word can be built for the device when a + * write request comes for any of the channels. + */ +struct ad7303 +{ + bool ext; + bool ldac; + bool pdb; + bool pda; + bool sel; /* !A/B in the datasheet for the AD7303, bit 10 in the control reg */ + bool cr1; + bool cr0; + uint8_t a_val; + uint8_t b_val; + struct mutex mutex; +}; + +static struct pmodda1_device *rgpmodda1_devices[PMODDA1_DEV_NUM]; /* create pointer array to hold device info */ + +static struct ad7303 dac1; +// Forward definitions +static uint16_t make_cmd_from_shadow_regs(struct ad7303 *dac); +int write_spi_16(struct spi_device *spi, uint16_t cmd_data); + +/* make_cmd_from_shadow_regs + * @dac the ad7303 structure who's bits are used. + * this function places the configuration bits in the proper + * bit position to form the command word the AD73703 expects + * to receive. + */ +static uint16_t make_cmd_from_shadow_regs(struct ad7303 *dac) +{ + uint16_t cd = 0; + + cd = ((dac->ext & 1) << 15); + cd |= ((dac->ldac & 1) << 13); + cd |= ((dac->pdb & 1) << 12); + cd |= ((dac->pda & 1) << 11); + cd |= ((dac->sel & 1) << 10); + cd |= ((dac->cr1 & 1) << 9); + cd |= ((dac->cr0 & 1) << 8); + + return cd; +} + +/** + * write_spi_16 - Write a 16 bit variable to SPI in High - Low order. + * @spi: pointer to spi_device structure + * @cmd_data: the 16 bits variable containing data to be written to spi + * + * This function writes to spi the 16 bits of data, big endian (first High and then Low bytes), regardless of CPU representation. + * It returns the spi write return value (0 on success). + */ +int write_spi_16(struct spi_device *spi, uint16_t cmd_data) +{ + int status; // spi_write return value + /* Change endianness of data, if necessary + * The data must be written to SPI in big endian, + * whereas some CPU architectures are little endian. + */ + uint16_t write_cmd_data = cpu_to_be16(cmd_data); + status = spi_write(spi, &write_cmd_data, 2); + return status; +} +/** + * A basic open function. + */ +static int pmodda1_open(struct inode *inode, struct file *fp) +{ + struct pmodda1_device *dev; + + dev = container_of(inode->i_cdev, struct pmodda1_device, cdev); + dev->minor_id = iminor(inode); + fp->private_data = dev; + + return 0; +} + +/** + * A basic close function, do nothing. + */ +static int pmodda1_close(struct inode *inode, struct file *fp) +{ + return 0; +} + +/* + * Driver write function + * + * This function uses a generic SPI write to send values to the Pmod device. + * It takes a string from the app in the buffer. + * It sends the commands and the text to PmodDA1 over the standard SPI interface. + * + */ +static ssize_t pmodda1_write(struct file *fp, const char __user *buffer, size_t length, loff_t *offset) +{ + ssize_t retval = 0; + int status; // spi_write return value + int cnt; + int i; + unsigned int minor_id; + struct mutex *mutex; + uint16_t cmd_data; + struct pmodda1_device *dev; + + dev = fp->private_data; + minor_id = dev->minor_id; + + if (minor_id > PMODDA1_DEV_NUM - 1) { + dev_err(&dev->spi->dev, "da1_write: ERROR: Attempt to read a non-existant device: %d\n", minor_id); + retval = -ENOTTY; + goto bad_device; + } + dev = rgpmodda1_devices[minor_id]; + mutex = &dac1.mutex; // get the mutex for the part we will be programming + + if (mutex_lock_interruptible(mutex)) { + retval = -ERESTARTSYS; + goto write_lock_err; + } + + + if(length > buf_sz) + cnt = buf_sz; + else + cnt = length; + + if(copy_from_user(dev->buf, buffer, cnt)) + { + retval = -EFAULT; + goto quit_write; + } + retval = cnt; + + dev->buf[cnt] = '\0'; + /* use the minor id number to select which channel to program */ + + // the command word is constructed here + if((minor_id == 0)) { + dev_dbg(&dev->spi->dev, "da1_write: setting DAC_A (or even number DAC)\n"); + dac1.pda = 0; // want DAC A powered up, don't touch DAC B's setting + dac1.sel = 0; // this will indicate to load DAC A + } + else { + dev_dbg(&dev->spi->dev, "da1_write: setting DAC_B (or odd number DAC)\n"); + dac1.pdb = 0; // want DAC B powered up, don't touch DAC A's setting + dac1.sel = 1; // this will indicate to load DAC B + } + dac1.ext = 0; // select internal reference for now + dac1.ldac = 1; // will program DAC input reg from shift reg and update both DAC registers + + cmd_data = make_cmd_from_shadow_regs(&dac1); + for (i = 0; i < cnt; i++) { + cmd_data &= 0xFF00; + cmd_data |= dev->buf[i]; + + status = write_spi_16(dev->spi, cmd_data); + + + if(!status) { // seems like spi_write returns 0 on success + retval = i+1; // but system write function expects to see number of bytes written + } + else { + retval = -EIO; + } + } + + // save the last value written to the DAC + switch(minor_id){ + case 0: dac1.a_val = dev->buf[i-1]; + break; + case 1: dac1.b_val = dev->buf[i-1]; + break; + } +quit_write: + mutex_unlock(mutex); + dev_dbg (&dev->spi->dev, "da1_write: Writing to display complete\n"); +bad_device: +write_lock_err: + + return(retval); +} + + +/* + * Driver read function + * + * This function does not actually read the Pmod as it is a read-only device. Instead + * it returns a shadowed copy of the value that was used when the DAC was last programmed. + */ +static ssize_t pmodda1_read(struct file *fp, char __user *buffer, size_t length, loff_t *offset) +{ + ssize_t retval = 0; + int i; + struct pmodda1_device *dev; + unsigned int minor_id; + uint8_t rd_val; + struct mutex *mutex; + int cnt; + + dev = fp->private_data; + minor_id = dev->minor_id; + + if (length > buf_sz) + cnt = buf_sz; + else + cnt = length; + if (minor_id > PMODDA1_DEV_NUM - 1) { + dev_err(&dev->spi->dev, "da1_read: ERROR: Attempt to read a non-existant device: %d\n", minor_id); + retval = -ENOTTY; + goto bad_device; + } + + if (minor_id < 2) + mutex = &dac1.mutex; + + if (mutex_lock_interruptible(mutex)) { + retval = -ERESTARTSYS; + goto lock_err; + } + + if (buffer == NULL) { + dev_err(&dev->spi->dev, "da1_read: ERROR: invalid buffer address: 0x%08X\n", (unsigned int)buffer); + retval = -EINVAL; + goto quit_read; + } + + /* ok, can use the minor id number to select which DAC value to return */ + switch (minor_id){ + case 0: rd_val = dac1.a_val; + break; + case 1: rd_val = dac1.b_val; + break; + default: + rd_val = 0; /* git rid of warning about rd_val may be used uninitialized */ + } +// tmp, read value from spi +spi_read(dev->spi, &rd_val, 2); +printk(KERN_INFO DRIVER_NAME "Read values Last Value\t%X\n", rd_val); + for (i = 0; i < cnt; i++) + dev->buf[i] = rd_val; + + retval = copy_to_user((void *)buffer, (void *)dev->buf, cnt); + if (!retval) + retval = cnt; /* copy success, return amount in buffer */ + +quit_read: + mutex_unlock(mutex); +lock_err: +bad_device: + return(retval); +} + + +struct file_operations pmodda1_cdev_fops = { + .owner = THIS_MODULE, + .write = pmodda1_write, + .read = pmodda1_read, + .open = pmodda1_open, + .release = pmodda1_close, +}; + + +/** + * add_pmodda1_device_to_bus - Add device to SPI bus, initialize SPI data. + * @dev: pointer to device tree node + * + * This function adds device to SPI bus, initialize SPI data. + */ +static int __init add_pmodda1_device_to_bus(struct pmodda1_device* dev) { + struct spi_master *spi_master; + int status = 0; + + spi_master = spi_busnum_to_master(dev->spi_id); + if(!spi_master) { + dev_err(&dev->pdev->dev, "spi_busnum_to_master(%d) returned NULL\n", dev->spi_id); + return -ENOSYS; + } + + spi_device = spi_alloc_device(spi_master); + if(!spi_device) { + put_device(&spi_master->dev); + dev_err(&dev->pdev->dev, "spi_alloc_device() failed\n"); + return -ENOMEM; + } + + spi_device->chip_select = 0; + spi_device->max_speed_hz = dev->spi_speed; + spi_device->mode = SPI_MODE_0; + spi_device->bits_per_word = 8; + spi_device->controller_data = (void *) dev->iCS; + spi_device->dev.platform_data = dev; + strlcpy(spi_device->modalias, SPI_DRIVER_NAME, sizeof(SPI_DRIVER_NAME)); + + status = spi_add_device(spi_device); + if(status < 0) { + spi_dev_put(spi_device); + dev_err(&dev->pdev->dev, "spi_add_device() failed %d\n", status); + return status; + } + dev->spi = spi_device; + + put_device(&spi_master->dev); + printk(KERN_INFO DRIVER_NAME " SPI initialized, max_speed_hz\t%d\n", spi_device->max_speed_hz); + + return status; +} + +/** + * pmodda1_setup_cdev - Setup Char Device for ZED PmodDA1 device. + * @dev: pointer to device tree node + * @dev_id: pointer to device major and minor number + * @spi: pointer to spi_device structure + * + * This function initializes char device for PmodDA1 device, and add it into + * kernel device structure. It returns 0, if the cdev is successfully + * initialized, or a negative value if there is an error. + */ +static int pmodda1_setup_cdev(struct pmodda1_device *dev, dev_t *dev_id, int idx, struct spi_device *spi) +{ + int status = 0; + struct device *device; + unsigned int major_id = MAJOR(pmodda1_first_dev_id); + unsigned int minor_id = MINOR(pmodda1_first_dev_id) + idx; + char min_name[50]; + + cdev_init(&dev->cdev, &pmodda1_cdev_fops); + dev->cdev.owner = THIS_MODULE; + dev->cdev.ops = &pmodda1_cdev_fops; + dev->spi = spi; + + *dev_id = MKDEV(major_id, minor_id); + status = cdev_add(&dev->cdev, *dev_id, 1); + if(status < 0) { + return status; + } + + /* Add Device node in system */ + sprintf(min_name, "%s_%d", dev->name, idx); + device = device_create(pmodda1_class, NULL, + *dev_id, NULL, + min_name); + if(IS_ERR(device)) { + status = PTR_ERR(device); + dev_err(&spi->dev, "failed to create device node %s, err %d\n", + dev->name, status); + cdev_del(&dev->cdev); + } + printk(KERN_INFO SPI_DRIVER_NAME "pmodda1_setup_cdev: Create device %s, major %d, minor %d\n", + min_name, major_id, minor_id); + return status; +} + + + + +/** + * SPI hardware probe. Sets correct SPI mode, attempts + * to obtain memory needed by the driver and, for each + * desired minor number device, it performs a simple + * initialization of the corresponding device. + */ +static int pmodda1_spi_probe(struct spi_device *spi) { + int status = 0; + struct pmodda1_device *pmodda1_dev; + int i; + /* We must use SPI_MODE_0 */ + spi->mode = SPI_MODE_0; + spi->bits_per_word = 8; + + status = spi_setup(spi); + if(status < 0) { + dev_err(&spi->dev, "needs SPI mode %02x, %d KHz; %d\n", + spi->mode, spi->max_speed_hz / 1000, + status); + goto spi_err; + } + + /* Get pmodda1_device structure */ + pmodda1_dev = (struct pmodda1_device*) spi->dev.platform_data; + if(pmodda1_dev == NULL) { + dev_err(&spi->dev, "Cannot get pmodda1_device.\n"); + status = -EINVAL; + goto spi_platform_data_err; + } + + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO SPI_DRIVER_NAME " [%s] spi_probe: setup char device\n", pmodda1_dev->name); +#endif + for (i = 0;i < PMODDA1_DEV_NUM; i++) { + rgpmodda1_devices[i] = kmalloc(sizeof(struct pmodda1_device), GFP_KERNEL); + if (!rgpmodda1_devices[i]) + { + status = -ENOMEM; + dev_err(&spi->dev, "da1_spi_probe: Device structure allocation failed: %d for device %d\n", status, i); + goto dev_alloc_err; + } + rgpmodda1_devices[i]->buf = NULL; + } + + for (i = 0; i < PMODDA1_DEV_NUM; i++) { + rgpmodda1_devices[i]->buf = (unsigned char *)kmalloc(buf_sz, GFP_KERNEL); + if (!rgpmodda1_devices[i]->buf) { + status = -ENOMEM; + dev_err(&spi->dev, "Device value buffer allocation " + "failed: %d\n", status); + goto buf_alloc_err; + } + rgpmodda1_devices[i]->spi = spi_device; + } + + /* Setup char driver for each device*/ + for (i = 0; i < PMODDA1_DEV_NUM; i++) { + status = pmodda1_setup_cdev(pmodda1_dev, &(pmodda1_dev->dev_id), i, spi); + if(status) { + dev_err(&spi->dev, "pmodda1_spi_probe: Error adding da1_spi device: %d for device %d\n", status, i); + goto cdev_add_err; + } + } + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO SPI_DRIVER_NAME " [%s] spi_probe: initialize device\n", pmodda1_dev->name); +#endif + + return status; +buf_alloc_err: + for (i = 0; i < PMODDA1_DEV_NUM; i++) { + if(rgpmodda1_devices[i] && rgpmodda1_devices[i]->buf) + kfree(rgpmodda1_devices[i]->buf); + } +dev_alloc_err: + for (i = 0; i < PMODDA1_DEV_NUM; i++) { + if(rgpmodda1_devices[i]) + kfree(rgpmodda1_devices[i]); + } +cdev_add_err: +spi_platform_data_err: +spi_err: + return(status); +} + +/** + * pmodda1_spi_remove - SPI hardware remove. + * Performs tasks required when SPI is removed. + */ +static int __devexit pmodda1_spi_remove(struct spi_device *spi) +{ + int status; + struct pmodda1_device *dev; + + dev = (struct pmodda1_device*) spi->dev.platform_data; + + if(dev == NULL) { + dev_err(&spi->dev, "spi_remove: Error fetch pmodda1_device struct\n"); + return -EINVAL; + } + + + if(&dev->cdev) { +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO SPI_DRIVER_NAME " [%s] spi_remove: Destroy Char Device\n", dev->name); +#endif + device_destroy(pmodda1_class, dev->dev_id); + cdev_del(&dev->cdev); + } + + return status; +} + +static struct spi_driver pmodda1_spi_driver = { + .driver = { + .name = SPI_DRIVER_NAME, + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = pmodda1_spi_probe, + .remove = __devexit_p(pmodda1_spi_remove), +}; + +static const struct of_device_id pmodda1_of_match[] __devinitconst = { + { .compatible = "dglnt,pmodda1", }, + {}, +}; +MODULE_DEVICE_TABLE(of, pmodda1_of_match); + +/** + * pmodda1_of_probe - Probe method for PmodDA1 device (over GPIO). + * @pdev: pointer to platform devices + * + * This function probes the PmodDA1 device in the device tree. It initializes the + * PmodDA1 driver data structure. It returns 0, if the driver is bound to the PmodDA1 + * device, or a negative value if there is an error. + */ +static int __devinit pmodda1_of_probe(struct platform_device *pdev) +{ + struct pmodda1_device *pmodda1_dev; + struct platform_device *pmodda1_pdev; + struct spi_gpio_platform_data *pmodda1_pdata; + + struct device_node *np = pdev->dev.of_node; + + const u32* tree_info; + const u32* spi_speed; + int status = 0; + uint16_t cmd_data; + + /* Alloc Space for platform device structure */ + pmodda1_dev = (struct pmodda1_device*) kzalloc(sizeof(*pmodda1_dev), GFP_KERNEL); + if(!pmodda1_dev) { + status = -ENOMEM; + goto dev_alloc_err; + } + + pmodda1_dev->buf = (unsigned char *)kmalloc(buf_sz, GFP_KERNEL); + if (!pmodda1_dev->buf) { + status = -ENOMEM; + printk(KERN_INFO DRIVER_NAME "Device value buffer allocation " + "failed: %d\n", status); + goto buf_alloc_err; + } + + /* Get the GPIO Pins */ + + pmodda1_dev->iSCLK = of_get_named_gpio(np, "spi-sclk-gpio", 0); + pmodda1_dev->iSDIN = of_get_named_gpio(np, "spi-sdin-gpio", 0); + status = of_get_named_gpio(np, "spi-cs-gpio", 0); + pmodda1_dev->iCS = (status < 0) ? SPI_GPIO_NO_CHIPSELECT : status; + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: iSCLK: 0x%lx\n", np->name, pmodda1_dev->iSCLK); + printk(KERN_INFO DRIVER_NAME " %s: iSDIN: 0x%lx\n", np->name, pmodda1_dev->iSDIN); + printk(KERN_INFO DRIVER_NAME " %s: iCS : 0x%lx\n", np->name, pmodda1_dev->iCS); +#endif + + /* Get SPI Related Params */ + tree_info = of_get_property(np, "spi-bus-num", NULL); + if(tree_info) { + pmodda1_dev->spi_id = be32_to_cpup((tree_info)); +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: BUS_ID\t%x\n", np->name, pmodda1_dev->spi_id); +#endif + } + + spi_speed = of_get_property(np, "spi-speed-hz", NULL); + if(spi_speed) { + pmodda1_dev->spi_speed = be32_to_cpup((spi_speed)); +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: SPI_SPEED\t%x\n", np->name, pmodda1_dev->spi_speed); +#endif + } + else + { + pmodda1_dev->spi_speed = DEFAULT_SPI_SPEED; + } + /* Alloc Space for platform data structure */ + pmodda1_pdata = (struct spi_gpio_platform_data*) kzalloc(sizeof(*pmodda1_pdata), GFP_KERNEL); + if(!pmodda1_pdata) { + status = -ENOMEM; + goto pdata_alloc_err; + } + + /* Fill up Platform Data Structure */ + pmodda1_pdata->sck = pmodda1_dev->iSCLK; + pmodda1_pdata->miso = SPI_GPIO_NO_MISO; + pmodda1_pdata->mosi = pmodda1_dev->iSDIN; + pmodda1_pdata->num_chipselect = 1; + + /* Alloc Space for platform data structure */ + pmodda1_pdev = (struct platform_device*) kzalloc(sizeof(*pmodda1_pdev), GFP_KERNEL); + if(!pmodda1_pdev) { + status = -ENOMEM; + goto pdev_alloc_err; + } + + /* Fill up Platform Device Structure */ + pmodda1_pdev->name = "spi_gpio"; + pmodda1_pdev->id = pmodda1_dev->spi_id; + pmodda1_pdev->dev.platform_data = pmodda1_pdata; + pmodda1_dev->pdev = pmodda1_pdev; + + /* Register spi_gpio master */ + status = platform_device_register(pmodda1_dev->pdev); + if(status < 0) { + dev_err(&pdev->dev, "platform_device_register failed: %d\n", status); + goto pdev_reg_err; + } + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: spi_gpio platform device registered.\n", np->name); +#endif + pmodda1_dev->name = (char *)np->name; + + if(pmodda1_first_dev_id == 0) { + /* Alloc Major & Minor number for char device */ + status = alloc_chrdev_region(&pmodda1_first_dev_id, 0, PMODDA1_DEV_NUM, DRIVER_NAME); + if(status) { + dev_err(&pdev->dev, "Character device region not allocated correctly: %d\n", status); + goto err_alloc_chrdev_region; + } +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Char Device Region Registered, with Major: %d.\n", + MAJOR(pmodda1_first_dev_id)); +#endif + } + + /* Point device node data to pmodda1_device structure */ + if(np->data == NULL) + np->data = pmodda1_dev; + + + if(pmodda1_class == NULL) { + /* Create Pmodda1 Device Class */ + pmodda1_class = class_create(THIS_MODULE, DRIVER_NAME); + if (IS_ERR(pmodda1_class)) { + status = PTR_ERR(pmodda1_class); + goto err_create_class; + } +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : pmodda1 device class registered.\n"); +#endif + } + + + /* Fill up Board Info for SPI device */ + status = add_pmodda1_device_to_bus(pmodda1_dev); + if(status < 0) { + dev_err(&pdev->dev, "add_pmodda1_device_to_bus failed: %d\n", status); + goto spi_add_err; + } + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: spi device registered.\n", np->name); +#endif + + + if(spi_drv_registered == 0) { + /* Register SPI Driver for Pmodda1 Device */ + status = spi_register_driver(&pmodda1_spi_driver); + if (status < 0) { + dev_err(&pdev->dev, "pmodda1_spi_driver register failed: %d\n", status); + goto err_spi_register; + } + spi_drv_registered = 1; + } + + /* + * although a well-designed part will power-up into a known good state, this is + * a good time to force it into a known good state just to be sure. In this case, + * the desired known good state is both DACs powered down. + */ + dac1.ext = 0; /* select internal reference for now */ + dac1.ldac = 0; /* want to be able to load both DACs together */ + dac1.pda = 1; /* want DAC A powered down */ + dac1.pdb = 1; /* want DAC B powered down */ + dac1.sel = 0; /* this won't matter this time since both devices will be loaded from the shift register */ + dac1.cr0 = 0; /* in conjunction with cr1 will load both devices from the shift register */ + dac1.cr1 = 0; /* in conjunction with cr0 will load both devices from the shift register */ + mutex_init(&dac1.mutex); + cmd_data = make_cmd_from_shadow_regs(&dac1); + cmd_data &= 0xFFFF0000; /* zeroes out the low order bits so that the DAC could be powered up and */ + /* the output would still be zero. */ + status = write_spi_16(rgpmodda1_devices[0]->spi, cmd_data); + if (status) { + dev_err(&pdev->dev, "da1_spi_probe: Error writing to device to initally power down: %d\n", status); + goto initial_state_err; + } + + return status; +initial_state_err: +err_spi_register: + class_destroy(pmodda1_class); + pmodda1_class = NULL; +err_create_class: + unregister_chrdev_region(pmodda1_first_dev_id, PMODDA1_DEV_NUM); + pmodda1_first_dev_id = 0; +err_alloc_chrdev_region: + spi_unregister_device(pmodda1_dev->spi); +spi_add_err: + platform_device_unregister(pmodda1_dev->pdev); +pdev_reg_err: + kfree(pmodda1_pdev); +pdev_alloc_err: + kfree(pmodda1_pdata); +buf_alloc_err: +pdata_alloc_err: + kfree(pmodda1_dev->buf); + kfree(pmodda1_dev); +dev_alloc_err: + return status; +} + +/** + * pmodda1_of_remove - Remove method for ZED PmodDA1 device. + * @np: pointer to device tree node + * + * This function removes the PmodDA1 device in the device tree. It frees the + * PmodDA1 driver data structure. It returns 0, if the driver is successfully + * removed, or a negative value if there is an error. + */ +static int pmodda1_of_remove(struct platform_device *pdev) +{ + struct pmodda1_device *pmodda1_dev; + struct device_node *np = pdev->dev.of_node; + + if(np->data == NULL) { + dev_err(&pdev->dev, "pmodda1 %s: ERROR: No pmodda1_device structure found!\n", np->name); + return -ENOSYS; + } + pmodda1_dev = (struct pmodda1_device*) (np->data); + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s : Free display buffer.\n", np->name); +#endif + + if(pmodda1_dev->buf != NULL) { + kfree(pmodda1_dev->buf); + } + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s : Unregister gpio_spi Platform Devices.\n", np->name); +#endif + + if(pmodda1_dev->pdev != NULL) { + platform_device_unregister(pmodda1_dev->pdev); + } + + np->data = NULL; + + /* Unregister SPI Driver, Destroy pmodda1 class, Release device id Region + */ + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Unregister SPI Driver.\n"); +#endif + spi_unregister_driver(&pmodda1_spi_driver); + spi_drv_registered = 0; + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Destroy pmodda1_gpio Class.\n"); +#endif + + if(pmodda1_class) { + class_destroy(pmodda1_class); + } + pmodda1_class = NULL; + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Release Char Device Region.\n"); +#endif + + unregister_chrdev_region(pmodda1_first_dev_id, PMODDA1_DEV_NUM); + pmodda1_first_dev_id = 0; + + + return 0; +} + +static struct platform_driver pmodda1_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = pmodda1_of_match, + }, + .probe = pmodda1_of_probe, + .remove = __devexit_p(pmodda1_of_remove), +}; + +module_platform_driver(pmodda1_driver); + +MODULE_AUTHOR("Digilent, Inc."); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(DRIVER_NAME": PmodDA1 display driver"); +MODULE_ALIAS(DRIVER_NAME); From 7ef96dcb2a38edbbcd5247979e65a785b01b36fc Mon Sep 17 00:00:00 2001 From: Cristian Fatu Date: Wed, 5 Dec 2012 21:06:42 -0800 Subject: [PATCH 231/261] Digilent: Pmods: Added PmodAD1 driver and documentation --- Documentation/pmods/pmodad1.txt | 99 +++++ drivers/pmods/Kconfig | 6 + drivers/pmods/Makefile | 1 + drivers/pmods/pmodad1.c | 638 ++++++++++++++++++++++++++++++++ 4 files changed, 744 insertions(+) create mode 100644 Documentation/pmods/pmodad1.txt create mode 100644 drivers/pmods/pmodad1.c diff --git a/Documentation/pmods/pmodad1.txt b/Documentation/pmods/pmodad1.txt new file mode 100644 index 0000000000000..7b575e54d4db7 --- /dev/null +++ b/Documentation/pmods/pmodad1.txt @@ -0,0 +1,99 @@ +PmodAD1 +======== + +Copyright 2012, Digilent Inc. + + +Description +----------- + +The Analog to Digital Module Converter Board converts signals at a +maximum sampling rate of one million samples per second. + +The Digilent PmodAD1 relies on two Analog Devices AD7476, thus implementing two +simultaneous A/D conversion channels, each with an 12-bit converter. + +The AD1 converts an analog input signal ranging from 0-3.3 volts to a 12-bit +digital value in the range 0 to 4095 (0x0FFF). + +This Linux driver is based on SPI. Because SPI can not read on Data Out line of +SPI, only the channel corresponding to the second AD7476 can be accessed using +this driver (the channel corresponding to P3, P4 pins of J2 connector of PmodAD1). + +The driver is implemented as a character driver. The basic action of the driver is +read, when 12 bits data is read over SPI. + +The Reference Manual for PmodAD1 display is available online at +Digilent Inc. Website (www.digilentinc.com). + + +Interface +--------- + +Signal Description + +SDOUT SPI Data In (MISO) +SCLK SPI Clock +SS Slave Select + + +Devicetree +---------- + +Required Properties: +- compatible : Should be "dlgnt,pmodad1" +- spi-bus-num : Should specify the bus number for PmodAD1 SPI controller. + This value cannot be shared by any other SPI controller present in the + device tree. +- spi-sclk-gpio : Should specify the GPIO for SCLK, see "gpios property" in + Documentation/devicetree/gpio.txt. +- spi-sdout-gpio : Should specify the GPIO for SDOUT, see "gpios property" in + Documentation/devicetree/gpio.txt. + +Optional Properties: +- spi-cs-gpio : Should specify the GPIO for CS, see "gpios property" in + Documentation/devicetree/gpio.txt. If unspecified, CS is assumed to be + tied to ground. +- spi-speed-hz : Should specify the spi speed (in Hz). If unspecified, spi + speed is assumed to be 625000 (625 kHz). + +Example: + + pmodad1 { + compatible = "dglnt,pmodad1"; + spi-bus-num = <0x5>; + spi-speed-hz = <1000000>; + spi-sclk-gpio = <0x8 85 0>; + spi-sdout-gpio = <0x8 84 0>; + spi-cs-gpio = <0x8 82 0>; + }; + +This example corresponds to PmodAD1 plugged into JA connector, pins 1-7. + +Configuration +------------- + +The PmodAD1 is located in the kernel configuration menu at +Device Drivers -> Pmods -> PmodAD1. The driver can be built into the kernel +by selecting (*) for it, or loadable module by selecting (M) for it. + + +Device Nodes +------------ + +A char device node will be created for each PmodAD1 device automatically. +The name of the node is default to the one declared in the device tree. + +Reading from the device +----------- +The PmodAD1 is a "read only" device, read being its main action. +2 bytes of data are read over the spi, a mask is applied so that the 12 LSB +bits are used to fill the read buffer. + +Example of commands +----------- + +- Read (repeatedly) the device +hexdump -v -d /dev/pmodad1 + + diff --git a/drivers/pmods/Kconfig b/drivers/pmods/Kconfig index df338863ed561..47ea2778a0a66 100644 --- a/drivers/pmods/Kconfig +++ b/drivers/pmods/Kconfig @@ -34,4 +34,10 @@ config PMODDA1 help This is the Digilent PmodDA1 driver. Uses SPI over GPIO. +config PMODAD1 + tristate "pmodad1" + select SPI_BITBANG + help + This is the Digilent PmodAD1 driver. Uses SPI over GPIO. + endif # PMODS diff --git a/drivers/pmods/Makefile b/drivers/pmods/Makefile index 109cb652393b4..5f9542b7c0392 100644 --- a/drivers/pmods/Makefile +++ b/drivers/pmods/Makefile @@ -5,4 +5,5 @@ obj-$(CONFIG_PMODOLED) += pmodoled-gpio.o obj-$(CONFIG_PMODCLS) += pmodcls.o obj-$(CONFIG_PMODCLP) += pmodclp.o obj-$(CONFIG_PMODDA1) += pmodda1.o +obj-$(CONFIG_PMODAD1) += pmodad1.o diff --git a/drivers/pmods/pmodad1.c b/drivers/pmods/pmodad1.c new file mode 100644 index 0000000000000..2be75c8cd36ca --- /dev/null +++ b/drivers/pmods/pmodad1.c @@ -0,0 +1,638 @@ +/* + * PmodAD1 linux driver for Zed + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "pmodad1" +#define SPI_DRIVER_NAME "pmodad1-spi" + +#define DEFAULT_SPI_SPEED 625000 +#define MAX_PMODAD1_DEV_NUM 16 +#define TXT_BUF_SIZE 1024 +#define MAX_NO_ROWS 2 // The device has 2 rows + + + +dev_t pmodad1_dev_id = 0; +static unsigned int device_num = 0; +static unsigned int cur_minor = 0; +static unsigned int spi_drv_registered = 0; +static struct class *pmodad1_class = NULL; + +/* Kernel space buffer size (in bytes) for the ad1_read function. + * Can be entered from the command line during insmod + */ +int read_buf_size = 512; +module_param(read_buf_size, int, 0); + + +struct pmodad1_device { + char *name; + /* R/W Mutex Lock */ + struct mutex mutex; + + unsigned short *val_buf; + + /* Pin Assignment */ + + unsigned long iSCLK; + unsigned long iSDOUT; + unsigned long iCS; + + /* SPI Info */ + uint32_t spi_speed; + uint32_t spi_id; + /* platform device structures */ + struct platform_device *pdev; + /* Char Device */ + struct cdev cdev; + struct spi_device *spi; + dev_t dev_id; +}; + + + + + +/* + * Driver read function + * + * This function uses a generic SPI read to read values from the Pmod. + * It will only read full values, so if the length from user space is + * not a multiple of 2, it will read up to length - 1 bytes. + * + * Function can possibly error out if: + * The mutex cannot be locked + * spi_read fails on the first read + * + * Otherwise, the function returns the number of successful values read, + * each with a size of 2 bytes. So for instance, if 13 bytes are read, + * the function will return 12, indicating 6 values were read successfully + * from the pmod. Additionally, if copy_to_user cannot successfully + * copy everything, the number of successfully copied full values (2 bytes) + * will be returned. + * + * We use goto in this function because there are multiple exit points, + * and it prevents us from having to call mutex_unlock() for the mutex + * each time. + */ +static ssize_t pmodad1_read(struct file *fp, char __user *buffer, size_t length, loff_t *offset) +{ + int status; /* spi_read return value */ + int num_reads; /* Number of values to read from Pmod */ + int i; + ssize_t retval; /* Function return value */ + ssize_t ret; /* copy_to_user return value */ + unsigned short buf; /* Temporary storage for each read value */ + struct pmodad1_device *dev; + + dev = fp->private_data; + status = 0; + num_reads = length/2; + + if (mutex_lock_interruptible(&dev->mutex)) { + retval = -ERESTARTSYS; + goto lock_err; + } + + if (buffer == NULL) { + retval = -EINVAL; + goto read_out; + } + + + for (i = 0; i < num_reads; i++) { + /* Use generic SPI read */ + status = spi_read(dev->spi, &buf, 2); + if (status) + break; + /* Change endianness of result, if necessary + * The result from the Pmod hardware is big endian, + * whereas Microblaze and other CPU architectures are + * little endian. + */ + dev->val_buf[i] = be16_to_cpu(buf) & 0x0FFF; // only 12 bits matters + } + + if (i == 0) { + dev_err(&dev->spi->dev, "SPI read failure: %d\n", status); + retval = status; + goto read_out; + } + + /* + * Only copy full values (2 bytes) in the case of a user space length + * that is not a multiple of 2. + */ + ret = copy_to_user((void *)buffer, (void *)dev->val_buf, i*2); + + retval = num_reads*2 - (ret + (ret % 2)); +read_out: + mutex_unlock(&dev->mutex); +lock_err: + return retval; +} + + +/** + * A basic open function. + */ +static int pmodad1_open(struct inode *inode, struct file *fp) +{ + struct pmodad1_device *dev; + + dev = container_of(inode->i_cdev, struct pmodad1_device, cdev); + fp->private_data = dev; + + return 0; +} + +struct file_operations pmodad1_cdev_fops = { + .owner = THIS_MODULE, + .open = pmodad1_open, + .read = pmodad1_read, +}; + + +/** + * add_pmodad1_device_to_bus - Add device to SPI bus, initialize SPI data. + * @dev: pointer to device tree node + * + * This function adds device to SPI bus, initialize SPI data. + */ +static int __init add_pmodad1_device_to_bus(struct pmodad1_device* dev) { + struct spi_master *spi_master; + struct spi_device *spi_device; + int status = 0; + + spi_master = spi_busnum_to_master(dev->spi_id); + if(!spi_master) { + dev_err(&dev->pdev->dev, "spi_busnum_to_master(%d) returned NULL\n", dev->spi_id); + return -ENOSYS; + } + + spi_device = spi_alloc_device(spi_master); + if(!spi_device) { + put_device(&spi_master->dev); + dev_err(&dev->pdev->dev, "spi_alloc_device() failed\n"); + return -ENOMEM; + } + + spi_device->chip_select = 0; + spi_device->max_speed_hz = dev->spi_speed; +// spi_device->max_speed_hz = 625000; + spi_device->mode = SPI_MODE_0; + spi_device->bits_per_word = 8; + spi_device->controller_data = (void *) dev->iCS; + spi_device->dev.platform_data = dev; + strlcpy(spi_device->modalias, SPI_DRIVER_NAME, sizeof(SPI_DRIVER_NAME)); + + status = spi_add_device(spi_device); + if(status < 0) { + spi_dev_put(spi_device); + dev_err(&dev->pdev->dev, "spi_add_device() failed %d\n", status); + return status; + } + dev->spi = spi_device; + + put_device(&spi_master->dev); + printk(KERN_INFO DRIVER_NAME " SPI initialized, max_speed_hz\t%d\n", spi_device->max_speed_hz); + return status; +} + +/** + * pmodad1_setup_cdev - Setup Char Device for ZED PmodAD1 device. + * @dev: pointer to device tree node + * @dev_id: pointer to device major and minor number + * @spi: pointer to spi_device structure + * + * This function initializes char device for PmodAD1 device, and add it into + * kernel device structure. It returns 0, if the cdev is successfully + * initialized, or a negative value if there is an error. + */ +static int pmodad1_setup_cdev(struct pmodad1_device *dev, dev_t *dev_id, struct spi_device *spi) +{ + int status = 0; + struct device *device; + + cdev_init(&dev->cdev, &pmodad1_cdev_fops); + dev->cdev.owner = THIS_MODULE; + dev->cdev.ops = &pmodad1_cdev_fops; + dev->spi = spi; + + *dev_id = MKDEV(MAJOR(pmodad1_dev_id), cur_minor++); + status = cdev_add(&dev->cdev, *dev_id, 1); + if(status < 0) { + return status; + } + + /* Add Device node in system */ + device = device_create(pmodad1_class, NULL, + *dev_id, NULL, + "%s", dev->name); + if(IS_ERR(device)) { + status = PTR_ERR(device); + dev_err(&spi->dev, "failed to create device node %s, err %d\n", + dev->name, status); + cdev_del(&dev->cdev); + } + + return status; +} + +/** + * SPI hardware probe. Sets correct SPI mode, attempts + * to obtain memory needed by the driver, and performs + * a simple initialization of the device. + * @spi : pointer to spi device being initialized. + */ +static int pmodad1_spi_probe(struct spi_device *spi) { + int status = 0; + struct pmodad1_device *pmodad1_dev; + if (spi->master->flags & SPI_MASTER_HALF_DUPLEX) { + status = -EINVAL; + printk(KERN_INFO SPI_DRIVER_NAME "SPI settings incorrect: %d\n", status); + goto spi_err; + } + + /* use SPI_MODE_0 */ + spi->mode = SPI_MODE_0; + spi->bits_per_word = 8; + + status = spi_setup(spi); + if(status < 0) { + dev_err(&spi->dev, "needs SPI mode %02x, %d KHz; %d\n", + spi->mode, spi->max_speed_hz / 1000, + status); + goto spi_err; + } + + /* Get pmodad1_device structure */ + pmodad1_dev = (struct pmodad1_device*) spi->dev.platform_data; + if(pmodad1_dev == NULL) { + dev_err(&spi->dev, "Cannot get pmodad1_device.\n"); + status = -EINVAL; + goto spi_platform_data_err; + } + + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO SPI_DRIVER_NAME " [%s] spi_probe: setup char device\n", pmodad1_dev->name); +#endif + + /* Setup char driver */ + status = pmodad1_setup_cdev(pmodad1_dev, &(pmodad1_dev->dev_id), spi); + if (status) { + printk(KERN_INFO " spi_probe: Error adding %s device: %d\n", SPI_DRIVER_NAME, status); + dev_err(&spi->dev, "spi_probe: Error adding %s device: %d\n", SPI_DRIVER_NAME, status); + goto cdev_add_err; + } + + /* Initialize Mutex */ + mutex_init(&pmodad1_dev->mutex); + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO SPI_DRIVER_NAME " [%s] spi_probe: initialize device\n", pmodad1_dev->name); +#endif + + return status; + +cdev_add_err: +spi_platform_data_err: +spi_err: + return(status); +} + +/** + * pmodad1_spi_remove - SPI hardware remove. + * Performs tasks required when SPI is removed. + * @spi : pointer to spi device being removed + */ +static int __devexit pmodad1_spi_remove(struct spi_device *spi) +{ + int status; + struct pmodad1_device *dev; + + dev = (struct pmodad1_device*) spi->dev.platform_data; + + if(dev == NULL) { + dev_err(&spi->dev, "spi_remove: Error fetch pmodad1_device struct\n"); + return -EINVAL; + } + + + if(&dev->cdev) { +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO SPI_DRIVER_NAME " [%s] spi_remove: Destroy Char Device\n", dev->name); +#endif + device_destroy(pmodad1_class, dev->dev_id); + cdev_del(&dev->cdev); + } + + cur_minor--; + + return status; +} + +static struct spi_driver pmodad1_spi_driver = { + .driver = { + .name = SPI_DRIVER_NAME, + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = pmodad1_spi_probe, + .remove = __devexit_p(pmodad1_spi_remove), +}; + +static const struct of_device_id pmodad1_of_match[] __devinitconst = { + { .compatible = "dglnt,pmodad1", }, + {}, +}; +MODULE_DEVICE_TABLE(of, pmodad1_of_match); + +/** + * pmodad1_of_probe - Probe method for PmodAD1 device (over GPIO). + * @pdev: pointer to platform devices + * + * This function probes the PmodAD1 device in the device tree. It initializes the + * PmodAD1 driver data structure. It returns 0, if the driver is bound to the PmodAD1 + * device, or a negative value if there is an error. + */ +static int __devinit pmodad1_of_probe(struct platform_device *pdev) +{ + struct pmodad1_device *pmodad1_dev; + struct platform_device *pmodad1_pdev; + struct spi_gpio_platform_data *pmodad1_pdata; + + struct device_node *np = pdev->dev.of_node; + + const u32* tree_info; + const u32* spi_speed; + int status = 0; + + /* Alloc Space for platform device structure */ + pmodad1_dev = (struct pmodad1_device*) kzalloc(sizeof(*pmodad1_dev), GFP_KERNEL); + if(!pmodad1_dev) { + status = -ENOMEM; + dev_err(&pdev->dev, "Platform device structure allocation " + "failed: %d\n", status); + goto dev_alloc_err; + } + + + pmodad1_dev->val_buf = (unsigned short *)kmalloc(read_buf_size, GFP_KERNEL); + if (!pmodad1_dev->val_buf) { + status = -ENOMEM; + dev_err(&pdev->dev, "Device value buffer allocation " + "failed: %d\n", status); + goto buf_alloc_err; + } + + /* Get the GPIO Pins */ + + pmodad1_dev->iSCLK = of_get_named_gpio(np, "spi-sclk-gpio", 0); + pmodad1_dev->iSDOUT = of_get_named_gpio(np, "spi-sdout-gpio", 0); + status = of_get_named_gpio(np, "spi-cs-gpio", 0); + pmodad1_dev->iCS = (status < 0) ? SPI_GPIO_NO_CHIPSELECT : status; + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: iSCLK: 0x%lx\n", np->name, pmodad1_dev->iSCLK); + printk(KERN_INFO DRIVER_NAME " %s: iSDOUT: 0x%lx\n", np->name, pmodad1_dev->iSDOUT); + printk(KERN_INFO DRIVER_NAME " %s: iCS : 0x%lx\n", np->name, pmodad1_dev->iCS); +#endif + + /* Get SPI Related Params */ + tree_info = of_get_property(np, "spi-bus-num", NULL); + if(tree_info) { + pmodad1_dev->spi_id = be32_to_cpup((tree_info)); +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: BUS_ID\t%x\n", np->name, pmodad1_dev->spi_id); +#endif + } + + spi_speed = of_get_property(np, "spi-speed-hz", NULL); + if(spi_speed) { + pmodad1_dev->spi_speed = be32_to_cpup((spi_speed)); +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: SPI_SPEED\t%x\n", np->name, pmodad1_dev->spi_speed); +#endif + } + else + { + pmodad1_dev->spi_speed = DEFAULT_SPI_SPEED; + } + + /* Alloc Space for platform data structure */ + pmodad1_pdata = (struct spi_gpio_platform_data*) kzalloc(sizeof(*pmodad1_pdata), GFP_KERNEL); + if(!pmodad1_pdata) { + status = -ENOMEM; + goto pdata_alloc_err; + } + + /* Fill up Platform Data Structure */ + pmodad1_pdata->sck = pmodad1_dev->iSCLK; + pmodad1_pdata->miso = pmodad1_dev->iSDOUT; + pmodad1_pdata->mosi = SPI_GPIO_NO_MOSI; + pmodad1_pdata->num_chipselect = 1; + + /* Alloc Space for platform data structure */ + pmodad1_pdev = (struct platform_device*) kzalloc(sizeof(*pmodad1_pdev), GFP_KERNEL); + if(!pmodad1_pdev) { + status = -ENOMEM; + goto pdev_alloc_err; + } + + /* Fill up Platform Device Structure */ + pmodad1_pdev->name = "spi_gpio"; + pmodad1_pdev->id = pmodad1_dev->spi_id; + pmodad1_pdev->dev.platform_data = pmodad1_pdata; + pmodad1_dev->pdev = pmodad1_pdev; + + /* Register spi_gpio master */ + status = platform_device_register(pmodad1_dev->pdev); + if(status < 0) { + dev_err(&pdev->dev, "platform_device_register failed: %d\n", status); + goto pdev_reg_err; + } + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: spi_gpio platform device registered.\n", np->name); +#endif + pmodad1_dev->name = (char *)np->name; + + /* Fill up Board Info for SPI device */ + status = add_pmodad1_device_to_bus(pmodad1_dev); + if(status < 0) { + dev_err(&pdev->dev, "add_pmodad1_device_to_bus failed: %d\n", status); + goto spi_add_err; + } + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s: spi device registered.\n", np->name); +#endif + + /* Point device node data to pmodad1_device structure */ + if(np->data == NULL) + np->data = pmodad1_dev; + + if(pmodad1_dev_id == 0) { + /* Alloc Major & Minor number for char device */ + status = alloc_chrdev_region(&pmodad1_dev_id, 0, MAX_PMODAD1_DEV_NUM, DRIVER_NAME); + if(status) { + dev_err(&pdev->dev, "Character device region not allocated correctly: %d\n", status); + goto err_alloc_chrdev_region; + } +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Char Device Region Registered, with Major: %d.\n", + MAJOR(pmodad1_dev_id)); +#endif + } + + if(pmodad1_class == NULL) { + /* Create Pmodad1 Device Class */ + pmodad1_class = class_create(THIS_MODULE, DRIVER_NAME); + if (IS_ERR(pmodad1_class)) { + status = PTR_ERR(pmodad1_class); + goto err_create_class; + } +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : pmodad1 device class registered.\n"); +#endif + } + + if(spi_drv_registered == 0) { + /* Register SPI Driver for Pmodad1 Device */ + status = spi_register_driver(&pmodad1_spi_driver); + if (status < 0) { + dev_err(&pdev->dev, "pmodad1_spi_driver register failed: %d\n", status); + goto err_spi_register; + } + spi_drv_registered = 1; + } + + device_num ++; + + return status; + +err_spi_register: + class_destroy(pmodad1_class); + pmodad1_class = NULL; +err_create_class: + unregister_chrdev_region(pmodad1_dev_id, MAX_PMODAD1_DEV_NUM); + pmodad1_dev_id = 0; +err_alloc_chrdev_region: + spi_unregister_device(pmodad1_dev->spi); +spi_add_err: + platform_device_unregister(pmodad1_dev->pdev); +pdev_reg_err: + kfree(pmodad1_pdev); +pdev_alloc_err: + kfree(pmodad1_pdata); +pdata_alloc_err: + kfree(pmodad1_dev->val_buf); +buf_alloc_err: + kfree(pmodad1_dev); +dev_alloc_err: + return status; +} + +/** + * pmodad1_of_remove - Remove method for ZED PmodAD1 device. + * @np: pointer to device tree node + * + * This function removes the PmodAD1 device in the device tree. It frees the + * PmodAD1 driver data structure. It returns 0, if the driver is successfully + * removed, or a negative value if there is an error. + */ +static int pmodad1_of_remove(struct platform_device *pdev) +{ + struct pmodad1_device *pmodad1_dev; + struct device_node *np = pdev->dev.of_node; + + if(np->data == NULL) { + dev_err(&pdev->dev, "pmodad1 %s: ERROR: No pmodad1_device structure found!\n", np->name); + return -ENOSYS; + } + pmodad1_dev = (struct pmodad1_device*) (np->data); + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s : Free display buffer.\n", np->name); +#endif + + if(pmodad1_dev->val_buf != NULL) { + kfree(pmodad1_dev->val_buf); + } + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " %s : Unregister gpio_spi Platform Devices.\n", np->name); +#endif + + if(pmodad1_dev->pdev != NULL) { + platform_device_unregister(pmodad1_dev->pdev); + } + + np->data = NULL; + device_num--; + + /* Unregister SPI Driver, Destroy pmodad1 class, Release device id Region after + * all pmodad1 devices have been removed. + */ + if(device_num == 0) { +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Unregister SPI Driver.\n"); +#endif + spi_unregister_driver(&pmodad1_spi_driver); + spi_drv_registered = 0; + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Destroy pmodad1 Class.\n"); +#endif + + if(pmodad1_class) { + class_destroy(pmodad1_class); + } + pmodad1_class = NULL; + +#ifdef CONFIG_PMODS_DEBUG + printk(KERN_INFO DRIVER_NAME " : Release Char Device Region.\n"); +#endif + + unregister_chrdev_region(pmodad1_dev_id, MAX_PMODAD1_DEV_NUM); + pmodad1_dev_id = 0; + } + + return 0; +} + +static struct platform_driver pmodad1_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = pmodad1_of_match, + }, + .probe = pmodad1_of_probe, + .remove = __devexit_p(pmodad1_of_remove), +}; + +module_platform_driver(pmodad1_driver); + +MODULE_AUTHOR("Cristian Fatu"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(DRIVER_NAME": PmodAD1 driver"); +MODULE_ALIAS(DRIVER_NAME); From 0b8350eb250d200861ca1bc4b152c452e47bc60b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 6 Dec 2012 13:30:41 +0100 Subject: [PATCH 232/261] Revert "DMA: Xilinx: Separation of DMA driver into three drivers" This reverts commit 60ea42affdc49e30cc41a12ff50b53c4871714fe. --- .../bindings/dma/xilinx/axi-cdma.txt | 18 - .../bindings/dma/xilinx/axi-dma.txt | 28 - .../bindings/dma/xilinx/axi-vdma.txt | 28 - drivers/dma/Kconfig | 24 +- drivers/dma/Makefile | 1 - drivers/dma/xilinx/Kconfig | 53 - drivers/dma/xilinx/Makefile | 6 - drivers/dma/xilinx/cdmatest.c | 644 -------- drivers/dma/xilinx/dmatest.c | 649 -------- drivers/dma/xilinx/vdmatest.c | 620 -------- drivers/dma/xilinx/xilinx_axicdma.c | 1095 -------------- drivers/dma/xilinx/xilinx_axidma.c | 1201 --------------- drivers/dma/xilinx/xilinx_axivdma.c | 1321 ----------------- include/linux/amba/xilinx_dma.h | 93 +- 14 files changed, 65 insertions(+), 5716 deletions(-) delete mode 100644 Documentation/devicetree/bindings/dma/xilinx/axi-cdma.txt delete mode 100644 Documentation/devicetree/bindings/dma/xilinx/axi-dma.txt delete mode 100644 Documentation/devicetree/bindings/dma/xilinx/axi-vdma.txt delete mode 100644 drivers/dma/xilinx/Kconfig delete mode 100644 drivers/dma/xilinx/Makefile delete mode 100644 drivers/dma/xilinx/cdmatest.c delete mode 100644 drivers/dma/xilinx/dmatest.c delete mode 100644 drivers/dma/xilinx/vdmatest.c delete mode 100644 drivers/dma/xilinx/xilinx_axicdma.c delete mode 100644 drivers/dma/xilinx/xilinx_axidma.c delete mode 100644 drivers/dma/xilinx/xilinx_axivdma.c diff --git a/Documentation/devicetree/bindings/dma/xilinx/axi-cdma.txt b/Documentation/devicetree/bindings/dma/xilinx/axi-cdma.txt deleted file mode 100644 index 903562647710c..0000000000000 --- a/Documentation/devicetree/bindings/dma/xilinx/axi-cdma.txt +++ /dev/null @@ -1,18 +0,0 @@ -Xilinx AXI CDMA engine, it does transfers between memory and memory - -Required properties: -- compatible: Should be "xlnx,axi-cdma" -- reg: Should contain CDMA registers location and length. -- interrupts: Should contain channel CDMA interrupts. - -Example: -++++++++ - -axi_cdma_0: axicdma@40030000 { - compatible = "xlnx,axi-cdma"; - reg = < 0x40030000 0x10000 >; - dma-channel@40030000 { - interrupts = < 0 59 4 >; - } ; -} ; - diff --git a/Documentation/devicetree/bindings/dma/xilinx/axi-dma.txt b/Documentation/devicetree/bindings/dma/xilinx/axi-dma.txt deleted file mode 100644 index 4b474a2d494e6..0000000000000 --- a/Documentation/devicetree/bindings/dma/xilinx/axi-dma.txt +++ /dev/null @@ -1,28 +0,0 @@ -Xilinx AXI DMA engine, it does transfers between memory and device. It can be -configured to have one channel or two channels. If configured as two -channels, one is to transmit to device and another is to receive from -device. - -Required properties: -- compatible: Should be "xlnx,axi-dma" -- reg: Should contain DMA registers location and length. -- interrupts: Should contain per channel DMA interrupts. -- compatible (child node): It should be either "xlnx,axi-dma-mm2s-channel" or - "xlnx,axi-dma-s2mm-channel". It depends on the hardware design and it - can also have both channels. - -Example: -++++++++ - -axi_dma_0: axidma@40400000 { - compatible = "xlnx,axi-dma"; - reg = < 0x40400000 0x10000 >; - dma-channel@40400000 { - compatible = "xlnx,axi-dma-mm2s-channel"; - interrupts = < 0 59 4 >; - } ; - dma-channel@40030030 { - compatible = "xlnx,axi-dma-s2mm-channel"; - interrupts = < 0 58 4 >; - } ; -} ; diff --git a/Documentation/devicetree/bindings/dma/xilinx/axi-vdma.txt b/Documentation/devicetree/bindings/dma/xilinx/axi-vdma.txt deleted file mode 100644 index a9cccf173fa45..0000000000000 --- a/Documentation/devicetree/bindings/dma/xilinx/axi-vdma.txt +++ /dev/null @@ -1,28 +0,0 @@ -Xilinx AXI VDMA engine, it does transfers between memory and video devices. -It can be configured to have one channel or two channels. If configured -as two channels, one is to transmit to the video device and another is -to receive from the video device. - -Required properties: -- compatible: Should be "xlnx,axi-vdma" -- reg: Should contain VDMA registers location and length. -- interrupts: Should contain per channel VDMA interrupts. -- compatible (child node): It should be either "xlnx,axi-vdma-mm2s-channel" or - "xlnx,axi-vdma-s2mm-channel". It depends on the hardware design and it - can also have both channels. - -Example: -++++++++ - -axi_vdma_0: axivdma@40030000 { - compatible = "xlnx,axi-vdma"; - reg = < 0x40030000 0x10000 >; - dma-channel@40030000 { - compatible = "xlnx,axi-vdma-mm2s-channel"; - interrupts = < 0 54 4 >; - } ; - dma-channel@40030030 { - compatible = "xlnx,axi-vdma-s2mm-channel"; - interrupts = < 0 53 4 >; - } ; -} ; diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index de754c3e1b7f5..bfeceb210d5b2 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -33,15 +33,13 @@ if DMADEVICES comment "DMA Devices" -source "drivers/dma/xilinx/Kconfig" - -#config XILINX_DMA -# tristate "Xilinx DMA engines support" -# select DMA_ENGINE -# ---help--- -# Enable support for the Xilinx DMA controllers. It supports three DMA -# engines: Axi Central DMA (memory to memory transfer), Axi DMA (memory and -# device transfer), and Axi VDMA (memory and video device transfer). +config XILINX_DMA + tristate "Xilinx DMA engines support" + select DMA_ENGINE + ---help--- + Enable support for the Xilinx DMA controllers. It supports three DMA + engines: Axi Central DMA (memory to memory transfer), Axi DMA (memory and + device transfer), and Axi VDMA (memory and video device transfer). config INTEL_MID_DMAC tristate "Intel MID DMA support for Peripheral DMA controllers" @@ -260,6 +258,14 @@ config IMX_DMA Support the i.MX DMA engine. This engine is integrated into Freescale i.MX1/21/27 chips. +config XILINX_DMA + tristate "Xilinx DMA engines support" + select DMA_ENGINE + help + Enable support for the Xilinx DMA controllers. It supports three DMA + engines: Axi Central DMA (memory to memory transfer), Axi DMA (memory and + device transfer), and Axi VDMA (memory and video device transfer). + config MXS_DMA bool "MXS DMA support" depends on SOC_IMX23 || SOC_IMX28 || SOC_IMX6Q diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index a34765439879b..2be9587c38ee4 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -33,4 +33,3 @@ obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o obj-$(CONFIG_DMA_OMAP) += omap-dma.o obj-$(CONFIG_XILINX_DMA) += xilinx_dma.o -obj-$(CONFIG_XILINX_DMA_ENGINES) += xilinx/ diff --git a/drivers/dma/xilinx/Kconfig b/drivers/dma/xilinx/Kconfig deleted file mode 100644 index 704a2b8784235..0000000000000 --- a/drivers/dma/xilinx/Kconfig +++ /dev/null @@ -1,53 +0,0 @@ -# -# XILINX DMA Engines configuration -# - -menuconfig XILINX_DMA_ENGINES - bool "Xilinx DMA Engines" - help - Enable support for the Xilinx DMA controllers. It supports three DMA - engines: Axi Central DMA (memory to memory transfer), Axi DMA (memory and - device transfer), and Axi VDMA (memory and video device transfer). - -if XILINX_DMA_ENGINES - -config XILINX_AXIDMA - tristate "Xilinx AXI DMA Engine" - select DMA_ENGINE - help - Enable support for Xilinx Axi DMA (memory and device transfer). - -config XILINX_DMATEST - tristate "DMA Test client for AXI DMA" - depends on XILINX_AXIDMA - help - Simple DMA test client. Say N unless you're debugging a - DMA Device driver. - -config XILINX_AXIVDMA - tristate "Xilinx AXI VDMA Engine" - select DMA_ENGINE - help - Enable support for Xilinx Axi VDMA (memory and video device transfer). - -config XILINX_VDMATEST - tristate "DMA Test client for VDMA" - depends on XILINX_AXIVDMA - help - Simple DMA test client. Say N unless you're debugging a - DMA Device driver. - -config XILINX_AXICDMA - tristate "Xilinx AXI CDMA Engine" - select DMA_ENGINE - help - Enable support for Xilinx Axi Central DMA (memory to memory transfer). - -config XILINX_CDMATEST - tristate "DMA Test client for CDMA" - depends on XILINX_AXICDMA - help - Simple DMA test client. Say N unless you're debugging a - DMA Device driver. - -endif # XILINX_DMA_ENGINES diff --git a/drivers/dma/xilinx/Makefile b/drivers/dma/xilinx/Makefile deleted file mode 100644 index 3362ad9b62a89..0000000000000 --- a/drivers/dma/xilinx/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -obj-$(CONFIG_XILINX_AXIDMA) += xilinx_axidma.o -obj-$(CONFIG_XILINX_DMATEST) += dmatest.o -obj-$(CONFIG_XILINX_AXIVDMA) += xilinx_axivdma.o -obj-$(CONFIG_XILINX_VDMATEST) += vdmatest.o -obj-$(CONFIG_XILINX_AXICDMA) += xilinx_axicdma.o -obj-$(CONFIG_XILINX_CDMATEST) += cdmatest.o diff --git a/drivers/dma/xilinx/cdmatest.c b/drivers/dma/xilinx/cdmatest.c deleted file mode 100644 index 4f2bb0ff12f62..0000000000000 --- a/drivers/dma/xilinx/cdmatest.c +++ /dev/null @@ -1,644 +0,0 @@ -/* - * XILINX CDMA Engine test module - * - * Copyright (C) 2012 Xilinx, Inc. All rights reserved. - * - * Based on Atmel DMA Test Client - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static unsigned int test_buf_size = 64; -module_param(test_buf_size, uint, S_IRUGO); -MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer"); - -static char test_channel[20]; -module_param_string(channel, test_channel, sizeof(test_channel), S_IRUGO); -MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)"); - -static char test_device[20]; -module_param_string(device, test_device, sizeof(test_device), S_IRUGO); -MODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)"); - -static unsigned int threads_per_chan = 1; -module_param(threads_per_chan, uint, S_IRUGO); -MODULE_PARM_DESC(threads_per_chan, - "Number of threads to start per channel (default: 1)"); - -static unsigned int max_channels; -module_param(max_channels, uint, S_IRUGO); -MODULE_PARM_DESC(max_channels, - "Maximum number of channels to use (default: all)"); - -static unsigned int iterations; -module_param(iterations, uint, S_IRUGO); -MODULE_PARM_DESC(iterations, - "Iterations before stopping test (default: infinite)"); - -static unsigned int xor_sources = 3; -module_param(xor_sources, uint, S_IRUGO); -MODULE_PARM_DESC(xor_sources, - "Number of xor source buffers (default: 3)"); - -static unsigned int pq_sources = 3; -module_param(pq_sources, uint, S_IRUGO); -MODULE_PARM_DESC(pq_sources, - "Number of p+q source buffers (default: 3)"); - -/* - * Initialization patterns. All bytes in the source buffer has bit 7 - * set, all bytes in the destination buffer has bit 7 cleared. - * - * Bit 6 is set for all bytes which are to be copied by the DMA - * engine. Bit 5 is set for all bytes which are to be overwritten by - * the DMA engine. - * - * The remaining bits are the inverse of a counter which increments by - * one for each byte address. - */ -#define PATTERN_SRC 0x80 -#define PATTERN_DST 0x00 -#define PATTERN_COPY 0x40 -#define PATTERN_OVERWRITE 0x20 -#define PATTERN_COUNT_MASK 0x1f - -struct cdmatest_thread { - struct list_head node; - struct task_struct *task; - struct dma_chan *chan; - u8 **srcs; - u8 **dsts; - enum dma_transaction_type type; -}; - -struct cdmatest_chan { - struct list_head node; - struct dma_chan *chan; - struct list_head threads; -}; - -/* - * These are protected by dma_list_mutex since they're only used by - * the DMA filter function callback - */ -static LIST_HEAD(cdmatest_channels); -static unsigned int nr_channels; - -static bool cdmatest_match_channel(struct dma_chan *chan) -{ - if (test_channel[0] == '\0') - return true; - return strcmp(dma_chan_name(chan), test_channel) == 0; -} - -static bool cdmatest_match_device(struct dma_device *device) -{ - if (test_device[0] == '\0') - return true; - return strcmp(dev_name(device->dev), test_device) == 0; -} - -static unsigned long cdmatest_random(void) -{ - unsigned long buf; - - get_random_bytes(&buf, sizeof(buf)); - return buf; -} - -static void cdmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len) -{ - unsigned int i; - u8 *buf; - - for (; (buf = *bufs); bufs++) { - for (i = 0; i < start; i++) - buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); - for ( ; i < start + len; i++) - buf[i] = PATTERN_SRC | PATTERN_COPY - | (~i & PATTERN_COUNT_MASK); - for ( ; i < test_buf_size; i++) - buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); - buf++; - } -} - -static void cdmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len) -{ - unsigned int i; - u8 *buf; - - for (; (buf = *bufs); bufs++) { - for (i = 0; i < start; i++) - buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); - for ( ; i < start + len; i++) - buf[i] = PATTERN_DST | PATTERN_OVERWRITE - | (~i & PATTERN_COUNT_MASK); - for ( ; i < test_buf_size; i++) - buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); - } -} - -static void cdmatest_mismatch(u8 actual, u8 pattern, unsigned int index, - unsigned int counter, bool is_srcbuf) -{ - u8 diff = actual ^ pattern; - u8 expected = pattern | (~counter & PATTERN_COUNT_MASK); - const char *thread_name = current->comm; - - if (is_srcbuf) - pr_warn( - "%s: srcbuf[0x%x] overwritten! Expected %02x, got %02x\n", - thread_name, index, expected, actual); - else if ((pattern & PATTERN_COPY) - && (diff & (PATTERN_COPY | PATTERN_OVERWRITE))) - pr_warn( - "%s: dstbuf[0x%x] not copied! Expected %02x, got %02x\n", - thread_name, index, expected, actual); - else if (diff & PATTERN_SRC) - pr_warn( - "%s: dstbuf[0x%x] was copied! Expected %02x, got %02x\n", - thread_name, index, expected, actual); - else - pr_warn( - "%s: dstbuf[0x%x] mismatch! Expected %02x, got %02x\n", - thread_name, index, expected, actual); -} - -static unsigned int cdmatest_verify(u8 **bufs, unsigned int start, - unsigned int end, unsigned int counter, u8 pattern, - bool is_srcbuf) -{ - unsigned int i; - unsigned int error_count = 0; - u8 actual; - u8 expected; - u8 *buf; - unsigned int counter_orig = counter; - - for (; (buf = *bufs); bufs++) { - counter = counter_orig; - for (i = start; i < end; i++) { - actual = buf[i]; - expected = pattern | (~counter & PATTERN_COUNT_MASK); - if (actual != expected) { - if (error_count < 32) - cdmatest_mismatch(actual, pattern, i, - counter, is_srcbuf); - error_count++; - } - counter++; - } - } - - if (error_count > 32) - pr_warn("%s: %u errors suppressed\n", - current->comm, error_count - 32); - - return error_count; -} - -static void cdmatest_callback(void *completion) -{ - complete(completion); -} - -/* - * This function repeatedly tests DMA transfers of various lengths and - * offsets for a given operation type until it is told to exit by - * kthread_stop(). There may be multiple threads running this function - * in parallel for a single channel, and there may be multiple channels - * being tested in parallel. - * - * Before each test, the source and destination buffer is initialized - * with a known pattern. This pattern is different depending on - * whether it's in an area which is supposed to be copied or - * overwritten, and different in the source and destination buffers. - * So if the DMA engine doesn't copy exactly what we tell it to copy, - * we'll notice. - */ -static int cdmatest_func(void *data) -{ - struct cdmatest_thread *thread = data; - struct dma_chan *chan; - const char *thread_name; - unsigned int src_off, dst_off, len; - unsigned int error_count; - unsigned int failed_tests = 0; - unsigned int total_tests = 0; - dma_cookie_t cookie; - enum dma_status status; - enum dma_ctrl_flags flags; - u8 pq_coefs[pq_sources + 1]; - int ret; - int src_cnt; - int dst_cnt; - int i; - - thread_name = current->comm; - - ret = -ENOMEM; - - /* JZ: limit testing scope here */ - iterations = 5; - - smp_rmb(); - chan = thread->chan; - if (thread->type == DMA_MEMCPY) - src_cnt = dst_cnt = 1; - else if (thread->type == DMA_XOR) { - src_cnt = xor_sources | 1; - /* force odd to ensure dst = src */ - dst_cnt = 1; - } else if (thread->type == DMA_PQ) { - src_cnt = pq_sources | 1; - /* force odd to ensure dst = src */ - dst_cnt = 2; - for (i = 0; i < src_cnt; i++) - pq_coefs[i] = 1; - } else - goto err_srcs; - - thread->srcs = kcalloc(src_cnt+1, sizeof(u8 *), GFP_KERNEL); - if (!thread->srcs) - goto err_srcs; - for (i = 0; i < src_cnt; i++) { - thread->srcs[i] = kmalloc(test_buf_size, GFP_KERNEL); - if (!thread->srcs[i]) - goto err_srcbuf; - } - thread->srcs[i] = NULL; - - thread->dsts = kcalloc(dst_cnt+1, sizeof(u8 *), GFP_KERNEL); - if (!thread->dsts) - goto err_dsts; - for (i = 0; i < dst_cnt; i++) { - thread->dsts[i] = kmalloc(test_buf_size, GFP_KERNEL); - if (!thread->dsts[i]) - goto err_dstbuf; - } - thread->dsts[i] = NULL; - - set_user_nice(current, 10); - - flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP | DMA_PREP_INTERRUPT; - - while (!kthread_should_stop() - && !(iterations && total_tests >= iterations)) { - struct dma_device *dev = chan->device; - struct dma_async_tx_descriptor *tx = NULL; - dma_addr_t dma_srcs[src_cnt]; - dma_addr_t dma_dsts[dst_cnt]; - struct completion cmp; - unsigned long tmo = msecs_to_jiffies(3000); - u8 align = 0; - - total_tests++; - - /* honor alignment restrictions */ - if (thread->type == DMA_MEMCPY) - align = dev->copy_align; - else if (thread->type == DMA_XOR) - align = dev->xor_align; - else if (thread->type == DMA_PQ) - align = dev->pq_align; - - if (1 << align > test_buf_size) { - pr_err("%u-byte buffer too small for %d-byte alignment\n", - test_buf_size, 1 << align); - break; - } - - len = cdmatest_random() % test_buf_size + 1; - len = (len >> align) << align; - if (!len) - len = 1 << align; - src_off = cdmatest_random() % (test_buf_size - len + 1); - dst_off = cdmatest_random() % (test_buf_size - len + 1); - - src_off = (src_off >> align) << align; - dst_off = (dst_off >> align) << align; - - cdmatest_init_srcs(thread->srcs, src_off, len); - cdmatest_init_dsts(thread->dsts, dst_off, len); - - for (i = 0; i < src_cnt; i++) { - u8 *buf = thread->srcs[i] + src_off; - - dma_srcs[i] = dma_map_single(dev->dev, buf, len, - DMA_MEM_TO_DEV); - } - /* map with DMA_MEM_TO_MEM to force writeback/invalidate */ - for (i = 0; i < dst_cnt; i++) { - dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i], - test_buf_size, - DMA_MEM_TO_MEM); - } - - if (thread->type == DMA_MEMCPY) { - tx = dev->device_prep_dma_memcpy(chan, - dma_dsts[0] + dst_off, - dma_srcs[0], len, - flags); - - } else if (thread->type == DMA_XOR) - tx = dev->device_prep_dma_xor(chan, - dma_dsts[0] + dst_off, - dma_srcs, src_cnt, - len, flags); - else if (thread->type == DMA_PQ) { - dma_addr_t dma_pq[dst_cnt]; - - for (i = 0; i < dst_cnt; i++) - dma_pq[i] = dma_dsts[i] + dst_off; - tx = dev->device_prep_dma_pq(chan, dma_pq, dma_srcs, - src_cnt, pq_coefs, - len, flags); - } - - if (!tx) { - for (i = 0; i < src_cnt; i++) - dma_unmap_single(dev->dev, dma_srcs[i], len, - DMA_MEM_TO_DEV); - for (i = 0; i < dst_cnt; i++) - dma_unmap_single(dev->dev, dma_dsts[i], - test_buf_size, - DMA_MEM_TO_MEM); - pr_warn( - "%s: #%u: prep error with src_off=0x%x ", - thread_name, total_tests - 1, src_off); - pr_warn("dst_off=0x%x len=0x%x\n", - dst_off, len); - msleep(100); - failed_tests++; - continue; - } - - init_completion(&cmp); - tx->callback = cdmatest_callback; - tx->callback_param = &cmp; - cookie = tx->tx_submit(tx); - - if (dma_submit_error(cookie)) { - pr_warn( - "%s: #%u: submit error %d with src_off=0x%x ", - thread_name, total_tests - 1, - cookie, src_off); - pr_warn("dst_off=0x%x len=0x%x\n", - dst_off, len); - msleep(100); - failed_tests++; - continue; - } - dma_async_issue_pending(chan); - - tmo = wait_for_completion_timeout(&cmp, tmo); - status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); - - if (tmo == 0) { - pr_warn("%s: #%u: test timed out\n", - thread_name, total_tests - 1); - failed_tests++; - continue; - } else if (status != DMA_SUCCESS) { - pr_warn( - "%s: #%u: got completion callback, ", - thread_name, total_tests - 1); - pr_warn("but status is \'%s\'\n", - status == DMA_ERROR ? "error" : - "in progress"); - failed_tests++; - continue; - } - - /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */ - for (i = 0; i < dst_cnt; i++) - dma_unmap_single(dev->dev, dma_dsts[i], test_buf_size, - DMA_MEM_TO_MEM); - - error_count = 0; - - pr_debug("%s: verifying source buffer...\n", thread_name); - error_count += cdmatest_verify(thread->srcs, 0, src_off, - 0, PATTERN_SRC, true); - error_count += cdmatest_verify(thread->srcs, src_off, - src_off + len, src_off, - PATTERN_SRC | PATTERN_COPY, true); - error_count += cdmatest_verify(thread->srcs, src_off + len, - test_buf_size, src_off + len, - PATTERN_SRC, true); - - pr_debug("%s: verifying dest buffer...\n", - thread->task->comm); - error_count += cdmatest_verify(thread->dsts, 0, dst_off, - 0, PATTERN_DST, false); - error_count += cdmatest_verify(thread->dsts, dst_off, - dst_off + len, src_off, - PATTERN_SRC | PATTERN_COPY, false); - error_count += cdmatest_verify(thread->dsts, dst_off + len, - test_buf_size, dst_off + len, - PATTERN_DST, false); - - if (error_count) { - pr_warn("%s: #%u: %u errors with ", - thread_name, total_tests - 1, error_count); - pr_warn("src_off=0x%x dst_off=0x%x len=0x%x\n", - src_off, dst_off, len); - failed_tests++; - } else { - pr_debug("%s: #%u: No errors with ", - thread_name, total_tests - 1); - pr_debug("src_off=0x%x dst_off=0x%x len=0x%x\n", - src_off, dst_off, len); - } - } - - ret = 0; - for (i = 0; thread->dsts[i]; i++) - kfree(thread->dsts[i]); -err_dstbuf: - kfree(thread->dsts); -err_dsts: - for (i = 0; thread->srcs[i]; i++) - kfree(thread->srcs[i]); -err_srcbuf: - kfree(thread->srcs); -err_srcs: - pr_notice("%s: terminating after %u tests, %u failures (status %d)\n", - thread_name, total_tests, failed_tests, ret); - - if (iterations > 0) - while (!kthread_should_stop()) { - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_cdmatest_exit); - interruptible_sleep_on(&wait_cdmatest_exit); - } - - return ret; -} - -static void cdmatest_cleanup_channel(struct cdmatest_chan *dtc) -{ - struct cdmatest_thread *thread; - struct cdmatest_thread *_thread; - int ret; - - list_for_each_entry_safe(thread, _thread, &dtc->threads, node) { - ret = kthread_stop(thread->task); - pr_debug("cdmatest: thread %s exited with status %d\n", - thread->task->comm, ret); - list_del(&thread->node); - kfree(thread); - } - kfree(dtc); -} - -static int cdmatest_add_threads(struct cdmatest_chan *dtc, - enum dma_transaction_type type) -{ - struct cdmatest_thread *thread; - struct dma_chan *chan = dtc->chan; - char *op; - unsigned int i; - - if (type == DMA_MEMCPY) - op = "copy"; - else if (type == DMA_XOR) - op = "xor"; - else if (type == DMA_PQ) - op = "pq"; - else - return -EINVAL; - - for (i = 0; i < threads_per_chan; i++) { - thread = kzalloc(sizeof(struct cdmatest_thread), GFP_KERNEL); - if (!thread) { - pr_warn("cdmatest: No memory for %s-%s%u\n", - dma_chan_name(chan), op, i); - - break; - } - thread->chan = dtc->chan; - thread->type = type; - smp_wmb(); - thread->task = kthread_run(cdmatest_func, thread, "%s-%s%u", - dma_chan_name(chan), op, i); - if (IS_ERR(thread->task)) { - pr_warn("cdmatest: Failed to run thread %s-%s%u\n", - dma_chan_name(chan), op, i); - kfree(thread); - break; - } - - /* srcbuf and dstbuf are allocated by the thread itself */ - - list_add_tail(&thread->node, &dtc->threads); - } - - return i; -} - -static int cdmatest_add_channel(struct dma_chan *chan) -{ - struct cdmatest_chan *dtc; - struct dma_device *dma_dev = chan->device; - unsigned int thread_count = 0; - int cnt; - - dtc = kmalloc(sizeof(struct cdmatest_chan), GFP_KERNEL); - if (!dtc) { - pr_warn("cdmatest: No memory for %s\n", dma_chan_name(chan)); - return -ENOMEM; - } - - dtc->chan = chan; - INIT_LIST_HEAD(&dtc->threads); - - if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) { - cnt = cdmatest_add_threads(dtc, DMA_MEMCPY); - thread_count += cnt > 0 ? cnt : 0; - } - if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) { - cnt = cdmatest_add_threads(dtc, DMA_XOR); - thread_count += cnt > 0 ? cnt : 0; - } - if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) { - cnt = cdmatest_add_threads(dtc, DMA_PQ); - thread_count += cnt > 0 ? cnt : 0; - } - - pr_info("cdmatest: Started %u threads using %s\n", - thread_count, dma_chan_name(chan)); - - list_add_tail(&dtc->node, &cdmatest_channels); - nr_channels++; - - return 0; -} - -static bool filter(struct dma_chan *chan, void *param) -{ - if (!cdmatest_match_channel(chan) || - !cdmatest_match_device(chan->device)) - return false; - - return true; -} - -static int __init cdmatest_init(void) -{ - dma_cap_mask_t mask; - struct dma_chan *chan; - int err = 0; - - dma_cap_zero(mask); - dma_cap_set(DMA_MEMCPY, mask); - for (;;) { - chan = dma_request_channel(mask, filter, NULL); - - if (chan) { - err = cdmatest_add_channel(chan); - if (err) { - dma_release_channel(chan); - break; /* add_channel failed, punt */ - } - } else - break; /* no more channels available */ - if (max_channels && nr_channels >= max_channels) - break; /* we have all we need */ - } - - return err; -} -/* when compiled-in wait for drivers to load first */ -late_initcall(cdmatest_init); - -static void __exit cdmatest_exit(void) -{ - struct cdmatest_chan *dtc, *_dtc; - struct dma_chan *chan; - - list_for_each_entry_safe(dtc, _dtc, &cdmatest_channels, node) { - list_del(&dtc->node); - chan = dtc->chan; - cdmatest_cleanup_channel(dtc); - pr_debug("cdmatest: dropped channel %s\n", - dma_chan_name(chan)); - dma_release_channel(chan); - } -} -module_exit(cdmatest_exit); - -MODULE_AUTHOR("Xilinx, Inc."); -MODULE_DESCRIPTION("Xilinx AXI CDMA Test Client"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/dma/xilinx/dmatest.c b/drivers/dma/xilinx/dmatest.c deleted file mode 100644 index e9104f27322ff..0000000000000 --- a/drivers/dma/xilinx/dmatest.c +++ /dev/null @@ -1,649 +0,0 @@ -/* - * XILINX AXI DMA Engine test module - * - * Copyright (C) 2010 Xilinx, Inc. All rights reserved. - * - * Based on Atmel DMA Test Client - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static unsigned int test_buf_size = 64; -module_param(test_buf_size, uint, S_IRUGO); -MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer"); - -static unsigned int iterations; -module_param(iterations, uint, S_IRUGO); -MODULE_PARM_DESC(iterations, - "Iterations before stopping test (default: infinite)"); - -/* - * Initialization patterns. All bytes in the source buffer has bit 7 - * set, all bytes in the destination buffer has bit 7 cleared. - * - * Bit 6 is set for all bytes which are to be copied by the DMA - * engine. Bit 5 is set for all bytes which are to be overwritten by - * the DMA engine. - * - * The remaining bits are the inverse of a counter which increments by - * one for each byte address. - */ -#define PATTERN_SRC 0x80 -#define PATTERN_DST 0x00 -#define PATTERN_COPY 0x40 -#define PATTERN_OVERWRITE 0x20 -#define PATTERN_COUNT_MASK 0x1f - -struct dmatest_slave_thread { - struct list_head node; - struct task_struct *task; - struct dma_chan *tx_chan; - struct dma_chan *rx_chan; - u8 **srcs; - u8 **dsts; - enum dma_transaction_type type; -}; - -struct dmatest_chan { - struct list_head node; - struct dma_chan *chan; - struct list_head threads; -}; - -/* - * These are protected by dma_list_mutex since they're only used by - * the DMA filter function callback - */ -static LIST_HEAD(dmatest_channels); -static unsigned int nr_channels; - -static unsigned long dmatest_random(void) -{ - unsigned long buf; - - get_random_bytes(&buf, sizeof(buf)); - return buf; -} - -static void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len) -{ - unsigned int i; - u8 *buf; - - for (; (buf = *bufs); bufs++) { - for (i = 0; i < start; i++) - buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); - for ( ; i < start + len; i++) - buf[i] = PATTERN_SRC | PATTERN_COPY - | (~i & PATTERN_COUNT_MASK); - for ( ; i < test_buf_size; i++) - buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); - buf++; - } -} - -static void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len) -{ - unsigned int i; - u8 *buf; - - for (; (buf = *bufs); bufs++) { - for (i = 0; i < start; i++) - buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); - for ( ; i < start + len; i++) - buf[i] = PATTERN_DST | PATTERN_OVERWRITE - | (~i & PATTERN_COUNT_MASK); - for ( ; i < test_buf_size; i++) - buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); - } -} - -static void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index, - unsigned int counter, bool is_srcbuf) -{ - u8 diff = actual ^ pattern; - u8 expected = pattern | (~counter & PATTERN_COUNT_MASK); - const char *thread_name = current->comm; - - if (is_srcbuf) - pr_warn( - "%s: srcbuf[0x%x] overwritten! Expected %02x, got %02x\n", - thread_name, index, expected, actual); - else if ((pattern & PATTERN_COPY) - && (diff & (PATTERN_COPY | PATTERN_OVERWRITE))) - pr_warn( - "%s: dstbuf[0x%x] not copied! Expected %02x, got %02x\n", - thread_name, index, expected, actual); - else if (diff & PATTERN_SRC) - pr_warn( - "%s: dstbuf[0x%x] was copied! Expected %02x, got %02x\n", - thread_name, index, expected, actual); - else - pr_warn( - "%s: dstbuf[0x%x] mismatch! Expected %02x, got %02x\n", - thread_name, index, expected, actual); -} - -static unsigned int dmatest_verify(u8 **bufs, unsigned int start, - unsigned int end, unsigned int counter, u8 pattern, - bool is_srcbuf) -{ - unsigned int i; - unsigned int error_count = 0; - u8 actual; - u8 expected; - u8 *buf; - unsigned int counter_orig = counter; - - for (; (buf = *bufs); bufs++) { - counter = counter_orig; - for (i = start; i < end; i++) { - actual = buf[i]; - expected = pattern | (~counter & PATTERN_COUNT_MASK); - if (actual != expected) { - if (error_count < 32) - dmatest_mismatch(actual, pattern, i, - counter, is_srcbuf); - error_count++; - } - counter++; - } - } - - if (error_count > 32) - pr_warn("%s: %u errors suppressed\n", - current->comm, error_count - 32); - - return error_count; -} - -static void dmatest_slave_tx_callback(void *completion) -{ - complete(completion); -} - -static void dmatest_slave_rx_callback(void *completion) -{ - complete(completion); -} - -/* Function for slave transfers - * Each thread requires 2 channels, one for transmit, and one for receive - */ -static int dmatest_slave_func(void *data) -{ - struct dmatest_slave_thread *thread = data; - struct dma_chan *tx_chan; - struct dma_chan *rx_chan; - const char *thread_name; - unsigned int src_off, dst_off, len; - unsigned int error_count; - unsigned int failed_tests = 0; - unsigned int total_tests = 0; - dma_cookie_t tx_cookie; - dma_cookie_t rx_cookie; - enum dma_status status; - enum dma_ctrl_flags flags; - int ret; - int src_cnt; - int dst_cnt; - int bd_cnt = 11; - int i; - struct xilinx_dma_config config; - thread_name = current->comm; - - ret = -ENOMEM; - - /* JZ: limit testing scope here */ - iterations = 5; - test_buf_size = 700; - - smp_rmb(); - tx_chan = thread->tx_chan; - rx_chan = thread->rx_chan; - src_cnt = dst_cnt = bd_cnt; - - thread->srcs = kcalloc(src_cnt+1, sizeof(u8 *), GFP_KERNEL); - if (!thread->srcs) - goto err_srcs; - for (i = 0; i < src_cnt; i++) { - thread->srcs[i] = kmalloc(test_buf_size, GFP_KERNEL); - if (!thread->srcs[i]) - goto err_srcbuf; - } - thread->srcs[i] = NULL; - - thread->dsts = kcalloc(dst_cnt+1, sizeof(u8 *), GFP_KERNEL); - if (!thread->dsts) - goto err_dsts; - for (i = 0; i < dst_cnt; i++) { - thread->dsts[i] = kmalloc(test_buf_size, GFP_KERNEL); - if (!thread->dsts[i]) - goto err_dstbuf; - } - thread->dsts[i] = NULL; - - set_user_nice(current, 10); - - flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP | DMA_PREP_INTERRUPT; - - while (!kthread_should_stop() - && !(iterations && total_tests >= iterations)) { - struct dma_device *tx_dev = tx_chan->device; - struct dma_device *rx_dev = rx_chan->device; - struct dma_async_tx_descriptor *txd = NULL; - struct dma_async_tx_descriptor *rxd = NULL; - dma_addr_t dma_srcs[src_cnt]; - dma_addr_t dma_dsts[dst_cnt]; - struct completion rx_cmp; - struct completion tx_cmp; - unsigned long rx_tmo = - msecs_to_jiffies(300000); /* RX takes longer */ - unsigned long tx_tmo = msecs_to_jiffies(30000); - u8 align = 0; - struct scatterlist tx_sg[bd_cnt]; - struct scatterlist rx_sg[bd_cnt]; - - total_tests++; - - /* honor larger alignment restrictions */ - align = tx_dev->copy_align; - if (rx_dev->copy_align > align) - align = rx_dev->copy_align; - - if (1 << align > test_buf_size) { - pr_err("%u-byte buffer too small for %d-byte alignment\n", - test_buf_size, 1 << align); - break; - } - - len = dmatest_random() % test_buf_size + 1; - len = (len >> align) << align; - if (!len) - len = 1 << align; - src_off = dmatest_random() % (test_buf_size - len + 1); - dst_off = dmatest_random() % (test_buf_size - len + 1); - - src_off = (src_off >> align) << align; - dst_off = (dst_off >> align) << align; - - dmatest_init_srcs(thread->srcs, src_off, len); - dmatest_init_dsts(thread->dsts, dst_off, len); - - for (i = 0; i < src_cnt; i++) { - u8 *buf = thread->srcs[i] + src_off; - - dma_srcs[i] = dma_map_single(tx_dev->dev, buf, len, - DMA_MEM_TO_DEV); - } - - for (i = 0; i < dst_cnt; i++) { - dma_dsts[i] = dma_map_single(rx_dev->dev, - thread->dsts[i], - test_buf_size, - DMA_MEM_TO_DEV); - - dma_unmap_single(rx_dev->dev, dma_dsts[i], - test_buf_size, - DMA_MEM_TO_DEV); - - dma_dsts[i] = dma_map_single(rx_dev->dev, - thread->dsts[i], - test_buf_size, - DMA_DEV_TO_MEM); - } - - sg_init_table(tx_sg, bd_cnt); - sg_init_table(rx_sg, bd_cnt); - - for (i = 0; i < bd_cnt; i++) { - sg_dma_address(&tx_sg[i]) = dma_srcs[i]; - sg_dma_address(&rx_sg[i]) = dma_dsts[i] + dst_off; - - sg_dma_len(&tx_sg[i]) = len; - sg_dma_len(&rx_sg[i]) = len; - - } - - /* Only one interrupt */ - config.coalesc = 1; - config.delay = 0; - rx_dev->device_control(rx_chan, DMA_SLAVE_CONFIG, - (unsigned long)&config); - - config.coalesc = 1; - config.delay = 0; - tx_dev->device_control(tx_chan, DMA_SLAVE_CONFIG, - (unsigned long)&config); - - rxd = rx_dev->device_prep_slave_sg(rx_chan, rx_sg, bd_cnt, - DMA_DEV_TO_MEM, flags, NULL); - - txd = tx_dev->device_prep_slave_sg(tx_chan, tx_sg, bd_cnt, - DMA_MEM_TO_DEV, flags, NULL); - - if (!rxd || !txd) { - for (i = 0; i < src_cnt; i++) - dma_unmap_single(tx_dev->dev, dma_srcs[i], len, - DMA_MEM_TO_DEV); - for (i = 0; i < dst_cnt; i++) - dma_unmap_single(rx_dev->dev, dma_dsts[i], - test_buf_size, - DMA_DEV_TO_MEM); - pr_warn( - "%s: #%u: prep error with src_off=0x%x ", - thread_name, total_tests - 1, src_off); - pr_warn("dst_off=0x%x len=0x%x\n", - dst_off, len); - msleep(100); - failed_tests++; - continue; - } - - init_completion(&rx_cmp); - rxd->callback = dmatest_slave_rx_callback; - rxd->callback_param = &rx_cmp; - rx_cookie = rxd->tx_submit(rxd); - - init_completion(&tx_cmp); - txd->callback = dmatest_slave_tx_callback; - txd->callback_param = &tx_cmp; - tx_cookie = txd->tx_submit(txd); - - if (dma_submit_error(rx_cookie) || - dma_submit_error(tx_cookie)) { - pr_warn( - "%s: #%u: submit error %d/%d with src_off=0x%x ", - thread_name, total_tests - 1, - rx_cookie, tx_cookie, src_off); - pr_warn("dst_off=0x%x len=0x%x\n", - dst_off, len); - msleep(100); - failed_tests++; - continue; - } - dma_async_issue_pending(tx_chan); - dma_async_issue_pending(rx_chan); - - tx_tmo = wait_for_completion_timeout(&tx_cmp, tx_tmo); - - status = dma_async_is_tx_complete(tx_chan, tx_cookie, - NULL, NULL); - - if (tx_tmo == 0) { - pr_warn("%s: #%u: tx test timed out\n", - thread_name, total_tests - 1); - failed_tests++; - continue; - } else if (status != DMA_SUCCESS) { - pr_warn( - "%s: #%u: tx got completion callback, ", - thread_name, total_tests - 1); - pr_warn("but status is \'%s\'\n", - status == DMA_ERROR ? "error" : - "in progress"); - failed_tests++; - continue; - } - - rx_tmo = wait_for_completion_timeout(&rx_cmp, rx_tmo); - status = dma_async_is_tx_complete(rx_chan, rx_cookie, - NULL, NULL); - - if (rx_tmo == 0) { - pr_warn("%s: #%u: rx test timed out\n", - thread_name, total_tests - 1); - failed_tests++; - continue; - } else if (status != DMA_SUCCESS) { - pr_warn( - "%s: #%u: rx got completion callback, ", - thread_name, total_tests - 1); - pr_warn("but status is \'%s\'\n", - status == DMA_ERROR ? "error" : - "in progress"); - failed_tests++; - continue; - } - - /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */ - for (i = 0; i < dst_cnt; i++) - dma_unmap_single(rx_dev->dev, dma_dsts[i], - test_buf_size, DMA_DEV_TO_MEM); - - error_count = 0; - - pr_debug("%s: verifying source buffer...\n", thread_name); - error_count += dmatest_verify(thread->srcs, 0, src_off, - 0, PATTERN_SRC, true); - error_count += dmatest_verify(thread->srcs, src_off, - src_off + len, src_off, - PATTERN_SRC | PATTERN_COPY, true); - error_count += dmatest_verify(thread->srcs, src_off + len, - test_buf_size, src_off + len, - PATTERN_SRC, true); - - pr_debug("%s: verifying dest buffer...\n", - thread->task->comm); - error_count += dmatest_verify(thread->dsts, 0, dst_off, - 0, PATTERN_DST, false); - error_count += dmatest_verify(thread->dsts, dst_off, - dst_off + len, src_off, - PATTERN_SRC | PATTERN_COPY, false); - error_count += dmatest_verify(thread->dsts, dst_off + len, - test_buf_size, dst_off + len, - PATTERN_DST, false); - - if (error_count) { - pr_warn("%s: #%u: %u errors with ", - thread_name, total_tests - 1, error_count); - pr_warn("src_off=0x%x dst_off=0x%x len=0x%x\n", - src_off, dst_off, len); - failed_tests++; - } else { - pr_debug("%s: #%u: No errors with ", - thread_name, total_tests - 1); - pr_debug("src_off=0x%x dst_off=0x%x len=0x%x\n", - src_off, dst_off, len); - } - } - - ret = 0; - for (i = 0; thread->dsts[i]; i++) - kfree(thread->dsts[i]); -err_dstbuf: - kfree(thread->dsts); -err_dsts: - for (i = 0; thread->srcs[i]; i++) - kfree(thread->srcs[i]); -err_srcbuf: - kfree(thread->srcs); -err_srcs: - pr_notice("%s: terminating after %u tests, %u failures (status %d)\n", - thread_name, total_tests, failed_tests, ret); - - if (iterations > 0) - while (!kthread_should_stop()) { - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit); - interruptible_sleep_on(&wait_dmatest_exit); - } - - return ret; -} - -static void dmatest_cleanup_channel(struct dmatest_chan *dtc) -{ - struct dmatest_slave_thread *thread; - struct dmatest_slave_thread *_thread; - int ret; - - list_for_each_entry_safe(thread, _thread, &dtc->threads, node) { - ret = kthread_stop(thread->task); - pr_debug("dmatest: thread %s exited with status %d\n", - thread->task->comm, ret); - list_del(&thread->node); - kfree(thread); - } - kfree(dtc); -} - -static int dmatest_add_slave_threads(struct dmatest_chan *tx_dtc, - struct dmatest_chan *rx_dtc) -{ - struct dmatest_slave_thread *thread; - struct dma_chan *tx_chan = tx_dtc->chan; - struct dma_chan *rx_chan = rx_dtc->chan; - - thread = kzalloc(sizeof(struct dmatest_slave_thread), GFP_KERNEL); - if (!thread) { - pr_warn("dmatest: No memory for slave thread %s-%s\n", - dma_chan_name(tx_chan), dma_chan_name(rx_chan)); - - } - - thread->tx_chan = tx_chan; - thread->rx_chan = rx_chan; - thread->type = (enum dma_transaction_type)DMA_SLAVE; - smp_wmb(); - thread->task = kthread_run(dmatest_slave_func, thread, "%s-%s", - dma_chan_name(tx_chan), dma_chan_name(rx_chan)); - if (IS_ERR(thread->task)) { - pr_warn("dmatest: Failed to run thread %s-%s\n", - dma_chan_name(tx_chan), dma_chan_name(rx_chan)); - kfree(thread); - } - - /* srcbuf and dstbuf are allocated by the thread itself */ - - list_add_tail(&thread->node, &tx_dtc->threads); - - /* Added one thread with 2 channels */ - return 1; -} - -static int dmatest_add_slave_channels(struct dma_chan *tx_chan, - struct dma_chan *rx_chan) -{ - struct dmatest_chan *tx_dtc; - struct dmatest_chan *rx_dtc; - unsigned int thread_count = 0; - - tx_dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL); - if (!tx_dtc) { - pr_warn("dmatest: No memory for tx %s\n", - dma_chan_name(tx_chan)); - return -ENOMEM; - } - - rx_dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL); - if (!rx_dtc) { - pr_warn("dmatest: No memory for rx %s\n", - dma_chan_name(rx_chan)); - return -ENOMEM; - } - - tx_dtc->chan = tx_chan; - rx_dtc->chan = rx_chan; - INIT_LIST_HEAD(&tx_dtc->threads); - INIT_LIST_HEAD(&rx_dtc->threads); - - dmatest_add_slave_threads(tx_dtc, rx_dtc); - thread_count += 1; - - pr_info("dmatest: Started %u threads using %s %s\n", - thread_count, dma_chan_name(tx_chan), dma_chan_name(rx_chan)); - - list_add_tail(&tx_dtc->node, &dmatest_channels); - list_add_tail(&rx_dtc->node, &dmatest_channels); - nr_channels += 2; - - return 0; -} - -static bool xdma_filter(struct dma_chan *chan, void *param) -{ - pr_debug("dmatest: Private is %x\n", *((int *)chan->private)); - - if (*((int *)chan->private) == *(int *)param) - return true; - - return false; -} - -static int __init dmatest_init(void) -{ - dma_cap_mask_t mask; - struct dma_chan *chan; - int err = 0; - - /* JZ for slave transfer channels */ - enum dma_data_direction direction; - struct dma_chan *rx_chan; - u32 match; - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE | DMA_PRIVATE, mask); - - direction = DMA_MEM_TO_DEV; - match = (direction & 0xFF) | XILINX_DMA_IP_DMA; - pr_debug("dmatest: match is %x\n", match); - - chan = dma_request_channel(mask, xdma_filter, (void *)&match); - - if (chan) - pr_debug("dmatest: Found tx device\n"); - else - pr_info("dmatest: Did not find tx device\n"); - - direction = DMA_DEV_TO_MEM; - match = (direction & 0xFF) | XILINX_DMA_IP_DMA; - rx_chan = dma_request_channel(mask, xdma_filter, &match); - - if (rx_chan) - pr_debug("dmatest: Found rx device\n"); - else - pr_info("dmatest: Did not find rx device\n"); - - if (chan && rx_chan) { - err = dmatest_add_slave_channels(chan, rx_chan); - if (err) { - dma_release_channel(chan); - dma_release_channel(rx_chan); - } - } - - return err; -} -/* when compiled-in wait for drivers to load first */ -late_initcall(dmatest_init); - -static void __exit dmatest_exit(void) -{ - struct dmatest_chan *dtc, *_dtc; - struct dma_chan *chan; - - list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) { - list_del(&dtc->node); - chan = dtc->chan; - dmatest_cleanup_channel(dtc); - pr_debug("dmatest: dropped channel %s\n", - dma_chan_name(chan)); - dma_release_channel(chan); - } -} -module_exit(dmatest_exit); - -MODULE_AUTHOR("Xilinx, Inc."); -MODULE_DESCRIPTION("Xilinx AXI DMA Test Client"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/dma/xilinx/vdmatest.c b/drivers/dma/xilinx/vdmatest.c deleted file mode 100644 index 6c7ada89c6233..0000000000000 --- a/drivers/dma/xilinx/vdmatest.c +++ /dev/null @@ -1,620 +0,0 @@ -/* - * XILIN VDMA Engine test module - * - * Copyright (C) 2012 Xilinx, Inc. All rights reserved. - * - * Based on Atmel DMA Test Client - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static unsigned int test_buf_size = 64; -module_param(test_buf_size, uint, S_IRUGO); -MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer"); - -static unsigned int iterations; -module_param(iterations, uint, S_IRUGO); -MODULE_PARM_DESC(iterations, - "Iterations before stopping test (default: infinite)"); - -/* - * Initialization patterns. All bytes in the source buffer has bit 7 - * set, all bytes in the destination buffer has bit 7 cleared. - * - * Bit 6 is set for all bytes which are to be copied by the DMA - * engine. Bit 5 is set for all bytes which are to be overwritten by - * the DMA engine. - * - * The remaining bits are the inverse of a counter which increments by - * one for each byte address. - */ -#define PATTERN_SRC 0x80 -#define PATTERN_DST 0x00 -#define PATTERN_COPY 0x40 -#define PATTERN_OVERWRITE 0x20 -#define PATTERN_COUNT_MASK 0x1f - -struct vdmatest_slave_thread { - struct list_head node; - struct task_struct *task; - struct dma_chan *tx_chan; - struct dma_chan *rx_chan; - u8 **srcs; - u8 **dsts; - enum dma_transaction_type type; -}; - -struct vdmatest_chan { - struct list_head node; - struct dma_chan *chan; - struct list_head threads; -}; - -/* - * These are protected by dma_list_mutex since they're only used by - * the DMA filter function callback - */ -static LIST_HEAD(vdmatest_channels); -static unsigned int nr_channels; - -static void vdmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len) -{ - unsigned int i; - u8 *buf; - - for (; (buf = *bufs); bufs++) { - for (i = 0; i < start; i++) - buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); - for ( ; i < start + len; i++) - buf[i] = PATTERN_SRC | PATTERN_COPY - | (~i & PATTERN_COUNT_MASK); - for ( ; i < test_buf_size; i++) - buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); - buf++; - } -} - -static void vdmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len) -{ - unsigned int i; - u8 *buf; - - for (; (buf = *bufs); bufs++) { - for (i = 0; i < start; i++) - buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); - for ( ; i < start + len; i++) - buf[i] = PATTERN_DST | PATTERN_OVERWRITE - | (~i & PATTERN_COUNT_MASK); - for ( ; i < test_buf_size; i++) - buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); - } -} - -static void vdmatest_mismatch(u8 actual, u8 pattern, unsigned int index, - unsigned int counter, bool is_srcbuf) -{ - u8 diff = actual ^ pattern; - u8 expected = pattern | (~counter & PATTERN_COUNT_MASK); - const char *thread_name = current->comm; - - if (is_srcbuf) - pr_warn( - "%s: srcbuf[0x%x] overwritten! Expected %02x, got %02x\n", - thread_name, index, expected, actual); - else if ((pattern & PATTERN_COPY) - && (diff & (PATTERN_COPY | PATTERN_OVERWRITE))) - pr_warn( - "%s: dstbuf[0x%x] not copied! Expected %02x, got %02x\n", - thread_name, index, expected, actual); - else if (diff & PATTERN_SRC) - pr_warn( - "%s: dstbuf[0x%x] was copied! Expected %02x, got %02x\n", - thread_name, index, expected, actual); - else - pr_warn( - "%s: dstbuf[0x%x] mismatch! Expected %02x, got %02x\n", - thread_name, index, expected, actual); -} - -static unsigned int vdmatest_verify(u8 **bufs, unsigned int start, - unsigned int end, unsigned int counter, u8 pattern, - bool is_srcbuf) -{ - unsigned int i; - unsigned int error_count = 0; - u8 actual; - u8 expected; - u8 *buf; - unsigned int counter_orig = counter; - - for (; (buf = *bufs); bufs++) { - counter = counter_orig; - for (i = start; i < end; i++) { - actual = buf[i]; - expected = pattern | (~counter & PATTERN_COUNT_MASK); - if (actual != expected) { - if (error_count < 32) - vdmatest_mismatch(actual, pattern, i, - counter, is_srcbuf); - error_count++; - } - counter++; - } - } - - if (error_count > 32) - pr_warn("%s: %u errors suppressed\n", - current->comm, error_count - 32); - - return error_count; -} - -static void vdmatest_slave_tx_callback(void *completion) -{ - pr_debug("Got tx callback\n"); - complete(completion); -} - -static void vdmatest_slave_rx_callback(void *completion) -{ - pr_debug("Got rx callback\n"); - complete(completion); -} - -/* - * Function for slave transfers - * Each thread requires 2 channels, one for transmit, and one for receive - */ -static int vdmatest_slave_func(void *data) -{ - struct vdmatest_slave_thread *thread = data; - struct dma_chan *tx_chan; - struct dma_chan *rx_chan; - const char *thread_name; - unsigned int len; - unsigned int error_count; - unsigned int failed_tests = 0; - unsigned int total_tests = 0; - dma_cookie_t tx_cookie; - dma_cookie_t rx_cookie; - enum dma_status status; - enum dma_ctrl_flags flags; - int ret; - int frm_cnt = 8; - int i; - int hsize = 64; - int vsize = 32; - struct xilinx_vdma_config config; - thread_name = current->comm; - - ret = -ENOMEM; - - /* JZ: limit testing scope here */ - iterations = 1; - test_buf_size = hsize * vsize; - - smp_rmb(); - tx_chan = thread->tx_chan; - rx_chan = thread->rx_chan; - - thread->srcs = kcalloc(frm_cnt+1, sizeof(u8 *), GFP_KERNEL); - if (!thread->srcs) - goto err_srcs; - for (i = 0; i < frm_cnt; i++) { - thread->srcs[i] = kmalloc(test_buf_size, GFP_KERNEL); - if (!thread->srcs[i]) - goto err_srcbuf; - } - thread->srcs[i] = NULL; - - thread->dsts = kcalloc(frm_cnt+1, sizeof(u8 *), GFP_KERNEL); - if (!thread->dsts) - goto err_dsts; - for (i = 0; i < frm_cnt; i++) { - thread->dsts[i] = kmalloc(test_buf_size, GFP_KERNEL); - if (!thread->dsts[i]) - goto err_dstbuf; - } - thread->dsts[i] = NULL; - - set_user_nice(current, 10); - - flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP | DMA_PREP_INTERRUPT; - - while (!kthread_should_stop() - && !(iterations && total_tests >= iterations)) { - struct dma_device *tx_dev = tx_chan->device; - struct dma_device *rx_dev = rx_chan->device; - struct dma_async_tx_descriptor *txd = NULL; - struct dma_async_tx_descriptor *rxd = NULL; - dma_addr_t dma_srcs[frm_cnt]; - dma_addr_t dma_dsts[frm_cnt]; - struct completion rx_cmp; - struct completion tx_cmp; - unsigned long rx_tmo = - msecs_to_jiffies(30000); /* RX takes longer */ - unsigned long tx_tmo = msecs_to_jiffies(30000); - u8 align = 0; - struct scatterlist tx_sg[frm_cnt]; - struct scatterlist rx_sg[frm_cnt]; - - total_tests++; - - /* honor larger alignment restrictions */ - align = tx_dev->copy_align; - if (rx_dev->copy_align > align) - align = rx_dev->copy_align; - - if (1 << align > test_buf_size) { - pr_err("%u-byte buffer too small for %d-byte alignment\n", - test_buf_size, 1 << align); - break; - } - - len = test_buf_size; - vdmatest_init_srcs(thread->srcs, 0, len); - vdmatest_init_dsts(thread->dsts, 0, len); - - sg_init_table(tx_sg, frm_cnt); - sg_init_table(rx_sg, frm_cnt); - - for (i = 0; i < frm_cnt; i++) { - u8 *buf = thread->srcs[i]; - - dma_srcs[i] = dma_map_single(tx_dev->dev, buf, len, - DMA_MEM_TO_DEV); - pr_debug("src buf %x dma %x\n", (unsigned int)buf, - dma_srcs[i]); - sg_dma_address(&tx_sg[i]) = dma_srcs[i]; - sg_dma_len(&tx_sg[i]) = len; - } - - for (i = 0; i < frm_cnt; i++) { - dma_dsts[i] = dma_map_single(rx_dev->dev, - thread->dsts[i], - test_buf_size, - DMA_DEV_TO_MEM); - pr_debug("dst %x dma %x\n", - (unsigned int)thread->dsts[i], - dma_dsts[i]); - sg_dma_address(&rx_sg[i]) = dma_dsts[i]; - sg_dma_len(&rx_sg[i]) = len; - } - - /* Set up hardware configuration information */ - config.direction = DMA_MEM_TO_DEV; - config.vsize = vsize; - config.hsize = hsize; - config.stride = hsize; - config.frm_cnt_en = 1; - config.coalesc = frm_cnt * 10; - config.delay = 0; - /* The following is do-not-care, need to set to 0 */ - config.frm_dly = 0; - config.park = 1; - config.gen_lock = 0; - config.master = 0; - config.park_frm = 0; - config.disable_intr = 0; - tx_dev->device_control(tx_chan, DMA_SLAVE_CONFIG, - (unsigned long)&config); - - config.direction = DMA_DEV_TO_MEM; - config.park = 0; - rx_dev->device_control(rx_chan, DMA_SLAVE_CONFIG, - (unsigned long)&config); - - rxd = rx_dev->device_prep_slave_sg(rx_chan, rx_sg, frm_cnt, - DMA_DEV_TO_MEM, flags, NULL); - - txd = tx_dev->device_prep_slave_sg(tx_chan, tx_sg, frm_cnt, - DMA_MEM_TO_DEV, flags, NULL); - - if (!rxd || !txd) { - for (i = 0; i < frm_cnt; i++) - dma_unmap_single(tx_dev->dev, dma_srcs[i], len, - DMA_MEM_TO_DEV); - for (i = 0; i < frm_cnt; i++) - dma_unmap_single(rx_dev->dev, dma_dsts[i], - test_buf_size, - DMA_DEV_TO_MEM); - pr_warn("%s: #%u: prep error with len=0x%x ", - thread_name, total_tests - 1, len); - msleep(100); - failed_tests++; - continue; - } - - init_completion(&rx_cmp); - rxd->callback = vdmatest_slave_rx_callback; - rxd->callback_param = &rx_cmp; - rx_cookie = rxd->tx_submit(rxd); - - init_completion(&tx_cmp); - txd->callback = vdmatest_slave_tx_callback; - txd->callback_param = &tx_cmp; - tx_cookie = txd->tx_submit(txd); - - if (dma_submit_error(rx_cookie) || - dma_submit_error(tx_cookie)) { - pr_warn("%s: #%u: submit error %d/%d with len=0x%x ", - thread_name, total_tests - 1, - rx_cookie, tx_cookie, len); - msleep(100); - failed_tests++; - continue; - } - dma_async_issue_pending(tx_chan); - dma_async_issue_pending(rx_chan); - - tx_tmo = wait_for_completion_timeout(&tx_cmp, tx_tmo); - - status = dma_async_is_tx_complete(tx_chan, tx_cookie, - NULL, NULL); - - if (tx_tmo == 0) { - pr_warn("%s: #%u: tx test timed out\n", - thread_name, total_tests - 1); - failed_tests++; - continue; - } else if (status != DMA_SUCCESS) { - pr_warn( - "%s: #%u: tx got completion callback, ", - thread_name, total_tests - 1); - pr_warn("but status is \'%s\'\n", - status == DMA_ERROR ? "error" : - "in progress"); - failed_tests++; - continue; - } - - rx_tmo = wait_for_completion_timeout(&rx_cmp, rx_tmo); - status = dma_async_is_tx_complete(rx_chan, rx_cookie, - NULL, NULL); - - if (rx_tmo == 0) { - pr_warn("%s: #%u: rx test timed out\n", - thread_name, total_tests - 1); - failed_tests++; - continue; - } else if (status != DMA_SUCCESS) { - pr_warn( - "%s: #%u: rx got completion callback, ", - thread_name, total_tests - 1); - pr_warn("but status is \'%s\'\n", - status == DMA_ERROR ? "error" : - "in progress"); - failed_tests++; - continue; - } - - /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */ - for (i = 0; i < frm_cnt; i++) - dma_unmap_single(rx_dev->dev, dma_dsts[i], - test_buf_size, DMA_DEV_TO_MEM); - - error_count = 0; - - pr_debug("%s: verifying source buffer...\n", thread_name); - error_count += vdmatest_verify(thread->srcs, 0, 0, - 0, PATTERN_SRC, true); - error_count += vdmatest_verify(thread->srcs, 0, - len, 0, PATTERN_SRC | PATTERN_COPY, true); - error_count += vdmatest_verify(thread->srcs, len, - test_buf_size, len, PATTERN_SRC, true); - - pr_debug("%s: verifying dest buffer...\n", - thread->task->comm); - error_count += vdmatest_verify(thread->dsts, 0, 0, - 0, PATTERN_DST, false); - error_count += vdmatest_verify(thread->dsts, 0, - len, 0, PATTERN_SRC | PATTERN_COPY, false); - error_count += vdmatest_verify(thread->dsts, len, - test_buf_size, len, PATTERN_DST, false); - - if (error_count) { - pr_warn("%s: #%u: %u errors with len=0x%x\n", - thread_name, total_tests - 1, error_count, len); - failed_tests++; - } else { - pr_debug("%s: #%u: No errors with len=0x%x\n", - thread_name, total_tests - 1, len); - } - } - - ret = 0; - for (i = 0; thread->dsts[i]; i++) - kfree(thread->dsts[i]); -err_dstbuf: - kfree(thread->dsts); -err_dsts: - for (i = 0; thread->srcs[i]; i++) - kfree(thread->srcs[i]); -err_srcbuf: - kfree(thread->srcs); -err_srcs: - pr_notice("%s: terminating after %u tests, %u failures (status %d)\n", - thread_name, total_tests, failed_tests, ret); - - if (iterations > 0) - while (!kthread_should_stop()) { - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_vdmatest_exit); - interruptible_sleep_on(&wait_vdmatest_exit); - } - - return ret; -} - -static void vdmatest_cleanup_channel(struct vdmatest_chan *dtc) -{ - struct vdmatest_slave_thread *thread; - struct vdmatest_slave_thread *_thread; - int ret; - - list_for_each_entry_safe(thread, _thread, - &dtc->threads, node) { - ret = kthread_stop(thread->task); - pr_info("vdmatest: thread %s exited with status %d\n", - thread->task->comm, ret); - list_del(&thread->node); - kfree(thread); - } - kfree(dtc); -} - -static int vdmatest_add_slave_threads(struct vdmatest_chan *tx_dtc, - struct vdmatest_chan *rx_dtc) -{ - struct vdmatest_slave_thread *thread; - struct dma_chan *tx_chan = tx_dtc->chan; - struct dma_chan *rx_chan = rx_dtc->chan; - - thread = kzalloc(sizeof(struct vdmatest_slave_thread), GFP_KERNEL); - if (!thread) { - pr_warn("vdmatest: No memory for slave thread %s-%s\n", - dma_chan_name(tx_chan), dma_chan_name(rx_chan)); - - } - - thread->tx_chan = tx_chan; - thread->rx_chan = rx_chan; - thread->type = (enum dma_transaction_type)DMA_SLAVE; - smp_wmb(); - thread->task = kthread_run(vdmatest_slave_func, thread, "%s-%s", - dma_chan_name(tx_chan), dma_chan_name(rx_chan)); - if (IS_ERR(thread->task)) { - pr_warn("vdmatest: Failed to run thread %s-%s\n", - dma_chan_name(tx_chan), dma_chan_name(rx_chan)); - kfree(thread); - } - - /* srcbuf and dstbuf are allocated by the thread itself */ - - list_add_tail(&thread->node, &tx_dtc->threads); - - /* Added one thread with 2 channels */ - return 1; -} - -static int vdmatest_add_slave_channels(struct dma_chan *tx_chan, - struct dma_chan *rx_chan) -{ - struct vdmatest_chan *tx_dtc; - struct vdmatest_chan *rx_dtc; - unsigned int thread_count = 0; - - tx_dtc = kmalloc(sizeof(struct vdmatest_chan), GFP_KERNEL); - if (!tx_dtc) { - pr_warn("vdmatest: No memory for tx %s\n", - dma_chan_name(tx_chan)); - return -ENOMEM; - } - - rx_dtc = kmalloc(sizeof(struct vdmatest_chan), GFP_KERNEL); - if (!rx_dtc) { - pr_warn("vdmatest: No memory for rx %s\n", - dma_chan_name(rx_chan)); - return -ENOMEM; - } - - tx_dtc->chan = tx_chan; - rx_dtc->chan = rx_chan; - INIT_LIST_HEAD(&tx_dtc->threads); - INIT_LIST_HEAD(&rx_dtc->threads); - - vdmatest_add_slave_threads(tx_dtc, rx_dtc); - thread_count += 1; - - pr_info("vdmatest: Started %u threads using %s %s\n", - thread_count, dma_chan_name(tx_chan), dma_chan_name(rx_chan)); - - list_add_tail(&tx_dtc->node, &vdmatest_channels); - list_add_tail(&rx_dtc->node, &vdmatest_channels); - nr_channels += 2; - - return 0; -} - -static bool xdma_filter(struct dma_chan *chan, void *param) -{ - if (*((int *)chan->private) == *(int *)param) - return true; - - return false; -} - -static int __init vdmatest_init(void) -{ - dma_cap_mask_t mask; - struct dma_chan *chan; - int err = 0; - - enum dma_data_direction direction; - u32 match; - struct dma_chan *rx_chan; - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE | DMA_PRIVATE, mask); - - direction = DMA_MEM_TO_DEV; - match = (direction & 0xFF) | XILINX_DMA_IP_VDMA; - pr_debug("vdmatest: match is %x\n", match); - - chan = dma_request_channel(mask, xdma_filter, (void *)&match); - - if (chan) - pr_debug("vdmatest: Found tx device\n"); - else - pr_info("vdmatest: Did not find tx device\n"); - - direction = DMA_DEV_TO_MEM; - match = (direction & 0xFF) | XILINX_DMA_IP_VDMA; - rx_chan = dma_request_channel(mask, xdma_filter, &match); - - if (rx_chan) - pr_debug("vdmatest: Found rx device\n"); - else - pr_info("vdmatest: Did not find rx device\n"); - - if (chan && rx_chan) { - err = vdmatest_add_slave_channels(chan, rx_chan); - if (err) { - dma_release_channel(chan); - dma_release_channel(rx_chan); - } - } - return err; -} -/* when compiled-in wait for drivers to load first */ -late_initcall(vdmatest_init); - -static void __exit vdmatest_exit(void) -{ - struct vdmatest_chan *dtc, *_dtc; - struct dma_chan *chan; - - list_for_each_entry_safe(dtc, _dtc, &vdmatest_channels, node) { - list_del(&dtc->node); - chan = dtc->chan; - vdmatest_cleanup_channel(dtc); - pr_info("vdmatest: dropped channel %s\n", - dma_chan_name(chan)); - dma_release_channel(chan); - } -} -module_exit(vdmatest_exit); - -MODULE_AUTHOR("Xilinx, Inc."); -MODULE_DESCRIPTION("Xilinx AXI VDMA Test Client"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/dma/xilinx/xilinx_axicdma.c b/drivers/dma/xilinx/xilinx_axicdma.c deleted file mode 100644 index 170c67a50b9ec..0000000000000 --- a/drivers/dma/xilinx/xilinx_axicdma.c +++ /dev/null @@ -1,1095 +0,0 @@ -/* - * Xilinx Central DMA Engine support - * - * Copyright (C) 2010 Xilinx, Inc. All rights reserved. - * - * Based on the Freescale DMA driver. - * - * Description: - * . Axi CDMA engine, it does transfers between memory and memory - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Hw specific definitions */ -#define XILINX_CDMA_MAX_CHANS_PER_DEVICE 0x1 -#define XILINX_CDMA_MAX_TRANS_LEN 0x7FFFFF - -/* General register bits definitions */ -#define XILINX_CDMA_CR_RESET_MASK 0x00000004 - /* Reset DMA engine */ - -#define XILINX_CDMA_SR_IDLE_MASK 0x00000002 - /* DMA channel idle */ - -#define XILINX_CDMA_SR_ERR_INTERNAL_MASK 0x00000010 - /* Datamover internal err */ -#define XILINX_CDMA_SR_ERR_SLAVE_MASK 0x00000020 - /* Datamover slave err */ -#define XILINX_CDMA_SR_ERR_DECODE_MASK 0x00000040 - /* Datamover decode err */ -#define XILINX_CDMA_SR_ERR_SG_INT_MASK 0x00000100 - /* SG internal err */ -#define XILINX_CDMA_SR_ERR_SG_SLV_MASK 0x00000200 - /* SG slave err */ -#define XILINX_CDMA_SR_ERR_SG_DEC_MASK 0x00000400 - /* SG decode err */ -#define XILINX_CDMA_SR_ERR_ALL_MASK 0x00000770 - /* All errors */ - -#define XILINX_CDMA_XR_IRQ_IOC_MASK 0x00001000 - /* Completion interrupt */ -#define XILINX_CDMA_XR_IRQ_DELAY_MASK 0x00002000 - /* Delay interrupt */ -#define XILINX_CDMA_XR_IRQ_ERROR_MASK 0x00004000 - /* Error interrupt */ -#define XILINX_CDMA_XR_IRQ_ALL_MASK 0x00007000 - /* All interrupts */ - -#define XILINX_CDMA_XR_DELAY_MASK 0xFF000000 - /* Delay timeout counter */ -#define XILINX_CDMA_XR_COALESCE_MASK 0x00FF0000 - /* Coalesce counter */ - -#define XILINX_CDMA_IRQ_SHIFT 12 -#define XILINX_CDMA_DELAY_SHIFT 24 -#define XILINX_CDMA_COALESCE_SHIFT 16 - -#define XILINX_CDMA_DELAY_MAX 0xFF - /* Maximum delay counter value */ -#define XILINX_CDMA_COALESCE_MAX 0xFF - /* Maximum coalescing counter value */ - -#define XILINX_CDMA_CR_SGMODE_MASK 0x00000008 - /* Scatter gather mode */ - -#define XILINX_CDMA_SR_SGINCLD_MASK 0x00000008 - /* Hybrid build */ -#define XILINX_CDMA_XR_IRQ_SIMPLE_ALL_MASK 0x00005000 - /* All interrupts for simple mode */ - -/* BD definitions for Axi Cdma */ -#define XILINX_CDMA_BD_STS_COMPL_MASK 0x80000000 -#define XILINX_CDMA_BD_STS_ERR_MASK 0x70000000 -#define XILINX_CDMA_BD_STS_ALL_MASK 0xF0000000 - -/* Feature encodings */ -#define XILINX_CDMA_FTR_DATA_WIDTH_MASK 0x000000FF - /* Data width mask, 1024 */ -#define XILINX_CDMA_FTR_HAS_SG 0x00000100 - /* Has SG */ -#define XILINX_CDMA_FTR_HAS_SG_SHIFT 8 - /* Has SG shift */ - -/* Delay loop counter to prevent hardware failure */ -#define XILINX_CDMA_RESET_LOOP 1000000 -#define XILINX_CDMA_HALT_LOOP 1000000 - -/* Device Id in the private structure */ -#define XILINX_CDMA_DEVICE_ID_SHIFT 28 - -/* IO accessors */ -#define CDMA_OUT(addr, val) (iowrite32(val, addr)) -#define CDMA_IN(addr) (ioread32(addr)) - -/* Hardware descriptor */ -struct xilinx_cdma_desc_hw { - u32 next_desc; /* 0x00 */ - u32 pad1; /* 0x04 */ - u32 src_addr; /* 0x08 */ - u32 pad2; /* 0x0C */ - u32 dest_addr; /* 0x10 */ - u32 pad3; /* 0x14 */ - u32 control; /* 0x18 */ - u32 status; /* 0x1C */ -} __aligned(64); - -/* Software descriptor */ -struct xilinx_cdma_desc_sw { - struct xilinx_cdma_desc_hw hw; - struct list_head node; - struct list_head tx_list; - struct dma_async_tx_descriptor async_tx; -} __aligned(64); - -/* AXI CDMA Registers Structure */ -struct xcdma_regs { - u32 cr; /* 0x00 Control Register */ - u32 sr; /* 0x04 Status Register */ - u32 cdr; /* 0x08 Current Descriptor Register */ - u32 pad1; - u32 tdr; /* 0x10 Tail Descriptor Register */ - u32 pad2; - u32 src; /* 0x18 Source Address Register */ - u32 pad3; - u32 dst; /* 0x20 Destination Address Register */ - u32 pad4; - u32 btt_ref; /* 0x28 Bytes To Transfer */ -}; - -/* Per DMA specific operations should be embedded in the channel structure */ -struct xilinx_cdma_chan { - struct xcdma_regs __iomem *regs; /* Control status registers */ - dma_cookie_t completed_cookie; /* Maximum cookie completed */ - dma_cookie_t cookie; /* The current cookie */ - spinlock_t lock; /* Descriptor operation lock */ - bool sg_waiting; /* SG transfer waiting */ - struct list_head active_list; /* Active descriptors */ - struct list_head pending_list; /* Descriptors waiting */ - struct dma_chan common; /* DMA common channel */ - struct dma_pool *desc_pool; /* Descriptors pool */ - struct device *dev; /* The dma device */ - int irq; /* Channel IRQ */ - int id; /* Channel ID */ - enum dma_transfer_direction direction; /* Transfer direction */ - int max_len; /* Max data len per transfer */ - int is_lite; /* Whether is light build */ - int has_SG; /* Support scatter transfers */ - int has_DRE; /* For unaligned transfers */ - int err; /* Channel has errors */ - struct tasklet_struct tasklet; /* Cleanup work after irq */ - u32 feature; /* IP feature */ - u32 private; /* Match info for - channel request */ - void (*start_transfer)(struct xilinx_cdma_chan *chan); - struct xilinx_cdma_config config; /* Device configuration info */ -}; - -struct xilinx_cdma_device { - void __iomem *regs; - struct device *dev; - struct dma_device common; - struct xilinx_cdma_chan *chan[XILINX_CDMA_MAX_CHANS_PER_DEVICE]; - u32 feature; - int irq; -}; - -#define to_xilinx_chan(chan) \ - container_of(chan, struct xilinx_cdma_chan, common) - -/* Required functions */ - -static int xilinx_cdma_alloc_chan_resources(struct dma_chan *dchan) -{ - struct xilinx_cdma_chan *chan = to_xilinx_chan(dchan); - - /* Has this channel already been allocated? */ - if (chan->desc_pool) - return 1; - - /* - * We need the descriptor to be aligned to 64bytes - * for meeting Xilinx DMA specification requirement. - */ - chan->desc_pool = dma_pool_create("xilinx_cdma_desc_pool", - chan->dev, - sizeof(struct xilinx_cdma_desc_sw), - __alignof__(struct xilinx_cdma_desc_sw), 0); - if (!chan->desc_pool) { - dev_err(chan->dev, - "unable to allocate channel %d descriptor pool\n", - chan->id); - return -ENOMEM; - } - - chan->completed_cookie = 1; - chan->cookie = 1; - - /* there is at least one descriptor free to be allocated */ - return 1; -} - -static void xilinx_cdma_free_desc_list(struct xilinx_cdma_chan *chan, - struct list_head *list) -{ - struct xilinx_cdma_desc_sw *desc, *_desc; - - list_for_each_entry_safe(desc, _desc, list, node) { - list_del(&desc->node); - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); - } -} - -static void xilinx_cdma_free_desc_list_reverse(struct xilinx_cdma_chan *chan, - struct list_head *list) -{ - struct xilinx_cdma_desc_sw *desc, *_desc; - - list_for_each_entry_safe_reverse(desc, _desc, list, node) { - list_del(&desc->node); - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); - } -} - -static void xilinx_cdma_free_chan_resources(struct dma_chan *dchan) -{ - struct xilinx_cdma_chan *chan = to_xilinx_chan(dchan); - unsigned long flags; - - dev_dbg(chan->dev, "Free all channel resources.\n"); - spin_lock_irqsave(&chan->lock, flags); - xilinx_cdma_free_desc_list(chan, &chan->active_list); - xilinx_cdma_free_desc_list(chan, &chan->pending_list); - spin_unlock_irqrestore(&chan->lock, flags); - - dma_pool_destroy(chan->desc_pool); - chan->desc_pool = NULL; -} - -static enum dma_status xilinx_cdma_desc_status(struct xilinx_cdma_chan *chan, - struct xilinx_cdma_desc_sw *desc) -{ - return dma_async_is_complete(desc->async_tx.cookie, - chan->completed_cookie, - chan->cookie); -} - -static void xilinx_cdma_chan_desc_cleanup(struct xilinx_cdma_chan *chan) -{ - struct xilinx_cdma_desc_sw *desc, *_desc; - unsigned long flags; - - spin_lock_irqsave(&chan->lock, flags); - - list_for_each_entry_safe(desc, _desc, &chan->active_list, node) { - dma_async_tx_callback callback; - void *callback_param; - - if (xilinx_cdma_desc_status(chan, desc) == DMA_IN_PROGRESS) - break; - - /* Remove from the list of running transactions */ - list_del(&desc->node); - - /* Run the link descriptor callback function */ - callback = desc->async_tx.callback; - callback_param = desc->async_tx.callback_param; - if (callback) { - spin_unlock_irqrestore(&chan->lock, flags); - callback(callback_param); - spin_lock_irqsave(&chan->lock, flags); - } - - /* Run any dependencies, then free the descriptor */ - dma_run_dependencies(&desc->async_tx); - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); - } - - spin_unlock_irqrestore(&chan->lock, flags); -} - -static enum dma_status xilinx_tx_status(struct dma_chan *dchan, - dma_cookie_t cookie, - struct dma_tx_state *txstate) -{ - struct xilinx_cdma_chan *chan = to_xilinx_chan(dchan); - dma_cookie_t last_used; - dma_cookie_t last_complete; - - xilinx_cdma_chan_desc_cleanup(chan); - - last_used = dchan->cookie; - last_complete = chan->completed_cookie; - - dma_set_tx_state(txstate, last_complete, last_used, 0); - - return dma_async_is_complete(cookie, last_complete, last_used); -} - -static int cdma_is_idle(struct xilinx_cdma_chan *chan) -{ - return CDMA_IN(&chan->regs->sr) & XILINX_CDMA_SR_IDLE_MASK; -} - -/* Only needed for Axi CDMA v2_00_a or earlier core */ -static void cdma_sg_toggle(struct xilinx_cdma_chan *chan) -{ - CDMA_OUT(&chan->regs->cr, - CDMA_IN(&chan->regs->cr) & ~XILINX_CDMA_CR_SGMODE_MASK); - - CDMA_OUT(&chan->regs->cr, - CDMA_IN(&chan->regs->cr) | XILINX_CDMA_CR_SGMODE_MASK); -} - -#define XILINX_CDMA_DRIVER_DEBUG 0 - -#if (XILINX_CDMA_DRIVER_DEBUG == 1) -static void desc_dump(struct xilinx_cdma_desc_hw *hw) -{ - pr_info("hw desc %x:\n", (unsigned int)hw); - pr_info("\tnext_desc %x\n", hw->next_desc); - pr_info("\tsrc_addr %x\n", hw->src_addr); - pr_info("\tdest_addr %x\n", hw->dest_addr); - pr_info("\thsize %x\n", hw->hsize); - pr_info("\tcontrol %x\n", hw->control); - pr_info("\tstatus %x\n", hw->status); -} -#endif - -static void xilinx_cdma_start_transfer(struct xilinx_cdma_chan *chan) -{ - unsigned long flags; - struct xilinx_cdma_desc_sw *desch, *desct; - struct xilinx_cdma_desc_hw *hw; - - if (chan->err) - return; - - spin_lock_irqsave(&chan->lock, flags); - - if (list_empty(&chan->pending_list)) - goto out_unlock; - - /* If hardware is busy, cannot submit */ - if (!cdma_is_idle(chan)) { - dev_dbg(chan->dev, "DMA controller still busy %x\n", - CDMA_IN(&chan->regs->sr)); - goto out_unlock; - } - - /* Enable interrupts */ - CDMA_OUT(&chan->regs->cr, - CDMA_IN(&chan->regs->cr) | XILINX_CDMA_XR_IRQ_ALL_MASK); - - desch = list_first_entry(&chan->pending_list, - struct xilinx_cdma_desc_sw, node); - - if (chan->has_SG) { - - /* If hybrid mode, append pending list to active list */ - desct = container_of(chan->pending_list.prev, - struct xilinx_cdma_desc_sw, node); - - list_splice_tail_init(&chan->pending_list, &chan->active_list); - - /* - * If hardware is idle, then all descriptors on the active list - * are done, start new transfers - */ - cdma_sg_toggle(chan); - - CDMA_OUT(&chan->regs->cdr, desch->async_tx.phys); - - /* Update tail ptr register and start the transfer */ - CDMA_OUT(&chan->regs->tdr, desct->async_tx.phys); - goto out_unlock; - } - - /* In simple mode */ - list_del(&desch->node); - list_add_tail(&desch->node, &chan->active_list); - - hw = &desch->hw; - - CDMA_OUT(&chan->regs->src, hw->src_addr); - CDMA_OUT(&chan->regs->dst, hw->dest_addr); - - /* Start the transfer */ - CDMA_OUT(&chan->regs->btt_ref, - hw->control & XILINX_CDMA_MAX_TRANS_LEN); - -out_unlock: - spin_unlock_irqrestore(&chan->lock, flags); -} - -/* - * If sg mode, link the pending list to running list; if simple mode, get the - * head of the pending list and submit it to hw - */ -static void xilinx_cdma_issue_pending(struct dma_chan *dchan) -{ - struct xilinx_cdma_chan *chan = to_xilinx_chan(dchan); - - xilinx_cdma_start_transfer(chan); -} - -/** - * xilinx_cdma_update_completed_cookie - Update the completed cookie. - * @chan : xilinx DMA channel - * - * CONTEXT: hardirq - */ -static void xilinx_cdma_update_completed_cookie(struct xilinx_cdma_chan *chan) -{ - struct xilinx_cdma_desc_sw *desc = NULL; - struct xilinx_cdma_desc_hw *hw = NULL; - unsigned long flags; - dma_cookie_t cookie = -EBUSY; - int done = 0; - - spin_lock_irqsave(&chan->lock, flags); - - if (list_empty(&chan->active_list)) { - dev_dbg(chan->dev, "no running descriptors\n"); - goto out_unlock; - } - - /* Get the last completed descriptor, update the cookie to that */ - list_for_each_entry(desc, &chan->active_list, node) { - if (chan->has_SG) { - hw = &desc->hw; - - /* If a BD has no status bits set, hw has it */ - if (!(hw->status & XILINX_CDMA_BD_STS_ALL_MASK)) { - break; - } else { - done = 1; - cookie = desc->async_tx.cookie; - } - } else { - /* In non-SG mode, all active entries are done */ - done = 1; - cookie = desc->async_tx.cookie; - } - } - - if (done) - chan->completed_cookie = cookie; - -out_unlock: - spin_unlock_irqrestore(&chan->lock, flags); -} - -/* Reset hardware */ -static int cdma_init(struct xilinx_cdma_chan *chan) -{ - int loop = XILINX_CDMA_RESET_LOOP; - u32 tmp; - - CDMA_OUT(&chan->regs->cr, - CDMA_IN(&chan->regs->cr) | XILINX_CDMA_CR_RESET_MASK); - - tmp = CDMA_IN(&chan->regs->cr) & XILINX_CDMA_CR_RESET_MASK; - - /* Wait for the hardware to finish reset */ - while (loop && tmp) { - tmp = CDMA_IN(&chan->regs->cr) & XILINX_CDMA_CR_RESET_MASK; - loop -= 1; - } - - if (!loop) { - dev_err(chan->dev, "reset timeout, cr %x, sr %x\n", - CDMA_IN(&chan->regs->cr), CDMA_IN(&chan->regs->sr)); - return 1; - } - - /* For Axi CDMA, always do sg transfers if sg mode is built in */ - if ((chan->feature & XILINX_DMA_IP_CDMA) && chan->has_SG) - CDMA_OUT(&chan->regs->cr, tmp | XILINX_CDMA_CR_SGMODE_MASK); - - return 0; -} - - -static irqreturn_t cdma_intr_handler(int irq, void *data) -{ - struct xilinx_cdma_chan *chan = data; - int update_cookie = 0; - int to_transfer = 0; - u32 stat, reg; - - reg = CDMA_IN(&chan->regs->cr); - - /* Disable intr */ - CDMA_OUT(&chan->regs->cr, - reg & ~XILINX_CDMA_XR_IRQ_ALL_MASK); - - stat = CDMA_IN(&chan->regs->sr); - if (!(stat & XILINX_CDMA_XR_IRQ_ALL_MASK)) - return IRQ_NONE; - - /* Ack the interrupts */ - CDMA_OUT(&chan->regs->sr, XILINX_CDMA_XR_IRQ_ALL_MASK); - - /* Check for only the interrupts which are enabled */ - stat &= (reg & XILINX_CDMA_XR_IRQ_ALL_MASK); - - if (stat & XILINX_CDMA_XR_IRQ_ERROR_MASK) { - dev_err(chan->dev, - "Channel %x has errors %x, cdr %x tdr %x\n", - (unsigned int)chan, - (unsigned int)CDMA_IN(&chan->regs->sr), - (unsigned int)CDMA_IN(&chan->regs->cdr), - (unsigned int)CDMA_IN(&chan->regs->tdr)); - chan->err = 1; - } - - /* - * Device takes too long to do the transfer when user requires - * responsiveness - */ - if (stat & XILINX_CDMA_XR_IRQ_DELAY_MASK) - dev_dbg(chan->dev, "Inter-packet latency too long\n"); - - if (stat & XILINX_CDMA_XR_IRQ_IOC_MASK) { - update_cookie = 1; - to_transfer = 1; - } - - if (update_cookie) - xilinx_cdma_update_completed_cookie(chan); - - if (to_transfer) - chan->start_transfer(chan); - - tasklet_schedule(&chan->tasklet); - return IRQ_HANDLED; -} - -static void cdma_do_tasklet(unsigned long data) -{ - struct xilinx_cdma_chan *chan = (struct xilinx_cdma_chan *)data; - - xilinx_cdma_chan_desc_cleanup(chan); -} - -/* Append the descriptor list to the pending list */ -static void append_desc_queue(struct xilinx_cdma_chan *chan, - struct xilinx_cdma_desc_sw *desc) -{ - struct xilinx_cdma_desc_sw *tail = container_of(chan->pending_list.prev, - struct xilinx_cdma_desc_sw, node); - struct xilinx_cdma_desc_hw *hw; - - if (list_empty(&chan->pending_list)) - goto out_splice; - - /* - * Add the hardware descriptor to the chain of hardware descriptors - * that already exists in memory. - */ - hw = &(tail->hw); - hw->next_desc = (u32)desc->async_tx.phys; - - /* - * Add the software descriptor and all children to the list - * of pending transactions - */ -out_splice: - list_splice_tail_init(&desc->tx_list, &chan->pending_list); -} - -/* - * Assign cookie to each descriptor, and append the descriptors to the pending - * list - */ -static dma_cookie_t xilinx_cdma_tx_submit(struct dma_async_tx_descriptor *tx) -{ - struct xilinx_cdma_chan *chan = to_xilinx_chan(tx->chan); - struct xilinx_cdma_desc_sw *desc = container_of(tx, - struct xilinx_cdma_desc_sw, async_tx); - struct xilinx_cdma_desc_sw *child; - unsigned long flags; - dma_cookie_t cookie = -EBUSY; - - if (chan->err) { - /* - * If reset fails, need to hard reset the system. - * Channel is no longer functional - */ - if (!cdma_init(chan)) - chan->err = 0; - else - return cookie; - } - - spin_lock_irqsave(&chan->lock, flags); - - /* - * assign cookies to all of the software descriptors - * that make up this transaction - */ - cookie = chan->cookie; - list_for_each_entry(child, &desc->tx_list, node) { - cookie++; - if (cookie < 0) - cookie = DMA_MIN_COOKIE; - - child->async_tx.cookie = cookie; - } - - chan->cookie = cookie; - - /* put this transaction onto the tail of the pending queue */ - append_desc_queue(chan, desc); - - spin_unlock_irqrestore(&chan->lock, flags); - - return cookie; -} - -static struct xilinx_cdma_desc_sw *xilinx_cdma_alloc_descriptor( - struct xilinx_cdma_chan *chan) -{ - struct xilinx_cdma_desc_sw *desc; - dma_addr_t pdesc; - - desc = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc); - if (!desc) { - dev_dbg(chan->dev, "out of memory for desc\n"); - return NULL; - } - - memset(desc, 0, sizeof(*desc)); - INIT_LIST_HEAD(&desc->tx_list); - dma_async_tx_descriptor_init(&desc->async_tx, &chan->common); - desc->async_tx.tx_submit = xilinx_cdma_tx_submit; - desc->async_tx.phys = pdesc; - - return desc; -} - -/** - * xilinx_cdma_prep_memcpy - prepare descriptors for a memcpy transaction - * @dchan: DMA channel - * @dma_dst: destination address - * @dma_src: source address - * @len: transfer length - * @flags: transfer ack flags - */ -static struct dma_async_tx_descriptor *xilinx_cdma_prep_memcpy( - struct dma_chan *dchan, dma_addr_t dma_dst, dma_addr_t dma_src, - size_t len, unsigned long flags) -{ - struct xilinx_cdma_chan *chan; - struct xilinx_cdma_desc_sw *first = NULL, *prev = NULL, *new; - struct xilinx_cdma_desc_hw *hw, *prev_hw; - size_t copy; - dma_addr_t src = dma_src; - dma_addr_t dst = dma_dst; - - if (!dchan) - return NULL; - - if (!len) - return NULL; - - chan = to_xilinx_chan(dchan); - - if (chan->err) { - - /* - * If reset fails, need to hard reset the system. - * Channel is no longer functional - */ - if (!cdma_init(chan)) - chan->err = 0; - else - return NULL; - } - - /* - * If build does not have Data Realignment Engine (DRE), - * src has to be aligned - */ - if (!chan->has_DRE) { - if ((dma_src & - (chan->feature & XILINX_CDMA_FTR_DATA_WIDTH_MASK)) || - (dma_dst & - (chan->feature & XILINX_CDMA_FTR_DATA_WIDTH_MASK))) { - - dev_err(chan->dev, - "Src/Dest address not aligned when no DRE\n"); - - return NULL; - } - } - - do { - /* Allocate descriptor from DMA pool */ - new = xilinx_cdma_alloc_descriptor(chan); - if (!new) { - dev_err(chan->dev, - "No free memory for link descriptor\n"); - goto fail; - } - - copy = min_t(size_t, len, chan->max_len); - - /* if lite build, transfer cannot cross page boundary */ - if (chan->is_lite) - copy = min(copy, (size_t)(PAGE_MASK - - (src & PAGE_MASK))); - - if (!copy) { - dev_err(chan->dev, - "Got zero transfer length for %x\n", - (unsigned int)src); - goto fail; - } - - hw = &(new->hw); - hw->control = - (hw->control & ~XILINX_CDMA_MAX_TRANS_LEN) | copy; - hw->src_addr = src; - hw->dest_addr = dst; - - if (!first) - first = new; - else { - prev_hw = &(prev->hw); - prev_hw->next_desc = new->async_tx.phys; - } - - new->async_tx.cookie = 0; - async_tx_ack(&new->async_tx); - - prev = new; - len -= copy; - src += copy; - dst += copy; - - /* Insert the descriptor to the list */ - list_add_tail(&new->node, &first->tx_list); - } while (len); - - /* Link the last BD with the first BD */ - hw->next_desc = first->async_tx.phys; - - new->async_tx.flags = flags; /* client is in control of this ack */ - new->async_tx.cookie = -EBUSY; - - return &first->async_tx; - -fail: - if (!first) - return NULL; - - xilinx_cdma_free_desc_list_reverse(chan, &first->tx_list); - return NULL; -} - -/* Run-time device configuration for Axi CDMA */ -static int xilinx_cdma_device_control(struct dma_chan *dchan, - enum dma_ctrl_cmd cmd, unsigned long arg) -{ - struct xilinx_cdma_chan *chan; - unsigned long flags; - - if (!dchan) - return -EINVAL; - - chan = to_xilinx_chan(dchan); - - if (cmd == DMA_TERMINATE_ALL) { - spin_lock_irqsave(&chan->lock, flags); - - /* Remove and free all of the descriptors in the lists */ - xilinx_cdma_free_desc_list(chan, &chan->pending_list); - xilinx_cdma_free_desc_list(chan, &chan->active_list); - - spin_unlock_irqrestore(&chan->lock, flags); - return 0; - } else if (cmd == DMA_SLAVE_CONFIG) { - /* - * Configure interrupt coalescing and delay counter - * Use value XILINX_CDMA_NO_CHANGE to signal no change - */ - struct xilinx_cdma_config *cfg = - (struct xilinx_cdma_config *)arg; - u32 reg = CDMA_IN(&chan->regs->cr); - - if (cfg->coalesc <= XILINX_CDMA_COALESCE_MAX) { - reg &= ~XILINX_CDMA_XR_COALESCE_MASK; - reg |= cfg->coalesc << XILINX_CDMA_COALESCE_SHIFT; - - chan->config.coalesc = cfg->coalesc; - } - - if (cfg->delay <= XILINX_CDMA_DELAY_MAX) { - reg &= ~XILINX_CDMA_XR_DELAY_MASK; - reg |= cfg->delay << XILINX_CDMA_DELAY_SHIFT; - chan->config.delay = cfg->delay; - } - - CDMA_OUT(&chan->regs->cr, reg); - - return 0; - } - - return -ENXIO; -} - -/* - * Logarithm function to compute alignment shift - * - * Only deals with value less than 4096. - */ -static int my_log(int value) -{ - int i = 0; - while ((1 << i) < value) { - i++; - - if (i >= 12) - return 0; - } - - return i; -} - -static void xilinx_cdma_chan_remove(struct xilinx_cdma_chan *chan) -{ - irq_dispose_mapping(chan->irq); - list_del(&chan->common.device_node); - kfree(chan); -} - -/* - * Probing channels - * - * . Get channel features from the device tree entry - * . Initialize special channel handling routines - */ -static int __devinit xilinx_cdma_chan_probe(struct xilinx_cdma_device *xdev, - struct device_node *node, u32 feature) -{ - struct xilinx_cdma_chan *chan; - int err; - int *value; - u32 width = 0, device_id = 0; - - /* alloc channel */ - chan = kzalloc(sizeof(*chan), GFP_KERNEL); - if (!chan) { - dev_err(xdev->dev, "no free memory for DMA channels!\n"); - err = -ENOMEM; - goto out_return; - } - - chan->feature = feature; - chan->is_lite = 0; - chan->has_DRE = 0; - chan->has_SG = 0; - chan->max_len = XILINX_CDMA_MAX_TRANS_LEN; - - value = (int *)of_get_property(node, "xlnx,include-dre", - NULL); - if (value) - chan->has_DRE = be32_to_cpup(value); - - value = (int *)of_get_property(node, - "xlnx,datawidth", - NULL); - if (value) { - width = be32_to_cpup(value) >> 3; /* convert bits to bytes */ - - /* If data width is greater than 8 bytes, DRE is not in hw */ - if (width > 8) - chan->has_DRE = 0; - - chan->feature |= width - 1; - } - - value = (int *)of_get_property(node, "xlnx,device-id", NULL); - if (value) - device_id = be32_to_cpup(value); - - chan->direction = DMA_MEM_TO_MEM; - chan->start_transfer = xilinx_cdma_start_transfer; - - chan->has_SG = (xdev->feature & XILINX_CDMA_FTR_HAS_SG) >> - XILINX_CDMA_FTR_HAS_SG_SHIFT; - - value = (int *)of_get_property(node, - "xlnx,lite-mode", NULL); - if (value) { - if (be32_to_cpup(value) == 1) { - chan->is_lite = 1; - value = (int *)of_get_property(node, - "xlnx,max-burst-len", NULL); - if (value) { - if (!width) { - dev_err(xdev->dev, - "Lite mode w/o data width property\n"); - goto out_free_chan; - } - chan->max_len = width * - be32_to_cpup(value); - } - } - } - - chan->regs = (struct xcdma_regs *)xdev->regs; - chan->id = 0; - - /* - * Used by dmatest channel matching in slave transfers - * Can change it to be a structure to have more matching information - */ - chan->private = (chan->direction & 0xFF) | - (chan->feature & XILINX_DMA_IP_MASK) | - (device_id << XILINX_CDMA_DEVICE_ID_SHIFT); - chan->common.private = (void *)&(chan->private); - - if (!chan->has_DRE) - xdev->common.copy_align = my_log(width); - - chan->dev = xdev->dev; - xdev->chan[chan->id] = chan; - - tasklet_init(&chan->tasklet, cdma_do_tasklet, (unsigned long)chan); - - /* Initialize the channel */ - if (cdma_init(chan)) { - dev_err(xdev->dev, "Reset channel failed\n"); - goto out_free_chan; - } - - spin_lock_init(&chan->lock); - INIT_LIST_HEAD(&chan->pending_list); - INIT_LIST_HEAD(&chan->active_list); - - chan->common.device = &xdev->common; - - /* Find the IRQ line, if it exists in the device tree */ - chan->irq = irq_of_parse_and_map(node, 0); - err = request_irq(chan->irq, cdma_intr_handler, IRQF_SHARED, - "xilinx-cdma-controller", chan); - if (err) { - dev_err(xdev->dev, "unable to request IRQ\n"); - goto out_free_irq; - } - - /* Add the channel to DMA device channel list */ - list_add_tail(&chan->common.device_node, &xdev->common.channels); - xdev->common.chancnt++; - - return 0; - -out_free_irq: - irq_dispose_mapping(chan->irq); -out_free_chan: - kfree(chan); -out_return: - return err; -} - -static int __devinit xilinx_cdma_of_probe(struct platform_device *op) -{ - struct xilinx_cdma_device *xdev; - struct device_node *child, *node; - int err; - int *value; - - dev_info(&op->dev, "Probing xilinx axi cdma engine\n"); - - xdev = kzalloc(sizeof(struct xilinx_cdma_device), GFP_KERNEL); - if (!xdev) { - dev_err(&op->dev, "Not enough memory for device\n"); - err = -ENOMEM; - goto out_return; - } - - xdev->dev = &(op->dev); - INIT_LIST_HEAD(&xdev->common.channels); - - node = op->dev.of_node; - xdev->feature = 0; - - /* iomap registers */ - xdev->regs = of_iomap(node, 0); - if (!xdev->regs) { - dev_err(&op->dev, "unable to iomap registers\n"); - err = -ENOMEM; - goto out_free_xdev; - } - - /* Axi CDMA only does memcpy */ - if (of_device_is_compatible(node, "xlnx,axi-cdma")) { - xdev->feature |= XILINX_DMA_IP_CDMA; - - value = (int *)of_get_property(node, "xlnx,include-sg", - NULL); - if (value) { - if (be32_to_cpup(value) == 1) - xdev->feature |= XILINX_CDMA_FTR_HAS_SG; - } - - dma_cap_set(DMA_MEMCPY, xdev->common.cap_mask); - xdev->common.device_prep_dma_memcpy = xilinx_cdma_prep_memcpy; - xdev->common.device_control = xilinx_cdma_device_control; - xdev->common.device_issue_pending = xilinx_cdma_issue_pending; - } - - xdev->common.device_alloc_chan_resources = - xilinx_cdma_alloc_chan_resources; - xdev->common.device_free_chan_resources = - xilinx_cdma_free_chan_resources; - xdev->common.device_tx_status = xilinx_tx_status; - xdev->common.dev = &op->dev; - - dev_set_drvdata(&op->dev, xdev); - - for_each_child_of_node(node, child) { - xilinx_cdma_chan_probe(xdev, child, xdev->feature); - } - - dma_async_device_register(&xdev->common); - - return 0; - -out_free_xdev: - kfree(xdev); - -out_return: - return err; -} - -static int __devexit xilinx_cdma_of_remove(struct platform_device *op) -{ - struct xilinx_cdma_device *xdev; - int i; - - xdev = dev_get_drvdata(&op->dev); - dma_async_device_unregister(&xdev->common); - - for (i = 0; i < XILINX_CDMA_MAX_CHANS_PER_DEVICE; i++) { - if (xdev->chan[i]) - xilinx_cdma_chan_remove(xdev->chan[i]); - } - - iounmap(xdev->regs); - dev_set_drvdata(&op->dev, NULL); - kfree(xdev); - - return 0; -} - -static const struct of_device_id xilinx_cdma_of_ids[] = { - { .compatible = "xlnx,axi-cdma",}, - {} -}; - -static struct platform_driver xilinx_cdma_of_driver = { - .driver = { - .name = "xilinx-cdma", - .owner = THIS_MODULE, - .of_match_table = xilinx_cdma_of_ids, - }, - .probe = xilinx_cdma_of_probe, - .remove = __devexit_p(xilinx_cdma_of_remove), -}; - -module_platform_driver(xilinx_cdma_of_driver); - -MODULE_AUTHOR("Xilinx, Inc."); -MODULE_DESCRIPTION("Xilinx CDMA driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/dma/xilinx/xilinx_axidma.c b/drivers/dma/xilinx/xilinx_axidma.c deleted file mode 100644 index 65a16edf94426..0000000000000 --- a/drivers/dma/xilinx/xilinx_axidma.c +++ /dev/null @@ -1,1201 +0,0 @@ -/* - * Xilinx AXI DMA Engine support - * - * Copyright (C) 2012 Xilinx, Inc. All rights reserved. - * - * Based on the Freescale DMA driver. - * - * Description: - * . Axi DMA engine, it does transfers between memory and device. It can be - * configured to have one channel or two channels. If configured as two - * channels, one is to transmit to a device and another is to receive from - * a device. - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Hw specific definitions */ -#define XILINX_DMA_MAX_CHANS_PER_DEVICE 0x2 -#define XILINX_DMA_MAX_TRANS_LEN 0x7FFFFF - -/* General register bits definitions */ -#define XILINX_DMA_CR_RESET_MASK 0x00000004 - /* Reset DMA engine */ -#define XILINX_DMA_CR_RUNSTOP_MASK 0x00000001 - /* Start/stop DMA engine */ - -#define XILINX_DMA_SR_HALTED_MASK 0x00000001 - /* DMA channel halted */ -#define XILINX_DMA_SR_IDLE_MASK 0x00000002 - /* DMA channel idle */ - -#define XILINX_DMA_SR_ERR_INTERNAL_MASK 0x00000010 - /* Datamover internal err */ -#define XILINX_DMA_SR_ERR_SLAVE_MASK 0x00000020 - /* Datamover slave err */ -#define XILINX_DMA_SR_ERR_DECODE_MASK 0x00000040 - /* Datamover decode err */ -#define XILINX_DMA_SR_ERR_SG_INT_MASK 0x00000100 - /* SG internal err */ -#define XILINX_DMA_SR_ERR_SG_SLV_MASK 0x00000200 - /* SG slave err */ -#define XILINX_DMA_SR_ERR_SG_DEC_MASK 0x00000400 - /* SG decode err */ -#define XILINX_DMA_SR_ERR_ALL_MASK 0x00000770 - /* All errors */ - -#define XILINX_DMA_XR_IRQ_IOC_MASK 0x00001000 - /* Completion interrupt */ -#define XILINX_DMA_XR_IRQ_DELAY_MASK 0x00002000 - /* Delay interrupt */ -#define XILINX_DMA_XR_IRQ_ERROR_MASK 0x00004000 - /* Error interrupt */ -#define XILINX_DMA_XR_IRQ_ALL_MASK 0x00007000 - /* All interrupts */ - -#define XILINX_DMA_XR_DELAY_MASK 0xFF000000 - /* Delay timeout counter */ -#define XILINX_DMA_XR_COALESCE_MASK 0x00FF0000 - /* Coalesce counter */ - -#define XILINX_DMA_IRQ_SHIFT 12 -#define XILINX_DMA_DELAY_SHIFT 24 -#define XILINX_DMA_COALESCE_SHIFT 16 - -#define XILINX_DMA_DELAY_MAX 0xFF - /* Maximum delay counter value */ -#define XILINX_DMA_COALESCE_MAX 0xFF - /* Maximum coalescing counter value */ - -#define XILINX_DMA_RX_CHANNEL_OFFSET 0x30 - -/* BD definitions for AXI Dma */ -#define XILINX_DMA_BD_STS_COMPL_MASK 0x80000000 -#define XILINX_DMA_BD_STS_ERR_MASK 0x70000000 -#define XILINX_DMA_BD_STS_ALL_MASK 0xF0000000 - -/* Axi DMA BD special bits definitions */ -#define XILINX_DMA_BD_SOP 0x08000000 /* Start of packet bit */ -#define XILINX_DMA_BD_EOP 0x04000000 /* End of packet bit */ - -/* Feature encodings */ -#define XILINX_DMA_FTR_DATA_WIDTH_MASK 0x000000FF - /* Data width mask, 1024 */ -#define XILINX_DMA_FTR_HAS_SG 0x00000100 - /* Has SG */ -#define XILINX_DMA_FTR_HAS_SG_SHIFT 8 - /* Has SG shift */ -#define XILINX_DMA_FTR_STSCNTRL_STRM 0x00010000 - /* Optional feature for dma */ - -/* Delay loop counter to prevent hardware failure */ -#define XILINX_DMA_RESET_LOOP 1000000 -#define XILINX_DMA_HALT_LOOP 1000000 - -/* Device Id in the private structure */ -#define XILINX_DMA_DEVICE_ID_SHIFT 28 - -/* IO accessors */ -#define DMA_OUT(addr, val) (iowrite32(val, addr)) -#define DMA_IN(addr) (ioread32(addr)) - -#ifdef CONFIG_XILINX_DMATEST -#define TEST_DMA_WITH_LOOPBACK -#endif - -/* Hardware descriptor */ -struct xilinx_dma_desc_hw { - u32 next_desc; /* 0x00 */ - u32 pad1; /* 0x04 */ - u32 buf_addr; /* 0x08 */ - u32 pad2; /* 0x0C */ - u32 pad3; /* 0x10 */ - u32 pad4; /* 0x14 */ - u32 control; /* 0x18 */ - u32 status; /* 0x1C */ - u32 app_0; /* 0x20 */ - u32 app_1; /* 0x24 */ - u32 app_2; /* 0x28 */ - u32 app_3; /* 0x2C */ - u32 app_4; /* 0x30 */ -} __aligned(64); - -/* Software descriptor */ -struct xilinx_dma_desc_sw { - struct xilinx_dma_desc_hw hw; - struct list_head node; - struct list_head tx_list; - struct dma_async_tx_descriptor async_tx; -} __aligned(64); - -/* AXI DMA Registers Structure */ -struct xdma_regs { - u32 cr; /* 0x00 Control Register */ - u32 sr; /* 0x04 Status Register */ - u32 cdr; /* 0x08 Current Descriptor Register */ - u32 pad1; - u32 tdr; /* 0x10 Tail Descriptor Register */ - u32 pad2; - u32 src; /* 0x18 Source Address Register (sg = 0) */ - u32 pad3; - u32 dst; /* 0x20 Destination Address Register (sg = 0) */ - u32 pad4; - u32 btt_ref; /* 0x28 Bytes To Transfer (sg = 0) */ -}; - -/* Per DMA specific operations should be embedded in the channel structure */ -struct xilinx_dma_chan { - struct xdma_regs __iomem *regs; /* Control status registers */ - dma_cookie_t completed_cookie; /* The maximum cookie completed */ - dma_cookie_t cookie; /* The current cookie */ - spinlock_t lock; /* Descriptor operation lock */ - bool sg_waiting; /* Scatter gather transfer waiting */ - struct list_head active_list; /* Active descriptors */ - struct list_head pending_list; /* Descriptors waiting */ - struct dma_chan common; /* DMA common channel */ - struct dma_pool *desc_pool; /* Descriptors pool */ - struct device *dev; /* The dma device */ - int irq; /* Channel IRQ */ - int id; /* Channel ID */ - enum dma_transfer_direction direction; - /* Transfer direction */ - int max_len; /* Maximum data len per transfer */ - int is_lite; /* Whether is light build */ - int has_SG; /* Support scatter transfers */ - int has_DRE; /* Support unaligned transfers */ - int err; /* Channel has errors */ - struct tasklet_struct tasklet; /* Cleanup work after irq */ - u32 feature; /* IP feature */ - u32 private; /* Match info for channel request */ - void (*start_transfer)(struct xilinx_dma_chan *chan); - struct xilinx_dma_config config; - /* Device configuration info */ -}; - -/* DMA Device Structure */ -struct xilinx_dma_device { - void __iomem *regs; - struct device *dev; - struct dma_device common; - struct xilinx_dma_chan *chan[XILINX_DMA_MAX_CHANS_PER_DEVICE]; - u32 feature; - int irq; -}; - -#define to_xilinx_chan(chan) \ - container_of(chan, struct xilinx_dma_chan, common) - -/* Required functions */ - -static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan) -{ - struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); - - /* Has this channel already been allocated? */ - if (chan->desc_pool) - return 1; - - /* - * We need the descriptor to be aligned to 64bytes - * for meeting Xilinx DMA specification requirement. - */ - chan->desc_pool = dma_pool_create("xilinx_dma_desc_pool", - chan->dev, - sizeof(struct xilinx_dma_desc_sw), - __alignof__(struct xilinx_dma_desc_sw), 0); - if (!chan->desc_pool) { - dev_err(chan->dev, - "unable to allocate channel %d descriptor pool\n", - chan->id); - return -ENOMEM; - } - - chan->completed_cookie = 1; - chan->cookie = 1; - - /* There is at least one descriptor free to be allocated */ - return 1; -} - -static void xilinx_dma_free_desc_list(struct xilinx_dma_chan *chan, - struct list_head *list) -{ - struct xilinx_dma_desc_sw *desc, *_desc; - - list_for_each_entry_safe(desc, _desc, list, node) { - list_del(&desc->node); - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); - } -} - -static void xilinx_dma_free_desc_list_reverse(struct xilinx_dma_chan *chan, - struct list_head *list) -{ - struct xilinx_dma_desc_sw *desc, *_desc; - - list_for_each_entry_safe_reverse(desc, _desc, list, node) { - list_del(&desc->node); - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); - } -} - -static void xilinx_dma_free_chan_resources(struct dma_chan *dchan) -{ - struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); - unsigned long flags; - - dev_dbg(chan->dev, "Free all channel resources.\n"); - spin_lock_irqsave(&chan->lock, flags); - xilinx_dma_free_desc_list(chan, &chan->active_list); - xilinx_dma_free_desc_list(chan, &chan->pending_list); - spin_unlock_irqrestore(&chan->lock, flags); - - dma_pool_destroy(chan->desc_pool); - chan->desc_pool = NULL; -} - -static enum dma_status xilinx_dma_desc_status(struct xilinx_dma_chan *chan, - struct xilinx_dma_desc_sw *desc) -{ - return dma_async_is_complete(desc->async_tx.cookie, - chan->completed_cookie, - chan->cookie); -} - -static void xilinx_chan_desc_cleanup(struct xilinx_dma_chan *chan) -{ - struct xilinx_dma_desc_sw *desc, *_desc; - unsigned long flags; - - spin_lock_irqsave(&chan->lock, flags); - - list_for_each_entry_safe(desc, _desc, &chan->active_list, node) { - dma_async_tx_callback callback; - void *callback_param; - - if (xilinx_dma_desc_status(chan, desc) == DMA_IN_PROGRESS) - break; - - /* Remove from the list of running transactions */ - list_del(&desc->node); - - /* Run the link descriptor callback function */ - callback = desc->async_tx.callback; - callback_param = desc->async_tx.callback_param; - if (callback) { - spin_unlock_irqrestore(&chan->lock, flags); - callback(callback_param); - spin_lock_irqsave(&chan->lock, flags); - } - - /* Run any dependencies, then free the descriptor */ - dma_run_dependencies(&desc->async_tx); - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); - } - - spin_unlock_irqrestore(&chan->lock, flags); -} - -static enum dma_status xilinx_tx_status(struct dma_chan *dchan, - dma_cookie_t cookie, - struct dma_tx_state *txstate) -{ - struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); - dma_cookie_t last_used; - dma_cookie_t last_complete; - - xilinx_chan_desc_cleanup(chan); - - last_used = dchan->cookie; - last_complete = chan->completed_cookie; - - dma_set_tx_state(txstate, last_complete, last_used, 0); - - return dma_async_is_complete(cookie, last_complete, last_used); -} - -static int dma_is_running(struct xilinx_dma_chan *chan) -{ - return !(DMA_IN(&chan->regs->sr) & XILINX_DMA_SR_HALTED_MASK) && - (DMA_IN(&chan->regs->cr) & XILINX_DMA_CR_RUNSTOP_MASK); -} - -static int dma_is_idle(struct xilinx_dma_chan *chan) -{ - return DMA_IN(&chan->regs->sr) & XILINX_DMA_SR_IDLE_MASK; -} - -#define XILINX_DMA_DRIVER_DEBUG 0 - -#if (XILINX_DMA_DRIVER_DEBUG == 1) -static void desc_dump(struct xilinx_dma_desc_hw *hw) -{ - pr_info("hw desc %x:\n", (unsigned int)hw); - pr_info("\tnext_desc %x\n", hw->next_desc); - pr_info("\tbuf_addr %x\n", hw->buf_addr); - pr_info("\taddr_vsize %x\n", hw->addr_vsize); - pr_info("\thsize %x\n", hw->hsize); - pr_info("\tcontrol %x\n", hw->control); - pr_info("\tstatus %x\n", hw->status); -} -#endif - -/* Stop the hardware, the ongoing transfer will be finished */ -static void dma_halt(struct xilinx_dma_chan *chan) -{ - int loop = XILINX_DMA_HALT_LOOP; - - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) & ~XILINX_DMA_CR_RUNSTOP_MASK); - - /* Wait for the hardware to halt */ - while (loop) { - if (!(DMA_IN(&chan->regs->cr) & XILINX_DMA_CR_RUNSTOP_MASK)) - break; - - loop -= 1; - } - - if (!loop) { - pr_debug("Cannot stop channel %x: %x\n", - (unsigned int)chan, - (unsigned int)DMA_IN(&chan->regs->cr)); - chan->err = 1; - } - - return; -} - -/* Start the hardware. Transfers are not started yet */ -static void dma_start(struct xilinx_dma_chan *chan) -{ - int loop = XILINX_DMA_HALT_LOOP; - - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) | XILINX_DMA_CR_RUNSTOP_MASK); - - /* Wait for the hardware to start */ - while (loop) { - if (DMA_IN(&chan->regs->cr) & XILINX_DMA_CR_RUNSTOP_MASK) - break; - - loop -= 1; - } - - if (!loop) { - pr_debug("Cannot start channel %x: %x\n", - (unsigned int)chan, - (unsigned int)DMA_IN(&chan->regs->cr)); - - chan->err = 1; - } - - return; -} - - -static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan) -{ - unsigned long flags; - struct xilinx_dma_desc_sw *desch, *desct; - struct xilinx_dma_desc_hw *hw; - - if (chan->err) - return; - - spin_lock_irqsave(&chan->lock, flags); - - if (list_empty(&chan->pending_list)) - goto out_unlock; - - /* If hardware is busy, cannot submit */ - if (dma_is_running(chan) && !dma_is_idle(chan)) { - dev_dbg(chan->dev, "DMA controller still busy\n"); - goto out_unlock; - } - - /* - * If hardware is idle, then all descriptors on active list are - * done, start new transfers - */ - dma_halt(chan); - - if (chan->err) - goto out_unlock; - - if (chan->has_SG) { - desch = list_first_entry(&chan->pending_list, - struct xilinx_dma_desc_sw, node); - - desct = container_of(chan->pending_list.prev, - struct xilinx_dma_desc_sw, node); - - DMA_OUT(&chan->regs->cdr, desch->async_tx.phys); - - dma_start(chan); - - if (chan->err) - goto out_unlock; - list_splice_tail_init(&chan->pending_list, &chan->active_list); - - /* Enable interrupts */ - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) | XILINX_DMA_XR_IRQ_ALL_MASK); - - /* Update tail ptr register and start the transfer */ - DMA_OUT(&chan->regs->tdr, desct->async_tx.phys); - goto out_unlock; - } - - /* In simple mode */ - dma_halt(chan); - - if (chan->err) - goto out_unlock; - - pr_info("xilinx_dma_start_transfer::simple DMA mode\n"); - - desch = list_first_entry(&chan->pending_list, - struct xilinx_dma_desc_sw, node); - - list_del(&desch->node); - list_add_tail(&desch->node, &chan->active_list); - - dma_start(chan); - - if (chan->err) - goto out_unlock; - - hw = &desch->hw; - - /* Enable interrupts */ - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) | XILINX_DMA_XR_IRQ_ALL_MASK); - - DMA_OUT(&chan->regs->src, hw->buf_addr); - - /* Start the transfer */ - DMA_OUT(&chan->regs->btt_ref, - hw->control & XILINX_DMA_MAX_TRANS_LEN); - -out_unlock: - spin_unlock_irqrestore(&chan->lock, flags); -} - -static void xilinx_dma_issue_pending(struct dma_chan *dchan) -{ - struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); - - xilinx_dma_start_transfer(chan); -} - -/** - * xilinx_dma_update_completed_cookie - Update the completed cookie. - * @chan : xilinx DMA channel - * - * CONTEXT: hardirq - */ -static void xilinx_dma_update_completed_cookie(struct xilinx_dma_chan *chan) -{ - struct xilinx_dma_desc_sw *desc = NULL; - struct xilinx_dma_desc_hw *hw = NULL; - unsigned long flags; - dma_cookie_t cookie = -EBUSY; - int done = 0; - - spin_lock_irqsave(&chan->lock, flags); - - if (list_empty(&chan->active_list)) { - dev_dbg(chan->dev, "no running descriptors\n"); - goto out_unlock; - } - - /* Get the last completed descriptor, update the cookie to that */ - list_for_each_entry(desc, &chan->active_list, node) { - if (chan->has_SG) { - hw = &desc->hw; - - /* If a BD has no status bits set, hw has it */ - if (!(hw->status & XILINX_DMA_BD_STS_ALL_MASK)) { - break; - } else { - done = 1; - cookie = desc->async_tx.cookie; - } - } else { - /* In non-SG mode, all active entries are done */ - done = 1; - cookie = desc->async_tx.cookie; - } - } - - if (done) - chan->completed_cookie = cookie; - -out_unlock: - spin_unlock_irqrestore(&chan->lock, flags); -} - -/* Reset hardware */ -static int dma_init(struct xilinx_dma_chan *chan) -{ - int loop = XILINX_DMA_RESET_LOOP; - u32 tmp; - - DMA_OUT(&chan->regs->cr, - DMA_IN(&chan->regs->cr) | XILINX_DMA_CR_RESET_MASK); - - tmp = DMA_IN(&chan->regs->cr) & XILINX_DMA_CR_RESET_MASK; - - /* Wait for the hardware to finish reset */ - while (loop && tmp) { - tmp = DMA_IN(&chan->regs->cr) & XILINX_DMA_CR_RESET_MASK; - loop -= 1; - } - - if (!loop) { - dev_err(chan->dev, "reset timeout, cr %x, sr %x\n", - DMA_IN(&chan->regs->cr), DMA_IN(&chan->regs->sr)); - return 1; - } - - return 0; -} - - -static irqreturn_t dma_intr_handler(int irq, void *data) -{ - struct xilinx_dma_chan *chan = data; - int update_cookie = 0; - int to_transfer = 0; - u32 stat, reg; - - reg = DMA_IN(&chan->regs->cr); - - /* Disable intr */ - DMA_OUT(&chan->regs->cr, - reg & ~XILINX_DMA_XR_IRQ_ALL_MASK); - - stat = DMA_IN(&chan->regs->sr); - if (!(stat & XILINX_DMA_XR_IRQ_ALL_MASK)) - return IRQ_NONE; - - /* Ack the interrupts */ - DMA_OUT(&chan->regs->sr, XILINX_DMA_XR_IRQ_ALL_MASK); - - /* Check for only the interrupts which are enabled */ - stat &= (reg & XILINX_DMA_XR_IRQ_ALL_MASK); - - if (stat & XILINX_DMA_XR_IRQ_ERROR_MASK) { - dev_err(chan->dev, - "Channel %x has errors %x, cdr %x tdr %x\n", - (unsigned int)chan, - (unsigned int)DMA_IN(&chan->regs->sr), - (unsigned int)DMA_IN(&chan->regs->cdr), - (unsigned int)DMA_IN(&chan->regs->tdr)); - chan->err = 1; - } - - /* - * Device takes too long to do the transfer when user requires - * responsiveness - */ - if (stat & XILINX_DMA_XR_IRQ_DELAY_MASK) - dev_dbg(chan->dev, "Inter-packet latency too long\n"); - - if (stat & XILINX_DMA_XR_IRQ_IOC_MASK) { - update_cookie = 1; - to_transfer = 1; - } - - if (update_cookie) - xilinx_dma_update_completed_cookie(chan); - - if (to_transfer) - chan->start_transfer(chan); - - tasklet_schedule(&chan->tasklet); - return IRQ_HANDLED; -} - -static void dma_do_tasklet(unsigned long data) -{ - struct xilinx_dma_chan *chan = (struct xilinx_dma_chan *)data; - - xilinx_chan_desc_cleanup(chan); -} - -/* Append the descriptor list to the pending list */ -static void append_desc_queue(struct xilinx_dma_chan *chan, - struct xilinx_dma_desc_sw *desc) -{ - struct xilinx_dma_desc_sw *tail = - container_of(chan->pending_list.prev, - struct xilinx_dma_desc_sw, node); - struct xilinx_dma_desc_hw *hw; - - if (list_empty(&chan->pending_list)) - goto out_splice; - - /* - * Add the hardware descriptor to the chain of hardware descriptors - * that already exists in memory. - */ - hw = &(tail->hw); - hw->next_desc = (u32)desc->async_tx.phys; - - /* - * Add the software descriptor and all children to the list - * of pending transactions - */ -out_splice: - list_splice_tail_init(&desc->tx_list, &chan->pending_list); -} - -/* - * Assign cookie to each descriptor, and append the descriptors to the pending - * list - */ -static dma_cookie_t xilinx_dma_tx_submit(struct dma_async_tx_descriptor *tx) -{ - struct xilinx_dma_chan *chan = to_xilinx_chan(tx->chan); - struct xilinx_dma_desc_sw *desc = container_of(tx, - struct xilinx_dma_desc_sw, async_tx); - struct xilinx_dma_desc_sw *child; - unsigned long flags; - dma_cookie_t cookie = -EBUSY; - - if (chan->err) { - /* - * If reset fails, need to hard reset the system. - * Channel is no longer functional - */ - if (!dma_init(chan)) - chan->err = 0; - else - return cookie; - } - - spin_lock_irqsave(&chan->lock, flags); - - /* - * Assign cookies to all of the software descriptors - * that make up this transaction - */ - cookie = chan->cookie; - list_for_each_entry(child, &desc->tx_list, node) { - cookie++; - if (cookie < 0) - cookie = DMA_MIN_COOKIE; - - child->async_tx.cookie = cookie; - } - - chan->cookie = cookie; - - /* Put this transaction onto the tail of the pending queue */ - append_desc_queue(chan, desc); - - spin_unlock_irqrestore(&chan->lock, flags); - - return cookie; -} - -static struct xilinx_dma_desc_sw *xilinx_dma_alloc_descriptor( - struct xilinx_dma_chan *chan) -{ - struct xilinx_dma_desc_sw *desc; - dma_addr_t pdesc; - - desc = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc); - if (!desc) { - dev_dbg(chan->dev, "out of memory for desc\n"); - return NULL; - } - - memset(desc, 0, sizeof(*desc)); - INIT_LIST_HEAD(&desc->tx_list); - dma_async_tx_descriptor_init(&desc->async_tx, &chan->common); - desc->async_tx.tx_submit = xilinx_dma_tx_submit; - desc->async_tx.phys = pdesc; - - return desc; -} - -/** - * xilinx_dma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction - * @chan: DMA channel - * @sgl: scatterlist to transfer to/from - * @sg_len: number of entries in @scatterlist - * @direction: DMA direction - * @flags: transfer ack flags - */ -static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg( - struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_transfer_direction direction, unsigned long flags, - void *context) -{ - struct xilinx_dma_chan *chan; - struct xilinx_dma_desc_sw *first = NULL, *prev = NULL, *new = NULL; - struct xilinx_dma_desc_hw *hw = NULL, *prev_hw = NULL; - - size_t copy; - - int i; - struct scatterlist *sg; - size_t sg_used; - dma_addr_t dma_src; - -#ifdef TEST_DMA_WITH_LOOPBACK - int total_len; -#endif - if (!dchan) - return NULL; - - chan = to_xilinx_chan(dchan); - - if (chan->direction != direction) - return NULL; - -#ifdef TEST_DMA_WITH_LOOPBACK - total_len = 0; - - for_each_sg(sgl, sg, sg_len, i) { - total_len += sg_dma_len(sg); - } -#endif - /* Build transactions using information in the scatter gather list */ - for_each_sg(sgl, sg, sg_len, i) { - sg_used = 0; - - /* Loop until the entire scatterlist entry is used */ - while (sg_used < sg_dma_len(sg)) { - - /* Allocate the link descriptor from DMA pool */ - new = xilinx_dma_alloc_descriptor(chan); - if (!new) { - dev_err(chan->dev, - "No free memory for link descriptor\n"); - goto fail; - } - - /* - * Calculate the maximum number of bytes to transfer, - * making sure it is less than the hw limit - */ - copy = min((size_t)(sg_dma_len(sg) - sg_used), - (size_t)chan->max_len); - hw = &(new->hw); - - dma_src = sg_dma_address(sg) + sg_used; - - hw->buf_addr = dma_src; - - /* Fill in the descriptor */ - hw->control = copy; - - /* - * If this is not the first descriptor, chain the - * current descriptor after the previous descriptor - * - * For the first DMA_MEM_TO_DEV transfer, set SOP - */ - if (!first) { - first = new; - if (direction == DMA_MEM_TO_DEV) { - hw->control |= XILINX_DMA_BD_SOP; -#ifdef TEST_DMA_WITH_LOOPBACK - hw->app_4 = total_len; -#endif - } - } else { - prev_hw = &(prev->hw); - prev_hw->next_desc = new->async_tx.phys; - } - - new->async_tx.cookie = 0; - async_tx_ack(&new->async_tx); - - prev = new; - sg_used += copy; - - /* Insert the link descriptor into the LD ring */ - list_add_tail(&new->node, &first->tx_list); - } - } - - /* Link the last BD with the first BD */ - hw->next_desc = first->async_tx.phys; - - if (direction == DMA_MEM_TO_DEV) - hw->control |= XILINX_DMA_BD_EOP; - - /* All scatter gather list entries has length == 0 */ - if (!first || !new) - return NULL; - - new->async_tx.flags = flags; - new->async_tx.cookie = -EBUSY; - - /* Set EOP to the last link descriptor of new list */ - hw->control |= XILINX_DMA_BD_EOP; - - return &first->async_tx; - -fail: - /* - * If first was not set, then we failed to allocate the very first - * descriptor, and we're done - */ - if (!first) - return NULL; - - /* - * First is set, so all of the descriptors we allocated have been added - * to first->tx_list, INCLUDING "first" itself. Therefore we - * must traverse the list backwards freeing each descriptor in turn - */ - xilinx_dma_free_desc_list_reverse(chan, &first->tx_list); - - return NULL; -} - -/* Run-time device configuration for Axi DMA */ -static int xilinx_dma_device_control(struct dma_chan *dchan, - enum dma_ctrl_cmd cmd, unsigned long arg) -{ - struct xilinx_dma_chan *chan; - unsigned long flags; - - if (!dchan) - return -EINVAL; - - chan = to_xilinx_chan(dchan); - - if (cmd == DMA_TERMINATE_ALL) { - /* Halt the DMA engine */ - dma_halt(chan); - - spin_lock_irqsave(&chan->lock, flags); - - /* Remove and free all of the descriptors in the lists */ - xilinx_dma_free_desc_list(chan, &chan->pending_list); - xilinx_dma_free_desc_list(chan, &chan->active_list); - - spin_unlock_irqrestore(&chan->lock, flags); - return 0; - } else if (cmd == DMA_SLAVE_CONFIG) { - /* - * Configure interrupt coalescing and delay counter - * Use value XILINX_DMA_NO_CHANGE to signal no change - */ - struct xilinx_dma_config *cfg = (struct xilinx_dma_config *)arg; - u32 reg = DMA_IN(&chan->regs->cr); - - if (cfg->coalesc <= XILINX_DMA_COALESCE_MAX) { - reg &= ~XILINX_DMA_XR_COALESCE_MASK; - reg |= cfg->coalesc << XILINX_DMA_COALESCE_SHIFT; - - chan->config.coalesc = cfg->coalesc; - } - - if (cfg->delay <= XILINX_DMA_DELAY_MAX) { - reg &= ~XILINX_DMA_XR_DELAY_MASK; - reg |= cfg->delay << XILINX_DMA_DELAY_SHIFT; - chan->config.delay = cfg->delay; - } - - DMA_OUT(&chan->regs->cr, reg); - - return 0; - } else - return -ENXIO; -} - -/* - * Logarithm function to compute alignment shift - * - * Only deals with value less than 4096. - */ -static int my_log(int value) -{ - int i = 0; - while ((1 << i) < value) { - i++; - - if (i >= 12) - return 0; - } - - return i; -} - -static void xilinx_dma_chan_remove(struct xilinx_dma_chan *chan) -{ - irq_dispose_mapping(chan->irq); - list_del(&chan->common.device_node); - kfree(chan); -} - -/* - * Probing channels - * - * . Get channel features from the device tree entry - * . Initialize special channel handling routines - */ -static int __devinit xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, - struct device_node *node, u32 feature) -{ - struct xilinx_dma_chan *chan; - int err; - int *value; - u32 width = 0, device_id = 0; - - /* alloc channel */ - chan = kzalloc(sizeof(*chan), GFP_KERNEL); - if (!chan) { - dev_err(xdev->dev, "no free memory for DMA channels!\n"); - err = -ENOMEM; - goto out_return; - } - - chan->feature = feature; - chan->is_lite = 0; - chan->has_DRE = 0; - chan->has_SG = 0; - chan->max_len = XILINX_DMA_MAX_TRANS_LEN; - - value = (int *)of_get_property(node, "xlnx,include-dre", - NULL); - if (value) - chan->has_DRE = be32_to_cpup(value); - - value = (int *)of_get_property(node, - "xlnx,datawidth", - NULL); - if (value) { - width = be32_to_cpup(value) >> 3; /* convert bits to bytes */ - - /* If data width is greater than 8 bytes, DRE is not in hw */ - if (width > 8) - chan->has_DRE = 0; - - chan->feature |= width - 1; - } - - value = (int *)of_get_property(node, "xlnx,device-id", NULL); - if (value) - device_id = be32_to_cpup(value); - - if (feature & XILINX_DMA_IP_DMA) { - chan->has_SG = (xdev->feature & XILINX_DMA_FTR_HAS_SG) >> - XILINX_DMA_FTR_HAS_SG_SHIFT; - - chan->start_transfer = xilinx_dma_start_transfer; - - if (of_device_is_compatible(node, - "xlnx,axi-dma-mm2s-channel")) - chan->direction = DMA_MEM_TO_DEV; - - if (of_device_is_compatible(node, - "xlnx,axi-dma-s2mm-channel")) - chan->direction = DMA_DEV_TO_MEM; - - } - - chan->regs = (struct xdma_regs *)xdev->regs; - chan->id = 0; - - if (chan->direction == DMA_DEV_TO_MEM) { - chan->regs = (struct xdma_regs *)((u32)xdev->regs + - XILINX_DMA_RX_CHANNEL_OFFSET); - chan->id = 1; - } - - /* - * Used by dmatest channel matching in slave transfers - * Can change it to be a structure to have more matching information - */ - chan->private = (chan->direction & 0xFF) | - (chan->feature & XILINX_DMA_IP_MASK) | - (device_id << XILINX_DMA_DEVICE_ID_SHIFT); - chan->common.private = (void *)&(chan->private); - - if (!chan->has_DRE) - xdev->common.copy_align = my_log(width); - - chan->dev = xdev->dev; - xdev->chan[chan->id] = chan; - - tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan); - - /* Initialize the channel */ - if (dma_init(chan)) { - dev_err(xdev->dev, "Reset channel failed\n"); - goto out_free_chan; - } - - - spin_lock_init(&chan->lock); - INIT_LIST_HEAD(&chan->pending_list); - INIT_LIST_HEAD(&chan->active_list); - - chan->common.device = &xdev->common; - - /* find the IRQ line, if it exists in the device tree */ - chan->irq = irq_of_parse_and_map(node, 0); - err = request_irq(chan->irq, dma_intr_handler, IRQF_SHARED, - "xilinx-dma-controller", chan); - if (err) { - dev_err(xdev->dev, "unable to request IRQ\n"); - goto out_free_irq; - } - - /* Add the channel to DMA device channel list */ - list_add_tail(&chan->common.device_node, &xdev->common.channels); - xdev->common.chancnt++; - - return 0; - -out_free_irq: - irq_dispose_mapping(chan->irq); -out_free_chan: - kfree(chan); -out_return: - return err; -} - -static int __devinit xilinx_dma_of_probe(struct platform_device *op) -{ - struct xilinx_dma_device *xdev; - struct device_node *child, *node; - int err; - int *value; - - dev_info(&op->dev, "Probing xilinx axi dma engine\n"); - - xdev = kzalloc(sizeof(struct xilinx_dma_device), GFP_KERNEL); - if (!xdev) { - dev_err(&op->dev, "Not enough memory for device\n"); - err = -ENOMEM; - goto out_return; - } - - xdev->dev = &(op->dev); - INIT_LIST_HEAD(&xdev->common.channels); - - node = op->dev.of_node; - xdev->feature = 0; - - /* iomap registers */ - xdev->regs = of_iomap(node, 0); - if (!xdev->regs) { - dev_err(&op->dev, "unable to iomap registers\n"); - err = -ENOMEM; - goto out_free_xdev; - } - - /* - * Axi DMA only do slave transfers - */ - if (of_device_is_compatible(node, "xlnx,axi-dma")) { - - xdev->feature |= XILINX_DMA_IP_DMA; - value = (int *)of_get_property(node, - "xlnx,sg-include-stscntrl-strm", - NULL); - if (value) { - if (be32_to_cpup(value) == 1) { - xdev->feature |= (XILINX_DMA_FTR_STSCNTRL_STRM | - XILINX_DMA_FTR_HAS_SG); - } - } - - dma_cap_set(DMA_SLAVE, xdev->common.cap_mask); - dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask); - xdev->common.device_prep_slave_sg = xilinx_dma_prep_slave_sg; - xdev->common.device_control = xilinx_dma_device_control; - xdev->common.device_issue_pending = xilinx_dma_issue_pending; - } - - xdev->common.device_alloc_chan_resources = - xilinx_dma_alloc_chan_resources; - xdev->common.device_free_chan_resources = - xilinx_dma_free_chan_resources; - xdev->common.device_tx_status = xilinx_tx_status; - xdev->common.dev = &op->dev; - - dev_set_drvdata(&op->dev, xdev); - - for_each_child_of_node(node, child) { - xilinx_dma_chan_probe(xdev, child, xdev->feature); - } - - dma_async_device_register(&xdev->common); - - return 0; - -out_free_xdev: - kfree(xdev); - -out_return: - return err; -} - -static int __devexit xilinx_dma_of_remove(struct platform_device *op) -{ - struct xilinx_dma_device *xdev; - int i; - - xdev = dev_get_drvdata(&op->dev); - dma_async_device_unregister(&xdev->common); - - for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++) { - if (xdev->chan[i]) - xilinx_dma_chan_remove(xdev->chan[i]); - } - - iounmap(xdev->regs); - dev_set_drvdata(&op->dev, NULL); - kfree(xdev); - - return 0; -} - -static const struct of_device_id xilinx_dma_of_ids[] = { - { .compatible = "xlnx,axi-dma",}, - {} -}; - -static struct platform_driver xilinx_dma_of_driver = { - .driver = { - .name = "xilinx-dma", - .owner = THIS_MODULE, - .of_match_table = xilinx_dma_of_ids, - }, - .probe = xilinx_dma_of_probe, - .remove = __devexit_p(xilinx_dma_of_remove), -}; - -module_platform_driver(xilinx_dma_of_driver); - -MODULE_AUTHOR("Xilinx, Inc."); -MODULE_DESCRIPTION("Xilinx DMA driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/dma/xilinx/xilinx_axivdma.c b/drivers/dma/xilinx/xilinx_axivdma.c deleted file mode 100644 index e39676c13f7af..0000000000000 --- a/drivers/dma/xilinx/xilinx_axivdma.c +++ /dev/null @@ -1,1321 +0,0 @@ -/* - * Xilinx Video DMA Engine support - * - * Copyright (C) 2010 Xilinx, Inc. All rights reserved. - * - * Based on the Freescale DMA driver. - * - * Description: - * . Axi VDMA engine, it does transfers between memory and video devices. - * It can be configured to have one channel or two channels. If configured - * as two channels, one is to transmit to the video device and another is - * to receive from the video device. - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* Hw specific definitions */ -#define XILINX_VDMA_MAX_CHANS_PER_DEVICE 0x2 -#define XILINX_VDMA_MAX_TRANS_LEN 0x7FFFFF - -/* General register bits definitions */ -#define XILINX_VDMA_CR_RESET_MASK 0x00000004 - /* Reset DMA engine */ -#define XILINX_VDMA_CR_RUNSTOP_MASK 0x00000001 - /* Start/stop DMA engine */ - -#define XILINX_VDMA_SR_HALTED_MASK 0x00000001 - /* DMA channel halted */ -#define XILINX_VDMA_SR_IDLE_MASK 0x00000002 - /* DMA channel idle */ - -#define XILINX_VDMA_SR_ERR_INTERNAL_MASK 0x00000010 - /* Datamover internal err */ -#define XILINX_VDMA_SR_ERR_SLAVE_MASK 0x00000020 - /* Datamover slave err */ -#define XILINX_VDMA_SR_ERR_DECODE_MASK 0x00000040 - /* Datamover decode err */ -#define XILINX_VDMA_SR_ERR_SG_INT_MASK 0x00000100 - /* SG internal err */ -#define XILINX_VDMA_SR_ERR_SG_SLV_MASK 0x00000200 - /* SG slave err */ -#define XILINX_VDMA_SR_ERR_SG_DEC_MASK 0x00000400 - /* SG decode err */ -#define XILINX_VDMA_SR_ERR_ALL_MASK 0x00000770 - /* All errors */ - -#define XILINX_VDMA_XR_IRQ_IOC_MASK 0x00001000 - /* Completion interrupt */ -#define XILINX_VDMA_XR_IRQ_DELAY_MASK 0x00002000 - /* Delay interrupt */ -#define XILINX_VDMA_XR_IRQ_ERROR_MASK 0x00004000 - /* Error interrupt */ -#define XILINX_VDMA_XR_IRQ_ALL_MASK 0x00007000 - /* All interrupts */ - -#define XILINX_VDMA_XR_DELAY_MASK 0xFF000000 - /* Delay timeout counter */ -#define XILINX_VDMA_XR_COALESCE_MASK 0x00FF0000 - /* Coalesce counter */ - -#define XILINX_VDMA_IRQ_SHIFT 12 -#define XILINX_VDMA_DELAY_SHIFT 24 -#define XILINX_VDMA_COALESCE_SHIFT 16 - -#define XILINX_VDMA_DELAY_MAX 0xFF - /* Maximum delay counter value */ -#define XILINX_VDMA_COALESCE_MAX 0xFF - /* Maximum coalescing counter value */ - -#define XILINX_VDMA_RX_CHANNEL_OFFSET 0x30 - -#define XILINX_VDMA_CIRC_EN 0x00000002 /* Circular mode */ -#define XILINX_VDMA_SYNC_EN 0x00000008 /* Sync enable mode */ -#define XILINX_VDMA_FRMCNT_EN 0x00000010 /* Frm Cnt enable mode */ -#define XILINX_VDMA_MSTR_MASK 0x00000F00 /* Master in control */ - -#define XILINX_VDMA_EXTFSYNC_SHIFT 6 -#define XILINX_VDMA_MSTR_SHIFT 8 -#define XILINX_VDMA_WR_REF_SHIFT 8 - -#define XILINX_VDMA_FRMDLY_SHIFT 24 - -#define XILINX_VDMA_DIRECT_REG_OFFSET 0x50 -#define XILINX_VDMA_CHAN_DIRECT_REG_SIZE 0x50 - -#define XILINX_VDMA_PARK_REG_OFFSET 0x28 - -#define XILINX_VDMA_SR_ERR_FSIZE_LESS_MASK 0x00000080 - /* FSize Less Mismatch err */ -#define XILINX_VDMA_SR_ERR_LSIZE_LESS_MASK 0x00000100 - /* LSize Less Mismatch err */ -#define XILINX_VDMA_SR_ERR_FSIZE_MORE_MASK 0x00000800 - /* FSize more err */ - -/* - * Recoverable errors are DMA Internal error, FSize Less, LSize Less - * and FSize More mismatch errors. These are only recoverable only - * when C_FLUSH_ON_FSYNC is enabled in the hardware system. - */ -#define XILINX_VDMA_SR_ERR_RECOVER_MASK 0x00000990 - /* Recoverable errs */ - -/* Axi VDMA Flush on Fsync bits */ -#define XILINX_VDMA_FLUSH_S2MM 3 -#define XILINX_VDMA_FLUSH_MM2S 2 -#define XILINX_VDMA_FLUSH_BOTH 1 - -/* Feature encodings */ -#define XILINX_VDMA_FTR_HAS_SG 0x00000100 - /* Has SG */ -#define XILINX_VDMA_FTR_HAS_SG_SHIFT 8 - /* Has SG shift */ -#define XILINX_VDMA_FTR_FLUSH_MASK 0x00000600 - /* Flush-on-FSync Mask */ -#define XILINX_VDMA_FTR_FLUSH_SHIFT 9 - /* Flush-on-FSync shift */ - -/* Delay loop counter to prevent hardware failure */ -#define XILINX_VDMA_RESET_LOOP 1000000 -#define XILINX_VDMA_HALT_LOOP 1000000 - -/* Device Id in the private structure */ -#define XILINX_VDMA_DEVICE_ID_SHIFT 28 - -/* IO accessors */ -#define VDMA_OUT(addr, val) (iowrite32(val, addr)) -#define VDMA_IN(addr) (ioread32(addr)) - -/* Hardware descriptor */ -struct xilinx_vdma_desc_hw { - u32 next_desc; /* 0x00 */ - u32 pad1; /* 0x04 */ - u32 buf_addr; /* 0x08 */ - u32 pad2; /* 0x0C */ - u32 vsize; /* 0x10 */ - u32 hsize; /* 0x14 */ - u32 stride; /* 0x18 */ -} __aligned(64); - -struct xilinx_vdma_desc_sw { - struct xilinx_vdma_desc_hw hw; - struct list_head node; - struct list_head tx_list; - struct dma_async_tx_descriptor async_tx; -} __aligned(64); - -struct xvdma_regs { - u32 cr; /* 0x00 Control Register */ - u32 sr; /* 0x04 Status Register */ - u32 cdr; /* 0x08 Current Descriptor Register */ - u32 pad1; - u32 tdr; /* 0x10 Tail Descriptor Register */ - u32 pad2; -}; - -struct vdma_addr_regs { - u32 vsize; /* 0x0 Vertical size */ - u32 hsize; /* 0x4 Horizontal size */ - u32 frmdly_stride; /* 0x8 Frame delay and stride */ - u32 buf_addr[16]; /* 0xC - 0x48 Src addresses */ -}; - -/* Per DMA specific operations should be embedded in the channel structure */ -struct xilinx_vdma_chan { - struct xvdma_regs __iomem *regs; /* Control status registers */ - struct vdma_addr_regs *addr_regs; /* Direct address registers */ - dma_cookie_t completed_cookie; /* Maximum cookie completed */ - dma_cookie_t cookie; /* The current cookie */ - spinlock_t lock; /* Descriptor operation lock */ - bool sg_waiting; /* SG transfer waiting */ - struct list_head active_list; /* Active descriptors */ - struct list_head pending_list; /* Descriptors waiting */ - struct dma_chan common; /* DMA common channel */ - struct dma_pool *desc_pool; /* Descriptors pool */ - struct device *dev; /* The dma device */ - int irq; /* Channel IRQ */ - int id; /* Channel ID */ - enum dma_transfer_direction direction; /* Transfer direction */ - int max_len; /* Max data len per transfer */ - int is_lite; /* Whether is light build */ - int num_frms; /* Number of frames */ - int has_SG; /* Support scatter transfers */ - int has_DRE; /* For unaligned transfers */ - int genlock; /* Support genlock mode */ - int err; /* Channel has errors */ - struct tasklet_struct tasklet; /* Cleanup work after irq */ - u32 feature; /* IP feature */ - u32 private; /* Match info for - channel request */ - void (*start_transfer)(struct xilinx_vdma_chan *chan); - struct xilinx_vdma_config config; /* Device configuration info */ - u32 flush_fsync; /* Flush on Fsync */ -}; - -struct xilinx_vdma_device { - void __iomem *regs; - struct device *dev; - struct dma_device common; - struct xilinx_vdma_chan *chan[XILINX_VDMA_MAX_CHANS_PER_DEVICE]; - u32 feature; - int irq; -}; - -#define to_xilinx_chan(chan) \ - container_of(chan, struct xilinx_vdma_chan, common) - -/* Required functions */ - -static int xilinx_vdma_alloc_chan_resources(struct dma_chan *dchan) -{ - struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan); - - /* Has this channel already been allocated? */ - if (chan->desc_pool) - return 1; - - /* - * We need the descriptor to be aligned to 64bytes - * for meeting Xilinx VDMA specification requirement. - */ - chan->desc_pool = dma_pool_create("xilinx_vdma_desc_pool", - chan->dev, - sizeof(struct xilinx_vdma_desc_sw), - __alignof__(struct xilinx_vdma_desc_sw), 0); - if (!chan->desc_pool) { - dev_err(chan->dev, - "unable to allocate channel %d descriptor pool\n", - chan->id); - return -ENOMEM; - } - - chan->completed_cookie = 1; - chan->cookie = 1; - - /* there is at least one descriptor free to be allocated */ - return 1; -} - -static void xilinx_vdma_free_desc_list(struct xilinx_vdma_chan *chan, - struct list_head *list) -{ - struct xilinx_vdma_desc_sw *desc, *_desc; - - list_for_each_entry_safe(desc, _desc, list, node) { - list_del(&desc->node); - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); - } -} - -static void xilinx_vdma_free_desc_list_reverse(struct xilinx_vdma_chan *chan, - struct list_head *list) -{ - struct xilinx_vdma_desc_sw *desc, *_desc; - - list_for_each_entry_safe_reverse(desc, _desc, list, node) { - list_del(&desc->node); - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); - } -} - -static void xilinx_vdma_free_chan_resources(struct dma_chan *dchan) -{ - struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan); - unsigned long flags; - - dev_dbg(chan->dev, "Free all channel resources.\n"); - spin_lock_irqsave(&chan->lock, flags); - xilinx_vdma_free_desc_list(chan, &chan->active_list); - xilinx_vdma_free_desc_list(chan, &chan->pending_list); - spin_unlock_irqrestore(&chan->lock, flags); - - dma_pool_destroy(chan->desc_pool); - chan->desc_pool = NULL; -} - -static enum dma_status xilinx_vdma_desc_status(struct xilinx_vdma_chan *chan, - struct xilinx_vdma_desc_sw *desc) -{ - return dma_async_is_complete(desc->async_tx.cookie, - chan->completed_cookie, - chan->cookie); -} - -static void xilinx_chan_desc_cleanup(struct xilinx_vdma_chan *chan) -{ - struct xilinx_vdma_desc_sw *desc, *_desc; - unsigned long flags; - - spin_lock_irqsave(&chan->lock, flags); - - list_for_each_entry_safe(desc, _desc, &chan->active_list, node) { - dma_async_tx_callback callback; - void *callback_param; - - if (xilinx_vdma_desc_status(chan, desc) == DMA_IN_PROGRESS) - break; - - /* Remove from the list of running transactions */ - list_del(&desc->node); - - /* Run the link descriptor callback function */ - callback = desc->async_tx.callback; - callback_param = desc->async_tx.callback_param; - if (callback) { - spin_unlock_irqrestore(&chan->lock, flags); - callback(callback_param); - spin_lock_irqsave(&chan->lock, flags); - } - - /* Run any dependencies, then free the descriptor */ - dma_run_dependencies(&desc->async_tx); - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); - } - - spin_unlock_irqrestore(&chan->lock, flags); -} - -static enum dma_status xilinx_tx_status(struct dma_chan *dchan, - dma_cookie_t cookie, - struct dma_tx_state *txstate) -{ - struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan); - dma_cookie_t last_used; - dma_cookie_t last_complete; - - xilinx_chan_desc_cleanup(chan); - - last_used = dchan->cookie; - last_complete = chan->completed_cookie; - - dma_set_tx_state(txstate, last_complete, last_used, 0); - - return dma_async_is_complete(cookie, last_complete, last_used); -} - -static int dma_is_running(struct xilinx_vdma_chan *chan) -{ - return !(VDMA_IN(&chan->regs->sr) & XILINX_VDMA_SR_HALTED_MASK) && - (VDMA_IN(&chan->regs->cr) & XILINX_VDMA_CR_RUNSTOP_MASK); -} - -static int dma_is_idle(struct xilinx_vdma_chan *chan) -{ - return VDMA_IN(&chan->regs->sr) & XILINX_VDMA_SR_IDLE_MASK; -} - -#define XILINX_VDMA_DRIVER_DEBUG 0 - -#if (XILINX_VDMA_DRIVER_DEBUG == 1) -static void desc_dump(struct xilinx_vdma_desc_hw *hw) -{ - pr_info("hw desc %x:\n", (unsigned int)hw); - pr_info("\tnext_desc %x\n", hw->next_desc); - pr_info("\tbuf_addr %x\n", hw->buf_addr); - pr_info("\tvsize %x\n", hw->vsize); - pr_info("\thsize %x\n", hw->hsize); - pr_info("\tstride %x\n", hw->stride); - pr_info("\tstatus %x\n", hw->status); - -} -#endif - -/* Stop the hardware, the ongoing transfer will be finished */ -static void vdma_halt(struct xilinx_vdma_chan *chan) -{ - int loop = XILINX_VDMA_HALT_LOOP; - - VDMA_OUT(&chan->regs->cr, - VDMA_IN(&chan->regs->cr) & ~XILINX_VDMA_CR_RUNSTOP_MASK); - - /* Wait for the hardware to halt */ - while (loop) { - if (!(VDMA_IN(&chan->regs->cr) & XILINX_VDMA_CR_RUNSTOP_MASK)) - break; - - loop -= 1; - } - - if (!loop) { - pr_debug("Cannot stop channel %x: %x\n", - (unsigned int)chan, - (unsigned int)VDMA_IN(&chan->regs->cr)); - chan->err = 1; - } - - return; -} - -/* Start the hardware. Transfers are not started yet */ -static void vdma_start(struct xilinx_vdma_chan *chan) -{ - int loop = XILINX_VDMA_HALT_LOOP; - - VDMA_OUT(&chan->regs->cr, - VDMA_IN(&chan->regs->cr) | XILINX_VDMA_CR_RUNSTOP_MASK); - - /* Wait for the hardware to start */ - while (loop) { - if (VDMA_IN(&chan->regs->cr) & XILINX_VDMA_CR_RUNSTOP_MASK) - break; - - loop -= 1; - } - - if (!loop) { - pr_debug("Cannot start channel %x: %x\n", - (unsigned int)chan, - (unsigned int)VDMA_IN(&chan->regs->cr)); - - chan->err = 1; - } - - return; -} - -static void xilinx_vdma_start_transfer(struct xilinx_vdma_chan *chan) -{ - unsigned long flags; - struct xilinx_vdma_desc_sw *desch, *desct = NULL; - struct xilinx_vdma_config *config; - u32 reg; - u8 *chan_base; - - if (chan->err) - return; - - spin_lock_irqsave(&chan->lock, flags); - - if (list_empty(&chan->pending_list)) - goto out_unlock; - - /* If it is SG mode and hardware is busy, cannot submit */ - if (chan->has_SG && dma_is_running(chan) && !dma_is_idle(chan)) { - dev_dbg(chan->dev, "DMA controller still busy\n"); - goto out_unlock; - } - - /* - * If hardware is idle, then all descriptors on the running lists are - * done, start new transfers - */ - if (chan->err) - goto out_unlock; - - if (chan->has_SG) { - desch = list_first_entry(&chan->pending_list, - struct xilinx_vdma_desc_sw, node); - - desct = container_of(chan->pending_list.prev, - struct xilinx_vdma_desc_sw, node); - - VDMA_OUT(&chan->regs->cdr, desch->async_tx.phys); - } - - /* Configure the hardware using info in the config structure */ - config = &(chan->config); - reg = VDMA_IN(&chan->regs->cr); - - if (config->frm_cnt_en) - reg |= XILINX_VDMA_FRMCNT_EN; - else - reg &= ~XILINX_VDMA_FRMCNT_EN; - - /* - * With SG, start with circular mode, so that BDs can be fetched. - * In direct register mode, if not parking, enable circular mode - */ - if ((chan->has_SG) || (!config->park)) - reg |= XILINX_VDMA_CIRC_EN; - - if (config->park) - reg &= ~XILINX_VDMA_CIRC_EN; - - VDMA_OUT(&chan->regs->cr, reg); - - if (config->park && (config->park_frm >= 0) - && (config->park_frm < chan->num_frms)) { - if (config->direction == DMA_MEM_TO_DEV) { - chan_base = (char *)chan->regs; - VDMA_OUT((chan_base + XILINX_VDMA_PARK_REG_OFFSET), - config->park_frm); - } else { - chan_base = ((char *)chan->regs - - XILINX_VDMA_RX_CHANNEL_OFFSET); - VDMA_OUT((chan_base + XILINX_VDMA_PARK_REG_OFFSET), - config->park_frm << XILINX_VDMA_WR_REF_SHIFT); - } - } - - /* Start the hardware */ - vdma_start(chan); - - if (chan->err) - goto out_unlock; - list_splice_tail_init(&chan->pending_list, &chan->active_list); - - /* - * Enable interrupts - * park/genlock testing does not use interrupts - */ - if (!chan->config.disable_intr) { - VDMA_OUT(&chan->regs->cr, - VDMA_IN(&chan->regs->cr) | - XILINX_VDMA_XR_IRQ_ALL_MASK); - } else { - VDMA_OUT(&chan->regs->cr, - (VDMA_IN(&chan->regs->cr) | - XILINX_VDMA_XR_IRQ_ALL_MASK) & - ~((chan->config.disable_intr << - XILINX_VDMA_IRQ_SHIFT))); - } - - /* Start the transfer */ - if (chan->has_SG) - VDMA_OUT(&chan->regs->tdr, desct->async_tx.phys); - else - VDMA_OUT(&chan->addr_regs->vsize, config->vsize); - -out_unlock: - spin_unlock_irqrestore(&chan->lock, flags); -} - -static void xilinx_vdma_issue_pending(struct dma_chan *dchan) -{ - struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan); - - xilinx_vdma_start_transfer(chan); -} - -/** - * xilinx_vdma_update_completed_cookie - Update the completed cookie. - * @chan : xilinx DMA channel - * - * CONTEXT: hardirq - */ -static void xilinx_vdma_update_completed_cookie(struct xilinx_vdma_chan *chan) -{ - struct xilinx_vdma_desc_sw *desc = NULL; - unsigned long flags; - dma_cookie_t cookie = -EBUSY; - int done = 0; - - spin_lock_irqsave(&chan->lock, flags); - - if (list_empty(&chan->active_list)) { - dev_dbg(chan->dev, "no running descriptors\n"); - goto out_unlock; - } - - /* Get the last completed descriptor, update the cookie to that */ - list_for_each_entry(desc, &chan->active_list, node) { - /* In non-SG mode, all active entries are done */ - done = 1; - cookie = desc->async_tx.cookie; - } - - if (done) - chan->completed_cookie = cookie; - -out_unlock: - spin_unlock_irqrestore(&chan->lock, flags); -} - -/* Reset hardware */ -static int vdma_init(struct xilinx_vdma_chan *chan) -{ - int loop = XILINX_VDMA_RESET_LOOP; - u32 tmp; - - VDMA_OUT(&chan->regs->cr, - VDMA_IN(&chan->regs->cr) | XILINX_VDMA_CR_RESET_MASK); - - tmp = VDMA_IN(&chan->regs->cr) & XILINX_VDMA_CR_RESET_MASK; - - /* Wait for the hardware to finish reset */ - while (loop && tmp) { - tmp = VDMA_IN(&chan->regs->cr) & XILINX_VDMA_CR_RESET_MASK; - loop -= 1; - } - - if (!loop) { - dev_err(chan->dev, "reset timeout, cr %x, sr %x\n", - VDMA_IN(&chan->regs->cr), VDMA_IN(&chan->regs->sr)); - return 1; - } - - return 0; -} - - -static irqreturn_t vdma_intr_handler(int irq, void *data) -{ - struct xilinx_vdma_chan *chan = data; - int update_cookie = 0; - int to_transfer = 0; - u32 stat, reg; - - reg = VDMA_IN(&chan->regs->cr); - - /* Disable intr */ - VDMA_OUT(&chan->regs->cr, - reg & ~XILINX_VDMA_XR_IRQ_ALL_MASK); - - stat = VDMA_IN(&chan->regs->sr); - if (!(stat & XILINX_VDMA_XR_IRQ_ALL_MASK)) - return IRQ_NONE; - - /* Ack the interrupts */ - VDMA_OUT(&chan->regs->sr, XILINX_VDMA_XR_IRQ_ALL_MASK); - - /* Check for only the interrupts which are enabled */ - stat &= (reg & XILINX_VDMA_XR_IRQ_ALL_MASK); - - if (stat & XILINX_VDMA_XR_IRQ_ERROR_MASK) { - if (chan->flush_fsync) { - /* - * VDMA Recoverable Errors, only when - * C_FLUSH_ON_FSYNC is enabled - */ - u32 error = VDMA_IN(&chan->regs->sr) & - XILINX_VDMA_SR_ERR_RECOVER_MASK; - if (error) - VDMA_OUT(&chan->regs->sr, error); - else - chan->err = 1; - } else { - dev_err(chan->dev, - "Channel %x has errors %x, cdr %x tdr %x\n", - (unsigned int)chan, - (unsigned int)VDMA_IN(&chan->regs->sr), - (unsigned int)VDMA_IN(&chan->regs->cdr), - (unsigned int)VDMA_IN(&chan->regs->tdr)); - chan->err = 1; - } - } - - /* - * Device takes too long to do the transfer when user requires - * responsiveness - */ - if (stat & XILINX_VDMA_XR_IRQ_DELAY_MASK) - dev_dbg(chan->dev, "Inter-packet latency too long\n"); - - if (stat & XILINX_VDMA_XR_IRQ_IOC_MASK) { - update_cookie = 1; - to_transfer = 1; - } - - if (update_cookie) - xilinx_vdma_update_completed_cookie(chan); - - if (to_transfer) - chan->start_transfer(chan); - - tasklet_schedule(&chan->tasklet); - return IRQ_HANDLED; -} - -static void dma_do_tasklet(unsigned long data) -{ - struct xilinx_vdma_chan *chan = (struct xilinx_vdma_chan *)data; - - xilinx_chan_desc_cleanup(chan); -} - -/* Append the descriptor list to the pending list */ -static void append_desc_queue(struct xilinx_vdma_chan *chan, - struct xilinx_vdma_desc_sw *desc) -{ - struct xilinx_vdma_desc_sw *tail = container_of(chan->pending_list.prev, - struct xilinx_vdma_desc_sw, node); - struct xilinx_vdma_desc_hw *hw; - - if (list_empty(&chan->pending_list)) - goto out_splice; - - /* - * Add the hardware descriptor to the chain of hardware descriptors - * that already exists in memory. - */ - hw = &(tail->hw); - hw->next_desc = (u32)desc->async_tx.phys; - - /* - * Add the software descriptor and all children to the list - * of pending transactions - */ -out_splice: - list_splice_tail_init(&desc->tx_list, &chan->pending_list); -} - -/* - * Assign cookie to each descriptor, and append the descriptors to the pending - * list - */ -static dma_cookie_t xilinx_vdma_tx_submit(struct dma_async_tx_descriptor *tx) -{ - struct xilinx_vdma_chan *chan = to_xilinx_chan(tx->chan); - struct xilinx_vdma_desc_sw *desc = container_of(tx, - struct xilinx_vdma_desc_sw, async_tx); - struct xilinx_vdma_desc_sw *child; - unsigned long flags; - dma_cookie_t cookie = -EBUSY; - - if (chan->err) { - /* - * If reset fails, need to hard reset the system. - * Channel is no longer functional - */ - if (!vdma_init(chan)) - chan->err = 0; - else - return cookie; - } - - spin_lock_irqsave(&chan->lock, flags); - - /* - * assign cookies to all of the software descriptors - * that make up this transaction - */ - cookie = chan->cookie; - list_for_each_entry(child, &desc->tx_list, node) { - cookie++; - if (cookie < 0) - cookie = DMA_MIN_COOKIE; - - child->async_tx.cookie = cookie; - } - - chan->cookie = cookie; - - /* Put this transaction onto the tail of the pending queue */ - append_desc_queue(chan, desc); - - spin_unlock_irqrestore(&chan->lock, flags); - - return cookie; -} - -static struct xilinx_vdma_desc_sw *xilinx_vdma_alloc_descriptor( - struct xilinx_vdma_chan *chan) -{ - struct xilinx_vdma_desc_sw *desc; - dma_addr_t pdesc; - - desc = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc); - if (!desc) { - dev_dbg(chan->dev, "out of memory for desc\n"); - return NULL; - } - - memset(desc, 0, sizeof(*desc)); - INIT_LIST_HEAD(&desc->tx_list); - dma_async_tx_descriptor_init(&desc->async_tx, &chan->common); - desc->async_tx.tx_submit = xilinx_vdma_tx_submit; - desc->async_tx.phys = pdesc; - - return desc; -} - -/** - * xilinx_vdma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction - * @chan: VDMA channel - * @sgl: scatterlist to transfer to/from - * @sg_len: number of entries in @scatterlist - * @direction: DMA direction - * @flags: transfer ack flags - */ -static struct dma_async_tx_descriptor *xilinx_vdma_prep_slave_sg( - struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_transfer_direction direction, unsigned long flags, - void *context) -{ - struct xilinx_vdma_chan *chan; - struct xilinx_vdma_desc_sw *first = NULL, *prev = NULL, *new = NULL; - struct xilinx_vdma_desc_hw *hw = NULL, *prev_hw = NULL; - int i; - struct scatterlist *sg; - dma_addr_t dma_src; - - if (!dchan) - return NULL; - - chan = to_xilinx_chan(dchan); - - if (chan->direction != direction) - return NULL; - - /* Enforce one sg entry for one frame */ - if (sg_len != chan->num_frms) { - dev_err(chan->dev, - "number of entries %d not the same as num stores %d\n", - sg_len, chan->num_frms); - - return NULL; - } - - if (!chan->has_SG) { - VDMA_OUT(&chan->addr_regs->hsize, chan->config.hsize); - VDMA_OUT(&chan->addr_regs->frmdly_stride, - chan->config.frm_dly << XILINX_VDMA_FRMDLY_SHIFT | - chan->config.stride); - } - - /* Build transactions using information in the scatter gather list */ - for_each_sg(sgl, sg, sg_len, i) { - /* Allocate the link descriptor from DMA pool */ - new = xilinx_vdma_alloc_descriptor(chan); - if (!new) { - dev_err(chan->dev, - "No free memory for link descriptor\n"); - goto fail; - } - - /* - * Calculate the maximum number of bytes to transfer, - * making sure it is less than the hw limit - */ - hw = &(new->hw); - - dma_src = sg_dma_address(sg); - if (chan->has_SG) { - hw->buf_addr = dma_src; - - /* Fill in the descriptor */ - hw->vsize = chan->config.vsize; - hw->hsize = chan->config.hsize; - hw->stride = (chan->config.frm_dly << - XILINX_VDMA_FRMDLY_SHIFT) | - chan->config.stride; - } else { - /* Update the registers */ - VDMA_OUT(&(chan->addr_regs->buf_addr[i]), dma_src); - } - - /* - * If this is not the first descriptor, chain the - * current descriptor after the previous descriptor - */ - if (!first) { - first = new; - } else { - prev_hw = &(prev->hw); - prev_hw->next_desc = new->async_tx.phys; - } - - new->async_tx.cookie = 0; - async_tx_ack(&new->async_tx); - - prev = new; - - /* Insert the link descriptor into the list */ - list_add_tail(&new->node, &first->tx_list); - } - - /* Link the last BD with the first BD */ - hw->next_desc = first->async_tx.phys; - - if (!first || !new) - return NULL; - - new->async_tx.flags = flags; - new->async_tx.cookie = -EBUSY; - - return &first->async_tx; - -fail: - /* - * If first was not set, then we failed to allocate the very first - * descriptor, and we're done */ - if (!first) - return NULL; - - /* - * First is set, so all of the descriptors we allocated have been added - * to first->tx_list, INCLUDING "first" itself. Therefore we - * must traverse the list backwards freeing each descriptor in turn - */ - xilinx_vdma_free_desc_list_reverse(chan, &first->tx_list); - return NULL; -} - -/* - * Run-time configuration for Axi VDMA, supports: - * . halt the channel - * . configure interrupt coalescing and inter-packet delay threshold - * . start/stop parking - * . enable genlock - * . set transfer information using config struct - */ -static int xilinx_vdma_device_control(struct dma_chan *dchan, - enum dma_ctrl_cmd cmd, unsigned long arg) -{ - struct xilinx_vdma_chan *chan; - unsigned long flags; - - if (!dchan) - return -EINVAL; - - chan = to_xilinx_chan(dchan); - - if (cmd == DMA_TERMINATE_ALL) { - /* Halt the DMA engine */ - vdma_halt(chan); - - spin_lock_irqsave(&chan->lock, flags); - - /* Remove and free all of the descriptors in the lists */ - xilinx_vdma_free_desc_list(chan, &chan->pending_list); - xilinx_vdma_free_desc_list(chan, &chan->active_list); - - spin_unlock_irqrestore(&chan->lock, flags); - return 0; - } else if (cmd == DMA_SLAVE_CONFIG) { - struct xilinx_vdma_config *cfg = - (struct xilinx_vdma_config *)arg; - u32 reg; - - if (cfg->reset) - vdma_init(chan); - - reg = VDMA_IN(&chan->regs->cr); - - /* If vsize is -1, it is park-related operations */ - if (cfg->vsize == -1) { - if (cfg->park) - reg &= ~XILINX_VDMA_CIRC_EN; - else - reg |= XILINX_VDMA_CIRC_EN; - - VDMA_OUT(&chan->regs->cr, reg); - return 0; - } - - /* If hsize is -1, it is interrupt threshold settings */ - if (cfg->hsize == -1) { - if (cfg->coalesc <= XILINX_VDMA_COALESCE_MAX) { - reg &= ~XILINX_VDMA_XR_COALESCE_MASK; - reg |= cfg->coalesc << - XILINX_VDMA_COALESCE_SHIFT; - chan->config.coalesc = cfg->coalesc; - } - - if (cfg->delay <= XILINX_VDMA_DELAY_MAX) { - reg &= ~XILINX_VDMA_XR_DELAY_MASK; - reg |= cfg->delay << XILINX_VDMA_DELAY_SHIFT; - chan->config.delay = cfg->delay; - } - - VDMA_OUT(&chan->regs->cr, reg); - return 0; - } - - /* Transfer information */ - chan->config.vsize = cfg->vsize; - chan->config.hsize = cfg->hsize; - chan->config.stride = cfg->stride; - chan->config.frm_dly = cfg->frm_dly; - chan->config.park = cfg->park; - chan->config.direction = cfg->direction; - - /* genlock settings */ - chan->config.gen_lock = cfg->gen_lock; - chan->config.master = cfg->master; - - if (cfg->gen_lock) { - if (chan->genlock) { - reg |= XILINX_VDMA_SYNC_EN; - reg |= cfg->master << XILINX_VDMA_MSTR_SHIFT; - } - } - - chan->config.frm_cnt_en = cfg->frm_cnt_en; - if (cfg->park) - chan->config.park_frm = cfg->park_frm; - else - chan->config.park_frm = -1; - - chan->config.coalesc = cfg->coalesc; - chan->config.delay = cfg->delay; - if (cfg->coalesc <= XILINX_VDMA_COALESCE_MAX) { - reg |= cfg->coalesc << XILINX_VDMA_COALESCE_SHIFT; - chan->config.coalesc = cfg->coalesc; - } - - if (cfg->delay <= XILINX_VDMA_DELAY_MAX) { - reg |= cfg->delay << XILINX_VDMA_DELAY_SHIFT; - chan->config.delay = cfg->delay; - } - - chan->config.disable_intr = cfg->disable_intr; - - if (cfg->ext_fsync) - reg |= cfg->ext_fsync << XILINX_VDMA_EXTFSYNC_SHIFT; - - VDMA_OUT(&chan->regs->cr, reg); - return 0; - } else - return -ENXIO; -} - - -/* - * Logarithm function to compute alignment shift - * Only deals with value less than 4096. - */ -static int my_log(int value) -{ - int i = 0; - while ((1 << i) < value) { - i++; - - if (i >= 12) - return 0; - } - - return i; -} - -static void xilinx_vdma_chan_remove(struct xilinx_vdma_chan *chan) -{ - irq_dispose_mapping(chan->irq); - list_del(&chan->common.device_node); - kfree(chan); -} - -/* - * Probing channels - * - * . Get channel features from the device tree entry - * . Initialize special channel handling routines - */ -static int __devinit xilinx_vdma_chan_probe(struct xilinx_vdma_device *xdev, - struct device_node *node, u32 feature) -{ - struct xilinx_vdma_chan *chan; - int err; - const __be32 *value; - u32 width = 0, device_id = 0, flush_fsync = 0; - - /* Alloc channel */ - chan = kzalloc(sizeof(*chan), GFP_KERNEL); - if (!chan) { - dev_err(xdev->dev, "no free memory for DMA channels!\n"); - err = -ENOMEM; - goto out_return; - } - - chan->feature = feature; - chan->is_lite = 0; - chan->has_DRE = 0; - chan->has_SG = 0; - chan->max_len = XILINX_VDMA_MAX_TRANS_LEN; - - value = of_get_property(node, "xlnx,include-dre", NULL); - if (value) - chan->has_DRE = be32_to_cpup(value); - - value = (int *)of_get_property(node, "xlnx,genlock-mode", NULL); - if (value) - chan->genlock = be32_to_cpup(value); - - value = (int *)of_get_property(node, "xlnx,datawidth", NULL); - if (value) { - width = be32_to_cpup(value) >> 3; /* Convert bits to bytes */ - - /* If data width is greater than 8 bytes, DRE is not in hw */ - if (width > 8) - chan->has_DRE = 0; - - chan->feature |= width - 1; - } - - value = (int *)of_get_property(node, "xlnx,device-id", NULL); - if (value) - device_id = be32_to_cpup(value); - - flush_fsync = (xdev->feature & XILINX_VDMA_FTR_FLUSH_MASK) >> - XILINX_VDMA_FTR_FLUSH_SHIFT; - - chan->start_transfer = xilinx_vdma_start_transfer; - - chan->has_SG = (xdev->feature & XILINX_VDMA_FTR_HAS_SG) >> - XILINX_VDMA_FTR_HAS_SG_SHIFT; - - if (of_device_is_compatible(node, - "xlnx,axi-vdma-mm2s-channel")) { - chan->direction = DMA_MEM_TO_DEV; - if (!chan->has_SG) { - chan->addr_regs = (struct vdma_addr_regs *) - ((u32)xdev->regs + - XILINX_VDMA_DIRECT_REG_OFFSET); - } - - if (flush_fsync == XILINX_VDMA_FLUSH_BOTH || - flush_fsync == XILINX_VDMA_FLUSH_MM2S) - chan->flush_fsync = 1; - } - - if (of_device_is_compatible(node, "xlnx,axi-vdma-s2mm-channel")) { - chan->direction = DMA_DEV_TO_MEM; - if (!chan->has_SG) { - chan->addr_regs = (struct vdma_addr_regs *) - ((u32)xdev->regs + - XILINX_VDMA_DIRECT_REG_OFFSET + - XILINX_VDMA_CHAN_DIRECT_REG_SIZE); - } - - if (flush_fsync == XILINX_VDMA_FLUSH_BOTH || - flush_fsync == XILINX_VDMA_FLUSH_S2MM) - chan->flush_fsync = 1; - } - - chan->regs = (struct xvdma_regs *)xdev->regs; - chan->id = 0; - - if (chan->direction == DMA_DEV_TO_MEM) { - chan->regs = (struct xvdma_regs *)((u32)xdev->regs + - XILINX_VDMA_RX_CHANNEL_OFFSET); - chan->id = 1; - } - - /* - * Used by dmatest channel matching in slave transfers - * Can change it to be a structure to have more matching information - */ - chan->private = (chan->direction & 0xFF) | - (chan->feature & XILINX_DMA_IP_MASK) | - (device_id << XILINX_VDMA_DEVICE_ID_SHIFT); - chan->common.private = (void *)&(chan->private); - - if (!chan->has_DRE) - xdev->common.copy_align = my_log(width); - - chan->dev = xdev->dev; - xdev->chan[chan->id] = chan; - - tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan); - - /* Initialize the channel */ - if (vdma_init(chan)) { - dev_err(xdev->dev, "Reset channel failed\n"); - goto out_free_chan; - } - - spin_lock_init(&chan->lock); - INIT_LIST_HEAD(&chan->pending_list); - INIT_LIST_HEAD(&chan->active_list); - - chan->common.device = &xdev->common; - - /* Find the IRQ line, if it exists in the device tree */ - chan->irq = irq_of_parse_and_map(node, 0); - err = request_irq(chan->irq, vdma_intr_handler, IRQF_SHARED, - "xilinx-vdma-controller", chan); - if (err) { - dev_err(xdev->dev, "unable to request IRQ\n"); - goto out_free_irq; - } - - /* Add the channel to DMA device channel list */ - list_add_tail(&chan->common.device_node, &xdev->common.channels); - xdev->common.chancnt++; - - return 0; - -out_free_irq: - irq_dispose_mapping(chan->irq); -out_free_chan: - kfree(chan); -out_return: - return err; -} - -static int __devinit xilinx_vdma_of_probe(struct platform_device *op) -{ - struct xilinx_vdma_device *xdev; - struct device_node *child, *node; - int err, i; - int *value; - int num_frames = 0; - - dev_info(&op->dev, "Probing xilinx axi vdma engine\n"); - - xdev = kzalloc(sizeof(struct xilinx_vdma_device), GFP_KERNEL); - if (!xdev) { - dev_err(&op->dev, "Not enough memory for device\n"); - err = -ENOMEM; - goto out_return; - } - - xdev->dev = &(op->dev); - INIT_LIST_HEAD(&xdev->common.channels); - - node = op->dev.of_node; - xdev->feature = 0; - - /* iomap registers */ - xdev->regs = of_iomap(node, 0); - if (!xdev->regs) { - dev_err(&op->dev, "unable to iomap registers\n"); - err = -ENOMEM; - goto out_free_xdev; - } - - /* Axi VDMA only do slave transfers */ - if (of_device_is_compatible(node, "xlnx,axi-vdma")) { - xdev->feature |= XILINX_DMA_IP_VDMA; - - value = (int *)of_get_property(node, "xlnx,include-sg", - NULL); - if (value) { - if (be32_to_cpup(value) == 1) - xdev->feature |= XILINX_VDMA_FTR_HAS_SG; - } - - value = (int *)of_get_property(node, "xlnx,num-fstores", - NULL); - if (value) - num_frames = be32_to_cpup(value); - - value = (int *)of_get_property(node, "xlnx,flush-fsync", NULL); - if (value) - xdev->feature |= be32_to_cpup(value) << - XILINX_VDMA_FTR_FLUSH_SHIFT; - - dma_cap_set(DMA_SLAVE, xdev->common.cap_mask); - dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask); - xdev->common.device_prep_slave_sg = xilinx_vdma_prep_slave_sg; - xdev->common.device_control = xilinx_vdma_device_control; - xdev->common.device_issue_pending = xilinx_vdma_issue_pending; - } - - xdev->common.device_alloc_chan_resources = - xilinx_vdma_alloc_chan_resources; - xdev->common.device_free_chan_resources = - xilinx_vdma_free_chan_resources; - xdev->common.device_tx_status = xilinx_tx_status; - xdev->common.dev = &op->dev; - - dev_set_drvdata(&op->dev, xdev); - - for_each_child_of_node(node, child) { - xilinx_vdma_chan_probe(xdev, child, xdev->feature); - } - - for (i = 0; i < XILINX_VDMA_MAX_CHANS_PER_DEVICE; i++) { - if (xdev->chan[i]) - xdev->chan[i]->num_frms = num_frames; - } - - dma_async_device_register(&xdev->common); - - return 0; - -out_free_xdev: - kfree(xdev); - -out_return: - return err; -} - -static int __devexit xilinx_vdma_of_remove(struct platform_device *op) -{ - struct xilinx_vdma_device *xdev; - int i; - - xdev = dev_get_drvdata(&op->dev); - dma_async_device_unregister(&xdev->common); - - for (i = 0; i < XILINX_VDMA_MAX_CHANS_PER_DEVICE; i++) { - if (xdev->chan[i]) - xilinx_vdma_chan_remove(xdev->chan[i]); - } - - iounmap(xdev->regs); - dev_set_drvdata(&op->dev, NULL); - kfree(xdev); - - return 0; -} - -static const struct of_device_id xilinx_vdma_of_ids[] = { - { .compatible = "xlnx,axi-vdma",}, - {} -}; - -static struct platform_driver xilinx_vdma_of_driver = { - .driver = { - .name = "xilinx-vdma", - .owner = THIS_MODULE, - .of_match_table = xilinx_vdma_of_ids, - }, - .probe = xilinx_vdma_of_probe, - .remove = __devexit_p(xilinx_vdma_of_remove), -}; - -module_platform_driver(xilinx_vdma_of_driver); - -MODULE_AUTHOR("Xilinx, Inc."); -MODULE_DESCRIPTION("Xilinx VDMA driver"); -MODULE_LICENSE("GPL v2"); diff --git a/include/linux/amba/xilinx_dma.h b/include/linux/amba/xilinx_dma.h index dca98af4b77c6..751a74339821a 100644 --- a/include/linux/amba/xilinx_dma.h +++ b/include/linux/amba/xilinx_dma.h @@ -1,11 +1,12 @@ /* - * Xilinx DMA Engines support header file + * Xilinx Central DMA Engine support * * Copyright (C) 2010 Xilinx, Inc. All rights reserved. * * Based on the Freescale DMA driver. * * Description: + * This driver supports three Xilinx DMA engines: * . Axi CDMA engine, it does transfers between memory and memory, it * only has one channel. * . Axi DMA engine, it does transfers between memory and device. It can be @@ -30,57 +31,63 @@ #include #include -/* Specific hardware configuration-related constants */ -#define XILINX_DMA_NO_CHANGE 0xFFFF; +/* Specific hardware configuration-related constants + */ +#define XILINX_DMA_NO_CHANGE 0xFFFF; -/* DMA IP masks */ -#define XILINX_DMA_IP_DMA 0x00100000 /* A DMA IP */ -#define XILINX_DMA_IP_CDMA 0x00200000 /* A Central DMA IP */ -#define XILINX_DMA_IP_VDMA 0x00400000 /* A Video DMA IP */ -#define XILINX_DMA_IP_MASK 0x00700000 /* DMA IP MASK */ +/* DMA IP masks + */ +#define XILINX_DMA_IP_DMA 0x00100000 /* A DMA IP */ +#define XILINX_DMA_IP_CDMA 0x00200000 /* A Central DMA IP */ +#define XILINX_DMA_IP_VDMA 0x00400000 /* A Video DMA IP */ +#define XILINX_DMA_IP_MASK 0x00700000 /* DMA IP MASK */ -/* - * Device configuration structure +/* shared by all Xilinx DMA engines + */ +/* Device configuration structure + * + * Xilinx CDMA and Xilinx DMA only use interrupt coalescing and delay counter + * settings. * * If used to start/stop parking mode for Xilinx VDMA, vsize must be -1 * If used to set interrupt coalescing and delay counter only for - * Xilinx VDMA, hsize must be -1 - */ -struct xilinx_vdma_config { - enum dma_transfer_direction direction; - /* Channel direction */ - int vsize; /* Vertical size */ - int hsize; /* Horizontal size */ - int stride; /* Stride */ - int frm_dly; /* Frame delay */ - int gen_lock; /* Whether in gen-lock mode */ - int master; /* Master that it syncs to */ - int frm_cnt_en; /* Enable frame count enable */ - int park; /* Whether wants to park */ - int park_frm; /* Frame to park on */ - int coalesc; /* Interrupt coalescing threshold */ - int delay; /* Delay counter */ - int disable_intr; /* Whether use interrupts */ - int reset; /* Reset Channel */ - int ext_fsync; /* External Frame Sync */ + * Xilinx VDMA, hsize must be -1 */ +struct xilinx_dma_config { + enum dma_transfer_direction direction; /* Channel direction */ + int vsize; /* Vertical size */ + int hsize; /* Horizontal size */ + int stride; /* Stride */ + int frm_dly; /* Frame delay */ + int gen_lock; /* Whether in gen-lock mode */ + int master; /* Master that it syncs to */ + int frm_cnt_en; /* Enable frame count enable */ + int park; /* Whether wants to park */ + int park_frm; /* Frame to park on */ + int coalesc; /* Interrupt coalescing threshold */ + int delay; /* Delay counter */ + int disable_intr; /* Whether use interrupts */ + int reset; /* Reset Channel */ + int ext_fsync; /* External Frame Sync */ }; -/* Device configuration structure for DMA */ -struct xilinx_dma_config { - enum dma_transfer_direction direction; - /* Channel direction */ - int coalesc; /* Interrupt coalescing threshold */ - int delay; /* Delay counter */ - int reset; /* Reset Channel */ +/* Platform data definition until ARM supports device tree */ + +struct dma_channel_config { + char *type; + unsigned int lite_mode; /* cdma only */ + unsigned int include_dre; + unsigned int genlock_mode; /* vdma only */ + unsigned int datawidth; + unsigned int max_burst_len; }; -/* Device configuration structure for CDMA */ -struct xilinx_cdma_config { - enum dma_transfer_direction direction; - /* Channel direction */ - int coalesc; /* Interrupt coalescing threshold */ - int delay; /* Delay counter */ - int reset; /* Reset Channel */ +struct dma_device_config { + char *type; + unsigned int include_sg; + unsigned int num_fstores; /* vdma only */ + unsigned int sg_include_stscntrl_strm; /* dma only */ + unsigned int channel_count; + struct dma_channel_config *channel_config; }; #endif From 4264126d9cd4b65841c30216d373312f49b27196 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 6 Dec 2012 12:35:25 +0100 Subject: [PATCH 233/261] xilinx-usbps: Initialize ehci hcd before using it In ehci_xusbps_setup ehci_halt is called before ehci_init. This means that the initial ehci_halt call is working on a not completely initialized ehci hcd struct, which might cause undefined behavior. So make sure to call ehci_init before calling ehci_halt. This fixes also the following lockdep warning: INFO: trying to register non-static key. the code is fine but needs lockdep annotation. turning off the locking correctness validator. [] (unwind_backtrace+0x0/0xe0) from [] (__lock_acquire+0x1ac/0x19c0) [] (__lock_acquire+0x1ac/0x19c0) from [] (lock_acquire+0x60/0x74) [] (lock_acquire+0x60/0x74) from [] (_raw_spin_lock_irq+0x50/0x60) [] (_raw_spin_lock_irq+0x50/0x60) from [] (ehci_halt+0x14/0xd8) [] (ehci_halt+0x14/0xd8) from [] (ehci_xusbps_setup+0x58/0x41c) [] (ehci_xusbps_setup+0x58/0x41c) from [] (usb_add_hcd+0x194/0x5c0) [] (usb_add_hcd+0x194/0x5c0) from [] (ehci_xusbps_drv_probe+0x158/0x1e0) [] (ehci_xusbps_drv_probe+0x158/0x1e0) from [] (platform_drv_probe+0x14/0x18) ... Signed-off-by: Lars-Peter Clausen --- drivers/usb/host/ehci-xilinx-usbps.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/ehci-xilinx-usbps.c b/drivers/usb/host/ehci-xilinx-usbps.c index b5a00904bd8ae..51343060560a4 100644 --- a/drivers/usb/host/ehci-xilinx-usbps.c +++ b/drivers/usb/host/ehci-xilinx-usbps.c @@ -344,12 +344,12 @@ static int ehci_xusbps_setup(struct usb_hcd *hcd) hcd->has_tt = 1; - retval = ehci_halt(ehci); + /* data structure init */ + retval = ehci_init(hcd); if (retval) return retval; - /* data structure init */ - retval = ehci_init(hcd); + retval = ehci_halt(ehci); if (retval) return retval; From f518f7350a83aae2b21c31452dc99554d1ec1f95 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 6 Dec 2012 14:37:19 +0100 Subject: [PATCH 234/261] usb: ehci: Fix ulpi type in the ehci_hcd struct Looks like this was missed during earlier conversions of the ZED USB fixes to usb_phy. Fixes the follow warnings: drivers/usb/host/ehci-hcd.c: In function 'ehci_run': drivers/usb/host/ehci-hcd.c:676:25: warning: initialization from incompatible pointer type In file included from drivers/usb/host/ehci-hcd.c:1300:0: drivers/usb/host/ehci-xilinx-usbps.c: In function 'usb_hcd_xusbps_probe': drivers/usb/host/ehci-xilinx-usbps.c:204:15: warning: assignment from incompatible pointer type Signed-off-by: Lars-Peter Clausen --- drivers/usb/host/ehci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 0a19e479d3c5d..6b6cbbc544f4d 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -180,7 +180,7 @@ struct ehci_hcd { /* one per controller */ */ void (*start_hnp)(struct ehci_hcd *ehci); #ifdef CONFIG_XILINX_ZED_USB_OTG - struct otg_transceiver *ulpi; + struct usb_phy *ulpi; #endif #endif From 1ccdef7c777d8cc61bac1945b5acdeb47343a902 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 6 Dec 2012 16:27:15 +0100 Subject: [PATCH 235/261] xcomm_adv7511_defconfig: Update to v3.6 Update the zync_xcomm_adv7511_defconfig to v3.6. Signed-off-by: Lars-Peter Clausen --- arch/arm/configs/zync_xcomm_adv7511_defconfig | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/arch/arm/configs/zync_xcomm_adv7511_defconfig b/arch/arm/configs/zync_xcomm_adv7511_defconfig index 1e6baa7489da2..e7f6390810d05 100644 --- a/arch/arm/configs/zync_xcomm_adv7511_defconfig +++ b/arch/arm/configs/zync_xcomm_adv7511_defconfig @@ -22,6 +22,7 @@ CONFIG_MODVERSIONS=y CONFIG_ARCH_ZYNQ=y CONFIG_ZYNQ_EARLY_UART1=y # CONFIG_ZYNQ_EARLY_UART_EP107 is not set +CONFIG_XILINX_FIXED_DEVTREE_ADDR=y CONFIG_XILINX_ZED=y CONFIG_SMP=y CONFIG_PREEMPT=y @@ -65,7 +66,7 @@ CONFIG_MTD_PHYSMAP_OF=y CONFIG_MTD_M25P80=y # CONFIG_M25PXX_USE_FAST_READ is not set CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_XILINX_PSS=y +CONFIG_MTD_NAND_XILINX_PS=y CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y @@ -116,12 +117,6 @@ CONFIG_GPIO_XILINX_PS=y # CONFIG_HWMON is not set CONFIG_WATCHDOG=y CONFIG_MEDIA_SUPPORT=y -CONFIG_VIDEO_DEV=y -# CONFIG_RC_CORE is not set -# CONFIG_MEDIA_TUNER_CUSTOMISE is not set -CONFIG_USB_VIDEO_CLASS=y -CONFIG_USB_GSPCA=y -# CONFIG_RADIO_ADAPTERS is not set CONFIG_DRM=y CONFIG_DRM_ENCODER_ADV7511=y CONFIG_DRM_ANALOG=y @@ -207,7 +202,7 @@ CONFIG_USB_EHCI_XUSBPS=y CONFIG_USB_STORAGE=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_XUSBPS=y -CONFIG_USB_XUSBPS_OTG=y +CONFIG_XILINX_ZED_USB_OTG=y CONFIG_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y From f4fb5ffd8f36a947c3e1aaf32bfe6bd6de16ba2c Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 6 Dec 2012 18:17:11 +0100 Subject: [PATCH 236/261] platform: zynq zed xcomm: fix cal eeprom slave addr Signed-off-by: Michael Hennerich --- arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts index 976f7ca753f61..988d90db9154b 100644 --- a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts +++ b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts @@ -124,13 +124,14 @@ }; }; + eeprom@50 { compatible = "at24,24c02"; reg = <0x50>; }; - eeprom@55 { + eeprom@54 { compatible = "at24,24c02"; - reg = <0x55>; + reg = <0x54>; }; }; From ef285f0dff30ccd7c9f71e462dfa0c122121d835 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Tue, 18 Dec 2012 12:15:47 -0800 Subject: [PATCH 237/261] PMOD: GPL License Header Added --- drivers/pmods/pmodad1.c | 20 +++++++++++++++++++- drivers/pmods/pmodclp.c | 21 +++++++++++++++++++++ drivers/pmods/pmodcls.c | 21 +++++++++++++++++++++ drivers/pmods/pmodda1.c | 20 +++++++++++++++++++- drivers/pmods/pmodoled-gpio.c | 21 +++++++++++++++++++++ 5 files changed, 101 insertions(+), 2 deletions(-) diff --git a/drivers/pmods/pmodad1.c b/drivers/pmods/pmodad1.c index 2be75c8cd36ca..0597c78179385 100644 --- a/drivers/pmods/pmodad1.c +++ b/drivers/pmods/pmodad1.c @@ -1,6 +1,24 @@ /* - * PmodAD1 linux driver for Zed + * pmodad1.c - Digilent PmodAD1 driver + * + * Copyright (c) 2012 Digilent. All right reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * */ + #include #include #include diff --git a/drivers/pmods/pmodclp.c b/drivers/pmods/pmodclp.c index 5c87ad1145873..896362624400b 100644 --- a/drivers/pmods/pmodclp.c +++ b/drivers/pmods/pmodclp.c @@ -1,3 +1,24 @@ +/* + * pmodclp.c - Digilent PmodCLP driver + * + * Copyright (c) 2012 Digilent. All right reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + #include #include #include diff --git a/drivers/pmods/pmodcls.c b/drivers/pmods/pmodcls.c index 8a812976c5eef..17ec2d7c066df 100644 --- a/drivers/pmods/pmodcls.c +++ b/drivers/pmods/pmodcls.c @@ -1,3 +1,24 @@ +/* + * pmodcls.c - Digilent PmodCLS driver + * + * Copyright (c) 2012 Digilent. All right reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + #include #include #include diff --git a/drivers/pmods/pmodda1.c b/drivers/pmods/pmodda1.c index 1912c09cb2cdb..581a5ea319cc4 100644 --- a/drivers/pmods/pmodda1.c +++ b/drivers/pmods/pmodda1.c @@ -1,6 +1,24 @@ /* - * Digilent PmodDA1 linux driver for Zed + * pmodda1.c - Digilent PmodDA1 driver + * + * Copyright (c) 2012 Digilent. All right reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * */ + #include #include #include diff --git a/drivers/pmods/pmodoled-gpio.c b/drivers/pmods/pmodoled-gpio.c index 6c03c0c2a8e39..59550bf6a1e2e 100644 --- a/drivers/pmods/pmodoled-gpio.c +++ b/drivers/pmods/pmodoled-gpio.c @@ -1,3 +1,24 @@ +/* + * pmodolde-gpio.c - PmodOLED-GPIO driver + * + * Copyright (c) 2012 Digilent. All right reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + #include #include #include From f7202e6a91d5b58994b54330d51aa1e8d5625245 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 20 Dec 2012 14:19:07 +0100 Subject: [PATCH 238/261] zynq-zc702-adv7511.dts: Update device tree Likewise Commit abdb1e4419a1b4d3ac4032491c9e7a522dab8acd ASoC: adv7511_hdmi: Get codec adapter from devicetree Signed-off-by: Michael Hennerich --- arch/arm/boot/dts/zynq-zc702-adv7511.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/zynq-zc702-adv7511.dts b/arch/arm/boot/dts/zynq-zc702-adv7511.dts index 56ff4393cf1a9..1f61c2b9f2985 100644 --- a/arch/arm/boot/dts/zynq-zc702-adv7511.dts +++ b/arch/arm/boot/dts/zynq-zc702-adv7511.dts @@ -211,7 +211,7 @@ adv7511_hdmi_snd: adv7511_hdmi_snd { compatible = "adv7511-hdmi-snd"; - audio-codec = <&i2c_adv7511>; + audio-codec-adapter = <&i2c_adv7511>; cpu-dai = <&axi_spdif_tx_0>; pcm = <&xilinx_pcm_audio>; }; From 4abc427d6f5243a394c9707b3ad9b2b543d428b0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 11 Jun 2012 18:46:39 +0200 Subject: [PATCH 239/261] ASoC: dmaengine-pcm: Rename and deprecate snd_dmaengine_pcm_pointer Currently the sound dmaengine pcm helper functions implement the pcm_pointer callback by trying to count the number of elapsed periods. This is done by advancing the stream position in the dmaengine callback by one period. Unfortunately there is no guarantee that the callback will be called for each elapsed period. It may be possible that under high system load it is only called once for multiple elapsed periods. This patch renames the current implementation and documents its shortcomings and that it should not be used anymore in new drivers. The next patch will introduce a new snd_dmaengine_pcm_pointer which will be implemented based on querying the current stream position from the dma device. Signed-off-by: Lars-Peter Clausen --- include/sound/dmaengine_pcm.h | 1 + sound/soc/soc-dmaengine-pcm.c | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h index 129783da65876..7f3f9088824ad 100644 --- a/include/sound/dmaengine_pcm.h +++ b/include/sound/dmaengine_pcm.h @@ -38,6 +38,7 @@ void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream); int snd_soc_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config); int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream); snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream); int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c index 643147ef885fe..9e844e192d57c 100644 --- a/sound/soc/soc-dmaengine-pcm.c +++ b/sound/soc/soc-dmaengine-pcm.c @@ -193,18 +193,18 @@ int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger); /** - * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation + * snd_dmaengine_pcm_pointer_no_residue - dmaengine based PCM pointer implementation * @substream: PCM substream * - * This function can be used as the PCM pointer callback for dmaengine based PCM - * driver implementations. + * This function is deprecated and should not be used by new drivers, as it's + * results may be unreliable. */ -snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream) { struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); return bytes_to_frames(substream->runtime, prtd->pos); } -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue); static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd, dma_filter_fn filter_fn, void *filter_data) From fd73d0e182d9f1e38795247724880b31918339f5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 13 Jun 2012 17:37:37 +0200 Subject: [PATCH 240/261] ASoC: dmaengine-pcm: Add support for querying stream position from DMA driver Currently the sound dmaengine pcm helper functions implement the pcm_pointer callback by trying to count the number of elapsed periods. This is done by advancing the stream position in the dmaengine callback by one period. Unfortunately there is no guarantee that the callback will be called for each elapsed period. It may be possible that under high system load it is only called once for multiple elapsed periods. This patch addresses the issue by implementing support for querying the current stream position directly from the dmaengine driver. Since not all dmaengine drivers support reporting the stream position yet the old period counting implementation is kept for now. Furthermore the new mechanism allows to report the stream position with a sub-period granularity, given that the dmaengine driver supports this. Signed-off-by: Lars-Peter Clausen Signed-off-by: Tinghui WANG (Steven) --- include/sound/dmaengine_pcm.h | 2 +- sound/soc/soc-dmaengine-pcm.c | 29 ++++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h index 7f3f9088824ad..ac993188adbd9 100644 --- a/include/sound/dmaengine_pcm.h +++ b/include/sound/dmaengine_pcm.h @@ -38,8 +38,8 @@ void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream); int snd_soc_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream, const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config); int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd); -snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream); snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream); +snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream); int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, dma_filter_fn filter_fn, void *filter_data); diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c index 9e844e192d57c..f41596d1daa97 100644 --- a/sound/soc/soc-dmaengine-pcm.c +++ b/sound/soc/soc-dmaengine-pcm.c @@ -30,6 +30,7 @@ struct dmaengine_pcm_runtime_data { struct dma_chan *dma_chan; + dma_cookie_t cookie; unsigned int pos; @@ -146,7 +147,7 @@ static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) desc->callback = dmaengine_pcm_dma_complete; desc->callback_param = substream; - dmaengine_submit(desc); + prtd->cookie = dmaengine_submit(desc); return 0; } @@ -206,6 +207,32 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream } EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue); +/** + * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation + * @substream: PCM substream + * + * This function can be used as the PCM pointer callback for dmaengine based PCM + * driver implementations. + */ +snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct dma_tx_state state; + enum dma_status status; + unsigned int buf_size; + unsigned int pos = 0; + + status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); + if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) { + buf_size = snd_pcm_lib_buffer_bytes(substream); + if (state.residue > 0 && state.residue <= buf_size) + pos = buf_size - state.residue; + } + + return bytes_to_frames(substream->runtime, pos); +} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); + static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd, dma_filter_fn filter_fn, void *filter_data) { From 174f0aa21cd25d37e615098064fa787eb36766eb Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 3 Nov 2011 14:04:25 +0100 Subject: [PATCH 241/261] ASoC: Add ADAU1X61 and ADAU1X81 CODECs common code The ADAU1X61 and ADAU1X81 are very similar in the digital domain of the CODECs, but are quite different in the analog domain. This patch adds support for the common parts of the ADAU161 and ADAU181 CODECs. Signed-off-by: Lars-Peter Clausen Signed-off-by: Tinghui WANG (Steven) --- include/sound/adau17x1.h | 23 + sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/adau17x1.c | 861 ++++++++++++++++++++++++++++++++++++ sound/soc/codecs/adau17x1.h | 124 ++++++ 5 files changed, 1014 insertions(+) create mode 100644 include/sound/adau17x1.h create mode 100644 sound/soc/codecs/adau17x1.c create mode 100644 sound/soc/codecs/adau17x1.h diff --git a/include/sound/adau17x1.h b/include/sound/adau17x1.h new file mode 100644 index 0000000000000..5ab9ba0cc4f0a --- /dev/null +++ b/include/sound/adau17x1.h @@ -0,0 +1,23 @@ +/* + * Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961/ADAU1781/ADAU1781 codecs + * + * Copyright 2011 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __SOUND_ADAU17X1_H__ +#define __SOUND_ADAU17X1_H__ + +/** + * enum adau17x1_micbias_voltage - Microphone bias voltage + * @ADAU17X1_MICBIAS_0_90_AVDD: 0.9 * AVDD + * @ADAU17X1_MICBIAS_0_65_AVDD: 0.65 * AVDD + */ +enum adau17x1_micbias_voltage { + ADAU17X1_MICBIAS_0_90_AVDD = 0, + ADAU17X1_MICBIAS_0_65_AVDD = 1, +}; + +#endif diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 7c205e77d83aa..3a93506f8dc0f 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -147,6 +147,10 @@ config SND_SOC_ADAU1701 config SND_SOC_ADAU1373 tristate +config SND_SOC_ADAU17X1 + select SND_SOC_SIGMADSP + tristate + config SND_SOC_ADAV80X tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index de8078178f86b..297ec12539a4b 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -6,6 +6,7 @@ snd-soc-ad1980-objs := ad1980.o snd-soc-ad73311-objs := ad73311.o snd-soc-adau1701-objs := adau1701.o snd-soc-adau1373-objs := adau1373.o +snd-soc-adau17x1-objs := adau17x1.o snd-soc-adav80x-objs := adav80x.o snd-soc-ads117x-objs := ads117x.o snd-soc-ak4104-objs := ak4104.o @@ -108,6 +109,7 @@ obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o +obj-$(CONFIG_SND_SOC_ADAU17X1) += snd-soc-adau17x1.o obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c new file mode 100644 index 0000000000000..7e2a1a6106814 --- /dev/null +++ b/sound/soc/codecs/adau17x1.c @@ -0,0 +1,861 @@ +/* + * Common code for ADAU1X61 and ADAU1X81 codecs + * + * Copyright 2011 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sigmadsp.h" +#include "adau17x1.h" + +static const char * const adau17x1_capture_mixer_boost_text[] = { + "Normal operation", "Boost Level 1", "Boost Level 2", "Boost Level 3", +}; + +static const SOC_ENUM_SINGLE_DECL(adau17x1_capture_boost_enum, + ADAU17X1_REC_POWER_MGMT, 5, adau17x1_capture_mixer_boost_text); + +static const char *const adau17x1_mic_bias_mode_text[] = { + "Normal operation", "High performance", +}; + +static SOC_ENUM_SINGLE_DECL(adau17x1_mic_bias_mode_enum, + ADAU17X1_MICBIAS, 3, adau17x1_mic_bias_mode_text); + +static const char * const adau17x1_mono_stereo_text[] = { + "Stereo", + "Mono Left Channel (L+R)", + "Mono Right Channel (L+R)", + "Mono (L+R)", +}; + +static const SOC_ENUM_SINGLE_DECL(adau17x1_dac_mode_enum, + ADAU17X1_DAC_CONTROL0, 6, adau17x1_mono_stereo_text); + +static const DECLARE_TLV_DB_MINMAX(adau17x1_digital_tlv, -9563, 0); + +static const struct snd_kcontrol_new adau17x1_controls[] = { + SOC_DOUBLE_R_TLV("Digital Capture Volume", + ADAU17X1_LEFT_INPUT_DIGITAL_VOL, ADAU17X1_RIGHT_INPUT_DIGITAL_VOL, + 0, 0xff, 1, adau17x1_digital_tlv), + SOC_DOUBLE_R_TLV("Digital Playback Volume", ADAU17X1_DAC_CONTROL1, + ADAU17X1_DAC_CONTROL2, 0, 0xff, 1, adau17x1_digital_tlv), + + SOC_SINGLE("ADC High Pass Filter Switch", ADAU17X1_ADC_CONTROL, + 5, 1, 0), + SOC_SINGLE("Playback De-emphasis Switch", ADAU17X1_DAC_CONTROL0, + 2, 1, 0), + + SOC_ENUM("Capture Boost", adau17x1_capture_boost_enum), + + SOC_ENUM("Mic Bias Mode", adau17x1_mic_bias_mode_enum), + + SOC_ENUM("DAC Mono Stereo", adau17x1_dac_mode_enum), +}; + +static int adau17x1_pll_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct adau *adau = snd_soc_codec_get_drvdata(w->codec); + int ret; + + if (SND_SOC_DAPM_EVENT_ON(event)) { + adau->pll_regs[5] = 1; + } else { + adau->pll_regs[5] = 0; + /* Bypass the PLL when disabled, otherwise registers will become + * inaccessible. */ + regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL, + ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL, 0); + } + + /* The PLL register is 6 bytes long and can only be written at once. */ + ret = regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL, + adau->pll_regs, ARRAY_SIZE(adau->pll_regs)); + + if (SND_SOC_DAPM_EVENT_ON(event)) { + mdelay(5); + regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL, + ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL, + ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL); + } + + return 0; +} + +static const struct snd_soc_dapm_widget adau17x1_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY_S("PLL", 0, SND_SOC_NOPM, 0, 0, adau17x1_pll_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY("AIFCLK", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("MICBIAS", ADAU17X1_MICBIAS, 0, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("Left Playback Enable", ADAU17X1_PLAY_POWER_MGMT, + 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Right Playback Enable", ADAU17X1_PLAY_POWER_MGMT, + 1, 0, NULL, 0), + + SND_SOC_DAPM_DAC("Left DAC", NULL, ADAU17X1_DAC_CONTROL0, 0, 0), + SND_SOC_DAPM_DAC("Right DAC", NULL, ADAU17X1_DAC_CONTROL0, 1, 0), + SND_SOC_DAPM_ADC("Left ADC", NULL, ADAU17X1_ADC_CONTROL, 0, 0), + SND_SOC_DAPM_ADC("Right ADC", NULL, ADAU17X1_ADC_CONTROL, 1, 0), + + SND_SOC_DAPM_AIF_OUT("AIFOUT", "Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("AIFIN", "Playback", 0, SND_SOC_NOPM, 0, 0), +}; + +static int adau17x1_check_sysclk_pll(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct adau *adau = snd_soc_codec_get_drvdata(source->codec); + + return adau->clk_src == ADAU17X1_CLK_SRC_PLL; +} + +static const struct snd_soc_dapm_route adau17x1_dapm_routes[] = { + { "SYSCLK", NULL, "PLL", adau17x1_check_sysclk_pll }, + + { "Left ADC", NULL, "SYSCLK" }, + { "Right ADC", NULL, "SYSCLK" }, + { "Left DAC", NULL, "SYSCLK" }, + { "Right DAC", NULL, "SYSCLK" }, + { "AIFOUT", NULL, "SYSCLK" }, + { "AIFIN", NULL, "SYSCLK" }, + + { "AIFOUT", NULL, "AIFCLK" }, + { "AIFIN", NULL, "AIFCLK" }, + + { "Left DAC", NULL, "AIFIN" }, + { "Right DAC", NULL, "AIFIN" }, +}; + +static int adau17x1_check_dsp_caputure(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct adau *adau = snd_soc_codec_get_drvdata(source->codec); + + return !adau->dsp_capture_bypass; +} + +static int adau17x1_check_dsp_playback(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct adau *adau = snd_soc_codec_get_drvdata(source->codec); + + return !adau->dsp_playback_bypass; +} + +/* This is not exacly by the book. It would be better to provide MIXER or MUX + * widgets for the DSP capture and playback path. */ +static const struct snd_soc_dapm_widget adau17x1_dsp_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("DSP", ADAU17X1_DSP_RUN, 0, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_route adau17x1_dsp_dapm_routes[] = { + { "AIFOUT", NULL, "DSP", adau17x1_check_dsp_caputure }, + { "AIFIN", NULL, "DSP", adau17x1_check_dsp_playback }, +}; + +static int adau17x1_dsp_bypass_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct adau *adau = snd_soc_codec_get_drvdata(codec); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + bool bypass = ucontrol->value.integer.value[0]; + unsigned int tdm_slot; + + switch (mc->reg) { + case ADAU17X1_SERIAL_INPUT_ROUTE: + adau->dsp_playback_bypass = bypass; + tdm_slot = adau->tdm_dac_slot; + break; + case ADAU17X1_SERIAL_OUTPUT_ROUTE: + adau->dsp_capture_bypass = bypass; + tdm_slot = adau->tdm_adc_slot; + break; + default: + return -EINVAL; + } + + if (bypass) + regmap_write(adau->regmap, mc->reg, (tdm_slot * 2) + 1); + else + regmap_write(adau->regmap, mc->reg, 0x00); + + return 0; +} + +static int adau17x1_dsp_bypass_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct adau *adau = snd_soc_codec_get_drvdata(codec); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + bool bypass; + + switch (mc->reg) { + case ADAU17X1_SERIAL_INPUT_ROUTE: + bypass = adau->dsp_playback_bypass; + break; + case ADAU17X1_SERIAL_OUTPUT_ROUTE: + bypass = adau->dsp_capture_bypass; + break; + default: + return -EINVAL; + } + + ucontrol->value.integer.value[0] = bypass; + + return 0; +} + +static const struct snd_kcontrol_new adau17x1_dsp_controls[] = { + SOC_SINGLE_EXT("DSP Bypass Playback Switch", ADAU17X1_SERIAL_INPUT_ROUTE, + 0, 1, 0, adau17x1_dsp_bypass_get, adau17x1_dsp_bypass_put), + SOC_SINGLE_EXT("DSP Bypass Capture Switch", ADAU17X1_SERIAL_OUTPUT_ROUTE, + 0, 1, 0, adau17x1_dsp_bypass_get, adau17x1_dsp_bypass_put), +}; + +static void adau17x1_check_aifclk(struct snd_soc_codec *codec) +{ + struct adau *adau = snd_soc_codec_get_drvdata(codec); + + /* If we are in master mode we need to generate bit- and frameclock, + * regardless of whether the AIF itself is powered or not */ + if (codec->active && adau->master) + snd_soc_dapm_force_enable_pin(&codec->dapm, "AIFCLK"); + else + snd_soc_dapm_disable_pin(&codec->dapm, "AIFCLK"); + snd_soc_dapm_sync(&codec->dapm); +} + +static bool adau17x1_has_dsp(struct adau *adau) +{ + switch (adau->type) { + case ADAU1761: + case ADAU1381: + case ADAU1781: + return true; + default: + return false; + } +} + +static int adau17x1_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct adau *adau = snd_soc_codec_get_drvdata(codec); + unsigned int val, div, dsp_div; + unsigned int freq; + + if (adau->clk_src == ADAU17X1_CLK_SRC_PLL) + freq = adau->pll_freq; + else + freq = adau->sysclk / adau->sysclk_div; + + if (freq % params_rate(params) != 0) + return -EINVAL; + + switch (freq / params_rate(params)) { + case 1024: /* fs */ + div = 0; + dsp_div = 1; + break; + case 6144: /* fs / 6 */ + div = 1; + dsp_div = 6; + break; + case 4096: /* fs / 4 */ + div = 2; + dsp_div = 5; + break; + case 3072: /* fs / 3 */ + div = 3; + dsp_div = 4; + break; + case 2048: /* fs / 2 */ + div = 4; + dsp_div = 3; + break; + case 1536: /* fs / 1.5 */ + div = 5; + dsp_div = 2; + break; + case 512: /* fs / 0.5 */ + div = 6; + dsp_div = 0; + break; + default: + return -EINVAL; + } + + regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0, 7, div); + if (adau17x1_has_dsp(adau)) { + regmap_write(adau->regmap, ADAU17X1_SERIAL_SAMPLING_RATE, div); + regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dsp_div); + } + + adau17x1_check_aifclk(codec); + + if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J) + return 0; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + val = ADAU17X1_SERIAL_PORT1_DELAY16; + break; + case SNDRV_PCM_FORMAT_S24_LE: + val = ADAU17X1_SERIAL_PORT1_DELAY8; + break; + case SNDRV_PCM_FORMAT_S32_LE: + val = ADAU17X1_SERIAL_PORT1_DELAY0; + break; + default: + return -EINVAL; + } + + return regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT1, + ADAU17X1_SERIAL_PORT1_DELAY_MASK, val); +} + +static int adau17x1_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + adau17x1_check_aifclk(dai->codec); + + return 0; +} + +static void adau17x1_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + adau17x1_check_aifclk(dai->codec); +} + +static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id, + int source, unsigned int freq_in, unsigned int freq_out) +{ + struct snd_soc_codec *codec = dai->codec; + struct adau *adau = snd_soc_codec_get_drvdata(codec); + unsigned int div; + unsigned int r, n, m, i, j; + + if (freq_in < 8000000 || freq_in > 27000000) + return -EINVAL; + + if (!freq_out) { + r = 0; + n = 0; + m = 0; + div = 0; + } else { + if (freq_out % freq_in != 0) { + div = DIV_ROUND_UP(freq_in, 13500000); + freq_in /= div; + r = freq_out / freq_in; + i = freq_out % freq_in; + j = gcd(i, freq_in); + n = i / j; + m = freq_in / j; + div--; + } else { + r = freq_out / freq_in; + n = 0; + m = 0; + div = 0; + } + if (n > 0xffff || m > 0xffff || div > 3 || r > 8 || r < 2) + return -EINVAL; + } + + adau->pll_regs[0] = m >> 8; + adau->pll_regs[1] = m & 0xff; + adau->pll_regs[2] = n >> 8; + adau->pll_regs[3] = n & 0xff; + adau->pll_regs[4] = (r << 3) | (div << 1); + if (m != 0) + adau->pll_regs[4] |= 1; /* Fractional mode */ + adau->pll_regs[5] = 0; + + adau->pll_freq = freq_out; + + return 0; +} + +static int adau17x1_set_dai_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct adau *adau = snd_soc_codec_get_drvdata(dai->codec); + + switch (clk_id) { + case ADAU17X1_CLK_SRC_MCLK: + case ADAU17X1_CLK_SRC_PLL: + break; + default: + return -EINVAL; + } + + adau->sysclk = freq; + adau->clk_src = clk_id; + + return 0; +} + +static int adau17x1_set_dai_clkdiv(struct snd_soc_dai *dai, int div_id, int div) +{ + struct adau *adau = snd_soc_codec_get_drvdata(dai->codec); + + switch (div) { + case 1: + case 2: + case 3: + case 4: + break; + default: + return -EINVAL; + } + + adau->sysclk_div = div; + + return regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL, + ADAU17X1_CLOCK_CONTROL_INFREQ_MASK, (div - 1) << 1); +} + +static int adau17x1_set_dai_fmt(struct snd_soc_dai *dai, + unsigned int fmt) +{ + struct adau *adau = snd_soc_codec_get_drvdata(dai->codec); + unsigned int ctrl0, ctrl1; + int lrclk_pol; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + ctrl0 = ADAU17X1_SERIAL_PORT0_MASTER; + adau->master = true; + break; + case SND_SOC_DAIFMT_CBS_CFS: + ctrl0 = 0; + adau->master = false; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + lrclk_pol = 0; + ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY1; + break; + case SND_SOC_DAIFMT_LEFT_J: + case SND_SOC_DAIFMT_RIGHT_J: + lrclk_pol = 1; + ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY0; + break; + case SND_SOC_DAIFMT_DSP_A: + lrclk_pol = 1; + ctrl0 |= ADAU17X1_SERIAL_PORT0_PULSE_MODE; + ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY1; + break; + case SND_SOC_DAIFMT_DSP_B: + lrclk_pol = 1; + ctrl0 |= ADAU17X1_SERIAL_PORT0_PULSE_MODE; + ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY0; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_NF: + ctrl0 |= ADAU17X1_SERIAL_PORT0_BCLK_POL; + break; + case SND_SOC_DAIFMT_NB_IF: + lrclk_pol = !lrclk_pol; + break; + case SND_SOC_DAIFMT_IB_IF: + ctrl0 |= ADAU17X1_SERIAL_PORT0_BCLK_POL; + lrclk_pol = !lrclk_pol; + break; + default: + return -EINVAL; + } + + if (lrclk_pol) + ctrl0 |= ADAU17X1_SERIAL_PORT0_LRCLK_POL; + + regmap_write(adau->regmap, ADAU17X1_SERIAL_PORT0, ctrl0); + regmap_write(adau->regmap, ADAU17X1_SERIAL_PORT1, ctrl1); + + adau->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; + + return 0; +} + +static int adau17x1_set_dai_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) +{ + struct adau *adau = snd_soc_codec_get_drvdata(dai->codec); + unsigned int ser_ctrl0, ser_ctrl1; + unsigned int conv_ctrl0, conv_ctrl1; + + /* I2S mode */ + if (slots == 0) { + slots = 2; + rx_mask = 3; + tx_mask = 3; + slot_width = 32; + } + + switch (slots) { + case 2: + ser_ctrl0 = ADUA_SERIAL_PORT0_STEREO; + break; + case 4: + ser_ctrl0 = ADUA_SERIAL_PORT0_TDM4; + break; + case 8: + if (adau->type == ADAU1361) + return -EINVAL; + + ser_ctrl0 = ADUA_SERIAL_PORT0_TDM8; + break; + default: + return -EINVAL; + } + + switch (slot_width * slots) { + case 32: + if (adau->type == ADAU1761) + return -EINVAL; + + ser_ctrl1 = ADUA_SERIAL_PORT1_BCLK32; + break; + case 64: + ser_ctrl1 = ADUA_SERIAL_PORT1_BCLK64; + break; + case 48: + ser_ctrl1 = ADUA_SERIAL_PORT1_BCLK48; + break; + case 128: + ser_ctrl1 = ADUA_SERIAL_PORT1_BCLK128; + break; + case 256: + if (adau->type == ADAU1361) + return -EINVAL; + + ser_ctrl1 = ADUA_SERIAL_PORT1_BCLK256; + break; + default: + return -EINVAL; + } + + switch (rx_mask) { + case 0x03: + conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(1); + adau->tdm_adc_slot = 0; + break; + case 0x0c: + conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(2); + adau->tdm_adc_slot = 1; + break; + case 0x30: + conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(3); + adau->tdm_adc_slot = 2; + break; + case 0xc0: + conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(4); + adau->tdm_adc_slot = 3; + break; + default: + return -EINVAL; + } + + switch (tx_mask) { + case 0x03: + conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(1); + adau->tdm_dac_slot = 0; + break; + case 0x0c: + conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(2); + adau->tdm_dac_slot = 1; + break; + case 0x30: + conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(3); + adau->tdm_dac_slot = 2; + break; + case 0xc0: + conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(4); + adau->tdm_dac_slot = 3; + break; + default: + return -EINVAL; + } + + regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0, + ADAU17X1_CONVERTER0_DAC_PAIR_MASK, conv_ctrl0); + regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER1, + ADAU17X1_CONVERTER1_ADC_PAIR_MASK, conv_ctrl1); + regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT0, + ADAU17X1_SERIAL_PORT0_TDM_MASK, ser_ctrl0); + regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT1, + ADAU17X1_SERIAL_PORT1_BCLK_MASK, ser_ctrl1); + + if (adau17x1_has_dsp(adau)) { + if (adau->dsp_playback_bypass) { + regmap_write(adau->regmap, ADAU17X1_SERIAL_INPUT_ROUTE, + (adau->tdm_dac_slot * 2) + 1); + } + if (adau->dsp_capture_bypass) { + regmap_write(adau->regmap, ADAU17X1_SERIAL_OUTPUT_ROUTE, + (adau->tdm_adc_slot * 2) + 1); + } + } + + return 0; +} + +const struct snd_soc_dai_ops adau17x1_dai_ops = { + .hw_params = adau17x1_hw_params, + .set_sysclk = adau17x1_set_dai_sysclk, + .set_fmt = adau17x1_set_dai_fmt, + .set_pll = adau17x1_set_dai_pll, + .set_clkdiv = adau17x1_set_dai_clkdiv, + .set_tdm_slot = adau17x1_set_dai_tdm_slot, + .startup = adau17x1_dai_startup, + .shutdown = adau17x1_dai_shutdown, +}; +EXPORT_SYMBOL_GPL(adau17x1_dai_ops); + +int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec, + enum adau17x1_micbias_voltage micbias) +{ + struct adau *adau = snd_soc_codec_get_drvdata(codec); + + switch (micbias) { + case ADAU17X1_MICBIAS_0_90_AVDD: + case ADAU17X1_MICBIAS_0_65_AVDD: + break; + default: + return -EINVAL; + } + + regmap_write(adau->regmap, ADAU17X1_MICBIAS, micbias << 2); + + return 0; +} +EXPORT_SYMBOL_GPL(adau17x1_set_micbias_voltage); + +bool adau17x1_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ADAU17X1_CLOCK_CONTROL: + case ADAU17X1_PLL_CONTROL: + case ADAU17X1_REC_POWER_MGMT: + case ADAU17X1_MICBIAS: + case ADAU17X1_SERIAL_PORT0: + case ADAU17X1_SERIAL_PORT1: + case ADAU17X1_CONVERTER0: + case ADAU17X1_CONVERTER1: + case ADAU17X1_LEFT_INPUT_DIGITAL_VOL: + case ADAU17X1_RIGHT_INPUT_DIGITAL_VOL: + case ADAU17X1_ADC_CONTROL: + case ADAU17X1_PLAY_POWER_MGMT: + case ADAU17X1_DAC_CONTROL0: + case ADAU17X1_DAC_CONTROL1: + case ADAU17X1_DAC_CONTROL2: + case ADAU17X1_SERIAL_PORT_PAD: + case ADAU17X1_CONTROL_PORT_PAD0: + case ADAU17X1_CONTROL_PORT_PAD1: + case ADAU17X1_DSP_SAMPLING_RATE: + case ADAU17X1_SERIAL_INPUT_ROUTE: + case ADAU17X1_SERIAL_OUTPUT_ROUTE: + case ADAU17X1_DSP_ENABLE: + case ADAU17X1_DSP_RUN: + case ADAU17X1_SERIAL_SAMPLING_RATE: + return true; + default: + break; + } + return false; +} +EXPORT_SYMBOL_GPL(adau17x1_readable_register); + +bool adau17x1_volatile_register(struct device *dev, unsigned int reg) +{ + /* SigmaDSP parameter and program memory */ + if (reg < 0x4000) + return true; + + switch (reg) { + /* The PLL register is 6 bytes long */ + case ADAU17X1_PLL_CONTROL: + case ADAU17X1_PLL_CONTROL + 1: + case ADAU17X1_PLL_CONTROL + 2: + case ADAU17X1_PLL_CONTROL + 3: + case ADAU17X1_PLL_CONTROL + 4: + case ADAU17X1_PLL_CONTROL + 5: + return true; + default: + break; + } + + return false; +} +EXPORT_SYMBOL_GPL(adau17x1_volatile_register); + +int adau17x1_load_firmware(struct adau *adau, struct device *dev, + const char *firmware) +{ + int ret; + int dspsr; + + ret = regmap_read(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, &dspsr); + if (ret) + return ret; + + regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 1); + regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, 0xf); + + ret = process_sigma_firmware_regmap(dev, adau->regmap, + firmware); + if (ret) { + regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 0); + return ret; + } + regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dspsr); + + return 0; +} +EXPORT_SYMBOL_GPL(adau17x1_load_firmware); + +int adau17x1_probe(struct snd_soc_codec *codec) +{ + struct adau *adau = snd_soc_codec_get_drvdata(codec); + int ret; + + /* TODO: Remove next line */ + codec->control_data = adau->regmap; + ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; + } + + codec->driver->set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + ret = snd_soc_add_controls(codec, adau17x1_controls, + ARRAY_SIZE(adau17x1_controls)); + if (ret) + return ret; + ret = snd_soc_dapm_new_controls(&codec->dapm, adau17x1_dapm_widgets, + ARRAY_SIZE(adau17x1_dapm_widgets)); + if (ret) + return ret; + ret = snd_soc_dapm_add_routes(&codec->dapm, adau17x1_dapm_routes, + ARRAY_SIZE(adau17x1_dapm_routes)); + if (ret) + return ret; + + if (!adau17x1_has_dsp(adau)) + return 0; + + ret = snd_soc_add_controls(codec, adau17x1_dsp_controls, + ARRAY_SIZE(adau17x1_dsp_controls)); + if (ret) + return ret; + ret = snd_soc_dapm_new_controls(&codec->dapm, adau17x1_dsp_dapm_widgets, + ARRAY_SIZE(adau17x1_dsp_dapm_widgets)); + if (ret) + return ret; + ret = snd_soc_dapm_add_routes(&codec->dapm, adau17x1_dsp_dapm_routes, + ARRAY_SIZE(adau17x1_dsp_dapm_routes)); + return ret; +} +EXPORT_SYMBOL_GPL(adau17x1_probe); + +#if IS_ENABLED(CONFIG_SPI_MASTER) +static void adau17x1_spi_mode(struct device *dev) +{ + /* To get the device into SPI mode CLATCH has to be pulled low three + * times. Do this by issuing three dummy reads. */ + spi_w8r8(to_spi_device(dev), 0x00); + spi_w8r8(to_spi_device(dev), 0x00); + spi_w8r8(to_spi_device(dev), 0x00); +} +#else +static inline void adau17x1_spi_mode(struct device *dev) {} +#endif + +int adau17x1_suspend(struct snd_soc_codec *codec) +{ + codec->driver->set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} +EXPORT_SYMBOL_GPL(adau17x1_suspend); + +int adau17x1_resume(struct snd_soc_codec *codec) +{ + struct adau *adau = snd_soc_codec_get_drvdata(codec); + + if (adau->control_type == SND_SOC_SPI) + adau17x1_spi_mode(codec->dev); + + codec->driver->set_bias_level(codec, SND_SOC_BIAS_OFF); + regcache_sync(adau->regmap); + + return 0; +} +EXPORT_SYMBOL_GPL(adau17x1_resume); + +int __devinit adau17x1_bus_probe(struct device *dev, struct regmap *regmap, + enum adau17x1_type type, enum snd_soc_control_type control_type) +{ + struct adau *adau; + + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + adau = devm_kzalloc(dev, sizeof(*adau), GFP_KERNEL); + if (!adau) + return -ENOMEM; + + adau->regmap = regmap; + adau->control_type = control_type; + adau->type = type; + adau->sysclk_div = 1; + + dev_set_drvdata(dev, adau); + + if (control_type == SND_SOC_SPI) + adau17x1_spi_mode(dev); + + return 0; +} +EXPORT_SYMBOL_GPL(adau17x1_bus_probe); + +MODULE_DESCRIPTION("ASoC ADAU1X61/ADAU1X81 common code"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adau17x1.h b/sound/soc/codecs/adau17x1.h new file mode 100644 index 0000000000000..920b5b865544f --- /dev/null +++ b/sound/soc/codecs/adau17x1.h @@ -0,0 +1,124 @@ +#ifndef __ADAU17X1_H__ +#define __ADAU17X1_H__ + +#include +#include + +enum adau17x1_type { + ADAU1361, + ADAU1761, + ADAU1381, + ADAU1781, +}; + +enum adau17x1_pll { + ADAU17X1_PLL, +}; + +enum adau17x1_pll_src { + ADAU17X1_PLL_SRC_MCLK, +}; + +enum adau17x1_clk_src { + ADAU17X1_CLK_SRC_MCLK, + ADAU17X1_CLK_SRC_PLL, +}; + +struct adau { + unsigned int sysclk; + unsigned int sysclk_div; + unsigned int pll_freq; + + enum adau17x1_clk_src clk_src; + enum adau17x1_type type; + enum snd_soc_control_type control_type; + + unsigned int dai_fmt; + + uint8_t pll_regs[6]; + + bool master; + + unsigned int tdm_dac_slot; + unsigned int tdm_adc_slot; + + bool dsp_playback_bypass; + bool dsp_capture_bypass; + + struct regmap *regmap; +}; + +int adau17x1_probe(struct snd_soc_codec *codec); +int adau17x1_bus_probe(struct device *dev, + struct regmap *regmap, enum adau17x1_type type, + enum snd_soc_control_type control_type); +int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec, + enum adau17x1_micbias_voltage micbias); +bool adau17x1_readable_register(struct device *dev, unsigned int reg); +bool adau17x1_volatile_register(struct device *dev, unsigned int reg); +int adau17x1_suspend(struct snd_soc_codec *codec); +int adau17x1_resume(struct snd_soc_codec *codec); + +extern const struct snd_soc_dai_ops adau17x1_dai_ops; + +int adau17x1_load_firmware(struct adau *adau, struct device *dev, + const char *firmware); + +#define ADAU17X1_CLOCK_CONTROL 0x4000 +#define ADAU17X1_PLL_CONTROL 0x4002 +#define ADAU17X1_REC_POWER_MGMT 0x4009 +#define ADAU17X1_MICBIAS 0x4010 +#define ADAU17X1_SERIAL_PORT0 0x4015 +#define ADAU17X1_SERIAL_PORT1 0x4016 +#define ADAU17X1_CONVERTER0 0x4017 +#define ADAU17X1_CONVERTER1 0x4018 +#define ADAU17X1_LEFT_INPUT_DIGITAL_VOL 0x401a +#define ADAU17X1_RIGHT_INPUT_DIGITAL_VOL 0x401b +#define ADAU17X1_ADC_CONTROL 0x4019 +#define ADAU17X1_PLAY_POWER_MGMT 0x4029 +#define ADAU17X1_DAC_CONTROL0 0x402a +#define ADAU17X1_DAC_CONTROL1 0x402b +#define ADAU17X1_DAC_CONTROL2 0x402c +#define ADAU17X1_SERIAL_PORT_PAD 0x402d +#define ADAU17X1_CONTROL_PORT_PAD0 0x402f +#define ADAU17X1_CONTROL_PORT_PAD1 0x4030 +#define ADAU17X1_DSP_SAMPLING_RATE 0x40eb +#define ADAU17X1_SERIAL_INPUT_ROUTE 0x40f2 +#define ADAU17X1_SERIAL_OUTPUT_ROUTE 0x40f3 +#define ADAU17X1_DSP_ENABLE 0x40f5 +#define ADAU17X1_DSP_RUN 0x40f6 +#define ADAU17X1_SERIAL_SAMPLING_RATE 0x40f8 + +#define ADAU17X1_SERIAL_PORT0_BCLK_POL BIT(4) +#define ADAU17X1_SERIAL_PORT0_LRCLK_POL BIT(3) +#define ADAU17X1_SERIAL_PORT0_MASTER BIT(0) + +#define ADAU17X1_SERIAL_PORT1_DELAY1 0x00 +#define ADAU17X1_SERIAL_PORT1_DELAY0 0x01 +#define ADAU17X1_SERIAL_PORT1_DELAY8 0x02 +#define ADAU17X1_SERIAL_PORT1_DELAY16 0x03 +#define ADAU17X1_SERIAL_PORT1_DELAY_MASK 0x03 + +#define ADAU17X1_CLOCK_CONTROL_INFREQ_MASK 0x6 +#define ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL BIT(3) +#define ADAU17X1_CLOCK_CONTROL_SYSCLK_EN BIT(0) + +#define ADUA_SERIAL_PORT1_BCLK32 (0x0 << 5) +#define ADUA_SERIAL_PORT1_BCLK48 (0x1 << 5) +#define ADUA_SERIAL_PORT1_BCLK64 (0x2 << 5) +#define ADUA_SERIAL_PORT1_BCLK128 (0x3 << 5) +#define ADUA_SERIAL_PORT1_BCLK256 (0x4 << 5) +#define ADAU17X1_SERIAL_PORT1_BCLK_MASK (0x7 << 5) + +#define ADUA_SERIAL_PORT0_STEREO (0x0 << 1) +#define ADUA_SERIAL_PORT0_TDM4 (0x1 << 1) +#define ADUA_SERIAL_PORT0_TDM8 (0x2 << 1) +#define ADAU17X1_SERIAL_PORT0_TDM_MASK (0x3 << 1) +#define ADAU17X1_SERIAL_PORT0_PULSE_MODE BIT(5) + +#define ADAU17X1_CONVERTER0_DAC_PAIR(x) (((x) - 1) << 5) +#define ADAU17X1_CONVERTER0_DAC_PAIR_MASK (0x3 << 5) +#define ADAU17X1_CONVERTER1_ADC_PAIR(x) ((x) - 1) +#define ADAU17X1_CONVERTER1_ADC_PAIR_MASK 0x3 + +#endif From 6c4c1ac961f6d193599e61d477545ee6ac3b50c5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 31 Oct 2011 11:47:48 +0100 Subject: [PATCH 242/261] ASoC: Add ADAU1X61 codec support This patch adds support for the Ananlog Devices ADAU1361 and ADAU1761 codecs. Signed-off-by: Lars-Peter Clausen Signed-off-by: Tinghui WANG (Steven) --- include/sound/adau17x1.h | 67 +++ sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/adau1761.c | 916 ++++++++++++++++++++++++++++++++++++ 4 files changed, 990 insertions(+) create mode 100644 sound/soc/codecs/adau1761.c diff --git a/include/sound/adau17x1.h b/include/sound/adau17x1.h index 5ab9ba0cc4f0a..513f0c5721aad 100644 --- a/include/sound/adau17x1.h +++ b/include/sound/adau17x1.h @@ -20,4 +20,71 @@ enum adau17x1_micbias_voltage { ADAU17X1_MICBIAS_0_65_AVDD = 1, }; +/** + * enum adau1761_digmic_jackdet_pin_mode - Configuration of the JACKDET/MICIN pin + * @ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE: Disable the pin + * @ADAU1761_DIGMIC_JACKDET_PIN_MODE_DIGMIC: Configure the pin for usage as + * digital microphone input. + * @ADAU1761_DIGMIC_JACKDET_PIN_MODE_JACKDETECT: Configure the pin for jack + * insertion detection. +*/ +enum adau1761_digmic_jackdet_pin_mode { + ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE = 0, + ADAU1761_DIGMIC_JACKDET_PIN_MODE_DIGMIC = 1, + ADAU1761_DIGMIC_JACKDET_PIN_MODE_JACKDETECT = 2, +}; + +/** + * adau1761_jackdetect_debounce_time - Jack insertion detection debounce time + * @ADAU1761_JACKDETECT_DEBOUNCE_5MS: 5 milliseconds + * @ADAU1761_JACKDETECT_DEBOUNCE_10MS: 10 milliseconds + * @ADAU1761_JACKDETECT_DEBOUNCE_20MS: 20 milliseconds + * @ADAU1761_JACKDETECT_DEBOUNCE_40MS: 40 milliseconds + */ +enum adau1761_jackdetect_debounce_time { + ADAU1761_JACKDETECT_DEBOUNCE_5MS = 0, + ADAU1761_JACKDETECT_DEBOUNCE_10MS = 1, + ADAU1761_JACKDETECT_DEBOUNCE_20MS = 2, + ADAU1761_JACKDETECT_DEBOUNCE_40MS = 3, +}; + +/** + * enum adau1761_output_mode - Output mode configuration + * @ADAU1761_OUTPUT_MODE_HEADPHONE: Headphone output + * @ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS: Capless headphone output + * @ADAU1761_OUTPUT_MODE_LINE: Line output + */ +enum adau1761_output_mode { + ADAU1761_OUTPUT_MODE_HEADPHONE = 0, + ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS = 1, + ADAU1761_OUTPUT_MODE_LINE = 2, +}; + +/** + * struct adau1761_platform_data - ADAU1761 Codec driver platform data + * @input_differential: If true the input pins will be configured in + * differential mode. + * @lineout_mode: Output mode for the LOUT/ROUT pins + * @headphone_mode: Output mode for the LHP/RHP pins + * @digmic_jackdetect_pin_mode: JACKDET/MICIN pin configuration + * @jackdetect_debounce_time: Jack insertion detection debounce time. + * Note: This value will only be used, if the JACKDET/MICIN pin is + * configured for jack insertion detection. + * @jackdetect_active_low: If true the jack insertion detection is active + * low. Othwise it will be active high. + * @micbias_voltage: Microphone voltage bias + */ +struct adau1761_platform_data { + bool input_differential; + enum adau1761_output_mode lineout_mode; + enum adau1761_output_mode headphone_mode; + + enum adau1761_digmic_jackdet_pin_mode digmic_jackdetect_pin_mode; + + enum adau1761_jackdetect_debounce_time jackdetect_debounce_time; + bool jackdetect_active_low; + + enum adau17x1_micbias_voltage micbias_voltage; +}; + #endif diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 3a93506f8dc0f..ec23c43928752 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -18,6 +18,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_AD1980 if SND_SOC_AC97_BUS select SND_SOC_AD73311 select SND_SOC_ADAU1373 if I2C + select SND_SOC_ADAU1761 if SND_SOC_I2C_AND_SPI select SND_SOC_ADAV80X select SND_SOC_ADS117X select SND_SOC_AK4104 if SPI_MASTER @@ -151,6 +152,10 @@ config SND_SOC_ADAU17X1 select SND_SOC_SIGMADSP tristate +config SND_SOC_ADAU1761 + select SND_SOC_ADAU17X1 + tristate + config SND_SOC_ADAV80X tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 297ec12539a4b..10c841f1f4026 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -7,6 +7,7 @@ snd-soc-ad73311-objs := ad73311.o snd-soc-adau1701-objs := adau1701.o snd-soc-adau1373-objs := adau1373.o snd-soc-adau17x1-objs := adau17x1.o +snd-soc-adau1761-objs := adau1761.o snd-soc-adav80x-objs := adav80x.o snd-soc-ads117x-objs := ads117x.o snd-soc-ak4104-objs := ak4104.o @@ -110,6 +111,7 @@ obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o obj-$(CONFIG_SND_SOC_ADAU17X1) += snd-soc-adau17x1.o +obj-$(CONFIG_SND_SOC_ADAU1761) += snd-soc-adau1761.o obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c new file mode 100644 index 0000000000000..54825a2ed4856 --- /dev/null +++ b/sound/soc/codecs/adau1761.c @@ -0,0 +1,916 @@ +/* + * Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961 codec + * + * Copyright 2011-2012 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "adau17x1.h" + +#define ADAU1761_DIGMIC_JACKDETECT 0x4008 +#define ADAU1761_REC_MIXER_LEFT0 0x400a +#define ADAU1761_REC_MIXER_LEFT1 0x400b +#define ADAU1761_REC_MIXER_RIGHT0 0x400c +#define ADAU1761_REC_MIXER_RIGHT1 0x400d +#define ADAU1761_LEFT_DIFF_INPUT_VOL 0x400e +#define ADAU1761_RIGHT_DIFF_INPUT_VOL 0x400f +#define ADAU1761_PLAY_LR_MIXER_LEFT 0x4020 +#define ADAU1761_PLAY_MIXER_LEFT0 0x401c +#define ADAU1761_PLAY_MIXER_LEFT1 0x401d +#define ADAU1761_PLAY_MIXER_RIGHT0 0x401e +#define ADAU1761_PLAY_MIXER_RIGHT1 0x401f +#define ADAU1761_PLAY_LR_MIXER_RIGHT 0x4021 +#define ADAU1761_PLAY_MIXER_MONO 0x4022 +#define ADAU1761_PLAY_HP_LEFT_VOL 0x4023 +#define ADAU1761_PLAY_HP_RIGHT_VOL 0x4024 +#define ADAU1761_PLAY_LINE_LEFT_VOL 0x4025 +#define ADAU1761_PLAY_LINE_RIGHT_VOL 0x4026 +#define ADAU1761_PLAY_MONO_OUTPUT_VOL 0x4027 +#define ADAU1761_POP_CLICK_SUPPRESS 0x4028 +#define ADAU1761_JACK_DETECT_PIN 0x4031 +#define ADAU1761_DEJITTER 0x4036 +#define ADAU1761_CLK_ENABLE0 0x40f9 +#define ADAU1761_CLK_ENABLE1 0x40fa + +#define ADAU1761_DIGMIC_JACKDETECT_ACTIVE_LOW BIT(0) +#define ADAU1761_DIGMIC_JACKDETECT_DIGMIC BIT(5) + +#define ADAU1761_DIFF_INPUT_VOL_LDEN 0x01 + +#define ADAU1761_FIRMWARE "adau1761.bin" + +static struct reg_default adau1761_reg_defaults[] = { + { ADAU1761_DEJITTER, 0x03 }, + { ADAU1761_DIGMIC_JACKDETECT, 0x00 }, + { ADAU1761_REC_MIXER_LEFT0, 0x00 }, + { ADAU1761_REC_MIXER_LEFT1, 0x00 }, + { ADAU1761_REC_MIXER_RIGHT0, 0x00 }, + { ADAU1761_REC_MIXER_RIGHT1, 0x00 }, + { ADAU1761_LEFT_DIFF_INPUT_VOL, 0x00 }, + { ADAU1761_RIGHT_DIFF_INPUT_VOL, 0x00 }, + { ADAU1761_PLAY_LR_MIXER_LEFT, 0x00 }, + { ADAU1761_PLAY_MIXER_LEFT0, 0x00 }, + { ADAU1761_PLAY_MIXER_LEFT1, 0x00 }, + { ADAU1761_PLAY_MIXER_RIGHT0, 0x00 }, + { ADAU1761_PLAY_MIXER_RIGHT1, 0x00 }, + { ADAU1761_PLAY_LR_MIXER_RIGHT, 0x00 }, + { ADAU1761_PLAY_MIXER_MONO, 0x00 }, + { ADAU1761_PLAY_HP_LEFT_VOL, 0x00 }, + { ADAU1761_PLAY_HP_RIGHT_VOL, 0x00 }, + { ADAU1761_PLAY_LINE_LEFT_VOL, 0x00 }, + { ADAU1761_PLAY_LINE_RIGHT_VOL, 0x00 }, + { ADAU1761_PLAY_MONO_OUTPUT_VOL, 0x00 }, + { ADAU1761_POP_CLICK_SUPPRESS, 0x00 }, + { ADAU1761_JACK_DETECT_PIN, 0x00 }, + { ADAU1761_CLK_ENABLE0, 0x00 }, + { ADAU1761_CLK_ENABLE1, 0x00 }, + { ADAU17X1_CLOCK_CONTROL, 0x00 }, + { ADAU17X1_PLL_CONTROL, 0x00 }, + { ADAU17X1_REC_POWER_MGMT, 0x00 }, + { ADAU17X1_MICBIAS, 0x00 }, + { ADAU17X1_SERIAL_PORT0, 0x00 }, + { ADAU17X1_SERIAL_PORT1, 0x00 }, + { ADAU17X1_CONVERTER0, 0x00 }, + { ADAU17X1_CONVERTER1, 0x00 }, + { ADAU17X1_LEFT_INPUT_DIGITAL_VOL, 0x00 }, + { ADAU17X1_RIGHT_INPUT_DIGITAL_VOL, 0x00 }, + { ADAU17X1_ADC_CONTROL, 0x00 }, + { ADAU17X1_PLAY_POWER_MGMT, 0x00 }, + { ADAU17X1_DAC_CONTROL0, 0x00 }, + { ADAU17X1_DAC_CONTROL1, 0x00 }, + { ADAU17X1_DAC_CONTROL2, 0x00 }, + { ADAU17X1_SERIAL_PORT_PAD, 0x00 }, + { ADAU17X1_CONTROL_PORT_PAD0, 0x00 }, + { ADAU17X1_CONTROL_PORT_PAD1, 0x00 }, + { ADAU17X1_DSP_SAMPLING_RATE, 0x01 }, + { ADAU17X1_SERIAL_INPUT_ROUTE, 0x00 }, + { ADAU17X1_SERIAL_OUTPUT_ROUTE, 0x00 }, + { ADAU17X1_DSP_ENABLE, 0x00 }, + { ADAU17X1_DSP_RUN, 0x00 }, + { ADAU17X1_SERIAL_SAMPLING_RATE, 0x00 }, +}; + +static const DECLARE_TLV_DB_SCALE(adau1761_sing_in_tlv, -1500, 300, 1); +static const DECLARE_TLV_DB_SCALE(adau1761_diff_in_tlv, -1200, 75, 0); +static const DECLARE_TLV_DB_SCALE(adau1761_out_tlv, -5700, 100, 0); +static const DECLARE_TLV_DB_SCALE(adau1761_sidetone_tlv, -1800, 300, 1); +static const DECLARE_TLV_DB_SCALE(adau1761_boost_tlv, -600, 600, 1); +static const DECLARE_TLV_DB_SCALE(adau1761_pga_boost_tlv, -2000, 2000, 1); + +static const unsigned int adau1761_bias_select_values[] = { + 0, 2, 3, +}; + +static const char * const adau1761_bias_select_text[] = { + "Normal operation", "Enhanced performance", "Power saving", +}; + +static const char * const adau1761_bias_select_extreme_text[] = { + "Normal operation", "Extreme power saving", "Enhanced performance", + "Power saving", +}; + +static const SOC_ENUM_SINGLE_DECL(adau1761_adc_bias_enum, + ADAU17X1_REC_POWER_MGMT, 3, adau1761_bias_select_extreme_text); +static const SOC_ENUM_SINGLE_DECL(adau1761_hp_bias_enum, + ADAU17X1_PLAY_POWER_MGMT, 6, adau1761_bias_select_extreme_text); +static const SOC_ENUM_SINGLE_DECL(adau1761_dac_bias_enum, + ADAU17X1_PLAY_POWER_MGMT, 4, adau1761_bias_select_extreme_text); +static const SOC_VALUE_ENUM_SINGLE_DECL(adau1761_playback_bias_enum, + ADAU17X1_PLAY_POWER_MGMT, 2, 0x3, adau1761_bias_select_text, + adau1761_bias_select_values); +static const SOC_VALUE_ENUM_SINGLE_DECL(adau1761_capture_bias_enum, + ADAU17X1_REC_POWER_MGMT, 1, 0x3, adau1761_bias_select_text, + adau1761_bias_select_values); + +static const struct snd_kcontrol_new adau1761_jack_detect_controls[] = { + SOC_SINGLE("Jack Detect Switch", 4, 1, 0, ADAU1761_DIGMIC_JACKDETECT), +}; + +static const struct snd_kcontrol_new adau1761_differential_mode_controls[] = { + SOC_DOUBLE_R_TLV("Capture Volume", ADAU1761_LEFT_DIFF_INPUT_VOL, + ADAU1761_RIGHT_DIFF_INPUT_VOL, 2, 0x3f, 0, adau1761_diff_in_tlv), + SOC_DOUBLE_R("Capture Switch", ADAU1761_LEFT_DIFF_INPUT_VOL, + ADAU1761_RIGHT_DIFF_INPUT_VOL, 1, 1, 0), + + SOC_DOUBLE_R_TLV("PGA Boost Capture Volume", ADAU1761_REC_MIXER_LEFT1, + ADAU1761_REC_MIXER_RIGHT1, 3, 2, 0, adau1761_pga_boost_tlv), +}; + +static const struct snd_kcontrol_new adau1761_single_mode_controls[] = { + SOC_SINGLE_TLV("Input 1 Capture Volume", ADAU1761_REC_MIXER_LEFT0, + 4, 7, 0, adau1761_sing_in_tlv), + SOC_SINGLE_TLV("Input 2 Capture Volume", ADAU1761_REC_MIXER_LEFT0, + 1, 7, 0, adau1761_sing_in_tlv), + SOC_SINGLE_TLV("Input 3 Capture Volume", ADAU1761_REC_MIXER_RIGHT0, + 4, 7, 0, adau1761_sing_in_tlv), + SOC_SINGLE_TLV("Input 4 Capture Volume", ADAU1761_REC_MIXER_RIGHT0, + 1, 7, 0, adau1761_sing_in_tlv), +}; + +static const struct snd_kcontrol_new adau1761_controls[] = { + SOC_DOUBLE_R_TLV("Aux Capture Volume", ADAU1761_REC_MIXER_LEFT1, + ADAU1761_REC_MIXER_RIGHT1, 0, 7, 0, adau1761_sing_in_tlv), + + SOC_DOUBLE_R_TLV("Headphone Playback Volume", ADAU1761_PLAY_HP_LEFT_VOL, + ADAU1761_PLAY_HP_RIGHT_VOL, 2, 0x3f, 0, adau1761_out_tlv), + SOC_DOUBLE_R("Headphone Playback Switch", ADAU1761_PLAY_HP_LEFT_VOL, + ADAU1761_PLAY_HP_RIGHT_VOL, 1, 1, 0), + SOC_DOUBLE_R_TLV("Lineout Playback Volume", ADAU1761_PLAY_LINE_LEFT_VOL, + ADAU1761_PLAY_LINE_RIGHT_VOL, 2, 0x3f, 0, adau1761_out_tlv), + SOC_DOUBLE_R("Lineout Playback Switch", ADAU1761_PLAY_LINE_LEFT_VOL, + ADAU1761_PLAY_LINE_RIGHT_VOL, 1, 1, 0), + + SOC_ENUM("ADC Bias", adau1761_adc_bias_enum), + SOC_ENUM("DAC Bias", adau1761_dac_bias_enum), + SOC_VALUE_ENUM("Capture Bias", adau1761_capture_bias_enum), + SOC_VALUE_ENUM("Playback Bias", adau1761_playback_bias_enum), + SOC_ENUM("Headphone Bias", adau1761_hp_bias_enum), +}; + +static const struct snd_kcontrol_new adau1761_mono_controls[] = { + SOC_SINGLE_TLV("Mono Playback Volume", ADAU1761_PLAY_MONO_OUTPUT_VOL, + 2, 0x3f, 0, adau1761_out_tlv), + SOC_SINGLE("Mono Playback Switch", ADAU1761_PLAY_MONO_OUTPUT_VOL, + 1, 1, 0), +}; + +static const struct snd_kcontrol_new adau1761_left_mixer_controls[] = { + SOC_DAPM_SINGLE("Left DAC Switch", ADAU1761_PLAY_MIXER_LEFT0, 5, 1, 0), + SOC_DAPM_SINGLE("Right DAC Switch", ADAU1761_PLAY_MIXER_LEFT0, 6, 1, 0), + SOC_DAPM_SINGLE_TLV("Aux Bypass Volume", + ADAU1761_PLAY_MIXER_LEFT0, 1, 8, 0, adau1761_sidetone_tlv), + SOC_DAPM_SINGLE_TLV("Right Bypass Volume", + ADAU1761_PLAY_MIXER_LEFT1, 4, 8, 0, adau1761_sidetone_tlv), + SOC_DAPM_SINGLE_TLV("Left Bypass Volume", + ADAU1761_PLAY_MIXER_LEFT1, 0, 8, 0, adau1761_sidetone_tlv), +}; + +static const struct snd_kcontrol_new adau1761_right_mixer_controls[] = { + SOC_DAPM_SINGLE("Left DAC Switch", ADAU1761_PLAY_MIXER_RIGHT0, 5, 1, 0), + SOC_DAPM_SINGLE("Right DAC Switch", ADAU1761_PLAY_MIXER_RIGHT0, 6, 1, 0), + SOC_DAPM_SINGLE_TLV("Aux Bypass Volume", + ADAU1761_PLAY_MIXER_RIGHT0, 1, 8, 0, adau1761_sidetone_tlv), + SOC_DAPM_SINGLE_TLV("Right Bypass Volume", + ADAU1761_PLAY_MIXER_RIGHT1, 4, 8, 0, adau1761_sidetone_tlv), + SOC_DAPM_SINGLE_TLV("Left Bypass Volume", + ADAU1761_PLAY_MIXER_RIGHT1, 0, 8, 0, adau1761_sidetone_tlv), +}; + +static const struct snd_kcontrol_new adau1761_left_lr_mixer_controls[] = { + SOC_DAPM_SINGLE_TLV("Left Volume", + ADAU1761_PLAY_LR_MIXER_LEFT, 1, 2, 0, adau1761_boost_tlv), + SOC_DAPM_SINGLE_TLV("Right Volume", + ADAU1761_PLAY_LR_MIXER_LEFT, 3, 2, 0, adau1761_boost_tlv), +}; + +static const struct snd_kcontrol_new adau1761_right_lr_mixer_controls[] = { + SOC_DAPM_SINGLE_TLV("Left Volume", + ADAU1761_PLAY_LR_MIXER_RIGHT, 1, 2, 0, adau1761_boost_tlv), + SOC_DAPM_SINGLE_TLV("Right Volume", + ADAU1761_PLAY_LR_MIXER_RIGHT, 3, 2, 0, adau1761_boost_tlv), +}; + +static const char * const adau1761_input_mux_text[] = { + "ADC", "DMIC", +}; + +static const SOC_ENUM_SINGLE_DECL(adau1761_input_mux_enum, + ADAU17X1_ADC_CONTROL, 2, adau1761_input_mux_text); + +static const struct snd_kcontrol_new adau1761_input_mux_control = + SOC_DAPM_ENUM("Input Select", adau1761_input_mux_enum); + +static int adau1761_dejitter_fixup(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct adau *adau = snd_soc_codec_get_drvdata(w->codec); + + /* After any power changes have been made the dejitter circuit + * has to be reinitialized. */ + regmap_write(adau->regmap, ADAU1761_DEJITTER, 0); + if (!adau->master) + regmap_write(adau->regmap, ADAU1761_DEJITTER, 3); + + return 0; +} + +static const struct snd_soc_dapm_widget adau1x61_dapm_widgets[] = { + SND_SOC_DAPM_MIXER("Left Input Mixer", ADAU1761_REC_MIXER_LEFT0, 0, 0, + NULL, 0), + SND_SOC_DAPM_MIXER("Right Input Mixer", ADAU1761_REC_MIXER_RIGHT0, 0, 0, + NULL, 0), + + SOC_MIXER_ARRAY("Left Playback Mixer", ADAU1761_PLAY_MIXER_LEFT0, + 0, 0, adau1761_left_mixer_controls), + SOC_MIXER_ARRAY("Right Playback Mixer", ADAU1761_PLAY_MIXER_RIGHT0, + 0, 0, adau1761_right_mixer_controls), + SOC_MIXER_ARRAY("Left LR Playback Mixer", ADAU1761_PLAY_LR_MIXER_LEFT, + 0, 0, adau1761_left_lr_mixer_controls), + SOC_MIXER_ARRAY("Right LR Playback Mixer", ADAU1761_PLAY_LR_MIXER_RIGHT, + 0, 0, adau1761_right_lr_mixer_controls), + + SND_SOC_DAPM_SUPPLY("Headphone", ADAU1761_PLAY_HP_LEFT_VOL, + 0, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("SYSCLK", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_POST("Dejitter fixup", adau1761_dejitter_fixup), + + SND_SOC_DAPM_INPUT("LAUX"), + SND_SOC_DAPM_INPUT("RAUX"), + SND_SOC_DAPM_INPUT("LINP"), + SND_SOC_DAPM_INPUT("LINN"), + SND_SOC_DAPM_INPUT("RINP"), + SND_SOC_DAPM_INPUT("RINN"), + + SND_SOC_DAPM_OUTPUT("LOUT"), + SND_SOC_DAPM_OUTPUT("ROUT"), + SND_SOC_DAPM_OUTPUT("LHP"), + SND_SOC_DAPM_OUTPUT("RHP"), +}; + +static const struct snd_soc_dapm_widget adau1761_mono_dapm_widgets[] = { + SND_SOC_DAPM_MIXER("Mono Playback Mixer", ADAU1761_PLAY_MIXER_MONO, + 0, 0, NULL, 0), + + SND_SOC_DAPM_OUTPUT("MONOOUT"), +}; + +static const struct snd_soc_dapm_widget adau1761_capless_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("Headphone VGND", ADAU1761_PLAY_MIXER_MONO, + 0, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_widget adau1761_dmic_widgets[] = { + SND_SOC_DAPM_MUX("Input Select", SND_SOC_NOPM, 0, 0, + &adau1761_input_mux_control), + + SND_SOC_DAPM_INPUT("DMIC"), +}; + +static const struct snd_soc_dapm_route adau1x61_dapm_routes[] = { + { "Left Input Mixer", NULL, "LINP" }, + { "Left Input Mixer", NULL, "LINN" }, + { "Left Input Mixer", NULL, "LAUX" }, + + { "Right Input Mixer", NULL, "RINP" }, + { "Right Input Mixer", NULL, "RINN" }, + { "Right Input Mixer", NULL, "RAUX" }, + + { "Left Playback Mixer", NULL, "Left Playback Enable"}, + { "Right Playback Mixer", NULL, "Right Playback Enable"}, + { "Left LR Playback Mixer", NULL, "Left Playback Enable"}, + { "Right LR Playback Mixer", NULL, "Right Playback Enable"}, + + { "Left Playback Mixer", "Left DAC Switch", "Left DAC" }, + { "Left Playback Mixer", "Right DAC Switch", "Right DAC" }, + + { "Right Playback Mixer", "Left DAC Switch", "Left DAC" }, + { "Right Playback Mixer", "Right DAC Switch", "Right DAC" }, + + { "Left LR Playback Mixer", "Left Volume", "Left Playback Mixer" }, + { "Left LR Playback Mixer", "Right Volume", "Right Playback Mixer" }, + + { "Right LR Playback Mixer", "Left Volume", "Left Playback Mixer" }, + { "Right LR Playback Mixer", "Right Volume", "Right Playback Mixer" }, + + { "Left ADC", NULL, "Left Input Mixer" }, + { "Right ADC", NULL, "Right Input Mixer" }, + + { "LHP", NULL, "Left Playback Mixer" }, + { "RHP", NULL, "Right Playback Mixer" }, + + { "LHP", NULL, "Headphone" }, + { "RHP", NULL, "Headphone" }, + + { "LOUT", NULL, "Left LR Playback Mixer" }, + { "ROUT", NULL, "Right LR Playback Mixer" }, + + { "Left Playback Mixer", "Aux Bypass Volume", "LAUX" }, + { "Left Playback Mixer", "Left Bypass Volume", "Left Input Mixer" }, + { "Left Playback Mixer", "Right Bypass Volume", "Right Input Mixer" }, + { "Right Playback Mixer", "Aux Bypass Volume", "RAUX" }, + { "Right Playback Mixer", "Left Bypass Volume", "Left Input Mixer" }, + { "Right Playback Mixer", "Right Bypass Volume", "Right Input Mixer" }, +}; + +static const struct snd_soc_dapm_route adau1761_mono_dapm_routes[] = { + { "Mono Playback Mixer", NULL, "Left Playback Mixer" }, + { "Mono Playback Mixer", NULL, "Right Playback Mixer" }, + + { "MONOOUT", NULL, "Mono Playback Mixer" }, +}; + +static const struct snd_soc_dapm_route adau1761_capless_dapm_routes[] = { + { "Headphone", NULL, "Headphone VGND" }, +}; + +static const struct snd_soc_dapm_route adau1761_dmic_routes[] = { + { "Input Select", "ADC", "Left ADC" }, + { "Input Select", "ADC", "Right ADC" }, + { "Input Select", "DMIC", "DMIC" }, + { "AIFOUT", NULL, "Input Select" }, +}; + +static const struct snd_soc_dapm_route adau1761_no_dmic_routes[] = { + { "AIFOUT", NULL, "Left ADC" }, + { "AIFOUT", NULL, "Right ADC" }, +}; + +static const struct snd_soc_dapm_widget adau1761_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("Serial Port Clock", ADAU1761_CLK_ENABLE0, + 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Serial Input Routing Clock", ADAU1761_CLK_ENABLE0, + 1, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Serial Output Routing Clock", ADAU1761_CLK_ENABLE0, + 3, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("Decimator Resync Clock", ADAU1761_CLK_ENABLE0, + 4, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Interpolator Resync Clock", ADAU1761_CLK_ENABLE0, + 2, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("Slew Clock", ADAU1761_CLK_ENABLE0, 6, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("Digital Clock 0", ADAU1761_CLK_ENABLE1, + 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Digital Clock 1", ADAU1761_CLK_ENABLE1, + 1, 0, NULL, 0), +}; + +static int adau1761_is_slave_mode(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct adau *adau = snd_soc_codec_get_drvdata(source->codec); + + return !adau->master; +} + +static const struct snd_soc_dapm_route adau1761_dapm_routes[] = { + { "Left ADC", NULL, "Digital Clock 0", }, + { "Right ADC", NULL, "Digital Clock 0", }, + { "Left DAC", NULL, "Digital Clock 0", }, + { "Right DAC", NULL, "Digital Clock 0", }, + + { "AIFCLK", NULL, "Digital Clock 1" }, + + { "AIFIN", NULL, "Serial Port Clock" }, + { "AIFOUT", NULL, "Serial Port Clock" }, + { "AIFIN", NULL, "Serial Input Routing Clock" }, + { "AIFOUT", NULL, "Serial Output Routing Clock" }, + + { "AIFIN", NULL, "Decimator Resync Clock" }, + { "AIFOUT", NULL, "Interpolator Resync Clock" }, + + { "DSP", NULL, "Decimator Resync Clock" }, + { "DSP", NULL, "Interpolator Resync Clock" }, + { "DSP", NULL, "Digital Clock 0" }, + + { "Slew Clock", NULL, "Digital Clock 0" }, + { "Right Playback Mixer", NULL, "Slew Clock" }, + { "Left Playback Mixer", NULL, "Slew Clock" }, + + { "Digital Clock 0", NULL, "SYSCLK" }, + { "Digital Clock 1", NULL, "SYSCLK" }, + + { "AIFOUT", NULL, "Decimator Resync Clock" }, +}; + +static int adau1761_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct adau *adau = snd_soc_codec_get_drvdata(codec); + + switch (level) { + case SND_SOC_BIAS_ON: + break; + case SND_SOC_BIAS_PREPARE: + break; + case SND_SOC_BIAS_STANDBY: + regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL, + ADAU17X1_CLOCK_CONTROL_SYSCLK_EN, + ADAU17X1_CLOCK_CONTROL_SYSCLK_EN); + break; + case SND_SOC_BIAS_OFF: + regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL, + ADAU17X1_CLOCK_CONTROL_SYSCLK_EN, 0); + break; + + } + codec->dapm.bias_level = level; + return 0; +} + +static enum adau1761_output_mode adau1761_get_lineout_mode( + struct snd_soc_codec *codec) +{ + struct adau1761_platform_data *pdata = codec->dev->platform_data; + + if (pdata) + return pdata->lineout_mode; + + return ADAU1761_OUTPUT_MODE_LINE; +} + +static int adau1761_setup_digmic_jackdetect(struct snd_soc_codec *codec) +{ + struct adau1761_platform_data *pdata = codec->dev->platform_data; + struct adau *adau = snd_soc_codec_get_drvdata(codec); + enum adau1761_digmic_jackdet_pin_mode mode; + unsigned int val = 0; + int ret; + + if (pdata) + mode = pdata->digmic_jackdetect_pin_mode; + else + mode = ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE; + + switch (mode) { + case ADAU1761_DIGMIC_JACKDET_PIN_MODE_JACKDETECT: + switch (pdata->jackdetect_debounce_time) { + case ADAU1761_JACKDETECT_DEBOUNCE_5MS: + case ADAU1761_JACKDETECT_DEBOUNCE_10MS: + case ADAU1761_JACKDETECT_DEBOUNCE_20MS: + case ADAU1761_JACKDETECT_DEBOUNCE_40MS: + val |= pdata->jackdetect_debounce_time << 6; + break; + default: + return -EINVAL; + } + if (pdata->jackdetect_active_low) + val |= ADAU1761_DIGMIC_JACKDETECT_ACTIVE_LOW; + + ret = snd_soc_add_controls(codec, + adau1761_jack_detect_controls, + ARRAY_SIZE(adau1761_jack_detect_controls)); + if (ret) + return ret; + case ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE: /* fall-through */ + ret = snd_soc_dapm_add_routes(&codec->dapm, + adau1761_no_dmic_routes, + ARRAY_SIZE(adau1761_no_dmic_routes)); + if (ret) + return ret; + break; + case ADAU1761_DIGMIC_JACKDET_PIN_MODE_DIGMIC: + ret = snd_soc_dapm_new_controls(&codec->dapm, + adau1761_dmic_widgets, + ARRAY_SIZE(adau1761_dmic_widgets)); + if (ret) + return ret; + ret = snd_soc_dapm_add_routes(&codec->dapm, + adau1761_dmic_routes, + ARRAY_SIZE(adau1761_dmic_routes)); + if (ret) + return ret; + val |= ADAU1761_DIGMIC_JACKDETECT_DIGMIC; + break; + default: + return -EINVAL; + } + + regmap_write(adau->regmap, ADAU1761_DIGMIC_JACKDETECT, val); + + return 0; +} + +static int adau1761_setup_headphone_mode(struct snd_soc_codec *codec) +{ + struct adau *adau = snd_soc_codec_get_drvdata(codec); + struct adau1761_platform_data *pdata = codec->dev->platform_data; + enum adau1761_output_mode mode; + int ret; + + if (pdata) + mode = pdata->headphone_mode; + else + mode = ADAU1761_OUTPUT_MODE_HEADPHONE; + + switch (mode) { + case ADAU1761_OUTPUT_MODE_LINE: + break; + case ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS: + regmap_update_bits(adau->regmap, ADAU1761_PLAY_MONO_OUTPUT_VOL, 3, 3); + case ADAU1761_OUTPUT_MODE_HEADPHONE: /* fall-through */ + regmap_update_bits(adau->regmap, ADAU1761_PLAY_HP_RIGHT_VOL, 1, 1); + break; + default: + return -EINVAL; + } + + if (mode == ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS) { + ret = snd_soc_dapm_new_controls(&codec->dapm, + adau1761_capless_dapm_widgets, + ARRAY_SIZE(adau1761_capless_dapm_widgets)); + if (ret) + return ret; + ret = snd_soc_dapm_add_routes(&codec->dapm, + adau1761_capless_dapm_routes, + ARRAY_SIZE(adau1761_capless_dapm_routes)); + } else { + ret = snd_soc_dapm_new_controls(&codec->dapm, + adau1761_mono_dapm_widgets, + ARRAY_SIZE(adau1761_mono_dapm_widgets)); + if (ret) + return ret; + ret = snd_soc_dapm_add_routes(&codec->dapm, + adau1761_mono_dapm_routes, + ARRAY_SIZE(adau1761_mono_dapm_routes)); + } + + return ret; +} + +static bool adau1761_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ADAU1761_DIGMIC_JACKDETECT: + case ADAU1761_REC_MIXER_LEFT0: + case ADAU1761_REC_MIXER_LEFT1: + case ADAU1761_REC_MIXER_RIGHT0: + case ADAU1761_REC_MIXER_RIGHT1: + case ADAU1761_LEFT_DIFF_INPUT_VOL: + case ADAU1761_RIGHT_DIFF_INPUT_VOL: + case ADAU1761_PLAY_LR_MIXER_LEFT: + case ADAU1761_PLAY_MIXER_LEFT0: + case ADAU1761_PLAY_MIXER_LEFT1: + case ADAU1761_PLAY_MIXER_RIGHT0: + case ADAU1761_PLAY_MIXER_RIGHT1: + case ADAU1761_PLAY_LR_MIXER_RIGHT: + case ADAU1761_PLAY_MIXER_MONO: + case ADAU1761_PLAY_HP_LEFT_VOL: + case ADAU1761_PLAY_HP_RIGHT_VOL: + case ADAU1761_PLAY_LINE_LEFT_VOL: + case ADAU1761_PLAY_LINE_RIGHT_VOL: + case ADAU1761_PLAY_MONO_OUTPUT_VOL: + case ADAU1761_POP_CLICK_SUPPRESS: + case ADAU1761_JACK_DETECT_PIN: + case ADAU1761_DEJITTER: + case ADAU1761_CLK_ENABLE0: + case ADAU1761_CLK_ENABLE1: + return true; + default: + break; + } + + return adau17x1_readable_register(dev, reg); +} + +static int adau1761_probe(struct snd_soc_codec *codec) +{ + struct adau1761_platform_data *pdata = codec->dev->platform_data; + struct adau *adau = snd_soc_codec_get_drvdata(codec); + int ret; + + ret = adau17x1_probe(codec); + if (ret < 0) + return ret; + + adau1761_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + + if (pdata && pdata->input_differential) { + regmap_update_bits(adau->regmap, ADAU1761_LEFT_DIFF_INPUT_VOL, + ADAU1761_DIFF_INPUT_VOL_LDEN, + ADAU1761_DIFF_INPUT_VOL_LDEN); + regmap_update_bits(adau->regmap, ADAU1761_RIGHT_DIFF_INPUT_VOL, + ADAU1761_DIFF_INPUT_VOL_LDEN, + ADAU1761_DIFF_INPUT_VOL_LDEN); + ret = snd_soc_add_controls(codec, + adau1761_differential_mode_controls, + ARRAY_SIZE(adau1761_differential_mode_controls)); + if (ret) + return ret; + } else { + ret = snd_soc_add_controls(codec, + adau1761_single_mode_controls, + ARRAY_SIZE(adau1761_single_mode_controls)); + if (ret) + return ret; + } + + switch (adau1761_get_lineout_mode(codec)) { + case ADAU1761_OUTPUT_MODE_LINE: + break; + case ADAU1761_OUTPUT_MODE_HEADPHONE: + regmap_update_bits(adau->regmap, ADAU1761_PLAY_LINE_LEFT_VOL, 1, 1); + regmap_update_bits(adau->regmap, ADAU1761_PLAY_LINE_RIGHT_VOL, 1, 1); + break; + default: + return -EINVAL; + } + + ret = adau1761_setup_headphone_mode(codec); + if (ret) + return ret; + + ret = adau1761_setup_digmic_jackdetect(codec); + if (ret) + return ret; + + if (adau->type == ADAU1761) { + ret = snd_soc_dapm_new_controls(&codec->dapm, + adau1761_dapm_widgets, + ARRAY_SIZE(adau1761_dapm_widgets)); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(&codec->dapm, + adau1761_dapm_routes, + ARRAY_SIZE(adau1761_dapm_routes)); + if (ret) + return ret; + + ret = adau17x1_load_firmware(adau, codec->dev, + ADAU1761_FIRMWARE); + if (ret) + dev_warn(codec->dev, "Failed to firmware\n"); + } + + return 0; +} + +static struct snd_soc_codec_driver adau1761_codec_driver = { + .probe = adau1761_probe, + .remove = adau17x1_suspend, + .suspend = adau17x1_suspend, + .resume = adau17x1_resume, + .set_bias_level = adau1761_set_bias_level, + + .controls = adau1761_controls, + .num_controls = ARRAY_SIZE(adau1761_controls), + .dapm_widgets = adau1x61_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau1x61_dapm_widgets), + .dapm_routes = adau1x61_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adau1x61_dapm_routes), +}; + +#define ADAU1761_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver adau1361_dai_driver = { + .name = "adau-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 4, + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = ADAU1761_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 4, + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = ADAU1761_FORMATS, + }, + .ops = &adau17x1_dai_ops, +}; + +static struct snd_soc_dai_driver adau1761_dai_driver = { + .name = "adau-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = ADAU1761_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = ADAU1761_FORMATS, + }, + .ops = &adau17x1_dai_ops, +}; + +static int __devinit adau1761_bus_probe(struct device *dev, + struct regmap *regmap, enum adau17x1_type type, + enum snd_soc_control_type control_type) +{ + struct snd_soc_dai_driver *dai_drv; + int ret; + + ret = adau17x1_bus_probe(dev, regmap, type, control_type); + if (ret) + return ret; + + if (type == ADAU1361) + dai_drv = &adau1361_dai_driver; + else + dai_drv = &adau1761_dai_driver; + + return snd_soc_register_codec(dev, &adau1761_codec_driver, + dai_drv, 1); +} + +#if IS_ENABLED(CONFIG_SPI_MASTER) + +static const struct regmap_config adau1761_spi_regmap_config = { + .val_bits = 8, + .reg_bits = 24, + .read_flag_mask = 0x01, + .max_register = 0x40fa, + .reg_defaults = adau1761_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(adau1761_reg_defaults), + .readable_reg = adau1761_readable_register, + .volatile_reg = adau17x1_volatile_register, + .cache_type = REGCACHE_RBTREE, +}; + +static int __devinit adau1761_spi_probe(struct spi_device *spi) +{ + enum adau17x1_type type = spi_get_device_id(spi)->driver_data; + struct regmap *regmap; + + regmap = devm_regmap_init_spi(spi, &adau1761_spi_regmap_config); + + return adau1761_bus_probe(&spi->dev, regmap, type, SND_SOC_SPI); +} + +static int __devexit adau1761_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static const struct spi_device_id adau1761_spi_id[] = { + { "adau1361", ADAU1361 }, + { "adau1461", ADAU1761 }, + { "adau1761", ADAU1761 }, + { "adau1961", ADAU1361 }, + { } +}; +MODULE_DEVICE_TABLE(spi, adau1761_spi_id); + +static struct spi_driver adau1761_spi_driver = { + .driver = { + .name = "adau1761", + .owner = THIS_MODULE, + }, + .probe = adau1761_spi_probe, + .remove = __devexit_p(adau1761_spi_remove), + .id_table = adau1761_spi_id, +}; + +static int adau1761_spi_register_driver(void) +{ + return spi_register_driver(&adau1761_spi_driver); +} + +static void adau1761_spi_unregister_driver(void) +{ + spi_unregister_driver(&adau1761_spi_driver); +} + +#else +static int adau1761_spi_register_driver(void) { return 0; } +static void adau1761_spi_unregister_driver(void) {} +#endif + +#if IS_ENABLED(CONFIG_I2C) + +static const struct regmap_config adau1761_i2c_regmap_config = { + .val_bits = 8, + .reg_bits = 16, + .max_register = 0x40fa, + .reg_defaults = adau1761_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(adau1761_reg_defaults), + .readable_reg = adau1761_readable_register, + .volatile_reg = adau17x1_volatile_register, + .cache_type = REGCACHE_RBTREE, +}; + +static int __devinit adau1761_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + enum adau17x1_type type = id->driver_data; + struct regmap *regmap; + + regmap = devm_regmap_init_i2c(client, &adau1761_i2c_regmap_config); + + return adau1761_bus_probe(&client->dev, regmap, type, SND_SOC_I2C); +} + +static int __devexit adau1761_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static const struct i2c_device_id adau1761_i2c_id[] = { + { "adau1361", ADAU1361 }, + { "adau1461", ADAU1761 }, + { "adau1761", ADAU1761 }, + { "adau1961", ADAU1361 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adau1761_i2c_id); + +static struct i2c_driver adau1761_i2c_driver = { + .driver = { + .name = "adau1761", + .owner = THIS_MODULE, + }, + .probe = adau1761_i2c_probe, + .remove = __devexit_p(adau1761_i2c_remove), + .id_table = adau1761_i2c_id, +}; + +static int adau1761_i2c_register_driver(void) +{ + return i2c_add_driver(&adau1761_i2c_driver); +} + +static void adau1761_i2c_unregister_driver(void) +{ + i2c_del_driver(&adau1761_i2c_driver); +} + +#else +static int adau1761_i2c_register_driver(void) { return 0; } +static void adau1761_i2c_unregister_driver(void) {} +#endif + +static int __init adau1761_init(void) +{ + int ret; + + ret = adau1761_spi_register_driver(); + if (ret) + return ret; + + ret = adau1761_i2c_register_driver(); + if (ret) + adau1761_spi_unregister_driver(); + + return ret; +} +module_init(adau1761_init); + +static void __exit adau1761_exit(void) +{ + adau1761_i2c_unregister_driver(); + adau1761_spi_unregister_driver(); +} +module_exit(adau1761_exit); + +MODULE_DESCRIPTION("ASoC ADAU1361/ADAU1461/ADAU1761/ADAU1961 CODEC driver"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_LICENSE("GPL"); From abc6992243a1ce98a3611888f60fc2a3b559ff3e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 13 Jun 2012 16:03:57 +0200 Subject: [PATCH 243/261] ASoC: xilinx_pcm: Add support for individual subchannels A DAI may support both capture and playback or just one of the two. Thus we need to be able to specify DMA channels for capture and playback independently of each other. Do this by adding a per direction subnode to the PCM device's node. Signed-off-by: Lars-Peter Clausen Signed-off-by: Tinghui WANG (Steven) --- arch/arm/boot/dts/zynq-zc702-adv7511.dts | 8 +++- arch/arm/boot/dts/zynq-zed-adv7511.dts | 8 +++- sound/soc/xlnx/xilinx-pcm.c | 54 ++++++++++++++++++++---- 3 files changed, 60 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/zynq-zc702-adv7511.dts b/arch/arm/boot/dts/zynq-zc702-adv7511.dts index 520f658ac7e64..730ee14c7c004 100644 --- a/arch/arm/boot/dts/zynq-zc702-adv7511.dts +++ b/arch/arm/boot/dts/zynq-zc702-adv7511.dts @@ -204,7 +204,13 @@ xilinx_pcm_audio: xilinx_pcm_audio { compatible = "xilinx-pcm-audio"; - dma-request = <&axi_dma_0 0>; + #size-cells = <0>; + #address-cells = <1>; + + playback: stream@0 { + reg = <0>; + dma-request = <&axi_dma_0 0>; + }; }; adv7511_hdmi_snd: adv7511_hdmi_snd { diff --git a/arch/arm/boot/dts/zynq-zed-adv7511.dts b/arch/arm/boot/dts/zynq-zed-adv7511.dts index a34acccf23043..ac3abf4963155 100644 --- a/arch/arm/boot/dts/zynq-zed-adv7511.dts +++ b/arch/arm/boot/dts/zynq-zed-adv7511.dts @@ -174,7 +174,13 @@ xilinx_pcm_audio: xilinx_pcm_audio { compatible = "xilinx-pcm-audio"; - dma-request = <&axi_dma_0 0>; + #size-cells = <0>; + #address-cells = <1>; + + playback: stream@0 { + reg = <0>; + dma-request = <&axi_dma_0 0>; + }; }; adv7511_hdmi_snd: adv7511_hdmi_snd { diff --git a/sound/soc/xlnx/xilinx-pcm.c b/sound/soc/xlnx/xilinx-pcm.c index a9680aa471917..37e9fdf8fddca 100644 --- a/sound/soc/xlnx/xilinx-pcm.c +++ b/sound/soc/xlnx/xilinx-pcm.c @@ -44,6 +44,8 @@ static const struct snd_pcm_hardware xlnx_pcm_hardware = { .buffer_bytes_max = ULONG_MAX, }; +#define XLNX_PCM_MAX_STREAMS 2 + static int xlnx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -70,11 +72,18 @@ static int xlnx_pcm_open(struct snd_pcm_substream *substream) struct xlnx_pcm_dma_params *params = dev_get_drvdata(dev); int ret; + if (substream->stream >= XLNX_PCM_MAX_STREAMS) + return -EINVAL; + + if (params[substream->stream].of_node == NULL) + return -EINVAL; + ret = snd_soc_set_runtime_hwparams(substream, &xlnx_pcm_hardware); if (ret) return ret; - return snd_dmaengine_pcm_open(substream, xlnx_pcm_filter, params); + return snd_dmaengine_pcm_open(substream, xlnx_pcm_filter, + ¶ms[substream->stream]); } static int xlnx_pcm_new(struct snd_soc_pcm_runtime *rtd) @@ -121,19 +130,48 @@ static int __devinit xlnx_pcm_soc_platform_probe(struct platform_device *pdev) { struct xlnx_pcm_dma_params *params; struct of_phandle_args dma_spec; + struct device_node *node; + u32 stream; int ret; - params = devm_kzalloc(&pdev->dev, sizeof(*params), GFP_KERNEL); + if (!pdev->dev.of_node) + return -EINVAL; + + params = devm_kzalloc(&pdev->dev, sizeof(*params) * XLNX_PCM_MAX_STREAMS, GFP_KERNEL); if (!params) return -ENOMEM; - ret = of_parse_phandle_with_args(pdev->dev.of_node, "dma-request", + for_each_child_of_node(pdev->dev.of_node, node) { + ret = of_property_read_u32(node, "reg", &stream); + if (ret) { + dev_err(&pdev->dev, "Missing 'reg' attribute for stream '%s'\n", + node->name); + continue; + } + + if (stream >= XLNX_PCM_MAX_STREAMS) { + dev_err(&pdev->dev, "Index to big for stream '%s'\n", + node->name); + continue; + } + + ret = of_parse_phandle_with_args(node, "dma-request", "#dma-cells", 0, &dma_spec); - if (ret) - return ret; - - params->of_node = dma_spec.np; - params->chan_id = dma_spec.args[0]; + if (ret) { + dev_err(&pdev->dev, "Can not parse dma channel for stream '%s': %d\n", + node->name, ret); + continue; + } + + if (dma_spec.args_count != 1) { + dev_err(&pdev->dev, "Invalid dma channel for stream '%s'\n", + node->name); + continue; + } + + params[stream].of_node = dma_spec.np; + params[stream].chan_id = dma_spec.args[0]; + } dev_set_drvdata(&pdev->dev, params); From bda4327d837595ef671363bca8f4107f9cbd34c7 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 13 Jun 2012 17:29:20 +0200 Subject: [PATCH 244/261] ASoC: Add AXI I2S driver Signed-off-by: Tinghui WANG (Steven) --- sound/soc/xlnx/Kconfig | 3 + sound/soc/xlnx/Makefile | 3 + sound/soc/xlnx/axi-i2s.c | 235 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 241 insertions(+) create mode 100644 sound/soc/xlnx/axi-i2s.c diff --git a/sound/soc/xlnx/Kconfig b/sound/soc/xlnx/Kconfig index 69192fcbba0ea..ad5455f9ce619 100644 --- a/sound/soc/xlnx/Kconfig +++ b/sound/soc/xlnx/Kconfig @@ -6,6 +6,9 @@ config SND_SOC_XILINX config SND_SOC_AXI_SPDIF tristate +config SND_SOC_AXI_I2S + tristate + config SND_SOC_ADV7511_HDMI tristate "ADV7511 HDMI transmitter sound support" depends on SND_SOC_XILINX diff --git a/sound/soc/xlnx/Makefile b/sound/soc/xlnx/Makefile index d758bbd0c28b4..d5908bdf96d80 100644 --- a/sound/soc/xlnx/Makefile +++ b/sound/soc/xlnx/Makefile @@ -1,7 +1,10 @@ snd-soc-xilinx-pcm-objs := xilinx-pcm.o snd-soc-axi-spdif-objs := axi-spdif.o +snd-soc-axi-i2s-objs := axi-i2s.o snd-soc-adv7511-hdmi-objs := adv7511_hdmi.o obj-$(CONFIG_SND_SOC_XILINX) += snd-soc-xilinx-pcm.o obj-$(CONFIG_SND_SOC_AXI_SPDIF) += snd-soc-axi-spdif.o +obj-$(CONFIG_SND_SOC_AXI_I2S) += snd-soc-axi-i2s.o + obj-$(CONFIG_SND_SOC_ADV7511_HDMI) += snd-soc-adv7511-hdmi.o diff --git a/sound/soc/xlnx/axi-i2s.c b/sound/soc/xlnx/axi-i2s.c new file mode 100644 index 0000000000000..18810e4026874 --- /dev/null +++ b/sound/soc/xlnx/axi-i2s.c @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +struct axi_i2s { + void __iomem *base; + + unsigned int clock; + + struct debugfs_regset32 regset; + spinlock_t lock; +}; + + +#define AXI_I2S_REG_RESET 0x00 +#define AXI_I2S_REG_CTRL 0x04 +#define AXI_I2S_REG_CLK_CTRL 0x08 +#define AXI_I2S_REG_STATUS 0x10 +#define AXI_I2S_REG_PERIOD_SIZE 0x18 + +#define AXI_I2S_RESET_GLOBAL BIT(0) +#define AXI_I2S_RESET_TX_FIFO BIT(1) +#define AXI_I2S_RESET_RX_FIFO BIT(2) + +#define AXI_I2S_CTRL_TX_EN BIT(0) +#define AXI_I2S_CTRL_RX_EN BIT(1) + +static const struct debugfs_reg32 axi_i2s_debugfs_regs[] = { + { "Reset", AXI_I2S_REG_RESET }, + { "Control", AXI_I2S_REG_CTRL }, + { "Status", AXI_I2S_REG_STATUS }, + { "Clock control", AXI_I2S_REG_CLK_CTRL }, + { "Period size", AXI_I2S_REG_PERIOD_SIZE }, +}; + +static inline uint32_t axi_i2s_read(const struct axi_i2s *i2s, + unsigned int reg) +{ + return readl(i2s->base + reg); +} + +static inline void axi_i2s_write(const struct axi_i2s *i2s, + unsigned int reg, uint32_t value) +{ + writel(value, i2s->base + reg); +} + +static int axi_i2s_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai); + uint32_t mask, ctrl; + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + mask = AXI_I2S_CTRL_RX_EN; + else + mask = AXI_I2S_CTRL_TX_EN; + + spin_lock(&i2s->lock); + ctrl = axi_i2s_read(i2s, AXI_I2S_REG_CTRL); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ctrl |= mask; + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ctrl &= ~mask; + break; + default: + return -EINVAL; + } + + axi_i2s_write(i2s, AXI_I2S_REG_CTRL, ctrl); + spin_unlock(&i2s->lock); + + return 0; +} + +static int axi_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai); + unsigned int bclk_div, frame_size; + + frame_size = snd_soc_params_to_frame_size(params) / 2; + bclk_div = DIV_ROUND_UP(i2s->clock, snd_soc_params_to_bclk(params)) - 1; + axi_i2s_write(i2s, AXI_I2S_REG_CLK_CTRL, (frame_size << 16) | bclk_div); + + printk("frame size: %d %d\n", frame_size, bclk_div); + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + unsigned int period_size = params_period_bytes(params) / 4 - 1; + axi_i2s_write(i2s, AXI_I2S_REG_PERIOD_SIZE, period_size); + } + + return 0; +} + +static int axi_i2s_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai); + uint32_t mask; + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + mask = AXI_I2S_RESET_RX_FIFO; + else + mask = AXI_I2S_RESET_TX_FIFO; + + axi_i2s_write(i2s, AXI_I2S_REG_RESET, mask); + + return 0; +} + +static const struct snd_soc_dai_ops axi_i2s_dai_ops = { + .startup = axi_i2s_startup, + .trigger = axi_i2s_trigger, + .hw_params = axi_i2s_hw_params, +}; + +static struct snd_soc_dai_driver axi_i2s_dai = { + .playback = { + .channels_min = 2, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S32_LE, + }, + .capture = { + .channels_min = 2, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &axi_i2s_dai_ops, + .symmetric_rates = 1, +}; + +static int __devinit axi_i2s_probe(struct platform_device *pdev) +{ + struct axi_i2s *i2s; + struct resource *res; + int ret; + + i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); + + if (!i2s) + return -ENOMEM; + + spin_lock_init(&i2s->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + i2s->base = devm_request_and_ioremap(&pdev->dev, res); + if (!i2s->base) + return -EBUSY; + + platform_set_drvdata(pdev, i2s); + + of_property_read_u32(pdev->dev.of_node, "clock-frequency", &i2s->clock); + ret = snd_soc_register_dai(&pdev->dev, &axi_i2s_dai); + + if (ret) { + dev_err(&pdev->dev, "Failed to register DAI\n"); + return ret; + } + + axi_i2s_write(i2s, AXI_I2S_REG_RESET, AXI_I2S_RESET_GLOBAL); + + i2s->regset.base = i2s->base; + i2s->regset.regs = axi_i2s_debugfs_regs; + i2s->regset.nregs = ARRAY_SIZE(axi_i2s_debugfs_regs); + + debugfs_create_regset32(dev_name(&pdev->dev), 0444, NULL, &i2s->regset); + + return 0; +} + +static int __devexit axi_i2s_dev_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dai(&pdev->dev); + + return 0; +} + +static const struct of_device_id axi_i2s_of_match[] __devinitconst = { + { .compatible = "adi,axi-i2s-1.00.a", }, + {}, +}; +MODULE_DEVICE_TABLE(of, axi_i2s_of_match); + +static struct platform_driver axi_i2s_driver = { + .driver = { + .name = "axi-i2s", + .owner = THIS_MODULE, + .of_match_table = axi_i2s_of_match, + }, + .probe = axi_i2s_probe, + .remove = __devexit_p(axi_i2s_dev_remove), +}; +module_platform_driver(axi_i2s_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("AXI I2S driver"); +MODULE_LICENSE("GPL"); From 7ff56ddb566526e9e2784bd71d227f57cf31c5f2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 13 Jun 2012 17:29:57 +0200 Subject: [PATCH 245/261] ASoC: Add ZED ADAU1761 board file Add support for the ADAU1761 found on the ZED board. Signed-off-by: Lars-Peter Clausen Signed-off-by: Tinghui WANG (Steven) --- sound/soc/xlnx/Kconfig | 6 ++ sound/soc/xlnx/Makefile | 2 + sound/soc/xlnx/zed_adau1761.c | 159 ++++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+) create mode 100644 sound/soc/xlnx/zed_adau1761.c diff --git a/sound/soc/xlnx/Kconfig b/sound/soc/xlnx/Kconfig index ad5455f9ce619..59974102be783 100644 --- a/sound/soc/xlnx/Kconfig +++ b/sound/soc/xlnx/Kconfig @@ -13,3 +13,9 @@ config SND_SOC_ADV7511_HDMI tristate "ADV7511 HDMI transmitter sound support" depends on SND_SOC_XILINX select SND_SOC_AXI_SPDIF + +config SND_SOC_ZED_ADAU1761 + tristate "ZED board sound support" + depends on SND_SOC_XILINX + select SND_SOC_AXI_I2S + select SND_SOC_ADAU1761 diff --git a/sound/soc/xlnx/Makefile b/sound/soc/xlnx/Makefile index d5908bdf96d80..2f352f18fd05a 100644 --- a/sound/soc/xlnx/Makefile +++ b/sound/soc/xlnx/Makefile @@ -2,9 +2,11 @@ snd-soc-xilinx-pcm-objs := xilinx-pcm.o snd-soc-axi-spdif-objs := axi-spdif.o snd-soc-axi-i2s-objs := axi-i2s.o snd-soc-adv7511-hdmi-objs := adv7511_hdmi.o +snd-soc-zed-adau1761-objs := zed_adau1761.o obj-$(CONFIG_SND_SOC_XILINX) += snd-soc-xilinx-pcm.o obj-$(CONFIG_SND_SOC_AXI_SPDIF) += snd-soc-axi-spdif.o obj-$(CONFIG_SND_SOC_AXI_I2S) += snd-soc-axi-i2s.o obj-$(CONFIG_SND_SOC_ADV7511_HDMI) += snd-soc-adv7511-hdmi.o +obj-$(CONFIG_SND_SOC_ZED_ADAU1761) += snd-soc-zed-adau1761.o diff --git a/sound/soc/xlnx/zed_adau1761.c b/sound/soc/xlnx/zed_adau1761.c new file mode 100644 index 0000000000000..08404c40b4c3a --- /dev/null +++ b/sound/soc/xlnx/zed_adau1761.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2012, Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "../codecs/adau17x1.h" + +static const struct snd_soc_dapm_widget zed_adau1761_widgets[] = { + SND_SOC_DAPM_SPK("Line Out", NULL), + SND_SOC_DAPM_HP("Headphone Out", NULL), + SND_SOC_DAPM_MIC("Mic In", NULL), + SND_SOC_DAPM_MIC("Line In", NULL), +}; + +static const struct snd_soc_dapm_route zed_adau1761_routes[] = { + { "Line Out", NULL, "LOUT" }, + { "Line Out", NULL, "ROUT" }, + { "Headphone Out", NULL, "LHP" }, + { "Headphone Out", NULL, "RHP" }, + { "Mic In", NULL, "MICBIAS" }, + { "LINN", NULL, "Mic In" }, + { "RINN", NULL, "Mic In" }, + { "LAUX", NULL, "Line In" }, + { "RAUX", NULL, "Line In" }, +}; + +static int zed_adau1761_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int pll_rate; + int ret; + + switch (params_rate(params)) { + case 48000: + case 8000: + case 12000: + case 16000: + case 24000: + case 32000: + case 96000: + pll_rate = 48000 * 1024; + break; + case 44100: + case 7350: + case 11025: + case 14700: + case 22050: + case 29400: + case 88200: + pll_rate = 44100 * 1024; + break; + default: + return -EINVAL; + } + + ret = snd_soc_dai_set_pll(codec_dai, ADAU17X1_PLL, + ADAU17X1_PLL_SRC_MCLK, 8000000, pll_rate); + if (ret) + return ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, ADAU17X1_CLK_SRC_PLL, pll_rate, + SND_SOC_CLOCK_IN); + + return ret; +} + +static struct snd_soc_ops zed_adau1761_ops = { + .hw_params = zed_adau1761_hw_params, +}; + +static struct snd_soc_dai_link zed_adau1761_dai_link = { + .name = "adau1761", + .stream_name = "adau1761", + .codec_dai_name = "adau-hifi", + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .ops = &zed_adau1761_ops, +}; + +static struct snd_soc_card zed_adau1761_card = { + .name = "ZED ADAU161", + .owner = THIS_MODULE, + .dai_link = &zed_adau1761_dai_link, + .num_links = 1, + .dapm_widgets = zed_adau1761_widgets, + .num_dapm_widgets = ARRAY_SIZE(zed_adau1761_widgets), + .dapm_routes = zed_adau1761_routes, + .num_dapm_routes = ARRAY_SIZE(zed_adau1761_routes), + .fully_routed = true, +}; + +static int __devinit zed_adau1761_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &zed_adau1761_card; + struct device_node *of_node = pdev->dev.of_node; + + if (!of_node) + return -ENXIO; + + card->dev = &pdev->dev; + + zed_adau1761_dai_link.codec_of_node = of_parse_phandle(of_node, "audio-codec", 0); + zed_adau1761_dai_link.cpu_dai_of_node = of_parse_phandle(of_node, "cpu-dai", 0); + zed_adau1761_dai_link.platform_of_node = of_parse_phandle(of_node, "pcm", 0); + + if (!zed_adau1761_dai_link.codec_of_node || !zed_adau1761_dai_link.cpu_dai_of_node || + !zed_adau1761_dai_link.platform_of_node) + return -ENXIO; + + return snd_soc_register_card(card); +} + +static int __devexit zed_adau1761_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + snd_soc_unregister_card(card); + + return 0; +} + +static const struct of_device_id zed_adau1761_of_match[] __devinitconst = { + { .compatible = "zed-adau1761-snd", }, + {}, +}; +MODULE_DEVICE_TABLE(of, zed_adau1761_of_match); + +static struct platform_driver zed_adau1761_card_driver = { + .driver = { + .name = "zed-adau1761-snd", + .owner = THIS_MODULE, + .of_match_table = zed_adau1761_of_match, + .pm = &snd_soc_pm_ops, + }, + .probe = zed_adau1761_probe, + .remove = __devexit_p(zed_adau1761_remove), +}; +module_platform_driver(zed_adau1761_card_driver); From beaecb3c1acaaf633996b0aa19d79557b0123f8b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 25 Jul 2012 17:11:56 +0200 Subject: [PATCH 246/261] ASoC: ADAU1761 hardcode ZED platform data This is a temporary hack for the ZED tree until we have proper device tree support in the ADAU1761 driver. Signed-off-by: Lars-Peter Clausen Signed-off-by: Tinghui WANG (Steven) --- sound/soc/codecs/adau1761.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c index 54825a2ed4856..2ae441ef589fa 100644 --- a/sound/soc/codecs/adau1761.c +++ b/sound/soc/codecs/adau1761.c @@ -611,12 +611,22 @@ static bool adau1761_readable_register(struct device *dev, unsigned int reg) return adau17x1_readable_register(dev, reg); } +static struct adau1761_platform_data def_pdata = { + .input_differential = true, + .lineout_mode = ADAU1761_OUTPUT_MODE_LINE, + .headphone_mode = ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS, + .digmic_jackdetect_pin_mode = ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE, +}; + static int adau1761_probe(struct snd_soc_codec *codec) { struct adau1761_platform_data *pdata = codec->dev->platform_data; struct adau *adau = snd_soc_codec_get_drvdata(codec); int ret; + pdata = &def_pdata; + codec->dev->platform_data = &def_pdata; + ret = adau17x1_probe(codec); if (ret < 0) return ret; From 047a048771b88bcc1ca01be3bcab9179c9f156bc Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 7 Aug 2012 15:05:23 +0200 Subject: [PATCH 247/261] ASoC: axi-spdif: Set frequency in SPDIF status word The the sampling frequency in the SPDIF status word. Signed-off-by: Lars-Peter Clausen Signed-off-by: Tinghui WANG (Steven) --- sound/soc/xlnx/axi-spdif.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/sound/soc/xlnx/axi-spdif.c b/sound/soc/xlnx/axi-spdif.c index 78d2a8ab28b49..02e41c1682979 100644 --- a/sound/soc/xlnx/axi-spdif.c +++ b/sound/soc/xlnx/axi-spdif.c @@ -46,6 +46,11 @@ struct axi_spdif { #define AXI_SPDIF_CTRL_RATIO_OFFSET 8 #define AXI_SPDIF_CTRL_RATIO_MASK (0xff << 8) +#define AXI_SPDIF_FREQ_44100 (0x0 << 6) +#define AXI_SPDIF_FREQ_48000 (0x1 << 6) +#define AXI_SPDIF_FREQ_32000 (0x2 << 6) +#define AXI_SPDIF_FREQ_NA (0x3 << 6) + static struct debugfs_reg32 axi_spdif_debugfs_regs[] = { { "Control", AXI_SPDIF_REG_CTRL }, { "Status", AXI_SPDIF_REG_STAT }, @@ -94,13 +99,29 @@ static int axi_spdif_hw_params(struct snd_pcm_substream *substream, { struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai); uint32_t ctrl = axi_spdif_read(spdif, AXI_SPDIF_REG_CTRL); - unsigned int ratio; + unsigned int ratio, stat; + + switch (params_rate(params)) { + case 32000: + stat = AXI_SPDIF_FREQ_32000; + break; + case 44100: + stat = AXI_SPDIF_FREQ_44100; + break; + case 48000: + stat = AXI_SPDIF_FREQ_48000; + break; + default: + stat = AXI_SPDIF_FREQ_NA; + break; + } ratio = DIV_ROUND_CLOSEST(spdif->clock, (params_rate(params) * 64 * 2)) - 1; ctrl &= ~AXI_SPDIF_CTRL_RATIO_MASK; ctrl |= ratio << AXI_SPDIF_CTRL_RATIO_OFFSET; + axi_spdif_write(spdif, AXI_SPDIF_REG_STAT, stat); axi_spdif_write(spdif, AXI_SPDIF_REG_CTRL, ctrl); return 0; From 0059111282f52102275fb00dc97c8587db315a1d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 29 Oct 2012 13:49:07 +0100 Subject: [PATCH 248/261] ASoC: xilinx-pcm: Reduce preallocated memory area We are running a little tight on DMAable memory otherwise if we have all three audio, video and xcomm running. Signed-off-by: Lars-Peter Clausen Signed-off-by: Tinghui WANG (Steven) --- sound/soc/xlnx/xilinx-pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/xlnx/xilinx-pcm.c b/sound/soc/xlnx/xilinx-pcm.c index 37e9fdf8fddca..085ab76af1135 100644 --- a/sound/soc/xlnx/xilinx-pcm.c +++ b/sound/soc/xlnx/xilinx-pcm.c @@ -92,7 +92,7 @@ static int xlnx_pcm_new(struct snd_soc_pcm_runtime *rtd) return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, - card->dev, 8 * 1024 * 1024, + card->dev, 1 * 1024 * 1024, xlnx_pcm_hardware.buffer_bytes_max); } From 032c865820896c708c40117744d122767659139a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 3 Dec 2012 10:52:34 +0100 Subject: [PATCH 249/261] ASoC:xlnx:zed_adau1761: Change MCLK frequency to 12288000 The bitstream contains a clock generator which generates a 12.288 MHz clock for the audio codec MCLK. Signed-off-by: Lars-Peter Clausen Signed-off-by: Tinghui WANG (Steven) --- sound/soc/xlnx/zed_adau1761.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/xlnx/zed_adau1761.c b/sound/soc/xlnx/zed_adau1761.c index 08404c40b4c3a..a2ed4c2c9a996 100644 --- a/sound/soc/xlnx/zed_adau1761.c +++ b/sound/soc/xlnx/zed_adau1761.c @@ -74,7 +74,7 @@ static int zed_adau1761_hw_params(struct snd_pcm_substream *substream, } ret = snd_soc_dai_set_pll(codec_dai, ADAU17X1_PLL, - ADAU17X1_PLL_SRC_MCLK, 8000000, pll_rate); + ADAU17X1_PLL_SRC_MCLK, 12288000, pll_rate); if (ret) return ret; From 244780985f6e25eb34a544571dc346e13f198e29 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 3 Dec 2012 10:53:29 +0100 Subject: [PATCH 250/261] ASoC:xlnx:axi-i2s: Fix bit-clock divider Also remove a debug printk. Signed-off-by: Lars-Peter Clausen Signed-off-by: Tinghui WANG (Steven) --- sound/soc/xlnx/axi-i2s.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/xlnx/axi-i2s.c b/sound/soc/xlnx/axi-i2s.c index 18810e4026874..0f9d359cbe6dc 100644 --- a/sound/soc/xlnx/axi-i2s.c +++ b/sound/soc/xlnx/axi-i2s.c @@ -114,11 +114,9 @@ static int axi_i2s_hw_params(struct snd_pcm_substream *substream, unsigned int bclk_div, frame_size; frame_size = snd_soc_params_to_frame_size(params) / 2; - bclk_div = DIV_ROUND_UP(i2s->clock, snd_soc_params_to_bclk(params)) - 1; + bclk_div = DIV_ROUND_UP(i2s->clock, snd_soc_params_to_bclk(params)) / 2 - 1; axi_i2s_write(i2s, AXI_I2S_REG_CLK_CTRL, (frame_size << 16) | bclk_div); - printk("frame size: %d %d\n", frame_size, bclk_div); - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { unsigned int period_size = params_period_bytes(params) / 4 - 1; axi_i2s_write(i2s, AXI_I2S_REG_PERIOD_SIZE, period_size); From 314e60d1e570a9c9152c847e7a79e83f767059a6 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Sun, 30 Dec 2012 14:27:56 -0800 Subject: [PATCH 251/261] ZedBoard: Fix mach-type to XILINX_EP107 --- arch/arm/mach-zynq/board_zed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-zynq/board_zed.c b/arch/arm/mach-zynq/board_zed.c index b615ed8c9f567..38ff153268702 100644 --- a/arch/arm/mach-zynq/board_zed.c +++ b/arch/arm/mach-zynq/board_zed.c @@ -61,7 +61,7 @@ static const char *xilinx_dt_match[] = { NULL }; -MACHINE_START(XILINX, "Xilinx Zynq Platform") +MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform") .map_io = xilinx_map_io, .init_irq = xilinx_irq_init, #ifdef GIC_CPU_CTRL From 30098401790527ad0e4d7303633976ad31345362 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Sun, 30 Dec 2012 14:30:55 -0800 Subject: [PATCH 252/261] XILINX: DMA: Fix merge error in xilinx dma driver. Keep consistent with the dma driver in ADI's tree. Certain functionalities in the driver are crucial for ADV7511 and sound drivers. --- drivers/dma/xilinx_dma.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/drivers/dma/xilinx_dma.c b/drivers/dma/xilinx_dma.c index f4f717eea8b9d..8888c00e6f837 100644 --- a/drivers/dma/xilinx_dma.c +++ b/drivers/dma/xilinx_dma.c @@ -1529,24 +1529,23 @@ static int __devinit xilinx_dma_of_probe(struct platform_device *pdev) if (xdev->chan[i]) xdev->chan[i]->num_frms = num_frames; } + } - ret = dma_async_device_register(&xdev->common); - if (ret) - goto err_free_chan; - - for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++) { - if (xdev->chan[i]) { - chan = xdev->chan[i]; - debugfs_create_regset32(dev_name(&chan->common.dev->device), S_IRUGO, NULL, &chan->debugfs_regset); - } - } - - platform_set_drvdata(pdev, xdev); + ret = dma_async_device_register(&xdev->common); + if (ret) + goto err_free_chan; - DMA_OUT(&chan->regs->cr, reg); - return 0; + for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++) { + if (xdev->chan[i]) { + chan = xdev->chan[i]; + debugfs_create_regset32(dev_name(&chan->common.dev->device), S_IRUGO, NULL, &chan->debugfs_regset); + } } + platform_set_drvdata(pdev, xdev); + + return 0; + err_free_chan: for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++) { if (xdev->chan[i]) @@ -1563,10 +1562,9 @@ static int __devexit xilinx_dma_of_remove(struct platform_device *pdev) dma_async_device_unregister(&xdev->common); - DMA_OUT(&chan->regs->cr, reg); - break; - default: - return -ENXIO; + for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++) { + if (xdev->chan[i]) + xilinx_dma_chan_remove(xdev->chan[i]); } iounmap(xdev->regs); From 349b81aec17a25514c3f0a3ac2681fb988301674 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Sun, 30 Dec 2012 14:37:01 -0800 Subject: [PATCH 253/261] ADV7511: Kconfig: Auto select DRM_ANALOG for ADV7511 in configuration DRM_ANALOG is needed for ADV7511 driver to compile. I2C is removed from the dependency checking as selecting DRM guarantees I2C selected. --- drivers/gpu/drm/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 9045141ef4b6e..453a226062843 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -198,8 +198,9 @@ config DRM_SAVAGE config DRM_ENCODER_ADV7511 tristate "AV7511 encoder" - depends on I2C && DRM + depends on DRM select REGMAP_I2C + select DRM_ANALOG source "drivers/gpu/drm/analog/Kconfig" From a42d4f71ec5e325f7ed306caf2a3c18b8eb2fc52 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Mon, 31 Dec 2012 15:05:29 -0800 Subject: [PATCH 254/261] Config: Update ZedBoard Default Configuration File: digilent_zed_defconfig --- arch/arm/configs/digilent_zed_defconfig | 476 +++++++++++------------- 1 file changed, 223 insertions(+), 253 deletions(-) diff --git a/arch/arm/configs/digilent_zed_defconfig b/arch/arm/configs/digilent_zed_defconfig index 7f1fdd0e93ade..846507d078f64 100755 --- a/arch/arm/configs/digilent_zed_defconfig +++ b/arch/arm/configs/digilent_zed_defconfig @@ -1,23 +1,17 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 3.3.0-14.2-build1 Kernel Configuration +# Linux/arm 3.6.0-digilent-13.01 Kernel Configuration # CONFIG_ARM=y +CONFIG_MIGHT_HAVE_PCI=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y CONFIG_GENERIC_GPIO=y -# CONFIG_ARCH_USES_GETTIMEOFFSET is not set -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_KTIME_SCALAR=y CONFIG_HAVE_PROC_CPU=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_LOCKDEP_SUPPORT=y CONFIG_TRACE_IRQFLAGS_SUPPORT=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_GENERIC_LOCKBREAK=y CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_ARCH_HAS_CPUFREQ=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_NEED_DMA_MAP_STATE=y @@ -39,9 +33,11 @@ CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_XZ is not set # CONFIG_KERNEL_LZO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y @@ -61,18 +57,30 @@ CONFIG_HAVE_GENERIC_HARDIRQS=y # IRQ subsystem # CONFIG_GENERIC_HARDIRQS=y -CONFIG_HAVE_SPARSE_IRQ=y +CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_HARDIRQS_SW_RESEND=y CONFIG_IRQ_DOMAIN=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_KTIME_SCALAR=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y # # RCU Subsystem # CONFIG_TREE_PREEMPT_RCU=y CONFIG_PREEMPT_RCU=y -# CONFIG_RCU_TRACE is not set CONFIG_RCU_FANOUT=32 +CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_RCU_FANOUT_EXACT is not set # CONFIG_TREE_RCU_TRACE is not set # CONFIG_RCU_BOOST is not set @@ -121,7 +129,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -# CONFIG_PERF_COUNTERS is not set # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -131,13 +138,20 @@ CONFIG_SLAB=y # CONFIG_PROFILING is not set CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set +# CONFIG_JUMP_LABEL is not set CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y # # GCOV-based kernel profiling @@ -182,7 +196,7 @@ CONFIG_DEFAULT_IOSCHED="cfq" # CONFIG_INLINE_SPIN_LOCK_BH is not set # CONFIG_INLINE_SPIN_LOCK_IRQ is not set # CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set -# CONFIG_INLINE_SPIN_UNLOCK is not set +CONFIG_UNINLINE_SPIN_UNLOCK=y # CONFIG_INLINE_SPIN_UNLOCK_BH is not set # CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set # CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set @@ -211,6 +225,7 @@ CONFIG_MUTEX_SPIN_ON_OWNER=y # System Type # CONFIG_MMU=y +# CONFIG_ARCH_SOCFPGA is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set @@ -232,9 +247,8 @@ CONFIG_MMU=y # CONFIG_ARCH_IOP13XX is not set # CONFIG_ARCH_IOP32X is not set # CONFIG_ARCH_IOP33X is not set -# CONFIG_ARCH_IXP23XX is not set -# CONFIG_ARCH_IXP2000 is not set # CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_MVEBU is not set # CONFIG_ARCH_DOVE is not set # CONFIG_ARCH_KIRKWOOD is not set # CONFIG_ARCH_LPC32XX is not set @@ -251,7 +265,7 @@ CONFIG_MMU=y # CONFIG_ARCH_SHMOBILE is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C24XX is not set # CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_S5P64X0 is not set # CONFIG_ARCH_S5PC100 is not set @@ -269,10 +283,6 @@ CONFIG_ARCH_ZYNQ=y # CONFIG_GPIO_PCA953X is not set # CONFIG_KEYBOARD_GPIO_POLLED is not set -# -# System MMU -# - # # Xilinx Specific Options # @@ -283,10 +293,7 @@ CONFIG_XILINX_L1_PREFETCH=y CONFIG_XILINX_L2_PREFETCH=y CONFIG_XILINX_ZED=y # CONFIG_XILINX_TEST is not set -CONFIG_ZYNQ_DEFAULT_KERNEL=y -# CONFIG_ZYNQ_AMP_CPU0_MASTER is not set -# CONFIG_ZYNQ_AMP_CPU1_SLAVE is not set -# CONFIG_ZYNQ_CPU1_TEST is not set +# CONFIG_XILINX_AXIPCIE is not set # # Processor Type @@ -348,6 +355,7 @@ CONFIG_ICST=y # CONFIG_ARM_AMBA=y CONFIG_ISA_DMA_API=y +# CONFIG_PCI is not set # CONFIG_PCI_SYSCALL is not set # CONFIG_ARCH_SUPPORTS_MSI is not set # CONFIG_PCCARD is not set @@ -355,10 +363,6 @@ CONFIG_ISA_DMA_API=y # # Kernel Features # -CONFIG_TICK_ONESHOT=y -# CONFIG_NO_HZ is not set -CONFIG_HIGH_RES_TIMERS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_HAVE_SMP=y CONFIG_SMP=y CONFIG_SMP_ON_UP=y @@ -366,13 +370,14 @@ CONFIG_ARM_CPU_TOPOLOGY=y # CONFIG_SCHED_MC is not set # CONFIG_SCHED_SMT is not set CONFIG_HAVE_ARM_SCU=y +# CONFIG_ARM_ARCH_TIMER is not set CONFIG_HAVE_ARM_TWD=y CONFIG_VMSPLIT_3G=y # CONFIG_VMSPLIT_2G is not set # CONFIG_VMSPLIT_1G is not set CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_NR_CPUS=4 -# CONFIG_HOTPLUG_CPU is not set +CONFIG_HOTPLUG_CPU=y CONFIG_LOCAL_TIMERS=y CONFIG_ARCH_NR_GPIO=0 # CONFIG_PREEMPT_NONE is not set @@ -403,7 +408,9 @@ CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_CROSS_MEMORY_ATTACH=y # CONFIG_CLEANCACHE is not set +# CONFIG_FRONTSWAP is not set CONFIG_FORCE_MAX_ZONEORDER=15 CONFIG_ALIGNMENT_TRAP=y # CONFIG_UACCESS_WITH_MEMCPY is not set @@ -423,13 +430,20 @@ CONFIG_CMDLINE_FROM_BOOTLOADER=y # CONFIG_CMDLINE_EXTEND is not set # CONFIG_CMDLINE_FORCE is not set # CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set # CONFIG_CRASH_DUMP is not set # CONFIG_AUTO_ZRELADDR is not set # # CPU Power Management # + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set # CONFIG_CPU_IDLE is not set +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set # # Floating point emulation @@ -460,6 +474,8 @@ CONFIG_PM_RUNTIME=y CONFIG_PM=y # CONFIG_PM_DEBUG is not set # CONFIG_APM_EMULATION is not set +CONFIG_ARCH_HAS_OPP=y +# CONFIG_PM_OPP is not set CONFIG_PM_CLK=y CONFIG_ARCH_SUSPEND_POSSIBLE=y # CONFIG_ARM_CPU_SUSPEND is not set @@ -489,6 +505,7 @@ CONFIG_NET_IPIP=m # CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_NET_IPVTI is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set @@ -544,7 +561,6 @@ CONFIG_VLAN_8021Q=m # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_PHONET is not set # CONFIG_IEEE802154 is not set @@ -556,6 +572,7 @@ CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y CONFIG_BQL=y +# CONFIG_BPF_JIT is not set # # Network testing @@ -579,6 +596,7 @@ CONFIG_WIRELESS=y # CONFIG_CAIF is not set # CONFIG_CEPH_LIB is not set # CONFIG_NFC is not set +CONFIG_HAVE_BPF_JIT=y # # Device Drivers @@ -602,7 +620,8 @@ CONFIG_EXTRA_FIRMWARE="" CONFIG_REGMAP=y CONFIG_REGMAP_I2C=y CONFIG_REGMAP_SPI=y -# CONFIG_DMA_SHARED_BUFFER is not set +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_CMA is not set CONFIG_CONNECTOR=y CONFIG_PROC_EVENTS=y CONFIG_MTD=y @@ -690,10 +709,11 @@ CONFIG_MTD_NAND=y # CONFIG_MTD_NAND_GPIO is not set CONFIG_MTD_NAND_IDS=y # CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_DOCG4 is not set # CONFIG_MTD_NAND_NANDSIM is not set # CONFIG_MTD_NAND_PLATFORM is not set # CONFIG_MTD_ALAUDA is not set -CONFIG_MTD_NAND_XILINX_PSS=y +# CONFIG_MTD_NAND_XILINX_PS is not set # CONFIG_MTD_ONENAND is not set # @@ -714,11 +734,10 @@ CONFIG_OF_EARLY_FLATTREE=y CONFIG_OF_ADDRESS=y CONFIG_OF_IRQ=y CONFIG_OF_DEVICE=y -CONFIG_OF_GPIO=y CONFIG_OF_I2C=y CONFIG_OF_NET=y -CONFIG_OF_SPI=y CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y # CONFIG_PARPORT is not set CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_COW_COMMON is not set @@ -735,6 +754,7 @@ CONFIG_BLK_DEV_RAM_SIZE=35384 # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set # CONFIG_MG_DISK is not set +# CONFIG_VIRTIO_BLK is not set # CONFIG_BLK_DEV_RBD is not set # @@ -755,7 +775,8 @@ CONFIG_BLK_DEV_RAM_SIZE=35384 # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set # CONFIG_TI_DAC7512 is not set -# CONFIG_BMP085 is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set # CONFIG_USB_SWITCH_FSA9480 is not set # CONFIG_SI570 is not set # CONFIG_C2PORT is not set @@ -769,7 +790,6 @@ CONFIG_EEPROM_AT25=y # CONFIG_EEPROM_MAX6875 is not set # CONFIG_EEPROM_93CX6 is not set # CONFIG_EEPROM_93XX46 is not set -# CONFIG_IWMC3200TOP is not set # # Texas Instruments shared transport line discipline @@ -807,7 +827,6 @@ CONFIG_SCSI_MULTI_LUN=y # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set # CONFIG_SCSI_SCAN_ASYNC is not set -CONFIG_SCSI_WAIT_SCAN=m # # SCSI Transports @@ -824,6 +843,7 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_LIBFC is not set # CONFIG_LIBFCOE is not set # CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_VIRTIO is not set # CONFIG_SCSI_DH is not set # CONFIG_SCSI_OSD_INITIATOR is not set # CONFIG_ATA is not set @@ -842,6 +862,7 @@ CONFIG_NET_CORE=y # CONFIG_NET_POLL_CONTROLLER is not set # CONFIG_TUN is not set # CONFIG_VETH is not set +# CONFIG_VIRTIO_NET is not set # # CAIF transport drivers @@ -850,6 +871,7 @@ CONFIG_ETHERNET=y # CONFIG_NET_VENDOR_BROADCOM is not set # CONFIG_NET_CALXEDA_XGMAC is not set # CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CIRRUS is not set # CONFIG_DM9000 is not set # CONFIG_DNET is not set # CONFIG_NET_VENDOR_FARADAY is not set @@ -862,7 +884,14 @@ CONFIG_ETHERNET=y # CONFIG_NET_VENDOR_SEEQ is not set # CONFIG_NET_VENDOR_SMSC is not set # CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_WIZNET is not set CONFIG_NET_VENDOR_XILINX=y +# CONFIG_XILINX_EMACLITE is not set +# CONFIG_XILINX_AXI_EMAC is not set +# CONFIG_XILINX_LLTEMAC_MARVELL_88E1111_RGMII is not set +CONFIG_XILINX_LLTEMAC_MARVELL_88E1111_GMII=y +# CONFIG_XILINX_LLTEMAC_MARVELL_88E1111_MII is not set +# CONFIG_XILINX_LLTEMAC_XILINX_1000BASEX is not set CONFIG_XILINX_PS_EMAC=y CONFIG_XILINX_PS_EMAC_HWTSTAMP=y CONFIG_PHYLIB=y @@ -870,6 +899,7 @@ CONFIG_PHYLIB=y # # MII PHY device drivers # +# CONFIG_AMD_PHY is not set CONFIG_MARVELL_PHY=y # CONFIG_DAVICOM_PHY is not set # CONFIG_QSEMI_PHY is not set @@ -878,6 +908,7 @@ CONFIG_MARVELL_PHY=y # CONFIG_VITESSE_PHY is not set # CONFIG_SMSC_PHY is not set # CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM87XX_PHY is not set # CONFIG_ICPLUS_PHY is not set # CONFIG_REALTEK_PHY is not set # CONFIG_NATIONAL_PHY is not set @@ -887,6 +918,7 @@ CONFIG_MARVELL_PHY=y # CONFIG_FIXED_PHY is not set CONFIG_MDIO_BITBANG=y # CONFIG_MDIO_GPIO is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set # CONFIG_MICREL_KS8995MA is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -907,7 +939,6 @@ CONFIG_MDIO_BITBANG=y # # CONFIG_WAN is not set # CONFIG_ISDN is not set -# CONFIG_PHONE is not set # # Input device support @@ -916,6 +947,7 @@ CONFIG_INPUT=y # CONFIG_INPUT_FF_MEMLESS is not set # CONFIG_INPUT_POLLDEV is not set CONFIG_INPUT_SPARSEKMAP=y +# CONFIG_INPUT_MATRIXKMAP is not set # # Userland interfaces @@ -943,6 +975,7 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_TCA8418 is not set # CONFIG_KEYBOARD_MATRIX is not set # CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set # CONFIG_KEYBOARD_MAX7359 is not set # CONFIG_KEYBOARD_MCS is not set # CONFIG_KEYBOARD_MPR121 is not set @@ -951,6 +984,7 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_SAMSUNG is not set # CONFIG_KEYBOARD_STOWAWAY is not set # CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set # CONFIG_KEYBOARD_XTKBD is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y @@ -967,6 +1001,7 @@ CONFIG_MOUSE_PS2_TRACKPOINT=y # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_MOUSE_GPIO is not set # CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set @@ -1012,6 +1047,7 @@ CONFIG_UNIX98_PTYS=y # CONFIG_SERIAL_AMBA_PL011 is not set # CONFIG_SERIAL_MAX3100 is not set # CONFIG_SERIAL_MAX3107 is not set +# CONFIG_SERIAL_UARTLITE is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_TIMBERDALE is not set @@ -1022,13 +1058,13 @@ CONFIG_SERIAL_XILINX_PS_UART=y CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y # CONFIG_TTY_PRINTK is not set # CONFIG_HVC_DCC is not set +# CONFIG_VIRTIO_CONSOLE is not set # CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set CONFIG_XILINX_DEVCFG=y # CONFIG_R3964 is not set # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set -# CONFIG_RAMOOPS is not set CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_COMPAT=y @@ -1053,6 +1089,7 @@ CONFIG_I2C_ALGOBIT=y # # CONFIG_I2C_DESIGNWARE_PLATFORM is not set CONFIG_I2C_GPIO=y +# CONFIG_I2C_NOMADIK is not set # CONFIG_I2C_OCORES is not set # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_PXA_PCI is not set @@ -1088,9 +1125,10 @@ CONFIG_SPI_GPIO=y # CONFIG_SPI_OC_TINY is not set # CONFIG_SPI_PL022 is not set # CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_AD9250FMC is not set # CONFIG_SPI_XILINX is not set CONFIG_SPI_XILINX_PS_QSPI=y -# CONFIG_XILINX_PS_QSPI_USE_DUAL_FLASH is not set CONFIG_SPI_XILINX_PS_SPI=y # CONFIG_SPI_DESIGNWARE is not set @@ -1099,6 +1137,7 @@ CONFIG_SPI_XILINX_PS_SPI=y # # CONFIG_SPI_SPIDEV is not set # CONFIG_SPI_TLE62X0 is not set +# CONFIG_HSI is not set # # PPS support @@ -1116,8 +1155,10 @@ CONFIG_SPI_XILINX_PS_SPI=y # # Enable Device Drivers -> PPS to see the PTP clock options. # +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y +CONFIG_OF_GPIO=y # CONFIG_DEBUG_GPIO is not set CONFIG_GPIO_SYSFS=y @@ -1125,6 +1166,7 @@ CONFIG_GPIO_SYSFS=y # Memory mapped GPIO drivers: # # CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_EM is not set # CONFIG_GPIO_PL061 is not set # CONFIG_GPIO_XILINX is not set CONFIG_GPIO_XILINX_PS=y @@ -1159,10 +1201,11 @@ CONFIG_GPIO_XILINX_PS=y # # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set +# CONFIG_POWER_AVS is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_CORE is not set +CONFIG_WATCHDOG_CORE=y # CONFIG_WATCHDOG_NOWAYOUT is not set # @@ -1173,7 +1216,6 @@ CONFIG_WATCHDOG=y # CONFIG_DW_WATCHDOG is not set # CONFIG_MPCORE_WATCHDOG is not set CONFIG_XILINX_PS_WATCHDOG=y -# CONFIG_XILINX_SCU_WATCHDOG is not set # CONFIG_MAX63XX_WATCHDOG is not set # @@ -1198,19 +1240,23 @@ CONFIG_BCMA_POSSIBLE=y # # CONFIG_MFD_CORE is not set # CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_ASIC3 is not set # CONFIG_HTC_EGPIO is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_HTC_I2CPLD is not set +# CONFIG_MFD_LM3533 is not set # CONFIG_TPS6105X is not set # CONFIG_TPS65010 is not set # CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65217 is not set # CONFIG_MFD_TPS65910 is not set # CONFIG_MFD_TPS65912_I2C is not set # CONFIG_MFD_TPS65912_SPI is not set # CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set # CONFIG_MFD_STMPE is not set # CONFIG_MFD_TC3589X is not set # CONFIG_MFD_TMIO is not set @@ -1221,218 +1267,62 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_DA9052_SPI is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set -# CONFIG_MFD_S5M_CORE is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM831X_SPI is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set # CONFIG_ABX500_CORE is not set # CONFIG_EZX_PCAP is not set # CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_TPS65090 is not set # CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_PALMAS is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=y # # Multimedia core support # -# CONFIG_MEDIA_CONTROLLER is not set -CONFIG_VIDEO_DEV=y -CONFIG_VIDEO_V4L2_COMMON=y -# CONFIG_DVB_CORE is not set -CONFIG_VIDEO_MEDIA=y - -# -# Multimedia drivers -# -# CONFIG_RC_CORE is not set -# CONFIG_MEDIA_ATTACH is not set -CONFIG_MEDIA_TUNER=y -# CONFIG_MEDIA_TUNER_CUSTOMISE is not set -CONFIG_MEDIA_TUNER_SIMPLE=y -CONFIG_MEDIA_TUNER_TDA8290=y -CONFIG_MEDIA_TUNER_TDA827X=y -CONFIG_MEDIA_TUNER_TDA18271=y -CONFIG_MEDIA_TUNER_TDA9887=y -CONFIG_MEDIA_TUNER_TEA5761=y -CONFIG_MEDIA_TUNER_TEA5767=y -CONFIG_MEDIA_TUNER_MT20XX=y -CONFIG_MEDIA_TUNER_XC2028=y -CONFIG_MEDIA_TUNER_XC5000=y -CONFIG_MEDIA_TUNER_XC4000=y -CONFIG_MEDIA_TUNER_MC44S803=y -CONFIG_VIDEO_V4L2=y -CONFIG_VIDEOBUF2_CORE=y -CONFIG_VIDEOBUF2_MEMOPS=y -CONFIG_VIDEOBUF2_VMALLOC=y -CONFIG_VIDEO_CAPTURE_DRIVERS=y -# CONFIG_VIDEO_ADV_DEBUG is not set -# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set -# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set - -# -# Encoders, decoders, sensors and other helper chips -# +# CONFIG_MEDIA_CAMERA_SUPPORT is not set +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set +# CONFIG_MEDIA_RADIO_SUPPORT is not set +# CONFIG_MEDIA_RC_SUPPORT is not set # -# Audio decoders, processors and mixers +# Media drivers # -# CONFIG_VIDEO_TVAUDIO is not set -# CONFIG_VIDEO_TDA7432 is not set -# CONFIG_VIDEO_TDA9840 is not set -# CONFIG_VIDEO_TEA6415C is not set -# CONFIG_VIDEO_TEA6420 is not set -# CONFIG_VIDEO_MSP3400 is not set -# CONFIG_VIDEO_CS5345 is not set -# CONFIG_VIDEO_CS53L32A is not set -# CONFIG_VIDEO_TLV320AIC23B is not set -# CONFIG_VIDEO_WM8775 is not set -# CONFIG_VIDEO_WM8739 is not set -# CONFIG_VIDEO_VP27SMPX is not set - -# -# RDS decoders -# -# CONFIG_VIDEO_SAA6588 is not set - -# -# Video decoders -# -# CONFIG_VIDEO_ADV7180 is not set -# CONFIG_VIDEO_BT819 is not set -# CONFIG_VIDEO_BT856 is not set -# CONFIG_VIDEO_BT866 is not set -# CONFIG_VIDEO_KS0127 is not set -# CONFIG_VIDEO_SAA7110 is not set -# CONFIG_VIDEO_SAA711X is not set -# CONFIG_VIDEO_SAA7191 is not set -# CONFIG_VIDEO_TVP514X is not set -# CONFIG_VIDEO_TVP5150 is not set -# CONFIG_VIDEO_TVP7002 is not set -# CONFIG_VIDEO_VPX3220 is not set - -# -# Video and audio decoders -# -# CONFIG_VIDEO_SAA717X is not set -# CONFIG_VIDEO_CX25840 is not set - -# -# MPEG video encoders -# -# CONFIG_VIDEO_CX2341X is not set - -# -# Video encoders -# -# CONFIG_VIDEO_SAA7127 is not set -# CONFIG_VIDEO_SAA7185 is not set -# CONFIG_VIDEO_ADV7170 is not set -# CONFIG_VIDEO_ADV7175 is not set -# CONFIG_VIDEO_ADV7343 is not set -# CONFIG_VIDEO_AK881X is not set - -# -# Camera sensor devices -# -# CONFIG_VIDEO_OV7670 is not set -# CONFIG_VIDEO_MT9V011 is not set -# CONFIG_VIDEO_TCM825X is not set -# CONFIG_VIDEO_SR030PC30 is not set - -# -# Flash devices -# - -# -# Video improvement chips -# -# CONFIG_VIDEO_UPD64031A is not set -# CONFIG_VIDEO_UPD64083 is not set - -# -# Miscelaneous helper chips -# -# CONFIG_VIDEO_THS7303 is not set -# CONFIG_VIDEO_M52790 is not set -# CONFIG_VIDEO_VIVI is not set -CONFIG_V4L_USB_DRIVERS=y -CONFIG_USB_VIDEO_CLASS=y -CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y -CONFIG_USB_GSPCA=y -# CONFIG_USB_M5602 is not set -# CONFIG_USB_STV06XX is not set -# CONFIG_USB_GL860 is not set -# CONFIG_USB_GSPCA_BENQ is not set -# CONFIG_USB_GSPCA_CONEX is not set -# CONFIG_USB_GSPCA_CPIA1 is not set -# CONFIG_USB_GSPCA_ETOMS is not set -# CONFIG_USB_GSPCA_FINEPIX is not set -# CONFIG_USB_GSPCA_JEILINJ is not set -# CONFIG_USB_GSPCA_JL2005BCD is not set -# CONFIG_USB_GSPCA_KINECT is not set -# CONFIG_USB_GSPCA_KONICA is not set -# CONFIG_USB_GSPCA_MARS is not set -# CONFIG_USB_GSPCA_MR97310A is not set -# CONFIG_USB_GSPCA_NW80X is not set -# CONFIG_USB_GSPCA_OV519 is not set -# CONFIG_USB_GSPCA_OV534 is not set -# CONFIG_USB_GSPCA_OV534_9 is not set -# CONFIG_USB_GSPCA_PAC207 is not set -# CONFIG_USB_GSPCA_PAC7302 is not set -# CONFIG_USB_GSPCA_PAC7311 is not set -# CONFIG_USB_GSPCA_SE401 is not set -# CONFIG_USB_GSPCA_SN9C2028 is not set -# CONFIG_USB_GSPCA_SN9C20X is not set -# CONFIG_USB_GSPCA_SONIXB is not set -# CONFIG_USB_GSPCA_SONIXJ is not set -# CONFIG_USB_GSPCA_SPCA500 is not set -# CONFIG_USB_GSPCA_SPCA501 is not set -# CONFIG_USB_GSPCA_SPCA505 is not set -# CONFIG_USB_GSPCA_SPCA506 is not set -# CONFIG_USB_GSPCA_SPCA508 is not set -# CONFIG_USB_GSPCA_SPCA561 is not set -# CONFIG_USB_GSPCA_SPCA1528 is not set -# CONFIG_USB_GSPCA_SQ905 is not set -# CONFIG_USB_GSPCA_SQ905C is not set -# CONFIG_USB_GSPCA_SQ930X is not set -# CONFIG_USB_GSPCA_STK014 is not set -# CONFIG_USB_GSPCA_STV0680 is not set -# CONFIG_USB_GSPCA_SUNPLUS is not set -# CONFIG_USB_GSPCA_T613 is not set -# CONFIG_USB_GSPCA_TOPRO is not set -# CONFIG_USB_GSPCA_TV8532 is not set -# CONFIG_USB_GSPCA_VC032X is not set -# CONFIG_USB_GSPCA_VICAM is not set -# CONFIG_USB_GSPCA_XIRLINK_CIT is not set -# CONFIG_USB_GSPCA_ZC3XX is not set -# CONFIG_VIDEO_PVRUSB2 is not set -# CONFIG_VIDEO_HDPVR is not set -# CONFIG_VIDEO_EM28XX is not set -# CONFIG_VIDEO_USBVISION is not set -# CONFIG_USB_ET61X251 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_PWC is not set -# CONFIG_VIDEO_CPIA2 is not set -# CONFIG_USB_ZR364XX is not set -# CONFIG_USB_STKWEBCAM is not set -# CONFIG_USB_S2255 is not set -# CONFIG_V4L_PLATFORM_DRIVERS is not set -# CONFIG_V4L_MEM2MEM_DRIVERS is not set -# CONFIG_RADIO_ADAPTERS is not set # # Graphics support # CONFIG_DRM=y CONFIG_DRM_KMS_HELPER=y +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +CONFIG_DRM_GEM_CMA_HELPER=y +CONFIG_DRM_KMS_CMA_HELPER=y + +# +# I2C encoder or helper chips +# +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_SIL164 is not set CONFIG_DRM_ENCODER_ADV7511=y +CONFIG_DRM_ANALOG=y +# CONFIG_DRM_UDL is not set # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set CONFIG_FB=y @@ -1467,7 +1357,9 @@ CONFIG_FB_SYS_IMAGEBLIT=y # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set # CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set # CONFIG_FB_XYLON is not set +# CONFIG_EXYNOS_VIDEO is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # @@ -1518,22 +1410,23 @@ CONFIG_SND_JACK=y # CONFIG_SND_USB is not set CONFIG_SND_SOC=y CONFIG_SND_SOC_DMAENGINE_PCM=y +# CONFIG_SND_DESIGNWARE_I2S is not set CONFIG_SND_SOC_XILINX=y CONFIG_SND_SOC_AXI_SPDIF=y CONFIG_SND_SOC_ADV7511_HDMI=y +# CONFIG_SND_SOC_ZED_ADAU1761 is not set CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_SND_SOC_ALL_CODECS is not set +# CONFIG_SND_SIMPLE_CARD is not set # CONFIG_SOUND_PRIME is not set -CONFIG_HID_SUPPORT=y -CONFIG_HID=y -# CONFIG_HIDRAW is not set # -# USB Input Devices +# HID support # -CONFIG_USB_HID=y -# CONFIG_HID_PID is not set -# CONFIG_USB_HIDDEV is not set +CONFIG_HID=y +# CONFIG_HIDRAW is not set +# CONFIG_UHID is not set +CONFIG_HID_GENERIC=y # # Special HID drivers @@ -1541,6 +1434,7 @@ CONFIG_USB_HID=y # CONFIG_HID_A4TECH is not set # CONFIG_HID_ACRUX is not set # CONFIG_HID_APPLE is not set +# CONFIG_HID_AUREAL is not set # CONFIG_HID_BELKIN is not set # CONFIG_HID_CHERRY is not set # CONFIG_HID_CHICONY is not set @@ -1558,6 +1452,7 @@ CONFIG_USB_HID=y # CONFIG_HID_TWINHAN is not set # CONFIG_HID_KENSINGTON is not set # CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO_TPKBD is not set # CONFIG_HID_LOGITECH is not set CONFIG_HID_MICROSOFT=y # CONFIG_HID_MONTEREY is not set @@ -1569,31 +1464,38 @@ CONFIG_HID_MICROSOFT=y # CONFIG_HID_PICOLCD is not set # CONFIG_HID_PRIMAX is not set # CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set # CONFIG_HID_SAMSUNG is not set # CONFIG_HID_SONY is not set # CONFIG_HID_SPEEDLINK is not set # CONFIG_HID_SUNPLUS is not set # CONFIG_HID_GREENASIA is not set # CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set # CONFIG_HID_TOPSEED is not set # CONFIG_HID_THRUSTMASTER is not set # CONFIG_HID_ZEROPLUS is not set # CONFIG_HID_ZYDACRON is not set -CONFIG_USB_SUPPORT=y -CONFIG_USB_COMMON=y -CONFIG_USB_ARCH_HAS_HCD=y + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set # CONFIG_USB_ARCH_HAS_OHCI is not set CONFIG_USB_ARCH_HAS_EHCI=y # CONFIG_USB_ARCH_HAS_XHCI is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB=y # CONFIG_USB_DEBUG is not set -# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y # # Miscellaneous USB options # -CONFIG_USB_DEVICEFS=y -CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_DYNAMIC_MINORS is not set CONFIG_USB_SUSPEND=y CONFIG_USB_OTG=y @@ -1612,14 +1514,15 @@ CONFIG_USB_EHCI_ROOT_HUB_TT=y # CONFIG_USB_EHCI_TT_NEWSCHED is not set CONFIG_USB_XUSBPS_DR_OF=y CONFIG_USB_EHCI_XUSBPS=y -# CONFIG_USB_EHCI_MV is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_CHIPIDEA is not set # CONFIG_USB_RENESAS_USBHS is not set # @@ -1689,17 +1592,26 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_YUREX is not set + +# +# USB Physical Layer drivers +# +# CONFIG_USB_ISP1301 is not set CONFIG_USB_GADGET=y # CONFIG_USB_GADGET_DEBUG is not set # CONFIG_USB_GADGET_DEBUG_FILES is not set # CONFIG_USB_GADGET_DEBUG_FS is not set CONFIG_USB_GADGET_VBUS_DRAW=2 CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# CONFIG_USB_GADGET_XUSBPS=y +# CONFIG_XUSBPS_ERRATA_DT654401 is not set CONFIG_USB_XUSBPS=y # CONFIG_USB_FUSB300 is not set # CONFIG_USB_R8A66597 is not set -# CONFIG_USB_GADGET_XILINX is not set # CONFIG_USB_MV_UDC is not set # CONFIG_USB_M66592 is not set # CONFIG_USB_NET2272 is not set @@ -1723,7 +1635,6 @@ CONFIG_USB_FILE_STORAGE=m # CONFIG_USB_G_MULTI is not set # CONFIG_USB_G_HID is not set # CONFIG_USB_G_DBGP is not set -# CONFIG_USB_G_WEBCAM is not set # # OTG and related infrastructure @@ -1734,6 +1645,7 @@ CONFIG_USB_ULPI=y CONFIG_USB_ULPI_VIEWPORT=y # CONFIG_NOP_USB_XCEIV is not set CONFIG_USB_XUSBPS_OTG=y +CONFIG_XILINX_ZED_USB_OTG=y CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_UNSAFE_RESUME is not set @@ -1775,18 +1687,22 @@ CONFIG_LEDS_GPIO=y # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set # CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA9633 is not set # CONFIG_LEDS_DAC124S085 is not set # CONFIG_LEDS_BD2802 is not set # CONFIG_LEDS_LT3593 is not set # CONFIG_LEDS_RENESAS_TPU is not set # CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_LM3556 is not set # CONFIG_LEDS_OT200 is not set +# CONFIG_LEDS_BLINKM is not set CONFIG_LEDS_TRIGGERS=y # # LED Triggers # CONFIG_LEDS_TRIGGER_TIMER=y +# CONFIG_LEDS_TRIGGER_ONESHOT is not set CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_BACKLIGHT=y CONFIG_LEDS_TRIGGER_GPIO=y @@ -1795,7 +1711,9 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y # # iptables trigger is under Netfilter config (LED target) # +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set # CONFIG_ACCESSIBILITY is not set +# CONFIG_EDAC is not set CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y CONFIG_RTC_HCTOSYS=y @@ -1879,7 +1797,7 @@ CONFIG_XILINX_DMA=y # CONFIG_AMBA_PL08X is not set # CONFIG_DW_DMAC is not set # CONFIG_TIMB_DMA is not set -# CONFIG_PL330_DMA is not set +CONFIG_PL330_DMA=y CONFIG_DMA_ENGINE=y # @@ -1890,6 +1808,8 @@ CONFIG_DMA_ENGINE=y # CONFIG_DMATEST is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set +CONFIG_VIRTIO=m +CONFIG_VIRTIO_RING=m # # Virtio drivers @@ -1908,22 +1828,45 @@ CONFIG_COMMON_CLK=y # # Common Clock Framework # -# CONFIG_COMMON_CLK_DISABLE_UNUSED is not set # CONFIG_COMMON_CLK_DEBUG is not set # # Hardware Spinlock drivers # # CONFIG_IOMMU_SUPPORT is not set + +# +# Remoteproc drivers (EXPERIMENTAL) +# +CONFIG_REMOTEPROC=m +CONFIG_ZYNQ_REMOTEPROC=m +CONFIG_MB_REMOTEPROC=m + +# +# Rpmsg drivers (EXPERIMENTAL) +# +CONFIG_RPMSG=m +# CONFIG_RPMSG_SERVER_SAMPLE is not set +# CONFIG_RPMSG_OMX is not set +# CONFIG_RPMSG_FREERTOS_STAT is not set # CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +# CONFIG_IIO is not set +# CONFIG_PWM is not set CONFIG_PMODS=y # CONFIG_PMODS_DEBUG is not set CONFIG_PMODOLED=y +# CONFIG_PMODCLS is not set +# CONFIG_PMODCLP is not set +# CONFIG_PMODDA1 is not set +# CONFIG_PMODAD1 is not set # # File systems # +CONFIG_DCACHE_WORD_ACCESS=y # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set CONFIG_EXT4_FS=y @@ -2002,6 +1945,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_PSTORE is not set # CONFIG_SYSV_FS is not set @@ -2046,6 +1990,17 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_ISO8859_15 is not set # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set # CONFIG_NLS_UTF8 is not set # @@ -2058,6 +2013,7 @@ CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 CONFIG_FRAME_WARN=1024 # CONFIG_MAGIC_SYSRQ is not set # CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set @@ -2066,6 +2022,8 @@ CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set # CONFIG_LOCKUP_DETECTOR is not set # CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 # CONFIG_DETECT_HUNG_TASK is not set # CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set @@ -2101,13 +2059,15 @@ CONFIG_DEBUG_KERNEL=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_RCU_CPU_STALL_VERBOSE is not set +# CONFIG_RCU_CPU_STALL_INFO is not set +# CONFIG_RCU_TRACE is not set # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set # CONFIG_DEBUG_PER_CPU_MAPS is not set # CONFIG_LKDTM is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set -# CONFIG_SYSCTL_SYSCALL_CHECK is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y @@ -2126,11 +2086,9 @@ CONFIG_HAVE_ARCH_KGDB=y # CONFIG_STRICT_DEVMEM is not set CONFIG_ARM_UNWIND=y # CONFIG_DEBUG_USER is not set -CONFIG_DEBUG_LL=y -CONFIG_DEBUG_LL_UART_NONE=y -# CONFIG_DEBUG_ICEDCC is not set -CONFIG_EARLY_PRINTK=y +# CONFIG_DEBUG_LL is not set # CONFIG_OC_ETM is not set +# CONFIG_PID_IN_CONTEXTIDR is not set # # Security options @@ -2147,8 +2105,10 @@ CONFIG_CRYPTO=y # Crypto core or helper # # CONFIG_CRYPTO_FIPS is not set -CONFIG_CRYPTO_ALGAPI=m -CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y CONFIG_CRYPTO_RNG=m CONFIG_CRYPTO_RNG2=m # CONFIG_CRYPTO_MANAGER is not set @@ -2189,7 +2149,7 @@ CONFIG_CRYPTO_RNG2=m # # Digest # -# CONFIG_CRYPTO_CRC32C is not set +CONFIG_CRYPTO_CRC32C=y # CONFIG_CRYPTO_GHASH is not set # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set @@ -2243,12 +2203,20 @@ CONFIG_CRYPTO_HW=y # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y # CONFIG_CRC_CCITT is not set CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set # CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set # CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set # CONFIG_CRC8 is not set @@ -2264,5 +2232,7 @@ CONFIG_HAS_DMA=y CONFIG_CPU_RMAP=y CONFIG_DQL=y CONFIG_NLATTR=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y # CONFIG_AVERAGE is not set # CONFIG_CORDIC is not set +# CONFIG_DDR is not set From 0c6d9450d7bb87c749a62593f92f485e39829af9 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Mon, 31 Dec 2012 15:12:42 -0800 Subject: [PATCH 255/261] DTS: Update Default DTS file for ZedBoard: digilent_zed.dts Remove other ZedBoard related device tree source file to avoid confusion. --- arch/arm/boot/dts/digilent-zed.dts | 603 ++++++++++++++----- arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts | 282 --------- arch/arm/boot/dts/zynq-zed-adv7511.dts | 188 ------ arch/arm/boot/dts/zynq-zed.dts | 311 ---------- 4 files changed, 445 insertions(+), 939 deletions(-) delete mode 100644 arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts delete mode 100644 arch/arm/boot/dts/zynq-zed-adv7511.dts delete mode 100644 arch/arm/boot/dts/zynq-zed.dts diff --git a/arch/arm/boot/dts/digilent-zed.dts b/arch/arm/boot/dts/digilent-zed.dts index 5e1755e6e988c..48fa1f08ef722 100644 --- a/arch/arm/boot/dts/digilent-zed.dts +++ b/arch/arm/boot/dts/digilent-zed.dts @@ -1,22 +1,56 @@ -/dts-v1/; +/* + * digilent-zed.dts - Default Device Tree for ZedBoard + * + * (C) Copyright 2012 Digilent, Inc. + * + * Code based on Device Tree Generator version: 1.1 + * + * (C) Copyright 2007-2012 Xilinx, Inc. + * (C) Copyright 2007-2012 Michal Simek + * (C) Copyright 2007-2012 PetaLogix Qld Pty Ltd + * + * Michal SIMEK + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * CAUTION: This file is automatically generated by libgen. + * Version: Xilinx EDK 14.4 EDK_P.49d + * Today is: Wednesday, the 26 of December, 2012; 15:18:18 + * + * XPS project directory: device-tree_bsp_0 + */ +/dts-v1/; / { - model = "Xilinx Zynq ZED"; + #address-cells = <1>; + #size-cells = <1>; compatible = "xlnx,zynq-zed"; - #address-cells = <0x1>; - #size-cells = <0x1>; - interrupt-parent = <&gic>; + model = "Xilinx Zynq ZED"; - ps7_ddr_0: memory@0 { - device_type = "memory"; - reg = <0x0 0x20000000>; + aliases { + ethernet0 = &ps7_ethernet_0; + serial0 = &ps7_uart_1; }; chosen { bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0"; - linux,stdout-path = "/axi@0/uart@E0001000"; + /* bootargs = "console=ttyPS0,115200 root=/dev/ram rw initrd=0x800000,8M init=/init earlyprintk rootwait devtmpfs.mount=0"; */ + linux,stdout-path = "/axi@0/serial@e0001000"; }; - + cpus { #address-cells = <1>; #cpus = <0x2>; @@ -34,7 +68,7 @@ timebase-frequency = <333333343>; xlnx,cpu-1x-clk-freq-hz = <0x69f6bcb>; xlnx,cpu-clk-freq-hz = <0x27bc86bf>; - } ; + }; ps7_cortexa9_1: cpu@1 { clock-frequency = <666666687>; compatible = "xlnx,ps7-cortexa9-1.00.a"; @@ -48,196 +82,449 @@ timebase-frequency = <333333343>; xlnx,cpu-1x-clk-freq-hz = <0x69f6bcb>; xlnx,cpu-clk-freq-hz = <0x27bc86bf>; - } ; - } ; + }; + }; + + ps7_ddr_0: memory@0 { + device_type = "memory"; + reg = < 0x0 0x20000000 >; + }; ps7_axi_interconnect_0: axi@0 { #address-cells = <1>; #size-cells = <1>; compatible = "xlnx,ps7-axi-interconnect-1.00.a", "simple-bus"; - ranges ; + ranges; - gic: intc@f8f01000 { - interrupt-controller; - compatible = "arm,cortex-a9-gic"; - #interrupt-cells = <0x3>; - reg = < 0xf8f01000 0x1000 >, - < 0xf8f00100 0x0100 >; + /* ADAU 1761 IP Part */ + /* Support for ADAU1761 is broken, will be fixed soon */ +/* axi_dma_i2s: axi-dma@40420000 { + axistream-connected = <&axi_i2s_adi_0>; + compatible = "xlnx,axi-dma-6.03.a", "xlnx,axi-dma-1.00.a"; + interrupt-parent = <&ps7_scugic_0>; + reg = < 0x40420000 0x10000 >; + xlnx,dlytmr-resolution = <0x7d>; + xlnx,enable-multi-channel = <0x0>; + xlnx,family = "zynq"; + xlnx,generic = <0x0>; + xlnx,include-mm2s = <0x1>; + xlnx,include-mm2s-dre = <0x0>; + xlnx,include-mm2s-sf = <0x1>; + xlnx,include-s2mm = <0x1>; + xlnx,include-s2mm-dre = <0x0>; + xlnx,include-s2mm-sf = <0x1>; + xlnx,include-sg = <0x1>; + xlnx,instance = "axi_dma_i2s"; + xlnx,mm2s-burst-size = <0x10>; + xlnx,num-mm2s-channels = <0x1>; + xlnx,num-s2mm-channels = <0x1>; + xlnx,prmry-is-aclk-async = <0x0>; + xlnx,s2mm-burst-size = <0x10>; + xlnx,sg-include-desc-queue = <0x0>; + xlnx,sg-include-stscntrl-strm = <0x0>; + xlnx,sg-length-width = <0x14>; + xlnx,sg-use-stsapp-length = <0x1>; + + dma-channel@40420000 { + compatible = "xlnx,axi-dma-mm2s-channel"; + xlnx,datawidth = <0x20>; + interrupts = < 0 54 4 >; + xlnx,include-dre = <0x0>; + }; + dma-channel@40420030 { + compatible = "xlnx,axi-dma-s2mm-channel"; + xlnx,datawidth = <0x20>; + interrupts = < 0 55 4 >; + xlnx,include-dre = <0x0>; + }; }; - pl310@f8f02000 { - compatible = "arm,pl310-cache"; - cache-unified; - cache-level = <2>; - reg = <0xf8f02000 0x1000>; - arm,data-latency = <3 2 2>; - arm,tag-latency = <2 2 2>; - interrupts = <0 34 4>; - }; - - uart@e0001000 { - compatible = "xlnx,ps7-uart-1.00.a"; - reg = <0xe0001000 0x1000>; - interrupts = <0x0 0x32 0x0>; - interrupt-parent = <&gic>; - clock = <50000000>; + axi_gpio_i2s: gpio@41200000 { + #gpio-cells = <2>; + compatible = "xlnx,axi-gpio-1.01.b", "xlnx,xps-gpio-1.00.a"; + gpio-controller; + reg = < 0x41200000 0x10000 >; + xlnx,all-inputs = <0x0>; + xlnx,all-inputs-2 = <0x0>; + xlnx,dout-default = <0x0>; + xlnx,dout-default-2 = <0x0>; + xlnx,family = "zynq"; + xlnx,gpio-width = <0x2>; + xlnx,gpio2-width = <0x20>; + xlnx,instance = "axi_gpio_i2s"; + xlnx,interrupt-present = <0x0>; + xlnx,is-dual = <0x0>; + xlnx,tri-default = <0xffffffff>; + xlnx,tri-default-2 = <0xffffffff>; }; - timer@0xf8001000 { - compatible = "xlnx,ps7-ttc-1.00.a"; - reg = <0xf8001000 0x1000>; - interrupts = <0 10 0>,<0 11 0>,<0 12 0>; - interrupt-parent = <&gic>; - clock-frequency-timer0 = <0x7ed6b40>; - clock-frequency-timer1 = <0x7ed6b40>; - clock-frequency-timer2 = <0x7ed6b40>; + axi_i2s_adi_0: axi-i2s-adi@77600000 { + compatible = "adi,axi-i2s-1.00.a"; + reg = < 0x77600000 0x10000 >; + clock-frequency = <12288000>; }; - swdt@f8005000 { - device_type = "watchdog"; - compatible = "xlnx,ps7-wdt-1.00.a"; - reg = <0xf8005000 0x100>; - clock-frequency = <111111111>; + axi_iic_i2s: i2c@41640000 { + compatible = "xlnx,axi-iic-1.02.a", "xlnx,xps-iic-2.00.a"; + interrupt-parent = <&ps7_scugic_0>; + interrupts = < 0 53 4 >; + reg = < 0x41640000 0x10000 >; + xlnx,family = "zynq"; + xlnx,gpo-width = <0x1>; + xlnx,iic-freq = <0x186a0>; + xlnx,instance = "axi_iic_i2s"; + xlnx,scl-inertial-delay = <0x0>; + xlnx,sda-inertial-delay = <0x0>; + xlnx,sda-level = <0x1>; + xlnx,ten-bit-adr = <0x0>; + + #size-cells = <0>; + #address-cells = <1>; + + adau1761: adau1761@3b { + compatible = "adi,adau1761"; + reg = <0x3b>; + }; + }; + + xilinx_pcm_audio_i2s: xilinx_pcm_audio_i2s { + compatible = "xilinx-pcm-audio"; + #size-cells = <0>; + #address-cells = <1>; + + stream@0{ + reg = <0>; + dma-request = <&axi_dma_i2s 0>; + }; + stream@1{ + reg = <1>; + dma-request = <&axi_dma_i2s 1>; + }; + }; + + zed_adau1761_snd: zed_adau1761_snd { + compatible = "zed-adau1761-snd"; + audio-codec = <&adau1761>; + cpu-dai = <&axi_i2s_adi_0>; + pcm = <&xilinx_pcm_audio_i2s>; + }; +*/ + /* ADV7511 Part (HDMI SPDIF Sound Supported) */ + axi_vdma_0: axivdma@43000000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + compatible = "xlnx,axi-vdma"; + ranges = < 0x43000000 0x43000000 0x10000 >; + reg = < 0x43000000 0x10000 >; + xlnx,flush-fsync = <0x1>; + xlnx,include-sg = <0x0>; + xlnx,num-fstores = <0x3>; + dma-channel@43000000 { + compatible = "xlnx,axi-vdma-mm2s-channel"; + interrupt-parent = <&ps7_scugic_0>; + interrupts = < 0 59 4 >; + xlnx,datawidth = <0x40>; + xlnx,device-id = <0x0>; + xlnx,genlock-mode = <0x0>; + xlnx,include-dre = <0x0>; + }; + }; + + axi_iic_hdmi: i2c@41600000 { + compatible = "xlnx,axi-iic-1.02.a", "xlnx,xps-iic-2.00.a"; + interrupt-parent = <&ps7_scugic_0>; + interrupts = < 0 56 4 >; + reg = < 0x41600000 0x10000 >; + xlnx,family = "zynq"; + xlnx,gpo-width = <0x1>; + xlnx,iic-freq = <0x186a0>; + xlnx,instance = "axi_iic_hdmi"; + xlnx,scl-inertial-delay = <0x0>; + xlnx,sda-inertial-delay = <0x0>; + xlnx,sda-level = <0x1>; + xlnx,ten-bit-adr = <0x0>; + }; + + axi_hdmi_tx_16b_0: axi-hdmi-tx-16b@70e00000 { + compatible = "adi,cf-adv7x11-core-1.00.a"; + reg = < 0x70e00000 0x10000 0x79000000 0x10000 >; + slave_adapter = <&axi_iic_hdmi>; + dma-request = <&axi_vdma_0 0x0>; + }; + + axi_dma_spdif: axi-dma@40400000 { + #address-cells = <1>; + #size-cells = <1>; + #dma-cells = <1>; + axistream-connected = <&axi_spdif_tx_0>; + compatible = "xlnx,axi-dma-6.03.a", "xlnx,axi-dma-1.00.a", "xlnx,axi-dma"; + interrupt-parent = <&ps7_scugic_0>; + reg = < 0x40400000 0x10000 >; + xlnx,sg-include-stscntrl-strm = <0x0>; + xlnx,dlytmr-resolution = <0x7d>; + xlnx,enable-multi-channel = <0x0>; + xlnx,family = "zynq"; + xlnx,generic = <0x0>; + xlnx,include-mm2s = <0x1>; + xlnx,include-mm2s-dre = <0x0>; + xlnx,include-mm2s-sf = <0x1>; + xlnx,include-s2mm = <0x0>; + xlnx,include-s2mm-dre = <0x0>; + xlnx,include-s2mm-sf = <0x1>; + xlnx,include-sg = <0x1>; + xlnx,instance = "axi_dma_spdif"; + xlnx,mm2s-burst-size = <0x10>; + xlnx,num-mm2s-channels = <0x1>; + xlnx,num-s2mm-channels = <0x1>; + xlnx,prmry-is-aclk-async = <0x0>; + xlnx,s2mm-burst-size = <0x10>; + xlnx,sg-include-desc-queue = <0x0>; + xlnx,sg-length-width = <0x14>; + xlnx,sg-use-stsapp-length = <0x1>; + + dma-channel@40400000 { + compatible = "xlnx,axi-dma-mm2s-channel"; + interrupts = < 0 58 4 >; + xlnx,datawidth = <0x20>; + xlnx,include-dre = <0x0>; + }; + }; + + axi_spdif_tx_0: axi-spdif-tx@75c00000 { + compatible = "adi,axi-spdif-tx-1.00.a"; + reg = < 0x75c00000 0x10000 >; + clock-frequency = <12288000>; + }; + + xlnx_pcm_spdif: xilinx_pcm_spdif_audio { + compatible = "xilinx-pcm-audio"; + dma-request = <&axi_dma_spdif 0x0>; + }; + + adv7511_hdmi_snd { + compatible = "adv7511-hdmi-snd"; + audio-codec-adapter = <&axi_iic_hdmi>; + cpu-dai = <&axi_spdif_tx_0>; + pcm = <&xlnx_pcm_spdif>; + }; + + /* PS system internal devices */ + ps7_afi_0: ps7-afi@f8008000 { + compatible = "xlnx,ps7-afi-1.00.a"; + reg = < 0xf8008000 0x1000 >; + }; + ps7_afi_1: ps7-afi@f8009000 { + compatible = "xlnx,ps7-afi-1.00.a"; + reg = < 0xf8009000 0x1000 >; + }; + ps7_afi_2: ps7-afi@f800a000 { + compatible = "xlnx,ps7-afi-1.00.a"; + reg = < 0xf800a000 0x1000 >; + }; + ps7_afi_3: ps7-afi@f800b000 { + compatible = "xlnx,ps7-afi-1.00.a"; + reg = < 0xf800b000 0x1000 >; + }; + + ps7_ddrc_0: ps7-ddrc@f8006000 { + compatible = "xlnx,ps7-ddrc-1.00.a"; + reg = < 0xf8006000 0x1000 >; + xlnx,has-ecc = <0x0>; + }; + + ps7_dev_cfg_0: ps7-dev-cfg@f8007000 { + compatible = "xlnx,ps7-dev-cfg-1.00.a"; + interrupt-parent = <&ps7_scugic_0>; + interrupts = < 0 8 4 >; + reg = < 0xf8007000 0x1000 >; + }; + + ps7_dma_ns: ps7-dma@f8004000 { + compatible = "xlnx,ps7-dma-1.00.a", "arm,pl330"; + interrupt-parent = <&ps7_scugic_0>; + interrupts = < 0 13 4 0 14 4 0 15 4 0 16 4 0 17 4 0 40 4 0 41 4 0 42 4 0 43 4 >; + reg = < 0xf8004000 0x1000 >; + }; + + ps7_dma_s: ps7-dma@f8003000 { + compatible = "xlnx,ps7-dma-1.00.a", "arm,pl330"; + interrupt-parent = <&ps7_scugic_0>; + interrupts = < 0 13 4 0 14 4 0 15 4 0 16 4 0 17 4 0 40 4 0 41 4 0 42 4 0 43 4 >; + reg = < 0xf8003000 0x1000 >; }; - ps7_ethernet_0: eth@e000b000 { + ps7_ethernet_0: ps7-ethernet@e000b000 { + #address-cells = <1>; + #size-cells = <0>; compatible = "xlnx,ps7-ethernet-1.00.a"; - reg = <0xe000b000 0x1000>; - interrupts = <0x0 0x16 0x0>; - interrupt-parent = <&gic>; + interrupt-parent = <&ps7_scugic_0>; + interrupts = < 0 22 4 >; + local-mac-address = [ 00 0a 35 00 00 00 ]; phy-handle = <&phy0>; - #address-cells = <0x1>; - #size-cells = <0x0>; - xlnx,ptp-enet-clock = <111111111>; - xlnx,slcr-div0-1000Mbps = <8>; - xlnx,slcr-div0-100Mbps = <8>; - xlnx,slcr-div0-10Mbps = <8>; - xlnx,slcr-div1-1000Mbps = <1>; - xlnx,slcr-div1-100Mbps = <5>; - xlnx,slcr-div1-10Mbps = <50>; + reg = < 0xe000b000 0x1000 >; + xlnx,enet-clk-freq-hz = <0x7735940>; + xlnx,enet-reset = <0xffffffff>; + xlnx,enet-slcr-1000mbps-div0 = <0x8>; + xlnx,enet-slcr-1000mbps-div1 = <0x1>; + xlnx,enet-slcr-100mbps-div0 = <0x8>; + xlnx,enet-slcr-100mbps-div1 = <0x5>; + xlnx,enet-slcr-10mbps-div0 = <0x8>; + xlnx,enet-slcr-10mbps-div1 = <0x32>; + xlnx,eth-mode = <0x1>; + xlnx,has-mdio = <0x1>; + xlnx,ptp-enet-clock = <111111115>; + mdio { #address-cells = <1>; #size-cells = <0>; - phy0: phy@0 { compatible = "marvell,88e1510"; device_type = "ethernet-phy"; - reg = <0x0>; + reg = <0>; marvell,reg-init = <0x3 0x10 0xff00 0x1e 0x3 0x11 0xfff0 0xa>; }; }; }; - ps7_i2c: i2c@41600000 { - compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; - interrupt-parent = <&gic>; - interrupts = <0x0 0x38 0x4>; - reg = <0x41600000 0x10000>; - #size-cells = <0x0>; - #address-cells = <0x1>; + ps7_gpio_0: ps7-gpio@e000a000 { + #gpio-cells = <2>; + compatible = "xlnx,ps7-gpio-1.00.a"; + emio-gpio-width = <60>; + gpio-controller; + gpio-mask-high = <0xc0000>; + gpio-mask-low = <0xfe81>; + interrupt-parent = <&ps7_scugic_0>; + interrupts = < 0 20 4 >; + reg = < 0xe000a000 0x1000 >; }; - sdhci@e0100000 { - compatible = "xlnx,ps7-sdhci-1.00.a"; - reg = <0xe0100000 0x1000>; - interrupts = <0x0 0x18 0x0>; - interrupt-parent = <&gic>; - /*xlnx,has-cd = <0x1>;*/ - clock-frequency = <0x1fc9f08>; + ps7_iop_bus_config_0: ps7-iop-bus-config@e0200000 { + compatible = "xlnx,ps7-iop-bus-config-1.00.a"; + reg = < 0xe0200000 0x1000 >; }; - usb@e0002000 { - compatible = "xlnx,ps7-usb-1.00.a"; - reg = <0xe0002000 0x1000>; - interrupts = <0x0 0x15 0x0>; - interrupt-parent = <&gic>; - dr_mode = "host"; - phy_type = "ulpi"; - }; - - gpiops: gpio@e000a000 { - compatible = "xlnx,ps7-gpio-1.00.a"; - #gpio-cells = <2>; - reg = <0xe000a000 0x1000>; - interrupts = <0x0 0x14 0x0>; - interrupt-parent = <&gic>; - gpio-controller; + ps7_pl310_0: ps7-pl310@f8f02000 { + arm,data-latency = < 3 2 2 >; + arm,tag-latency = < 2 2 2 >; + cache-level = < 2 >; + cache-unified; + compatible = "xlnx,ps7-pl310-1.00.a", "arm,pl310-cache"; + reg = < 0xf8f02000 0x1000 >; }; - qspi@e000d000 { + ps7_qspi_0: ps7-qspi@e000d000 { + bus-num = <0>; compatible = "xlnx,ps7-qspi-1.00.a"; - reg = <0xe000d000 0x1000>; - interrupts = <0x0 0x13 0x0>; - interrupt-parent = <&gic>; - speed-hz = <0xbebc200>; - bus-num = <0x1>; - num-chip-select = <0x1>; - is-dual = <0x0>; + interrupt-parent = <&ps7_scugic_0>; + interrupts = < 0 19 4 >; + is-dual = <0>; + num-chip-select = <1>; + reg = < 0xe000d000 0x1000 >; + speed-hz = <200000000>; + xlnx,fb-clk = <0x1>; + xlnx,qspi-clk-freq-hz = <0xbebc200>; + xlnx,qspi-mode = <0x0>; }; - devcfg@f8007000 { - compatible = "xlnx,ps7-dev-cfg-1.00.a"; - reg = <0xf8007000 0x1000>; - interrupts = <0x0 0x8 0x0>; - interrupt-parent = <&gic>; + ps7_qspi_linear_0: ps7-qspi-linear@fc000000 { + compatible = "xlnx,ps7-qspi-linear-1.00.a"; + reg = < 0xfc000000 0x1000000 >; + xlnx,qspi-clk-freq-hz = <0xe4e1c0>; }; - axi_dma: axidma@40400000 { - #address-cells = <0x1>; - #size-cells = <0x1>; - #dma-cells = <0x1>; - compatible = "xlnx,axi-dma"; - reg = <0x40400000 0x1000>; - xlnx,sg-include-stscntrl-strm = <0x0>; + ps7_scugic_0: ps7-scugic@f8f01000 { + #address-cells = < 2 >; + #interrupt-cells = < 3 >; + #size-cells = < 1 >; + compatible = "xlnx,ps7-scugic-1.00.a", "arm,cortex-a9-gic", "arm,gic"; + interrupt-controller; + linux,phandle = < 0x1 >; + phandle = < 0x1 >; + reg = < 0xf8f01000 0x1000 0xf8f00100 0x100 >; + }; - dma-channel@40400000 { - compatible = "xlnx,axi-dma-mm2s-channel"; - interrupts = <0x0 0x3a 0x4>; - xlnx,datawidth = <0x20>; - xlnx,include-dre = <0x0>; - }; + ps7_scutimer_0: ps7-scutimer@f8f00600 { + clock-frequency = <333333343>; + compatible = "xlnx,ps7-scutimer-1.00.a", "arm,cortex-a9-twd-timer"; + interrupt-parent = <&ps7_scugic_0>; + interrupts = < 1 13 769 >; + reg = < 0xf8f00600 0x20 >; }; - axi_spdif: axi-spdif-tx@0x75c00000 { - compatible = "adi,axi-spdif-tx-1.00.a"; - reg = <0x75c00000 0x1000>; - clock-frequency = <0xbb8000>; + ps7_scuwdt_0: ps7-scuwdt@f8f00620 { + clock-frequency = <333333343>; + /* clock-frequency = <111111111>; */ + compatible = "xlnx,ps7-scuwdt-1.00.a"; + device_type = "watchdog"; + interrupt-parent = <&ps7_scugic_0>; + interrupts = < 1 14 769 >; + reg = < 0xf8f00620 0xe0 >; }; - axi_vdma: axivdma@43000000 { - #address-cells = <0x1>; - #size-cells = <0x1>; - #dma-cells = <0x1>; - compatible = "xlnx,axi-vdma"; - reg = <0x43000000 0x1000>; - xlnx,include-sg = <0x0>; - xlnx,num-fstores = <0x3>; + ps7_sd_0: ps7-sdio@e0100000 { + clock-frequency = <50000000>; + compatible = "xlnx,ps7-sdio-1.00.a", "generic-sdhci"; + interrupt-parent = <&ps7_scugic_0>; + interrupts = < 0 24 4 >; + reg = < 0xe0100000 0x1000 >; + xlnx,has-cd = <0x1>; + xlnx,has-power = <0x0>; + xlnx,has-wp = <0x1>; + xlnx,sdio-clk-freq-hz = <0x2faf080>; + /* clock-frequency = <0x1fc9f08>; */ + }; - dma-channel@43000000 { - compatible = "xlnx,axi-vdma-mm2s-channel"; - interrupts = <0x0 0x3b 0x4>; - xlnx,datawidth = <0x40>; - xlnx,genlock-mode = <0x0>; - xlnx,include-dre = <0x0>; - }; + ps7_slcr_0: ps7-slcr@f8000000 { + compatible = "xlnx,ps7-slcr-1.00.a"; + reg = < 0xf8000000 0x1000 >; }; - cf-adv7x11-core@70e00000 { - compatible = "adi,cf-adv7x11-core-1.00.a"; - reg = <0x70e00000 0x10000 0x79000000 0x10000>; - slave_adapter = <&ps7_i2c>; - dma-request = <&axi_vdma 0x0>; + ps7_ttc_0: ps7-ttc@f8001000 { + clock-frequency = <111111115>; + clock-frequency-timer0 = <111111115>; + clock-frequency-timer1 = <111111115>; + clock-frequency-timer2 = <111111115>; + compatible = "xlnx,ps7-ttc-1.00.a"; + interrupt-parent = <&ps7_scugic_0>; + interrupts = < 0 10 4 0 11 4 0 12 4 >; + reg = < 0xf8001000 0x1000 >; + xlnx,ttc-clk0-clksrc = <0x0>; + xlnx,ttc-clk0-freq-hz = <0x69f6bcb>; + xlnx,ttc-clk1-clksrc = <0x0>; + xlnx,ttc-clk1-freq-hz = <0x69f6bcb>; + xlnx,ttc-clk2-clksrc = <0x0>; + xlnx,ttc-clk2-freq-hz = <0x69f6bcb>; }; - xlnx_pcm: xilinx_pcm_audio { - compatible = "xilinx-pcm-audio"; - dma-request = <&axi_dma 0x0>; + ps7_uart_1: serial@e0001000 { + clock = <50000000>; + clock-frequency = <50000000>; + compatible = "xlnx,ps7-uart-1.00.a", "xlnx,xuartps"; + current-speed = <115200>; + device_type = "serial"; + interrupt-parent = <&ps7_scugic_0>; + interrupts = < 0 50 4 >; + port-number = <0>; + reg = < 0xe0001000 0x1000 >; + xlnx,has-modem = <0x0>; + xlnx,uart-clk-freq-hz = <0x2faf080>; }; - adv7511_hdmi_snd { - compatible = "adv7511-hdmi-snd"; - cpu-dai = <&axi_spdif>; - pcm = <&xlnx_pcm>; + ps7_usb_0: ps7-usb@e0002000 { + compatible = "xlnx,ps7-usb-1.00.a"; + dr_mode = "host"; + interrupt-parent = <&ps7_scugic_0>; + interrupts = < 0 21 4 >; + phy_type = "ulpi"; + reg = < 0xe0002000 0x1000 >; + xlnx,usb-reset = <0xffffffff>; + }; + + ps7_xadc: ps7_xadc@f8007100 { + compatible = "xlnx,ps7-xadc-1.00.a"; + interrupts = < 0 7 4 >; + reg = < 0xf8007100 0x20 >; }; leds { @@ -245,7 +532,7 @@ mmc_led { label = "mmc_led"; - gpios = <&gpiops 7 0>; + gpios = <&ps7_gpio_0 7 0>; linux,default-trigger = "mmc0"; }; }; @@ -253,15 +540,15 @@ zed_oled { compatible = "dglnt,pmodoled-gpio"; /* GPIO Pins */ - vbat-gpio = <&gpiops 55 0>; - vdd-gpio = <&gpiops 56 0>; - res-gpio = <&gpiops 57 0>; - dc-gpio = <&gpiops 58 0>; + vbat-gpio = <&ps7_gpio_0 55 0>; + vdd-gpio = <&ps7_gpio_0 56 0>; + res-gpio = <&ps7_gpio_0 57 0>; + dc-gpio = <&ps7_gpio_0 58 0>; /* SPI-GPIOs */ spi-bus-num = <2>; spi-speed-hz = <4000000>; - spi-sclk-gpio = <&gpiops 59 0>; - spi-sdin-gpio = <&gpiops 60 0>; + spi-sclk-gpio = <&ps7_gpio_0 59 0>; + spi-sdin-gpio = <&ps7_gpio_0 60 0>; }; }; }; diff --git a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts b/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts deleted file mode 100644 index 988d90db9154b..0000000000000 --- a/arch/arm/boot/dts/zynq-zed-adv7511-xcomm.dts +++ /dev/null @@ -1,282 +0,0 @@ -/dts-v1/; - -/ { - model = "Xilinx Zynq ZC702"; - compatible = "xlnx,zynq-zc702"; - #address-cells = <0x1>; - #size-cells = <0x1>; - interrupt-parent = <0x1>; - - memory { - device_type = "memory"; - reg = <0x000000000 0x20000000>; - }; - chosen { -// bootargs = "console=ttyPS0,115200 root=/dev/ram rw initrd=0x1100000,33M ip=:::::eth0:dhcp earlyprintk"; - bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0"; - linux,stdout-path = "/amba@0/uart@E0001000"; - }; - - amba@0 { - compatible = "simple-bus"; - #address-cells = <0x1>; - #size-cells = <0x1>; - ranges; - - gic: intc@f8f01000 { - interrupt-controller; - compatible = "arm,cortex-a9-gic"; - #interrupt-cells = <3>; - reg = < 0xf8f01000 0x1000 >, - < 0xf8f00100 0x0100 >; - }; - - uart@e0001000 { - compatible = "xlnx,ps7-uart-1.00.a"; - reg = <0xe0001000 0x1000>; - interrupts = < 0 50 0 >; - interrupt-parent = <&gic>; - clock = <50000000>; - }; - - timer@0xf8001000 { - compatible = "xlnx,ps7-ttc-1.00.a"; - reg = <0xf8001000 0x1000>; - interrupts = <0 10 0>,<0 11 0>,<0 12 0>; - interrupt-parent = <&gic>; -/* clock-frequency = <111111111>;*/ - clock-frequency-timer0 = <111111111>; - clock-frequency-timer1 = <111111111>; - clock-frequency-timer2 = <111111111>; - }; - - swdt@f8005000 { - device_type = "watchdog"; - compatible = "xlnx,ps7-wdt-1.00.a"; - reg = <0xf8005000 0x100>; - }; - - eth@e000b000 { - compatible = "xlnx,ps7-ethernet-1.00.a"; - reg = <0xe000b000 0x1000>; - interrupts = <0 22 0>; - interrupt-parent = <&gic>; - phy-handle = <&phy0>; - #address-cells = <0x1>; - #size-cells = <0x0>; - - phy0: phy@0 { - compatible = "marvell,88e1510"; - device_type = "ethernet-phy"; - reg = <0x0>; - marvell,reg-init=<3 16 0xff00 0x1e 3 17 0xfff0 0x0a>; - }; - }; - - gpio: gpio@e000a000 { - compatible = "xlnx,ps7-gpio-1.00.a"; - reg = <0xe000a000 0x1000>; - interrupts = <0 20 0>; - interrupt-parent = <&gic>; - gpio-controller; - #gpio-cells = <2>; - }; - - - i2c_adv7511: i2c@41620000 { - compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; - interrupt-parent = <&gic>; - interrupts = < 0 54 0x4 >; - reg = < 0x41620000 0x10000 >; - - #size-cells = <0>; - #address-cells = <1>; - }; - - axi_iic_1: i2c@41600000 { - compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; - interrupt-parent = <&gic>; - interrupts = < 0 53 0x4 >; - reg = < 0x41600000 0x10000 >; - - #size-cells = <0>; - #address-cells = <1>; - - spi_xcomm0: spi_xcomm0@58 { - #size-cells = <0>; - #address-cells = <1>; - compatible = "spi-xcomm"; - reg = <0x58>; - dac0_ad9122: ad9122@0 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "ad9122"; - reg = <0>; - spi-max-frequency = <10000000>; - }; - adc0_ad9467: ad9467@1 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "ad9643"; - reg = <1>; - spi-3wire; - spi-max-frequency = <10000000>; - }; - - }; - - eeprom@50 { - compatible = "at24,24c02"; - reg = <0x50>; - }; - eeprom@54 { - compatible = "at24,24c02"; - reg = <0x54>; - }; - }; - - sdhci@e0100000 { - compatible = "xlnx,ps7-sdhci-1.00.a"; - reg = <0xe0100000 0x1000>; - interrupts = <0 24 0>; - interrupt-parent = <&gic>; - clock-frequency = <50000000>; - }; - - usb@e0002000 { - compatible = "xlnx,ps7-usb-1.00.a"; - reg = <0xe0002000 0x1000>; - interrupts = <0 21 0>; - interrupt-parent = <&gic>; - dr_mode = "host"; - phy_type = "ulpi"; - }; - - devcfg@f8007000 { - compatible = "xlnx,ps7-dev-cfg-1.00.a"; - reg = <0xf8007000 0x1000>; - interrupts = <0 8 0>; - interrupt-parent = <&gic>; - }; - - axi_dma_0: axidma@40440000 { - #address-cells = <1>; - #size-cells = <1>; - #dma-cells = <1>; - compatible = "xlnx,axi-dma"; - reg = < 0x40440000 0x1000 >; - xlnx,sg-include-stscntrl-strm = <0x0>; - dma-channel@40440000 { - compatible = "xlnx,axi-dma-mm2s-channel"; - interrupts = < 0 56 0x4 >; - xlnx,datawidth = <0x20>; - xlnx,include-dre = <0x0>; - }; - }; - - axi_spdif_tx_0: axi-spdif-tx@0x75c00000 { - compatible = "adi,axi-spdif-tx-1.00.a"; - reg = < 0x75c00000 0x1000 >; - clock-frequency = <12288000>; - }; - - axi_vdma_0: axivdma@43020000 { - #address-cells = <1>; - #size-cells = <1>; - #dma-cells = <1>; - compatible = "xlnx,axi-vdma"; - reg = <0x43020000 0x1000>; - xlnx,include-sg = <0x0>; - xlnx,num-fstores = <0x3>; - dma-channel@43020000 { - compatible = "xlnx,axi-vdma-mm2s-channel"; - interrupts = <0 57 0x4>; - xlnx,datawidth = <0x40>; - xlnx,genlock-mode = <0x0>; - xlnx,include-dre = <0x0>; - }; - }; - - axi_vdma_1: axivdma@43000000 { - #address-cells = <1>; - #size-cells = <1>; - #dma-cells = <1>; - compatible = "xlnx,axi-vdma"; - reg = <0x43000000 0x1000>; - xlnx,include-sg = <0x0>; - xlnx,num-fstores = <0x3>; - dma-channel@43000000 { - compatible = "xlnx,axi-vdma-mm2s-channel"; - interrupts = <0 59 0x4>; - xlnx,datawidth = <0x40>; - xlnx,genlock-mode = <0x0>; - xlnx,include-dre = <0x0>; - }; - }; - - cf_adv7x11_core_0: cf-adv7x11-core@6c000000 { - compatible = "adi,cf-adv7x11-core-1.00.a"; - reg = <0x70e00000 0x10000 - 0x79000000 0x10000>; - slave_adapter = <&i2c_adv7511>; - dma-request = <&axi_vdma_0 0>; - }; - - xilinx_pcm_audio: xilinx_pcm_audio { - compatible = "xilinx-pcm-audio"; - dma-request = <&axi_dma_0 0>; - }; - - adv7511_hdmi_snd: adv7511_hdmi_snd { - compatible = "adv7511-hdmi-snd"; - audio-codec-adapter = <&i2c_adv7511>; - cpu-dai = <&axi_spdif_tx_0>; - pcm = <&xilinx_pcm_audio>; - }; - - axi_dma_1: axidma@40420000 { - #address-cells = <1>; - #size-cells = <1>; - #dma-cells = <1>; - compatible = "xlnx,axi-dma"; - reg = < 0x40420000 0x10000 >; -// xlnx,sg-include-stscntrl-strm = <0x0>; - dma-channel@40420000 { - compatible = "xlnx,axi-dma-s2mm-channel"; - interrupts = < 0 58 0x4 >; - xlnx,datawidth = <0x40>; - xlnx,include-dre = <0x0>; - } ; - } ; - - cf_ad9643_core_0: cf-ad9643-core-lpc@79020000 { - compatible = "xlnx,axi-adc-2c-1.00.a"; - reg = < 0x79020000 0x10000 >; - dma-request = <&axi_dma_1 0>; - spibus-connected = <&adc0_ad9467>; - xlnx,dphase-timeout = <0x8>; - xlnx,num-mem = <0x1>; - xlnx,num-reg = <0x1>; - xlnx,s-axi-min-size = <0x1ff>; - xlnx,slv-awidth = <0x20>; - xlnx,slv-dwidth = <0x20>; - xlnx,use-wstrb = <0x0>; - } ; - - cf_ad9122_core_0: cf-ad9122-core-lpc@74200000 { - compatible = "xlnx,axi-dac-4d-2c-1.00.a"; - reg = < 0x74200000 0x10000 >; - spibus-connected = <&dac0_ad9122>; - dma-request = <&axi_vdma_1 0>; - dac-sample-frequency = <491520000>; - xlnx,dphase-timeout = <0x8>; - xlnx,num-mem = <0x1>; - xlnx,num-reg = <0x1>; - xlnx,s-axi-min-size = <0x1ff>; - xlnx,slv-awidth = <0x20>; - xlnx,slv-dwidth = <0x20>; - xlnx,use-wstrb = <0x0>; - } ; - - }; -}; diff --git a/arch/arm/boot/dts/zynq-zed-adv7511.dts b/arch/arm/boot/dts/zynq-zed-adv7511.dts deleted file mode 100644 index 10ee4be89e4b2..0000000000000 --- a/arch/arm/boot/dts/zynq-zed-adv7511.dts +++ /dev/null @@ -1,188 +0,0 @@ -/dts-v1/; - -/ { - model = "Xilinx Zynq ZED"; - compatible = "xlnx,zynq-zc702"; - #address-cells = <0x1>; - #size-cells = <0x1>; - interrupt-parent = <0x1>; - - memory { - device_type = "memory"; - reg = <0x000000000 0x20000000>; - }; - chosen { -// bootargs = "console=ttyPS0,115200 root=/dev/ram rw initrd=0x1100000,33M ip=:::::eth0:dhcp earlyprintk"; - bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0"; - linux,stdout-path = "/amba@0/uart@E0001000"; - }; - - amba@0 { - compatible = "simple-bus"; - #address-cells = <0x1>; - #size-cells = <0x1>; - ranges; - - gic: intc@f8f01000 { - interrupt-controller; - compatible = "arm,cortex-a9-gic"; - #interrupt-cells = <3>; - reg = < 0xf8f01000 0x1000 >, - < 0xf8f00100 0x0100 >; - }; - - uart@e0001000 { - compatible = "xlnx,ps7-uart-1.00.a"; - reg = <0xe0001000 0x1000>; - interrupts = < 0 50 0 >; - interrupt-parent = <&gic>; - clock = <50000000>; - }; - - timer@0xf8001000 { - compatible = "xlnx,ps7-ttc-1.00.a"; - reg = <0xf8001000 0x1000>; - interrupts = <0 10 0>,<0 11 0>,<0 12 0>; - interrupt-parent = <&gic>; -/* clock-frequency = <111111111>;*/ - clock-frequency-timer0 = <111111111>; - clock-frequency-timer1 = <111111111>; - clock-frequency-timer2 = <111111111>; - }; - - swdt@f8005000 { - device_type = "watchdog"; - compatible = "xlnx,ps7-wdt-1.00.a"; - reg = <0xf8005000 0x100>; - }; - - eth@e000b000 { - compatible = "xlnx,ps7-ethernet-1.00.a"; - reg = <0xe000b000 0x1000>; - interrupts = <0 22 0>; - interrupt-parent = <&gic>; - phy-handle = <&phy0>; - #address-cells = <0x1>; - #size-cells = <0x0>; - - phy0: phy@0 { - compatible = "marvell,88e1510"; - device_type = "ethernet-phy"; - reg = <0x0>; - marvell,reg-init=<3 16 0xff00 0x1e 3 17 0xfff0 0x0a>; - }; - }; - - gpio: gpio@e000a000 { - compatible = "xlnx,ps7-gpio-1.00.a"; - reg = <0xe000a000 0x1000>; - interrupts = <0 20 0>; - interrupt-parent = <&gic>; - gpio-controller; - #gpio-cells = <2>; - }; - - axi_iic_0: i2c@41600000 { - compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a"; - interrupt-parent = <&gic>; - interrupts = < 0 56 0x4 >; - reg = < 0x41600000 0x10000 >; - - #size-cells = <0>; - #address-cells = <1>; - }; - - sdhci@e0100000 { - compatible = "xlnx,ps7-sdhci-1.00.a"; - reg = <0xe0100000 0x1000>; - interrupts = <0 24 0>; - interrupt-parent = <&gic>; - clock-frequency = <50000000>; - }; - - usb@e0002000 { - compatible = "xlnx,ps7-usb-1.00.a"; - reg = <0xe0002000 0x1000>; - interrupts = <0 21 0>; - interrupt-parent = <&gic>; - dr_mode = "host"; - phy_type = "ulpi"; - }; - - qspi0: spi@e000d000 { - compatible = "xlnx,ps7-qspi-1.00.a"; - reg = <0xE000D000 0x1000>; - interrupts = <0 19 0>; - interrupt-parent = <&gic>; - speed-hz = <200000000>; - bus-num = <1>; - num-chip-select = <1>; - is-dual = <0>; - }; - - devcfg@f8007000 { - compatible = "xlnx,ps7-dev-cfg-1.00.a"; - reg = <0xf8007000 0x1000>; - interrupts = <0 8 0>; - interrupt-parent = <&gic>; - }; - - axi_dma_0: axidma@40400000 { - #address-cells = <1>; - #size-cells = <1>; - #dma-cells = <1>; - compatible = "xlnx,axi-dma"; - reg = < 0x40400000 0x1000 >; - xlnx,sg-include-stscntrl-strm = <0x0>; - dma-channel@40400000 { - compatible = "xlnx,axi-dma-mm2s-channel"; - interrupts = < 0 58 0x4 >; - xlnx,datawidth = <0x20>; - xlnx,include-dre = <0x0>; - }; - }; - - axi_spdif_tx_0: axi-spdif-tx@0x75c00000 { - compatible = "adi,axi-spdif-tx-1.00.a"; - reg = < 0x75c00000 0x1000 >; - clock-frequency = <12288000>; - }; - - axi_vdma_0: axivdma@43000000 { - #address-cells = <1>; - #size-cells = <1>; - #dma-cells = <1>; - compatible = "xlnx,axi-vdma"; - reg = <0x43000000 0x1000>; - xlnx,include-sg = <0x0>; - xlnx,num-fstores = <0x3>; - dma-channel@7e200000 { - compatible = "xlnx,axi-vdma-mm2s-channel"; - interrupts = <0 59 0x4>; - xlnx,datawidth = <0x40>; - xlnx,genlock-mode = <0x0>; - xlnx,include-dre = <0x0>; - }; - }; - - cf_adv7x11_core_0: cf-adv7x11-core@6c000000 { - compatible = "adi,cf-adv7x11-core-1.00.a"; - reg = <0x6c000000 0x10000 - 0x66000000 0x10000>; - slave_adapter = <&axi_iic_0>; - dma-request = <&axi_vdma_0 0>; - }; - - xilinx_pcm_audio: xilinx_pcm_audio { - compatible = "xilinx-pcm-audio"; - dma-request = <&axi_dma_0 0>; - }; - - adv7511_hdmi_snd: adv7511_hdmi_snd { - compatible = "adv7511-hdmi-snd"; -// audio-codec = <&>; - cpu-dai = <&axi_spdif_tx_0>; - pcm = <&xilinx_pcm_audio>; - }; - }; -}; diff --git a/arch/arm/boot/dts/zynq-zed.dts b/arch/arm/boot/dts/zynq-zed.dts deleted file mode 100644 index bc9f168f34bb3..0000000000000 --- a/arch/arm/boot/dts/zynq-zed.dts +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Device Tree Generator version: 1.1 - * - * (C) Copyright 2007-2012 Xilinx, Inc. - * (C) Copyright 2007-2012 Michal Simek - * (C) Copyright 2007-2012 PetaLogix Qld Pty Ltd - * - * Michal SIMEK - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * CAUTION: This file is automatically generated by libgen. - * Version: Xilinx EDK 14.3 EDK_P.40xd - * Today is: Tuesday, the 27 of November, 2012; 12:29:21 - * - * XPS project directory: device-tree_bsp_0 - */ - -/dts-v1/; -/ { - #address-cells = <1>; - #size-cells = <1>; - compatible = "xlnx,zynq-zc770"; - model = "Xilinx Zynq"; - aliases { - ethernet0 = &ps7_ethernet_0; - serial0 = &ps7_uart_1; - } ; - chosen { - bootargs = "console=ttyPS0,115200 root=/dev/ram rw ip=:::::eth0:dhcp earlyprintk"; - linux,stdout-path = "/axi@0/serial@e0001000"; - } ; - cpus { - #address-cells = <1>; - #cpus = <0x2>; - #size-cells = <0>; - ps7_cortexa9_0: cpu@0 { - clock-frequency = <666666687>; - compatible = "xlnx,ps7-cortexa9-1.00.a"; - d-cache-line-size = <0x20>; - d-cache-size = <0x8000>; - device_type = "cpu"; - i-cache-line-size = <0x20>; - i-cache-size = <0x8000>; - model = "ps7_cortexa9,1.00.a"; - reg = <0>; - timebase-frequency = <333333343>; - xlnx,cpu-1x-clk-freq-hz = <0x69f6bcb>; - xlnx,cpu-clk-freq-hz = <0x27bc86bf>; - } ; - ps7_cortexa9_1: cpu@1 { - clock-frequency = <666666687>; - compatible = "xlnx,ps7-cortexa9-1.00.a"; - d-cache-line-size = <0x20>; - d-cache-size = <0x8000>; - device_type = "cpu"; - i-cache-line-size = <0x20>; - i-cache-size = <0x8000>; - model = "ps7_cortexa9,1.00.a"; - reg = <1>; - timebase-frequency = <333333343>; - xlnx,cpu-1x-clk-freq-hz = <0x69f6bcb>; - xlnx,cpu-clk-freq-hz = <0x27bc86bf>; - } ; - } ; - ps7_ddr_0: memory@0 { - device_type = "memory"; - reg = < 0x0 0x20000000 >; - } ; - ps7_axi_interconnect_0: axi@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "xlnx,ps7-axi-interconnect-1.00.a", "simple-bus"; - ranges ; - ps7_afi_0: ps7-afi@f8008000 { - compatible = "xlnx,ps7-afi-1.00.a"; - reg = < 0xf8008000 0x1000 >; - } ; - ps7_afi_1: ps7-afi@f8009000 { - compatible = "xlnx,ps7-afi-1.00.a"; - reg = < 0xf8009000 0x1000 >; - } ; - ps7_afi_2: ps7-afi@f800a000 { - compatible = "xlnx,ps7-afi-1.00.a"; - reg = < 0xf800a000 0x1000 >; - } ; - ps7_afi_3: ps7-afi@f800b000 { - compatible = "xlnx,ps7-afi-1.00.a"; - reg = < 0xf800b000 0x1000 >; - } ; - ps7_ddrc_0: ps7-ddrc@f8006000 { - compatible = "xlnx,ps7-ddrc-1.00.a"; - reg = < 0xf8006000 0x1000 >; - xlnx,has-ecc = <0x0>; - } ; - ps7_dev_cfg_0: ps7-dev-cfg@f8007000 { - compatible = "xlnx,ps7-dev-cfg-1.00.a"; - interrupt-parent = <&ps7_scugic_0>; - interrupts = < 0 8 0 >; - reg = < 0xf8007000 0x1000 >; - } ; - ps7_dma_ns: ps7-dma@f8004000 { - compatible = "xlnx,ps7-dma-1.00.a"; - reg = < 0xf8004000 0x1000 >; - } ; - ps7_dma_s: ps7-dma@f8003000 { - compatible = "xlnx,ps7-dma-1.00.a"; - reg = < 0xf8003000 0x1000 >; - } ; - ps7_ethernet_0: ps7-ethernet@e000b000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "xlnx,ps7-ethernet-1.00.a"; - interrupt-parent = <&ps7_scugic_0>; - interrupts = < 0 22 0 >; - local-mac-address = [ 00 0a 35 00 00 00 ]; - phy-handle = <&phy0>; - reg = < 0xe000b000 0x1000 >; - xlnx,enet-clk-freq-hz = <0x7735940>; - xlnx,enet-reset = <0xffffffff>; - xlnx,enet-slcr-1000mbps-div0 = <0x8>; - xlnx,enet-slcr-1000mbps-div1 = <0x1>; - xlnx,enet-slcr-100mbps-div0 = <0x8>; - xlnx,enet-slcr-100mbps-div1 = <0x5>; - xlnx,enet-slcr-10mbps-div0 = <0x8>; - xlnx,enet-slcr-10mbps-div1 = <0x32>; - xlnx,eth-mode = <0x1>; - xlnx,has-mdio = <0x1>; - xlnx,ptp-enet-clock = <111111115>; - mdio { - #address-cells = <1>; - #size-cells = <0>; - phy0: phy@7 { - compatible = "marvell,88e1510"; - device_type = "ethernet-phy"; - reg = <7>; - } ; - } ; - } ; - ps7_gpio_0: ps7-gpio@e000a000 { - #gpio-cells = <2>; - compatible = "xlnx,ps7-gpio-1.00.a"; - emio-gpio-width = <64>; - gpio-controller ; - gpio-mask-high = <0xc0000>; - gpio-mask-low = <0xfe81>; - interrupt-parent = <&ps7_scugic_0>; - interrupts = < 0 20 0 >; - reg = < 0xe000a000 0x1000 >; - } ; - ps7_iop_bus_config_0: ps7-iop-bus-config@e0200000 { - compatible = "xlnx,ps7-iop-bus-config-1.00.a"; - reg = < 0xe0200000 0x1000 >; - } ; - ps7_pl310_0: ps7-pl310@f8f02000 { - arm,data-latency = < 3 2 2 >; - arm,tag-latency = < 2 2 2 >; - cache-level = < 2 >; - cache-unified ; - compatible = "xlnx,ps7-pl310-1.00.a", "arm,pl310-cache"; - reg = < 0xf8f02000 0x1000 >; - } ; - ps7_qspi_0: ps7-qspi@e000d000 { - bus-num = <0>; - compatible = "xlnx,ps7-qspi-1.00.a"; - interrupt-parent = <&ps7_scugic_0>; - interrupts = < 0 19 0 >; - is-dual = <0>; - num-chip-select = <1>; - reg = < 0xe000d000 0x1000 >; - speed-hz = <200000000>; - xlnx,fb-clk = <0x1>; - xlnx,qspi-clk-freq-hz = <0xbebc200>; - xlnx,qspi-mode = <0x0>; - #address-cells = <1>; - #size-cells = <0>; - flash@0 { - compatible = "n25q128"; - reg = <0x0>; - spi-max-frequency = <50000000>; - #address-cells = <1>; - #size-cells = <1>; - partition@qspi-fsbl-uboot { - label = "qspi-fsbl-uboot"; - reg = <0x0 0x100000>; - }; - partition@qspi-linux { - label = "qspi-linux"; - reg = <0x100000 0x500000>; - }; - partition@qspi-device-tree { - label = "qspi-device-tree"; - reg = <0x600000 0x20000>; - }; - partition@qspi-rootfs { - label = "qspi-rootfs"; - reg = <0x620000 0x9D0000>; - }; - }; - } ; - ps7_qspi_linear_0: ps7-qspi-linear@fc000000 { - compatible = "xlnx,ps7-qspi-linear-1.00.a"; - reg = < 0xfc000000 0x1000000 >; - xlnx,qspi-clk-freq-hz = <0xe4e1c0>; - } ; - ps7_ram_0: ps7-ram@0 { - compatible = "xlnx,ps7-ram-1.00.a"; - reg = < 0x0 0x30000 >; - } ; - ps7_ram_1: ps7-ram@ffff0000 { - compatible = "xlnx,ps7-ram-1.00.a"; - reg = < 0xffff0000 0xfe00 >; - } ; - ps7_scugic_0: ps7-scugic@f8f01000 { - #address-cells = < 2 >; - #interrupt-cells = < 3 >; - #size-cells = < 1 >; - compatible = "xlnx,ps7-scugic-1.00.a", "arm,cortex-a9-gic", "arm,gic"; - interrupt-controller ; - linux,phandle = < 0x1 >; - phandle = < 0x1 >; - reg = < 0xf8f01000 0x1000 0xf8f00100 0x100 >; - } ; - ps7_scutimer_0: ps7-scutimer@f8f00600 { - clock-frequency = <333333343>; - compatible = "xlnx,ps7-scutimer-1.00.a", "arm,cortex-a9-twd-timer"; - interrupt-parent = <&ps7_scugic_0>; - interrupts = < 1 13 0 >; - reg = < 0xf8f00600 0x20 >; - } ; - ps7_scuwdt_0: ps7-scuwdt@f8f00620 { - clock-frequency = <333333343>; - compatible = "xlnx,ps7-scuwdt-1.00.a"; - device_type = "watchdog"; - interrupt-parent = <&ps7_scugic_0>; - interrupts = < 1 14 0 >; - reg = < 0xf8f00620 0xe0 >; - } ; - ps7_sd_0: ps7-sdio@e0100000 { - clock-frequency = <50000000>; - compatible = "xlnx,ps7-sdio-1.00.a", "generic-sdhci"; - interrupt-parent = <&ps7_scugic_0>; - interrupts = < 0 24 0 >; - reg = < 0xe0100000 0x1000 >; - xlnx,has-cd = <0x1>; - xlnx,has-power = <0x0>; - xlnx,has-wp = <0x1>; - xlnx,sdio-clk-freq-hz = <0x2faf080>; - } ; - ps7_slcr_0: ps7-slcr@f8000000 { - compatible = "xlnx,ps7-slcr-1.00.a"; - reg = < 0xf8000000 0x1000 >; - } ; - ps7_ttc_0: ps7-ttc@f8001000 { - clock-frequency = <111111115>; - clock-frequency-timer0 = <111111115>; - clock-frequency-timer1 = <111111115>; - clock-frequency-timer2 = <111111115>; - compatible = "xlnx,ps7-ttc-1.00.a"; - interrupt-parent = <&ps7_scugic_0>; - interrupts = < 0 10 0 0 11 0 0 12 0 >; - reg = < 0xf8001000 0x1000 >; - xlnx,ttc-clk0-clksrc = <0x0>; - xlnx,ttc-clk0-freq-hz = <0x69f6bcb>; - xlnx,ttc-clk1-clksrc = <0x0>; - xlnx,ttc-clk1-freq-hz = <0x69f6bcb>; - xlnx,ttc-clk2-clksrc = <0x0>; - xlnx,ttc-clk2-freq-hz = <0x69f6bcb>; - } ; - ps7_uart_1: serial@e0001000 { - clock = <50000000>; - clock-frequency = <50000000>; - compatible = "xlnx,ps7-uart-1.00.a", "xlnx,xuartps"; - current-speed = <115200>; - device_type = "serial"; - interrupt-parent = <&ps7_scugic_0>; - interrupts = < 0 50 0 >; - port-number = <0>; - reg = < 0xe0001000 0x1000 >; - xlnx,has-modem = <0x0>; - xlnx,uart-clk-freq-hz = <0x2faf080>; - } ; - ps7_usb_0: ps7-usb@e0002000 { - compatible = "xlnx,ps7-usb-1.00.a"; - dr_mode = "host"; - interrupt-parent = <&ps7_scugic_0>; - interrupts = < 0 21 0 >; - phy_type = "ulpi"; - reg = < 0xe0002000 0x1000 >; - xlnx,usb-reset = <0xffffffff>; - } ; - ps7_xadc: ps7_xadc@f8007100 { - compatible = "xlnx,ps7-xadc-1.00.a"; - interrupts = < 0 7 4 >; - reg = < 0xf8007100 0x20 >; - } ; - } ; -} ; From e50974bb8a7342a6a9979ce382c86d4cf053c8f2 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 3 Jan 2013 13:24:47 -0800 Subject: [PATCH 256/261] DTS: ZedBoard: enable mounting devtmpfs to /dev devtmpfs contains all the device nodes for all devices known to the kernel. It needs to be mounted to access SD card partition via corresponding device nodes under /dev. --- arch/arm/boot/dts/digilent-zed.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/digilent-zed.dts b/arch/arm/boot/dts/digilent-zed.dts index 48fa1f08ef722..cbea708dc6eb2 100644 --- a/arch/arm/boot/dts/digilent-zed.dts +++ b/arch/arm/boot/dts/digilent-zed.dts @@ -46,8 +46,8 @@ }; chosen { - bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0"; - /* bootargs = "console=ttyPS0,115200 root=/dev/ram rw initrd=0x800000,8M init=/init earlyprintk rootwait devtmpfs.mount=0"; */ + bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=1"; + /* bootargs = "console=ttyPS0,115200 root=/dev/ram rw initrd=0x800000,8M init=/init earlyprintk rootwait devtmpfs.mount=1"; */ linux,stdout-path = "/axi@0/serial@e0001000"; }; From 9b7d71dcd0ad42f6a42bf0fa2379ed9b36f625d2 Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 3 Jan 2013 13:29:44 -0800 Subject: [PATCH 257/261] ZedBoard: Add restart functions to support reboot --- arch/arm/mach-zynq/board_zed.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-zynq/board_zed.c b/arch/arm/mach-zynq/board_zed.c index 38ff153268702..ab9c72650c3c6 100644 --- a/arch/arm/mach-zynq/board_zed.c +++ b/arch/arm/mach-zynq/board_zed.c @@ -71,4 +71,5 @@ MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform") .timer = &xttcpss_sys_timer, .dt_compat = xilinx_dt_match, .reserve = xilinx_memory_init, + .restart = xilinx_system_reset, MACHINE_END From 5265e2500368c02c7ca8ad12f9ea4eaf0b9f364d Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Thu, 3 Jan 2013 13:51:15 -0800 Subject: [PATCH 258/261] ARM: Makefile: Temporary Fix for an error when using Make 3.82 Some Linux distribution upgraded GNU Make from v3.81 to v3.82 For those who use v3.82, an error may occur during compilation which goes as follows: .../arch/arm/Makefile:296: *** mixed implicit and normal rules. Stop This temporarily fixes the error. --- arch/arm/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 7a7bd8c163a38..b64b568737264 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -293,7 +293,10 @@ archprepare: bzImage: zImage #zImage Image xipImage bootpImage uImage: vmlinux -$(BOOT_TARGETS1) $(BOOT_TARGETS2) : vmlinux +$(BOOT_TARGETS1) : vmlinux + $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ + +$(BOOT_TARGETS2) : vmlinux $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ zinstall uinstall install: vmlinux From 220a7572d365a2d94eb58fcd1a0f286db59c698e Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Tue, 15 Jan 2013 16:13:31 -0800 Subject: [PATCH 259/261] net: xilinx_emacps: Obtain MAC Address from Device Tree if available xilinx_emacps will obtain MAC address from local-mac-address property in device tree first. If the property is not set, it will try to obtain mac address from EMACPS hardware registers. If the mac hardware address from EMACPS registers is not valid, it will generate a random mac address. --- drivers/net/ethernet/xilinx/xilinx_emacps.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ethernet/xilinx/xilinx_emacps.c b/drivers/net/ethernet/xilinx/xilinx_emacps.c index a4786f378587a..ae113c8f795df 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emacps.c +++ b/drivers/net/ethernet/xilinx/xilinx_emacps.c @@ -2918,6 +2918,7 @@ static int __devinit xemacps_probe(struct platform_device *pdev) const void *prop; u32 regval = 0; int rc = -ENXIO; + int size = 0; r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); r_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); @@ -3064,6 +3065,12 @@ static int __devinit xemacps_probe(struct platform_device *pdev) goto err_out_unregister_clk_notifier; } + lp->ndev->dev_addr = of_get_property(lp->pdev->dev.of_node, "local-mac-address", &size); + if ((!lp->ndev->dev_addr) || (size != 6)) { + dev_warn(&lp->pdev->dev, "Could not find MAC address in device tree, use default\n"); + } else { + xemacps_set_hwaddr(lp); + } xemacps_update_hwaddr(lp); platform_set_drvdata(pdev, ndev); From 06b388903e5459687ba2538ae3895ffe29e2e39e Mon Sep 17 00:00:00 2001 From: "Tinghui WANG (Steven)" Date: Wed, 16 Jan 2013 15:49:04 -0800 Subject: [PATCH 260/261] net: xilinx_emacps: Fixed accessing NULL pointer error when local-mac-address is not available in device tree --- drivers/net/ethernet/xilinx/xilinx_emacps.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_emacps.c b/drivers/net/ethernet/xilinx/xilinx_emacps.c index ae113c8f795df..7b4667ffb5b0c 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emacps.c +++ b/drivers/net/ethernet/xilinx/xilinx_emacps.c @@ -2919,6 +2919,7 @@ static int __devinit xemacps_probe(struct platform_device *pdev) u32 regval = 0; int rc = -ENXIO; int size = 0; + const u8* addr; r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); r_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); @@ -3065,10 +3066,11 @@ static int __devinit xemacps_probe(struct platform_device *pdev) goto err_out_unregister_clk_notifier; } - lp->ndev->dev_addr = of_get_property(lp->pdev->dev.of_node, "local-mac-address", &size); - if ((!lp->ndev->dev_addr) || (size != 6)) { + addr = of_get_property(lp->pdev->dev.of_node, "local-mac-address", &size); + if ((!addr) || (size != 6)) { dev_warn(&lp->pdev->dev, "Could not find MAC address in device tree, use default\n"); } else { + memcpy(lp->ndev->dev_addr, addr, sizeof(addr)); xemacps_set_hwaddr(lp); } xemacps_update_hwaddr(lp); From e4b6c4593e8d20ae25c31ccf87effda83d1f9c9e Mon Sep 17 00:00:00 2001 From: chungerz Date: Sun, 25 Aug 2013 15:04:02 -0700 Subject: [PATCH 261/261] Update spidev.c help spidev be probe from device tree, see https://patchwork.kernel.org/patch/1519151/ for original patch. --- drivers/spi/spidev.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 830adbed1d7ac..8ae06601b5bea 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include @@ -642,10 +644,18 @@ static int __devexit spidev_remove(struct spi_device *spi) return 0; } +static const struct of_device_id spidev_dt_ids[] = { + { .compatible = "linux,spidev" }, + {}, +}; + +MODULE_DEVICE_TABLE(of, spidev_dt_ids); + static struct spi_driver spidev_spi_driver = { .driver = { .name = "spidev", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(spidev_dt_ids), }, .probe = spidev_probe, .remove = __devexit_p(spidev_remove),