From 49920bc66984a512f4bcc7735a61642cd0e4d6f2 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 13 Oct 2011 15:15:27 +0530 Subject: dmaengine: add new enum dma_transfer_direction This new enum removes usage of dma_data_direction for dma direction. The new enum cleans tells the DMA direction and mode This further paves way for merging the dmaengine _prep operations and also for interleaved dma Suggested-by: Jassi Brar Reviewed-by: Barry Song Signed-off-by: Vinod Koul diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index ace51af..d946ef7 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -23,7 +23,6 @@ #include #include -#include #include /** @@ -75,6 +74,19 @@ enum dma_transaction_type { /* last transaction type for creation of the capabilities mask */ #define DMA_TX_TYPE_END (DMA_CYCLIC + 1) +/** + * enum dma_transfer_direction - dma transfer mode and direction indicator + * @DMA_MEM_TO_MEM: Async/Memcpy mode + * @DMA_MEM_TO_DEV: Slave mode & From Memory to Device + * @DMA_DEV_TO_MEM: Slave mode & From Device to Memory + * @DMA_DEV_TO_DEV: Slave mode & From Device to Device + */ +enum dma_transfer_direction { + DMA_MEM_TO_MEM, + DMA_MEM_TO_DEV, + DMA_DEV_TO_MEM, + DMA_DEV_TO_DEV, +}; /** * enum dma_ctrl_flags - DMA flags to augment operation preparation, @@ -267,7 +279,7 @@ enum dma_slave_buswidth { * struct, if applicable. */ struct dma_slave_config { - enum dma_data_direction direction; + enum dma_transfer_direction direction; dma_addr_t src_addr; dma_addr_t dst_addr; enum dma_slave_buswidth src_addr_width; @@ -490,11 +502,11 @@ struct dma_device { struct dma_async_tx_descriptor *(*device_prep_slave_sg)( struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags); struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, - size_t period_len, enum dma_data_direction direction); + size_t period_len, enum dma_transfer_direction direction); int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg); @@ -520,7 +532,7 @@ 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, - enum dma_data_direction dir, unsigned long flags) + enum dma_transfer_direction dir, unsigned long flags) { struct scatterlist sg; sg_init_one(&sg, buf, len); -- cgit v0.10.2 From db8196df4bb6f117caa163aa73b0f16fd62290bd Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 13 Oct 2011 22:34:23 +0530 Subject: dmaengine: move drivers to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves dma/drivers/* to use new enum Cc: Jassi Brar Cc: Russell King Cc: Viresh Kumar Cc: Linus Walleij Cc: Nicolas Ferre Cc: Mika Westerberg Cc: H Hartley Sweeten Cc: Li Yang Cc: Zhang Wei Cc: Sascha Hauer Cc: Guennadi Liakhovetski Cc: Shawn Guo Cc: Yong Wang Cc: Tomoya MORINAGA Cc: Boojin Kim Cc: Barry Song Acked-by: Mika Westerberg Acked-by: Linus Walleij Acked-by: Viresh Kumar Acked-by: Nicolas Ferre Signed-off-by: Vinod Koul diff --git a/arch/arm/mach-ep93xx/include/mach/dma.h b/arch/arm/mach-ep93xx/include/mach/dma.h index 46d4d87..e82c642 100644 --- a/arch/arm/mach-ep93xx/include/mach/dma.h +++ b/arch/arm/mach-ep93xx/include/mach/dma.h @@ -37,7 +37,7 @@ */ struct ep93xx_dma_data { int port; - enum dma_data_direction direction; + enum dma_transfer_direction direction; const char *name; }; @@ -80,14 +80,14 @@ static inline bool ep93xx_dma_chan_is_m2p(struct dma_chan *chan) * channel supports given DMA direction. Only M2P channels have such * limitation, for M2M channels the direction is configurable. */ -static inline enum dma_data_direction +static inline enum dma_transfer_direction ep93xx_dma_chan_direction(struct dma_chan *chan) { if (!ep93xx_dma_chan_is_m2p(chan)) return DMA_NONE; /* even channels are for TX, odd for RX */ - return (chan->chan_id % 2 == 0) ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + return (chan->chan_id % 2 == 0) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; } #endif /* __ASM_ARCH_DMA_H */ diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h index 685c787..38b041a 100644 --- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h +++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h @@ -187,7 +187,7 @@ static inline struct dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan, dma_addr_t addr, unsigned int size, - enum dma_data_direction direction, + enum dma_transfer_direction direction, unsigned long flags) { struct scatterlist sg; @@ -209,7 +209,7 @@ static inline struct dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan, dma_addr_t addr, unsigned int size, - enum dma_data_direction direction, + enum dma_transfer_direction direction, unsigned long flags) { return NULL; diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index b7cbd1a..41c62fd 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -882,9 +882,9 @@ static int prep_phy_channel(struct pl08x_dma_chan *plchan, ch->signal = ret; /* Assign the flow control signal to this channel */ - if (txd->direction == DMA_TO_DEVICE) + if (txd->direction == DMA_MEM_TO_DEV) txd->ccfg |= ch->signal << PL080_CONFIG_DST_SEL_SHIFT; - else if (txd->direction == DMA_FROM_DEVICE) + else if (txd->direction == DMA_DEV_TO_MEM) txd->ccfg |= ch->signal << PL080_CONFIG_SRC_SEL_SHIFT; } @@ -1102,10 +1102,10 @@ static int dma_set_runtime_config(struct dma_chan *chan, /* Transfer direction */ plchan->runtime_direction = config->direction; - if (config->direction == DMA_TO_DEVICE) { + if (config->direction == DMA_MEM_TO_DEV) { addr_width = config->dst_addr_width; maxburst = config->dst_maxburst; - } else if (config->direction == DMA_FROM_DEVICE) { + } else if (config->direction == DMA_DEV_TO_MEM) { addr_width = config->src_addr_width; maxburst = config->src_maxburst; } else { @@ -1136,7 +1136,7 @@ static int dma_set_runtime_config(struct dma_chan *chan, cctl |= burst << PL080_CONTROL_SB_SIZE_SHIFT; cctl |= burst << PL080_CONTROL_DB_SIZE_SHIFT; - if (plchan->runtime_direction == DMA_FROM_DEVICE) { + if (plchan->runtime_direction == DMA_DEV_TO_MEM) { plchan->src_addr = config->src_addr; plchan->src_cctl = pl08x_cctl(cctl) | PL080_CONTROL_DST_INCR | pl08x_select_bus(plchan->cd->periph_buses, @@ -1152,7 +1152,7 @@ static int dma_set_runtime_config(struct dma_chan *chan, "configured channel %s (%s) for %s, data width %d, " "maxburst %d words, LE, CCTL=0x%08x\n", dma_chan_name(chan), plchan->name, - (config->direction == DMA_FROM_DEVICE) ? "RX" : "TX", + (config->direction == DMA_DEV_TO_MEM) ? "RX" : "TX", addr_width, maxburst, cctl); @@ -1322,7 +1322,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy( static struct dma_async_tx_descriptor *pl08x_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags) { struct pl08x_dma_chan *plchan = to_pl08x_chan(chan); @@ -1354,10 +1354,10 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg( */ txd->direction = direction; - if (direction == DMA_TO_DEVICE) { + if (direction == DMA_MEM_TO_DEV) { txd->cctl = plchan->dst_cctl; slave_addr = plchan->dst_addr; - } else if (direction == DMA_FROM_DEVICE) { + } else if (direction == DMA_DEV_TO_MEM) { txd->cctl = plchan->src_cctl; slave_addr = plchan->src_addr; } else { @@ -1368,10 +1368,10 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg( } if (plchan->cd->device_fc) - tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER_PER : + tmp = (direction == DMA_MEM_TO_DEV) ? PL080_FLOW_MEM2PER_PER : PL080_FLOW_PER2MEM_PER; else - tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER : + tmp = (direction == DMA_MEM_TO_DEV) ? PL080_FLOW_MEM2PER : PL080_FLOW_PER2MEM; txd->ccfg |= tmp << PL080_CONFIG_FLOW_CONTROL_SHIFT; @@ -1387,7 +1387,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg( list_add_tail(&dsg->node, &txd->dsg_list); dsg->len = sg_dma_len(sg); - if (direction == DMA_TO_DEVICE) { + if (direction == DMA_MEM_TO_DEV) { dsg->src_addr = sg_phys(sg); dsg->dst_addr = slave_addr; } else { diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index fcfa0a8..7e76574 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -660,7 +660,7 @@ err_desc_get: */ static struct dma_async_tx_descriptor * atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags) { struct at_dma_chan *atchan = to_at_dma_chan(chan); @@ -678,7 +678,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, dev_vdbg(chan2dev(chan), "prep_slave_sg (%d): %s f0x%lx\n", sg_len, - direction == DMA_TO_DEVICE ? "TO DEVICE" : "FROM DEVICE", + direction == DMA_MEM_TO_DEV ? "TO DEVICE" : "FROM DEVICE", flags); if (unlikely(!atslave || !sg_len)) { @@ -692,7 +692,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ctrlb = ATC_IEN; switch (direction) { - case DMA_TO_DEVICE: + case DMA_MEM_TO_DEV: ctrla |= ATC_DST_WIDTH(reg_width); ctrlb |= ATC_DST_ADDR_MODE_FIXED | ATC_SRC_ADDR_MODE_INCR @@ -725,7 +725,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, total_len += len; } break; - case DMA_FROM_DEVICE: + case DMA_DEV_TO_MEM: ctrla |= ATC_SRC_WIDTH(reg_width); ctrlb |= ATC_DST_ADDR_MODE_INCR | ATC_SRC_ADDR_MODE_FIXED @@ -787,7 +787,7 @@ err_desc_get: */ static int atc_dma_cyclic_check_values(unsigned int reg_width, dma_addr_t buf_addr, - size_t period_len, enum dma_data_direction direction) + size_t period_len, enum dma_transfer_direction direction) { if (period_len > (ATC_BTSIZE_MAX << reg_width)) goto err_out; @@ -795,7 +795,7 @@ atc_dma_cyclic_check_values(unsigned int reg_width, dma_addr_t buf_addr, goto err_out; if (unlikely(buf_addr & ((1 << reg_width) - 1))) goto err_out; - if (unlikely(!(direction & (DMA_TO_DEVICE | DMA_FROM_DEVICE)))) + if (unlikely(!(direction & (DMA_DEV_TO_MEM | DMA_MEM_TO_DEV)))) goto err_out; return 0; @@ -810,7 +810,7 @@ err_out: static int atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc, unsigned int period_index, dma_addr_t buf_addr, - size_t period_len, enum dma_data_direction direction) + size_t period_len, enum dma_transfer_direction direction) { u32 ctrla; unsigned int reg_width = atslave->reg_width; @@ -822,7 +822,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc, | period_len >> reg_width; switch (direction) { - case DMA_TO_DEVICE: + case DMA_MEM_TO_DEV: desc->lli.saddr = buf_addr + (period_len * period_index); desc->lli.daddr = atslave->tx_reg; desc->lli.ctrla = ctrla; @@ -833,7 +833,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc, | ATC_DIF(AT_DMA_PER_IF); break; - case DMA_FROM_DEVICE: + case DMA_DEV_TO_MEM: desc->lli.saddr = atslave->rx_reg; desc->lli.daddr = buf_addr + (period_len * period_index); desc->lli.ctrla = ctrla; @@ -861,7 +861,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc, */ static struct dma_async_tx_descriptor * atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, - size_t period_len, enum dma_data_direction direction) + size_t period_len, enum dma_transfer_direction direction) { struct at_dma_chan *atchan = to_at_dma_chan(chan); struct at_dma_slave *atslave = chan->private; @@ -872,7 +872,7 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, unsigned int i; dev_vdbg(chan2dev(chan), "prep_dma_cyclic: %s buf@0x%08x - %d (%d/%d)\n", - direction == DMA_TO_DEVICE ? "TO DEVICE" : "FROM DEVICE", + direction == DMA_MEM_TO_DEV ? "TO DEVICE" : "FROM DEVICE", buf_addr, periods, buf_len, period_len); diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c index 4234f41..d65a718 100644 --- a/drivers/dma/coh901318.c +++ b/drivers/dma/coh901318.c @@ -39,7 +39,7 @@ struct coh901318_desc { struct scatterlist *sg; unsigned int sg_len; struct coh901318_lli *lli; - enum dma_data_direction dir; + enum dma_transfer_direction dir; unsigned long flags; u32 head_config; u32 head_ctrl; @@ -1034,7 +1034,7 @@ coh901318_prep_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, static struct dma_async_tx_descriptor * coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags) { struct coh901318_chan *cohc = to_coh901318_chan(chan); @@ -1077,7 +1077,7 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ctrl_last |= cohc->runtime_ctrl; ctrl |= cohc->runtime_ctrl; - if (direction == DMA_TO_DEVICE) { + if (direction == DMA_MEM_TO_DEV) { u32 tx_flags = COH901318_CX_CTRL_PRDD_SOURCE | COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE; @@ -1085,7 +1085,7 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ctrl_chained |= tx_flags; ctrl_last |= tx_flags; ctrl |= tx_flags; - } else if (direction == DMA_FROM_DEVICE) { + } else if (direction == DMA_DEV_TO_MEM) { u32 rx_flags = COH901318_CX_CTRL_PRDD_DEST | COH901318_CX_CTRL_DST_ADDR_INC_ENABLE; @@ -1274,11 +1274,11 @@ static void coh901318_dma_set_runtimeconfig(struct dma_chan *chan, int i = 0; /* We only support mem to per or per to mem transfers */ - if (config->direction == DMA_FROM_DEVICE) { + if (config->direction == DMA_DEV_TO_MEM) { addr = config->src_addr; addr_width = config->src_addr_width; maxburst = config->src_maxburst; - } else if (config->direction == DMA_TO_DEVICE) { + } else if (config->direction == DMA_MEM_TO_DEV) { addr = config->dst_addr; addr_width = config->dst_addr_width; maxburst = config->dst_maxburst; diff --git a/drivers/dma/coh901318_lli.c b/drivers/dma/coh901318_lli.c index 9f7e0e6a..6c0e2d4 100644 --- a/drivers/dma/coh901318_lli.c +++ b/drivers/dma/coh901318_lli.c @@ -7,11 +7,10 @@ * Author: Per Friden */ -#include #include -#include #include #include +#include #include #include "coh901318_lli.h" @@ -177,18 +176,18 @@ coh901318_lli_fill_single(struct coh901318_pool *pool, struct coh901318_lli *lli, dma_addr_t buf, unsigned int size, dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl_eom, - enum dma_data_direction dir) + enum dma_transfer_direction dir) { int s = size; dma_addr_t src; dma_addr_t dst; - if (dir == DMA_TO_DEVICE) { + if (dir == DMA_MEM_TO_DEV) { src = buf; dst = dev_addr; - } else if (dir == DMA_FROM_DEVICE) { + } else if (dir == DMA_DEV_TO_MEM) { src = dev_addr; dst = buf; @@ -215,9 +214,9 @@ coh901318_lli_fill_single(struct coh901318_pool *pool, lli = coh901318_lli_next(lli); - if (dir == DMA_TO_DEVICE) + if (dir == DMA_MEM_TO_DEV) src += block_size; - else if (dir == DMA_FROM_DEVICE) + else if (dir == DMA_DEV_TO_MEM) dst += block_size; } @@ -234,7 +233,7 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool, struct scatterlist *sgl, unsigned int nents, dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl, u32 ctrl_last, - enum dma_data_direction dir, u32 ctrl_irq_mask) + enum dma_transfer_direction dir, u32 ctrl_irq_mask) { int i; struct scatterlist *sg; @@ -249,9 +248,9 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool, spin_lock(&pool->lock); - if (dir == DMA_TO_DEVICE) + if (dir == DMA_MEM_TO_DEV) dst = dev_addr; - else if (dir == DMA_FROM_DEVICE) + else if (dir == DMA_DEV_TO_MEM) src = dev_addr; else goto err; @@ -269,7 +268,7 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool, ctrl_sg = ctrl ? ctrl : ctrl_last; - if (dir == DMA_TO_DEVICE) + if (dir == DMA_MEM_TO_DEV) /* increment source address */ src = sg_phys(sg); else @@ -293,7 +292,7 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool, lli->src_addr = src; lli->dst_addr = dst; - if (dir == DMA_FROM_DEVICE) + if (dir == DMA_DEV_TO_MEM) dst += elem_size; else src += elem_size; diff --git a/drivers/dma/coh901318_lli.h b/drivers/dma/coh901318_lli.h index 7a5c809..abff371 100644 --- a/drivers/dma/coh901318_lli.h +++ b/drivers/dma/coh901318_lli.h @@ -97,7 +97,7 @@ coh901318_lli_fill_single(struct coh901318_pool *pool, struct coh901318_lli *lli, dma_addr_t buf, unsigned int size, dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl_last, - enum dma_data_direction dir); + enum dma_transfer_direction dir); /** * coh901318_lli_fill_single() - Prepares the lli:s for dma scatter list transfer @@ -119,6 +119,6 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool, struct scatterlist *sg, unsigned int nents, dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl, u32 ctrl_last, - enum dma_data_direction dir, u32 ctrl_irq_mask); + enum dma_transfer_direction dir, u32 ctrl_irq_mask); #endif /* COH901318_LLI_H */ diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 9bfd6d3..decca1c 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -696,7 +696,7 @@ err_desc_get: static struct dma_async_tx_descriptor * dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); @@ -720,7 +720,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, prev = first = NULL; switch (direction) { - case DMA_TO_DEVICE: + case DMA_MEM_TO_DEV: ctllo = (DWC_DEFAULT_CTLLO(chan->private) | DWC_CTLL_DST_WIDTH(reg_width) | DWC_CTLL_DST_FIX @@ -777,7 +777,7 @@ slave_sg_todev_fill_desc: goto slave_sg_todev_fill_desc; } break; - case DMA_FROM_DEVICE: + case DMA_DEV_TO_MEM: ctllo = (DWC_DEFAULT_CTLLO(chan->private) | DWC_CTLL_SRC_WIDTH(reg_width) | DWC_CTLL_DST_INC @@ -1165,7 +1165,7 @@ EXPORT_SYMBOL(dw_dma_cyclic_stop); */ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, - enum dma_data_direction direction) + enum dma_transfer_direction direction) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); struct dw_cyclic_desc *cdesc; @@ -1206,7 +1206,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, goto out_err; if (unlikely(buf_addr & ((1 << reg_width) - 1))) goto out_err; - if (unlikely(!(direction & (DMA_TO_DEVICE | DMA_FROM_DEVICE)))) + if (unlikely(!(direction & (DMA_MEM_TO_DEV | DMA_DEV_TO_MEM)))) goto out_err; retval = ERR_PTR(-ENOMEM); @@ -1228,7 +1228,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, goto out_err_desc_get; switch (direction) { - case DMA_TO_DEVICE: + case DMA_MEM_TO_DEV: desc->lli.dar = dws->tx_reg; desc->lli.sar = buf_addr + (period_len * i); desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private) @@ -1239,7 +1239,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, | DWC_CTLL_FC(dws->fc) | DWC_CTLL_INT_EN); break; - case DMA_FROM_DEVICE: + case DMA_DEV_TO_MEM: desc->lli.dar = buf_addr + (period_len * i); desc->lli.sar = dws->rx_reg; desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private) diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index b47e2b8..009851b 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c @@ -330,7 +330,7 @@ static void m2p_fill_desc(struct ep93xx_dma_chan *edmac) struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac); u32 bus_addr; - if (ep93xx_dma_chan_direction(&edmac->chan) == DMA_TO_DEVICE) + if (ep93xx_dma_chan_direction(&edmac->chan) == DMA_MEM_TO_DEV) bus_addr = desc->src_addr; else bus_addr = desc->dst_addr; @@ -443,7 +443,7 @@ static int m2m_hw_setup(struct ep93xx_dma_chan *edmac) control = (5 << M2M_CONTROL_PWSC_SHIFT); control |= M2M_CONTROL_NO_HDSK; - if (data->direction == DMA_TO_DEVICE) { + if (data->direction == DMA_MEM_TO_DEV) { control |= M2M_CONTROL_DAH; control |= M2M_CONTROL_TM_TX; control |= M2M_CONTROL_RSS_SSPTX; @@ -463,7 +463,7 @@ static int m2m_hw_setup(struct ep93xx_dma_chan *edmac) control |= M2M_CONTROL_RSS_IDE; control |= M2M_CONTROL_PW_16; - if (data->direction == DMA_TO_DEVICE) { + if (data->direction == DMA_MEM_TO_DEV) { /* Worst case from the UG */ control = (3 << M2M_CONTROL_PWSC_SHIFT); control |= M2M_CONTROL_DAH; @@ -803,8 +803,8 @@ static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan) switch (data->port) { case EP93XX_DMA_SSP: case EP93XX_DMA_IDE: - if (data->direction != DMA_TO_DEVICE && - data->direction != DMA_FROM_DEVICE) + if (data->direction != DMA_MEM_TO_DEV && + data->direction != DMA_DEV_TO_MEM) return -EINVAL; break; default: @@ -952,7 +952,7 @@ fail: */ static struct dma_async_tx_descriptor * ep93xx_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction dir, + unsigned int sg_len, enum dma_transfer_direction dir, unsigned long flags) { struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan); @@ -988,7 +988,7 @@ ep93xx_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, goto fail; } - if (dir == DMA_TO_DEVICE) { + if (dir == DMA_MEM_TO_DEV) { desc->src_addr = sg_dma_address(sg); desc->dst_addr = edmac->runtime_addr; } else { @@ -1032,7 +1032,7 @@ fail: static struct dma_async_tx_descriptor * ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, size_t period_len, - enum dma_data_direction dir) + enum dma_transfer_direction dir) { struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan); struct ep93xx_dma_desc *desc, *first; @@ -1065,7 +1065,7 @@ ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr, goto fail; } - if (dir == DMA_TO_DEVICE) { + if (dir == DMA_MEM_TO_DEV) { desc->src_addr = dma_addr + offset; desc->dst_addr = edmac->runtime_addr; } else { @@ -1133,12 +1133,12 @@ static int ep93xx_dma_slave_config(struct ep93xx_dma_chan *edmac, return -EINVAL; switch (config->direction) { - case DMA_FROM_DEVICE: + case DMA_DEV_TO_MEM: width = config->src_addr_width; addr = config->src_addr; break; - case DMA_TO_DEVICE: + case DMA_MEM_TO_DEV: width = config->dst_addr_width; addr = config->dst_addr; break; diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 8a78154..b98070c 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -772,7 +772,7 @@ fail: */ static struct dma_async_tx_descriptor *fsl_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) { /* * This operation is not supported on the Freescale DMA controller @@ -819,7 +819,7 @@ static int fsl_dma_device_control(struct dma_chan *dchan, return -ENXIO; /* we set the controller burst size depending on direction */ - if (config->direction == DMA_TO_DEVICE) + if (config->direction == DMA_MEM_TO_DEV) size = config->dst_addr_width * config->dst_maxburst; else size = config->src_addr_width * config->src_maxburst; diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index d746899..678cd01 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -106,7 +106,7 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, imx_dma_disable(imxdmac->imxdma_channel); return 0; case DMA_SLAVE_CONFIG: - if (dmaengine_cfg->direction == DMA_FROM_DEVICE) { + if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) { imxdmac->per_address = dmaengine_cfg->src_addr; imxdmac->watermark_level = dmaengine_cfg->src_maxburst; imxdmac->word_size = dmaengine_cfg->src_addr_width; @@ -223,7 +223,7 @@ static void imxdma_free_chan_resources(struct dma_chan *chan) static struct dma_async_tx_descriptor *imxdma_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags) { struct imxdma_channel *imxdmac = to_imxdma_chan(chan); @@ -240,7 +240,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_slave_sg( dma_length += sg->length; } - if (direction == DMA_FROM_DEVICE) + if (direction == DMA_DEV_TO_MEM) dmamode = DMA_MODE_READ; else dmamode = DMA_MODE_WRITE; @@ -270,7 +270,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_slave_sg( static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, - size_t period_len, enum dma_data_direction direction) + size_t period_len, enum dma_transfer_direction direction) { struct imxdma_channel *imxdmac = to_imxdma_chan(chan); struct imxdma_engine *imxdma = imxdmac->imxdma; @@ -316,7 +316,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic( imxdmac->sg_list[periods].page_link = ((unsigned long)imxdmac->sg_list | 0x01) & ~0x02; - if (direction == DMA_FROM_DEVICE) + if (direction == DMA_DEV_TO_MEM) dmamode = DMA_MODE_READ; else dmamode = DMA_MODE_WRITE; diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index eab1fe7..065de54 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -246,7 +246,7 @@ struct sdma_engine; struct sdma_channel { struct sdma_engine *sdma; unsigned int channel; - enum dma_data_direction direction; + enum dma_transfer_direction direction; enum sdma_peripheral_type peripheral_type; unsigned int event_id0; unsigned int event_id1; @@ -649,7 +649,7 @@ static int sdma_load_context(struct sdma_channel *sdmac) struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd; int ret; - if (sdmac->direction == DMA_FROM_DEVICE) { + if (sdmac->direction == DMA_DEV_TO_MEM) { load_address = sdmac->pc_from_device; } else { load_address = sdmac->pc_to_device; @@ -910,7 +910,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan) static struct dma_async_tx_descriptor *sdma_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags) { struct sdma_channel *sdmac = to_sdma_chan(chan); @@ -1007,7 +1007,7 @@ err_out: static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, - size_t period_len, enum dma_data_direction direction) + size_t period_len, enum dma_transfer_direction direction) { struct sdma_channel *sdmac = to_sdma_chan(chan); struct sdma_engine *sdma = sdmac->sdma; @@ -1092,7 +1092,7 @@ static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, sdma_disable_channel(sdmac); return 0; case DMA_SLAVE_CONFIG: - if (dmaengine_cfg->direction == DMA_FROM_DEVICE) { + if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) { sdmac->per_address = dmaengine_cfg->src_addr; sdmac->watermark_level = dmaengine_cfg->src_maxburst; sdmac->word_size = dmaengine_cfg->src_addr_width; diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c index 9e96c43..6deda25 100644 --- a/drivers/dma/intel_mid_dma.c +++ b/drivers/dma/intel_mid_dma.c @@ -394,10 +394,10 @@ static int midc_lli_fill_sg(struct intel_mid_dma_chan *midc, midc->dma->block_size); /*Populate SAR and DAR values*/ sg_phy_addr = sg_phys(sg); - if (desc->dirn == DMA_TO_DEVICE) { + if (desc->dirn == DMA_MEM_TO_DEV) { lli_bloc_desc->sar = sg_phy_addr; lli_bloc_desc->dar = mids->dma_slave.dst_addr; - } else if (desc->dirn == DMA_FROM_DEVICE) { + } else if (desc->dirn == DMA_DEV_TO_MEM) { lli_bloc_desc->sar = mids->dma_slave.src_addr; lli_bloc_desc->dar = sg_phy_addr; } @@ -631,13 +631,13 @@ static struct dma_async_tx_descriptor *intel_mid_dma_prep_memcpy( if (midc->dma->pimr_mask) { cfg_hi.cfgx.protctl = 0x0; /*default value*/ cfg_hi.cfgx.fifo_mode = 1; - if (mids->dma_slave.direction == DMA_TO_DEVICE) { + if (mids->dma_slave.direction == DMA_MEM_TO_DEV) { cfg_hi.cfgx.src_per = 0; if (mids->device_instance == 0) cfg_hi.cfgx.dst_per = 3; if (mids->device_instance == 1) cfg_hi.cfgx.dst_per = 1; - } else if (mids->dma_slave.direction == DMA_FROM_DEVICE) { + } else if (mids->dma_slave.direction == DMA_DEV_TO_MEM) { if (mids->device_instance == 0) cfg_hi.cfgx.src_per = 2; if (mids->device_instance == 1) @@ -681,11 +681,11 @@ static struct dma_async_tx_descriptor *intel_mid_dma_prep_memcpy( ctl_lo.ctlx.sinc = 0; ctl_lo.ctlx.dinc = 0; } else { - if (mids->dma_slave.direction == DMA_TO_DEVICE) { + if (mids->dma_slave.direction == DMA_MEM_TO_DEV) { ctl_lo.ctlx.sinc = 0; ctl_lo.ctlx.dinc = 2; ctl_lo.ctlx.tt_fc = 1; - } else if (mids->dma_slave.direction == DMA_FROM_DEVICE) { + } else if (mids->dma_slave.direction == DMA_DEV_TO_MEM) { ctl_lo.ctlx.sinc = 2; ctl_lo.ctlx.dinc = 0; ctl_lo.ctlx.tt_fc = 2; @@ -731,7 +731,7 @@ err_desc_get: */ static struct dma_async_tx_descriptor *intel_mid_dma_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags) { struct intel_mid_dma_chan *midc = NULL; diff --git a/drivers/dma/intel_mid_dma_regs.h b/drivers/dma/intel_mid_dma_regs.h index aea5ee8..c6de919 100644 --- a/drivers/dma/intel_mid_dma_regs.h +++ b/drivers/dma/intel_mid_dma_regs.h @@ -262,7 +262,7 @@ struct intel_mid_dma_desc { unsigned int lli_length; unsigned int current_lli; dma_addr_t next; - enum dma_data_direction dirn; + enum dma_transfer_direction dirn; enum dma_status status; enum dma_slave_buswidth width; /*width of DMA txn*/ enum intel_mid_dma_mode cfg_mode; /*mode configuration*/ diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index 6815905..0cee3b3 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c @@ -1362,7 +1362,7 @@ static void ipu_gc_tasklet(unsigned long arg) /* Allocate and initialise a transfer descriptor. */ static struct dma_async_tx_descriptor *idmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_data_direction direction, unsigned long tx_flags) + enum dma_transfer_direction direction, unsigned long tx_flags) { struct idmac_channel *ichan = to_idmac_chan(chan); struct idmac_tx_desc *desc = NULL; @@ -1374,7 +1374,7 @@ static struct dma_async_tx_descriptor *idmac_prep_slave_sg(struct dma_chan *chan chan->chan_id != IDMAC_IC_7) return NULL; - if (direction != DMA_FROM_DEVICE && direction != DMA_TO_DEVICE) { + if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) { dev_err(chan->device->dev, "Invalid DMA direction %d!\n", direction); return NULL; } diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index b4588bd..bdf4672 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -377,7 +377,7 @@ static void mxs_dma_free_chan_resources(struct dma_chan *chan) static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long append) { struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); @@ -450,7 +450,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( ccw->bits |= CCW_CHAIN; ccw->bits |= CCW_HALT_ON_TERM; ccw->bits |= CCW_TERM_FLUSH; - ccw->bits |= BF_CCW(direction == DMA_FROM_DEVICE ? + ccw->bits |= BF_CCW(direction == DMA_DEV_TO_MEM ? MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ, COMMAND); @@ -472,7 +472,7 @@ err_out: static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, - size_t period_len, enum dma_data_direction direction) + size_t period_len, enum dma_transfer_direction direction) { struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; @@ -515,7 +515,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic( ccw->bits |= CCW_IRQ; ccw->bits |= CCW_HALT_ON_TERM; ccw->bits |= CCW_TERM_FLUSH; - ccw->bits |= BF_CCW(direction == DMA_FROM_DEVICE ? + ccw->bits |= BF_CCW(direction == DMA_DEV_TO_MEM ? MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ, COMMAND); dma_addr += period_len; diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c index a6d0e3d..9944e82 100644 --- a/drivers/dma/pch_dma.c +++ b/drivers/dma/pch_dma.c @@ -99,7 +99,7 @@ struct pch_dma_desc { struct pch_dma_chan { struct dma_chan chan; void __iomem *membase; - enum dma_data_direction dir; + enum dma_transfer_direction dir; struct tasklet_struct tasklet; unsigned long err_status; @@ -224,7 +224,7 @@ static void pdc_set_dir(struct dma_chan *chan) mask_ctl = DMA_MASK_CTL0_MODE & ~(DMA_CTL0_MODE_MASK_BITS << (DMA_CTL0_BITS_PER_CH * chan->chan_id)); val &= mask_mode; - if (pd_chan->dir == DMA_TO_DEVICE) + if (pd_chan->dir == DMA_MEM_TO_DEV) val |= 0x1 << (DMA_CTL0_BITS_PER_CH * chan->chan_id + DMA_CTL0_DIR_SHIFT_BITS); else @@ -242,7 +242,7 @@ static void pdc_set_dir(struct dma_chan *chan) mask_ctl = DMA_MASK_CTL2_MODE & ~(DMA_CTL0_MODE_MASK_BITS << (DMA_CTL0_BITS_PER_CH * ch)); val &= mask_mode; - if (pd_chan->dir == DMA_TO_DEVICE) + if (pd_chan->dir == DMA_MEM_TO_DEV) val |= 0x1 << (DMA_CTL0_BITS_PER_CH * ch + DMA_CTL0_DIR_SHIFT_BITS); else @@ -607,7 +607,7 @@ static void pd_issue_pending(struct dma_chan *chan) static struct dma_async_tx_descriptor *pd_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_data_direction direction, unsigned long flags) + enum dma_transfer_direction direction, unsigned long flags) { struct pch_dma_chan *pd_chan = to_pd_chan(chan); struct pch_dma_slave *pd_slave = chan->private; @@ -623,9 +623,9 @@ static struct dma_async_tx_descriptor *pd_prep_slave_sg(struct dma_chan *chan, return NULL; } - if (direction == DMA_FROM_DEVICE) + if (direction == DMA_DEV_TO_MEM) reg = pd_slave->rx_reg; - else if (direction == DMA_TO_DEVICE) + else if (direction == DMA_MEM_TO_DEV) reg = pd_slave->tx_reg; else return NULL; diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 57104147..1e58eeb 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -320,14 +320,14 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned case DMA_SLAVE_CONFIG: slave_config = (struct dma_slave_config *)arg; - if (slave_config->direction == DMA_TO_DEVICE) { + if (slave_config->direction == DMA_MEM_TO_DEV) { if (slave_config->dst_addr) pch->fifo_addr = slave_config->dst_addr; if (slave_config->dst_addr_width) pch->burst_sz = __ffs(slave_config->dst_addr_width); if (slave_config->dst_maxburst) pch->burst_len = slave_config->dst_maxburst; - } else if (slave_config->direction == DMA_FROM_DEVICE) { + } else if (slave_config->direction == DMA_DEV_TO_MEM) { if (slave_config->src_addr) pch->fifo_addr = slave_config->src_addr; if (slave_config->src_addr_width) @@ -597,7 +597,7 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( struct dma_chan *chan, dma_addr_t dma_addr, size_t len, - size_t period_len, enum dma_data_direction direction) + size_t period_len, enum dma_transfer_direction direction) { struct dma_pl330_desc *desc; struct dma_pl330_chan *pch = to_pchan(chan); @@ -612,13 +612,13 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( } switch (direction) { - case DMA_TO_DEVICE: + case DMA_MEM_TO_DEV: desc->rqcfg.src_inc = 1; desc->rqcfg.dst_inc = 0; src = dma_addr; dst = pch->fifo_addr; break; - case DMA_FROM_DEVICE: + case DMA_DEV_TO_MEM: desc->rqcfg.src_inc = 0; desc->rqcfg.dst_inc = 1; src = pch->fifo_addr; @@ -687,7 +687,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst, static struct dma_async_tx_descriptor * pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flg) { struct dma_pl330_desc *first, *desc = NULL; @@ -702,9 +702,9 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, return NULL; /* Make sure the direction is consistent */ - if ((direction == DMA_TO_DEVICE && + if ((direction == DMA_MEM_TO_DEV && peri->rqtype != MEMTODEV) || - (direction == DMA_FROM_DEVICE && + (direction == DMA_DEV_TO_MEM && peri->rqtype != DEVTOMEM)) { dev_err(pch->dmac->pif.dev, "%s:%d Invalid Direction\n", __func__, __LINE__); @@ -747,7 +747,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, else list_add_tail(&desc->node, &first->node); - if (direction == DMA_TO_DEVICE) { + if (direction == DMA_MEM_TO_DEV) { desc->rqcfg.src_inc = 1; desc->rqcfg.dst_inc = 0; fill_px(&desc->px, diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 81809c2..592304f 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -479,19 +478,19 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan) * @sh_chan: DMA channel * @flags: DMA transfer flags * @dest: destination DMA address, incremented when direction equals - * DMA_FROM_DEVICE or DMA_BIDIRECTIONAL + * DMA_DEV_TO_MEM * @src: source DMA address, incremented when direction equals - * DMA_TO_DEVICE or DMA_BIDIRECTIONAL + * DMA_MEM_TO_DEV * @len: DMA transfer length * @first: if NULL, set to the current descriptor and cookie set to -EBUSY * @direction: needed for slave DMA to decide which address to keep constant, - * equals DMA_BIDIRECTIONAL for MEMCPY + * equals DMA_MEM_TO_MEM for MEMCPY * Returns 0 or an error * Locks: called with desc_lock held */ static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan, unsigned long flags, dma_addr_t *dest, dma_addr_t *src, size_t *len, - struct sh_desc **first, enum dma_data_direction direction) + struct sh_desc **first, enum dma_transfer_direction direction) { struct sh_desc *new; size_t copy_size; @@ -531,9 +530,9 @@ static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan, new->direction = direction; *len -= copy_size; - if (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE) + if (direction == DMA_MEM_TO_MEM || direction == DMA_MEM_TO_DEV) *src += copy_size; - if (direction == DMA_BIDIRECTIONAL || direction == DMA_FROM_DEVICE) + if (direction == DMA_MEM_TO_MEM || direction == DMA_DEV_TO_MEM) *dest += copy_size; return new; @@ -546,12 +545,12 @@ static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan, * converted to scatter-gather to guarantee consistent locking and a correct * list manipulation. For slave DMA direction carries the usual meaning, and, * logically, the SG list is RAM and the addr variable contains slave address, - * e.g., the FIFO I/O register. For MEMCPY direction equals DMA_BIDIRECTIONAL + * e.g., the FIFO I/O register. For MEMCPY direction equals DMA_MEM_TO_MEM * and the SG list contains only one element and points at the source buffer. */ static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_chan, struct scatterlist *sgl, unsigned int sg_len, dma_addr_t *addr, - enum dma_data_direction direction, unsigned long flags) + enum dma_transfer_direction direction, unsigned long flags) { struct scatterlist *sg; struct sh_desc *first = NULL, *new = NULL /* compiler... */; @@ -592,7 +591,7 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_c dev_dbg(sh_chan->dev, "Add SG #%d@%p[%d], dma %llx\n", i, sg, len, (unsigned long long)sg_addr); - if (direction == DMA_FROM_DEVICE) + if (direction == DMA_DEV_TO_MEM) new = sh_dmae_add_desc(sh_chan, flags, &sg_addr, addr, &len, &first, direction); @@ -646,13 +645,13 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy( sg_dma_address(&sg) = dma_src; sg_dma_len(&sg) = len; - return sh_dmae_prep_sg(sh_chan, &sg, 1, &dma_dest, DMA_BIDIRECTIONAL, + return sh_dmae_prep_sg(sh_chan, &sg, 1, &dma_dest, DMA_MEM_TO_MEM, flags); } static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_data_direction direction, unsigned long flags) + enum dma_transfer_direction direction, unsigned long flags) { struct sh_dmae_slave *param; struct sh_dmae_chan *sh_chan; @@ -996,7 +995,7 @@ static void dmae_do_tasklet(unsigned long data) spin_lock_irq(&sh_chan->desc_lock); list_for_each_entry(desc, &sh_chan->ld_queue, node) { if (desc->mark == DESC_SUBMITTED && - ((desc->direction == DMA_FROM_DEVICE && + ((desc->direction == DMA_DEV_TO_MEM && (desc->hw.dar + desc->hw.tcr) == dar_buf) || (desc->hw.sar + desc->hw.tcr) == sar_buf)) { dev_dbg(sh_chan->dev, "done #%d@%p dst %u\n", diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 467e4dc..0c6cbac 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -216,7 +216,7 @@ struct d40_chan { struct d40_log_lli_full *lcpa; /* Runtime reconfiguration */ dma_addr_t runtime_addr; - enum dma_data_direction runtime_direction; + enum dma_transfer_direction runtime_direction; }; /** @@ -1854,7 +1854,7 @@ err: } static dma_addr_t -d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction) +d40_get_dev_addr(struct d40_chan *chan, enum dma_transfer_direction direction) { struct stedma40_platform_data *plat = chan->base->plat_data; struct stedma40_chan_cfg *cfg = &chan->dma_cfg; @@ -1863,9 +1863,9 @@ d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction) if (chan->runtime_addr) return chan->runtime_addr; - if (direction == DMA_FROM_DEVICE) + if (direction == DMA_DEV_TO_MEM) addr = plat->dev_rx[cfg->src_dev_type]; - else if (direction == DMA_TO_DEVICE) + else if (direction == DMA_MEM_TO_DEV) addr = plat->dev_tx[cfg->dst_dev_type]; return addr; @@ -1874,7 +1874,7 @@ d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction) static struct dma_async_tx_descriptor * d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src, struct scatterlist *sg_dst, unsigned int sg_len, - enum dma_data_direction direction, unsigned long dma_flags) + enum dma_transfer_direction direction, unsigned long dma_flags) { struct d40_chan *chan = container_of(dchan, struct d40_chan, chan); dma_addr_t src_dev_addr = 0; @@ -1901,9 +1901,9 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src, if (direction != DMA_NONE) { dma_addr_t dev_addr = d40_get_dev_addr(chan, direction); - if (direction == DMA_FROM_DEVICE) + if (direction == DMA_DEV_TO_MEM) src_dev_addr = dev_addr; - else if (direction == DMA_TO_DEVICE) + else if (direction == DMA_MEM_TO_DEV) dst_dev_addr = dev_addr; } @@ -2107,10 +2107,10 @@ d40_prep_memcpy_sg(struct dma_chan *chan, static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_data_direction direction, + enum dma_transfer_direction direction, unsigned long dma_flags) { - if (direction != DMA_FROM_DEVICE && direction != DMA_TO_DEVICE) + if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) return NULL; return d40_prep_sg(chan, sgl, sgl, sg_len, direction, dma_flags); @@ -2119,7 +2119,7 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, static struct dma_async_tx_descriptor * dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, size_t period_len, - enum dma_data_direction direction) + enum dma_transfer_direction direction) { unsigned int periods = buf_len / period_len; struct dma_async_tx_descriptor *txd; @@ -2268,7 +2268,7 @@ static int d40_set_runtime_config(struct dma_chan *chan, dst_addr_width = config->dst_addr_width; dst_maxburst = config->dst_maxburst; - if (config->direction == DMA_FROM_DEVICE) { + if (config->direction == DMA_DEV_TO_MEM) { dma_addr_t dev_addr_rx = d40c->base->plat_data->dev_rx[cfg->src_dev_type]; @@ -2291,7 +2291,7 @@ static int d40_set_runtime_config(struct dma_chan *chan, if (dst_maxburst == 0) dst_maxburst = src_maxburst; - } else if (config->direction == DMA_TO_DEVICE) { + } else if (config->direction == DMA_MEM_TO_DEV) { dma_addr_t dev_addr_tx = d40c->base->plat_data->dev_tx[cfg->dst_dev_type]; @@ -2356,7 +2356,7 @@ static int d40_set_runtime_config(struct dma_chan *chan, "configured channel %s for %s, data width %d/%d, " "maxburst %d/%d elements, LE, no flow control\n", dma_chan_name(chan), - (config->direction == DMA_FROM_DEVICE) ? "RX" : "TX", + (config->direction == DMA_DEV_TO_MEM) ? "RX" : "TX", src_addr_width, dst_addr_width, src_maxburst, dst_maxburst); diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c index a4a398f..8c88072 100644 --- a/drivers/dma/timb_dma.c +++ b/drivers/dma/timb_dma.c @@ -90,7 +90,7 @@ struct timb_dma_chan { struct list_head queue; struct list_head free_list; unsigned int bytes_per_line; - enum dma_data_direction direction; + enum dma_transfer_direction direction; unsigned int descs; /* Descriptors to allocate */ unsigned int desc_elems; /* number of elems per descriptor */ }; @@ -235,7 +235,7 @@ static void __td_start_dma(struct timb_dma_chan *td_chan) "td_chan: %p, chan: %d, membase: %p\n", td_chan, td_chan->chan.chan_id, td_chan->membase); - if (td_chan->direction == DMA_FROM_DEVICE) { + if (td_chan->direction == DMA_DEV_TO_MEM) { /* descriptor address */ iowrite32(0, td_chan->membase + TIMBDMA_OFFS_RX_DHAR); @@ -278,7 +278,7 @@ static void __td_finish(struct timb_dma_chan *td_chan) txd->cookie); /* make sure to stop the transfer */ - if (td_chan->direction == DMA_FROM_DEVICE) + if (td_chan->direction == DMA_DEV_TO_MEM) iowrite32(0, td_chan->membase + TIMBDMA_OFFS_RX_ER); /* Currently no support for stopping DMA transfers else @@ -398,7 +398,7 @@ static struct timb_dma_desc *td_alloc_init_desc(struct timb_dma_chan *td_chan) td_desc->txd.flags = DMA_CTRL_ACK; td_desc->txd.phys = dma_map_single(chan2dmadev(chan), - td_desc->desc_list, td_desc->desc_list_len, DMA_TO_DEVICE); + td_desc->desc_list, td_desc->desc_list_len, DMA_MEM_TO_DEV); err = dma_mapping_error(chan2dmadev(chan), td_desc->txd.phys); if (err) { @@ -419,7 +419,7 @@ static void td_free_desc(struct timb_dma_desc *td_desc) { dev_dbg(chan2dev(td_desc->txd.chan), "Freeing desc: %p\n", td_desc); dma_unmap_single(chan2dmadev(td_desc->txd.chan), td_desc->txd.phys, - td_desc->desc_list_len, DMA_TO_DEVICE); + td_desc->desc_list_len, DMA_MEM_TO_DEV); kfree(td_desc->desc_list); kfree(td_desc); @@ -558,7 +558,7 @@ static void td_issue_pending(struct dma_chan *chan) static struct dma_async_tx_descriptor *td_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_data_direction direction, unsigned long flags) + enum dma_transfer_direction direction, unsigned long flags) { struct timb_dma_chan *td_chan = container_of(chan, struct timb_dma_chan, chan); @@ -606,7 +606,7 @@ static struct dma_async_tx_descriptor *td_prep_slave_sg(struct dma_chan *chan, } dma_sync_single_for_device(chan2dmadev(chan), td_desc->txd.phys, - td_desc->desc_list_len, DMA_TO_DEVICE); + td_desc->desc_list_len, DMA_MEM_TO_DEV); return &td_desc->txd; } @@ -775,8 +775,8 @@ static int __devinit td_probe(struct platform_device *pdev) td_chan->descs = pchan->descriptors; td_chan->desc_elems = pchan->descriptor_elements; td_chan->bytes_per_line = pchan->bytes_per_line; - td_chan->direction = pchan->rx ? DMA_FROM_DEVICE : - DMA_TO_DEVICE; + td_chan->direction = pchan->rx ? DMA_DEV_TO_MEM : + DMA_MEM_TO_DEV; td_chan->membase = td->membase + (i / 2) * TIMBDMA_INSTANCE_OFFSET + diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c index cbd83e36..6122c36 100644 --- a/drivers/dma/txx9dmac.c +++ b/drivers/dma/txx9dmac.c @@ -845,7 +845,7 @@ txx9dmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, static struct dma_async_tx_descriptor * txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, - unsigned int sg_len, enum dma_data_direction direction, + unsigned int sg_len, enum dma_transfer_direction direction, unsigned long flags) { struct txx9dmac_chan *dc = to_txx9dmac_chan(chan); @@ -860,9 +860,9 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, BUG_ON(!ds || !ds->reg_width); if (ds->tx_reg) - BUG_ON(direction != DMA_TO_DEVICE); + BUG_ON(direction != DMA_MEM_TO_DEV); else - BUG_ON(direction != DMA_FROM_DEVICE); + BUG_ON(direction != DMA_DEV_TO_MEM); if (unlikely(!sg_len)) return NULL; @@ -882,7 +882,7 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, mem = sg_dma_address(sg); if (__is_dmac64(ddev)) { - if (direction == DMA_TO_DEVICE) { + if (direction == DMA_MEM_TO_DEV) { desc->hwdesc.SAR = mem; desc->hwdesc.DAR = ds->tx_reg; } else { @@ -891,7 +891,7 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, } desc->hwdesc.CNTR = sg_dma_len(sg); } else { - if (direction == DMA_TO_DEVICE) { + if (direction == DMA_MEM_TO_DEV) { desc->hwdesc32.SAR = mem; desc->hwdesc32.DAR = ds->tx_reg; } else { @@ -900,7 +900,7 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, } desc->hwdesc32.CNTR = sg_dma_len(sg); } - if (direction == DMA_TO_DEVICE) { + if (direction == DMA_MEM_TO_DEV) { sai = ds->reg_width; dai = 0; } else { diff --git a/include/linux/amba/pl08x.h b/include/linux/amba/pl08x.h index 9eabffb..033f6aa 100644 --- a/include/linux/amba/pl08x.h +++ b/include/linux/amba/pl08x.h @@ -134,7 +134,7 @@ struct pl08x_txd { struct dma_async_tx_descriptor tx; struct list_head node; struct list_head dsg_list; - enum dma_data_direction direction; + enum dma_transfer_direction direction; dma_addr_t llis_bus; struct pl08x_lli *llis_va; /* Default cctl value for LLIs */ @@ -197,7 +197,7 @@ struct pl08x_dma_chan { dma_addr_t dst_addr; u32 src_cctl; u32 dst_cctl; - enum dma_data_direction runtime_direction; + enum dma_transfer_direction runtime_direction; dma_cookie_t lc; struct list_head pend_list; struct pl08x_txd *at; diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h index 4bfe0a2..f2c64f9 100644 --- a/include/linux/dw_dmac.h +++ b/include/linux/dw_dmac.h @@ -127,7 +127,7 @@ struct dw_cyclic_desc { struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, - enum dma_data_direction direction); + enum dma_transfer_direction direction); void dw_dma_cyclic_free(struct dma_chan *chan); int dw_dma_cyclic_start(struct dma_chan *chan); void dw_dma_cyclic_stop(struct dma_chan *chan); diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h index cb2dd11..62ef693 100644 --- a/include/linux/sh_dma.h +++ b/include/linux/sh_dma.h @@ -30,7 +30,7 @@ struct sh_desc { struct sh_dmae_regs hw; struct list_head node; struct dma_async_tx_descriptor async_tx; - enum dma_data_direction direction; + enum dma_transfer_direction direction; dma_cookie_t cookie; size_t partial; int chunks; -- cgit v0.10.2 From 20dd5a356efcb5bf574baa9adccc775158f13ae1 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 10:35:16 +0530 Subject: plat-samsung: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves samsung drivers to use new enum Cc: Ben Dooks Cc: Kukjin Kim Cc: Boojin Kim Acked-by: Kukjin Kim Signed-off-by: Vinod Koul diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c index 6e3d9ab..3df0bad 100644 --- a/arch/arm/plat-samsung/dma-ops.c +++ b/arch/arm/plat-samsung/dma-ops.c @@ -35,14 +35,14 @@ static unsigned samsung_dmadev_request(enum dma_ch dma_ch, chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch); - if (info->direction == DMA_FROM_DEVICE) { + if (info->direction == DMA_DEV_TO_MEM) { memset(&slave_config, 0, sizeof(struct dma_slave_config)); slave_config.direction = info->direction; slave_config.src_addr = info->fifo; slave_config.src_addr_width = info->width; slave_config.src_maxburst = 1; dmaengine_slave_config(chan, &slave_config); - } else if (info->direction == DMA_TO_DEVICE) { + } else if (info->direction == DMA_MEM_TO_DEV) { memset(&slave_config, 0, sizeof(struct dma_slave_config)); slave_config.direction = info->direction; slave_config.dst_addr = info->fifo; diff --git a/arch/arm/plat-samsung/include/plat/dma-ops.h b/arch/arm/plat-samsung/include/plat/dma-ops.h index 4c1a363..1256115 100644 --- a/arch/arm/plat-samsung/include/plat/dma-ops.h +++ b/arch/arm/plat-samsung/include/plat/dma-ops.h @@ -17,7 +17,7 @@ struct samsung_dma_prep_info { enum dma_transaction_type cap; - enum dma_data_direction direction; + enum dma_transfer_direction direction; dma_addr_t buf; unsigned long period; unsigned long len; @@ -27,7 +27,7 @@ struct samsung_dma_prep_info { struct samsung_dma_info { enum dma_transaction_type cap; - enum dma_data_direction direction; + enum dma_transfer_direction direction; enum dma_slave_buswidth width; dma_addr_t fifo; struct s3c2410_dma_client *client; -- cgit v0.10.2 From 1003cab8276cd34d9deab8ca9d148ee59f7728a7 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 10:39:23 +0530 Subject: media, video: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves media and video drivers to use new enum Cc: Mauro Carvalho Chehab Cc: Paul Mundt Cc: Guennadi Liakhovetski Acked-by: Guennadi Liakhovetski Acked-by: Guennadi Liakhovetski Signed-off-by: Vinod Koul diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index c045b47..ec98eae 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c @@ -251,7 +251,7 @@ static int mx3_videobuf_prepare(struct vb2_buffer *vb) sg_dma_len(sg) = new_size; buf->txd = ichan->dma_chan.device->device_prep_slave_sg( - &ichan->dma_chan, sg, 1, DMA_FROM_DEVICE, + &ichan->dma_chan, sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); if (!buf->txd) return -EIO; diff --git a/drivers/media/video/timblogiw.c b/drivers/media/video/timblogiw.c index 84cd1b6..d542c8b 100644 --- a/drivers/media/video/timblogiw.c +++ b/drivers/media/video/timblogiw.c @@ -564,7 +564,7 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) spin_unlock_irq(&fh->queue_lock); desc = fh->chan->device->device_prep_slave_sg(fh->chan, - buf->sg, sg_elems, DMA_FROM_DEVICE, + buf->sg, sg_elems, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); if (!desc) { spin_lock_irq(&fh->queue_lock); diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 7e3a490..e2caf88 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -334,7 +334,7 @@ static void sdc_enable_channel(struct mx3fb_info *mx3_fbi) /* This enables the channel */ if (mx3_fbi->cookie < 0) { mx3_fbi->txd = dma_chan->device->device_prep_slave_sg(dma_chan, - &mx3_fbi->sg[0], 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT); + &mx3_fbi->sg[0], 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); if (!mx3_fbi->txd) { dev_err(mx3fb->dev, "Cannot allocate descriptor on %d\n", dma_chan->chan_id); @@ -1104,7 +1104,7 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var, async_tx_ack(mx3_fbi->txd); txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg + - mx3_fbi->cur_ipu_buf, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT); + mx3_fbi->cur_ipu_buf, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); if (!txd) { dev_err(fbi->device, "Error preparing a DMA transaction descriptor.\n"); -- cgit v0.10.2 From 1d0c81e876fe04295ef5df387ba057bf9cfae3d8 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 10:42:56 +0530 Subject: carma: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves carma drivers to use new enum Signed-off-by: Vinod Koul CC Ira W. Snyder diff --git a/drivers/misc/carma/carma-fpga-program.c b/drivers/misc/carma/carma-fpga-program.c index 7ce6065..20ef1ea 100644 --- a/drivers/misc/carma/carma-fpga-program.c +++ b/drivers/misc/carma/carma-fpga-program.c @@ -513,7 +513,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv) * transaction, and then put it under external control */ memset(&config, 0, sizeof(config)); - config.direction = DMA_TO_DEVICE; + config.direction = DMA_MEM_TO_DEV; config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; config.dst_maxburst = fpga_fifo_size(priv->regs) / 2 / 4; ret = chan->device->device_control(chan, DMA_SLAVE_CONFIG, -- cgit v0.10.2 From 05f5799cbe5c9e2c03f604b3de5783cf4d726227 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 10:45:11 +0530 Subject: mmc-host: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves mmc drivers to use new enum Cc: Nicolas Ferre Cc: Chris Ball Cc: Guennadi Liakhovetski Acked-by: Nicolas Ferre Acked-by: Guennadi Liakhovetski Signed-off-by: Vinod Koul diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index fa8cae1..ac87803 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -653,6 +653,7 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) struct scatterlist *sg; unsigned int i; enum dma_data_direction direction; + enum dma_transfer_direction slave_dirn; unsigned int sglen; /* @@ -681,16 +682,19 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) if (atmci_is_mci2()) mci_writel(host, DMA, MCI_DMA_CHKSIZE(3) | MCI_DMAEN); - if (data->flags & MMC_DATA_READ) + if (data->flags & MMC_DATA_READ) { direction = DMA_FROM_DEVICE; - else + slave_dirn = DMA_DEV_TO_MEM; + } else { direction = DMA_TO_DEVICE; + slave_dirn = DMA_MEM_TO_DEV; + } sglen = dma_map_sg(chan->device->dev, data->sg, data->sg_len, direction); desc = chan->device->device_prep_slave_sg(chan, - data->sg, sglen, direction, + data->sg, sglen, slave_dirn, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) goto unmap_exit; diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 56e9a416..3abd51a 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -372,6 +372,7 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data, struct dma_chan *chan; struct dma_device *device; struct dma_async_tx_descriptor *desc; + enum dma_data_direction buffer_dirn; int nr_sg; /* Check if next job is already prepared */ @@ -385,10 +386,12 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data, } if (data->flags & MMC_DATA_READ) { - conf.direction = DMA_FROM_DEVICE; + conf.direction = DMA_DEV_TO_MEM; + buffer_dirn = DMA_FROM_DEVICE; chan = host->dma_rx_channel; } else { - conf.direction = DMA_TO_DEVICE; + conf.direction = DMA_MEM_TO_DEV; + buffer_dirn = DMA_TO_DEVICE; chan = host->dma_tx_channel; } @@ -401,7 +404,7 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data, return -EINVAL; device = chan->device; - nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, conf.direction); + nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, buffer_dirn); if (nr_sg == 0) return -EINVAL; @@ -424,7 +427,7 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data, unmap_exit: if (!next) dmaengine_terminate_all(chan); - dma_unmap_sg(device->dev, data->sg, data->sg_len, conf.direction); + dma_unmap_sg(device->dev, data->sg, data->sg_len, buffer_dirn); return -ENOMEM; } diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 14aa213..8a81663 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -217,6 +217,7 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) unsigned int blksz = data->blksz; unsigned int datasize = nob * blksz; struct scatterlist *sg; + enum dma_transfer_direction slave_dirn; int i, nents; if (data->flags & MMC_DATA_STREAM) @@ -239,10 +240,13 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) } } - if (data->flags & MMC_DATA_READ) + if (data->flags & MMC_DATA_READ) { host->dma_dir = DMA_FROM_DEVICE; - else + slave_dirn = DMA_DEV_TO_MEM; + } else { host->dma_dir = DMA_TO_DEVICE; + slave_dirn = DMA_MEM_TO_DEV; + } nents = dma_map_sg(host->dma->device->dev, data->sg, data->sg_len, host->dma_dir); @@ -250,7 +254,7 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) return -EINVAL; host->desc = host->dma->device->device_prep_slave_sg(host->dma, - data->sg, data->sg_len, host->dma_dir, + data->sg, data->sg_len, slave_dirn, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!host->desc) { diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index d513d47..996b9a9 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -153,6 +153,7 @@ struct mxs_mmc_host { struct dma_chan *dmach; struct mxs_dma_data dma_data; unsigned int dma_dir; + enum dma_transfer_direction slave_dirn; u32 ssp_pio_words[SSP_PIO_NUM]; unsigned int version; @@ -323,7 +324,7 @@ static struct dma_async_tx_descriptor *mxs_mmc_prep_dma( } desc = host->dmach->device->device_prep_slave_sg(host->dmach, - sgl, sg_len, host->dma_dir, append); + sgl, sg_len, host->slave_dirn, append); if (desc) { desc->callback = mxs_mmc_dma_irq_callback; desc->callback_param = host; @@ -432,6 +433,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) int i; unsigned short dma_data_dir, timeout; + enum dma_transfer_direction slave_dirn; unsigned int data_size = 0, log2_blksz; unsigned int blocks = data->blocks; @@ -447,9 +449,11 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) if (data->flags & MMC_DATA_WRITE) { dma_data_dir = DMA_TO_DEVICE; + slave_dirn = DMA_MEM_TO_DEV; read = 0; } else { dma_data_dir = DMA_FROM_DEVICE; + slave_dirn = DMA_DEV_TO_MEM; read = BM_SSP_CTRL0_READ; } @@ -517,6 +521,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) WARN_ON(host->data != NULL); host->data = data; host->dma_dir = dma_data_dir; + host->slave_dirn = slave_dirn; desc = mxs_mmc_prep_dma(host, 1); if (!desc) goto out; diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 557886b..0ae8d62 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -230,7 +230,7 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) if (ret > 0) { host->dma_active = true; desc = chan->device->device_prep_slave_sg(chan, sg, ret, - DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } if (desc) { @@ -278,7 +278,7 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) if (ret > 0) { host->dma_active = true; desc = chan->device->device_prep_slave_sg(chan, sg, ret, - DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } if (desc) { diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c index 86f259c..7a6e6cc 100644 --- a/drivers/mmc/host/tmio_mmc_dma.c +++ b/drivers/mmc/host/tmio_mmc_dma.c @@ -77,7 +77,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_FROM_DEVICE); if (ret > 0) desc = chan->device->device_prep_slave_sg(chan, sg, ret, - DMA_FROM_DEVICE, DMA_CTRL_ACK); + DMA_DEV_TO_MEM, DMA_CTRL_ACK); if (desc) { cookie = dmaengine_submit(desc); @@ -158,7 +158,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_TO_DEVICE); if (ret > 0) desc = chan->device->device_prep_slave_sg(chan, sg, ret, - DMA_TO_DEVICE, DMA_CTRL_ACK); + DMA_MEM_TO_DEV, DMA_CTRL_ACK); if (desc) { cookie = dmaengine_submit(desc); -- cgit v0.10.2 From a485df4b4404379786c4bdd258bc528b2617449d Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 10:47:38 +0530 Subject: spi, serial: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves spi, serial drivers to use new enum Signed-off-by: Vinod Koul Cc: Grant Likely Cc: Alan Cox Acked-by: Mika Westerberg diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c index 130e555..0a1fc8a 100644 --- a/drivers/spi/spi-dw-mid.c +++ b/drivers/spi/spi-dw-mid.c @@ -131,7 +131,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) rxchan = dws->rxchan; /* 2. Prepare the TX dma transfer */ - txconf.direction = DMA_TO_DEVICE; + txconf.direction = DMA_MEM_TO_DEV; txconf.dst_addr = dws->dma_addr; txconf.dst_maxburst = LNW_DMA_MSIZE_16; txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; @@ -147,13 +147,13 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) txdesc = txchan->device->device_prep_slave_sg(txchan, &dws->tx_sgl, 1, - DMA_TO_DEVICE, + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP); txdesc->callback = dw_spi_dma_done; txdesc->callback_param = dws; /* 3. Prepare the RX dma transfer */ - rxconf.direction = DMA_FROM_DEVICE; + rxconf.direction = DMA_DEV_TO_MEM; rxconf.src_addr = dws->dma_addr; rxconf.src_maxburst = LNW_DMA_MSIZE_16; rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; @@ -169,7 +169,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) rxdesc = rxchan->device->device_prep_slave_sg(rxchan, &dws->rx_sgl, 1, - DMA_FROM_DEVICE, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP); rxdesc->callback = dw_spi_dma_done; rxdesc->callback_param = dws; diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 1cf64547..0afd87d 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -550,6 +550,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir) struct dma_async_tx_descriptor *txd; enum dma_slave_buswidth buswidth; struct dma_slave_config conf; + enum dma_transfer_direction slave_dirn; struct scatterlist *sg; struct sg_table *sgt; struct dma_chan *chan; @@ -572,6 +573,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir) conf.src_addr = espi->sspdr_phys; conf.src_addr_width = buswidth; + slave_dirn = DMA_DEV_TO_MEM; } else { chan = espi->dma_tx; buf = t->tx_buf; @@ -579,6 +581,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir) conf.dst_addr = espi->sspdr_phys; conf.dst_addr_width = buswidth; + slave_dirn = DMA_MEM_TO_DEV; } ret = dmaengine_slave_config(chan, &conf); @@ -630,7 +633,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir) return ERR_PTR(-ENOMEM); txd = chan->device->device_prep_slave_sg(chan, sgt->sgl, nents, - dir, DMA_CTRL_ACK); + slave_dirn, DMA_CTRL_ACK); if (!txd) { dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir); return ERR_PTR(-ENOMEM); @@ -978,7 +981,7 @@ static int ep93xx_spi_setup_dma(struct ep93xx_spi *espi) dma_cap_set(DMA_SLAVE, mask); espi->dma_rx_data.port = EP93XX_DMA_SSP; - espi->dma_rx_data.direction = DMA_FROM_DEVICE; + espi->dma_rx_data.direction = DMA_DEV_TO_MEM; espi->dma_rx_data.name = "ep93xx-spi-rx"; espi->dma_rx = dma_request_channel(mask, ep93xx_spi_dma_filter, @@ -989,7 +992,7 @@ static int ep93xx_spi_setup_dma(struct ep93xx_spi *espi) } espi->dma_tx_data.port = EP93XX_DMA_SSP; - espi->dma_tx_data.direction = DMA_TO_DEVICE; + espi->dma_tx_data.direction = DMA_MEM_TO_DEV; espi->dma_tx_data.name = "ep93xx-spi-tx"; espi->dma_tx = dma_request_channel(mask, ep93xx_spi_dma_filter, diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 730b4a3..ddcddf4 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -910,11 +910,11 @@ static int configure_dma(struct pl022 *pl022) { struct dma_slave_config rx_conf = { .src_addr = SSP_DR(pl022->phybase), - .direction = DMA_FROM_DEVICE, + .direction = DMA_DEV_TO_MEM, }; struct dma_slave_config tx_conf = { .dst_addr = SSP_DR(pl022->phybase), - .direction = DMA_TO_DEVICE, + .direction = DMA_MEM_TO_DEV, }; unsigned int pages; int ret; @@ -1051,7 +1051,7 @@ static int configure_dma(struct pl022 *pl022) rxdesc = rxchan->device->device_prep_slave_sg(rxchan, pl022->sgt_rx.sgl, rx_sglen, - DMA_FROM_DEVICE, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!rxdesc) goto err_rxdesc; @@ -1059,7 +1059,7 @@ static int configure_dma(struct pl022 *pl022) txdesc = txchan->device->device_prep_slave_sg(txchan, pl022->sgt_tx.sgl, tx_sglen, - DMA_TO_DEVICE, + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!txdesc) goto err_txdesc; diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 1d23f38..7eba26e 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1051,7 +1051,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) } sg = dma->sg_rx_p; desc_rx = dma->chan_rx->device->device_prep_slave_sg(dma->chan_rx, sg, - num, DMA_FROM_DEVICE, + num, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_rx) { dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n", @@ -1086,7 +1086,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) } sg = dma->sg_tx_p; desc_tx = dma->chan_tx->device->device_prep_slave_sg(dma->chan_tx, - sg, num, DMA_TO_DEVICE, + sg, num, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_tx) { dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n", diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index f5f6831..460ff7d 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -268,7 +268,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap) struct dma_slave_config tx_conf = { .dst_addr = uap->port.mapbase + UART01x_DR, .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, - .direction = DMA_TO_DEVICE, + .direction = DMA_MEM_TO_DEV, .dst_maxburst = uap->fifosize >> 1, }; struct dma_chan *chan; @@ -301,7 +301,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap) struct dma_slave_config rx_conf = { .src_addr = uap->port.mapbase + UART01x_DR, .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, - .direction = DMA_FROM_DEVICE, + .direction = DMA_DEV_TO_MEM, .src_maxburst = uap->fifosize >> 1, }; @@ -480,7 +480,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap) return -EBUSY; } - desc = dma_dev->device_prep_slave_sg(chan, &dmatx->sg, 1, DMA_TO_DEVICE, + desc = dma_dev->device_prep_slave_sg(chan, &dmatx->sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { dma_unmap_sg(dma_dev->dev, &dmatx->sg, 1, DMA_TO_DEVICE); @@ -676,7 +676,7 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap) &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a; dma_dev = rxchan->device; desc = rxchan->device->device_prep_slave_sg(rxchan, &sgbuf->sg, 1, - DMA_FROM_DEVICE, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); /* * If the DMA engine is busy and cannot prepare a diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index b46218d..73201a1 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -747,7 +747,7 @@ static int dma_handle_rx(struct eg20t_port *priv) sg_dma_address(sg) = priv->rx_buf_dma; desc = priv->chan_rx->device->device_prep_slave_sg(priv->chan_rx, - sg, 1, DMA_FROM_DEVICE, + sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) @@ -906,7 +906,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv) } desc = priv->chan_tx->device->device_prep_slave_sg(priv->chan_tx, - priv->sg_tx_p, nent, DMA_TO_DEVICE, + priv->sg_tx_p, nent, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { dev_err(priv->port.dev, "%s:device_prep_slave_sg Failed\n", diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index dbd32a1..3683a69 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1207,7 +1207,7 @@ static void sci_submit_rx(struct sci_port *s) struct dma_async_tx_descriptor *desc; desc = chan->device->device_prep_slave_sg(chan, - sg, 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT); + sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); if (desc) { s->desc_rx[i] = desc; @@ -1322,7 +1322,7 @@ static void work_fn_tx(struct work_struct *work) BUG_ON(!sg_dma_len(sg)); desc = chan->device->device_prep_slave_sg(chan, - sg, s->sg_len_tx, DMA_TO_DEVICE, + sg, s->sg_len_tx, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { /* switch to PIO */ -- cgit v0.10.2 From 35e16581ed6bff55009a0bac34c755140407b03f Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 10:49:30 +0530 Subject: sound-soc: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves asoc drivers to use new enum Signed-off-by: Vinod Koul Cc: Liam Girdwood Cc: Mark Brown Acked-by: Mark Brown diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c index 6fd9391..4fa1dbd 100644 --- a/sound/atmel/abdac.c +++ b/sound/atmel/abdac.c @@ -133,7 +133,7 @@ static int atmel_abdac_prepare_dma(struct atmel_abdac *dac, period_len = frames_to_bytes(runtime, runtime->period_size); cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len, - period_len, DMA_TO_DEVICE); + period_len, DMA_MEM_TO_DEV); if (IS_ERR(cdesc)) { dev_dbg(&dac->pdev->dev, "could not prepare cyclic DMA\n"); return PTR_ERR(cdesc); diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 6e5adde..cd9428b 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -102,7 +102,7 @@ static void atmel_ac97c_dma_capture_period_done(void *arg) static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip, struct snd_pcm_substream *substream, - enum dma_data_direction direction) + enum dma_transfer_direction direction) { struct dma_chan *chan; struct dw_cyclic_desc *cdesc; @@ -118,7 +118,7 @@ static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip, return -EINVAL; } - if (direction == DMA_TO_DEVICE) + if (direction == DMA_MEM_TO_DEV) chan = chip->dma.tx_chan; else chan = chip->dma.rx_chan; @@ -133,7 +133,7 @@ static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip, return PTR_ERR(cdesc); } - if (direction == DMA_TO_DEVICE) { + if (direction == DMA_MEM_TO_DEV) { cdesc->period_callback = atmel_ac97c_dma_playback_period_done; set_bit(DMA_TX_READY, &chip->flags); } else { @@ -393,7 +393,7 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) if (cpu_is_at32ap7000()) { if (!test_bit(DMA_TX_READY, &chip->flags)) retval = atmel_ac97c_prepare_dma(chip, substream, - DMA_TO_DEVICE); + DMA_MEM_TO_DEV); } else { /* Initialize and start the PDC */ writel(runtime->dma_addr, chip->regs + ATMEL_PDC_TPR); @@ -484,7 +484,7 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) if (cpu_is_at32ap7000()) { if (!test_bit(DMA_RX_READY, &chip->flags)) retval = atmel_ac97c_prepare_dma(chip, substream, - DMA_FROM_DEVICE); + DMA_DEV_TO_MEM); } else { /* Initialize and start the PDC */ writel(runtime->dma_addr, chip->regs + ATMEL_PDC_RPR); diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c index 8dfd3ad..faf7d4f 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.c +++ b/sound/soc/ep93xx/ep93xx-pcm.c @@ -113,9 +113,9 @@ static int ep93xx_pcm_open(struct snd_pcm_substream *substream) rtd->dma_data.name = dma_params->name; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - rtd->dma_data.direction = DMA_TO_DEVICE; + rtd->dma_data.direction = DMA_MEM_TO_DEV; else - rtd->dma_data.direction = DMA_FROM_DEVICE; + rtd->dma_data.direction = DMA_DEV_TO_MEM; rtd->dma_chan = dma_request_channel(mask, ep93xx_pcm_dma_filter, &rtd->dma_data); diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c index 43fdc24f..7d28de9 100644 --- a/sound/soc/imx/imx-pcm-dma-mx2.c +++ b/sound/soc/imx/imx-pcm-dma-mx2.c @@ -107,12 +107,12 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream, } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - slave_config.direction = DMA_TO_DEVICE; + slave_config.direction = DMA_MEM_TO_DEV; slave_config.dst_addr = dma_params->dma_addr; slave_config.dst_addr_width = buswidth; slave_config.dst_maxburst = dma_params->burstsize; } else { - slave_config.direction = DMA_FROM_DEVICE; + slave_config.direction = DMA_DEV_TO_MEM; slave_config.src_addr = dma_params->dma_addr; slave_config.src_addr_width = buswidth; slave_config.src_maxburst = dma_params->burstsize; @@ -159,7 +159,7 @@ static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream, iprtd->period_bytes * iprtd->periods, iprtd->period_bytes, substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - DMA_TO_DEVICE : DMA_FROM_DEVICE); + DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); if (!iprtd->desc) { dev_err(&chan->dev->device, "cannot prepare slave dma\n"); return -EINVAL; diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c index 851346f..87a3957 100644 --- a/sound/soc/samsung/dma.c +++ b/sound/soc/samsung/dma.c @@ -85,7 +85,7 @@ static void dma_enqueue(struct snd_pcm_substream *substream) dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE); dma_info.direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK - ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); dma_info.fp = audio_buffdone; dma_info.fp_param = substream; dma_info.period = prtd->dma_period; @@ -170,7 +170,7 @@ static int dma_hw_params(struct snd_pcm_substream *substream, dma_info.client = prtd->params->client; dma_info.direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK - ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); dma_info.width = prtd->params->dma_size; dma_info.fifo = prtd->params->dma_addr; prtd->params->ch = prtd->params->ops->request( diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index f8f6816..0193e59 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c @@ -131,7 +131,7 @@ static int siu_pcm_wr_set(struct siu_port *port_info, sg_dma_address(&sg) = buff; desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan, - &sg, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + &sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { dev_err(dev, "Failed to allocate a dma descriptor\n"); return -ENOMEM; @@ -181,7 +181,7 @@ static int siu_pcm_rd_set(struct siu_port *port_info, sg_dma_address(&sg) = buff; desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan, - &sg, 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + &sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { dev_err(dev, "Failed to allocate dma descriptor\n"); return -ENOMEM; diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c index 3de99af..602bb68 100644 --- a/sound/soc/txx9/txx9aclc.c +++ b/sound/soc/txx9/txx9aclc.c @@ -134,7 +134,7 @@ txx9aclc_dma_submit(struct txx9aclc_dmadata *dmadata, dma_addr_t buf_dma_addr) sg_dma_address(&sg) = buf_dma_addr; desc = chan->device->device_prep_slave_sg(chan, &sg, 1, dmadata->substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - DMA_TO_DEVICE : DMA_FROM_DEVICE, + DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { dev_err(&chan->dev->device, "cannot prepare slave dma\n"); -- cgit v0.10.2 From 8af11fd3f013892c918a39acb691bc7469c5ad77 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 10:52:48 +0530 Subject: net-ks8842: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves net/ks8842 drivers to use new enum Signed-off-by: Vinod Koul Cc: David S. Miller Cc: Samuel Ortiz diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c index 4a6ae05..de9f2e2 100644 --- a/drivers/net/ks8842.c +++ b/drivers/net/ks8842.c @@ -459,7 +459,7 @@ static int ks8842_tx_frame_dma(struct sk_buff *skb, struct net_device *netdev) sg_dma_len(&ctl->sg) += 4 - sg_dma_len(&ctl->sg) % 4; ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan, - &ctl->sg, 1, DMA_TO_DEVICE, + &ctl->sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); if (!ctl->adesc) return NETDEV_TX_BUSY; @@ -571,7 +571,7 @@ static int __ks8842_start_new_rx_dma(struct net_device *netdev) sg_dma_len(sg) = DMA_BUFFER_SIZE; ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan, - sg, 1, DMA_FROM_DEVICE, + sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); if (!ctl->adesc) -- cgit v0.10.2 From 0b934ccd707ff33a87f15a35a9916d1d8e85d30e Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 4 Nov 2011 15:41:27 -0400 Subject: Xen: Export xen_biovec_phys_mergeable When Xen is enabled, using BIOVEC_PHYS_MERGEABLE in a module causes xen_biovec_phys_mergeable to be referenced, so it needs to be exported. Acked-by: Jens Axboe Signed-off-by: Matthew Wilcox diff --git a/drivers/xen/biomerge.c b/drivers/xen/biomerge.c index ba6eda4..18c1bb6 100644 --- a/drivers/xen/biomerge.c +++ b/drivers/xen/biomerge.c @@ -11,3 +11,4 @@ bool xen_biovec_phys_mergeable(const struct bio_vec *vec1, return __BIOVEC_PHYS_MERGEABLE(vec1, vec2) && ((mfn1 == mfn2) || ((mfn1+1) == mfn2)); } +EXPORT_SYMBOL(xen_biovec_phys_mergeable); -- cgit v0.10.2 From b60503ba432b16fc84442a84e29a7aad2c0c363d Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 20 Jan 2011 12:50:14 -0500 Subject: NVMe: New driver This driver is for devices that follow the NVM Express standard Signed-off-by: Matthew Wilcox diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index 54078ed..4840334 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -149,6 +149,7 @@ Code Seq#(hex) Include File Comments 'M' 01-03 drivers/scsi/megaraid/megaraid_sas.h 'M' 00-0F drivers/video/fsl-diu-fb.h conflict! 'N' 00-1F drivers/usb/scanner.h +'N' 40-7F drivers/block/nvme.c 'O' 00-06 mtd/ubi-user.h UBI 'P' all linux/soundcard.h conflict! 'P' 60-6F sound/sscape_ioctl.h conflict! diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 6f07ec1..35e56e1 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -315,6 +315,17 @@ config BLK_DEV_NBD If unsure, say N. +config BLK_DEV_NVME + tristate "NVM Express block device" + depends on PCI + ---help--- + The NVM Express driver is for solid state drives directly + connected to the PCI or PCI Express bus. If you know you + don't have one of these, it is safe to answer N. + + To compile this driver as a module, choose M here: the + module will be called nvme. + config BLK_DEV_OSD tristate "OSD object-as-blkdev support" depends on SCSI_OSD_ULD diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 76646e9..349539a 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_XILINX_SYSACE) += xsysace.o obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o obj-$(CONFIG_MG_DISK) += mg_disk.o obj-$(CONFIG_SUNVDC) += sunvdc.o +obj-$(CONFIG_BLK_DEV_NVME) += nvme.o obj-$(CONFIG_BLK_DEV_OSD) += osdblk.o obj-$(CONFIG_BLK_DEV_UMEM) += umem.o diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c new file mode 100644 index 0000000..ef66ecc --- /dev/null +++ b/drivers/block/nvme.c @@ -0,0 +1,1043 @@ +/* + * NVM Express device driver + * Copyright (c) 2011, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NVME_Q_DEPTH 1024 +#define SQ_SIZE(depth) (depth * sizeof(struct nvme_command)) +#define CQ_SIZE(depth) (depth * sizeof(struct nvme_completion)) +#define NVME_MINORS 64 + +static int nvme_major; +module_param(nvme_major, int, 0); + +/* + * Represents an NVM Express device. Each nvme_dev is a PCI function. + */ +struct nvme_dev { + struct list_head node; + struct nvme_queue **queues; + u32 __iomem *dbs; + struct pci_dev *pci_dev; + int instance; + int queue_count; + u32 ctrl_config; + struct msix_entry *entry; + struct nvme_bar __iomem *bar; + struct list_head namespaces; +}; + +/* + * An NVM Express namespace is equivalent to a SCSI LUN + */ +struct nvme_ns { + struct list_head list; + + struct nvme_dev *dev; + struct request_queue *queue; + struct gendisk *disk; + + int ns_id; + int lba_shift; +}; + +/* + * An NVM Express queue. Each device has at least two (one for admin + * commands and one for I/O commands). + */ +struct nvme_queue { + struct device *q_dmadev; + spinlock_t q_lock; + struct nvme_command *sq_cmds; + volatile struct nvme_completion *cqes; + dma_addr_t sq_dma_addr; + dma_addr_t cq_dma_addr; + wait_queue_head_t sq_full; + struct bio_list sq_cong; + u32 __iomem *q_db; + u16 q_depth; + u16 cq_vector; + u16 sq_head; + u16 sq_tail; + u16 cq_head; + u16 cq_cycle; + unsigned long cmdid_data[]; +}; + +/* + * Check we didin't inadvertently grow the command struct + */ +static inline void _nvme_check_size(void) +{ + BUILD_BUG_ON(sizeof(struct nvme_rw_command) != 64); + BUILD_BUG_ON(sizeof(struct nvme_create_cq) != 64); + BUILD_BUG_ON(sizeof(struct nvme_create_sq) != 64); + BUILD_BUG_ON(sizeof(struct nvme_delete_queue) != 64); + BUILD_BUG_ON(sizeof(struct nvme_features) != 64); + BUILD_BUG_ON(sizeof(struct nvme_command) != 64); + BUILD_BUG_ON(sizeof(struct nvme_id_ctrl) != 4096); + BUILD_BUG_ON(sizeof(struct nvme_id_ns) != 4096); + BUILD_BUG_ON(sizeof(struct nvme_lba_range_type) != 64); +} + +/** + * alloc_cmdid - Allocate a Command ID + * @param nvmeq The queue that will be used for this command + * @param ctx A pointer that will be passed to the handler + * @param handler The ID of the handler to call + * + * Allocate a Command ID for a queue. The data passed in will + * be passed to the completion handler. This is implemented by using + * the bottom two bits of the ctx pointer to store the handler ID. + * Passing in a pointer that's not 4-byte aligned will cause a BUG. + * We can change this if it becomes a problem. + */ +static int alloc_cmdid(struct nvme_queue *nvmeq, void *ctx, int handler) +{ + int depth = nvmeq->q_depth; + unsigned long data = (unsigned long)ctx | handler; + int cmdid; + + BUG_ON((unsigned long)ctx & 3); + + do { + cmdid = find_first_zero_bit(nvmeq->cmdid_data, depth); + if (cmdid >= depth) + return -EBUSY; + } while (test_and_set_bit(cmdid, nvmeq->cmdid_data)); + + nvmeq->cmdid_data[cmdid + BITS_TO_LONGS(depth)] = data; + return cmdid; +} + +static int alloc_cmdid_killable(struct nvme_queue *nvmeq, void *ctx, + int handler) +{ + int cmdid; + wait_event_killable(nvmeq->sq_full, + (cmdid = alloc_cmdid(nvmeq, ctx, handler)) >= 0); + return (cmdid < 0) ? -EINTR : cmdid; +} + +/* If you need more than four handlers, you'll need to change how + * alloc_cmdid and nvme_process_cq work + */ +enum { + sync_completion_id = 0, + bio_completion_id, +}; + +static unsigned long free_cmdid(struct nvme_queue *nvmeq, int cmdid) +{ + unsigned long data; + + data = nvmeq->cmdid_data[cmdid + BITS_TO_LONGS(nvmeq->q_depth)]; + clear_bit(cmdid, nvmeq->cmdid_data); + wake_up(&nvmeq->sq_full); + return data; +} + +static struct nvme_queue *get_nvmeq(struct nvme_ns *ns) +{ + return ns->dev->queues[1]; +} + +static void put_nvmeq(struct nvme_queue *nvmeq) +{ +} + +/** + * nvme_submit_cmd: Copy a command into a queue and ring the doorbell + * @nvmeq: The queue to use + * @cmd: The command to send + * + * Safe to use from interrupt context + */ +static int nvme_submit_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd) +{ + unsigned long flags; + u16 tail; + /* XXX: Need to check tail isn't going to overrun head */ + spin_lock_irqsave(&nvmeq->q_lock, flags); + tail = nvmeq->sq_tail; + memcpy(&nvmeq->sq_cmds[tail], cmd, sizeof(*cmd)); + writel(tail, nvmeq->q_db); + if (++tail == nvmeq->q_depth) + tail = 0; + nvmeq->sq_tail = tail; + spin_unlock_irqrestore(&nvmeq->q_lock, flags); + + return 0; +} + +struct nvme_req_info { + struct bio *bio; + int nents; + struct scatterlist sg[0]; +}; + +/* XXX: use a mempool */ +static struct nvme_req_info *alloc_info(unsigned nseg, gfp_t gfp) +{ + return kmalloc(sizeof(struct nvme_req_info) + + sizeof(struct scatterlist) * nseg, gfp); +} + +static void free_info(struct nvme_req_info *info) +{ + kfree(info); +} + +static void bio_completion(struct nvme_queue *nvmeq, void *ctx, + struct nvme_completion *cqe) +{ + struct nvme_req_info *info = ctx; + struct bio *bio = info->bio; + u16 status = le16_to_cpup(&cqe->status) >> 1; + + dma_unmap_sg(nvmeq->q_dmadev, info->sg, info->nents, + bio_data_dir(bio) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + free_info(info); + bio_endio(bio, status ? -EIO : 0); +} + +static int nvme_map_bio(struct device *dev, struct nvme_req_info *info, + struct bio *bio, enum dma_data_direction dma_dir, int psegs) +{ + struct bio_vec *bvec; + struct scatterlist *sg = info->sg; + int i, nsegs; + + sg_init_table(sg, psegs); + bio_for_each_segment(bvec, bio, i) { + sg_set_page(sg, bvec->bv_page, bvec->bv_len, bvec->bv_offset); + /* XXX: handle non-mergable here */ + nsegs++; + } + info->nents = nsegs; + + return dma_map_sg(dev, info->sg, info->nents, dma_dir); +} + +static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, + struct bio *bio) +{ + struct nvme_rw_command *cmnd; + struct nvme_req_info *info; + enum dma_data_direction dma_dir; + int cmdid; + u16 control; + u32 dsmgmt; + unsigned long flags; + int psegs = bio_phys_segments(ns->queue, bio); + + info = alloc_info(psegs, GFP_NOIO); + if (!info) + goto congestion; + info->bio = bio; + + cmdid = alloc_cmdid(nvmeq, info, bio_completion_id); + if (unlikely(cmdid < 0)) + goto free_info; + + control = 0; + if (bio->bi_rw & REQ_FUA) + control |= NVME_RW_FUA; + if (bio->bi_rw & (REQ_FAILFAST_DEV | REQ_RAHEAD)) + control |= NVME_RW_LR; + + dsmgmt = 0; + if (bio->bi_rw & REQ_RAHEAD) + dsmgmt |= NVME_RW_DSM_FREQ_PREFETCH; + + spin_lock_irqsave(&nvmeq->q_lock, flags); + cmnd = &nvmeq->sq_cmds[nvmeq->sq_tail].rw; + + if (bio_data_dir(bio)) { + cmnd->opcode = nvme_cmd_write; + dma_dir = DMA_TO_DEVICE; + } else { + cmnd->opcode = nvme_cmd_read; + dma_dir = DMA_FROM_DEVICE; + } + + nvme_map_bio(nvmeq->q_dmadev, info, bio, dma_dir, psegs); + + cmnd->flags = 1; + cmnd->command_id = cmdid; + cmnd->nsid = cpu_to_le32(ns->ns_id); + cmnd->prp1 = cpu_to_le64(sg_phys(info->sg)); + /* XXX: Support more than one PRP */ + cmnd->slba = cpu_to_le64(bio->bi_sector >> (ns->lba_shift - 9)); + cmnd->length = cpu_to_le16((bio->bi_size >> ns->lba_shift) - 1); + cmnd->control = cpu_to_le16(control); + cmnd->dsmgmt = cpu_to_le32(dsmgmt); + + writel(nvmeq->sq_tail, nvmeq->q_db); + if (++nvmeq->sq_tail == nvmeq->q_depth) + nvmeq->sq_tail = 0; + + spin_unlock_irqrestore(&nvmeq->q_lock, flags); + + return 0; + + free_info: + free_info(info); + congestion: + return -EBUSY; +} + +/* + * NB: return value of non-zero would mean that we were a stacking driver. + * make_request must always succeed. + */ +static int nvme_make_request(struct request_queue *q, struct bio *bio) +{ + struct nvme_ns *ns = q->queuedata; + struct nvme_queue *nvmeq = get_nvmeq(ns); + + if (nvme_submit_bio_queue(nvmeq, ns, bio)) { + blk_set_queue_congested(q, rw_is_sync(bio->bi_rw)); + bio_list_add(&nvmeq->sq_cong, bio); + } + put_nvmeq(nvmeq); + + return 0; +} + +struct sync_cmd_info { + struct task_struct *task; + u32 result; + int status; +}; + +static void sync_completion(struct nvme_queue *nvmeq, void *ctx, + struct nvme_completion *cqe) +{ + struct sync_cmd_info *cmdinfo = ctx; + cmdinfo->result = le32_to_cpup(&cqe->result); + cmdinfo->status = le16_to_cpup(&cqe->status) >> 1; + wake_up_process(cmdinfo->task); +} + +typedef void (*completion_fn)(struct nvme_queue *, void *, + struct nvme_completion *); + +static irqreturn_t nvme_process_cq(struct nvme_queue *nvmeq) +{ + u16 head, cycle; + + static const completion_fn completions[4] = { + [sync_completion_id] = sync_completion, + [bio_completion_id] = bio_completion, + }; + + head = nvmeq->cq_head; + cycle = nvmeq->cq_cycle; + + for (;;) { + unsigned long data; + void *ptr; + unsigned char handler; + struct nvme_completion cqe = nvmeq->cqes[head]; + if ((le16_to_cpu(cqe.status) & 1) != cycle) + break; + nvmeq->sq_head = le16_to_cpu(cqe.sq_head); + if (++head == nvmeq->q_depth) { + head = 0; + cycle = !cycle; + } + + data = free_cmdid(nvmeq, cqe.command_id); + handler = data & 3; + ptr = (void *)(data & ~3UL); + completions[handler](nvmeq, ptr, &cqe); + } + + /* If the controller ignores the cq head doorbell and continuously + * writes to the queue, it is theoretically possible to wrap around + * the queue twice and mistakenly return IRQ_NONE. Linux only + * requires that 0.1% of your interrupts are handled, so this isn't + * a big problem. + */ + if (head == nvmeq->cq_head && cycle == nvmeq->cq_cycle) + return IRQ_NONE; + + writel(head, nvmeq->q_db + 1); + nvmeq->cq_head = head; + nvmeq->cq_cycle = cycle; + + return IRQ_HANDLED; +} + +static irqreturn_t nvme_irq(int irq, void *data) +{ + return nvme_process_cq(data); +} + +/* + * Returns 0 on success. If the result is negative, it's a Linux error code; + * if the result is positive, it's an NVM Express status code + */ +static int nvme_submit_sync_cmd(struct nvme_queue *q, struct nvme_command *cmd, + u32 *result) +{ + int cmdid; + struct sync_cmd_info cmdinfo; + + cmdinfo.task = current; + cmdinfo.status = -EINTR; + + cmdid = alloc_cmdid_killable(q, &cmdinfo, sync_completion_id); + if (cmdid < 0) + return cmdid; + cmd->common.command_id = cmdid; + + set_current_state(TASK_UNINTERRUPTIBLE); + nvme_submit_cmd(q, cmd); + schedule(); + + if (result) + *result = cmdinfo.result; + + return cmdinfo.status; +} + +static int nvme_submit_admin_cmd(struct nvme_dev *dev, struct nvme_command *cmd, + u32 *result) +{ + return nvme_submit_sync_cmd(dev->queues[0], cmd, result); +} + +static int adapter_delete_queue(struct nvme_dev *dev, u8 opcode, u16 id) +{ + int status; + struct nvme_command c; + + memset(&c, 0, sizeof(c)); + c.delete_queue.opcode = opcode; + c.delete_queue.qid = cpu_to_le16(id); + + status = nvme_submit_admin_cmd(dev, &c, NULL); + if (status) + return -EIO; + return 0; +} + +static int adapter_alloc_cq(struct nvme_dev *dev, u16 qid, + struct nvme_queue *nvmeq) +{ + int status; + struct nvme_command c; + int flags = NVME_QUEUE_PHYS_CONTIG | NVME_CQ_IRQ_ENABLED; + + memset(&c, 0, sizeof(c)); + c.create_cq.opcode = nvme_admin_create_cq; + c.create_cq.prp1 = cpu_to_le64(nvmeq->cq_dma_addr); + c.create_cq.cqid = cpu_to_le16(qid); + c.create_cq.qsize = cpu_to_le16(nvmeq->q_depth - 1); + c.create_cq.cq_flags = cpu_to_le16(flags); + c.create_cq.irq_vector = cpu_to_le16(nvmeq->cq_vector); + + status = nvme_submit_admin_cmd(dev, &c, NULL); + if (status) + return -EIO; + return 0; +} + +static int adapter_alloc_sq(struct nvme_dev *dev, u16 qid, + struct nvme_queue *nvmeq) +{ + int status; + struct nvme_command c; + int flags = NVME_QUEUE_PHYS_CONTIG | NVME_SQ_PRIO_MEDIUM; + + memset(&c, 0, sizeof(c)); + c.create_sq.opcode = nvme_admin_create_sq; + c.create_sq.prp1 = cpu_to_le64(nvmeq->sq_dma_addr); + c.create_sq.sqid = cpu_to_le16(qid); + c.create_sq.qsize = cpu_to_le16(nvmeq->q_depth - 1); + c.create_sq.sq_flags = cpu_to_le16(flags); + c.create_sq.cqid = cpu_to_le16(qid); + + status = nvme_submit_admin_cmd(dev, &c, NULL); + if (status) + return -EIO; + return 0; +} + +static int adapter_delete_cq(struct nvme_dev *dev, u16 cqid) +{ + return adapter_delete_queue(dev, nvme_admin_delete_cq, cqid); +} + +static int adapter_delete_sq(struct nvme_dev *dev, u16 sqid) +{ + return adapter_delete_queue(dev, nvme_admin_delete_sq, sqid); +} + +static void nvme_free_queue(struct nvme_dev *dev, int qid) +{ + struct nvme_queue *nvmeq = dev->queues[qid]; + + free_irq(dev->entry[nvmeq->cq_vector].vector, nvmeq); + + /* Don't tell the adapter to delete the admin queue */ + if (qid) { + adapter_delete_sq(dev, qid); + adapter_delete_cq(dev, qid); + } + + dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth), + (void *)nvmeq->cqes, nvmeq->cq_dma_addr); + dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth), + nvmeq->sq_cmds, nvmeq->sq_dma_addr); + kfree(nvmeq); +} + +static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid, + int depth, int vector) +{ + struct device *dmadev = &dev->pci_dev->dev; + unsigned extra = (depth + BITS_TO_LONGS(depth)) * sizeof(long); + struct nvme_queue *nvmeq = kzalloc(sizeof(*nvmeq) + extra, GFP_KERNEL); + if (!nvmeq) + return NULL; + + nvmeq->cqes = dma_alloc_coherent(dmadev, CQ_SIZE(depth), + &nvmeq->cq_dma_addr, GFP_KERNEL); + if (!nvmeq->cqes) + goto free_nvmeq; + memset((void *)nvmeq->cqes, 0, CQ_SIZE(depth)); + + nvmeq->sq_cmds = dma_alloc_coherent(dmadev, SQ_SIZE(depth), + &nvmeq->sq_dma_addr, GFP_KERNEL); + if (!nvmeq->sq_cmds) + goto free_cqdma; + + nvmeq->q_dmadev = dmadev; + spin_lock_init(&nvmeq->q_lock); + nvmeq->cq_head = 0; + nvmeq->cq_cycle = 1; + init_waitqueue_head(&nvmeq->sq_full); + bio_list_init(&nvmeq->sq_cong); + nvmeq->q_db = &dev->dbs[qid * 2]; + nvmeq->q_depth = depth; + nvmeq->cq_vector = vector; + + return nvmeq; + + free_cqdma: + dma_free_coherent(dmadev, CQ_SIZE(nvmeq->q_depth), (void *)nvmeq->cqes, + nvmeq->cq_dma_addr); + free_nvmeq: + kfree(nvmeq); + return NULL; +} + +static __devinit struct nvme_queue *nvme_create_queue(struct nvme_dev *dev, + int qid, int cq_size, int vector) +{ + int result; + struct nvme_queue *nvmeq = nvme_alloc_queue(dev, qid, cq_size, vector); + + result = adapter_alloc_cq(dev, qid, nvmeq); + if (result < 0) + goto free_nvmeq; + + result = adapter_alloc_sq(dev, qid, nvmeq); + if (result < 0) + goto release_cq; + + result = request_irq(dev->entry[vector].vector, nvme_irq, + IRQF_DISABLED | IRQF_SHARED, "nvme", nvmeq); + if (result < 0) + goto release_sq; + + return nvmeq; + + release_sq: + adapter_delete_sq(dev, qid); + release_cq: + adapter_delete_cq(dev, qid); + free_nvmeq: + dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth), + (void *)nvmeq->cqes, nvmeq->cq_dma_addr); + dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth), + nvmeq->sq_cmds, nvmeq->sq_dma_addr); + kfree(nvmeq); + return NULL; +} + +static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) +{ + int result; + u32 aqa; + struct nvme_queue *nvmeq; + + dev->dbs = ((void __iomem *)dev->bar) + 4096; + + nvmeq = nvme_alloc_queue(dev, 0, 64, 0); + + aqa = nvmeq->q_depth - 1; + aqa |= aqa << 16; + + dev->ctrl_config = NVME_CC_ENABLE | NVME_CC_CSS_NVM; + dev->ctrl_config |= (PAGE_SHIFT - 12) << NVME_CC_MPS_SHIFT; + dev->ctrl_config |= NVME_CC_ARB_RR | NVME_CC_SHN_NONE; + + writel(aqa, &dev->bar->aqa); + writeq(nvmeq->sq_dma_addr, &dev->bar->asq); + writeq(nvmeq->cq_dma_addr, &dev->bar->acq); + writel(dev->ctrl_config, &dev->bar->cc); + + while (!(readl(&dev->bar->csts) & NVME_CSTS_RDY)) { + msleep(100); + if (fatal_signal_pending(current)) + return -EINTR; + } + + result = request_irq(dev->entry[0].vector, nvme_irq, + IRQF_DISABLED | IRQF_SHARED, "nvme admin", nvmeq); + dev->queues[0] = nvmeq; + return result; +} + +static int nvme_identify(struct nvme_ns *ns, void __user *addr, int cns) +{ + struct nvme_dev *dev = ns->dev; + int status; + struct nvme_command c; + void *page; + dma_addr_t dma_addr; + + page = dma_alloc_coherent(&dev->pci_dev->dev, 4096, &dma_addr, + GFP_KERNEL); + + memset(&c, 0, sizeof(c)); + c.identify.opcode = nvme_admin_identify; + c.identify.nsid = cns ? 0 : cpu_to_le32(ns->ns_id); + c.identify.prp1 = cpu_to_le64(dma_addr); + c.identify.cns = cpu_to_le32(cns); + + status = nvme_submit_admin_cmd(dev, &c, NULL); + + if (status) + status = -EIO; + else if (copy_to_user(addr, page, 4096)) + status = -EFAULT; + + dma_free_coherent(&dev->pci_dev->dev, 4096, page, dma_addr); + + return status; +} + +static int nvme_get_range_type(struct nvme_ns *ns, void __user *addr) +{ + struct nvme_dev *dev = ns->dev; + int status; + struct nvme_command c; + void *page; + dma_addr_t dma_addr; + + page = dma_alloc_coherent(&dev->pci_dev->dev, 4096, &dma_addr, + GFP_KERNEL); + + memset(&c, 0, sizeof(c)); + c.features.opcode = nvme_admin_get_features; + c.features.nsid = cpu_to_le32(ns->ns_id); + c.features.prp1 = cpu_to_le64(dma_addr); + c.features.fid = cpu_to_le32(NVME_FEAT_LBA_RANGE); + + status = nvme_submit_admin_cmd(dev, &c, NULL); + + /* XXX: Assuming first range for now */ + if (status) + status = -EIO; + else if (copy_to_user(addr, page, 64)) + status = -EFAULT; + + dma_free_coherent(&dev->pci_dev->dev, 4096, page, dma_addr); + + return status; +} + +static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, + unsigned long arg) +{ + struct nvme_ns *ns = bdev->bd_disk->private_data; + + switch (cmd) { + case NVME_IOCTL_IDENTIFY_NS: + return nvme_identify(ns, (void __user *)arg, 0); + case NVME_IOCTL_IDENTIFY_CTRL: + return nvme_identify(ns, (void __user *)arg, 1); + case NVME_IOCTL_GET_RANGE_TYPE: + return nvme_get_range_type(ns, (void __user *)arg); + default: + return -ENOTTY; + } +} + +static const struct block_device_operations nvme_fops = { + .owner = THIS_MODULE, + .ioctl = nvme_ioctl, +}; + +static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int index, + struct nvme_id_ns *id, struct nvme_lba_range_type *rt) +{ + struct nvme_ns *ns; + struct gendisk *disk; + int lbaf; + + if (rt->attributes & NVME_LBART_ATTRIB_HIDE) + return NULL; + + ns = kzalloc(sizeof(*ns), GFP_KERNEL); + if (!ns) + return NULL; + ns->queue = blk_alloc_queue(GFP_KERNEL); + if (!ns->queue) + goto out_free_ns; + ns->queue->queue_flags = QUEUE_FLAG_DEFAULT | QUEUE_FLAG_NOMERGES | + QUEUE_FLAG_NONROT | QUEUE_FLAG_DISCARD; + blk_queue_make_request(ns->queue, nvme_make_request); + ns->dev = dev; + ns->queue->queuedata = ns; + + disk = alloc_disk(NVME_MINORS); + if (!disk) + goto out_free_queue; + ns->ns_id = index; + ns->disk = disk; + lbaf = id->flbas & 0xf; + ns->lba_shift = id->lbaf[lbaf].ds; + + disk->major = nvme_major; + disk->minors = NVME_MINORS; + disk->first_minor = NVME_MINORS * index; + disk->fops = &nvme_fops; + disk->private_data = ns; + disk->queue = ns->queue; + sprintf(disk->disk_name, "nvme%dn%d", dev->instance, index); + set_capacity(disk, le64_to_cpup(&id->nsze) << (ns->lba_shift - 9)); + + return ns; + + out_free_queue: + blk_cleanup_queue(ns->queue); + out_free_ns: + kfree(ns); + return NULL; +} + +static void nvme_ns_free(struct nvme_ns *ns) +{ + put_disk(ns->disk); + blk_cleanup_queue(ns->queue); + kfree(ns); +} + +static int set_queue_count(struct nvme_dev *dev, int sq_count, int cq_count) +{ + int status; + u32 result; + struct nvme_command c; + u32 q_count = (sq_count - 1) | ((cq_count - 1) << 16); + + memset(&c, 0, sizeof(c)); + c.features.opcode = nvme_admin_get_features; + c.features.fid = cpu_to_le32(NVME_FEAT_NUM_QUEUES); + c.features.dword11 = cpu_to_le32(q_count); + + status = nvme_submit_admin_cmd(dev, &c, &result); + if (status) + return -EIO; + return min(result & 0xffff, result >> 16) + 1; +} + +/* XXX: Create per-CPU queues */ +static int __devinit nvme_setup_io_queues(struct nvme_dev *dev) +{ + int this_cpu; + + set_queue_count(dev, 1, 1); + + this_cpu = get_cpu(); + dev->queues[1] = nvme_create_queue(dev, 1, NVME_Q_DEPTH, this_cpu); + put_cpu(); + if (!dev->queues[1]) + return -ENOMEM; + dev->queue_count++; + + return 0; +} + +static void nvme_free_queues(struct nvme_dev *dev) +{ + int i; + + for (i = dev->queue_count - 1; i >= 0; i--) + nvme_free_queue(dev, i); +} + +static int __devinit nvme_dev_add(struct nvme_dev *dev) +{ + int res, nn, i; + struct nvme_ns *ns, *next; + void *id; + dma_addr_t dma_addr; + struct nvme_command cid, crt; + + res = nvme_setup_io_queues(dev); + if (res) + return res; + + /* XXX: Switch to a SG list once prp2 works */ + id = dma_alloc_coherent(&dev->pci_dev->dev, 8192, &dma_addr, + GFP_KERNEL); + + memset(&cid, 0, sizeof(cid)); + cid.identify.opcode = nvme_admin_identify; + cid.identify.nsid = 0; + cid.identify.prp1 = cpu_to_le64(dma_addr); + cid.identify.cns = cpu_to_le32(1); + + res = nvme_submit_admin_cmd(dev, &cid, NULL); + if (res) { + res = -EIO; + goto out_free; + } + + nn = le32_to_cpup(&((struct nvme_id_ctrl *)id)->nn); + + cid.identify.cns = 0; + memset(&crt, 0, sizeof(crt)); + crt.features.opcode = nvme_admin_get_features; + crt.features.prp1 = cpu_to_le64(dma_addr + 4096); + crt.features.fid = cpu_to_le32(NVME_FEAT_LBA_RANGE); + + for (i = 0; i < nn; i++) { + cid.identify.nsid = cpu_to_le32(i); + res = nvme_submit_admin_cmd(dev, &cid, NULL); + if (res) + continue; + + if (((struct nvme_id_ns *)id)->ncap == 0) + continue; + + crt.features.nsid = cpu_to_le32(i); + res = nvme_submit_admin_cmd(dev, &crt, NULL); + if (res) + continue; + + ns = nvme_alloc_ns(dev, i, id, id + 4096); + if (ns) + list_add_tail(&ns->list, &dev->namespaces); + } + list_for_each_entry(ns, &dev->namespaces, list) + add_disk(ns->disk); + + dma_free_coherent(&dev->pci_dev->dev, 4096, id, dma_addr); + return 0; + + out_free: + list_for_each_entry_safe(ns, next, &dev->namespaces, list) { + list_del(&ns->list); + nvme_ns_free(ns); + } + + dma_free_coherent(&dev->pci_dev->dev, 4096, id, dma_addr); + return res; +} + +static int nvme_dev_remove(struct nvme_dev *dev) +{ + struct nvme_ns *ns, *next; + + /* TODO: wait all I/O finished or cancel them */ + + list_for_each_entry_safe(ns, next, &dev->namespaces, list) { + list_del(&ns->list); + del_gendisk(ns->disk); + nvme_ns_free(ns); + } + + nvme_free_queues(dev); + + return 0; +} + +/* XXX: Use an ida or something to let remove / add work correctly */ +static void nvme_set_instance(struct nvme_dev *dev) +{ + static int instance; + dev->instance = instance++; +} + +static void nvme_release_instance(struct nvme_dev *dev) +{ +} + +static int __devinit nvme_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + int result = -ENOMEM; + struct nvme_dev *dev; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + dev->entry = kcalloc(num_possible_cpus(), sizeof(*dev->entry), + GFP_KERNEL); + if (!dev->entry) + goto free; + dev->queues = kcalloc(2, sizeof(void *), GFP_KERNEL); + if (!dev->queues) + goto free; + + INIT_LIST_HEAD(&dev->namespaces); + dev->pci_dev = pdev; + pci_set_drvdata(pdev, dev); + dma_set_mask(&dev->pci_dev->dev, DMA_BIT_MASK(64)); + nvme_set_instance(dev); + + dev->bar = ioremap(pci_resource_start(pdev, 0), 8192); + if (!dev->bar) { + result = -ENOMEM; + goto disable; + } + + result = nvme_configure_admin_queue(dev); + if (result) + goto unmap; + dev->queue_count++; + + result = nvme_dev_add(dev); + if (result) + goto delete; + return 0; + + delete: + nvme_free_queues(dev); + unmap: + iounmap(dev->bar); + disable: + pci_disable_msix(pdev); + nvme_release_instance(dev); + free: + kfree(dev->queues); + kfree(dev->entry); + kfree(dev); + return result; +} + +static void __devexit nvme_remove(struct pci_dev *pdev) +{ + struct nvme_dev *dev = pci_get_drvdata(pdev); + nvme_dev_remove(dev); + pci_disable_msix(pdev); + iounmap(dev->bar); + nvme_release_instance(dev); + kfree(dev->queues); + kfree(dev->entry); + kfree(dev); +} + +/* These functions are yet to be implemented */ +#define nvme_error_detected NULL +#define nvme_dump_registers NULL +#define nvme_link_reset NULL +#define nvme_slot_reset NULL +#define nvme_error_resume NULL +#define nvme_suspend NULL +#define nvme_resume NULL + +static struct pci_error_handlers nvme_err_handler = { + .error_detected = nvme_error_detected, + .mmio_enabled = nvme_dump_registers, + .link_reset = nvme_link_reset, + .slot_reset = nvme_slot_reset, + .resume = nvme_error_resume, +}; + +/* Move to pci_ids.h later */ +#define PCI_CLASS_STORAGE_EXPRESS 0x010802 + +static DEFINE_PCI_DEVICE_TABLE(nvme_id_table) = { + { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) }, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, nvme_id_table); + +static struct pci_driver nvme_driver = { + .name = "nvme", + .id_table = nvme_id_table, + .probe = nvme_probe, + .remove = __devexit_p(nvme_remove), + .suspend = nvme_suspend, + .resume = nvme_resume, + .err_handler = &nvme_err_handler, +}; + +static int __init nvme_init(void) +{ + int result; + + nvme_major = register_blkdev(nvme_major, "nvme"); + if (nvme_major <= 0) + return -EBUSY; + + result = pci_register_driver(&nvme_driver); + if (!result) + return 0; + + unregister_blkdev(nvme_major, "nvme"); + return result; +} + +static void __exit nvme_exit(void) +{ + pci_unregister_driver(&nvme_driver); + unregister_blkdev(nvme_major, "nvme"); +} + +MODULE_AUTHOR("Matthew Wilcox "); +MODULE_LICENSE("GPL"); +MODULE_VERSION("0.1"); +module_init(nvme_init); +module_exit(nvme_exit); diff --git a/include/linux/nvme.h b/include/linux/nvme.h new file mode 100644 index 0000000..9ba5358 --- /dev/null +++ b/include/linux/nvme.h @@ -0,0 +1,343 @@ +/* + * Definitions for the NVM Express interface + * Copyright (c) 2011, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _LINUX_NVME_H +#define _LINUX_NVME_H + +#include + +struct nvme_bar { + __u64 cap; /* Controller Capabilities */ + __u32 vs; /* Version */ + __u32 ims; /* Interrupt Mask Set */ + __u32 imc; /* Interrupt Mask Clear */ + __u32 cc; /* Controller Configuration */ + __u32 csts; /* Controller Status */ + __u32 aqa; /* Admin Queue Attributes */ + __u64 asq; /* Admin SQ Base Address */ + __u64 acq; /* Admin CQ Base Address */ +}; + +enum { + NVME_CC_ENABLE = 1 << 0, + NVME_CC_CSS_NVM = 0 << 4, + NVME_CC_MPS_SHIFT = 7, + NVME_CC_ARB_RR = 0 << 11, + NVME_CC_ARB_WRRU = 1 << 11, + NVME_CC_ARB_VS = 3 << 11, + NVME_CC_SHN_NONE = 0 << 13, + NVME_CC_SHN_NORMAL = 1 << 13, + NVME_CC_SHN_ABRUPT = 2 << 13, + NVME_CSTS_RDY = 1 << 0, + NVME_CSTS_CFS = 1 << 1, + NVME_CSTS_SHST_NORMAL = 0 << 2, + NVME_CSTS_SHST_OCCUR = 1 << 2, + NVME_CSTS_SHST_CMPLT = 2 << 2, +}; + +#define NVME_VS(major, minor) (major << 16 | minor) + +struct nvme_id_ctrl { + __le16 vid; + __le16 ssvid; + char sn[20]; + char mn[40]; + char fr[8]; + __le32 nn; + __u8 rab; + __u8 rsvd77[178]; + __le16 oacs; + __u8 acl; + __u8 aerl; + __u8 frmw; + __u8 lpa; + __u8 elpe; + __u8 npss; + __u8 rsvd264[248]; + __le64 psd[32]; + __le16 oncs; + __le16 fuses; + __u8 fna; + __u8 vwc; + __le16 awun; + __le16 awupf; + __u8 rsvd778[246]; + __u8 cmdset[2048]; + __u8 vs[1024]; +}; + +struct nvme_lbaf { + __le16 ms; + __u8 ds; + __u8 rp; +}; + +struct nvme_id_ns { + __le64 nsze; + __le64 ncap; + __le64 nuse; + __u8 nsfeat; + __u8 nlbaf; + __u8 flbas; + __u8 mc; + __u8 dpc; + __u8 dps; + __u8 rsvd30[98]; + struct nvme_lbaf lbaf[16]; + __u8 rsvd192[192]; + __u8 vs[3712]; +}; + +enum { + NVME_NS_FEAT_THIN = 1 << 0, + NVME_LBAF_RP_BEST = 0, + NVME_LBAF_RP_BETTER = 1, + NVME_LBAF_RP_GOOD = 2, + NVME_LBAF_RP_DEGRADED = 3, +}; + +struct nvme_lba_range_type { + __u8 type; + __u8 attributes; + __u8 rsvd2[14]; + __u64 slba; + __u64 nlb; + __u8 guid[16]; + __u8 rsvd48[16]; +}; + +enum { + NVME_LBART_TYPE_FS = 0x01, + NVME_LBART_TYPE_RAID = 0x02, + NVME_LBART_TYPE_CACHE = 0x03, + NVME_LBART_TYPE_SWAP = 0x04, + + NVME_LBART_ATTRIB_TEMP = 1 << 0, + NVME_LBART_ATTRIB_HIDE = 1 << 1, +}; + +/* I/O commands */ + +enum nvme_opcode { + nvme_cmd_flush = 0x00, + nvme_cmd_write = 0x01, + nvme_cmd_read = 0x02, + nvme_cmd_write_uncor = 0x04, + nvme_cmd_compare = 0x05, + nvme_cmd_dsm = 0x09, +}; + +struct nvme_rw_command { + __u8 opcode; + __u8 flags; + __u16 command_id; + __le32 nsid; + __u64 rsvd2; + __le64 metadata; + __le64 prp1; + __le64 prp2; + __le64 slba; + __le16 length; + __le16 control; + __le32 dsmgmt; + __le32 reftag; + __le16 apptag; + __le16 appmask; +}; + +enum { + NVME_RW_LR = 1 << 15, + NVME_RW_FUA = 1 << 14, + NVME_RW_DSM_FREQ_UNSPEC = 0, + NVME_RW_DSM_FREQ_TYPICAL = 1, + NVME_RW_DSM_FREQ_RARE = 2, + NVME_RW_DSM_FREQ_READS = 3, + NVME_RW_DSM_FREQ_WRITES = 4, + NVME_RW_DSM_FREQ_RW = 5, + NVME_RW_DSM_FREQ_ONCE = 6, + NVME_RW_DSM_FREQ_PREFETCH = 7, + NVME_RW_DSM_FREQ_TEMP = 8, + NVME_RW_DSM_LATENCY_NONE = 0 << 4, + NVME_RW_DSM_LATENCY_IDLE = 1 << 4, + NVME_RW_DSM_LATENCY_NORM = 2 << 4, + NVME_RW_DSM_LATENCY_LOW = 3 << 4, + NVME_RW_DSM_SEQ_REQ = 1 << 6, + NVME_RW_DSM_COMPRESSED = 1 << 7, +}; + +/* Admin commands */ + +enum nvme_admin_opcode { + nvme_admin_delete_sq = 0x00, + nvme_admin_create_sq = 0x01, + nvme_admin_get_features = 0x02, + nvme_admin_delete_cq = 0x04, + nvme_admin_create_cq = 0x05, + nvme_admin_identify = 0x06, + nvme_admin_abort_cmd = 0x08, + nvme_admin_set_features = 0x09, + nvme_admin_get_log_page = 0x0a, + nvme_admin_async_event = 0x0c, + nvme_admin_download_fw = 0x0d, + nvme_admin_security_recv = 0x0e, + nvme_admin_format_nvm = 0x10, + nvme_admin_security_send = 0x11, + nvme_admin_activate_fw = 0x14, +}; + +enum { + NVME_QUEUE_PHYS_CONTIG = (1 << 0), + NVME_CQ_IRQ_ENABLED = (1 << 1), + NVME_SQ_PRIO_URGENT = (0 << 1), + NVME_SQ_PRIO_HIGH = (1 << 1), + NVME_SQ_PRIO_MEDIUM = (2 << 1), + NVME_SQ_PRIO_LOW = (3 << 1), + NVME_FEAT_ARBITRATION = 0x01, + NVME_FEAT_POWER_MGMT = 0x02, + NVME_FEAT_LBA_RANGE = 0x03, + NVME_FEAT_TEMP_THRESH = 0x04, + NVME_FEAT_ERR_RECOVERY = 0x05, + NVME_FEAT_VOLATILE_WC = 0x06, + NVME_FEAT_NUM_QUEUES = 0x07, + NVME_FEAT_IRQ_COALESCE = 0x08, + NVME_FEAT_IRQ_CONFIG = 0x09, + NVME_FEAT_WRITE_ATOMIC = 0x0a, + NVME_FEAT_ASYNC_EVENT = 0x0b, + NVME_FEAT_SW_PROGRESS = 0x0c, +}; + +struct nvme_identify { + __u8 opcode; + __u8 flags; + __u16 command_id; + __le32 nsid; + __u64 rsvd2[2]; + __le64 prp1; + __le64 prp2; + __le32 cns; + __u32 rsvd11[5]; +}; + +struct nvme_features { + __u8 opcode; + __u8 flags; + __u16 command_id; + __le32 nsid; + __u64 rsvd2[2]; + __le64 prp1; + __le64 prp2; + __le32 fid; + __le32 dword11; + __u32 rsvd12[4]; +}; + +struct nvme_create_cq { + __u8 opcode; + __u8 flags; + __u16 command_id; + __le32 rsvd1[5]; + __le64 prp1; + __u64 rsvd8; + __le16 cqid; + __le16 qsize; + __le16 cq_flags; + __le16 irq_vector; + __u32 rsvd12[4]; +}; + +struct nvme_create_sq { + __u8 opcode; + __u8 flags; + __u16 command_id; + __le32 rsvd1[5]; + __le64 prp1; + __u64 rsvd8; + __le16 sqid; + __le16 qsize; + __le16 sq_flags; + __le16 cqid; + __le32 rsvd12[4]; +}; + +struct nvme_delete_queue { + __u8 opcode; + __u8 flags; + __u16 command_id; + __u32 rsvd1[9]; + __le16 qid; + __le16 rsvd10; + __le32 rsvd11[5]; +}; + +struct nvme_common_command { + __u8 opcode; + __u8 flags; + __u16 command_id; + __le32 nsid; + __u32 rsvd2[14]; +}; + +struct nvme_command { + union { + struct nvme_common_command common; + struct nvme_rw_command rw; + struct nvme_identify identify; + struct nvme_features features; + struct nvme_create_cq create_cq; + struct nvme_create_sq create_sq; + struct nvme_delete_queue delete_queue; + }; +}; + +/* XXX: Sync with spec */ +enum { + NVME_SC_SUCCESS = 0x0, + NVME_SC_INVALID_OPCODE = 0x1, + NVME_SC_INVALID_FIELD = 0x2, + NVME_SC_CMDID_CONFLICT = 0x3, + NVME_SC_DATA_XFER_ERROR = 0x4, + NVME_SC_POWER_LOSS = 0x5, + NVME_SC_INTERNAL = 0x6, + NVME_SC_ABORT_REQ = 0x7, + NVME_SC_ABORT_QUEUE = 0x8, + NVME_SC_FUSED_FAIL = 0x9, + NVME_SC_FUSED_MISSING = 0xa, + NVME_SC_LBA_RANGE = 0x80, + NVME_SC_CAP_EXCEEDED = 0x81, + NVME_SC_NS_NOT_READY = 0x82, + NVME_SC_CQ_INVALID = 0x100, + NVME_SC_QID_INVALID = 0x101, + NVME_SC_QUEUE_SIZE = 0x102, + NVME_SC_WRITE_FAULT = 0x280, + NVME_SC_READ_ERROR = 0x281, +}; + +struct nvme_completion { + __le32 result; /* Used by admin commands to return data */ + __le32 rsvd; + __le16 sq_head; /* how much of this queue may be reclaimed */ + __le16 sq_id; /* submission queue that generated this entry */ + __u16 command_id; /* of the command which completed */ + __le16 status; /* did the command fail, and if so, why? */ +}; + +#define NVME_IOCTL_IDENTIFY_NS _IOW('N', 0x40, struct nvme_id_ns) +#define NVME_IOCTL_IDENTIFY_CTRL _IOW('N', 0x41, struct nvme_id_ctrl) +#define NVME_IOCTL_GET_RANGE_TYPE _IOW('N', 0x42, struct nvme_lba_range_type) + +#endif /* _LINUX_NVME_H */ -- cgit v0.10.2 From 3001082cac4bf6ffd09f72b39e6292ad6394ef17 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 20 Jan 2011 09:10:15 -0500 Subject: NVMe: Factor out queue_request_irq() Two callers with an almost identical long string of arguments, and introducing a third soon. Time to factor out the commonalities. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index ef66ecc..b10e064 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -568,6 +568,13 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid, return NULL; } +static int queue_request_irq(struct nvme_dev *dev, struct nvme_queue *nvmeq, + const char *name) +{ + return request_irq(dev->entry[nvmeq->cq_vector].vector, nvme_irq, + IRQF_DISABLED | IRQF_SHARED, name, nvmeq); +} + static __devinit struct nvme_queue *nvme_create_queue(struct nvme_dev *dev, int qid, int cq_size, int vector) { @@ -582,8 +589,7 @@ static __devinit struct nvme_queue *nvme_create_queue(struct nvme_dev *dev, if (result < 0) goto release_cq; - result = request_irq(dev->entry[vector].vector, nvme_irq, - IRQF_DISABLED | IRQF_SHARED, "nvme", nvmeq); + result = queue_request_irq(dev, nvmeq, "nvme"); if (result < 0) goto release_sq; @@ -630,8 +636,7 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) return -EINTR; } - result = request_irq(dev->entry[0].vector, nvme_irq, - IRQF_DISABLED | IRQF_SHARED, "nvme admin", nvmeq); + result = queue_request_irq(dev, nvmeq, "nvme admin"); dev->queues[0] = nvmeq; return result; } -- cgit v0.10.2 From b3b06812e199f248561ce7824a4a8a9cd573c05a Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 20 Jan 2011 09:14:34 -0500 Subject: NVMe: Reduce set_queue_count arguments by one sq_count and cq_count are always the same, so just call it 'count'. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index b10e064..7efd7e9 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -777,12 +777,12 @@ static void nvme_ns_free(struct nvme_ns *ns) kfree(ns); } -static int set_queue_count(struct nvme_dev *dev, int sq_count, int cq_count) +static int set_queue_count(struct nvme_dev *dev, int count) { int status; u32 result; struct nvme_command c; - u32 q_count = (sq_count - 1) | ((cq_count - 1) << 16); + u32 q_count = (count - 1) | ((count - 1) << 16); memset(&c, 0, sizeof(c)); c.features.opcode = nvme_admin_get_features; @@ -800,7 +800,7 @@ static int __devinit nvme_setup_io_queues(struct nvme_dev *dev) { int this_cpu; - set_queue_count(dev, 1, 1); + set_queue_count(dev, 1); this_cpu = get_cpu(); dev->queues[1] = nvme_create_queue(dev, 1, NVME_Q_DEPTH, this_cpu); -- cgit v0.10.2 From 1b23484bd012c078de2ea939249e2fb2e85a0a6e Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 20 Jan 2011 13:01:49 -0500 Subject: NVMe: Implement per-CPU queues Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 7efd7e9..b6a213c 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -172,11 +172,17 @@ static unsigned long free_cmdid(struct nvme_queue *nvmeq, int cmdid) static struct nvme_queue *get_nvmeq(struct nvme_ns *ns) { - return ns->dev->queues[1]; + int qid, cpu = get_cpu(); + if (cpu < ns->dev->queue_count) + qid = cpu + 1; + else + qid = (cpu % rounddown_pow_of_two(ns->dev->queue_count)) + 1; + return ns->dev->queues[qid]; } static void put_nvmeq(struct nvme_queue *nvmeq) { + put_cpu(); } /** @@ -795,19 +801,51 @@ static int set_queue_count(struct nvme_dev *dev, int count) return min(result & 0xffff, result >> 16) + 1; } -/* XXX: Create per-CPU queues */ static int __devinit nvme_setup_io_queues(struct nvme_dev *dev) { - int this_cpu; + int result, cpu, i, nr_queues; - set_queue_count(dev, 1); + nr_queues = num_online_cpus(); + result = set_queue_count(dev, nr_queues); + if (result < 0) + return result; + if (result < nr_queues) + nr_queues = result; - this_cpu = get_cpu(); - dev->queues[1] = nvme_create_queue(dev, 1, NVME_Q_DEPTH, this_cpu); - put_cpu(); - if (!dev->queues[1]) - return -ENOMEM; - dev->queue_count++; + /* Deregister the admin queue's interrupt */ + free_irq(dev->entry[0].vector, dev->queues[0]); + + for (i = 0; i < nr_queues; i++) + dev->entry[i].entry = i; + for (;;) { + result = pci_enable_msix(dev->pci_dev, dev->entry, nr_queues); + if (result == 0) { + break; + } else if (result > 0) { + nr_queues = result; + continue; + } else { + nr_queues = 1; + break; + } + } + + result = queue_request_irq(dev, dev->queues[0], "nvme admin"); + /* XXX: handle failure here */ + + cpu = cpumask_first(cpu_online_mask); + for (i = 0; i < nr_queues; i++) { + irq_set_affinity_hint(dev->entry[i].vector, get_cpu_mask(cpu)); + cpu = cpumask_next(cpu, cpu_online_mask); + } + + for (i = 0; i < nr_queues; i++) { + dev->queues[i + 1] = nvme_create_queue(dev, i + 1, + NVME_Q_DEPTH, i); + if (!dev->queues[i + 1]) + return -ENOMEM; + dev->queue_count++; + } return 0; } @@ -931,7 +969,8 @@ static int __devinit nvme_probe(struct pci_dev *pdev, GFP_KERNEL); if (!dev->entry) goto free; - dev->queues = kcalloc(2, sizeof(void *), GFP_KERNEL); + dev->queues = kcalloc(num_possible_cpus() + 1, sizeof(void *), + GFP_KERNEL); if (!dev->queues) goto free; -- cgit v0.10.2 From 821234603b265f59d7eebce16d9e8beca2a5752d Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 20 Jan 2011 13:24:06 -0500 Subject: NVMe: Rename 'cycle' to 'phase' It's called the phase bit in the current draft Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index b6a213c..3d917a8 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -93,7 +93,7 @@ struct nvme_queue { u16 sq_head; u16 sq_tail; u16 cq_head; - u16 cq_cycle; + u16 cq_phase; unsigned long cmdid_data[]; }; @@ -364,7 +364,7 @@ typedef void (*completion_fn)(struct nvme_queue *, void *, static irqreturn_t nvme_process_cq(struct nvme_queue *nvmeq) { - u16 head, cycle; + u16 head, phase; static const completion_fn completions[4] = { [sync_completion_id] = sync_completion, @@ -372,19 +372,19 @@ static irqreturn_t nvme_process_cq(struct nvme_queue *nvmeq) }; head = nvmeq->cq_head; - cycle = nvmeq->cq_cycle; + phase = nvmeq->cq_phase; for (;;) { unsigned long data; void *ptr; unsigned char handler; struct nvme_completion cqe = nvmeq->cqes[head]; - if ((le16_to_cpu(cqe.status) & 1) != cycle) + if ((le16_to_cpu(cqe.status) & 1) != phase) break; nvmeq->sq_head = le16_to_cpu(cqe.sq_head); if (++head == nvmeq->q_depth) { head = 0; - cycle = !cycle; + phase = !phase; } data = free_cmdid(nvmeq, cqe.command_id); @@ -399,12 +399,12 @@ static irqreturn_t nvme_process_cq(struct nvme_queue *nvmeq) * requires that 0.1% of your interrupts are handled, so this isn't * a big problem. */ - if (head == nvmeq->cq_head && cycle == nvmeq->cq_cycle) + if (head == nvmeq->cq_head && phase == nvmeq->cq_phase) return IRQ_NONE; writel(head, nvmeq->q_db + 1); nvmeq->cq_head = head; - nvmeq->cq_cycle = cycle; + nvmeq->cq_phase = phase; return IRQ_HANDLED; } @@ -557,7 +557,7 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid, nvmeq->q_dmadev = dmadev; spin_lock_init(&nvmeq->q_lock); nvmeq->cq_head = 0; - nvmeq->cq_cycle = 1; + nvmeq->cq_phase = 1; init_waitqueue_head(&nvmeq->sq_full); bio_list_init(&nvmeq->sq_cong); nvmeq->q_db = &dev->dbs[qid * 2]; -- cgit v0.10.2 From 53c9577e9ca68a633c6e9df2b54eaecacfa77f62 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 20 Jan 2011 13:42:34 -0500 Subject: NVMe: Fix admin IRQ claim on real hardware The admin IRQ is supposed to use the pin-based (or single message MSI) interrupt. Accomplish this by filling in entry[0]'s vector with the INTx irq number. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 3d917a8..44a9d5e 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -979,6 +979,7 @@ static int __devinit nvme_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, dev); dma_set_mask(&dev->pci_dev->dev, DMA_BIT_MASK(64)); nvme_set_instance(dev); + dev->entry[0].vector = pdev->irq; dev->bar = ioremap(pci_resource_start(pdev, 0), 8192); if (!dev->bar) { -- cgit v0.10.2 From 36c14ed9caa957c686d4a48fd598a5ec2aa0331b Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 24 Jan 2011 07:52:07 -0500 Subject: NVMe: Use PRP2 for the nvme_identify ioctl DMA the result straight to userspace instead of bounce-buffering in the kernel. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 44a9d5e..c0ef1dd 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -647,33 +647,57 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) return result; } -static int nvme_identify(struct nvme_ns *ns, void __user *addr, int cns) +static int nvme_identify(struct nvme_ns *ns, unsigned long addr, int cns) { struct nvme_dev *dev = ns->dev; - int status; + int i, err, count, nents, offset; struct nvme_command c; - void *page; - dma_addr_t dma_addr; - - page = dma_alloc_coherent(&dev->pci_dev->dev, 4096, &dma_addr, - GFP_KERNEL); + struct scatterlist sg[2]; + struct page *pages[2]; + + if (addr & 3) + return -EINVAL; + offset = offset_in_page(addr); + count = offset ? 2 : 1; + + err = get_user_pages_fast(addr, count, 1, pages); + if (err < count) { + count = err; + err = -EFAULT; + goto put_pages; + } + sg_init_table(sg, count); + for (i = 0; i < count; i++) + sg_set_page(&sg[i], pages[i], PAGE_SIZE, 0); + nents = dma_map_sg(&dev->pci_dev->dev, sg, count, DMA_FROM_DEVICE); + if (!nents) + goto put_pages; memset(&c, 0, sizeof(c)); c.identify.opcode = nvme_admin_identify; c.identify.nsid = cns ? 0 : cpu_to_le32(ns->ns_id); - c.identify.prp1 = cpu_to_le64(dma_addr); + c.identify.prp1 = cpu_to_le64(sg_dma_address(&sg[0]) + offset); + if (count > 1) { + u64 dma_addr; + if (nents > 1) + dma_addr = sg_dma_address(&sg[1]); + else + dma_addr = sg_dma_address(&sg[0]) + PAGE_SIZE; + c.identify.prp2 = cpu_to_le64(dma_addr); + } c.identify.cns = cpu_to_le32(cns); - status = nvme_submit_admin_cmd(dev, &c, NULL); + err = nvme_submit_admin_cmd(dev, &c, NULL); - if (status) - status = -EIO; - else if (copy_to_user(addr, page, 4096)) - status = -EFAULT; + if (err) + err = -EIO; - dma_free_coherent(&dev->pci_dev->dev, 4096, page, dma_addr); + dma_unmap_sg(&dev->pci_dev->dev, sg, nents, DMA_FROM_DEVICE); + put_pages: + for (i = 0; i < count; i++) + put_page(pages[i]); - return status; + return err; } static int nvme_get_range_type(struct nvme_ns *ns, void __user *addr) @@ -713,9 +737,9 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, switch (cmd) { case NVME_IOCTL_IDENTIFY_NS: - return nvme_identify(ns, (void __user *)arg, 0); + return nvme_identify(ns, arg, 0); case NVME_IOCTL_IDENTIFY_CTRL: - return nvme_identify(ns, (void __user *)arg, 1); + return nvme_identify(ns, arg, 1); case NVME_IOCTL_GET_RANGE_TYPE: return nvme_get_range_type(ns, (void __user *)arg); default: -- cgit v0.10.2 From 7b4fe9b1cb4b9a6f4ae23a12ef96d08d96e2a5da Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 26 Jan 2011 10:01:21 -0500 Subject: NVMe: Make nvme_common_command more featureful Add prp1, prp2 and the metadata prp to the common command, since the fields are generally used this way. Signed-off-by: Matthew Wilcox diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 9ba5358..1c0b5ef 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -142,6 +142,18 @@ enum nvme_opcode { nvme_cmd_dsm = 0x09, }; +struct nvme_common_command { + __u8 opcode; + __u8 flags; + __u16 command_id; + __le32 nsid; + __u64 rsvd2; + __le64 metadata; + __le64 prp1; + __le64 prp2; + __u32 rsvd10[6]; +}; + struct nvme_rw_command { __u8 opcode; __u8 flags; @@ -284,14 +296,6 @@ struct nvme_delete_queue { __le32 rsvd11[5]; }; -struct nvme_common_command { - __u8 opcode; - __u8 flags; - __u16 command_id; - __le32 nsid; - __u32 rsvd2[14]; -}; - struct nvme_command { union { struct nvme_common_command common; -- cgit v0.10.2 From ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 26 Jan 2011 10:02:29 -0500 Subject: NVMe: Add nvme_setup_prps() Generalise the code from nvme_identify() that sets PRP1 & PRP2 so that it's usable for commands sent by nvme_submit_bio_queue(). Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index c0ef1dd..1e57737 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -240,6 +240,36 @@ static void bio_completion(struct nvme_queue *nvmeq, void *ctx, bio_endio(bio, status ? -EIO : 0); } +/* length is in bytes */ +static void nvme_setup_prps(struct nvme_common_command *cmd, + struct scatterlist *sg, int length) +{ + int dma_len = sg_dma_len(sg); + u64 dma_addr = sg_dma_address(sg); + int offset = offset_in_page(dma_addr); + + cmd->prp1 = cpu_to_le64(dma_addr); + length -= (PAGE_SIZE - offset); + if (length <= 0) + return; + + dma_len -= (PAGE_SIZE - offset); + if (dma_len) { + dma_addr += (PAGE_SIZE - offset); + } else { + sg = sg_next(sg); + dma_addr = sg_dma_address(sg); + dma_len = sg_dma_len(sg); + } + + if (length <= PAGE_SIZE) { + cmd->prp2 = cpu_to_le64(dma_addr); + return; + } + + /* XXX: support PRP lists */ +} + static int nvme_map_bio(struct device *dev, struct nvme_req_info *info, struct bio *bio, enum dma_data_direction dma_dir, int psegs) { @@ -261,7 +291,7 @@ static int nvme_map_bio(struct device *dev, struct nvme_req_info *info, static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, struct bio *bio) { - struct nvme_rw_command *cmnd; + struct nvme_command *cmnd; struct nvme_req_info *info; enum dma_data_direction dma_dir; int cmdid; @@ -290,27 +320,26 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, dsmgmt |= NVME_RW_DSM_FREQ_PREFETCH; spin_lock_irqsave(&nvmeq->q_lock, flags); - cmnd = &nvmeq->sq_cmds[nvmeq->sq_tail].rw; + cmnd = &nvmeq->sq_cmds[nvmeq->sq_tail]; if (bio_data_dir(bio)) { - cmnd->opcode = nvme_cmd_write; + cmnd->rw.opcode = nvme_cmd_write; dma_dir = DMA_TO_DEVICE; } else { - cmnd->opcode = nvme_cmd_read; + cmnd->rw.opcode = nvme_cmd_read; dma_dir = DMA_FROM_DEVICE; } nvme_map_bio(nvmeq->q_dmadev, info, bio, dma_dir, psegs); - cmnd->flags = 1; - cmnd->command_id = cmdid; - cmnd->nsid = cpu_to_le32(ns->ns_id); - cmnd->prp1 = cpu_to_le64(sg_phys(info->sg)); - /* XXX: Support more than one PRP */ - cmnd->slba = cpu_to_le64(bio->bi_sector >> (ns->lba_shift - 9)); - cmnd->length = cpu_to_le16((bio->bi_size >> ns->lba_shift) - 1); - cmnd->control = cpu_to_le16(control); - cmnd->dsmgmt = cpu_to_le32(dsmgmt); + cmnd->rw.flags = 1; + cmnd->rw.command_id = cmdid; + cmnd->rw.nsid = cpu_to_le32(ns->ns_id); + nvme_setup_prps(&cmnd->common, info->sg, bio->bi_size); + cmnd->rw.slba = cpu_to_le64(bio->bi_sector >> (ns->lba_shift - 9)); + cmnd->rw.length = cpu_to_le16((bio->bi_size >> ns->lba_shift) - 1); + cmnd->rw.control = cpu_to_le16(control); + cmnd->rw.dsmgmt = cpu_to_le32(dsmgmt); writel(nvmeq->sq_tail, nvmeq->q_db); if (++nvmeq->sq_tail == nvmeq->q_depth) @@ -667,8 +696,9 @@ static int nvme_identify(struct nvme_ns *ns, unsigned long addr, int cns) goto put_pages; } sg_init_table(sg, count); - for (i = 0; i < count; i++) - sg_set_page(&sg[i], pages[i], PAGE_SIZE, 0); + sg_set_page(&sg[0], pages[0], PAGE_SIZE - offset, offset); + if (count > 1) + sg_set_page(&sg[1], pages[1], offset, 0); nents = dma_map_sg(&dev->pci_dev->dev, sg, count, DMA_FROM_DEVICE); if (!nents) goto put_pages; @@ -676,15 +706,7 @@ static int nvme_identify(struct nvme_ns *ns, unsigned long addr, int cns) memset(&c, 0, sizeof(c)); c.identify.opcode = nvme_admin_identify; c.identify.nsid = cns ? 0 : cpu_to_le32(ns->ns_id); - c.identify.prp1 = cpu_to_le64(sg_dma_address(&sg[0]) + offset); - if (count > 1) { - u64 dma_addr; - if (nents > 1) - dma_addr = sg_dma_address(&sg[1]); - else - dma_addr = sg_dma_address(&sg[0]) + PAGE_SIZE; - c.identify.prp2 = cpu_to_le64(dma_addr); - } + nvme_setup_prps(&c.common, sg, 4096); c.identify.cns = cpu_to_le32(cns); err = nvme_submit_admin_cmd(dev, &c, NULL); -- cgit v0.10.2 From b8deb62cf271fa9381edc8cf52bcae2f0225c55a Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 26 Jan 2011 10:08:25 -0500 Subject: NVMe: Zero the command before we send it Make sure there's no left-over bits set from previous commands that used this slot. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 1e57737..25ca7af 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -322,6 +322,7 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, spin_lock_irqsave(&nvmeq->q_lock, flags); cmnd = &nvmeq->sq_cmds[nvmeq->sq_tail]; + memset(cmnd, 0, sizeof(*cmnd)); if (bio_data_dir(bio)) { cmnd->rw.opcode = nvme_cmd_write; dma_dir = DMA_TO_DEVICE; -- cgit v0.10.2 From bd38c5557cf482fc195e2264b32ea62eed60730a Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 26 Jan 2011 14:34:32 -0500 Subject: NVMe: Change NVME_IOCTL_GET_RANGE_TYPE to return all the ranges Factor out most of nvme_identify() into a new nvme_submit_user_admin_command() function. Change nvme_get_range_type() to call it and change nvme_ioctl to realise that it's getting back all 64 ranges. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 25ca7af..b28d188 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -677,18 +677,17 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) return result; } -static int nvme_identify(struct nvme_ns *ns, unsigned long addr, int cns) +static int nvme_submit_user_admin_command(struct nvme_dev *dev, unsigned long addr, + unsigned length, struct nvme_command *cmd) { - struct nvme_dev *dev = ns->dev; int i, err, count, nents, offset; - struct nvme_command c; struct scatterlist sg[2]; struct page *pages[2]; if (addr & 3) return -EINVAL; offset = offset_in_page(addr); - count = offset ? 2 : 1; + count = ((offset + length) > PAGE_SIZE) ? 2 : 1; err = get_user_pages_fast(addr, count, 1, pages); if (err < count) { @@ -704,13 +703,9 @@ static int nvme_identify(struct nvme_ns *ns, unsigned long addr, int cns) if (!nents) goto put_pages; - memset(&c, 0, sizeof(c)); - c.identify.opcode = nvme_admin_identify; - c.identify.nsid = cns ? 0 : cpu_to_le32(ns->ns_id); - nvme_setup_prps(&c.common, sg, 4096); - c.identify.cns = cpu_to_le32(cns); + nvme_setup_prps(&cmd->common, sg, length); - err = nvme_submit_admin_cmd(dev, &c, NULL); + err = nvme_submit_admin_cmd(dev, cmd, NULL); if (err) err = -EIO; @@ -723,34 +718,28 @@ static int nvme_identify(struct nvme_ns *ns, unsigned long addr, int cns) return err; } -static int nvme_get_range_type(struct nvme_ns *ns, void __user *addr) +static int nvme_identify(struct nvme_ns *ns, unsigned long addr, int cns) { - struct nvme_dev *dev = ns->dev; - int status; struct nvme_command c; - void *page; - dma_addr_t dma_addr; - page = dma_alloc_coherent(&dev->pci_dev->dev, 4096, &dma_addr, - GFP_KERNEL); + memset(&c, 0, sizeof(c)); + c.identify.opcode = nvme_admin_identify; + c.identify.nsid = cns ? 0 : cpu_to_le32(ns->ns_id); + c.identify.cns = cpu_to_le32(cns); + + return nvme_submit_user_admin_command(ns->dev, addr, 4096, &c); +} + +static int nvme_get_range_type(struct nvme_ns *ns, unsigned long addr) +{ + struct nvme_command c; memset(&c, 0, sizeof(c)); c.features.opcode = nvme_admin_get_features; c.features.nsid = cpu_to_le32(ns->ns_id); - c.features.prp1 = cpu_to_le64(dma_addr); c.features.fid = cpu_to_le32(NVME_FEAT_LBA_RANGE); - status = nvme_submit_admin_cmd(dev, &c, NULL); - - /* XXX: Assuming first range for now */ - if (status) - status = -EIO; - else if (copy_to_user(addr, page, 64)) - status = -EFAULT; - - dma_free_coherent(&dev->pci_dev->dev, 4096, page, dma_addr); - - return status; + return nvme_submit_user_admin_command(ns->dev, addr, 4096, &c); } static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, @@ -764,7 +753,7 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, case NVME_IOCTL_IDENTIFY_CTRL: return nvme_identify(ns, arg, 1); case NVME_IOCTL_GET_RANGE_TYPE: - return nvme_get_range_type(ns, (void __user *)arg); + return nvme_get_range_type(ns, arg); default: return -ENOTTY; } -- cgit v0.10.2 From 7fc3cdabba75c2516b8b645eb0ca7907aea70415 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 26 Jan 2011 17:05:50 -0500 Subject: NVMe: Create nvme_map_user_pages() and nvme_unmap_user_pages() These are generalisations of the code that was in nvme_submit_user_admin_command(). Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index b28d188..f44d6cd 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -677,17 +677,22 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) return result; } -static int nvme_submit_user_admin_command(struct nvme_dev *dev, unsigned long addr, - unsigned length, struct nvme_command *cmd) +static int nvme_map_user_pages(struct nvme_dev *dev, int write, + unsigned long addr, unsigned length, + struct scatterlist **sgp) { int i, err, count, nents, offset; - struct scatterlist sg[2]; - struct page *pages[2]; + struct scatterlist *sg; + struct page **pages; if (addr & 3) return -EINVAL; + if (!length) + return -EINVAL; + offset = offset_in_page(addr); - count = ((offset + length) > PAGE_SIZE) ? 2 : 1; + count = DIV_ROUND_UP(offset + length, PAGE_SIZE); + pages = kcalloc(count, sizeof(*pages), GFP_KERNEL); err = get_user_pages_fast(addr, count, 1, pages); if (err < count) { @@ -695,27 +700,60 @@ static int nvme_submit_user_admin_command(struct nvme_dev *dev, unsigned long ad err = -EFAULT; goto put_pages; } + + sg = kcalloc(count, sizeof(*sg), GFP_KERNEL); sg_init_table(sg, count); sg_set_page(&sg[0], pages[0], PAGE_SIZE - offset, offset); - if (count > 1) - sg_set_page(&sg[1], pages[1], offset, 0); - nents = dma_map_sg(&dev->pci_dev->dev, sg, count, DMA_FROM_DEVICE); + length -= (PAGE_SIZE - offset); + for (i = 1; i < count; i++) { + sg_set_page(&sg[i], pages[i], min_t(int, length, PAGE_SIZE), 0); + length -= PAGE_SIZE; + } + + err = -ENOMEM; + nents = dma_map_sg(&dev->pci_dev->dev, sg, count, + write ? DMA_TO_DEVICE : DMA_FROM_DEVICE); if (!nents) goto put_pages; - nvme_setup_prps(&cmd->common, sg, length); + kfree(pages); + *sgp = sg; + return nents; - err = nvme_submit_admin_cmd(dev, cmd, NULL); + put_pages: + for (i = 0; i < count; i++) + put_page(pages[i]); + kfree(pages); + return err; +} - if (err) - err = -EIO; +static void nvme_unmap_user_pages(struct nvme_dev *dev, int write, + unsigned long addr, int length, + struct scatterlist *sg, int nents) +{ + int i, count; + count = DIV_ROUND_UP(offset_in_page(addr) + length, PAGE_SIZE); dma_unmap_sg(&dev->pci_dev->dev, sg, nents, DMA_FROM_DEVICE); - put_pages: + for (i = 0; i < count; i++) - put_page(pages[i]); + put_page(sg_page(&sg[i])); +} - return err; +static int nvme_submit_user_admin_command(struct nvme_dev *dev, + unsigned long addr, unsigned length, + struct nvme_command *cmd) +{ + int err, nents; + struct scatterlist *sg; + + nents = nvme_map_user_pages(dev, 0, addr, length, &sg); + if (nents < 0) + return nents; + nvme_setup_prps(&cmd->common, sg, length); + err = nvme_submit_admin_cmd(dev, cmd, NULL); + nvme_unmap_user_pages(dev, 0, addr, length, sg, nents); + return err ? -EIO : 0; } static int nvme_identify(struct nvme_ns *ns, unsigned long addr, int cns) -- cgit v0.10.2 From a53295b6998f62d961c29e54051c1cf1d738c2b3 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 1 Feb 2011 16:13:29 -0500 Subject: NVMe: Add NVME_IOCTL_SUBMIT_IO Allow userspace to submit synchronous I/O like the SCSI sg interface does. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index f44d6cd..40fb2e1 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -780,6 +780,47 @@ static int nvme_get_range_type(struct nvme_ns *ns, unsigned long addr) return nvme_submit_user_admin_command(ns->dev, addr, 4096, &c); } +static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) +{ + struct nvme_dev *dev = ns->dev; + struct nvme_queue *nvmeq; + struct nvme_user_io io; + struct nvme_command c; + unsigned length; + u32 result; + int nents, status; + struct scatterlist *sg; + + if (copy_from_user(&io, uio, sizeof(io))) + return -EFAULT; + length = io.nblocks << io.block_shift; + nents = nvme_map_user_pages(dev, io.opcode & 1, io.addr, length, &sg); + if (nents < 0) + return nents; + + memset(&c, 0, sizeof(c)); + c.rw.opcode = io.opcode; + c.rw.flags = io.flags; + c.rw.nsid = cpu_to_le32(io.nsid); + c.rw.slba = cpu_to_le64(io.slba); + c.rw.length = cpu_to_le16(io.nblocks - 1); + c.rw.control = cpu_to_le16(io.control); + c.rw.dsmgmt = cpu_to_le16(io.dsmgmt); + c.rw.reftag = cpu_to_le32(io.reftag); /* XXX: endian? */ + c.rw.apptag = cpu_to_le16(io.apptag); + c.rw.appmask = cpu_to_le16(io.appmask); + /* XXX: metadata */ + nvme_setup_prps(&c.common, sg, length); + + nvmeq = get_nvmeq(ns); + status = nvme_submit_sync_cmd(nvmeq, &c, &result); + put_nvmeq(nvmeq); + + nvme_unmap_user_pages(dev, io.opcode & 1, io.addr, length, sg, nents); + put_user(result, &uio->result); + return status; +} + static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { @@ -792,6 +833,8 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, return nvme_identify(ns, arg, 1); case NVME_IOCTL_GET_RANGE_TYPE: return nvme_get_range_type(ns, arg); + case NVME_IOCTL_SUBMIT_IO: + return nvme_submit_io(ns, (void __user *)arg); default: return -ENOTTY; } diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 1c0b5ef..0aaecb0 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -340,8 +340,26 @@ struct nvme_completion { __le16 status; /* did the command fail, and if so, why? */ }; +struct nvme_user_io { + __u8 opcode; + __u8 flags; + __u16 control; + __u32 nsid; + __u64 metadata; + __u64 addr; + __u64 slba; + __u16 nblocks; + __u16 block_shift; + __u32 dsmgmt; + __u32 reftag; + __u16 apptag; + __u16 appmask; + __u32 result; +}; + #define NVME_IOCTL_IDENTIFY_NS _IOW('N', 0x40, struct nvme_id_ns) #define NVME_IOCTL_IDENTIFY_CTRL _IOW('N', 0x41, struct nvme_id_ctrl) #define NVME_IOCTL_GET_RANGE_TYPE _IOW('N', 0x42, struct nvme_lba_range_type) +#define NVME_IOCTL_SUBMIT_IO _IOWR('N', 0x43, struct nvme_rw_command) #endif /* _LINUX_NVME_H */ -- cgit v0.10.2 From 51814232ecae90f888c902e252306df8d017f0dd Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 1 Feb 2011 16:18:08 -0500 Subject: NVMe: Read the model, serial & firmware rev from the controller Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 40fb2e1..12e37c1 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -58,6 +58,9 @@ struct nvme_dev { struct msix_entry *entry; struct nvme_bar __iomem *bar; struct list_head namespaces; + char serial[20]; + char model[40]; + char firmware_rev[8]; }; /* @@ -979,6 +982,7 @@ static int __devinit nvme_dev_add(struct nvme_dev *dev) { int res, nn, i; struct nvme_ns *ns, *next; + struct nvme_id_ctrl *ctrl; void *id; dma_addr_t dma_addr; struct nvme_command cid, crt; @@ -1003,7 +1007,11 @@ static int __devinit nvme_dev_add(struct nvme_dev *dev) goto out_free; } - nn = le32_to_cpup(&((struct nvme_id_ctrl *)id)->nn); + ctrl = id; + nn = le32_to_cpup(&ctrl->nn); + memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn)); + memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn)); + memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr)); cid.identify.cns = 0; memset(&crt, 0, sizeof(crt)); -- cgit v0.10.2 From 8e9f0e71150bf6277d0ea40bc8feb1338ddf13fd Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 31 Jan 2011 10:46:14 -0500 Subject: NVMe: Remove 'node' from nvme_dev We don't keep a list of nvme_dev any more Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 12e37c1..9377cf3 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -48,7 +48,6 @@ module_param(nvme_major, int, 0); * Represents an NVM Express device. Each nvme_dev is a PCI function. */ struct nvme_dev { - struct list_head node; struct nvme_queue **queues; u32 __iomem *dbs; struct pci_dev *pci_dev; -- cgit v0.10.2 From 3f85d50b609e8a5ef151656210203a6e94c19538 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 1 Feb 2011 08:39:04 -0500 Subject: NVMe: Check returns from nvme_alloc_queue() It can return NULL, so handle that. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 9377cf3..dc82177 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -619,6 +619,9 @@ static __devinit struct nvme_queue *nvme_create_queue(struct nvme_dev *dev, int result; struct nvme_queue *nvmeq = nvme_alloc_queue(dev, qid, cq_size, vector); + if (!nvmeq) + return NULL; + result = adapter_alloc_cq(dev, qid, nvmeq); if (result < 0) goto free_nvmeq; @@ -655,6 +658,8 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) dev->dbs = ((void __iomem *)dev->bar) + 4096; nvmeq = nvme_alloc_queue(dev, 0, 64, 0); + if (!nvmeq) + return -ENOMEM; aqa = nvmeq->q_depth - 1; aqa |= aqa << 16; -- cgit v0.10.2 From 0ee5a7d7cb9309bd393a25c395f19fb12a842602 Mon Sep 17 00:00:00 2001 From: Shane Michael Matthews Date: Tue, 1 Feb 2011 08:49:30 -0500 Subject: NVMe: Enable and disable the PCI device Call pci_enable_device_mem() at initialisation and pci_disable_device at exit. Signed-off-by: Shane Michael Matthews Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index dc82177..1dda4b5 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1103,6 +1103,9 @@ static int __devinit nvme_probe(struct pci_dev *pdev, if (!dev->queues) goto free; + if (pci_enable_device_mem(pdev)) + goto free; + INIT_LIST_HEAD(&dev->namespaces); dev->pci_dev = pdev; pci_set_drvdata(pdev, dev); @@ -1133,6 +1136,7 @@ static int __devinit nvme_probe(struct pci_dev *pdev, disable: pci_disable_msix(pdev); nvme_release_instance(dev); + pci_disable_device(pdev); free: kfree(dev->queues); kfree(dev->entry); @@ -1147,6 +1151,7 @@ static void __devexit nvme_remove(struct pci_dev *pdev) pci_disable_msix(pdev); iounmap(dev->bar); nvme_release_instance(dev); + pci_disable_device(pdev); kfree(dev->queues); kfree(dev->entry); kfree(dev); -- cgit v0.10.2 From f64d3365a3e5cb46e69db7e2c82a7cb9a5bed1b8 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 1 Feb 2011 09:01:59 -0500 Subject: NVMe: Enable device DMA Need to call pci_set_master() to enable device DMA Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 1dda4b5..128fd70 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1105,6 +1105,7 @@ static int __devinit nvme_probe(struct pci_dev *pdev, if (pci_enable_device_mem(pdev)) goto free; + pci_set_master(pdev); INIT_LIST_HEAD(&dev->namespaces); dev->pci_dev = pdev; -- cgit v0.10.2 From 2930353f9f2b9e4629e935acd970cb73c1171229 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 1 Feb 2011 16:23:39 -0500 Subject: NVMe: Allow queues to be allocated above 4GB Need to call dma_set_coherent_mask() to allow queues to be allocated above 4GB. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 128fd70..46f8720 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1110,7 +1110,8 @@ static int __devinit nvme_probe(struct pci_dev *pdev, INIT_LIST_HEAD(&dev->namespaces); dev->pci_dev = pdev; pci_set_drvdata(pdev, dev); - dma_set_mask(&dev->pci_dev->dev, DMA_BIT_MASK(64)); + dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); + dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); nvme_set_instance(dev); dev->entry[0].vector = pdev->irq; -- cgit v0.10.2 From 574e8b95bc3780e10e9b5e9d51074d503dd3d5d9 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 1 Feb 2011 16:24:35 -0500 Subject: NVMe: Request I/O regions Calling pci_request_selected_regions() reserves these regions for our use. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 46f8720..bda9117 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1088,7 +1088,7 @@ static void nvme_release_instance(struct nvme_dev *dev) static int __devinit nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - int result = -ENOMEM; + int bars, result = -ENOMEM; struct nvme_dev *dev; dev = kzalloc(sizeof(*dev), GFP_KERNEL); @@ -1106,6 +1106,9 @@ static int __devinit nvme_probe(struct pci_dev *pdev, if (pci_enable_device_mem(pdev)) goto free; pci_set_master(pdev); + bars = pci_select_bars(pdev, IORESOURCE_MEM); + if (pci_request_selected_regions(pdev, bars, "nvme")) + goto disable; INIT_LIST_HEAD(&dev->namespaces); dev->pci_dev = pdev; @@ -1118,7 +1121,7 @@ static int __devinit nvme_probe(struct pci_dev *pdev, dev->bar = ioremap(pci_resource_start(pdev, 0), 8192); if (!dev->bar) { result = -ENOMEM; - goto disable; + goto disable_msix; } result = nvme_configure_admin_queue(dev); @@ -1135,10 +1138,12 @@ static int __devinit nvme_probe(struct pci_dev *pdev, nvme_free_queues(dev); unmap: iounmap(dev->bar); - disable: + disable_msix: pci_disable_msix(pdev); nvme_release_instance(dev); + disable: pci_disable_device(pdev); + pci_release_regions(pdev); free: kfree(dev->queues); kfree(dev->entry); @@ -1154,6 +1159,7 @@ static void __devexit nvme_remove(struct pci_dev *pdev) iounmap(dev->bar); nvme_release_instance(dev); pci_disable_device(pdev); + pci_release_regions(pdev); kfree(dev->queues); kfree(dev->entry); kfree(dev); -- cgit v0.10.2 From 5911f20039ce59d7e7834f0c42151cf759b6f786 Mon Sep 17 00:00:00 2001 From: Shane Michael Matthews Date: Tue, 1 Feb 2011 11:31:55 -0500 Subject: NVMe: Disable the device before we write the admin queues In case the card has been left in a partially-configured state, write 0 to the Enable bit. Signed-off-by: Shane Michael Matthews Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index bda9117..e3d9215 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -668,6 +668,7 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) dev->ctrl_config |= (PAGE_SHIFT - 12) << NVME_CC_MPS_SHIFT; dev->ctrl_config |= NVME_CC_ARB_RR | NVME_CC_SHN_NONE; + writel(0, &dev->bar->cc); writel(aqa, &dev->bar->aqa); writeq(nvmeq->sq_dma_addr, &dev->bar->asq); writeq(nvmeq->cq_dma_addr, &dev->bar->acq); -- cgit v0.10.2 From 388f037f4e7f0a24bac6b1a24f144f5d939f58cf Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 1 Feb 2011 12:49:38 -0500 Subject: NVMe: Move sysfs entries to the right place Because I wasn't setting driverfs_dev, the devices were showing up under /sys/devices/virtual/block. Now they appear underneath the PCI device which they belong to. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index e3d9215..744db38 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -889,6 +889,7 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int index, disk->fops = &nvme_fops; disk->private_data = ns; disk->queue = ns->queue; + disk->driverfs_dev = &dev->pci_dev->dev; sprintf(disk->disk_name, "nvme%dn%d", dev->instance, index); set_capacity(disk, le64_to_cpup(&id->nsze) << (ns->lba_shift - 9)); -- cgit v0.10.2 From 7a63e07b9a98b77dd075e06b93c1d8dc871ddad5 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 3 Feb 2011 09:20:57 -0500 Subject: NVMe: Add remaining status codes Signed-off-by: Matthew Wilcox diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 0aaecb0..dbbdc12 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -321,14 +321,29 @@ enum { NVME_SC_ABORT_QUEUE = 0x8, NVME_SC_FUSED_FAIL = 0x9, NVME_SC_FUSED_MISSING = 0xa, + NVME_SC_INVALID_NS = 0xb, NVME_SC_LBA_RANGE = 0x80, NVME_SC_CAP_EXCEEDED = 0x81, NVME_SC_NS_NOT_READY = 0x82, NVME_SC_CQ_INVALID = 0x100, NVME_SC_QID_INVALID = 0x101, NVME_SC_QUEUE_SIZE = 0x102, + NVME_SC_ABORT_LIMIT = 0x103, + NVME_SC_ABORT_MISSING = 0x104, + NVME_SC_ASYNC_LIMIT = 0x105, + NVME_SC_FIRMWARE_SLOT = 0x106, + NVME_SC_FIRMWARE_IMAGE = 0x107, + NVME_SC_INVALID_VECTOR = 0x108, + NVME_SC_INVALID_LOG_PAGE = 0x109, + NVME_SC_INVALID_FORMAT = 0x10a, + NVME_SC_BAD_ATTRIBUTES = 0x180, NVME_SC_WRITE_FAULT = 0x280, NVME_SC_READ_ERROR = 0x281, + NVME_SC_GUARD_CHECK = 0x282, + NVME_SC_APPTAG_CHECK = 0x283, + NVME_SC_REFTAG_CHECK = 0x284, + NVME_SC_COMPARE_FAILED = 0x285, + NVME_SC_ACCESS_DENIED = 0x286, }; struct nvme_completion { -- cgit v0.10.2 From 6ee44cdced04a53dc4f27eb97067e6cd33784726 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 3 Feb 2011 10:58:26 -0500 Subject: NVMe: Add download / activate firmware ioctls Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 744db38..7cdf7f6 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -829,6 +829,47 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) return status; } +static int nvme_download_firmware(struct nvme_ns *ns, + struct nvme_dlfw __user *udlfw) +{ + struct nvme_dev *dev = ns->dev; + struct nvme_dlfw dlfw; + struct nvme_command c; + int nents, status; + struct scatterlist *sg; + + if (copy_from_user(&dlfw, udlfw, sizeof(dlfw))) + return -EFAULT; + if (dlfw.length >= (1 << 30)) + return -EINVAL; + + nents = nvme_map_user_pages(dev, 1, dlfw.addr, dlfw.length * 4, &sg); + if (nents < 0) + return nents; + + memset(&c, 0, sizeof(c)); + c.dlfw.opcode = nvme_admin_download_fw; + c.dlfw.numd = cpu_to_le32(dlfw.length); + c.dlfw.offset = cpu_to_le32(dlfw.offset); + nvme_setup_prps(&c.common, sg, dlfw.length * 4); + + status = nvme_submit_admin_cmd(dev, &c, NULL); + nvme_unmap_user_pages(dev, 0, dlfw.addr, dlfw.length * 4, sg, nents); + return status; +} + +static int nvme_activate_firmware(struct nvme_ns *ns, unsigned long arg) +{ + struct nvme_dev *dev = ns->dev; + struct nvme_command c; + + memset(&c, 0, sizeof(c)); + c.common.opcode = nvme_admin_activate_fw; + c.common.rsvd10[0] = cpu_to_le32(arg); + + return nvme_submit_admin_cmd(dev, &c, NULL); +} + static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { @@ -843,6 +884,10 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, return nvme_get_range_type(ns, arg); case NVME_IOCTL_SUBMIT_IO: return nvme_submit_io(ns, (void __user *)arg); + case NVME_IOCTL_DOWNLOAD_FW: + return nvme_download_firmware(ns, (void __user *)arg); + case NVME_IOCTL_ACTIVATE_FW: + return nvme_activate_firmware(ns, arg); default: return -ENOTTY; } diff --git a/include/linux/nvme.h b/include/linux/nvme.h index dbbdc12..8eed0e4 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -262,7 +262,7 @@ struct nvme_create_cq { __u8 opcode; __u8 flags; __u16 command_id; - __le32 rsvd1[5]; + __u32 rsvd1[5]; __le64 prp1; __u64 rsvd8; __le16 cqid; @@ -276,14 +276,14 @@ struct nvme_create_sq { __u8 opcode; __u8 flags; __u16 command_id; - __le32 rsvd1[5]; + __u32 rsvd1[5]; __le64 prp1; __u64 rsvd8; __le16 sqid; __le16 qsize; __le16 sq_flags; __le16 cqid; - __le32 rsvd12[4]; + __u32 rsvd12[4]; }; struct nvme_delete_queue { @@ -292,8 +292,20 @@ struct nvme_delete_queue { __u16 command_id; __u32 rsvd1[9]; __le16 qid; - __le16 rsvd10; - __le32 rsvd11[5]; + __u16 rsvd10; + __u32 rsvd11[5]; +}; + +struct nvme_download_firmware { + __u8 opcode; + __u8 flags; + __u16 command_id; + __u32 rsvd1[5]; + __le64 prp1; + __le64 prp2; + __le32 numd; + __le32 offset; + __u32 rsvd12[4]; }; struct nvme_command { @@ -305,6 +317,7 @@ struct nvme_command { struct nvme_create_cq create_cq; struct nvme_create_sq create_sq; struct nvme_delete_queue delete_queue; + struct nvme_download_firmware dlfw; }; }; @@ -348,7 +361,7 @@ enum { struct nvme_completion { __le32 result; /* Used by admin commands to return data */ - __le32 rsvd; + __u32 rsvd; __le16 sq_head; /* how much of this queue may be reclaimed */ __le16 sq_id; /* submission queue that generated this entry */ __u16 command_id; /* of the command which completed */ @@ -372,9 +385,17 @@ struct nvme_user_io { __u32 result; }; +struct nvme_dlfw { + __u64 addr; + __u32 length; /* In dwords */ + __u32 offset; /* In dwords */ +}; + #define NVME_IOCTL_IDENTIFY_NS _IOW('N', 0x40, struct nvme_id_ns) #define NVME_IOCTL_IDENTIFY_CTRL _IOW('N', 0x41, struct nvme_id_ctrl) #define NVME_IOCTL_GET_RANGE_TYPE _IOW('N', 0x42, struct nvme_lba_range_type) #define NVME_IOCTL_SUBMIT_IO _IOWR('N', 0x43, struct nvme_rw_command) +#define NVME_IOCTL_DOWNLOAD_FW _IOR('N', 0x44, struct nvme_dlfw) +#define NVME_IOCTL_ACTIVATE_FW _IO('N', 0x45) #endif /* _LINUX_NVME_H */ -- cgit v0.10.2 From db5d0c198d673b6a932b449d4db95a2ad50c755e Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 3 Feb 2011 14:36:07 -0500 Subject: NVMe: Release 0.2 Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 7cdf7f6..06a6aea 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1272,6 +1272,6 @@ static void __exit nvme_exit(void) MODULE_AUTHOR("Matthew Wilcox "); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.1"); +MODULE_VERSION("0.2"); module_init(nvme_init); module_exit(nvme_exit); -- cgit v0.10.2 From 3c0cf138d7789feb3f335f6f1d24ad8fc8b3a23f Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 4 Feb 2011 16:03:56 -0500 Subject: NVMe: Allow fatal signals to interrupt I/O If the user sends a fatal signal, sleeping in the TASK_KILLABLE state permits the task to be aborted. The only wrinkle is making sure that if/when the command completes later that it doesn't upset anything. Handle this by setting the data pointer to 0, and checking the value isn't NULL in the sync completion path. Eventually, bios can be cancelled through this path too. Note that the cmdid isn't freed to prevent reuse. We should also abort the command in the future, but this is a good start. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 06a6aea..4bfed59 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -155,7 +155,9 @@ static int alloc_cmdid_killable(struct nvme_queue *nvmeq, void *ctx, } /* If you need more than four handlers, you'll need to change how - * alloc_cmdid and nvme_process_cq work + * alloc_cmdid and nvme_process_cq work. Also, aborted commands take + * the sync_completion path (if they complete), so don't put anything + * else in slot zero. */ enum { sync_completion_id = 0, @@ -172,6 +174,11 @@ static unsigned long free_cmdid(struct nvme_queue *nvmeq, int cmdid) return data; } +static void clear_cmdid_data(struct nvme_queue *nvmeq, int cmdid) +{ + nvmeq->cmdid_data[cmdid + BITS_TO_LONGS(nvmeq->q_depth)] = 0; +} + static struct nvme_queue *get_nvmeq(struct nvme_ns *ns) { int qid, cpu = get_cpu(); @@ -386,6 +393,8 @@ static void sync_completion(struct nvme_queue *nvmeq, void *ctx, struct nvme_completion *cqe) { struct sync_cmd_info *cmdinfo = ctx; + if (!cmdinfo) + return; /* Command aborted */ cmdinfo->result = le32_to_cpup(&cqe->result); cmdinfo->status = le16_to_cpup(&cqe->status) >> 1; wake_up_process(cmdinfo->task); @@ -446,12 +455,19 @@ static irqreturn_t nvme_irq(int irq, void *data) return nvme_process_cq(data); } +static void nvme_abort_command(struct nvme_queue *nvmeq, int cmdid) +{ + spin_lock_irq(&nvmeq->q_lock); + clear_cmdid_data(nvmeq, cmdid); + spin_unlock_irq(&nvmeq->q_lock); +} + /* * Returns 0 on success. If the result is negative, it's a Linux error code; * if the result is positive, it's an NVM Express status code */ -static int nvme_submit_sync_cmd(struct nvme_queue *q, struct nvme_command *cmd, - u32 *result) +static int nvme_submit_sync_cmd(struct nvme_queue *nvmeq, + struct nvme_command *cmd, u32 *result) { int cmdid; struct sync_cmd_info cmdinfo; @@ -459,15 +475,20 @@ static int nvme_submit_sync_cmd(struct nvme_queue *q, struct nvme_command *cmd, cmdinfo.task = current; cmdinfo.status = -EINTR; - cmdid = alloc_cmdid_killable(q, &cmdinfo, sync_completion_id); + cmdid = alloc_cmdid_killable(nvmeq, &cmdinfo, sync_completion_id); if (cmdid < 0) return cmdid; cmd->common.command_id = cmdid; - set_current_state(TASK_UNINTERRUPTIBLE); - nvme_submit_cmd(q, cmd); + set_current_state(TASK_KILLABLE); + nvme_submit_cmd(nvmeq, cmd); schedule(); + if (cmdinfo.status == -EINTR) { + nvme_abort_command(nvmeq, cmdid); + return -EINTR; + } + if (result) *result = cmdinfo.result; -- cgit v0.10.2 From b1ad37efcafe396ac3944853589688dd0ec3c64e Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 4 Feb 2011 16:14:30 -0500 Subject: NVMe: Call put_nvmeq() before calling nvme_submit_sync_cmd() We can't have preemption disabled when we call schedule(). Accept the possibility that we'll get preempted, and it'll cost us some cacheline bounces. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 4bfed59..1c3cd6c 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -842,8 +842,13 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) nvme_setup_prps(&c.common, sg, length); nvmeq = get_nvmeq(ns); - status = nvme_submit_sync_cmd(nvmeq, &c, &result); + /* Since nvme_submit_sync_cmd sleeps, we can't keep preemption + * disabled. We may be preempted at any point, and be rescheduled + * to a different CPU. That will cause cacheline bouncing, but no + * additional races since q_lock already protects against other CPUs. + */ put_nvmeq(nvmeq); + status = nvme_submit_sync_cmd(nvmeq, &c, &result); nvme_unmap_user_pages(dev, io.opcode & 1, io.addr, length, sg, nents); put_user(result, &uio->result); -- cgit v0.10.2 From 58ffacb545f76fc2c65d1fbfa5acf5184a2a09e6 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sun, 6 Feb 2011 07:28:06 -0500 Subject: NVMe: Add a module parameter to use a threaded interrupt We're currently calling bio_endio from hard interrupt context. This is not a good idea for preemptible kernels as it will cause longer latencies. Using a threaded interrupt will run the entire queue processing mechanism (including bio_endio) in a thread, which can be preempted. Unfortuantely, it also adds about 7us of latency to the single-I/O case, so make it a module parameter for the moment. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 1c3cd6c..60c3786 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -44,6 +44,9 @@ static int nvme_major; module_param(nvme_major, int, 0); +static int use_threaded_interrupts; +module_param(use_threaded_interrupts, int, 0); + /* * Represents an NVM Express device. Each nvme_dev is a PCI function. */ @@ -455,6 +458,25 @@ static irqreturn_t nvme_irq(int irq, void *data) return nvme_process_cq(data); } +static irqreturn_t nvme_irq_thread(int irq, void *data) +{ + irqreturn_t result; + struct nvme_queue *nvmeq = data; + spin_lock(&nvmeq->q_lock); + result = nvme_process_cq(nvmeq); + spin_unlock(&nvmeq->q_lock); + return result; +} + +static irqreturn_t nvme_irq_check(int irq, void *data) +{ + struct nvme_queue *nvmeq = data; + struct nvme_completion cqe = nvmeq->cqes[nvmeq->cq_head]; + if ((le16_to_cpu(cqe.status) & 1) != nvmeq->cq_phase) + return IRQ_NONE; + return IRQ_WAKE_THREAD; +} + static void nvme_abort_command(struct nvme_queue *nvmeq, int cmdid) { spin_lock_irq(&nvmeq->q_lock); @@ -630,6 +652,11 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid, static int queue_request_irq(struct nvme_dev *dev, struct nvme_queue *nvmeq, const char *name) { + if (use_threaded_interrupts) + return request_threaded_irq(dev->entry[nvmeq->cq_vector].vector, + nvme_irq_check, nvme_irq_thread, + IRQF_DISABLED | IRQF_SHARED, + name, nvmeq); return request_irq(dev->entry[nvmeq->cq_vector].vector, nvme_irq, IRQF_DISABLED | IRQF_SHARED, name, nvmeq); } -- cgit v0.10.2 From be7b62754e097adc0cb16c25c9ee86ee20de62fb Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sun, 6 Feb 2011 07:53:23 -0500 Subject: NVMe: Use a symbolic name to represent cancelled commands instead of 0 I have plans for other special values in sync_completion. Plus, this is more self-documenting, and lets us detect bogus usages. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 60c3786..802d763 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -158,15 +159,17 @@ static int alloc_cmdid_killable(struct nvme_queue *nvmeq, void *ctx, } /* If you need more than four handlers, you'll need to change how - * alloc_cmdid and nvme_process_cq work. Also, aborted commands take - * the sync_completion path (if they complete), so don't put anything - * else in slot zero. + * alloc_cmdid and nvme_process_cq work. Consider using a special + * CMD_CTX value instead, if that works for your situation. */ enum { sync_completion_id = 0, bio_completion_id, }; +#define CMD_CTX_BASE (POISON_POINTER_DELTA + sync_completion_id) +#define CMD_CTX_CANCELLED (0x2008 + CMD_CTX_BASE) + static unsigned long free_cmdid(struct nvme_queue *nvmeq, int cmdid) { unsigned long data; @@ -177,9 +180,10 @@ static unsigned long free_cmdid(struct nvme_queue *nvmeq, int cmdid) return data; } -static void clear_cmdid_data(struct nvme_queue *nvmeq, int cmdid) +static void cancel_cmdid_data(struct nvme_queue *nvmeq, int cmdid) { - nvmeq->cmdid_data[cmdid + BITS_TO_LONGS(nvmeq->q_depth)] = 0; + nvmeq->cmdid_data[cmdid + BITS_TO_LONGS(nvmeq->q_depth)] = + CMD_CTX_CANCELLED; } static struct nvme_queue *get_nvmeq(struct nvme_ns *ns) @@ -396,8 +400,8 @@ static void sync_completion(struct nvme_queue *nvmeq, void *ctx, struct nvme_completion *cqe) { struct sync_cmd_info *cmdinfo = ctx; - if (!cmdinfo) - return; /* Command aborted */ + if ((unsigned long)cmdinfo == CMD_CTX_CANCELLED) + return; cmdinfo->result = le32_to_cpup(&cqe->result); cmdinfo->status = le16_to_cpup(&cqe->status) >> 1; wake_up_process(cmdinfo->task); @@ -480,7 +484,7 @@ static irqreturn_t nvme_irq_check(int irq, void *data) static void nvme_abort_command(struct nvme_queue *nvmeq, int cmdid) { spin_lock_irq(&nvmeq->q_lock); - clear_cmdid_data(nvmeq, cmdid); + cancel_cmdid_data(nvmeq, cmdid); spin_unlock_irq(&nvmeq->q_lock); } -- cgit v0.10.2 From b36235df01ec4141b4e589571d6789076c346d88 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sun, 6 Feb 2011 08:49:55 -0500 Subject: NVMe: Detect commands that are completed twice Set the context value to CMD_CTX_COMPLETED, and print a message in the sync_completion handler if we see it. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 802d763..2dd09e7 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -169,12 +169,15 @@ enum { #define CMD_CTX_BASE (POISON_POINTER_DELTA + sync_completion_id) #define CMD_CTX_CANCELLED (0x2008 + CMD_CTX_BASE) +#define CMD_CTX_COMPLETED (0x2010 + CMD_CTX_BASE) static unsigned long free_cmdid(struct nvme_queue *nvmeq, int cmdid) { unsigned long data; + unsigned offset = cmdid + BITS_TO_LONGS(nvmeq->q_depth); - data = nvmeq->cmdid_data[cmdid + BITS_TO_LONGS(nvmeq->q_depth)]; + data = nvmeq->cmdid_data[offset]; + nvmeq->cmdid_data[offset] = CMD_CTX_COMPLETED; clear_bit(cmdid, nvmeq->cmdid_data); wake_up(&nvmeq->sq_full); return data; @@ -182,8 +185,8 @@ static unsigned long free_cmdid(struct nvme_queue *nvmeq, int cmdid) static void cancel_cmdid_data(struct nvme_queue *nvmeq, int cmdid) { - nvmeq->cmdid_data[cmdid + BITS_TO_LONGS(nvmeq->q_depth)] = - CMD_CTX_CANCELLED; + unsigned offset = cmdid + BITS_TO_LONGS(nvmeq->q_depth); + nvmeq->cmdid_data[offset] = CMD_CTX_CANCELLED; } static struct nvme_queue *get_nvmeq(struct nvme_ns *ns) @@ -402,6 +405,12 @@ static void sync_completion(struct nvme_queue *nvmeq, void *ctx, struct sync_cmd_info *cmdinfo = ctx; if ((unsigned long)cmdinfo == CMD_CTX_CANCELLED) return; + if (unlikely((unsigned long)cmdinfo == CMD_CTX_COMPLETED)) { + dev_warn(nvmeq->q_dmadev, + "completed id %d twice on queue %d\n", + cqe->command_id, le16_to_cpup(&cqe->sq_id)); + return; + } cmdinfo->result = le32_to_cpup(&cqe->result); cmdinfo->status = le16_to_cpup(&cqe->status) >> 1; wake_up_process(cmdinfo->task); -- cgit v0.10.2 From 48e3d39816416b3bf03dee3a796c0c04427c1a31 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sun, 6 Feb 2011 08:51:15 -0500 Subject: NVMe: Detect command IDs completing that are out of range If the adapter completes a command ID that is outside the bounds of the array, return CMD_CTX_INVALID instead of random data, and print a message in the sync_completion handler (which is rapidly becoming the misc completion handler :-) Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 2dd09e7..f4085d4 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -170,12 +170,15 @@ enum { #define CMD_CTX_BASE (POISON_POINTER_DELTA + sync_completion_id) #define CMD_CTX_CANCELLED (0x2008 + CMD_CTX_BASE) #define CMD_CTX_COMPLETED (0x2010 + CMD_CTX_BASE) +#define CMD_CTX_INVALID (0x2014 + CMD_CTX_BASE) static unsigned long free_cmdid(struct nvme_queue *nvmeq, int cmdid) { unsigned long data; unsigned offset = cmdid + BITS_TO_LONGS(nvmeq->q_depth); + if (cmdid > nvmeq->q_depth) + return CMD_CTX_INVALID; data = nvmeq->cmdid_data[offset]; nvmeq->cmdid_data[offset] = CMD_CTX_COMPLETED; clear_bit(cmdid, nvmeq->cmdid_data); @@ -411,6 +414,12 @@ static void sync_completion(struct nvme_queue *nvmeq, void *ctx, cqe->command_id, le16_to_cpup(&cqe->sq_id)); return; } + if (unlikely((unsigned long)cmdinfo == CMD_CTX_INVALID)) { + dev_warn(nvmeq->q_dmadev, + "invalid id %d completed on queue %d\n", + cqe->command_id, le16_to_cpup(&cqe->sq_id)); + return; + } cmdinfo->result = le32_to_cpup(&cqe->result); cmdinfo->status = le16_to_cpup(&cqe->status) >> 1; wake_up_process(cmdinfo->task); -- cgit v0.10.2 From ec6ce618d65b5ce1bef83a5509255107a0feac44 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sun, 6 Feb 2011 09:01:00 -0500 Subject: NVMe: Need to lock queue during interrupt handling If we're sharing a queue between multiple CPUs and we cancel a sync I/O, we must have the queue locked to avoid corrupting the stack of the thread that submitted the I/O. It turns out this is the same locking that's needed for the threaded irq handler, so share that code. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index f4085d4..139e6fc 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -477,11 +477,6 @@ static irqreturn_t nvme_process_cq(struct nvme_queue *nvmeq) static irqreturn_t nvme_irq(int irq, void *data) { - return nvme_process_cq(data); -} - -static irqreturn_t nvme_irq_thread(int irq, void *data) -{ irqreturn_t result; struct nvme_queue *nvmeq = data; spin_lock(&nvmeq->q_lock); @@ -676,7 +671,7 @@ static int queue_request_irq(struct nvme_dev *dev, struct nvme_queue *nvmeq, { if (use_threaded_interrupts) return request_threaded_irq(dev->entry[nvmeq->cq_vector].vector, - nvme_irq_check, nvme_irq_thread, + nvme_irq_check, nvme_irq, IRQF_DISABLED | IRQF_SHARED, name, nvmeq); return request_irq(dev->entry[nvmeq->cq_vector].vector, nvme_irq, -- cgit v0.10.2 From e85248e516c550382ba33ca325c272a0ca397e44 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sun, 6 Feb 2011 18:30:16 -0500 Subject: NVMe: Record the timeout for each command In addition to recording the completion data for each command, record the anticipated completion time. Choose a timeout of 5 seconds for normal I/Os and 60 seconds for admin I/Os. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 139e6fc..60c1048 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -41,6 +41,8 @@ #define SQ_SIZE(depth) (depth * sizeof(struct nvme_command)) #define CQ_SIZE(depth) (depth * sizeof(struct nvme_completion)) #define NVME_MINORS 64 +#define IO_TIMEOUT (5 * HZ) +#define ADMIN_TIMEOUT (60 * HZ) static int nvme_major; module_param(nvme_major, int, 0); @@ -119,6 +121,16 @@ static inline void _nvme_check_size(void) BUILD_BUG_ON(sizeof(struct nvme_lba_range_type) != 64); } +struct nvme_cmd_info { + unsigned long ctx; + unsigned long timeout; +}; + +static struct nvme_cmd_info *nvme_cmd_info(struct nvme_queue *nvmeq) +{ + return (void *)&nvmeq->cmdid_data[BITS_TO_LONGS(nvmeq->q_depth)]; +} + /** * alloc_cmdid - Allocate a Command ID * @param nvmeq The queue that will be used for this command @@ -131,10 +143,11 @@ static inline void _nvme_check_size(void) * Passing in a pointer that's not 4-byte aligned will cause a BUG. * We can change this if it becomes a problem. */ -static int alloc_cmdid(struct nvme_queue *nvmeq, void *ctx, int handler) +static int alloc_cmdid(struct nvme_queue *nvmeq, void *ctx, int handler, + unsigned timeout) { int depth = nvmeq->q_depth; - unsigned long data = (unsigned long)ctx | handler; + struct nvme_cmd_info *info = nvme_cmd_info(nvmeq); int cmdid; BUG_ON((unsigned long)ctx & 3); @@ -145,16 +158,17 @@ static int alloc_cmdid(struct nvme_queue *nvmeq, void *ctx, int handler) return -EBUSY; } while (test_and_set_bit(cmdid, nvmeq->cmdid_data)); - nvmeq->cmdid_data[cmdid + BITS_TO_LONGS(depth)] = data; + info[cmdid].ctx = (unsigned long)ctx | handler; + info[cmdid].timeout = jiffies + timeout; return cmdid; } static int alloc_cmdid_killable(struct nvme_queue *nvmeq, void *ctx, - int handler) + int handler, unsigned timeout) { int cmdid; wait_event_killable(nvmeq->sq_full, - (cmdid = alloc_cmdid(nvmeq, ctx, handler)) >= 0); + (cmdid = alloc_cmdid(nvmeq, ctx, handler, timeout)) >= 0); return (cmdid < 0) ? -EINTR : cmdid; } @@ -175,12 +189,12 @@ enum { static unsigned long free_cmdid(struct nvme_queue *nvmeq, int cmdid) { unsigned long data; - unsigned offset = cmdid + BITS_TO_LONGS(nvmeq->q_depth); + struct nvme_cmd_info *info = nvme_cmd_info(nvmeq); - if (cmdid > nvmeq->q_depth) + if (cmdid >= nvmeq->q_depth) return CMD_CTX_INVALID; - data = nvmeq->cmdid_data[offset]; - nvmeq->cmdid_data[offset] = CMD_CTX_COMPLETED; + data = info[cmdid].ctx; + info[cmdid].ctx = CMD_CTX_COMPLETED; clear_bit(cmdid, nvmeq->cmdid_data); wake_up(&nvmeq->sq_full); return data; @@ -188,8 +202,8 @@ static unsigned long free_cmdid(struct nvme_queue *nvmeq, int cmdid) static void cancel_cmdid_data(struct nvme_queue *nvmeq, int cmdid) { - unsigned offset = cmdid + BITS_TO_LONGS(nvmeq->q_depth); - nvmeq->cmdid_data[offset] = CMD_CTX_CANCELLED; + struct nvme_cmd_info *info = nvme_cmd_info(nvmeq); + info[cmdid].ctx = CMD_CTX_CANCELLED; } static struct nvme_queue *get_nvmeq(struct nvme_ns *ns) @@ -327,7 +341,7 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, goto congestion; info->bio = bio; - cmdid = alloc_cmdid(nvmeq, info, bio_completion_id); + cmdid = alloc_cmdid(nvmeq, info, bio_completion_id, IO_TIMEOUT); if (unlikely(cmdid < 0)) goto free_info; @@ -506,7 +520,7 @@ static void nvme_abort_command(struct nvme_queue *nvmeq, int cmdid) * if the result is positive, it's an NVM Express status code */ static int nvme_submit_sync_cmd(struct nvme_queue *nvmeq, - struct nvme_command *cmd, u32 *result) + struct nvme_command *cmd, u32 *result, unsigned timeout) { int cmdid; struct sync_cmd_info cmdinfo; @@ -514,7 +528,8 @@ static int nvme_submit_sync_cmd(struct nvme_queue *nvmeq, cmdinfo.task = current; cmdinfo.status = -EINTR; - cmdid = alloc_cmdid_killable(nvmeq, &cmdinfo, sync_completion_id); + cmdid = alloc_cmdid_killable(nvmeq, &cmdinfo, sync_completion_id, + timeout); if (cmdid < 0) return cmdid; cmd->common.command_id = cmdid; @@ -537,7 +552,7 @@ static int nvme_submit_sync_cmd(struct nvme_queue *nvmeq, static int nvme_submit_admin_cmd(struct nvme_dev *dev, struct nvme_command *cmd, u32 *result) { - return nvme_submit_sync_cmd(dev->queues[0], cmd, result); + return nvme_submit_sync_cmd(dev->queues[0], cmd, result, ADMIN_TIMEOUT); } static int adapter_delete_queue(struct nvme_dev *dev, u8 opcode, u16 id) @@ -630,7 +645,7 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth, int vector) { struct device *dmadev = &dev->pci_dev->dev; - unsigned extra = (depth + BITS_TO_LONGS(depth)) * sizeof(long); + unsigned extra = (depth / 8) + (depth * sizeof(struct nvme_cmd_info)); struct nvme_queue *nvmeq = kzalloc(sizeof(*nvmeq) + extra, GFP_KERNEL); if (!nvmeq) return NULL; @@ -892,7 +907,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) * additional races since q_lock already protects against other CPUs. */ put_nvmeq(nvmeq); - status = nvme_submit_sync_cmd(nvmeq, &c, &result); + status = nvme_submit_sync_cmd(nvmeq, &c, &result, IO_TIMEOUT); nvme_unmap_user_pages(dev, io.opcode & 1, io.addr, length, sg, nents); put_user(result, &uio->result); -- cgit v0.10.2 From 9294bbed78926a895516ec016ba23033f58d1a88 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 7 Feb 2011 12:45:24 -0500 Subject: NVMe: Handle the congestion list a little better In the bio completion handler, check for bios on the congestion list for this NVM queue. Also, lock the congestion list in the make_request function as the queue may end up being shared between multiple CPUs. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 60c1048..2a0dd5e 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -105,6 +105,8 @@ struct nvme_queue { unsigned long cmdid_data[]; }; +static void nvme_resubmit_bio(struct nvme_queue *nvmeq, struct bio *bio); + /* * Check we didin't inadvertently grow the command struct */ @@ -274,6 +276,9 @@ static void bio_completion(struct nvme_queue *nvmeq, void *ctx, bio_data_dir(bio) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); free_info(info); bio_endio(bio, status ? -EIO : 0); + bio = bio_list_pop(&nvmeq->sq_cong); + if (bio) + nvme_resubmit_bio(nvmeq, bio); } /* length is in bytes */ @@ -392,6 +397,16 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, return -EBUSY; } +static void nvme_resubmit_bio(struct nvme_queue *nvmeq, struct bio *bio) +{ + struct nvme_ns *ns = bio->bi_bdev->bd_disk->private_data; + if (nvme_submit_bio_queue(nvmeq, ns, bio)) + bio_list_add_head(&nvmeq->sq_cong, bio); + else if (bio_list_empty(&nvmeq->sq_cong)) + blk_clear_queue_congested(ns->queue, rw_is_sync(bio->bi_rw)); + /* XXX: Need to duplicate the logic from __freed_request here */ +} + /* * NB: return value of non-zero would mean that we were a stacking driver. * make_request must always succeed. @@ -403,7 +418,9 @@ static int nvme_make_request(struct request_queue *q, struct bio *bio) if (nvme_submit_bio_queue(nvmeq, ns, bio)) { blk_set_queue_congested(q, rw_is_sync(bio->bi_rw)); + spin_lock_irq(&nvmeq->q_lock); bio_list_add(&nvmeq->sq_cong, bio); + spin_unlock_irq(&nvmeq->q_lock); } put_nvmeq(nvmeq); -- cgit v0.10.2 From d2d8703481f60d67f49e3177196cbe474b11377c Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 7 Feb 2011 15:55:59 -0500 Subject: NVMe: Renumber the special context values If POISON_POINTER_DELTA isn't defined, ensure they're in page 0 which should never be mapped. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 2a0dd5e..71bdf6f 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -184,9 +184,9 @@ enum { }; #define CMD_CTX_BASE (POISON_POINTER_DELTA + sync_completion_id) -#define CMD_CTX_CANCELLED (0x2008 + CMD_CTX_BASE) -#define CMD_CTX_COMPLETED (0x2010 + CMD_CTX_BASE) -#define CMD_CTX_INVALID (0x2014 + CMD_CTX_BASE) +#define CMD_CTX_CANCELLED (0x30C + CMD_CTX_BASE) +#define CMD_CTX_COMPLETED (0x310 + CMD_CTX_BASE) +#define CMD_CTX_INVALID (0x314 + CMD_CTX_BASE) static unsigned long free_cmdid(struct nvme_queue *nvmeq, int cmdid) { -- cgit v0.10.2 From 51882d00f07da9601cc962a3596e48aafb4f4163 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 10 Feb 2011 08:49:59 -0500 Subject: NVMe: Advance the sg pointer when filling in an sg list For multipage BIOs, we were always using sg[0] instead of advancing through the list. Oops :-) Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 71bdf6f..903e7f1 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -321,6 +321,7 @@ static int nvme_map_bio(struct device *dev, struct nvme_req_info *info, sg_init_table(sg, psegs); bio_for_each_segment(bvec, bio, i) { sg_set_page(sg, bvec->bv_page, bvec->bv_len, bvec->bv_offset); + sg++; /* XXX: handle non-mergable here */ nsegs++; } -- cgit v0.10.2 From e025344c56e08b155f43ea09647969286c78377c Mon Sep 17 00:00:00 2001 From: Shane Michael Matthews Date: Thu, 10 Feb 2011 08:51:24 -0500 Subject: NVMe: Initial PRP List support Add a pointer to the nvme_req_info to hold a new data structure (nvme_prps) which contains a list of the pages allocated to this particular request for holding PRP list entries. nvme_setup_prps() now returns this pointer. To allocate and free the memory used for PRP lists, we need a struct device, so we need to pass the nvme_queue pointer to many functions which didn't use to need it. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 903e7f1..b1e8445 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -247,21 +247,55 @@ static int nvme_submit_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd) return 0; } +static __le64 *alloc_prp_list(struct nvme_queue *nvmeq, int length, + dma_addr_t *addr) +{ + return dma_alloc_coherent(nvmeq->q_dmadev, PAGE_SIZE, addr, GFP_ATOMIC); +} + +struct nvme_prps { + int npages; + dma_addr_t first_dma; + __le64 *list[0]; +}; + +static void nvme_free_prps(struct nvme_queue *nvmeq, struct nvme_prps *prps) +{ + const int last_prp = PAGE_SIZE / 8 - 1; + int i; + dma_addr_t prp_dma; + + if (!prps) + return; + + prp_dma = prps->first_dma; + for (i = 0; i < prps->npages; i++) { + __le64 *prp_list = prps->list[i]; + dma_addr_t next_prp_dma = le64_to_cpu(prp_list[last_prp]); + dma_free_coherent(nvmeq->q_dmadev, PAGE_SIZE, prp_list, + prp_dma); + prp_dma = next_prp_dma; + } + kfree(prps); +} + struct nvme_req_info { struct bio *bio; int nents; + struct nvme_prps *prps; struct scatterlist sg[0]; }; /* XXX: use a mempool */ static struct nvme_req_info *alloc_info(unsigned nseg, gfp_t gfp) { - return kmalloc(sizeof(struct nvme_req_info) + + return kzalloc(sizeof(struct nvme_req_info) + sizeof(struct scatterlist) * nseg, gfp); } -static void free_info(struct nvme_req_info *info) +static void free_info(struct nvme_queue *nvmeq, struct nvme_req_info *info) { + nvme_free_prps(nvmeq, info->prps); kfree(info); } @@ -274,7 +308,7 @@ static void bio_completion(struct nvme_queue *nvmeq, void *ctx, dma_unmap_sg(nvmeq->q_dmadev, info->sg, info->nents, bio_data_dir(bio) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - free_info(info); + free_info(nvmeq, info); bio_endio(bio, status ? -EIO : 0); bio = bio_list_pop(&nvmeq->sq_cong); if (bio) @@ -282,17 +316,22 @@ static void bio_completion(struct nvme_queue *nvmeq, void *ctx, } /* length is in bytes */ -static void nvme_setup_prps(struct nvme_common_command *cmd, +static struct nvme_prps *nvme_setup_prps(struct nvme_queue *nvmeq, + struct nvme_common_command *cmd, struct scatterlist *sg, int length) { int dma_len = sg_dma_len(sg); u64 dma_addr = sg_dma_address(sg); int offset = offset_in_page(dma_addr); + __le64 *prp_list; + dma_addr_t prp_dma; + int nprps, npages, i, prp_page; + struct nvme_prps *prps = NULL; cmd->prp1 = cpu_to_le64(dma_addr); length -= (PAGE_SIZE - offset); if (length <= 0) - return; + return prps; dma_len -= (PAGE_SIZE - offset); if (dma_len) { @@ -305,10 +344,42 @@ static void nvme_setup_prps(struct nvme_common_command *cmd, if (length <= PAGE_SIZE) { cmd->prp2 = cpu_to_le64(dma_addr); - return; + return prps; } - /* XXX: support PRP lists */ + nprps = DIV_ROUND_UP(length, PAGE_SIZE); + npages = DIV_ROUND_UP(8 * nprps, PAGE_SIZE); + prps = kmalloc(sizeof(*prps) + sizeof(__le64 *) * npages, GFP_ATOMIC); + prps->npages = npages; + prp_page = 0; + prp_list = alloc_prp_list(nvmeq, length, &prp_dma); + prps->list[prp_page++] = prp_list; + prps->first_dma = prp_dma; + cmd->prp2 = cpu_to_le64(prp_dma); + i = 0; + for (;;) { + if (i == PAGE_SIZE / 8 - 1) { + __le64 *old_prp_list = prp_list; + prp_list = alloc_prp_list(nvmeq, length, &prp_dma); + prps->list[prp_page++] = prp_list; + old_prp_list[i] = cpu_to_le64(prp_dma); + i = 0; + } + prp_list[i++] = cpu_to_le64(dma_addr); + dma_len -= PAGE_SIZE; + dma_addr += PAGE_SIZE; + length -= PAGE_SIZE; + if (length <= 0) + break; + if (dma_len > 0) + continue; + BUG_ON(dma_len < 0); + sg = sg_next(sg); + dma_addr = sg_dma_address(sg); + dma_len = sg_dma_len(sg); + } + + return prps; } static int nvme_map_bio(struct device *dev, struct nvme_req_info *info, @@ -378,7 +449,8 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, cmnd->rw.flags = 1; cmnd->rw.command_id = cmdid; cmnd->rw.nsid = cpu_to_le32(ns->ns_id); - nvme_setup_prps(&cmnd->common, info->sg, bio->bi_size); + info->prps = nvme_setup_prps(nvmeq, &cmnd->common, info->sg, + bio->bi_size); cmnd->rw.slba = cpu_to_le64(bio->bi_sector >> (ns->lba_shift - 9)); cmnd->rw.length = cpu_to_le16((bio->bi_size >> ns->lba_shift) - 1); cmnd->rw.control = cpu_to_le16(control); @@ -393,7 +465,7 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, return 0; free_info: - free_info(info); + free_info(nvmeq, info); congestion: return -EBUSY; } @@ -852,13 +924,15 @@ static int nvme_submit_user_admin_command(struct nvme_dev *dev, { int err, nents; struct scatterlist *sg; + struct nvme_prps *prps; nents = nvme_map_user_pages(dev, 0, addr, length, &sg); if (nents < 0) return nents; - nvme_setup_prps(&cmd->common, sg, length); + prps = nvme_setup_prps(dev->queues[0], &cmd->common, sg, length); err = nvme_submit_admin_cmd(dev, cmd, NULL); nvme_unmap_user_pages(dev, 0, addr, length, sg, nents); + nvme_free_prps(dev->queues[0], prps); return err ? -EIO : 0; } @@ -896,6 +970,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) u32 result; int nents, status; struct scatterlist *sg; + struct nvme_prps *prps; if (copy_from_user(&io, uio, sizeof(io))) return -EFAULT; @@ -915,10 +990,10 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) c.rw.reftag = cpu_to_le32(io.reftag); /* XXX: endian? */ c.rw.apptag = cpu_to_le16(io.apptag); c.rw.appmask = cpu_to_le16(io.appmask); + nvmeq = get_nvmeq(ns); /* XXX: metadata */ - nvme_setup_prps(&c.common, sg, length); + prps = nvme_setup_prps(nvmeq, &c.common, sg, length); - nvmeq = get_nvmeq(ns); /* Since nvme_submit_sync_cmd sleeps, we can't keep preemption * disabled. We may be preempted at any point, and be rescheduled * to a different CPU. That will cause cacheline bouncing, but no @@ -928,6 +1003,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) status = nvme_submit_sync_cmd(nvmeq, &c, &result, IO_TIMEOUT); nvme_unmap_user_pages(dev, io.opcode & 1, io.addr, length, sg, nents); + nvme_free_prps(nvmeq, prps); put_user(result, &uio->result); return status; } @@ -940,6 +1016,7 @@ static int nvme_download_firmware(struct nvme_ns *ns, struct nvme_command c; int nents, status; struct scatterlist *sg; + struct nvme_prps *prps; if (copy_from_user(&dlfw, udlfw, sizeof(dlfw))) return -EFAULT; @@ -954,10 +1031,11 @@ static int nvme_download_firmware(struct nvme_ns *ns, c.dlfw.opcode = nvme_admin_download_fw; c.dlfw.numd = cpu_to_le32(dlfw.length); c.dlfw.offset = cpu_to_le32(dlfw.offset); - nvme_setup_prps(&c.common, sg, dlfw.length * 4); + prps = nvme_setup_prps(dev->queues[0], &c.common, sg, dlfw.length * 4); status = nvme_submit_admin_cmd(dev, &c, NULL); nvme_unmap_user_pages(dev, 0, dlfw.addr, dlfw.length * 4, sg, nents); + nvme_free_prps(dev->queues[0], prps); return status; } -- cgit v0.10.2 From d534df3c730af9073a9ddc076d9fd65cbdca22b3 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 10 Feb 2011 09:03:06 -0500 Subject: NVMe: Rename nvme_req_info to nvme_bio There are too many things called 'info' in this driver. This data structure is auxiliary information for a struct bio, so call it nvme_bio, or nbio when used as a variable. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index b1e8445..11df0e9 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -279,7 +279,7 @@ static void nvme_free_prps(struct nvme_queue *nvmeq, struct nvme_prps *prps) kfree(prps); } -struct nvme_req_info { +struct nvme_bio { struct bio *bio; int nents; struct nvme_prps *prps; @@ -287,28 +287,28 @@ struct nvme_req_info { }; /* XXX: use a mempool */ -static struct nvme_req_info *alloc_info(unsigned nseg, gfp_t gfp) +static struct nvme_bio *alloc_nbio(unsigned nseg, gfp_t gfp) { - return kzalloc(sizeof(struct nvme_req_info) + + return kzalloc(sizeof(struct nvme_bio) + sizeof(struct scatterlist) * nseg, gfp); } -static void free_info(struct nvme_queue *nvmeq, struct nvme_req_info *info) +static void free_nbio(struct nvme_queue *nvmeq, struct nvme_bio *nbio) { - nvme_free_prps(nvmeq, info->prps); - kfree(info); + nvme_free_prps(nvmeq, nbio->prps); + kfree(nbio); } static void bio_completion(struct nvme_queue *nvmeq, void *ctx, struct nvme_completion *cqe) { - struct nvme_req_info *info = ctx; - struct bio *bio = info->bio; + struct nvme_bio *nbio = ctx; + struct bio *bio = nbio->bio; u16 status = le16_to_cpup(&cqe->status) >> 1; - dma_unmap_sg(nvmeq->q_dmadev, info->sg, info->nents, + dma_unmap_sg(nvmeq->q_dmadev, nbio->sg, nbio->nents, bio_data_dir(bio) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - free_info(nvmeq, info); + free_nbio(nvmeq, nbio); bio_endio(bio, status ? -EIO : 0); bio = bio_list_pop(&nvmeq->sq_cong); if (bio) @@ -382,11 +382,11 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_queue *nvmeq, return prps; } -static int nvme_map_bio(struct device *dev, struct nvme_req_info *info, +static int nvme_map_bio(struct device *dev, struct nvme_bio *nbio, struct bio *bio, enum dma_data_direction dma_dir, int psegs) { struct bio_vec *bvec; - struct scatterlist *sg = info->sg; + struct scatterlist *sg = nbio->sg; int i, nsegs; sg_init_table(sg, psegs); @@ -396,16 +396,16 @@ static int nvme_map_bio(struct device *dev, struct nvme_req_info *info, /* XXX: handle non-mergable here */ nsegs++; } - info->nents = nsegs; + nbio->nents = nsegs; - return dma_map_sg(dev, info->sg, info->nents, dma_dir); + return dma_map_sg(dev, nbio->sg, nbio->nents, dma_dir); } static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, struct bio *bio) { struct nvme_command *cmnd; - struct nvme_req_info *info; + struct nvme_bio *nbio; enum dma_data_direction dma_dir; int cmdid; u16 control; @@ -413,14 +413,14 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, unsigned long flags; int psegs = bio_phys_segments(ns->queue, bio); - info = alloc_info(psegs, GFP_NOIO); - if (!info) + nbio = alloc_nbio(psegs, GFP_NOIO); + if (!nbio) goto congestion; - info->bio = bio; + nbio->bio = bio; - cmdid = alloc_cmdid(nvmeq, info, bio_completion_id, IO_TIMEOUT); + cmdid = alloc_cmdid(nvmeq, nbio, bio_completion_id, IO_TIMEOUT); if (unlikely(cmdid < 0)) - goto free_info; + goto free_nbio; control = 0; if (bio->bi_rw & REQ_FUA) @@ -444,12 +444,12 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, dma_dir = DMA_FROM_DEVICE; } - nvme_map_bio(nvmeq->q_dmadev, info, bio, dma_dir, psegs); + nvme_map_bio(nvmeq->q_dmadev, nbio, bio, dma_dir, psegs); cmnd->rw.flags = 1; cmnd->rw.command_id = cmdid; cmnd->rw.nsid = cpu_to_le32(ns->ns_id); - info->prps = nvme_setup_prps(nvmeq, &cmnd->common, info->sg, + nbio->prps = nvme_setup_prps(nvmeq, &cmnd->common, nbio->sg, bio->bi_size); cmnd->rw.slba = cpu_to_le64(bio->bi_sector >> (ns->lba_shift - 9)); cmnd->rw.length = cpu_to_le16((bio->bi_size >> ns->lba_shift) - 1); @@ -464,8 +464,8 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, return 0; - free_info: - free_info(nvmeq, info); + free_nbio: + free_nbio(nvmeq, nbio); congestion: return -EBUSY; } -- cgit v0.10.2 From 091b609258b8e01cc45b01a41ca5e496f674d989 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 10 Feb 2011 09:56:01 -0500 Subject: NVMe: Switch to use DMA Pool API Calling dma_free_coherent from interrupt context causes warnings. Using the DMA pools delays freeing until pool destruction, so avoids the problem. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 11df0e9..80fe6a7 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -57,6 +57,7 @@ struct nvme_dev { struct nvme_queue **queues; u32 __iomem *dbs; struct pci_dev *pci_dev; + struct dma_pool *prp_page_pool; int instance; int queue_count; u32 ctrl_config; @@ -88,6 +89,7 @@ struct nvme_ns { */ struct nvme_queue { struct device *q_dmadev; + struct nvme_dev *dev; spinlock_t q_lock; struct nvme_command *sq_cmds; volatile struct nvme_completion *cqes; @@ -247,10 +249,9 @@ static int nvme_submit_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd) return 0; } -static __le64 *alloc_prp_list(struct nvme_queue *nvmeq, int length, - dma_addr_t *addr) +static __le64 *alloc_prp_list(struct nvme_dev *dev, dma_addr_t *addr) { - return dma_alloc_coherent(nvmeq->q_dmadev, PAGE_SIZE, addr, GFP_ATOMIC); + return dma_pool_alloc(dev->prp_page_pool, GFP_ATOMIC, addr); } struct nvme_prps { @@ -262,6 +263,7 @@ struct nvme_prps { static void nvme_free_prps(struct nvme_queue *nvmeq, struct nvme_prps *prps) { const int last_prp = PAGE_SIZE / 8 - 1; + struct nvme_dev *dev = nvmeq->dev; int i; dma_addr_t prp_dma; @@ -272,8 +274,7 @@ static void nvme_free_prps(struct nvme_queue *nvmeq, struct nvme_prps *prps) for (i = 0; i < prps->npages; i++) { __le64 *prp_list = prps->list[i]; dma_addr_t next_prp_dma = le64_to_cpu(prp_list[last_prp]); - dma_free_coherent(nvmeq->q_dmadev, PAGE_SIZE, prp_list, - prp_dma); + dma_pool_free(dev->prp_page_pool, prp_list, prp_dma); prp_dma = next_prp_dma; } kfree(prps); @@ -320,6 +321,7 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_queue *nvmeq, struct nvme_common_command *cmd, struct scatterlist *sg, int length) { + struct nvme_dev *dev = nvmeq->dev; int dma_len = sg_dma_len(sg); u64 dma_addr = sg_dma_address(sg); int offset = offset_in_page(dma_addr); @@ -352,7 +354,7 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_queue *nvmeq, prps = kmalloc(sizeof(*prps) + sizeof(__le64 *) * npages, GFP_ATOMIC); prps->npages = npages; prp_page = 0; - prp_list = alloc_prp_list(nvmeq, length, &prp_dma); + prp_list = alloc_prp_list(dev, &prp_dma); prps->list[prp_page++] = prp_list; prps->first_dma = prp_dma; cmd->prp2 = cpu_to_le64(prp_dma); @@ -360,7 +362,7 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_queue *nvmeq, for (;;) { if (i == PAGE_SIZE / 8 - 1) { __le64 *old_prp_list = prp_list; - prp_list = alloc_prp_list(nvmeq, length, &prp_dma); + prp_list = alloc_prp_list(dev, &prp_dma); prps->list[prp_page++] = prp_list; old_prp_list[i] = cpu_to_le64(prp_dma); i = 0; @@ -752,6 +754,7 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid, goto free_cqdma; nvmeq->q_dmadev = dmadev; + nvmeq->dev = dev; spin_lock_init(&nvmeq->q_lock); nvmeq->cq_head = 0; nvmeq->cq_phase = 1; @@ -1302,6 +1305,22 @@ static int nvme_dev_remove(struct nvme_dev *dev) return 0; } +static int nvme_setup_prp_pools(struct nvme_dev *dev) +{ + struct device *dmadev = &dev->pci_dev->dev; + dev->prp_page_pool = dma_pool_create("prp list page", dmadev, + PAGE_SIZE, PAGE_SIZE, 0); + if (!dev->prp_page_pool) + return -ENOMEM; + + return 0; +} + +static void nvme_release_prp_pools(struct nvme_dev *dev) +{ + dma_pool_destroy(dev->prp_page_pool); +} + /* XXX: Use an ida or something to let remove / add work correctly */ static void nvme_set_instance(struct nvme_dev *dev) { @@ -1346,6 +1365,10 @@ static int __devinit nvme_probe(struct pci_dev *pdev, nvme_set_instance(dev); dev->entry[0].vector = pdev->irq; + result = nvme_setup_prp_pools(dev); + if (result) + goto disable_msix; + dev->bar = ioremap(pci_resource_start(pdev, 0), 8192); if (!dev->bar) { result = -ENOMEM; @@ -1369,6 +1392,7 @@ static int __devinit nvme_probe(struct pci_dev *pdev, disable_msix: pci_disable_msix(pdev); nvme_release_instance(dev); + nvme_release_prp_pools(dev); disable: pci_disable_device(pdev); pci_release_regions(pdev); @@ -1386,6 +1410,7 @@ static void __devexit nvme_remove(struct pci_dev *pdev) pci_disable_msix(pdev); iounmap(dev->bar); nvme_release_instance(dev); + nvme_release_prp_pools(dev); pci_disable_device(pdev); pci_release_regions(pdev); kfree(dev->queues); -- cgit v0.10.2 From 99802a7aee2b3dd720e382c52b892cc6a8122b11 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 10 Feb 2011 10:30:34 -0500 Subject: NVMe: Optimise memory usage for I/Os between 4k and 128k Add a second memory pool for smaller I/Os. We can pack 16 of these on a single page instead of using an entire page for each one. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 80fe6a7..cd7aeba 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -58,6 +58,7 @@ struct nvme_dev { u32 __iomem *dbs; struct pci_dev *pci_dev; struct dma_pool *prp_page_pool; + struct dma_pool *prp_small_pool; int instance; int queue_count; u32 ctrl_config; @@ -249,11 +250,6 @@ static int nvme_submit_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd) return 0; } -static __le64 *alloc_prp_list(struct nvme_dev *dev, dma_addr_t *addr) -{ - return dma_pool_alloc(dev->prp_page_pool, GFP_ATOMIC, addr); -} - struct nvme_prps { int npages; dma_addr_t first_dma; @@ -271,6 +267,9 @@ static void nvme_free_prps(struct nvme_queue *nvmeq, struct nvme_prps *prps) return; prp_dma = prps->first_dma; + + if (prps->npages == 0) + dma_pool_free(dev->prp_small_pool, prps->list[0], prp_dma); for (i = 0; i < prps->npages; i++) { __le64 *prp_list = prps->list[i]; dma_addr_t next_prp_dma = le64_to_cpu(prp_list[last_prp]); @@ -322,6 +321,7 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_queue *nvmeq, struct scatterlist *sg, int length) { struct nvme_dev *dev = nvmeq->dev; + struct dma_pool *pool; int dma_len = sg_dma_len(sg); u64 dma_addr = sg_dma_address(sg); int offset = offset_in_page(dma_addr); @@ -352,9 +352,16 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_queue *nvmeq, nprps = DIV_ROUND_UP(length, PAGE_SIZE); npages = DIV_ROUND_UP(8 * nprps, PAGE_SIZE); prps = kmalloc(sizeof(*prps) + sizeof(__le64 *) * npages, GFP_ATOMIC); - prps->npages = npages; prp_page = 0; - prp_list = alloc_prp_list(dev, &prp_dma); + if (nprps <= (256 / 8)) { + pool = dev->prp_small_pool; + prps->npages = 0; + } else { + pool = dev->prp_page_pool; + prps->npages = npages; + } + + prp_list = dma_pool_alloc(pool, GFP_ATOMIC, &prp_dma); prps->list[prp_page++] = prp_list; prps->first_dma = prp_dma; cmd->prp2 = cpu_to_le64(prp_dma); @@ -362,7 +369,7 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_queue *nvmeq, for (;;) { if (i == PAGE_SIZE / 8 - 1) { __le64 *old_prp_list = prp_list; - prp_list = alloc_prp_list(dev, &prp_dma); + prp_list = dma_pool_alloc(pool, GFP_ATOMIC, &prp_dma); prps->list[prp_page++] = prp_list; old_prp_list[i] = cpu_to_le64(prp_dma); i = 0; @@ -1313,12 +1320,20 @@ static int nvme_setup_prp_pools(struct nvme_dev *dev) if (!dev->prp_page_pool) return -ENOMEM; + /* Optimisation for I/Os between 4k and 128k */ + dev->prp_small_pool = dma_pool_create("prp list 256", dmadev, + 256, 256, 0); + if (!dev->prp_small_pool) { + dma_pool_destroy(dev->prp_page_pool); + return -ENOMEM; + } return 0; } static void nvme_release_prp_pools(struct nvme_dev *dev) { dma_pool_destroy(dev->prp_page_pool); + dma_pool_destroy(dev->prp_small_pool); } /* XXX: Use an ida or something to let remove / add work correctly */ -- cgit v0.10.2 From d567760c409f981d35fc755b51d5bf56a99a467b Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 10 Feb 2011 10:47:55 -0500 Subject: NVMe: Pass the nvme_dev to nvme_free_prps and nvme_setup_prps We were passing the nvme_queue to access the q_dmadev for the dma_alloc_coherent calls, but since we moved to the dma pool API, we really only need the nvme_dev. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index cd7aeba..2948043 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -256,10 +256,9 @@ struct nvme_prps { __le64 *list[0]; }; -static void nvme_free_prps(struct nvme_queue *nvmeq, struct nvme_prps *prps) +static void nvme_free_prps(struct nvme_dev *dev, struct nvme_prps *prps) { const int last_prp = PAGE_SIZE / 8 - 1; - struct nvme_dev *dev = nvmeq->dev; int i; dma_addr_t prp_dma; @@ -295,7 +294,7 @@ static struct nvme_bio *alloc_nbio(unsigned nseg, gfp_t gfp) static void free_nbio(struct nvme_queue *nvmeq, struct nvme_bio *nbio) { - nvme_free_prps(nvmeq, nbio->prps); + nvme_free_prps(nvmeq->dev, nbio->prps); kfree(nbio); } @@ -316,11 +315,10 @@ static void bio_completion(struct nvme_queue *nvmeq, void *ctx, } /* length is in bytes */ -static struct nvme_prps *nvme_setup_prps(struct nvme_queue *nvmeq, +static struct nvme_prps *nvme_setup_prps(struct nvme_dev *dev, struct nvme_common_command *cmd, struct scatterlist *sg, int length) { - struct nvme_dev *dev = nvmeq->dev; struct dma_pool *pool; int dma_len = sg_dma_len(sg); u64 dma_addr = sg_dma_address(sg); @@ -458,7 +456,7 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, cmnd->rw.flags = 1; cmnd->rw.command_id = cmdid; cmnd->rw.nsid = cpu_to_le32(ns->ns_id); - nbio->prps = nvme_setup_prps(nvmeq, &cmnd->common, nbio->sg, + nbio->prps = nvme_setup_prps(nvmeq->dev, &cmnd->common, nbio->sg, bio->bi_size); cmnd->rw.slba = cpu_to_le64(bio->bi_sector >> (ns->lba_shift - 9)); cmnd->rw.length = cpu_to_le16((bio->bi_size >> ns->lba_shift) - 1); @@ -939,10 +937,10 @@ static int nvme_submit_user_admin_command(struct nvme_dev *dev, nents = nvme_map_user_pages(dev, 0, addr, length, &sg); if (nents < 0) return nents; - prps = nvme_setup_prps(dev->queues[0], &cmd->common, sg, length); + prps = nvme_setup_prps(dev, &cmd->common, sg, length); err = nvme_submit_admin_cmd(dev, cmd, NULL); nvme_unmap_user_pages(dev, 0, addr, length, sg, nents); - nvme_free_prps(dev->queues[0], prps); + nvme_free_prps(dev, prps); return err ? -EIO : 0; } @@ -1000,10 +998,10 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) c.rw.reftag = cpu_to_le32(io.reftag); /* XXX: endian? */ c.rw.apptag = cpu_to_le16(io.apptag); c.rw.appmask = cpu_to_le16(io.appmask); - nvmeq = get_nvmeq(ns); /* XXX: metadata */ - prps = nvme_setup_prps(nvmeq, &c.common, sg, length); + prps = nvme_setup_prps(dev, &c.common, sg, length); + nvmeq = get_nvmeq(ns); /* Since nvme_submit_sync_cmd sleeps, we can't keep preemption * disabled. We may be preempted at any point, and be rescheduled * to a different CPU. That will cause cacheline bouncing, but no @@ -1013,7 +1011,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) status = nvme_submit_sync_cmd(nvmeq, &c, &result, IO_TIMEOUT); nvme_unmap_user_pages(dev, io.opcode & 1, io.addr, length, sg, nents); - nvme_free_prps(nvmeq, prps); + nvme_free_prps(dev, prps); put_user(result, &uio->result); return status; } @@ -1041,11 +1039,11 @@ static int nvme_download_firmware(struct nvme_ns *ns, c.dlfw.opcode = nvme_admin_download_fw; c.dlfw.numd = cpu_to_le32(dlfw.length); c.dlfw.offset = cpu_to_le32(dlfw.offset); - prps = nvme_setup_prps(dev->queues[0], &c.common, sg, dlfw.length * 4); + prps = nvme_setup_prps(dev, &c.common, sg, dlfw.length * 4); status = nvme_submit_admin_cmd(dev, &c, NULL); nvme_unmap_user_pages(dev, 0, dlfw.addr, dlfw.length * 4, sg, nents); - nvme_free_prps(dev->queues[0], prps); + nvme_free_prps(dev, prps); return status; } -- cgit v0.10.2 From 1974b1ae8852324a75fb8cfecbc7b758fd5a2c3c Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 10 Feb 2011 12:01:09 -0500 Subject: NVMe: Check for DMA mapping failure If dma_map_sg returns 0 (failure), we need to fail the I/O. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 2948043..bfdca3a 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -451,7 +451,8 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, dma_dir = DMA_FROM_DEVICE; } - nvme_map_bio(nvmeq->q_dmadev, nbio, bio, dma_dir, psegs); + if (nvme_map_bio(nvmeq->q_dmadev, nbio, bio, dma_dir, psegs) == 0) + goto mapping_failed; cmnd->rw.flags = 1; cmnd->rw.command_id = cmdid; @@ -471,6 +472,11 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, return 0; + mapping_failed: + free_nbio(nvmeq, nbio); + bio_endio(bio, -ENOMEM); + return 0; + free_nbio: free_nbio(nvmeq, nbio); congestion: -- cgit v0.10.2 From 768308400f5b4ce665a072eb976a851978b7706e Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 10 Feb 2011 13:55:39 -0500 Subject: NVMe: Handle physical merging of bvec entries In order to not overrun the sg array, we have to merge physically contiguous pages into a single sg entry. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index bfdca3a..c0e84b6 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -392,19 +392,25 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_dev *dev, static int nvme_map_bio(struct device *dev, struct nvme_bio *nbio, struct bio *bio, enum dma_data_direction dma_dir, int psegs) { - struct bio_vec *bvec; - struct scatterlist *sg = nbio->sg; - int i, nsegs; + struct bio_vec *bvec, *bvprv = NULL; + struct scatterlist *sg = NULL; + int i, nsegs = 0; - sg_init_table(sg, psegs); + sg_init_table(nbio->sg, psegs); bio_for_each_segment(bvec, bio, i) { - sg_set_page(sg, bvec->bv_page, bvec->bv_len, bvec->bv_offset); - sg++; - /* XXX: handle non-mergable here */ - nsegs++; + if (bvprv && BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) { + sg->length += bvec->bv_len; + } else { + /* Check bvprv && offset == 0 */ + sg = sg ? sg + 1 : nbio->sg; + sg_set_page(sg, bvec->bv_page, bvec->bv_len, + bvec->bv_offset); + nsegs++; + } + bvprv = bvec; } nbio->nents = nsegs; - + sg_mark_end(sg); return dma_map_sg(dev, nbio->sg, nbio->nents, dma_dir); } -- cgit v0.10.2 From 897cfe1ce7db152fa6dde576f4213a6160bf6502 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 14 Feb 2011 12:20:15 -0500 Subject: NVMe: Update BAR structure to match the current spec Add two reserved registers in the middle of the BAR to match the 1.0 spec plus ECN 0002. Also rename IMC and ISC to INTMC and INTSC to conform with the spec. We still don't need to use them :-) Signed-off-by: Matthew Wilcox diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 8eed0e4..757faa7 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -24,10 +24,12 @@ struct nvme_bar { __u64 cap; /* Controller Capabilities */ __u32 vs; /* Version */ - __u32 ims; /* Interrupt Mask Set */ - __u32 imc; /* Interrupt Mask Clear */ + __u32 intms; /* Interrupt Mask Set */ + __u32 intmc; /* Interrupt Mask Clear */ __u32 cc; /* Controller Configuration */ + __u32 rsvd1; /* Reserved */ __u32 csts; /* Controller Status */ + __u32 rsvd2; /* Reserved */ __u32 aqa; /* Admin Queue Attributes */ __u64 asq; /* Admin SQ Base Address */ __u64 acq; /* Admin CQ Base Address */ -- cgit v0.10.2 From eeee322647a67c20d9277c5e02c42b2126ea74bc Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 14 Feb 2011 15:55:33 -0500 Subject: NVMe: Handle failures differently in nvme_submit_bio_queue() Return -EBUSY if the queue is full or -ENOMEM if we failed to allocate memory (or map a scatterlist). Also use GFP_ATOMIC to allocate the nvme_bio and move the locking to the callers of nvme_submit_bio_queue(). In nvme_make_request(), don't permit an I/O to jump the queue -- if the congestion list already has an entry, just add to the tail, rather than trying to submit. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index c0e84b6..61a2417 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -420,17 +420,17 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, struct nvme_command *cmnd; struct nvme_bio *nbio; enum dma_data_direction dma_dir; - int cmdid; + int cmdid, result = -ENOMEM; u16 control; u32 dsmgmt; - unsigned long flags; int psegs = bio_phys_segments(ns->queue, bio); - nbio = alloc_nbio(psegs, GFP_NOIO); + nbio = alloc_nbio(psegs, GFP_ATOMIC); if (!nbio) - goto congestion; + goto nomem; nbio->bio = bio; + result = -EBUSY; cmdid = alloc_cmdid(nvmeq, nbio, bio_completion_id, IO_TIMEOUT); if (unlikely(cmdid < 0)) goto free_nbio; @@ -445,7 +445,6 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, if (bio->bi_rw & REQ_RAHEAD) dsmgmt |= NVME_RW_DSM_FREQ_PREFETCH; - spin_lock_irqsave(&nvmeq->q_lock, flags); cmnd = &nvmeq->sq_cmds[nvmeq->sq_tail]; memset(cmnd, 0, sizeof(*cmnd)); @@ -457,8 +456,9 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, dma_dir = DMA_FROM_DEVICE; } + result = -ENOMEM; if (nvme_map_bio(nvmeq->q_dmadev, nbio, bio, dma_dir, psegs) == 0) - goto mapping_failed; + goto free_nbio; cmnd->rw.flags = 1; cmnd->rw.command_id = cmdid; @@ -474,19 +474,12 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, if (++nvmeq->sq_tail == nvmeq->q_depth) nvmeq->sq_tail = 0; - spin_unlock_irqrestore(&nvmeq->q_lock, flags); - - return 0; - - mapping_failed: - free_nbio(nvmeq, nbio); - bio_endio(bio, -ENOMEM); return 0; free_nbio: free_nbio(nvmeq, nbio); - congestion: - return -EBUSY; + nomem: + return result; } static void nvme_resubmit_bio(struct nvme_queue *nvmeq, struct bio *bio) @@ -507,13 +500,18 @@ static int nvme_make_request(struct request_queue *q, struct bio *bio) { struct nvme_ns *ns = q->queuedata; struct nvme_queue *nvmeq = get_nvmeq(ns); + int result = -EBUSY; - if (nvme_submit_bio_queue(nvmeq, ns, bio)) { - blk_set_queue_congested(q, rw_is_sync(bio->bi_rw)); - spin_lock_irq(&nvmeq->q_lock); + spin_lock_irq(&nvmeq->q_lock); + if (bio_list_empty(&nvmeq->sq_cong)) + result = nvme_submit_bio_queue(nvmeq, ns, bio); + if (unlikely(result)) { + if (bio_list_empty(&nvmeq->sq_cong)) + add_wait_queue(&nvmeq->sq_full, &nvmeq->sq_cong_wait); bio_list_add(&nvmeq->sq_cong, bio); - spin_unlock_irq(&nvmeq->q_lock); } + + spin_unlock_irq(&nvmeq->q_lock); put_nvmeq(nvmeq); return 0; -- cgit v0.10.2 From 1fa6aeadf18aeebd7a217d7a3a933856448375b6 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 2 Mar 2011 18:37:18 -0500 Subject: NVMe: Add a kthread to handle the congestion list Instead of trying to resubmit I/Os in the I/O completion path (in interrupt context), wake up a kthread which will resubmit I/O from user context. This allows mke2fs to run to completion. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 61a2417..606371e 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -50,10 +51,15 @@ module_param(nvme_major, int, 0); static int use_threaded_interrupts; module_param(use_threaded_interrupts, int, 0); +static DEFINE_SPINLOCK(dev_list_lock); +static LIST_HEAD(dev_list); +static struct task_struct *nvme_thread; + /* * Represents an NVM Express device. Each nvme_dev is a PCI function. */ struct nvme_dev { + struct list_head node; struct nvme_queue **queues; u32 __iomem *dbs; struct pci_dev *pci_dev; @@ -97,6 +103,7 @@ struct nvme_queue { dma_addr_t sq_dma_addr; dma_addr_t cq_dma_addr; wait_queue_head_t sq_full; + wait_queue_t sq_cong_wait; struct bio_list sq_cong; u32 __iomem *q_db; u16 q_depth; @@ -108,8 +115,6 @@ struct nvme_queue { unsigned long cmdid_data[]; }; -static void nvme_resubmit_bio(struct nvme_queue *nvmeq, struct bio *bio); - /* * Check we didin't inadvertently grow the command struct */ @@ -309,9 +314,6 @@ static void bio_completion(struct nvme_queue *nvmeq, void *ctx, bio_data_dir(bio) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); free_nbio(nvmeq, nbio); bio_endio(bio, status ? -EIO : 0); - bio = bio_list_pop(&nvmeq->sq_cong); - if (bio) - nvme_resubmit_bio(nvmeq, bio); } /* length is in bytes */ @@ -482,16 +484,6 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, return result; } -static void nvme_resubmit_bio(struct nvme_queue *nvmeq, struct bio *bio) -{ - struct nvme_ns *ns = bio->bi_bdev->bd_disk->private_data; - if (nvme_submit_bio_queue(nvmeq, ns, bio)) - bio_list_add_head(&nvmeq->sq_cong, bio); - else if (bio_list_empty(&nvmeq->sq_cong)) - blk_clear_queue_congested(ns->queue, rw_is_sync(bio->bi_rw)); - /* XXX: Need to duplicate the logic from __freed_request here */ -} - /* * NB: return value of non-zero would mean that we were a stacking driver. * make_request must always succeed. @@ -774,6 +766,7 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid, nvmeq->cq_head = 0; nvmeq->cq_phase = 1; init_waitqueue_head(&nvmeq->sq_full); + init_waitqueue_entry(&nvmeq->sq_cong_wait, nvme_thread); bio_list_init(&nvmeq->sq_cong); nvmeq->q_db = &dev->dbs[qid * 2]; nvmeq->q_depth = depth; @@ -1097,6 +1090,43 @@ static const struct block_device_operations nvme_fops = { .ioctl = nvme_ioctl, }; +static void nvme_resubmit_bios(struct nvme_queue *nvmeq) +{ + while (bio_list_peek(&nvmeq->sq_cong)) { + struct bio *bio = bio_list_pop(&nvmeq->sq_cong); + struct nvme_ns *ns = bio->bi_bdev->bd_disk->private_data; + if (nvme_submit_bio_queue(nvmeq, ns, bio)) { + bio_list_add_head(&nvmeq->sq_cong, bio); + break; + } + } +} + +static int nvme_kthread(void *data) +{ + struct nvme_dev *dev; + + while (!kthread_should_stop()) { + __set_current_state(TASK_RUNNING); + spin_lock(&dev_list_lock); + list_for_each_entry(dev, &dev_list, node) { + int i; + for (i = 0; i < dev->queue_count; i++) { + struct nvme_queue *nvmeq = dev->queues[i]; + spin_lock_irq(&nvmeq->q_lock); + if (nvme_process_cq(nvmeq)) + printk("process_cq did something\n"); + nvme_resubmit_bios(nvmeq); + spin_unlock_irq(&nvmeq->q_lock); + } + } + spin_unlock(&dev_list_lock); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ); + } + return 0; +} + static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int index, struct nvme_id_ns *id, struct nvme_lba_range_type *rt) { @@ -1307,6 +1337,10 @@ static int nvme_dev_remove(struct nvme_dev *dev) { struct nvme_ns *ns, *next; + spin_lock(&dev_list_lock); + list_del(&dev->node); + spin_unlock(&dev_list_lock); + /* TODO: wait all I/O finished or cancel them */ list_for_each_entry_safe(ns, next, &dev->namespaces, list) { @@ -1406,6 +1440,11 @@ static int __devinit nvme_probe(struct pci_dev *pdev, result = nvme_dev_add(dev); if (result) goto delete; + + spin_lock(&dev_list_lock); + list_add(&dev->node, &dev_list); + spin_unlock(&dev_list_lock); + return 0; delete: @@ -1479,17 +1518,25 @@ static struct pci_driver nvme_driver = { static int __init nvme_init(void) { - int result; + int result = -EBUSY; + + nvme_thread = kthread_run(nvme_kthread, NULL, "nvme"); + if (IS_ERR(nvme_thread)) + return PTR_ERR(nvme_thread); nvme_major = register_blkdev(nvme_major, "nvme"); if (nvme_major <= 0) - return -EBUSY; + goto kill_kthread; result = pci_register_driver(&nvme_driver); - if (!result) - return 0; + if (result) + goto unregister_blkdev; + return 0; + unregister_blkdev: unregister_blkdev(nvme_major, "nvme"); + kill_kthread: + kthread_stop(nvme_thread); return result; } @@ -1497,6 +1544,7 @@ static void __exit nvme_exit(void) { pci_unregister_driver(&nvme_driver); unregister_blkdev(nvme_major, "nvme"); + kthread_stop(nvme_thread); } MODULE_AUTHOR("Matthew Wilcox "); -- cgit v0.10.2 From ad8a5df97cb060aa4d817af25587c99e2d2fda97 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 14 Feb 2011 17:35:00 -0500 Subject: NVMe: Release 0.3 Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 606371e..7554625 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1549,6 +1549,6 @@ static void __exit nvme_exit(void) MODULE_AUTHOR("Matthew Wilcox "); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.2"); +MODULE_VERSION("0.3"); module_init(nvme_init); module_exit(nvme_exit); -- cgit v0.10.2 From ca1615424c9adfdbe7d484771d7a7c5ecc4bb6d2 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 15 Feb 2011 13:44:13 -0500 Subject: NVMe: Remove setting of 'flags' in rw command This was the data transfer bit until spec rev 0.92 Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 7554625..37cdf07 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -462,7 +462,6 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, if (nvme_map_bio(nvmeq->q_dmadev, nbio, bio, dma_dir, psegs) == 0) goto free_nbio; - cmnd->rw.flags = 1; cmnd->rw.command_id = cmdid; cmnd->rw.nsid = cpu_to_le32(ns->ns_id); nbio->prps = nvme_setup_prps(nvmeq->dev, &cmnd->common, nbio->sg, -- cgit v0.10.2 From b348b7d54368c87811907a8e88f0d96713c43009 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 15 Feb 2011 16:16:02 -0500 Subject: NVMe: Rename nr_queues to nr_io_queues I got confused about whether this included the admin queue or not, and had to resort to reading the spec. It doesn't include the admin queue, so make that clear in the name. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 37cdf07..f3aa809 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1202,29 +1202,30 @@ static int set_queue_count(struct nvme_dev *dev, int count) static int __devinit nvme_setup_io_queues(struct nvme_dev *dev) { - int result, cpu, i, nr_queues; + int result, cpu, i, nr_io_queues; - nr_queues = num_online_cpus(); - result = set_queue_count(dev, nr_queues); + nr_io_queues = num_online_cpus(); + result = set_queue_count(dev, nr_io_queues); if (result < 0) return result; - if (result < nr_queues) - nr_queues = result; + if (result < nr_io_queues) + nr_io_queues = result; /* Deregister the admin queue's interrupt */ free_irq(dev->entry[0].vector, dev->queues[0]); - for (i = 0; i < nr_queues; i++) + for (i = 0; i < nr_io_queues; i++) dev->entry[i].entry = i; for (;;) { - result = pci_enable_msix(dev->pci_dev, dev->entry, nr_queues); + result = pci_enable_msix(dev->pci_dev, dev->entry, + nr_io_queues); if (result == 0) { break; } else if (result > 0) { - nr_queues = result; + nr_io_queues = result; continue; } else { - nr_queues = 1; + nr_io_queues = 1; break; } } @@ -1233,12 +1234,12 @@ static int __devinit nvme_setup_io_queues(struct nvme_dev *dev) /* XXX: handle failure here */ cpu = cpumask_first(cpu_online_mask); - for (i = 0; i < nr_queues; i++) { + for (i = 0; i < nr_io_queues; i++) { irq_set_affinity_hint(dev->entry[i].vector, get_cpu_mask(cpu)); cpu = cpumask_next(cpu, cpu_online_mask); } - for (i = 0; i < nr_queues; i++) { + for (i = 0; i < nr_io_queues; i++) { dev->queues[i + 1] = nvme_create_queue(dev, i + 1, NVME_Q_DEPTH, i); if (!dev->queues[i + 1]) -- cgit v0.10.2 From 740216fc59cba54f65187c9ed92f29bce3cf8778 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 15 Feb 2011 16:28:20 -0500 Subject: NVMe: Let the kthread take care of devices earlier If interrupts are misconfigured, the kthread will be needed to process admin queue completions. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index f3aa809..df1d8bd 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1112,6 +1112,8 @@ static int nvme_kthread(void *data) int i; for (i = 0; i < dev->queue_count; i++) { struct nvme_queue *nvmeq = dev->queues[i]; + if (!nvmeq) + continue; spin_lock_irq(&nvmeq->q_lock); if (nvme_process_cq(nvmeq)) printk("process_cq did something\n"); @@ -1437,17 +1439,21 @@ static int __devinit nvme_probe(struct pci_dev *pdev, goto unmap; dev->queue_count++; - result = nvme_dev_add(dev); - if (result) - goto delete; - spin_lock(&dev_list_lock); list_add(&dev->node, &dev_list); spin_unlock(&dev_list_lock); + result = nvme_dev_add(dev); + if (result) + goto delete; + return 0; delete: + spin_lock(&dev_list_lock); + list_del(&dev->node); + spin_unlock(&dev_list_lock); + nvme_free_queues(dev); unmap: iounmap(dev->bar); -- cgit v0.10.2 From 7547881d0951384f9833ec3a80fac8f3f16f3b98 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 16 Feb 2011 09:59:59 -0500 Subject: NVMe: Correct SQ doorbell semantics The value written to the doorbell needs to be the first free index in the queue, not the most recently used index in the queue. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index df1d8bd..af45e28 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -246,9 +246,9 @@ static int nvme_submit_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd) spin_lock_irqsave(&nvmeq->q_lock, flags); tail = nvmeq->sq_tail; memcpy(&nvmeq->sq_cmds[tail], cmd, sizeof(*cmd)); - writel(tail, nvmeq->q_db); if (++tail == nvmeq->q_depth) tail = 0; + writel(tail, nvmeq->q_db); nvmeq->sq_tail = tail; spin_unlock_irqrestore(&nvmeq->q_lock, flags); @@ -471,9 +471,9 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, cmnd->rw.control = cpu_to_le16(control); cmnd->rw.dsmgmt = cpu_to_le32(dsmgmt); - writel(nvmeq->sq_tail, nvmeq->q_db); if (++nvmeq->sq_tail == nvmeq->q_depth) nvmeq->sq_tail = 0; + writel(nvmeq->sq_tail, nvmeq->q_db); return 0; -- cgit v0.10.2 From c42705592be2a539f3027b6f3907de8e8f9591a8 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 22 Feb 2011 14:15:34 -0500 Subject: NVMe: Mark CMD_CTX_CANCELLED as being unlikely Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index af45e28..ce919b4 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -518,7 +518,7 @@ static void sync_completion(struct nvme_queue *nvmeq, void *ctx, struct nvme_completion *cqe) { struct sync_cmd_info *cmdinfo = ctx; - if ((unsigned long)cmdinfo == CMD_CTX_CANCELLED) + if (unlikely((unsigned long)cmdinfo == CMD_CTX_CANCELLED)) return; if (unlikely((unsigned long)cmdinfo == CMD_CTX_COMPLETED)) { dev_warn(nvmeq->q_dmadev, -- cgit v0.10.2 From 00df5cb4eb927078850086f8becc3286a69ea12e Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 22 Feb 2011 14:18:30 -0500 Subject: NVMe: Implement Flush Linux implements Flush as a bit in the bio. That means there may also be data associated with the flush; if so the flush should be sent before the data. To avoid completing the bio twice, I add CMD_CTX_FLUSH to indicate the completion routine should do nothing. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index ce919b4..d99b400 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -191,10 +191,12 @@ enum { bio_completion_id, }; +/* Special values must be a multiple of 4, and less than 0x1000 */ #define CMD_CTX_BASE (POISON_POINTER_DELTA + sync_completion_id) #define CMD_CTX_CANCELLED (0x30C + CMD_CTX_BASE) #define CMD_CTX_COMPLETED (0x310 + CMD_CTX_BASE) #define CMD_CTX_INVALID (0x314 + CMD_CTX_BASE) +#define CMD_CTX_FLUSH (0x318 + CMD_CTX_BASE) static unsigned long free_cmdid(struct nvme_queue *nvmeq, int cmdid) { @@ -416,6 +418,33 @@ static int nvme_map_bio(struct device *dev, struct nvme_bio *nbio, return dma_map_sg(dev, nbio->sg, nbio->nents, dma_dir); } +static int nvme_submit_flush(struct nvme_queue *nvmeq, struct nvme_ns *ns, + int cmdid) +{ + struct nvme_command *cmnd = &nvmeq->sq_cmds[nvmeq->sq_tail]; + + memset(cmnd, 0, sizeof(*cmnd)); + cmnd->common.opcode = nvme_cmd_flush; + cmnd->common.command_id = cmdid; + cmnd->common.nsid = cpu_to_le32(ns->ns_id); + + if (++nvmeq->sq_tail == nvmeq->q_depth) + nvmeq->sq_tail = 0; + writel(nvmeq->sq_tail, nvmeq->q_db); + + return 0; +} + +static int nvme_submit_flush_data(struct nvme_queue *nvmeq, struct nvme_ns *ns) +{ + int cmdid = alloc_cmdid(nvmeq, (void *)CMD_CTX_FLUSH, + sync_completion_id, IO_TIMEOUT); + if (unlikely(cmdid < 0)) + return cmdid; + + return nvme_submit_flush(nvmeq, ns, cmdid); +} + static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, struct bio *bio) { @@ -427,6 +456,12 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, u32 dsmgmt; int psegs = bio_phys_segments(ns->queue, bio); + if ((bio->bi_rw & REQ_FLUSH) && psegs) { + result = nvme_submit_flush_data(nvmeq, ns); + if (result) + return result; + } + nbio = alloc_nbio(psegs, GFP_ATOMIC); if (!nbio) goto nomem; @@ -437,6 +472,9 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, if (unlikely(cmdid < 0)) goto free_nbio; + if ((bio->bi_rw & REQ_FLUSH) && !psegs) + return nvme_submit_flush(nvmeq, ns, cmdid); + control = 0; if (bio->bi_rw & REQ_FUA) control |= NVME_RW_FUA; @@ -520,6 +558,8 @@ static void sync_completion(struct nvme_queue *nvmeq, void *ctx, struct sync_cmd_info *cmdinfo = ctx; if (unlikely((unsigned long)cmdinfo == CMD_CTX_CANCELLED)) return; + if ((unsigned long)cmdinfo == CMD_CTX_FLUSH) + return; if (unlikely((unsigned long)cmdinfo == CMD_CTX_COMPLETED)) { dev_warn(nvmeq->q_dmadev, "completed id %d twice on queue %d\n", -- cgit v0.10.2 From 1ad2f8932a72bf375361727949ced2cb4e8cfcef Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 23 Feb 2011 15:20:00 -0500 Subject: NVMe: Handle bios that contain non-virtually contiguous addresses NVMe scatterlists must be virtually contiguous, like almost all I/Os. However, when the filesystem lays out files with a hole, it can be that adjacent LBAs map to non-adjacent virtual addresses. Handle this by submitting one NVMe command at a time for each virtually discontiguous range. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index d99b400..2409227 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -315,7 +315,14 @@ static void bio_completion(struct nvme_queue *nvmeq, void *ctx, dma_unmap_sg(nvmeq->q_dmadev, nbio->sg, nbio->nents, bio_data_dir(bio) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); free_nbio(nvmeq, nbio); - bio_endio(bio, status ? -EIO : 0); + if (status) + bio_endio(bio, -EIO); + if (bio->bi_vcnt > bio->bi_idx) { + bio_list_add(&nvmeq->sq_cong, bio); + wake_up_process(nvme_thread); + } else { + bio_endio(bio, 0); + } } /* length is in bytes */ @@ -393,29 +400,41 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_dev *dev, return prps; } +/* NVMe scatterlists require no holes in the virtual address */ +#define BIOVEC_NOT_VIRT_MERGEABLE(vec1, vec2) ((vec2)->bv_offset || \ + (((vec1)->bv_offset + (vec1)->bv_len) % PAGE_SIZE)) + static int nvme_map_bio(struct device *dev, struct nvme_bio *nbio, struct bio *bio, enum dma_data_direction dma_dir, int psegs) { struct bio_vec *bvec, *bvprv = NULL; struct scatterlist *sg = NULL; - int i, nsegs = 0; + int i, old_idx, length = 0, nsegs = 0; sg_init_table(nbio->sg, psegs); + old_idx = bio->bi_idx; bio_for_each_segment(bvec, bio, i) { if (bvprv && BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) { sg->length += bvec->bv_len; } else { - /* Check bvprv && offset == 0 */ + if (bvprv && BIOVEC_NOT_VIRT_MERGEABLE(bvprv, bvec)) + break; sg = sg ? sg + 1 : nbio->sg; sg_set_page(sg, bvec->bv_page, bvec->bv_len, bvec->bv_offset); nsegs++; } + length += bvec->bv_len; bvprv = bvec; } + bio->bi_idx = i; nbio->nents = nsegs; sg_mark_end(sg); - return dma_map_sg(dev, nbio->sg, nbio->nents, dma_dir); + if (dma_map_sg(dev, nbio->sg, nbio->nents, dma_dir) == 0) { + bio->bi_idx = old_idx; + return -ENOMEM; + } + return length; } static int nvme_submit_flush(struct nvme_queue *nvmeq, struct nvme_ns *ns, @@ -451,7 +470,7 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, struct nvme_command *cmnd; struct nvme_bio *nbio; enum dma_data_direction dma_dir; - int cmdid, result = -ENOMEM; + int cmdid, length, result = -ENOMEM; u16 control; u32 dsmgmt; int psegs = bio_phys_segments(ns->queue, bio); @@ -496,16 +515,17 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, dma_dir = DMA_FROM_DEVICE; } - result = -ENOMEM; - if (nvme_map_bio(nvmeq->q_dmadev, nbio, bio, dma_dir, psegs) == 0) + result = nvme_map_bio(nvmeq->q_dmadev, nbio, bio, dma_dir, psegs); + if (result < 0) goto free_nbio; + length = result; cmnd->rw.command_id = cmdid; cmnd->rw.nsid = cpu_to_le32(ns->ns_id); nbio->prps = nvme_setup_prps(nvmeq->dev, &cmnd->common, nbio->sg, - bio->bi_size); + length); cmnd->rw.slba = cpu_to_le64(bio->bi_sector >> (ns->lba_shift - 9)); - cmnd->rw.length = cpu_to_le16((bio->bi_size >> ns->lba_shift) - 1); + cmnd->rw.length = cpu_to_le16((length >> ns->lba_shift) - 1); cmnd->rw.control = cpu_to_le16(control); cmnd->rw.dsmgmt = cpu_to_le32(dsmgmt); -- cgit v0.10.2 From d8ee9d69f275769aaad40ef7c944565ff8d2d24f Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 24 Feb 2011 08:46:00 -0500 Subject: NVMe: Fix discontiguous accesses When we submit subsequent portions of the I/O, we need to access the updated block, not start reading again from the original position. This was showing up as miscompares in the XFS randholes testcase. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 2409227..562d75a 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -529,6 +529,8 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, cmnd->rw.control = cpu_to_le16(control); cmnd->rw.dsmgmt = cpu_to_le32(dsmgmt); + bio->bi_sector += length >> 9; + if (++nvmeq->sq_tail == nvmeq->q_depth) nvmeq->sq_tail = 0; writel(nvmeq->sq_tail, nvmeq->q_db); -- cgit v0.10.2 From e6d15f79f997a98b3a69abbc462fc9041cc1a7b4 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 24 Feb 2011 08:49:41 -0500 Subject: NVMe: Reduce maximum queue depth by 1 The spec says we're not allowed to completely fill the submission queue. Solve this by reducing the number of allocatable cmdids by 1. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 562d75a..45bfae1 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -156,7 +156,7 @@ static struct nvme_cmd_info *nvme_cmd_info(struct nvme_queue *nvmeq) static int alloc_cmdid(struct nvme_queue *nvmeq, void *ctx, int handler, unsigned timeout) { - int depth = nvmeq->q_depth; + int depth = nvmeq->q_depth - 1; struct nvme_cmd_info *info = nvme_cmd_info(nvmeq); int cmdid; -- cgit v0.10.2 From b57ab0fada358357571f0eb448cdf2f144785321 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 24 Feb 2011 16:20:14 -0500 Subject: NVMe: Version 0.4 Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 45bfae1..a8549df 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1617,6 +1617,6 @@ static void __exit nvme_exit(void) MODULE_AUTHOR("Matthew Wilcox "); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.3"); +MODULE_VERSION("0.4"); module_init(nvme_init); module_exit(nvme_exit); -- cgit v0.10.2 From 2ddc4f74d8adcf3e1cdec7f3e72d19b5c878597c Mon Sep 17 00:00:00 2001 From: Krzysztof Wierzbicki Date: Mon, 28 Feb 2011 08:27:13 +0100 Subject: NVMe: Update admin opcodes to match the 1.0RC spec Signed-off-by: Krzysztof Wierzbicki Signed-off-by: Matthew Wilcox Signed-off-by: Matthew Wilcox diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 757faa7..c46a9b7 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -199,19 +199,19 @@ enum { enum nvme_admin_opcode { nvme_admin_delete_sq = 0x00, nvme_admin_create_sq = 0x01, - nvme_admin_get_features = 0x02, + nvme_admin_get_log_page = 0x02, nvme_admin_delete_cq = 0x04, nvme_admin_create_cq = 0x05, nvme_admin_identify = 0x06, nvme_admin_abort_cmd = 0x08, nvme_admin_set_features = 0x09, - nvme_admin_get_log_page = 0x0a, + nvme_admin_get_features = 0x0a, nvme_admin_async_event = 0x0c, - nvme_admin_download_fw = 0x0d, - nvme_admin_security_recv = 0x0e, - nvme_admin_format_nvm = 0x10, - nvme_admin_security_send = 0x11, - nvme_admin_activate_fw = 0x14, + nvme_admin_activate_fw = 0x10, + nvme_admin_download_fw = 0x11, + nvme_admin_format_nvm = 0x80, + nvme_admin_security_send = 0x81, + nvme_admin_security_recv = 0x82, }; enum { -- cgit v0.10.2 From 714a7a22884b74862540bc84955274d86b2f6040 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 16 Mar 2011 16:28:24 -0400 Subject: NVMe: Convert comments to kernel-doc notation Reported-by: Randy Dunlap Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index a8549df..e392919 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -142,10 +142,10 @@ static struct nvme_cmd_info *nvme_cmd_info(struct nvme_queue *nvmeq) } /** - * alloc_cmdid - Allocate a Command ID - * @param nvmeq The queue that will be used for this command - * @param ctx A pointer that will be passed to the handler - * @param handler The ID of the handler to call + * alloc_cmdid() - Allocate a Command ID + * @nvmeq: The queue that will be used for this command + * @ctx: A pointer that will be passed to the handler + * @handler: The ID of the handler to call * * Allocate a Command ID for a queue. The data passed in will * be passed to the completion handler. This is implemented by using @@ -234,7 +234,7 @@ static void put_nvmeq(struct nvme_queue *nvmeq) } /** - * nvme_submit_cmd: Copy a command into a queue and ring the doorbell + * nvme_submit_cmd() - Copy a command into a queue and ring the doorbell * @nvmeq: The queue to use * @cmd: The command to send * -- cgit v0.10.2 From fa92282149842645931580225647238428374758 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 16 Mar 2011 16:29:00 -0400 Subject: NVMe: Fix comment formatting Reported-by: Randy Dunlap Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index e392919..740a9c1 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -182,7 +182,8 @@ static int alloc_cmdid_killable(struct nvme_queue *nvmeq, void *ctx, return (cmdid < 0) ? -EINTR : cmdid; } -/* If you need more than four handlers, you'll need to change how +/* + * If you need more than four handlers, you'll need to change how * alloc_cmdid and nvme_process_cq work. Consider using a special * CMD_CTX value instead, if that works for your situation. */ @@ -1066,7 +1067,8 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) prps = nvme_setup_prps(dev, &c.common, sg, length); nvmeq = get_nvmeq(ns); - /* Since nvme_submit_sync_cmd sleeps, we can't keep preemption + /* + * Since nvme_submit_sync_cmd sleeps, we can't keep preemption * disabled. We may be preempted at any point, and be rescheduled * to a different CPU. That will cause cacheline bouncing, but no * additional races since q_lock already protects against other CPUs. -- cgit v0.10.2 From 19e899b2f9f89f4a290dd5c9c24d15987a18ab21 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 16 Mar 2011 16:29:24 -0400 Subject: NVMe: Remove outdated comments The head can never overrun the tail since we won't allocate enough command IDs to let that happen. The status codes are in sync with the spec. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 740a9c1..d4f95eb 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -245,7 +245,6 @@ static int nvme_submit_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd) { unsigned long flags; u16 tail; - /* XXX: Need to check tail isn't going to overrun head */ spin_lock_irqsave(&nvmeq->q_lock, flags); tail = nvmeq->sq_tail; memcpy(&nvmeq->sq_cmds[tail], cmd, sizeof(*cmd)); diff --git a/include/linux/nvme.h b/include/linux/nvme.h index c46a9b7..6b5a8d1 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -323,7 +323,6 @@ struct nvme_command { }; }; -/* XXX: Sync with spec */ enum { NVME_SC_SUCCESS = 0x0, NVME_SC_INVALID_OPCODE = 0x1, -- cgit v0.10.2 From ac88c36a385b848cb9efcb877fdfc4153a60bcab Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 16 Mar 2011 16:29:58 -0400 Subject: NVMe: Fix interpretation of 'Number of Namespaces' field The spec says this is a 0s based value. We don't need to handle the maximal value because it's reserved to mean "every namespace". Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index d4f95eb..0d5c918 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1364,7 +1364,7 @@ static int __devinit nvme_dev_add(struct nvme_dev *dev) crt.features.prp1 = cpu_to_le64(dma_addr + 4096); crt.features.fid = cpu_to_le32(NVME_FEAT_LBA_RANGE); - for (i = 0; i < nn; i++) { + for (i = 0; i <= nn; i++) { cid.identify.nsid = cpu_to_le32(i); res = nvme_submit_admin_cmd(dev, &cid, NULL); if (res) -- cgit v0.10.2 From 7523d834dd1573610078eb1ac0933f6490232f90 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 16 Mar 2011 16:43:40 -0400 Subject: NVMe: Fix off-by-one when filling in PRP lists If the last element in the PRP list fits on the end of the page, there's no need to allocate an extra page to put that single element in. It can fit on the end of the page. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 0d5c918..cf89db8 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -376,12 +376,13 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_dev *dev, cmd->prp2 = cpu_to_le64(prp_dma); i = 0; for (;;) { - if (i == PAGE_SIZE / 8 - 1) { + if (i == PAGE_SIZE / 8) { __le64 *old_prp_list = prp_list; prp_list = dma_pool_alloc(pool, GFP_ATOMIC, &prp_dma); prps->list[prp_page++] = prp_list; - old_prp_list[i] = cpu_to_le64(prp_dma); - i = 0; + prp_list[0] = old_prp_list[i - 1]; + old_prp_list[i - 1] = cpu_to_le64(prp_dma); + i = 1; } prp_list[i++] = cpu_to_le64(dma_addr); dma_len -= PAGE_SIZE; -- cgit v0.10.2 From 3cb967c03926edd2c414082f4cc0feb7b372edae Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 16 Mar 2011 16:45:49 -0400 Subject: NVMe: Remove the kthread from the wait queue Once there are no more bios on the congestion list, we can stop waking up the nvme kthread every time a completion happens. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index cf89db8..8d3c0b7 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1162,6 +1162,9 @@ static void nvme_resubmit_bios(struct nvme_queue *nvmeq) bio_list_add_head(&nvmeq->sq_cong, bio); break; } + if (bio_list_empty(&nvmeq->sq_cong)) + remove_wait_queue(&nvmeq->sq_full, + &nvmeq->sq_cong_wait); } } -- cgit v0.10.2 From 9ecdc946212f7cd592986b2c519b470404caa6b8 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 16 Mar 2011 16:52:19 -0400 Subject: NVMe: Simplify queue lookup Fill in all the num_possible_cpus() entries with duplicate pointers. This reduces the complexity of the frequently-called get_nvmeq(), as well as avoiding a bug in it when there are fewer queues than CPUs. Reported-by: Shane Michael Matthews Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 8d3c0b7..f94f173 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -221,12 +221,7 @@ static void cancel_cmdid_data(struct nvme_queue *nvmeq, int cmdid) static struct nvme_queue *get_nvmeq(struct nvme_ns *ns) { - int qid, cpu = get_cpu(); - if (cpu < ns->dev->queue_count) - qid = cpu + 1; - else - qid = (cpu % rounddown_pow_of_two(ns->dev->queue_count)) + 1; - return ns->dev->queues[qid]; + return ns->dev->queues[get_cpu() + 1]; } static void put_nvmeq(struct nvme_queue *nvmeq) @@ -1316,6 +1311,11 @@ static int __devinit nvme_setup_io_queues(struct nvme_dev *dev) dev->queue_count++; } + for (; i < num_possible_cpus(); i++) { + int target = i % rounddown_pow_of_two(dev->queue_count - 1); + dev->queues[i + 1] = dev->queues[target + 1]; + } + return 0; } -- cgit v0.10.2 From 4948168280b269a514045766ddd872cfac5968e1 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sat, 19 Mar 2011 14:55:38 -0400 Subject: NVMe: Add compat_ioctl Make ioctls work for 32-bit applications on 64-bit kernels. The structures are defined to be the same for both 32- and 64-bit applications, so we can use the same handler for both. Reported-by: Arnd Bergmann Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index f94f173..d0b5262 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1146,6 +1146,7 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, static const struct block_device_operations nvme_fops = { .owner = THIS_MODULE, .ioctl = nvme_ioctl, + .compat_ioctl = nvme_ioctl, }; static void nvme_resubmit_bios(struct nvme_queue *nvmeq) -- cgit v0.10.2 From 9d4af1b7796ba02b73a79a8694399e5a3cd1c55d Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sun, 20 Mar 2011 07:27:10 -0400 Subject: NVMe: Correct the definitions of two ioctls NVME_IOCTL_SUBMIT_IO has a struct nvme_user_io, not a struct nvme_rw_command as a parameter, and NVME_IOCTL_DOWNLOAD_FW is a Write, not a Read. Reported-by: Arnd Bergmann Signed-off-by: Matthew Wilcox diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 6b5a8d1..fd10d59 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -395,8 +395,8 @@ struct nvme_dlfw { #define NVME_IOCTL_IDENTIFY_NS _IOW('N', 0x40, struct nvme_id_ns) #define NVME_IOCTL_IDENTIFY_CTRL _IOW('N', 0x41, struct nvme_id_ctrl) #define NVME_IOCTL_GET_RANGE_TYPE _IOW('N', 0x42, struct nvme_lba_range_type) -#define NVME_IOCTL_SUBMIT_IO _IOWR('N', 0x43, struct nvme_rw_command) -#define NVME_IOCTL_DOWNLOAD_FW _IOR('N', 0x44, struct nvme_dlfw) +#define NVME_IOCTL_SUBMIT_IO _IOWR('N', 0x43, struct nvme_user_io) +#define NVME_IOCTL_DOWNLOAD_FW _IOW('N', 0x44, struct nvme_dlfw) #define NVME_IOCTL_ACTIVATE_FW _IO('N', 0x45) #endif /* _LINUX_NVME_H */ -- cgit v0.10.2 From 6c7d49455ceb63064f992347d9185ff5bf43497a Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 21 Mar 2011 09:48:57 -0400 Subject: NVMe: Change the definition of nvme_user_io The read and write commands don't define a 'result', so there's no need to copy it back to userspace. Remove the ability of the ioctl to submit commands to a different namespace; it's just asking for trouble, and the use case I have in mind will be addressed througha different ioctl in the future. That removes the need for both the block_shift and nsid arguments. Check that the opcode is one of 'read' or 'write'. Future opcodes may be added in the future, but we will need a different structure definition for them. The nblocks field is redefined to be 0-based. This allows the user to request the full 65536 blocks. Don't byteswap the reftag, apptag and appmask. Martin Petersen tells me these are calculated in big-endian and are transmitted to the device in big-endian. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index d0b5262..90a96ec 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1035,29 +1035,37 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) struct nvme_user_io io; struct nvme_command c; unsigned length; - u32 result; int nents, status; struct scatterlist *sg; struct nvme_prps *prps; if (copy_from_user(&io, uio, sizeof(io))) return -EFAULT; - length = io.nblocks << io.block_shift; - nents = nvme_map_user_pages(dev, io.opcode & 1, io.addr, length, &sg); + length = (io.nblocks + 1) << ns->lba_shift; + + switch (io.opcode) { + case nvme_cmd_write: + case nvme_cmd_read: + nents = nvme_map_user_pages(dev, io.opcode & 1, io.addr, + length, &sg); + default: + return -EFAULT; + } + if (nents < 0) return nents; memset(&c, 0, sizeof(c)); c.rw.opcode = io.opcode; c.rw.flags = io.flags; - c.rw.nsid = cpu_to_le32(io.nsid); + c.rw.nsid = cpu_to_le32(ns->ns_id); c.rw.slba = cpu_to_le64(io.slba); - c.rw.length = cpu_to_le16(io.nblocks - 1); + c.rw.length = cpu_to_le16(io.nblocks); c.rw.control = cpu_to_le16(io.control); c.rw.dsmgmt = cpu_to_le16(io.dsmgmt); - c.rw.reftag = cpu_to_le32(io.reftag); /* XXX: endian? */ - c.rw.apptag = cpu_to_le16(io.apptag); - c.rw.appmask = cpu_to_le16(io.appmask); + c.rw.reftag = io.reftag; + c.rw.apptag = io.apptag; + c.rw.appmask = io.appmask; /* XXX: metadata */ prps = nvme_setup_prps(dev, &c.common, sg, length); @@ -1069,11 +1077,10 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) * additional races since q_lock already protects against other CPUs. */ put_nvmeq(nvmeq); - status = nvme_submit_sync_cmd(nvmeq, &c, &result, IO_TIMEOUT); + status = nvme_submit_sync_cmd(nvmeq, &c, NULL, IO_TIMEOUT); nvme_unmap_user_pages(dev, io.opcode & 1, io.addr, length, sg, nents); nvme_free_prps(dev, prps); - put_user(result, &uio->result); return status; } diff --git a/include/linux/nvme.h b/include/linux/nvme.h index fd10d59..347ad5f 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -373,17 +373,15 @@ struct nvme_user_io { __u8 opcode; __u8 flags; __u16 control; - __u32 nsid; + __u16 nblocks; + __u16 rsvd; __u64 metadata; __u64 addr; __u64 slba; - __u16 nblocks; - __u16 block_shift; __u32 dsmgmt; __u32 reftag; __u16 apptag; __u16 appmask; - __u32 result; }; struct nvme_dlfw { @@ -395,7 +393,7 @@ struct nvme_dlfw { #define NVME_IOCTL_IDENTIFY_NS _IOW('N', 0x40, struct nvme_id_ns) #define NVME_IOCTL_IDENTIFY_CTRL _IOW('N', 0x41, struct nvme_id_ctrl) #define NVME_IOCTL_GET_RANGE_TYPE _IOW('N', 0x42, struct nvme_lba_range_type) -#define NVME_IOCTL_SUBMIT_IO _IOWR('N', 0x43, struct nvme_user_io) +#define NVME_IOCTL_SUBMIT_IO _IOW('N', 0x43, struct nvme_user_io) #define NVME_IOCTL_DOWNLOAD_FW _IOW('N', 0x44, struct nvme_dlfw) #define NVME_IOCTL_ACTIVATE_FW _IO('N', 0x45) -- cgit v0.10.2 From 8ef700678f65e2eef1c3a94cdedb79d757608392 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 21 Mar 2011 10:28:43 -0400 Subject: NVMe: Version 0.5 Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 90a96ec..d3eeca5 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1630,6 +1630,6 @@ static void __exit nvme_exit(void) MODULE_AUTHOR("Matthew Wilcox "); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.4"); +MODULE_VERSION("0.5"); module_init(nvme_init); module_exit(nvme_exit); -- cgit v0.10.2 From 7f53f9d2424533256ae86f7df5661a17de743de8 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 22 Mar 2011 15:55:45 -0400 Subject: NVMe: Correct the Controller Configuration settings The arbitration field was extended by one bit, shifting the shutdown notification bits by one. Also, the SQ/CQ entry size was made configurable for future extensions. Reported-by: Paul Luse Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index d3eeca5..014a7f6 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -905,6 +905,7 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) dev->ctrl_config = NVME_CC_ENABLE | NVME_CC_CSS_NVM; dev->ctrl_config |= (PAGE_SHIFT - 12) << NVME_CC_MPS_SHIFT; dev->ctrl_config |= NVME_CC_ARB_RR | NVME_CC_SHN_NONE; + dev->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES; writel(0, &dev->bar->cc); writel(aqa, &dev->bar->aqa); diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 347ad5f..9d6febb 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -41,10 +41,12 @@ enum { NVME_CC_MPS_SHIFT = 7, NVME_CC_ARB_RR = 0 << 11, NVME_CC_ARB_WRRU = 1 << 11, - NVME_CC_ARB_VS = 3 << 11, - NVME_CC_SHN_NONE = 0 << 13, - NVME_CC_SHN_NORMAL = 1 << 13, - NVME_CC_SHN_ABRUPT = 2 << 13, + NVME_CC_ARB_VS = 7 << 11, + NVME_CC_SHN_NONE = 0 << 14, + NVME_CC_SHN_NORMAL = 1 << 14, + NVME_CC_SHN_ABRUPT = 2 << 14, + NVME_CC_IOSQES = 6 << 16, + NVME_CC_IOCQES = 4 << 20, NVME_CSTS_RDY = 1 << 0, NVME_CSTS_CFS = 1 << 1, NVME_CSTS_SHST_NORMAL = 0 << 2, -- cgit v0.10.2 From aba2080f3f1639f9202f1a52993669844abcfb80 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sun, 27 Mar 2011 08:52:06 -0400 Subject: NVMe: Fix warning in free_irq We need to clear the affinity mask before calling free_irq() Reported-by: Shane Michael Matthews Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 014a7f6..bcc780a 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -781,8 +781,10 @@ static int adapter_delete_sq(struct nvme_dev *dev, u16 sqid) static void nvme_free_queue(struct nvme_dev *dev, int qid) { struct nvme_queue *nvmeq = dev->queues[qid]; + int vector = dev->entry[nvmeq->cq_vector].vector; - free_irq(dev->entry[nvmeq->cq_vector].vector, nvmeq); + irq_set_affinity_hint(vector, NULL); + free_irq(vector, nvmeq); /* Don't tell the adapter to delete the admin queue */ if (qid) { -- cgit v0.10.2 From 22605f96810d073eb74051d0295b6577d6a6a563 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 19 Apr 2011 15:04:20 -0400 Subject: NVMe: Time out initialisation after a few seconds THe device reports (in its capability register) how long it will take to initialise. If that time elapses before the ready bit becomes set, conclude the device is broken and refuse to initialise it. Log a nice error message so the user knows why we did nothing. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index bcc780a..57f2b33a 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -893,6 +893,8 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) { int result; u32 aqa; + u64 cap; + unsigned long timeout; struct nvme_queue *nvmeq; dev->dbs = ((void __iomem *)dev->bar) + 4096; @@ -915,10 +917,18 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) writeq(nvmeq->cq_dma_addr, &dev->bar->acq); writel(dev->ctrl_config, &dev->bar->cc); + cap = readq(&dev->bar->cap); + timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies; + while (!(readl(&dev->bar->csts) & NVME_CSTS_RDY)) { msleep(100); if (fatal_signal_pending(current)) return -EINTR; + if (time_after(jiffies, timeout)) { + dev_err(&dev->pci_dev->dev, + "Device not ready; aborting initialisation\n"); + return -ENODEV; + } } result = queue_request_irq(dev, nvmeq, "nvme admin"); diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 9d6febb..a19304f 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -35,6 +35,8 @@ struct nvme_bar { __u64 acq; /* Admin CQ Base Address */ }; +#define NVME_CAP_TIMEOUT(cap) (((cap) >> 24) & 0xff) + enum { NVME_CC_ENABLE = 1 << 0, NVME_CC_CSS_NVM = 0 << 4, -- cgit v0.10.2 From 09a58f536436efed02ead722e835cb4ce7674afc Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 28 Apr 2011 23:09:09 -0700 Subject: NVMe: Fix bug in error handling When an I/O completed with an error, we would call bio_endio twice (once with -EIO and once with 0). Found by inspection. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 57f2b33a..205405e 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -310,9 +310,9 @@ static void bio_completion(struct nvme_queue *nvmeq, void *ctx, dma_unmap_sg(nvmeq->q_dmadev, nbio->sg, nbio->nents, bio_data_dir(bio) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); free_nbio(nvmeq, nbio); - if (status) + if (status) { bio_endio(bio, -EIO); - if (bio->bi_vcnt > bio->bi_idx) { + } else if (bio->bi_vcnt > bio->bi_idx) { bio_list_add(&nvmeq->sq_cong, bio); wake_up_process(nvme_thread); } else { -- cgit v0.10.2 From 21075bdee0a6f56058920d889df4ae561bfed754 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 28 Apr 2011 23:17:36 -0700 Subject: NVMe: Rename cancel_cmdid_data to cancel_cmdid The trailing '_data' on the end was annoying and inconsistent. Also, make it actually return the data since this is needed for timing out commands. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 205405e..9ca9db9 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -213,10 +213,13 @@ static unsigned long free_cmdid(struct nvme_queue *nvmeq, int cmdid) return data; } -static void cancel_cmdid_data(struct nvme_queue *nvmeq, int cmdid) +static unsigned long cancel_cmdid(struct nvme_queue *nvmeq, int cmdid) { + unsigned long data; struct nvme_cmd_info *info = nvme_cmd_info(nvmeq); + data = info[cmdid].ctx; info[cmdid].ctx = CMD_CTX_CANCELLED; + return data; } static struct nvme_queue *get_nvmeq(struct nvme_ns *ns) @@ -667,7 +670,7 @@ static irqreturn_t nvme_irq_check(int irq, void *data) static void nvme_abort_command(struct nvme_queue *nvmeq, int cmdid) { spin_lock_irq(&nvmeq->q_lock); - cancel_cmdid_data(nvmeq, cmdid); + cancel_cmdid(nvmeq, cmdid); spin_unlock_irq(&nvmeq->q_lock); } -- cgit v0.10.2 From 8de055350fbaa96b6563892c195a60be583faa9c Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 12 May 2011 13:50:28 -0400 Subject: NVMe: Add support for timing out I/Os In the kthread, walk the list of outstanding I/Os and check they've not hit the timeout. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 9ca9db9..9c0ab2a 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -601,15 +602,15 @@ static void sync_completion(struct nvme_queue *nvmeq, void *ctx, typedef void (*completion_fn)(struct nvme_queue *, void *, struct nvme_completion *); +static const completion_fn nvme_completions[4] = { + [sync_completion_id] = sync_completion, + [bio_completion_id] = bio_completion, +}; + static irqreturn_t nvme_process_cq(struct nvme_queue *nvmeq) { u16 head, phase; - static const completion_fn completions[4] = { - [sync_completion_id] = sync_completion, - [bio_completion_id] = bio_completion, - }; - head = nvmeq->cq_head; phase = nvmeq->cq_phase; @@ -629,7 +630,7 @@ static irqreturn_t nvme_process_cq(struct nvme_queue *nvmeq) data = free_cmdid(nvmeq, cqe.command_id); handler = data & 3; ptr = (void *)(data & ~3UL); - completions[handler](nvmeq, ptr, &cqe); + nvme_completions[handler](nvmeq, ptr, &cqe); } /* If the controller ignores the cq head doorbell and continuously @@ -1172,6 +1173,29 @@ static const struct block_device_operations nvme_fops = { .compat_ioctl = nvme_ioctl, }; +static void nvme_timeout_ios(struct nvme_queue *nvmeq) +{ + int depth = nvmeq->q_depth - 1; + struct nvme_cmd_info *info = nvme_cmd_info(nvmeq); + unsigned long now = jiffies; + int cmdid; + + for_each_set_bit(cmdid, nvmeq->cmdid_data, depth) { + unsigned long data; + void *ptr; + unsigned char handler; + static struct nvme_completion cqe = { .status = cpu_to_le16(NVME_SC_ABORT_REQ) << 1, }; + + if (!time_after(now, info[cmdid].timeout)) + continue; + dev_warn(nvmeq->q_dmadev, "Timing out I/O %d\n", cmdid); + data = cancel_cmdid(nvmeq, cmdid); + handler = data & 3; + ptr = (void *)(data & ~3UL); + nvme_completions[handler](nvmeq, ptr, &cqe); + } +} + static void nvme_resubmit_bios(struct nvme_queue *nvmeq) { while (bio_list_peek(&nvmeq->sq_cong)) { @@ -1203,6 +1227,7 @@ static int nvme_kthread(void *data) spin_lock_irq(&nvmeq->q_lock); if (nvme_process_cq(nvmeq)) printk("process_cq did something\n"); + nvme_timeout_ios(nvmeq); nvme_resubmit_bios(nvmeq); spin_unlock_irq(&nvmeq->q_lock); } -- cgit v0.10.2 From fd63e9ceeeae58cfe877c2d49d41c1bf7532303c Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 6 May 2011 08:37:54 -0400 Subject: NVMe: Add include of delay.h for msleep Previously it was being implicitly included through some other header file Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 9c0ab2a..b285a7e 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include -- cgit v0.10.2 From 5aff9382ddc8aac6eb0c70ffbb351652d71da69a Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 6 May 2011 08:45:47 -0400 Subject: NVMe: Use an IDA to allocate minor numbers The current approach of using the namespace ID as the minor number doesn't work when there are multiple adapters in the machine. Rather than statically partitioning the number of namespaces between adapters, dynamically allocate minor numbers to namespaces as they are detected. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index b285a7e..79012c5 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1240,7 +1241,34 @@ static int nvme_kthread(void *data) return 0; } -static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int index, +static DEFINE_IDA(nvme_index_ida); + +static int nvme_get_ns_idx(void) +{ + int index, error; + + do { + if (!ida_pre_get(&nvme_index_ida, GFP_KERNEL)) + return -1; + + spin_lock(&dev_list_lock); + error = ida_get_new(&nvme_index_ida, &index); + spin_unlock(&dev_list_lock); + } while (error == -EAGAIN); + + if (error) + index = -1; + return index; +} + +static void nvme_put_ns_idx(int index) +{ + spin_lock(&dev_list_lock); + ida_remove(&nvme_index_ida, index); + spin_unlock(&dev_list_lock); +} + +static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int nsid, struct nvme_id_ns *id, struct nvme_lba_range_type *rt) { struct nvme_ns *ns; @@ -1265,19 +1293,19 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int index, disk = alloc_disk(NVME_MINORS); if (!disk) goto out_free_queue; - ns->ns_id = index; + ns->ns_id = nsid; ns->disk = disk; lbaf = id->flbas & 0xf; ns->lba_shift = id->lbaf[lbaf].ds; disk->major = nvme_major; disk->minors = NVME_MINORS; - disk->first_minor = NVME_MINORS * index; + disk->first_minor = NVME_MINORS * nvme_get_ns_idx(); disk->fops = &nvme_fops; disk->private_data = ns; disk->queue = ns->queue; disk->driverfs_dev = &dev->pci_dev->dev; - sprintf(disk->disk_name, "nvme%dn%d", dev->instance, index); + sprintf(disk->disk_name, "nvme%dn%d", dev->instance, nsid); set_capacity(disk, le64_to_cpup(&id->nsze) << (ns->lba_shift - 9)); return ns; @@ -1291,7 +1319,9 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int index, static void nvme_ns_free(struct nvme_ns *ns) { + int index = ns->disk->first_minor / NVME_MINORS; put_disk(ns->disk); + nvme_put_ns_idx(index); blk_cleanup_queue(ns->queue); kfree(ns); } -- cgit v0.10.2 From b77954cbddff28d55a36fad3c16f4daebb0f01df Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 12 May 2011 13:51:41 -0400 Subject: NVMe: Handle failures from memory allocations in nvme_setup_prps If any of the memory allocations in nvme_setup_prps fail, handle it by modifying the passed-in data length to reflect the number of bytes we are actually able to send. Also allow the caller to specify the GFP flags they need; for user-initiated commands, we can use GFP_KERNEL allocations. The various callers are updated to handle this possibility; the main I/O path is already prepared for this possibility (as it may happen due to nvme_map_bio being unable to map all the segments of the I/O). The other callers return -ENOMEM instead of doing partial I/Os. Reported-by: Andi Kleen Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 79012c5..ddc21ba 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -329,9 +329,11 @@ static void bio_completion(struct nvme_queue *nvmeq, void *ctx, /* length is in bytes */ static struct nvme_prps *nvme_setup_prps(struct nvme_dev *dev, struct nvme_common_command *cmd, - struct scatterlist *sg, int length) + struct scatterlist *sg, int *len, + gfp_t gfp) { struct dma_pool *pool; + int length = *len; int dma_len = sg_dma_len(sg); u64 dma_addr = sg_dma_address(sg); int offset = offset_in_page(dma_addr); @@ -361,7 +363,12 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_dev *dev, nprps = DIV_ROUND_UP(length, PAGE_SIZE); npages = DIV_ROUND_UP(8 * nprps, PAGE_SIZE); - prps = kmalloc(sizeof(*prps) + sizeof(__le64 *) * npages, GFP_ATOMIC); + prps = kmalloc(sizeof(*prps) + sizeof(__le64 *) * npages, gfp); + if (!prps) { + cmd->prp2 = cpu_to_le64(dma_addr); + *len = (*len - length) + PAGE_SIZE; + return prps; + } prp_page = 0; if (nprps <= (256 / 8)) { pool = dev->prp_small_pool; @@ -371,7 +378,13 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_dev *dev, prps->npages = npages; } - prp_list = dma_pool_alloc(pool, GFP_ATOMIC, &prp_dma); + prp_list = dma_pool_alloc(pool, gfp, &prp_dma); + if (!prp_list) { + cmd->prp2 = cpu_to_le64(dma_addr); + *len = (*len - length) + PAGE_SIZE; + kfree(prps); + return NULL; + } prps->list[prp_page++] = prp_list; prps->first_dma = prp_dma; cmd->prp2 = cpu_to_le64(prp_dma); @@ -379,7 +392,11 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_dev *dev, for (;;) { if (i == PAGE_SIZE / 8) { __le64 *old_prp_list = prp_list; - prp_list = dma_pool_alloc(pool, GFP_ATOMIC, &prp_dma); + prp_list = dma_pool_alloc(pool, gfp, &prp_dma); + if (!prp_list) { + *len = (*len - length); + return prps; + } prps->list[prp_page++] = prp_list; prp_list[0] = old_prp_list[i - 1]; old_prp_list[i - 1] = cpu_to_le64(prp_dma); @@ -525,7 +542,7 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, cmnd->rw.command_id = cmdid; cmnd->rw.nsid = cpu_to_le32(ns->ns_id); nbio->prps = nvme_setup_prps(nvmeq->dev, &cmnd->common, nbio->sg, - length); + &length, GFP_ATOMIC); cmnd->rw.slba = cpu_to_le64(bio->bi_sector >> (ns->lba_shift - 9)); cmnd->rw.length = cpu_to_le16((length >> ns->lba_shift) - 1); cmnd->rw.control = cpu_to_le16(control); @@ -1009,15 +1026,18 @@ static int nvme_submit_user_admin_command(struct nvme_dev *dev, unsigned long addr, unsigned length, struct nvme_command *cmd) { - int err, nents; + int err, nents, tmplen = length; struct scatterlist *sg; struct nvme_prps *prps; nents = nvme_map_user_pages(dev, 0, addr, length, &sg); if (nents < 0) return nents; - prps = nvme_setup_prps(dev, &cmd->common, sg, length); - err = nvme_submit_admin_cmd(dev, cmd, NULL); + prps = nvme_setup_prps(dev, &cmd->common, sg, &tmplen, GFP_KERNEL); + if (tmplen != length) + err = -ENOMEM; + else + err = nvme_submit_admin_cmd(dev, cmd, NULL); nvme_unmap_user_pages(dev, 0, addr, length, sg, nents); nvme_free_prps(dev, prps); return err ? -EIO : 0; @@ -1086,7 +1106,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) c.rw.apptag = io.apptag; c.rw.appmask = io.appmask; /* XXX: metadata */ - prps = nvme_setup_prps(dev, &c.common, sg, length); + prps = nvme_setup_prps(dev, &c.common, sg, &length, GFP_KERNEL); nvmeq = get_nvmeq(ns); /* @@ -1096,7 +1116,10 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) * additional races since q_lock already protects against other CPUs. */ put_nvmeq(nvmeq); - status = nvme_submit_sync_cmd(nvmeq, &c, NULL, IO_TIMEOUT); + if (length != (io.nblocks + 1) << ns->lba_shift) + status = -ENOMEM; + else + status = nvme_submit_sync_cmd(nvmeq, &c, NULL, IO_TIMEOUT); nvme_unmap_user_pages(dev, io.opcode & 1, io.addr, length, sg, nents); nvme_free_prps(dev, prps); @@ -1109,7 +1132,7 @@ static int nvme_download_firmware(struct nvme_ns *ns, struct nvme_dev *dev = ns->dev; struct nvme_dlfw dlfw; struct nvme_command c; - int nents, status; + int nents, status, length; struct scatterlist *sg; struct nvme_prps *prps; @@ -1117,8 +1140,9 @@ static int nvme_download_firmware(struct nvme_ns *ns, return -EFAULT; if (dlfw.length >= (1 << 30)) return -EINVAL; + length = dlfw.length * 4; - nents = nvme_map_user_pages(dev, 1, dlfw.addr, dlfw.length * 4, &sg); + nents = nvme_map_user_pages(dev, 1, dlfw.addr, length, &sg); if (nents < 0) return nents; @@ -1126,9 +1150,11 @@ static int nvme_download_firmware(struct nvme_ns *ns, c.dlfw.opcode = nvme_admin_download_fw; c.dlfw.numd = cpu_to_le32(dlfw.length); c.dlfw.offset = cpu_to_le32(dlfw.offset); - prps = nvme_setup_prps(dev, &c.common, sg, dlfw.length * 4); - - status = nvme_submit_admin_cmd(dev, &c, NULL); + prps = nvme_setup_prps(dev, &c.common, sg, &length, GFP_KERNEL); + if (length != dlfw.length * 4) + status = -ENOMEM; + else + status = nvme_submit_admin_cmd(dev, &c, NULL); nvme_unmap_user_pages(dev, 0, dlfw.addr, dlfw.length * 4, sg, nents); nvme_free_prps(dev, prps); return status; -- cgit v0.10.2 From 184d2944cb3b92a2e8e1733c59d1e531ad6e924a Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 11 May 2011 21:36:38 -0400 Subject: NVMe: Add a few calling convention notes For the benefit of reviewers, add comments to a few functions describing their calling context Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index ddc21ba..12062c1 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -155,6 +155,9 @@ static struct nvme_cmd_info *nvme_cmd_info(struct nvme_queue *nvmeq) * the bottom two bits of the ctx pointer to store the handler ID. * Passing in a pointer that's not 4-byte aligned will cause a BUG. * We can change this if it becomes a problem. + * + * May be called with local interrupts disabled and the q_lock held, + * or with interrupts enabled and no locks held. */ static int alloc_cmdid(struct nvme_queue *nvmeq, void *ctx, int handler, unsigned timeout) @@ -202,6 +205,9 @@ enum { #define CMD_CTX_INVALID (0x314 + CMD_CTX_BASE) #define CMD_CTX_FLUSH (0x318 + CMD_CTX_BASE) +/* + * Called with local interrupts disabled and the q_lock held. May not sleep. + */ static unsigned long free_cmdid(struct nvme_queue *nvmeq, int cmdid) { unsigned long data; @@ -326,7 +332,7 @@ static void bio_completion(struct nvme_queue *nvmeq, void *ctx, } } -/* length is in bytes */ +/* length is in bytes. gfp flags indicates whether we may sleep. */ static struct nvme_prps *nvme_setup_prps(struct nvme_dev *dev, struct nvme_common_command *cmd, struct scatterlist *sg, int *len, @@ -483,6 +489,9 @@ static int nvme_submit_flush_data(struct nvme_queue *nvmeq, struct nvme_ns *ns) return nvme_submit_flush(nvmeq, ns, cmdid); } +/* + * Called with local interrupts disabled and the q_lock held. May not sleep. + */ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, struct bio *bio) { -- cgit v0.10.2 From be5e09484078e95af20acb13e215cd8aec705893 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 11 May 2011 21:38:57 -0400 Subject: NVMe: Version 0.6 Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 12062c1..d1cd91b 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1737,6 +1737,6 @@ static void __exit nvme_exit(void) MODULE_AUTHOR("Matthew Wilcox "); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.5"); +MODULE_VERSION("0.6"); module_init(nvme_init); module_exit(nvme_exit); -- cgit v0.10.2 From 6f0f54499f2edf7e25410cdd99e6f030f3485fd1 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 11 May 2011 13:30:59 -0700 Subject: NVMe: Return real error from nvme_create_queue nvme_setup_io_queues() was assuming that a NULL return from nvme_create_queue() was an out-of-memory error. That's not necessarily true; the adapter might return -EIO, for example. Change the calling convention to return an ERR_PTR on failure instead of NULL. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index d1cd91b..843edbd 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -892,7 +892,7 @@ static __devinit struct nvme_queue *nvme_create_queue(struct nvme_dev *dev, struct nvme_queue *nvmeq = nvme_alloc_queue(dev, qid, cq_size, vector); if (!nvmeq) - return NULL; + return ERR_PTR(-ENOMEM); result = adapter_alloc_cq(dev, qid, nvmeq); if (result < 0) @@ -918,7 +918,7 @@ static __devinit struct nvme_queue *nvme_create_queue(struct nvme_dev *dev, dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth), nvmeq->sq_cmds, nvmeq->sq_dma_addr); kfree(nvmeq); - return NULL; + return ERR_PTR(result); } static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) @@ -1421,8 +1421,8 @@ static int __devinit nvme_setup_io_queues(struct nvme_dev *dev) for (i = 0; i < nr_io_queues; i++) { dev->queues[i + 1] = nvme_create_queue(dev, i + 1, NVME_Q_DEPTH, i); - if (!dev->queues[i + 1]) - return -ENOMEM; + if (IS_ERR(dev->queues[i + 1])) + return PTR_ERR(dev->queues[i + 1]); dev->queue_count++; } -- cgit v0.10.2 From eac623ba7a91474a688eb5d0fcd0eaa6a56dc41c Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 20 May 2011 09:34:43 -0400 Subject: NVMe: Add the nvme thread to the wait queue before waking it up If the I/O was not completed by a single NVMe command, we add the bio to the congestion list and wake up the kthread to resubmit it. But the kthread calls remove_wait_queue() unconditionally, which will oops if it's not on the wait queue. So add the kthread to the wait queue before waking it up. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 843edbd..f5e51a6 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -325,6 +325,8 @@ static void bio_completion(struct nvme_queue *nvmeq, void *ctx, if (status) { bio_endio(bio, -EIO); } else if (bio->bi_vcnt > bio->bi_idx) { + if (bio_list_empty(&nvmeq->sq_cong)) + add_wait_queue(&nvmeq->sq_full, &nvmeq->sq_cong_wait); bio_list_add(&nvmeq->sq_cong, bio); wake_up_process(nvme_thread); } else { -- cgit v0.10.2 From 6bbf1acddeed0bfb345a5578f9fcada16f1e514f Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 20 May 2011 13:03:42 -0400 Subject: NVMe: Rework ioctls Remove the special-purpose IDENTIFY, GET_RANGE_TYPE, DOWNLOAD_FIRMWARE and ACTIVATE_FIRMWARE commands. Replace them with a generic ADMIN_CMD ioctl that can submit any admin command. Add a new ID ioctl that returns the namespace ID of the queried device. It corresponds to the SCSI Idlun ioctl. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index f5e51a6..9e3c724 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1033,51 +1033,6 @@ static void nvme_unmap_user_pages(struct nvme_dev *dev, int write, put_page(sg_page(&sg[i])); } -static int nvme_submit_user_admin_command(struct nvme_dev *dev, - unsigned long addr, unsigned length, - struct nvme_command *cmd) -{ - int err, nents, tmplen = length; - struct scatterlist *sg; - struct nvme_prps *prps; - - nents = nvme_map_user_pages(dev, 0, addr, length, &sg); - if (nents < 0) - return nents; - prps = nvme_setup_prps(dev, &cmd->common, sg, &tmplen, GFP_KERNEL); - if (tmplen != length) - err = -ENOMEM; - else - err = nvme_submit_admin_cmd(dev, cmd, NULL); - nvme_unmap_user_pages(dev, 0, addr, length, sg, nents); - nvme_free_prps(dev, prps); - return err ? -EIO : 0; -} - -static int nvme_identify(struct nvme_ns *ns, unsigned long addr, int cns) -{ - struct nvme_command c; - - memset(&c, 0, sizeof(c)); - c.identify.opcode = nvme_admin_identify; - c.identify.nsid = cns ? 0 : cpu_to_le32(ns->ns_id); - c.identify.cns = cpu_to_le32(cns); - - return nvme_submit_user_admin_command(ns->dev, addr, 4096, &c); -} - -static int nvme_get_range_type(struct nvme_ns *ns, unsigned long addr) -{ - struct nvme_command c; - - memset(&c, 0, sizeof(c)); - c.features.opcode = nvme_admin_get_features; - c.features.nsid = cpu_to_le32(ns->ns_id); - c.features.fid = cpu_to_le32(NVME_FEAT_LBA_RANGE); - - return nvme_submit_user_admin_command(ns->dev, addr, 4096, &c); -} - static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) { struct nvme_dev *dev = ns->dev; @@ -1096,10 +1051,11 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) switch (io.opcode) { case nvme_cmd_write: case nvme_cmd_read: + case nvme_cmd_compare: nents = nvme_map_user_pages(dev, io.opcode & 1, io.addr, length, &sg); default: - return -EFAULT; + return -EINVAL; } if (nents < 0) @@ -1137,70 +1093,66 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) return status; } -static int nvme_download_firmware(struct nvme_ns *ns, - struct nvme_dlfw __user *udlfw) +static int nvme_user_admin_cmd(struct nvme_ns *ns, + struct nvme_admin_cmd __user *ucmd) { struct nvme_dev *dev = ns->dev; - struct nvme_dlfw dlfw; + struct nvme_admin_cmd cmd; struct nvme_command c; - int nents, status, length; + int status, length, nents = 0; struct scatterlist *sg; - struct nvme_prps *prps; + struct nvme_prps *prps = NULL; - if (copy_from_user(&dlfw, udlfw, sizeof(dlfw))) + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (copy_from_user(&cmd, ucmd, sizeof(cmd))) return -EFAULT; - if (dlfw.length >= (1 << 30)) - return -EINVAL; - length = dlfw.length * 4; - - nents = nvme_map_user_pages(dev, 1, dlfw.addr, length, &sg); - if (nents < 0) - return nents; memset(&c, 0, sizeof(c)); - c.dlfw.opcode = nvme_admin_download_fw; - c.dlfw.numd = cpu_to_le32(dlfw.length); - c.dlfw.offset = cpu_to_le32(dlfw.offset); - prps = nvme_setup_prps(dev, &c.common, sg, &length, GFP_KERNEL); - if (length != dlfw.length * 4) + c.common.opcode = cmd.opcode; + c.common.flags = cmd.flags; + c.common.nsid = cpu_to_le32(cmd.nsid); + c.common.cdw2[0] = cpu_to_le32(cmd.cdw2); + c.common.cdw2[1] = cpu_to_le32(cmd.cdw3); + c.common.cdw10[0] = cpu_to_le32(cmd.cdw10); + c.common.cdw10[1] = cpu_to_le32(cmd.cdw11); + c.common.cdw10[2] = cpu_to_le32(cmd.cdw12); + c.common.cdw10[3] = cpu_to_le32(cmd.cdw13); + c.common.cdw10[4] = cpu_to_le32(cmd.cdw14); + c.common.cdw10[5] = cpu_to_le32(cmd.cdw15); + + length = cmd.data_len; + if (cmd.data_len) { + nents = nvme_map_user_pages(dev, 1, cmd.addr, length, &sg); + if (nents < 0) + return nents; + prps = nvme_setup_prps(dev, &c.common, sg, &length, GFP_KERNEL); + } + + if (length != cmd.data_len) status = -ENOMEM; else status = nvme_submit_admin_cmd(dev, &c, NULL); - nvme_unmap_user_pages(dev, 0, dlfw.addr, dlfw.length * 4, sg, nents); - nvme_free_prps(dev, prps); + if (cmd.data_len) { + nvme_unmap_user_pages(dev, 0, cmd.addr, cmd.data_len, sg, + nents); + nvme_free_prps(dev, prps); + } return status; } -static int nvme_activate_firmware(struct nvme_ns *ns, unsigned long arg) -{ - struct nvme_dev *dev = ns->dev; - struct nvme_command c; - - memset(&c, 0, sizeof(c)); - c.common.opcode = nvme_admin_activate_fw; - c.common.rsvd10[0] = cpu_to_le32(arg); - - return nvme_submit_admin_cmd(dev, &c, NULL); -} - static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { struct nvme_ns *ns = bdev->bd_disk->private_data; switch (cmd) { - case NVME_IOCTL_IDENTIFY_NS: - return nvme_identify(ns, arg, 0); - case NVME_IOCTL_IDENTIFY_CTRL: - return nvme_identify(ns, arg, 1); - case NVME_IOCTL_GET_RANGE_TYPE: - return nvme_get_range_type(ns, arg); + case NVME_IOCTL_ID: + return ns->ns_id; + case NVME_IOCTL_ADMIN_CMD: + return nvme_user_admin_cmd(ns, (void __user *)arg); case NVME_IOCTL_SUBMIT_IO: return nvme_submit_io(ns, (void __user *)arg); - case NVME_IOCTL_DOWNLOAD_FW: - return nvme_download_firmware(ns, (void __user *)arg); - case NVME_IOCTL_ACTIVATE_FW: - return nvme_activate_firmware(ns, arg); default: return -ENOTTY; } diff --git a/include/linux/nvme.h b/include/linux/nvme.h index a19304f..c96ab0f 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -153,11 +153,11 @@ struct nvme_common_command { __u8 flags; __u16 command_id; __le32 nsid; - __u64 rsvd2; + __u32 cdw2[2]; __le64 metadata; __le64 prp1; __le64 prp2; - __u32 rsvd10[6]; + __u32 cdw10[6]; }; struct nvme_rw_command { @@ -388,17 +388,29 @@ struct nvme_user_io { __u16 appmask; }; -struct nvme_dlfw { +struct nvme_admin_cmd { + __u8 opcode; + __u8 flags; + __u16 rsvd1; + __u32 nsid; + __u32 cdw2; + __u32 cdw3; + __u64 metadata; __u64 addr; - __u32 length; /* In dwords */ - __u32 offset; /* In dwords */ + __u32 metadata_len; + __u32 data_len; + __u32 cdw10; + __u32 cdw11; + __u32 cdw12; + __u32 cdw13; + __u32 cdw14; + __u32 cdw15; + __u32 timeout_ms; + __u32 result; }; -#define NVME_IOCTL_IDENTIFY_NS _IOW('N', 0x40, struct nvme_id_ns) -#define NVME_IOCTL_IDENTIFY_CTRL _IOW('N', 0x41, struct nvme_id_ctrl) -#define NVME_IOCTL_GET_RANGE_TYPE _IOW('N', 0x42, struct nvme_lba_range_type) -#define NVME_IOCTL_SUBMIT_IO _IOW('N', 0x43, struct nvme_user_io) -#define NVME_IOCTL_DOWNLOAD_FW _IOW('N', 0x44, struct nvme_dlfw) -#define NVME_IOCTL_ACTIVATE_FW _IO('N', 0x45) +#define NVME_IOCTL_ID _IO('N', 0x40) +#define NVME_IOCTL_ADMIN_CMD _IOWR('N', 0x41, struct nvme_admin_cmd) +#define NVME_IOCTL_SUBMIT_IO _IOW('N', 0x42, struct nvme_user_io) #endif /* _LINUX_NVME_H */ -- cgit v0.10.2 From 6413214c5d424fd5aae6567848340f962ad2ce0f Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 9 Aug 2011 12:56:37 -0400 Subject: Fix bug in NVME_IOCTL_SUBMIT_IO Missing 'break' in the switch statement meant that we'd fall through to the 'return -EINVAL' case. diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 9e3c724..0956e12 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1054,6 +1054,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) case nvme_cmd_compare: nents = nvme_map_user_pages(dev, io.opcode & 1, io.addr, length, &sg); + break; default: return -EINVAL; } -- cgit v0.10.2 From d0ba1e497bca83a3d353eb47c9658afc54d83228 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 13 Sep 2011 17:01:39 -0400 Subject: NVMe: Correct sg list setup in nvme_map_user_pages Our SG list was constructed to always fill the entire first page, even if that was more than the length of the I/O. This is probably harmless, but some IOMMUs might do something bad. Correcting the first call to sg_set_page() made it look a lot closer to the sg_set_page() in the loop, so fold the first call to sg_set_page() into the loop. Reported-by: Nisheeth Bhat Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 0956e12..5843409 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -996,11 +996,11 @@ static int nvme_map_user_pages(struct nvme_dev *dev, int write, sg = kcalloc(count, sizeof(*sg), GFP_KERNEL); sg_init_table(sg, count); - sg_set_page(&sg[0], pages[0], PAGE_SIZE - offset, offset); - length -= (PAGE_SIZE - offset); - for (i = 1; i < count; i++) { - sg_set_page(&sg[i], pages[i], min_t(int, length, PAGE_SIZE), 0); - length -= PAGE_SIZE; + for (i = 0; i < count; i++) { + sg_set_page(&sg[i], pages[i], + min_t(int, length, PAGE_SIZE - offset), offset); + length -= (PAGE_SIZE - offset); + offset = 0; } err = -ENOMEM; -- cgit v0.10.2 From d1a490e026efb22851ed60588b5fad1281d80ec3 Mon Sep 17 00:00:00 2001 From: Nisheeth Bhat Date: Thu, 15 Sep 2011 16:52:24 -0400 Subject: NVMe: Fix calls to dma_unmap_sg dma_unmap_sg() must be called with the same 'nents' passed to dma_map_sg(), not the number returned from dma_map_sg(). Signed-off-by: Nisheeth Bhat Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 5843409..a7f82fb 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1021,13 +1021,12 @@ static int nvme_map_user_pages(struct nvme_dev *dev, int write, } static void nvme_unmap_user_pages(struct nvme_dev *dev, int write, - unsigned long addr, int length, - struct scatterlist *sg, int nents) + unsigned long addr, int length, struct scatterlist *sg) { int i, count; count = DIV_ROUND_UP(offset_in_page(addr) + length, PAGE_SIZE); - dma_unmap_sg(&dev->pci_dev->dev, sg, nents, DMA_FROM_DEVICE); + dma_unmap_sg(&dev->pci_dev->dev, sg, count, DMA_FROM_DEVICE); for (i = 0; i < count; i++) put_page(sg_page(&sg[i])); @@ -1089,7 +1088,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) else status = nvme_submit_sync_cmd(nvmeq, &c, NULL, IO_TIMEOUT); - nvme_unmap_user_pages(dev, io.opcode & 1, io.addr, length, sg, nents); + nvme_unmap_user_pages(dev, io.opcode & 1, io.addr, length, sg); nvme_free_prps(dev, prps); return status; } @@ -1135,8 +1134,7 @@ static int nvme_user_admin_cmd(struct nvme_ns *ns, else status = nvme_submit_admin_cmd(dev, &c, NULL); if (cmd.data_len) { - nvme_unmap_user_pages(dev, 0, cmd.addr, cmd.data_len, sg, - nents); + nvme_unmap_user_pages(dev, 0, cmd.addr, cmd.data_len, sg); nvme_free_prps(dev, prps); } return status; -- cgit v0.10.2 From 684f5c2025b067a23722e620d0b3b858d8dc5d01 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 19 Sep 2011 17:14:53 -0400 Subject: NVMe: Fix memory leak in nvme_dev_add() The driver was allocating 8k of memory, then freeing 4k of it. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index a7f82fb..705f66e 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1457,7 +1457,7 @@ static int __devinit nvme_dev_add(struct nvme_dev *dev) list_for_each_entry(ns, &dev->namespaces, list) add_disk(ns->disk); - dma_free_coherent(&dev->pci_dev->dev, 4096, id, dma_addr); + dma_free_coherent(&dev->pci_dev->dev, 8192, id, dma_addr); return 0; out_free: @@ -1466,7 +1466,7 @@ static int __devinit nvme_dev_add(struct nvme_dev *dev) nvme_ns_free(ns); } - dma_free_coherent(&dev->pci_dev->dev, 4096, id, dma_addr); + dma_free_coherent(&dev->pci_dev->dev, 8192, mem, dma_addr); return res; } -- cgit v0.10.2 From bc5fc7e4b22ca855902aba02b28c96f09b446407 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 19 Sep 2011 17:08:14 -0400 Subject: NVMe: Create nvme_identify and nvme_get_features functions Instead of open-coding calls to nvme_submit_admin_cmd, these small wrappers are simpler to use (the patch removes 14 lines from nvme_dev_add() for example). Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 705f66e..b77894a 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -812,6 +812,34 @@ static int adapter_delete_sq(struct nvme_dev *dev, u16 sqid) return adapter_delete_queue(dev, nvme_admin_delete_sq, sqid); } +static int nvme_identify(struct nvme_dev *dev, unsigned nsid, unsigned cns, + dma_addr_t dma_addr) +{ + struct nvme_command c; + + memset(&c, 0, sizeof(c)); + c.identify.opcode = nvme_admin_identify; + c.identify.nsid = cpu_to_le32(nsid); + c.identify.prp1 = cpu_to_le64(dma_addr); + c.identify.cns = cpu_to_le32(cns); + + return nvme_submit_admin_cmd(dev, &c, NULL); +} + +static int nvme_get_features(struct nvme_dev *dev, unsigned fid, + unsigned dword11, dma_addr_t dma_addr, u32 *result) +{ + struct nvme_command c; + + memset(&c, 0, sizeof(c)); + c.features.opcode = nvme_admin_get_features; + c.features.prp1 = cpu_to_le64(dma_addr); + c.features.fid = cpu_to_le32(fid); + c.features.dword11 = cpu_to_le32(dword11); + + return nvme_submit_admin_cmd(dev, &c, result); +} + static void nvme_free_queue(struct nvme_dev *dev, int qid) { struct nvme_queue *nvmeq = dev->queues[qid]; @@ -1318,15 +1346,10 @@ static int set_queue_count(struct nvme_dev *dev, int count) { int status; u32 result; - struct nvme_command c; u32 q_count = (count - 1) | ((count - 1) << 16); - memset(&c, 0, sizeof(c)); - c.features.opcode = nvme_admin_get_features; - c.features.fid = cpu_to_le32(NVME_FEAT_NUM_QUEUES); - c.features.dword11 = cpu_to_le32(q_count); - - status = nvme_submit_admin_cmd(dev, &c, &result); + status = nvme_get_features(dev, NVME_FEAT_NUM_QUEUES, q_count, 0, + &result); if (status) return -EIO; return min(result & 0xffff, result >> 16) + 1; @@ -1400,65 +1423,51 @@ static int __devinit nvme_dev_add(struct nvme_dev *dev) int res, nn, i; struct nvme_ns *ns, *next; struct nvme_id_ctrl *ctrl; - void *id; + struct nvme_id_ns *id_ns; + void *mem; dma_addr_t dma_addr; - struct nvme_command cid, crt; res = nvme_setup_io_queues(dev); if (res) return res; - /* XXX: Switch to a SG list once prp2 works */ - id = dma_alloc_coherent(&dev->pci_dev->dev, 8192, &dma_addr, + mem = dma_alloc_coherent(&dev->pci_dev->dev, 8192, &dma_addr, GFP_KERNEL); - memset(&cid, 0, sizeof(cid)); - cid.identify.opcode = nvme_admin_identify; - cid.identify.nsid = 0; - cid.identify.prp1 = cpu_to_le64(dma_addr); - cid.identify.cns = cpu_to_le32(1); - - res = nvme_submit_admin_cmd(dev, &cid, NULL); + res = nvme_identify(dev, 0, 1, dma_addr); if (res) { res = -EIO; goto out_free; } - ctrl = id; + ctrl = mem; nn = le32_to_cpup(&ctrl->nn); memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn)); memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn)); memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr)); - cid.identify.cns = 0; - memset(&crt, 0, sizeof(crt)); - crt.features.opcode = nvme_admin_get_features; - crt.features.prp1 = cpu_to_le64(dma_addr + 4096); - crt.features.fid = cpu_to_le32(NVME_FEAT_LBA_RANGE); - + id_ns = mem; for (i = 0; i <= nn; i++) { - cid.identify.nsid = cpu_to_le32(i); - res = nvme_submit_admin_cmd(dev, &cid, NULL); + res = nvme_identify(dev, i, 0, dma_addr); if (res) continue; - if (((struct nvme_id_ns *)id)->ncap == 0) + if (id_ns->ncap == 0) continue; - crt.features.nsid = cpu_to_le32(i); - res = nvme_submit_admin_cmd(dev, &crt, NULL); + res = nvme_get_features(dev, NVME_FEAT_LBA_RANGE, i, + dma_addr + 4096, NULL); if (res) continue; - ns = nvme_alloc_ns(dev, i, id, id + 4096); + ns = nvme_alloc_ns(dev, i, mem, mem + 4096); if (ns) list_add_tail(&ns->list, &dev->namespaces); } list_for_each_entry(ns, &dev->namespaces, list) add_disk(ns->disk); - dma_free_coherent(&dev->pci_dev->dev, 8192, id, dma_addr); - return 0; + goto out; out_free: list_for_each_entry_safe(ns, next, &dev->namespaces, list) { @@ -1466,6 +1475,7 @@ static int __devinit nvme_dev_add(struct nvme_dev *dev) nvme_ns_free(ns); } + out: dma_free_coherent(&dev->pci_dev->dev, 8192, mem, dma_addr); return res; } -- cgit v0.10.2 From 0d1bc9125890426b52ca2de6abedd32e31722e5c Mon Sep 17 00:00:00 2001 From: Nisheeth Bhat Date: Thu, 29 Sep 2011 10:10:10 -0400 Subject: Fix calculation of number of pages in a PRP List The existing calculation underestimated the number of pages required as it did not take into account the pointer at the end of each page. The replacement calculation may overestimate the number of pages required if the last page in the PRP List is entirely full. By using ->npages as a counter as we fill in the pages, we ensure that we don't try to free a page that was never allocated. Signed-off-by: Nisheeth Bhat Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index b77894a..3afdc75 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -265,7 +265,7 @@ static int nvme_submit_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd) } struct nvme_prps { - int npages; + int npages; /* 0 means small pool in use */ dma_addr_t first_dma; __le64 *list[0]; }; @@ -347,7 +347,7 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_dev *dev, int offset = offset_in_page(dma_addr); __le64 *prp_list; dma_addr_t prp_dma; - int nprps, npages, i, prp_page; + int nprps, npages, i; struct nvme_prps *prps = NULL; cmd->prp1 = cpu_to_le64(dma_addr); @@ -370,20 +370,20 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_dev *dev, } nprps = DIV_ROUND_UP(length, PAGE_SIZE); - npages = DIV_ROUND_UP(8 * nprps, PAGE_SIZE); + npages = DIV_ROUND_UP(8 * nprps, PAGE_SIZE - 8); prps = kmalloc(sizeof(*prps) + sizeof(__le64 *) * npages, gfp); if (!prps) { cmd->prp2 = cpu_to_le64(dma_addr); *len = (*len - length) + PAGE_SIZE; return prps; } - prp_page = 0; + if (nprps <= (256 / 8)) { pool = dev->prp_small_pool; prps->npages = 0; } else { pool = dev->prp_page_pool; - prps->npages = npages; + prps->npages = 1; } prp_list = dma_pool_alloc(pool, gfp, &prp_dma); @@ -393,7 +393,7 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_dev *dev, kfree(prps); return NULL; } - prps->list[prp_page++] = prp_list; + prps->list[0] = prp_list; prps->first_dma = prp_dma; cmd->prp2 = cpu_to_le64(prp_dma); i = 0; @@ -405,7 +405,7 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_dev *dev, *len = (*len - length); return prps; } - prps->list[prp_page++] = prp_list; + prps->list[prps->npages++] = prp_list; prp_list[0] = old_prp_list[i - 1]; old_prp_list[i - 1] = cpu_to_le64(prp_dma); i = 1; -- cgit v0.10.2 From 2b2c1896871838cdf549442e8ad0264be5fa74e3 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 7 Oct 2011 13:10:13 -0400 Subject: NVMe: Don't probe namespace 0 ECN 001 documented that namespace 0 is not valid. Sending an Identify with CNS of 0 and Namespace of 0 is an undefined command. Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 3afdc75..660aa5d 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1447,7 +1447,7 @@ static int __devinit nvme_dev_add(struct nvme_dev *dev) memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr)); id_ns = mem; - for (i = 0; i <= nn; i++) { + for (i = 1; i <= nn; i++) { res = nvme_identify(dev, i, 0, dma_addr); if (res) continue; -- cgit v0.10.2 From ce38c149576fd0a3360fec3bef4012212d42e736 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 7 Oct 2011 13:20:37 -0400 Subject: NVMe: Version 0.7 Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 660aa5d..cfe5932 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1700,6 +1700,6 @@ static void __exit nvme_exit(void) MODULE_AUTHOR("Matthew Wilcox "); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.6"); +MODULE_VERSION("0.7"); module_init(nvme_init); module_exit(nvme_exit); -- cgit v0.10.2 From f1938f6e1ee1583c87ec74dc406fdd8694e99ac8 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 20 Oct 2011 17:00:41 -0400 Subject: NVMe: Implement doorbell stride capability The doorbell stride allows devices to spread out their doorbells instead of packing them tightly. This feature was added as part of ECN 003. This patch also enables support for more than 512 queues :-) Signed-off-by: Matthew Wilcox diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index cfe5932..a17f80f 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -70,6 +70,7 @@ struct nvme_dev { struct dma_pool *prp_small_pool; int instance; int queue_count; + int db_stride; u32 ctrl_config; struct msix_entry *entry; struct nvme_bar __iomem *bar; @@ -672,7 +673,7 @@ static irqreturn_t nvme_process_cq(struct nvme_queue *nvmeq) if (head == nvmeq->cq_head && phase == nvmeq->cq_phase) return IRQ_NONE; - writel(head, nvmeq->q_db + 1); + writel(head, nvmeq->q_db + (1 << nvmeq->dev->db_stride)); nvmeq->cq_head = head; nvmeq->cq_phase = phase; @@ -889,7 +890,7 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid, init_waitqueue_head(&nvmeq->sq_full); init_waitqueue_entry(&nvmeq->sq_cong_wait, nvme_thread); bio_list_init(&nvmeq->sq_cong); - nvmeq->q_db = &dev->dbs[qid * 2]; + nvmeq->q_db = &dev->dbs[qid << (dev->db_stride + 1)]; nvmeq->q_depth = depth; nvmeq->cq_vector = vector; @@ -981,6 +982,7 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev) cap = readq(&dev->bar->cap); timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies; + dev->db_stride = NVME_CAP_STRIDE(cap); while (!(readl(&dev->bar->csts) & NVME_CSTS_RDY)) { msleep(100); @@ -1357,7 +1359,7 @@ static int set_queue_count(struct nvme_dev *dev, int count) static int __devinit nvme_setup_io_queues(struct nvme_dev *dev) { - int result, cpu, i, nr_io_queues; + int result, cpu, i, nr_io_queues, db_bar_size; nr_io_queues = num_online_cpus(); result = set_queue_count(dev, nr_io_queues); @@ -1369,6 +1371,15 @@ static int __devinit nvme_setup_io_queues(struct nvme_dev *dev) /* Deregister the admin queue's interrupt */ free_irq(dev->entry[0].vector, dev->queues[0]); + db_bar_size = 4096 + ((nr_io_queues + 1) << (dev->db_stride + 3)); + if (db_bar_size > 8192) { + iounmap(dev->bar); + dev->bar = ioremap(pci_resource_start(dev->pci_dev, 0), + db_bar_size); + dev->dbs = ((void __iomem *)dev->bar) + 4096; + dev->queues[0]->q_db = dev->dbs; + } + for (i = 0; i < nr_io_queues; i++) dev->entry[i].entry = i; for (;;) { diff --git a/include/linux/nvme.h b/include/linux/nvme.h index c96ab0f..2a2c535 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -36,6 +36,7 @@ struct nvme_bar { }; #define NVME_CAP_TIMEOUT(cap) (((cap) >> 24) & 0xff) +#define NVME_CAP_STRIDE(cap) (((cap) >> 32) & 0xf) enum { NVME_CC_ENABLE = 1 << 0, -- cgit v0.10.2 From 010e646ba2fdfc558048a97da746381c35836280 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 4 Nov 2011 16:24:23 -0400 Subject: NVMe: Update Identify Controller data structure The driver was still using an old definition of Identify Controller which only came to light once we started using the 'number of namespaces' field properly. Reported-by: Nisheeth Bhat Reported-by: Khosrow Panah Signed-off-by: Matthew Wilcox diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 2a2c535..9490a00 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -57,6 +57,18 @@ enum { NVME_CSTS_SHST_CMPLT = 2 << 2, }; +struct nvme_id_power_state { + __le16 max_power; /* centiwatts */ + __u16 rsvd2; + __le32 entry_lat; /* microseconds */ + __le32 exit_lat; /* microseconds */ + __u8 read_tput; + __u8 read_lat; + __u8 write_tput; + __u8 write_lat; + __u8 rsvd16[16]; +}; + #define NVME_VS(major, minor) (major << 16 | minor) struct nvme_id_ctrl { @@ -65,9 +77,11 @@ struct nvme_id_ctrl { char sn[20]; char mn[40]; char fr[8]; - __le32 nn; __u8 rab; - __u8 rsvd77[178]; + __u8 ieee[3]; + __u8 mic; + __u8 mdts; + __u8 rsvd78[178]; __le16 oacs; __u8 acl; __u8 aerl; @@ -76,15 +90,18 @@ struct nvme_id_ctrl { __u8 elpe; __u8 npss; __u8 rsvd264[248]; - __le64 psd[32]; + __u8 sqes; + __u8 cqes; + __u8 rsvd514[2]; + __le32 nn; __le16 oncs; __le16 fuses; __u8 fna; __u8 vwc; __le16 awun; __le16 awupf; - __u8 rsvd778[246]; - __u8 cmdset[2048]; + __u8 rsvd530[1518]; + struct nvme_id_power_state psd[32]; __u8 vs[1024]; }; -- cgit v0.10.2 From 88523a61558a040546bf7d8b079ae0755d8e7005 Mon Sep 17 00:00:00 2001 From: Sam Bradshaw Date: Tue, 30 Aug 2011 08:34:26 -0600 Subject: block: Add driver for Micron RealSSD pcie flash cards This adds mtip32xx, a driver supporting Microns line of pci-express flash storage cards. Signed-off-by: Asai Thambi S P Signed-off-by: Sam Bradshaw Signed-off-by: Jens Axboe diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 6f07ec1..a30aa10 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -116,6 +116,8 @@ config PARIDE source "drivers/block/paride/Kconfig" +source "drivers/block/mtip32xx/Kconfig" + config BLK_CPQ_DA tristate "Compaq SMART2 support" depends on PCI && VIRT_TO_BUS diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 76646e9..ad7b74a 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -39,5 +39,6 @@ obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o obj-$(CONFIG_XEN_BLKDEV_BACKEND) += xen-blkback/ obj-$(CONFIG_BLK_DEV_DRBD) += drbd/ obj-$(CONFIG_BLK_DEV_RBD) += rbd.o +obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX) += mtip32xx/ swim_mod-y := swim.o swim_asm.o diff --git a/drivers/block/mtip32xx/Kconfig b/drivers/block/mtip32xx/Kconfig new file mode 100644 index 0000000..b5dd14e --- /dev/null +++ b/drivers/block/mtip32xx/Kconfig @@ -0,0 +1,9 @@ +# +# mtip32xx device driver configuration +# + +config BLK_DEV_PCIESSD_MTIP32XX + tristate "Block Device Driver for Micron PCIe SSDs" + depends on HOTPLUG_PCI_PCIE + help + This enables the block driver for Micron PCIe SSDs. diff --git a/drivers/block/mtip32xx/Makefile b/drivers/block/mtip32xx/Makefile new file mode 100644 index 0000000..4fbef8c --- /dev/null +++ b/drivers/block/mtip32xx/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for Block device driver for Micron PCIe SSD +# + +obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX) += mtip32xx.o diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c new file mode 100644 index 0000000..847b8ff --- /dev/null +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -0,0 +1,3581 @@ +/* + * Driver for the Micron P320 SSD + * Copyright (C) 2011 Micron Technology, Inc. + * + * Portions of this code were derived from works subjected to the + * following copyright: + * Copyright (C) 2009 Integrated Device Technology, Inc. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include <../drivers/ata/ahci.h> +#include "mtip32xx.h" + +#define HW_CMD_SLOT_SZ (MTIP_MAX_COMMAND_SLOTS * 32) +#define HW_CMD_TBL_SZ (AHCI_CMD_TBL_HDR_SZ + (MTIP_MAX_SG * 16)) +#define HW_CMD_TBL_AR_SZ (HW_CMD_TBL_SZ * MTIP_MAX_COMMAND_SLOTS) +#define HW_PORT_PRIV_DMA_SZ \ + (HW_CMD_SLOT_SZ + HW_CMD_TBL_AR_SZ + AHCI_RX_FIS_SZ) + +#define HOST_HSORG 0xFC +#define HSORG_DISABLE_SLOTGRP_INTR (1<<24) +#define HSORG_DISABLE_SLOTGRP_PXIS (1<<16) +#define HSORG_HWREV 0xFF00 +#define HSORG_STYLE 0x8 +#define HSORG_SLOTGROUPS 0x7 + +#define PORT_COMMAND_ISSUE 0x38 +#define PORT_SDBV 0x7C + +#define PORT_OFFSET 0x100 +#define PORT_MEM_SIZE 0x80 + +#define PORT_IRQ_ERR \ + (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | PORT_IRQ_CONNECT | \ + PORT_IRQ_PHYRDY | PORT_IRQ_UNK_FIS | PORT_IRQ_BAD_PMP | \ + PORT_IRQ_TF_ERR | PORT_IRQ_HBUS_DATA_ERR | PORT_IRQ_IF_NONFATAL | \ + PORT_IRQ_OVERFLOW) +#define PORT_IRQ_LEGACY \ + (PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS) +#define PORT_IRQ_HANDLED \ + (PORT_IRQ_SDB_FIS | PORT_IRQ_LEGACY | \ + PORT_IRQ_TF_ERR | PORT_IRQ_IF_ERR | \ + PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY) +#define DEF_PORT_IRQ \ + (PORT_IRQ_ERR | PORT_IRQ_LEGACY | PORT_IRQ_SDB_FIS) + +/* product numbers */ +#define MTIP_PRODUCT_UNKNOWN 0x00 +#define MTIP_PRODUCT_ASICFPGA 0x11 + +/* Device instance number, incremented each time a device is probed. */ +static int instance; + +/* + * Global variable used to hold the major block device number + * allocated in mtip_init(). + */ +int mtip_major; + +static DEFINE_SPINLOCK(rssd_index_lock); +static DEFINE_IDA(rssd_index_ida); + +struct mtip_compat_ide_task_request_s { + __u8 io_ports[8]; + __u8 hob_ports[8]; + ide_reg_valid_t out_flags; + ide_reg_valid_t in_flags; + int data_phase; + int req_cmd; + compat_ulong_t out_size; + compat_ulong_t in_size; +}; + +static int mtip_exec_internal_command(struct mtip_port *port, + void *fis, + int fisLen, + dma_addr_t buffer, + int bufLen, + u32 opts, + gfp_t atomic, + unsigned long timeout); + +/* + * Obtain an empty command slot. + * + * This function needs to be reentrant since it could be called + * at the same time on multiple CPUs. The allocation of the + * command slot must be atomic. + * + * @port Pointer to the port data structure. + * + * return value + * >= 0 Index of command slot obtained. + * -1 No command slots available. + */ +static int get_slot(struct mtip_port *port) +{ + int slot, i; + unsigned int num_command_slots = port->dd->slot_groups * 32; + + /* + * Try 10 times, because there is a small race here. + * that's ok, because it's still cheaper than a lock. + * + * Race: Since this section is not protected by lock, same bit + * could be chosen by different process contexts running in + * different processor. So instead of costly lock, we are going + * with loop. + */ + for (i = 0; i < 10; i++) { + slot = find_next_zero_bit(port->allocated, + num_command_slots, 1); + if ((slot < num_command_slots) && + (!test_and_set_bit(slot, port->allocated))) + return slot; + } + dev_warn(&port->dd->pdev->dev, "Failed to get a tag.\n"); + + if (mtip_check_surprise_removal(port->dd->pdev)) { + /* Device not present, clean outstanding commands */ + mtip_command_cleanup(port->dd); + } + return -1; +} + +/* + * Release a command slot. + * + * @port Pointer to the port data structure. + * @tag Tag of command to release + * + * return value + * None + */ +static inline void release_slot(struct mtip_port *port, int tag) +{ + smp_mb__before_clear_bit(); + clear_bit(tag, port->allocated); + smp_mb__after_clear_bit(); +} + +/* + * Issue a command to the hardware. + * + * Set the appropriate bit in the s_active and Command Issue hardware + * registers, causing hardware command processing to begin. + * + * @port Pointer to the port structure. + * @tag The tag of the command to be issued. + * + * return value + * None + */ +static inline void mtip_issue_ncq_command(struct mtip_port *port, int tag) +{ + unsigned long flags = 0; + + atomic_set(&port->commands[tag].active, 1); + + spin_lock_irqsave(&port->cmd_issue_lock, flags); + + writel((1 << MTIP_TAG_BIT(tag)), + port->s_active[MTIP_TAG_INDEX(tag)]); + writel((1 << MTIP_TAG_BIT(tag)), + port->cmd_issue[MTIP_TAG_INDEX(tag)]); + + spin_unlock_irqrestore(&port->cmd_issue_lock, flags); +} + +/* + * Called periodically to see if any read/write commands are + * taking too long to complete. + * + * @data Pointer to the PORT data structure. + * + * return value + * None + */ +void mtip_timeout_function(unsigned long int data) +{ + struct mtip_port *port = (struct mtip_port *) data; + struct host_to_dev_fis *fis; + struct mtip_cmd *command; + int tag, cmdto_cnt = 0; + unsigned int bit, group; + unsigned int num_command_slots = port->dd->slot_groups * 32; + + if (unlikely(!port)) + return; + + if (atomic_read(&port->dd->resumeflag) == true) { + mod_timer(&port->cmd_timer, + jiffies + msecs_to_jiffies(30000)); + return; + } + + for (tag = 0; tag < num_command_slots; tag++) { + /* + * Skip internal command slot as it has + * its own timeout mechanism + */ + if (tag == MTIP_TAG_INTERNAL) + continue; + + if (atomic_read(&port->commands[tag].active) && + (time_after(jiffies, port->commands[tag].comp_time))) { + group = tag >> 5; + bit = tag & 0x1f; + + command = &port->commands[tag]; + fis = (struct host_to_dev_fis *) command->command; + + dev_warn(&port->dd->pdev->dev, + "Timeout for command tag %d\n", tag); + + cmdto_cnt++; + if (cmdto_cnt == 1) + atomic_inc(&port->dd->eh_active); + + /* + * Clear the completed bit. This should prevent + * any interrupt handlers from trying to retire + * the command. + */ + writel(1 << bit, port->completed[group]); + + /* Call the async completion callback. */ + if (likely(command->async_callback)) + command->async_callback(command->async_data, + -EIO); + command->async_callback = NULL; + command->comp_func = NULL; + + /* Unmap the DMA scatter list entries */ + dma_unmap_sg(&port->dd->pdev->dev, + command->sg, + command->scatter_ents, + command->direction); + + /* + * Clear the allocated bit and active tag for the + * command. + */ + atomic_set(&port->commands[tag].active, 0); + release_slot(port, tag); + + up(&port->cmd_slot); + } + } + + if (cmdto_cnt) { + dev_warn(&port->dd->pdev->dev, + "%d commands timed out: restarting port", + cmdto_cnt); + mtip_restart_port(port); + atomic_dec(&port->dd->eh_active); + } + + /* Restart the timer */ + mod_timer(&port->cmd_timer, + jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD)); +} + +/* + * IO completion function. + * + * This completion function is called by the driver ISR when a + * command that was issued by the kernel completes. It first calls the + * asynchronous completion function which normally calls back into the block + * layer passing the asynchronous callback data, then unmaps the + * scatter list associated with the completed command, and finally + * clears the allocated bit associated with the completed command. + * + * @port Pointer to the port data structure. + * @tag Tag of the command. + * @data Pointer to driver_data. + * @status Completion status. + * + * return value + * None + */ +static void mtip_async_complete(struct mtip_port *port, + int tag, + void *data, + int status) +{ + struct mtip_cmd *command; + struct driver_data *dd = data; + int cb_status = status ? -EIO : 0; + + if (unlikely(!dd) || unlikely(!port)) + return; + + command = &port->commands[tag]; + + if (unlikely(status == PORT_IRQ_TF_ERR)) { + dev_warn(&port->dd->pdev->dev, + "Command tag %d failed due to TFE\n", tag); + } + + /* Upper layer callback */ + if (likely(command->async_callback)) + command->async_callback(command->async_data, cb_status); + + command->async_callback = NULL; + command->comp_func = NULL; + + /* Unmap the DMA scatter list entries */ + dma_unmap_sg(&dd->pdev->dev, + command->sg, + command->scatter_ents, + command->direction); + + /* Clear the allocated and active bits for the command */ + atomic_set(&port->commands[tag].active, 0); + release_slot(port, tag); + + up(&port->cmd_slot); +} + +/* + * Internal command completion callback function. + * + * This function is normally called by the driver ISR when an internal + * command completed. This function signals the command completion by + * calling complete(). + * + * @port Pointer to the port data structure. + * @tag Tag of the command that has completed. + * @data Pointer to a completion structure. + * @status Completion status. + * + * return value + * None + */ +static void mtip_completion(struct mtip_port *port, + int tag, + void *data, + int status) +{ + struct mtip_cmd *command = &port->commands[tag]; + struct completion *waiting = data; + if (unlikely(status == PORT_IRQ_TF_ERR)) + dev_warn(&port->dd->pdev->dev, + "Internal command %d completed with TFE\n", tag); + + command->async_callback = NULL; + command->comp_func = NULL; + + complete(waiting); +} + +/* + * Enable/disable the reception of FIS + * + * @port Pointer to the port data structure + * @enable 1 to enable, 0 to disable + * + * return value + * Previous state: 1 enabled, 0 disabled + */ +static int mtip_enable_fis(struct mtip_port *port, int enable) +{ + u32 tmp; + + /* enable FIS reception */ + tmp = readl(port->mmio + PORT_CMD); + if (enable) + writel(tmp | PORT_CMD_FIS_RX, port->mmio + PORT_CMD); + else + writel(tmp & ~PORT_CMD_FIS_RX, port->mmio + PORT_CMD); + + /* Flush */ + readl(port->mmio + PORT_CMD); + + return (((tmp & PORT_CMD_FIS_RX) == PORT_CMD_FIS_RX)); +} + +/* + * Enable/disable the DMA engine + * + * @port Pointer to the port data structure + * @enable 1 to enable, 0 to disable + * + * return value + * Previous state: 1 enabled, 0 disabled. + */ +static int mtip_enable_engine(struct mtip_port *port, int enable) +{ + u32 tmp; + + /* enable FIS reception */ + tmp = readl(port->mmio + PORT_CMD); + if (enable) + writel(tmp | PORT_CMD_START, port->mmio + PORT_CMD); + else + writel(tmp & ~PORT_CMD_START, port->mmio + PORT_CMD); + + readl(port->mmio + PORT_CMD); + return (((tmp & PORT_CMD_START) == PORT_CMD_START)); +} + +/* + * Enables the port DMA engine and FIS reception. + * + * return value + * None + */ +static inline void mtip_start_port(struct mtip_port *port) +{ + /* Enable FIS reception */ + mtip_enable_fis(port, 1); + + /* Enable the DMA engine */ + mtip_enable_engine(port, 1); +} + +/* + * Deinitialize a port by disabling port interrupts, the DMA engine, + * and FIS reception. + * + * @port Pointer to the port structure + * + * return value + * None + */ +static inline void mtip_deinit_port(struct mtip_port *port) +{ + /* Disable interrupts on this port */ + writel(0, port->mmio + PORT_IRQ_MASK); + + /* Disable the DMA engine */ + mtip_enable_engine(port, 0); + + /* Disable FIS reception */ + mtip_enable_fis(port, 0); +} + +/* + * Initialize a port. + * + * This function deinitializes the port by calling mtip_deinit_port() and + * then initializes it by setting the command header and RX FIS addresses, + * clearing the SError register and any pending port interrupts before + * re-enabling the default set of port interrupts. + * + * @port Pointer to the port structure. + * + * return value + * None + */ +static void mtip_init_port(struct mtip_port *port) +{ + int i; + mtip_deinit_port(port); + + /* Program the command list base and FIS base addresses */ + if (readl(port->dd->mmio + HOST_CAP) & HOST_CAP_64) { + writel((port->command_list_dma >> 16) >> 16, + port->mmio + PORT_LST_ADDR_HI); + writel((port->rxfis_dma >> 16) >> 16, + port->mmio + PORT_FIS_ADDR_HI); + } + + writel(port->command_list_dma & 0xffffffff, + port->mmio + PORT_LST_ADDR); + writel(port->rxfis_dma & 0xffffffff, port->mmio + PORT_FIS_ADDR); + + /* Clear SError */ + writel(readl(port->mmio + PORT_SCR_ERR), port->mmio + PORT_SCR_ERR); + + /* reset the completed registers.*/ + for (i = 0; i < port->dd->slot_groups; i++) + writel(0xFFFFFFFF, port->completed[i]); + + /* Clear any pending interrupts for this port */ + writel(readl(port->mmio + PORT_IRQ_STAT), port->mmio + PORT_IRQ_STAT); + + /* Enable port interrupts */ + writel(DEF_PORT_IRQ, port->mmio + PORT_IRQ_MASK); +} + +/* + * Reset the HBA (without sleeping) + * + * Just like hba_reset, except does not call sleep, so can be + * run from interrupt/tasklet context. + * + * @dd Pointer to the driver data structure. + * + * return value + * 0 The reset was successful. + * -1 The HBA Reset bit did not clear. + */ +int hba_reset_nosleep(struct driver_data *dd) +{ + unsigned long timeout; + + /* Chip quirk: quiesce any chip function */ + mdelay(10); + + /* Set the reset bit */ + writel(HOST_RESET, dd->mmio + HOST_CTL); + + /* Flush */ + readl(dd->mmio + HOST_CTL); + + /* + * Wait 10ms then spin for up to 1 second + * waiting for reset acknowledgement + */ + timeout = jiffies + msecs_to_jiffies(1000); + mdelay(10); + while ((readl(dd->mmio + HOST_CTL) & HOST_RESET) + && time_before(jiffies, timeout)) + mdelay(1); + + if (readl(dd->mmio + HOST_CTL) & HOST_RESET) + return -1; + + return 0; +} + +/* + * Restart a port + * + * @port Pointer to the port data structure. + * + * return value + * None + */ +void mtip_restart_port(struct mtip_port *port) +{ + unsigned long timeout; + + /* Disable the DMA engine */ + mtip_enable_engine(port, 0); + + /* Chip quirk: wait up to 500ms for PxCMD.CR == 0 */ + timeout = jiffies + msecs_to_jiffies(500); + while ((readl(port->mmio + PORT_CMD) & PORT_CMD_LIST_ON) + && time_before(jiffies, timeout)) + ; + + /* + * Chip quirk: escalate to hba reset if + * PxCMD.CR not clear after 500 ms + */ + if (readl(port->mmio + PORT_CMD) & PORT_CMD_LIST_ON) { + dev_warn(&port->dd->pdev->dev, + "PxCMD.CR not clear, escalating reset\n"); + + if (hba_reset_nosleep(port->dd)) + dev_err(&port->dd->pdev->dev, + "HBA reset escalation failed.\n"); + + /* 30 ms delay before com reset to quiesce chip */ + mdelay(30); + } + + dev_warn(&port->dd->pdev->dev, "Issuing COM reset\n"); + + /* Set PxSCTL.DET */ + writel(readl(port->mmio + PORT_SCR_CTL) | + 1, port->mmio + PORT_SCR_CTL); + readl(port->mmio + PORT_SCR_CTL); + + /* Wait 1 ms to quiesce chip function */ + timeout = jiffies + msecs_to_jiffies(1); + while (time_before(jiffies, timeout)) + ; + + /* Clear PxSCTL.DET */ + writel(readl(port->mmio + PORT_SCR_CTL) & ~1, + port->mmio + PORT_SCR_CTL); + readl(port->mmio + PORT_SCR_CTL); + + /* Wait 500 ms for bit 0 of PORT_SCR_STS to be set */ + timeout = jiffies + msecs_to_jiffies(500); + while (((readl(port->mmio + PORT_SCR_STAT) & 0x01) == 0) + && time_before(jiffies, timeout)) + ; + + if ((readl(port->mmio + PORT_SCR_STAT) & 0x01) == 0) + dev_warn(&port->dd->pdev->dev, + "COM reset failed\n"); + + /* Clear SError, the PxSERR.DIAG.x should be set so clear it */ + writel(readl(port->mmio + PORT_SCR_ERR), port->mmio + PORT_SCR_ERR); + + /* Enable the DMA engine */ + mtip_enable_engine(port, 1); +} + +/* + * Helper function for tag logging + */ +static void print_tags(struct driver_data *dd, + char *msg, + unsigned long *tagbits) +{ + unsigned int tag, count = 0; + + for (tag = 0; tag < (dd->slot_groups) * 32; tag++) { + if (test_bit(tag, tagbits)) + count++; + } + if (count) + dev_info(&dd->pdev->dev, "%s [%i tags]\n", msg, count); +} + +/* + * Handle an error. + * + * @dd Pointer to the DRIVER_DATA structure. + * + * return value + * None + */ +static void mtip_handle_tfe(struct driver_data *dd) +{ + int group, tag, bit, reissue; + struct mtip_port *port; + struct mtip_cmd *command; + u32 completed; + struct host_to_dev_fis *fis; + unsigned long tagaccum[SLOTBITS_IN_LONGS]; + + dev_warn(&dd->pdev->dev, "Taskfile error\n"); + + port = dd->port; + + /* Stop the timer to prevent command timeouts. */ + del_timer(&port->cmd_timer); + + /* Set eh_active */ + atomic_inc(&dd->eh_active); + + /* Loop through all the groups */ + for (group = 0; group < dd->slot_groups; group++) { + completed = readl(port->completed[group]); + + /* clear completed status register in the hardware.*/ + writel(completed, port->completed[group]); + + /* clear the tag accumulator */ + memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long)); + + /* Process successfully completed commands */ + for (bit = 0; bit < 32 && completed; bit++) { + if (!(completed & (1<commands[tag]; + if (likely(command->comp_func)) { + set_bit(tag, tagaccum); + atomic_set(&port->commands[tag].active, 0); + command->comp_func(port, + tag, + command->comp_data, + 0); + } else { + dev_err(&port->dd->pdev->dev, + "Missing completion func for tag %d", + tag); + if (mtip_check_surprise_removal(dd->pdev)) { + mtip_command_cleanup(dd); + /* don't proceed further */ + return; + } + } + } + } + print_tags(dd, "TFE tags completed:", tagaccum); + + /* Restart the port */ + mdelay(20); + mtip_restart_port(port); + + /* clear the tag accumulator */ + memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long)); + + /* Loop through all the groups */ + for (group = 0; group < dd->slot_groups; group++) { + for (bit = 0; bit < 32; bit++) { + reissue = 1; + tag = (group << 5) + bit; + + /* If the active bit is set re-issue the command */ + if (atomic_read(&port->commands[tag].active) == 0) + continue; + + fis = (struct host_to_dev_fis *) + port->commands[tag].command; + + /* Should re-issue? */ + if (tag == MTIP_TAG_INTERNAL || + fis->command == ATA_CMD_SET_FEATURES) + reissue = 0; + + /* + * First check if this command has + * exceeded its retries. + */ + if (reissue && + (port->commands[tag].retries-- > 0)) { + + set_bit(tag, tagaccum); + + /* Update the timeout value. */ + port->commands[tag].comp_time = + jiffies + msecs_to_jiffies( + MTIP_NCQ_COMMAND_TIMEOUT_MS); + /* Re-issue the command. */ + mtip_issue_ncq_command(port, tag); + + continue; + } + + /* Retire a command that will not be reissued */ + dev_warn(&port->dd->pdev->dev, + "retiring tag %d\n", tag); + atomic_set(&port->commands[tag].active, 0); + + if (port->commands[tag].comp_func) + port->commands[tag].comp_func( + port, + tag, + port->commands[tag].comp_data, + PORT_IRQ_TF_ERR); + else + dev_warn(&port->dd->pdev->dev, + "Bad completion for tag %d\n", + tag); + } + } + print_tags(dd, "TFE tags reissued:", tagaccum); + + /* Decrement eh_active */ + atomic_dec(&dd->eh_active); + + mod_timer(&port->cmd_timer, + jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD)); +} + +/* + * Handle a set device bits interrupt + */ +static inline void mtip_process_sdbf(struct driver_data *dd) +{ + struct mtip_port *port = dd->port; + int group, tag, bit; + u32 completed; + struct mtip_cmd *command; + + /* walk all bits in all slot groups */ + for (group = 0; group < dd->slot_groups; group++) { + completed = readl(port->completed[group]); + + /* clear completed status register in the hardware.*/ + writel(completed, port->completed[group]); + + /* Process completed commands. */ + for (bit = 0; + (bit < 32) && completed; + bit++, completed >>= 1) { + if (completed & 0x01) { + tag = (group << 5) | bit; + + /* skip internal command slot. */ + if (unlikely(tag == MTIP_TAG_INTERNAL)) + continue; + + command = &port->commands[tag]; + + /* make internal callback */ + if (likely(command->comp_func)) { + command->comp_func( + port, + tag, + command->comp_data, + 0); + } else { + dev_warn(&dd->pdev->dev, + "Null completion " + "for tag %d", + tag); + + if (mtip_check_surprise_removal( + dd->pdev)) { + mtip_command_cleanup(dd); + return; + } + } + } + } + } +} + +/* + * Process legacy pio and d2h interrupts + */ +static inline void mtip_process_legacy(struct driver_data *dd, u32 port_stat) +{ + struct mtip_port *port = dd->port; + struct mtip_cmd *cmd = &port->commands[MTIP_TAG_INTERNAL]; + + if (port->internal_cmd_in_progress && + cmd != NULL && + !(readl(port->cmd_issue[MTIP_TAG_INTERNAL]) + & (1 << MTIP_TAG_INTERNAL))) { + if (cmd->comp_func) { + cmd->comp_func(port, + MTIP_TAG_INTERNAL, + cmd->comp_data, + 0); + return; + } + } + + dev_warn(&dd->pdev->dev, "IRQ status 0x%x ignored.\n", port_stat); + + return; +} + +/* + * Demux and handle errors + */ +static inline void mtip_process_errors(struct driver_data *dd, u32 port_stat) +{ + if (likely(port_stat & (PORT_IRQ_TF_ERR | PORT_IRQ_IF_ERR))) + mtip_handle_tfe(dd); + + if (unlikely(port_stat & PORT_IRQ_CONNECT)) { + dev_warn(&dd->pdev->dev, + "Clearing PxSERR.DIAG.x\n"); + writel((1 << 26), dd->port->mmio + PORT_SCR_ERR); + } + + if (unlikely(port_stat & PORT_IRQ_PHYRDY)) { + dev_warn(&dd->pdev->dev, + "Clearing PxSERR.DIAG.n\n"); + writel((1 << 16), dd->port->mmio + PORT_SCR_ERR); + } + + if (unlikely(port_stat & ~PORT_IRQ_HANDLED)) { + dev_warn(&dd->pdev->dev, + "Port stat errors %x unhandled\n", + (port_stat & ~PORT_IRQ_HANDLED)); + } +} + +static inline irqreturn_t mtip_handle_irq(struct driver_data *data) +{ + struct driver_data *dd = (struct driver_data *) data; + struct mtip_port *port = dd->port; + u32 hba_stat, port_stat; + int rv = IRQ_NONE; + + hba_stat = readl(dd->mmio + HOST_IRQ_STAT); + if (hba_stat) { + rv = IRQ_HANDLED; + + /* Acknowledge the interrupt status on the port.*/ + port_stat = readl(port->mmio + PORT_IRQ_STAT); + writel(port_stat, port->mmio + PORT_IRQ_STAT); + + /* Demux port status */ + if (likely(port_stat & PORT_IRQ_SDB_FIS)) + mtip_process_sdbf(dd); + + if (unlikely(port_stat & PORT_IRQ_ERR)) { + if (unlikely(mtip_check_surprise_removal(dd->pdev))) { + mtip_command_cleanup(dd); + /* don't proceed further */ + return IRQ_HANDLED; + } + + mtip_process_errors(dd, port_stat & PORT_IRQ_ERR); + } + + if (unlikely(port_stat & PORT_IRQ_LEGACY)) + mtip_process_legacy(dd, port_stat & PORT_IRQ_LEGACY); + } + + /* acknowledge interrupt */ + writel(hba_stat, dd->mmio + HOST_IRQ_STAT); + + return rv; +} + +/* + * Wrapper for mtip_handle_irq + * (ignores return code) + */ +static void mtip_tasklet(unsigned long data) +{ + mtip_handle_irq((struct driver_data *) data); +} + +/* + * HBA interrupt subroutine. + * + * @irq IRQ number. + * @instance Pointer to the driver data structure. + * + * return value + * IRQ_HANDLED A HBA interrupt was pending and handled. + * IRQ_NONE This interrupt was not for the HBA. + */ +static irqreturn_t mtip_irq_handler(int irq, void *instance) +{ + struct driver_data *dd = instance; + tasklet_schedule(&dd->tasklet); + return IRQ_HANDLED; +} + +static void mtip_issue_non_ncq_command(struct mtip_port *port, int tag) +{ + atomic_set(&port->commands[tag].active, 1); + writel(1 << MTIP_TAG_BIT(tag), + port->cmd_issue[MTIP_TAG_INDEX(tag)]); +} + +/* + * Wait for port to quiesce + * + * @port Pointer to port data structure + * @timeout Max duration to wait (ms) + * + * return value + * 0 Success + * -EBUSY Commands still active + */ +static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout) +{ + unsigned long to; + unsigned int n, active; + + to = jiffies + msecs_to_jiffies(timeout); + do { + /* + * Ignore s_active bit 0 of array element 0. + * This bit will always be set + */ + active = readl(port->s_active[0]) & 0xfffffffe; + for (n = 1; n < port->dd->slot_groups; n++) + active |= readl(port->s_active[n]); + + if (!active) + break; + + msleep(20); + } while (time_before(jiffies, to)); + + return active ? -EBUSY : 0; +} + +/* + * Execute an internal command and wait for the completion. + * + * @port Pointer to the port data structure. + * @fis Pointer to the FIS that describes the command. + * @fisLen Length in WORDS of the FIS. + * @buffer DMA accessible for command data. + * @bufLen Length, in bytes, of the data buffer. + * @opts Command header options, excluding the FIS length + * and the number of PRD entries. + * @timeout Time in ms to wait for the command to complete. + * + * return value + * 0 Command completed successfully. + * -EFAULT The buffer address is not correctly aligned. + * -EBUSY Internal command or other IO in progress. + * -EAGAIN Time out waiting for command to complete. + */ +static int mtip_exec_internal_command(struct mtip_port *port, + void *fis, + int fisLen, + dma_addr_t buffer, + int bufLen, + u32 opts, + gfp_t atomic, + unsigned long timeout) +{ + struct mtip_cmd_sg *command_sg; + DECLARE_COMPLETION_ONSTACK(wait); + int rv = 0; + struct mtip_cmd *int_cmd = &port->commands[MTIP_TAG_INTERNAL]; + + /* Make sure the buffer is 8 byte aligned. This is asic specific. */ + if (buffer & 0x00000007) { + dev_err(&port->dd->pdev->dev, + "SG buffer is not 8 byte aligned\n"); + return -EFAULT; + } + + /* Only one internal command should be running at a time */ + if (test_and_set_bit(MTIP_TAG_INTERNAL, port->allocated)) { + dev_warn(&port->dd->pdev->dev, + "Internal command already active\n"); + return -EBUSY; + } + port->internal_cmd_in_progress = 1; + + if (atomic == GFP_KERNEL) { + /* wait for io to complete if non atomic */ + if (mtip_quiesce_io(port, 5000) < 0) { + dev_warn(&port->dd->pdev->dev, + "Failed to quiesce IO\n"); + release_slot(port, MTIP_TAG_INTERNAL); + port->internal_cmd_in_progress = 0; + return -EBUSY; + } + + /* Set the completion function and data for the command. */ + int_cmd->comp_data = &wait; + int_cmd->comp_func = mtip_completion; + + } else { + /* Clear completion - we're going to poll */ + int_cmd->comp_data = NULL; + int_cmd->comp_func = NULL; + } + + /* Copy the command to the command table */ + memcpy(int_cmd->command, fis, fisLen*4); + + /* Populate the SG list */ + int_cmd->command_header->opts = + cpu_to_le32(opts | fisLen); + if (bufLen) { + command_sg = int_cmd->command + AHCI_CMD_TBL_HDR_SZ; + + command_sg->info = cpu_to_le32((bufLen-1) & 0x3fffff); + command_sg->dba = cpu_to_le32(buffer & 0xffffffff); + command_sg->dba_upper = cpu_to_le32((buffer >> 16) >> 16); + + int_cmd->command_header->opts |= cpu_to_le32((1 << 16)); + } + + /* Populate the command header */ + int_cmd->command_header->byte_count = 0; + + /* Issue the command to the hardware */ + mtip_issue_non_ncq_command(port, MTIP_TAG_INTERNAL); + + /* Poll if atomic, wait_for_completion otherwise */ + if (atomic == GFP_KERNEL) { + /* Wait for the command to complete or timeout. */ + if (wait_for_completion_timeout( + &wait, + msecs_to_jiffies(timeout)) == 0) { + dev_err(&port->dd->pdev->dev, + "Internal command did not complete [%d]\n", + atomic); + rv = -EAGAIN; + } + + if (readl(port->cmd_issue[MTIP_TAG_INTERNAL]) + & (1 << MTIP_TAG_INTERNAL)) { + dev_warn(&port->dd->pdev->dev, + "Retiring internal command but CI is 1.\n"); + } + + } else { + /* Spin for checking if command still outstanding */ + timeout = jiffies + msecs_to_jiffies(timeout); + + while ((readl( + port->cmd_issue[MTIP_TAG_INTERNAL]) + & (1 << MTIP_TAG_INTERNAL)) + && time_before(jiffies, timeout)) + ; + + if (readl(port->cmd_issue[MTIP_TAG_INTERNAL]) + & (1 << MTIP_TAG_INTERNAL)) { + dev_err(&port->dd->pdev->dev, + "Internal command did not complete [%d]\n", + atomic); + rv = -EAGAIN; + } + } + + /* Clear the allocated and active bits for the internal command. */ + atomic_set(&int_cmd->active, 0); + release_slot(port, MTIP_TAG_INTERNAL); + port->internal_cmd_in_progress = 0; + + return rv; +} + +/* + * Byte-swap ATA ID strings. + * + * ATA identify data contains strings in byte-swapped 16-bit words. + * They must be swapped (on all architectures) to be usable as C strings. + * This function swaps bytes in-place. + * + * @buf The buffer location of the string + * @len The number of bytes to swap + * + * return value + * None + */ +static inline void ata_swap_string(u16 *buf, unsigned int len) +{ + int i; + for (i = 0; i < (len/2); i++) + be16_to_cpus(&buf[i]); +} + +/* + * Request the device identity information. + * + * If a user space buffer is not specified, i.e. is NULL, the + * identify information is still read from the drive and placed + * into the identify data buffer (@e port->identify) in the + * port data structure. + * When the identify buffer contains valid identify information @e + * port->identify_valid is non-zero. + * + * @port Pointer to the port structure. + * @user_buffer A user space buffer where the identify data should be + * copied. + * + * return value + * 0 Command completed successfully. + * -EFAULT An error occurred while coping data to the user buffer. + * -1 Command failed. + */ +static int mtip_get_identify(struct mtip_port *port, void __user *user_buffer) +{ + int rv = 0; + struct host_to_dev_fis fis; + + down_write(&port->dd->internal_sem); + + /* Build the FIS. */ + memset(&fis, 0, sizeof(struct host_to_dev_fis)); + fis.type = 0x27; + fis.opts = 1 << 7; + fis.command = ATA_CMD_ID_ATA; + + /* Set the identify information as invalid. */ + port->identify_valid = 0; + + /* Clear the identify information. */ + memset(port->identify, 0, sizeof(u16) * ATA_ID_WORDS); + + /* Execute the command. */ + if (mtip_exec_internal_command(port, + &fis, + 5, + port->identify_dma, + sizeof(u16) * ATA_ID_WORDS, + 0, + GFP_KERNEL, + MTIP_INTERNAL_COMMAND_TIMEOUT_MS) + < 0) { + rv = -1; + goto out; + } + + /* + * Perform any necessary byte-swapping. Yes, the kernel does in fact + * perform field-sensitive swapping on the string fields. + * See the kernel use of ata_id_string() for proof of this. + */ +#ifdef __LITTLE_ENDIAN + ata_swap_string(port->identify + 27, 40); /* model string*/ + ata_swap_string(port->identify + 23, 8); /* firmware string*/ + ata_swap_string(port->identify + 10, 20); /* serial# string*/ +#else + { + int i; + for (i = 0; i < ATA_ID_WORDS; i++) + port->identify[i] = le16_to_cpu(port->identify[i]); + } +#endif + + /* Set the identify buffer as valid. */ + port->identify_valid = 1; + + if (user_buffer) { + if (copy_to_user( + user_buffer, + port->identify, + ATA_ID_WORDS * sizeof(u16))) { + rv = -EFAULT; + goto out; + } + } + +out: + up_write(&port->dd->internal_sem); + return rv; +} + +/* + * Issue a standby immediate command to the device. + * + * @port Pointer to the port structure. + * + * return value + * 0 Command was executed successfully. + * -1 An error occurred while executing the command. + */ +static int mtip_standby_immediate(struct mtip_port *port) +{ + int rv; + struct host_to_dev_fis fis; + + down_write(&port->dd->internal_sem); + + /* Build the FIS. */ + memset(&fis, 0, sizeof(struct host_to_dev_fis)); + fis.type = 0x27; + fis.opts = 1 << 7; + fis.command = ATA_CMD_STANDBYNOW1; + + /* Execute the command. Use a 15-second timeout for large drives. */ + rv = mtip_exec_internal_command(port, + &fis, + 5, + 0, + 0, + 0, + GFP_KERNEL, + 15000); + + up_write(&port->dd->internal_sem); + + return rv; +} + +/* + * Get the drive capacity. + * + * @dd Pointer to the device data structure. + * @sectors Pointer to the variable that will receive the sector count. + * + * return value + * 1 Capacity was returned successfully. + * 0 The identify information is invalid. + */ +bool mtip_hw_get_capacity(struct driver_data *dd, sector_t *sectors) +{ + struct mtip_port *port = dd->port; + u64 total, raw0, raw1, raw2, raw3; + raw0 = port->identify[100]; + raw1 = port->identify[101]; + raw2 = port->identify[102]; + raw3 = port->identify[103]; + total = raw0 | raw1<<16 | raw2<<32 | raw3<<48; + *sectors = total; + return (bool) !!port->identify_valid; +} + +/* + * Reset the HBA. + * + * Resets the HBA by setting the HBA Reset bit in the Global + * HBA Control register. After setting the HBA Reset bit the + * function waits for 1 second before reading the HBA Reset + * bit to make sure it has cleared. If HBA Reset is not clear + * an error is returned. Cannot be used in non-blockable + * context. + * + * @dd Pointer to the driver data structure. + * + * return value + * 0 The reset was successful. + * -1 The HBA Reset bit did not clear. + */ +static int mtip_hba_reset(struct driver_data *dd) +{ + mtip_deinit_port(dd->port); + + /* Set the reset bit */ + writel(HOST_RESET, dd->mmio + HOST_CTL); + + /* Flush */ + readl(dd->mmio + HOST_CTL); + + /* Wait for reset to clear */ + ssleep(1); + + /* Check the bit has cleared */ + if (readl(dd->mmio + HOST_CTL) & HOST_RESET) { + dev_err(&dd->pdev->dev, + "Reset bit did not clear.\n"); + return -1; + } + + return 0; +} + +/* + * Display the identify command data. + * + * @port Pointer to the port data structure. + * + * return value + * None + */ +static void mtip_dump_identify(struct mtip_port *port) +{ + sector_t sectors; + unsigned short revid; + char cbuf[42]; + + if (!port->identify_valid) + return; + + strlcpy(cbuf, (char *)(port->identify+10), 21); + dev_info(&port->dd->pdev->dev, + "Serial No.: %s\n", cbuf); + + strlcpy(cbuf, (char *)(port->identify+23), 9); + dev_info(&port->dd->pdev->dev, + "Firmware Ver.: %s\n", cbuf); + + strlcpy(cbuf, (char *)(port->identify+27), 41); + dev_info(&port->dd->pdev->dev, "Model: %s\n", cbuf); + + if (mtip_hw_get_capacity(port->dd, §ors)) + dev_info(&port->dd->pdev->dev, + "Capacity: %llu sectors (%llu MB)\n", + (u64)sectors, + ((u64)sectors) * ATA_SECT_SIZE >> 20); + + pci_read_config_word(port->dd->pdev, PCI_REVISION_ID, &revid); + switch (revid & 0xff) { + case 0x1: + strlcpy(cbuf, "A0", 3); + break; + case 0x3: + strlcpy(cbuf, "A2", 3); + break; + default: + strlcpy(cbuf, "?", 2); + break; + } + dev_info(&port->dd->pdev->dev, + "Card Type: %s\n", cbuf); +} + +/* + * Map the commands scatter list into the command table. + * + * @command Pointer to the command. + * @nents Number of scatter list entries. + * + * return value + * None + */ +static inline void fill_command_sg(struct driver_data *dd, + struct mtip_cmd *command, + int nents) +{ + int n; + unsigned int dma_len; + struct mtip_cmd_sg *command_sg; + struct scatterlist *sg = command->sg; + + command_sg = command->command + AHCI_CMD_TBL_HDR_SZ; + + for (n = 0; n < nents; n++) { + dma_len = sg_dma_len(sg); + if (dma_len > 0x400000) + dev_err(&dd->pdev->dev, + "DMA segment length truncated\n"); + command_sg->info = cpu_to_le32((dma_len-1) & 0x3fffff); +#if (BITS_PER_LONG == 64) + *((unsigned long *) &command_sg->dba) = + cpu_to_le64(sg_dma_address(sg)); +#else + command_sg->dba = cpu_to_le32(sg_dma_address(sg)); + command_sg->dba_upper = + cpu_to_le32((sg_dma_address(sg) >> 16) >> 16); +#endif + command_sg++; + sg++; + } +} + +/* + * @brief Execute a drive command. + * + * return value 0 The command completed successfully. + * return value -1 An error occurred while executing the command. + */ +int exec_drive_task(struct mtip_port *port, u8 *command) +{ + struct host_to_dev_fis fis; + struct host_to_dev_fis *reply = (port->rxfis + RX_FIS_D2H_REG); + + /* Lock the internal command semaphore. */ + down_write(&port->dd->internal_sem); + + /* Build the FIS. */ + memset(&fis, 0, sizeof(struct host_to_dev_fis)); + fis.type = 0x27; + fis.opts = 1 << 7; + fis.command = command[0]; + fis.features = command[1]; + fis.sect_count = command[2]; + fis.sector = command[3]; + fis.cyl_low = command[4]; + fis.cyl_hi = command[5]; + fis.device = command[6] & ~0x10; /* Clear the dev bit*/ + + + dbg_printk(MTIP_DRV_NAME "%s: User Command: cmd %x, feat %x, " + "nsect %x, sect %x, lcyl %x, " + "hcyl %x, sel %x\n", + __func__, + command[0], + command[1], + command[2], + command[3], + command[4], + command[5], + command[6]); + + /* Execute the command. */ + if (mtip_exec_internal_command(port, + &fis, + 5, + 0, + 0, + 0, + GFP_KERNEL, + MTIP_IOCTL_COMMAND_TIMEOUT_MS) < 0) { + up_write(&port->dd->internal_sem); + return -1; + } + + command[0] = reply->command; /* Status*/ + command[1] = reply->features; /* Error*/ + command[4] = reply->cyl_low; + command[5] = reply->cyl_hi; + + dbg_printk(MTIP_DRV_NAME "%s: Completion Status: stat %x, " + "err %x , cyl_lo %x cyl_hi %x\n", + __func__, + command[0], + command[1], + command[4], + command[5]); + + up_write(&port->dd->internal_sem); + return 0; +} + +/* + * @brief Execute a drive command. + * + * @param port Pointer to the port data structure. + * @param command Pointer to the user specified command parameters. + * @param user_buffer Pointer to the user space buffer where read sector + * data should be copied. + * + * return value 0 The command completed successfully. + * return value -EFAULT An error occurred while copying the completion + * data to the user space buffer. + * return value -1 An error occurred while executing the command. + */ +int exec_drive_command(struct mtip_port *port, u8 *command, + void __user *user_buffer) +{ + struct host_to_dev_fis fis; + struct host_to_dev_fis *reply = (port->rxfis + RX_FIS_D2H_REG); + + /* Lock the internal command semaphore. */ + down_write(&port->dd->internal_sem); + + /* Build the FIS. */ + memset(&fis, 0, sizeof(struct host_to_dev_fis)); + fis.type = 0x27; + fis.opts = 1 << 7; + fis.command = command[0]; + fis.features = command[2]; + fis.sect_count = command[3]; + if (fis.command == ATA_CMD_SMART) { + fis.sector = command[1]; + fis.cyl_low = 0x4f; + fis.cyl_hi = 0xc2; + } + + dbg_printk(MTIP_DRV_NAME + "%s: User Command: cmd %x, sect %x, " + "feat %x, sectcnt %x\n", + __func__, + command[0], + command[1], + command[2], + command[3]); + + memset(port->sector_buffer, 0x00, ATA_SECT_SIZE); + + /* Execute the command. */ + if (mtip_exec_internal_command(port, + &fis, + 5, + port->sector_buffer_dma, + (command[3] != 0) ? ATA_SECT_SIZE : 0, + 0, + GFP_KERNEL, + MTIP_IOCTL_COMMAND_TIMEOUT_MS) + < 0) { + up_write(&port->dd->internal_sem); + return -1; + } + + /* Collect the completion status. */ + command[0] = reply->command; /* Status*/ + command[1] = reply->features; /* Error*/ + command[2] = command[3]; + + dbg_printk(MTIP_DRV_NAME + "%s: Completion Status: stat %x, " + "err %x, cmd %x\n", + __func__, + command[0], + command[1], + command[2]); + + if (user_buffer && command[3]) { + if (copy_to_user(user_buffer, + port->sector_buffer, + ATA_SECT_SIZE * command[3])) { + up_write(&port->dd->internal_sem); + return -EFAULT; + } + } + + up_write(&port->dd->internal_sem); + return 0; +} + +/* + * Indicates whether a command has a single sector payload. + * + * @command passed to the device to perform the certain event. + * @features passed to the device to perform the certain event. + * + * return value + * 1 command is one that always has a single sector payload, + * regardless of the value in the Sector Count field. + * 0 otherwise + * + */ +static unsigned int implicit_sector(unsigned char command, + unsigned char features) +{ + unsigned int rv = 0; + + /* list of commands that have an implicit sector count of 1 */ + switch (command) { + case 0xF1: + case 0xF2: + case 0xF3: + case 0xF4: + case 0xF5: + case 0xF6: + case 0xE4: + case 0xE8: + rv = 1; + break; + case 0xF9: + if (features == 0x03) + rv = 1; + break; + case 0xB0: + if ((features == 0xD0) || (features == 0xD1)) + rv = 1; + break; + case 0xB1: + if ((features == 0xC2) || (features == 0xC3)) + rv = 1; + break; + } + return rv; +} + +/* + * Executes a taskfile + * See ide_taskfile_ioctl() for derivation + */ +static int exec_drive_taskfile(struct driver_data *dd, + unsigned long arg, + unsigned char compat) +{ + struct host_to_dev_fis fis; + struct host_to_dev_fis *reply; + ide_task_request_t *req_task; + u8 *outbuf = NULL; + u8 *inbuf = NULL; + dma_addr_t outbuf_dma = (dma_addr_t)NULL; + dma_addr_t inbuf_dma = (dma_addr_t)NULL; + dma_addr_t dma_buffer = (dma_addr_t)NULL; + int err = 0; + int tasksize = sizeof(struct ide_task_request_s); + unsigned int taskin = 0; + unsigned int taskout = 0; + u8 nsect = 0; + char __user *buf = (char __user *)arg; + unsigned int timeout = MTIP_IOCTL_COMMAND_TIMEOUT_MS; + unsigned int force_single_sector; + unsigned int transfer_size; + unsigned long task_file_data; + int intotal, outtotal; + struct mtip_compat_ide_task_request_s *compat_req_task = NULL; + int compat_tasksize = sizeof(struct mtip_compat_ide_task_request_s); + + req_task = kzalloc(tasksize, GFP_KERNEL); + if (req_task == NULL) + return -ENOMEM; + + if (compat == 1) { + compat_req_task = + (struct mtip_compat_ide_task_request_s __user *) arg; + + if (copy_from_user(req_task, buf, + compat_tasksize - + (2 * sizeof(compat_long_t)))) { + err = -EFAULT; + goto abort; + } + + if (get_user(req_task->out_size, &compat_req_task->out_size)) { + err = -EFAULT; + goto abort; + } + + if (get_user(req_task->in_size, &compat_req_task->in_size)) { + err = -EFAULT; + goto abort; + } + + outtotal = compat_tasksize; + intotal = compat_tasksize + req_task->out_size; + } else { + if (copy_from_user(req_task, buf, tasksize)) { + kfree(req_task); + err = -EFAULT; + goto abort; + } + + outtotal = tasksize; + intotal = tasksize + req_task->out_size; + } + + taskout = req_task->out_size; + taskin = req_task->in_size; + /* 130560 = 512 * 0xFF*/ + if (taskin > 130560 || taskout > 130560) { + err = -EINVAL; + goto abort; + } + + if (taskout) { + outbuf = kzalloc(taskout, GFP_KERNEL); + if (outbuf == NULL) { + err = -ENOMEM; + goto abort; + } + if (copy_from_user(outbuf, buf + outtotal, taskout)) { + err = -EFAULT; + goto abort; + } + outbuf_dma = pci_map_single(dd->pdev, + outbuf, + taskout, + DMA_TO_DEVICE); + if (outbuf_dma == (dma_addr_t)NULL) { + err = -ENOMEM; + goto abort; + } + dma_buffer = outbuf_dma; + } + + if (taskin) { + inbuf = kzalloc(taskin, GFP_KERNEL); + if (inbuf == NULL) { + err = -ENOMEM; + goto abort; + } + + if (copy_from_user(inbuf, buf + intotal, taskin)) { + err = -EFAULT; + goto abort; + } + inbuf_dma = pci_map_single(dd->pdev, + inbuf, + taskin, DMA_FROM_DEVICE); + if (inbuf_dma == (dma_addr_t)NULL) { + err = -ENOMEM; + goto abort; + } + dma_buffer = inbuf_dma; + } + + /* only supports PIO and non-data commands from this ioctl. */ + switch (req_task->data_phase) { + case TASKFILE_OUT: + nsect = taskout / ATA_SECT_SIZE; + reply = (dd->port->rxfis + RX_FIS_PIO_SETUP); + break; + case TASKFILE_IN: + reply = (dd->port->rxfis + RX_FIS_PIO_SETUP); + break; + case TASKFILE_NO_DATA: + reply = (dd->port->rxfis + RX_FIS_D2H_REG); + break; + default: + err = -EINVAL; + goto abort; + } + + /* Lock the internal command semaphore. */ + down_write(&dd->internal_sem); + + /* Build the FIS. */ + memset(&fis, 0, sizeof(struct host_to_dev_fis)); + + fis.type = 0x27; + fis.opts = 1 << 7; + fis.command = req_task->io_ports[7]; + fis.features = req_task->io_ports[1]; + fis.sect_count = req_task->io_ports[2]; + fis.lba_low = req_task->io_ports[3]; + fis.lba_mid = req_task->io_ports[4]; + fis.lba_hi = req_task->io_ports[5]; + /* Clear the dev bit*/ + fis.device = req_task->io_ports[6] & ~0x10; + + if ((req_task->in_flags.all == 0) && (req_task->out_flags.all & 1)) { + req_task->in_flags.all = + IDE_TASKFILE_STD_IN_FLAGS | + (IDE_HOB_STD_IN_FLAGS << 8); + fis.lba_low_ex = req_task->hob_ports[3]; + fis.lba_mid_ex = req_task->hob_ports[4]; + fis.lba_hi_ex = req_task->hob_ports[5]; + fis.features_ex = req_task->hob_ports[1]; + fis.sect_cnt_ex = req_task->hob_ports[2]; + + } else { + req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS; + } + + force_single_sector = implicit_sector(fis.command, fis.features); + + if ((taskin || taskout) && (!fis.sect_count)) { + if (nsect) + fis.sect_count = nsect; + else { + if (!force_single_sector) { + dev_warn(&dd->pdev->dev, + "data movement but " + "sect_count is 0\n"); + up_write(&dd->internal_sem); + err = -EINVAL; + goto abort; + } + } + } + + dbg_printk(MTIP_DRV_NAME + "taskfile: cmd %x, feat %x, nsect %x," + " sect/lbal %x, lcyl/lbam %x, hcyl/lbah %x," + " head/dev %x\n", + fis.command, + fis.features, + fis.sect_count, + fis.lba_low, + fis.lba_mid, + fis.lba_hi, + fis.device); + + switch (fis.command) { + case 0x92: /* Change timeout for Download Microcode to 60 seconds.*/ + timeout = 60000; + break; + case 0xf4: /* Change timeout for Security Erase Unit to 4 minutes.*/ + timeout = 240000; + break; + case 0xe0: /* Change timeout for standby immediate to 10 seconds.*/ + timeout = 10000; + break; + case 0xf7: /* Change timeout for vendor unique command to 10 secs */ + timeout = 10000; + break; + case 0xfa: /* Change timeout for vendor unique command to 10 secs */ + timeout = 10000; + break; + default: + timeout = MTIP_IOCTL_COMMAND_TIMEOUT_MS; + break; + } + + /* Determine the correct transfer size.*/ + if (force_single_sector) + transfer_size = ATA_SECT_SIZE; + else + transfer_size = ATA_SECT_SIZE * fis.sect_count; + + /* Execute the command.*/ + if (mtip_exec_internal_command(dd->port, + &fis, + 5, + dma_buffer, + transfer_size, + 0, + GFP_KERNEL, + timeout) < 0) { + up_write(&dd->internal_sem); + err = -EIO; + goto abort; + } + + task_file_data = readl(dd->port->mmio+PORT_TFDATA); + + if ((req_task->data_phase == TASKFILE_IN) && !(task_file_data & 1)) { + reply = dd->port->rxfis + RX_FIS_PIO_SETUP; + req_task->io_ports[7] = reply->control; + } else { + reply = dd->port->rxfis + RX_FIS_D2H_REG; + req_task->io_ports[7] = reply->command; + } + + /* reclaim the DMA buffers.*/ + if (inbuf_dma) + pci_unmap_single(dd->pdev, inbuf_dma, + taskin, DMA_FROM_DEVICE); + if (outbuf_dma) + pci_unmap_single(dd->pdev, outbuf_dma, + taskout, DMA_TO_DEVICE); + inbuf_dma = (dma_addr_t) NULL; + outbuf_dma = (dma_addr_t) NULL; + + /* return the ATA registers to the caller.*/ + req_task->io_ports[1] = reply->features; + req_task->io_ports[2] = reply->sect_count; + req_task->io_ports[3] = reply->lba_low; + req_task->io_ports[4] = reply->lba_mid; + req_task->io_ports[5] = reply->lba_hi; + req_task->io_ports[6] = reply->device; + + if (req_task->out_flags.all & 1) { + + req_task->hob_ports[3] = reply->lba_low_ex; + req_task->hob_ports[4] = reply->lba_mid_ex; + req_task->hob_ports[5] = reply->lba_hi_ex; + req_task->hob_ports[1] = reply->features_ex; + req_task->hob_ports[2] = reply->sect_cnt_ex; + } + + /* Com rest after secure erase or lowlevel format */ + if (((fis.command == 0xF4) || + ((fis.command == 0xFC) && + (fis.features == 0x27 || fis.features == 0x72 || + fis.features == 0x62 || fis.features == 0x26))) && + !(reply->command & 1)) { + mtip_restart_port(dd->port); + } + + dbg_printk(MTIP_DRV_NAME + "%s: Completion: stat %x," + "err %x, sect_cnt %x, lbalo %x," + "lbamid %x, lbahi %x, dev %x\n", + __func__, + req_task->io_ports[7], + req_task->io_ports[1], + req_task->io_ports[2], + req_task->io_ports[3], + req_task->io_ports[4], + req_task->io_ports[5], + req_task->io_ports[6]); + + up_write(&dd->internal_sem); + + if (compat == 1) { + if (copy_to_user(buf, req_task, + compat_tasksize - + (2 * sizeof(compat_long_t)))) { + err = -EFAULT; + goto abort; + } + if (put_user(req_task->out_size, + &compat_req_task->out_size)) { + err = -EFAULT; + goto abort; + } + if (put_user(req_task->in_size, &compat_req_task->in_size)) { + err = -EFAULT; + goto abort; + } + } else { + if (copy_to_user(buf, req_task, tasksize)) { + err = -EFAULT; + goto abort; + } + } + if (taskout) { + if (copy_to_user(buf + outtotal, outbuf, taskout)) { + err = -EFAULT; + goto abort; + } + } + if (taskin) { + if (copy_to_user(buf + intotal, inbuf, taskin)) { + err = -EFAULT; + goto abort; + } + } +abort: + if (inbuf_dma) + pci_unmap_single(dd->pdev, inbuf_dma, + taskin, DMA_FROM_DEVICE); + if (outbuf_dma) + pci_unmap_single(dd->pdev, outbuf_dma, + taskout, DMA_TO_DEVICE); + kfree(req_task); + kfree(outbuf); + kfree(inbuf); + + return err; +} + +/* + * Handle IOCTL calls from the Block Layer. + * + * This function is called by the Block Layer when it receives an IOCTL + * command that it does not understand. If the IOCTL command is not supported + * this function returns -ENOTTY. + * + * @dd Pointer to the driver data structure. + * @cmd IOCTL command passed from the Block Layer. + * @arg IOCTL argument passed from the Block Layer. + * + * return value + * 0 The IOCTL completed successfully. + * -ENOTTY The specified command is not supported. + * -EFAULT An error occurred copying data to a user space buffer. + * -EIO An error occurred while executing the command. + */ +int mtip_hw_ioctl(struct driver_data *dd, + unsigned int cmd, + unsigned long arg, + unsigned char compat) +{ + switch (cmd) { + case HDIO_GET_IDENTITY: + if (mtip_get_identify(dd->port, (void __user *) arg) < 0) { + dev_warn(&dd->pdev->dev, + "Unable to read identity\n"); + return -EIO; + } + + break; + case HDIO_DRIVE_CMD: + { + u8 drive_command[4]; + + /* Copy the user command info to our buffer. */ + if (copy_from_user(drive_command, + (void __user *) arg, + sizeof(drive_command))) + return -EFAULT; + + /* Execute the drive command. */ + if (exec_drive_command(dd->port, + drive_command, + (void __user *) (arg+4))) + return -EIO; + + /* Copy the status back to the users buffer. */ + if (copy_to_user((void __user *) arg, + drive_command, + sizeof(drive_command))) + return -EFAULT; + + break; + } + case HDIO_DRIVE_TASK: + { + u8 drive_command[7]; + + /* Copy the user command info to our buffer. */ + if (copy_from_user(drive_command, + (void __user *) arg, + sizeof(drive_command))) + return -EFAULT; + + /* Execute the drive command. */ + if (exec_drive_task(dd->port, drive_command)) + return -EIO; + + /* Copy the status back to the users buffer. */ + if (copy_to_user((void __user *) arg, + drive_command, + sizeof(drive_command))) + return -EFAULT; + + break; + } + case HDIO_DRIVE_TASKFILE: + return exec_drive_taskfile(dd, arg, compat); + + default: + return -EINVAL; + } + return 0; +} + +/* + * Submit an IO to the hw + * + * This function is called by the block layer to issue an io + * to the device. Upon completion, the callback function will + * be called with the data parameter passed as the callback data. + * + * @dd Pointer to the driver data structure. + * @start First sector to read. + * @nsect Number of sectors to read. + * @nents Number of entries in scatter list for the read command. + * @tag The tag of this read command. + * @callback Pointer to the function that should be called + * when the read completes. + * @data Callback data passed to the callback function + * when the read completes. + * @barrier If non-zero, this command must be completed before + * issuing any other commands. + * @dir Direction (read or write) + * + * return value + * None + */ +void mtip_hw_submit_io(struct driver_data *dd, + sector_t start, + int nsect, + int nents, + int tag, + void *callback, + void *data, + int barrier, + int dir) +{ + struct host_to_dev_fis *fis; + struct mtip_port *port = dd->port; + struct mtip_cmd *command = &port->commands[tag]; + + /* Map the scatter list for DMA access */ + if (dir == READ) + nents = dma_map_sg(&dd->pdev->dev, command->sg, + nents, DMA_FROM_DEVICE); + else + nents = dma_map_sg(&dd->pdev->dev, command->sg, + nents, DMA_TO_DEVICE); + + command->scatter_ents = nents; + + /* + * The number of retries for this command before it is + * reported as a failure to the upper layers. + */ + command->retries = MTIP_MAX_RETRIES; + + /* Fill out fis */ + fis = command->command; + fis->type = 0x27; + fis->opts = 1 << 7; + fis->command = + (dir == READ ? ATA_CMD_FPDMA_READ : ATA_CMD_FPDMA_WRITE); + *((unsigned int *) &fis->lba_low) = (start & 0xffffff); + *((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xffffff); + fis->device = 1 << 6; + if (barrier) + fis->device |= FUA_BIT; + fis->features = nsect & 0xff; + fis->features_ex = (nsect >> 8) & 0xff; + fis->sect_count = ((tag << 3) | (tag >> 5)); + fis->sect_cnt_ex = 0; + fis->control = 0; + fis->res2 = 0; + fis->res3 = 0; + fill_command_sg(dd, command, nents); + + /* Populate the command header */ + command->command_header->opts = cpu_to_le32( + (nents << 16) | 5 | AHCI_CMD_PREFETCH); + command->command_header->byte_count = 0; + + /* + * Set the completion function and data for the command + * within this layer. + */ + command->comp_data = dd; + command->comp_func = mtip_async_complete; + command->direction = (dir == READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE); + + /* + * Set the completion function and data for the command passed + * from the upper layer. + */ + command->async_data = data; + command->async_callback = callback; + + /* + * Lock used to prevent this command from being issued + * if an internal command is in progress. + */ + down_read(&port->dd->internal_sem); + + /* Issue the command to the hardware */ + mtip_issue_ncq_command(port, tag); + + /* Set the command's timeout value.*/ + port->commands[tag].comp_time = jiffies + msecs_to_jiffies( + MTIP_NCQ_COMMAND_TIMEOUT_MS); + + up_read(&port->dd->internal_sem); +} + +/* + * Release a command slot. + * + * @dd Pointer to the driver data structure. + * @tag Slot tag + * + * return value + * None + */ +void mtip_hw_release_scatterlist(struct driver_data *dd, int tag) +{ + release_slot(dd->port, tag); +} + +/* + * Obtain a command slot and return its associated scatter list. + * + * @dd Pointer to the driver data structure. + * @tag Pointer to an int that will receive the allocated command + * slot tag. + * + * return value + * Pointer to the scatter list for the allocated command slot + * or NULL if no command slots are available. + */ +struct scatterlist *mtip_hw_get_scatterlist(struct driver_data *dd, + int *tag) +{ + /* + * It is possible that, even with this semaphore, a thread + * may think that no command slots are available. Therefore, we + * need to make an attempt to get_slot(). + */ + down(&dd->port->cmd_slot); + *tag = get_slot(dd->port); + + if (unlikely(*tag < 0)) + return NULL; + + return dd->port->commands[*tag].sg; +} + +/* + * Sysfs register/status dump. + * + * @dev Pointer to the device structure, passed by the kernrel. + * @attr Pointer to the device_attribute structure passed by the kernel. + * @buf Pointer to the char buffer that will receive the stats info. + * + * return value + * The size, in bytes, of the data copied into buf. + */ +static ssize_t hw_show_registers(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + u32 group_allocated; + struct driver_data *dd = dev_to_disk(dev)->private_data; + int size = 0; + int n; + + size += sprintf(&buf[size], "%s:\ns_active:\n", __func__); + + for (n = 0; n < dd->slot_groups; n++) + size += sprintf(&buf[size], "0x%08x\n", + readl(dd->port->s_active[n])); + + size += sprintf(&buf[size], "Command Issue:\n"); + + for (n = 0; n < dd->slot_groups; n++) + size += sprintf(&buf[size], "0x%08x\n", + readl(dd->port->cmd_issue[n])); + + size += sprintf(&buf[size], "Allocated:\n"); + + for (n = 0; n < dd->slot_groups; n++) { + if (sizeof(long) > sizeof(u32)) + group_allocated = + dd->port->allocated[n/2] >> (32*(n&1)); + else + group_allocated = dd->port->allocated[n]; + size += sprintf(&buf[size], "0x%08x\n", + group_allocated); + } + + size += sprintf(&buf[size], "completed:\n"); + + for (n = 0; n < dd->slot_groups; n++) + size += sprintf(&buf[size], "0x%08x\n", + readl(dd->port->completed[n])); + + size += sprintf(&buf[size], "PORT_IRQ_STAT 0x%08x\n", + readl(dd->port->mmio + PORT_IRQ_STAT)); + size += sprintf(&buf[size], "HOST_IRQ_STAT 0x%08x\n", + readl(dd->mmio + HOST_IRQ_STAT)); + + return size; +} +static DEVICE_ATTR(registers, S_IRUGO, hw_show_registers, NULL); + +/* + * Create the sysfs related attributes. + * + * @dd Pointer to the driver data structure. + * @kobj Pointer to the kobj for the block device. + * + * return value + * 0 Operation completed successfully. + * -EINVAL Invalid parameter. + */ +int mtip_hw_sysfs_init(struct driver_data *dd, struct kobject *kobj) +{ + if (!kobj || !dd) + return -EINVAL; + + if (sysfs_create_file(kobj, &dev_attr_registers.attr)) + dev_warn(&dd->pdev->dev, + "Error creating registers sysfs entry\n"); + return 0; +} + +/* + * Remove the sysfs related attributes. + * + * @dd Pointer to the driver data structure. + * @kobj Pointer to the kobj for the block device. + * + * return value + * 0 Operation completed successfully. + * -EINVAL Invalid parameter. + */ +int mtip_hw_sysfs_exit(struct driver_data *dd, struct kobject *kobj) +{ + if (!kobj || !dd) + return -EINVAL; + + sysfs_remove_file(kobj, &dev_attr_registers.attr); + + return 0; +} + +/* + * Perform any init/resume time hardware setup + * + * @dd Pointer to the driver data structure. + * + * return value + * None + */ +static inline void hba_setup(struct driver_data *dd) +{ + u32 hwdata; + hwdata = readl(dd->mmio + HOST_HSORG); + + /* interrupt bug workaround: use only 1 IS bit.*/ + writel(hwdata | + HSORG_DISABLE_SLOTGRP_INTR | + HSORG_DISABLE_SLOTGRP_PXIS, + dd->mmio + HOST_HSORG); +} + +/* + * Detect the details of the product, and store anything needed + * into the driver data structure. This includes product type and + * version and number of slot groups. + * + * @dd Pointer to the driver data structure. + * + * return value + * None + */ +static void mtip_detect_product(struct driver_data *dd) +{ + u32 hwdata; + unsigned int rev, slotgroups; + + /* + * HBA base + 0xFC [15:0] - vendor-specific hardware interface + * info register: + * [15:8] hardware/software interface rev# + * [ 3] asic-style interface + * [ 2:0] number of slot groups, minus 1 (only valid for asic-style). + */ + hwdata = readl(dd->mmio + HOST_HSORG); + + dd->product_type = MTIP_PRODUCT_UNKNOWN; + dd->slot_groups = 1; + + if (hwdata & 0x8) { + dd->product_type = MTIP_PRODUCT_ASICFPGA; + rev = (hwdata & HSORG_HWREV) >> 8; + slotgroups = (hwdata & HSORG_SLOTGROUPS) + 1; + dev_info(&dd->pdev->dev, + "ASIC-FPGA design, HS rev 0x%x, " + "%i slot groups [%i slots]\n", + rev, + slotgroups, + slotgroups * 32); + + if (slotgroups > MTIP_MAX_SLOT_GROUPS) { + dev_warn(&dd->pdev->dev, + "Warning: driver only supports " + "%i slot groups.\n", MTIP_MAX_SLOT_GROUPS); + slotgroups = MTIP_MAX_SLOT_GROUPS; + } + dd->slot_groups = slotgroups; + return; + } + + dev_warn(&dd->pdev->dev, "Unrecognized product id\n"); +} + +/* + * Blocking wait for FTL rebuild to complete + * + * @dd Pointer to the DRIVER_DATA structure. + * + * return value + * 0 FTL rebuild completed successfully + * -EFAULT FTL rebuild error/timeout/interruption + */ +static int mtip_ftl_rebuild_poll(struct driver_data *dd) +{ + unsigned long timeout, cnt = 0, start; + + dev_warn(&dd->pdev->dev, + "FTL rebuild in progress. Polling for completion.\n"); + + start = jiffies; + dd->ftlrebuildflag = 1; + timeout = jiffies + msecs_to_jiffies(MTIP_FTL_REBUILD_TIMEOUT_MS); + + do { +#ifdef CONFIG_HOTPLUG + if (mtip_check_surprise_removal(dd->pdev)) + return -EFAULT; +#endif + if (mtip_get_identify(dd->port, NULL) < 0) + return -EFAULT; + + if (*(dd->port->identify + MTIP_FTL_REBUILD_OFFSET) == + MTIP_FTL_REBUILD_MAGIC) { + ssleep(1); + /* Print message every 3 minutes */ + if (cnt++ >= 180) { + dev_warn(&dd->pdev->dev, + "FTL rebuild in progress (%d secs).\n", + jiffies_to_msecs(jiffies - start) / 1000); + cnt = 0; + } + } else { + dev_warn(&dd->pdev->dev, + "FTL rebuild complete (%d secs).\n", + jiffies_to_msecs(jiffies - start) / 1000); + dd->ftlrebuildflag = 0; + break; + } + ssleep(10); + } while (time_before(jiffies, timeout)); + + /* Check for timeout */ + if (dd->ftlrebuildflag) { + dev_err(&dd->pdev->dev, + "Timed out waiting for FTL rebuild to complete (%d secs).\n", + jiffies_to_msecs(jiffies - start) / 1000); + return -EFAULT; + } + + return 0; +} + +/* + * Called once for each card. + * + * @dd Pointer to the driver data structure. + * + * return value + * 0 on success, else an error code. + */ +int mtip_hw_init(struct driver_data *dd) +{ + int i; + int rv; + unsigned int num_command_slots; + + dd->mmio = pcim_iomap_table(dd->pdev)[MTIP_ABAR]; + + mtip_detect_product(dd); + if (dd->product_type == MTIP_PRODUCT_UNKNOWN) { + rv = -EIO; + goto out1; + } + num_command_slots = dd->slot_groups * 32; + + hba_setup(dd); + + /* + * Initialize the internal semaphore + * Use a rw semaphore to enable prioritization of + * mgmnt ioctl traffic during heavy IO load + */ + init_rwsem(&dd->internal_sem); + + tasklet_init(&dd->tasklet, mtip_tasklet, (unsigned long)dd); + + dd->port = kzalloc(sizeof(struct mtip_port), GFP_KERNEL); + if (!dd->port) { + dev_err(&dd->pdev->dev, + "Memory allocation: port structure\n"); + return -ENOMEM; + } + + /* Counting semaphore to track command slot usage */ + sema_init(&dd->port->cmd_slot, num_command_slots - 1); + + /* Spinlock to prevent concurrent issue */ + spin_lock_init(&dd->port->cmd_issue_lock); + + /* Set the port mmio base address. */ + dd->port->mmio = dd->mmio + PORT_OFFSET; + dd->port->dd = dd; + + /* Allocate memory for the command list. */ + dd->port->command_list = + dmam_alloc_coherent(&dd->pdev->dev, + HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2), + &dd->port->command_list_dma, + GFP_KERNEL); + if (!dd->port->command_list) { + dev_err(&dd->pdev->dev, + "Memory allocation: command list\n"); + rv = -ENOMEM; + goto out1; + } + + /* Clear the memory we have allocated. */ + memset(dd->port->command_list, + 0, + HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2)); + + /* Setup the addresse of the RX FIS. */ + dd->port->rxfis = dd->port->command_list + HW_CMD_SLOT_SZ; + dd->port->rxfis_dma = dd->port->command_list_dma + HW_CMD_SLOT_SZ; + + /* Setup the address of the command tables. */ + dd->port->command_table = dd->port->rxfis + AHCI_RX_FIS_SZ; + dd->port->command_tbl_dma = dd->port->rxfis_dma + AHCI_RX_FIS_SZ; + + /* Setup the address of the identify data. */ + dd->port->identify = dd->port->command_table + + HW_CMD_TBL_AR_SZ; + dd->port->identify_dma = dd->port->command_tbl_dma + + HW_CMD_TBL_AR_SZ; + + /* Setup the address of the sector buffer. */ + dd->port->sector_buffer = (void *) dd->port->identify + ATA_SECT_SIZE; + dd->port->sector_buffer_dma = dd->port->identify_dma + ATA_SECT_SIZE; + + /* Point the command headers at the command tables. */ + for (i = 0; i < num_command_slots; i++) { + dd->port->commands[i].command_header = + dd->port->command_list + + (sizeof(struct mtip_cmd_hdr) * i); + dd->port->commands[i].command_header_dma = + dd->port->command_list_dma + + (sizeof(struct mtip_cmd_hdr) * i); + + dd->port->commands[i].command = + dd->port->command_table + (HW_CMD_TBL_SZ * i); + dd->port->commands[i].command_dma = + dd->port->command_tbl_dma + (HW_CMD_TBL_SZ * i); + + if (readl(dd->mmio + HOST_CAP) & HOST_CAP_64) + dd->port->commands[i].command_header->ctbau = + cpu_to_le32( + (dd->port->commands[i].command_dma >> 16) >> 16); + dd->port->commands[i].command_header->ctba = cpu_to_le32( + dd->port->commands[i].command_dma & 0xffffffff); + + /* + * If this is not done, a bug is reported by the stock + * FC11 i386. Due to the fact that it has lots of kernel + * debugging enabled. + */ + sg_init_table(dd->port->commands[i].sg, MTIP_MAX_SG); + + /* Mark all commands as currently inactive.*/ + atomic_set(&dd->port->commands[i].active, 0); + } + + /* Setup the pointers to the extended s_active and CI registers. */ + for (i = 0; i < dd->slot_groups; i++) { + dd->port->s_active[i] = + dd->port->mmio + i*0x80 + PORT_SCR_ACT; + dd->port->cmd_issue[i] = + dd->port->mmio + i*0x80 + PORT_COMMAND_ISSUE; + dd->port->completed[i] = + dd->port->mmio + i*0x80 + PORT_SDBV; + } + + /* Reset the HBA. */ + if (mtip_hba_reset(dd) < 0) { + dev_err(&dd->pdev->dev, + "Card did not reset within timeout\n"); + rv = -EIO; + goto out2; + } + + mtip_init_port(dd->port); + mtip_start_port(dd->port); + + /* Setup the ISR and enable interrupts. */ + rv = devm_request_irq(&dd->pdev->dev, + dd->pdev->irq, + mtip_irq_handler, + IRQF_SHARED, + dev_driver_string(&dd->pdev->dev), + dd); + + if (rv) { + dev_err(&dd->pdev->dev, + "Unable to allocate IRQ %d\n", dd->pdev->irq); + goto out2; + } + + /* Enable interrupts on the HBA. */ + writel(readl(dd->mmio + HOST_CTL) | HOST_IRQ_EN, + dd->mmio + HOST_CTL); + + init_timer(&dd->port->cmd_timer); + dd->port->cmd_timer.data = (unsigned long int) dd->port; + dd->port->cmd_timer.function = mtip_timeout_function; + mod_timer(&dd->port->cmd_timer, + jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD)); + + if (mtip_get_identify(dd->port, NULL) < 0) { + rv = -EFAULT; + goto out3; + } + mtip_dump_identify(dd->port); + + if (*(dd->port->identify + MTIP_FTL_REBUILD_OFFSET) == + MTIP_FTL_REBUILD_MAGIC) { + return mtip_ftl_rebuild_poll(dd); + } + return rv; + +out3: + del_timer_sync(&dd->port->cmd_timer); + + /* Disable interrupts on the HBA. */ + writel(readl(dd->mmio + HOST_CTL) & ~HOST_IRQ_EN, + dd->mmio + HOST_CTL); + + /*Release the IRQ. */ + devm_free_irq(&dd->pdev->dev, dd->pdev->irq, dd); + +out2: + mtip_deinit_port(dd->port); + + /* Free the command/command header memory. */ + dmam_free_coherent(&dd->pdev->dev, + HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2), + dd->port->command_list, + dd->port->command_list_dma); +out1: + /* Free the memory allocated for the for structure. */ + kfree(dd->port); + + return rv; +} + +/* + * Called to deinitialize an interface. + * + * @dd Pointer to the driver data structure. + * + * return value + * 0 + */ +int mtip_hw_exit(struct driver_data *dd) +{ + /* + * Send standby immediate (E0h) to the drive so that it + * saves its state. + */ + if (atomic_read(&dd->drv_cleanup_done) != true) { + + mtip_standby_immediate(dd->port); + + /* de-initialize the port. */ + mtip_deinit_port(dd->port); + + /* Disable interrupts on the HBA. */ + writel(readl(dd->mmio + HOST_CTL) & ~HOST_IRQ_EN, + dd->mmio + HOST_CTL); + } + + del_timer_sync(&dd->port->cmd_timer); + + /* Stop the bottom half tasklet. */ + tasklet_kill(&dd->tasklet); + + /* Release the IRQ. */ + devm_free_irq(&dd->pdev->dev, dd->pdev->irq, dd); + + /* Free the command/command header memory. */ + dmam_free_coherent(&dd->pdev->dev, + HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2), + dd->port->command_list, + dd->port->command_list_dma); + /* Free the memory allocated for the for structure. */ + kfree(dd->port); + + return 0; +} + +/* + * Issue a Standby Immediate command to the device. + * + * This function is called by the Block Layer just before the + * system powers off during a shutdown. + * + * @dd Pointer to the driver data structure. + * + * return value + * 0 + */ +int mtip_hw_shutdown(struct driver_data *dd) +{ + /* + * Send standby immediate (E0h) to the drive so that it + * saves its state. + */ + mtip_standby_immediate(dd->port); + + return 0; +} + +/* + * Suspend function + * + * This function is called by the Block Layer just before the + * system hibernates. + * + * @dd Pointer to the driver data structure. + * + * return value + * 0 Suspend was successful + * -EFAULT Suspend was not successful + */ +int mtip_hw_suspend(struct driver_data *dd) +{ + /* + * Send standby immediate (E0h) to the drive + * so that it saves its state. + */ + if (mtip_standby_immediate(dd->port) != 0) { + dev_err(&dd->pdev->dev, + "Failed standby-immediate command\n"); + return -EFAULT; + } + + /* Disable interrupts on the HBA.*/ + writel(readl(dd->mmio + HOST_CTL) & ~HOST_IRQ_EN, + dd->mmio + HOST_CTL); + mtip_deinit_port(dd->port); + + return 0; +} + +/* + * Resume function + * + * This function is called by the Block Layer as the + * system resumes. + * + * @dd Pointer to the driver data structure. + * + * return value + * 0 Resume was successful + * -EFAULT Resume was not successful + */ +int mtip_hw_resume(struct driver_data *dd) +{ + /* Perform any needed hardware setup steps */ + hba_setup(dd); + + /* Reset the HBA */ + if (mtip_hba_reset(dd) != 0) { + dev_err(&dd->pdev->dev, + "Unable to reset the HBA\n"); + return -EFAULT; + } + + /* + * Enable the port, DMA engine, and FIS reception specific + * h/w in controller. + */ + mtip_init_port(dd->port); + mtip_start_port(dd->port); + + /* Enable interrupts on the HBA.*/ + writel(readl(dd->mmio + HOST_CTL) | HOST_IRQ_EN, + dd->mmio + HOST_CTL); + + return 0; +} + +/* + * This function is called for clean the pending command in the + * command slot during the surprise removal of device and return + * error to the upper layer. + * + * @dd Pointer to the DRIVER_DATA structure. + * + * return value + * None + */ +void mtip_command_cleanup(struct driver_data *dd) +{ + int group = 0, commandslot = 0, commandindex = 0; + struct mtip_cmd *command; + struct mtip_port *port = dd->port; + + for (group = 0; group < 4; group++) { + for (commandslot = 0; commandslot < 32; commandslot++) { + if (!(port->allocated[group] & (1 << commandslot))) + continue; + + commandindex = group << 5 | commandslot; + command = &port->commands[commandindex]; + + if (atomic_read(&command->active) + && (command->async_callback)) { + command->async_callback(command->async_data, + -ENODEV); + command->async_callback = NULL; + command->async_data = NULL; + } + + dma_unmap_sg(&port->dd->pdev->dev, + command->sg, + command->scatter_ents, + command->direction); + } + } + + up(&port->cmd_slot); + + atomic_set(&dd->drv_cleanup_done, true); +} + +/* + * Helper function for reusing disk name + * upon hot insertion. + */ +static int rssd_disk_name_format(char *prefix, + int index, + char *buf, + int buflen) +{ + const int base = 'z' - 'a' + 1; + char *begin = buf + strlen(prefix); + char *end = buf + buflen; + char *p; + int unit; + + p = end - 1; + *p = '\0'; + unit = base; + do { + if (p == begin) + return -EINVAL; + *--p = 'a' + (index % unit); + index = (index / unit) - 1; + } while (index >= 0); + + memmove(begin, p, end - p); + memcpy(buf, prefix, strlen(prefix)); + + return 0; +} + +/* + * Block layer IOCTL handler. + * + * @dev Pointer to the block_device structure. + * @mode ignored + * @cmd IOCTL command passed from the user application. + * @arg Argument passed from the user application. + * + * return value + * 0 IOCTL completed successfully. + * -ENOTTY IOCTL not supported or invalid driver data + * structure pointer. + */ +static int mtip_block_ioctl(struct block_device *dev, + fmode_t mode, + unsigned cmd, + unsigned long arg) +{ + struct driver_data *dd = dev->bd_disk->private_data; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (!dd) + return -ENOTTY; + + switch (cmd) { + case BLKFLSBUF: + return 0; + default: + return mtip_hw_ioctl(dd, cmd, arg, 0); + } +} + +/* + * Block layer compat IOCTL handler. + * + * @dev Pointer to the block_device structure. + * @mode ignored + * @cmd IOCTL command passed from the user application. + * @arg Argument passed from the user application. + * + * return value + * 0 IOCTL completed successfully. + * -ENOTTY IOCTL not supported or invalid driver data + * structure pointer. + */ +static int mtip_block_compat_ioctl(struct block_device *dev, + fmode_t mode, + unsigned cmd, + unsigned long arg) +{ + struct driver_data *dd = dev->bd_disk->private_data; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (!dd) + return -ENOTTY; + + switch (cmd) { + case BLKFLSBUF: + return 0; + default: + return mtip_hw_ioctl(dd, cmd, arg, 1); + } +} + +/* + * Obtain the geometry of the device. + * + * You may think that this function is obsolete, but some applications, + * fdisk for example still used CHS values. This function describes the + * device as having 224 heads and 56 sectors per cylinder. These values are + * chosen so that each cylinder is aligned on a 4KB boundary. Since a + * partition is described in terms of a start and end cylinder this means + * that each partition is also 4KB aligned. Non-aligned partitions adversely + * affects performance. + * + * @dev Pointer to the block_device strucutre. + * @geo Pointer to a hd_geometry structure. + * + * return value + * 0 Operation completed successfully. + * -ENOTTY An error occurred while reading the drive capacity. + */ +static int mtip_block_getgeo(struct block_device *dev, + struct hd_geometry *geo) +{ + struct driver_data *dd = dev->bd_disk->private_data; + sector_t capacity; + + if (!dd) + return -ENOTTY; + + if (!(mtip_hw_get_capacity(dd, &capacity))) { + dev_warn(&dd->pdev->dev, + "Could not get drive capacity.\n"); + return -ENOTTY; + } + + geo->heads = 224; + geo->sectors = 56; +#if BITS_PER_LONG == 64 + geo->cylinders = capacity / (geo->heads * geo->sectors); +#else + do_div(capacity, (geo->heads * geo->sectors)); + geo->cylinders = capacity; +#endif + return 0; +} + +/* + * Block device operation function. + * + * This structure contains pointers to the functions required by the block + * layer. + */ +static const struct block_device_operations mtip_block_ops = { + .ioctl = mtip_block_ioctl, + .compat_ioctl = mtip_block_compat_ioctl, + .getgeo = mtip_block_getgeo, + .owner = THIS_MODULE +}; + +/* + * Block layer make request function. + * + * This function is called by the kernel to process a BIO for + * the P320 device. + * + * @queue Pointer to the request queue. Unused other than to obtain + * the driver data structure. + * @bio Pointer to the BIO. + * + * return value + * 0 + */ +static int mtip_make_request(struct request_queue *queue, struct bio *bio) +{ + struct driver_data *dd = queue->queuedata; + struct scatterlist *sg; + struct bio_vec *bvec; + int nents = 0; + int tag = 0; + + if (unlikely(!bio_has_data(bio))) { + blk_queue_flush(queue, 0); + bio_endio(bio, 0); + return 0; + } + + if (unlikely(atomic_read(&dd->eh_active))) { + bio_endio(bio, -EBUSY); + return 0; + } + + sg = mtip_hw_get_scatterlist(dd, &tag); + if (likely(sg != NULL)) { + blk_queue_bounce(queue, &bio); + + if (unlikely((bio)->bi_vcnt > MTIP_MAX_SG)) { + dev_warn(&dd->pdev->dev, + "Maximum number of SGL entries exceeded"); + bio_io_error(bio); + mtip_hw_release_scatterlist(dd, tag); + return 0; + } + + /* Create the scatter list for this bio. */ + bio_for_each_segment(bvec, bio, nents) { + sg_set_page(&sg[nents], + bvec->bv_page, + bvec->bv_len, + bvec->bv_offset); + } + + /* Issue the read/write. */ + mtip_hw_submit_io(dd, + bio->bi_sector, + bio_sectors(bio), + nents, + tag, + bio_endio, + bio, + bio->bi_rw & REQ_FLUSH, + bio_data_dir(bio)); + } else { + bio_io_error(bio); + } + + return 0; +} + +/* + * Block layer initialization function. + * + * This function is called once by the PCI layer for each P320 + * device that is connected to the system. + * + * @dd Pointer to the driver data structure. + * + * return value + * 0 on success else an error code. + */ +int mtip_block_initialize(struct driver_data *dd) +{ + int rv = 0; + sector_t capacity; + unsigned int index = 0; + struct kobject *kobj; + + /* Initialize the protocol layer. */ + rv = mtip_hw_init(dd); + if (rv < 0) { + dev_err(&dd->pdev->dev, + "Protocol layer initialization failed\n"); + rv = -EINVAL; + goto protocol_init_error; + } + + /* Allocate the request queue. */ + dd->queue = blk_alloc_queue(GFP_KERNEL); + if (dd->queue == NULL) { + dev_err(&dd->pdev->dev, + "Unable to allocate request queue\n"); + rv = -ENOMEM; + goto block_queue_alloc_init_error; + } + + /* Attach our request function to the request queue. */ + blk_queue_make_request(dd->queue, mtip_make_request); + + /* Set device limits. */ + set_bit(QUEUE_FLAG_NONROT, &dd->queue->queue_flags); + blk_queue_max_segments(dd->queue, MTIP_MAX_SG); + blk_queue_physical_block_size(dd->queue, 4096); + blk_queue_io_min(dd->queue, 4096); + + dd->disk = alloc_disk(MTIP_MAX_MINORS); + if (dd->disk == NULL) { + dev_err(&dd->pdev->dev, + "Unable to allocate gendisk structure\n"); + rv = -EINVAL; + goto alloc_disk_error; + } + + /* Generate the disk name, implemented same as in sd.c */ + do { + if (!ida_pre_get(&rssd_index_ida, GFP_KERNEL)) + goto ida_get_error; + + spin_lock(&rssd_index_lock); + rv = ida_get_new(&rssd_index_ida, &index); + spin_unlock(&rssd_index_lock); + } while (rv == -EAGAIN); + + if (rv) + goto ida_get_error; + + rv = rssd_disk_name_format("rssd", + index, + dd->disk->disk_name, + DISK_NAME_LEN); + if (rv) + goto disk_index_error; + + dd->disk->driverfs_dev = &dd->pdev->dev; + dd->disk->major = dd->major; + dd->disk->first_minor = dd->instance * MTIP_MAX_MINORS; + dd->disk->fops = &mtip_block_ops; + dd->disk->queue = dd->queue; + dd->disk->private_data = dd; + dd->queue->queuedata = dd; + dd->index = index; + + /* Set the capacity of the device in 512 byte sectors. */ + if (!(mtip_hw_get_capacity(dd, &capacity))) { + dev_warn(&dd->pdev->dev, + "Could not read drive capacity\n"); + rv = -EIO; + goto read_capacity_error; + } + set_capacity(dd->disk, capacity); + + /* Enable the block device and add it to /dev */ + add_disk(dd->disk); + + /* + * Now that the disk is active, initialize any sysfs attributes + * managed by the protocol layer. + */ + kobj = kobject_get(&disk_to_dev(dd->disk)->kobj); + if (kobj) { + mtip_hw_sysfs_init(dd, kobj); + kobject_put(kobj); + } + + return rv; + +read_capacity_error: + /* + * Delete our gendisk structure. This also removes the device + * from /dev + */ + del_gendisk(dd->disk); + +disk_index_error: + spin_lock(&rssd_index_lock); + ida_remove(&rssd_index_ida, index); + spin_unlock(&rssd_index_lock); + +ida_get_error: + put_disk(dd->disk); + +alloc_disk_error: + blk_cleanup_queue(dd->queue); + +block_queue_alloc_init_error: + /* De-initialize the protocol layer. */ + mtip_hw_exit(dd); + +protocol_init_error: + return rv; +} + +/* + * Block layer deinitialization function. + * + * Called by the PCI layer as each P320 device is removed. + * + * @dd Pointer to the driver data structure. + * + * return value + * 0 + */ +int mtip_block_remove(struct driver_data *dd) +{ + struct kobject *kobj; + /* Clean up the sysfs attributes managed by the protocol layer. */ + kobj = kobject_get(&disk_to_dev(dd->disk)->kobj); + if (kobj) { + mtip_hw_sysfs_exit(dd, kobj); + kobject_put(kobj); + } + + /* + * Delete our gendisk structure. This also removes the device + * from /dev + */ + del_gendisk(dd->disk); + blk_cleanup_queue(dd->queue); + dd->disk = NULL; + dd->queue = NULL; + + /* De-initialize the protocol layer. */ + mtip_hw_exit(dd); + + return 0; +} + +/* + * Function called by the PCI layer when just before the + * machine shuts down. + * + * If a protocol layer shutdown function is present it will be called + * by this function. + * + * @dd Pointer to the driver data structure. + * + * return value + * 0 + */ +int mtip_block_shutdown(struct driver_data *dd) +{ + dev_info(&dd->pdev->dev, + "Shutting down %s ...\n", dd->disk->disk_name); + + /* Delete our gendisk structure, and cleanup the blk queue. */ + del_gendisk(dd->disk); + blk_cleanup_queue(dd->queue); + dd->disk = NULL; + dd->queue = NULL; + + mtip_hw_shutdown(dd); + return 0; +} + +int mtip_block_suspend(struct driver_data *dd) +{ + dev_info(&dd->pdev->dev, + "Suspending %s ...\n", dd->disk->disk_name); + mtip_hw_suspend(dd); + return 0; +} + +int mtip_block_resume(struct driver_data *dd) +{ + dev_info(&dd->pdev->dev, "Resuming %s ...\n", + dd->disk->disk_name); + mtip_hw_resume(dd); + return 0; +} + +/* + * Called for each supported PCI device detected. + * + * This function allocates the private data structure, enables the + * PCI device and then calls the block layer initialization function. + * + * return value + * 0 on success else an error code. + */ +static int mtip_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int rv = 0; + struct driver_data *dd = NULL; + + /* Allocate memory for this devices private data. */ + dd = kzalloc(sizeof(struct driver_data), GFP_KERNEL); + if (dd == NULL) { + dev_err(&pdev->dev, + "Unable to allocate memory for driver data\n"); + return -ENOMEM; + } + + /* Set the atomic variable as 1 in case of SRSI */ + atomic_set(&dd->drv_cleanup_done, true); + + atomic_set(&dd->resumeflag, false); + atomic_set(&dd->eh_active, 0); + + /* Attach the private data to this PCI device. */ + pci_set_drvdata(pdev, dd); + + rv = pcim_enable_device(pdev); + if (rv < 0) { + dev_err(&pdev->dev, "Unable to enable device\n"); + goto iomap_err; + } + + /* Map BAR5 to memory. */ + rv = pcim_iomap_regions(pdev, 1 << MTIP_ABAR, MTIP_DRV_NAME); + if (rv < 0) { + dev_err(&pdev->dev, "Unable to map regions\n"); + goto iomap_err; + } + + if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { + rv = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + + if (rv) { + rv = pci_set_consistent_dma_mask(pdev, + DMA_BIT_MASK(32)); + if (rv) { + dev_warn(&pdev->dev, + "64-bit DMA enable failed\n"); + goto setmask_err; + } + } + } + + pci_set_master(pdev); + + if (pci_enable_msi(pdev)) { + dev_warn(&pdev->dev, + "Unable to enable MSI interrupt.\n"); + goto block_initialize_err; + } + + /* Copy the info we may need later into the private data structure. */ + dd->major = mtip_major; + dd->protocol = ent->driver_data; + dd->instance = instance; + dd->pdev = pdev; + + /* Initialize the block layer. */ + rv = mtip_block_initialize(dd); + if (rv < 0) { + dev_err(&pdev->dev, + "Unable to initialize block layer\n"); + goto block_initialize_err; + } + + /* + * Increment the instance count so that each device has a unique + * instance number. + */ + instance++; + + goto done; + +block_initialize_err: + pci_disable_msi(pdev); + +setmask_err: + pcim_iounmap_regions(pdev, 1 << MTIP_ABAR); + +iomap_err: + kfree(dd); + pci_set_drvdata(pdev, NULL); + return rv; +done: + /* Set the atomic variable as 0 in case of SRSI */ + atomic_set(&dd->drv_cleanup_done, true); + + return rv; +} + +/* + * Called for each probed device when the device is removed or the + * driver is unloaded. + * + * return value + * None + */ +static void mtip_pci_remove(struct pci_dev *pdev) +{ + struct driver_data *dd = pci_get_drvdata(pdev); + int counter = 0; + + if (mtip_check_surprise_removal(pdev)) { + while (atomic_read(&dd->drv_cleanup_done) == false) { + counter++; + msleep(20); + if (counter == 10) { + /* Cleanup the outstanding commands */ + mtip_command_cleanup(dd); + break; + } + } + } + /* Set the atomic variable as 1 in case of SRSI */ + atomic_set(&dd->drv_cleanup_done, true); + + /* Clean up the block layer. */ + mtip_block_remove(dd); + + pci_disable_msi(pdev); + + kfree(dd); + pcim_iounmap_regions(pdev, 1 << MTIP_ABAR); +} + +/* + * Called for each probed device when the device is suspended. + * + * return value + * 0 Success + * <0 Error + */ +static int mtip_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) +{ + int rv = 0; + struct driver_data *dd = pci_get_drvdata(pdev); + + if (!dd) { + dev_err(&pdev->dev, + "Driver private datastructure is NULL\n"); + return -EFAULT; + } + + atomic_set(&dd->resumeflag, true); + + /* Disable ports & interrupts then send standby immediate */ + rv = mtip_block_suspend(dd); + if (rv < 0) { + dev_err(&pdev->dev, + "Failed to suspend controller\n"); + return rv; + } + + /* + * Save the pci config space to pdev structure & + * disable the device + */ + pci_save_state(pdev); + pci_disable_device(pdev); + + /* Move to Low power state*/ + pci_set_power_state(pdev, PCI_D3hot); + + return rv; +} + +/* + * Called for each probed device when the device is resumed. + * + * return value + * 0 Success + * <0 Error + */ +static int mtip_pci_resume(struct pci_dev *pdev) +{ + int rv = 0; + struct driver_data *dd; + + dd = pci_get_drvdata(pdev); + if (!dd) { + dev_err(&pdev->dev, + "Driver private datastructure is NULL\n"); + return -EFAULT; + } + + /* Move the device to active State */ + pci_set_power_state(pdev, PCI_D0); + + /* Restore PCI configuration space */ + pci_restore_state(pdev); + + /* Enable the PCI device*/ + rv = pcim_enable_device(pdev); + if (rv < 0) { + dev_err(&pdev->dev, + "Failed to enable card during resume\n"); + goto err; + } + pci_set_master(pdev); + + /* + * Calls hbaReset, initPort, & startPort function + * then enables interrupts + */ + rv = mtip_block_resume(dd); + if (rv < 0) + dev_err(&pdev->dev, "Unable to resume\n"); + +err: + atomic_set(&dd->resumeflag, false); + + return rv; +} + +/* + * Shutdown routine + * + * return value + * None + */ +static void mtip_pci_shutdown(struct pci_dev *pdev) +{ + struct driver_data *dd = pci_get_drvdata(pdev); + if (dd) + mtip_block_shutdown(dd); +} + +/* + * This function check_for_surprise_removal is called + * while card is removed from the system and it will + * read the vendor id from the configration space + * + * @pdev Pointer to the pci_dev structure. + * + * return value + * true if device removed, else false + */ +bool mtip_check_surprise_removal(struct pci_dev *pdev) +{ + u16 vendor_id = 0; + + /* Read the vendorID from the configuration space */ + pci_read_config_word(pdev, 0x00, &vendor_id); + if (vendor_id == 0xFFFF) + return true; /* device removed */ + + return false; /* device present */ +} + +/* Table of device ids supported by this driver. */ +static DEFINE_PCI_DEVICE_TABLE(mtip_pci_tbl) = { + { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320_DEVICE_ID) }, + { 0 } +}; + +/* Structure that describes the PCI driver functions. */ +struct pci_driver mtip_pci_driver = { + .name = MTIP_DRV_NAME, + .id_table = mtip_pci_tbl, + .probe = mtip_pci_probe, + .remove = mtip_pci_remove, + .suspend = mtip_pci_suspend, + .resume = mtip_pci_resume, + .shutdown = mtip_pci_shutdown, +}; + +MODULE_DEVICE_TABLE(pci, mtip_pci_tbl); + +/* + * Module initialization function. + * + * Called once when the module is loaded. This function allocates a major + * block device number to the Cyclone devices and registers the PCI layer + * of the driver. + * + * Return value + * 0 on success else error code. + */ +static int __init mtip_init(void) +{ + printk(KERN_INFO MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n"); + + /* Allocate a major block device number to use with this driver. */ + mtip_major = register_blkdev(0, MTIP_DRV_NAME); + if (mtip_major < 0) { + printk(KERN_ERR "Unable to register block device (%d)\n", + mtip_major); + return -EBUSY; + } + + /* Register our PCI operations. */ + return pci_register_driver(&mtip_pci_driver); +} + +/* + * Module de-initialization function. + * + * Called once when the module is unloaded. This function deallocates + * the major block device number allocated by mtip_init() and + * unregisters the PCI layer of the driver. + * + * Return value + * none + */ +static void __exit mtip_exit(void) +{ + /* Release the allocated major block device number. */ + unregister_blkdev(mtip_major, MTIP_DRV_NAME); + + /* Unregister the PCI driver. */ + pci_unregister_driver(&mtip_pci_driver); +} + +MODULE_AUTHOR("Micron Technology, Inc"); +MODULE_DESCRIPTION("Micron RealSSD PCIe Block Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(MTIP_DRV_VERSION); + +module_init(mtip_init); +module_exit(mtip_exit); diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h new file mode 100644 index 0000000..3423d18 --- /dev/null +++ b/drivers/block/mtip32xx/mtip32xx.h @@ -0,0 +1,445 @@ +/* + * mtip32xx.h - Header file for the P320 SSD Block Driver + * Copyright (C) 2011 Micron Technology, Inc. + * + * Portions of this code were derived from works subjected to the + * following copyright: + * Copyright (C) 2009 Integrated Device Technology, Inc. + * + * 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. + * + */ + +#ifndef __MTIP32XX_H__ +#define __MTIP32XX_H__ + +#include +#include +#include +#include +#include +#include + +/* Offset of Subsystem Device ID in pci confoguration space */ +#define PCI_SUBSYSTEM_DEVICEID 0x2E + +/* offset of Device Control register in PCIe extended capabilites space */ +#define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET 0x48 + +/* # of times to retry timed out IOs */ +#define MTIP_MAX_RETRIES 5 + +/* Various timeout values in ms */ +#define MTIP_NCQ_COMMAND_TIMEOUT_MS 5000 +#define MTIP_IOCTL_COMMAND_TIMEOUT_MS 5000 +#define MTIP_INTERNAL_COMMAND_TIMEOUT_MS 5000 + +/* check for timeouts every 500ms */ +#define MTIP_TIMEOUT_CHECK_PERIOD 500 + +/* ftl rebuild */ +#define MTIP_FTL_REBUILD_OFFSET 142 +#define MTIP_FTL_REBUILD_MAGIC 0xed51 +#define MTIP_FTL_REBUILD_TIMEOUT_MS 2400000 + +/* Macro to extract the tag bit number from a tag value. */ +#define MTIP_TAG_BIT(tag) (tag & 0x1f) + +/* + * Macro to extract the tag index from a tag value. The index + * is used to access the correct s_active/Command Issue register based + * on the tag value. + */ +#define MTIP_TAG_INDEX(tag) (tag >> 5) + +/* + * Maximum number of scatter gather entries + * a single command may have. + */ +#define MTIP_MAX_SG 128 + +/* + * Maximum number of slot groups (Command Issue & s_active registers) + * NOTE: This is the driver maximum; check dd->slot_groups for actual value. + */ +#define MTIP_MAX_SLOT_GROUPS 8 + +/* Internal command tag. */ +#define MTIP_TAG_INTERNAL 0 + +/* Micron Vendor ID & P320x SSD Device ID */ +#define PCI_VENDOR_ID_MICRON 0x1344 +#define P320_DEVICE_ID 0x5150 + +/* Driver name and version strings */ +#define MTIP_DRV_NAME "mtip32xx" +#define MTIP_DRV_VERSION "1.2.6os2" + +/* Maximum number of minor device numbers per device. */ +#define MTIP_MAX_MINORS 16 + +/* Maximum number of supported command slots. */ +#define MTIP_MAX_COMMAND_SLOTS (MTIP_MAX_SLOT_GROUPS * 32) + +/* + * Per-tag bitfield size in longs. + * Linux bit manipulation functions + * (i.e. test_and_set_bit, find_next_zero_bit) + * manipulate memory in longs, so we try to make the math work. + * take the slot groups and find the number of longs, rounding up. + * Careful! i386 and x86_64 use different size longs! + */ +#define U32_PER_LONG (sizeof(long) / sizeof(u32)) +#define SLOTBITS_IN_LONGS ((MTIP_MAX_SLOT_GROUPS + \ + (U32_PER_LONG-1))/U32_PER_LONG) + +/* BAR number used to access the HBA registers. */ +#define MTIP_ABAR 5 + +/* Forced Unit Access Bit */ +#define FUA_BIT 0x80 + +#ifdef DEBUG + #define dbg_printk(format, arg...) \ + printk(pr_fmt(format), ##arg); +#else + #define dbg_printk(format, arg...) +#endif + +/* Register Frame Information Structure (FIS), host to device. */ +struct host_to_dev_fis { + /* + * FIS type. + * - 27h Register FIS, host to device. + * - 34h Register FIS, device to host. + * - 39h DMA Activate FIS, device to host. + * - 41h DMA Setup FIS, bi-directional. + * - 46h Data FIS, bi-directional. + * - 58h BIST Activate FIS, bi-directional. + * - 5Fh PIO Setup FIS, device to host. + * - A1h Set Device Bits FIS, device to host. + */ + unsigned char type; + unsigned char opts; + unsigned char command; + unsigned char features; + + union { + unsigned char lba_low; + unsigned char sector; + }; + union { + unsigned char lba_mid; + unsigned char cyl_low; + }; + union { + unsigned char lba_hi; + unsigned char cyl_hi; + }; + union { + unsigned char device; + unsigned char head; + }; + + union { + unsigned char lba_low_ex; + unsigned char sector_ex; + }; + union { + unsigned char lba_mid_ex; + unsigned char cyl_low_ex; + }; + union { + unsigned char lba_hi_ex; + unsigned char cyl_hi_ex; + }; + unsigned char features_ex; + + unsigned char sect_count; + unsigned char sect_cnt_ex; + unsigned char res2; + unsigned char control; + + unsigned int res3; +}; + +/* Command header structure. */ +struct mtip_cmd_hdr { + /* + * Command options. + * - Bits 31:16 Number of PRD entries. + * - Bits 15:8 Unused in this implementation. + * - Bit 7 Prefetch bit, informs the drive to prefetch PRD entries. + * - Bit 6 Write bit, should be set when writing data to the device. + * - Bit 5 Unused in this implementation. + * - Bits 4:0 Length of the command FIS in DWords (DWord = 4 bytes). + */ + unsigned int opts; + /* This field is unsed when using NCQ. */ + union { + unsigned int byte_count; + unsigned int status; + }; + /* + * Lower 32 bits of the command table address associated with this + * header. The command table addresses must be 128 byte aligned. + */ + unsigned int ctba; + /* + * If 64 bit addressing is used this field is the upper 32 bits + * of the command table address associated with this command. + */ + unsigned int ctbau; + /* Reserved and unused. */ + unsigned int res[4]; +}; + +/* Command scatter gather structure (PRD). */ +struct mtip_cmd_sg { + /* + * Low 32 bits of the data buffer address. For P320 this + * address must be 8 byte aligned signified by bits 2:0 being + * set to 0. + */ + unsigned int dba; + /* + * When 64 bit addressing is used this field is the upper + * 32 bits of the data buffer address. + */ + unsigned int dba_upper; + /* Unused. */ + unsigned int reserved; + /* + * Bit 31: interrupt when this data block has been transferred. + * Bits 30..22: reserved + * Bits 21..0: byte count (minus 1). For P320 the byte count must be + * 8 byte aligned signified by bits 2:0 being set to 1. + */ + unsigned int info; +}; +struct mtip_port; + +/* Structure used to describe a command. */ +struct mtip_cmd { + + struct mtip_cmd_hdr *command_header; /* ptr to command header entry */ + + dma_addr_t command_header_dma; /* corresponding physical address */ + + void *command; /* ptr to command table entry */ + + dma_addr_t command_dma; /* corresponding physical address */ + + void *comp_data; /* data passed to completion function comp_func() */ + /* + * Completion function called by the ISR upon completion of + * a command. + */ + void (*comp_func)(struct mtip_port *port, + int tag, + void *data, + int status); + /* Additional callback function that may be called by comp_func() */ + void (*async_callback)(void *data, int status); + + void *async_data; /* Addl. data passed to async_callback() */ + + int scatter_ents; /* Number of scatter list entries used */ + + struct scatterlist sg[MTIP_MAX_SG]; /* Scatter list entries */ + + int retries; /* The number of retries left for this command. */ + + int direction; /* Data transfer direction */ + + unsigned long comp_time; /* command completion time, in jiffies */ + + atomic_t active; /* declares if this command sent to the drive. */ +}; + +/* Structure used to describe a port. */ +struct mtip_port { + /* Pointer back to the driver data for this port. */ + struct driver_data *dd; + /* + * Used to determine if the data pointed to by the + * identify field is valid. + */ + unsigned long identify_valid; + /* Base address of the memory mapped IO for the port. */ + void __iomem *mmio; + /* Array of pointers to the memory mapped s_active registers. */ + void __iomem *s_active[MTIP_MAX_SLOT_GROUPS]; + /* Array of pointers to the memory mapped completed registers. */ + void __iomem *completed[MTIP_MAX_SLOT_GROUPS]; + /* Array of pointers to the memory mapped Command Issue registers. */ + void __iomem *cmd_issue[MTIP_MAX_SLOT_GROUPS]; + /* + * Pointer to the beginning of the command header memory as used + * by the driver. + */ + void *command_list; + /* + * Pointer to the beginning of the command header memory as used + * by the DMA. + */ + dma_addr_t command_list_dma; + /* + * Pointer to the beginning of the RX FIS memory as used + * by the driver. + */ + void *rxfis; + /* + * Pointer to the beginning of the RX FIS memory as used + * by the DMA. + */ + dma_addr_t rxfis_dma; + /* + * Pointer to the beginning of the command table memory as used + * by the driver. + */ + void *command_table; + /* + * Pointer to the beginning of the command table memory as used + * by the DMA. + */ + dma_addr_t command_tbl_dma; + /* + * Pointer to the beginning of the identify data memory as used + * by the driver. + */ + u16 *identify; + /* + * Pointer to the beginning of the identify data memory as used + * by the DMA. + */ + dma_addr_t identify_dma; + /* + * Pointer to the beginning of a sector buffer that is used + * by the driver when issuing internal commands. + */ + u16 *sector_buffer; + /* + * Pointer to the beginning of a sector buffer that is used + * by the DMA when the driver issues internal commands. + */ + dma_addr_t sector_buffer_dma; + /* + * Bit significant, used to determine if a command slot has + * been allocated. i.e. the slot is in use. Bits are cleared + * when the command slot and all associated data structures + * are no longer needed. + */ + unsigned long allocated[SLOTBITS_IN_LONGS]; + /* + * Array of command slots. Structure includes pointers to the + * command header and command table, and completion function and data + * pointers. + */ + struct mtip_cmd commands[MTIP_MAX_COMMAND_SLOTS]; + /* Non-zero if an internal command is in progress. */ + int internal_cmd_in_progress; + /* + * Timer used to complete commands that have been active for too long. + */ + struct timer_list cmd_timer; + /* + * Semaphore used to block threads if there are no + * command slots available. + */ + struct semaphore cmd_slot; + /* Spinlock for working around command-issue bug. */ + spinlock_t cmd_issue_lock; +}; + +/* + * Driver private data structure. + * + * One structure is allocated per probed device. + */ +struct driver_data { + void __iomem *mmio; /* Base address of the HBA registers. */ + + int major; /* Major device number. */ + + int instance; /* Instance number. First device probed is 0, ... */ + + int protocol; /* FIXME: Protocol ops array index. */ + + struct gendisk *disk; /* Pointer to our gendisk structure. */ + + struct pci_dev *pdev; /* Pointer to the PCI device structure. */ + + struct request_queue *queue; /* Our request queue. */ + /* + * Semaphore used to lock out read/write commands during the + * execution of an internal command. + */ + struct rw_semaphore internal_sem; + + struct mtip_port *port; /* Pointer to the port data structure. */ + + /* Tasklet used to process the bottom half of the ISR. */ + struct tasklet_struct tasklet; + + unsigned product_type; /* magic value declaring the product type */ + + unsigned slot_groups; /* number of slot groups the product supports */ + + atomic_t drv_cleanup_done; /* Atomic variable for SRSI */ + + unsigned long index; /* Index to determine the disk name */ + + unsigned int ftlrebuildflag; /* FTL rebuild flag */ + + atomic_t resumeflag; /* Atomic variable to track suspend/resume */ + + atomic_t eh_active; /* Flag for error handling tracking */ +}; + +/* Function declarations */ +extern int mtip_block_initialize(struct driver_data *dd); +extern int mtip_block_remove(struct driver_data *dd); +extern int mtip_block_shutdown(struct driver_data *dd); +extern int mtip_block_suspend(struct driver_data *dd); +extern int mtip_block_resume(struct driver_data *dd); +extern int mtip_hw_init(struct driver_data *dd); +extern int mtip_hw_exit(struct driver_data *dd); +extern int mtip_hw_shutdown(struct driver_data *dd); +extern bool mtip_hw_get_capacity(struct driver_data *dd, sector_t *sectors); +extern void mtip_hw_release_scatterlist( + struct driver_data *dd, + int tag); +extern struct scatterlist *mtip_hw_get_scatterlist( + struct driver_data *dd, + int *tag); +extern void mtip_hw_submit_io(struct driver_data *dd, + sector_t start, + int nsect, + int nents, + int tag, + void *callback, + void *data, + int barrier, + int dir); +extern int mtip_hw_ioctl(struct driver_data *dd, + unsigned int cmd, + unsigned long arg, + unsigned char compat); +extern int mtip_hw_sysfs_init(struct driver_data *dd, struct kobject *kobj); +extern int mtip_hw_sysfs_exit(struct driver_data *dd, struct kobject *kobj); +extern int mtip_hw_resume(struct driver_data *dd); +extern int mtip_hw_suspend(struct driver_data *dd); +void mtip_command_cleanup(struct driver_data *dd); +bool mtip_check_surprise_removal(struct pci_dev *pdev); +void mtip_restart_port(struct mtip_port *port); + +#endif -- cgit v0.10.2 From 16d02c040bb6769068f7c4b54ea8542f14237362 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 27 Sep 2011 15:50:01 -0600 Subject: mtip32xx: fix warnings/errors on 32-bit compiles We need to clean up the compat ioctl handling, but this makes it work for now at least. Signed-off-by: Jens Axboe diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 847b8ff..1cf2b04 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -85,6 +85,7 @@ int mtip_major; static DEFINE_SPINLOCK(rssd_index_lock); static DEFINE_IDA(rssd_index_ida); +#ifdef CONFIG_COMPAT struct mtip_compat_ide_task_request_s { __u8 io_ports[8]; __u8 hob_ports[8]; @@ -95,6 +96,7 @@ struct mtip_compat_ide_task_request_s { compat_ulong_t out_size; compat_ulong_t in_size; }; +#endif static int mtip_exec_internal_command(struct mtip_port *port, void *fis, @@ -1628,9 +1630,9 @@ static int exec_drive_taskfile(struct driver_data *dd, ide_task_request_t *req_task; u8 *outbuf = NULL; u8 *inbuf = NULL; - dma_addr_t outbuf_dma = (dma_addr_t)NULL; - dma_addr_t inbuf_dma = (dma_addr_t)NULL; - dma_addr_t dma_buffer = (dma_addr_t)NULL; + dma_addr_t outbuf_dma = 0; + dma_addr_t inbuf_dma = 0; + dma_addr_t dma_buffer = 0; int err = 0; int tasksize = sizeof(struct ide_task_request_s); unsigned int taskin = 0; @@ -1642,14 +1644,18 @@ static int exec_drive_taskfile(struct driver_data *dd, unsigned int transfer_size; unsigned long task_file_data; int intotal, outtotal; +#ifdef CONFIG_COMPAT struct mtip_compat_ide_task_request_s *compat_req_task = NULL; int compat_tasksize = sizeof(struct mtip_compat_ide_task_request_s); +#endif + req_task = kzalloc(tasksize, GFP_KERNEL); if (req_task == NULL) return -ENOMEM; if (compat == 1) { +#ifdef CONFIG_COMPAT compat_req_task = (struct mtip_compat_ide_task_request_s __user *) arg; @@ -1672,6 +1678,10 @@ static int exec_drive_taskfile(struct driver_data *dd, outtotal = compat_tasksize; intotal = compat_tasksize + req_task->out_size; +#else + outtotal = 0; + intotal = 0; +#endif } else { if (copy_from_user(req_task, buf, tasksize)) { kfree(req_task); @@ -1705,7 +1715,7 @@ static int exec_drive_taskfile(struct driver_data *dd, outbuf, taskout, DMA_TO_DEVICE); - if (outbuf_dma == (dma_addr_t)NULL) { + if (outbuf_dma == 0) { err = -ENOMEM; goto abort; } @@ -1726,7 +1736,7 @@ static int exec_drive_taskfile(struct driver_data *dd, inbuf_dma = pci_map_single(dd->pdev, inbuf, taskin, DMA_FROM_DEVICE); - if (inbuf_dma == (dma_addr_t)NULL) { + if (inbuf_dma == 0) { err = -ENOMEM; goto abort; } @@ -1868,8 +1878,8 @@ static int exec_drive_taskfile(struct driver_data *dd, if (outbuf_dma) pci_unmap_single(dd->pdev, outbuf_dma, taskout, DMA_TO_DEVICE); - inbuf_dma = (dma_addr_t) NULL; - outbuf_dma = (dma_addr_t) NULL; + inbuf_dma = 0; + outbuf_dma = 0; /* return the ATA registers to the caller.*/ req_task->io_ports[1] = reply->features; @@ -1913,6 +1923,7 @@ static int exec_drive_taskfile(struct driver_data *dd, up_write(&dd->internal_sem); if (compat == 1) { +#ifdef CONFIG_COMPAT if (copy_to_user(buf, req_task, compat_tasksize - (2 * sizeof(compat_long_t)))) { @@ -1928,6 +1939,7 @@ static int exec_drive_taskfile(struct driver_data *dd, err = -EFAULT; goto abort; } +#endif } else { if (copy_to_user(buf, req_task, tasksize)) { err = -EFAULT; @@ -2873,6 +2885,7 @@ static int mtip_block_ioctl(struct block_device *dev, } } +#ifdef CONFIG_COMPAT /* * Block layer compat IOCTL handler. * @@ -2906,6 +2919,7 @@ static int mtip_block_compat_ioctl(struct block_device *dev, return mtip_hw_ioctl(dd, cmd, arg, 1); } } +#endif /* * Obtain the geometry of the device. @@ -2959,7 +2973,9 @@ static int mtip_block_getgeo(struct block_device *dev, */ static const struct block_device_operations mtip_block_ops = { .ioctl = mtip_block_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = mtip_block_compat_ioctl, +#endif .getgeo = mtip_block_getgeo, .owner = THIS_MODULE }; -- cgit v0.10.2 From ef0f1587343a4c17b9b0d9061546e36c1c1bb2ec Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 27 Sep 2011 21:19:53 -0600 Subject: mtip32xx: cleanup compat ioctl handling Do the conversion/copy up front instead of passing in a compat flag to the ioctl handler and subsequently to the exec_drive_taskfile() function. Signed-off-by: Jens Axboe diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 1cf2b04..d58581b 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -1622,76 +1622,26 @@ static unsigned int implicit_sector(unsigned char command, * See ide_taskfile_ioctl() for derivation */ static int exec_drive_taskfile(struct driver_data *dd, - unsigned long arg, - unsigned char compat) + void __user *buf, + ide_task_request_t *req_task, + int outtotal) { struct host_to_dev_fis fis; struct host_to_dev_fis *reply; - ide_task_request_t *req_task; u8 *outbuf = NULL; u8 *inbuf = NULL; dma_addr_t outbuf_dma = 0; dma_addr_t inbuf_dma = 0; dma_addr_t dma_buffer = 0; int err = 0; - int tasksize = sizeof(struct ide_task_request_s); unsigned int taskin = 0; unsigned int taskout = 0; u8 nsect = 0; - char __user *buf = (char __user *)arg; unsigned int timeout = MTIP_IOCTL_COMMAND_TIMEOUT_MS; unsigned int force_single_sector; unsigned int transfer_size; unsigned long task_file_data; - int intotal, outtotal; -#ifdef CONFIG_COMPAT - struct mtip_compat_ide_task_request_s *compat_req_task = NULL; - int compat_tasksize = sizeof(struct mtip_compat_ide_task_request_s); -#endif - - - req_task = kzalloc(tasksize, GFP_KERNEL); - if (req_task == NULL) - return -ENOMEM; - - if (compat == 1) { -#ifdef CONFIG_COMPAT - compat_req_task = - (struct mtip_compat_ide_task_request_s __user *) arg; - - if (copy_from_user(req_task, buf, - compat_tasksize - - (2 * sizeof(compat_long_t)))) { - err = -EFAULT; - goto abort; - } - - if (get_user(req_task->out_size, &compat_req_task->out_size)) { - err = -EFAULT; - goto abort; - } - - if (get_user(req_task->in_size, &compat_req_task->in_size)) { - err = -EFAULT; - goto abort; - } - - outtotal = compat_tasksize; - intotal = compat_tasksize + req_task->out_size; -#else - outtotal = 0; - intotal = 0; -#endif - } else { - if (copy_from_user(req_task, buf, tasksize)) { - kfree(req_task); - err = -EFAULT; - goto abort; - } - - outtotal = tasksize; - intotal = tasksize + req_task->out_size; - } + int intotal = outtotal + req_task->out_size; taskout = req_task->out_size; taskin = req_task->in_size; @@ -1922,30 +1872,6 @@ static int exec_drive_taskfile(struct driver_data *dd, up_write(&dd->internal_sem); - if (compat == 1) { -#ifdef CONFIG_COMPAT - if (copy_to_user(buf, req_task, - compat_tasksize - - (2 * sizeof(compat_long_t)))) { - err = -EFAULT; - goto abort; - } - if (put_user(req_task->out_size, - &compat_req_task->out_size)) { - err = -EFAULT; - goto abort; - } - if (put_user(req_task->in_size, &compat_req_task->in_size)) { - err = -EFAULT; - goto abort; - } -#endif - } else { - if (copy_to_user(buf, req_task, tasksize)) { - err = -EFAULT; - goto abort; - } - } if (taskout) { if (copy_to_user(buf + outtotal, outbuf, taskout)) { err = -EFAULT; @@ -1965,7 +1891,6 @@ abort: if (outbuf_dma) pci_unmap_single(dd->pdev, outbuf_dma, taskout, DMA_TO_DEVICE); - kfree(req_task); kfree(outbuf); kfree(inbuf); @@ -1989,10 +1914,8 @@ abort: * -EFAULT An error occurred copying data to a user space buffer. * -EIO An error occurred while executing the command. */ -int mtip_hw_ioctl(struct driver_data *dd, - unsigned int cmd, - unsigned long arg, - unsigned char compat) +static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd, + unsigned long arg) { switch (cmd) { case HDIO_GET_IDENTITY: @@ -2049,8 +1972,24 @@ int mtip_hw_ioctl(struct driver_data *dd, break; } - case HDIO_DRIVE_TASKFILE: - return exec_drive_taskfile(dd, arg, compat); + case HDIO_DRIVE_TASKFILE: { + ide_task_request_t req_task; + int ret, outtotal; + + if (copy_from_user(&req_task, (void __user *) arg, + sizeof(req_task))) + return -EFAULT; + + outtotal = sizeof(req_task); + + ret = exec_drive_taskfile(dd, (void __user *) arg, + &req_task, outtotal); + + if (copy_to_user((void __user *) arg, &req_task, sizeof(req_task))) + return -EFAULT; + + return ret; + } default: return -EINVAL; @@ -2881,7 +2820,7 @@ static int mtip_block_ioctl(struct block_device *dev, case BLKFLSBUF: return 0; default: - return mtip_hw_ioctl(dd, cmd, arg, 0); + return mtip_hw_ioctl(dd, cmd, arg); } } @@ -2915,8 +2854,46 @@ static int mtip_block_compat_ioctl(struct block_device *dev, switch (cmd) { case BLKFLSBUF: return 0; + case HDIO_DRIVE_TASKFILE: { + struct mtip_compat_ide_task_request_s *compat_req_task; + ide_task_request_t req_task; + int compat_tasksize, outtotal, ret; + + compat_tasksize = sizeof(struct mtip_compat_ide_task_request_s); + + compat_req_task = + (struct mtip_compat_ide_task_request_s __user *) arg; + + if (copy_from_user(&req_task, (void __user *) arg, + compat_tasksize - (2 * sizeof(compat_long_t)))) + return -EFAULT; + + if (get_user(req_task.out_size, &compat_req_task->out_size)) + return -EFAULT; + + if (get_user(req_task.in_size, &compat_req_task->in_size)) + return -EFAULT; + + outtotal = sizeof(struct mtip_compat_ide_task_request_s); + + ret = exec_drive_taskfile(dd, (void __user *) arg, + &req_task, outtotal); + + if (copy_to_user((void __user *) arg, &req_task, + compat_tasksize - + (2 * sizeof(compat_long_t)))) + return -EFAULT; + + if (put_user(req_task.out_size, &compat_req_task->out_size)) + return -EFAULT; + + if (put_user(req_task.in_size, &compat_req_task->in_size)) + return -EFAULT; + + return ret; + } default: - return mtip_hw_ioctl(dd, cmd, arg, 1); + return mtip_hw_ioctl(dd, cmd, arg); } } #endif diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index 3423d18..d6355c6 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h @@ -430,10 +430,6 @@ extern void mtip_hw_submit_io(struct driver_data *dd, void *data, int barrier, int dir); -extern int mtip_hw_ioctl(struct driver_data *dd, - unsigned int cmd, - unsigned long arg, - unsigned char compat); extern int mtip_hw_sysfs_init(struct driver_data *dd, struct kobject *kobj); extern int mtip_hw_sysfs_exit(struct driver_data *dd, struct kobject *kobj); extern int mtip_hw_resume(struct driver_data *dd); -- cgit v0.10.2 From 6316668fbcf8a0a166830e7e84cdbdf0ab9392c8 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 27 Sep 2011 21:27:43 -0600 Subject: mtip32xx: ensure that all local functions are static Kill the declarations in the header file and mark them as static. Reshuffle a few functions to ensure that everything is properly declared before being used. Signed-off-by: Jens Axboe diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index d58581b..40d840e 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -108,6 +108,72 @@ static int mtip_exec_internal_command(struct mtip_port *port, unsigned long timeout); /* + * This function check_for_surprise_removal is called + * while card is removed from the system and it will + * read the vendor id from the configration space + * + * @pdev Pointer to the pci_dev structure. + * + * return value + * true if device removed, else false + */ +static bool mtip_check_surprise_removal(struct pci_dev *pdev) +{ + u16 vendor_id = 0; + + /* Read the vendorID from the configuration space */ + pci_read_config_word(pdev, 0x00, &vendor_id); + if (vendor_id == 0xFFFF) + return true; /* device removed */ + + return false; /* device present */ +} + +/* + * This function is called for clean the pending command in the + * command slot during the surprise removal of device and return + * error to the upper layer. + * + * @dd Pointer to the DRIVER_DATA structure. + * + * return value + * None + */ +static void mtip_command_cleanup(struct driver_data *dd) +{ + int group = 0, commandslot = 0, commandindex = 0; + struct mtip_cmd *command; + struct mtip_port *port = dd->port; + + for (group = 0; group < 4; group++) { + for (commandslot = 0; commandslot < 32; commandslot++) { + if (!(port->allocated[group] & (1 << commandslot))) + continue; + + commandindex = group << 5 | commandslot; + command = &port->commands[commandindex]; + + if (atomic_read(&command->active) + && (command->async_callback)) { + command->async_callback(command->async_data, + -ENODEV); + command->async_callback = NULL; + command->async_data = NULL; + } + + dma_unmap_sg(&port->dd->pdev->dev, + command->sg, + command->scatter_ents, + command->direction); + } + } + + up(&port->cmd_slot); + + atomic_set(&dd->drv_cleanup_done, true); +} + +/* * Obtain an empty command slot. * * This function needs to be reentrant since it could be called @@ -167,214 +233,72 @@ static inline void release_slot(struct mtip_port *port, int tag) } /* - * Issue a command to the hardware. - * - * Set the appropriate bit in the s_active and Command Issue hardware - * registers, causing hardware command processing to begin. - * - * @port Pointer to the port structure. - * @tag The tag of the command to be issued. + * Reset the HBA (without sleeping) * - * return value - * None - */ -static inline void mtip_issue_ncq_command(struct mtip_port *port, int tag) -{ - unsigned long flags = 0; - - atomic_set(&port->commands[tag].active, 1); - - spin_lock_irqsave(&port->cmd_issue_lock, flags); - - writel((1 << MTIP_TAG_BIT(tag)), - port->s_active[MTIP_TAG_INDEX(tag)]); - writel((1 << MTIP_TAG_BIT(tag)), - port->cmd_issue[MTIP_TAG_INDEX(tag)]); - - spin_unlock_irqrestore(&port->cmd_issue_lock, flags); -} - -/* - * Called periodically to see if any read/write commands are - * taking too long to complete. + * Just like hba_reset, except does not call sleep, so can be + * run from interrupt/tasklet context. * - * @data Pointer to the PORT data structure. + * @dd Pointer to the driver data structure. * * return value - * None + * 0 The reset was successful. + * -1 The HBA Reset bit did not clear. */ -void mtip_timeout_function(unsigned long int data) +static int hba_reset_nosleep(struct driver_data *dd) { - struct mtip_port *port = (struct mtip_port *) data; - struct host_to_dev_fis *fis; - struct mtip_cmd *command; - int tag, cmdto_cnt = 0; - unsigned int bit, group; - unsigned int num_command_slots = port->dd->slot_groups * 32; - - if (unlikely(!port)) - return; - - if (atomic_read(&port->dd->resumeflag) == true) { - mod_timer(&port->cmd_timer, - jiffies + msecs_to_jiffies(30000)); - return; - } - - for (tag = 0; tag < num_command_slots; tag++) { - /* - * Skip internal command slot as it has - * its own timeout mechanism - */ - if (tag == MTIP_TAG_INTERNAL) - continue; - - if (atomic_read(&port->commands[tag].active) && - (time_after(jiffies, port->commands[tag].comp_time))) { - group = tag >> 5; - bit = tag & 0x1f; - - command = &port->commands[tag]; - fis = (struct host_to_dev_fis *) command->command; - - dev_warn(&port->dd->pdev->dev, - "Timeout for command tag %d\n", tag); - - cmdto_cnt++; - if (cmdto_cnt == 1) - atomic_inc(&port->dd->eh_active); - - /* - * Clear the completed bit. This should prevent - * any interrupt handlers from trying to retire - * the command. - */ - writel(1 << bit, port->completed[group]); + unsigned long timeout; - /* Call the async completion callback. */ - if (likely(command->async_callback)) - command->async_callback(command->async_data, - -EIO); - command->async_callback = NULL; - command->comp_func = NULL; + /* Chip quirk: quiesce any chip function */ + mdelay(10); - /* Unmap the DMA scatter list entries */ - dma_unmap_sg(&port->dd->pdev->dev, - command->sg, - command->scatter_ents, - command->direction); + /* Set the reset bit */ + writel(HOST_RESET, dd->mmio + HOST_CTL); - /* - * Clear the allocated bit and active tag for the - * command. - */ - atomic_set(&port->commands[tag].active, 0); - release_slot(port, tag); + /* Flush */ + readl(dd->mmio + HOST_CTL); - up(&port->cmd_slot); - } - } + /* + * Wait 10ms then spin for up to 1 second + * waiting for reset acknowledgement + */ + timeout = jiffies + msecs_to_jiffies(1000); + mdelay(10); + while ((readl(dd->mmio + HOST_CTL) & HOST_RESET) + && time_before(jiffies, timeout)) + mdelay(1); - if (cmdto_cnt) { - dev_warn(&port->dd->pdev->dev, - "%d commands timed out: restarting port", - cmdto_cnt); - mtip_restart_port(port); - atomic_dec(&port->dd->eh_active); - } + if (readl(dd->mmio + HOST_CTL) & HOST_RESET) + return -1; - /* Restart the timer */ - mod_timer(&port->cmd_timer, - jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD)); + return 0; } /* - * IO completion function. + * Issue a command to the hardware. * - * This completion function is called by the driver ISR when a - * command that was issued by the kernel completes. It first calls the - * asynchronous completion function which normally calls back into the block - * layer passing the asynchronous callback data, then unmaps the - * scatter list associated with the completed command, and finally - * clears the allocated bit associated with the completed command. + * Set the appropriate bit in the s_active and Command Issue hardware + * registers, causing hardware command processing to begin. * - * @port Pointer to the port data structure. - * @tag Tag of the command. - * @data Pointer to driver_data. - * @status Completion status. + * @port Pointer to the port structure. + * @tag The tag of the command to be issued. * * return value - * None + * None */ -static void mtip_async_complete(struct mtip_port *port, - int tag, - void *data, - int status) +static inline void mtip_issue_ncq_command(struct mtip_port *port, int tag) { - struct mtip_cmd *command; - struct driver_data *dd = data; - int cb_status = status ? -EIO : 0; - - if (unlikely(!dd) || unlikely(!port)) - return; - - command = &port->commands[tag]; - - if (unlikely(status == PORT_IRQ_TF_ERR)) { - dev_warn(&port->dd->pdev->dev, - "Command tag %d failed due to TFE\n", tag); - } - - /* Upper layer callback */ - if (likely(command->async_callback)) - command->async_callback(command->async_data, cb_status); - - command->async_callback = NULL; - command->comp_func = NULL; - - /* Unmap the DMA scatter list entries */ - dma_unmap_sg(&dd->pdev->dev, - command->sg, - command->scatter_ents, - command->direction); - - /* Clear the allocated and active bits for the command */ - atomic_set(&port->commands[tag].active, 0); - release_slot(port, tag); + unsigned long flags = 0; - up(&port->cmd_slot); -} + atomic_set(&port->commands[tag].active, 1); -/* - * Internal command completion callback function. - * - * This function is normally called by the driver ISR when an internal - * command completed. This function signals the command completion by - * calling complete(). - * - * @port Pointer to the port data structure. - * @tag Tag of the command that has completed. - * @data Pointer to a completion structure. - * @status Completion status. - * - * return value - * None - */ -static void mtip_completion(struct mtip_port *port, - int tag, - void *data, - int status) -{ - struct mtip_cmd *command = &port->commands[tag]; - struct completion *waiting = data; - if (unlikely(status == PORT_IRQ_TF_ERR)) - dev_warn(&port->dd->pdev->dev, - "Internal command %d completed with TFE\n", tag); + spin_lock_irqsave(&port->cmd_issue_lock, flags); - command->async_callback = NULL; - command->comp_func = NULL; + writel((1 << MTIP_TAG_BIT(tag)), + port->s_active[MTIP_TAG_INDEX(tag)]); + writel((1 << MTIP_TAG_BIT(tag)), + port->cmd_issue[MTIP_TAG_INDEX(tag)]); - complete(waiting); + spin_unlock_irqrestore(&port->cmd_issue_lock, flags); } /* @@ -496,56 +420,15 @@ static void mtip_init_port(struct mtip_port *port) /* Clear SError */ writel(readl(port->mmio + PORT_SCR_ERR), port->mmio + PORT_SCR_ERR); - /* reset the completed registers.*/ - for (i = 0; i < port->dd->slot_groups; i++) - writel(0xFFFFFFFF, port->completed[i]); - - /* Clear any pending interrupts for this port */ - writel(readl(port->mmio + PORT_IRQ_STAT), port->mmio + PORT_IRQ_STAT); - - /* Enable port interrupts */ - writel(DEF_PORT_IRQ, port->mmio + PORT_IRQ_MASK); -} - -/* - * Reset the HBA (without sleeping) - * - * Just like hba_reset, except does not call sleep, so can be - * run from interrupt/tasklet context. - * - * @dd Pointer to the driver data structure. - * - * return value - * 0 The reset was successful. - * -1 The HBA Reset bit did not clear. - */ -int hba_reset_nosleep(struct driver_data *dd) -{ - unsigned long timeout; - - /* Chip quirk: quiesce any chip function */ - mdelay(10); - - /* Set the reset bit */ - writel(HOST_RESET, dd->mmio + HOST_CTL); - - /* Flush */ - readl(dd->mmio + HOST_CTL); - - /* - * Wait 10ms then spin for up to 1 second - * waiting for reset acknowledgement - */ - timeout = jiffies + msecs_to_jiffies(1000); - mdelay(10); - while ((readl(dd->mmio + HOST_CTL) & HOST_RESET) - && time_before(jiffies, timeout)) - mdelay(1); + /* reset the completed registers.*/ + for (i = 0; i < port->dd->slot_groups; i++) + writel(0xFFFFFFFF, port->completed[i]); - if (readl(dd->mmio + HOST_CTL) & HOST_RESET) - return -1; + /* Clear any pending interrupts for this port */ + writel(readl(port->mmio + PORT_IRQ_STAT), port->mmio + PORT_IRQ_STAT); - return 0; + /* Enable port interrupts */ + writel(DEF_PORT_IRQ, port->mmio + PORT_IRQ_MASK); } /* @@ -556,7 +439,7 @@ int hba_reset_nosleep(struct driver_data *dd) * return value * None */ -void mtip_restart_port(struct mtip_port *port) +static void mtip_restart_port(struct mtip_port *port) { unsigned long timeout; @@ -620,6 +503,189 @@ void mtip_restart_port(struct mtip_port *port) } /* + * Called periodically to see if any read/write commands are + * taking too long to complete. + * + * @data Pointer to the PORT data structure. + * + * return value + * None + */ +static void mtip_timeout_function(unsigned long int data) +{ + struct mtip_port *port = (struct mtip_port *) data; + struct host_to_dev_fis *fis; + struct mtip_cmd *command; + int tag, cmdto_cnt = 0; + unsigned int bit, group; + unsigned int num_command_slots = port->dd->slot_groups * 32; + + if (unlikely(!port)) + return; + + if (atomic_read(&port->dd->resumeflag) == true) { + mod_timer(&port->cmd_timer, + jiffies + msecs_to_jiffies(30000)); + return; + } + + for (tag = 0; tag < num_command_slots; tag++) { + /* + * Skip internal command slot as it has + * its own timeout mechanism + */ + if (tag == MTIP_TAG_INTERNAL) + continue; + + if (atomic_read(&port->commands[tag].active) && + (time_after(jiffies, port->commands[tag].comp_time))) { + group = tag >> 5; + bit = tag & 0x1f; + + command = &port->commands[tag]; + fis = (struct host_to_dev_fis *) command->command; + + dev_warn(&port->dd->pdev->dev, + "Timeout for command tag %d\n", tag); + + cmdto_cnt++; + if (cmdto_cnt == 1) + atomic_inc(&port->dd->eh_active); + + /* + * Clear the completed bit. This should prevent + * any interrupt handlers from trying to retire + * the command. + */ + writel(1 << bit, port->completed[group]); + + /* Call the async completion callback. */ + if (likely(command->async_callback)) + command->async_callback(command->async_data, + -EIO); + command->async_callback = NULL; + command->comp_func = NULL; + + /* Unmap the DMA scatter list entries */ + dma_unmap_sg(&port->dd->pdev->dev, + command->sg, + command->scatter_ents, + command->direction); + + /* + * Clear the allocated bit and active tag for the + * command. + */ + atomic_set(&port->commands[tag].active, 0); + release_slot(port, tag); + + up(&port->cmd_slot); + } + } + + if (cmdto_cnt) { + dev_warn(&port->dd->pdev->dev, + "%d commands timed out: restarting port", + cmdto_cnt); + mtip_restart_port(port); + atomic_dec(&port->dd->eh_active); + } + + /* Restart the timer */ + mod_timer(&port->cmd_timer, + jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD)); +} + +/* + * IO completion function. + * + * This completion function is called by the driver ISR when a + * command that was issued by the kernel completes. It first calls the + * asynchronous completion function which normally calls back into the block + * layer passing the asynchronous callback data, then unmaps the + * scatter list associated with the completed command, and finally + * clears the allocated bit associated with the completed command. + * + * @port Pointer to the port data structure. + * @tag Tag of the command. + * @data Pointer to driver_data. + * @status Completion status. + * + * return value + * None + */ +static void mtip_async_complete(struct mtip_port *port, + int tag, + void *data, + int status) +{ + struct mtip_cmd *command; + struct driver_data *dd = data; + int cb_status = status ? -EIO : 0; + + if (unlikely(!dd) || unlikely(!port)) + return; + + command = &port->commands[tag]; + + if (unlikely(status == PORT_IRQ_TF_ERR)) { + dev_warn(&port->dd->pdev->dev, + "Command tag %d failed due to TFE\n", tag); + } + + /* Upper layer callback */ + if (likely(command->async_callback)) + command->async_callback(command->async_data, cb_status); + + command->async_callback = NULL; + command->comp_func = NULL; + + /* Unmap the DMA scatter list entries */ + dma_unmap_sg(&dd->pdev->dev, + command->sg, + command->scatter_ents, + command->direction); + + /* Clear the allocated and active bits for the command */ + atomic_set(&port->commands[tag].active, 0); + release_slot(port, tag); + + up(&port->cmd_slot); +} + +/* + * Internal command completion callback function. + * + * This function is normally called by the driver ISR when an internal + * command completed. This function signals the command completion by + * calling complete(). + * + * @port Pointer to the port data structure. + * @tag Tag of the command that has completed. + * @data Pointer to a completion structure. + * @status Completion status. + * + * return value + * None + */ +static void mtip_completion(struct mtip_port *port, + int tag, + void *data, + int status) +{ + struct mtip_cmd *command = &port->commands[tag]; + struct completion *waiting = data; + if (unlikely(status == PORT_IRQ_TF_ERR)) + dev_warn(&port->dd->pdev->dev, + "Internal command %d completed with TFE\n", tag); + + command->async_callback = NULL; + command->comp_func = NULL; + + complete(waiting); +} + +/* * Helper function for tag logging */ static void print_tags(struct driver_data *dd, @@ -1276,7 +1342,7 @@ static int mtip_standby_immediate(struct mtip_port *port) * 1 Capacity was returned successfully. * 0 The identify information is invalid. */ -bool mtip_hw_get_capacity(struct driver_data *dd, sector_t *sectors) +static bool mtip_hw_get_capacity(struct driver_data *dd, sector_t *sectors) { struct mtip_port *port = dd->port; u64 total, raw0, raw1, raw2, raw3; @@ -1423,7 +1489,7 @@ static inline void fill_command_sg(struct driver_data *dd, * return value 0 The command completed successfully. * return value -1 An error occurred while executing the command. */ -int exec_drive_task(struct mtip_port *port, u8 *command) +static int exec_drive_task(struct mtip_port *port, u8 *command) { struct host_to_dev_fis fis; struct host_to_dev_fis *reply = (port->rxfis + RX_FIS_D2H_REG); @@ -1499,8 +1565,8 @@ int exec_drive_task(struct mtip_port *port, u8 *command) * data to the user space buffer. * return value -1 An error occurred while executing the command. */ -int exec_drive_command(struct mtip_port *port, u8 *command, - void __user *user_buffer) +static int exec_drive_command(struct mtip_port *port, u8 *command, + void __user *user_buffer) { struct host_to_dev_fis fis; struct host_to_dev_fis *reply = (port->rxfis + RX_FIS_D2H_REG); @@ -2020,15 +2086,9 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd, * return value * None */ -void mtip_hw_submit_io(struct driver_data *dd, - sector_t start, - int nsect, - int nents, - int tag, - void *callback, - void *data, - int barrier, - int dir) +static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, + int nsect, int nents, int tag, void *callback, + void *data, int barrier, int dir) { struct host_to_dev_fis *fis; struct mtip_port *port = dd->port; @@ -2115,7 +2175,7 @@ void mtip_hw_submit_io(struct driver_data *dd, * return value * None */ -void mtip_hw_release_scatterlist(struct driver_data *dd, int tag) +static void mtip_hw_release_scatterlist(struct driver_data *dd, int tag) { release_slot(dd->port, tag); } @@ -2131,8 +2191,8 @@ void mtip_hw_release_scatterlist(struct driver_data *dd, int tag) * Pointer to the scatter list for the allocated command slot * or NULL if no command slots are available. */ -struct scatterlist *mtip_hw_get_scatterlist(struct driver_data *dd, - int *tag) +static struct scatterlist *mtip_hw_get_scatterlist(struct driver_data *dd, + int *tag) { /* * It is possible that, even with this semaphore, a thread @@ -2216,7 +2276,7 @@ static DEVICE_ATTR(registers, S_IRUGO, hw_show_registers, NULL); * 0 Operation completed successfully. * -EINVAL Invalid parameter. */ -int mtip_hw_sysfs_init(struct driver_data *dd, struct kobject *kobj) +static int mtip_hw_sysfs_init(struct driver_data *dd, struct kobject *kobj) { if (!kobj || !dd) return -EINVAL; @@ -2237,7 +2297,7 @@ int mtip_hw_sysfs_init(struct driver_data *dd, struct kobject *kobj) * 0 Operation completed successfully. * -EINVAL Invalid parameter. */ -int mtip_hw_sysfs_exit(struct driver_data *dd, struct kobject *kobj) +static int mtip_hw_sysfs_exit(struct driver_data *dd, struct kobject *kobj) { if (!kobj || !dd) return -EINVAL; @@ -2385,7 +2445,7 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd) * return value * 0 on success, else an error code. */ -int mtip_hw_init(struct driver_data *dd) +static int mtip_hw_init(struct driver_data *dd) { int i; int rv; @@ -2586,7 +2646,7 @@ out1: * return value * 0 */ -int mtip_hw_exit(struct driver_data *dd) +static int mtip_hw_exit(struct driver_data *dd) { /* * Send standby immediate (E0h) to the drive so that it @@ -2634,7 +2694,7 @@ int mtip_hw_exit(struct driver_data *dd) * return value * 0 */ -int mtip_hw_shutdown(struct driver_data *dd) +static int mtip_hw_shutdown(struct driver_data *dd) { /* * Send standby immediate (E0h) to the drive so that it @@ -2657,7 +2717,7 @@ int mtip_hw_shutdown(struct driver_data *dd) * 0 Suspend was successful * -EFAULT Suspend was not successful */ -int mtip_hw_suspend(struct driver_data *dd) +static int mtip_hw_suspend(struct driver_data *dd) { /* * Send standby immediate (E0h) to the drive @@ -2689,7 +2749,7 @@ int mtip_hw_suspend(struct driver_data *dd) * 0 Resume was successful * -EFAULT Resume was not successful */ -int mtip_hw_resume(struct driver_data *dd) +static int mtip_hw_resume(struct driver_data *dd) { /* Perform any needed hardware setup steps */ hba_setup(dd); @@ -2716,50 +2776,6 @@ int mtip_hw_resume(struct driver_data *dd) } /* - * This function is called for clean the pending command in the - * command slot during the surprise removal of device and return - * error to the upper layer. - * - * @dd Pointer to the DRIVER_DATA structure. - * - * return value - * None - */ -void mtip_command_cleanup(struct driver_data *dd) -{ - int group = 0, commandslot = 0, commandindex = 0; - struct mtip_cmd *command; - struct mtip_port *port = dd->port; - - for (group = 0; group < 4; group++) { - for (commandslot = 0; commandslot < 32; commandslot++) { - if (!(port->allocated[group] & (1 << commandslot))) - continue; - - commandindex = group << 5 | commandslot; - command = &port->commands[commandindex]; - - if (atomic_read(&command->active) - && (command->async_callback)) { - command->async_callback(command->async_data, - -ENODEV); - command->async_callback = NULL; - command->async_data = NULL; - } - - dma_unmap_sg(&port->dd->pdev->dev, - command->sg, - command->scatter_ents, - command->direction); - } - } - - up(&port->cmd_slot); - - atomic_set(&dd->drv_cleanup_done, true); -} - -/* * Helper function for reusing disk name * upon hot insertion. */ @@ -3037,7 +3053,7 @@ static int mtip_make_request(struct request_queue *queue, struct bio *bio) * return value * 0 on success else an error code. */ -int mtip_block_initialize(struct driver_data *dd) +static int mtip_block_initialize(struct driver_data *dd) { int rv = 0; sector_t capacity; @@ -3168,7 +3184,7 @@ protocol_init_error: * return value * 0 */ -int mtip_block_remove(struct driver_data *dd) +static int mtip_block_remove(struct driver_data *dd) { struct kobject *kobj; /* Clean up the sysfs attributes managed by the protocol layer. */ @@ -3205,7 +3221,7 @@ int mtip_block_remove(struct driver_data *dd) * return value * 0 */ -int mtip_block_shutdown(struct driver_data *dd) +static int mtip_block_shutdown(struct driver_data *dd) { dev_info(&dd->pdev->dev, "Shutting down %s ...\n", dd->disk->disk_name); @@ -3220,7 +3236,7 @@ int mtip_block_shutdown(struct driver_data *dd) return 0; } -int mtip_block_suspend(struct driver_data *dd) +static int mtip_block_suspend(struct driver_data *dd) { dev_info(&dd->pdev->dev, "Suspending %s ...\n", dd->disk->disk_name); @@ -3228,7 +3244,7 @@ int mtip_block_suspend(struct driver_data *dd) return 0; } -int mtip_block_resume(struct driver_data *dd) +static int mtip_block_resume(struct driver_data *dd) { dev_info(&dd->pdev->dev, "Resuming %s ...\n", dd->disk->disk_name); @@ -3479,28 +3495,6 @@ static void mtip_pci_shutdown(struct pci_dev *pdev) mtip_block_shutdown(dd); } -/* - * This function check_for_surprise_removal is called - * while card is removed from the system and it will - * read the vendor id from the configration space - * - * @pdev Pointer to the pci_dev structure. - * - * return value - * true if device removed, else false - */ -bool mtip_check_surprise_removal(struct pci_dev *pdev) -{ - u16 vendor_id = 0; - - /* Read the vendorID from the configuration space */ - pci_read_config_word(pdev, 0x00, &vendor_id); - if (vendor_id == 0xFFFF) - return true; /* device removed */ - - return false; /* device present */ -} - /* Table of device ids supported by this driver. */ static DEFINE_PCI_DEVICE_TABLE(mtip_pci_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320_DEVICE_ID) }, diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index d6355c6..17be4f4 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h @@ -405,37 +405,4 @@ struct driver_data { atomic_t eh_active; /* Flag for error handling tracking */ }; -/* Function declarations */ -extern int mtip_block_initialize(struct driver_data *dd); -extern int mtip_block_remove(struct driver_data *dd); -extern int mtip_block_shutdown(struct driver_data *dd); -extern int mtip_block_suspend(struct driver_data *dd); -extern int mtip_block_resume(struct driver_data *dd); -extern int mtip_hw_init(struct driver_data *dd); -extern int mtip_hw_exit(struct driver_data *dd); -extern int mtip_hw_shutdown(struct driver_data *dd); -extern bool mtip_hw_get_capacity(struct driver_data *dd, sector_t *sectors); -extern void mtip_hw_release_scatterlist( - struct driver_data *dd, - int tag); -extern struct scatterlist *mtip_hw_get_scatterlist( - struct driver_data *dd, - int *tag); -extern void mtip_hw_submit_io(struct driver_data *dd, - sector_t start, - int nsect, - int nents, - int tag, - void *callback, - void *data, - int barrier, - int dir); -extern int mtip_hw_sysfs_init(struct driver_data *dd, struct kobject *kobj); -extern int mtip_hw_sysfs_exit(struct driver_data *dd, struct kobject *kobj); -extern int mtip_hw_resume(struct driver_data *dd); -extern int mtip_hw_suspend(struct driver_data *dd); -void mtip_command_cleanup(struct driver_data *dd); -bool mtip_check_surprise_removal(struct pci_dev *pdev); -void mtip_restart_port(struct mtip_port *port); - #endif -- cgit v0.10.2 From 3ff147d3a88e43135b1861d964496101657fa9a2 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 27 Sep 2011 21:33:53 -0600 Subject: mtip32xx: mark a few more items static Missed two items: mtip_major, and mtip_pci_driver. Signed-off-by: Jens Axboe diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 40d840e..b426a93 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -80,7 +80,7 @@ static int instance; * Global variable used to hold the major block device number * allocated in mtip_init(). */ -int mtip_major; +static int mtip_major; static DEFINE_SPINLOCK(rssd_index_lock); static DEFINE_IDA(rssd_index_ida); @@ -3502,7 +3502,7 @@ static DEFINE_PCI_DEVICE_TABLE(mtip_pci_tbl) = { }; /* Structure that describes the PCI driver functions. */ -struct pci_driver mtip_pci_driver = { +static struct pci_driver mtip_pci_driver = { .name = MTIP_DRV_NAME, .id_table = mtip_pci_tbl, .probe = mtip_pci_probe, -- cgit v0.10.2 From 0e838c624e04490985162a1b00d7aa1956c8834e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 28 Sep 2011 07:35:40 -0600 Subject: mtip32xx: add module.h include to avoid conflict with moduleh tree Signed-off-by: Jens Axboe diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index b426a93..f7a3321 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include -- cgit v0.10.2 From a71f483d7957c74368a76a3a88ae54d524fa3b49 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sat, 5 Nov 2011 08:36:21 +0100 Subject: mtip32xx: update to new ->make_request() API Signed-off-by: Jens Axboe diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index f7a3321..880facb 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -2984,10 +2984,8 @@ static const struct block_device_operations mtip_block_ops = { * the driver data structure. * @bio Pointer to the BIO. * - * return value - * 0 */ -static int mtip_make_request(struct request_queue *queue, struct bio *bio) +static void mtip_make_request(struct request_queue *queue, struct bio *bio) { struct driver_data *dd = queue->queuedata; struct scatterlist *sg; @@ -2998,12 +2996,12 @@ static int mtip_make_request(struct request_queue *queue, struct bio *bio) if (unlikely(!bio_has_data(bio))) { blk_queue_flush(queue, 0); bio_endio(bio, 0); - return 0; + return; } if (unlikely(atomic_read(&dd->eh_active))) { bio_endio(bio, -EBUSY); - return 0; + return; } sg = mtip_hw_get_scatterlist(dd, &tag); @@ -3015,7 +3013,7 @@ static int mtip_make_request(struct request_queue *queue, struct bio *bio) "Maximum number of SGL entries exceeded"); bio_io_error(bio); mtip_hw_release_scatterlist(dd, tag); - return 0; + return; } /* Create the scatter list for this bio. */ @@ -3036,11 +3034,8 @@ static int mtip_make_request(struct request_queue *queue, struct bio *bio) bio, bio->bi_rw & REQ_FLUSH, bio_data_dir(bio)); - } else { + } else bio_io_error(bio); - } - - return 0; } /* -- cgit v0.10.2 From b3c7d453a00b7dadc2a7435f68b012371ccc3a3e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 3 Nov 2011 06:57:08 -0300 Subject: [media] solo6x10: rename jpeg.h to solo6x10-jpeg.h This header clashes with the jpeg.h in gspca when doing a compatibility build using the media_build system. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/solo6x10/jpeg.h b/drivers/staging/media/solo6x10/jpeg.h deleted file mode 100644 index 50defec..0000000 --- a/drivers/staging/media/solo6x10/jpeg.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com - * Copyright (C) 2010 Ben Collins - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __SOLO6X10_JPEG_H -#define __SOLO6X10_JPEG_H - -static unsigned char jpeg_header[] = { - 0xff, 0xd8, 0xff, 0xfe, 0x00, 0x0d, 0x42, 0x6c, - 0x75, 0x65, 0x63, 0x68, 0x65, 0x72, 0x72, 0x79, - 0x20, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x20, 0x16, - 0x18, 0x1c, 0x18, 0x14, 0x20, 0x1c, 0x1a, 0x1c, - 0x24, 0x22, 0x20, 0x26, 0x30, 0x50, 0x34, 0x30, - 0x2c, 0x2c, 0x30, 0x62, 0x46, 0x4a, 0x3a, 0x50, - 0x74, 0x66, 0x7a, 0x78, 0x72, 0x66, 0x70, 0x6e, - 0x80, 0x90, 0xb8, 0x9c, 0x80, 0x88, 0xae, 0x8a, - 0x6e, 0x70, 0xa0, 0xda, 0xa2, 0xae, 0xbe, 0xc4, - 0xce, 0xd0, 0xce, 0x7c, 0x9a, 0xe2, 0xf2, 0xe0, - 0xc8, 0xf0, 0xb8, 0xca, 0xce, 0xc6, 0xff, 0xdb, - 0x00, 0x43, 0x01, 0x22, 0x24, 0x24, 0x30, 0x2a, - 0x30, 0x5e, 0x34, 0x34, 0x5e, 0xc6, 0x84, 0x70, - 0x84, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xff, 0xc4, 0x01, 0xa2, 0x00, - 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, - 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, - 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, - 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, - 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, - 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, - 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, - 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, - 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, - 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, - 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, - 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, - 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, - 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, - 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, - 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, - 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, - 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, - 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, - 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, - 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, - 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x01, - 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x11, 0x00, 0x02, 0x01, - 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, - 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, - 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, - 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, - 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, - 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, - 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, - 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, - 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, - 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, - 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, - 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, - 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, - 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, - 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, - 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, - 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, - 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, - 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, - 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, - 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, - 0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x02, 0xc0, - 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, - 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, - 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 -}; - -/* This is the byte marker for the start of SOF0: 0xffc0 marker */ -#define SOF0_START 575 - -#endif /* __SOLO6X10_JPEG_H */ diff --git a/drivers/staging/media/solo6x10/solo6x10-jpeg.h b/drivers/staging/media/solo6x10/solo6x10-jpeg.h new file mode 100644 index 0000000..50defec --- /dev/null +++ b/drivers/staging/media/solo6x10/solo6x10-jpeg.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com + * Copyright (C) 2010 Ben Collins + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __SOLO6X10_JPEG_H +#define __SOLO6X10_JPEG_H + +static unsigned char jpeg_header[] = { + 0xff, 0xd8, 0xff, 0xfe, 0x00, 0x0d, 0x42, 0x6c, + 0x75, 0x65, 0x63, 0x68, 0x65, 0x72, 0x72, 0x79, + 0x20, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x20, 0x16, + 0x18, 0x1c, 0x18, 0x14, 0x20, 0x1c, 0x1a, 0x1c, + 0x24, 0x22, 0x20, 0x26, 0x30, 0x50, 0x34, 0x30, + 0x2c, 0x2c, 0x30, 0x62, 0x46, 0x4a, 0x3a, 0x50, + 0x74, 0x66, 0x7a, 0x78, 0x72, 0x66, 0x70, 0x6e, + 0x80, 0x90, 0xb8, 0x9c, 0x80, 0x88, 0xae, 0x8a, + 0x6e, 0x70, 0xa0, 0xda, 0xa2, 0xae, 0xbe, 0xc4, + 0xce, 0xd0, 0xce, 0x7c, 0x9a, 0xe2, 0xf2, 0xe0, + 0xc8, 0xf0, 0xb8, 0xca, 0xce, 0xc6, 0xff, 0xdb, + 0x00, 0x43, 0x01, 0x22, 0x24, 0x24, 0x30, 0x2a, + 0x30, 0x5e, 0x34, 0x34, 0x5e, 0xc6, 0x84, 0x70, + 0x84, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xff, 0xc4, 0x01, 0xa2, 0x00, + 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, + 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, + 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, + 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, + 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, + 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, + 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, + 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, + 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, + 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, + 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, + 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, + 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, + 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, + 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, + 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, + 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, + 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, + 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x01, + 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x11, 0x00, 0x02, 0x01, + 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, + 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, + 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, + 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, + 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, + 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, + 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, + 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, + 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, + 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, + 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, + 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, + 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, + 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, + 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, + 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, + 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, + 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, + 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, + 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, + 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, + 0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x02, 0xc0, + 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, + 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, + 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 +}; + +/* This is the byte marker for the start of SOF0: 0xffc0 marker */ +#define SOF0_START 575 + +#endif /* __SOLO6X10_JPEG_H */ diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c index bee7280..f8f0da9 100644 --- a/drivers/staging/media/solo6x10/v4l2-enc.c +++ b/drivers/staging/media/solo6x10/v4l2-enc.c @@ -26,7 +26,7 @@ #include #include "solo6x10.h" #include "tw28.h" -#include "jpeg.h" +#include "solo6x10-jpeg.h" #define MIN_VID_BUFFERS 4 #define FRAME_BUF_SIZE (128 * 1024) -- cgit v0.10.2 From 33cdf5b0e75142096d79cbe3cb7c3dc797499562 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 4 Nov 2011 06:13:14 -0300 Subject: [media] solo6x10: fix broken Makefile The Makefile used := instead of +=, this broke the compatibility build. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/solo6x10/Makefile b/drivers/staging/media/solo6x10/Makefile index 72816cf..337e38c 100644 --- a/drivers/staging/media/solo6x10/Makefile +++ b/drivers/staging/media/solo6x10/Makefile @@ -1,3 +1,3 @@ solo6x10-y := core.o i2c.o p2m.o v4l2.o tw28.o gpio.o disp.o enc.o v4l2-enc.o g723.o -obj-$(CONFIG_SOLO6X10) := solo6x10.o +obj-$(CONFIG_SOLO6X10) += solo6x10.o -- cgit v0.10.2 From b682ad1d178d1686a4db07535d1e611342cde012 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 12 Aug 2011 18:29:10 -0300 Subject: [media] tda18212: add DVB-T2 support Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/tuners/tda18212.c b/drivers/media/common/tuners/tda18212.c index e29cc2bc1..6374a1e 100644 --- a/drivers/media/common/tuners/tda18212.c +++ b/drivers/media/common/tuners/tda18212.c @@ -136,12 +136,24 @@ static int tda18212_set_params(struct dvb_frontend *fe, int ret, i; u32 if_khz; u8 buf[9]; + #define DVBT_6 0 + #define DVBT_7 1 + #define DVBT_8 2 + #define DVBT2_6 3 + #define DVBT2_7 4 + #define DVBT2_8 5 + #define DVBC_6 6 + #define DVBC_8 7 static const u8 bw_params[][3] = { - /* 0f 13 23 */ - { 0xb3, 0x20, 0x03 }, /* DVB-T 6 MHz */ - { 0xb3, 0x31, 0x01 }, /* DVB-T 7 MHz */ - { 0xb3, 0x22, 0x01 }, /* DVB-T 8 MHz */ - { 0x92, 0x53, 0x03 }, /* DVB-C */ + /* reg: 0f 13 23 */ + [DVBT_6] = { 0xb3, 0x20, 0x03 }, + [DVBT_7] = { 0xb3, 0x31, 0x01 }, + [DVBT_8] = { 0xb3, 0x22, 0x01 }, + [DVBT2_6] = { 0xbc, 0x20, 0x03 }, + [DVBT2_7] = { 0xbc, 0x72, 0x03 }, + [DVBT2_8] = { 0xbc, 0x22, 0x01 }, + [DVBC_6] = { 0x92, 0x50, 0x03 }, + [DVBC_8] = { 0x92, 0x53, 0x03 }, }; dbg("delsys=%d RF=%d BW=%d\n", @@ -155,15 +167,34 @@ static int tda18212_set_params(struct dvb_frontend *fe, switch (c->bandwidth_hz) { case 6000000: if_khz = priv->cfg->if_dvbt_6; - i = 0; + i = DVBT_6; break; case 7000000: if_khz = priv->cfg->if_dvbt_7; - i = 1; + i = DVBT_7; break; case 8000000: if_khz = priv->cfg->if_dvbt_8; - i = 2; + i = DVBT_8; + break; + default: + ret = -EINVAL; + goto error; + } + break; + case SYS_DVBT2: + switch (c->bandwidth_hz) { + case 6000000: + if_khz = priv->cfg->if_dvbt2_6; + i = DVBT2_6; + break; + case 7000000: + if_khz = priv->cfg->if_dvbt2_7; + i = DVBT2_7; + break; + case 8000000: + if_khz = priv->cfg->if_dvbt2_8; + i = DVBT2_8; break; default: ret = -EINVAL; @@ -172,7 +203,7 @@ static int tda18212_set_params(struct dvb_frontend *fe, break; case SYS_DVBC_ANNEX_AC: if_khz = priv->cfg->if_dvbc; - i = 3; + i = DVBC_8; break; default: ret = -EINVAL; diff --git a/drivers/media/common/tuners/tda18212.h b/drivers/media/common/tuners/tda18212.h index 83b497f..9bd5da4 100644 --- a/drivers/media/common/tuners/tda18212.h +++ b/drivers/media/common/tuners/tda18212.h @@ -29,6 +29,10 @@ struct tda18212_config { u16 if_dvbt_6; u16 if_dvbt_7; u16 if_dvbt_8; + u16 if_dvbt2_5; + u16 if_dvbt2_6; + u16 if_dvbt2_7; + u16 if_dvbt2_8; u16 if_dvbc; }; -- cgit v0.10.2 From 608add85decc7a13194072fbb0c6aadc89d394e5 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 12 Aug 2011 18:29:46 -0300 Subject: [media] anysee: add support for Anysee E7 T2C Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 5825716..3e316f2 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -311,6 +311,7 @@ config DVB_USB_ANYSEE select DVB_STV0900 if !DVB_FE_CUSTOMISE select DVB_STV6110 if !DVB_FE_CUSTOMISE select DVB_ISL6423 if !DVB_FE_CUSTOMISE + select DVB_CXD2820R if !DVB_FE_CUSTOMISE help Say Y here to support the Anysee E30, Anysee E30 Plus or Anysee E30 C Plus DVB USB2.0 receiver. diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index 5f2278b..9c1ed3b 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c @@ -41,6 +41,7 @@ #include "stv0900.h" #include "stv6110.h" #include "isl6423.h" +#include "cxd2820r.h" /* debug */ static int dvb_usb_anysee_debug; @@ -309,6 +310,17 @@ static struct tda18212_config anysee_tda18212_config = { .if_dvbc = 5000, }; +static struct tda18212_config anysee_tda18212_config2 = { + .i2c_address = 0x60 /* (0xc0 >> 1) */, + .if_dvbt_6 = 3550, + .if_dvbt_7 = 3700, + .if_dvbt_8 = 4150, + .if_dvbt2_6 = 3250, + .if_dvbt2_7 = 4000, + .if_dvbt2_8 = 4000, + .if_dvbc = 5000, +}; + static struct cx24116_config anysee_cx24116_config = { .demod_address = (0xaa >> 1), .mpg_clk_pos_pol = 0x00, @@ -339,6 +351,18 @@ static struct isl6423_config anysee_isl6423_config = { .addr = (0x10 >> 1), }; +static struct cxd2820r_config anysee_cxd2820r_config = { + .i2c_address = 0x6d, /* (0xda >> 1) */ + .ts_mode = 0x38, + .if_dvbt_6 = 3550, + .if_dvbt_7 = 3700, + .if_dvbt_8 = 4150, + .if_dvbt2_6 = 3250, + .if_dvbt2_7 = 4000, + .if_dvbt2_8 = 4000, + .if_dvbc = 5000, +}; + /* * New USB device strings: Mfr=1, Product=2, SerialNumber=0 * Manufacturer: AMT.CO.KR @@ -421,6 +445,14 @@ static struct isl6423_config anysee_isl6423_config = { * IOA[7] TS 1=enabled * IOE[5] STV0903 1=enabled * + * E7 T2C VID=1c73 PID=861f HW=20 FW=0.1 AMTCI=0.5 "anysee-E7T2C(LP)" + * PCB: 508T2C (rev0.3) + * parts: DNOQ44QCH106A(CXD2820R, TDA18212), TDA8024 + * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff + * IOA=4d IOB=00 IOC=cc IOD=48 IOE=e4 + * IOA[7] TS 1=enabled + * IOE[5] CXD2820R 1=enabled + * * E7 PTC VID=1c73 PID=861f HW=21 FW=0.1 AMTCI=?? "anysee-E7PTC(LP)" * PCB: 508PTC (rev0.5) * parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212) @@ -437,7 +469,7 @@ static struct isl6423_config anysee_isl6423_config = { * IOD[6] ZL10353 1=enabled * IOE[0] IF 0=enabled * - * E7 S2 VID=1c73 PID=861f HW=22 FW=0.1 AMTCI=?? "anysee-E7PS2(LP)" + * E7 PS2 VID=1c73 PID=861f HW=22 FW=0.1 AMTCI=?? "anysee-E7PS2(LP)" * PCB: 508PS2 (rev0.4) * parts: DNBU10512IST(STV0903, STV6110), ISL6423 * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff @@ -818,6 +850,32 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) &adap->dev->i2c_adap, 0); break; + case ANYSEE_HW_508T2C: /* 20 */ + /* E7 T2C */ + + /* enable transport stream on IOA[7] */ + ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80); + if (ret) + goto error; + + /* enable DVB-T/T2/C demod on IOE[5] */ + ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20); + if (ret) + goto error; + + if (state->fe_id == 0) { + /* DVB-T/T2 */ + adap->fe[0] = dvb_attach(cxd2820r_attach, + &anysee_cxd2820r_config, + &adap->dev->i2c_adap, NULL); + } else { + /* DVB-C */ + adap->fe[1] = dvb_attach(cxd2820r_attach, + &anysee_cxd2820r_config, + &adap->dev->i2c_adap, adap->fe[0]); + } + + break; } if (!adap->fe_adap[0].fe) { @@ -930,6 +988,15 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) } break; + + case ANYSEE_HW_508T2C: /* 20 */ + /* E7 T2C */ + + /* attach tuner */ + fe = dvb_attach(tda18212_attach, adap->fe[state->fe_id], + &adap->dev->i2c_adap, &anysee_tda18212_config2); + + break; default: fe = NULL; } diff --git a/drivers/media/dvb/dvb-usb/anysee.h b/drivers/media/dvb/dvb-usb/anysee.h index 57ee500..da32350 100644 --- a/drivers/media/dvb/dvb-usb/anysee.h +++ b/drivers/media/dvb/dvb-usb/anysee.h @@ -69,6 +69,7 @@ struct anysee_state { #define ANYSEE_HW_507FA 15 /* E30 Combo Plus / E30 C Plus */ #define ANYSEE_HW_508TC 18 /* E7 TC */ #define ANYSEE_HW_508S2 19 /* E7 S2 */ +#define ANYSEE_HW_508T2C 20 /* E7 T2C */ #define ANYSEE_HW_508PTC 21 /* E7 PTC Plus */ #define ANYSEE_HW_508PS2 22 /* E7 PS2 Plus */ -- cgit v0.10.2 From be94351e592cb71fb61aa8eeed7bf3f877dc6fff Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 5 Sep 2011 22:10:05 -0300 Subject: [media] anysee: I2C gate control DNOD44CDH086A tuner module DNOD44CDH086A (NXP TDA18212) tuner module is not connected to demodulator I2C gate. Instead demodulator gate it uses external GPIO driven gate. Override demodulator I2C gate control with own in that case. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index 9c1ed3b..28c7b23 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c @@ -478,6 +478,16 @@ static struct cxd2820r_config anysee_cxd2820r_config = { * IOE[5] STV0903 1=enabled */ + +/* external I2C gate used for DNOD44CDH086A(TDA18212) tuner module */ +static int anysee_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct dvb_usb_adapter *adap = fe->dvb->priv; + + /* enable / disable tuner access on IOE[4] */ + return anysee_wr_reg_mask(adap->dev, REG_IOE, (enable << 4), 0x10); +} + static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff) { struct dvb_usb_adapter *adap = fe->dvb->priv; @@ -779,6 +789,13 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) } } + /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */ + if (tmp == 0xc7) { + if (adap->fe_adap[state->fe_id].fe) + adap->fe_adap[state->fe_id].fe->ops.i2c_gate_ctrl = + anysee_i2c_gate_ctrl; + } + break; case ANYSEE_HW_508TC: /* 18 */ case ANYSEE_HW_508PTC: /* 21 */ @@ -826,6 +843,11 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) &adap->dev->i2c_adap); } + /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */ + if (adap->fe_adap[state->fe_id].fe) + adap->fe_adap[state->fe_id].fe->ops.i2c_gate_ctrl = + anysee_i2c_gate_ctrl; + break; case ANYSEE_HW_508S2: /* 19 */ case ANYSEE_HW_508PS2: /* 22 */ @@ -865,14 +887,14 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) if (state->fe_id == 0) { /* DVB-T/T2 */ - adap->fe[0] = dvb_attach(cxd2820r_attach, + adap->fe_adap[state->fe_id].fe = dvb_attach(cxd2820r_attach, &anysee_cxd2820r_config, &adap->dev->i2c_adap, NULL); } else { /* DVB-C */ - adap->fe[1] = dvb_attach(cxd2820r_attach, + adap->fe_adap[state->fe_id].fe = dvb_attach(cxd2820r_attach, &anysee_cxd2820r_config, - &adap->dev->i2c_adap, adap->fe[0]); + &adap->dev->i2c_adap, adap->fe_adap[0].fe); } break; @@ -935,22 +957,12 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) /* Try first attach TDA18212 silicon tuner on IOE[4], if that * fails attach old simple PLL. */ - /* enable tuner on IOE[4] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10); - if (ret) - goto error; - /* attach tuner */ fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe, &adap->dev->i2c_adap, &anysee_tda18212_config); if (fe) break; - /* disable tuner on IOE[4] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10); - if (ret) - goto error; - /* attach tuner */ fe = dvb_attach(dvb_pll_attach, adap->fe_adap[state->fe_id].fe, (0xc0 >> 1), &adap->dev->i2c_adap, @@ -962,11 +974,6 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) /* E7 TC */ /* E7 PTC */ - /* enable tuner on IOE[4] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10); - if (ret) - goto error; - /* attach tuner */ fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe, &adap->dev->i2c_adap, &anysee_tda18212_config); @@ -993,7 +1000,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) /* E7 T2C */ /* attach tuner */ - fe = dvb_attach(tda18212_attach, adap->fe[state->fe_id], + fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe, &adap->dev->i2c_adap, &anysee_tda18212_config2); break; @@ -1006,7 +1013,6 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) else ret = -ENODEV; -error: return ret; } -- cgit v0.10.2 From 05cd37def5e697e158470d826cb75c5607c04bd1 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 5 Sep 2011 23:33:04 -0300 Subject: [media] anysee: CI/CAM support Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index 28c7b23..0bc1372 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c @@ -130,6 +130,29 @@ static int anysee_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val, return anysee_write_reg(d, reg, val); } +/* read single register with mask */ +static int anysee_rd_reg_mask(struct dvb_usb_device *d, u16 reg, u8 *val, + u8 mask) +{ + int ret, i; + u8 tmp; + + ret = anysee_read_reg(d, reg, &tmp); + if (ret) + return ret; + + tmp &= mask; + + /* find position of the first bit */ + for (i = 0; i < 8; i++) { + if ((mask >> i) & 0x01) + break; + } + *val = tmp >> i; + + return 0; +} + static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id) { u8 buf[] = {CMD_GET_HW_INFO}; @@ -157,22 +180,6 @@ static int anysee_ir_ctrl(struct dvb_usb_device *d, u8 onoff) return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); } -static int anysee_init(struct dvb_usb_device *d) -{ - int ret; - /* LED light */ - ret = anysee_led_ctrl(d, 0x01, 0x03); - if (ret) - return ret; - - /* enable IR */ - ret = anysee_ir_ctrl(d, 1); - if (ret) - return ret; - - return 0; -} - /* I2C */ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num) @@ -298,7 +305,7 @@ static struct tda10023_config anysee_tda10023_tda18212_config = { .pll_m = 12, .pll_p = 3, .pll_n = 1, - .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C, + .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_B, .deltaf = 0xba02, }; @@ -802,11 +809,6 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) /* E7 TC */ /* E7 PTC */ - /* enable transport stream on IOA[7] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80); - if (ret) - goto error; - if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0) { /* disable DVB-T demod on IOD[6] */ ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6), @@ -848,6 +850,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) adap->fe_adap[state->fe_id].fe->ops.i2c_gate_ctrl = anysee_i2c_gate_ctrl; + state->has_ci = true; + break; case ANYSEE_HW_508S2: /* 19 */ case ANYSEE_HW_508PS2: /* 22 */ @@ -857,11 +861,6 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) if (state->fe_id) break; - /* enable transport stream on IOA[7] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80); - if (ret) - goto error; - /* enable DVB-S/S2 demod on IOE[5] */ ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20); if (ret) @@ -871,15 +870,12 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) adap->fe_adap[0].fe = dvb_attach(stv0900_attach, &anysee_stv0900_config, &adap->dev->i2c_adap, 0); + state->has_ci = true; + break; case ANYSEE_HW_508T2C: /* 20 */ /* E7 T2C */ - /* enable transport stream on IOA[7] */ - ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80); - if (ret) - goto error; - /* enable DVB-T/T2/C demod on IOE[5] */ ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20); if (ret) @@ -897,6 +893,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) &adap->dev->i2c_adap, adap->fe_adap[0].fe); } + state->has_ci = true; + break; } @@ -1042,6 +1040,201 @@ static int anysee_rc_query(struct dvb_usb_device *d) return 0; } +static int anysee_ci_read_attribute_mem(struct dvb_ca_en50221 *ci, int slot, + int addr) +{ + struct dvb_usb_device *d = ci->data; + int ret; + u8 buf[] = {CMD_CI, 0x02, 0x40 | addr >> 8, addr & 0xff, 0x00, 1}; + u8 val; + + ret = anysee_ctrl_msg(d, buf, sizeof(buf), &val, 1); + if (ret) + return ret; + + return val; +} + +static int anysee_ci_write_attribute_mem(struct dvb_ca_en50221 *ci, int slot, + int addr, u8 val) +{ + struct dvb_usb_device *d = ci->data; + int ret; + u8 buf[] = {CMD_CI, 0x03, 0x40 | addr >> 8, addr & 0xff, 0x00, 1, val}; + + ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); + if (ret) + return ret; + + return 0; +} + +static int anysee_ci_read_cam_control(struct dvb_ca_en50221 *ci, int slot, + u8 addr) +{ + struct dvb_usb_device *d = ci->data; + int ret; + u8 buf[] = {CMD_CI, 0x04, 0x40, addr, 0x00, 1}; + u8 val; + + ret = anysee_ctrl_msg(d, buf, sizeof(buf), &val, 1); + if (ret) + return ret; + + return val; +} + +static int anysee_ci_write_cam_control(struct dvb_ca_en50221 *ci, int slot, + u8 addr, u8 val) +{ + struct dvb_usb_device *d = ci->data; + int ret; + u8 buf[] = {CMD_CI, 0x05, 0x40, addr, 0x00, 1, val}; + + ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); + if (ret) + return ret; + + return 0; +} + +static int anysee_ci_slot_reset(struct dvb_ca_en50221 *ci, int slot) +{ + struct dvb_usb_device *d = ci->data; + int ret; + struct anysee_state *state = d->priv; + + state->ci_cam_ready = jiffies + msecs_to_jiffies(1000); + + ret = anysee_wr_reg_mask(d, REG_IOA, (0 << 7), 0x80); + if (ret) + return ret; + + msleep(300); + + ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80); + if (ret) + return ret; + + return 0; +} + +static int anysee_ci_slot_shutdown(struct dvb_ca_en50221 *ci, int slot) +{ + struct dvb_usb_device *d = ci->data; + int ret; + + ret = anysee_wr_reg_mask(d, REG_IOA, (0 << 7), 0x80); + if (ret) + return ret; + + msleep(30); + + ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80); + if (ret) + return ret; + + return 0; +} + +static int anysee_ci_slot_ts_enable(struct dvb_ca_en50221 *ci, int slot) +{ + struct dvb_usb_device *d = ci->data; + int ret; + + ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 1), 0x02); + if (ret) + return ret; + + return 0; +} + +static int anysee_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot, + int open) +{ + struct dvb_usb_device *d = ci->data; + struct anysee_state *state = d->priv; + int ret; + u8 tmp; + + ret = anysee_rd_reg_mask(d, REG_IOC, &tmp, 0x40); + if (ret) + return ret; + + if (tmp == 0) { + ret = DVB_CA_EN50221_POLL_CAM_PRESENT; + if (time_after(jiffies, state->ci_cam_ready)) + ret |= DVB_CA_EN50221_POLL_CAM_READY; + } + + return ret; +} + +static int anysee_ci_init(struct dvb_usb_device *d) +{ + struct anysee_state *state = d->priv; + int ret; + + state->ci.owner = THIS_MODULE; + state->ci.read_attribute_mem = anysee_ci_read_attribute_mem; + state->ci.write_attribute_mem = anysee_ci_write_attribute_mem; + state->ci.read_cam_control = anysee_ci_read_cam_control; + state->ci.write_cam_control = anysee_ci_write_cam_control; + state->ci.slot_reset = anysee_ci_slot_reset; + state->ci.slot_shutdown = anysee_ci_slot_shutdown; + state->ci.slot_ts_enable = anysee_ci_slot_ts_enable; + state->ci.poll_slot_status = anysee_ci_poll_slot_status; + state->ci.data = d; + + ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80); + if (ret) + return ret; + + ret = dvb_ca_en50221_init(&d->adapter[0].dvb_adap, &state->ci, 0, 1); + if (ret) + return ret; + + return 0; +} + +static void anysee_ci_release(struct dvb_usb_device *d) +{ + struct anysee_state *state = d->priv; + + /* detach CI */ + if (state->has_ci) + dvb_ca_en50221_release(&state->ci); + + return; +} + +static int anysee_init(struct dvb_usb_device *d) +{ + struct anysee_state *state = d->priv; + int ret; + + /* LED light */ + ret = anysee_led_ctrl(d, 0x01, 0x03); + if (ret) + return ret; + + /* enable IR */ + ret = anysee_ir_ctrl(d, 1); + if (ret) + return ret; + + /* attach CI */ + if (state->has_ci) { + ret = anysee_ci_init(d); + if (ret) { + state->has_ci = false; + return ret; + } + } + + return 0; +} + /* DVB USB Driver stuff */ static struct dvb_usb_device_properties anysee_properties; @@ -1083,6 +1276,16 @@ static int anysee_probe(struct usb_interface *intf, return anysee_init(d); } +static void anysee_disconnect(struct usb_interface *intf) +{ + struct dvb_usb_device *d = usb_get_intfdata(intf); + + anysee_ci_release(d); + dvb_usb_device_exit(intf); + + return; +} + static struct usb_device_id anysee_table[] = { { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE) }, { USB_DEVICE(USB_VID_AMT, USB_PID_ANYSEE) }, @@ -1160,7 +1363,7 @@ static struct dvb_usb_device_properties anysee_properties = { static struct usb_driver anysee_driver = { .name = "dvb_usb_anysee", .probe = anysee_probe, - .disconnect = dvb_usb_device_exit, + .disconnect = anysee_disconnect, .id_table = anysee_table, }; diff --git a/drivers/media/dvb/dvb-usb/anysee.h b/drivers/media/dvb/dvb-usb/anysee.h index da32350..8ac8794 100644 --- a/drivers/media/dvb/dvb-usb/anysee.h +++ b/drivers/media/dvb/dvb-usb/anysee.h @@ -36,6 +36,7 @@ #define DVB_USB_LOG_PREFIX "anysee" #include "dvb-usb.h" +#include "dvb_ca_en50221.h" #define deb_info(args...) dprintk(dvb_usb_anysee_debug, 0x01, args) #define deb_xfer(args...) dprintk(dvb_usb_anysee_debug, 0x02, args) @@ -54,12 +55,16 @@ enum cmd { CMD_GET_IR_CODE = 0x41, CMD_GET_HW_INFO = 0x19, CMD_SMARTCARD = 0x34, + CMD_CI = 0x37, }; struct anysee_state { u8 hw; /* PCB ID */ u8 seq; u8 fe_id:1; /* frondend ID */ + u8 has_ci:1; + struct dvb_ca_en50221 ci; + unsigned long ci_cam_ready; /* jiffies */ }; #define ANYSEE_HW_507T 2 /* E30 */ -- cgit v0.10.2 From 4048da2fa3c8c5088901d2adc4f7b5b5ccc05e79 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 29 Sep 2011 20:28:53 -0300 Subject: [media] anysee: add control message debugs Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index 0bc1372..2e70879 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c @@ -67,10 +67,12 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, if (mutex_lock_interruptible(&anysee_usb_mutex) < 0) return -EAGAIN; + deb_xfer(">>> "); + debug_dump(buf, slen, deb_xfer); + /* We need receive one message more after dvb_usb_generic_rw due to weird transaction flow, which is 1 x send + 2 x receive. */ ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0); - if (!ret) { /* receive 2nd answer */ ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, @@ -80,7 +82,10 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, err("%s: recv bulk message failed: %d", __func__, ret); else { deb_xfer("<<< "); - debug_dump(buf, act_len, deb_xfer); + debug_dump(buf, rlen, deb_xfer); + + if (buf[63] != 0x4f) + deb_info("%s: cmd failed\n", __func__); } } -- cgit v0.10.2 From 8f4ffb1d4752ebce153e88266ac1164e8ecc5854 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 29 Sep 2011 20:36:33 -0300 Subject: [media] anysee: fix style issues Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index 2e70879..c64eb56 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c @@ -631,7 +631,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) /* detect hardware only once */ if (adap->fe_adap[0].fe == NULL) { /* Check which hardware we have. - * We must do this call two times to get reliable values (hw bug). + * We must do this call two times to get reliable values + * (hw/fw bug). */ ret = anysee_get_hw_info(adap->dev, hw_info); if (ret) @@ -660,14 +661,14 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) break; /* attach demod */ - adap->fe_adap[0].fe = dvb_attach(mt352_attach, &anysee_mt352_config, - &adap->dev->i2c_adap); + adap->fe_adap[0].fe = dvb_attach(mt352_attach, + &anysee_mt352_config, &adap->dev->i2c_adap); if (adap->fe_adap[0].fe) break; /* attach demod */ - adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &anysee_zl10353_config, - &adap->dev->i2c_adap); + adap->fe_adap[0].fe = dvb_attach(zl10353_attach, + &anysee_zl10353_config, &adap->dev->i2c_adap); break; case ANYSEE_HW_507CD: /* 6 */ @@ -719,8 +720,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) goto error; /* attach demod */ - adap->fe_adap[0].fe = dvb_attach(cx24116_attach, &anysee_cx24116_config, - &adap->dev->i2c_adap); + adap->fe_adap[0].fe = dvb_attach(cx24116_attach, + &anysee_cx24116_config, &adap->dev->i2c_adap); break; case ANYSEE_HW_507FA: /* 15 */ @@ -828,7 +829,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) goto error; /* attach demod */ - adap->fe_adap[state->fe_id].fe = dvb_attach(tda10023_attach, + adap->fe_adap[state->fe_id].fe = + dvb_attach(tda10023_attach, &anysee_tda10023_tda18212_config, &adap->dev->i2c_adap, 0x48); } else { @@ -845,7 +847,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) goto error; /* attach demod */ - adap->fe_adap[state->fe_id].fe = dvb_attach(zl10353_attach, + adap->fe_adap[state->fe_id].fe = + dvb_attach(zl10353_attach, &anysee_zl10353_tda18212_config, &adap->dev->i2c_adap); } @@ -872,8 +875,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) goto error; /* attach demod */ - adap->fe_adap[0].fe = dvb_attach(stv0900_attach, &anysee_stv0900_config, - &adap->dev->i2c_adap, 0); + adap->fe_adap[0].fe = dvb_attach(stv0900_attach, + &anysee_stv0900_config, &adap->dev->i2c_adap, 0); state->has_ci = true; @@ -888,12 +891,14 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) if (state->fe_id == 0) { /* DVB-T/T2 */ - adap->fe_adap[state->fe_id].fe = dvb_attach(cxd2820r_attach, + adap->fe_adap[state->fe_id].fe = + dvb_attach(cxd2820r_attach, &anysee_cxd2820r_config, &adap->dev->i2c_adap, NULL); } else { /* DVB-C */ - adap->fe_adap[state->fe_id].fe = dvb_attach(cxd2820r_attach, + adap->fe_adap[state->fe_id].fe = + dvb_attach(cxd2820r_attach, &anysee_cxd2820r_config, &adap->dev->i2c_adap, adap->fe_adap[0].fe); } @@ -925,24 +930,26 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap) /* E30 */ /* attach tuner */ - fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc2 >> 1), - NULL, DVB_PLL_THOMSON_DTT7579); + fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, + (0xc2 >> 1), NULL, DVB_PLL_THOMSON_DTT7579); break; case ANYSEE_HW_507CD: /* 6 */ /* E30 Plus */ /* attach tuner */ - fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc2 >> 1), - &adap->dev->i2c_adap, DVB_PLL_THOMSON_DTT7579); + fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, + (0xc2 >> 1), &adap->dev->i2c_adap, + DVB_PLL_THOMSON_DTT7579); break; case ANYSEE_HW_507DC: /* 10 */ /* E30 C Plus */ /* attach tuner */ - fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc0 >> 1), - &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); + fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, + (0xc0 >> 1), &adap->dev->i2c_adap, + DVB_PLL_SAMSUNG_DTOS403IH102A); break; case ANYSEE_HW_507SI: /* 11 */ @@ -1310,7 +1317,7 @@ static struct dvb_usb_device_properties anysee_properties = { { .num_frontends = 2, .frontend_ctrl = anysee_frontend_ctrl, - .fe = {{ + .fe = { { .streaming_ctrl = anysee_streaming_ctrl, .frontend_attach = anysee_frontend_attach, .tuner_attach = anysee_tuner_attach, @@ -1338,7 +1345,7 @@ static struct dvb_usb_device_properties anysee_properties = { } } }, - }}, + } }, } }, -- cgit v0.10.2 From 3f8770454b82c166662201a8966476f4538cbfeb Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Fri, 21 Oct 2011 09:30:25 -0300 Subject: [media] v4l: use i2c_smbus_read_word_swapped Function ensures that error codes don't get mangled. Dependant on: which is working it's way through the i2c tree. Signed-off-by: Jonathan Cameron Acked-by: Jean Delvare Acked-by: Robert Jarzmik Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 63ae5c6..9f3ffc7 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -108,14 +108,13 @@ static struct mt9m001 *to_mt9m001(const struct i2c_client *client) static int reg_read(struct i2c_client *client, const u8 reg) { - s32 data = i2c_smbus_read_word_data(client, reg); - return data < 0 ? data : swab16(data); + return i2c_smbus_read_word_swapped(client, reg); } static int reg_write(struct i2c_client *client, const u8 reg, const u16 data) { - return i2c_smbus_write_word_data(client, reg, swab16(data)); + return i2c_smbus_write_word_swapped(client, reg, data); } static int reg_set(struct i2c_client *client, const u8 reg, diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index f023cc0..59bfe39 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -210,7 +210,7 @@ static int reg_page_map_set(struct i2c_client *client, const u16 reg) if (page > 2) return -EINVAL; - ret = i2c_smbus_write_word_data(client, MT9M111_PAGE_MAP, swab16(page)); + ret = i2c_smbus_write_word_swapped(client, MT9M111_PAGE_MAP, page); if (!ret) mt9m111->lastpage = page; return ret; @@ -222,7 +222,7 @@ static int mt9m111_reg_read(struct i2c_client *client, const u16 reg) ret = reg_page_map_set(client, reg); if (!ret) - ret = swab16(i2c_smbus_read_word_data(client, reg & 0xff)); + ret = i2c_smbus_read_word_swapped(client, reg & 0xff); dev_dbg(&client->dev, "read reg.%03x -> %04x\n", reg, ret); return ret; @@ -235,8 +235,7 @@ static int mt9m111_reg_write(struct i2c_client *client, const u16 reg, ret = reg_page_map_set(client, reg); if (!ret) - ret = i2c_smbus_write_word_data(client, reg & 0xff, - swab16(data)); + ret = i2c_smbus_write_word_swapped(client, reg & 0xff, data); dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret); return ret; } diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index 7ee84cc..198298c 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c @@ -89,14 +89,13 @@ static struct mt9t031 *to_mt9t031(const struct i2c_client *client) static int reg_read(struct i2c_client *client, const u8 reg) { - s32 data = i2c_smbus_read_word_data(client, reg); - return data < 0 ? data : swab16(data); + return i2c_smbus_read_word_swapped(client, reg); } static int reg_write(struct i2c_client *client, const u8 reg, const u16 data) { - return i2c_smbus_write_word_data(client, reg, swab16(data)); + return i2c_smbus_write_word_swapped(client, reg, data); } static int reg_set(struct i2c_client *client, const u8 reg, diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index b6a29f7..c5c67ec 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -129,14 +129,13 @@ static struct mt9v022 *to_mt9v022(const struct i2c_client *client) static int reg_read(struct i2c_client *client, const u8 reg) { - s32 data = i2c_smbus_read_word_data(client, reg); - return data < 0 ? data : swab16(data); + return i2c_smbus_read_word_swapped(client, reg); } static int reg_write(struct i2c_client *client, const u8 reg, const u16 data) { - return i2c_smbus_write_word_data(client, reg, swab16(data)); + return i2c_smbus_write_word_swapped(client, reg, data); } static int reg_set(struct i2c_client *client, const u8 reg, diff --git a/drivers/media/video/mt9v032.c b/drivers/media/video/mt9v032.c index c64e1dc..7906929 100644 --- a/drivers/media/video/mt9v032.c +++ b/drivers/media/video/mt9v032.c @@ -138,10 +138,10 @@ static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd) static int mt9v032_read(struct i2c_client *client, const u8 reg) { - s32 data = i2c_smbus_read_word_data(client, reg); + s32 data = i2c_smbus_read_word_swapped(client, reg); dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__, - swab16(data), reg); - return data < 0 ? data : swab16(data); + data, reg); + return data; } static int mt9v032_write(struct i2c_client *client, const u8 reg, @@ -149,7 +149,7 @@ static int mt9v032_write(struct i2c_client *client, const u8 reg, { dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__, data, reg); - return i2c_smbus_write_word_data(client, reg, swab16(data)); + return i2c_smbus_write_word_swapped(client, reg, data); } static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set) -- cgit v0.10.2 From d06db7ec908869cbf79829b8cbd9a04a7c802905 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Wed, 28 Sep 2011 10:49:24 -0300 Subject: [media] OMAP_VOUT: Fix check in reqbuf for buf_size allocation The commit 383e4f69879d11c86ebdd38b3356f6d0690fb4cc makes reqbuf prevent requesting a larger size buffer than what is allocated at kernel boot during omap_vout_probe. In omap_vout_buffer_setup callback API, the requested size is compared with vout->buffer_size, this isn't correct as vout->buffer_size is later set to the size requested in reqbuf. When the video device is opened the next time, this check will prevent us to allocate a buffer which is larger than what we requested the last time. Don't use vout->buffer_size, always check with the parameters video1_bufsize or video2_bufsize. Signed-off-by: Archit Taneja Acked-by: Vaibhav Hiremath Signed-off-by: Vaibhav Hiremath Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index 9c5c19f..11f5638 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -663,10 +663,14 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count, u32 phy_addr = 0, virt_addr = 0; struct omap_vout_device *vout = q->priv_data; struct omapvideo_info *ovid = &vout->vid_info; + int vid_max_buf_size; if (!vout) return -EINVAL; + vid_max_buf_size = vout->vid == OMAP_VIDEO1 ? video1_bufsize : + video2_bufsize; + if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type) return -EINVAL; @@ -689,7 +693,7 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count, video1_numbuffers : video2_numbuffers; /* Check the size of the buffer */ - if (*size > vout->buffer_size) { + if (*size > vid_max_buf_size) { v4l2_err(&vout->vid_dev->v4l2_dev, "buffer allocation mismatch [%u] [%u]\n", *size, vout->buffer_size); -- cgit v0.10.2 From 2780168859645353086b98492a979ae97da0a2dc Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Wed, 28 Sep 2011 10:49:25 -0300 Subject: [media] OMAP_VOUT: CLEANUP: Remove redundant code from omap_vout_isr Currently, there is a lot of redundant code is between DPI and VENC panels, this can be made common by moving out field/interlace specific code to a separate function called omapvid_handle_interlace_display(). There is no functional change made. Signed-off-by: Archit Taneja Reviewed-by: Sumit Semwal Acked-by: Vaibhav Hiremath Signed-off-by: Vaibhav Hiremath Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index 11f5638..7bfe577 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -523,10 +523,50 @@ static int omapvid_apply_changes(struct omap_vout_device *vout) return 0; } +static int omapvid_handle_interlace_display(struct omap_vout_device *vout, + unsigned int irqstatus, struct timeval timevalue) +{ + u32 fid; + + if (vout->first_int) { + vout->first_int = 0; + goto err; + } + + if (irqstatus & DISPC_IRQ_EVSYNC_ODD) + fid = 1; + else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN) + fid = 0; + else + goto err; + + vout->field_id ^= 1; + if (fid != vout->field_id) { + if (fid == 0) + vout->field_id = fid; + } else if (0 == fid) { + if (vout->cur_frm == vout->next_frm) + goto err; + + vout->cur_frm->ts = timevalue; + vout->cur_frm->state = VIDEOBUF_DONE; + wake_up_interruptible(&vout->cur_frm->done); + vout->cur_frm = vout->next_frm; + } else { + if (list_empty(&vout->dma_queue) || + (vout->cur_frm != vout->next_frm)) + goto err; + } + + return vout->field_id; +err: + return 0; +} + static void omap_vout_isr(void *arg, unsigned int irqstatus) { - int ret; - u32 addr, fid; + int ret, fid; + u32 addr; struct omap_overlay *ovl; struct timeval timevalue; struct omapvideo_info *ovid; @@ -547,107 +587,59 @@ static void omap_vout_isr(void *arg, unsigned int irqstatus) spin_lock(&vout->vbq_lock); do_gettimeofday(&timevalue); - if (cur_display->type != OMAP_DISPLAY_TYPE_VENC) { - switch (cur_display->type) { - case OMAP_DISPLAY_TYPE_DPI: - if (!(irqstatus & (DISPC_IRQ_VSYNC | DISPC_IRQ_VSYNC2))) - goto vout_isr_err; - break; - case OMAP_DISPLAY_TYPE_HDMI: - if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN)) - goto vout_isr_err; - break; - default: + switch (cur_display->type) { + case OMAP_DISPLAY_TYPE_DPI: + if (!(irqstatus & (DISPC_IRQ_VSYNC | DISPC_IRQ_VSYNC2))) goto vout_isr_err; - } - if (!vout->first_int && (vout->cur_frm != vout->next_frm)) { - vout->cur_frm->ts = timevalue; - vout->cur_frm->state = VIDEOBUF_DONE; - wake_up_interruptible(&vout->cur_frm->done); - vout->cur_frm = vout->next_frm; - } - vout->first_int = 0; - if (list_empty(&vout->dma_queue)) + break; + case OMAP_DISPLAY_TYPE_VENC: + fid = omapvid_handle_interlace_display(vout, irqstatus, + timevalue); + if (!fid) goto vout_isr_err; + break; + case OMAP_DISPLAY_TYPE_HDMI: + if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN)) + goto vout_isr_err; + break; + default: + goto vout_isr_err; + } - vout->next_frm = list_entry(vout->dma_queue.next, - struct videobuf_buffer, queue); - list_del(&vout->next_frm->queue); - - vout->next_frm->state = VIDEOBUF_ACTIVE; - - addr = (unsigned long) vout->queued_buf_addr[vout->next_frm->i] - + vout->cropped_offset; + if (!vout->first_int && (vout->cur_frm != vout->next_frm)) { + vout->cur_frm->ts = timevalue; + vout->cur_frm->state = VIDEOBUF_DONE; + wake_up_interruptible(&vout->cur_frm->done); + vout->cur_frm = vout->next_frm; + } - /* First save the configuration in ovelray structure */ - ret = omapvid_init(vout, addr); - if (ret) - printk(KERN_ERR VOUT_NAME - "failed to set overlay info\n"); - /* Enable the pipeline and set the Go bit */ - ret = omapvid_apply_changes(vout); - if (ret) - printk(KERN_ERR VOUT_NAME "failed to change mode\n"); - } else { + vout->first_int = 0; + if (list_empty(&vout->dma_queue)) + goto vout_isr_err; - if (vout->first_int) { - vout->first_int = 0; - goto vout_isr_err; - } - if (irqstatus & DISPC_IRQ_EVSYNC_ODD) - fid = 1; - else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN) - fid = 0; - else - goto vout_isr_err; + vout->next_frm = list_entry(vout->dma_queue.next, + struct videobuf_buffer, queue); + list_del(&vout->next_frm->queue); - vout->field_id ^= 1; - if (fid != vout->field_id) { - if (0 == fid) - vout->field_id = fid; + vout->next_frm->state = VIDEOBUF_ACTIVE; - goto vout_isr_err; - } - if (0 == fid) { - if (vout->cur_frm == vout->next_frm) - goto vout_isr_err; - - vout->cur_frm->ts = timevalue; - vout->cur_frm->state = VIDEOBUF_DONE; - wake_up_interruptible(&vout->cur_frm->done); - vout->cur_frm = vout->next_frm; - } else if (1 == fid) { - if (list_empty(&vout->dma_queue) || - (vout->cur_frm != vout->next_frm)) - goto vout_isr_err; - - vout->next_frm = list_entry(vout->dma_queue.next, - struct videobuf_buffer, queue); - list_del(&vout->next_frm->queue); - - vout->next_frm->state = VIDEOBUF_ACTIVE; - addr = (unsigned long) - vout->queued_buf_addr[vout->next_frm->i] + - vout->cropped_offset; - /* First save the configuration in ovelray structure */ - ret = omapvid_init(vout, addr); - if (ret) - printk(KERN_ERR VOUT_NAME - "failed to set overlay info\n"); - /* Enable the pipeline and set the Go bit */ - ret = omapvid_apply_changes(vout); - if (ret) - printk(KERN_ERR VOUT_NAME - "failed to change mode\n"); - } + addr = (unsigned long) vout->queued_buf_addr[vout->next_frm->i] + + vout->cropped_offset; - } + /* First save the configuration in ovelray structure */ + ret = omapvid_init(vout, addr); + if (ret) + printk(KERN_ERR VOUT_NAME + "failed to set overlay info\n"); + /* Enable the pipeline and set the Go bit */ + ret = omapvid_apply_changes(vout); + if (ret) + printk(KERN_ERR VOUT_NAME "failed to change mode\n"); vout_isr_err: spin_unlock(&vout->vbq_lock); } - /* Video buffer call backs */ /* -- cgit v0.10.2 From e144ca6426655aec8ec828e339ac57a3e00fefd0 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Wed, 28 Sep 2011 10:49:26 -0300 Subject: [media] OMAP_VOUT: Fix VSYNC IRQ handling in omap_vout_isr Currently, in omap_vout_isr(), if the panel type is DPI, and if we get either VSYNC or VSYNC2 interrupts, we proceed ahead to set the current buffers state to VIDEOBUF_DONE and prepare to display the next frame in the queue. On OMAP4, because we have 2 LCD managers, the panel type itself is not sufficient to tell if we have received the correct irq, i.e, we shouldn't proceed ahead if we get a VSYNC interrupt for LCD2 manager, or a VSYNC2 interrupt for LCD manager. Fix this by correlating LCD manager to VSYNC interrupt and LCD2 manager to VSYNC2 interrupt. Signed-off-by: Archit Taneja Reviewed-by: Sumit Semwal Acked-by: Vaibhav Hiremath Signed-off-by: Vaibhav Hiremath Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index 7bfe577..c344d59 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -565,8 +565,8 @@ err: static void omap_vout_isr(void *arg, unsigned int irqstatus) { - int ret, fid; - u32 addr; + int ret, fid, mgr_id; + u32 addr, irq; struct omap_overlay *ovl; struct timeval timevalue; struct omapvideo_info *ovid; @@ -582,6 +582,7 @@ static void omap_vout_isr(void *arg, unsigned int irqstatus) if (!ovl->manager || !ovl->manager->device) return; + mgr_id = ovl->manager->id; cur_display = ovl->manager->device; spin_lock(&vout->vbq_lock); @@ -589,7 +590,14 @@ static void omap_vout_isr(void *arg, unsigned int irqstatus) switch (cur_display->type) { case OMAP_DISPLAY_TYPE_DPI: - if (!(irqstatus & (DISPC_IRQ_VSYNC | DISPC_IRQ_VSYNC2))) + if (mgr_id == OMAP_DSS_CHANNEL_LCD) + irq = DISPC_IRQ_VSYNC; + else if (mgr_id == OMAP_DSS_CHANNEL_LCD2) + irq = DISPC_IRQ_VSYNC2; + else + goto vout_isr_err; + + if (!(irqstatus & irq)) goto vout_isr_err; break; case OMAP_DISPLAY_TYPE_VENC: -- cgit v0.10.2 From 881a9640112f89fbe2ffdcec2b06ab163739595f Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Wed, 28 Sep 2011 10:49:27 -0300 Subject: [media] OMAP_VOUT: Add support for DSI panels Add support for DSI panels. DSI video mode panels will work directly. For command mode panels, we will need to trigger updates regularly. This isn't done by the omap_vout driver currently. It can still be supported if we connect a framebuffer device to the panel and configure it in auto update mode. Signed-off-by: Archit Taneja Acked-by: Vaibhav Hiremath Signed-off-by: Vaibhav Hiremath Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index c344d59..def6472 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -589,6 +589,7 @@ static void omap_vout_isr(void *arg, unsigned int irqstatus) do_gettimeofday(&timevalue); switch (cur_display->type) { + case OMAP_DISPLAY_TYPE_DSI: case OMAP_DISPLAY_TYPE_DPI: if (mgr_id == OMAP_DSS_CHANNEL_LCD) irq = DISPC_IRQ_VSYNC; -- cgit v0.10.2 From cfb128ed0768320c2d0e43cf781c8eaa622876b6 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Wed, 28 Sep 2011 10:49:28 -0300 Subject: [media] OMAP_VOUT: Increase MAX_DISPLAYS to a larger value There is no limit to the number of displays that can registered with DSS2. The current value of MAX_DISPLAYS is 3, set this to 10 so that the 'displays' member of omap2video_device struct can store more omap_dss_device pointers. This fixes a crash seen in omap_vout_probe when DSS2 registers for more than 3 displays. Signed-off-by: Archit Taneja Acked-by: Vaibhav Hiremath Signed-off-by: Vaibhav Hiremath Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/omap/omap_voutdef.h b/drivers/media/video/omap/omap_voutdef.h index d793501..27a95d2 100644 --- a/drivers/media/video/omap/omap_voutdef.h +++ b/drivers/media/video/omap/omap_voutdef.h @@ -25,7 +25,7 @@ #define MAC_VRFB_CTXS 4 #define MAX_VOUT_DEV 2 #define MAX_OVLS 3 -#define MAX_DISPLAYS 3 +#define MAX_DISPLAYS 10 #define MAX_MANAGERS 3 #define QQVGA_WIDTH 160 -- cgit v0.10.2 From c27e3050378ec0d96d964cbf18746a30ad00ab9f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 22 Oct 2011 04:57:54 -0300 Subject: [media] v4l: mt9p031/mt9t001: Use i2c_smbus_{read|write}_word_swapped() The MT9P031 and MT9T001 sensors transfer 16-bit data on the I2C bus in swapped order. Let the I2C core handle byte order by using the i2c_smbus_{read|write}_word_swapped() functions. Signed-off-by: Laurent Pinchart Acked-by: Jonathan Cameron Acked-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/mt9p031.c b/drivers/media/video/mt9p031.c index 73c0689..93c3ec7 100644 --- a/drivers/media/video/mt9p031.c +++ b/drivers/media/video/mt9p031.c @@ -132,13 +132,12 @@ static struct mt9p031 *to_mt9p031(struct v4l2_subdev *sd) static int mt9p031_read(struct i2c_client *client, u8 reg) { - s32 data = i2c_smbus_read_word_data(client, reg); - return data < 0 ? data : be16_to_cpu(data); + return i2c_smbus_read_word_swapped(client, reg); } static int mt9p031_write(struct i2c_client *client, u8 reg, u16 data) { - return i2c_smbus_write_word_data(client, reg, cpu_to_be16(data)); + return i2c_smbus_write_word_swapped(client, reg, data); } static int mt9p031_set_output_control(struct mt9p031 *mt9p031, u16 clear, diff --git a/drivers/media/video/mt9t001.c b/drivers/media/video/mt9t001.c index 08074b8..cd81d04a 100644 --- a/drivers/media/video/mt9t001.c +++ b/drivers/media/video/mt9t001.c @@ -133,13 +133,12 @@ static inline struct mt9t001 *to_mt9t001(struct v4l2_subdev *sd) static int mt9t001_read(struct i2c_client *client, u8 reg) { - s32 data = i2c_smbus_read_word_data(client, reg); - return data < 0 ? data : be16_to_cpu(data); + return i2c_smbus_read_word_swapped(client, reg); } static int mt9t001_write(struct i2c_client *client, u8 reg, u16 data) { - return i2c_smbus_write_word_data(client, reg, cpu_to_be16(data)); + return i2c_smbus_write_word_swapped(client, reg, data); } static int mt9t001_set_output_control(struct mt9t001 *mt9t001, u16 clear, -- cgit v0.10.2 From a61f96bc3abccc8b41e422da8e808eb685527305 Mon Sep 17 00:00:00 2001 From: sensoray-dev Date: Mon, 24 Oct 2011 19:46:52 -0300 Subject: [media] saa7134: adding Sensoray boards to saa7134 driver commit cf5886c3dd2f65c817cb6ca5e7202fa3a3bdc872 Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 7efae9b..e7ef38a 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -186,3 +186,4 @@ 185 -> MagicPro ProHDTV Pro2 DMB-TH/Hybrid [17de:d136] 186 -> Beholder BeholdTV 501 [5ace:5010] 187 -> Beholder BeholdTV 503 FM [5ace:5030] +188 -> Sensoray 811/911 [6000:0811,6000:0911] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 0f9fb99..065d0f6 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5691,6 +5691,27 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }, }, + [SAA7134_BOARD_SENSORAY811_911] = { + .name = "Sensoray 811/911", + .audio_clock = 0x00200000, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = name_comp1, + .vmux = 0, + .amux = LINE1, + }, { + .name = name_comp3, + .vmux = 2, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + }, }; @@ -6914,6 +6935,18 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0xd136, .driver_data = SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2, }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x6000, + .subdevice = 0x0811, + .driver_data = SAA7134_BOARD_SENSORAY811_911, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x6000, + .subdevice = 0x0911, + .driver_data = SAA7134_BOARD_SENSORAY811_911, + }, { /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 9b55068..4ad9de4 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -330,6 +330,7 @@ struct saa7134_card_ir { #define SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2 185 #define SAA7134_BOARD_BEHOLD_501 186 #define SAA7134_BOARD_BEHOLD_503FM 187 +#define SAA7134_BOARD_SENSORAY811_911 188 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 -- cgit v0.10.2 From 57437c1da54e5cf7d536d72d61e77ebeb528a87d Mon Sep 17 00:00:00 2001 From: sensoray-dev Date: Tue, 25 Oct 2011 19:43:55 -0300 Subject: [media] bttv: adding Sensoray 611 board to driver commit affebd4db94b459f676a14d9bb696c3c2b73643d [media] bttv: adding Sensoray 611 board to bttv driver Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index 4739d56..8948da4 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -71,7 +71,7 @@ 70 -> Prolink Pixelview PV-BT878P+ (Rev.4C,8E) 71 -> Lifeview FlyVideo 98EZ (capture only) LR51 [1851:1851] 72 -> Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM) [1554:4011] - 73 -> Sensoray 311 [6000:0311] + 73 -> Sensoray 311/611 [6000:0311,6000:0611] 74 -> RemoteVision MX (RV605) 75 -> Powercolor MTV878/ MTV878R/ MTV878F 76 -> Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP) [0e11:0079] diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 5939021..076b7f2 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -284,7 +284,8 @@ static struct CARD { { 0x10b42636, BTTV_BOARD_HAUPPAUGE878, "STB ???" }, { 0x217d6606, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" }, { 0xfff6f6ff, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" }, - { 0x03116000, BTTV_BOARD_SENSORAY311, "Sensoray 311" }, + { 0x03116000, BTTV_BOARD_SENSORAY311_611, "Sensoray 311" }, + { 0x06116000, BTTV_BOARD_SENSORAY311_611, "Sensoray 611" }, { 0x00790e11, BTTV_BOARD_WINDVR, "Canopus WinDVR PCI" }, { 0xa0fca1a0, BTTV_BOARD_ZOLTRIX, "Face to Face Tvmax" }, { 0x82b2aa6a, BTTV_BOARD_SIMUS_GVC1100, "SIMUS GVC1100" }, @@ -1526,10 +1527,10 @@ struct tvcard bttv_tvcards[] = { GPIO20,22,23: R30,R29,R28 */ }, - [BTTV_BOARD_SENSORAY311] = { + [BTTV_BOARD_SENSORAY311_611] = { /* Clay Kunz */ - /* you must jumper JP5 for the card to work */ - .name = "Sensoray 311", + /* you must jumper JP5 for the 311 card (PC/104+) to work */ + .name = "Sensoray 311/611", .video_inputs = 5, /* .audio_inputs= 0, */ .svhs = 4, diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index c633359..4db8b7d 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -96,7 +96,7 @@ #define BTTV_BOARD_PV_BT878P_PLUS 0x46 #define BTTV_BOARD_FLYVIDEO98EZ 0x47 #define BTTV_BOARD_PV_BT878P_9B 0x48 -#define BTTV_BOARD_SENSORAY311 0x49 +#define BTTV_BOARD_SENSORAY311_611 0x49 #define BTTV_BOARD_RV605 0x4a #define BTTV_BOARD_POWERCLR_MTV878 0x4b #define BTTV_BOARD_WINDVR 0x4c -- cgit v0.10.2 From 318cde38af41fefdd03a7e42c9fb70e9719ed83f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 7 Nov 2011 12:01:49 -0200 Subject: [media] Update some CARDLIST's Re-run the cardlist script, in order to update the cardlists for a few drivers, to sync with the driver changes. Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index 8910449..99acaa3 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -29,3 +29,5 @@ 28 -> LEADTEK WinFast PxTV1200 [107d:6f22] 29 -> GoTView X5 3D Hybrid [5654:2390] 30 -> NetUP Dual DVB-T/C-CI RF [1b55:e2e4] + 31 -> Leadtek Winfast PxDVR3200 H XC4000 [107d:6f39] + 32 -> MPX-885 diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index d9c0f11..eee18e6 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -85,3 +85,5 @@ 84 -> Samsung SMT 7020 DVB-S [18ac:dc00,18ac:dccd] 85 -> Twinhan VP-1027 DVB-S [1822:0023] 86 -> TeVii S464 DVB-S/S2 [d464:9022] + 87 -> Leadtek WinFast DTV2000 H PLUS [107d:6f42] + 88 -> Leadtek WinFast DTV1800 H (XC4000) [107d:6f38] diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 4a7b3df..d8c8544 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -11,7 +11,7 @@ 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500] 11 -> Terratec Hybrid XS (em2880) 12 -> Kworld PVR TV 2800 RF (em2820/em2840) - 13 -> Terratec Prodigy XS (em2880) [0ccd:0047] + 13 -> Terratec Prodigy XS (em2880) [0ccd:10ad] 14 -> SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0 (em2820/em2840) 15 -> V-Gear PocketTV (em2800) 16 -> Hauppauge WinTV HVR 950 (em2883) [2040:6513,2040:6517,2040:651b] @@ -41,7 +41,7 @@ 40 -> Plextor ConvertX PX-TV100U (em2861) [093b:a005] 41 -> Kworld 350 U DVB-T (em2870) [eb1a:e350] 42 -> Kworld 355 U DVB-T (em2870) [eb1a:e355,eb1a:e357] - 43 -> Terratec Cinergy T XS (em2870) [0ccd:0043] + 43 -> Terratec Cinergy T XS (em2870) 44 -> Terratec Cinergy T XS (MT2060) (em2870) 45 -> Pinnacle PCTV DVB-T (em2870) 46 -> Compro, VideoMate U3 (em2870) [185b:2870] @@ -64,7 +64,7 @@ 64 -> Easy Cap Capture DC-60 (em2860) 65 -> IO-DATA GV-MVP/SZ (em2820/em2840) [04bb:0515] 66 -> Empire dual TV (em2880) - 67 -> Terratec Grabby (em2860) [0ccd:0096] + 67 -> Terratec Grabby (em2860) [0ccd:0096,0ccd:10AF] 68 -> Terratec AV350 (em2860) [0ccd:0084] 69 -> KWorld ATSC 315U HDTV TV Box (em2882) [eb1a:a313] 70 -> Evga inDtube (em2882) @@ -76,3 +76,5 @@ 76 -> KWorld PlusTV 340U or UB435-Q (ATSC) (em2870) [1b80:a340] 77 -> EM2874 Leadership ISDBT (em2874) 78 -> PCTV nanoStick T2 290e (em28174) + 79 -> Terratec Cinergy H5 (em2884) [0ccd:0043,0ccd:10a2] + 80 -> PCTV DVB-S2 Stick (460e) (em28174) diff --git a/Documentation/video4linux/CARDLIST.saa7164 b/Documentation/video4linux/CARDLIST.saa7164 index 152bd7b..2205e8d 100644 --- a/Documentation/video4linux/CARDLIST.saa7164 +++ b/Documentation/video4linux/CARDLIST.saa7164 @@ -7,3 +7,5 @@ 6 -> Hauppauge WinTV-HVR2200 [0070:8901] 7 -> Hauppauge WinTV-HVR2250 [0070:8891,0070:8851] 8 -> Hauppauge WinTV-HVR2250 [0070:88A1] + 9 -> Hauppauge WinTV-HVR2200 [0070:8940] + 10 -> Hauppauge WinTV-HVR2200 [0070:8953] -- cgit v0.10.2 From 9c900f02385cb18e1a6c65d22a7acbb8c73c07c2 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 26 Oct 2011 09:16:50 -0300 Subject: [media] via-camera: disable RGB mode The RGB mode does not work correctly. It captures fine at 640x480 but whenever the scaling engine is used to produce another resolution, color corruption occurs (lots of erroneous pink and green). It is not clear how the scaling engine is supposed to work and how it knows which pixel format it is dealing with. Work around this problem by disabling RGB support. YUYV scaling works just fine. Test case: gst-launch v4l2src ! video/x-raw-rgb,bpp=16,width=320,height=240 ! \ ffmpegcolorspace ! xvimagesink Signed-off-by: Daniel Drake Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/via-camera.c b/drivers/media/video/via-camera.c index cbf13d0..6a82875 100644 --- a/drivers/media/video/via-camera.c +++ b/drivers/media/video/via-camera.c @@ -156,14 +156,10 @@ static struct via_format { .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, .bpp = 2, }, - { - .desc = "RGB 565", - .pixelformat = V4L2_PIX_FMT_RGB565, - .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, - .bpp = 2, - }, /* RGB444 and Bayer should be doable, but have never been - tested with this driver. */ + tested with this driver. RGB565 seems to work at the default + resolution, but results in color corruption when being scaled by + viacam_set_scaled(), and is disabled as a result. */ }; #define N_VIA_FMTS ARRAY_SIZE(via_formats) -- cgit v0.10.2 From fabade547fd306cd3e8b1dc068ccdfec2553bad5 Mon Sep 17 00:00:00 2001 From: Dmitri Belimov Date: Thu, 23 Apr 2009 01:40:46 -0300 Subject: [media] FM1216ME_MK3 AUX byte for FM mode Write AUX byte to FM1216ME_MK3 when FM mode, better sensitivity. It can be usefull for other tuners. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c index f8ee29e..4092200 100644 --- a/drivers/media/common/tuners/tuner-simple.c +++ b/drivers/media/common/tuners/tuner-simple.c @@ -751,6 +751,17 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, if (4 != rc) tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc); + /* Write AUX byte */ + switch (priv->type) { + case TUNER_PHILIPS_FM1216ME_MK3: + buffer[2] = 0x98; + buffer[3] = 0x20; /* set TOP AGC */ + rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); + if (4 != rc) + tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc); + break; + } + return 0; } -- cgit v0.10.2 From 0d37d35035cb41f01e12082fa6b39a2e465ca4ba Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Thu, 27 Oct 2011 18:50:21 -0300 Subject: [media] Make use of media bus pixel codes in adv7170 driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ADV7170/ADV7171 can operate in either 8-bit or 16-bit YCrCb Mode. * 8-Bit YCrCb Mode This default mode accepts multiplexed YCrCb inputs through the P7-P0 pixel inputs. The inputs follow the sequence Cb0, Y0 Cr0, Y1 Cb1, Y2, etc. The Y, Cb and Cr data are input on a rising clock edge. * 16-Bit YCrCb Mode This mode accepts Y inputs through the P7–P0 pixel inputs and multiplexed CrCb inputs through the P15–P8 pixel inputs. The data is loaded on every second rising edge of CLOCK. The inputs follow the sequence Cb0, Y0 Cr0, Y1 Cb1, Y2, etc. Signed-off-by: Christian Gmeiner Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index 23ba5c3..879f1d8 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -64,6 +64,11 @@ static inline struct adv7170 *to_adv7170(struct v4l2_subdev *sd) static char *inputs[] = { "pass_through", "play_back" }; +static enum v4l2_mbus_pixelcode adv7170_codes[] = { + V4L2_MBUS_FMT_UYVY8_2X8, + V4L2_MBUS_FMT_UYVY8_1X16, +}; + /* ----------------------------------------------------------------------- */ static inline int adv7170_write(struct v4l2_subdev *sd, u8 reg, u8 value) @@ -258,6 +263,60 @@ static int adv7170_s_routing(struct v4l2_subdev *sd, return 0; } +static int adv7170_enum_fmt(struct v4l2_subdev *sd, unsigned int index, + enum v4l2_mbus_pixelcode *code) +{ + if (index >= ARRAY_SIZE(adv7170_codes)) + return -EINVAL; + + *code = adv7170_codes[index]; + return 0; +} + +static int adv7170_g_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) +{ + u8 val = adv7170_read(sd, 0x7); + + if ((val & 0x40) == (1 << 6)) + mf->code = V4L2_MBUS_FMT_UYVY8_1X16; + else + mf->code = V4L2_MBUS_FMT_UYVY8_2X8; + + mf->colorspace = V4L2_COLORSPACE_SMPTE170M; + mf->width = 0; + mf->height = 0; + mf->field = V4L2_FIELD_ANY; + + return 0; +} + +static int adv7170_s_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) +{ + u8 val = adv7170_read(sd, 0x7); + int ret; + + switch (mf->code) { + case V4L2_MBUS_FMT_UYVY8_2X8: + val &= ~0x40; + break; + + case V4L2_MBUS_FMT_UYVY8_1X16: + val |= 0x40; + break; + + default: + v4l2_dbg(1, debug, sd, + "illegal v4l2_mbus_framefmt code: %d\n", mf->code); + return -EINVAL; + } + + ret = adv7170_write(sd, 0x7, val); + + return ret; +} + static int adv7170_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -274,6 +333,9 @@ static const struct v4l2_subdev_core_ops adv7170_core_ops = { static const struct v4l2_subdev_video_ops adv7170_video_ops = { .s_std_output = adv7170_s_std_output, .s_routing = adv7170_s_routing, + .s_mbus_fmt = adv7170_s_fmt, + .g_mbus_fmt = adv7170_g_fmt, + .enum_mbus_fmt = adv7170_enum_fmt, }; static const struct v4l2_subdev_ops adv7170_ops = { -- cgit v0.10.2 From 0a4524d726cd4d109c57fc194a55ff0a9e4df0e9 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 28 Oct 2011 19:58:16 -0300 Subject: [media] drivers/media/video/atmel-isi.c: eliminate a null pointer dereference The variable isi might be null or might be freed at the point of the call to clk_put. pclk contains the value that isi->pclk is expected to point to. The semantic match that finds this problem is as follows: // @r@ expression E, E1; identifier f; statement S1,S2,S3; @@ if (E == NULL) { ... when != if (E == NULL || ...) S1 else S2 when != E = E1 *E->f ... when any return ...; } else S3 // Signed-off-by: Julia Lawall Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/video/atmel-isi.c index 8c775c5..fbc904f 100644 --- a/drivers/media/video/atmel-isi.c +++ b/drivers/media/video/atmel-isi.c @@ -1036,7 +1036,7 @@ err_alloc_ctx: err_alloc_descriptors: kfree(isi); err_alloc_isi: - clk_put(isi->pclk); + clk_put(pclk); return ret; } -- cgit v0.10.2 From 49a0513c1fca2c43b14416f3f40220fa01ab5e39 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 28 Oct 2011 19:58:17 -0300 Subject: [media] drivers/media/video/davinci/vpbe_display.c: eliminate a null pointer dereference In the original code, probe_out could be reached when res was null and then when the irq had not yet been requested. In those cases, the call to free_irq is not needed, so move probe_out down and introduce a new label for the case where calling free_irq is useful. The semantic match that finds this problem is as follows: // @r@ expression E, E1; identifier f; statement S1,S2,S3; @@ if (E == NULL) { ... when != if (E == NULL || ...) S1 else S2 when != E = E1 *E->f ... when any return ...; } else S3 // Signed-off-by: Julia Lawall Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/davinci/vpbe_display.c b/drivers/media/video/davinci/vpbe_display.c index 8588a86..d98da4b 100644 --- a/drivers/media/video/davinci/vpbe_display.c +++ b/drivers/media/video/davinci/vpbe_display.c @@ -1746,15 +1746,16 @@ static __devinit int vpbe_display_probe(struct platform_device *pdev) for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) { if (register_device(disp_dev->dev[i], disp_dev, pdev)) { err = -ENODEV; - goto probe_out; + goto probe_out_irq; } } printk(KERN_DEBUG "Successfully completed the probing of vpbe v4l2 device\n"); return 0; -probe_out: +probe_out_irq: free_irq(res->start, disp_dev); +probe_out: for (k = 0; k < VPBE_DISPLAY_MAX_DEVICES; k++) { /* Get the pointer to the layer object */ vpbe_display_layer = disp_dev->dev[k]; -- cgit v0.10.2 From 5279b1ff3699153a53d7ca030b5fb95950001c36 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 31 Oct 2011 08:11:00 -0300 Subject: [media] au8522: Calculate signal strength shown as percentage from SNR up to 35dB As done first in lgdt330x.c, calculate signal strength from SNR up to 35dB Even though the SNR can go higher than 35dB, there is some comfort factor in having a range of strong signals that can show at 100% Signed-off-by: Michael Krufky Signed-off-by: Devin Heitmueller Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/au8522_dig.c b/drivers/media/dvb/frontends/au8522_dig.c index 1d57294..5c0d398 100644 --- a/drivers/media/dvb/frontends/au8522_dig.c +++ b/drivers/media/dvb/frontends/au8522_dig.c @@ -862,7 +862,36 @@ static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr) static int au8522_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength) { - return au8522_read_snr(fe, signal_strength); + /* borrowed from lgdt330x.c + * + * Calculate strength from SNR up to 35dB + * Even though the SNR can go higher than 35dB, + * there is some comfort factor in having a range of + * strong signals that can show at 100% + */ + u16 snr; + u32 tmp; + int ret = au8522_read_snr(fe, &snr); + + *signal_strength = 0; + + if (0 == ret) { + /* The following calculation method was chosen + * purely for the sake of code re-use from the + * other demod drivers that use this method */ + + /* Convert from SNR in dB * 10 to 8.24 fixed-point */ + tmp = (snr * ((1 << 24) / 10)); + + /* Convert from 8.24 fixed-point to + * scale the range 0 - 35*2^24 into 0 - 65535*/ + if (tmp >= 8960 * 0x10000) + *signal_strength = 0xffff; + else + *signal_strength = tmp / 8960; + } + + return ret; } static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -- cgit v0.10.2 From 19661c08fe11590e04832ed8b3cabe5e4bf11e48 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 31 Oct 2011 08:12:18 -0300 Subject: [media] s5h1409: Calculate signal strength shown as percentage from SNR up to 35dB As done first in lgdt330x.c, calculate signal strength from SNR up to 35dB Even though the SNR can go higher than 35dB, there is some comfort factor in having a range of strong signals that can show at 100% Signed-off-by: Michael Krufky Signed-off-by: Devin Heitmueller Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c index 0e2f61a..0d6d5e3 100644 --- a/drivers/media/dvb/frontends/s5h1409.c +++ b/drivers/media/dvb/frontends/s5h1409.c @@ -879,7 +879,36 @@ static int s5h1409_read_snr(struct dvb_frontend *fe, u16 *snr) static int s5h1409_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength) { - return s5h1409_read_snr(fe, signal_strength); + /* borrowed from lgdt330x.c + * + * Calculate strength from SNR up to 35dB + * Even though the SNR can go higher than 35dB, + * there is some comfort factor in having a range of + * strong signals that can show at 100% + */ + u16 snr; + u32 tmp; + int ret = s5h1409_read_snr(fe, &snr); + + *signal_strength = 0; + + if (0 == ret) { + /* The following calculation method was chosen + * purely for the sake of code re-use from the + * other demod drivers that use this method */ + + /* Convert from SNR in dB * 10 to 8.24 fixed-point */ + tmp = (snr * ((1 << 24) / 10)); + + /* Convert from 8.24 fixed-point to + * scale the range 0 - 35*2^24 into 0 - 65535*/ + if (tmp >= 8960 * 0x10000) + *signal_strength = 0xffff; + else + *signal_strength = tmp / 8960; + } + + return ret; } static int s5h1409_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -- cgit v0.10.2 From ead32d5357e4aae732ccd7427073ab4bf30d3068 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 31 Oct 2011 08:12:54 -0300 Subject: [media] s5h1411: Calculate signal strength shown as percentage from SNR up to 35dB As done first in lgdt330x.c, calculate signal strength from SNR up to 35dB Even though the SNR can go higher than 35dB, there is some comfort factor in having a range of strong signals that can show at 100% Signed-off-by: Michael Krufky Signed-off-by: Devin Heitmueller Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c index d8adf1e..5fca113 100644 --- a/drivers/media/dvb/frontends/s5h1411.c +++ b/drivers/media/dvb/frontends/s5h1411.c @@ -794,7 +794,36 @@ static int s5h1411_read_snr(struct dvb_frontend *fe, u16 *snr) static int s5h1411_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength) { - return s5h1411_read_snr(fe, signal_strength); + /* borrowed from lgdt330x.c + * + * Calculate strength from SNR up to 35dB + * Even though the SNR can go higher than 35dB, + * there is some comfort factor in having a range of + * strong signals that can show at 100% + */ + u16 snr; + u32 tmp; + int ret = s5h1411_read_snr(fe, &snr); + + *signal_strength = 0; + + if (0 == ret) { + /* The following calculation method was chosen + * purely for the sake of code re-use from the + * other demod drivers that use this method */ + + /* Convert from SNR in dB * 10 to 8.24 fixed-point */ + tmp = (snr * ((1 << 24) / 10)); + + /* Convert from 8.24 fixed-point to + * scale the range 0 - 35*2^24 into 0 - 65535*/ + if (tmp >= 8960 * 0x10000) + *signal_strength = 0xffff; + else + *signal_strength = tmp / 8960; + } + + return ret; } static int s5h1411_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -- cgit v0.10.2 From b7d425d39179e125604cbf451a06d3204d2e1398 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Mon, 31 Oct 2011 12:02:08 -0300 Subject: [media] it913x Support it9135 Verions 2 chip Support for version 2 type chips and other LNA versions of version 1 Scripts may be compressed slightly at a later stage. TODO Firmware loader However, things are a little confusing, it is not clear that dvb-usb-it9137-01.fw does not work with version 2 chips as in recent files both firmwares are the same. Should be applied to: 8133 Support for single ITE 9135 device. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c index c462261..a541904 100644 --- a/drivers/media/dvb/dvb-usb/it913x.c +++ b/drivers/media/dvb/dvb-usb/it913x.c @@ -60,15 +60,6 @@ struct it913x_state { u8 id; }; -struct ite_config { - u8 chip_ver; - u16 chip_type; - u32 firmware; - u8 tuner_id_0; - u8 tuner_id_1; - u8 dual_mode; -}; - struct ite_config it913x_config; static int it913x_bulk_write(struct usb_device *dev, @@ -390,8 +381,8 @@ static int it913x_identify_state(struct usb_device *udev, if (ret != 0) ret = it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x0); + props->num_adapters = 2; } - props->num_adapters = 2; } else props->num_adapters = 1; @@ -474,12 +465,17 @@ static int it913x_download_firmware(struct usb_device *udev, /* Tuner function */ if (it913x_config.dual_mode) ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0xa0); - - ret |= it913x_wr_reg(udev, DEV_0, PADODPU, 0x0); - ret |= it913x_wr_reg(udev, DEV_0, AGC_O_D, 0x0); - if (it913x_config.dual_mode) { - ret |= it913x_wr_reg(udev, DEV_1, PADODPU, 0x0); - ret |= it913x_wr_reg(udev, DEV_1, AGC_O_D, 0x0); + else + ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0x68); + + if ((it913x_config.chip_ver == 1) && + (it913x_config.chip_type == 0x9135)) { + ret |= it913x_wr_reg(udev, DEV_0, PADODPU, 0x0); + ret |= it913x_wr_reg(udev, DEV_0, AGC_O_D, 0x0); + if (it913x_config.dual_mode) { + ret |= it913x_wr_reg(udev, DEV_1, PADODPU, 0x0); + ret |= it913x_wr_reg(udev, DEV_1, AGC_O_D, 0x0); + } } return (ret < 0) ? -ENODEV : 0; @@ -501,31 +497,13 @@ static int it913x_frontend_attach(struct dvb_usb_adapter *adap) { struct usb_device *udev = adap->dev->udev; int ret = 0; - u8 adf = it913x_read_reg(udev, IO_MUX_POWER_CLK); u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5); u16 ep_size = adap->props.fe[0].stream.u.bulk.buffersize; - u8 tuner_id, tuner_type; - if (adap->id == 0) - tuner_id = it913x_config.tuner_id_0; - else - tuner_id = it913x_config.tuner_id_1; - - /* TODO we always use IT9137 possible references here*/ - /* Documentation suggests don't care */ - switch (tuner_id) { - case 0x51: - case 0x52: - case 0x60: - case 0x61: - case 0x62: - default: - case 0x38: - tuner_type = IT9137; - } + it913x_config.adf = it913x_read_reg(udev, IO_MUX_POWER_CLK); adap->fe_adap[0].fe = dvb_attach(it913x_fe_attach, - &adap->dev->i2c_adap, adap_addr, adf, tuner_type); + &adap->dev->i2c_adap, adap_addr, &it913x_config); if (adap->id == 0 && adap->fe_adap[0].fe) { ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x1); @@ -698,5 +676,5 @@ module_exit(it913x_module_exit); MODULE_AUTHOR("Malcolm Priestley "); MODULE_DESCRIPTION("it913x USB 2 Driver"); -MODULE_VERSION("1.07"); +MODULE_VERSION("1.08"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/it913x-fe-priv.h b/drivers/media/dvb/frontends/it913x-fe-priv.h index 1c6fb4b..abf1395 100644 --- a/drivers/media/dvb/frontends/it913x-fe-priv.h +++ b/drivers/media/dvb/frontends/it913x-fe-priv.h @@ -205,6 +205,10 @@ fe_modulation_t fe_con[] = { /* Standard demodulator functions */ static struct it913xset set_solo_fe[] = { + {PRO_LINK, GPIOH5_EN, {0x01}, 0x01}, + {PRO_LINK, GPIOH5_ON, {0x01}, 0x01}, + {PRO_LINK, GPIOH5_O, {0x00}, 0x01}, + {PRO_LINK, GPIOH5_O, {0x01}, 0x01}, {PRO_LINK, DVBT_INTEN, {0x04}, 0x01}, {PRO_LINK, DVBT_ENABLE, {0x05}, 0x01}, {PRO_DMOD, MP2IF_MPEG_PAR_MODE, {0x00}, 0x01}, @@ -233,8 +237,121 @@ static struct it913xset init_1[] = { {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */ }; -/* ---------IT9137 0x38 tuner init---------- */ -static struct it913xset it9137_set[] = { + +/* Version 1 types */ +static struct it913xset it9135_v1[] = { + {PRO_DMOD, 0x0051, {0x01}, 0x01}, + {PRO_DMOD, 0x0070, {0x0a}, 0x01}, + {PRO_DMOD, 0x007e, {0x04}, 0x01}, + {PRO_DMOD, 0x0081, {0x0a}, 0x01}, + {PRO_DMOD, 0x008a, {0x01}, 0x01}, + {PRO_DMOD, 0x008e, {0x01}, 0x01}, + {PRO_DMOD, 0x0092, {0x06}, 0x01}, + {PRO_DMOD, 0x0099, {0x01}, 0x01}, + {PRO_DMOD, 0x009f, {0xe1}, 0x01}, + {PRO_DMOD, 0x00a0, {0xcf}, 0x01}, + {PRO_DMOD, 0x00a3, {0x01}, 0x01}, + {PRO_DMOD, 0x00a5, {0x01}, 0x01}, + {PRO_DMOD, 0x00a6, {0x01}, 0x01}, + {PRO_DMOD, 0x00a9, {0x00}, 0x01}, + {PRO_DMOD, 0x00aa, {0x01}, 0x01}, + {PRO_DMOD, 0x00b0, {0x01}, 0x01}, + {PRO_DMOD, 0x00c2, {0x05}, 0x01}, + {PRO_DMOD, 0x00c6, {0x19}, 0x01}, + {PRO_DMOD, 0xf000, {0x0f}, 0x01}, + {PRO_DMOD, 0xf016, {0x10}, 0x01}, + {PRO_DMOD, 0xf017, {0x04}, 0x01}, + {PRO_DMOD, 0xf018, {0x05}, 0x01}, + {PRO_DMOD, 0xf019, {0x04}, 0x01}, + {PRO_DMOD, 0xf01a, {0x05}, 0x01}, + {PRO_DMOD, 0xf021, {0x03}, 0x01}, + {PRO_DMOD, 0xf022, {0x0a}, 0x01}, + {PRO_DMOD, 0xf023, {0x0a}, 0x01}, + {PRO_DMOD, 0xf02b, {0x00}, 0x01}, + {PRO_DMOD, 0xf02c, {0x01}, 0x01}, + {PRO_DMOD, 0xf064, {0x03}, 0x01}, + {PRO_DMOD, 0xf065, {0xf9}, 0x01}, + {PRO_DMOD, 0xf066, {0x03}, 0x01}, + {PRO_DMOD, 0xf067, {0x01}, 0x01}, + {PRO_DMOD, 0xf06f, {0xe0}, 0x01}, + {PRO_DMOD, 0xf070, {0x03}, 0x01}, + {PRO_DMOD, 0xf072, {0x0f}, 0x01}, + {PRO_DMOD, 0xf073, {0x03}, 0x01}, + {PRO_DMOD, 0xf078, {0x00}, 0x01}, + {PRO_DMOD, 0xf087, {0x00}, 0x01}, + {PRO_DMOD, 0xf09b, {0x3f}, 0x01}, + {PRO_DMOD, 0xf09c, {0x00}, 0x01}, + {PRO_DMOD, 0xf09d, {0x20}, 0x01}, + {PRO_DMOD, 0xf09e, {0x00}, 0x01}, + {PRO_DMOD, 0xf09f, {0x0c}, 0x01}, + {PRO_DMOD, 0xf0a0, {0x00}, 0x01}, + {PRO_DMOD, 0xf130, {0x04}, 0x01}, + {PRO_DMOD, 0xf132, {0x04}, 0x01}, + {PRO_DMOD, 0xf144, {0x1a}, 0x01}, + {PRO_DMOD, 0xf146, {0x00}, 0x01}, + {PRO_DMOD, 0xf14a, {0x01}, 0x01}, + {PRO_DMOD, 0xf14c, {0x00}, 0x01}, + {PRO_DMOD, 0xf14d, {0x00}, 0x01}, + {PRO_DMOD, 0xf14f, {0x04}, 0x01}, + {PRO_DMOD, 0xf158, {0x7f}, 0x01}, + {PRO_DMOD, 0xf15a, {0x00}, 0x01}, + {PRO_DMOD, 0xf15b, {0x08}, 0x01}, + {PRO_DMOD, 0xf15d, {0x03}, 0x01}, + {PRO_DMOD, 0xf15e, {0x05}, 0x01}, + {PRO_DMOD, 0xf163, {0x05}, 0x01}, + {PRO_DMOD, 0xf166, {0x01}, 0x01}, + {PRO_DMOD, 0xf167, {0x40}, 0x01}, + {PRO_DMOD, 0xf168, {0x0f}, 0x01}, + {PRO_DMOD, 0xf17a, {0x00}, 0x01}, + {PRO_DMOD, 0xf17b, {0x00}, 0x01}, + {PRO_DMOD, 0xf183, {0x01}, 0x01}, + {PRO_DMOD, 0xf19d, {0x40}, 0x01}, + {PRO_DMOD, 0xf1bc, {0x36}, 0x01}, + {PRO_DMOD, 0xf1bd, {0x00}, 0x01}, + {PRO_DMOD, 0xf1cb, {0xa0}, 0x01}, + {PRO_DMOD, 0xf1cc, {0x01}, 0x01}, + {PRO_DMOD, 0xf204, {0x10}, 0x01}, + {PRO_DMOD, 0xf214, {0x00}, 0x01}, + {PRO_DMOD, 0xf40e, {0x0a}, 0x01}, + {PRO_DMOD, 0xf40f, {0x40}, 0x01}, + {PRO_DMOD, 0xf410, {0x08}, 0x01}, + {PRO_DMOD, 0xf55f, {0x0a}, 0x01}, + {PRO_DMOD, 0xf561, {0x15}, 0x01}, + {PRO_DMOD, 0xf562, {0x20}, 0x01}, + {PRO_DMOD, 0xf5df, {0xfb}, 0x01}, + {PRO_DMOD, 0xf5e0, {0x00}, 0x01}, + {PRO_DMOD, 0xf5e3, {0x09}, 0x01}, + {PRO_DMOD, 0xf5e4, {0x01}, 0x01}, + {PRO_DMOD, 0xf5e5, {0x01}, 0x01}, + {PRO_DMOD, 0xf5f8, {0x01}, 0x01}, + {PRO_DMOD, 0xf5fd, {0x01}, 0x01}, + {PRO_DMOD, 0xf600, {0x05}, 0x01}, + {PRO_DMOD, 0xf601, {0x08}, 0x01}, + {PRO_DMOD, 0xf602, {0x0b}, 0x01}, + {PRO_DMOD, 0xf603, {0x0e}, 0x01}, + {PRO_DMOD, 0xf604, {0x11}, 0x01}, + {PRO_DMOD, 0xf605, {0x14}, 0x01}, + {PRO_DMOD, 0xf606, {0x17}, 0x01}, + {PRO_DMOD, 0xf607, {0x1f}, 0x01}, + {PRO_DMOD, 0xf60e, {0x00}, 0x01}, + {PRO_DMOD, 0xf60f, {0x04}, 0x01}, + {PRO_DMOD, 0xf610, {0x32}, 0x01}, + {PRO_DMOD, 0xf611, {0x10}, 0x01}, + {PRO_DMOD, 0xf707, {0xfc}, 0x01}, + {PRO_DMOD, 0xf708, {0x00}, 0x01}, + {PRO_DMOD, 0xf709, {0x37}, 0x01}, + {PRO_DMOD, 0xf70a, {0x00}, 0x01}, + {PRO_DMOD, 0xf78b, {0x01}, 0x01}, + {PRO_DMOD, 0xf80f, {0x40}, 0x01}, + {PRO_DMOD, 0xf810, {0x54}, 0x01}, + {PRO_DMOD, 0xf811, {0x5a}, 0x01}, + {PRO_DMOD, 0xf905, {0x01}, 0x01}, + {PRO_DMOD, 0xfb06, {0x03}, 0x01}, + {PRO_DMOD, 0xfd8b, {0x00}, 0x01}, + {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */ +}; + +static struct it913xset it9135_38[] = { {PRO_DMOD, 0x0043, {0x00}, 0x01}, {PRO_DMOD, 0x0046, {0x38}, 0x01}, {PRO_DMOD, 0x0051, {0x01}, 0x01}, @@ -244,7 +361,7 @@ static struct it913xset it9137_set[] = { {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xc8, 0x01}, 0x05}, {PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02}, {PRO_DMOD, 0x0081, { 0x0a, 0x12, 0x02, 0x0a, 0x03, 0xc8, 0xb8, - 0xd0, 0xc3, 0x01 }, 0x0a}, + 0xd0, 0xc3, 0x01}, 0x0a}, {PRO_DMOD, 0x008e, {0x01}, 0x01}, {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05}, {PRO_DMOD, 0x0099, {0x01}, 0x01}, @@ -262,15 +379,25 @@ static struct it913xset it9137_set[] = { {PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03}, {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03}, {PRO_DMOD, 0x00fc, { 0x02, 0x02, 0x02, 0x09, 0x50, 0x7b, 0x77, - 0x00, 0x02, 0xc8, 0x05, 0x7b }, 0x0c}, + 0x00, 0x02, 0xc8, 0x05, 0x7b}, 0x0c}, {PRO_DMOD, 0x0109, {0x02}, 0x01}, - {PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02}, - {PRO_DMOD, 0x011a, {0xc8, 0x7b, 0xbc, 0xa0}, 0x04}, + {PRO_DMOD, 0x0115, {0x0a, 0x03, 0x02, 0x80}, 0x04}, + {PRO_DMOD, 0x011a, {0xc8, 0x7b, 0x8a, 0xa0}, 0x04}, {PRO_DMOD, 0x0122, {0x02, 0x18, 0xc3}, 0x03}, {PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02}, {PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04}, {PRO_DMOD, 0x0137, {0x01, 0x00, 0x07, 0x00, 0x06}, 0x05}, - {PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xc8}, 0x04}, + {PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xc8, 0x59}, 0x05}, + {PRO_DMOD, 0xf000, {0x0f}, 0x01}, + {PRO_DMOD, 0xf016, {0x10, 0x04, 0x05, 0x04, 0x05}, 0x05}, + {PRO_DMOD, 0xf01f, {0x8c, 0x00, 0x03, 0x0a, 0x0a}, 0x05}, + {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00, 0x01}, 0x04}, + {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04}, + {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02}, + {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02}, + {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02}, + {PRO_DMOD, 0xf085, {0x00, 0x02, 0x00}, 0x03}, + {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06}, {PRO_DMOD, 0xf130, {0x04}, 0x01}, {PRO_DMOD, 0xf132, {0x04}, 0x01}, {PRO_DMOD, 0xf144, {0x1a}, 0x01}, @@ -301,7 +428,7 @@ static struct it913xset it9137_set[] = { {PRO_DMOD, 0xf5f8, {0x01}, 0x01}, {PRO_DMOD, 0xf5fd, {0x01}, 0x01}, {PRO_DMOD, 0xf600, { 0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17, - 0x1f }, 0x08}, + 0x1f}, 0x08}, {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04}, {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04}, {PRO_DMOD, 0xf78b, {0x01}, 0x01}, @@ -309,13 +436,578 @@ static struct it913xset it9137_set[] = { {PRO_DMOD, 0xf905, {0x01}, 0x01}, {PRO_DMOD, 0xfb06, {0x03}, 0x01}, {PRO_DMOD, 0xfd8b, {0x00}, 0x01}, - {PRO_LINK, GPIOH5_EN, {0x01}, 0x01}, - {PRO_LINK, GPIOH5_ON, {0x01}, 0x01}, - {PRO_LINK, GPIOH5_O, {0x00}, 0x01}, - {PRO_LINK, GPIOH5_O, {0x01}, 0x01}, - {0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */ + {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */ +}; + +static struct it913xset it9135_51[] = { + {PRO_DMOD, 0x0043, {0x00}, 0x01}, + {PRO_DMOD, 0x0046, {0x51}, 0x01}, + {PRO_DMOD, 0x0051, {0x01}, 0x01}, + {PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02}, + {PRO_DMOD, 0x0068, {0x0a}, 0x01}, + {PRO_DMOD, 0x0070, {0x0a, 0x06, 0x02}, 0x03}, + {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xc8, 0x01}, 0x05}, + {PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02}, + {PRO_DMOD, 0x0081, { 0x0a, 0x12, 0x02, 0x0a, 0x03, 0xc0, 0x96, + 0xcf, 0xc3, 0x01}, 0x0a}, + {PRO_DMOD, 0x008e, {0x01}, 0x01}, + {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05}, + {PRO_DMOD, 0x0099, {0x01}, 0x01}, + {PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02}, + {PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02}, + {PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04}, + {PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02}, + {PRO_DMOD, 0x00b0, {0x01}, 0x01}, + {PRO_DMOD, 0x00b3, {0x02, 0x3c}, 0x02}, + {PRO_DMOD, 0x00b6, {0x14}, 0x01}, + {PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05}, 0x03}, + {PRO_DMOD, 0x00c4, {0x00}, 0x01}, + {PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02}, + {PRO_DMOD, 0x00cc, {0x2e, 0x51, 0x33}, 0x03}, + {PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03}, + {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03}, + {PRO_DMOD, 0x00fc, { 0x03, 0x02, 0x02, 0x09, 0x50, 0x7a, 0x77, + 0x01, 0x02, 0xb0, 0x02, 0x7a}, 0x0c}, + {PRO_DMOD, 0x0109, {0x02}, 0x01}, + {PRO_DMOD, 0x0115, {0x0a, 0x03, 0x02, 0x80}, 0x04}, + {PRO_DMOD, 0x011a, {0xc0, 0x7a, 0xac, 0x8c}, 0x04}, + {PRO_DMOD, 0x0122, {0x02, 0x70, 0xa4}, 0x03}, + {PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02}, + {PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04}, + {PRO_DMOD, 0x0137, {0x01, 0x00, 0x07, 0x00, 0x06}, 0x05}, + {PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xc0, 0x59}, 0x05}, + {PRO_DMOD, 0xf000, {0x0f}, 0x01}, + {PRO_DMOD, 0xf016, {0x10, 0x04, 0x05, 0x04, 0x05}, 0x05}, + {PRO_DMOD, 0xf01f, {0x8c, 0x00, 0x03, 0x0a, 0x0a}, 0x05}, + {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00, 0x01}, 0x04}, + {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04}, + {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02}, + {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02}, + {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02}, + {PRO_DMOD, 0xf085, {0xc0, 0x01, 0x00}, 0x03}, + {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06}, + {PRO_DMOD, 0xf130, {0x04}, 0x01}, + {PRO_DMOD, 0xf132, {0x04}, 0x01}, + {PRO_DMOD, 0xf144, {0x1a}, 0x01}, + {PRO_DMOD, 0xf146, {0x00}, 0x01}, + {PRO_DMOD, 0xf14a, {0x01}, 0x01}, + {PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02}, + {PRO_DMOD, 0xf14f, {0x04}, 0x01}, + {PRO_DMOD, 0xf158, {0x7f}, 0x01}, + {PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02}, + {PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02}, + {PRO_DMOD, 0xf163, {0x05}, 0x01}, + {PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03}, + {PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02}, + {PRO_DMOD, 0xf183, {0x01}, 0x01}, + {PRO_DMOD, 0xf19d, {0x40}, 0x01}, + {PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02}, + {PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02}, + {PRO_DMOD, 0xf204, {0x10}, 0x01}, + {PRO_DMOD, 0xf214, {0x00}, 0x01}, + {PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04}, + {PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05}, + {PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04}, + {PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03}, + {PRO_DMOD, 0xf55f, {0x0a}, 0x01}, + {PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02}, + {PRO_DMOD, 0xf5df, {0xfb, 0x00}, 0x02}, + {PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03}, + {PRO_DMOD, 0xf5f8, {0x01}, 0x01}, + {PRO_DMOD, 0xf5fd, {0x01}, 0x01}, + {PRO_DMOD, 0xf600, { 0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17, + 0x1f}, 0x08}, + {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04}, + {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04}, + {PRO_DMOD, 0xf78b, {0x01}, 0x01}, + {PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03}, + {PRO_DMOD, 0xf905, {0x01}, 0x01}, + {PRO_DMOD, 0xfb06, {0x03}, 0x01}, + {PRO_DMOD, 0xfd8b, {0x00}, 0x01}, + {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */ +}; + +static struct it913xset it9135_52[] = { + {PRO_DMOD, 0x0043, {0x00}, 0x01}, + {PRO_DMOD, 0x0046, {0x52}, 0x01}, + {PRO_DMOD, 0x0051, {0x01}, 0x01}, + {PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02}, + {PRO_DMOD, 0x0068, {0x10}, 0x01}, + {PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03}, + {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xa0, 0x01}, 0x05}, + {PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02}, + {PRO_DMOD, 0x0081, { 0x0a, 0x12, 0x03, 0x0a, 0x03, 0xb3, 0x97, + 0xc0, 0x9e, 0x01}, 0x0a}, + {PRO_DMOD, 0x008e, {0x01}, 0x01}, + {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05}, + {PRO_DMOD, 0x0099, {0x01}, 0x01}, + {PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02}, + {PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02}, + {PRO_DMOD, 0x00a3, {0x01, 0x5c, 0x01, 0x01}, 0x04}, + {PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02}, + {PRO_DMOD, 0x00b0, {0x01}, 0x01}, + {PRO_DMOD, 0x00b3, {0x02, 0x3c}, 0x02}, + {PRO_DMOD, 0x00b6, {0x14}, 0x01}, + {PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05}, 0x03}, + {PRO_DMOD, 0x00c4, {0x00}, 0x01}, + {PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02}, + {PRO_DMOD, 0x00cc, {0x2e, 0x51, 0x33}, 0x03}, + {PRO_DMOD, 0x00f3, {0x05, 0x91, 0x8c}, 0x03}, + {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03}, + {PRO_DMOD, 0x00fc, { 0x03, 0x02, 0x02, 0x09, 0x50, 0x74, 0x77, + 0x02, 0x02, 0xae, 0x02, 0x6e}, 0x0c}, + {PRO_DMOD, 0x0109, {0x02}, 0x01}, + {PRO_DMOD, 0x0115, {0x0a, 0x03, 0x02, 0x80}, 0x04}, + {PRO_DMOD, 0x011a, {0xcd, 0x62, 0xa4, 0x8c}, 0x04}, + {PRO_DMOD, 0x0122, {0x03, 0x18, 0x9e}, 0x03}, + {PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02}, + {PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04}, + {PRO_DMOD, 0x0137, {0x00, 0x00, 0x07, 0x00, 0x06}, 0x05}, + {PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xb6, 0x59}, 0x05}, + {PRO_DMOD, 0xf000, {0x0f}, 0x01}, + {PRO_DMOD, 0xf016, {0x10, 0x04, 0x05, 0x04, 0x05}, 0x05}, + {PRO_DMOD, 0xf01f, {0x8c, 0x00, 0x03, 0x0a, 0x0a}, 0x05}, + {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00, 0x01}, 0x04}, + {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04}, + {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02}, + {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02}, + {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02}, + {PRO_DMOD, 0xf085, {0xc0, 0x01, 0x00}, 0x03}, + {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06}, + {PRO_DMOD, 0xf130, {0x04}, 0x01}, + {PRO_DMOD, 0xf132, {0x04}, 0x01}, + {PRO_DMOD, 0xf144, {0x1a}, 0x01}, + {PRO_DMOD, 0xf146, {0x00}, 0x01}, + {PRO_DMOD, 0xf14a, {0x01}, 0x01}, + {PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02}, + {PRO_DMOD, 0xf14f, {0x04}, 0x01}, + {PRO_DMOD, 0xf158, {0x7f}, 0x01}, + {PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02}, + {PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02}, + {PRO_DMOD, 0xf163, {0x05}, 0x01}, + {PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03}, + {PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02}, + {PRO_DMOD, 0xf183, {0x01}, 0x01}, + {PRO_DMOD, 0xf19d, {0x40}, 0x01}, + {PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02}, + {PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02}, + {PRO_DMOD, 0xf204, {0x10}, 0x01}, + {PRO_DMOD, 0xf214, {0x00}, 0x01}, + {PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04}, + {PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05}, + {PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04}, + {PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03}, + {PRO_DMOD, 0xf55f, {0x0a}, 0x01}, + {PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02}, + {PRO_DMOD, 0xf5df, {0xfb, 0x00}, 0x02}, + {PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03}, + {PRO_DMOD, 0xf5f8, {0x01}, 0x01}, + {PRO_DMOD, 0xf5fd, {0x01}, 0x01}, + {PRO_DMOD, 0xf600, {0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17, + 0x1f}, 0x08}, + {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04}, + {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04}, + {PRO_DMOD, 0xf78b, {0x01}, 0x01}, + {PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03}, + {PRO_DMOD, 0xf905, {0x01}, 0x01}, + {PRO_DMOD, 0xfb06, {0x03}, 0x01}, + {PRO_DMOD, 0xfd8b, {0x00}, 0x01}, + {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */ +}; + +/* Version 2 types */ +static struct it913xset it9135_v2[] = { + {PRO_DMOD, 0x0051, {0x01}, 0x01}, + {PRO_DMOD, 0x0070, {0x0a}, 0x01}, + {PRO_DMOD, 0x007e, {0x04}, 0x01}, + {PRO_DMOD, 0x0081, {0x0a}, 0x01}, + {PRO_DMOD, 0x008a, {0x01}, 0x01}, + {PRO_DMOD, 0x008e, {0x01}, 0x01}, + {PRO_DMOD, 0x0092, {0x06}, 0x01}, + {PRO_DMOD, 0x0099, {0x01}, 0x01}, + {PRO_DMOD, 0x009f, {0xe1}, 0x01}, + {PRO_DMOD, 0x00a0, {0xcf}, 0x01}, + {PRO_DMOD, 0x00a3, {0x01}, 0x01}, + {PRO_DMOD, 0x00a5, {0x01}, 0x01}, + {PRO_DMOD, 0x00a6, {0x01}, 0x01}, + {PRO_DMOD, 0x00a9, {0x00}, 0x01}, + {PRO_DMOD, 0x00aa, {0x01}, 0x01}, + {PRO_DMOD, 0x00b0, {0x01}, 0x01}, + {PRO_DMOD, 0x00c2, {0x05}, 0x01}, + {PRO_DMOD, 0x00c6, {0x19}, 0x01}, + {PRO_DMOD, 0xf000, {0x0f}, 0x01}, + {PRO_DMOD, 0xf02b, {0x00}, 0x01}, + {PRO_DMOD, 0xf064, {0x03}, 0x01}, + {PRO_DMOD, 0xf065, {0xf9}, 0x01}, + {PRO_DMOD, 0xf066, {0x03}, 0x01}, + {PRO_DMOD, 0xf067, {0x01}, 0x01}, + {PRO_DMOD, 0xf06f, {0xe0}, 0x01}, + {PRO_DMOD, 0xf070, {0x03}, 0x01}, + {PRO_DMOD, 0xf072, {0x0f}, 0x01}, + {PRO_DMOD, 0xf073, {0x03}, 0x01}, + {PRO_DMOD, 0xf078, {0x00}, 0x01}, + {PRO_DMOD, 0xf087, {0x00}, 0x01}, + {PRO_DMOD, 0xf09b, {0x3f}, 0x01}, + {PRO_DMOD, 0xf09c, {0x00}, 0x01}, + {PRO_DMOD, 0xf09d, {0x20}, 0x01}, + {PRO_DMOD, 0xf09e, {0x00}, 0x01}, + {PRO_DMOD, 0xf09f, {0x0c}, 0x01}, + {PRO_DMOD, 0xf0a0, {0x00}, 0x01}, + {PRO_DMOD, 0xf130, {0x04}, 0x01}, + {PRO_DMOD, 0xf132, {0x04}, 0x01}, + {PRO_DMOD, 0xf144, {0x1a}, 0x01}, + {PRO_DMOD, 0xf146, {0x00}, 0x01}, + {PRO_DMOD, 0xf14a, {0x01}, 0x01}, + {PRO_DMOD, 0xf14c, {0x00}, 0x01}, + {PRO_DMOD, 0xf14d, {0x00}, 0x01}, + {PRO_DMOD, 0xf14f, {0x04}, 0x01}, + {PRO_DMOD, 0xf158, {0x7f}, 0x01}, + {PRO_DMOD, 0xf15a, {0x00}, 0x01}, + {PRO_DMOD, 0xf15b, {0x08}, 0x01}, + {PRO_DMOD, 0xf15d, {0x03}, 0x01}, + {PRO_DMOD, 0xf15e, {0x05}, 0x01}, + {PRO_DMOD, 0xf163, {0x05}, 0x01}, + {PRO_DMOD, 0xf166, {0x01}, 0x01}, + {PRO_DMOD, 0xf167, {0x40}, 0x01}, + {PRO_DMOD, 0xf168, {0x0f}, 0x01}, + {PRO_DMOD, 0xf17a, {0x00}, 0x01}, + {PRO_DMOD, 0xf17b, {0x00}, 0x01}, + {PRO_DMOD, 0xf183, {0x01}, 0x01}, + {PRO_DMOD, 0xf19d, {0x40}, 0x01}, + {PRO_DMOD, 0xf1bc, {0x36}, 0x01}, + {PRO_DMOD, 0xf1bd, {0x00}, 0x01}, + {PRO_DMOD, 0xf1cb, {0xa0}, 0x01}, + {PRO_DMOD, 0xf1cc, {0x01}, 0x01}, + {PRO_DMOD, 0xf204, {0x10}, 0x01}, + {PRO_DMOD, 0xf214, {0x00}, 0x01}, + {PRO_DMOD, 0xf40e, {0x0a}, 0x01}, + {PRO_DMOD, 0xf40f, {0x40}, 0x01}, + {PRO_DMOD, 0xf410, {0x08}, 0x01}, + {PRO_DMOD, 0xf55f, {0x0a}, 0x01}, + {PRO_DMOD, 0xf561, {0x15}, 0x01}, + {PRO_DMOD, 0xf562, {0x20}, 0x01}, + {PRO_DMOD, 0xf5e3, {0x09}, 0x01}, + {PRO_DMOD, 0xf5e4, {0x01}, 0x01}, + {PRO_DMOD, 0xf5e5, {0x01}, 0x01}, + {PRO_DMOD, 0xf600, {0x05}, 0x01}, + {PRO_DMOD, 0xf601, {0x08}, 0x01}, + {PRO_DMOD, 0xf602, {0x0b}, 0x01}, + {PRO_DMOD, 0xf603, {0x0e}, 0x01}, + {PRO_DMOD, 0xf604, {0x11}, 0x01}, + {PRO_DMOD, 0xf605, {0x14}, 0x01}, + {PRO_DMOD, 0xf606, {0x17}, 0x01}, + {PRO_DMOD, 0xf607, {0x1f}, 0x01}, + {PRO_DMOD, 0xf60e, {0x00}, 0x01}, + {PRO_DMOD, 0xf60f, {0x04}, 0x01}, + {PRO_DMOD, 0xf610, {0x32}, 0x01}, + {PRO_DMOD, 0xf611, {0x10}, 0x01}, + {PRO_DMOD, 0xf707, {0xfc}, 0x01}, + {PRO_DMOD, 0xf708, {0x00}, 0x01}, + {PRO_DMOD, 0xf709, {0x37}, 0x01}, + {PRO_DMOD, 0xf70a, {0x00}, 0x01}, + {PRO_DMOD, 0xf78b, {0x01}, 0x01}, + {PRO_DMOD, 0xf80f, {0x40}, 0x01}, + {PRO_DMOD, 0xf810, {0x54}, 0x01}, + {PRO_DMOD, 0xf811, {0x5a}, 0x01}, + {PRO_DMOD, 0xf905, {0x01}, 0x01}, + {PRO_DMOD, 0xfb06, {0x03}, 0x01}, + {PRO_DMOD, 0xfd8b, {0x00}, 0x01}, + {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */ +}; + +static struct it913xset it9135_60[] = { + {PRO_DMOD, 0x0043, {0x00}, 0x01}, + {PRO_DMOD, 0x0046, {0x60}, 0x01}, + {PRO_DMOD, 0x0051, {0x01}, 0x01}, + {PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02}, + {PRO_DMOD, 0x0068, {0x0a}, 0x01}, + {PRO_DMOD, 0x006a, {0x03}, 0x01}, + {PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03}, + {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0x8c, 0x01}, 0x05}, + {PRO_DMOD, 0x007e, {0x04}, 0x01}, + {PRO_DMOD, 0x0081, {0x0a, 0x12}, 0x02}, + {PRO_DMOD, 0x0084, {0x0a, 0x33, 0xbe, 0xa0, 0xc6, 0xb6, 0x01}, 0x07}, + {PRO_DMOD, 0x008e, {0x01}, 0x01}, + {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05}, + {PRO_DMOD, 0x0099, {0x01}, 0x01}, + {PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02}, + {PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02}, + {PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04}, + {PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02}, + {PRO_DMOD, 0x00b0, {0x01}, 0x01}, + {PRO_DMOD, 0x00b3, {0x02, 0x3a}, 0x02}, + {PRO_DMOD, 0x00b6, {0x14}, 0x01}, + {PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05, 0x01, 0x00}, 0x05}, + {PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02}, + {PRO_DMOD, 0x00cb, {0x32, 0x2c, 0x4f, 0x30}, 0x04}, + {PRO_DMOD, 0x00f3, {0x05, 0xa0, 0x8c}, 0x03}, + {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03}, + {PRO_DMOD, 0x00fc, { 0x03, 0x03, 0x02, 0x0a, 0x50, 0x7b, 0x8c, + 0x00, 0x02, 0xbe, 0x00}, 0x0b}, + {PRO_DMOD, 0x0109, {0x02}, 0x01}, + {PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02}, + {PRO_DMOD, 0x011a, {0xbe}, 0x01}, + {PRO_DMOD, 0x0124, {0xae}, 0x01}, + {PRO_DMOD, 0x0127, {0x00}, 0x01}, + {PRO_DMOD, 0x012a, {0x56, 0x50, 0x47, 0x42}, 0x04}, + {PRO_DMOD, 0x0137, {0x00}, 0x01}, + {PRO_DMOD, 0x013b, {0x08}, 0x01}, + {PRO_DMOD, 0x013f, {0x5b}, 0x01}, + {PRO_DMOD, 0x0141, { 0x59, 0xf9, 0x19, 0x19, 0x8c, 0x8c, 0x8c, + 0x6e, 0x8c, 0x50, 0x8c, 0x8c, 0xac, 0xc6, + 0x33}, 0x0f}, + {PRO_DMOD, 0x0151, {0x28}, 0x01}, + {PRO_DMOD, 0x0153, {0xbc}, 0x01}, + {PRO_DMOD, 0x0178, {0x09}, 0x01}, + {PRO_DMOD, 0x0181, {0x94, 0x6e}, 0x02}, + {PRO_DMOD, 0x0185, {0x24}, 0x01}, + {PRO_DMOD, 0x0187, {0x00, 0x00, 0xbe, 0x02, 0x80}, 0x05}, + {PRO_DMOD, 0xed02, {0xff}, 0x01}, + {PRO_DMOD, 0xee42, {0xff}, 0x01}, + {PRO_DMOD, 0xee82, {0xff}, 0x01}, + {PRO_DMOD, 0xf000, {0x0f}, 0x01}, + {PRO_DMOD, 0xf01f, {0x8c, 0x00}, 0x02}, + {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00}, 0x03}, + {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04}, + {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02}, + {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02}, + {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02}, + {PRO_DMOD, 0xf087, {0x00}, 0x01}, + {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06}, + {PRO_DMOD, 0xf130, {0x04}, 0x01}, + {PRO_DMOD, 0xf132, {0x04}, 0x01}, + {PRO_DMOD, 0xf144, {0x1a}, 0x01}, + {PRO_DMOD, 0xf146, {0x00}, 0x01}, + {PRO_DMOD, 0xf14a, {0x01}, 0x01}, + {PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02}, + {PRO_DMOD, 0xf14f, {0x04}, 0x01}, + {PRO_DMOD, 0xf158, {0x7f}, 0x01}, + {PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02}, + {PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02}, + {PRO_DMOD, 0xf163, {0x05}, 0x01}, + {PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03}, + {PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02}, + {PRO_DMOD, 0xf183, {0x01}, 0x01}, + {PRO_DMOD, 0xf19d, {0x40}, 0x01}, + {PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02}, + {PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02}, + {PRO_DMOD, 0xf204, {0x10}, 0x01}, + {PRO_DMOD, 0xf214, {0x00}, 0x01}, + {PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04}, + {PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05}, + {PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04}, + {PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03}, + {PRO_DMOD, 0xf55f, {0x0a}, 0x01}, + {PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02}, + {PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03}, + {PRO_DMOD, 0xf600, {0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17 + , 0x1f}, 0x08}, + {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04}, + {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04}, + {PRO_DMOD, 0xf78b, {0x01}, 0x01}, + {PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03}, + {PRO_DMOD, 0xf905, {0x01}, 0x01}, + {PRO_DMOD, 0xfb06, {0x03}, 0x01}, + {PRO_DMOD, 0xfd8b, {0x00}, 0x01}, + {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */ +}; + +static struct it913xset it9135_61[] = { + {PRO_DMOD, 0x0043, {0x00}, 0x01}, + {PRO_DMOD, 0x0046, {0x61}, 0x01}, + {PRO_DMOD, 0x0051, {0x01}, 0x01}, + {PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02}, + {PRO_DMOD, 0x0068, {0x06}, 0x01}, + {PRO_DMOD, 0x006a, {0x03}, 0x01}, + {PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03}, + {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0x90, 0x01}, 0x05}, + {PRO_DMOD, 0x007e, {0x04}, 0x01}, + {PRO_DMOD, 0x0081, {0x0a, 0x12}, 0x02}, + {PRO_DMOD, 0x0084, {0x0a, 0x33, 0xbc, 0x9c, 0xcc, 0xa8, 0x01}, 0x07}, + {PRO_DMOD, 0x008e, {0x01}, 0x01}, + {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05}, + {PRO_DMOD, 0x0099, {0x01}, 0x01}, + {PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02}, + {PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02}, + {PRO_DMOD, 0x00a3, {0x01, 0x5c, 0x01, 0x01}, 0x04}, + {PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02}, + {PRO_DMOD, 0x00b0, {0x01}, 0x01}, + {PRO_DMOD, 0x00b3, {0x02, 0x3a}, 0x02}, + {PRO_DMOD, 0x00b6, {0x14}, 0x01}, + {PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05, 0x01, 0x00}, 0x05}, + {PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02}, + {PRO_DMOD, 0x00cb, {0x32, 0x2c, 0x4f, 0x30}, 0x04}, + {PRO_DMOD, 0x00f3, {0x05, 0xa0, 0x8c}, 0x03}, + {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03}, + {PRO_DMOD, 0x00fc, { 0x03, 0x03, 0x02, 0x08, 0x50, 0x7b, 0x8c, + 0x01, 0x02, 0xc8, 0x00}, 0x0b}, + {PRO_DMOD, 0x0109, {0x02}, 0x01}, + {PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02}, + {PRO_DMOD, 0x011a, {0xc6}, 0x01}, + {PRO_DMOD, 0x0124, {0xa8}, 0x01}, + {PRO_DMOD, 0x0127, {0x00}, 0x01}, + {PRO_DMOD, 0x012a, {0x59, 0x50, 0x47, 0x42}, 0x04}, + {PRO_DMOD, 0x0137, {0x00}, 0x01}, + {PRO_DMOD, 0x013b, {0x05}, 0x01}, + {PRO_DMOD, 0x013f, {0x5b}, 0x01}, + {PRO_DMOD, 0x0141, { 0x59, 0xf9, 0x59, 0x59, 0x8c, 0x8c, 0x8c, + 0x7b, 0x8c, 0x50, 0x8c, 0x8c, 0xa8, 0xc6, + 0x33}, 0x0f}, + {PRO_DMOD, 0x0151, {0x28}, 0x01}, + {PRO_DMOD, 0x0153, {0xcc}, 0x01}, + {PRO_DMOD, 0x0178, {0x09}, 0x01}, + {PRO_DMOD, 0x0181, {0x9c, 0x76}, 0x02}, + {PRO_DMOD, 0x0185, {0x28}, 0x01}, + {PRO_DMOD, 0x0187, {0x01, 0x00, 0xaa, 0x02, 0x80}, 0x05}, + {PRO_DMOD, 0xed02, {0xff}, 0x01}, + {PRO_DMOD, 0xee42, {0xff}, 0x01}, + {PRO_DMOD, 0xee82, {0xff}, 0x01}, + {PRO_DMOD, 0xf000, {0x0f}, 0x01}, + {PRO_DMOD, 0xf01f, {0x8c, 0x00}, 0x02}, + {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00}, 0x03}, + {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04}, + {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02}, + {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02}, + {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02}, + {PRO_DMOD, 0xf087, {0x00}, 0x01}, + {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06}, + {PRO_DMOD, 0xf130, {0x04}, 0x01}, + {PRO_DMOD, 0xf132, {0x04}, 0x01}, + {PRO_DMOD, 0xf144, {0x1a}, 0x01}, + {PRO_DMOD, 0xf146, {0x00}, 0x01}, + {PRO_DMOD, 0xf14a, {0x01}, 0x01}, + {PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02}, + {PRO_DMOD, 0xf14f, {0x04}, 0x01}, + {PRO_DMOD, 0xf158, {0x7f}, 0x01}, + {PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02}, + {PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02}, + {PRO_DMOD, 0xf163, {0x05}, 0x01}, + {PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03}, + {PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02}, + {PRO_DMOD, 0xf183, {0x01}, 0x01}, + {PRO_DMOD, 0xf19d, {0x40}, 0x01}, + {PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02}, + {PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02}, + {PRO_DMOD, 0xf204, {0x10}, 0x01}, + {PRO_DMOD, 0xf214, {0x00}, 0x01}, + {PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04}, + {PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05}, + {PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04}, + {PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03}, + {PRO_DMOD, 0xf55f, {0x0a}, 0x01}, + {PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02}, + {PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03}, + {PRO_DMOD, 0xf600, { 0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17, + 0x1f}, 0x08}, + {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04}, + {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04}, + {PRO_DMOD, 0xf78b, {0x01}, 0x01}, + {PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03}, + {PRO_DMOD, 0xf905, {0x01}, 0x01}, + {PRO_DMOD, 0xfb06, {0x03}, 0x01}, + {PRO_DMOD, 0xfd8b, {0x00}, 0x01}, + {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */ +}; + +static struct it913xset it9135_62[] = { + {PRO_DMOD, 0x0043, {0x00}, 0x01}, + {PRO_DMOD, 0x0046, {0x62}, 0x01}, + {PRO_DMOD, 0x0051, {0x01}, 0x01}, + {PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02}, + {PRO_DMOD, 0x0068, {0x0a}, 0x01}, + {PRO_DMOD, 0x006a, {0x03}, 0x01}, + {PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03}, + {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0x8c, 0x01}, 0x05}, + {PRO_DMOD, 0x007e, {0x04}, 0x01}, + {PRO_DMOD, 0x0081, {0x0a, 0x12}, 0x02}, + {PRO_DMOD, 0x0084, { 0x0a, 0x33, 0xb8, 0x9c, 0xb2, 0xa6, 0x01}, + 0x07}, + {PRO_DMOD, 0x008e, {0x01}, 0x01}, + {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05}, + {PRO_DMOD, 0x0099, {0x01}, 0x01}, + {PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02}, + {PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02}, + {PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04}, + {PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02}, + {PRO_DMOD, 0x00b0, {0x01}, 0x01}, + {PRO_DMOD, 0x00b3, {0x02, 0x3a}, 0x02}, + {PRO_DMOD, 0x00b6, {0x14}, 0x01}, + {PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05, 0x01, 0x00}, 0x05}, + {PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02}, + {PRO_DMOD, 0x00cb, {0x32, 0x2c, 0x4f, 0x30}, 0x04}, + {PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03}, + {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03}, + {PRO_DMOD, 0x00fc, { 0x02, 0x03, 0x02, 0x09, 0x50, 0x6e, 0x8c, + 0x02, 0x02, 0xc2, 0x00}, 0x0b}, + {PRO_DMOD, 0x0109, {0x02}, 0x01}, + {PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02}, + {PRO_DMOD, 0x011a, {0xb8}, 0x01}, + {PRO_DMOD, 0x0124, {0xa8}, 0x01}, + {PRO_DMOD, 0x0127, {0x00}, 0x01}, + {PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04}, + {PRO_DMOD, 0x0137, {0x00}, 0x01}, + {PRO_DMOD, 0x013b, {0x05}, 0x01}, + {PRO_DMOD, 0x013f, {0x5b}, 0x01}, + {PRO_DMOD, 0x0141, { 0x59, 0xf9, 0x59, 0x19, 0x8c, 0x8c, 0x8c, + 0x7b, 0x8c, 0x50, 0x70, 0x8c, 0x96, 0xd0, + 0x33}, 0x0f}, + {PRO_DMOD, 0x0151, {0x28}, 0x01}, + {PRO_DMOD, 0x0153, {0xb2}, 0x01}, + {PRO_DMOD, 0x0178, {0x09}, 0x01}, + {PRO_DMOD, 0x0181, {0x9c, 0x6e}, 0x02}, + {PRO_DMOD, 0x0185, {0x24}, 0x01}, + {PRO_DMOD, 0x0187, {0x00, 0x00, 0xb8, 0x02, 0x80}, 0x05}, + {PRO_DMOD, 0xed02, {0xff}, 0x01}, + {PRO_DMOD, 0xee42, {0xff}, 0x01}, + {PRO_DMOD, 0xee82, {0xff}, 0x01}, + {PRO_DMOD, 0xf000, {0x0f}, 0x01}, + {PRO_DMOD, 0xf01f, {0x8c, 0x00}, 0x02}, + {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00}, 0x03}, + {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04}, + {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02}, + {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02}, + {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02}, + {PRO_DMOD, 0xf087, {0x00}, 0x01}, + {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06}, + {PRO_DMOD, 0xf130, {0x04}, 0x01}, + {PRO_DMOD, 0xf132, {0x04}, 0x01}, + {PRO_DMOD, 0xf144, {0x1a}, 0x01}, + {PRO_DMOD, 0xf146, {0x00}, 0x01}, + {PRO_DMOD, 0xf14a, {0x01}, 0x01}, + {PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02}, + {PRO_DMOD, 0xf14f, {0x04}, 0x01}, + {PRO_DMOD, 0xf158, {0x7f}, 0x01}, + {PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02}, + {PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02}, + {PRO_DMOD, 0xf163, {0x05}, 0x01}, + {PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03}, + {PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02}, + {PRO_DMOD, 0xf183, {0x01}, 0x01}, + {PRO_DMOD, 0xf19d, {0x40}, 0x01}, + {PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02}, + {PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02}, + {PRO_DMOD, 0xf204, {0x10}, 0x01}, + {PRO_DMOD, 0xf214, {0x00}, 0x01}, + {PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04}, + {PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05}, + {PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04}, + {PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03}, + {PRO_DMOD, 0xf55f, {0x0a}, 0x01}, + {PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02}, + {PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03}, + {PRO_DMOD, 0xf600, { 0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17, + 0x1f}, 0x08}, + {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04}, + {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04}, + {PRO_DMOD, 0xf78b, {0x01}, 0x01}, + {PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03}, + {PRO_DMOD, 0xf905, {0x01}, 0x01}, + {PRO_DMOD, 0xfb06, {0x03}, 0x01}, + {PRO_DMOD, 0xfd8b, {0x00}, 0x01}, + {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */ }; +/* Tuner setting scripts (still keeping it9137) */ static struct it913xset it9137_tuner_off[] = { {PRO_DMOD, 0xfba8, {0x01}, 0x01}, /* Tuner Clock Off */ {PRO_DMOD, 0xec40, {0x00}, 0x01}, /* Power Down Tuner */ diff --git a/drivers/media/dvb/frontends/it913x-fe.c b/drivers/media/dvb/frontends/it913x-fe.c index d4bd24e..5113b89 100644 --- a/drivers/media/dvb/frontends/it913x-fe.c +++ b/drivers/media/dvb/frontends/it913x-fe.c @@ -50,6 +50,7 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); struct it913x_fe_state { struct dvb_frontend frontend; struct i2c_adapter *i2c_adap; + struct ite_config *config; u8 i2c_addr; u32 frequency; u8 adf; @@ -211,13 +212,17 @@ static int it913x_init_tuner(struct it913x_fe_state *state) state->tun_fn_min /= (state->tun_fdiv * nv_val); deb_info("Tuner fn_min %d", state->tun_fn_min); - for (i = 0; i < 50; i++) { - reg = it913x_read_reg_u8(state, 0xec82); - if (reg > 0) - break; - if (reg < 0) - return -ENODEV; - udelay(2000); + if (state->config->chip_ver > 1) + msleep(50); + else { + for (i = 0; i < 50; i++) { + reg = it913x_read_reg_u8(state, 0xec82); + if (reg > 0) + break; + if (reg < 0) + return -ENODEV; + udelay(2000); + } } return it913x_write_reg(state, PRO_DMOD, 0xed81, val); @@ -578,7 +583,12 @@ static int it913x_fe_set_frontend(struct dvb_frontend *fe, deb_info("Frontend Set Tuner Type %02x", state->tuner_type); switch (state->tuner_type) { - case IT9137: /* Tuner type 0x38 */ + case IT9135_38: + case IT9135_51: + case IT9135_52: + case IT9135_60: + case IT9135_61: + case IT9135_62: ret = it9137_set_tuner(state, p->u.ofdm.bandwidth, p->frequency); break; @@ -678,14 +688,15 @@ static u32 compute_div(u32 a, u32 b, u32 x) static int it913x_fe_start(struct it913x_fe_state *state) { - struct it913xset *set_fe; + struct it913xset *set_lna; struct it913xset *set_mode; int ret; - u8 adf = (state->adf & 0xf); + u8 adf = (state->config->adf & 0xf); u32 adc, xtal; u8 b[4]; - ret = it913x_init_tuner(state); + if (state->config->chip_ver == 1) + ret = it913x_init_tuner(state); if (adf < 12) { state->crystalFrequency = fe_clockTable[adf].xtal ; @@ -720,23 +731,57 @@ static int it913x_fe_start(struct it913x_fe_state *state) b[1] = (adc >> 8) & 0xff; b[2] = (adc >> 16) & 0xff; ret |= it913x_write(state, PRO_DMOD, ADC_FREQ, b, 3); + if (ret < 0) + return -ENODEV; + /* v1 or v2 tuner script */ + if (state->config->chip_ver > 1) + ret = it913x_fe_script_loader(state, it9135_v2); + else + ret = it913x_fe_script_loader(state, it9135_v1); + if (ret < 0) + return ret; + + /* LNA Scripts */ switch (state->tuner_type) { - case IT9137: /* Tuner type 0x38 */ - set_fe = it9137_set; + case IT9135_51: + set_lna = it9135_51; + break; + case IT9135_52: + set_lna = it9135_52; break; + case IT9135_60: + set_lna = it9135_60; + break; + case IT9135_61: + set_lna = it9135_61; + break; + case IT9135_62: + set_lna = it9135_62; + break; + case IT9135_38: default: - return -EINVAL; + set_lna = it9135_38; } + ret = it913x_fe_script_loader(state, set_lna); + if (ret < 0) + return ret; + + if (state->config->chip_ver == 2) { + ret = it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x1); + ret |= it913x_write_reg(state, PRO_LINK, PADODPU, 0x0); + ret |= it913x_write_reg(state, PRO_LINK, AGC_O_D, 0x0); + ret |= it913x_init_tuner(state); + } + if (ret < 0) + return -ENODEV; - /* set the demod */ - ret = it913x_fe_script_loader(state, set_fe); /* Always solo frontend */ set_mode = set_solo_fe; ret |= it913x_fe_script_loader(state, set_mode); ret |= it913x_fe_suspend(state); - return 0; + return (ret < 0) ? -ENODEV : 0; } static int it913x_fe_init(struct dvb_frontend *fe) @@ -750,13 +795,7 @@ static int it913x_fe_init(struct dvb_frontend *fe) ret |= it913x_fe_script_loader(state, init_1); - switch (state->tuner_type) { - case IT9137: - ret |= it913x_write_reg(state, PRO_DMOD, 0xfba8, 0x0); - break; - default: - return -EINVAL; - } + ret |= it913x_write_reg(state, PRO_DMOD, 0xfba8, 0x0); return (ret < 0) ? -ENODEV : 0; } @@ -770,19 +809,34 @@ static void it913x_fe_release(struct dvb_frontend *fe) static struct dvb_frontend_ops it913x_fe_ofdm_ops; struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap, - u8 i2c_addr, u8 adf, u8 type) + u8 i2c_addr, struct ite_config *config) { struct it913x_fe_state *state = NULL; int ret; + /* allocate memory for the internal state */ state = kzalloc(sizeof(struct it913x_fe_state), GFP_KERNEL); if (state == NULL) + return NULL; + if (config == NULL) goto error; state->i2c_adap = i2c_adap; state->i2c_addr = i2c_addr; - state->adf = adf; - state->tuner_type = type; + state->config = config; + + switch (state->config->tuner_id_0) { + case IT9135_51: + case IT9135_52: + case IT9135_60: + case IT9135_61: + case IT9135_62: + state->tuner_type = state->config->tuner_id_0; + break; + default: + case IT9135_38: + state->tuner_type = IT9135_38; + } ret = it913x_fe_start(state); if (ret < 0) @@ -835,5 +889,5 @@ static struct dvb_frontend_ops it913x_fe_ofdm_ops = { MODULE_DESCRIPTION("it913x Frontend and it9137 tuner"); MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); -MODULE_VERSION("1.07"); +MODULE_VERSION("1.08"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/it913x-fe.h b/drivers/media/dvb/frontends/it913x-fe.h index 9d97f32..43f879a 100644 --- a/drivers/media/dvb/frontends/it913x-fe.h +++ b/drivers/media/dvb/frontends/it913x-fe.h @@ -23,13 +23,25 @@ #include #include "dvb_frontend.h" + +struct ite_config { + u8 chip_ver; + u16 chip_type; + u32 firmware; + u8 tuner_id_0; + u8 tuner_id_1; + u8 dual_mode; + u8 adf; +}; + #if defined(CONFIG_DVB_IT913X_FE) || (defined(CONFIG_DVB_IT913X_FE_MODULE) && \ defined(MODULE)) extern struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap, - u8 i2c_addr, u8 adf, u8 type); + u8 i2c_addr, struct ite_config *config); #else static inline struct dvb_frontend *it913x_fe_attach( - struct i2c_adapter *i2c_adap, u8 i2c_addr, u8 adf, u8 type) + struct i2c_adapter *i2c_adap, + u8 i2c_addr, struct ite_config *config) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; @@ -144,8 +156,14 @@ static inline struct dvb_frontend *it913x_fe_attach( #define EST_SIGNAL_LEVEL 0x004a #define FREE_BAND 0x004b #define SUSPEND_FLAG 0x004c -/* Build in tuners */ +/* Build in tuner types */ #define IT9137 0x38 +#define IT9135_38 0x38 +#define IT9135_51 0x50 +#define IT9135_52 0x52 +#define IT9135_60 0x60 +#define IT9135_61 0x61 +#define IT9135_62 0x62 enum { CMD_DEMOD_READ = 0, -- cgit v0.10.2 From 2b3c13ecce3bc0fbdeb5ef0596b350dc702d01d5 Mon Sep 17 00:00:00 2001 From: tvboxspy Date: Mon, 31 Oct 2011 12:06:34 -0300 Subject: [media] it913x-fe ver 1.09 amend adc table entries Amend adc table entries and size. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/it913x-fe-priv.h b/drivers/media/dvb/frontends/it913x-fe-priv.h index abf1395..836a5b8 100644 --- a/drivers/media/dvb/frontends/it913x-fe-priv.h +++ b/drivers/media/dvb/frontends/it913x-fe-priv.h @@ -153,8 +153,7 @@ struct table { }; static struct table fe_clockTable[] = { - {12000000, tab3}, /* FPGA */ - {16384000, tab6}, /* 16.38MHz */ + {12000000, tab3}, /* 12.00MHz */ {20480000, tab6}, /* 20.48MHz */ {36000000, tab3}, /* 36.00MHz */ {30000000, tab1}, /* 30.00MHz */ @@ -164,7 +163,6 @@ static struct table fe_clockTable[] = { {34000000, tab2}, /* 34.00MHz */ {24000000, tab1}, /* 24.00MHz */ {22000000, tab8}, /* 22.00MHz */ - {12000000, tab3} /* 12.00MHz */ }; /* fe get */ diff --git a/drivers/media/dvb/frontends/it913x-fe.c b/drivers/media/dvb/frontends/it913x-fe.c index 5113b89..6d12dcc 100644 --- a/drivers/media/dvb/frontends/it913x-fe.c +++ b/drivers/media/dvb/frontends/it913x-fe.c @@ -53,7 +53,6 @@ struct it913x_fe_state { struct ite_config *config; u8 i2c_addr; u32 frequency; - u8 adf; u32 crystalFrequency; u32 adcFrequency; u8 tuner_type; @@ -698,7 +697,7 @@ static int it913x_fe_start(struct it913x_fe_state *state) if (state->config->chip_ver == 1) ret = it913x_init_tuner(state); - if (adf < 12) { + if (adf < 10) { state->crystalFrequency = fe_clockTable[adf].xtal ; state->table = fe_clockTable[adf].table; state->adcFrequency = state->table->adcFrequency; @@ -889,5 +888,5 @@ static struct dvb_frontend_ops it913x_fe_ofdm_ops = { MODULE_DESCRIPTION("it913x Frontend and it9137 tuner"); MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); -MODULE_VERSION("1.08"); +MODULE_VERSION("1.09"); MODULE_LICENSE("GPL"); -- cgit v0.10.2 From ff17999184ed13829bc14c3be412d980173dff40 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 2 Nov 2011 16:39:58 -0300 Subject: [media] ttusb2: Don't use stack variables for DMA The ttusb2_msg function uses on-stack variables to submit commands to dvb_usb_generic. This eventually gets to the DMA api layer and will throw a traceback if the debugging options are set. This allocates the temporary buffer variables with kzalloc instead. Fixes https://bugzilla.redhat.com/show_bug.cgi?id=734506 Signed-off-by: Josh Boyer Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c index ea4eab8..faed393 100644 --- a/drivers/media/dvb/dvb-usb/ttusb2.c +++ b/drivers/media/dvb/dvb-usb/ttusb2.c @@ -75,10 +75,18 @@ static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { struct ttusb2_state *st = d->priv; - u8 s[wlen+4],r[64] = { 0 }; + u8 *s, *r = NULL; int ret = 0; - memset(s,0,wlen+4); + s = kzalloc(wlen+4, GFP_KERNEL); + if (!s) + return -ENOMEM; + + r = kzalloc(64, GFP_KERNEL); + if (!r) { + kfree(s); + return -ENOMEM; + } s[0] = 0xaa; s[1] = ++st->id; @@ -94,12 +102,17 @@ static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd, r[2] != cmd || (rlen > 0 && r[3] != rlen)) { warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]); + kfree(s); + kfree(r); return -EIO; } if (rlen > 0) memcpy(rbuf, &r[4], rlen); + kfree(s); + kfree(r); + return 0; } -- cgit v0.10.2 From f8e6defe7f4456d8700e5a3796a1e9fb54a88543 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 28 Oct 2011 08:40:00 +1100 Subject: Update NFSD MAINTAINER Neil hasn't really been at all active as a maintainer for some years now. So move his maintainership to CREDITS Signed-off-by: NeilBrown Signed-off-by: J. Bruce Fields diff --git a/CREDITS b/CREDITS index 07e32a87..557da47 100644 --- a/CREDITS +++ b/CREDITS @@ -514,6 +514,11 @@ S: Bessemerstraat 21 S: Amsterdam S: The Netherlands +N: NeilBrown +E: neil@brown.name +P: 4096R/566281B9 1BC6 29EB D390 D870 7B5F 497A 39EC 9EDD 5662 81B9 +D: NFSD Maintainer 2000-2007 + N: Zach Brown E: zab@zabbo.net D: maestro pci sound diff --git a/MAINTAINERS b/MAINTAINERS index 4808256..6ab923d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3770,7 +3770,6 @@ S: Odd Fixes KERNEL NFSD, SUNRPC, AND LOCKD SERVERS M: "J. Bruce Fields" -M: Neil Brown L: linux-nfs@vger.kernel.org W: http://nfs.sourceforge.net/ S: Supported -- cgit v0.10.2 From b93d87c19821ba7d3ee11557403d782e541071ad Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 7 Nov 2011 16:37:57 -0500 Subject: nfsd4: fix lockowner matching Lockowners are looked up by file as well as by owner, but we were forgetting to do a comparison on the file. This could cause an incorrect result from lockt. (Note looking up the inode from the lockowner is pretty awkward here. The data structures need fixing.) Cc: stable@kernel.org Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 47e94e3..5abced7 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3809,16 +3809,29 @@ nevermind: deny->ld_type = NFS4_WRITE_LT; } +static bool same_lockowner_ino(struct nfs4_lockowner *lo, struct inode *inode, clientid_t *clid, struct xdr_netobj *owner) +{ + struct nfs4_ol_stateid *lst; + + if (!same_owner_str(&lo->lo_owner, owner, clid)) + return false; + lst = list_first_entry(&lo->lo_owner.so_stateids, + struct nfs4_ol_stateid, st_perstateowner); + return lst->st_file->fi_inode == inode; +} + static struct nfs4_lockowner * find_lockowner_str(struct inode *inode, clientid_t *clid, struct xdr_netobj *owner) { unsigned int hashval = lock_ownerstr_hashval(inode, clid->cl_id, owner); + struct nfs4_lockowner *lo; struct nfs4_stateowner *op; list_for_each_entry(op, &lock_ownerstr_hashtbl[hashval], so_strhash) { - if (same_owner_str(op, owner, clid)) - return lockowner(op); + lo = lockowner(op); + if (same_lockowner_ino(lo, inode, clid, owner)) + return lo; } return NULL; } -- cgit v0.10.2 From 684e563858018d27acb8f00e30c026215bbd0ffb Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 4 Nov 2011 17:08:10 -0400 Subject: nfsd4: cleanup lock clientid handling in sessions case I'd rather the "ignore clientid in sessions case" rule be enforced in just one place. Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 5abced7..9354dde 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3946,10 +3946,15 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, * lock stateid. */ struct nfs4_ol_stateid *open_stp = NULL; - + + if (nfsd4_has_session(cstate)) + /* See rfc 5661 18.10.3: given clientid is ignored: */ + memcpy(&lock->v.new.clientid, + &cstate->session->se_client->cl_clientid, + sizeof(clientid_t)); + status = nfserr_stale_clientid; - if (!nfsd4_has_session(cstate) && - STALE_CLIENTID(&lock->lk_new_clientid)) + if (STALE_CLIENTID(&lock->lk_new_clientid)) goto out; /* validate and update open stateid and open seqid */ @@ -3961,8 +3966,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, goto out; open_sop = openowner(open_stp->st_stateowner); status = nfserr_bad_stateid; - if (!nfsd4_has_session(cstate) && - !same_clid(&open_sop->oo_owner.so_client->cl_clientid, + if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid, &lock->v.new.clientid)) goto out; /* create lockowner and lock stateid */ -- cgit v0.10.2 From 64a284d07c7d84299a90826950079a8ef11e8204 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 20 Oct 2011 06:57:46 -0400 Subject: nfsd4: maintain one seqid stream per (lockowner, file) Instead of creating a new lockowner and stateid for every open_to_lockowner call, reuse the existing lockowner if it exists. Reported-by: Trond Myklebust Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 9354dde..d09d524 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3905,6 +3905,37 @@ static void get_lock_access(struct nfs4_ol_stateid *lock_stp, u32 access) __set_bit(access, &lock_stp->st_access_bmap); } +__be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, struct nfs4_ol_stateid *ost, struct nfsd4_lock *lock, struct nfs4_ol_stateid **lst, bool *new) +{ + struct nfs4_file *fi = ost->st_file; + struct nfs4_openowner *oo = openowner(ost->st_stateowner); + struct nfs4_client *cl = oo->oo_owner.so_client; + struct nfs4_lockowner *lo; + unsigned int strhashval; + + lo = find_lockowner_str(fi->fi_inode, &cl->cl_clientid, &lock->v.new.owner); + if (lo) { + if (!cstate->minorversion) + return nfserr_bad_seqid; + /* XXX: a lockowner always has exactly one stateid: */ + *lst = list_first_entry(&lo->lo_owner.so_stateids, + struct nfs4_ol_stateid, st_perstateowner); + return nfs_ok; + } + strhashval = lock_ownerstr_hashval(fi->fi_inode, cl->cl_clientid.cl_id, + &lock->v.new.owner); + lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock); + if (lo == NULL) + return nfserr_jukebox; + *lst = alloc_init_lock_stateid(lo, fi, ost); + if (*lst == NULL) { + release_lockowner(lo); + return nfserr_jukebox; + } + *new = true; + return nfs_ok; +} + /* * LOCK operation */ @@ -3920,7 +3951,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct file_lock file_lock; struct file_lock conflock; __be32 status = 0; - unsigned int strhashval; + bool new_state = false; int lkflg; int err; @@ -3969,21 +4000,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid, &lock->v.new.clientid)) goto out; - /* create lockowner and lock stateid */ - fp = open_stp->st_file; - strhashval = lock_ownerstr_hashval(fp->fi_inode, - open_sop->oo_owner.so_client->cl_clientid.cl_id, - &lock->v.new.owner); - /* XXX: Do we need to check for duplicate stateowners on - * the same file, or should they just be allowed (and - * create new stateids)? */ - status = nfserr_jukebox; - lock_sop = alloc_init_lock_stateowner(strhashval, - open_sop->oo_owner.so_client, open_stp, lock); - if (lock_sop == NULL) - goto out; - lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp); - if (lock_stp == NULL) + status = lookup_or_create_lock_state(cstate, open_stp, lock, + &lock_stp, &new_state); + if (status) goto out; } else { /* lock (lock owner + lock stateid) already exists */ @@ -3993,10 +4012,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, NFS4_LOCK_STID, &lock_stp); if (status) goto out; - lock_sop = lockowner(lock_stp->st_stateowner); - fp = lock_stp->st_file; } - /* lock_sop and lock_stp have been created or found */ + lock_sop = lockowner(lock_stp->st_stateowner); + fp = lock_stp->st_file; lkflg = setlkflg(lock->lk_type); status = nfs4_check_openmode(lock_stp, lkflg); @@ -4071,7 +4089,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, break; } out: - if (status && lock->lk_is_new && lock_sop) + if (status && new_state) release_lockowner(lock_sop); if (!cstate->replay_owner) nfs4_unlock_state(); -- cgit v0.10.2 From 65178db42a02c7984f711614546e97e9952d8e01 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Tue, 1 Nov 2011 13:35:21 -0400 Subject: NFSD: Added fault injection Fault injection on the NFS server makes it easier to test the client's state manager and recovery threads. Simulating errors on the server is easier than finding the right conditions that cause them naturally. This patch uses debugfs to add a simple framework for fault injection to the server. This framework is a config option, and can be enabled through CONFIG_NFSD_FAULT_INJECTION. Assuming you have debugfs mounted to /sys/debug, a set of files will be created in /sys/debug/nfsd/. Writing to any of these files will cause the corresponding action and write a log entry to dmesg. Signed-off-by: Bryan Schumaker Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig index 10e6366..8df1ea4 100644 --- a/fs/nfsd/Kconfig +++ b/fs/nfsd/Kconfig @@ -80,3 +80,13 @@ config NFSD_V4 available from http://linux-nfs.org/. If unsure, say N. + +config NFSD_FAULT_INJECTION + bool "NFS server manual fault injection" + depends on NFSD_V4 && DEBUG_KERNEL + help + This option enables support for manually injecting faults + into the NFS server. This is intended to be used for + testing error recovery on the NFS client. + + If unsure, say N. diff --git a/fs/nfsd/Makefile b/fs/nfsd/Makefile index 9b118ee..af32ef0 100644 --- a/fs/nfsd/Makefile +++ b/fs/nfsd/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_NFSD) += nfsd.o nfsd-y := nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \ export.o auth.o lockd.o nfscache.o nfsxdr.o stats.o +nfsd-$(CONFIG_NFSD_FAULT_INJECTION) += fault_inject.o nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o diff --git a/fs/nfsd/fault_inject.c b/fs/nfsd/fault_inject.c new file mode 100644 index 0000000..ce7f075 --- /dev/null +++ b/fs/nfsd/fault_inject.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2011 Bryan Schumaker + * + * Uses debugfs to create fault injection points for client testing + */ + +#include +#include +#include +#include + +#include "state.h" +#include "fault_inject.h" + +struct nfsd_fault_inject_op { + char *file; + void (*func)(u64); +}; + +static struct nfsd_fault_inject_op inject_ops[] = { + { + .file = "forget_clients", + .func = nfsd_forget_clients, + }, + { + .file = "forget_locks", + .func = nfsd_forget_locks, + }, + { + .file = "forget_openowners", + .func = nfsd_forget_openowners, + }, + { + .file = "forget_delegations", + .func = nfsd_forget_delegations, + }, + { + .file = "recall_delegations", + .func = nfsd_recall_delegations, + }, +}; + +static long int NUM_INJECT_OPS = sizeof(inject_ops) / sizeof(struct nfsd_fault_inject_op); +static struct dentry *debug_dir; + +static int nfsd_inject_set(void *op_ptr, u64 val) +{ + struct nfsd_fault_inject_op *op = op_ptr; + + if (val == 0) + printk(KERN_INFO "NFSD Fault Injection: %s (all)", op->file); + else + printk(KERN_INFO "NFSD Fault Injection: %s (n = %llu)", op->file, val); + + op->func(val); + return 0; +} + +static int nfsd_inject_get(void *data, u64 *val) +{ + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(fops_nfsd, nfsd_inject_get, nfsd_inject_set, "%llu\n"); + +void nfsd_fault_inject_cleanup(void) +{ + debugfs_remove_recursive(debug_dir); +} + +int nfsd_fault_inject_init(void) +{ + unsigned int i; + struct nfsd_fault_inject_op *op; + mode_t mode = S_IFREG | S_IRUSR | S_IWUSR; + + debug_dir = debugfs_create_dir("nfsd", NULL); + if (!debug_dir) + goto fail; + + for (i = 0; i < NUM_INJECT_OPS; i++) { + op = &inject_ops[i]; + if (!debugfs_create_file(op->file, mode, debug_dir, op, &fops_nfsd)) + goto fail; + } + return 0; + +fail: + nfsd_fault_inject_cleanup(); + return -ENOMEM; +} diff --git a/fs/nfsd/fault_inject.h b/fs/nfsd/fault_inject.h new file mode 100644 index 0000000..90bd057 --- /dev/null +++ b/fs/nfsd/fault_inject.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2011 Bryan Schumaker + * + * Function definitions for fault injection + */ + +#ifndef LINUX_NFSD_FAULT_INJECT_H +#define LINUX_NFSD_FAULT_INJECT_H + +#ifdef CONFIG_NFSD_FAULT_INJECTION +int nfsd_fault_inject_init(void); +void nfsd_fault_inject_cleanup(void); +void nfsd_forget_clients(u64); +void nfsd_forget_locks(u64); +void nfsd_forget_openowners(u64); +void nfsd_forget_delegations(u64); +void nfsd_recall_delegations(u64); +#else /* CONFIG_NFSD_FAULT_INJECTION */ +static inline int nfsd_fault_inject_init(void) { return 0; } +static inline void nfsd_fault_inject_cleanup(void) {} +static inline void nfsd_forget_clients(u64 num) {} +static inline void nfsd_forget_locks(u64 num) {} +static inline void nfsd_forget_openowners(u64 num) {} +static inline void nfsd_forget_delegations(u64 num) {} +static inline void nfsd_recall_delegations(u64 num) {} +#endif /* CONFIG_NFSD_FAULT_INJECTION */ + +#endif /* LINUX_NFSD_FAULT_INJECT_H */ diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index d09d524..a511eff 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4429,6 +4429,121 @@ nfs4_check_open_reclaim(clientid_t *clid) return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad; } +#ifdef CONFIG_NFSD_FAULT_INJECTION + +void nfsd_forget_clients(u64 num) +{ + struct nfs4_client *clp, *next; + int count = 0; + + nfs4_lock_state(); + list_for_each_entry_safe(clp, next, &client_lru, cl_lru) { + nfsd4_remove_clid_dir(clp); + expire_client(clp); + if (++count == num) + break; + } + nfs4_unlock_state(); + + printk(KERN_INFO "NFSD: Forgot %d clients", count); +} + +static void release_lockowner_sop(struct nfs4_stateowner *sop) +{ + release_lockowner(lockowner(sop)); +} + +static void release_openowner_sop(struct nfs4_stateowner *sop) +{ + release_openowner(openowner(sop)); +} + +static int nfsd_release_n_owners(u64 num, + struct list_head hashtbl[], + unsigned int hashtbl_size, + void (*release_sop)(struct nfs4_stateowner *)) +{ + int i, count = 0; + struct nfs4_stateowner *sop, *next; + + for (i = 0; i < hashtbl_size; i++) { + list_for_each_entry_safe(sop, next, &hashtbl[i], so_strhash) { + release_sop(sop); + if (++count == num) + return count; + } + } + return count; +} + +void nfsd_forget_locks(u64 num) +{ + int count; + + nfs4_lock_state(); + count = nfsd_release_n_owners(num, lock_ownerstr_hashtbl, + LOCK_HASH_SIZE, release_lockowner_sop); + nfs4_unlock_state(); + + printk(KERN_INFO "NFSD: Forgot %d locks", count); +} + +void nfsd_forget_openowners(u64 num) +{ + int count; + + nfs4_lock_state(); + count = nfsd_release_n_owners(num, open_ownerstr_hashtbl, + OPEN_OWNER_HASH_SIZE, release_openowner_sop); + nfs4_unlock_state(); + + printk(KERN_INFO "NFSD: Forgot %d open owners", count); +} + +int nfsd_process_n_delegations(u64 num, void (*deleg_func)(struct nfs4_delegation *)) +{ + int i, count = 0; + struct nfs4_file *fp; + struct nfs4_delegation *dp, *next; + + for (i = 0; i < FILE_HASH_SIZE; i++) { + list_for_each_entry(fp, &file_hashtbl[i], fi_hash) { + list_for_each_entry_safe(dp, next, &fp->fi_delegations, dl_perfile) { + deleg_func(dp); + if (++count == num) + return count; + } + } + } + return count; +} + +void nfsd_forget_delegations(u64 num) +{ + unsigned int count; + + nfs4_lock_state(); + count = nfsd_process_n_delegations(num, unhash_delegation); + nfs4_unlock_state(); + + printk(KERN_INFO "NFSD: Forgot %d delegations", count); +} + +void nfsd_recall_delegations(u64 num) +{ + unsigned int count; + + nfs4_lock_state(); + spin_lock(&recall_lock); + count = nfsd_process_n_delegations(num, nfsd_break_one_deleg); + spin_unlock(&recall_lock); + nfs4_unlock_state(); + + printk(KERN_INFO "NFSD: Recalled %d delegations", count); +} + +#endif /* CONFIG_NFSD_FAULT_INJECTION */ + /* initialization to perform at module load time: */ int diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index c45a2ea..b2e8093 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -18,6 +18,7 @@ #include "idmap.h" #include "nfsd.h" #include "cache.h" +#include "fault_inject.h" /* * We have a single directory with several nodes in it. @@ -1131,6 +1132,9 @@ static int __init init_nfsd(void) retval = nfs4_state_init(); /* nfs4 locking state */ if (retval) return retval; + retval = nfsd_fault_inject_init(); /* nfsd fault injection controls */ + if (retval) + goto out_free_slabs; nfsd_stat_init(); /* Statistics */ retval = nfsd_reply_cache_init(); if (retval) @@ -1161,6 +1165,8 @@ out_free_cache: nfsd_reply_cache_shutdown(); out_free_stat: nfsd_stat_shutdown(); + nfsd_fault_inject_cleanup(); +out_free_slabs: nfsd4_free_slabs(); return retval; } @@ -1175,6 +1181,7 @@ static void __exit exit_nfsd(void) nfsd_lockd_shutdown(); nfsd_idmap_shutdown(); nfsd4_free_slabs(); + nfsd_fault_inject_cleanup(); unregister_filesystem(&nfsd_fs_type); } -- cgit v0.10.2 From 800b927b38c7cdfbd7df39d7a8a4b065637ab7b6 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Tue, 1 Nov 2011 13:35:22 -0400 Subject: NFSD: Added fault injection script This script provides a convenient way to use the NFSD fault injection framework. Fault injection writes to dmesg using the KERN_INFO flag, so this script will compare the before and after output of `dmesg` to show the user what happened Signed-off-by: Bryan Schumaker Signed-off-by: J. Bruce Fields diff --git a/tools/nfsd/inject_fault.sh b/tools/nfsd/inject_fault.sh new file mode 100755 index 0000000..06a399a --- /dev/null +++ b/tools/nfsd/inject_fault.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# +# Copyright (c) 2011 Bryan Schumaker +# +# Script for easier NFSD fault injection + +# Check that debugfs has been mounted +DEBUGFS=`cat /proc/mounts | grep debugfs` +if [ "$DEBUGFS" == "" ]; then + echo "debugfs does not appear to be mounted!" + echo "Please mount debugfs and try again" + exit 1 +fi + +# Check that the fault injection directory exists +DEBUGDIR=`echo $DEBUGFS | awk '{print $2}'`/nfsd +if [ ! -d "$DEBUGDIR" ]; then + echo "$DEBUGDIR does not exist" + echo "Check that your .config selects CONFIG_NFSD_FAULT_INJECTION" + exit 1 +fi + +function help() +{ + echo "Usage $0 injection_type [count]" + echo "" + echo "Injection types are:" + ls $DEBUGDIR + exit 1 +} + +if [ $# == 0 ]; then + help +elif [ ! -f $DEBUGDIR/$1 ]; then + help +elif [ $# != 2 ]; then + COUNT=0 +else + COUNT=$2 +fi + +BEFORE=`mktemp` +AFTER=`mktemp` +dmesg > $BEFORE +echo $COUNT > $DEBUGDIR/$1 +dmesg > $AFTER +# Capture lines that only exist in the $AFTER file +diff $BEFORE $AFTER | grep ">" +rm -f $BEFORE $AFTER -- cgit v0.10.2 From 114a0a08d46cfb0eefb1a882f7866b7f57bfc5ba Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Tue, 1 Nov 2011 13:35:23 -0400 Subject: NFSD: Added fault injection documentation Signed-off-by: Bryan Schumaker Signed-off-by: J. Bruce Fields diff --git a/Documentation/filesystems/nfs/00-INDEX b/Documentation/filesystems/nfs/00-INDEX index a57e124..1716874a 100644 --- a/Documentation/filesystems/nfs/00-INDEX +++ b/Documentation/filesystems/nfs/00-INDEX @@ -2,6 +2,8 @@ - this file (nfs-related documentation). Exporting - explanation of how to make filesystems exportable. +fault_injection.txt + - information for using fault injection on the server knfsd-stats.txt - statistics which the NFS server makes available to user space. nfs.txt diff --git a/Documentation/filesystems/nfs/fault_injection.txt b/Documentation/filesystems/nfs/fault_injection.txt new file mode 100644 index 0000000..426d166 --- /dev/null +++ b/Documentation/filesystems/nfs/fault_injection.txt @@ -0,0 +1,69 @@ + +Fault Injection +=============== +Fault injection is a method for forcing errors that may not normally occur, or +may be difficult to reproduce. Forcing these errors in a controlled environment +can help the developer find and fix bugs before their code is shipped in a +production system. Injecting an error on the Linux NFS server will allow us to +observe how the client reacts and if it manages to recover its state correctly. + +NFSD_FAULT_INJECTION must be selected when configuring the kernel to use this +feature. + + +Using Fault Injection +===================== +On the client, mount the fault injection server through NFS v4.0+ and do some +work over NFS (open files, take locks, ...). + +On the server, mount the debugfs filesystem to and ls +/nfsd. This will show a list of files that will be used for +injecting faults on the NFS server. As root, write a number n to the file +corresponding to the action you want the server to take. The server will then +process the first n items it finds. So if you want to forget 5 locks, echo '5' +to /nfsd/forget_locks. A value of 0 will tell the server to forget +all corresponding items. A log message will be created containing the number +of items forgotten (check dmesg). + +Go back to work on the client and check if the client recovered from the error +correctly. + + +Available Faults +================ +forget_clients: + The NFS server keeps a list of clients that have placed a mount call. If + this list is cleared, the server will have no knowledge of who the client + is, forcing the client to reauthenticate with the server. + +forget_openowners: + The NFS server keeps a list of what files are currently opened and who + they were opened by. Clearing this list will force the client to reopen + its files. + +forget_locks: + The NFS server keeps a list of what files are currently locked in the VFS. + Clearing this list will force the client to reclaim its locks (files are + unlocked through the VFS as they are cleared from this list). + +forget_delegations: + A delegation is used to assure the client that a file, or part of a file, + has not changed since the delegation was awarded. Clearing this list will + force the client to reaquire its delegation before accessing the file + again. + +recall_delegations: + Delegations can be recalled by the server when another client attempts to + access a file. This test will notify the client that its delegation has + been revoked, forcing the client to reaquire the delegation before using + the file again. + + +tools/nfs/inject_faults.sh script +================================= +This script has been created to ease the fault injection process. This script +will detect the mounted debugfs directory and write to the files located there +based on the arguments passed by the user. For example, running +`inject_faults.sh forget_locks 1` as root will instruct the server to forget +one lock. Running `inject_faults forget_locks` will instruct the server to +forgetall locks. -- cgit v0.10.2 From 72083396074035ffa5cf81b6bb3e55f1d615badf Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Tue, 1 Nov 2011 15:24:59 -0400 Subject: NFSD: Call nfsd4_init_slabs() from init_nfsd() init_nfsd() was calling free_slabs() during cleanup code, but the call to init_slabs() was hidden in nfsd4_state_init(). This could be confusing to people unfamiliar with the code. Signed-off-by: Bryan Schumaker Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index a511eff..1d6812d 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -2301,7 +2301,7 @@ nfsd4_free_slabs(void) nfsd4_free_slab(&deleg_slab); } -static int +int nfsd4_init_slabs(void) { openowner_slab = kmem_cache_create("nfsd4_openowners", @@ -4546,14 +4546,11 @@ void nfsd_recall_delegations(u64 num) /* initialization to perform at module load time: */ -int +void nfs4_state_init(void) { - int i, status; + int i; - status = nfsd4_init_slabs(); - if (status) - return status; for (i = 0; i < CLIENT_HASH_SIZE; i++) { INIT_LIST_HEAD(&conf_id_hashtbl[i]); INIT_LIST_HEAD(&conf_str_hashtbl[i]); @@ -4577,7 +4574,6 @@ nfs4_state_init(void) INIT_LIST_HEAD(&client_lru); INIT_LIST_HEAD(&del_recall_lru); reclaim_str_hashtbl_size = 0; - return 0; } static void diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index b2e8093..8daa935 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -1129,9 +1129,10 @@ static int __init init_nfsd(void) int retval; printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n"); - retval = nfs4_state_init(); /* nfs4 locking state */ + retval = nfsd4_init_slabs(); if (retval) return retval; + nfs4_state_init(); retval = nfsd_fault_inject_init(); /* nfsd fault injection controls */ if (retval) goto out_free_slabs; diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 58134a2..4e2ee29 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -104,14 +104,16 @@ static inline int nfsd_v4client(struct svc_rqst *rq) */ #ifdef CONFIG_NFSD_V4 extern unsigned int max_delegations; -int nfs4_state_init(void); +void nfs4_state_init(void); +int nfsd4_init_slabs(void); void nfsd4_free_slabs(void); int nfs4_state_start(void); void nfs4_state_shutdown(void); void nfs4_reset_lease(time_t leasetime); int nfs4_reset_recoverydir(char *recdir); #else -static inline int nfs4_state_init(void) { return 0; } +static inline void nfs4_state_init(void) { } +static inline int nfsd4_init_slabs(void) { return 0; } static inline void nfsd4_free_slabs(void) { } static inline int nfs4_state_start(void) { return 0; } static inline void nfs4_state_shutdown(void) { } -- cgit v0.10.2 From c7e8472cf8ae877b232eb506284a5b15cf7efb2c Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Tue, 1 Nov 2011 14:18:28 -0400 Subject: NFSD: Remove unnecessary whitespace The close parenthesis was hard to find with it spaced so far over. Signed-off-by: Bryan Schumaker [bfields@redhat.com: get all these lines under 80 chars while we're here] Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 4e2ee29..1d1e858 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -340,15 +340,15 @@ static inline u32 nfsd_suppattrs2(u32 minorversion) } /* These will return ERR_INVAL if specified in GETATTR or READDIR. */ -#define NFSD_WRITEONLY_ATTRS_WORD1 \ -(FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET) +#define NFSD_WRITEONLY_ATTRS_WORD1 \ + (FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET) /* These are the only attrs allowed in CREATE/OPEN/SETATTR. */ -#define NFSD_WRITEABLE_ATTRS_WORD0 \ -(FATTR4_WORD0_SIZE | FATTR4_WORD0_ACL ) -#define NFSD_WRITEABLE_ATTRS_WORD1 \ -(FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \ - | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET) +#define NFSD_WRITEABLE_ATTRS_WORD0 \ + (FATTR4_WORD0_SIZE | FATTR4_WORD0_ACL) +#define NFSD_WRITEABLE_ATTRS_WORD1 \ + (FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \ + | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET) #define NFSD_WRITEABLE_ATTRS_WORD2 0 #define NFSD_SUPPATTR_EXCLCREAT_WORD0 \ -- cgit v0.10.2 From 06f1f864d4ae5804e83785308d41f14a08e4b980 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 7 Nov 2011 16:58:18 -0500 Subject: nfsd4: hash lockowners to simplify RELEASE_LOCKOWNER Hash lockowners on just the owner string rather than on (owner, inode). This makes the owner-string lookup needed for RELEASE_LOCKOWNER simpler (currently it's doing at a linear search through the entire hash table!). That may come at the expense of making (owner, inode) lookups more expensive if a client reuses the same lockowner across multiple files. We might add a separate lookup for that. Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 1d6812d..eec9900 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3746,15 +3746,6 @@ last_byte_offset(u64 start, u64 len) return end > start ? end - 1: NFS4_MAX_UINT64; } -static inline unsigned int -lock_ownerstr_hashval(struct inode *inode, u32 cl_id, - struct xdr_netobj *ownername) -{ - return (file_hashval(inode) + cl_id - + opaque_hashval(ownername->data, ownername->len)) - & LOCK_HASH_MASK; -} - static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE]; /* @@ -3824,7 +3815,7 @@ static struct nfs4_lockowner * find_lockowner_str(struct inode *inode, clientid_t *clid, struct xdr_netobj *owner) { - unsigned int hashval = lock_ownerstr_hashval(inode, clid->cl_id, owner); + unsigned int hashval = open_ownerstr_hashval(clid->cl_id, owner); struct nfs4_lockowner *lo; struct nfs4_stateowner *op; @@ -3847,7 +3838,7 @@ static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, s * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has * occurred. * - * strhashval = lock_ownerstr_hashval + * strhashval = open_ownerstr_hashval */ static struct nfs4_lockowner * @@ -3922,7 +3913,7 @@ __be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, struct n struct nfs4_ol_stateid, st_perstateowner); return nfs_ok; } - strhashval = lock_ownerstr_hashval(fi->fi_inode, cl->cl_clientid.cl_id, + strhashval = open_ownerstr_hashval(cl->cl_clientid.cl_id, &lock->v.new.owner); lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock); if (lo == NULL) @@ -4286,7 +4277,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfs4_ol_stateid *stp; struct xdr_netobj *owner = &rlockowner->rl_owner; struct list_head matches; - int i; + unsigned int hashval = open_ownerstr_hashval(clid->cl_id, owner); __be32 status; dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n", @@ -4301,22 +4292,17 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, nfs4_lock_state(); status = nfserr_locks_held; - /* XXX: we're doing a linear search through all the lockowners. - * Yipes! For now we'll just hope clients aren't really using - * release_lockowner much, but eventually we have to fix these - * data structures. */ INIT_LIST_HEAD(&matches); - for (i = 0; i < LOCK_HASH_SIZE; i++) { - list_for_each_entry(sop, &lock_ownerstr_hashtbl[i], so_strhash) { - if (!same_owner_str(sop, owner, clid)) - continue; - list_for_each_entry(stp, &sop->so_stateids, - st_perstateowner) { - lo = lockowner(sop); - if (check_for_locks(stp->st_file, lo)) - goto out; - list_add(&lo->lo_list, &matches); - } + + list_for_each_entry(sop, &lock_ownerstr_hashtbl[hashval], so_strhash) { + if (!same_owner_str(sop, owner, clid)) + continue; + list_for_each_entry(stp, &sop->so_stateids, + st_perstateowner) { + lo = lockowner(sop); + if (check_for_locks(stp->st_file, lo)) + goto out; + list_add(&lo->lo_list, &matches); } } /* Clients probably won't expect us to return with some (but not all) -- cgit v0.10.2 From f7901f9b4ae06d65537ff3db8605e657f6d4afce Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 3 Nov 2011 08:39:12 -0300 Subject: [media] mxl111sf: add mxl111sf_tuner_get_if_frequency Reported-by: Antti Palosaari Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c b/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c index a634105..3bfc6d8 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c +++ b/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c @@ -38,6 +38,8 @@ struct mxl111sf_tuner_state { struct mxl111sf_tuner_config *cfg; + enum mxl_if_freq if_freq; + u32 frequency; u32 bandwidth; }; @@ -186,7 +188,10 @@ static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state *state) ctrl = iffcw & 0x00ff; #endif ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_REG, ctrl); - mxl_fail(ret); + if (mxl_fail(ret)) + goto fail; + + state->if_freq = state->cfg->if_freq; fail: return ret; } @@ -407,6 +412,54 @@ static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) return 0; } +static int mxl111sf_tuner_get_if_frequency(struct dvb_frontend *fe, + u32 *frequency) +{ + struct mxl111sf_tuner_state *state = fe->tuner_priv; + + *frequency = 0; + + switch (state->if_freq) { + case MXL_IF_4_0: /* 4.0 MHz */ + *frequency = 4000000; + break; + case MXL_IF_4_5: /* 4.5 MHz */ + *frequency = 4500000; + break; + case MXL_IF_4_57: /* 4.57 MHz */ + *frequency = 4570000; + break; + case MXL_IF_5_0: /* 5.0 MHz */ + *frequency = 5000000; + break; + case MXL_IF_5_38: /* 5.38 MHz */ + *frequency = 5380000; + break; + case MXL_IF_6_0: /* 6.0 MHz */ + *frequency = 6000000; + break; + case MXL_IF_6_28: /* 6.28 MHz */ + *frequency = 6280000; + break; + case MXL_IF_7_2: /* 7.2 MHz */ + *frequency = 7200000; + break; + case MXL_IF_35_25: /* 35.25 MHz */ + *frequency = 35250000; + break; + case MXL_IF_36: /* 36 MHz */ + *frequency = 36000000; + break; + case MXL_IF_36_15: /* 36.15 MHz */ + *frequency = 36150000; + break; + case MXL_IF_44: /* 44 MHz */ + *frequency = 44000000; + break; + } + return 0; +} + static int mxl111sf_tuner_release(struct dvb_frontend *fe) { struct mxl111sf_tuner_state *state = fe->tuner_priv; @@ -436,6 +489,7 @@ static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = { .get_rf_strength = mxl111sf_get_rf_strength, .get_frequency = mxl111sf_tuner_get_frequency, .get_bandwidth = mxl111sf_tuner_get_bandwidth, + .get_if_frequency = mxl111sf_tuner_get_if_frequency, .release = mxl111sf_tuner_release, }; -- cgit v0.10.2 From d697b4ce9490d82380a3fe153a7f9fbe017295f2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 3 Nov 2011 09:12:04 -0300 Subject: [media] mxl5007t: add mxl5007t_get_if_frequency Reported-by: Antti Palosaari Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c index 7eb1bf7..2f0e550 100644 --- a/drivers/media/common/tuners/mxl5007t.c +++ b/drivers/media/common/tuners/mxl5007t.c @@ -165,6 +165,8 @@ struct mxl5007t_state { struct reg_pair_t tab_init_cable[ARRAY_SIZE(init_tab_cable)]; struct reg_pair_t tab_rftune[ARRAY_SIZE(reg_pair_rftune)]; + enum mxl5007t_if_freq if_freq; + u32 frequency; u32 bandwidth; }; @@ -286,6 +288,8 @@ static void mxl5007t_set_if_freq_bits(struct mxl5007t_state *state, /* set inverted IF or normal IF */ set_reg_bits(state->tab_init, 0x02, 0x10, invert_if ? 0x10 : 0x00); + state->if_freq = if_freq; + return; } @@ -737,6 +741,50 @@ static int mxl5007t_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) return 0; } +static int mxl5007t_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct mxl5007t_state *state = fe->tuner_priv; + + *frequency = 0; + + switch (state->if_freq) { + case MxL_IF_4_MHZ: + *frequency = 4000000; + break; + case MxL_IF_4_5_MHZ: + *frequency = 4500000; + break; + case MxL_IF_4_57_MHZ: + *frequency = 4570000; + break; + case MxL_IF_5_MHZ: + *frequency = 5000000; + break; + case MxL_IF_5_38_MHZ: + *frequency = 5380000; + break; + case MxL_IF_6_MHZ: + *frequency = 6000000; + break; + case MxL_IF_6_28_MHZ: + *frequency = 6280000; + break; + case MxL_IF_9_1915_MHZ: + *frequency = 9191500; + break; + case MxL_IF_35_25_MHZ: + *frequency = 35250000; + break; + case MxL_IF_36_15_MHZ: + *frequency = 36150000; + break; + case MxL_IF_44_MHZ: + *frequency = 44000000; + break; + } + return 0; +} + static int mxl5007t_release(struct dvb_frontend *fe) { struct mxl5007t_state *state = fe->tuner_priv; @@ -766,6 +814,7 @@ static struct dvb_tuner_ops mxl5007t_tuner_ops = { .get_frequency = mxl5007t_get_frequency, .get_bandwidth = mxl5007t_get_bandwidth, .release = mxl5007t_release, + .get_if_frequency = mxl5007t_get_if_frequency, }; static int mxl5007t_get_chip_id(struct mxl5007t_state *state) -- cgit v0.10.2 From 8c8ee11345fa26e46cbc9ec88581736e38915b16 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 3 Nov 2011 09:59:42 -0300 Subject: [media] tda18271: add tda18271_get_if_frequency Reported-by: Antti Palosaari Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 63cc400..3347c5b 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -994,6 +994,7 @@ static int tda18271_set_params(struct dvb_frontend *fe, if (tda_fail(ret)) goto fail; + priv->if_freq = map->if_freq; priv->frequency = freq; priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; @@ -1050,6 +1051,7 @@ static int tda18271_set_analog_params(struct dvb_frontend *fe, if (tda_fail(ret)) goto fail; + priv->if_freq = map->if_freq; priv->frequency = freq; priv->bandwidth = 0; fail: @@ -1086,6 +1088,13 @@ static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) return 0; } +static int tda18271_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct tda18271_priv *priv = fe->tuner_priv; + *frequency = (u32)priv->if_freq * 1000; + return 0; +} + /* ------------------------------------------------------------------ */ #define tda18271_update_std(std_cfg, name) do { \ @@ -1245,6 +1254,7 @@ static const struct dvb_tuner_ops tda18271_tuner_ops = { .set_config = tda18271_set_config, .get_frequency = tda18271_get_frequency, .get_bandwidth = tda18271_get_bandwidth, + .get_if_frequency = tda18271_get_if_frequency, }; struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, diff --git a/drivers/media/common/tuners/tda18271-priv.h b/drivers/media/common/tuners/tda18271-priv.h index 94340f4..454c152 100644 --- a/drivers/media/common/tuners/tda18271-priv.h +++ b/drivers/media/common/tuners/tda18271-priv.h @@ -122,6 +122,8 @@ struct tda18271_priv { struct mutex lock; + u16 if_freq; + u32 frequency; u32 bandwidth; }; -- cgit v0.10.2 From 918847341af0f5f1907fc0b52549f0dc29192c03 Mon Sep 17 00:00:00 2001 From: Kamil Debski Date: Thu, 6 Oct 2011 11:32:12 -0300 Subject: [media] v4l: add G2D driver for s5p device family G2D is a 2D graphics accelerator engine present in the s5p family of Samsung SoCs. It is capable of bitblt and raster operations on images having dimensions of up to 8000x8000. Signed-off-by: Kamil Debski Signed-off-by: Kyungmin Park Signed-off-by: Marek Szyprowski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index b303a3f..d960656 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -1098,6 +1098,15 @@ config VIDEO_MEM2MEM_TESTDEV This is a virtual test device for the memory-to-memory driver framework. +config VIDEO_SAMSUNG_S5P_G2D + tristate "Samsung S5P and EXYNOS4 G2D 2d graphics accelerator driver" + depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P + select VIDEOBUF2_DMA_CONTIG + select V4L2_MEM2MEM_DEV + default n + ---help--- + This is a v4l2 driver for Samsung S5P and EXYNOS4 G2D + 2d graphics accelerator. config VIDEO_SAMSUNG_S5P_MFC tristate "Samsung S5P MFC 5.1 Video Codec" diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 117f9c4..ddeaa6c 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -180,6 +180,8 @@ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc/ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV) += s5p-tv/ +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D) += s5p-g2d/ + obj-$(CONFIG_ARCH_DAVINCI) += davinci/ obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o diff --git a/drivers/media/video/s5p-g2d/Makefile b/drivers/media/video/s5p-g2d/Makefile new file mode 100644 index 0000000..2c48c41 --- /dev/null +++ b/drivers/media/video/s5p-g2d/Makefile @@ -0,0 +1,3 @@ +s5p-g2d-objs := g2d.o g2d-hw.o + +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D) += s5p-g2d.o diff --git a/drivers/media/video/s5p-g2d/g2d-hw.c b/drivers/media/video/s5p-g2d/g2d-hw.c new file mode 100644 index 0000000..e5249f3 --- /dev/null +++ b/drivers/media/video/s5p-g2d/g2d-hw.c @@ -0,0 +1,106 @@ +/* + * Samsung S5P G2D - 2D Graphics Accelerator Driver + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * Kamil Debski, + * + * 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 "g2d.h" +#include "g2d-regs.h" + +#define w(x, a) writel((x), d->regs + (a)) +#define r(a) readl(d->regs + (a)) + +/* g2d_reset clears all g2d registers */ +void g2d_reset(struct g2d_dev *d) +{ + w(1, SOFT_RESET_REG); +} + +void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f) +{ + u32 n; + u32 stride; + + w(f->stride & 0xFFFF, SRC_STRIDE_REG); + + n = f->o_height & 0xFFF; + n <<= 16; + n |= f->o_width & 0xFFF; + w(n, SRC_LEFT_TOP_REG); + + n = f->bottom & 0xFFF; + n <<= 16; + n |= f->right & 0xFFF; + w(n, SRC_RIGHT_BOTTOM_REG); + + w(f->fmt->hw, SRC_COLOR_MODE_REG); +} + +void g2d_set_src_addr(struct g2d_dev *d, dma_addr_t a) +{ + w(a, SRC_BASE_ADDR_REG); +} + +void g2d_set_dst_size(struct g2d_dev *d, struct g2d_frame *f) +{ + u32 n; + u32 stride; + + w(f->stride & 0xFFFF, DST_STRIDE_REG); + + n = f->o_height & 0xFFF; + n <<= 16; + n |= f->o_width & 0xFFF; + w(n, DST_LEFT_TOP_REG); + + n = f->bottom & 0xFFF; + n <<= 16; + n |= f->right & 0xFFF; + w(n, DST_RIGHT_BOTTOM_REG); + + w(f->fmt->hw, DST_COLOR_MODE_REG); +} + +void g2d_set_dst_addr(struct g2d_dev *d, dma_addr_t a) +{ + w(a, DST_BASE_ADDR_REG); +} + +void g2d_set_rop4(struct g2d_dev *d, u32 r) +{ + w(r, ROP4_REG); +} + +u32 g2d_cmd_stretch(u32 e) +{ + e &= 1; + return e << 4; +} + +void g2d_set_cmd(struct g2d_dev *d, u32 c) +{ + w(c, BITBLT_COMMAND_REG); +} + +void g2d_start(struct g2d_dev *d) +{ + /* Clear cache */ + w(0x7, CACHECTL_REG); + /* Enable interrupt */ + w(1, INTEN_REG); + /* Start G2D engine */ + w(1, BITBLT_START_REG); +} + +void g2d_clear_int(struct g2d_dev *d) +{ + w(1, INTC_PEND_REG); +} diff --git a/drivers/media/video/s5p-g2d/g2d-regs.h b/drivers/media/video/s5p-g2d/g2d-regs.h new file mode 100644 index 0000000..02e1cf5 --- /dev/null +++ b/drivers/media/video/s5p-g2d/g2d-regs.h @@ -0,0 +1,115 @@ +/* + * Samsung S5P G2D - 2D Graphics Accelerator Driver + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * Kamil Debski, + * + * 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 + */ + +/* General Registers */ +#define SOFT_RESET_REG 0x0000 /* Software reset reg */ +#define INTEN_REG 0x0004 /* Interrupt Enable reg */ +#define INTC_PEND_REG 0x000C /* Interrupt Control Pending reg */ +#define FIFO_STAT_REG 0x0010 /* Command FIFO Status reg */ +#define AXI_ID_MODE_REG 0x0014 /* AXI Read ID Mode reg */ +#define CACHECTL_REG 0x0018 /* Cache & Buffer clear reg */ +#define AXI_MODE_REG 0x001C /* AXI Mode reg */ + +/* Command Registers */ +#define BITBLT_START_REG 0x0100 /* BitBLT Start reg */ +#define BITBLT_COMMAND_REG 0x0104 /* Command reg for BitBLT */ + +/* Parameter Setting Registers (Rotate & Direction) */ +#define ROTATE_REG 0x0200 /* Rotation reg */ +#define SRC_MSK_DIRECT_REG 0x0204 /* Src and Mask Direction reg */ +#define DST_PAT_DIRECT_REG 0x0208 /* Dest and Pattern Direction reg */ + +/* Parameter Setting Registers (Src) */ +#define SRC_SELECT_REG 0x0300 /* Src Image Selection reg */ +#define SRC_BASE_ADDR_REG 0x0304 /* Src Image Base Address reg */ +#define SRC_STRIDE_REG 0x0308 /* Src Stride reg */ +#define SRC_COLOR_MODE_REG 0x030C /* Src Image Color Mode reg */ +#define SRC_LEFT_TOP_REG 0x0310 /* Src Left Top Coordinate reg */ +#define SRC_RIGHT_BOTTOM_REG 0x0314 /* Src Right Bottom Coordinate reg */ + +/* Parameter Setting Registers (Dest) */ +#define DST_SELECT_REG 0x0400 /* Dest Image Selection reg */ +#define DST_BASE_ADDR_REG 0x0404 /* Dest Image Base Address reg */ +#define DST_STRIDE_REG 0x0408 /* Dest Stride reg */ +#define DST_COLOR_MODE_REG 0x040C /* Dest Image Color Mode reg */ +#define DST_LEFT_TOP_REG 0x0410 /* Dest Left Top Coordinate reg */ +#define DST_RIGHT_BOTTOM_REG 0x0414 /* Dest Right Bottom Coordinate reg */ + +/* Parameter Setting Registers (Pattern) */ +#define PAT_BASE_ADDR_REG 0x0500 /* Pattern Image Base Address reg */ +#define PAT_SIZE_REG 0x0504 /* Pattern Image Size reg */ +#define PAT_COLOR_MODE_REG 0x0508 /* Pattern Image Color Mode reg */ +#define PAT_OFFSET_REG 0x050C /* Pattern Left Top Coordinate reg */ +#define PAT_STRIDE_REG 0x0510 /* Pattern Stride reg */ + +/* Parameter Setting Registers (Mask) */ +#define MASK_BASE_ADDR_REG 0x0520 /* Mask Base Address reg */ +#define MASK_STRIDE_REG 0x0524 /* Mask Stride reg */ + +/* Parameter Setting Registers (Clipping Window) */ +#define CW_LT_REG 0x0600 /* LeftTop coordinates of Clip Window */ +#define CW_RB_REG 0x0604 /* RightBottom coordinates of Clip + Window */ + +/* Parameter Setting Registers (ROP & Alpha Setting) */ +#define THIRD_OPERAND_REG 0x0610 /* Third Operand Selection reg */ +#define ROP4_REG 0x0614 /* Raster Operation reg */ +#define ALPHA_REG 0x0618 /* Alpha value, Fading offset value */ + +/* Parameter Setting Registers (Color) */ +#define FG_COLOR_REG 0x0700 /* Foreground Color reg */ +#define BG_COLOR_REG 0x0704 /* Background Color reg */ +#define BS_COLOR_REG 0x0708 /* Blue Screen Color reg */ + +/* Parameter Setting Registers (Color Key) */ +#define SRC_COLORKEY_CTRL_REG 0x0710 /* Src Colorkey control reg */ +#define SRC_COLORKEY_DR_MIN_REG 0x0714 /* Src Colorkey Decision Reference + Min reg */ +#define SRC_COLORKEY_DR_MAX_REG 0x0718 /* Src Colorkey Decision Reference + Max reg */ +#define DST_COLORKEY_CTRL_REG 0x071C /* Dest Colorkey control reg */ +#define DST_COLORKEY_DR_MIN_REG 0x0720 /* Dest Colorkey Decision Reference + Min reg */ +#define DST_COLORKEY_DR_MAX_REG 0x0724 /* Dest Colorkey Decision Reference + Max reg */ + +/* Color mode values */ + +#define ORDER_XRGB 0 +#define ORDER_RGBX 1 +#define ORDER_XBGR 2 +#define ORDER_BGRX 3 + +#define MODE_XRGB_8888 0 +#define MODE_ARGB_8888 1 +#define MODE_RGB_565 2 +#define MODE_XRGB_1555 3 +#define MODE_ARGB_1555 4 +#define MODE_XRGB_4444 5 +#define MODE_ARGB_4444 6 +#define MODE_PACKED_RGB_888 7 + +#define COLOR_MODE(o, m) (((o) << 4) | (m)) + +/* ROP4 operation values */ +#define ROP4_COPY 0xCCCC +#define ROP4_INVERT 0x3333 + +/* Hardware limits */ +#define MAX_WIDTH 8000 +#define MAX_HEIGHT 8000 + +#define G2D_TIMEOUT 500 + +#define DEFAULT_WIDTH 100 +#define DEFAULT_HEIGHT 100 + diff --git a/drivers/media/video/s5p-g2d/g2d.c b/drivers/media/video/s5p-g2d/g2d.c new file mode 100644 index 0000000..1f156c8 --- /dev/null +++ b/drivers/media/video/s5p-g2d/g2d.c @@ -0,0 +1,824 @@ +/* + * Samsung S5P G2D - 2D Graphics Accelerator Driver + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * Kamil Debski, + * + * 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 +#include + +#include "g2d.h" +#include "g2d-regs.h" + +#define fh2ctx(__fh) container_of(__fh, struct g2d_ctx, fh) + +static struct g2d_fmt formats[] = { + { + .name = "XRGB_8888", + .fourcc = V4L2_PIX_FMT_RGB32, + .depth = 32, + .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_8888), + }, + { + .name = "RGB_565", + .fourcc = V4L2_PIX_FMT_RGB565X, + .depth = 16, + .hw = COLOR_MODE(ORDER_XRGB, MODE_RGB_565), + }, + { + .name = "XRGB_1555", + .fourcc = V4L2_PIX_FMT_RGB555X, + .depth = 16, + .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_1555), + }, + { + .name = "XRGB_4444", + .fourcc = V4L2_PIX_FMT_RGB444, + .depth = 16, + .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_4444), + }, + { + .name = "PACKED_RGB_888", + .fourcc = V4L2_PIX_FMT_RGB24, + .depth = 24, + .hw = COLOR_MODE(ORDER_XRGB, MODE_PACKED_RGB_888), + }, +}; +#define NUM_FORMATS ARRAY_SIZE(formats) + +struct g2d_frame def_frame = { + .width = DEFAULT_WIDTH, + .height = DEFAULT_HEIGHT, + .c_width = DEFAULT_WIDTH, + .c_height = DEFAULT_HEIGHT, + .o_width = 0, + .o_height = 0, + .fmt = &formats[0], + .right = DEFAULT_WIDTH, + .bottom = DEFAULT_HEIGHT, +}; + +struct g2d_fmt *find_fmt(struct v4l2_format *f) +{ + unsigned int i; + for (i = 0; i < NUM_FORMATS; i++) { + if (formats[i].fourcc == f->fmt.pix.pixelformat) + return &formats[i]; + } + return NULL; +} + + +static struct g2d_frame *get_frame(struct g2d_ctx *ctx, + enum v4l2_buf_type type) +{ + switch (type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + return &ctx->in; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return &ctx->out; + default: + return ERR_PTR(-EINVAL); + } +} + +static int g2d_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct g2d_ctx *ctx = vb2_get_drv_priv(vq); + struct g2d_frame *f = get_frame(ctx, vq->type); + + if (IS_ERR(f)) + return PTR_ERR(f); + + sizes[0] = f->size; + *nplanes = 1; + alloc_ctxs[0] = ctx->dev->alloc_ctx; + + if (*nbuffers == 0) + *nbuffers = 1; + + return 0; +} + +static int g2d_buf_prepare(struct vb2_buffer *vb) +{ + struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct g2d_frame *f = get_frame(ctx, vb->vb2_queue->type); + + if (IS_ERR(f)) + return PTR_ERR(f); + vb2_set_plane_payload(vb, 0, f->size); + return 0; +} + +static void g2d_buf_queue(struct vb2_buffer *vb) +{ + struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); +} + + +static struct vb2_ops g2d_qops = { + .queue_setup = g2d_queue_setup, + .buf_prepare = g2d_buf_prepare, + .buf_queue = g2d_buf_queue, +}; + +static int queue_init(void *priv, struct vb2_queue *src_vq, + struct vb2_queue *dst_vq) +{ + struct g2d_ctx *ctx = priv; + int ret; + + memset(src_vq, 0, sizeof(*src_vq)); + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + src_vq->io_modes = VB2_MMAP | VB2_USERPTR; + src_vq->drv_priv = ctx; + src_vq->ops = &g2d_qops; + src_vq->mem_ops = &vb2_dma_contig_memops; + src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + + ret = vb2_queue_init(src_vq); + if (ret) + return ret; + + memset(dst_vq, 0, sizeof(*dst_vq)); + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; + dst_vq->drv_priv = ctx; + dst_vq->ops = &g2d_qops; + dst_vq->mem_ops = &vb2_dma_contig_memops; + dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + + return vb2_queue_init(dst_vq); +} + +static int g2d_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct g2d_ctx *ctx = container_of(ctrl->handler, struct g2d_ctx, + ctrl_handler); + switch (ctrl->id) { + case V4L2_CID_COLORFX: + if (ctrl->val == V4L2_COLORFX_NEGATIVE) + ctx->rop = ROP4_INVERT; + else + ctx->rop = ROP4_COPY; + default: + v4l2_err(&ctx->dev->v4l2_dev, "unknown control\n"); + return -EINVAL; + } + return 0; +} + +static const struct v4l2_ctrl_ops g2d_ctrl_ops = { + .s_ctrl = g2d_s_ctrl, +}; + +int g2d_setup_ctrls(struct g2d_ctx *ctx) +{ + struct g2d_dev *dev = ctx->dev; + + v4l2_ctrl_handler_init(&ctx->ctrl_handler, 1); + if (ctx->ctrl_handler.error) { + v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n"); + return ctx->ctrl_handler.error; + } + + v4l2_ctrl_new_std_menu( + &ctx->ctrl_handler, + &g2d_ctrl_ops, + V4L2_CID_COLORFX, + V4L2_COLORFX_NEGATIVE, + ~((1 << V4L2_COLORFX_NONE) | (1 << V4L2_COLORFX_NEGATIVE)), + V4L2_COLORFX_NONE); + + if (ctx->ctrl_handler.error) { + v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n"); + return ctx->ctrl_handler.error; + } + + return 0; +} + +static int g2d_open(struct file *file) +{ + struct g2d_dev *dev = video_drvdata(file); + struct g2d_ctx *ctx = NULL; + int ret = 0; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + ctx->dev = dev; + /* Set default formats */ + ctx->in = def_frame; + ctx->out = def_frame; + + ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init); + if (IS_ERR(ctx->m2m_ctx)) { + ret = PTR_ERR(ctx->m2m_ctx); + kfree(ctx); + return ret; + } + v4l2_fh_init(&ctx->fh, video_devdata(file)); + file->private_data = &ctx->fh; + v4l2_fh_add(&ctx->fh); + + g2d_setup_ctrls(ctx); + + /* Write the default values to the ctx struct */ + v4l2_ctrl_handler_setup(&ctx->ctrl_handler); + + ctx->fh.ctrl_handler = &ctx->ctrl_handler; + + v4l2_info(&dev->v4l2_dev, "instance opened\n"); + return 0; +} + +static int g2d_release(struct file *file) +{ + struct g2d_dev *dev = video_drvdata(file); + struct g2d_ctx *ctx = fh2ctx(file->private_data); + + v4l2_ctrl_handler_free(&ctx->ctrl_handler); + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + kfree(ctx); + v4l2_info(&dev->v4l2_dev, "instance closed\n"); + return 0; +} + + +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + strncpy(cap->driver, G2D_NAME, sizeof(cap->driver) - 1); + strncpy(cap->card, G2D_NAME, sizeof(cap->card) - 1); + cap->bus_info[0] = 0; + cap->version = KERNEL_VERSION(1, 0, 0); + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT + | V4L2_CAP_STREAMING; + return 0; +} + +static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) +{ + struct g2d_fmt *fmt; + if (f->index >= NUM_FORMATS) + return -EINVAL; + fmt = &formats[f->index]; + f->pixelformat = fmt->fourcc; + strncpy(f->description, fmt->name, sizeof(f->description) - 1); + return 0; +} + +static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) +{ + struct g2d_ctx *ctx = prv; + struct vb2_queue *vq; + struct g2d_frame *frm; + + vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + if (!vq) + return -EINVAL; + frm = get_frame(ctx, f->type); + if (IS_ERR(frm)) + return PTR_ERR(frm); + + f->fmt.pix.width = frm->width; + f->fmt.pix.height = frm->height; + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.pixelformat = frm->fmt->fourcc; + f->fmt.pix.bytesperline = (frm->width * frm->fmt->depth) >> 3; + f->fmt.pix.sizeimage = frm->size; + return 0; +} + +static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f) +{ + struct g2d_fmt *fmt; + enum v4l2_field *field; + + fmt = find_fmt(f); + if (!fmt) + return -EINVAL; + + field = &f->fmt.pix.field; + if (*field == V4L2_FIELD_ANY) + *field = V4L2_FIELD_NONE; + else if (*field != V4L2_FIELD_NONE) + return -EINVAL; + + if (f->fmt.pix.width > MAX_WIDTH) + f->fmt.pix.width = MAX_WIDTH; + if (f->fmt.pix.height > MAX_HEIGHT) + f->fmt.pix.height = MAX_HEIGHT; + + if (f->fmt.pix.width < 1) + f->fmt.pix.width = 1; + if (f->fmt.pix.height < 1) + f->fmt.pix.height = 1; + + f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + return 0; +} + +static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) +{ + struct g2d_ctx *ctx = prv; + struct g2d_dev *dev = ctx->dev; + struct vb2_queue *vq; + struct g2d_frame *frm; + struct g2d_fmt *fmt; + int ret = 0; + + /* Adjust all values accordingly to the hardware capabilities + * and chosen format. */ + ret = vidioc_try_fmt(file, prv, f); + if (ret) + return ret; + vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); + if (vb2_is_busy(vq)) { + v4l2_err(&dev->v4l2_dev, "queue (%d) bust\n", f->type); + return -EBUSY; + } + frm = get_frame(ctx, f->type); + if (IS_ERR(frm)) + return PTR_ERR(frm); + fmt = find_fmt(f); + if (!fmt) + return -EINVAL; + frm->width = f->fmt.pix.width; + frm->height = f->fmt.pix.height; + frm->size = f->fmt.pix.sizeimage; + /* Reset crop settings */ + frm->o_width = 0; + frm->o_height = 0; + frm->c_width = frm->width; + frm->c_height = frm->height; + frm->right = frm->width; + frm->bottom = frm->height; + frm->fmt = fmt; + frm->stride = f->fmt.pix.bytesperline; + return 0; +} + +static unsigned int g2d_poll(struct file *file, struct poll_table_struct *wait) +{ + struct g2d_ctx *ctx = fh2ctx(file->private_data); + return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); +} + +static int g2d_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct g2d_ctx *ctx = fh2ctx(file->private_data); + return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); +} + +static int vidioc_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *reqbufs) +{ + struct g2d_ctx *ctx = priv; + return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); +} + +static int vidioc_querybuf(struct file *file, void *priv, + struct v4l2_buffer *buf) +{ + struct g2d_ctx *ctx = priv; + return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); +} + +static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) +{ + struct g2d_ctx *ctx = priv; + return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) +{ + struct g2d_ctx *ctx = priv; + return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); +} + + +static int vidioc_streamon(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct g2d_ctx *ctx = priv; + return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); +} + +static int vidioc_streamoff(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct g2d_ctx *ctx = priv; + return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); +} + +static int vidioc_cropcap(struct file *file, void *priv, + struct v4l2_cropcap *cr) +{ + struct g2d_ctx *ctx = priv; + struct g2d_frame *f; + + f = get_frame(ctx, cr->type); + if (IS_ERR(f)) + return PTR_ERR(f); + + cr->bounds.left = 0; + cr->bounds.top = 0; + cr->bounds.width = f->width; + cr->bounds.height = f->height; + cr->defrect = cr->bounds; + return 0; +} + +static int vidioc_g_crop(struct file *file, void *prv, struct v4l2_crop *cr) +{ + struct g2d_ctx *ctx = prv; + struct g2d_frame *f; + + f = get_frame(ctx, cr->type); + if (IS_ERR(f)) + return PTR_ERR(f); + + cr->c.left = f->o_height; + cr->c.top = f->o_width; + cr->c.width = f->c_width; + cr->c.height = f->c_height; + return 0; +} + +static int vidioc_try_crop(struct file *file, void *prv, struct v4l2_crop *cr) +{ + struct g2d_ctx *ctx = prv; + struct g2d_dev *dev = ctx->dev; + struct g2d_frame *f; + + f = get_frame(ctx, cr->type); + if (IS_ERR(f)) + return PTR_ERR(f); + + if (cr->c.top < 0 || cr->c.left < 0) { + v4l2_err(&dev->v4l2_dev, + "doesn't support negative values for top & left\n"); + return -EINVAL; + } + + return 0; +} + +static int vidioc_s_crop(struct file *file, void *prv, struct v4l2_crop *cr) +{ + struct g2d_ctx *ctx = prv; + struct g2d_frame *f; + int ret; + + ret = vidioc_try_crop(file, prv, cr); + if (ret) + return ret; + f = get_frame(ctx, cr->type); + if (IS_ERR(f)) + return PTR_ERR(f); + + f->c_width = cr->c.width; + f->c_height = cr->c.height; + f->o_width = cr->c.left; + f->o_height = cr->c.top; + f->bottom = f->o_height + f->c_height; + f->right = f->o_width + f->c_width; + return 0; +} + +static void g2d_lock(void *prv) +{ + struct g2d_ctx *ctx = prv; + struct g2d_dev *dev = ctx->dev; + mutex_lock(&dev->mutex); +} + +static void g2d_unlock(void *prv) +{ + struct g2d_ctx *ctx = prv; + struct g2d_dev *dev = ctx->dev; + mutex_unlock(&dev->mutex); +} + +static void job_abort(void *prv) +{ + struct g2d_ctx *ctx = prv; + struct g2d_dev *dev = ctx->dev; + int ret; + + if (dev->curr == 0) /* No job currently running */ + return; + + ret = wait_event_timeout(dev->irq_queue, + dev->curr == 0, + msecs_to_jiffies(G2D_TIMEOUT)); +} + +static void device_run(void *prv) +{ + struct g2d_ctx *ctx = prv; + struct g2d_dev *dev = ctx->dev; + struct vb2_buffer *src, *dst; + u32 cmd = 0; + + dev->curr = ctx; + + src = v4l2_m2m_next_src_buf(ctx->m2m_ctx); + dst = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + + clk_enable(dev->gate); + g2d_reset(dev); + + g2d_set_src_size(dev, &ctx->in); + g2d_set_src_addr(dev, vb2_dma_contig_plane_dma_addr(src, 0)); + + g2d_set_dst_size(dev, &ctx->out); + g2d_set_dst_addr(dev, vb2_dma_contig_plane_dma_addr(dst, 0)); + + g2d_set_rop4(dev, ctx->rop); + if (ctx->in.c_width != ctx->out.c_width || + ctx->in.c_height != ctx->out.c_height) + cmd |= g2d_cmd_stretch(1); + g2d_set_cmd(dev, cmd); + g2d_start(dev); +} + +static irqreturn_t g2d_isr(int irq, void *prv) +{ + struct g2d_dev *dev = prv; + struct g2d_ctx *ctx = dev->curr; + struct vb2_buffer *src, *dst; + + g2d_clear_int(dev); + clk_disable(dev->gate); + + BUG_ON(ctx == 0); + + src = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + dst = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); + + BUG_ON(src == 0); + BUG_ON(dst == 0); + + v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE); + v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE); + v4l2_m2m_job_finish(dev->m2m_dev, ctx->m2m_ctx); + + dev->curr = 0; + wake_up(&dev->irq_queue); + return IRQ_HANDLED; +} + +static const struct v4l2_file_operations g2d_fops = { + .owner = THIS_MODULE, + .open = g2d_open, + .release = g2d_release, + .poll = g2d_poll, + .unlocked_ioctl = video_ioctl2, + .mmap = g2d_mmap, +}; + +static const struct v4l2_ioctl_ops g2d_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt, + + .vidioc_enum_fmt_vid_out = vidioc_enum_fmt, + .vidioc_g_fmt_vid_out = vidioc_g_fmt, + .vidioc_try_fmt_vid_out = vidioc_try_fmt, + .vidioc_s_fmt_vid_out = vidioc_s_fmt, + + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + + .vidioc_g_crop = vidioc_g_crop, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_cropcap = vidioc_cropcap, +}; + +static struct video_device g2d_videodev = { + .name = G2D_NAME, + .fops = &g2d_fops, + .ioctl_ops = &g2d_ioctl_ops, + .minor = -1, + .release = video_device_release, +}; + +static struct v4l2_m2m_ops g2d_m2m_ops = { + .device_run = device_run, + .job_abort = job_abort, + .lock = g2d_lock, + .unlock = g2d_unlock, +}; + +static int g2d_probe(struct platform_device *pdev) +{ + struct g2d_dev *dev; + struct video_device *vfd; + struct resource *res; + int ret = 0; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + spin_lock_init(&dev->irqlock); + mutex_init(&dev->mutex); + atomic_set(&dev->num_inst, 0); + init_waitqueue_head(&dev->irq_queue); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "failed to find registers\n"); + ret = -ENOENT; + goto free_dev; + } + + dev->res_regs = request_mem_region(res->start, resource_size(res), + dev_name(&pdev->dev)); + + if (!dev->res_regs) { + dev_err(&pdev->dev, "failed to obtain register region\n"); + ret = -ENOENT; + goto free_dev; + } + + dev->regs = ioremap(res->start, resource_size(res)); + if (!dev->regs) { + dev_err(&pdev->dev, "failed to map registers\n"); + ret = -ENOENT; + goto rel_res_regs; + } + + dev->clk = clk_get(&pdev->dev, "sclk_fimg2d"); + if (IS_ERR_OR_NULL(dev->clk)) { + dev_err(&pdev->dev, "failed to get g2d clock\n"); + ret = -ENXIO; + goto unmap_regs; + } + + dev->gate = clk_get(&pdev->dev, "fimg2d"); + if (IS_ERR_OR_NULL(dev->gate)) { + dev_err(&pdev->dev, "failed to get g2d clock gate\n"); + ret = -ENXIO; + goto put_clk; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(&pdev->dev, "failed to find IRQ\n"); + ret = -ENXIO; + goto put_clk_gate; + } + + dev->irq = res->start; + + ret = request_irq(dev->irq, g2d_isr, 0, pdev->name, dev); + if (ret) { + dev_err(&pdev->dev, "failed to install IRQ\n"); + goto put_clk_gate; + } + + dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); + if (IS_ERR(dev->alloc_ctx)) { + ret = PTR_ERR(dev->alloc_ctx); + goto rel_irq; + } + + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); + if (ret) + goto alloc_ctx_cleanup; + vfd = video_device_alloc(); + if (!vfd) { + v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n"); + ret = -ENOMEM; + goto unreg_v4l2_dev; + } + *vfd = g2d_videodev; + vfd->lock = &dev->mutex; + ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); + if (ret) { + v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); + goto rel_vdev; + } + video_set_drvdata(vfd, dev); + snprintf(vfd->name, sizeof(vfd->name), "%s", g2d_videodev.name); + dev->vfd = vfd; + v4l2_info(&dev->v4l2_dev, "device registered as /dev/video%d\n", + vfd->num); + platform_set_drvdata(pdev, dev); + dev->m2m_dev = v4l2_m2m_init(&g2d_m2m_ops); + if (IS_ERR(dev->m2m_dev)) { + v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n"); + ret = PTR_ERR(dev->m2m_dev); + goto unreg_video_dev; + } + + def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3; + + return 0; + +unreg_video_dev: + video_unregister_device(dev->vfd); +rel_vdev: + video_device_release(vfd); +unreg_v4l2_dev: + v4l2_device_unregister(&dev->v4l2_dev); +alloc_ctx_cleanup: + vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); +rel_irq: + free_irq(dev->irq, dev); +put_clk_gate: + clk_put(dev->gate); +put_clk: + clk_put(dev->clk); +unmap_regs: + iounmap(dev->regs); +rel_res_regs: + release_resource(dev->res_regs); +free_dev: + kfree(dev); + return ret; +} + +static int g2d_remove(struct platform_device *pdev) +{ + struct g2d_dev *dev = (struct g2d_dev *)platform_get_drvdata(pdev); + + v4l2_info(&dev->v4l2_dev, "Removing " G2D_NAME); + v4l2_m2m_release(dev->m2m_dev); + video_unregister_device(dev->vfd); + v4l2_device_unregister(&dev->v4l2_dev); + vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); + free_irq(dev->irq, dev); + clk_put(dev->gate); + clk_put(dev->clk); + iounmap(dev->regs); + release_resource(dev->res_regs); + kfree(dev); + return 0; +} + +static struct platform_driver g2d_pdrv = { + .probe = g2d_probe, + .remove = g2d_remove, + .driver = { + .name = G2D_NAME, + .owner = THIS_MODULE, + }, +}; + +static void __exit g2d_exit(void) +{ + platform_driver_unregister(&g2d_pdrv); +}; + +static int __init g2d_init(void) +{ + int ret = 0; + + ret = platform_driver_register(&g2d_pdrv); + return ret; +}; + +module_init(g2d_init); +module_exit(g2d_exit); + +MODULE_AUTHOR("Kamil Debski "); +MODULE_DESCRIPTION("S5P G2D 2d graphics accelerator driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/s5p-g2d/g2d.h b/drivers/media/video/s5p-g2d/g2d.h new file mode 100644 index 0000000..5eae901 --- /dev/null +++ b/drivers/media/video/s5p-g2d/g2d.h @@ -0,0 +1,83 @@ +/* + * Samsung S5P G2D - 2D Graphics Accelerator Driver + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * Kamil Debski, + * + * 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 + +#define G2D_NAME "s5p-g2d" + +struct g2d_dev { + struct v4l2_device v4l2_dev; + struct v4l2_m2m_dev *m2m_dev; + struct video_device *vfd; + struct mutex mutex; + spinlock_t irqlock; + atomic_t num_inst; + struct vb2_alloc_ctx *alloc_ctx; + struct resource *res_regs; + void __iomem *regs; + struct clk *clk; + struct clk *gate; + struct g2d_ctx *curr; + int irq; + wait_queue_head_t irq_queue; +}; + +struct g2d_frame { + /* Original dimensions */ + u32 width; + u32 height; + /* Crop size */ + u32 c_width; + u32 c_height; + /* Offset */ + u32 o_width; + u32 o_height; + /* Image format */ + struct g2d_fmt *fmt; + /* Variables that can calculated once and reused */ + u32 stride; + u32 bottom; + u32 right; + u32 size; +}; + +struct g2d_ctx { + struct v4l2_fh fh; + struct g2d_dev *dev; + struct v4l2_m2m_ctx *m2m_ctx; + struct g2d_frame in; + struct g2d_frame out; + struct v4l2_ctrl_handler ctrl_handler; + u32 rop; +}; + +struct g2d_fmt { + char *name; + u32 fourcc; + int depth; + u32 hw; +}; + + +void g2d_reset(struct g2d_dev *d); +void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f); +void g2d_set_src_addr(struct g2d_dev *d, dma_addr_t a); +void g2d_set_dst_size(struct g2d_dev *d, struct g2d_frame *f); +void g2d_set_dst_addr(struct g2d_dev *d, dma_addr_t a); +void g2d_start(struct g2d_dev *d); +void g2d_clear_int(struct g2d_dev *d); +void g2d_set_rop4(struct g2d_dev *d, u32 r); +u32 g2d_cmd_stretch(u32 e); +void g2d_set_cmd(struct g2d_dev *d, u32 c); + + -- cgit v0.10.2 From 2da12fcbea0a2faa94a5d4e58eb2f0f79f9739db Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 4 Nov 2011 13:23:21 -0300 Subject: [media] tvp5150: replace video standard "magic" numbers 64933337e3cb61ca555969a35ab68b477db34ee2 [media] tvp5150: Add video format registers configuration values Added constants for each video standard supported by TVP5150, so this patch get rid of the magic numbers. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index e927d25..2a10b03 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -702,21 +702,21 @@ static int tvp5150_set_std(struct v4l2_subdev *sd, v4l2_std_id std) /* First tests should be against specific std */ if (std == V4L2_STD_ALL) { - fmt = 0; /* Autodetect mode */ + fmt = VIDEO_STD_AUTO_SWITCH_BIT; /* Autodetect mode */ } else if (std & V4L2_STD_NTSC_443) { - fmt = 0xa; + fmt = VIDEO_STD_NTSC_4_43_BIT; } else if (std & V4L2_STD_PAL_M) { - fmt = 0x6; + fmt = VIDEO_STD_PAL_M_BIT; } else if (std & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) { - fmt = 0x8; + fmt = VIDEO_STD_PAL_COMBINATION_N_BIT; } else { /* Then, test against generic ones */ if (std & V4L2_STD_NTSC) - fmt = 0x2; + fmt = VIDEO_STD_NTSC_MJ_BIT; else if (std & V4L2_STD_PAL) - fmt = 0x4; + fmt = VIDEO_STD_PAL_BDGHIN_BIT; else if (std & V4L2_STD_SECAM) - fmt = 0xc; + fmt = VIDEO_STD_SECAM_BIT; } v4l2_dbg(1, debug, sd, "Set video std register to %d.\n", fmt); -- cgit v0.10.2 From 3822c7cef7b422833f1b58949a01bd87b822d280 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 6 Nov 2011 10:24:30 -0300 Subject: [media] it913x ver 1.09 support for USB 1 devices (IT9135) IT9135 devices do support USB 1. Support added with restricton on pid count to 5. IT9137 devices wil not connect in USB 1 mode. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c index a541904..9f58241 100644 --- a/drivers/media/dvb/dvb-usb/it913x.c +++ b/drivers/media/dvb/dvb-usb/it913x.c @@ -350,6 +350,19 @@ static int it913x_identify_state(struct usb_device *udev, /* checnk for dual mode */ it913x_config.dual_mode = it913x_read_reg(udev, 0x49c5); + if (udev->speed != USB_SPEED_HIGH) { + props->adapter[0].fe[0].pid_filter_count = 5; + info("USB 1 low speed mode - connect to USB 2 port"); + if (pid_filter > 0) + pid_filter = 0; + if (it913x_config.dual_mode) { + it913x_config.dual_mode = 0; + info("Dual mode not supported in USB 1"); + } + } else /* For replugging */ + if(props->adapter[0].fe[0].pid_filter_count == 5) + props->adapter[0].fe[0].pid_filter_count = 31; + /* TODO different remotes */ remote = it913x_read_reg(udev, 0x49ac); /* Remote */ if (remote == 0) @@ -499,6 +512,10 @@ static int it913x_frontend_attach(struct dvb_usb_adapter *adap) int ret = 0; u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5); u16 ep_size = adap->props.fe[0].stream.u.bulk.buffersize; + u8 pkt_size = 0x80; + + if (adap->dev->udev->speed != USB_SPEED_HIGH) + pkt_size = 0x10; it913x_config.adf = it913x_read_reg(udev, IO_MUX_POWER_CLK); @@ -514,13 +531,13 @@ static int it913x_frontend_attach(struct dvb_usb_adapter *adap) ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_LSB, ep_size & 0xff); ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_MSB, ep_size >> 8); - ret = it913x_wr_reg(udev, DEV_0, EP4_MAX_PKT, 0x80); + ret = it913x_wr_reg(udev, DEV_0, EP4_MAX_PKT, pkt_size); } else if (adap->id == 1 && adap->fe_adap[0].fe) { ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x6f); ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_LSB, ep_size & 0xff); ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_MSB, ep_size >> 8); - ret = it913x_wr_reg(udev, DEV_0, EP5_MAX_PKT, 0x80); + ret = it913x_wr_reg(udev, DEV_0, EP5_MAX_PKT, pkt_size); ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_EN, 0x1); ret = it913x_wr_reg(udev, DEV_1_DMOD, MP2IF_SERIAL, 0x1); ret = it913x_wr_reg(udev, DEV_1, TOP_HOSTB_SER_MODE, 0x1); @@ -676,5 +693,5 @@ module_exit(it913x_module_exit); MODULE_AUTHOR("Malcolm Priestley "); MODULE_DESCRIPTION("it913x USB 2 Driver"); -MODULE_VERSION("1.08"); +MODULE_VERSION("1.09"); MODULE_LICENSE("GPL"); -- cgit v0.10.2 From de2843b663fd621e9a6c75fed4da73e8c9a1b094 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Sun, 6 Nov 2011 10:15:47 -0300 Subject: [media] bt8xx: add support for Tongwei Video Technology TD-3116 The following patch adds support for the Tongwei Video Technology TD-3116 board. This is a Bt878 based capture card with 16 inputs meant for surveilance applications. It also offers a way to check which inputs have a video signal while capturing another input. In addition there are a number of alarm inputs and outputs available and there is microcontroller which is presumably intended for use as a system watchdog. None of these extra capabilities are supported by the patch. Signed-off-by: Peter De Schrijver Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 076b7f2..ff2933a 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -80,6 +80,8 @@ static void phytec_muxsel(struct bttv *btv, unsigned int input); static void gv800s_muxsel(struct bttv *btv, unsigned int input); static void gv800s_init(struct bttv *btv); +static void td3116_muxsel(struct bttv *btv, unsigned int input); + static int terratec_active_radio_upgrade(struct bttv *btv); static int tea5757_read(struct bttv *btv); static int tea5757_write(struct bttv *btv, int value); @@ -342,6 +344,7 @@ static struct CARD { { 0x15401835, BTTV_BOARD_PV183, "Provideo PV183-6" }, { 0x15401836, BTTV_BOARD_PV183, "Provideo PV183-7" }, { 0x15401837, BTTV_BOARD_PV183, "Provideo PV183-8" }, + { 0x3116f200, BTTV_BOARD_TVT_TD3116, "Tongwei Video Technology TD-3116" }, { 0, -1, NULL } }; @@ -2880,6 +2883,16 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, }, + [BTTV_BOARD_TVT_TD3116] = { + .name = "Tongwei Video Technology TD-3116", + .video_inputs = 16, + .gpiomask = 0xc00ff, + .muxsel = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), + .muxsel_hook = td3116_muxsel, + .svhs = NO_SVHS, + .pll = PLL_28, + .tuner_type = TUNER_ABSENT, + }, }; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); @@ -3229,6 +3242,42 @@ static void geovision_muxsel(struct bttv *btv, unsigned int input) gpio_bits(0xf, inmux); } +/* + * The TD3116 has 2 74HC4051 muxes wired to the MUX0 input of a bt878. + * The first 74HC4051 has the lower 8 inputs, the second one the higher 8. + * The muxes are controlled via a 74HC373 latch which is connected to + * GPIOs 0-7. GPIO 18 is connected to the LE signal of the latch. + * Q0 of the latch is connected to the Enable (~E) input of the first + * 74HC4051. Q1 - Q3 are connected to S0 - S2 of the same 74HC4051. + * Q4 - Q7 are connected to the second 74HC4051 in the same way. + */ + +static void td3116_latch_value(struct bttv *btv, u32 value) +{ + gpio_bits((1<<18) | 0xff, value); + gpio_bits((1<<18) | 0xff, (1<<18) | value); + udelay(1); + gpio_bits((1<<18) | 0xff, value); +} + +static void td3116_muxsel(struct bttv *btv, unsigned int input) +{ + u32 value; + u32 highbit; + + highbit = (input & 0x8) >> 3 ; + + /* Disable outputs and set value in the mux */ + value = 0x11; /* Disable outputs */ + value |= ((input & 0x7) << 1) << (4 * highbit); + td3116_latch_value(btv, value); + + /* Enable the correct output */ + value &= ~0x11; + value |= ((highbit ^ 0x1) << 4) | highbit; + td3116_latch_value(btv, value); +} + /* ----------------------------------------------------------------------- */ static void bttv_reset_audio(struct bttv *btv) diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index 4db8b7d..c517161 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -183,6 +183,7 @@ #define BTTV_BOARD_GEOVISION_GV800S 0x9d #define BTTV_BOARD_GEOVISION_GV800S_SL 0x9e #define BTTV_BOARD_PV183 0x9f +#define BTTV_BOARD_TVT_TD3116 0xa0 /* more card-specific defines */ -- cgit v0.10.2 From c540d9f13d1f0f6913434b0b8241bb6270818769 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Sun, 6 Nov 2011 10:47:58 -0300 Subject: [media] bt8xx: add support for PCI device ID 0x36c add support for conexant PCI device 0x36c. Seems to be fully compatible with the currently supported chips, yet the chip has different PCI ID. Signed-off-by: Peter De Schrijver Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/bt8xx/bt848.h b/drivers/media/video/bt8xx/bt848.h index 0bcd953..c37e6ac 100644 --- a/drivers/media/video/bt8xx/bt848.h +++ b/drivers/media/video/bt8xx/bt848.h @@ -30,6 +30,10 @@ #ifndef PCI_DEVICE_ID_BT849 #define PCI_DEVICE_ID_BT849 0x351 #endif +#ifndef PCI_DEVICE_ID_FUSION879 +#define PCI_DEVICE_ID_FUSION879 0x36c +#endif + #ifndef PCI_DEVICE_ID_BT878 #define PCI_DEVICE_ID_BT878 0x36e #endif @@ -37,7 +41,6 @@ #define PCI_DEVICE_ID_BT879 0x36f #endif - /* Brooktree 848 registers */ #define BT848_DSTATUS 0x000 diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 3dd0660..76c301f 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -4572,6 +4572,7 @@ static struct pci_device_id bttv_pci_tbl[] = { {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0}, {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0}, {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0}, + {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_FUSION879), 0}, {0,} }; -- cgit v0.10.2 From 3339a5b165c2769a84346cac342ade67d7b7a510 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 6 Nov 2011 11:19:14 -0300 Subject: [media] it913x-fe ver 1.10 correct SNR reading from frontend Correction of reading from frontend and represents a SNR nonlinear scale of minimum signal to full signal. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/it913x-fe.c b/drivers/media/dvb/frontends/it913x-fe.c index 6d12dcc..07c1b46 100644 --- a/drivers/media/dvb/frontends/it913x-fe.c +++ b/drivers/media/dvb/frontends/it913x-fe.c @@ -53,6 +53,8 @@ struct it913x_fe_state { struct ite_config *config; u8 i2c_addr; u32 frequency; + fe_modulation_t constellation; + fe_transmit_mode_t transmission_mode; u32 crystalFrequency; u32 adcFrequency; u8 tuner_type; @@ -496,14 +498,50 @@ static int it913x_fe_read_signal_strength(struct dvb_frontend *fe, return 0; } -static int it913x_fe_read_snr(struct dvb_frontend *fe, u16* snr) +static int it913x_fe_read_snr(struct dvb_frontend *fe, u16 *snr) { struct it913x_fe_state *state = fe->demodulator_priv; - int ret = it913x_read_reg_u8(state, SIGNAL_QUALITY); - ret = (ret * 0xff) / 0x64; - ret |= (ret << 0x8); - *snr = ~ret; - return 0; + int ret; + u8 reg[3]; + u32 snr_val, snr_min, snr_max; + u32 temp; + + ret = it913x_read_reg(state, 0x2c, reg, sizeof(reg)); + + snr_val = (u32)(reg[2] << 16) | (reg[1] < 8) | reg[0]; + + ret |= it913x_read_reg(state, 0xf78b, reg, 1); + if (reg[0]) + snr_val /= reg[0]; + + if (state->transmission_mode == TRANSMISSION_MODE_2K) + snr_val *= 4; + else if (state->transmission_mode == TRANSMISSION_MODE_4K) + snr_val *= 2; + + if (state->constellation == QPSK) { + snr_min = 0xb4711; + snr_max = 0x191451; + } else if (state->constellation == QAM_16) { + snr_min = 0x4f0d5; + snr_max = 0xc7925; + } else if (state->constellation == QAM_64) { + snr_min = 0x256d0; + snr_max = 0x626be; + } else + return -EINVAL; + + if (snr_val < snr_min) + *snr = 0; + else if (snr_val < snr_max) { + temp = (snr_val - snr_min) >> 5; + temp *= 0xffff; + temp /= (snr_max - snr_min) >> 5; + *snr = (u16)temp; + } else + *snr = 0xffff; + + return (ret < 0) ? -ENODEV : 0; } static int it913x_fe_read_ber(struct dvb_frontend *fe, u32 *ber) @@ -530,9 +568,13 @@ static int it913x_fe_get_frontend(struct dvb_frontend *fe, if (reg[3] < 3) p->u.ofdm.constellation = fe_con[reg[3]]; + state->constellation = p->u.ofdm.constellation; + if (reg[0] < 3) p->u.ofdm.transmission_mode = fe_mode[reg[0]]; + state->transmission_mode = p->u.ofdm.transmission_mode; + if (reg[1] < 4) p->u.ofdm.guard_interval = fe_gi[reg[1]]; @@ -888,5 +930,5 @@ static struct dvb_frontend_ops it913x_fe_ofdm_ops = { MODULE_DESCRIPTION("it913x Frontend and it9137 tuner"); MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); -MODULE_VERSION("1.09"); +MODULE_VERSION("1.10"); MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 7f033e3354b40fdb5c4c8a15cce733cecd0f963a Mon Sep 17 00:00:00 2001 From: Piotr Chmura Date: Sun, 6 Nov 2011 16:31:38 -0300 Subject: [media] staging: as102: Remove comment tags for editors configuration Cc: Devin Heitmueller Signed-off-by: Piotr Chmura Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/as102/as102_drv.c b/drivers/staging/media/as102/as102_drv.c index d335c7d..771d550 100644 --- a/drivers/staging/media/as102/as102_drv.c +++ b/drivers/staging/media/as102/as102_drv.c @@ -347,5 +347,3 @@ module_exit(as102_driver_exit); MODULE_DESCRIPTION(DRIVER_FULL_NAME); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Pierrick Hascoet "); - -/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */ diff --git a/drivers/staging/media/as102/as102_drv.h b/drivers/staging/media/as102/as102_drv.h index bcda635..7f56f64 100644 --- a/drivers/staging/media/as102/as102_drv.h +++ b/drivers/staging/media/as102/as102_drv.h @@ -137,5 +137,3 @@ void as102_dvb_unregister(struct as102_dev_t *dev); int as102_dvb_register_fe(struct as102_dev_t *dev, struct dvb_frontend *fe); int as102_dvb_unregister_fe(struct dvb_frontend *dev); - -/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */ diff --git a/drivers/staging/media/as102/as102_fe.c b/drivers/staging/media/as102/as102_fe.c index 3550f90..7d7dd55 100644 --- a/drivers/staging/media/as102/as102_fe.c +++ b/drivers/staging/media/as102/as102_fe.c @@ -599,5 +599,3 @@ static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args, as102_fe_get_code_rate(params->u.ofdm.code_rate_HP); } } - -/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */ diff --git a/drivers/staging/media/as102/as102_fw.c b/drivers/staging/media/as102/as102_fw.c index c019df9..4fb2987 100644 --- a/drivers/staging/media/as102/as102_fw.c +++ b/drivers/staging/media/as102/as102_fw.c @@ -247,5 +247,3 @@ error: return errno; } #endif - -/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */ diff --git a/drivers/staging/media/as102/as102_fw.h b/drivers/staging/media/as102/as102_fw.h index 27e5347..951a1fa 100644 --- a/drivers/staging/media/as102/as102_fw.h +++ b/drivers/staging/media/as102/as102_fw.h @@ -38,5 +38,3 @@ struct as10x_fw_pkt_t { #ifdef __KERNEL__ int as102_fw_upload(struct as102_bus_adapter_t *bus_adap); #endif - -/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */ diff --git a/drivers/staging/media/as102/as102_usb_drv.c b/drivers/staging/media/as102/as102_usb_drv.c index 264be2d..0a8f12b 100644 --- a/drivers/staging/media/as102/as102_usb_drv.c +++ b/drivers/staging/media/as102/as102_usb_drv.c @@ -474,5 +474,3 @@ static int as102_release(struct inode *inode, struct file *file) } MODULE_DEVICE_TABLE(usb, as102_usb_id_table); - -/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */ diff --git a/drivers/staging/media/as102/as102_usb_drv.h b/drivers/staging/media/as102/as102_usb_drv.h index fb1fc41..35925b7 100644 --- a/drivers/staging/media/as102/as102_usb_drv.h +++ b/drivers/staging/media/as102/as102_usb_drv.h @@ -56,4 +56,3 @@ struct as10x_usb_token_cmd_t { struct as10x_cmd_t r; }; #endif -/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */ diff --git a/drivers/staging/media/as102/as10x_cmd.h b/drivers/staging/media/as102/as10x_cmd.h index 01a7163..6f837b1 100644 --- a/drivers/staging/media/as102/as10x_cmd.h +++ b/drivers/staging/media/as102/as10x_cmd.h @@ -537,4 +537,3 @@ int as10x_context_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id); } #endif #endif -/* EOF - vim: set textwidth=80 ts=3 sw=3 sts=3 et: */ -- cgit v0.10.2 From c06271e052cd00217a26d5aadfa7cf937eaa97a6 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 6 Nov 2011 16:31:39 -0300 Subject: [media] staging: as102: Remove unnecessary typedefs According to the kernel coding rules typedefs should be avoided, so replace theit occurances with explicit enum/union types. Cc: Devin Heitmueller Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/as102/as10x_cmd.h b/drivers/staging/media/as102/as10x_cmd.h index 6f837b1..8f13bea 100644 --- a/drivers/staging/media/as102/as10x_cmd.h +++ b/drivers/staging/media/as102/as10x_cmd.h @@ -52,7 +52,7 @@ /*********************************/ /* TYPE DEFINITION */ /*********************************/ -typedef enum { +enum control_proc { CONTROL_PROC_TURNON = 0x0001, CONTROL_PROC_TURNON_RSP = 0x0100, CONTROL_PROC_SET_REGISTER = 0x0002, @@ -92,11 +92,11 @@ typedef enum { CONTROL_PROC_DUMPLOG_MEMORY_RSP = 0xFE00, CONTROL_PROC_TURNOFF = 0x00FF, CONTROL_PROC_TURNOFF_RSP = 0xFF00 -} control_proc; +}; #pragma pack(1) -typedef union { +union as10x_turn_on { /* request */ struct { /* request identifier */ @@ -109,9 +109,9 @@ typedef union { /* error */ uint8_t error; } rsp; -} TURN_ON; +}; -typedef union { +union as10x_turn_off { /* request */ struct { /* request identifier */ @@ -124,9 +124,9 @@ typedef union { /* error */ uint8_t err; } rsp; -} TURN_OFF; +}; -typedef union { +union as10x_set_tune { /* request */ struct { /* request identifier */ @@ -141,9 +141,9 @@ typedef union { /* response error */ uint8_t error; } rsp; -} SET_TUNE; +}; -typedef union { +union as10x_get_tune_status { /* request */ struct { /* request identifier */ @@ -158,9 +158,9 @@ typedef union { /* tune status */ struct as10x_tune_status sts; } rsp; -} GET_TUNE_STATUS; +}; -typedef union { +union as10x_get_tps { /* request */ struct { /* request identifier */ @@ -175,9 +175,9 @@ typedef union { /* tps details */ struct as10x_tps tps; } rsp; -} GET_TPS; +}; -typedef union { +union as10x_common { /* request */ struct { /* request identifier */ @@ -190,9 +190,9 @@ typedef union { /* response error */ uint8_t error; } rsp; -} COMMON; +}; -typedef union { +union as10x_add_pid_filter { /* request */ struct { /* request identifier */ @@ -213,9 +213,9 @@ typedef union { /* Filter id */ uint8_t filter_id; } rsp; -} ADD_PID_FILTER; +}; -typedef union { +union as10x_del_pid_filter { /* request */ struct { /* request identifier */ @@ -230,9 +230,9 @@ typedef union { /* response error */ uint8_t error; } rsp; -} DEL_PID_FILTER; +}; -typedef union { +union as10x_start_streaming { /* request */ struct { /* request identifier */ @@ -245,9 +245,9 @@ typedef union { /* error */ uint8_t error; } rsp; -} START_STREAMING; +}; -typedef union { +union as10x_stop_streaming { /* request */ struct { /* request identifier */ @@ -260,9 +260,9 @@ typedef union { /* error */ uint8_t error; } rsp; -} STOP_STREAMING; +}; -typedef union { +union as10x_get_demod_stats { /* request */ struct { /* request identifier */ @@ -277,9 +277,9 @@ typedef union { /* demod stats */ struct as10x_demod_stats stats; } rsp; -} GET_DEMOD_STATS; +}; -typedef union { +union as10x_get_impulse_resp { /* request */ struct { /* request identifier */ @@ -294,9 +294,9 @@ typedef union { /* impulse response ready */ uint8_t is_ready; } rsp; -} GET_IMPULSE_RESP; +}; -typedef union { +union as10x_fw_context { /* request */ struct { /* request identifier */ @@ -319,9 +319,9 @@ typedef union { /* error */ uint8_t error; } rsp; -} FW_CONTEXT; +}; -typedef union { +union as10x_set_register { /* request */ struct { /* response identifier */ @@ -338,9 +338,9 @@ typedef union { /* error */ uint8_t error; } rsp; -} SET_REGISTER; +}; -typedef union { +union as10x_get_register { /* request */ struct { /* response identifier */ @@ -357,9 +357,9 @@ typedef union { /* register content */ struct as10x_register_value reg_val; } rsp; -} GET_REGISTER; +}; -typedef union { +union as10x_cfg_change_mode { /* request */ struct { /* request identifier */ @@ -374,7 +374,7 @@ typedef union { /* error */ uint8_t error; } rsp; -} CFG_CHANGE_MODE; +}; struct as10x_cmd_header_t { uint16_t req_id; @@ -384,7 +384,8 @@ struct as10x_cmd_header_t { }; #define DUMP_BLOCK_SIZE 16 -typedef union { + +union as10x_dump_memory { /* request */ struct { /* request identifier */ @@ -411,9 +412,9 @@ typedef union { uint32_t data32[DUMP_BLOCK_SIZE / sizeof(uint32_t)]; } u; } rsp; -} DUMP_MEMORY; +}; -typedef union { +union as10x_dumplog_memory { struct { /* request identifier */ uint16_t proc_id; @@ -430,9 +431,9 @@ typedef union { /* dump data */ uint8_t data[DUMP_BLOCK_SIZE]; } rsp; -} DUMPLOG_MEMORY; +}; -typedef union { +union as10x_raw_data { /* request */ struct { uint16_t proc_id; @@ -445,33 +446,31 @@ typedef union { uint8_t data[64 - sizeof(struct as10x_cmd_header_t) /* header */ - 2 /* proc_id */ - 1 /* rc */]; } rsp; -} RAW_DATA; +}; struct as10x_cmd_t { - /* header */ - struct as10x_cmd_header_t header; - /* body */ - union { - TURN_ON turn_on; - TURN_OFF turn_off; - SET_TUNE set_tune; - GET_TUNE_STATUS get_tune_status; - GET_TPS get_tps; - COMMON common; - ADD_PID_FILTER add_pid_filter; - DEL_PID_FILTER del_pid_filter; - START_STREAMING start_streaming; - STOP_STREAMING stop_streaming; - GET_DEMOD_STATS get_demod_stats; - GET_IMPULSE_RESP get_impulse_rsp; - FW_CONTEXT context; - SET_REGISTER set_register; - GET_REGISTER get_register; - CFG_CHANGE_MODE cfg_change_mode; - DUMP_MEMORY dump_memory; - DUMPLOG_MEMORY dumplog_memory; - RAW_DATA raw_data; - } body; + struct as10x_cmd_header_t header; + union { + union as10x_turn_on turn_on; + union as10x_turn_off turn_off; + union as10x_set_tune set_tune; + union as10x_get_tune_status get_tune_status; + union as10x_get_tps get_tps; + union as10x_common common; + union as10x_add_pid_filter add_pid_filter; + union as10x_del_pid_filter del_pid_filter; + union as10x_start_streaming start_streaming; + union as10x_stop_streaming stop_streaming; + union as10x_get_demod_stats get_demod_stats; + union as10x_get_impulse_resp get_impulse_rsp; + union as10x_fw_context context; + union as10x_set_register set_register; + union as10x_get_register get_register; + union as10x_cfg_change_mode cfg_change_mode; + union as10x_dump_memory dump_memory; + union as10x_dumplog_memory dumplog_memory; + union as10x_raw_data raw_data; + } body; }; struct as10x_token_cmd_t { -- cgit v0.10.2 From 82aae98df488c15c212059b23460fe9a9dd97412 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 6 Nov 2011 16:31:40 -0300 Subject: [media] staging: as102: Remove leftovers of the SPI bus driver SPI bus driver support is not included in this module, the SPI driver files are missing. But some bits are still present so clean up the unused code. The SPI driver support can be properly added later if needed. Then CONFIG_AS102_SPI and CONFIG_AS102_USB is now not needed and the pre-processor statements using these config options can now be removed from *.c files. Cc: Devin Heitmueller Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/as102/Makefile b/drivers/staging/media/as102/Makefile index e7dbb6f..1bca43e8 100644 --- a/drivers/staging/media/as102/Makefile +++ b/drivers/staging/media/as102/Makefile @@ -3,4 +3,4 @@ dvb-as102-objs := as102_drv.o as102_fw.o as10x_cmd.o as10x_cmd_stream.o \ obj-$(CONFIG_DVB_AS102) += dvb-as102.o -EXTRA_CFLAGS += -DCONFIG_AS102_USB -Idrivers/media/dvb/dvb-core +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core diff --git a/drivers/staging/media/as102/as102_drv.c b/drivers/staging/media/as102/as102_drv.c index 771d550..0bcc55c 100644 --- a/drivers/staging/media/as102/as102_drv.c +++ b/drivers/staging/media/as102/as102_drv.c @@ -56,9 +56,7 @@ int elna_enable = 1; module_param_named(elna_enable, elna_enable, int, 0644); MODULE_PARM_DESC(elna_enable, "Activate eLNA (default: on)"); -#ifdef DVB_DEFINE_MOD_OPT_ADAPTER_NR DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -#endif static void as102_stop_stream(struct as102_dev_t *dev) { @@ -203,16 +201,8 @@ int as102_dvb_register(struct as102_dev_t *as102_dev) ret = dvb_register_adapter(&as102_dev->dvb_adap, as102_dev->name, THIS_MODULE, -#if defined(CONFIG_AS102_USB) - &as102_dev->bus_adap.usb_dev->dev -#elif defined(CONFIG_AS102_SPI) - &as102_dev->bus_adap.spi_dev->dev -#else -#error >>> dvb_register_adapter <<< -#endif -#ifdef DVB_DEFINE_MOD_OPT_ADAPTER_NR - , adapter_nr -#endif + &as102_dev->bus_adap.usb_dev->dev, + adapter_nr ); if (ret < 0) { err("%s: dvb_register_adapter() failed (errno = %d)", @@ -294,23 +284,13 @@ void as102_dvb_unregister(struct as102_dev_t *as102_dev) static int __init as102_driver_init(void) { - int ret = 0; - - ENTER(); + int ret; /* register this driver with the low level subsystem */ -#if defined(CONFIG_AS102_USB) ret = usb_register(&as102_usb_driver); if (ret) err("usb_register failed (ret = %d)", ret); -#endif -#if defined(CONFIG_AS102_SPI) - ret = spi_register_driver(&as102_spi_driver); - if (ret) - printk(KERN_ERR "spi_register failed (ret = %d)", ret); -#endif - LEAVE(); return ret; } @@ -327,15 +307,8 @@ module_init(as102_driver_init); */ static void __exit as102_driver_exit(void) { - ENTER(); /* deregister this driver with the low level bus subsystem */ -#if defined(CONFIG_AS102_USB) usb_deregister(&as102_usb_driver); -#endif -#if defined(CONFIG_AS102_SPI) - spi_unregister_driver(&as102_spi_driver); -#endif - LEAVE(); } /* diff --git a/drivers/staging/media/as102/as102_drv.h b/drivers/staging/media/as102/as102_drv.h index 7f56f64..af2bf1e 100644 --- a/drivers/staging/media/as102/as102_drv.h +++ b/drivers/staging/media/as102/as102_drv.h @@ -17,27 +17,18 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#if defined(CONFIG_AS102_USB) #include -extern struct usb_driver as102_usb_driver; -#endif - -#if defined(CONFIG_AS102_SPI) -#include -#include -#include - -extern struct spi_driver as102_spi_driver; -#endif - -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dmxdev.h" +#include +#include +#include +#include "as10x_cmd.h" +#include "as102_usb_drv.h" #define DRIVER_FULL_NAME "Abilis Systems as10x usb driver" #define DRIVER_NAME "as10x_usb" extern int debug; +extern struct usb_driver as102_usb_driver; #define dprintk(debug, args...) \ do { if (debug) { \ @@ -58,39 +49,14 @@ extern int debug; #define AS102_USB_BUF_SIZE 512 #define MAX_STREAM_URB 32 -#include "as10x_cmd.h" - -#if defined(CONFIG_AS102_USB) -#include "as102_usb_drv.h" -#endif - -#if defined(CONFIG_AS102_SPI) -#include "as10x_spi_drv.h" -#endif - - struct as102_bus_adapter_t { -#if defined(CONFIG_AS102_USB) struct usb_device *usb_dev; -#elif defined(CONFIG_AS102_SPI) - struct spi_device *spi_dev; - struct cdev cdev; /* spidev raw device */ - - struct timer_list timer; - struct completion xfer_done; -#endif /* bus token lock */ struct mutex lock; /* low level interface for bus adapter */ union as10x_bus_token_t { -#if defined(CONFIG_AS102_USB) /* usb token */ struct as10x_usb_token_cmd_t usb; -#endif -#if defined(CONFIG_AS102_SPI) - /* spi token */ - struct as10x_spi_token_cmd_t spi; -#endif } token; /* token cmd xfer id */ diff --git a/drivers/staging/media/as102/as102_fw.c b/drivers/staging/media/as102/as102_fw.c index 4fb2987..3aa4aad 100644 --- a/drivers/staging/media/as102/as102_fw.c +++ b/drivers/staging/media/as102/as102_fw.c @@ -169,13 +169,8 @@ int as102_fw_upload(struct as102_bus_adapter_t *bus_adap) const struct firmware *firmware; unsigned char *cmd_buf = NULL; char *fw1, *fw2; - -#if defined(CONFIG_AS102_USB) struct usb_device *dev = bus_adap->usb_dev; -#endif -#if defined(CONFIG_AS102_SPI) - struct spi_device *dev = bus_adap->spi_dev; -#endif + ENTER(); /* select fw file to upload */ -- cgit v0.10.2 From 57753767dda8a0f415555da3d94947d2687bc421 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 6 Nov 2011 16:31:41 -0300 Subject: [media] staging: as102: Make the driver select CONFIG_FW_LOADER It doesn't seem to be of much advantage to compile in FW_LOADER support conditionally, then make the driver always select FW_LOADER and remove #idefs from the code. Cc: Devin Heitmueller Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/as102/Kconfig b/drivers/staging/media/as102/Kconfig index 5865029..28aba00 100644 --- a/drivers/staging/media/as102/Kconfig +++ b/drivers/staging/media/as102/Kconfig @@ -1,6 +1,7 @@ config DVB_AS102 tristate "Abilis AS102 DVB receiver" depends on DVB_CORE && USB && I2C && INPUT + select FW_LOADER help Choose Y or M here if you have a device containing an AS102 diff --git a/drivers/staging/media/as102/as102_drv.c b/drivers/staging/media/as102/as102_drv.c index 0bcc55c..85f58b9 100644 --- a/drivers/staging/media/as102/as102_drv.c +++ b/drivers/staging/media/as102/as102_drv.c @@ -249,7 +249,6 @@ int as102_dvb_register(struct as102_dev_t *as102_dev) /* init start / stop stream mutex */ mutex_init(&as102_dev->sem); -#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) /* * try to load as102 firmware. If firmware upload failed, we'll be * able to upload it later. @@ -257,8 +256,6 @@ int as102_dvb_register(struct as102_dev_t *as102_dev) if (fw_upload) try_then_request_module(as102_fw_upload(&as102_dev->bus_adap), "firmware_class"); -#endif - failed: LEAVE(); /* FIXME: free dvb_XXX */ diff --git a/drivers/staging/media/as102/as102_fw.c b/drivers/staging/media/as102/as102_fw.c index 3aa4aad..ab7dcdb 100644 --- a/drivers/staging/media/as102/as102_fw.c +++ b/drivers/staging/media/as102/as102_fw.c @@ -26,7 +26,6 @@ #include "as102_drv.h" #include "as102_fw.h" -#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) char as102_st_fw1[] = "as102_data1_st.hex"; char as102_st_fw2[] = "as102_data2_st.hex"; char as102_dt_fw1[] = "as102_data1_dt.hex"; @@ -182,7 +181,6 @@ int as102_fw_upload(struct as102_bus_adapter_t *bus_adap) fw2 = as102_st_fw2; } -#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) /* allocate buffer to store firmware upload command and data */ cmd_buf = kzalloc(MAX_FW_PKT_SIZE, GFP_KERNEL); if (cmd_buf == NULL) { @@ -237,8 +235,7 @@ error: /* release firmware if needed */ if (firmware != NULL) release_firmware(firmware); -#endif + LEAVE(); return errno; } -#endif -- cgit v0.10.2 From fa1a13f621c6de8c3a6e6fa8b3dd66094f0f660a Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 6 Nov 2011 16:31:42 -0300 Subject: [media] staging: as102: Replace pragma(pack) with attribute __packed Cc: Devin Heitmueller Signed-off-by: Sylwester Nawrocki Signed-off-by: Piotr Chmura Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/as102/as102_fw.h b/drivers/staging/media/as102/as102_fw.h index 951a1fa..a1fdb92 100644 --- a/drivers/staging/media/as102/as102_fw.h +++ b/drivers/staging/media/as102/as102_fw.h @@ -20,11 +20,10 @@ extern int dual_tuner; -#pragma pack(1) struct as10x_raw_fw_pkt { unsigned char address[4]; unsigned char data[MAX_FW_PKT_SIZE - 6]; -}; +} __packed; struct as10x_fw_pkt_t { union { @@ -32,8 +31,7 @@ struct as10x_fw_pkt_t { unsigned char length[2]; } u; struct as10x_raw_fw_pkt raw; -}; -#pragma pack() +} __packed; #ifdef __KERNEL__ int as102_fw_upload(struct as102_bus_adapter_t *bus_adap); diff --git a/drivers/staging/media/as102/as10x_cmd.h b/drivers/staging/media/as102/as10x_cmd.h index 8f13bea..05f7150 100644 --- a/drivers/staging/media/as102/as10x_cmd.h +++ b/drivers/staging/media/as102/as10x_cmd.h @@ -94,8 +94,6 @@ enum control_proc { CONTROL_PROC_TURNOFF_RSP = 0xFF00 }; - -#pragma pack(1) union as10x_turn_on { /* request */ struct { @@ -109,7 +107,7 @@ union as10x_turn_on { /* error */ uint8_t error; } rsp; -}; +} __packed; union as10x_turn_off { /* request */ @@ -124,7 +122,7 @@ union as10x_turn_off { /* error */ uint8_t err; } rsp; -}; +} __packed; union as10x_set_tune { /* request */ @@ -141,7 +139,7 @@ union as10x_set_tune { /* response error */ uint8_t error; } rsp; -}; +} __packed; union as10x_get_tune_status { /* request */ @@ -158,7 +156,7 @@ union as10x_get_tune_status { /* tune status */ struct as10x_tune_status sts; } rsp; -}; +} __packed; union as10x_get_tps { /* request */ @@ -175,7 +173,7 @@ union as10x_get_tps { /* tps details */ struct as10x_tps tps; } rsp; -}; +} __packed; union as10x_common { /* request */ @@ -190,7 +188,7 @@ union as10x_common { /* response error */ uint8_t error; } rsp; -}; +} __packed; union as10x_add_pid_filter { /* request */ @@ -213,7 +211,7 @@ union as10x_add_pid_filter { /* Filter id */ uint8_t filter_id; } rsp; -}; +} __packed; union as10x_del_pid_filter { /* request */ @@ -230,7 +228,7 @@ union as10x_del_pid_filter { /* response error */ uint8_t error; } rsp; -}; +} __packed; union as10x_start_streaming { /* request */ @@ -245,7 +243,7 @@ union as10x_start_streaming { /* error */ uint8_t error; } rsp; -}; +} __packed; union as10x_stop_streaming { /* request */ @@ -260,7 +258,7 @@ union as10x_stop_streaming { /* error */ uint8_t error; } rsp; -}; +} __packed; union as10x_get_demod_stats { /* request */ @@ -277,7 +275,7 @@ union as10x_get_demod_stats { /* demod stats */ struct as10x_demod_stats stats; } rsp; -}; +} __packed; union as10x_get_impulse_resp { /* request */ @@ -294,7 +292,7 @@ union as10x_get_impulse_resp { /* impulse response ready */ uint8_t is_ready; } rsp; -}; +} __packed; union as10x_fw_context { /* request */ @@ -319,7 +317,7 @@ union as10x_fw_context { /* error */ uint8_t error; } rsp; -}; +} __packed; union as10x_set_register { /* request */ @@ -338,7 +336,7 @@ union as10x_set_register { /* error */ uint8_t error; } rsp; -}; +} __packed; union as10x_get_register { /* request */ @@ -357,7 +355,7 @@ union as10x_get_register { /* register content */ struct as10x_register_value reg_val; } rsp; -}; +} __packed; union as10x_cfg_change_mode { /* request */ @@ -374,14 +372,14 @@ union as10x_cfg_change_mode { /* error */ uint8_t error; } rsp; -}; +} __packed; struct as10x_cmd_header_t { uint16_t req_id; uint16_t prog; uint16_t version; uint16_t data_len; -}; +} __packed; #define DUMP_BLOCK_SIZE 16 @@ -412,7 +410,7 @@ union as10x_dump_memory { uint32_t data32[DUMP_BLOCK_SIZE / sizeof(uint32_t)]; } u; } rsp; -}; +} __packed; union as10x_dumplog_memory { struct { @@ -431,7 +429,7 @@ union as10x_dumplog_memory { /* dump data */ uint8_t data[DUMP_BLOCK_SIZE]; } rsp; -}; +} __packed; union as10x_raw_data { /* request */ @@ -446,7 +444,7 @@ union as10x_raw_data { uint8_t data[64 - sizeof(struct as10x_cmd_header_t) /* header */ - 2 /* proc_id */ - 1 /* rc */]; } rsp; -}; +} __packed; struct as10x_cmd_t { struct as10x_cmd_header_t header; @@ -471,15 +469,14 @@ struct as10x_cmd_t { union as10x_dumplog_memory dumplog_memory; union as10x_raw_data raw_data; } body; -}; +} __packed; struct as10x_token_cmd_t { /* token cmd */ struct as10x_cmd_t c; /* token response */ struct as10x_cmd_t r; -}; -#pragma pack() +} __packed; /**************************/ diff --git a/drivers/staging/media/as102/as10x_types.h b/drivers/staging/media/as102/as10x_types.h index 3dedb3c..0b27f3a 100644 --- a/drivers/staging/media/as102/as10x_types.h +++ b/drivers/staging/media/as102/as10x_types.h @@ -111,7 +111,6 @@ #define CFG_MODE_OFF 1 #define CFG_MODE_AUTO 2 -#pragma pack(1) struct as10x_tps { uint8_t constellation; uint8_t hierarchy; @@ -123,7 +122,7 @@ struct as10x_tps { uint8_t DVBH_mask_HP; uint8_t DVBH_mask_LP; uint16_t cell_ID; -}; +} __packed; struct as10x_tune_args { /* frequency */ @@ -144,7 +143,7 @@ struct as10x_tune_args { uint8_t guard_interval; /* transmission mode */ uint8_t transmission_mode; -}; +} __packed; struct as10x_tune_status { /* tune status */ @@ -155,7 +154,7 @@ struct as10x_tune_status { uint16_t PER; /* bit error rate 10^-4 */ uint16_t BER; -}; +} __packed; struct as10x_demod_stats { /* frame counter */ @@ -168,13 +167,13 @@ struct as10x_demod_stats { uint16_t mer; /* statistics calculation state indicator (started or not) */ uint8_t has_started; -}; +} __packed; struct as10x_ts_filter { uint16_t pid; /** valid PID value 0x00 : 0x2000 */ uint8_t type; /** Red TS_PID_TYPE_ values */ uint8_t idx; /** index in filtering table */ -}; +} __packed; struct as10x_register_value { uint8_t mode; @@ -183,9 +182,7 @@ struct as10x_register_value { uint16_t value16; /* 16 bit value */ uint32_t value32; /* 32 bit value */ }u; -}; - -#pragma pack() +} __packed; struct as10x_register_addr { /* register addr */ -- cgit v0.10.2 From 880102898f19cf9f9ba36dc9d838b5476645ce00 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 6 Nov 2011 16:31:43 -0300 Subject: [media] staging: as102: Fix the dvb device registration error path Release already acquired resources when error happens during devices registration steps. Use dev_err() where struct device is available, instead of driver specific err(). Cc: Devin Heitmueller Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/as102/as102_drv.c b/drivers/staging/media/as102/as102_drv.c index 85f58b9..e775900 100644 --- a/drivers/staging/media/as102/as102_drv.c +++ b/drivers/staging/media/as102/as102_drv.c @@ -195,19 +195,16 @@ static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed) int as102_dvb_register(struct as102_dev_t *as102_dev) { - int ret = 0; - ENTER(); + struct device *dev = &as102_dev->bus_adap.usb_dev->dev; + int ret; ret = dvb_register_adapter(&as102_dev->dvb_adap, - as102_dev->name, - THIS_MODULE, - &as102_dev->bus_adap.usb_dev->dev, - adapter_nr - ); + as102_dev->name, THIS_MODULE, + dev, adapter_nr); if (ret < 0) { - err("%s: dvb_register_adapter() failed (errno = %d)", - __func__, ret); - goto failed; + dev_err(dev, "%s: dvb_register_adapter() failed: %d\n", + __func__, ret); + return ret; } as102_dev->dvb_dmx.priv = as102_dev; @@ -225,22 +222,22 @@ int as102_dvb_register(struct as102_dev_t *as102_dev) ret = dvb_dmx_init(&as102_dev->dvb_dmx); if (ret < 0) { - err("%s: dvb_dmx_init() failed (errno = %d)", __func__, ret); - goto failed; + dev_err("%s: dvb_dmx_init() failed: %d\n", __func__, ret); + goto edmxinit; } ret = dvb_dmxdev_init(&as102_dev->dvb_dmxdev, &as102_dev->dvb_adap); if (ret < 0) { - err("%s: dvb_dmxdev_init() failed (errno = %d)", __func__, - ret); - goto failed; + dev_err(dev, "%s: dvb_dmxdev_init() failed: %d\n", + __func__, ret); + goto edmxdinit; } ret = as102_dvb_register_fe(as102_dev, &as102_dev->dvb_fe); if (ret < 0) { - err("%s: as102_dvb_register_frontend() failed (errno = %d)", + dev_err(dev, "%s: as102_dvb_register_frontend() failed: %d", __func__, ret); - goto failed; + goto efereg; } /* init bus mutex for token locking */ @@ -256,16 +253,21 @@ int as102_dvb_register(struct as102_dev_t *as102_dev) if (fw_upload) try_then_request_module(as102_fw_upload(&as102_dev->bus_adap), "firmware_class"); -failed: - LEAVE(); - /* FIXME: free dvb_XXX */ + + pr_info("Registered device %s", as102_dev->name); + return 0; + +efereg: + dvb_dmxdev_release(&as102_dev->dvb_dmxdev); +edmxdinit: + dvb_dmx_release(&as102_dev->dvb_dmx); +edmxinit: + dvb_unregister_adapter(&as102_dev->dvb_adap); return ret; } void as102_dvb_unregister(struct as102_dev_t *as102_dev) { - ENTER(); - /* unregister as102 frontend */ as102_dvb_unregister_fe(&as102_dev->dvb_fe); @@ -276,7 +278,7 @@ void as102_dvb_unregister(struct as102_dev_t *as102_dev) /* unregister dvb adapter */ dvb_unregister_adapter(&as102_dev->dvb_adap); - LEAVE(); + pr_info("Unregistered device %s", as102_dev->name); } static int __init as102_driver_init(void) -- cgit v0.10.2 From 14e0e4bf6c8c98ef36542280b3147b4e79e7131b Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 6 Nov 2011 16:31:44 -0300 Subject: [media] staging: as102: Whitespace and indentation cleanup Remove some unnecessary braces. Replace spaces with tabs where expected. Replace gcc specific __FUNCTION__ with C99 __func__. No functional changes. Cc: Devin Heitmueller Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/as102/as102_drv.c b/drivers/staging/media/as102/as102_drv.c index e775900..3234039 100644 --- a/drivers/staging/media/as102/as102_drv.c +++ b/drivers/staging/media/as102/as102_drv.c @@ -121,22 +121,22 @@ static int as10x_pid_filter(struct as102_dev_t *dev, switch (onoff) { case 0: - ret = as10x_cmd_del_PID_filter(bus_adap, (uint16_t) pid); - dprintk(debug, "DEL_PID_FILTER([%02d] 0x%04x) ret = %d\n", - index, pid, ret); - break; + ret = as10x_cmd_del_PID_filter(bus_adap, (uint16_t) pid); + dprintk(debug, "DEL_PID_FILTER([%02d] 0x%04x) ret = %d\n", + index, pid, ret); + break; case 1: { - struct as10x_ts_filter filter; + struct as10x_ts_filter filter; - filter.type = TS_PID_TYPE_TS; - filter.idx = 0xFF; - filter.pid = pid; + filter.type = TS_PID_TYPE_TS; + filter.idx = 0xFF; + filter.pid = pid; - ret = as10x_cmd_add_PID_filter(bus_adap, &filter); - dprintk(debug, "ADD_PID_FILTER([%02d -> %02d], 0x%04x) ret = %d\n", - index, filter.idx, filter.pid, ret); - break; + ret = as10x_cmd_add_PID_filter(bus_adap, &filter); + dprintk(debug, "ADD_PID_FILTER([%02d -> %02d], 0x%04x) ret = %d\n", + index, filter.idx, filter.pid, ret); + break; } } @@ -157,10 +157,9 @@ static int as102_dvb_dmx_start_feed(struct dvb_demux_feed *dvbdmxfeed) if (mutex_lock_interruptible(&as102_dev->sem)) return -ERESTARTSYS; - if (pid_filtering) { - as10x_pid_filter(as102_dev, - dvbdmxfeed->index, dvbdmxfeed->pid, 1); - } + if (pid_filtering) + as10x_pid_filter(as102_dev, dvbdmxfeed->index, + dvbdmxfeed->pid, 1); if (as102_dev->streaming++ == 0) ret = as102_start_stream(as102_dev); @@ -183,10 +182,9 @@ static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed) if (--as102_dev->streaming == 0) as102_stop_stream(as102_dev); - if (pid_filtering) { - as10x_pid_filter(as102_dev, - dvbdmxfeed->index, dvbdmxfeed->pid, 0); - } + if (pid_filtering) + as10x_pid_filter(as102_dev, dvbdmxfeed->index, + dvbdmxfeed->pid, 0); mutex_unlock(&as102_dev->sem); LEAVE(); diff --git a/drivers/staging/media/as102/as102_drv.h b/drivers/staging/media/as102/as102_drv.h index af2bf1e..d32019c 100644 --- a/drivers/staging/media/as102/as102_drv.h +++ b/drivers/staging/media/as102/as102_drv.h @@ -32,13 +32,13 @@ extern struct usb_driver as102_usb_driver; #define dprintk(debug, args...) \ do { if (debug) { \ - printk(KERN_DEBUG "%s: ",__FUNCTION__); \ + pr_debug("%s: ", __func__); \ printk(args); \ } } while (0) #ifdef TRACE -#define ENTER() printk(">> enter %s\n", __FUNCTION__) -#define LEAVE() printk("<< leave %s\n", __FUNCTION__) +#define ENTER() pr_debug(">> enter %s\n", __func__) +#define LEAVE() pr_debug("<< leave %s\n", __func__) #else #define ENTER() #define LEAVE() diff --git a/drivers/staging/media/as102/as102_usb_drv.c b/drivers/staging/media/as102/as102_usb_drv.c index 0a8f12b..e0c3854 100644 --- a/drivers/staging/media/as102/as102_usb_drv.c +++ b/drivers/staging/media/as102/as102_usb_drv.c @@ -56,16 +56,16 @@ static const char *as102_device_names[] = { }; struct usb_driver as102_usb_driver = { - .name = DRIVER_FULL_NAME, - .probe = as102_usb_probe, - .disconnect = as102_usb_disconnect, - .id_table = as102_usb_id_table + .name = DRIVER_FULL_NAME, + .probe = as102_usb_probe, + .disconnect = as102_usb_disconnect, + .id_table = as102_usb_id_table }; static const struct file_operations as102_dev_fops = { - .owner = THIS_MODULE, - .open = as102_open, - .release = as102_release, + .owner = THIS_MODULE, + .open = as102_open, + .release = as102_release, }; static struct usb_class_driver as102_usb_class_driver = { diff --git a/drivers/staging/media/as102/as10x_cmd.c b/drivers/staging/media/as102/as10x_cmd.c index 0dcba80..1663a45 100644 --- a/drivers/staging/media/as102/as10x_cmd.c +++ b/drivers/staging/media/as102/as10x_cmd.c @@ -232,7 +232,7 @@ out: } /** - * send get TPS command to AS10x + * as10x_cmd_get_tps - send get TPS command to AS10x * @phandle: pointer to AS10x handle * @ptps: pointer to TPS parameters structure * diff --git a/drivers/staging/media/as102/as10x_cmd.h b/drivers/staging/media/as102/as10x_cmd.h index 05f7150..9af8862 100644 --- a/drivers/staging/media/as102/as10x_cmd.h +++ b/drivers/staging/media/as102/as10x_cmd.h @@ -28,422 +28,423 @@ /*********************************/ /* MACRO DEFINITIONS */ /*********************************/ -#define AS10X_CMD_ERROR -1 +#define AS10X_CMD_ERROR -1 -#define SERVICE_PROG_ID 0x0002 -#define SERVICE_PROG_VERSION 0x0001 +#define SERVICE_PROG_ID 0x0002 +#define SERVICE_PROG_VERSION 0x0001 -#define HIER_NONE 0x00 -#define HIER_LOW_PRIORITY 0x01 +#define HIER_NONE 0x00 +#define HIER_LOW_PRIORITY 0x01 #define HEADER_SIZE (sizeof(struct as10x_cmd_header_t)) /* context request types */ -#define GET_CONTEXT_DATA 1 -#define SET_CONTEXT_DATA 2 +#define GET_CONTEXT_DATA 1 +#define SET_CONTEXT_DATA 2 /* ODSP suspend modes */ -#define CFG_MODE_ODSP_RESUME 0 -#define CFG_MODE_ODSP_SUSPEND 1 +#define CFG_MODE_ODSP_RESUME 0 +#define CFG_MODE_ODSP_SUSPEND 1 /* Dump memory size */ -#define DUMP_BLOCK_SIZE_MAX 0x20 +#define DUMP_BLOCK_SIZE_MAX 0x20 /*********************************/ /* TYPE DEFINITION */ /*********************************/ enum control_proc { - CONTROL_PROC_TURNON = 0x0001, - CONTROL_PROC_TURNON_RSP = 0x0100, - CONTROL_PROC_SET_REGISTER = 0x0002, - CONTROL_PROC_SET_REGISTER_RSP = 0x0200, - CONTROL_PROC_GET_REGISTER = 0x0003, - CONTROL_PROC_GET_REGISTER_RSP = 0x0300, - CONTROL_PROC_SETTUNE = 0x000A, - CONTROL_PROC_SETTUNE_RSP = 0x0A00, - CONTROL_PROC_GETTUNESTAT = 0x000B, - CONTROL_PROC_GETTUNESTAT_RSP = 0x0B00, - CONTROL_PROC_GETTPS = 0x000D, - CONTROL_PROC_GETTPS_RSP = 0x0D00, - CONTROL_PROC_SETFILTER = 0x000E, - CONTROL_PROC_SETFILTER_RSP = 0x0E00, - CONTROL_PROC_REMOVEFILTER = 0x000F, - CONTROL_PROC_REMOVEFILTER_RSP = 0x0F00, - CONTROL_PROC_GET_IMPULSE_RESP = 0x0012, - CONTROL_PROC_GET_IMPULSE_RESP_RSP = 0x1200, - CONTROL_PROC_START_STREAMING = 0x0013, - CONTROL_PROC_START_STREAMING_RSP = 0x1300, - CONTROL_PROC_STOP_STREAMING = 0x0014, - CONTROL_PROC_STOP_STREAMING_RSP = 0x1400, - CONTROL_PROC_GET_DEMOD_STATS = 0x0015, - CONTROL_PROC_GET_DEMOD_STATS_RSP = 0x1500, - CONTROL_PROC_ELNA_CHANGE_MODE = 0x0016, - CONTROL_PROC_ELNA_CHANGE_MODE_RSP = 0x1600, - CONTROL_PROC_ODSP_CHANGE_MODE = 0x0017, - CONTROL_PROC_ODSP_CHANGE_MODE_RSP = 0x1700, - CONTROL_PROC_AGC_CHANGE_MODE = 0x0018, - CONTROL_PROC_AGC_CHANGE_MODE_RSP = 0x1800, - - CONTROL_PROC_CONTEXT = 0x00FC, - CONTROL_PROC_CONTEXT_RSP = 0xFC00, - CONTROL_PROC_DUMP_MEMORY = 0x00FD, - CONTROL_PROC_DUMP_MEMORY_RSP = 0xFD00, - CONTROL_PROC_DUMPLOG_MEMORY = 0x00FE, - CONTROL_PROC_DUMPLOG_MEMORY_RSP = 0xFE00, - CONTROL_PROC_TURNOFF = 0x00FF, - CONTROL_PROC_TURNOFF_RSP = 0xFF00 + CONTROL_PROC_TURNON = 0x0001, + CONTROL_PROC_TURNON_RSP = 0x0100, + CONTROL_PROC_SET_REGISTER = 0x0002, + CONTROL_PROC_SET_REGISTER_RSP = 0x0200, + CONTROL_PROC_GET_REGISTER = 0x0003, + CONTROL_PROC_GET_REGISTER_RSP = 0x0300, + CONTROL_PROC_SETTUNE = 0x000A, + CONTROL_PROC_SETTUNE_RSP = 0x0A00, + CONTROL_PROC_GETTUNESTAT = 0x000B, + CONTROL_PROC_GETTUNESTAT_RSP = 0x0B00, + CONTROL_PROC_GETTPS = 0x000D, + CONTROL_PROC_GETTPS_RSP = 0x0D00, + CONTROL_PROC_SETFILTER = 0x000E, + CONTROL_PROC_SETFILTER_RSP = 0x0E00, + CONTROL_PROC_REMOVEFILTER = 0x000F, + CONTROL_PROC_REMOVEFILTER_RSP = 0x0F00, + CONTROL_PROC_GET_IMPULSE_RESP = 0x0012, + CONTROL_PROC_GET_IMPULSE_RESP_RSP = 0x1200, + CONTROL_PROC_START_STREAMING = 0x0013, + CONTROL_PROC_START_STREAMING_RSP = 0x1300, + CONTROL_PROC_STOP_STREAMING = 0x0014, + CONTROL_PROC_STOP_STREAMING_RSP = 0x1400, + CONTROL_PROC_GET_DEMOD_STATS = 0x0015, + CONTROL_PROC_GET_DEMOD_STATS_RSP = 0x1500, + CONTROL_PROC_ELNA_CHANGE_MODE = 0x0016, + CONTROL_PROC_ELNA_CHANGE_MODE_RSP = 0x1600, + CONTROL_PROC_ODSP_CHANGE_MODE = 0x0017, + CONTROL_PROC_ODSP_CHANGE_MODE_RSP = 0x1700, + CONTROL_PROC_AGC_CHANGE_MODE = 0x0018, + CONTROL_PROC_AGC_CHANGE_MODE_RSP = 0x1800, + + CONTROL_PROC_CONTEXT = 0x00FC, + CONTROL_PROC_CONTEXT_RSP = 0xFC00, + CONTROL_PROC_DUMP_MEMORY = 0x00FD, + CONTROL_PROC_DUMP_MEMORY_RSP = 0xFD00, + CONTROL_PROC_DUMPLOG_MEMORY = 0x00FE, + CONTROL_PROC_DUMPLOG_MEMORY_RSP = 0xFE00, + CONTROL_PROC_TURNOFF = 0x00FF, + CONTROL_PROC_TURNOFF_RSP = 0xFF00 }; union as10x_turn_on { - /* request */ - struct { - /* request identifier */ - uint16_t proc_id; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* error */ - uint8_t error; - } rsp; + /* request */ + struct { + /* request identifier */ + uint16_t proc_id; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* error */ + uint8_t error; + } rsp; } __packed; union as10x_turn_off { - /* request */ - struct { - /* request identifier */ - uint16_t proc_id; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* error */ - uint8_t err; - } rsp; + /* request */ + struct { + /* request identifier */ + uint16_t proc_id; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* error */ + uint8_t err; + } rsp; } __packed; union as10x_set_tune { - /* request */ - struct { - /* request identifier */ - uint16_t proc_id; - /* tune params */ - struct as10x_tune_args args; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* response error */ - uint8_t error; - } rsp; + /* request */ + struct { + /* request identifier */ + uint16_t proc_id; + /* tune params */ + struct as10x_tune_args args; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* response error */ + uint8_t error; + } rsp; } __packed; union as10x_get_tune_status { - /* request */ - struct { - /* request identifier */ - uint16_t proc_id; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* response error */ - uint8_t error; - /* tune status */ - struct as10x_tune_status sts; - } rsp; + /* request */ + struct { + /* request identifier */ + uint16_t proc_id; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* response error */ + uint8_t error; + /* tune status */ + struct as10x_tune_status sts; + } rsp; } __packed; union as10x_get_tps { - /* request */ - struct { - /* request identifier */ - uint16_t proc_id; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* response error */ - uint8_t error; - /* tps details */ - struct as10x_tps tps; - } rsp; + /* request */ + struct { + /* request identifier */ + uint16_t proc_id; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* response error */ + uint8_t error; + /* tps details */ + struct as10x_tps tps; + } rsp; } __packed; union as10x_common { - /* request */ - struct { - /* request identifier */ - uint16_t proc_id; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* response error */ - uint8_t error; - } rsp; + /* request */ + struct { + /* request identifier */ + uint16_t proc_id; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* response error */ + uint8_t error; + } rsp; } __packed; union as10x_add_pid_filter { - /* request */ - struct { - /* request identifier */ - uint16_t proc_id; - /* PID to filter */ - uint16_t pid; - /* stream type (MPE, PSI/SI or PES )*/ - uint8_t stream_type; - /* PID index in filter table */ - uint8_t idx; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* response error */ - uint8_t error; - /* Filter id */ - uint8_t filter_id; - } rsp; + /* request */ + struct { + /* request identifier */ + uint16_t proc_id; + /* PID to filter */ + uint16_t pid; + /* stream type (MPE, PSI/SI or PES )*/ + uint8_t stream_type; + /* PID index in filter table */ + uint8_t idx; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* response error */ + uint8_t error; + /* Filter id */ + uint8_t filter_id; + } rsp; } __packed; union as10x_del_pid_filter { - /* request */ - struct { - /* request identifier */ - uint16_t proc_id; - /* PID to remove */ - uint16_t pid; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* response error */ - uint8_t error; - } rsp; + /* request */ + struct { + /* request identifier */ + uint16_t proc_id; + /* PID to remove */ + uint16_t pid; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* response error */ + uint8_t error; + } rsp; } __packed; union as10x_start_streaming { - /* request */ - struct { - /* request identifier */ - uint16_t proc_id; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* error */ - uint8_t error; - } rsp; + /* request */ + struct { + /* request identifier */ + uint16_t proc_id; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* error */ + uint8_t error; + } rsp; } __packed; union as10x_stop_streaming { - /* request */ - struct { - /* request identifier */ - uint16_t proc_id; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* error */ - uint8_t error; - } rsp; + /* request */ + struct { + /* request identifier */ + uint16_t proc_id; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* error */ + uint8_t error; + } rsp; } __packed; union as10x_get_demod_stats { - /* request */ - struct { - /* request identifier */ - uint16_t proc_id; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* error */ - uint8_t error; - /* demod stats */ - struct as10x_demod_stats stats; - } rsp; + /* request */ + struct { + /* request identifier */ + uint16_t proc_id; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* error */ + uint8_t error; + /* demod stats */ + struct as10x_demod_stats stats; + } rsp; } __packed; union as10x_get_impulse_resp { - /* request */ - struct { - /* request identifier */ - uint16_t proc_id; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* error */ - uint8_t error; - /* impulse response ready */ - uint8_t is_ready; - } rsp; + /* request */ + struct { + /* request identifier */ + uint16_t proc_id; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* error */ + uint8_t error; + /* impulse response ready */ + uint8_t is_ready; + } rsp; } __packed; union as10x_fw_context { - /* request */ - struct { - /* request identifier */ - uint16_t proc_id; - /* value to write (for set context)*/ - struct as10x_register_value reg_val; - /* context tag */ - uint16_t tag; - /* context request type */ - uint16_t type; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* value read (for get context) */ - struct as10x_register_value reg_val; - /* context request type */ - uint16_t type; - /* error */ - uint8_t error; - } rsp; + /* request */ + struct { + /* request identifier */ + uint16_t proc_id; + /* value to write (for set context)*/ + struct as10x_register_value reg_val; + /* context tag */ + uint16_t tag; + /* context request type */ + uint16_t type; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* value read (for get context) */ + struct as10x_register_value reg_val; + /* context request type */ + uint16_t type; + /* error */ + uint8_t error; + } rsp; } __packed; union as10x_set_register { - /* request */ - struct { - /* response identifier */ - uint16_t proc_id; - /* register description */ - struct as10x_register_addr reg_addr; - /* register content */ - struct as10x_register_value reg_val; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* error */ - uint8_t error; - } rsp; + /* request */ + struct { + /* response identifier */ + uint16_t proc_id; + /* register description */ + struct as10x_register_addr reg_addr; + /* register content */ + struct as10x_register_value reg_val; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* error */ + uint8_t error; + } rsp; } __packed; union as10x_get_register { - /* request */ - struct { - /* response identifier */ - uint16_t proc_id; - /* register description */ - struct as10x_register_addr reg_addr; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* error */ - uint8_t error; - /* register content */ - struct as10x_register_value reg_val; - } rsp; + /* request */ + struct { + /* response identifier */ + uint16_t proc_id; + /* register description */ + struct as10x_register_addr reg_addr; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* error */ + uint8_t error; + /* register content */ + struct as10x_register_value reg_val; + } rsp; } __packed; union as10x_cfg_change_mode { - /* request */ - struct { - /* request identifier */ - uint16_t proc_id; - /* mode */ - uint8_t mode; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* error */ - uint8_t error; - } rsp; + /* request */ + struct { + /* request identifier */ + uint16_t proc_id; + /* mode */ + uint8_t mode; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* error */ + uint8_t error; + } rsp; } __packed; struct as10x_cmd_header_t { - uint16_t req_id; - uint16_t prog; - uint16_t version; - uint16_t data_len; + uint16_t req_id; + uint16_t prog; + uint16_t version; + uint16_t data_len; } __packed; #define DUMP_BLOCK_SIZE 16 union as10x_dump_memory { - /* request */ - struct { - /* request identifier */ - uint16_t proc_id; - /* dump memory type request */ - uint8_t dump_req; - /* register description */ - struct as10x_register_addr reg_addr; - /* nb blocks to read */ - uint16_t num_blocks; - } req; - /* response */ - struct { - /* response identifier */ - uint16_t proc_id; - /* error */ - uint8_t error; - /* dump response */ - uint8_t dump_rsp; - /* data */ - union { - uint8_t data8[DUMP_BLOCK_SIZE]; - uint16_t data16[DUMP_BLOCK_SIZE / sizeof(uint16_t)]; - uint32_t data32[DUMP_BLOCK_SIZE / sizeof(uint32_t)]; - } u; - } rsp; + /* request */ + struct { + /* request identifier */ + uint16_t proc_id; + /* dump memory type request */ + uint8_t dump_req; + /* register description */ + struct as10x_register_addr reg_addr; + /* nb blocks to read */ + uint16_t num_blocks; + } req; + /* response */ + struct { + /* response identifier */ + uint16_t proc_id; + /* error */ + uint8_t error; + /* dump response */ + uint8_t dump_rsp; + /* data */ + union { + uint8_t data8[DUMP_BLOCK_SIZE]; + uint16_t data16[DUMP_BLOCK_SIZE / sizeof(uint16_t)]; + uint32_t data32[DUMP_BLOCK_SIZE / sizeof(uint32_t)]; + } u; + } rsp; } __packed; union as10x_dumplog_memory { - struct { - /* request identifier */ - uint16_t proc_id; - /* dump memory type request */ - uint8_t dump_req; - } req; - struct { - /* request identifier */ - uint16_t proc_id; - /* error */ - uint8_t error; - /* dump response */ - uint8_t dump_rsp; - /* dump data */ - uint8_t data[DUMP_BLOCK_SIZE]; - } rsp; + struct { + /* request identifier */ + uint16_t proc_id; + /* dump memory type request */ + uint8_t dump_req; + } req; + struct { + /* request identifier */ + uint16_t proc_id; + /* error */ + uint8_t error; + /* dump response */ + uint8_t dump_rsp; + /* dump data */ + uint8_t data[DUMP_BLOCK_SIZE]; + } rsp; } __packed; union as10x_raw_data { - /* request */ - struct { - uint16_t proc_id; - uint8_t data[64 - sizeof(struct as10x_cmd_header_t) -2 /* proc_id */]; - } req; - /* response */ - struct { - uint16_t proc_id; - uint8_t error; - uint8_t data[64 - sizeof(struct as10x_cmd_header_t) /* header */ - - 2 /* proc_id */ - 1 /* rc */]; - } rsp; + /* request */ + struct { + uint16_t proc_id; + uint8_t data[64 - sizeof(struct as10x_cmd_header_t) + - 2 /* proc_id */]; + } req; + /* response */ + struct { + uint16_t proc_id; + uint8_t error; + uint8_t data[64 - sizeof(struct as10x_cmd_header_t) + - 2 /* proc_id */ - 1 /* rc */]; + } rsp; } __packed; struct as10x_cmd_t { @@ -472,10 +473,10 @@ struct as10x_cmd_t { } __packed; struct as10x_token_cmd_t { - /* token cmd */ - struct as10x_cmd_t c; - /* token response */ - struct as10x_cmd_t r; + /* token cmd */ + struct as10x_cmd_t c; + /* token response */ + struct as10x_cmd_t r; } __packed; diff --git a/drivers/staging/media/as102/as10x_handle.h b/drivers/staging/media/as102/as10x_handle.h index 4f01a76..d67203a 100644 --- a/drivers/staging/media/as102/as10x_handle.h +++ b/drivers/staging/media/as102/as10x_handle.h @@ -24,9 +24,9 @@ struct as102_dev_t; #include "as10x_cmd.h" /* values for "mode" field */ -#define REGMODE8 8 -#define REGMODE16 16 -#define REGMODE32 32 +#define REGMODE8 8 +#define REGMODE16 16 +#define REGMODE32 32 struct as102_priv_ops_t { int (*upload_fw_pkt) (struct as102_bus_adapter_t *bus_adap, diff --git a/drivers/staging/media/as102/as10x_types.h b/drivers/staging/media/as102/as10x_types.h index 0b27f3a..c40c812 100644 --- a/drivers/staging/media/as102/as10x_types.h +++ b/drivers/staging/media/as102/as10x_types.h @@ -26,170 +26,169 @@ /*********************************/ /* bandwidth constant values */ -#define BW_5_MHZ 0x00 -#define BW_6_MHZ 0x01 -#define BW_7_MHZ 0x02 -#define BW_8_MHZ 0x03 +#define BW_5_MHZ 0x00 +#define BW_6_MHZ 0x01 +#define BW_7_MHZ 0x02 +#define BW_8_MHZ 0x03 /* hierarchy priority selection values */ -#define HIER_NO_PRIORITY 0x00 -#define HIER_LOW_PRIORITY 0x01 -#define HIER_HIGH_PRIORITY 0x02 +#define HIER_NO_PRIORITY 0x00 +#define HIER_LOW_PRIORITY 0x01 +#define HIER_HIGH_PRIORITY 0x02 /* constellation available values */ -#define CONST_QPSK 0x00 -#define CONST_QAM16 0x01 -#define CONST_QAM64 0x02 -#define CONST_UNKNOWN 0xFF +#define CONST_QPSK 0x00 +#define CONST_QAM16 0x01 +#define CONST_QAM64 0x02 +#define CONST_UNKNOWN 0xFF /* hierarchy available values */ -#define HIER_NONE 0x00 -#define HIER_ALPHA_1 0x01 -#define HIER_ALPHA_2 0x02 -#define HIER_ALPHA_4 0x03 -#define HIER_UNKNOWN 0xFF +#define HIER_NONE 0x00 +#define HIER_ALPHA_1 0x01 +#define HIER_ALPHA_2 0x02 +#define HIER_ALPHA_4 0x03 +#define HIER_UNKNOWN 0xFF /* interleaving available values */ -#define INTLV_NATIVE 0x00 -#define INTLV_IN_DEPTH 0x01 -#define INTLV_UNKNOWN 0xFF +#define INTLV_NATIVE 0x00 +#define INTLV_IN_DEPTH 0x01 +#define INTLV_UNKNOWN 0xFF /* code rate available values */ -#define CODE_RATE_1_2 0x00 -#define CODE_RATE_2_3 0x01 -#define CODE_RATE_3_4 0x02 -#define CODE_RATE_5_6 0x03 -#define CODE_RATE_7_8 0x04 -#define CODE_RATE_UNKNOWN 0xFF +#define CODE_RATE_1_2 0x00 +#define CODE_RATE_2_3 0x01 +#define CODE_RATE_3_4 0x02 +#define CODE_RATE_5_6 0x03 +#define CODE_RATE_7_8 0x04 +#define CODE_RATE_UNKNOWN 0xFF /* guard interval available values */ -#define GUARD_INT_1_32 0x00 -#define GUARD_INT_1_16 0x01 -#define GUARD_INT_1_8 0x02 -#define GUARD_INT_1_4 0x03 -#define GUARD_UNKNOWN 0xFF +#define GUARD_INT_1_32 0x00 +#define GUARD_INT_1_16 0x01 +#define GUARD_INT_1_8 0x02 +#define GUARD_INT_1_4 0x03 +#define GUARD_UNKNOWN 0xFF /* transmission mode available values */ -#define TRANS_MODE_2K 0x00 -#define TRANS_MODE_8K 0x01 -#define TRANS_MODE_4K 0x02 -#define TRANS_MODE_UNKNOWN 0xFF +#define TRANS_MODE_2K 0x00 +#define TRANS_MODE_8K 0x01 +#define TRANS_MODE_4K 0x02 +#define TRANS_MODE_UNKNOWN 0xFF /* DVBH signalling available values */ -#define TIMESLICING_PRESENT 0x01 -#define MPE_FEC_PRESENT 0x02 +#define TIMESLICING_PRESENT 0x01 +#define MPE_FEC_PRESENT 0x02 /* tune state available */ -#define TUNE_STATUS_NOT_TUNED 0x00 -#define TUNE_STATUS_IDLE 0x01 -#define TUNE_STATUS_LOCKING 0x02 -#define TUNE_STATUS_SIGNAL_DVB_OK 0x03 -#define TUNE_STATUS_STREAM_DETECTED 0x04 -#define TUNE_STATUS_STREAM_TUNED 0x05 -#define TUNE_STATUS_ERROR 0xFF +#define TUNE_STATUS_NOT_TUNED 0x00 +#define TUNE_STATUS_IDLE 0x01 +#define TUNE_STATUS_LOCKING 0x02 +#define TUNE_STATUS_SIGNAL_DVB_OK 0x03 +#define TUNE_STATUS_STREAM_DETECTED 0x04 +#define TUNE_STATUS_STREAM_TUNED 0x05 +#define TUNE_STATUS_ERROR 0xFF /* available TS FID filter types */ -#define TS_PID_TYPE_TS 0 -#define TS_PID_TYPE_PSI_SI 1 -#define TS_PID_TYPE_MPE 2 +#define TS_PID_TYPE_TS 0 +#define TS_PID_TYPE_PSI_SI 1 +#define TS_PID_TYPE_MPE 2 /* number of echos available */ -#define MAX_ECHOS 15 +#define MAX_ECHOS 15 /* Context types */ -#define CONTEXT_LNA 1010 -#define CONTEXT_ELNA_HYSTERESIS 4003 -#define CONTEXT_ELNA_GAIN 4004 -#define CONTEXT_MER_THRESHOLD 5005 -#define CONTEXT_MER_OFFSET 5006 -#define CONTEXT_IR_STATE 7000 -#define CONTEXT_TSOUT_MSB_FIRST 7004 -#define CONTEXT_TSOUT_FALLING_EDGE 7005 +#define CONTEXT_LNA 1010 +#define CONTEXT_ELNA_HYSTERESIS 4003 +#define CONTEXT_ELNA_GAIN 4004 +#define CONTEXT_MER_THRESHOLD 5005 +#define CONTEXT_MER_OFFSET 5006 +#define CONTEXT_IR_STATE 7000 +#define CONTEXT_TSOUT_MSB_FIRST 7004 +#define CONTEXT_TSOUT_FALLING_EDGE 7005 /* Configuration modes */ -#define CFG_MODE_ON 0 -#define CFG_MODE_OFF 1 -#define CFG_MODE_AUTO 2 +#define CFG_MODE_ON 0 +#define CFG_MODE_OFF 1 +#define CFG_MODE_AUTO 2 struct as10x_tps { - uint8_t constellation; - uint8_t hierarchy; - uint8_t interleaving_mode; - uint8_t code_rate_HP; - uint8_t code_rate_LP; - uint8_t guard_interval; - uint8_t transmission_mode; - uint8_t DVBH_mask_HP; - uint8_t DVBH_mask_LP; - uint16_t cell_ID; + uint8_t constellation; + uint8_t hierarchy; + uint8_t interleaving_mode; + uint8_t code_rate_HP; + uint8_t code_rate_LP; + uint8_t guard_interval; + uint8_t transmission_mode; + uint8_t DVBH_mask_HP; + uint8_t DVBH_mask_LP; + uint16_t cell_ID; } __packed; struct as10x_tune_args { - /* frequency */ - uint32_t freq; - /* bandwidth */ - uint8_t bandwidth; - /* hierarchy selection */ - uint8_t hier_select; - /* constellation */ - uint8_t constellation; - /* hierarchy */ - uint8_t hierarchy; - /* interleaving mode */ - uint8_t interleaving_mode; - /* code rate */ - uint8_t code_rate; - /* guard interval */ - uint8_t guard_interval; - /* transmission mode */ - uint8_t transmission_mode; + /* frequency */ + uint32_t freq; + /* bandwidth */ + uint8_t bandwidth; + /* hierarchy selection */ + uint8_t hier_select; + /* constellation */ + uint8_t constellation; + /* hierarchy */ + uint8_t hierarchy; + /* interleaving mode */ + uint8_t interleaving_mode; + /* code rate */ + uint8_t code_rate; + /* guard interval */ + uint8_t guard_interval; + /* transmission mode */ + uint8_t transmission_mode; } __packed; struct as10x_tune_status { - /* tune status */ - uint8_t tune_state; - /* signal strength */ - int16_t signal_strength; - /* packet error rate 10^-4 */ - uint16_t PER; - /* bit error rate 10^-4 */ - uint16_t BER; + /* tune status */ + uint8_t tune_state; + /* signal strength */ + int16_t signal_strength; + /* packet error rate 10^-4 */ + uint16_t PER; + /* bit error rate 10^-4 */ + uint16_t BER; } __packed; struct as10x_demod_stats { - /* frame counter */ - uint32_t frame_count; - /* Bad frame counter */ - uint32_t bad_frame_count; - /* Number of wrong bytes fixed by Reed-Solomon */ - uint32_t bytes_fixed_by_rs; - /* Averaged MER */ - uint16_t mer; - /* statistics calculation state indicator (started or not) */ - uint8_t has_started; + /* frame counter */ + uint32_t frame_count; + /* Bad frame counter */ + uint32_t bad_frame_count; + /* Number of wrong bytes fixed by Reed-Solomon */ + uint32_t bytes_fixed_by_rs; + /* Averaged MER */ + uint16_t mer; + /* statistics calculation state indicator (started or not) */ + uint8_t has_started; } __packed; struct as10x_ts_filter { - uint16_t pid; /** valid PID value 0x00 : 0x2000 */ - uint8_t type; /** Red TS_PID_TYPE_ values */ - uint8_t idx; /** index in filtering table */ + uint16_t pid; /* valid PID value 0x00 : 0x2000 */ + uint8_t type; /* Red TS_PID_TYPE_ values */ + uint8_t idx; /* index in filtering table */ } __packed; struct as10x_register_value { - uint8_t mode; - union { - uint8_t value8; /* 8 bit value */ - uint16_t value16; /* 16 bit value */ - uint32_t value32; /* 32 bit value */ - }u; + uint8_t mode; + union { + uint8_t value8; /* 8 bit value */ + uint16_t value16; /* 16 bit value */ + uint32_t value32; /* 32 bit value */ + } u; } __packed; struct as10x_register_addr { - /* register addr */ - uint32_t addr; - /* register mode access */ - uint8_t mode; + /* register addr */ + uint32_t addr; + /* register mode access */ + uint8_t mode; }; - #endif -- cgit v0.10.2 From 7d462fe580d6b73f0307588b898b2e6c8ad45d41 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 6 Nov 2011 16:31:45 -0300 Subject: [media] staging: as102: Replace printk(KERN_ witk pr_ While at it also correct some spelling errors. Cc: Devin Heitmueller Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/as102/as102_fw.c b/drivers/staging/media/as102/as102_fw.c index ab7dcdb..fa56939 100644 --- a/drivers/staging/media/as102/as102_fw.c +++ b/drivers/staging/media/as102/as102_fw.c @@ -58,7 +58,7 @@ static int parse_hex_line(unsigned char *fw_data, unsigned char *addr, unsigned char *src, dst; if (*fw_data++ != ':') { - printk(KERN_ERR "invalid firmware file\n"); + pr_err("invalid firmware file\n"); return -EFAULT; } @@ -191,21 +191,21 @@ int as102_fw_upload(struct as102_bus_adapter_t *bus_adap) /* request kernel to locate firmware file: part1 */ errno = request_firmware(&firmware, fw1, &dev->dev); if (errno < 0) { - printk(KERN_ERR "%s: unable to locate firmware file: %s\n", - DRIVER_NAME, fw1); + pr_err("%s: unable to locate firmware file: %s\n", + DRIVER_NAME, fw1); goto error; } /* initiate firmware upload */ errno = as102_firmware_upload(bus_adap, cmd_buf, firmware); if (errno < 0) { - printk(KERN_ERR "%s: error during firmware upload part1\n", - DRIVER_NAME); + pr_err("%s: error during firmware upload part1\n", + DRIVER_NAME); goto error; } - printk(KERN_INFO "%s: fimrware: %s loaded with success\n", - DRIVER_NAME, fw1); + pr_info("%s: firmware: %s loaded with success\n", + DRIVER_NAME, fw1); release_firmware(firmware); /* wait for boot to complete */ @@ -214,21 +214,21 @@ int as102_fw_upload(struct as102_bus_adapter_t *bus_adap) /* request kernel to locate firmware file: part2 */ errno = request_firmware(&firmware, fw2, &dev->dev); if (errno < 0) { - printk(KERN_ERR "%s: unable to locate firmware file: %s\n", - DRIVER_NAME, fw2); + pr_err("%s: unable to locate firmware file: %s\n", + DRIVER_NAME, fw2); goto error; } /* initiate firmware upload */ errno = as102_firmware_upload(bus_adap, cmd_buf, firmware); if (errno < 0) { - printk(KERN_ERR "%s: error during firmware upload part2\n", - DRIVER_NAME); + pr_err("%s: error during firmware upload part2\n", + DRIVER_NAME); goto error; } - printk(KERN_INFO "%s: fimrware: %s loaded with success\n", - DRIVER_NAME, fw2); + pr_info("%s: firmware: %s loaded with success\n", + DRIVER_NAME, fw2); error: /* free data buffer */ kfree(cmd_buf); diff --git a/drivers/staging/media/as102/as102_usb_drv.c b/drivers/staging/media/as102/as102_usb_drv.c index e0c3854..3ded7d6 100644 --- a/drivers/staging/media/as102/as102_usb_drv.c +++ b/drivers/staging/media/as102/as102_usb_drv.c @@ -337,7 +337,7 @@ static void as102_usb_disconnect(struct usb_interface *intf) /* decrement usage counter */ kref_put(&as102_dev->kref, as102_usb_release); - printk(KERN_INFO "%s: device has been disconnected\n", DRIVER_NAME); + pr_info("%s: device has been disconnected\n", DRIVER_NAME); LEAVE(); } @@ -360,7 +360,7 @@ static int as102_usb_probe(struct usb_interface *intf, /* This should never actually happen */ if ((sizeof(as102_usb_id_table) / sizeof(struct usb_device_id)) != (sizeof(as102_device_names) / sizeof(const char *))) { - printk(KERN_ERR "Device names table invalid size"); + pr_err("Device names table invalid size"); return -EINVAL; } @@ -399,7 +399,7 @@ static int as102_usb_probe(struct usb_interface *intf, goto failed; } - printk(KERN_INFO "%s: device has been detected\n", DRIVER_NAME); + pr_info("%s: device has been detected\n", DRIVER_NAME); /* request buffer allocation for streaming */ ret = as102_alloc_usb_stream_buffer(as102_dev); @@ -432,8 +432,8 @@ static int as102_open(struct inode *inode, struct file *file) /* fetch device from usb interface */ intf = usb_find_interface(&as102_usb_driver, minor); if (intf == NULL) { - printk(KERN_ERR "%s: can't find device for minor %d\n", - __func__, minor); + pr_err("%s: can't find device for minor %d\n", + __func__, minor); ret = -ENODEV; goto exit; } -- cgit v0.10.2 From c20ec0354f89d402c68d657d94ec3a96c82dcfb5 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 6 Nov 2011 16:31:46 -0300 Subject: [media] staging: as102: Remove linkage specifiers for C++ The as10x_cmd.h header is not public so there should be no need for an "extern "C"" in it. Cc: Devin Heitmueller Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/as102/as10x_cmd.h b/drivers/staging/media/as102/as10x_cmd.h index 9af8862..da31c6d 100644 --- a/drivers/staging/media/as102/as10x_cmd.h +++ b/drivers/staging/media/as102/as10x_cmd.h @@ -488,10 +488,6 @@ void as10x_cmd_build(struct as10x_cmd_t *pcmd, uint16_t proc_id, uint16_t cmd_len); int as10x_rsp_parse(struct as10x_cmd_t *r, uint16_t proc_id); -#ifdef __cplusplus -extern "C" { -#endif - /* as10x cmd */ int as10x_cmd_turn_on(as10x_handle_t *phandle); int as10x_cmd_turn_off(as10x_handle_t *phandle); @@ -530,7 +526,4 @@ int as10x_cmd_get_context(as10x_handle_t *phandle, int as10x_cmd_eLNA_change_mode(as10x_handle_t *phandle, uint8_t mode); int as10x_context_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id); -#ifdef __cplusplus -} -#endif #endif -- cgit v0.10.2 From 3288e201a1308051b9c8ee858437ab9ef3bcac41 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 6 Nov 2011 16:31:47 -0300 Subject: [media] staging: as102: Use linux/uaccess.h instead of asm/uaccess.h Cc: Devin Heitmueller Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/as102/as102_drv.c b/drivers/staging/media/as102/as102_drv.c index 3234039..44f6017 100644 --- a/drivers/staging/media/as102/as102_drv.c +++ b/drivers/staging/media/as102/as102_drv.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include /* header file for Usb device driver*/ -- cgit v0.10.2 From a11726349c4a5add63a9d51c0e8079e0e9f20624 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 6 Nov 2011 16:31:48 -0300 Subject: [media] staging: as102: Move variable declarations to the header Fixes following checkpatch.pl warning: WARNING: externs should be avoided in .c files Cc: Devin Heitmueller Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/as102/as102_drv.h b/drivers/staging/media/as102/as102_drv.h index d32019c..06466fd 100644 --- a/drivers/staging/media/as102/as102_drv.h +++ b/drivers/staging/media/as102/as102_drv.h @@ -29,6 +29,7 @@ extern int debug; extern struct usb_driver as102_usb_driver; +extern int elna_enable; #define dprintk(debug, args...) \ do { if (debug) { \ diff --git a/drivers/staging/media/as102/as102_fe.c b/drivers/staging/media/as102/as102_fe.c index 7d7dd55..c2adfe5 100644 --- a/drivers/staging/media/as102/as102_fe.c +++ b/drivers/staging/media/as102/as102_fe.c @@ -23,8 +23,6 @@ #include "as10x_types.h" #include "as10x_cmd.h" -extern int elna_enable; - static void as10x_fe_copy_tps_parameters(struct dvb_frontend_parameters *dst, struct as10x_tps *src); -- cgit v0.10.2 From d758b9ef7aacb66d99529b6a24dc54e9d11434b7 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 6 Nov 2011 16:31:49 -0300 Subject: [media] staging: as102: Define device name string pointers constant Supresses following checkpatch warning: WARNING: static const char * array should probably be static const char * const Cc: Devin Heitmueller Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/as102/as102_usb_drv.c b/drivers/staging/media/as102/as102_usb_drv.c index 3ded7d6..97bceeb 100644 --- a/drivers/staging/media/as102/as102_usb_drv.c +++ b/drivers/staging/media/as102/as102_usb_drv.c @@ -47,7 +47,7 @@ static struct usb_device_id as102_usb_id_table[] = { /* Note that this table must always have the same number of entries as the as102_usb_id_table struct */ -static const char *as102_device_names[] = { +static const char * const as102_device_names[] = { AS102_REFERENCE_DESIGN, AS102_PCTV_74E, AS102_ELGATO_EYETV_DTT_NAME, -- cgit v0.10.2 From 34490a0a3dfd9c048abc5b9a3ce86fb0fbf881cf Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Sun, 6 Nov 2011 16:31:50 -0300 Subject: [media] staging: as102: Eliminate as10x_handle_t alias Remove pre-processor defined as10x_handle_t data type by directly replacing it with struct as102_bus_adapter_t. phandle is renamed to adap inside function bodies. Cc: Devin Heitmueller Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/as102/as102_drv.c b/drivers/staging/media/as102/as102_drv.c index 44f6017..b8adfd2 100644 --- a/drivers/staging/media/as102/as102_drv.c +++ b/drivers/staging/media/as102/as102_drv.c @@ -60,7 +60,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); static void as102_stop_stream(struct as102_dev_t *dev) { - struct as102_bus_adapter_t *bus_adap; + struct as10x_bus_adapter_t *bus_adap; if (dev != NULL) bus_adap = &dev->bus_adap; @@ -83,7 +83,7 @@ static void as102_stop_stream(struct as102_dev_t *dev) static int as102_start_stream(struct as102_dev_t *dev) { - struct as102_bus_adapter_t *bus_adap; + struct as10x_bus_adapter_t *bus_adap; int ret = -EFAULT; if (dev != NULL) @@ -109,7 +109,7 @@ static int as102_start_stream(struct as102_dev_t *dev) static int as10x_pid_filter(struct as102_dev_t *dev, int index, u16 pid, int onoff) { - struct as102_bus_adapter_t *bus_adap = &dev->bus_adap; + struct as10x_bus_adapter_t *bus_adap = &dev->bus_adap; int ret = -EFAULT; ENTER(); diff --git a/drivers/staging/media/as102/as102_drv.h b/drivers/staging/media/as102/as102_drv.h index 06466fd..0ecef9e 100644 --- a/drivers/staging/media/as102/as102_drv.h +++ b/drivers/staging/media/as102/as102_drv.h @@ -50,7 +50,7 @@ extern int elna_enable; #define AS102_USB_BUF_SIZE 512 #define MAX_STREAM_URB 32 -struct as102_bus_adapter_t { +struct as10x_bus_adapter_t { struct usb_device *usb_dev; /* bus token lock */ struct mutex lock; @@ -72,7 +72,7 @@ struct as102_bus_adapter_t { struct as102_dev_t { const char *name; - struct as102_bus_adapter_t bus_adap; + struct as10x_bus_adapter_t bus_adap; struct list_head device_entry; struct kref kref; unsigned long minor; diff --git a/drivers/staging/media/as102/as102_fw.c b/drivers/staging/media/as102/as102_fw.c index fa56939..43ebc43 100644 --- a/drivers/staging/media/as102/as102_fw.c +++ b/drivers/staging/media/as102/as102_fw.c @@ -101,7 +101,7 @@ static int parse_hex_line(unsigned char *fw_data, unsigned char *addr, return (count * 2) + 2; } -static int as102_firmware_upload(struct as102_bus_adapter_t *bus_adap, +static int as102_firmware_upload(struct as10x_bus_adapter_t *bus_adap, unsigned char *cmd, const struct firmware *firmware) { @@ -162,7 +162,7 @@ error: return (errno == 0) ? total_read_bytes : errno; } -int as102_fw_upload(struct as102_bus_adapter_t *bus_adap) +int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap) { int errno = -EFAULT; const struct firmware *firmware; diff --git a/drivers/staging/media/as102/as102_fw.h b/drivers/staging/media/as102/as102_fw.h index a1fdb92..bd21f05 100644 --- a/drivers/staging/media/as102/as102_fw.h +++ b/drivers/staging/media/as102/as102_fw.h @@ -34,5 +34,5 @@ struct as10x_fw_pkt_t { } __packed; #ifdef __KERNEL__ -int as102_fw_upload(struct as102_bus_adapter_t *bus_adap); +int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap); #endif diff --git a/drivers/staging/media/as102/as102_usb_drv.c b/drivers/staging/media/as102/as102_usb_drv.c index 97bceeb..9faab5b 100644 --- a/drivers/staging/media/as102/as102_usb_drv.c +++ b/drivers/staging/media/as102/as102_usb_drv.c @@ -74,7 +74,7 @@ static struct usb_class_driver as102_usb_class_driver = { .minor_base = AS102_DEVICE_MAJOR, }; -static int as102_usb_xfer_cmd(struct as102_bus_adapter_t *bus_adap, +static int as102_usb_xfer_cmd(struct as10x_bus_adapter_t *bus_adap, unsigned char *send_buf, int send_buf_len, unsigned char *recv_buf, int recv_buf_len) { @@ -131,7 +131,7 @@ static int as102_usb_xfer_cmd(struct as102_bus_adapter_t *bus_adap, return ret; } -static int as102_send_ep1(struct as102_bus_adapter_t *bus_adap, +static int as102_send_ep1(struct as10x_bus_adapter_t *bus_adap, unsigned char *send_buf, int send_buf_len, int swap32) @@ -154,7 +154,7 @@ static int as102_send_ep1(struct as102_bus_adapter_t *bus_adap, return ret ? ret : actual_len; } -static int as102_read_ep2(struct as102_bus_adapter_t *bus_adap, +static int as102_read_ep2(struct as10x_bus_adapter_t *bus_adap, unsigned char *recv_buf, int recv_buf_len) { int ret = 0, actual_len; diff --git a/drivers/staging/media/as102/as10x_cmd.c b/drivers/staging/media/as102/as10x_cmd.c index 1663a45..0387bb8 100644 --- a/drivers/staging/media/as102/as10x_cmd.c +++ b/drivers/staging/media/as102/as10x_cmd.c @@ -25,35 +25,35 @@ /** * as10x_cmd_turn_on - send turn on command to AS10x - * @phandle: pointer to AS10x handle + * @adap: pointer to AS10x bus adapter * * Return 0 when no error, < 0 in case of error. */ -int as10x_cmd_turn_on(as10x_handle_t *phandle) +int as10x_cmd_turn_on(struct as10x_bus_adapter_t *adap) { int error; struct as10x_cmd_t *pcmd, *prsp; ENTER(); - pcmd = phandle->cmd; - prsp = phandle->rsp; + pcmd = adap->cmd; + prsp = adap->rsp; /* prepare command */ - as10x_cmd_build(pcmd, (++phandle->cmd_xid), + as10x_cmd_build(pcmd, (++adap->cmd_xid), sizeof(pcmd->body.turn_on.req)); /* fill command */ pcmd->body.turn_on.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNON); /* send command */ - if (phandle->ops->xfer_cmd) { - error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd, - sizeof(pcmd->body.turn_on.req) + - HEADER_SIZE, - (uint8_t *) prsp, - sizeof(prsp->body.turn_on.rsp) + - HEADER_SIZE); + if (adap->ops->xfer_cmd) { + error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd, + sizeof(pcmd->body.turn_on.req) + + HEADER_SIZE, + (uint8_t *) prsp, + sizeof(prsp->body.turn_on.rsp) + + HEADER_SIZE); } else { error = AS10X_CMD_ERROR; } @@ -71,31 +71,31 @@ out: /** * as10x_cmd_turn_off - send turn off command to AS10x - * @phandle: pointer to AS10x handle + * @adap: pointer to AS10x bus adapter * * Return 0 on success or negative value in case of error. */ -int as10x_cmd_turn_off(as10x_handle_t *phandle) +int as10x_cmd_turn_off(struct as10x_bus_adapter_t *adap) { int error; struct as10x_cmd_t *pcmd, *prsp; ENTER(); - pcmd = phandle->cmd; - prsp = phandle->rsp; + pcmd = adap->cmd; + prsp = adap->rsp; /* prepare command */ - as10x_cmd_build(pcmd, (++phandle->cmd_xid), + as10x_cmd_build(pcmd, (++adap->cmd_xid), sizeof(pcmd->body.turn_off.req)); /* fill command */ pcmd->body.turn_off.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNOFF); /* send command */ - if (phandle->ops->xfer_cmd) { - error = phandle->ops->xfer_cmd( - phandle, (uint8_t *) pcmd, + if (adap->ops->xfer_cmd) { + error = adap->ops->xfer_cmd( + adap, (uint8_t *) pcmd, sizeof(pcmd->body.turn_off.req) + HEADER_SIZE, (uint8_t *) prsp, sizeof(prsp->body.turn_off.rsp) + HEADER_SIZE); @@ -116,23 +116,24 @@ out: /** * as10x_cmd_set_tune - send set tune command to AS10x - * @phandle: pointer to AS10x handle + * @adap: pointer to AS10x bus adapter * @ptune: tune parameters * * Return 0 on success or negative value in case of error. */ -int as10x_cmd_set_tune(as10x_handle_t *phandle, struct as10x_tune_args *ptune) +int as10x_cmd_set_tune(struct as10x_bus_adapter_t *adap, + struct as10x_tune_args *ptune) { int error; struct as10x_cmd_t *preq, *prsp; ENTER(); - preq = phandle->cmd; - prsp = phandle->rsp; + preq = adap->cmd; + prsp = adap->rsp; /* prepare command */ - as10x_cmd_build(preq, (++phandle->cmd_xid), + as10x_cmd_build(preq, (++adap->cmd_xid), sizeof(preq->body.set_tune.req)); /* fill command */ @@ -150,14 +151,14 @@ int as10x_cmd_set_tune(as10x_handle_t *phandle, struct as10x_tune_args *ptune) ptune->transmission_mode; /* send command */ - if (phandle->ops->xfer_cmd) { - error = phandle->ops->xfer_cmd(phandle, - (uint8_t *) preq, - sizeof(preq->body.set_tune.req) - + HEADER_SIZE, - (uint8_t *) prsp, - sizeof(prsp->body.set_tune.rsp) - + HEADER_SIZE); + if (adap->ops->xfer_cmd) { + error = adap->ops->xfer_cmd(adap, + (uint8_t *) preq, + sizeof(preq->body.set_tune.req) + + HEADER_SIZE, + (uint8_t *) prsp, + sizeof(prsp->body.set_tune.rsp) + + HEADER_SIZE); } else { error = AS10X_CMD_ERROR; } @@ -175,12 +176,12 @@ out: /** * as10x_cmd_get_tune_status - send get tune status command to AS10x - * @phandle: pointer to AS10x handle + * @adap: pointer to AS10x bus adapter * @pstatus: pointer to updated status structure of the current tune * * Return 0 on success or negative value in case of error. */ -int as10x_cmd_get_tune_status(as10x_handle_t *phandle, +int as10x_cmd_get_tune_status(struct as10x_bus_adapter_t *adap, struct as10x_tune_status *pstatus) { int error; @@ -188,11 +189,11 @@ int as10x_cmd_get_tune_status(as10x_handle_t *phandle, ENTER(); - preq = phandle->cmd; - prsp = phandle->rsp; + preq = adap->cmd; + prsp = adap->rsp; /* prepare command */ - as10x_cmd_build(preq, (++phandle->cmd_xid), + as10x_cmd_build(preq, (++adap->cmd_xid), sizeof(preq->body.get_tune_status.req)); /* fill command */ @@ -200,9 +201,9 @@ int as10x_cmd_get_tune_status(as10x_handle_t *phandle, cpu_to_le16(CONTROL_PROC_GETTUNESTAT); /* send command */ - if (phandle->ops->xfer_cmd) { - error = phandle->ops->xfer_cmd( - phandle, + if (adap->ops->xfer_cmd) { + error = adap->ops->xfer_cmd( + adap, (uint8_t *) preq, sizeof(preq->body.get_tune_status.req) + HEADER_SIZE, (uint8_t *) prsp, @@ -233,23 +234,23 @@ out: /** * as10x_cmd_get_tps - send get TPS command to AS10x - * @phandle: pointer to AS10x handle + * @adap: pointer to AS10x handle * @ptps: pointer to TPS parameters structure * * Return 0 on success or negative value in case of error. */ -int as10x_cmd_get_tps(as10x_handle_t *phandle, struct as10x_tps *ptps) +int as10x_cmd_get_tps(struct as10x_bus_adapter_t *adap, struct as10x_tps *ptps) { int error; struct as10x_cmd_t *pcmd, *prsp; ENTER(); - pcmd = phandle->cmd; - prsp = phandle->rsp; + pcmd = adap->cmd; + prsp = adap->rsp; /* prepare command */ - as10x_cmd_build(pcmd, (++phandle->cmd_xid), + as10x_cmd_build(pcmd, (++adap->cmd_xid), sizeof(pcmd->body.get_tps.req)); /* fill command */ @@ -257,14 +258,14 @@ int as10x_cmd_get_tps(as10x_handle_t *phandle, struct as10x_tps *ptps) cpu_to_le16(CONTROL_PROC_GETTPS); /* send command */ - if (phandle->ops->xfer_cmd) { - error = phandle->ops->xfer_cmd(phandle, - (uint8_t *) pcmd, - sizeof(pcmd->body.get_tps.req) + - HEADER_SIZE, - (uint8_t *) prsp, - sizeof(prsp->body.get_tps.rsp) + - HEADER_SIZE); + if (adap->ops->xfer_cmd) { + error = adap->ops->xfer_cmd(adap, + (uint8_t *) pcmd, + sizeof(pcmd->body.get_tps.req) + + HEADER_SIZE, + (uint8_t *) prsp, + sizeof(prsp->body.get_tps.rsp) + + HEADER_SIZE); } else { error = AS10X_CMD_ERROR; } @@ -296,12 +297,12 @@ out: /** * as10x_cmd_get_demod_stats - send get demod stats command to AS10x - * @phandle: pointer to AS10x handle + * @adap: pointer to AS10x bus adapter * @pdemod_stats: pointer to demod stats parameters structure * * Return 0 on success or negative value in case of error. */ -int as10x_cmd_get_demod_stats(as10x_handle_t *phandle, +int as10x_cmd_get_demod_stats(struct as10x_bus_adapter_t *adap, struct as10x_demod_stats *pdemod_stats) { int error; @@ -309,11 +310,11 @@ int as10x_cmd_get_demod_stats(as10x_handle_t *phandle, ENTER(); - pcmd = phandle->cmd; - prsp = phandle->rsp; + pcmd = adap->cmd; + prsp = adap->rsp; /* prepare command */ - as10x_cmd_build(pcmd, (++phandle->cmd_xid), + as10x_cmd_build(pcmd, (++adap->cmd_xid), sizeof(pcmd->body.get_demod_stats.req)); /* fill command */ @@ -321,8 +322,8 @@ int as10x_cmd_get_demod_stats(as10x_handle_t *phandle, cpu_to_le16(CONTROL_PROC_GET_DEMOD_STATS); /* send command */ - if (phandle->ops->xfer_cmd) { - error = phandle->ops->xfer_cmd(phandle, + if (adap->ops->xfer_cmd) { + error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd, sizeof(pcmd->body.get_demod_stats.req) + HEADER_SIZE, @@ -360,13 +361,13 @@ out: /** * as10x_cmd_get_impulse_resp - send get impulse response command to AS10x - * @phandle: pointer to AS10x handle + * @adap: pointer to AS10x bus adapter * @is_ready: pointer to value indicating when impulse * response data is ready * * Return 0 on success or negative value in case of error. */ -int as10x_cmd_get_impulse_resp(as10x_handle_t *phandle, +int as10x_cmd_get_impulse_resp(struct as10x_bus_adapter_t *adap, uint8_t *is_ready) { int error; @@ -374,11 +375,11 @@ int as10x_cmd_get_impulse_resp(as10x_handle_t *phandle, ENTER(); - pcmd = phandle->cmd; - prsp = phandle->rsp; + pcmd = adap->cmd; + prsp = adap->rsp; /* prepare command */ - as10x_cmd_build(pcmd, (++phandle->cmd_xid), + as10x_cmd_build(pcmd, (++adap->cmd_xid), sizeof(pcmd->body.get_impulse_rsp.req)); /* fill command */ @@ -386,8 +387,8 @@ int as10x_cmd_get_impulse_resp(as10x_handle_t *phandle, cpu_to_le16(CONTROL_PROC_GET_IMPULSE_RESP); /* send command */ - if (phandle->ops->xfer_cmd) { - error = phandle->ops->xfer_cmd(phandle, + if (adap->ops->xfer_cmd) { + error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd, sizeof(pcmd->body.get_impulse_rsp.req) + HEADER_SIZE, diff --git a/drivers/staging/media/as102/as10x_cmd.h b/drivers/staging/media/as102/as10x_cmd.h index da31c6d..4ea249e 100644 --- a/drivers/staging/media/as102/as10x_cmd.h +++ b/drivers/staging/media/as102/as10x_cmd.h @@ -489,41 +489,41 @@ void as10x_cmd_build(struct as10x_cmd_t *pcmd, uint16_t proc_id, int as10x_rsp_parse(struct as10x_cmd_t *r, uint16_t proc_id); /* as10x cmd */ -int as10x_cmd_turn_on(as10x_handle_t *phandle); -int as10x_cmd_turn_off(as10x_handle_t *phandle); +int as10x_cmd_turn_on(struct as10x_bus_adapter_t *adap); +int as10x_cmd_turn_off(struct as10x_bus_adapter_t *adap); -int as10x_cmd_set_tune(as10x_handle_t *phandle, +int as10x_cmd_set_tune(struct as10x_bus_adapter_t *adap, struct as10x_tune_args *ptune); -int as10x_cmd_get_tune_status(as10x_handle_t *phandle, +int as10x_cmd_get_tune_status(struct as10x_bus_adapter_t *adap, struct as10x_tune_status *pstatus); -int as10x_cmd_get_tps(as10x_handle_t *phandle, +int as10x_cmd_get_tps(struct as10x_bus_adapter_t *adap, struct as10x_tps *ptps); -int as10x_cmd_get_demod_stats(as10x_handle_t *phandle, +int as10x_cmd_get_demod_stats(struct as10x_bus_adapter_t *adap, struct as10x_demod_stats *pdemod_stats); -int as10x_cmd_get_impulse_resp(as10x_handle_t *phandle, +int as10x_cmd_get_impulse_resp(struct as10x_bus_adapter_t *adap, uint8_t *is_ready); /* as10x cmd stream */ -int as10x_cmd_add_PID_filter(as10x_handle_t *phandle, +int as10x_cmd_add_PID_filter(struct as10x_bus_adapter_t *adap, struct as10x_ts_filter *filter); -int as10x_cmd_del_PID_filter(as10x_handle_t *phandle, +int as10x_cmd_del_PID_filter(struct as10x_bus_adapter_t *adap, uint16_t pid_value); -int as10x_cmd_start_streaming(as10x_handle_t *phandle); -int as10x_cmd_stop_streaming(as10x_handle_t *phandle); +int as10x_cmd_start_streaming(struct as10x_bus_adapter_t *adap); +int as10x_cmd_stop_streaming(struct as10x_bus_adapter_t *adap); /* as10x cmd cfg */ -int as10x_cmd_set_context(as10x_handle_t *phandle, +int as10x_cmd_set_context(struct as10x_bus_adapter_t *adap, uint16_t tag, uint32_t value); -int as10x_cmd_get_context(as10x_handle_t *phandle, +int as10x_cmd_get_context(struct as10x_bus_adapter_t *adap, uint16_t tag, uint32_t *pvalue); -int as10x_cmd_eLNA_change_mode(as10x_handle_t *phandle, uint8_t mode); +int as10x_cmd_eLNA_change_mode(struct as10x_bus_adapter_t *adap, uint8_t mode); int as10x_context_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id); #endif diff --git a/drivers/staging/media/as102/as10x_cmd_cfg.c b/drivers/staging/media/as102/as10x_cmd_cfg.c index ec6f69f..d2a4bce 100644 --- a/drivers/staging/media/as102/as10x_cmd_cfg.c +++ b/drivers/staging/media/as102/as10x_cmd_cfg.c @@ -28,13 +28,13 @@ /** * as10x_cmd_get_context - Send get context command to AS10x - * @phandle: pointer to AS10x handle + * @adap: pointer to AS10x bus adapter * @tag: context tag * @pvalue: pointer where to store context value read * * Return 0 on success or negative value in case of error. */ -int as10x_cmd_get_context(as10x_handle_t *phandle, uint16_t tag, +int as10x_cmd_get_context(struct as10x_bus_adapter_t *adap, uint16_t tag, uint32_t *pvalue) { int error; @@ -42,11 +42,11 @@ int as10x_cmd_get_context(as10x_handle_t *phandle, uint16_t tag, ENTER(); - pcmd = phandle->cmd; - prsp = phandle->rsp; + pcmd = adap->cmd; + prsp = adap->rsp; /* prepare command */ - as10x_cmd_build(pcmd, (++phandle->cmd_xid), + as10x_cmd_build(pcmd, (++adap->cmd_xid), sizeof(pcmd->body.context.req)); /* fill command */ @@ -55,14 +55,14 @@ int as10x_cmd_get_context(as10x_handle_t *phandle, uint16_t tag, pcmd->body.context.req.type = cpu_to_le16(GET_CONTEXT_DATA); /* send command */ - if (phandle->ops->xfer_cmd) { - error = phandle->ops->xfer_cmd(phandle, - (uint8_t *) pcmd, - sizeof(pcmd->body.context.req) - + HEADER_SIZE, - (uint8_t *) prsp, - sizeof(prsp->body.context.rsp) - + HEADER_SIZE); + if (adap->ops->xfer_cmd) { + error = adap->ops->xfer_cmd(adap, + (uint8_t *) pcmd, + sizeof(pcmd->body.context.req) + + HEADER_SIZE, + (uint8_t *) prsp, + sizeof(prsp->body.context.rsp) + + HEADER_SIZE); } else { error = AS10X_CMD_ERROR; } @@ -87,13 +87,13 @@ out: /** * as10x_cmd_set_context - send set context command to AS10x - * @phandle: pointer to AS10x handle + * @adap: pointer to AS10x bus adapter * @tag: context tag * @value: value to set in context * * Return 0 on success or negative value in case of error. */ -int as10x_cmd_set_context(as10x_handle_t *phandle, uint16_t tag, +int as10x_cmd_set_context(struct as10x_bus_adapter_t *adap, uint16_t tag, uint32_t value) { int error; @@ -101,11 +101,11 @@ int as10x_cmd_set_context(as10x_handle_t *phandle, uint16_t tag, ENTER(); - pcmd = phandle->cmd; - prsp = phandle->rsp; + pcmd = adap->cmd; + prsp = adap->rsp; /* prepare command */ - as10x_cmd_build(pcmd, (++phandle->cmd_xid), + as10x_cmd_build(pcmd, (++adap->cmd_xid), sizeof(pcmd->body.context.req)); /* fill command */ @@ -116,14 +116,14 @@ int as10x_cmd_set_context(as10x_handle_t *phandle, uint16_t tag, pcmd->body.context.req.type = cpu_to_le16(SET_CONTEXT_DATA); /* send command */ - if (phandle->ops->xfer_cmd) { - error = phandle->ops->xfer_cmd(phandle, - (uint8_t *) pcmd, - sizeof(pcmd->body.context.req) - + HEADER_SIZE, - (uint8_t *) prsp, - sizeof(prsp->body.context.rsp) - + HEADER_SIZE); + if (adap->ops->xfer_cmd) { + error = adap->ops->xfer_cmd(adap, + (uint8_t *) pcmd, + sizeof(pcmd->body.context.req) + + HEADER_SIZE, + (uint8_t *) prsp, + sizeof(prsp->body.context.rsp) + + HEADER_SIZE); } else { error = AS10X_CMD_ERROR; } @@ -142,7 +142,7 @@ out: /** * as10x_cmd_eLNA_change_mode - send eLNA change mode command to AS10x - * @phandle: pointer to AS10x handle + * @adap: pointer to AS10x bus adapter * @mode: mode selected: * - ON : 0x0 => eLNA always ON * - OFF : 0x1 => eLNA always OFF @@ -151,18 +151,18 @@ out: * * Return 0 on success or negative value in case of error. */ -int as10x_cmd_eLNA_change_mode(as10x_handle_t *phandle, uint8_t mode) +int as10x_cmd_eLNA_change_mode(struct as10x_bus_adapter_t *adap, uint8_t mode) { int error; struct as10x_cmd_t *pcmd, *prsp; ENTER(); - pcmd = phandle->cmd; - prsp = phandle->rsp; + pcmd = adap->cmd; + prsp = adap->rsp; /* prepare command */ - as10x_cmd_build(pcmd, (++phandle->cmd_xid), + as10x_cmd_build(pcmd, (++adap->cmd_xid), sizeof(pcmd->body.cfg_change_mode.req)); /* fill command */ @@ -171,8 +171,8 @@ int as10x_cmd_eLNA_change_mode(as10x_handle_t *phandle, uint8_t mode) pcmd->body.cfg_change_mode.req.mode = mode; /* send command */ - if (phandle->ops->xfer_cmd) { - error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd, + if (adap->ops->xfer_cmd) { + error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd, sizeof(pcmd->body.cfg_change_mode.req) + HEADER_SIZE, (uint8_t *) prsp, sizeof(prsp->body.cfg_change_mode.rsp) diff --git a/drivers/staging/media/as102/as10x_cmd_stream.c b/drivers/staging/media/as102/as10x_cmd_stream.c index 045c706..6d000f6 100644 --- a/drivers/staging/media/as102/as10x_cmd_stream.c +++ b/drivers/staging/media/as102/as10x_cmd_stream.c @@ -23,12 +23,12 @@ /** * as10x_cmd_add_PID_filter - send add filter command to AS10x - * @phandle: pointer to AS10x handle + * @adap: pointer to AS10x bus adapter * @filter: TSFilter filter for DVB-T * * Return 0 on success or negative value in case of error. */ -int as10x_cmd_add_PID_filter(as10x_handle_t *phandle, +int as10x_cmd_add_PID_filter(struct as10x_bus_adapter_t *adap, struct as10x_ts_filter *filter) { int error; @@ -36,11 +36,11 @@ int as10x_cmd_add_PID_filter(as10x_handle_t *phandle, ENTER(); - pcmd = phandle->cmd; - prsp = phandle->rsp; + pcmd = adap->cmd; + prsp = adap->rsp; /* prepare command */ - as10x_cmd_build(pcmd, (++phandle->cmd_xid), + as10x_cmd_build(pcmd, (++adap->cmd_xid), sizeof(pcmd->body.add_pid_filter.req)); /* fill command */ @@ -55,8 +55,8 @@ int as10x_cmd_add_PID_filter(as10x_handle_t *phandle, pcmd->body.add_pid_filter.req.idx = 0xFF; /* send command */ - if (phandle->ops->xfer_cmd) { - error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd, + if (adap->ops->xfer_cmd) { + error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd, sizeof(pcmd->body.add_pid_filter.req) + HEADER_SIZE, (uint8_t *) prsp, sizeof(prsp->body.add_pid_filter.rsp) @@ -83,12 +83,12 @@ out: /** * as10x_cmd_del_PID_filter - Send delete filter command to AS10x - * @phandle: pointer to AS10x handle + * @adap: pointer to AS10x bus adapte * @pid_value: PID to delete * * Return 0 on success or negative value in case of error. */ -int as10x_cmd_del_PID_filter(as10x_handle_t *phandle, +int as10x_cmd_del_PID_filter(struct as10x_bus_adapter_t *adap, uint16_t pid_value) { int error; @@ -96,11 +96,11 @@ int as10x_cmd_del_PID_filter(as10x_handle_t *phandle, ENTER(); - pcmd = phandle->cmd; - prsp = phandle->rsp; + pcmd = adap->cmd; + prsp = adap->rsp; /* prepare command */ - as10x_cmd_build(pcmd, (++phandle->cmd_xid), + as10x_cmd_build(pcmd, (++adap->cmd_xid), sizeof(pcmd->body.del_pid_filter.req)); /* fill command */ @@ -109,8 +109,8 @@ int as10x_cmd_del_PID_filter(as10x_handle_t *phandle, pcmd->body.del_pid_filter.req.pid = cpu_to_le16(pid_value); /* send command */ - if (phandle->ops->xfer_cmd) { - error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd, + if (adap->ops->xfer_cmd) { + error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd, sizeof(pcmd->body.del_pid_filter.req) + HEADER_SIZE, (uint8_t *) prsp, sizeof(prsp->body.del_pid_filter.rsp) @@ -132,22 +132,22 @@ out: /** * as10x_cmd_start_streaming - Send start streaming command to AS10x - * @phandle: pointer to AS10x handle + * @adap: pointer to AS10x bus adapter * * Return 0 on success or negative value in case of error. */ -int as10x_cmd_start_streaming(as10x_handle_t *phandle) +int as10x_cmd_start_streaming(struct as10x_bus_adapter_t *adap) { int error; struct as10x_cmd_t *pcmd, *prsp; ENTER(); - pcmd = phandle->cmd; - prsp = phandle->rsp; + pcmd = adap->cmd; + prsp = adap->rsp; /* prepare command */ - as10x_cmd_build(pcmd, (++phandle->cmd_xid), + as10x_cmd_build(pcmd, (++adap->cmd_xid), sizeof(pcmd->body.start_streaming.req)); /* fill command */ @@ -155,8 +155,8 @@ int as10x_cmd_start_streaming(as10x_handle_t *phandle) cpu_to_le16(CONTROL_PROC_START_STREAMING); /* send command */ - if (phandle->ops->xfer_cmd) { - error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd, + if (adap->ops->xfer_cmd) { + error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd, sizeof(pcmd->body.start_streaming.req) + HEADER_SIZE, (uint8_t *) prsp, sizeof(prsp->body.start_streaming.rsp) @@ -178,22 +178,22 @@ out: /** * as10x_cmd_stop_streaming - Send stop streaming command to AS10x - * @phandle: pointer to AS10x handle + * @adap: pointer to AS10x bus adapter * * Return 0 on success or negative value in case of error. */ -int as10x_cmd_stop_streaming(as10x_handle_t *phandle) +int as10x_cmd_stop_streaming(struct as10x_bus_adapter_t *adap) { int8_t error; struct as10x_cmd_t *pcmd, *prsp; ENTER(); - pcmd = phandle->cmd; - prsp = phandle->rsp; + pcmd = adap->cmd; + prsp = adap->rsp; /* prepare command */ - as10x_cmd_build(pcmd, (++phandle->cmd_xid), + as10x_cmd_build(pcmd, (++adap->cmd_xid), sizeof(pcmd->body.stop_streaming.req)); /* fill command */ @@ -201,8 +201,8 @@ int as10x_cmd_stop_streaming(as10x_handle_t *phandle) cpu_to_le16(CONTROL_PROC_STOP_STREAMING); /* send command */ - if (phandle->ops->xfer_cmd) { - error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd, + if (adap->ops->xfer_cmd) { + error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd, sizeof(pcmd->body.stop_streaming.req) + HEADER_SIZE, (uint8_t *) prsp, sizeof(prsp->body.stop_streaming.rsp) diff --git a/drivers/staging/media/as102/as10x_handle.h b/drivers/staging/media/as102/as10x_handle.h index d67203a..62b9795 100644 --- a/drivers/staging/media/as102/as10x_handle.h +++ b/drivers/staging/media/as102/as10x_handle.h @@ -17,10 +17,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef __KERNEL__ -struct as102_bus_adapter_t; +struct as10x_bus_adapter_t; struct as102_dev_t; -#define as10x_handle_t struct as102_bus_adapter_t #include "as10x_cmd.h" /* values for "mode" field */ @@ -29,29 +28,26 @@ struct as102_dev_t; #define REGMODE32 32 struct as102_priv_ops_t { - int (*upload_fw_pkt) (struct as102_bus_adapter_t *bus_adap, + int (*upload_fw_pkt) (struct as10x_bus_adapter_t *bus_adap, unsigned char *buf, int buflen, int swap32); - int (*send_cmd) (struct as102_bus_adapter_t *bus_adap, + int (*send_cmd) (struct as10x_bus_adapter_t *bus_adap, unsigned char *buf, int buflen); - int (*xfer_cmd) (struct as102_bus_adapter_t *bus_adap, + int (*xfer_cmd) (struct as10x_bus_adapter_t *bus_adap, unsigned char *send_buf, int send_buf_len, unsigned char *recv_buf, int recv_buf_len); -/* - int (*pid_filter) (struct as102_bus_adapter_t *bus_adap, - int index, u16 pid, int onoff); -*/ + int (*start_stream) (struct as102_dev_t *dev); void (*stop_stream) (struct as102_dev_t *dev); - int (*reset_target) (struct as102_bus_adapter_t *bus_adap); + int (*reset_target) (struct as10x_bus_adapter_t *bus_adap); - int (*read_write)(struct as102_bus_adapter_t *bus_adap, uint8_t mode, + int (*read_write)(struct as10x_bus_adapter_t *bus_adap, uint8_t mode, uint32_t rd_addr, uint16_t rd_len, uint32_t wr_addr, uint16_t wr_len); - int (*as102_read_ep2) (struct as102_bus_adapter_t *bus_adap, + int (*as102_read_ep2) (struct as10x_bus_adapter_t *bus_adap, unsigned char *recv_buf, int recv_buf_len); }; -- cgit v0.10.2 From fdb5a9111ef77d537efb86e90e8073ebfd0b553e Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 6 Nov 2011 18:30:26 -0300 Subject: [media] Support for Sveon STV22 (IT9137) This indeed a clone of Kworld UB499 2T Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 2d08c9b..0040aa2 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -322,6 +322,7 @@ #define USB_PID_TVWAY_PLUS 0x0002 #define USB_PID_SVEON_STV20 0xe39d #define USB_PID_SVEON_STV22 0xe401 +#define USB_PID_SVEON_STV22_IT9137 0xe411 #define USB_PID_AZUREWAVE_AZ6027 0x3275 #define USB_PID_TERRATEC_DVBS2CI_V1 0x10a4 #define USB_PID_TERRATEC_DVBS2CI_V2 0x10ac diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c index 9f58241..9abdaee 100644 --- a/drivers/media/dvb/dvb-usb/it913x.c +++ b/drivers/media/dvb/dvb-usb/it913x.c @@ -577,6 +577,7 @@ static int it913x_probe(struct usb_interface *intf, static struct usb_device_id it913x_table[] = { { USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09) }, { USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135) }, + { USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22_IT9137) }, {} /* Terminating entry */ }; @@ -652,7 +653,7 @@ static struct dvb_usb_device_properties it913x_properties = { .rc_codes = RC_MAP_KWORLD_315U, }, .i2c_algo = &it913x_i2c_algo, - .num_device_descs = 2, + .num_device_descs = 3, .devices = { { "Kworld UB499-2T T09(IT9137)", { &it913x_table[0], NULL }, @@ -660,6 +661,9 @@ static struct dvb_usb_device_properties it913x_properties = { { "ITE 9135 Generic", { &it913x_table[1], NULL }, }, + { "Sveon STV22 Dual DVB-T HDTV(IT9137)", + { &it913x_table[2], NULL }, + }, } }; -- cgit v0.10.2 From 819cd82b0a994d9d83dc1d1ced1088e71d702d4c Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 7 Nov 2011 05:24:49 -0300 Subject: [media] usbvision: Drop broken 10-bit I2C address support The support for 10-bit I2C addresses in usbvision seems plain broken to me. I had already noticed that back in February 2007 [1]. The code was not fixed since then, so I take it that it's not actually needed. And as a matter of fact I don't know of any 10-bit addressed I2C tuner, encode, decoder or the like. So let's simply get rid of the broken and useless code. I'm also adding I2C_FUNC_I2C, as the driver and hardware support plain I2C messaging. [1] http://marc.info/?l=linux-i2c&m=117499415208244&w=2 Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index d7f9751..89fec02 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c @@ -110,42 +110,20 @@ static inline int usb_find_address(struct i2c_adapter *i2c_adap, unsigned char addr; int ret; - if ((flags & I2C_M_TEN)) { - /* a ten bit address */ - addr = 0xf0 | ((msg->addr >> 7) & 0x03); - /* try extended address code... */ - ret = try_write_address(i2c_adap, addr, retries); - if (ret != 1) { - dev_err(&i2c_adap->dev, - "died at extended address code, while writing\n"); - return -EREMOTEIO; - } - add[0] = addr; - if (flags & I2C_M_RD) { - /* okay, now switch into reading mode */ - addr |= 0x01; - ret = try_read_address(i2c_adap, addr, retries); - if (ret != 1) { - dev_err(&i2c_adap->dev, - "died at extended address code, while reading\n"); - return -EREMOTEIO; - } - } - } else { /* normal 7bit address */ - addr = (msg->addr << 1); - if (flags & I2C_M_RD) - addr |= 1; + addr = (msg->addr << 1); + if (flags & I2C_M_RD) + addr |= 1; - add[0] = addr; - if (flags & I2C_M_RD) - ret = try_read_address(i2c_adap, addr, retries); - else - ret = try_write_address(i2c_adap, addr, retries); + add[0] = addr; + if (flags & I2C_M_RD) + ret = try_read_address(i2c_adap, addr, retries); + else + ret = try_write_address(i2c_adap, addr, retries); + + if (ret != 1) + return -EREMOTEIO; - if (ret != 1) - return -EREMOTEIO; - } return 0; } @@ -184,7 +162,7 @@ usbvision_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) static u32 functionality(struct i2c_adapter *adap) { - return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } /* -----exported algorithm data: ------------------------------------- */ -- cgit v0.10.2 From 044ab15353dffd977770df3cb3c286240642a3f7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 30 Sep 2011 05:05:35 -0300 Subject: [media] V4L menu: move USB drivers section to the top USB webcams are some of the most used V4L devices, so move it to a more prominent place in the menu instead of being at the end. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index d960656..cf16dbc 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -580,6 +580,79 @@ config VIDEO_M52790 endmenu # encoder / decoder chips +# +# USB Multimedia device configuration +# + +menuconfig V4L_USB_DRIVERS + bool "V4L USB devices" + depends on USB + default y + +if V4L_USB_DRIVERS && USB + +source "drivers/media/video/uvc/Kconfig" + +source "drivers/media/video/gspca/Kconfig" + +source "drivers/media/video/pvrusb2/Kconfig" + +source "drivers/media/video/hdpvr/Kconfig" + +source "drivers/media/video/em28xx/Kconfig" + +source "drivers/media/video/tlg2300/Kconfig" + +source "drivers/media/video/cx231xx/Kconfig" + +source "drivers/media/video/tm6000/Kconfig" + +source "drivers/media/video/usbvision/Kconfig" + +source "drivers/media/video/et61x251/Kconfig" + +source "drivers/media/video/sn9c102/Kconfig" + +source "drivers/media/video/pwc/Kconfig" + +config USB_ZR364XX + tristate "USB ZR364XX Camera support" + depends on VIDEO_V4L2 + select VIDEOBUF_GEN + select VIDEOBUF_VMALLOC + ---help--- + Say Y here if you want to connect this type of camera to your + computer's USB port. + See for more info + and list of supported cameras. + + To compile this driver as a module, choose M here: the + module will be called zr364xx. + +config USB_STKWEBCAM + tristate "USB Syntek DC1125 Camera support" + depends on VIDEO_V4L2 && EXPERIMENTAL + ---help--- + Say Y here if you want to use this type of camera. + Supported devices are typically found in some Asus laptops, + with USB id 174f:a311 and 05e1:0501. Other Syntek cameras + may be supported by the stk11xx driver, from which this is + derived, see + + To compile this driver as a module, choose M here: the + module will be called stkwebcam. + +config USB_S2255 + tristate "USB Sensoray 2255 video capture device" + depends on VIDEO_V4L2 + select VIDEOBUF_VMALLOC + default n + help + Say Y here if you want support for the Sensoray 2255 USB device. + This driver can be compiled as a module, called s2255drv. + +endif # V4L_USB_DRIVERS + config VIDEO_SH_VOU tristate "SuperH VOU video output driver" depends on VIDEO_DEV && ARCH_SHMOBILE @@ -1002,78 +1075,6 @@ config VIDEO_S5P_MIPI_CSIS source "drivers/media/video/s5p-tv/Kconfig" -# -# USB Multimedia device configuration -# - -menuconfig V4L_USB_DRIVERS - bool "V4L USB devices" - depends on USB - default y - -if V4L_USB_DRIVERS && USB - -source "drivers/media/video/uvc/Kconfig" - -source "drivers/media/video/gspca/Kconfig" - -source "drivers/media/video/pvrusb2/Kconfig" - -source "drivers/media/video/hdpvr/Kconfig" - -source "drivers/media/video/em28xx/Kconfig" - -source "drivers/media/video/tlg2300/Kconfig" - -source "drivers/media/video/cx231xx/Kconfig" - -source "drivers/media/video/tm6000/Kconfig" - -source "drivers/media/video/usbvision/Kconfig" - -source "drivers/media/video/et61x251/Kconfig" - -source "drivers/media/video/sn9c102/Kconfig" - -source "drivers/media/video/pwc/Kconfig" - -config USB_ZR364XX - tristate "USB ZR364XX Camera support" - depends on VIDEO_V4L2 - select VIDEOBUF_GEN - select VIDEOBUF_VMALLOC - ---help--- - Say Y here if you want to connect this type of camera to your - computer's USB port. - See for more info - and list of supported cameras. - - To compile this driver as a module, choose M here: the - module will be called zr364xx. - -config USB_STKWEBCAM - tristate "USB Syntek DC1125 Camera support" - depends on VIDEO_V4L2 && EXPERIMENTAL - ---help--- - Say Y here if you want to use this type of camera. - Supported devices are typically found in some Asus laptops, - with USB id 174f:a311 and 05e1:0501. Other Syntek cameras - may be supported by the stk11xx driver, from which this is - derived, see - - To compile this driver as a module, choose M here: the - module will be called stkwebcam. - -config USB_S2255 - tristate "USB Sensoray 2255 video capture device" - depends on VIDEO_V4L2 - select VIDEOBUF_VMALLOC - default n - help - Say Y here if you want support for the Sensoray 2255 USB device. - This driver can be compiled as a module, called s2255drv. - -endif # V4L_USB_DRIVERS endif # VIDEO_CAPTURE_DRIVERS menuconfig V4L_MEM2MEM_DRIVERS -- cgit v0.10.2 From a3c581be78cbd8ab9106935cb760facc29e9ea2b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 30 Sep 2011 09:03:06 -0300 Subject: [media] V4L menu: move ISA and parport drivers into their own submenu Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index cf16dbc..256ff4a 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -692,49 +692,6 @@ source "drivers/media/video/omap/Kconfig" source "drivers/media/video/bt8xx/Kconfig" -config VIDEO_PMS - tristate "Mediavision Pro Movie Studio Video For Linux" - depends on ISA && VIDEO_V4L2 - help - Say Y if you have such a thing. - - To compile this driver as a module, choose M here: the - module will be called pms. - -config VIDEO_BWQCAM - tristate "Quickcam BW Video For Linux" - depends on PARPORT && VIDEO_V4L2 - help - Say Y have if you the black and white version of the QuickCam - camera. See the next option for the color version. - - To compile this driver as a module, choose M here: the - module will be called bw-qcam. - -config VIDEO_CQCAM - tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)" - depends on EXPERIMENTAL && PARPORT && VIDEO_V4L2 - help - This is the video4linux driver for the colour version of the - Connectix QuickCam. If you have one of these cameras, say Y here, - otherwise say N. This driver does not work with the original - monochrome QuickCam, QuickCam VC or QuickClip. It is also available - as a module (c-qcam). - Read for more information. - -config VIDEO_W9966 - tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux" - depends on PARPORT_1284 && PARPORT && VIDEO_V4L2 - help - Video4linux driver for Winbond's w9966 based Webcams. - Currently tested with the LifeView FlyCam Supra. - If you have one of these cameras, say Y here - otherwise say N. - This driver is also available as a module (w9966). - - Check out for more - information. - source "drivers/media/video/cpia2/Kconfig" config VIDEO_VINO @@ -826,6 +783,65 @@ source "drivers/media/video/cx18/Kconfig" source "drivers/media/video/saa7164/Kconfig" +# +# ISA & parallel port drivers configuration +# + +menuconfig V4L_ISA_PARPORT_DRIVERS + bool "V4L ISA and parallel port devices" + depends on ISA || PARPORT + default n + ---help--- + Say Y here to enable support for these ISA and parallel port drivers. + +if V4L_ISA_PARPORT_DRIVERS + +config VIDEO_BWQCAM + tristate "Quickcam BW Video For Linux" + depends on PARPORT && VIDEO_V4L2 + help + Say Y have if you the black and white version of the QuickCam + camera. See the next option for the color version. + + To compile this driver as a module, choose M here: the + module will be called bw-qcam. + +config VIDEO_CQCAM + tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)" + depends on EXPERIMENTAL && PARPORT && VIDEO_V4L2 + help + This is the video4linux driver for the colour version of the + Connectix QuickCam. If you have one of these cameras, say Y here, + otherwise say N. This driver does not work with the original + monochrome QuickCam, QuickCam VC or QuickClip. It is also available + as a module (c-qcam). + Read for more information. + +config VIDEO_PMS + tristate "Mediavision Pro Movie Studio Video For Linux" + depends on ISA && VIDEO_V4L2 + help + Say Y if you have the ISA Mediavision Pro Movie Studio + capture card. + + To compile this driver as a module, choose M here: the + module will be called pms. + +config VIDEO_W9966 + tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux" + depends on PARPORT_1284 && PARPORT && VIDEO_V4L2 + help + Video4linux driver for Winbond's w9966 based Webcams. + Currently tested with the LifeView FlyCam Supra. + If you have one of these cameras, say Y here + otherwise say N. + This driver is also available as a module (w9966). + + Check out for more + information. + +endif # V4L_ISA_PARPORT_DRIVERS + source "drivers/media/video/marvell-ccic/Kconfig" config VIDEO_M32R_AR -- cgit v0.10.2 From 053fed7ef91206b371afbd8cb3e8cd1f27ca8bd3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 30 Sep 2011 09:03:57 -0300 Subject: [media] V4L menu: remove the EXPERIMENTAL tag from vino and c-qcam These are really, really old drivers. These are really no longer experimental... Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 256ff4a..988823b 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -695,8 +695,8 @@ source "drivers/media/video/bt8xx/Kconfig" source "drivers/media/video/cpia2/Kconfig" config VIDEO_VINO - tristate "SGI Vino Video For Linux (EXPERIMENTAL)" - depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2 + tristate "SGI Vino Video For Linux" + depends on I2C && SGI_IP22 && VIDEO_V4L2 select VIDEO_SAA7191 if VIDEO_HELPER_CHIPS_AUTO help Say Y here to build in support for the Vino video input system found @@ -807,8 +807,8 @@ config VIDEO_BWQCAM module will be called bw-qcam. config VIDEO_CQCAM - tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)" - depends on EXPERIMENTAL && PARPORT && VIDEO_V4L2 + tristate "QuickCam Colour Video For Linux" + depends on PARPORT && VIDEO_V4L2 help This is the video4linux driver for the colour version of the Connectix QuickCam. If you have one of these cameras, say Y here, -- cgit v0.10.2 From 9fa0b852e1e3c0f6abbff4e34896aabc6a555df8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 30 Sep 2011 09:06:11 -0300 Subject: [media] V4L menu: move all platform drivers to the bottom of the menu Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 988823b..717a881 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -653,25 +653,6 @@ config USB_S2255 endif # V4L_USB_DRIVERS -config VIDEO_SH_VOU - tristate "SuperH VOU video output driver" - depends on VIDEO_DEV && ARCH_SHMOBILE - select VIDEOBUF_DMA_CONTIG - help - Support for the Video Output Unit (VOU) on SuperH SoCs. - -config VIDEO_VIU - tristate "Freescale VIU Video Driver" - depends on VIDEO_V4L2 && PPC_MPC512x - select VIDEOBUF_DMA_CONTIG - default y - ---help--- - Support for Freescale VIU video driver. This device captures - video data, or overlays video on DIU frame buffer. - - Say Y here if you want to enable VIU device on MPC5121e Rev2+. - In doubt, say N. - config VIDEO_VIVI tristate "Virtual Video Driver" depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 @@ -686,22 +667,10 @@ config VIDEO_VIVI Say Y here if you want to test video apps or debug V4L devices. In doubt, say N. -source "drivers/media/video/davinci/Kconfig" - -source "drivers/media/video/omap/Kconfig" - source "drivers/media/video/bt8xx/Kconfig" source "drivers/media/video/cpia2/Kconfig" -config VIDEO_VINO - tristate "SGI Vino Video For Linux" - depends on I2C && SGI_IP22 && VIDEO_V4L2 - select VIDEO_SAA7191 if VIDEO_HELPER_CHIPS_AUTO - help - Say Y here to build in support for the Vino video input system found - on SGI Indy machines. - source "drivers/media/video/zoran/Kconfig" config VIDEO_MEYE @@ -759,16 +728,6 @@ config VIDEO_HEXIUM_GEMINI To compile this driver as a module, choose M here: the module will be called hexium_gemini. -config VIDEO_TIMBERDALE - tristate "Support for timberdale Video In/LogiWIN" - depends on VIDEO_V4L2 && I2C && DMADEVICES - select DMA_ENGINE - select TIMB_DMA - select VIDEO_ADV7180 - select VIDEOBUF_DMA_CONTIG - ---help--- - Add support for the Video In peripherial of the timberdale FPGA. - source "drivers/media/video/cx88/Kconfig" source "drivers/media/video/cx23885/Kconfig" @@ -844,6 +803,61 @@ endif # V4L_ISA_PARPORT_DRIVERS source "drivers/media/video/marvell-ccic/Kconfig" +config VIDEO_VIA_CAMERA + tristate "VIAFB camera controller support" + depends on FB_VIA + select VIDEOBUF_DMA_SG + select VIDEO_OV7670 + help + Driver support for the integrated camera controller in VIA + Chrome9 chipsets. Currently only tested on OLPC xo-1.5 systems + with ov7670 sensors. + +# +# Platform multimedia device configuration +# + +source "drivers/media/video/davinci/Kconfig" + +source "drivers/media/video/omap/Kconfig" + +config VIDEO_SH_VOU + tristate "SuperH VOU video output driver" + depends on VIDEO_DEV && ARCH_SHMOBILE + select VIDEOBUF_DMA_CONTIG + help + Support for the Video Output Unit (VOU) on SuperH SoCs. + +config VIDEO_VIU + tristate "Freescale VIU Video Driver" + depends on VIDEO_V4L2 && PPC_MPC512x + select VIDEOBUF_DMA_CONTIG + default y + ---help--- + Support for Freescale VIU video driver. This device captures + video data, or overlays video on DIU frame buffer. + + Say Y here if you want to enable VIU device on MPC5121e Rev2+. + In doubt, say N. + +config VIDEO_TIMBERDALE + tristate "Support for timberdale Video In/LogiWIN" + depends on VIDEO_V4L2 && I2C && DMADEVICES + select DMA_ENGINE + select TIMB_DMA + select VIDEO_ADV7180 + select VIDEOBUF_DMA_CONTIG + ---help--- + Add support for the Video In peripherial of the timberdale FPGA. + +config VIDEO_VINO + tristate "SGI Vino Video For Linux" + depends on I2C && SGI_IP22 && VIDEO_V4L2 + select VIDEO_SAA7191 if VIDEO_HELPER_CHIPS_AUTO + help + Say Y here to build in support for the Vino video input system found + on SGI Indy machines. + config VIDEO_M32R_AR tristate "AR devices" depends on M32R && VIDEO_V4L2 @@ -863,16 +877,6 @@ config VIDEO_M32R_AR_M64278 To compile this driver as a module, choose M here: the module will be called arv. -config VIDEO_VIA_CAMERA - tristate "VIAFB camera controller support" - depends on FB_VIA - select VIDEOBUF_DMA_SG - select VIDEO_OV7670 - help - Driver support for the integrated camera controller in VIA - Chrome9 chipsets. Currently only tested on OLPC xo-1.5 systems - with ov7670 sensors. - config VIDEO_OMAP3 tristate "OMAP 3 Camera support (EXPERIMENTAL)" depends on OMAP_IOVMM && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL -- cgit v0.10.2 From 6e66135cab8ed4ff5c1ee0dd63ff7e44e33f355f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 30 Sep 2011 05:16:48 -0300 Subject: [media] V4L menu: remove duplicate USB dependency Thanks to Guennadi Liakhovetski for pointing this out to me. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 717a881..b14f5fe 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -589,7 +589,7 @@ menuconfig V4L_USB_DRIVERS depends on USB default y -if V4L_USB_DRIVERS && USB +if V4L_USB_DRIVERS source "drivers/media/video/uvc/Kconfig" -- cgit v0.10.2 From e21d98651ae42dc7c50e539296e88a73c1e78fd8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 30 Sep 2011 05:31:24 -0300 Subject: [media] V4L menu: reorganize the radio menu Move all USB radio devices to the top of the list and move all ISA devices to a separate menu. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 52798a1..e954781 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -11,6 +11,162 @@ menuconfig RADIO_ADAPTERS if RADIO_ADAPTERS && VIDEO_V4L2 +config RADIO_SI470X + bool "Silicon Labs Si470x FM Radio Receiver support" + depends on VIDEO_V4L2 + +source "drivers/media/radio/si470x/Kconfig" + +config USB_MR800 + tristate "AverMedia MR 800 USB FM radio support" + depends on USB && VIDEO_V4L2 + ---help--- + Say Y here if you want to connect this type of radio to your + computer's USB port. Note that the audio is not digital, and + you must connect the line out connector to a sound card or a + set of speakers. + + To compile this driver as a module, choose M here: the + module will be called radio-mr800. + +config USB_DSBR + tristate "D-Link/GemTek USB FM radio support" + depends on USB && VIDEO_V4L2 + ---help--- + Say Y here if you want to connect this type of radio to your + computer's USB port. Note that the audio is not digital, and + you must connect the line out connector to a sound card or a + set of speakers. + + To compile this driver as a module, choose M here: the + module will be called dsbr100. + +config RADIO_MAXIRADIO + tristate "Guillemot MAXI Radio FM 2000 radio" + depends on VIDEO_V4L2 && PCI + ---help--- + Choose Y here if you have this radio card. This card may also be + found as Gemtek PCI FM. + + In order to control your radio card, you will need to use programs + that are compatible with the Video For Linux API. Information on + this API and pointers to "v4l" programs may be found at + . + + To compile this driver as a module, choose M here: the + module will be called radio-maxiradio. + + +config I2C_SI4713 + tristate "I2C driver for Silicon Labs Si4713 device" + depends on I2C && VIDEO_V4L2 + ---help--- + Say Y here if you want support to Si4713 I2C device. + This device driver supports only i2c bus. + + To compile this driver as a module, choose M here: the + module will be called si4713. + +config RADIO_SI4713 + tristate "Silicon Labs Si4713 FM Radio Transmitter support" + depends on I2C && VIDEO_V4L2 + select I2C_SI4713 + ---help--- + Say Y here if you want support to Si4713 FM Radio Transmitter. + This device can transmit audio through FM. It can transmit + RDS and RBDS signals as well. This module is the v4l2 radio + interface for the i2c driver of this device. + + To compile this driver as a module, choose M here: the + module will be called radio-si4713. + +config RADIO_TEA5764 + tristate "TEA5764 I2C FM radio support" + depends on I2C && VIDEO_V4L2 + ---help--- + Say Y here if you want to use the TEA5764 FM chip found in + EZX phones. This FM chip is present in EZX phones from Motorola, + connected to internal pxa I2C bus. + + To compile this driver as a module, choose M here: the + module will be called radio-tea5764. + +config RADIO_TEA5764_XTAL + bool "TEA5764 crystal reference" + depends on RADIO_TEA5764=y + default y + help + Say Y here if TEA5764 have a 32768 Hz crystal in circuit, say N + here if TEA5764 reference frequency is connected in FREQIN. + +config RADIO_SAA7706H + tristate "SAA7706H Car Radio DSP" + depends on I2C && VIDEO_V4L2 + ---help--- + Say Y here if you want to use the SAA7706H Car radio Digital + Signal Processor, found for instance on the Russellville development + board. On the russellville the device is connected to internal + timberdale I2C bus. + + To compile this driver as a module, choose M here: the + module will be called SAA7706H. + +config RADIO_TEF6862 + tristate "TEF6862 Car Radio Enhanced Selectivity Tuner" + depends on I2C && VIDEO_V4L2 + ---help--- + Say Y here if you want to use the TEF6862 Car Radio Enhanced + Selectivity Tuner, found for instance on the Russellville development + board. On the russellville the device is connected to internal + timberdale I2C bus. + + To compile this driver as a module, choose M here: the + module will be called TEF6862. + +config RADIO_TIMBERDALE + tristate "Enable the Timberdale radio driver" + depends on MFD_TIMBERDALE && VIDEO_V4L2 + depends on I2C # for RADIO_SAA7706H + select RADIO_TEF6862 + select RADIO_SAA7706H + ---help--- + This is a kind of umbrella driver for the Radio Tuner and DSP + found behind the Timberdale FPGA on the Russellville board. + Enabling this driver will automatically select the DSP and tuner. + +config RADIO_WL1273 + tristate "Texas Instruments WL1273 I2C FM Radio" + depends on I2C && VIDEO_V4L2 + select MFD_CORE + select MFD_WL1273_CORE + select FW_LOADER + ---help--- + Choose Y here if you have this FM radio chip. + + In order to control your radio card, you will need to use programs + that are compatible with the Video For Linux 2 API. Information on + this API and pointers to "v4l2" programs may be found at + . + + To compile this driver as a module, choose M here: the + module will be called radio-wl1273. + +# TI's ST based wl128x FM radio +source "drivers/media/radio/wl128x/Kconfig" + +# +# ISA drivers configuration +# + +menuconfig V4L_RADIO_ISA_DRIVERS + bool "ISA radio devices" + depends on ISA + default n + ---help--- + Say Y here to enable support for these ISA drivers. + +if V4L_RADIO_ISA_DRIVERS + config RADIO_CADET tristate "ADS Cadet AM/FM Tuner" depends on ISA && VIDEO_V4L2 @@ -151,21 +307,6 @@ config RADIO_GEMTEK_PROBE following ports will be probed: 0x20c, 0x30c, 0x24c, 0x34c, 0x248 and 0x28c. -config RADIO_MAXIRADIO - tristate "Guillemot MAXI Radio FM 2000 radio" - depends on VIDEO_V4L2 && PCI - ---help--- - Choose Y here if you have this radio card. This card may also be - found as Gemtek PCI FM. - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux API. Information on - this API and pointers to "v4l" programs may be found at - . - - To compile this driver as a module, choose M here: the - module will be called radio-maxiradio. - config RADIO_MIROPCM20 tristate "miroSOUND PCM20 radio" depends on ISA && ISA_DMA_API && VIDEO_V4L2 && SND @@ -316,131 +457,6 @@ config RADIO_ZOLTRIX_PORT help Enter the I/O port of your Zoltrix radio card. -config I2C_SI4713 - tristate "I2C driver for Silicon Labs Si4713 device" - depends on I2C && VIDEO_V4L2 - ---help--- - Say Y here if you want support to Si4713 I2C device. - This device driver supports only i2c bus. - - To compile this driver as a module, choose M here: the - module will be called si4713. - -config RADIO_SI4713 - tristate "Silicon Labs Si4713 FM Radio Transmitter support" - depends on I2C && VIDEO_V4L2 - select I2C_SI4713 - ---help--- - Say Y here if you want support to Si4713 FM Radio Transmitter. - This device can transmit audio through FM. It can transmit - RDS and RBDS signals as well. This module is the v4l2 radio - interface for the i2c driver of this device. - - To compile this driver as a module, choose M here: the - module will be called radio-si4713. - -config USB_DSBR - tristate "D-Link/GemTek USB FM radio support" - depends on USB && VIDEO_V4L2 - ---help--- - Say Y here if you want to connect this type of radio to your - computer's USB port. Note that the audio is not digital, and - you must connect the line out connector to a sound card or a - set of speakers. - - To compile this driver as a module, choose M here: the - module will be called dsbr100. - -config RADIO_SI470X - bool "Silicon Labs Si470x FM Radio Receiver support" - depends on VIDEO_V4L2 - -source "drivers/media/radio/si470x/Kconfig" - -config USB_MR800 - tristate "AverMedia MR 800 USB FM radio support" - depends on USB && VIDEO_V4L2 - ---help--- - Say Y here if you want to connect this type of radio to your - computer's USB port. Note that the audio is not digital, and - you must connect the line out connector to a sound card or a - set of speakers. - - To compile this driver as a module, choose M here: the - module will be called radio-mr800. - -config RADIO_TEA5764 - tristate "TEA5764 I2C FM radio support" - depends on I2C && VIDEO_V4L2 - ---help--- - Say Y here if you want to use the TEA5764 FM chip found in - EZX phones. This FM chip is present in EZX phones from Motorola, - connected to internal pxa I2C bus. - - To compile this driver as a module, choose M here: the - module will be called radio-tea5764. - -config RADIO_TEA5764_XTAL - bool "TEA5764 crystal reference" - depends on RADIO_TEA5764=y - default y - help - Say Y here if TEA5764 have a 32768 Hz crystal in circuit, say N - here if TEA5764 reference frequency is connected in FREQIN. - -config RADIO_SAA7706H - tristate "SAA7706H Car Radio DSP" - depends on I2C && VIDEO_V4L2 - ---help--- - Say Y here if you want to use the SAA7706H Car radio Digital - Signal Processor, found for instance on the Russellville development - board. On the russellville the device is connected to internal - timberdale I2C bus. - - To compile this driver as a module, choose M here: the - module will be called SAA7706H. - -config RADIO_TEF6862 - tristate "TEF6862 Car Radio Enhanced Selectivity Tuner" - depends on I2C && VIDEO_V4L2 - ---help--- - Say Y here if you want to use the TEF6862 Car Radio Enhanced - Selectivity Tuner, found for instance on the Russellville development - board. On the russellville the device is connected to internal - timberdale I2C bus. - - To compile this driver as a module, choose M here: the - module will be called TEF6862. - -config RADIO_TIMBERDALE - tristate "Enable the Timberdale radio driver" - depends on MFD_TIMBERDALE && VIDEO_V4L2 - depends on I2C # for RADIO_SAA7706H - select RADIO_TEF6862 - select RADIO_SAA7706H - ---help--- - This is a kind of umbrella driver for the Radio Tuner and DSP - found behind the Timberdale FPGA on the Russellville board. - Enabling this driver will automatically select the DSP and tuner. - -config RADIO_WL1273 - tristate "Texas Instruments WL1273 I2C FM Radio" - depends on I2C && VIDEO_V4L2 - select MFD_CORE - select MFD_WL1273_CORE - select FW_LOADER - ---help--- - Choose Y here if you have this FM radio chip. - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux 2 API. Information on - this API and pointers to "v4l2" programs may be found at - . - - To compile this driver as a module, choose M here: the - module will be called radio-wl1273. - -# TI's ST based wl128x FM radio -source "drivers/media/radio/wl128x/Kconfig" +endif # V4L_RADIO_ISA_DRIVERS endif # RADIO_ADAPTERS -- cgit v0.10.2 From 486eeb5628f812b4836405e2b2e76594287dd873 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 30 Sep 2011 09:14:19 -0300 Subject: [media] V4L menu: move all PCI(e) devices to their own submenu Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index b14f5fe..b43366a 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -580,6 +580,20 @@ config VIDEO_M52790 endmenu # encoder / decoder chips +config VIDEO_VIVI + tristate "Virtual Video Driver" + depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 + depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE + select FONT_8x16 + select VIDEOBUF2_VMALLOC + default n + ---help--- + Enables a virtual video driver. This device shows a color bar + and a timestamp, as a real device would generate by using V4L2 + api. + Say Y here if you want to test video apps or debug V4L devices. + In doubt, say N. + # # USB Multimedia device configuration # @@ -615,6 +629,8 @@ source "drivers/media/video/sn9c102/Kconfig" source "drivers/media/video/pwc/Kconfig" +source "drivers/media/video/cpia2/Kconfig" + config USB_ZR364XX tristate "USB ZR364XX Camera support" depends on VIDEO_V4L2 @@ -653,25 +669,55 @@ config USB_S2255 endif # V4L_USB_DRIVERS -config VIDEO_VIVI - tristate "Virtual Video Driver" - depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 - depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE - select FONT_8x16 - select VIDEOBUF2_VMALLOC - default n +# +# PCI drivers configuration +# + +menuconfig V4L_PCI_DRIVERS + bool "V4L PCI(e) devices" + depends on PCI + default y ---help--- - Enables a virtual video driver. This device shows a color bar - and a timestamp, as a real device would generate by using V4L2 - api. - Say Y here if you want to test video apps or debug V4L devices. - In doubt, say N. + Say Y here to enable support for these PCI(e) drivers. + +if V4L_PCI_DRIVERS + +source "drivers/media/video/au0828/Kconfig" source "drivers/media/video/bt8xx/Kconfig" -source "drivers/media/video/cpia2/Kconfig" +source "drivers/media/video/cx18/Kconfig" -source "drivers/media/video/zoran/Kconfig" +source "drivers/media/video/cx23885/Kconfig" + +source "drivers/media/video/cx25821/Kconfig" + +source "drivers/media/video/cx88/Kconfig" + +config VIDEO_HEXIUM_GEMINI + tristate "Hexium Gemini frame grabber" + depends on PCI && VIDEO_V4L2 && I2C + select VIDEO_SAA7146_VV + ---help--- + This is a video4linux driver for the Hexium Gemini frame + grabber card by Hexium. Please note that the Gemini Dual + card is *not* fully supported. + + To compile this driver as a module, choose M here: the + module will be called hexium_gemini. + +config VIDEO_HEXIUM_ORION + tristate "Hexium HV-PCI6 and Orion frame grabber" + depends on PCI && VIDEO_V4L2 && I2C + select VIDEO_SAA7146_VV + ---help--- + This is a video4linux driver for the Hexium HV-PCI6 and + Orion frame grabber cards by Hexium. + + To compile this driver as a module, choose M here: the + module will be called hexium_orion. + +source "drivers/media/video/ivtv/Kconfig" config VIDEO_MEYE tristate "Sony Vaio Picturebook Motion Eye Video For Linux" @@ -687,8 +733,6 @@ config VIDEO_MEYE To compile this driver as a module, choose M here: the module will be called meye. -source "drivers/media/video/saa7134/Kconfig" - config VIDEO_MXB tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" depends on PCI && VIDEO_V4L2 && I2C @@ -705,42 +749,13 @@ config VIDEO_MXB To compile this driver as a module, choose M here: the module will be called mxb. -config VIDEO_HEXIUM_ORION - tristate "Hexium HV-PCI6 and Orion frame grabber" - depends on PCI && VIDEO_V4L2 && I2C - select VIDEO_SAA7146_VV - ---help--- - This is a video4linux driver for the Hexium HV-PCI6 and - Orion frame grabber cards by Hexium. - - To compile this driver as a module, choose M here: the - module will be called hexium_orion. - -config VIDEO_HEXIUM_GEMINI - tristate "Hexium Gemini frame grabber" - depends on PCI && VIDEO_V4L2 && I2C - select VIDEO_SAA7146_VV - ---help--- - This is a video4linux driver for the Hexium Gemini frame - grabber card by Hexium. Please note that the Gemini Dual - card is *not* fully supported. - - To compile this driver as a module, choose M here: the - module will be called hexium_gemini. - -source "drivers/media/video/cx88/Kconfig" - -source "drivers/media/video/cx23885/Kconfig" - -source "drivers/media/video/cx25821/Kconfig" - -source "drivers/media/video/au0828/Kconfig" +source "drivers/media/video/saa7134/Kconfig" -source "drivers/media/video/ivtv/Kconfig" +source "drivers/media/video/saa7164/Kconfig" -source "drivers/media/video/cx18/Kconfig" +source "drivers/media/video/zoran/Kconfig" -source "drivers/media/video/saa7164/Kconfig" +endif # V4L_PCI_DRIVERS # # ISA & parallel port drivers configuration -- cgit v0.10.2 From 1df3a2c6d036f4923c229fa98725deda320680e1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 7 Nov 2011 06:26:59 -0300 Subject: [media] cx88: fix menu level for the VP-3054 module Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 5c42abd..3598dc0 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -70,11 +70,6 @@ config VIDEO_CX88_DVB To compile this driver as a module, choose M here: the module will be called cx88-dvb. -config VIDEO_CX88_MPEG - tristate - depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD - default y - config VIDEO_CX88_VP3054 tristate "VP-3054 Secondary I2C Bus Support" default m @@ -84,3 +79,8 @@ config VIDEO_CX88_VP3054 Conexant 2388x chip and the MT352 demodulator, which also require support for the VP-3054 Secondary I2C bus, such at DNTV Live! DVB-T Pro. + +config VIDEO_CX88_MPEG + tristate + depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD + default y -- cgit v0.10.2 From e9eb0dadba932940f721f9d27544a7818b2fa1c5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 8 Nov 2011 11:02:34 -0300 Subject: [media] V4L menu: add submenu for platform devices Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index b43366a..4e8a0c4 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -816,6 +816,14 @@ config VIDEO_W9966 endif # V4L_ISA_PARPORT_DRIVERS +menuconfig V4L_PLATFORM_DRIVERS + bool "V4L platform devices" + default n + ---help--- + Say Y here to enable support for platform-specific V4L drivers. + +if V4L_PLATFORM_DRIVERS + source "drivers/media/video/marvell-ccic/Kconfig" config VIDEO_VIA_CAMERA @@ -1110,6 +1118,7 @@ config VIDEO_S5P_MIPI_CSIS source "drivers/media/video/s5p-tv/Kconfig" +endif # V4L_PLATFORM_DRIVERS endif # VIDEO_CAPTURE_DRIVERS menuconfig V4L_MEM2MEM_DRIVERS -- cgit v0.10.2 From 16bfdaafa2c66d8cc81422a97a105a849ca65b3e Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 7 Nov 2011 17:23:30 -0500 Subject: nfsd4: share open and lock owner hash tables Now that they're used in the same way, it's a little simpler to put open and lock owners in the same hash table, and I can't see a reason not to. Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index eec9900..dcbe7f3 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -133,21 +133,21 @@ unsigned int max_delegations; * Open owner state (share locks) */ -/* hash tables for open owners */ -#define OPEN_OWNER_HASH_BITS 8 -#define OPEN_OWNER_HASH_SIZE (1 << OPEN_OWNER_HASH_BITS) -#define OPEN_OWNER_HASH_MASK (OPEN_OWNER_HASH_SIZE - 1) +/* hash tables for lock and open owners */ +#define OWNER_HASH_BITS 8 +#define OWNER_HASH_SIZE (1 << OWNER_HASH_BITS) +#define OWNER_HASH_MASK (OWNER_HASH_SIZE - 1) -static unsigned int open_ownerstr_hashval(u32 clientid, struct xdr_netobj *ownername) +static unsigned int ownerstr_hashval(u32 clientid, struct xdr_netobj *ownername) { unsigned int ret; ret = opaque_hashval(ownername->data, ownername->len); ret += clientid; - return ret & OPEN_OWNER_HASH_MASK; + return ret & OWNER_HASH_MASK; } -static struct list_head open_ownerstr_hashtbl[OPEN_OWNER_HASH_SIZE]; +static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE]; /* hash table for nfs4_file */ #define FILE_HASH_BITS 8 @@ -2373,7 +2373,7 @@ static inline void *alloc_stateowner(struct kmem_cache *slab, struct xdr_netobj static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval) { - list_add(&oo->oo_owner.so_strhash, &open_ownerstr_hashtbl[strhashval]); + list_add(&oo->oo_owner.so_strhash, &ownerstr_hashtbl[strhashval]); list_add(&oo->oo_perclient, &clp->cl_openowners); } @@ -2436,7 +2436,9 @@ find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open) struct nfs4_stateowner *so; struct nfs4_openowner *oo; - list_for_each_entry(so, &open_ownerstr_hashtbl[hashval], so_strhash) { + list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) { + if (!so->so_is_open_owner) + continue; if (same_owner_str(so, &open->op_owner, &open->op_clientid)) { oo = openowner(so); renew_client(oo->oo_owner.so_client); @@ -2580,7 +2582,7 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate, if (open->op_file == NULL) return nfserr_jukebox; - strhashval = open_ownerstr_hashval(clientid->cl_id, &open->op_owner); + strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner); oo = find_openstateowner_str(strhashval, open); open->op_openowner = oo; if (!oo) { @@ -3718,13 +3720,7 @@ out: } -/* - * Lock owner state (byte-range locks) - */ #define LOFF_OVERFLOW(start, len) ((u64)(len) > ~(u64)(start)) -#define LOCK_HASH_BITS 8 -#define LOCK_HASH_SIZE (1 << LOCK_HASH_BITS) -#define LOCK_HASH_MASK (LOCK_HASH_SIZE - 1) static inline u64 end_offset(u64 start, u64 len) @@ -3746,8 +3742,6 @@ last_byte_offset(u64 start, u64 len) return end > start ? end - 1: NFS4_MAX_UINT64; } -static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE]; - /* * TODO: Linux file offsets are _signed_ 64-bit quantities, which means that * we can't properly handle lock requests that go beyond the (2^63 - 1)-th @@ -3815,11 +3809,13 @@ static struct nfs4_lockowner * find_lockowner_str(struct inode *inode, clientid_t *clid, struct xdr_netobj *owner) { - unsigned int hashval = open_ownerstr_hashval(clid->cl_id, owner); + unsigned int hashval = ownerstr_hashval(clid->cl_id, owner); struct nfs4_lockowner *lo; struct nfs4_stateowner *op; - list_for_each_entry(op, &lock_ownerstr_hashtbl[hashval], so_strhash) { + list_for_each_entry(op, &ownerstr_hashtbl[hashval], so_strhash) { + if (op->so_is_open_owner) + continue; lo = lockowner(op); if (same_lockowner_ino(lo, inode, clid, owner)) return lo; @@ -3829,7 +3825,7 @@ find_lockowner_str(struct inode *inode, clientid_t *clid, static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, struct nfs4_client *clp, struct nfs4_ol_stateid *open_stp) { - list_add(&lo->lo_owner.so_strhash, &lock_ownerstr_hashtbl[strhashval]); + list_add(&lo->lo_owner.so_strhash, &ownerstr_hashtbl[strhashval]); list_add(&lo->lo_perstateid, &open_stp->st_lockowners); } @@ -3838,7 +3834,7 @@ static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, s * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has * occurred. * - * strhashval = open_ownerstr_hashval + * strhashval = ownerstr_hashval */ static struct nfs4_lockowner * @@ -3913,7 +3909,7 @@ __be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, struct n struct nfs4_ol_stateid, st_perstateowner); return nfs_ok; } - strhashval = open_ownerstr_hashval(cl->cl_clientid.cl_id, + strhashval = ownerstr_hashval(cl->cl_clientid.cl_id, &lock->v.new.owner); lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock); if (lo == NULL) @@ -4277,7 +4273,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfs4_ol_stateid *stp; struct xdr_netobj *owner = &rlockowner->rl_owner; struct list_head matches; - unsigned int hashval = open_ownerstr_hashval(clid->cl_id, owner); + unsigned int hashval = ownerstr_hashval(clid->cl_id, owner); __be32 status; dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n", @@ -4294,7 +4290,9 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, status = nfserr_locks_held; INIT_LIST_HEAD(&matches); - list_for_each_entry(sop, &lock_ownerstr_hashtbl[hashval], so_strhash) { + list_for_each_entry(sop, &ownerstr_hashtbl[hashval], so_strhash) { + if (sop->so_is_open_owner) + continue; if (!same_owner_str(sop, owner, clid)) continue; list_for_each_entry(stp, &sop->so_stateids, @@ -4444,16 +4442,16 @@ static void release_openowner_sop(struct nfs4_stateowner *sop) release_openowner(openowner(sop)); } -static int nfsd_release_n_owners(u64 num, - struct list_head hashtbl[], - unsigned int hashtbl_size, +static int nfsd_release_n_owners(u64 num, bool is_open_owner void (*release_sop)(struct nfs4_stateowner *)) { int i, count = 0; struct nfs4_stateowner *sop, *next; - for (i = 0; i < hashtbl_size; i++) { - list_for_each_entry_safe(sop, next, &hashtbl[i], so_strhash) { + for (i = 0; i < OWNER_HASH_SIZE; i++) { + list_for_each_entry_safe(sop, next, &ownerstr_hashtbl[i], so_strhash) { + if (sop->so_is_open_owner != is_open_owner) + continue; release_sop(sop); if (++count == num) return count; @@ -4467,8 +4465,7 @@ void nfsd_forget_locks(u64 num) int count; nfs4_lock_state(); - count = nfsd_release_n_owners(num, lock_ownerstr_hashtbl, - LOCK_HASH_SIZE, release_lockowner_sop); + count = nfsd_release_n_owners(num, false, release_lockowner_sop); nfs4_unlock_state(); printk(KERN_INFO "NFSD: Forgot %d locks", count); @@ -4479,8 +4476,7 @@ void nfsd_forget_openowners(u64 num) int count; nfs4_lock_state(); - count = nfsd_release_n_owners(num, open_ownerstr_hashtbl, - OPEN_OWNER_HASH_SIZE, release_openowner_sop); + count = nfsd_release_n_owners(num, true, release_openowner_sop); nfs4_unlock_state(); printk(KERN_INFO "NFSD: Forgot %d open owners", count); @@ -4549,11 +4545,8 @@ nfs4_state_init(void) for (i = 0; i < FILE_HASH_SIZE; i++) { INIT_LIST_HEAD(&file_hashtbl[i]); } - for (i = 0; i < OPEN_OWNER_HASH_SIZE; i++) { - INIT_LIST_HEAD(&open_ownerstr_hashtbl[i]); - } - for (i = 0; i < LOCK_HASH_SIZE; i++) { - INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]); + for (i = 0; i < OWNER_HASH_SIZE; i++) { + INIT_LIST_HEAD(&ownerstr_hashtbl[i]); } memset(&onestateid, ~0, sizeof(stateid_t)); INIT_LIST_HEAD(&close_lru); -- cgit v0.10.2 From ed6c038c2167bee886291b62a6865f0da825e8a6 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Mon, 7 Nov 2011 16:11:24 +0300 Subject: CIFS: Add descriptions to the brlock cache functions Signed-off-by: Pavel Shilovsky Signed-off-by: Steve French diff --git a/fs/cifs/file.c b/fs/cifs/file.c index cf0b153..4dd9283 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -702,6 +702,13 @@ cifs_find_lock_conflict(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, lock->type, lock->netfid, conf_lock); } +/* + * Check if there is another lock that prevents us to set the lock (mandatory + * style). If such a lock exists, update the flock structure with its + * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks + * or leave it the same if we can't. Returns 0 if we don't need to request to + * the server or 1 otherwise. + */ static int cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, __u8 type, __u16 netfid, struct file_lock *flock) @@ -739,6 +746,12 @@ cifs_lock_add(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock) mutex_unlock(&cinode->lock_mutex); } +/* + * Set the byte-range lock (mandatory style). Returns: + * 1) 0, if we set the lock and don't need to request to the server; + * 2) 1, if no locks prevent us but we need to request to the server; + * 3) -EACCESS, if there is a lock that prevents us and wait is false. + */ static int cifs_lock_add_if(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, bool wait) @@ -778,6 +791,13 @@ try_again: return rc; } +/* + * Check if there is another lock that prevents us to set the lock (posix + * style). If such a lock exists, update the flock structure with its + * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks + * or leave it the same if we can't. Returns 0 if we don't need to request to + * the server or 1 otherwise. + */ static int cifs_posix_lock_test(struct file *file, struct file_lock *flock) { @@ -800,6 +820,12 @@ cifs_posix_lock_test(struct file *file, struct file_lock *flock) return rc; } +/* + * Set the byte-range lock (posix style). Returns: + * 1) 0, if we set the lock and don't need to request to the server; + * 2) 1, if we need to request to the server; + * 3) <0, if the error occurs while setting the lock. + */ static int cifs_posix_lock_set(struct file *file, struct file_lock *flock) { -- cgit v0.10.2 From 67348450b86cb1b42aa4dd55cf7cde19c2e53461 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Mon, 17 Oct 2011 14:56:40 +0200 Subject: dmaengine: at_hdmac: platform data move to use .id_table We remove the use of platform data from DMA controller driver. We now use of .id_table to distinguish between compatible types. The two implementations allow to determine the number of channels and the capabilities of the controller. Signed-off-by: Nicolas Ferre Acked-by: Grant Likely Signed-off-by: Vinod Koul diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index fcfa0a8..d1869c5 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1175,6 +1175,18 @@ static void atc_free_chan_resources(struct dma_chan *chan) /*-- Module Management -----------------------------------------------*/ +static struct platform_device_id atdma_devtypes[] = { + { + .name = "at91sam9rl_dma", + .driver_data = ATDMA_DEVTYPE_SAM9RL, + }, { + .name = "at91sam9g45_dma", + .driver_data = ATDMA_DEVTYPE_SAM9G45, + }, { + /* sentinel */ + } +}; + /** * at_dma_off - disable DMA controller * @atdma: the Atmel HDAMC device @@ -1193,18 +1205,32 @@ static void at_dma_off(struct at_dma *atdma) static int __init at_dma_probe(struct platform_device *pdev) { - struct at_dma_platform_data *pdata; struct resource *io; struct at_dma *atdma; size_t size; int irq; int err; int i; + u32 nr_channels; + dma_cap_mask_t cap_mask = {}; + enum atdma_devtype atdmatype; + + dma_cap_set(DMA_MEMCPY, cap_mask); + + /* get DMA parameters from controller type */ + atdmatype = platform_get_device_id(pdev)->driver_data; - /* get DMA Controller parameters from platform */ - pdata = pdev->dev.platform_data; - if (!pdata || pdata->nr_channels > AT_DMA_MAX_NR_CHANNELS) + switch (atdmatype) { + case ATDMA_DEVTYPE_SAM9RL: + nr_channels = 2; + break; + case ATDMA_DEVTYPE_SAM9G45: + nr_channels = 8; + dma_cap_set(DMA_SLAVE, cap_mask); + break; + default: return -EINVAL; + } io = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!io) @@ -1215,14 +1241,15 @@ static int __init at_dma_probe(struct platform_device *pdev) return irq; size = sizeof(struct at_dma); - size += pdata->nr_channels * sizeof(struct at_dma_chan); + size += nr_channels * sizeof(struct at_dma_chan); atdma = kzalloc(size, GFP_KERNEL); if (!atdma) return -ENOMEM; - /* discover transaction capabilites from the platform data */ - atdma->dma_common.cap_mask = pdata->cap_mask; - atdma->all_chan_mask = (1 << pdata->nr_channels) - 1; + /* discover transaction capabilities */ + atdma->dma_common.cap_mask = cap_mask; + atdma->all_chan_mask = (1 << nr_channels) - 1; + atdma->devtype = atdmatype; size = resource_size(io); if (!request_mem_region(io->start, size, pdev->dev.driver->name)) { @@ -1268,7 +1295,7 @@ static int __init at_dma_probe(struct platform_device *pdev) /* initialize channels related values */ INIT_LIST_HEAD(&atdma->dma_common.channels); - for (i = 0; i < pdata->nr_channels; i++) { + for (i = 0; i < nr_channels; i++) { struct at_dma_chan *atchan = &atdma->chan[i]; atchan->chan_common.device = &atdma->dma_common; @@ -1313,7 +1340,7 @@ static int __init at_dma_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n", dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "", dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask) ? "slave " : "", - pdata->nr_channels); + nr_channels); dma_async_device_register(&atdma->dma_common); @@ -1495,6 +1522,7 @@ static const struct dev_pm_ops at_dma_dev_pm_ops = { static struct platform_driver at_dma_driver = { .remove = __exit_p(at_dma_remove), .shutdown = at_dma_shutdown, + .id_table = atdma_devtypes, .driver = { .name = "at_hdmac", .pm = &at_dma_dev_pm_ops, diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index aa4c9ae..d7d6737 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h @@ -248,9 +248,16 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan) /*-- Controller ------------------------------------------------------*/ +enum atdma_devtype { + ATDMA_DEVTYPE_UNDEFINED = 0, + ATDMA_DEVTYPE_SAM9RL, /* compatible with SAM9RL DMA controller */ + ATDMA_DEVTYPE_SAM9G45, /* compatible with SAM9G45 DMA controller */ +}; + /** * struct at_dma - internal representation of an Atmel HDMA Controller * @chan_common: common dmaengine dma_device object members + * @atdma_devtype: identifier of DMA controller compatibility * @ch_regs: memory mapped register base * @clk: dma controller clock * @save_imr: interrupt mask register that is saved on suspend/resume cycle @@ -260,6 +267,7 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan) */ struct at_dma { struct dma_device dma_common; + enum atdma_devtype devtype; void __iomem *regs; struct clk *clk; u32 save_imr; -- cgit v0.10.2 From c511595390a373e19a774246c659b4f563a4c3f3 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Mon, 17 Oct 2011 14:56:41 +0200 Subject: dmaengine: at_hdmac: add device tree support Add device tree probe support for atmel at_hdmac DMA driver. Bindings are added to specify DMA controller configuration. Signed-off-by: Nicolas Ferre Acked-by: Grant Likely Signed-off-by: Vinod Koul diff --git a/Documentation/devicetree/bindings/dma/atmel-dma.txt b/Documentation/devicetree/bindings/dma/atmel-dma.txt new file mode 100644 index 0000000..3c046ee --- /dev/null +++ b/Documentation/devicetree/bindings/dma/atmel-dma.txt @@ -0,0 +1,14 @@ +* Atmel Direct Memory Access Controller (DMA) + +Required properties: +- compatible: Should be "atmel,-dma" +- reg: Should contain DMA registers location and length +- interrupts: Should contain DMA interrupt + +Examples: + +dma@ffffec00 { + compatible = "atmel,at91sam9g45-dma"; + reg = <0xffffec00 0x200>; + interrupts = <21>; +}; diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index d1869c5..f3cb4a0 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "at_hdmac_regs.h" @@ -1175,6 +1177,20 @@ static void atc_free_chan_resources(struct dma_chan *chan) /*-- Module Management -----------------------------------------------*/ +#if defined(CONFIG_OF) +static const struct of_device_id atmel_dma_dt_ids[] = { + { + .compatible = "atmel,at91sam9rl-dma", + .data = (void *)ATDMA_DEVTYPE_SAM9RL + }, { + .compatible = "atmel,at91sam9g45-dma", + .data = (void *)ATDMA_DEVTYPE_SAM9G45 + }, { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, atmel_dma_dt_ids); +#endif + static struct platform_device_id atdma_devtypes[] = { { .name = "at91sam9rl_dma", @@ -1187,6 +1203,19 @@ static struct platform_device_id atdma_devtypes[] = { } }; +static inline enum atdma_devtype __init at_dma_get_driver_data( + struct platform_device *pdev) +{ + if (pdev->dev.of_node) { + const struct of_device_id *match; + match = of_match_node(atmel_dma_dt_ids, pdev->dev.of_node); + if (match == NULL) + return ATDMA_DEVTYPE_UNDEFINED; + return (enum atdma_devtype)match->data; + } + return platform_get_device_id(pdev)->driver_data; +} + /** * at_dma_off - disable DMA controller * @atdma: the Atmel HDAMC device @@ -1218,7 +1247,7 @@ static int __init at_dma_probe(struct platform_device *pdev) dma_cap_set(DMA_MEMCPY, cap_mask); /* get DMA parameters from controller type */ - atdmatype = platform_get_device_id(pdev)->driver_data; + atdmatype = at_dma_get_driver_data(pdev); switch (atdmatype) { case ATDMA_DEVTYPE_SAM9RL: @@ -1526,6 +1555,7 @@ static struct platform_driver at_dma_driver = { .driver = { .name = "at_hdmac", .pm = &at_dma_dev_pm_ops, + .of_match_table = of_match_ptr(atmel_dma_dt_ids), }, }; -- cgit v0.10.2 From 035c17dac4ce1f03d6831ff403f5aea7dcb927b4 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 10 Nov 2011 09:54:42 +0100 Subject: ARM i.MX5: remove unnecessary includes from board files Signed-off-by: Sascha Hauer diff --git a/arch/arm/mach-mx5/board-mx53_ard.c b/arch/arm/mach-mx5/board-mx53_ard.c index 0d7f0ff..b88a2bc 100644 --- a/arch/arm/mach-mx5/board-mx53_ard.c +++ b/arch/arm/mach-mx5/board-mx53_ard.c @@ -32,7 +32,6 @@ #include #include -#include "crm_regs.h" #include "devices-imx53.h" #define ARD_ETHERNET_INT_B IMX_GPIO_NR(2, 31) diff --git a/arch/arm/mach-mx5/board-mx53_evk.c b/arch/arm/mach-mx5/board-mx53_evk.c index 6bea31a..c69413d 100644 --- a/arch/arm/mach-mx5/board-mx53_evk.c +++ b/arch/arm/mach-mx5/board-mx53_evk.c @@ -37,7 +37,6 @@ #define EVK_ECSPI1_CS1 IMX_GPIO_NR(3, 19) #define MX53EVK_LED IMX_GPIO_NR(7, 7) -#include "crm_regs.h" #include "devices-imx53.h" static iomux_v3_cfg_t mx53_evk_pads[] = { diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c index 7678f77..e64a8f7 100644 --- a/arch/arm/mach-mx5/board-mx53_loco.c +++ b/arch/arm/mach-mx5/board-mx53_loco.c @@ -32,7 +32,6 @@ #include #include -#include "crm_regs.h" #include "devices-imx53.h" #define MX53_LOCO_POWER IMX_GPIO_NR(1, 8) diff --git a/arch/arm/mach-mx5/board-mx53_smd.c b/arch/arm/mach-mx5/board-mx53_smd.c index 59c0845..d498573 100644 --- a/arch/arm/mach-mx5/board-mx53_smd.c +++ b/arch/arm/mach-mx5/board-mx53_smd.c @@ -31,7 +31,6 @@ #include #include -#include "crm_regs.h" #include "devices-imx53.h" #define SMD_FEC_PHY_RST IMX_GPIO_NR(7, 6) -- cgit v0.10.2 From dab6538e29e68af6206ec1889c847b428f290989 Mon Sep 17 00:00:00 2001 From: Boojin Kim Date: Thu, 3 Nov 2011 15:48:49 +0900 Subject: DMA: PL330: Fix build warning This patch adds to fix the build warning as following. drivers/dma/pl330.c: In function 'pl330_probe': drivers/dma/pl330.c:859: warning: comparison of distinct pointer types lacks a cast Signed-off-by: Boojin Kim Signed-off-by: Vinod Koul diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 57104147..186b822 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -856,7 +856,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) INIT_LIST_HEAD(&pd->channels); /* Initialize channel parameters */ - num_chan = max(pdat ? pdat->nr_valid_peri : 0, (u8)pi->pcfg.num_chan); + num_chan = max(pdat ? (int)pdat->nr_valid_peri : 0, + (int)pi->pcfg.num_chan); pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); for (i = 0; i < num_chan; i++) { -- cgit v0.10.2 From 9c32c63bb70b2fafc3b18bee29959c3bf245ceba Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 10 Nov 2011 12:48:20 -0600 Subject: cifs: Fix sparse warning when calling cifs_strtoUCS Fix sparse endian check warning while calling cifs_strtoUCS CHECK fs/cifs/smbencrypt.c fs/cifs/smbencrypt.c:216:37: warning: incorrect type in argument 1 (different base types) fs/cifs/smbencrypt.c:216:37: expected restricted __le16 [usertype] * fs/cifs/smbencrypt.c:216:37: got unsigned short * Signed-off-by: Steve French Acked-by: Shirish Pargaonkar Date: Fri, 11 Nov 2011 12:46:23 -0200 Subject: [media] dvb: Allow select between DVB-C Annex A and Annex C DVB-C, as defined by ITU-T J.83 has 3 annexes. The differences between Annex A and Annex C is that Annex C uses a subset of the modulation types, and uses a different rolloff factor. A different rolloff means that the bandwidth required is slicely different, and may affect the saw filter configuration at the tuners. Also, some demods have different configurations, depending on using Annex A or Annex C. So, allow userspace to specify it, by changing the rolloff factor. Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/DocBook/media/dvb/dvbproperty.xml b/Documentation/DocBook/media/dvb/dvbproperty.xml index 3bc8a61..6ac8039 100644 --- a/Documentation/DocBook/media/dvb/dvbproperty.xml +++ b/Documentation/DocBook/media/dvb/dvbproperty.xml @@ -311,6 +311,8 @@ typedef enum fe_rolloff { ROLLOFF_20, ROLLOFF_25, ROLLOFF_AUTO, + ROLLOFF_15, /* DVB-C Annex A */ + ROLLOFF_13, /* DVB-C Annex C */ } fe_rolloff_t; @@ -778,8 +780,10 @@ typedef enum fe_hierarchy { DTV_MODULATION DTV_INVERSION DTV_SYMBOL_RATE + DTV_ROLLOFF DTV_INNER_FEC + The Rolloff of 0.15 (ROLLOFF_15) is assumed, as ITU-T J.83 Annex A is more common. For Annex C, rolloff should be 0.13 (ROLLOFF_13). All other values are invalid.
DVB-C Annex B delivery system diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 2c0acdb..c849455 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -876,6 +876,7 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe) c->symbol_rate = QAM_AUTO; c->code_rate_HP = FEC_AUTO; c->code_rate_LP = FEC_AUTO; + c->rolloff = ROLLOFF_AUTO; c->isdbt_partial_reception = -1; c->isdbt_sb_mode = -1; @@ -1030,6 +1031,7 @@ static void dtv_property_cache_init(struct dvb_frontend *fe, break; case FE_QAM: c->delivery_system = SYS_DVBC_ANNEX_AC; + c->rolloff = ROLLOFF_15; /* implied for Annex A */ break; case FE_OFDM: c->delivery_system = SYS_DVBT; diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index 1b1094c..d9251df 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -329,6 +329,8 @@ typedef enum fe_rolloff { ROLLOFF_20, ROLLOFF_25, ROLLOFF_AUTO, + ROLLOFF_15, /* DVB-C Annex A */ + ROLLOFF_13, /* DVB-C Annex C */ } fe_rolloff_t; typedef enum fe_delivery_system { -- cgit v0.10.2 From 5a6b5e02d673486c96003d4a6e3e2510f4c59f92 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sat, 3 Sep 2011 01:36:08 +0000 Subject: fbdev: remove display subsystem This four year old subsystem does not have a single in-tree user not even in staging and as far as I know also none out-of-tree. I think that justifies removing it which cleans the config up. Signed-off-by: Florian Tobias Schandinat Acked-by: James Simmons Cc: Andrew Morton diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 8165c55..1b5b98f 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2413,7 +2413,6 @@ source "drivers/video/omap/Kconfig" source "drivers/video/omap2/Kconfig" source "drivers/video/backlight/Kconfig" -source "drivers/video/display/Kconfig" if VT source "drivers/video/console/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 9b9d8ff..1426068 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -13,7 +13,7 @@ fb-objs := $(fb-y) obj-$(CONFIG_VT) += console/ obj-$(CONFIG_LOGO) += logo/ -obj-y += backlight/ display/ +obj-y += backlight/ obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig deleted file mode 100644 index f99af93..0000000 --- a/drivers/video/display/Kconfig +++ /dev/null @@ -1,24 +0,0 @@ -# -# Display drivers configuration -# - -menu "Display device support" - -config DISPLAY_SUPPORT - tristate "Display panel/monitor support" - ---help--- - This framework adds support for low-level control of a display. - This includes support for power. - - Enable this to be able to choose the drivers for controlling the - physical display panel/monitor on some platforms. This not only - covers LCD displays for PDAs but also other types of displays - such as CRT, TVout etc. - - To have support for your specific display panel you will have to - select the proper drivers which depend on this option. - -comment "Display hardware drivers" - depends on DISPLAY_SUPPORT - -endmenu diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile deleted file mode 100644 index c0ea832..0000000 --- a/drivers/video/display/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# Display drivers - -display-objs := display-sysfs.o - -obj-$(CONFIG_DISPLAY_SUPPORT) += display.o - diff --git a/drivers/video/display/display-sysfs.c b/drivers/video/display/display-sysfs.c deleted file mode 100644 index 0c647d7..0000000 --- a/drivers/video/display/display-sysfs.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * display-sysfs.c - Display output driver sysfs interface - * - * Copyright (C) 2007 James Simmons - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ -#include -#include -#include -#include -#include -#include -#include - -static ssize_t display_show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct display_device *dsp = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%s\n", dsp->name); -} - -static ssize_t display_show_type(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct display_device *dsp = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type); -} - -static ssize_t display_show_contrast(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct display_device *dsp = dev_get_drvdata(dev); - ssize_t rc = -ENXIO; - - mutex_lock(&dsp->lock); - if (likely(dsp->driver) && dsp->driver->get_contrast) - rc = sprintf(buf, "%d\n", dsp->driver->get_contrast(dsp)); - mutex_unlock(&dsp->lock); - return rc; -} - -static ssize_t display_store_contrast(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct display_device *dsp = dev_get_drvdata(dev); - ssize_t ret = -EINVAL, size; - int contrast; - char *endp; - - contrast = simple_strtoul(buf, &endp, 0); - size = endp - buf; - - if (isspace(*endp)) - size++; - - if (size != count) - return ret; - - mutex_lock(&dsp->lock); - if (likely(dsp->driver && dsp->driver->set_contrast)) { - pr_debug("display: set contrast to %d\n", contrast); - dsp->driver->set_contrast(dsp, contrast); - ret = count; - } - mutex_unlock(&dsp->lock); - return ret; -} - -static ssize_t display_show_max_contrast(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct display_device *dsp = dev_get_drvdata(dev); - ssize_t rc = -ENXIO; - - mutex_lock(&dsp->lock); - if (likely(dsp->driver)) - rc = sprintf(buf, "%d\n", dsp->driver->max_contrast); - mutex_unlock(&dsp->lock); - return rc; -} - -static struct device_attribute display_attrs[] = { - __ATTR(name, S_IRUGO, display_show_name, NULL), - __ATTR(type, S_IRUGO, display_show_type, NULL), - __ATTR(contrast, S_IRUGO | S_IWUSR, display_show_contrast, display_store_contrast), - __ATTR(max_contrast, S_IRUGO, display_show_max_contrast, NULL), -}; - -static int display_suspend(struct device *dev, pm_message_t state) -{ - struct display_device *dsp = dev_get_drvdata(dev); - - mutex_lock(&dsp->lock); - if (likely(dsp->driver->suspend)) - dsp->driver->suspend(dsp, state); - mutex_unlock(&dsp->lock); - return 0; -}; - -static int display_resume(struct device *dev) -{ - struct display_device *dsp = dev_get_drvdata(dev); - - mutex_lock(&dsp->lock); - if (likely(dsp->driver->resume)) - dsp->driver->resume(dsp); - mutex_unlock(&dsp->lock); - return 0; -}; - -static struct mutex allocated_dsp_lock; -static DEFINE_IDR(allocated_dsp); -static struct class *display_class; - -struct display_device *display_device_register(struct display_driver *driver, - struct device *parent, void *devdata) -{ - struct display_device *new_dev = NULL; - int ret = -EINVAL; - - if (unlikely(!driver)) - return ERR_PTR(ret); - - mutex_lock(&allocated_dsp_lock); - ret = idr_pre_get(&allocated_dsp, GFP_KERNEL); - mutex_unlock(&allocated_dsp_lock); - if (!ret) - return ERR_PTR(ret); - - new_dev = kzalloc(sizeof(struct display_device), GFP_KERNEL); - if (likely(new_dev) && unlikely(driver->probe(new_dev, devdata))) { - // Reserve the index for this display - mutex_lock(&allocated_dsp_lock); - ret = idr_get_new(&allocated_dsp, new_dev, &new_dev->idx); - mutex_unlock(&allocated_dsp_lock); - - if (!ret) { - new_dev->dev = device_create(display_class, parent, - MKDEV(0, 0), new_dev, - "display%d", new_dev->idx); - if (!IS_ERR(new_dev->dev)) { - new_dev->parent = parent; - new_dev->driver = driver; - mutex_init(&new_dev->lock); - return new_dev; - } - mutex_lock(&allocated_dsp_lock); - idr_remove(&allocated_dsp, new_dev->idx); - mutex_unlock(&allocated_dsp_lock); - ret = -EINVAL; - } - } - kfree(new_dev); - return ERR_PTR(ret); -} -EXPORT_SYMBOL(display_device_register); - -void display_device_unregister(struct display_device *ddev) -{ - if (!ddev) - return; - // Free device - mutex_lock(&ddev->lock); - device_unregister(ddev->dev); - mutex_unlock(&ddev->lock); - // Mark device index as available - mutex_lock(&allocated_dsp_lock); - idr_remove(&allocated_dsp, ddev->idx); - mutex_unlock(&allocated_dsp_lock); - kfree(ddev); -} -EXPORT_SYMBOL(display_device_unregister); - -static int __init display_class_init(void) -{ - display_class = class_create(THIS_MODULE, "display"); - if (IS_ERR(display_class)) { - printk(KERN_ERR "Failed to create display class\n"); - display_class = NULL; - return -EINVAL; - } - display_class->dev_attrs = display_attrs; - display_class->suspend = display_suspend; - display_class->resume = display_resume; - mutex_init(&allocated_dsp_lock); - return 0; -} - -static void __exit display_class_exit(void) -{ - class_destroy(display_class); -} - -module_init(display_class_init); -module_exit(display_class_exit); - -MODULE_DESCRIPTION("Display Hardware handling"); -MODULE_AUTHOR("James Simmons "); -MODULE_LICENSE("GPL"); - diff --git a/include/linux/display.h b/include/linux/display.h deleted file mode 100644 index 3bf70d6..0000000 --- a/include/linux/display.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2006 James Simmons - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#ifndef _LINUX_DISPLAY_H -#define _LINUX_DISPLAY_H - -#include - -struct display_device; - -/* This structure defines all the properties of a Display. */ -struct display_driver { - int (*set_contrast)(struct display_device *, unsigned int); - int (*get_contrast)(struct display_device *); - void (*suspend)(struct display_device *, pm_message_t state); - void (*resume)(struct display_device *); - int (*probe)(struct display_device *, void *); - int (*remove)(struct display_device *); - int max_contrast; -}; - -struct display_device { - struct module *owner; /* Owner module */ - struct display_driver *driver; - struct device *parent; /* This is the parent */ - struct device *dev; /* This is this display device */ - struct mutex lock; - void *priv_data; - char type[16]; - char *name; - int idx; -}; - -extern struct display_device *display_device_register(struct display_driver *driver, - struct device *dev, void *devdata); -extern void display_device_unregister(struct display_device *dev); - -extern int probe_edid(struct display_device *dev, void *devdata); - -#define to_display_device(obj) container_of(obj, struct display_device, class_dev) - -#endif -- cgit v0.10.2 From 5d910426a6e80194a50e33351c91abcad266c809 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 5 Oct 2011 09:59:57 +0200 Subject: atmel_lcdfb: Adjust HFP calculation so it matches the manual. In the AT91SAM9263 Manual the HFP part in LCDTIM2 is described as follows: * HFP: Horizontal Front Porch Number of idle LCDDOTCK cycles at the end of the line. Idle period is (HFP+2) LCDDOTCK cycles. It is only a minor issue. I also changed all boards using atmel_lcdfb I found to respect the new calculation. Signed-off-by: Alexander Stein Signed-off-by: Florian Tobias Schandinat diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c index 679b0b7..ae962bf 100644 --- a/arch/arm/mach-at91/board-cap9adk.c +++ b/arch/arm/mach-at91/board-cap9adk.c @@ -304,7 +304,7 @@ static struct fb_videomode at91_tft_vga_modes[] = { .xres = 240, .yres = 320, .pixclock = KHZ2PICOS(4965), - .left_margin = 1, .right_margin = 33, + .left_margin = 1, .right_margin = 34, .upper_margin = 1, .lower_margin = 0, .hsync_len = 5, .vsync_len = 1, diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c index 9bc6ab3..583878e 100644 --- a/arch/arm/mach-at91/board-neocore926.c +++ b/arch/arm/mach-at91/board-neocore926.c @@ -235,7 +235,7 @@ static struct fb_videomode at91_tft_vga_modes[] = { .xres = 240, .yres = 320, .pixclock = KHZ2PICOS(5000), - .left_margin = 1, .right_margin = 33, + .left_margin = 1, .right_margin = 34, .upper_margin = 1, .lower_margin = 0, .hsync_len = 5, .vsync_len = 1, diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index 5096a0e..8dda83b 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -370,7 +370,7 @@ static struct fb_videomode at91_stn_modes[] = { .xres = 320, .yres = 240, .pixclock = KHZ2PICOS(1440), - .left_margin = 1, .right_margin = 1, + .left_margin = 1, .right_margin = 2, .upper_margin = 0, .lower_margin = 0, .hsync_len = 1, .vsync_len = 1, @@ -431,7 +431,7 @@ static struct fb_videomode at91_tft_vga_modes[] = { .xres = 240, .yres = 320, .pixclock = KHZ2PICOS(4965), - .left_margin = 1, .right_margin = 33, + .left_margin = 1, .right_margin = 34, .upper_margin = 1, .lower_margin = 0, .hsync_len = 5, .vsync_len = 1, diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index ea8f185..e260070 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -258,7 +258,7 @@ static struct fb_videomode at91_tft_vga_modes[] = { .xres = 240, .yres = 320, .pixclock = KHZ2PICOS(4965), - .left_margin = 1, .right_margin = 33, + .left_margin = 1, .right_margin = 34, .upper_margin = 1, .lower_margin = 0, .hsync_len = 5, .vsync_len = 1, diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c index ad234cc..5e9a5ca 100644 --- a/arch/arm/mach-at91/board-sam9m10g45ek.c +++ b/arch/arm/mach-at91/board-sam9m10g45ek.c @@ -197,7 +197,7 @@ static struct fb_videomode at91_tft_vga_modes[] = { .xres = 480, .yres = 272, .pixclock = KHZ2PICOS(9000), - .left_margin = 1, .right_margin = 1, + .left_margin = 1, .right_margin = 2, .upper_margin = 40, .lower_margin = 1, .hsync_len = 45, .vsync_len = 1, diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c index 4f14b54..ad9e5c9 100644 --- a/arch/arm/mach-at91/board-sam9rlek.c +++ b/arch/arm/mach-at91/board-sam9rlek.c @@ -154,7 +154,7 @@ static struct fb_videomode at91_tft_vga_modes[] = { .xres = 240, .yres = 320, .pixclock = KHZ2PICOS(4965), - .left_margin = 1, .right_margin = 33, + .left_margin = 1, .right_margin = 34, .upper_margin = 1, .lower_margin = 0, .hsync_len = 5, .vsync_len = 1, diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 244d55b..7e66263 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -396,7 +396,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, var->lower_margin = min_t(u32, var->lower_margin, ATMEL_LCDC_VFP); var->right_margin = min_t(u32, var->right_margin, - (ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 1); + (ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 2); var->hsync_len = min_t(u32, var->hsync_len, (ATMEL_LCDC_HPW >> ATMEL_LCDC_HPW_OFFSET) + 1); var->left_margin = min_t(u32, var->left_margin, @@ -581,7 +581,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info) lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value); /* Horizontal timing */ - value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET; + value = (info->var.right_margin - 2) << ATMEL_LCDC_HFP_OFFSET; value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET; value |= (info->var.left_margin - 1); dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value); -- cgit v0.10.2 From acfdc2e1bdb4b148e7546fe8948d8f75bd2f9377 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 5 Oct 2011 09:59:58 +0200 Subject: atmel_lcdfb: Use proper blanking on negative contrast polarity If used with negative polarity the PWM unit cannot be disabled. This would result in a full contrast screen. Instead let the PWM unit enabled using 0x0 as compare value which darkens the display. In result no power saving is possible if inverted contrast polarity is used. Signed-off-by: Alexander Stein Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 7e66263..8bfee6a 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -99,8 +99,11 @@ static int atmel_bl_update_status(struct backlight_device *bl) brightness = 0; lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness); - lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, + if (contrast_ctr & ATMEL_LCDC_POL_POSITIVE) + lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, brightness ? contrast_ctr : 0); + else + lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr); bl->props.fb_blank = bl->props.power = sinfo->bl_power = power; -- cgit v0.10.2 From 5d67b89ce88f2db60573de859649b1b5a8c830d6 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Thu, 13 Oct 2011 16:45:52 +0200 Subject: atmel_lcdfb: support new-style palette format The newer Atmel SoCs use normal 16bit 565 BGR/RGB for the palette data, rather than the special intensity + 555 format. Fill out palette data correctly on these devices, and at the same time respect the RGB/BGR wiring mode. Signed-off-by: Peter Korsgaard Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 8bfee6a..2226aca 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -684,14 +684,30 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red, case FB_VISUAL_PSEUDOCOLOR: if (regno < 256) { - val = ((red >> 11) & 0x001f); - val |= ((green >> 6) & 0x03e0); - val |= ((blue >> 1) & 0x7c00); - - /* - * TODO: intensity bit. Maybe something like - * ~(red[10] ^ green[10] ^ blue[10]) & 1 - */ + if (cpu_is_at91sam9261() || cpu_is_at91sam9263() + || cpu_is_at91sam9rl()) { + /* old style I+BGR:555 */ + val = ((red >> 11) & 0x001f); + val |= ((green >> 6) & 0x03e0); + val |= ((blue >> 1) & 0x7c00); + + /* + * TODO: intensity bit. Maybe something like + * ~(red[10] ^ green[10] ^ blue[10]) & 1 + */ + } else { + /* new style BGR:565 / RGB:565 */ + if (sinfo->lcd_wiring_mode == + ATMEL_LCDC_WIRING_RGB) { + val = ((blue >> 11) & 0x001f); + val |= ((red >> 0) & 0xf800); + } else { + val = ((red >> 11) & 0x001f); + val |= ((blue >> 0) & 0xf800); + } + + val |= ((green >> 5) & 0x07e0); + } lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val); ret = 0; -- cgit v0.10.2 From 38eb6863ed21de9beab792f66cd282c21e0dc10b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Oct 2011 13:42:22 +0200 Subject: zorro: Rename Picasso IV Z2 "MEM" to "RAM" for consistency Signed-off-by: Geert Uytterhoeven Signed-off-by: Florian Tobias Schandinat diff --git a/include/linux/zorro_ids.h b/include/linux/zorro_ids.h index 7e74908..74bc53b 100644 --- a/include/linux/zorro_ids.h +++ b/include/linux/zorro_ids.h @@ -360,8 +360,8 @@ #define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM ZORRO_ID(VILLAGE_TRONIC, 0x0B, 0) #define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG ZORRO_ID(VILLAGE_TRONIC, 0x0C, 0) #define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_SEGMENTED_MODE ZORRO_ID(VILLAGE_TRONIC, 0x0D, 0) -#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_MEM1 ZORRO_ID(VILLAGE_TRONIC, 0x15, 0) -#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_MEM2 ZORRO_ID(VILLAGE_TRONIC, 0x16, 0) +#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1 ZORRO_ID(VILLAGE_TRONIC, 0x15, 0) +#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM2 ZORRO_ID(VILLAGE_TRONIC, 0x16, 0) #define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG ZORRO_ID(VILLAGE_TRONIC, 0x17, 0) #define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3 ZORRO_ID(VILLAGE_TRONIC, 0x18, 0) #define ZORRO_PROD_VILLAGE_TRONIC_ARIADNE ZORRO_ID(VILLAGE_TRONIC, 0xC9, 0) -- cgit v0.10.2 From 0e0d13364b417a40266999c61671db0ef8690ad3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Oct 2011 13:42:23 +0200 Subject: fbdev/cirrusfb: Rewrite Zorro graphics card probing As indicated by commit a7f4d00a82feb5b311f765bf9522bc55bee0684f ("zorro: Defer device_register() until all devices have been identified"), cirrusfb crashes if zorro_find_device() cannot find an expected device. Rewrite the Zorro device probe code to make it more robust, easier to understand, and more extensible. Other logical changes: - For cards that show up as 2 Zorro devices, autoprobe graphics memory sizes based on the size of the Zorro device containing the graphics memory. Acording to the NetBSD sources, this is safe. Signed-off-by: Geert Uytterhoeven Acked-by: Jeff Garzik Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 6df7c54..357139a 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -280,52 +280,63 @@ MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table); #endif /* CONFIG_PCI */ #ifdef CONFIG_ZORRO -static const struct zorro_device_id cirrusfb_zorro_table[] = { +struct zorrocl { + enum cirrus_board type; /* Board type */ + u32 regoffset; /* Offset of registers in first Zorro device */ + u32 ramsize; /* Size of video RAM in first Zorro device */ + /* If zero, use autoprobe on RAM device */ + u32 ramoffset; /* Offset of video RAM in first Zorro device */ + zorro_id ramid; /* Zorro ID of RAM device */ +}; + +static const struct zorrocl zcl_sd64 __devinitconst = { + .type = BT_SD64, + .ramid = ZORRO_PROD_HELFRICH_SD64_RAM, +}; + +static const struct zorrocl zcl_piccolo __devinitconst = { + .type = BT_PICCOLO, + .ramid = ZORRO_PROD_HELFRICH_PICCOLO_RAM, +}; + +static const struct zorrocl zcl_picasso __devinitconst = { + .type = BT_PICASSO, + .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, +}; + +static const struct zorrocl zcl_spectrum __devinitconst = { + .type = BT_SPECTRUM, + .ramid = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, +}; + +static const struct zorrocl zcl_picasso4_z3 __devinitconst = { + .type = BT_PICASSO4, + .regoffset = 0x00600000, + .ramsize = 4 * MB_, + .ramoffset = 0x01000000, +}; + + +static const struct zorro_device_id cirrusfb_zorro_table[] __devinitconst = { { - .id = ZORRO_PROD_HELFRICH_SD64_RAM, - .driver_data = BT_SD64, + .id = ZORRO_PROD_HELFRICH_SD64_REG, + .driver_data = (unsigned long)&zcl_sd64, }, { - .id = ZORRO_PROD_HELFRICH_PICCOLO_RAM, - .driver_data = BT_PICCOLO, + .id = ZORRO_PROD_HELFRICH_PICCOLO_REG, + .driver_data = (unsigned long)&zcl_piccolo, }, { - .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, - .driver_data = BT_PICASSO, + .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG, + .driver_data = (unsigned long)&zcl_picasso, }, { - .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, - .driver_data = BT_SPECTRUM, + .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG, + .driver_data = (unsigned long)&zcl_spectrum, }, { .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3, - .driver_data = BT_PICASSO4, + .driver_data = (unsigned long)&zcl_picasso4_z3, }, { 0 } }; MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table); - -static const struct { - zorro_id id2; - unsigned long size; -} cirrusfb_zorro_table2[] = { - [BT_SD64] = { - .id2 = ZORRO_PROD_HELFRICH_SD64_REG, - .size = 0x400000 - }, - [BT_PICCOLO] = { - .id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG, - .size = 0x200000 - }, - [BT_PICASSO] = { - .id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG, - .size = 0x200000 - }, - [BT_SPECTRUM] = { - .id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG, - .size = 0x200000 - }, - [BT_PICASSO4] = { - .id2 = 0, - .size = 0x400000 - } -}; #endif /* CONFIG_ZORRO */ #ifdef CIRRUSFB_DEBUG @@ -1956,16 +1967,12 @@ static void cirrusfb_zorro_unmap(struct fb_info *info) struct cirrusfb_info *cinfo = info->par; struct zorro_dev *zdev = to_zorro_dev(info->device); - zorro_release_device(zdev); - - if (cinfo->btype == BT_PICASSO4) { - cinfo->regbase -= 0x600000; - iounmap((void *)cinfo->regbase); + if (info->fix.smem_start > 16 * MB_) iounmap(info->screen_base); - } else { - if (zorro_resource_start(zdev) > 0x01000000) - iounmap(info->screen_base); - } + if (info->fix.mmio_start > 16 * MB_) + iounmap(cinfo->regbase); + + zorro_release_device(zdev); } #endif /* CONFIG_ZORRO */ @@ -2222,115 +2229,102 @@ static struct pci_driver cirrusfb_pci_driver = { static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, const struct zorro_device_id *ent) { - struct cirrusfb_info *cinfo; struct fb_info *info; + int error; + const struct zorrocl *zcl; enum cirrus_board btype; - struct zorro_dev *z2 = NULL; - unsigned long board_addr, board_size, size; - int ret; - - btype = ent->driver_data; - if (cirrusfb_zorro_table2[btype].id2) - z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL); - size = cirrusfb_zorro_table2[btype].size; + unsigned long regbase, ramsize, rambase; + struct cirrusfb_info *cinfo; info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev); if (!info) { printk(KERN_ERR "cirrusfb: could not allocate memory\n"); - ret = -ENOMEM; - goto err_out; + return -ENOMEM; } - dev_info(info->device, "%s board detected\n", - cirrusfb_board_info[btype].name); - - cinfo = info->par; - cinfo->btype = btype; - - assert(z); - assert(btype != BT_NONE); + zcl = (const struct zorrocl *)ent->driver_data; + btype = zcl->type; + regbase = zorro_resource_start(z) + zcl->regoffset; + ramsize = zcl->ramsize; + if (ramsize) { + rambase = zorro_resource_start(z) + zcl->ramoffset; + } else { + struct zorro_dev *ram = zorro_find_device(zcl->ramid, NULL); + if (!ram || !zorro_resource_len(ram)) { + dev_err(info->device, "No video RAM found\n"); + error = -ENODEV; + goto err_release_fb; + } + rambase = zorro_resource_start(ram); + ramsize = zorro_resource_len(ram); + } - board_addr = zorro_resource_start(z); - board_size = zorro_resource_len(z); - info->screen_size = size; + dev_info(info->device, + "%s board detected, REG at 0x%lx, %lu MiB RAM at 0x%lx\n", + cirrusfb_board_info[btype].name, regbase, ramsize / MB_, + rambase); if (!zorro_request_device(z, "cirrusfb")) { - dev_err(info->device, "cannot reserve region 0x%lx, abort\n", - board_addr); - ret = -EBUSY; + dev_err(info->device, "Cannot reserve %pR\n", &z->resource); + error = -EBUSY; goto err_release_fb; } - ret = -EIO; - - if (btype == BT_PICASSO4) { - dev_info(info->device, " REG at $%lx\n", board_addr + 0x600000); - - /* To be precise, for the P4 this is not the */ - /* begin of the board, but the begin of RAM. */ - /* for P4, map in its address space in 2 chunks (### TEST! ) */ - /* (note the ugly hardcoded 16M number) */ - cinfo->regbase = ioremap(board_addr, 16777216); - if (!cinfo->regbase) - goto err_release_region; - - dev_dbg(info->device, "Virtual address for board set to: $%p\n", - cinfo->regbase); - cinfo->regbase += 0x600000; - info->fix.mmio_start = board_addr + 0x600000; - - info->fix.smem_start = board_addr + 16777216; - info->screen_base = ioremap(info->fix.smem_start, 16777216); - if (!info->screen_base) - goto err_unmap_regbase; - } else { - dev_info(info->device, " REG at $%lx\n", - (unsigned long) z2->resource.start); - - info->fix.smem_start = board_addr; - if (board_addr > 0x01000000) - info->screen_base = ioremap(board_addr, board_size); - else - info->screen_base = (caddr_t) ZTWO_VADDR(board_addr); - if (!info->screen_base) - goto err_release_region; + cinfo = info->par; + cinfo->btype = btype; - /* set address for REG area of board */ - cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start); - info->fix.mmio_start = z2->resource.start; + info->fix.mmio_start = regbase; + cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024) + : (caddr_t)ZTWO_VADDR(regbase); + if (!cinfo->regbase) { + dev_err(info->device, "Cannot map registers\n"); + error = -EIO; + goto err_release_dev; + } - dev_dbg(info->device, "Virtual address for board set to: $%p\n", - cinfo->regbase); + info->fix.smem_start = rambase; + info->screen_size = ramsize; + info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize) + : (caddr_t)ZTWO_VADDR(rambase); + if (!info->screen_base) { + dev_err(info->device, "Cannot map video RAM\n"); + error = -EIO; + goto err_unmap_reg; } + cinfo->unmap = cirrusfb_zorro_unmap; dev_info(info->device, - "Cirrus Logic chipset on Zorro bus, RAM (%lu MB) at $%lx\n", - board_size / MB_, board_addr); - - zorro_set_drvdata(z, info); + "Cirrus Logic chipset on Zorro bus, RAM (%lu MiB) at 0x%lx\n", + ramsize / MB_, rambase); /* MCLK select etc. */ if (cirrusfb_board_info[btype].init_sr1f) vga_wseq(cinfo->regbase, CL_SEQR1F, cirrusfb_board_info[btype].sr1f); - ret = cirrusfb_register(info); - if (!ret) - return 0; + error = cirrusfb_register(info); + if (error) { + dev_err(info->device, "Failed to register device, error %d\n", + error); + goto err_unmap_ram; + } - if (btype == BT_PICASSO4 || board_addr > 0x01000000) + zorro_set_drvdata(z, info); + return 0; + +err_unmap_ram: + if (rambase > 16 * MB_) iounmap(info->screen_base); -err_unmap_regbase: - if (btype == BT_PICASSO4) - iounmap(cinfo->regbase - 0x600000); -err_release_region: - release_region(board_addr, board_size); +err_unmap_reg: + if (regbase > 16 * MB_) + iounmap(cinfo->regbase); +err_release_dev: + zorro_release_device(z); err_release_fb: framebuffer_release(info); -err_out: - return ret; + return error; } void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z) @@ -2338,6 +2332,7 @@ void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z) struct fb_info *info = zorro_get_drvdata(z); cirrusfb_cleanup(info); + zorro_set_drvdata(z, NULL); } static struct zorro_driver cirrusfb_zorro_driver = { -- cgit v0.10.2 From 17bdf48952d3f5c0be8137058f81d398d4606820 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Oct 2011 13:42:24 +0200 Subject: fbdev/cirrusfb: Add support for Picasso IV in Zorro II mode In Zorro II mode, the Village Tronic Picasso IV graphics card shows up as either 2 or 3 Zorro devices: - One for the registers of the Cirrus Logic graphics chip, - One for the first bank of 2 MiB of graphics memory, - An optional one for the second bank of 2 MiB of graphics memory, if there was enough free Zorro II address space. Based on src/sys/arch/amiga/dev/grf_cl.c from NetBSD. Signed-off-by: Geert Uytterhoeven Acked-by: Jeff Garzik Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 357139a..816433f 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -287,6 +287,7 @@ struct zorrocl { /* If zero, use autoprobe on RAM device */ u32 ramoffset; /* Offset of video RAM in first Zorro device */ zorro_id ramid; /* Zorro ID of RAM device */ + zorro_id ramid2; /* Zorro ID of optional second RAM device */ }; static const struct zorrocl zcl_sd64 __devinitconst = { @@ -316,6 +317,13 @@ static const struct zorrocl zcl_picasso4_z3 __devinitconst = { .ramoffset = 0x01000000, }; +static const struct zorrocl zcl_picasso4_z2 __devinitconst = { + .type = BT_PICASSO4, + .regoffset = 0x10000, + .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1, + .ramid2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM2, +}; + static const struct zorro_device_id cirrusfb_zorro_table[] __devinitconst = { { @@ -333,6 +341,9 @@ static const struct zorro_device_id cirrusfb_zorro_table[] __devinitconst = { }, { .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3, .driver_data = (unsigned long)&zcl_picasso4_z3, + }, { + .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG, + .driver_data = (unsigned long)&zcl_picasso4_z2, }, { 0 } }; @@ -2257,6 +2268,16 @@ static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, } rambase = zorro_resource_start(ram); ramsize = zorro_resource_len(ram); + if (zcl->ramid2 && + (ram = zorro_find_device(zcl->ramid2, NULL))) { + if (zorro_resource_start(ram) != rambase + ramsize) { + dev_warn(info->device, + "Skipping non-contiguous RAM at %pR\n", + &ram->resource); + } else { + ramsize += zorro_resource_len(ram); + } + } } dev_info(info->device, -- cgit v0.10.2 From e78bb882bf318bb41e17b33729cca3bdd26b42a0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Oct 2011 13:42:25 +0200 Subject: fbdev/cirrusfb: Add support for "64 MiB" version of Picasso IV Some Village Tronic Picasso IV graphics cards identify as a 64 MiB Zorro device in Zorro III mode. While the total graphics memory size is the same on such cards, the offset of the graphics memory differs. Add a quirk to handle this. Based on src/sys/arch/amiga/dev/grf_cl.c from NetBSD. Signed-off-by: Geert Uytterhoeven Acked-by: Jeff Garzik Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 816433f..6ea505c 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -314,7 +314,7 @@ static const struct zorrocl zcl_picasso4_z3 __devinitconst = { .type = BT_PICASSO4, .regoffset = 0x00600000, .ramsize = 4 * MB_, - .ramoffset = 0x01000000, + .ramoffset = 0x01000000, /* 0x02000000 for 64 MiB boards */ }; static const struct zorrocl zcl_picasso4_z2 __devinitconst = { @@ -2259,6 +2259,10 @@ static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, ramsize = zcl->ramsize; if (ramsize) { rambase = zorro_resource_start(z) + zcl->ramoffset; + if (zorro_resource_len(z) == 64 * MB_) { + /* Quirk for 64 MiB Picasso IV */ + rambase += zcl->ramoffset; + } } else { struct zorro_dev *ram = zorro_find_device(zcl->ramid, NULL); if (!ram || !zorro_resource_len(ram)) { -- cgit v0.10.2 From 4420dd2b306f1997232a13462bca0d420be5b1b8 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 7 Nov 2011 15:03:01 +0900 Subject: video: s3c-fb: fix transparency length for pixel blending Transparency length is fixed for pixel blending in order to support ARGB 8888 format. Signed-off-by: Jingoo Han Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 0753b1c..12eaee0 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -621,7 +621,8 @@ static int s3c_fb_set_par(struct fb_info *info) } else if (var->transp.length == 1) data |= WINCON1_BPPMODE_25BPP_A1888 | WINCON1_BLD_PIX; - else if (var->transp.length == 4) + else if ((var->transp.length == 4) || + (var->transp.length == 8)) data |= WINCON1_BPPMODE_28BPP_A4888 | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL; else -- cgit v0.10.2 From 2440f7aff46af4187d0518e92adaddf475aa82b0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 11 Nov 2011 20:26:03 -0200 Subject: [media] Properly implement ITU-T J.88 Annex C support The Annex C support were broken with the previous implementation, as, at xc5000 and tda18271c2dd, it were choosing the wrong bandwidth for some symbol rates. At DRX-J, it were always selecting Annex A, even having Annex C support coded there. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index aa1b2e8..88b329c 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -628,20 +628,12 @@ static void xc_debug_dump(struct xc5000_priv *priv) dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality); } -/* - * As defined on EN 300 429, the DVB-C roll-off factor is 0.15. - * So, the amount of the needed bandwith is given by: - * Bw = Symbol_rate * (1 + 0.15) - * As such, the maximum symbol rate supported by 6 MHz is given by: - * max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds - */ -#define MAX_SYMBOL_RATE_6MHz 5217391 - static int xc5000_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct xc5000_priv *priv = fe->tuner_priv; int ret; + u32 bw; if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) { @@ -707,11 +699,19 @@ static int xc5000_set_params(struct dvb_frontend *fe, dprintk(1, "%s() QAM modulation\n", __func__); priv->rf_mode = XC_RF_MODE_CABLE; /* - * Using a 8MHz bandwidth sometimes fail - * with 6MHz-spaced channels, due to inter-carrier - * interference. So, use DTV6 firmware + * Using a higher bandwidth at the tuner filter may + * allow inter-carrier interference. + * So, determine the minimal channel spacing, in order + * to better adjust the tuner filter. + * According with ITU-T J.83, the bandwidth is given by: + * bw = Simbol Rate * (1 + roll_off), where the roll_off + * is equal to 0.15 for Annex A, and 0.13 for annex C */ - if (params->u.qam.symbol_rate <= MAX_SYMBOL_RATE_6MHz) { + if (fe->dtv_property_cache.rolloff == ROLLOFF_13) + bw = (params->u.qam.symbol_rate * 13) / 10; + else + bw = (params->u.qam.symbol_rate * 15) / 10; + if (bw <= 6000000) { priv->bandwidth = BANDWIDTH_6_MHZ; priv->video_standard = DTV6; priv->freq_hz = params->frequency - 1750000; diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index f6431ef..dc13fd8 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -6218,6 +6218,13 @@ static int drxk_set_parameters(struct dvb_frontend *fe, return -EINVAL; } + if (state->m_OperationMode == OM_QAM_ITU_A || + state->m_OperationMode == OM_QAM_ITU_C) { + if (fe->dtv_property_cache.rolloff == ROLLOFF_13) + state->m_OperationMode = OM_QAM_ITU_C; + else + state->m_OperationMode = OM_QAM_ITU_A; + } if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); diff --git a/drivers/media/dvb/frontends/tda18271c2dd.c b/drivers/media/dvb/frontends/tda18271c2dd.c index 1b1bf20..de544f6 100644 --- a/drivers/media/dvb/frontends/tda18271c2dd.c +++ b/drivers/media/dvb/frontends/tda18271c2dd.c @@ -1123,20 +1123,6 @@ static int release(struct dvb_frontend *fe) return 0; } -/* - * As defined on EN 300 429 Annex A and on ITU-T J.83 annex A, the DVB-C - * roll-off factor is 0.15. - * According with the specs, the amount of the needed bandwith is given by: - * Bw = Symbol_rate * (1 + 0.15) - * As such, the maximum symbol rate supported by 6 MHz is - * max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds - *NOTE: For ITU-T J.83 Annex C, the roll-off factor is 0.13. So: - * max_symbol_rate = 6 MHz / 1.13 = 5309735 Baud - * That means that an adjustment is needed for Japan, - * but, as currently DRX-K is hardcoded to Annex A, let's stick - * with 0.15 roll-off factor. - */ -#define MAX_SYMBOL_RATE_6MHz 5217391 static int set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) @@ -1144,6 +1130,7 @@ static int set_params(struct dvb_frontend *fe, struct tda_state *state = fe->tuner_priv; int status = 0; int Standard; + u32 bw; state->m_Frequency = params->frequency; @@ -1161,8 +1148,23 @@ static int set_params(struct dvb_frontend *fe, break; } else if (fe->ops.info.type == FE_QAM) { - if (params->u.qam.symbol_rate <= MAX_SYMBOL_RATE_6MHz) + /* + * Using a higher bandwidth at the tuner filter may + * allow inter-carrier interference. + * So, determine the minimal channel spacing, in order + * to better adjust the tuner filter. + * According with ITU-T J.83, the bandwidth is given by: + * bw = Simbol Rate * (1 + roll_off), where the roll_off + * is equal to 0.15 for Annex A, and 0.13 for annex C + */ + if (fe->dtv_property_cache.rolloff == ROLLOFF_13) + bw = (params->u.qam.symbol_rate * 13) / 10; + else + bw = (params->u.qam.symbol_rate * 15) / 10; + if (bw <= 6000000) Standard = HF_DVBC_6MHZ; + else if (bw <= 7000000) + Standard = HF_DVBC_7MHZ; else Standard = HF_DVBC_8MHZ; } else -- cgit v0.10.2 From 358142dd8cbbfa2abb1090aca1b636b98ed75ef5 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 3 Nov 2011 10:09:57 -0700 Subject: scripts/tags.sh: Add Page flag function magic It takes a while to find the macro-magically defined Page*() functions defined in include/linux/page-flags.h if you're new to the kernel. Add some magic to the tags script to transform these macros into the actual functions they are, so that tag jumping in the mm code is a bit easier. Signed-off-by: Stephen Boyd Signed-off-by: Michal Marek diff --git a/scripts/tags.sh b/scripts/tags.sh index 38f6617..028dc5c 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -132,7 +132,28 @@ exuberant() --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \ --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \ --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \ - --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' + --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' \ + --regex-c++='/PAGEFLAG\(([^,)]*).*/Page\1/' \ + --regex-c++='/PAGEFLAG\(([^,)]*).*/SetPage\1/' \ + --regex-c++='/PAGEFLAG\(([^,)]*).*/ClearPage\1/' \ + --regex-c++='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/' \ + --regex-c++='/TESTPAGEFLAG\(([^,)]*).*/Page\1/' \ + --regex-c++='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/' \ + --regex-c++='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/' \ + --regex-c++='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex-c++='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex-c++='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/' \ + --regex-c++='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ + --regex-c++='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/' \ + --regex-c++='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ + --regex-c++='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/' \ + --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/' \ + --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex-c++='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/' \ + --regex-c++='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \ + --regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ + --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ + --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' all_kconfigs | xargs $1 -a \ --langdef=kconfig --language-force=kconfig \ @@ -154,7 +175,28 @@ emacs() --regex='/^(ENTRY|_GLOBAL)(\([^)]*\)).*/\2/' \ --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/' \ --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/' \ - --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' + --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' \ + --regex='/PAGEFLAG\(([^,)]*).*/Page\1/' \ + --regex='/PAGEFLAG\(([^,)]*).*/SetPage\1/' \ + --regex='/PAGEFLAG\(([^,)]*).*/ClearPage\1/' \ + --regex='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/' \ + --regex='/TESTPAGEFLAG\(([^,)]*).*/Page\1/' \ + --regex='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/' \ + --regex='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/' \ + --regex='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/' \ + --regex='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ + --regex='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/' \ + --regex='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ + --regex='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/' \ + --regex='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/' \ + --regex='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/' \ + --regex='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \ + --regex='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ + --regex='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ + --regex='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' all_kconfigs | xargs $1 -a \ --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/' -- cgit v0.10.2 From 353de31b86850309b205a3d4cc1294052471b14d Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 15 Nov 2011 19:25:03 -0500 Subject: nfsd4: fix CONFIG_NFSD_FAULT_INJECTION compile error Reported-by: Stephen Rothwell Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index dcbe7f3..7e4edbd 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4442,7 +4442,7 @@ static void release_openowner_sop(struct nfs4_stateowner *sop) release_openowner(openowner(sop)); } -static int nfsd_release_n_owners(u64 num, bool is_open_owner +static int nfsd_release_n_owners(u64 num, bool is_open_owner, void (*release_sop)(struct nfs4_stateowner *)) { int i, count = 0; -- cgit v0.10.2 From 009673b439cf74d70a486fca0177e274febd81a7 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 7 Nov 2011 17:40:10 -0500 Subject: nfsd4: add a separate (lockowner, inode) lookup Address the possible performance regression mentioned in "nfsd4: hash lockowners to simplify RELEASE_LOCKOWNER" by providing a separate (lockowner, inode) hash. Really, I doubt this matters much, but I think it's likely we'll change these data structures here and I'd rather that the need for (owner, inode) lookups be well-documented. Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 7e4edbd..a84978c 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -514,6 +514,7 @@ static void unhash_lockowner(struct nfs4_lockowner *lo) list_del(&lo->lo_owner.so_strhash); list_del(&lo->lo_perstateid); + list_del(&lo->lo_owner_ino_hash); while (!list_empty(&lo->lo_owner.so_stateids)) { stp = list_first_entry(&lo->lo_owner.so_stateids, struct nfs4_ol_stateid, st_perstateowner); @@ -3722,6 +3723,10 @@ out: #define LOFF_OVERFLOW(start, len) ((u64)(len) > ~(u64)(start)) +#define LOCKOWNER_INO_HASH_BITS 8 +#define LOCKOWNER_INO_HASH_SIZE (1 << LOCKOWNER_INO_HASH_BITS) +#define LOCKOWNER_INO_HASH_MASK (LOCKOWNER_INO_HASH_SIZE - 1) + static inline u64 end_offset(u64 start, u64 len) { @@ -3742,6 +3747,15 @@ last_byte_offset(u64 start, u64 len) return end > start ? end - 1: NFS4_MAX_UINT64; } +static unsigned int lockowner_ino_hashval(struct inode *inode, u32 cl_id, struct xdr_netobj *ownername) +{ + return (file_hashval(inode) + cl_id + + opaque_hashval(ownername->data, ownername->len)) + & LOCKOWNER_INO_HASH_MASK; +} + +static struct list_head lockowner_ino_hashtbl[LOCKOWNER_INO_HASH_SIZE]; + /* * TODO: Linux file offsets are _signed_ 64-bit quantities, which means that * we can't properly handle lock requests that go beyond the (2^63 - 1)-th @@ -3809,14 +3823,10 @@ static struct nfs4_lockowner * find_lockowner_str(struct inode *inode, clientid_t *clid, struct xdr_netobj *owner) { - unsigned int hashval = ownerstr_hashval(clid->cl_id, owner); + unsigned int hashval = lockowner_ino_hashval(inode, clid->cl_id, owner); struct nfs4_lockowner *lo; - struct nfs4_stateowner *op; - list_for_each_entry(op, &ownerstr_hashtbl[hashval], so_strhash) { - if (op->so_is_open_owner) - continue; - lo = lockowner(op); + list_for_each_entry(lo, &lockowner_ino_hashtbl[hashval], lo_owner_ino_hash) { if (same_lockowner_ino(lo, inode, clid, owner)) return lo; } @@ -3825,7 +3835,12 @@ find_lockowner_str(struct inode *inode, clientid_t *clid, static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, struct nfs4_client *clp, struct nfs4_ol_stateid *open_stp) { + struct inode *inode = open_stp->st_file->fi_inode; + unsigned int inohash = lockowner_ino_hashval(inode, + clp->cl_clientid.cl_id, &lo->lo_owner.so_owner); + list_add(&lo->lo_owner.so_strhash, &ownerstr_hashtbl[strhashval]); + list_add(&lo->lo_owner_ino_hash, &lockowner_ino_hashtbl[inohash]); list_add(&lo->lo_perstateid, &open_stp->st_lockowners); } @@ -4548,6 +4563,8 @@ nfs4_state_init(void) for (i = 0; i < OWNER_HASH_SIZE; i++) { INIT_LIST_HEAD(&ownerstr_hashtbl[i]); } + for (i = 0; i < LOCKOWNER_INO_HASH_SIZE; i++) + INIT_LIST_HEAD(&lockowner_ino_hashtbl[i]); memset(&onestateid, ~0, sizeof(stateid_t)); INIT_LIST_HEAD(&close_lru); INIT_LIST_HEAD(&client_lru); diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index a3cf384..89c2cd8 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -366,6 +366,7 @@ struct nfs4_openowner { struct nfs4_lockowner { struct nfs4_stateowner lo_owner; /* must be first element */ + struct list_head lo_owner_ino_hash; /* hash by owner,file */ struct list_head lo_perstateid; /* for lockowners only */ struct list_head lo_list; /* for temporary uses */ }; -- cgit v0.10.2 From 784a90c0a7d8f5aa94b6c7d295ad44ae8e045aa3 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 7 Nov 2011 12:36:48 +0100 Subject: ARM i.MX: Merge i.MX5 support into mach-imx This patch moves the contents of arch/arm/mach-mx5 to arch/arm/mach-imx and adjusts the Makefile/Kconfig entries in a way that it's possible to compile i.MX5 together with i.MX3/6. Signed-off-by: Sascha Hauer Tested-by: Shawn Guo Tested-by: Dirk Behme diff --git a/arch/arm/Makefile b/arch/arm/Makefile index dfcf3b0..cf7d467 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -160,7 +160,6 @@ machine-$(CONFIG_ARCH_MSM) := msm machine-$(CONFIG_ARCH_MV78XX0) := mv78xx0 machine-$(CONFIG_ARCH_IMX_V4_V5) := imx machine-$(CONFIG_ARCH_IMX_V6_V7) := imx -machine-$(CONFIG_ARCH_MX5) := mx5 machine-$(CONFIG_ARCH_MXS) := mxs machine-$(CONFIG_ARCH_NETX) := netx machine-$(CONFIG_ARCH_NOMADIK) := nomadik diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 5f7f9c2..ef6a6b8 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -33,6 +33,18 @@ config ARCH_MX31 config ARCH_MX35 bool +config ARCH_MX5 + bool + +config ARCH_MX50 + bool + +config ARCH_MX51 + bool + +config ARCH_MX53 + bool + config SOC_IMX1 bool select ARCH_MX1 @@ -86,6 +98,32 @@ config SOC_IMX35 select MXC_AVIC select SMP_ON_UP if SMP +config SOC_IMX5 + select CPU_V7 + select ARM_L1_CACHE_SHIFT_6 + select MXC_TZIC + select ARCH_MXC_IOMUX_V3 + select ARCH_MXC_AUDMUX_V2 + select ARCH_HAS_CPUFREQ + select ARCH_MX5 + bool + +config SOC_IMX50 + bool + select SOC_IMX5 + select ARCH_MX50 + +config SOC_IMX51 + bool + select SOC_IMX5 + select ARCH_MX5 + select ARCH_MX51 + +config SOC_IMX53 + bool + select SOC_IMX5 + select ARCH_MX5 + select ARCH_MX53 if ARCH_IMX_V4_V5 @@ -604,6 +642,207 @@ config MACH_VPR200 Include support for VPR200 platform. This includes specific configurations for the board and its peripherals. +comment "i.MX5 platforms:" + +config MACH_MX50_RDP + bool "Support MX50 reference design platform" + depends on BROKEN + select SOC_IMX50 + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_SPI_IMX + help + Include support for MX50 reference design platform (RDP) board. This + includes specific configurations for the board and its peripherals. + +comment "i.MX51 machines:" + +config MACH_IMX51_DT + bool "Support i.MX51 platforms from device tree" + select SOC_IMX51 + select USE_OF + select MACH_MX51_BABBAGE + help + Include support for Freescale i.MX51 based platforms + using the device tree for discovery + +config MACH_MX51_BABBAGE + bool "Support MX51 BABBAGE platforms" + select SOC_IMX51 + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_SPI_IMX + help + Include support for MX51 Babbage platform, also known as MX51EVK in + u-boot. This includes specific configurations for the board and its + peripherals. + +config MACH_MX51_3DS + bool "Support MX51PDK (3DS)" + select SOC_IMX51 + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_KEYPAD + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_SPI_IMX + select MXC_DEBUG_BOARD + help + Include support for MX51PDK (3DS) platform. This includes specific + configurations for the board and its peripherals. + +config MACH_EUKREA_CPUIMX51 + bool "Support Eukrea CPUIMX51 module" + select SOC_IMX51 + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_SPI_IMX + help + Include support for Eukrea CPUIMX51 platform. This includes + specific configurations for the module and its peripherals. + +choice + prompt "Baseboard" + depends on MACH_EUKREA_CPUIMX51 + default MACH_EUKREA_MBIMX51_BASEBOARD + +config MACH_EUKREA_MBIMX51_BASEBOARD + prompt "Eukrea MBIMX51 development board" + bool + select IMX_HAVE_PLATFORM_IMX_KEYPAD + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select LEDS_GPIO_REGISTER + help + This adds board specific devices that can be found on Eukrea's + MBIMX51 evaluation board. + +endchoice + +config MACH_EUKREA_CPUIMX51SD + bool "Support Eukrea CPUIMX51SD module" + select SOC_IMX51 + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_SPI_IMX + help + Include support for Eukrea CPUIMX51SD platform. This includes + specific configurations for the module and its peripherals. + +choice + prompt "Baseboard" + depends on MACH_EUKREA_CPUIMX51SD + default MACH_EUKREA_MBIMXSD51_BASEBOARD + +config MACH_EUKREA_MBIMXSD51_BASEBOARD + prompt "Eukrea MBIMXSD development board" + bool + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select LEDS_GPIO_REGISTER + help + This adds board specific devices that can be found on Eukrea's + MBIMXSD evaluation board. + +endchoice + +config MX51_EFIKA_COMMON + bool + select SOC_IMX51 + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_PATA_IMX + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_SPI_IMX + select MXC_ULPI if USB_ULPI + +config MACH_MX51_EFIKAMX + bool "Support MX51 Genesi Efika MX nettop" + select LEDS_GPIO_REGISTER + select MX51_EFIKA_COMMON + help + Include support for Genesi Efika MX nettop. This includes specific + configurations for the board and its peripherals. + +config MACH_MX51_EFIKASB + bool "Support MX51 Genesi Efika Smartbook" + select LEDS_GPIO_REGISTER + select MX51_EFIKA_COMMON + help + Include support for Genesi Efika Smartbook. This includes specific + configurations for the board and its peripherals. + +comment "i.MX53 machines:" + +config MACH_IMX53_DT + bool "Support i.MX53 platforms from device tree" + select SOC_IMX53 + select USE_OF + select MACH_MX53_ARD + select MACH_MX53_EVK + select MACH_MX53_LOCO + select MACH_MX53_SMD + help + Include support for Freescale i.MX53 based platforms + using the device tree for discovery + +config MACH_MX53_EVK + bool "Support MX53 EVK platforms" + select SOC_IMX53 + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_SPI_IMX + select LEDS_GPIO_REGISTER + help + Include support for MX53 EVK platform. This includes specific + configurations for the board and its peripherals. + +config MACH_MX53_SMD + bool "Support MX53 SMD platforms" + select SOC_IMX53 + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + help + Include support for MX53 SMD platform. This includes specific + configurations for the board and its peripherals. + +config MACH_MX53_LOCO + bool "Support MX53 LOCO platforms" + select SOC_IMX53 + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_GPIO_KEYS + select LEDS_GPIO_REGISTER + help + Include support for MX53 LOCO platform. This includes specific + configurations for the board and its peripherals. + +config MACH_MX53_ARD + bool "Support MX53 ARD platforms" + select SOC_IMX53 + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_GPIO_KEYS + help + Include support for MX53 ARD platform. This includes specific + configurations for the board and its peripherals. + comment "i.MX6 family:" config SOC_IMX6Q diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index aba7321..9cf630a 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -11,6 +11,8 @@ obj-$(CONFIG_SOC_IMX27) += clock-imx27.o mm-imx27.o ehci-imx27.o obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o +obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o + # Support for CMOS sensor interface obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o @@ -71,3 +73,22 @@ obj-$(CONFIG_SMP) += platsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o pm-imx6q.o + +# i.MX5 based machines +obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o +obj-$(CONFIG_MACH_MX51_3DS) += mach-mx51_3ds.o +obj-$(CONFIG_MACH_MX53_EVK) += mach-mx53_evk.o +obj-$(CONFIG_MACH_MX53_SMD) += mach-mx53_smd.o +obj-$(CONFIG_MACH_MX53_LOCO) += mach-mx53_loco.o +obj-$(CONFIG_MACH_MX53_ARD) += mach-mx53_ard.o +obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += mach-cpuimx51.o +obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o +obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += mach-cpuimx51sd.o +obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o +obj-$(CONFIG_MX51_EFIKA_COMMON) += mx51_efika.o +obj-$(CONFIG_MACH_MX51_EFIKAMX) += mach-mx51_efikamx.o +obj-$(CONFIG_MACH_MX51_EFIKASB) += mach-mx51_efikasb.o +obj-$(CONFIG_MACH_MX50_RDP) += mach-mx50_rdp.o + +obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o +obj-$(CONFIG_MACH_IMX53_DT) += imx53-dt.o diff --git a/arch/arm/mach-imx/Makefile.boot b/arch/arm/mach-imx/Makefile.boot index 22d8588..2c12b78 100644 --- a/arch/arm/mach-imx/Makefile.boot +++ b/arch/arm/mach-imx/Makefile.boot @@ -18,6 +18,18 @@ zreladdr-$(CONFIG_ARCH_MX3) += 0x80008000 params_phys-$(CONFIG_ARCH_MX3) := 0x80000100 initrd_phys-$(CONFIG_ARCH_MX3) := 0x80800000 +zreladdr-$(CONFIG_SOC_IMX50) += 0x70008000 +params_phys-$(CONFIG_SOC_IMX50) := 0x70000100 +initrd_phys-$(CONFIG_SOC_IMX50) := 0x70800000 + +zreladdr-$(CONFIG_SOC_IMX51) += 0x90008000 +params_phys-$(CONFIG_SOC_IMX51) := 0x90000100 +initrd_phys-$(CONFIG_SOC_IMX51) := 0x90800000 + +zreladdr-$(CONFIG_SOC_IMX53) += 0x70008000 +params_phys-$(CONFIG_SOC_IMX53) := 0x70000100 +initrd_phys-$(CONFIG_SOC_IMX53) := 0x70800000 + zreladdr-$(CONFIG_SOC_IMX6Q) += 0x10008000 params_phys-$(CONFIG_SOC_IMX6Q) := 0x10000100 initrd_phys-$(CONFIG_SOC_IMX6Q) := 0x10800000 diff --git a/arch/arm/mach-imx/clock-mx51-mx53.c b/arch/arm/mach-imx/clock-mx51-mx53.c new file mode 100644 index 0000000..a2c654d --- /dev/null +++ b/arch/arm/mach-imx/clock-mx51-mx53.c @@ -0,0 +1,1673 @@ +/* + * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2009-2010 Amit Kucheria + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "crm-regs-imx5.h" + +/* External clock values passed-in by the board code */ +static unsigned long external_high_reference, external_low_reference; +static unsigned long oscillator_reference, ckih2_reference; + +static struct clk osc_clk; +static struct clk pll1_main_clk; +static struct clk pll1_sw_clk; +static struct clk pll2_sw_clk; +static struct clk pll3_sw_clk; +static struct clk mx53_pll4_sw_clk; +static struct clk lp_apm_clk; +static struct clk periph_apm_clk; +static struct clk ahb_clk; +static struct clk ipg_clk; +static struct clk usboh3_clk; +static struct clk emi_fast_clk; +static struct clk ipu_clk; +static struct clk mipi_hsc1_clk; +static struct clk esdhc1_clk; +static struct clk esdhc2_clk; +static struct clk esdhc3_mx53_clk; + +#define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */ + +/* calculate best pre and post dividers to get the required divider */ +static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post, + u32 max_pre, u32 max_post) +{ + if (div >= max_pre * max_post) { + *pre = max_pre; + *post = max_post; + } else if (div >= max_pre) { + u32 min_pre, temp_pre, old_err, err; + min_pre = DIV_ROUND_UP(div, max_post); + old_err = max_pre; + for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) { + err = div % temp_pre; + if (err == 0) { + *pre = temp_pre; + break; + } + err = temp_pre - err; + if (err < old_err) { + old_err = err; + *pre = temp_pre; + } + } + *post = DIV_ROUND_UP(div, *pre); + } else { + *pre = div; + *post = 1; + } +} + +static void _clk_ccgr_setclk(struct clk *clk, unsigned mode) +{ + u32 reg = __raw_readl(clk->enable_reg); + + reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift); + reg |= mode << clk->enable_shift; + + __raw_writel(reg, clk->enable_reg); +} + +static int _clk_ccgr_enable(struct clk *clk) +{ + _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON); + return 0; +} + +static void _clk_ccgr_disable(struct clk *clk) +{ + _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF); +} + +static int _clk_ccgr_enable_inrun(struct clk *clk) +{ + _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE); + return 0; +} + +static void _clk_ccgr_disable_inwait(struct clk *clk) +{ + _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE); +} + +/* + * For the 4-to-1 muxed input clock + */ +static inline u32 _get_mux(struct clk *parent, struct clk *m0, + struct clk *m1, struct clk *m2, struct clk *m3) +{ + if (parent == m0) + return 0; + else if (parent == m1) + return 1; + else if (parent == m2) + return 2; + else if (parent == m3) + return 3; + else + BUG(); + + return -EINVAL; +} + +static inline void __iomem *_mx51_get_pll_base(struct clk *pll) +{ + if (pll == &pll1_main_clk) + return MX51_DPLL1_BASE; + else if (pll == &pll2_sw_clk) + return MX51_DPLL2_BASE; + else if (pll == &pll3_sw_clk) + return MX51_DPLL3_BASE; + else + BUG(); + + return NULL; +} + +static inline void __iomem *_mx53_get_pll_base(struct clk *pll) +{ + if (pll == &pll1_main_clk) + return MX53_DPLL1_BASE; + else if (pll == &pll2_sw_clk) + return MX53_DPLL2_BASE; + else if (pll == &pll3_sw_clk) + return MX53_DPLL3_BASE; + else if (pll == &mx53_pll4_sw_clk) + return MX53_DPLL4_BASE; + else + BUG(); + + return NULL; +} + +static inline void __iomem *_get_pll_base(struct clk *pll) +{ + if (cpu_is_mx51()) + return _mx51_get_pll_base(pll); + else + return _mx53_get_pll_base(pll); +} + +static unsigned long clk_pll_get_rate(struct clk *clk) +{ + long mfi, mfn, mfd, pdf, ref_clk, mfn_abs; + unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl; + void __iomem *pllbase; + s64 temp; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + pllbase = _get_pll_base(clk); + + dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); + pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM; + dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN; + + if (pll_hfsm == 0) { + dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP); + dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD); + dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN); + } else { + dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP); + dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD); + dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN); + } + pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK; + mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET; + mfi = (mfi <= 5) ? 5 : mfi; + mfd = dp_mfd & MXC_PLL_DP_MFD_MASK; + mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK; + /* Sign extend to 32-bits */ + if (mfn >= 0x04000000) { + mfn |= 0xFC000000; + mfn_abs = -mfn; + } + + ref_clk = 2 * parent_rate; + if (dbl != 0) + ref_clk *= 2; + + ref_clk /= (pdf + 1); + temp = (u64) ref_clk * mfn_abs; + do_div(temp, mfd + 1); + if (mfn < 0) + temp = -temp; + temp = (ref_clk * mfi) + temp; + + return temp; +} + +static int _clk_pll_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + void __iomem *pllbase; + + long mfi, pdf, mfn, mfd = 999999; + s64 temp64; + unsigned long quad_parent_rate; + unsigned long pll_hfsm, dp_ctl; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + pllbase = _get_pll_base(clk); + + quad_parent_rate = 4 * parent_rate; + pdf = mfi = -1; + while (++pdf < 16 && mfi < 5) + mfi = rate * (pdf+1) / quad_parent_rate; + if (mfi > 15) + return -EINVAL; + pdf--; + + temp64 = rate * (pdf+1) - quad_parent_rate * mfi; + do_div(temp64, quad_parent_rate/1000000); + mfn = (long)temp64; + + dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); + /* use dpdck0_2 */ + __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL); + pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM; + if (pll_hfsm == 0) { + reg = mfi << 4 | pdf; + __raw_writel(reg, pllbase + MXC_PLL_DP_OP); + __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD); + __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN); + } else { + reg = mfi << 4 | pdf; + __raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP); + __raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD); + __raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN); + } + + return 0; +} + +static int _clk_pll_enable(struct clk *clk) +{ + u32 reg; + void __iomem *pllbase; + int i = 0; + + pllbase = _get_pll_base(clk); + reg = __raw_readl(pllbase + MXC_PLL_DP_CTL); + if (reg & MXC_PLL_DP_CTL_UPEN) + return 0; + + reg |= MXC_PLL_DP_CTL_UPEN; + __raw_writel(reg, pllbase + MXC_PLL_DP_CTL); + + /* Wait for lock */ + do { + reg = __raw_readl(pllbase + MXC_PLL_DP_CTL); + if (reg & MXC_PLL_DP_CTL_LRF) + break; + + udelay(1); + } while (++i < MAX_DPLL_WAIT_TRIES); + + if (i == MAX_DPLL_WAIT_TRIES) { + pr_err("MX5: pll locking failed\n"); + return -EINVAL; + } + + return 0; +} + +static void _clk_pll_disable(struct clk *clk) +{ + u32 reg; + void __iomem *pllbase; + + pllbase = _get_pll_base(clk); + reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN; + __raw_writel(reg, pllbase + MXC_PLL_DP_CTL); +} + +static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, step; + + reg = __raw_readl(MXC_CCM_CCSR); + + /* When switching from pll_main_clk to a bypass clock, first select a + * multiplexed clock in 'step_sel', then shift the glitchless mux + * 'pll1_sw_clk_sel'. + * + * When switching back, do it in reverse order + */ + if (parent == &pll1_main_clk) { + /* Switch to pll1_main_clk */ + reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL; + __raw_writel(reg, MXC_CCM_CCSR); + /* step_clk mux switched to lp_apm, to save power. */ + reg = __raw_readl(MXC_CCM_CCSR); + reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK; + reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM << + MXC_CCM_CCSR_STEP_SEL_OFFSET); + } else { + if (parent == &lp_apm_clk) { + step = MXC_CCM_CCSR_STEP_SEL_LP_APM; + } else if (parent == &pll2_sw_clk) { + step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED; + } else if (parent == &pll3_sw_clk) { + step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED; + } else + return -EINVAL; + + reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK; + reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET); + + __raw_writel(reg, MXC_CCM_CCSR); + /* Switch to step_clk */ + reg = __raw_readl(MXC_CCM_CCSR); + reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL; + } + __raw_writel(reg, MXC_CCM_CCSR); + return 0; +} + +static unsigned long clk_pll1_sw_get_rate(struct clk *clk) +{ + u32 reg, div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + reg = __raw_readl(MXC_CCM_CCSR); + + if (clk->parent == &pll2_sw_clk) { + div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >> + MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1; + } else if (clk->parent == &pll3_sw_clk) { + div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >> + MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1; + } else + div = 1; + return parent_rate / div; +} + +static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CCSR); + + if (parent == &pll2_sw_clk) + reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL; + else + reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL; + + __raw_writel(reg, MXC_CCM_CCSR); + return 0; +} + +static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + if (parent == &osc_clk) + reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL; + else + return -EINVAL; + + __raw_writel(reg, MXC_CCM_CCSR); + + return 0; +} + +static unsigned long clk_cpu_get_rate(struct clk *clk) +{ + u32 cacrr, div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + cacrr = __raw_readl(MXC_CCM_CACRR); + div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1; + + return parent_rate / div; +} + +static int clk_cpu_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, cpu_podf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + cpu_podf = parent_rate / rate - 1; + /* use post divider to change freq */ + reg = __raw_readl(MXC_CCM_CACRR); + reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK; + reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_CACRR); + + return 0; +} + +static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + int i = 0; + + mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL); + + reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK; + reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET; + __raw_writel(reg, MXC_CCM_CBCMR); + + /* Wait for lock */ + do { + reg = __raw_readl(MXC_CCM_CDHIPR); + if (!(reg & MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY)) + break; + + udelay(1); + } while (++i < MAX_DPLL_WAIT_TRIES); + + if (i == MAX_DPLL_WAIT_TRIES) { + pr_err("MX5: Set parent for periph_apm clock failed\n"); + return -EINVAL; + } + + return 0; +} + +static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CBCDR); + + if (parent == &pll2_sw_clk) + reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL; + else if (parent == &periph_apm_clk) + reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL; + else + return -EINVAL; + + __raw_writel(reg, MXC_CCM_CBCDR); + + return 0; +} + +static struct clk main_bus_clk = { + .parent = &pll2_sw_clk, + .set_parent = _clk_main_bus_set_parent, +}; + +static unsigned long clk_ahb_get_rate(struct clk *clk) +{ + u32 reg, div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >> + MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1; + return parent_rate / div; +} + + +static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, div; + unsigned long parent_rate; + int i = 0; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + if (div > 8 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + + reg = __raw_readl(MXC_CCM_CBCDR); + reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK; + reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_CBCDR); + + /* Wait for lock */ + do { + reg = __raw_readl(MXC_CCM_CDHIPR); + if (!(reg & MXC_CCM_CDHIPR_AHB_PODF_BUSY)) + break; + + udelay(1); + } while (++i < MAX_DPLL_WAIT_TRIES); + + if (i == MAX_DPLL_WAIT_TRIES) { + pr_err("MX5: clk_ahb_set_rate failed\n"); + return -EINVAL; + } + + return 0; +} + +static unsigned long _clk_ahb_round_rate(struct clk *clk, + unsigned long rate) +{ + u32 div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + if (div > 8) + div = 8; + else if (div == 0) + div++; + return parent_rate / div; +} + + +static int _clk_max_enable(struct clk *clk) +{ + u32 reg; + + _clk_ccgr_enable(clk); + + /* Handshake with MAX when LPM is entered. */ + reg = __raw_readl(MXC_CCM_CLPCR); + if (cpu_is_mx51()) + reg &= ~MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS; + else if (cpu_is_mx53()) + reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); + + return 0; +} + +static void _clk_max_disable(struct clk *clk) +{ + u32 reg; + + _clk_ccgr_disable_inwait(clk); + + /* No Handshake with MAX when LPM is entered as its disabled. */ + reg = __raw_readl(MXC_CCM_CLPCR); + if (cpu_is_mx51()) + reg |= MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS; + else if (cpu_is_mx53()) + reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); +} + +static unsigned long clk_ipg_get_rate(struct clk *clk) +{ + u32 reg, div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >> + MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1; + + return parent_rate / div; +} + +static unsigned long clk_ipg_per_get_rate(struct clk *clk) +{ + u32 reg, prediv1, prediv2, podf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) { + /* the main_bus_clk is the one before the DVFS engine */ + reg = __raw_readl(MXC_CCM_CBCDR); + prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >> + MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1; + prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >> + MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1; + podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >> + MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1; + return parent_rate / (prediv1 * prediv2 * podf); + } else if (clk->parent == &ipg_clk) + return parent_rate; + else + BUG(); +} + +static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CBCMR); + + reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL; + reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL; + + if (parent == &ipg_clk) + reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL; + else if (parent == &lp_apm_clk) + reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL; + else if (parent != &main_bus_clk) + return -EINVAL; + + __raw_writel(reg, MXC_CCM_CBCMR); + + return 0; +} + +#define clk_nfc_set_parent NULL + +static unsigned long clk_nfc_get_rate(struct clk *clk) +{ + unsigned long rate; + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >> + MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1; + rate = clk_get_rate(clk->parent) / div; + WARN_ON(rate == 0); + return rate; +} + +static unsigned long clk_nfc_round_rate(struct clk *clk, + unsigned long rate) +{ + u32 div; + unsigned long parent_rate = clk_get_rate(clk->parent); + + if (!rate) + return -EINVAL; + + div = parent_rate / rate; + + if (parent_rate % rate) + div++; + + if (div > 8) + return -EINVAL; + + return parent_rate / div; + +} + +static int clk_nfc_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, div; + + div = clk_get_rate(clk->parent) / rate; + if (div == 0) + div++; + if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8)) + return -EINVAL; + + reg = __raw_readl(MXC_CCM_CBCDR); + reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK; + reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_CBCDR); + + while (__raw_readl(MXC_CCM_CDHIPR) & + MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){ + } + + return 0; +} + +static unsigned long get_high_reference_clock_rate(struct clk *clk) +{ + return external_high_reference; +} + +static unsigned long get_low_reference_clock_rate(struct clk *clk) +{ + return external_low_reference; +} + +static unsigned long get_oscillator_reference_clock_rate(struct clk *clk) +{ + return oscillator_reference; +} + +static unsigned long get_ckih2_reference_clock_rate(struct clk *clk) +{ + return ckih2_reference; +} + +static unsigned long clk_emi_slow_get_rate(struct clk *clk) +{ + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >> + MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1; + + return clk_get_rate(clk->parent) / div; +} + +static unsigned long _clk_ddr_hf_get_rate(struct clk *clk) +{ + unsigned long rate; + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >> + MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1; + rate = clk_get_rate(clk->parent) / div; + + return rate; +} + +/* External high frequency clock */ +static struct clk ckih_clk = { + .get_rate = get_high_reference_clock_rate, +}; + +static struct clk ckih2_clk = { + .get_rate = get_ckih2_reference_clock_rate, +}; + +static struct clk osc_clk = { + .get_rate = get_oscillator_reference_clock_rate, +}; + +/* External low frequency (32kHz) clock */ +static struct clk ckil_clk = { + .get_rate = get_low_reference_clock_rate, +}; + +static struct clk pll1_main_clk = { + .parent = &osc_clk, + .get_rate = clk_pll_get_rate, + .enable = _clk_pll_enable, + .disable = _clk_pll_disable, +}; + +/* Clock tree block diagram (WIP): + * CCM: Clock Controller Module + * + * PLL output -> | + * | CCM Switcher -> CCM_CLK_ROOT_GEN -> + * PLL bypass -> | + * + */ + +/* PLL1 SW supplies to ARM core */ +static struct clk pll1_sw_clk = { + .parent = &pll1_main_clk, + .set_parent = _clk_pll1_sw_set_parent, + .get_rate = clk_pll1_sw_get_rate, +}; + +/* PLL2 SW supplies to AXI/AHB/IP buses */ +static struct clk pll2_sw_clk = { + .parent = &osc_clk, + .get_rate = clk_pll_get_rate, + .set_rate = _clk_pll_set_rate, + .set_parent = _clk_pll2_sw_set_parent, + .enable = _clk_pll_enable, + .disable = _clk_pll_disable, +}; + +/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */ +static struct clk pll3_sw_clk = { + .parent = &osc_clk, + .set_rate = _clk_pll_set_rate, + .get_rate = clk_pll_get_rate, + .enable = _clk_pll_enable, + .disable = _clk_pll_disable, +}; + +/* PLL4 SW supplies to LVDS Display Bridge(LDB) */ +static struct clk mx53_pll4_sw_clk = { + .parent = &osc_clk, + .set_rate = _clk_pll_set_rate, + .enable = _clk_pll_enable, + .disable = _clk_pll_disable, +}; + +/* Low-power Audio Playback Mode clock */ +static struct clk lp_apm_clk = { + .parent = &osc_clk, + .set_parent = _clk_lp_apm_set_parent, +}; + +static struct clk periph_apm_clk = { + .parent = &pll1_sw_clk, + .set_parent = _clk_periph_apm_set_parent, +}; + +static struct clk cpu_clk = { + .parent = &pll1_sw_clk, + .get_rate = clk_cpu_get_rate, + .set_rate = clk_cpu_set_rate, +}; + +static struct clk ahb_clk = { + .parent = &main_bus_clk, + .get_rate = clk_ahb_get_rate, + .set_rate = _clk_ahb_set_rate, + .round_rate = _clk_ahb_round_rate, +}; + +static struct clk iim_clk = { + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET, +}; + +/* Main IP interface clock for access to registers */ +static struct clk ipg_clk = { + .parent = &ahb_clk, + .get_rate = clk_ipg_get_rate, +}; + +static struct clk ipg_perclk = { + .parent = &lp_apm_clk, + .get_rate = clk_ipg_per_get_rate, + .set_parent = _clk_ipg_per_set_parent, +}; + +static struct clk ahb_max_clk = { + .parent = &ahb_clk, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET, + .enable = _clk_max_enable, + .disable = _clk_max_disable, +}; + +static struct clk aips_tz1_clk = { + .parent = &ahb_clk, + .secondary = &ahb_max_clk, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET, + .enable = _clk_ccgr_enable, + .disable = _clk_ccgr_disable_inwait, +}; + +static struct clk aips_tz2_clk = { + .parent = &ahb_clk, + .secondary = &ahb_max_clk, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET, + .enable = _clk_ccgr_enable, + .disable = _clk_ccgr_disable_inwait, +}; + +static struct clk gpc_dvfs_clk = { + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET, + .enable = _clk_ccgr_enable, + .disable = _clk_ccgr_disable, +}; + +static struct clk gpt_32k_clk = { + .id = 0, + .parent = &ckil_clk, +}; + +static struct clk dummy_clk = { + .id = 0, +}; + +static struct clk emi_slow_clk = { + .parent = &pll2_sw_clk, + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET, + .enable = _clk_ccgr_enable, + .disable = _clk_ccgr_disable_inwait, + .get_rate = clk_emi_slow_get_rate, +}; + +static int clk_ipu_enable(struct clk *clk) +{ + u32 reg; + + _clk_ccgr_enable(clk); + + /* Enable handshake with IPU when certain clock rates are changed */ + reg = __raw_readl(MXC_CCM_CCDR); + reg &= ~MXC_CCM_CCDR_IPU_HS_MASK; + __raw_writel(reg, MXC_CCM_CCDR); + + /* Enable handshake with IPU when LPM is entered */ + reg = __raw_readl(MXC_CCM_CLPCR); + reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); + + return 0; +} + +static void clk_ipu_disable(struct clk *clk) +{ + u32 reg; + + _clk_ccgr_disable(clk); + + /* Disable handshake with IPU whe dividers are changed */ + reg = __raw_readl(MXC_CCM_CCDR); + reg |= MXC_CCM_CCDR_IPU_HS_MASK; + __raw_writel(reg, MXC_CCM_CCDR); + + /* Disable handshake with IPU when LPM is entered */ + reg = __raw_readl(MXC_CCM_CLPCR); + reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); +} + +static struct clk ahbmux1_clk = { + .parent = &ahb_clk, + .secondary = &ahb_max_clk, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET, + .enable = _clk_ccgr_enable, + .disable = _clk_ccgr_disable_inwait, +}; + +static struct clk ipu_sec_clk = { + .parent = &emi_fast_clk, + .secondary = &ahbmux1_clk, +}; + +static struct clk ddr_hf_clk = { + .parent = &pll1_sw_clk, + .get_rate = _clk_ddr_hf_get_rate, +}; + +static struct clk ddr_clk = { + .parent = &ddr_hf_clk, +}; + +/* clock definitions for MIPI HSC unit which has been removed + * from documentation, but not from hardware + */ +static int _clk_hsc_enable(struct clk *clk) +{ + u32 reg; + + _clk_ccgr_enable(clk); + /* Handshake with IPU when certain clock rates are changed. */ + reg = __raw_readl(MXC_CCM_CCDR); + reg &= ~MXC_CCM_CCDR_HSC_HS_MASK; + __raw_writel(reg, MXC_CCM_CCDR); + + reg = __raw_readl(MXC_CCM_CLPCR); + reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); + + return 0; +} + +static void _clk_hsc_disable(struct clk *clk) +{ + u32 reg; + + _clk_ccgr_disable(clk); + /* No handshake with HSC as its not enabled. */ + reg = __raw_readl(MXC_CCM_CCDR); + reg |= MXC_CCM_CCDR_HSC_HS_MASK; + __raw_writel(reg, MXC_CCM_CCDR); + + reg = __raw_readl(MXC_CCM_CLPCR); + reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); +} + +static struct clk mipi_hsp_clk = { + .parent = &ipu_clk, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET, + .enable = _clk_hsc_enable, + .disable = _clk_hsc_disable, + .secondary = &mipi_hsc1_clk, +}; + +#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = pfx##_get_rate, \ + .set_rate = pfx##_set_rate, \ + .round_rate = pfx##_round_rate, \ + .set_parent = pfx##_set_parent, \ + .enable = _clk_ccgr_enable, \ + .disable = _clk_ccgr_disable, \ + .parent = p, \ + .secondary = s, \ + } + +#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = pfx##_get_rate, \ + .set_rate = pfx##_set_rate, \ + .set_parent = pfx##_set_parent, \ + .enable = _clk_max_enable, \ + .disable = _clk_max_disable, \ + .parent = p, \ + .secondary = s, \ + } + +#define CLK_GET_RATE(name, nr, bitsname) \ +static unsigned long clk_##name##_get_rate(struct clk *clk) \ +{ \ + u32 reg, pred, podf; \ + \ + reg = __raw_readl(MXC_CCM_CSCDR##nr); \ + pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK) \ + >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \ + podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK) \ + >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \ + \ + return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), \ + (pred + 1) * (podf + 1)); \ +} + +#define CLK_SET_PARENT(name, nr, bitsname) \ +static int clk_##name##_set_parent(struct clk *clk, struct clk *parent) \ +{ \ + u32 reg, mux; \ + \ + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, \ + &pll3_sw_clk, &lp_apm_clk); \ + reg = __raw_readl(MXC_CCM_CSCMR##nr) & \ + ~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK; \ + reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET; \ + __raw_writel(reg, MXC_CCM_CSCMR##nr); \ + \ + return 0; \ +} + +#define CLK_SET_RATE(name, nr, bitsname) \ +static int clk_##name##_set_rate(struct clk *clk, unsigned long rate) \ +{ \ + u32 reg, div, parent_rate; \ + u32 pre = 0, post = 0; \ + \ + parent_rate = clk_get_rate(clk->parent); \ + div = parent_rate / rate; \ + \ + if ((parent_rate / div) != rate) \ + return -EINVAL; \ + \ + __calc_pre_post_dividers(div, &pre, &post, \ + (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >> \ + MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1, \ + (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >> \ + MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\ + \ + /* Set sdhc1 clock divider */ \ + reg = __raw_readl(MXC_CCM_CSCDR##nr) & \ + ~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK \ + | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK); \ + reg |= (post - 1) << \ + MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \ + reg |= (pre - 1) << \ + MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \ + __raw_writel(reg, MXC_CCM_CSCDR##nr); \ + \ + return 0; \ +} + +/* UART */ +CLK_GET_RATE(uart, 1, UART) +CLK_SET_PARENT(uart, 1, UART) + +static struct clk uart_root_clk = { + .parent = &pll2_sw_clk, + .get_rate = clk_uart_get_rate, + .set_parent = clk_uart_set_parent, +}; + +/* USBOH3 */ +CLK_GET_RATE(usboh3, 1, USBOH3) +CLK_SET_PARENT(usboh3, 1, USBOH3) + +static struct clk usboh3_clk = { + .parent = &pll2_sw_clk, + .get_rate = clk_usboh3_get_rate, + .set_parent = clk_usboh3_set_parent, + .enable = _clk_ccgr_enable, + .disable = _clk_ccgr_disable, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET, +}; + +static struct clk usb_ahb_clk = { + .parent = &ipg_clk, + .enable = _clk_ccgr_enable, + .disable = _clk_ccgr_disable, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET, +}; + +static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL; + + if (parent == &pll3_sw_clk) + reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET; + + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static struct clk usb_phy1_clk = { + .parent = &pll3_sw_clk, + .set_parent = clk_usb_phy1_set_parent, + .enable = _clk_ccgr_enable, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET, + .disable = _clk_ccgr_disable, +}; + +/* eCSPI */ +CLK_GET_RATE(ecspi, 2, CSPI) +CLK_SET_PARENT(ecspi, 1, CSPI) + +static struct clk ecspi_main_clk = { + .parent = &pll3_sw_clk, + .get_rate = clk_ecspi_get_rate, + .set_parent = clk_ecspi_set_parent, +}; + +/* eSDHC */ +CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1) +CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1) +CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1) + +/* mx51 specific */ +CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2) +CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2) +CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2) + +static int clk_esdhc3_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCMR1); + if (parent == &esdhc1_clk) + reg &= ~MXC_CCM_CSCMR1_ESDHC3_CLK_SEL; + else if (parent == &esdhc2_clk) + reg |= MXC_CCM_CSCMR1_ESDHC3_CLK_SEL; + else + return -EINVAL; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static int clk_esdhc4_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCMR1); + if (parent == &esdhc1_clk) + reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL; + else if (parent == &esdhc2_clk) + reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL; + else + return -EINVAL; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +/* mx53 specific */ +static int clk_esdhc2_mx53_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCMR1); + if (parent == &esdhc1_clk) + reg &= ~MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL; + else if (parent == &esdhc3_mx53_clk) + reg |= MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL; + else + return -EINVAL; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +CLK_GET_RATE(esdhc3_mx53, 1, ESDHC3_MX53) +CLK_SET_PARENT(esdhc3_mx53, 1, ESDHC3_MX53) +CLK_SET_RATE(esdhc3_mx53, 1, ESDHC3_MX53) + +static int clk_esdhc4_mx53_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCMR1); + if (parent == &esdhc1_clk) + reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL; + else if (parent == &esdhc3_mx53_clk) + reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL; + else + return -EINVAL; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = gr, \ + .set_rate = sr, \ + .enable = e, \ + .disable = d, \ + .parent = p, \ + .secondary = s, \ + } + +#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s) \ + DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s) + +/* Shared peripheral bus arbiter */ +DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET, + NULL, NULL, &ipg_clk, NULL); + +/* UART */ +DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET, + NULL, NULL, &ipg_clk, &aips_tz1_clk); +DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET, + NULL, NULL, &ipg_clk, &aips_tz1_clk); +DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET, + NULL, NULL, &ipg_clk, &spba_clk); +DEFINE_CLOCK(uart4_ipg_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG4_OFFSET, + NULL, NULL, &ipg_clk, &spba_clk); +DEFINE_CLOCK(uart5_ipg_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG6_OFFSET, + NULL, NULL, &ipg_clk, &spba_clk); +DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET, + NULL, NULL, &uart_root_clk, &uart1_ipg_clk); +DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET, + NULL, NULL, &uart_root_clk, &uart2_ipg_clk); +DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET, + NULL, NULL, &uart_root_clk, &uart3_ipg_clk); +DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG5_OFFSET, + NULL, NULL, &uart_root_clk, &uart4_ipg_clk); +DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG7_OFFSET, + NULL, NULL, &uart_root_clk, &uart5_ipg_clk); + +/* GPT */ +DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET, + NULL, NULL, &ipg_clk, NULL); +DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET, + NULL, NULL, &ipg_clk, &gpt_ipg_clk); + +DEFINE_CLOCK(pwm1_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG6_OFFSET, + NULL, NULL, &ipg_clk, NULL); +DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET, + NULL, NULL, &ipg_clk, NULL); + +/* I2C */ +DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET, + NULL, NULL, &ipg_perclk, NULL); +DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET, + NULL, NULL, &ipg_perclk, NULL); +DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET, + NULL, NULL, &ipg_clk, NULL); +DEFINE_CLOCK(i2c3_mx53_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET, + NULL, NULL, &ipg_perclk, NULL); + +/* FEC */ +DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET, + NULL, NULL, &ipg_clk, NULL); + +/* NFC */ +DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET, + clk_nfc, &emi_slow_clk, NULL); + +/* SSI */ +DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET, + NULL, NULL, &ipg_clk, NULL); +DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET, + NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk); +DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET, + NULL, NULL, &ipg_clk, NULL); +DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET, + NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk); +DEFINE_CLOCK(ssi3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG12_OFFSET, + NULL, NULL, &ipg_clk, NULL); +DEFINE_CLOCK(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET, + NULL, NULL, &pll3_sw_clk, &ssi3_ipg_clk); + +/* eCSPI */ +DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET, + NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable, + &ipg_clk, &spba_clk); +DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET, + NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk); +DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET, + NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable, + &ipg_clk, &aips_tz2_clk); +DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET, + NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk); + +/* CSPI */ +DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET, + NULL, NULL, &ipg_clk, &aips_tz2_clk); +DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET, + NULL, NULL, &ipg_clk, &cspi_ipg_clk); + +/* SDMA */ +DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET, + NULL, NULL, &ahb_clk, NULL); + +/* eSDHC */ +DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET, + NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL); +DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET, + clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk); +DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET, + NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL); +DEFINE_CLOCK_FULL(esdhc3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG4_OFFSET, + NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL); +DEFINE_CLOCK_FULL(esdhc4_ipg_clk, 3, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG6_OFFSET, + NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL); + +/* mx51 specific */ +DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET, + clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk); + +static struct clk esdhc3_clk = { + .id = 2, + .parent = &esdhc1_clk, + .set_parent = clk_esdhc3_set_parent, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET, + .enable = _clk_max_enable, + .disable = _clk_max_disable, + .secondary = &esdhc3_ipg_clk, +}; +static struct clk esdhc4_clk = { + .id = 3, + .parent = &esdhc1_clk, + .set_parent = clk_esdhc4_set_parent, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET, + .enable = _clk_max_enable, + .disable = _clk_max_disable, + .secondary = &esdhc4_ipg_clk, +}; + +/* mx53 specific */ +static struct clk esdhc2_mx53_clk = { + .id = 2, + .parent = &esdhc1_clk, + .set_parent = clk_esdhc2_mx53_set_parent, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET, + .enable = _clk_max_enable, + .disable = _clk_max_disable, + .secondary = &esdhc3_ipg_clk, +}; + +DEFINE_CLOCK_MAX(esdhc3_mx53_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG5_OFFSET, + clk_esdhc3_mx53, &pll2_sw_clk, &esdhc2_ipg_clk); + +static struct clk esdhc4_mx53_clk = { + .id = 3, + .parent = &esdhc1_clk, + .set_parent = clk_esdhc4_mx53_set_parent, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET, + .enable = _clk_max_enable, + .disable = _clk_max_disable, + .secondary = &esdhc4_ipg_clk, +}; + +static struct clk sata_clk = { + .parent = &ipg_clk, + .enable = _clk_max_enable, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET, + .disable = _clk_max_disable, +}; + +static struct clk ahci_phy_clk = { + .parent = &usb_phy1_clk, +}; + +static struct clk ahci_dma_clk = { + .parent = &ahb_clk, +}; + +DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk); +DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk); +DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk); + +/* IPU */ +DEFINE_CLOCK_FULL(ipu_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG5_OFFSET, + NULL, NULL, clk_ipu_enable, clk_ipu_disable, &ahb_clk, &ipu_sec_clk); + +DEFINE_CLOCK_FULL(emi_fast_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG7_OFFSET, + NULL, NULL, _clk_ccgr_enable, _clk_ccgr_disable_inwait, + &ddr_clk, NULL); + +DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET, + NULL, NULL, &pll3_sw_clk, NULL); +DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET, + NULL, NULL, &pll3_sw_clk, NULL); + +/* PATA */ +DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG0_OFFSET, + NULL, NULL, &ipg_clk, &spba_clk); + +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + }, + +static struct clk_lookup mx51_lookups[] = { + /* i.mx51 has the i.mx21 type uart */ + _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk) + _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk) + _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk) + _REGISTER_CLOCK(NULL, "gpt", gpt_clk) + /* i.mx51 has the i.mx27 type fec */ + _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk) + _REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk) + _REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk) + _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) + _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk) + _REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_ahb_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", usb_phy1_clk) + _REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk) + _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_ahb_clk) + _REGISTER_CLOCK("mxc-ehci.2", "usb", usboh3_clk) + _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk) + _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk) + _REGISTER_CLOCK("mxc_nand", NULL, nfc_clk) + _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) + _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) + _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk) + /* i.mx51 has the i.mx35 type sdma */ + _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk) + _REGISTER_CLOCK(NULL, "ckih", ckih_clk) + _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk) + _REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk) + _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk) + _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk) + /* i.mx51 has the i.mx35 type cspi */ + _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx51.0", NULL, esdhc1_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx51.1", NULL, esdhc2_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx51.2", NULL, esdhc3_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx51.3", NULL, esdhc4_clk) + _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk) + _REGISTER_CLOCK(NULL, "iim_clk", iim_clk) + _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk) + _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk) + _REGISTER_CLOCK(NULL, "mipi_hsp", mipi_hsp_clk) + _REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk) + _REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk) + _REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk) + _REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk) + _REGISTER_CLOCK("pata_imx", NULL, pata_clk) +}; + +static struct clk_lookup mx53_lookups[] = { + /* i.mx53 has the i.mx21 type uart */ + _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk) + _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk) + _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk) + _REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk) + _REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk) + _REGISTER_CLOCK(NULL, "gpt", gpt_clk) + /* i.mx53 has the i.mx25 type fec */ + _REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk) + _REGISTER_CLOCK(NULL, "iim_clk", iim_clk) + _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) + _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk) + _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_mx53_clk) + /* i.mx53 has the i.mx51 type ecspi */ + _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk) + _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk) + /* i.mx53 has the i.mx25 type cspi */ + _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx53.0", NULL, esdhc1_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx53.1", NULL, esdhc2_mx53_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx53.2", NULL, esdhc3_mx53_clk) + _REGISTER_CLOCK("sdhci-esdhc-imx53.3", NULL, esdhc4_mx53_clk) + _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk) + _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk) + /* i.mx53 has the i.mx35 type sdma */ + _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk) + _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) + _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) + _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk) + _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk) + _REGISTER_CLOCK("pata_imx", NULL, pata_clk) + _REGISTER_CLOCK("imx53-ahci.0", "ahci", sata_clk) + _REGISTER_CLOCK("imx53-ahci.0", "ahci_phy", ahci_phy_clk) + _REGISTER_CLOCK("imx53-ahci.0", "ahci_dma", ahci_dma_clk) +}; + +static void clk_tree_init(void) +{ + u32 reg; + + ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk); + + /* + * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at + * 8MHz, its derived from lp_apm. + * + * FIXME: Verify if true for all boards + */ + reg = __raw_readl(MXC_CCM_CBCDR); + reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK; + reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK; + reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK; + reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET); + __raw_writel(reg, MXC_CCM_CBCDR); +} + +int __init mx51_clocks_init(unsigned long ckil, unsigned long osc, + unsigned long ckih1, unsigned long ckih2) +{ + int i; + + external_low_reference = ckil; + external_high_reference = ckih1; + ckih2_reference = ckih2; + oscillator_reference = osc; + + for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++) + clkdev_add(&mx51_lookups[i]); + + clk_tree_init(); + + clk_enable(&cpu_clk); + clk_enable(&main_bus_clk); + + clk_enable(&iim_clk); + imx_print_silicon_rev("i.MX51", mx51_revision()); + clk_disable(&iim_clk); + + /* move usb_phy_clk to 24MHz */ + clk_set_parent(&usb_phy1_clk, &osc_clk); + + /* set the usboh3_clk parent to pll2_sw_clk */ + clk_set_parent(&usboh3_clk, &pll2_sw_clk); + + /* Set SDHC parents to be PLL2 */ + clk_set_parent(&esdhc1_clk, &pll2_sw_clk); + clk_set_parent(&esdhc2_clk, &pll2_sw_clk); + + /* set SDHC root clock as 166.25MHZ*/ + clk_set_rate(&esdhc1_clk, 166250000); + clk_set_rate(&esdhc2_clk, 166250000); + + /* System timer */ + mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR), + MX51_INT_GPT); + return 0; +} + +int __init mx53_clocks_init(unsigned long ckil, unsigned long osc, + unsigned long ckih1, unsigned long ckih2) +{ + int i; + + external_low_reference = ckil; + external_high_reference = ckih1; + ckih2_reference = ckih2; + oscillator_reference = osc; + + for (i = 0; i < ARRAY_SIZE(mx53_lookups); i++) + clkdev_add(&mx53_lookups[i]); + + clk_tree_init(); + + clk_set_parent(&uart_root_clk, &pll3_sw_clk); + clk_enable(&cpu_clk); + clk_enable(&main_bus_clk); + + clk_enable(&iim_clk); + imx_print_silicon_rev("i.MX53", mx53_revision()); + clk_disable(&iim_clk); + + /* Set SDHC parents to be PLL2 */ + clk_set_parent(&esdhc1_clk, &pll2_sw_clk); + clk_set_parent(&esdhc3_mx53_clk, &pll2_sw_clk); + + /* set SDHC root clock as 200MHZ*/ + clk_set_rate(&esdhc1_clk, 200000000); + clk_set_rate(&esdhc3_mx53_clk, 200000000); + + /* System timer */ + mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR), + MX53_INT_GPT); + return 0; +} + +static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc, + unsigned long *ckih1, unsigned long *ckih2) +{ + struct device_node *np; + + /* retrieve the freqency of fixed clocks from device tree */ + for_each_compatible_node(np, NULL, "fixed-clock") { + u32 rate; + if (of_property_read_u32(np, "clock-frequency", &rate)) + continue; + + if (of_device_is_compatible(np, "fsl,imx-ckil")) + *ckil = rate; + else if (of_device_is_compatible(np, "fsl,imx-osc")) + *osc = rate; + else if (of_device_is_compatible(np, "fsl,imx-ckih1")) + *ckih1 = rate; + else if (of_device_is_compatible(np, "fsl,imx-ckih2")) + *ckih2 = rate; + } +} + +int __init mx51_clocks_init_dt(void) +{ + unsigned long ckil, osc, ckih1, ckih2; + + clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2); + return mx51_clocks_init(ckil, osc, ckih1, ckih2); +} + +int __init mx53_clocks_init_dt(void) +{ + unsigned long ckil, osc, ckih1, ckih2; + + clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2); + return mx53_clocks_init(ckil, osc, ckih1, ckih2); +} diff --git a/arch/arm/mach-imx/cpu-imx5.c b/arch/arm/mach-imx/cpu-imx5.c new file mode 100644 index 0000000..5c53282 --- /dev/null +++ b/arch/arm/mach-imx/cpu-imx5.c @@ -0,0 +1,186 @@ +/* + * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + * + * This file contains the CPU initialization code. + */ + +#include +#include +#include +#include +#include +#include + +static int mx5_cpu_rev = -1; + +#define IIM_SREV 0x24 +#define MX50_HW_ADADIG_DIGPROG 0xB0 + +static int get_mx51_srev(void) +{ + void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR); + u32 rev = readl(iim_base + IIM_SREV) & 0xff; + + switch (rev) { + case 0x0: + return IMX_CHIP_REVISION_2_0; + case 0x10: + return IMX_CHIP_REVISION_3_0; + default: + return IMX_CHIP_REVISION_UNKNOWN; + } +} + +/* + * Returns: + * the silicon revision of the cpu + * -EINVAL - not a mx51 + */ +int mx51_revision(void) +{ + if (!cpu_is_mx51()) + return -EINVAL; + + if (mx5_cpu_rev == -1) + mx5_cpu_rev = get_mx51_srev(); + + return mx5_cpu_rev; +} +EXPORT_SYMBOL(mx51_revision); + +#ifdef CONFIG_NEON + +/* + * All versions of the silicon before Rev. 3 have broken NEON implementations. + * Dependent on link order - so the assumption is that vfp_init is called + * before us. + */ +static int __init mx51_neon_fixup(void) +{ + if (!cpu_is_mx51()) + return 0; + + if (mx51_revision() < IMX_CHIP_REVISION_3_0 && (elf_hwcap & HWCAP_NEON)) { + elf_hwcap &= ~HWCAP_NEON; + pr_info("Turning off NEON support, detected broken NEON implementation\n"); + } + return 0; +} + +late_initcall(mx51_neon_fixup); +#endif + +static int get_mx53_srev(void) +{ + void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR); + u32 rev = readl(iim_base + IIM_SREV) & 0xff; + + switch (rev) { + case 0x0: + return IMX_CHIP_REVISION_1_0; + case 0x2: + return IMX_CHIP_REVISION_2_0; + case 0x3: + return IMX_CHIP_REVISION_2_1; + default: + return IMX_CHIP_REVISION_UNKNOWN; + } +} + +/* + * Returns: + * the silicon revision of the cpu + * -EINVAL - not a mx53 + */ +int mx53_revision(void) +{ + if (!cpu_is_mx53()) + return -EINVAL; + + if (mx5_cpu_rev == -1) + mx5_cpu_rev = get_mx53_srev(); + + return mx5_cpu_rev; +} +EXPORT_SYMBOL(mx53_revision); + +static int get_mx50_srev(void) +{ + void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K); + u32 rev; + + if (!anatop) { + mx5_cpu_rev = -EINVAL; + return 0; + } + + rev = readl(anatop + MX50_HW_ADADIG_DIGPROG); + rev &= 0xff; + + iounmap(anatop); + if (rev == 0x0) + return IMX_CHIP_REVISION_1_0; + else if (rev == 0x1) + return IMX_CHIP_REVISION_1_1; + return 0; +} + +/* + * Returns: + * the silicon revision of the cpu + * -EINVAL - not a mx50 + */ +int mx50_revision(void) +{ + if (!cpu_is_mx50()) + return -EINVAL; + + if (mx5_cpu_rev == -1) + mx5_cpu_rev = get_mx50_srev(); + + return mx5_cpu_rev; +} +EXPORT_SYMBOL(mx50_revision); + +static int __init post_cpu_init(void) +{ + unsigned int reg; + void __iomem *base; + + if (cpu_is_mx51() || cpu_is_mx53()) { + if (cpu_is_mx51()) + base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR); + else + base = MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR); + + __raw_writel(0x0, base + 0x40); + __raw_writel(0x0, base + 0x44); + __raw_writel(0x0, base + 0x48); + __raw_writel(0x0, base + 0x4C); + reg = __raw_readl(base + 0x50) & 0x00FFFFFF; + __raw_writel(reg, base + 0x50); + + if (cpu_is_mx51()) + base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR); + else + base = MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR); + + __raw_writel(0x0, base + 0x40); + __raw_writel(0x0, base + 0x44); + __raw_writel(0x0, base + 0x48); + __raw_writel(0x0, base + 0x4C); + reg = __raw_readl(base + 0x50) & 0x00FFFFFF; + __raw_writel(reg, base + 0x50); + } + + return 0; +} + +postcore_initcall(post_cpu_init); diff --git a/arch/arm/mach-imx/cpu_op-mx51.c b/arch/arm/mach-imx/cpu_op-mx51.c new file mode 100644 index 0000000..9d34c3d --- /dev/null +++ b/arch/arm/mach-imx/cpu_op-mx51.c @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include + +static struct cpu_op mx51_cpu_op[] = { + { + .cpu_rate = 160000000,}, + { + .cpu_rate = 800000000,}, +}; + +struct cpu_op *mx51_get_cpu_op(int *op) +{ + *op = ARRAY_SIZE(mx51_cpu_op); + return mx51_cpu_op; +} diff --git a/arch/arm/mach-imx/cpu_op-mx51.h b/arch/arm/mach-imx/cpu_op-mx51.h new file mode 100644 index 0000000..97477fe --- /dev/null +++ b/arch/arm/mach-imx/cpu_op-mx51.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +extern struct cpu_op *mx51_get_cpu_op(int *op); diff --git a/arch/arm/mach-imx/crm-regs-imx5.h b/arch/arm/mach-imx/crm-regs-imx5.h new file mode 100644 index 0000000..5e11ba7 --- /dev/null +++ b/arch/arm/mach-imx/crm-regs-imx5.h @@ -0,0 +1,600 @@ +/* + * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#ifndef __ARCH_ARM_MACH_MX51_CRM_REGS_H__ +#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__ + +#define MX51_CCM_BASE MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR) +#define MX51_DPLL1_BASE MX51_IO_ADDRESS(MX51_PLL1_BASE_ADDR) +#define MX51_DPLL2_BASE MX51_IO_ADDRESS(MX51_PLL2_BASE_ADDR) +#define MX51_DPLL3_BASE MX51_IO_ADDRESS(MX51_PLL3_BASE_ADDR) +#define MX51_CORTEXA8_BASE MX51_IO_ADDRESS(MX51_ARM_BASE_ADDR) +#define MX51_GPC_BASE MX51_IO_ADDRESS(MX51_GPC_BASE_ADDR) + +/*MX53*/ +#define MX53_CCM_BASE MX53_IO_ADDRESS(MX53_CCM_BASE_ADDR) +#define MX53_DPLL1_BASE MX53_IO_ADDRESS(MX53_PLL1_BASE_ADDR) +#define MX53_DPLL2_BASE MX53_IO_ADDRESS(MX53_PLL2_BASE_ADDR) +#define MX53_DPLL3_BASE MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR) +#define MX53_DPLL4_BASE MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR) + +/* PLL Register Offsets */ +#define MXC_PLL_DP_CTL 0x00 +#define MXC_PLL_DP_CONFIG 0x04 +#define MXC_PLL_DP_OP 0x08 +#define MXC_PLL_DP_MFD 0x0C +#define MXC_PLL_DP_MFN 0x10 +#define MXC_PLL_DP_MFNMINUS 0x14 +#define MXC_PLL_DP_MFNPLUS 0x18 +#define MXC_PLL_DP_HFS_OP 0x1C +#define MXC_PLL_DP_HFS_MFD 0x20 +#define MXC_PLL_DP_HFS_MFN 0x24 +#define MXC_PLL_DP_MFN_TOGC 0x28 +#define MXC_PLL_DP_DESTAT 0x2c + +/* PLL Register Bit definitions */ +#define MXC_PLL_DP_CTL_MUL_CTRL 0x2000 +#define MXC_PLL_DP_CTL_DPDCK0_2_EN 0x1000 +#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET 12 +#define MXC_PLL_DP_CTL_ADE 0x800 +#define MXC_PLL_DP_CTL_REF_CLK_DIV 0x400 +#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK (3 << 8) +#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET 8 +#define MXC_PLL_DP_CTL_HFSM 0x80 +#define MXC_PLL_DP_CTL_PRE 0x40 +#define MXC_PLL_DP_CTL_UPEN 0x20 +#define MXC_PLL_DP_CTL_RST 0x10 +#define MXC_PLL_DP_CTL_RCP 0x8 +#define MXC_PLL_DP_CTL_PLM 0x4 +#define MXC_PLL_DP_CTL_BRM0 0x2 +#define MXC_PLL_DP_CTL_LRF 0x1 + +#define MXC_PLL_DP_CONFIG_BIST 0x8 +#define MXC_PLL_DP_CONFIG_SJC_CE 0x4 +#define MXC_PLL_DP_CONFIG_AREN 0x2 +#define MXC_PLL_DP_CONFIG_LDREQ 0x1 + +#define MXC_PLL_DP_OP_MFI_OFFSET 4 +#define MXC_PLL_DP_OP_MFI_MASK (0xF << 4) +#define MXC_PLL_DP_OP_PDF_OFFSET 0 +#define MXC_PLL_DP_OP_PDF_MASK 0xF + +#define MXC_PLL_DP_MFD_OFFSET 0 +#define MXC_PLL_DP_MFD_MASK 0x07FFFFFF + +#define MXC_PLL_DP_MFN_OFFSET 0x0 +#define MXC_PLL_DP_MFN_MASK 0x07FFFFFF + +#define MXC_PLL_DP_MFN_TOGC_TOG_DIS (1 << 17) +#define MXC_PLL_DP_MFN_TOGC_TOG_EN (1 << 16) +#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET 0x0 +#define MXC_PLL_DP_MFN_TOGC_CNT_MASK 0xFFFF + +#define MXC_PLL_DP_DESTAT_TOG_SEL (1 << 31) +#define MXC_PLL_DP_DESTAT_MFN 0x07FFFFFF + +/* Register addresses of CCM*/ +#define MXC_CCM_CCR (MX51_CCM_BASE + 0x00) +#define MXC_CCM_CCDR (MX51_CCM_BASE + 0x04) +#define MXC_CCM_CSR (MX51_CCM_BASE + 0x08) +#define MXC_CCM_CCSR (MX51_CCM_BASE + 0x0C) +#define MXC_CCM_CACRR (MX51_CCM_BASE + 0x10) +#define MXC_CCM_CBCDR (MX51_CCM_BASE + 0x14) +#define MXC_CCM_CBCMR (MX51_CCM_BASE + 0x18) +#define MXC_CCM_CSCMR1 (MX51_CCM_BASE + 0x1C) +#define MXC_CCM_CSCMR2 (MX51_CCM_BASE + 0x20) +#define MXC_CCM_CSCDR1 (MX51_CCM_BASE + 0x24) +#define MXC_CCM_CS1CDR (MX51_CCM_BASE + 0x28) +#define MXC_CCM_CS2CDR (MX51_CCM_BASE + 0x2C) +#define MXC_CCM_CDCDR (MX51_CCM_BASE + 0x30) +#define MXC_CCM_CHSCDR (MX51_CCM_BASE + 0x34) +#define MXC_CCM_CSCDR2 (MX51_CCM_BASE + 0x38) +#define MXC_CCM_CSCDR3 (MX51_CCM_BASE + 0x3C) +#define MXC_CCM_CSCDR4 (MX51_CCM_BASE + 0x40) +#define MXC_CCM_CWDR (MX51_CCM_BASE + 0x44) +#define MXC_CCM_CDHIPR (MX51_CCM_BASE + 0x48) +#define MXC_CCM_CDCR (MX51_CCM_BASE + 0x4C) +#define MXC_CCM_CTOR (MX51_CCM_BASE + 0x50) +#define MXC_CCM_CLPCR (MX51_CCM_BASE + 0x54) +#define MXC_CCM_CISR (MX51_CCM_BASE + 0x58) +#define MXC_CCM_CIMR (MX51_CCM_BASE + 0x5C) +#define MXC_CCM_CCOSR (MX51_CCM_BASE + 0x60) +#define MXC_CCM_CGPR (MX51_CCM_BASE + 0x64) +#define MXC_CCM_CCGR0 (MX51_CCM_BASE + 0x68) +#define MXC_CCM_CCGR1 (MX51_CCM_BASE + 0x6C) +#define MXC_CCM_CCGR2 (MX51_CCM_BASE + 0x70) +#define MXC_CCM_CCGR3 (MX51_CCM_BASE + 0x74) +#define MXC_CCM_CCGR4 (MX51_CCM_BASE + 0x78) +#define MXC_CCM_CCGR5 (MX51_CCM_BASE + 0x7C) +#define MXC_CCM_CCGR6 (MX51_CCM_BASE + 0x80) +#define MXC_CCM_CCGR7 (MX51_CCM_BASE + 0x84) + +#define MXC_CCM_CMEOR (MX51_CCM_BASE + 0x84) + +/* Define the bits in register CCR */ +#define MXC_CCM_CCR_COSC_EN (1 << 12) +#define MXC_CCM_CCR_FPM_MULT_MASK (1 << 11) +#define MXC_CCM_CCR_CAMP2_EN (1 << 10) +#define MXC_CCM_CCR_CAMP1_EN (1 << 9) +#define MXC_CCM_CCR_FPM_EN (1 << 8) +#define MXC_CCM_CCR_OSCNT_OFFSET (0) +#define MXC_CCM_CCR_OSCNT_MASK (0xFF) + +/* Define the bits in register CCDR */ +#define MXC_CCM_CCDR_HSC_HS_MASK (0x1 << 18) +#define MXC_CCM_CCDR_IPU_HS_MASK (0x1 << 17) +#define MXC_CCM_CCDR_EMI_HS_MASK (0x1 << 16) + +/* Define the bits in register CSR */ +#define MXC_CCM_CSR_COSR_READY (1 << 5) +#define MXC_CCM_CSR_LVS_VALUE (1 << 4) +#define MXC_CCM_CSR_CAMP2_READY (1 << 3) +#define MXC_CCM_CSR_CAMP1_READY (1 << 2) +#define MXC_CCM_CSR_FPM_READY (1 << 1) +#define MXC_CCM_CSR_REF_EN_B (1 << 0) + +/* Define the bits in register CCSR */ +#define MXC_CCM_CCSR_LP_APM_SEL (0x1 << 9) +#define MXC_CCM_CCSR_STEP_SEL_OFFSET (7) +#define MXC_CCM_CCSR_STEP_SEL_MASK (0x3 << 7) +#define MXC_CCM_CCSR_STEP_SEL_LP_APM 0 +#define MXC_CCM_CCSR_STEP_SEL_PLL1_BYPASS 1 /* Only when JTAG connected? */ +#define MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED 2 +#define MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED 3 +#define MXC_CCM_CCSR_PLL2_PODF_OFFSET (5) +#define MXC_CCM_CCSR_PLL2_PODF_MASK (0x3 << 5) +#define MXC_CCM_CCSR_PLL3_PODF_OFFSET (3) +#define MXC_CCM_CCSR_PLL3_PODF_MASK (0x3 << 3) +#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL (1 << 2) /* 0: pll1_main_clk, + 1: step_clk */ +#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL (1 << 1) +#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL (1 << 0) + +/* Define the bits in register CACRR */ +#define MXC_CCM_CACRR_ARM_PODF_OFFSET (0) +#define MXC_CCM_CACRR_ARM_PODF_MASK (0x7) + +/* Define the bits in register CBCDR */ +#define MXC_CCM_CBCDR_EMI_CLK_SEL (0x1 << 26) +#define MXC_CCM_CBCDR_PERIPH_CLK_SEL (0x1 << 25) +#define MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET (30) +#define MXC_CCM_CBCDR_DDR_HF_SEL (0x1 << 30) +#define MXC_CCM_CBCDR_DDR_PODF_OFFSET (27) +#define MXC_CCM_CBCDR_DDR_PODF_MASK (0x7 << 27) +#define MXC_CCM_CBCDR_EMI_PODF_OFFSET (22) +#define MXC_CCM_CBCDR_EMI_PODF_MASK (0x7 << 22) +#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET (19) +#define MXC_CCM_CBCDR_AXI_B_PODF_MASK (0x7 << 19) +#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET (16) +#define MXC_CCM_CBCDR_AXI_A_PODF_MASK (0x7 << 16) +#define MXC_CCM_CBCDR_NFC_PODF_OFFSET (13) +#define MXC_CCM_CBCDR_NFC_PODF_MASK (0x7 << 13) +#define MXC_CCM_CBCDR_AHB_PODF_OFFSET (10) +#define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << 10) +#define MXC_CCM_CBCDR_IPG_PODF_OFFSET (8) +#define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << 8) +#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET (6) +#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK (0x3 << 6) +#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET (3) +#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK (0x7 << 3) +#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET (0) +#define MXC_CCM_CBCDR_PERCLK_PODF_MASK (0x7) + +/* Define the bits in register CBCMR */ +#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET (14) +#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET (12) +#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK (0x3 << 12) +#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET (10) +#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK (0x3 << 10) +#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET (8) +#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK (0x3 << 8) +#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET (6) +#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK (0x3 << 6) +#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET (4) +#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK (0x3 << 4) +#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET (14) +#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL (0x1 << 1) +#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL (0x1 << 0) + +/* Define the bits in register CSCMR1 */ +#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET (30) +#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK (0x3 << 30) +#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET (28) +#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK (0x3 << 28) +#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET (26) +#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL (0x1 << 26) +#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET (24) +#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK (0x3 << 24) +#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET (22) +#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK (0x3 << 22) +#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET (20) +#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK (0x3 << 20) +#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL (0x1 << 19) +#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL (0x1 << 19) +#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL (0x1 << 18) +#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET (16) +#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK (0x3 << 16) +#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_OFFSET (16) +#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_MASK (0x3 << 16) +#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET (14) +#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET (12) +#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << 12) +#define MXC_CCM_CSCMR1_SSI3_CLK_SEL (0x1 << 11) +#define MXC_CCM_CSCMR1_VPU_RCLK_SEL (0x1 << 10) +#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET (8) +#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK (0x3 << 8) +#define MXC_CCM_CSCMR1_TVE_CLK_SEL (0x1 << 7) +#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL (0x1 << 6) +#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET (4) +#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK (0x3 << 4) +#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET (2) +#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK (0x3 << 2) +#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL (0x1 << 1) +#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL (0x1) + +/* Define the bits in register CSCMR2 */ +#define MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(n) (26+n*3) +#define MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(n) (0x7 << (26+n*3)) +#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET (24) +#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK (0x3 << 24) +#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET (22) +#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK (0x3 << 22) +#define MXC_CCM_CSCMR2_ESC_CLK_SEL_OFFSET (20) +#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK (0x3 << 20) +#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_OFFSET (18) +#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_MASK (0x3 << 18) +#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_OFFSET (16) +#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_MASK (0x3 << 16) +#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_OFFSET (14) +#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_OFFSET (12) +#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_MASK (0x3 << 12) +#define MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET (10) +#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK (0x3 << 10) +#define MXC_CCM_CSCMR2_SLIMBUS_COM (0x1 << 9) +#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET (6) +#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_MASK (0x7 << 6) +#define MXC_CCM_CSCMR2_SPDIF1_COM (1 << 5) +#define MXC_CCM_CSCMR2_SPDIF0_COM (1 << 4) +#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET (2) +#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK (0x3 << 2) +#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET (0) +#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK (0x3) + +/* Define the bits in register CSCDR1 */ +#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET (22) +#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK (0x7 << 22) +#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET (19) +#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK (0x7 << 19) +#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_OFFSET (22) +#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_MASK (0x7 << 22) +#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET (19) +#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK (0x7 << 19) +#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET (16) +#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET (14) +#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK (0x3 << 14) +#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET (11) +#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK (0x7 << 11) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET (8) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK (0x7 << 8) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET (6) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK (0x3 << 6) +#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET (3) +#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK (0x7 << 3) +#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET (0) +#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x7) + +/* Define the bits in register CS1CDR and CS2CDR */ +#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET (22) +#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK (0x7 << 22) +#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET (16) +#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK (0x3F << 16) +#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET (6) +#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET (0) +#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK (0x3F) + +#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET (22) +#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK (0x7 << 22) +#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET (16) +#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK (0x3F << 16) +#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET (6) +#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET (0) +#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK (0x3F) + +/* Define the bits in register CDCDR */ +#define MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET (28) +#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK (0x7 << 28) +#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET (25) +#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK (0x7 << 25) +#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET (19) +#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK (0x3F << 19) +#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET (16) +#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET (9) +#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK (0x3F << 9) +#define MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET (6) +#define MXC_CCM_CDCDR_DI_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET (3) +#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK (0x7 << 3) +#define MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET (0) +#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK (0x7) + +/* Define the bits in register CHSCCDR */ +#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_OFFSET (12) +#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_MASK (0x7 << 12) +#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET (6) +#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_MASK (0x3F << 6) +#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET (3) +#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_MASK (0x7 << 3) +#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET (0) +#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_MASK (0x7) + +/* Define the bits in register CSCDR2 */ +#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET (25) +#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK (0x7 << 25) +#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET (19) +#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK (0x3F << 19) +#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET (16) +#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET (9) +#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK (0x3F << 9) +#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET (6) +#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK (0x7 << 6) +#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET (0) +#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK (0x3F) + +/* Define the bits in register CSCDR3 */ +#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET (16) +#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET (9) +#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK (0x3F << 9) +#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_OFFSET (6) +#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_OFFSET (0) +#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_MASK (0x3F) + +/* Define the bits in register CSCDR4 */ +#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET (16) +#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET (9) +#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK (0x3F << 9) +#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET (6) +#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET (0) +#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK (0x3F) + +/* Define the bits in register CDHIPR */ +#define MXC_CCM_CDHIPR_ARM_PODF_BUSY (1 << 16) +#define MXC_CCM_CDHIPR_DDR_HF_CLK_SEL_BUSY (1 << 8) +#define MXC_CCM_CDHIPR_DDR_PODF_BUSY (1 << 7) +#define MXC_CCM_CDHIPR_EMI_CLK_SEL_BUSY (1 << 6) +#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY (1 << 5) +#define MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY (1 << 4) +#define MXC_CCM_CDHIPR_AHB_PODF_BUSY (1 << 3) +#define MXC_CCM_CDHIPR_EMI_PODF_BUSY (1 << 2) +#define MXC_CCM_CDHIPR_AXI_B_PODF_BUSY (1 << 1) +#define MXC_CCM_CDHIPR_AXI_A_PODF_BUSY (1 << 0) + +/* Define the bits in register CDCR */ +#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER (0x1 << 2) +#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET (0) +#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK (0x3) + +/* Define the bits in register CLPCR */ +#define MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS (0x1 << 23) +#define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS (0x1 << 22) +#define MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 21) +#define MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 25) +#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS (0x1 << 20) +#define MXC_CCM_CLPCR_BYPASS_EMI_LPM_HS (0x1 << 19) +#define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS (0x1 << 18) +#define MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS (0x1 << 17) +#define MXC_CCM_CLPCR_BYPASS_RNGC_LPM_HS (0x1 << 16) +#define MXC_CCM_CLPCR_COSC_PWRDOWN (0x1 << 11) +#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET (9) +#define MXC_CCM_CLPCR_STBY_COUNT_MASK (0x3 << 9) +#define MXC_CCM_CLPCR_VSTBY (0x1 << 8) +#define MXC_CCM_CLPCR_DIS_REF_OSC (0x1 << 7) +#define MXC_CCM_CLPCR_SBYOS (0x1 << 6) +#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5) +#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET (3) +#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK (0x3 << 3) +#define MXC_CCM_CLPCR_LPM_OFFSET (0) +#define MXC_CCM_CLPCR_LPM_MASK (0x3) + +/* Define the bits in register CISR */ +#define MXC_CCM_CISR_ARM_PODF_LOADED (0x1 << 25) +#define MXC_CCM_CISR_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21) +#define MXC_CCM_CISR_AHB_PODF_LOADED (0x1 << 20) +#define MXC_CCM_CISR_EMI_PODF_LOADED (0x1 << 19) +#define MXC_CCM_CISR_AXI_B_PODF_LOADED (0x1 << 18) +#define MXC_CCM_CISR_AXI_A_PODF_LOADED (0x1 << 17) +#define MXC_CCM_CISR_DIVIDER_LOADED (0x1 << 16) +#define MXC_CCM_CISR_COSC_READY (0x1 << 6) +#define MXC_CCM_CISR_CKIH2_READY (0x1 << 5) +#define MXC_CCM_CISR_CKIH_READY (0x1 << 4) +#define MXC_CCM_CISR_FPM_READY (0x1 << 3) +#define MXC_CCM_CISR_LRF_PLL3 (0x1 << 2) +#define MXC_CCM_CISR_LRF_PLL2 (0x1 << 1) +#define MXC_CCM_CISR_LRF_PLL1 (0x1) + +/* Define the bits in register CIMR */ +#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED (0x1 << 25) +#define MXC_CCM_CIMR_MASK_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21) +#define MXC_CCM_CIMR_MASK_EMI_PODF_LOADED (0x1 << 20) +#define MXC_CCM_CIMR_MASK_AXI_C_PODF_LOADED (0x1 << 19) +#define MXC_CCM_CIMR_MASK_AXI_B_PODF_LOADED (0x1 << 18) +#define MXC_CCM_CIMR_MASK_AXI_A_PODF_LOADED (0x1 << 17) +#define MXC_CCM_CIMR_MASK_DIVIDER_LOADED (0x1 << 16) +#define MXC_CCM_CIMR_MASK_COSC_READY (0x1 << 5) +#define MXC_CCM_CIMR_MASK_CKIH_READY (0x1 << 4) +#define MXC_CCM_CIMR_MASK_FPM_READY (0x1 << 3) +#define MXC_CCM_CIMR_MASK_LRF_PLL3 (0x1 << 2) +#define MXC_CCM_CIMR_MASK_LRF_PLL2 (0x1 << 1) +#define MXC_CCM_CIMR_MASK_LRF_PLL1 (0x1) + +/* Define the bits in register CCOSR */ +#define MXC_CCM_CCOSR_CKO2_EN_OFFSET (0x1 << 24) +#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET (21) +#define MXC_CCM_CCOSR_CKO2_DIV_MASK (0x7 << 21) +#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET (16) +#define MXC_CCM_CCOSR_CKO2_SEL_MASK (0x1F << 16) +#define MXC_CCM_CCOSR_CKOL_EN (0x1 << 7) +#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET (4) +#define MXC_CCM_CCOSR_CKOL_DIV_MASK (0x7 << 4) +#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET (0) +#define MXC_CCM_CCOSR_CKOL_SEL_MASK (0xF) + +/* Define the bits in registers CGPR */ +#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE (0x1 << 4) +#define MXC_CCM_CGPR_FPM_SEL (0x1 << 3) +#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_OFFSET (0) +#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_MASK (0x7) + +/* Define the bits in registers CCGRx */ +#define MXC_CCM_CCGRx_CG_MASK 0x3 +#define MXC_CCM_CCGRx_MOD_OFF 0x0 +#define MXC_CCM_CCGRx_MOD_ON 0x3 +#define MXC_CCM_CCGRx_MOD_IDLE 0x1 + +#define MXC_CCM_CCGRx_CG15_MASK (0x3 << 30) +#define MXC_CCM_CCGRx_CG14_MASK (0x3 << 28) +#define MXC_CCM_CCGRx_CG13_MASK (0x3 << 26) +#define MXC_CCM_CCGRx_CG12_MASK (0x3 << 24) +#define MXC_CCM_CCGRx_CG11_MASK (0x3 << 22) +#define MXC_CCM_CCGRx_CG10_MASK (0x3 << 20) +#define MXC_CCM_CCGRx_CG9_MASK (0x3 << 18) +#define MXC_CCM_CCGRx_CG8_MASK (0x3 << 16) +#define MXC_CCM_CCGRx_CG5_MASK (0x3 << 10) +#define MXC_CCM_CCGRx_CG4_MASK (0x3 << 8) +#define MXC_CCM_CCGRx_CG3_MASK (0x3 << 6) +#define MXC_CCM_CCGRx_CG2_MASK (0x3 << 4) +#define MXC_CCM_CCGRx_CG1_MASK (0x3 << 2) +#define MXC_CCM_CCGRx_CG0_MASK (0x3 << 0) + +#define MXC_CCM_CCGRx_CG15_OFFSET 30 +#define MXC_CCM_CCGRx_CG14_OFFSET 28 +#define MXC_CCM_CCGRx_CG13_OFFSET 26 +#define MXC_CCM_CCGRx_CG12_OFFSET 24 +#define MXC_CCM_CCGRx_CG11_OFFSET 22 +#define MXC_CCM_CCGRx_CG10_OFFSET 20 +#define MXC_CCM_CCGRx_CG9_OFFSET 18 +#define MXC_CCM_CCGRx_CG8_OFFSET 16 +#define MXC_CCM_CCGRx_CG7_OFFSET 14 +#define MXC_CCM_CCGRx_CG6_OFFSET 12 +#define MXC_CCM_CCGRx_CG5_OFFSET 10 +#define MXC_CCM_CCGRx_CG4_OFFSET 8 +#define MXC_CCM_CCGRx_CG3_OFFSET 6 +#define MXC_CCM_CCGRx_CG2_OFFSET 4 +#define MXC_CCM_CCGRx_CG1_OFFSET 2 +#define MXC_CCM_CCGRx_CG0_OFFSET 0 + +#define MXC_DPTC_LP_BASE (MX51_GPC_BASE + 0x80) +#define MXC_DPTC_GP_BASE (MX51_GPC_BASE + 0x100) +#define MXC_DVFS_CORE_BASE (MX51_GPC_BASE + 0x180) +#define MXC_DPTC_PER_BASE (MX51_GPC_BASE + 0x1C0) +#define MXC_PGC_IPU_BASE (MX51_GPC_BASE + 0x220) +#define MXC_PGC_VPU_BASE (MX51_GPC_BASE + 0x240) +#define MXC_PGC_GPU_BASE (MX51_GPC_BASE + 0x260) +#define MXC_SRPG_NEON_BASE (MX51_GPC_BASE + 0x280) +#define MXC_SRPG_ARM_BASE (MX51_GPC_BASE + 0x2A0) +#define MXC_SRPG_EMPGC0_BASE (MX51_GPC_BASE + 0x2C0) +#define MXC_SRPG_EMPGC1_BASE (MX51_GPC_BASE + 0x2D0) +#define MXC_SRPG_MEGAMIX_BASE (MX51_GPC_BASE + 0x2E0) +#define MXC_SRPG_EMI_BASE (MX51_GPC_BASE + 0x300) + +/* CORTEXA8 platform */ +#define MXC_CORTEXA8_PLAT_PVID (MX51_CORTEXA8_BASE + 0x0) +#define MXC_CORTEXA8_PLAT_GPC (MX51_CORTEXA8_BASE + 0x4) +#define MXC_CORTEXA8_PLAT_PIC (MX51_CORTEXA8_BASE + 0x8) +#define MXC_CORTEXA8_PLAT_LPC (MX51_CORTEXA8_BASE + 0xC) +#define MXC_CORTEXA8_PLAT_NEON_LPC (MX51_CORTEXA8_BASE + 0x10) +#define MXC_CORTEXA8_PLAT_ICGC (MX51_CORTEXA8_BASE + 0x14) +#define MXC_CORTEXA8_PLAT_AMC (MX51_CORTEXA8_BASE + 0x18) +#define MXC_CORTEXA8_PLAT_NMC (MX51_CORTEXA8_BASE + 0x20) +#define MXC_CORTEXA8_PLAT_NMS (MX51_CORTEXA8_BASE + 0x24) + +/* DVFS CORE */ +#define MXC_DVFSTHRS (MXC_DVFS_CORE_BASE + 0x00) +#define MXC_DVFSCOUN (MXC_DVFS_CORE_BASE + 0x04) +#define MXC_DVFSSIG1 (MXC_DVFS_CORE_BASE + 0x08) +#define MXC_DVFSSIG0 (MXC_DVFS_CORE_BASE + 0x0C) +#define MXC_DVFSGPC0 (MXC_DVFS_CORE_BASE + 0x10) +#define MXC_DVFSGPC1 (MXC_DVFS_CORE_BASE + 0x14) +#define MXC_DVFSGPBT (MXC_DVFS_CORE_BASE + 0x18) +#define MXC_DVFSEMAC (MXC_DVFS_CORE_BASE + 0x1C) +#define MXC_DVFSCNTR (MXC_DVFS_CORE_BASE + 0x20) +#define MXC_DVFSLTR0_0 (MXC_DVFS_CORE_BASE + 0x24) +#define MXC_DVFSLTR0_1 (MXC_DVFS_CORE_BASE + 0x28) +#define MXC_DVFSLTR1_0 (MXC_DVFS_CORE_BASE + 0x2C) +#define MXC_DVFSLTR1_1 (MXC_DVFS_CORE_BASE + 0x30) +#define MXC_DVFSPT0 (MXC_DVFS_CORE_BASE + 0x34) +#define MXC_DVFSPT1 (MXC_DVFS_CORE_BASE + 0x38) +#define MXC_DVFSPT2 (MXC_DVFS_CORE_BASE + 0x3C) +#define MXC_DVFSPT3 (MXC_DVFS_CORE_BASE + 0x40) + +/* GPC */ +#define MXC_GPC_CNTR (MX51_GPC_BASE + 0x0) +#define MXC_GPC_PGR (MX51_GPC_BASE + 0x4) +#define MXC_GPC_VCR (MX51_GPC_BASE + 0x8) +#define MXC_GPC_ALL_PU (MX51_GPC_BASE + 0xC) +#define MXC_GPC_NEON (MX51_GPC_BASE + 0x10) +#define MXC_GPC_PGR_ARMPG_OFFSET 8 +#define MXC_GPC_PGR_ARMPG_MASK (3 << 8) + +/* PGC */ +#define MXC_PGC_IPU_PGCR (MXC_PGC_IPU_BASE + 0x0) +#define MXC_PGC_IPU_PGSR (MXC_PGC_IPU_BASE + 0xC) +#define MXC_PGC_VPU_PGCR (MXC_PGC_VPU_BASE + 0x0) +#define MXC_PGC_VPU_PGSR (MXC_PGC_VPU_BASE + 0xC) +#define MXC_PGC_GPU_PGCR (MXC_PGC_GPU_BASE + 0x0) +#define MXC_PGC_GPU_PGSR (MXC_PGC_GPU_BASE + 0xC) + +#define MXC_PGCR_PCR 1 +#define MXC_SRPGCR_PCR 1 +#define MXC_EMPGCR_PCR 1 +#define MXC_PGSR_PSR 1 + + +#define MXC_CORTEXA8_PLAT_LPC_DSM (1 << 0) +#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM (1 << 1) + +/* SRPG */ +#define MXC_SRPG_NEON_SRPGCR (MXC_SRPG_NEON_BASE + 0x0) +#define MXC_SRPG_NEON_PUPSCR (MXC_SRPG_NEON_BASE + 0x4) +#define MXC_SRPG_NEON_PDNSCR (MXC_SRPG_NEON_BASE + 0x8) + +#define MXC_SRPG_ARM_SRPGCR (MXC_SRPG_ARM_BASE + 0x0) +#define MXC_SRPG_ARM_PUPSCR (MXC_SRPG_ARM_BASE + 0x4) +#define MXC_SRPG_ARM_PDNSCR (MXC_SRPG_ARM_BASE + 0x8) + +#define MXC_SRPG_EMPGC0_SRPGCR (MXC_SRPG_EMPGC0_BASE + 0x0) +#define MXC_SRPG_EMPGC0_PUPSCR (MXC_SRPG_EMPGC0_BASE + 0x4) +#define MXC_SRPG_EMPGC0_PDNSCR (MXC_SRPG_EMPGC0_BASE + 0x8) + +#define MXC_SRPG_EMPGC1_SRPGCR (MXC_SRPG_EMPGC1_BASE + 0x0) +#define MXC_SRPG_EMPGC1_PUPSCR (MXC_SRPG_EMPGC1_BASE + 0x4) +#define MXC_SRPG_EMPGC1_PDNSCR (MXC_SRPG_EMPGC1_BASE + 0x8) + +#define MXC_SRPG_MEGAMIX_SRPGCR (MXC_SRPG_MEGAMIX_BASE + 0x0) +#define MXC_SRPG_MEGAMIX_PUPSCR (MXC_SRPG_MEGAMIX_BASE + 0x4) +#define MXC_SRPG_MEGAMIX_PDNSCR (MXC_SRPG_MEGAMIX_BASE + 0x8) + +#define MXC_SRPGC_EMI_SRPGCR (MXC_SRPGC_EMI_BASE + 0x0) +#define MXC_SRPGC_EMI_PUPSCR (MXC_SRPGC_EMI_BASE + 0x4) +#define MXC_SRPGC_EMI_PDNSCR (MXC_SRPGC_EMI_BASE + 0x8) + +#endif /* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */ diff --git a/arch/arm/mach-imx/devices-imx50.h b/arch/arm/mach-imx/devices-imx50.h new file mode 100644 index 0000000..7216667 --- /dev/null +++ b/arch/arm/mach-imx/devices-imx50.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[]; +#define imx50_add_imx_uart(id, pdata) \ + imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata) + +extern const struct imx_fec_data imx50_fec_data; +#define imx50_add_fec(pdata) \ + imx_add_fec(&imx50_fec_data, pdata) + +extern const struct imx_imx_i2c_data imx50_imx_i2c_data[]; +#define imx50_add_imx_i2c(id, pdata) \ + imx_add_imx_i2c(&imx50_imx_i2c_data[id], pdata) diff --git a/arch/arm/mach-imx/devices-imx51.h b/arch/arm/mach-imx/devices-imx51.h new file mode 100644 index 0000000..af488bc --- /dev/null +++ b/arch/arm/mach-imx/devices-imx51.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 Pengutronix + * Uwe Kleine-Koenig + * + * 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 + +extern const struct imx_fec_data imx51_fec_data; +#define imx51_add_fec(pdata) \ + imx_add_fec(&imx51_fec_data, pdata) + +extern const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data; +#define imx51_add_fsl_usb2_udc(pdata) \ + imx_add_fsl_usb2_udc(&imx51_fsl_usb2_udc_data, pdata) + +extern const struct imx_imx_i2c_data imx51_imx_i2c_data[]; +#define imx51_add_imx_i2c(id, pdata) \ + imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata) +#define imx51_add_hsi2c(pdata) \ + imx51_add_imx_i2c(2, pdata) + +extern const struct imx_imx_ssi_data imx51_imx_ssi_data[]; +#define imx51_add_imx_ssi(id, pdata) \ + imx_add_imx_ssi(&imx51_imx_ssi_data[id], pdata) + +extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[]; +#define imx51_add_imx_uart(id, pdata) \ + imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata) + +extern const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data; +#define imx51_add_mxc_ehci_otg(pdata) \ + imx_add_mxc_ehci(&imx51_mxc_ehci_otg_data, pdata) +extern const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[]; +#define imx51_add_mxc_ehci_hs(id, pdata) \ + imx_add_mxc_ehci(&imx51_mxc_ehci_hs_data[id - 1], pdata) + +extern const struct imx_mxc_nand_data imx51_mxc_nand_data; +#define imx51_add_mxc_nand(pdata) \ + imx_add_mxc_nand(&imx51_mxc_nand_data, pdata) + +extern const struct imx_sdhci_esdhc_imx_data imx51_sdhci_esdhc_imx_data[]; +#define imx51_add_sdhci_esdhc_imx(id, pdata) \ + imx_add_sdhci_esdhc_imx(&imx51_sdhci_esdhc_imx_data[id], pdata) + +extern const struct imx_spi_imx_data imx51_cspi_data; +#define imx51_add_cspi(pdata) \ + imx_add_spi_imx(&imx51_cspi_data, pdata) + +extern const struct imx_spi_imx_data imx51_ecspi_data[]; +#define imx51_add_ecspi(id, pdata) \ + imx_add_spi_imx(&imx51_ecspi_data[id], pdata) + +extern const struct imx_imx2_wdt_data imx51_imx2_wdt_data[]; +#define imx51_add_imx2_wdt(id, pdata) \ + imx_add_imx2_wdt(&imx51_imx2_wdt_data[id]) + +extern const struct imx_mxc_pwm_data imx51_mxc_pwm_data[]; +#define imx51_add_mxc_pwm(id) \ + imx_add_mxc_pwm(&imx51_mxc_pwm_data[id]) + +extern const struct imx_imx_keypad_data imx51_imx_keypad_data; +#define imx51_add_imx_keypad(pdata) \ + imx_add_imx_keypad(&imx51_imx_keypad_data, pdata) + +extern const struct imx_pata_imx_data imx51_pata_imx_data; +#define imx51_add_pata_imx() \ + imx_add_pata_imx(&imx51_pata_imx_data) diff --git a/arch/arm/mach-imx/devices-imx53.h b/arch/arm/mach-imx/devices-imx53.h new file mode 100644 index 0000000..6e1e5d1 --- /dev/null +++ b/arch/arm/mach-imx/devices-imx53.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010 Yong Shen. + * + * 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 + +extern const struct imx_fec_data imx53_fec_data; +#define imx53_add_fec(pdata) \ + imx_add_fec(&imx53_fec_data, pdata) + +extern const struct imx_imx_uart_1irq_data imx53_imx_uart_data[]; +#define imx53_add_imx_uart(id, pdata) \ + imx_add_imx_uart_1irq(&imx53_imx_uart_data[id], pdata) + + +extern const struct imx_imx_i2c_data imx53_imx_i2c_data[]; +#define imx53_add_imx_i2c(id, pdata) \ + imx_add_imx_i2c(&imx53_imx_i2c_data[id], pdata) + +extern const struct imx_sdhci_esdhc_imx_data imx53_sdhci_esdhc_imx_data[]; +#define imx53_add_sdhci_esdhc_imx(id, pdata) \ + imx_add_sdhci_esdhc_imx(&imx53_sdhci_esdhc_imx_data[id], pdata) + +extern const struct imx_spi_imx_data imx53_ecspi_data[]; +#define imx53_add_ecspi(id, pdata) \ + imx_add_spi_imx(&imx53_ecspi_data[id], pdata) + +extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[]; +#define imx53_add_imx2_wdt(id, pdata) \ + imx_add_imx2_wdt(&imx53_imx2_wdt_data[id]) + +extern const struct imx_imx_ssi_data imx53_imx_ssi_data[]; +#define imx53_add_imx_ssi(id, pdata) \ + imx_add_imx_ssi(&imx53_imx_ssi_data[id], pdata) + +extern const struct imx_imx_keypad_data imx53_imx_keypad_data; +#define imx53_add_imx_keypad(pdata) \ + imx_add_imx_keypad(&imx53_imx_keypad_data, pdata) + +extern const struct imx_pata_imx_data imx53_pata_imx_data; +#define imx53_add_pata_imx() \ + imx_add_pata_imx(&imx53_pata_imx_data) + +extern struct platform_device *__init imx53_add_ahci_imx(void); diff --git a/arch/arm/mach-imx/efika.h b/arch/arm/mach-imx/efika.h new file mode 100644 index 0000000..014aa98 --- /dev/null +++ b/arch/arm/mach-imx/efika.h @@ -0,0 +1,10 @@ +#ifndef _EFIKA_H +#define _EFIKA_H + +#define EFIKA_WLAN_EN IMX_GPIO_NR(2, 16) +#define EFIKA_WLAN_RESET IMX_GPIO_NR(2, 10) +#define EFIKA_USB_PHY_RESET IMX_GPIO_NR(2, 9) + +void __init efika_board_common_init(void); + +#endif diff --git a/arch/arm/mach-imx/ehci-imx5.c b/arch/arm/mach-imx/ehci-imx5.c new file mode 100644 index 0000000..c17fa13 --- /dev/null +++ b/arch/arm/mach-imx/ehci-imx5.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2009 Daniel Mack + * Copyright (C) 2010 Freescale Semiconductor, Inc. + * + * 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 + +#define MXC_OTG_OFFSET 0 +#define MXC_H1_OFFSET 0x200 +#define MXC_H2_OFFSET 0x400 + +/* USB_CTRL */ +#define MXC_OTG_UCTRL_OWIE_BIT (1 << 27) /* OTG wakeup intr enable */ +#define MXC_OTG_UCTRL_OPM_BIT (1 << 24) /* OTG power mask */ +#define MXC_H1_UCTRL_H1UIE_BIT (1 << 12) /* Host1 ULPI interrupt enable */ +#define MXC_H1_UCTRL_H1WIE_BIT (1 << 11) /* HOST1 wakeup intr enable */ +#define MXC_H1_UCTRL_H1PM_BIT (1 << 8) /* HOST1 power mask */ + +/* USB_PHY_CTRL_FUNC */ +#define MXC_OTG_PHYCTRL_OC_DIS_BIT (1 << 8) /* OTG Disable Overcurrent Event */ +#define MXC_H1_OC_DIS_BIT (1 << 5) /* UH1 Disable Overcurrent Event */ + +/* USBH2CTRL */ +#define MXC_H2_UCTRL_H2UIE_BIT (1 << 8) +#define MXC_H2_UCTRL_H2WIE_BIT (1 << 7) +#define MXC_H2_UCTRL_H2PM_BIT (1 << 4) + +#define MXC_USBCMD_OFFSET 0x140 + +/* USBCMD */ +#define MXC_UCMD_ITC_NO_THRESHOLD_MASK (~(0xff << 16)) /* Interrupt Threshold Control */ + +int mx51_initialize_usb_hw(int port, unsigned int flags) +{ + unsigned int v; + void __iomem *usb_base; + void __iomem *usbotg_base; + void __iomem *usbother_base; + int ret = 0; + + usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); + if (!usb_base) { + printk(KERN_ERR "%s(): ioremap failed\n", __func__); + return -ENOMEM; + } + + switch (port) { + case 0: /* OTG port */ + usbotg_base = usb_base + MXC_OTG_OFFSET; + break; + case 1: /* Host 1 port */ + usbotg_base = usb_base + MXC_H1_OFFSET; + break; + case 2: /* Host 2 port */ + usbotg_base = usb_base + MXC_H2_OFFSET; + break; + default: + printk(KERN_ERR"%s no such port %d\n", __func__, port); + ret = -ENOENT; + goto error; + } + usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; + + switch (port) { + case 0: /*OTG port */ + if (flags & MXC_EHCI_INTERNAL_PHY) { + v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); + + if (flags & MXC_EHCI_POWER_PINS_ENABLED) { + /* OC/USBPWR is not used */ + v |= MXC_OTG_PHYCTRL_OC_DIS_BIT; + } else { + /* OC/USBPWR is used */ + v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT; + } + __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); + + v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET); + if (flags & MXC_EHCI_WAKEUP_ENABLED) + v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */ + else + v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */ + if (flags & MXC_EHCI_POWER_PINS_ENABLED) + v |= MXC_OTG_UCTRL_OPM_BIT; + else + v &= ~MXC_OTG_UCTRL_OPM_BIT; + __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET); + } + break; + case 1: /* Host 1 */ + /*Host ULPI */ + v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET); + if (flags & MXC_EHCI_WAKEUP_ENABLED) { + /* HOST1 wakeup/ULPI intr enable */ + v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT); + } else { + /* HOST1 wakeup/ULPI intr disable */ + v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT); + } + + if (flags & MXC_EHCI_POWER_PINS_ENABLED) + v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/ + else + v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/ + __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET); + + v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); + if (flags & MXC_EHCI_POWER_PINS_ENABLED) + v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */ + else + v |= MXC_H1_OC_DIS_BIT; /* OC is not used */ + __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); + + v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET); + if (flags & MXC_EHCI_ITC_NO_THRESHOLD) + /* Interrupt Threshold Control:Immediate (no threshold) */ + v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK; + __raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET); + break; + case 2: /* Host 2 ULPI */ + v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET); + if (flags & MXC_EHCI_WAKEUP_ENABLED) { + /* HOST1 wakeup/ULPI intr enable */ + v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT); + } else { + /* HOST1 wakeup/ULPI intr disable */ + v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT); + } + + if (flags & MXC_EHCI_POWER_PINS_ENABLED) + v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/ + else + v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/ + __raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET); + break; + } + +error: + iounmap(usb_base); + return ret; +} + diff --git a/arch/arm/mach-imx/eukrea_mbimx51-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx51-baseboard.c new file mode 100644 index 0000000..a6a3ab8 --- /dev/null +++ b/arch/arm/mach-imx/eukrea_mbimx51-baseboard.c @@ -0,0 +1,206 @@ +/* + * + * Copyright (C) 2010 Eric Bénard + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "devices-imx51.h" + +#define MBIMX51_TSC2007_GPIO IMX_GPIO_NR(3, 30) +#define MBIMX51_LED0 IMX_GPIO_NR(3, 5) +#define MBIMX51_LED1 IMX_GPIO_NR(3, 6) +#define MBIMX51_LED2 IMX_GPIO_NR(3, 7) +#define MBIMX51_LED3 IMX_GPIO_NR(3, 8) + +static const struct gpio_led mbimx51_leds[] __initconst = { + { + .name = "led0", + .default_trigger = "heartbeat", + .active_low = 1, + .gpio = MBIMX51_LED0, + }, + { + .name = "led1", + .default_trigger = "nand-disk", + .active_low = 1, + .gpio = MBIMX51_LED1, + }, + { + .name = "led2", + .default_trigger = "mmc0", + .active_low = 1, + .gpio = MBIMX51_LED2, + }, + { + .name = "led3", + .default_trigger = "default-on", + .active_low = 1, + .gpio = MBIMX51_LED3, + }, +}; + +static const struct gpio_led_platform_data mbimx51_leds_info __initconst = { + .leds = mbimx51_leds, + .num_leds = ARRAY_SIZE(mbimx51_leds), +}; + +static iomux_v3_cfg_t mbimx51_pads[] = { + /* UART2 */ + MX51_PAD_UART2_RXD__UART2_RXD, + MX51_PAD_UART2_TXD__UART2_TXD, + + /* UART3 */ + MX51_PAD_UART3_RXD__UART3_RXD, + MX51_PAD_UART3_TXD__UART3_TXD, + MX51_PAD_KEY_COL4__UART3_RTS, + MX51_PAD_KEY_COL5__UART3_CTS, + + /* TSC2007 IRQ */ + MX51_PAD_NANDF_D10__GPIO3_30, + + /* LEDS */ + MX51_PAD_DISPB2_SER_DIN__GPIO3_5, + MX51_PAD_DISPB2_SER_DIO__GPIO3_6, + MX51_PAD_DISPB2_SER_CLK__GPIO3_7, + MX51_PAD_DISPB2_SER_RS__GPIO3_8, + + /* KPP */ + MX51_PAD_KEY_ROW0__KEY_ROW0, + MX51_PAD_KEY_ROW1__KEY_ROW1, + MX51_PAD_KEY_ROW2__KEY_ROW2, + MX51_PAD_KEY_ROW3__KEY_ROW3, + MX51_PAD_KEY_COL0__KEY_COL0, + MX51_PAD_KEY_COL1__KEY_COL1, + MX51_PAD_KEY_COL2__KEY_COL2, + MX51_PAD_KEY_COL3__KEY_COL3, + + /* SD 1 */ + MX51_PAD_SD1_CMD__SD1_CMD, + MX51_PAD_SD1_CLK__SD1_CLK, + MX51_PAD_SD1_DATA0__SD1_DATA0, + MX51_PAD_SD1_DATA1__SD1_DATA1, + MX51_PAD_SD1_DATA2__SD1_DATA2, + MX51_PAD_SD1_DATA3__SD1_DATA3, + + /* SD 2 */ + MX51_PAD_SD2_CMD__SD2_CMD, + MX51_PAD_SD2_CLK__SD2_CLK, + MX51_PAD_SD2_DATA0__SD2_DATA0, + MX51_PAD_SD2_DATA1__SD2_DATA1, + MX51_PAD_SD2_DATA2__SD2_DATA2, + MX51_PAD_SD2_DATA3__SD2_DATA3, +}; + +static const struct imxuart_platform_data uart_pdata __initconst = { + .flags = IMXUART_HAVE_RTSCTS, +}; + +static int mbimx51_keymap[] = { + KEY(0, 0, KEY_1), + KEY(0, 1, KEY_2), + KEY(0, 2, KEY_3), + KEY(0, 3, KEY_UP), + + KEY(1, 0, KEY_4), + KEY(1, 1, KEY_5), + KEY(1, 2, KEY_6), + KEY(1, 3, KEY_LEFT), + + KEY(2, 0, KEY_7), + KEY(2, 1, KEY_8), + KEY(2, 2, KEY_9), + KEY(2, 3, KEY_RIGHT), + + KEY(3, 0, KEY_0), + KEY(3, 1, KEY_DOWN), + KEY(3, 2, KEY_ESC), + KEY(3, 3, KEY_ENTER), +}; + +static const struct matrix_keymap_data mbimx51_map_data __initconst = { + .keymap = mbimx51_keymap, + .keymap_size = ARRAY_SIZE(mbimx51_keymap), +}; + +static int tsc2007_get_pendown_state(void) +{ + return !gpio_get_value(MBIMX51_TSC2007_GPIO); +} + +struct tsc2007_platform_data tsc2007_data = { + .model = 2007, + .x_plate_ohms = 180, + .get_pendown_state = tsc2007_get_pendown_state, +}; + +static struct i2c_board_info mbimx51_i2c_devices[] = { + { + I2C_BOARD_INFO("tsc2007", 0x49), + .irq = IMX_GPIO_TO_IRQ(MBIMX51_TSC2007_GPIO), + .platform_data = &tsc2007_data, + }, { + I2C_BOARD_INFO("tlv320aic23", 0x1a), + }, +}; + +/* + * baseboard initialization. + */ +void __init eukrea_mbimx51_baseboard_init(void) +{ + mxc_iomux_v3_setup_multiple_pads(mbimx51_pads, + ARRAY_SIZE(mbimx51_pads)); + + imx51_add_imx_uart(1, NULL); + imx51_add_imx_uart(2, &uart_pdata); + + gpio_request(MBIMX51_LED0, "LED0"); + gpio_direction_output(MBIMX51_LED0, 1); + gpio_free(MBIMX51_LED0); + gpio_request(MBIMX51_LED1, "LED1"); + gpio_direction_output(MBIMX51_LED1, 1); + gpio_free(MBIMX51_LED1); + gpio_request(MBIMX51_LED2, "LED2"); + gpio_direction_output(MBIMX51_LED2, 1); + gpio_free(MBIMX51_LED2); + gpio_request(MBIMX51_LED3, "LED3"); + gpio_direction_output(MBIMX51_LED3, 1); + gpio_free(MBIMX51_LED3); + + gpio_led_register_device(-1, &mbimx51_leds_info); + + imx51_add_imx_keypad(&mbimx51_map_data); + + gpio_request(MBIMX51_TSC2007_GPIO, "tsc2007_irq"); + gpio_direction_input(MBIMX51_TSC2007_GPIO); + irq_set_irq_type(gpio_to_irq(MBIMX51_TSC2007_GPIO), + IRQF_TRIGGER_FALLING); + i2c_register_board_info(1, mbimx51_i2c_devices, + ARRAY_SIZE(mbimx51_i2c_devices)); + + imx51_add_sdhci_esdhc_imx(0, NULL); + imx51_add_sdhci_esdhc_imx(1, NULL); +} diff --git a/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c new file mode 100644 index 0000000..d817fc8 --- /dev/null +++ b/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2010 Eric Benard - eric@eukrea.com + * + * Based on pcm970-baseboard.c which is : + * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de) + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "devices-imx51.h" + +static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = { + /* LED */ + MX51_PAD_NANDF_D10__GPIO3_30, + /* SWITCH */ + NEW_PAD_CTRL(MX51_PAD_NANDF_D9__GPIO3_31, PAD_CTL_PUS_22K_UP | + PAD_CTL_PKE | PAD_CTL_SRE_FAST | + PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS), + /* UART2 */ + MX51_PAD_UART2_RXD__UART2_RXD, + MX51_PAD_UART2_TXD__UART2_TXD, + /* UART 3 */ + MX51_PAD_UART3_RXD__UART3_RXD, + MX51_PAD_UART3_TXD__UART3_TXD, + MX51_PAD_KEY_COL4__UART3_RTS, + MX51_PAD_KEY_COL5__UART3_CTS, + /* SD */ + MX51_PAD_SD1_CMD__SD1_CMD, + MX51_PAD_SD1_CLK__SD1_CLK, + MX51_PAD_SD1_DATA0__SD1_DATA0, + MX51_PAD_SD1_DATA1__SD1_DATA1, + MX51_PAD_SD1_DATA2__SD1_DATA2, + MX51_PAD_SD1_DATA3__SD1_DATA3, + /* SD1 CD */ + NEW_PAD_CTRL(MX51_PAD_GPIO1_0__SD1_CD, PAD_CTL_PUS_22K_UP | + PAD_CTL_PKE | PAD_CTL_SRE_FAST | + PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS), +}; + +#define GPIO_LED1 IMX_GPIO_NR(3, 30) +#define GPIO_SWITCH1 IMX_GPIO_NR(3, 31) + +static const struct gpio_led eukrea_mbimxsd_leds[] __initconst = { + { + .name = "led1", + .default_trigger = "heartbeat", + .active_low = 1, + .gpio = GPIO_LED1, + }, +}; + +static const struct gpio_led_platform_data + eukrea_mbimxsd_led_info __initconst = { + .leds = eukrea_mbimxsd_leds, + .num_leds = ARRAY_SIZE(eukrea_mbimxsd_leds), +}; + +static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = { + { + .gpio = GPIO_SWITCH1, + .code = BTN_0, + .desc = "BP1", + .active_low = 1, + .wakeup = 1, + }, +}; + +static const struct gpio_keys_platform_data + eukrea_mbimxsd_button_data __initconst = { + .buttons = eukrea_mbimxsd_gpio_buttons, + .nbuttons = ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons), +}; + +static const struct imxuart_platform_data uart_pdata __initconst = { + .flags = IMXUART_HAVE_RTSCTS, +}; + +static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = { + { + I2C_BOARD_INFO("tlv320aic23", 0x1a), + }, +}; + +/* + * system init for baseboard usage. Will be called by cpuimx51sd init. + * + * Add platform devices present on this baseboard and init + * them from CPU side as far as required to use them later on + */ +void __init eukrea_mbimxsd51_baseboard_init(void) +{ + if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads, + ARRAY_SIZE(eukrea_mbimxsd_pads))) + printk(KERN_ERR "error setting mbimxsd pads !\n"); + + imx51_add_imx_uart(1, NULL); + imx51_add_imx_uart(2, &uart_pdata); + + imx51_add_sdhci_esdhc_imx(0, NULL); + + gpio_request(GPIO_LED1, "LED1"); + gpio_direction_output(GPIO_LED1, 1); + gpio_free(GPIO_LED1); + + gpio_request(GPIO_SWITCH1, "SWITCH1"); + gpio_direction_input(GPIO_SWITCH1); + gpio_free(GPIO_SWITCH1); + + i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices, + ARRAY_SIZE(eukrea_mbimxsd_i2c_devices)); + + gpio_led_register_device(-1, &eukrea_mbimxsd_led_info); + imx_add_gpio_keys(&eukrea_mbimxsd_button_data); +} diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/imx51-dt.c new file mode 100644 index 0000000..ccc6158 --- /dev/null +++ b/arch/arm/mach-imx/imx51-dt.c @@ -0,0 +1,116 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Lookup table for attaching a specific name and platform_data pointer to + * devices as they get created by of_platform_populate(). Ideally this table + * would not exist, but the current clock implementation depends on some devices + * having a specific name. + */ +static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = { + OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx21-uart.0", NULL), + OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx21-uart.1", NULL), + OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx21-uart.2", NULL), + OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "imx27-fec.0", NULL), + OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx51.0", NULL), + OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx51.1", NULL), + OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx51.2", NULL), + OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx51.3", NULL), + OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL), + OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL), + OF_DEV_AUXDATA("fsl,imx51-cspi", MX51_CSPI_BASE_ADDR, "imx35-cspi.0", NULL), + OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C1_BASE_ADDR, "imx-i2c.0", NULL), + OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C2_BASE_ADDR, "imx-i2c.1", NULL), + OF_DEV_AUXDATA("fsl,imx51-sdma", MX51_SDMA_BASE_ADDR, "imx35-sdma", NULL), + OF_DEV_AUXDATA("fsl,imx51-wdt", MX51_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL), + { /* sentinel */ } +}; + +static void __init imx51_tzic_add_irq_domain(struct device_node *np, + struct device_node *interrupt_parent) +{ + irq_domain_add_simple(np, 0); +} + +static void __init imx51_gpio_add_irq_domain(struct device_node *np, + struct device_node *interrupt_parent) +{ + static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS - + 32 * 4; /* imx51 gets 4 gpio ports */ + + irq_domain_add_simple(np, gpio_irq_base); + gpio_irq_base += 32; +} + +static const struct of_device_id imx51_irq_match[] __initconst = { + { .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, }, + { .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, }, + { /* sentinel */ } +}; + +static const struct of_device_id imx51_iomuxc_of_match[] __initconst = { + { .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, }, + { /* sentinel */ } +}; + +static void __init imx51_dt_init(void) +{ + struct device_node *node; + const struct of_device_id *of_id; + void (*func)(void); + + of_irq_init(imx51_irq_match); + + node = of_find_matching_node(NULL, imx51_iomuxc_of_match); + if (node) { + of_id = of_match_node(imx51_iomuxc_of_match, node); + func = of_id->data; + func(); + of_node_put(node); + } + + of_platform_populate(NULL, of_default_bus_match_table, + imx51_auxdata_lookup, NULL); +} + +static void __init imx51_timer_init(void) +{ + mx51_clocks_init_dt(); +} + +static struct sys_timer imx51_timer = { + .init = imx51_timer_init, +}; + +static const char *imx51_dt_board_compat[] __initdata = { + "fsl,imx51-babbage", + NULL +}; + +DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)") + .map_io = mx51_map_io, + .init_early = imx51_init_early, + .init_irq = mx51_init_irq, + .handle_irq = imx51_handle_irq, + .timer = &imx51_timer, + .init_machine = imx51_dt_init, + .dt_compat = imx51_dt_board_compat, +MACHINE_END diff --git a/arch/arm/mach-imx/imx53-dt.c b/arch/arm/mach-imx/imx53-dt.c new file mode 100644 index 0000000..ccaa0b8 --- /dev/null +++ b/arch/arm/mach-imx/imx53-dt.c @@ -0,0 +1,126 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Lookup table for attaching a specific name and platform_data pointer to + * devices as they get created by of_platform_populate(). Ideally this table + * would not exist, but the current clock implementation depends on some devices + * having a specific name. + */ +static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = { + OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART1_BASE_ADDR, "imx21-uart.0", NULL), + OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART2_BASE_ADDR, "imx21-uart.1", NULL), + OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART3_BASE_ADDR, "imx21-uart.2", NULL), + OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART4_BASE_ADDR, "imx21-uart.3", NULL), + OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART5_BASE_ADDR, "imx21-uart.4", NULL), + OF_DEV_AUXDATA("fsl,imx53-fec", MX53_FEC_BASE_ADDR, "imx25-fec.0", NULL), + OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx53.0", NULL), + OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx53.1", NULL), + OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx53.2", NULL), + OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx53.3", NULL), + OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL), + OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL), + OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL), + OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL), + OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL), + OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL), + OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL), + OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL), + { /* sentinel */ } +}; + +static void __init imx53_tzic_add_irq_domain(struct device_node *np, + struct device_node *interrupt_parent) +{ + irq_domain_add_simple(np, 0); +} + +static void __init imx53_gpio_add_irq_domain(struct device_node *np, + struct device_node *interrupt_parent) +{ + static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS - + 32 * 7; /* imx53 gets 7 gpio ports */ + + irq_domain_add_simple(np, gpio_irq_base); + gpio_irq_base += 32; +} + +static const struct of_device_id imx53_irq_match[] __initconst = { + { .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, }, + { .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, }, + { /* sentinel */ } +}; + +static const struct of_device_id imx53_iomuxc_of_match[] __initconst = { + { .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, }, + { .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, }, + { .compatible = "fsl,imx53-iomuxc-qsb", .data = imx53_qsb_common_init, }, + { .compatible = "fsl,imx53-iomuxc-smd", .data = imx53_smd_common_init, }, + { /* sentinel */ } +}; + +static void __init imx53_dt_init(void) +{ + struct device_node *node; + const struct of_device_id *of_id; + void (*func)(void); + + of_irq_init(imx53_irq_match); + + node = of_find_matching_node(NULL, imx53_iomuxc_of_match); + if (node) { + of_id = of_match_node(imx53_iomuxc_of_match, node); + func = of_id->data; + func(); + of_node_put(node); + } + + of_platform_populate(NULL, of_default_bus_match_table, + imx53_auxdata_lookup, NULL); +} + +static void __init imx53_timer_init(void) +{ + mx53_clocks_init_dt(); +} + +static struct sys_timer imx53_timer = { + .init = imx53_timer_init, +}; + +static const char *imx53_dt_board_compat[] __initdata = { + "fsl,imx53-ard", + "fsl,imx53-evk", + "fsl,imx53-qsb", + "fsl,imx53-smd", + NULL +}; + +DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)") + .map_io = mx53_map_io, + .init_early = imx53_init_early, + .init_irq = mx53_init_irq, + .handle_irq = imx53_handle_irq, + .timer = &imx53_timer, + .init_machine = imx53_dt_init, + .dt_compat = imx53_dt_board_compat, +MACHINE_END diff --git a/arch/arm/mach-imx/mach-cpuimx51.c b/arch/arm/mach-imx/mach-cpuimx51.c new file mode 100644 index 0000000..1fc1103 --- /dev/null +++ b/arch/arm/mach-imx/mach-cpuimx51.c @@ -0,0 +1,300 @@ +/* + * + * Copyright (C) 2010 Eric Bénard + * + * based on board-mx51_babbage.c which is + * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2009-2010 Amit Kucheria + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "devices-imx51.h" + +#define CPUIMX51_USBH1_STP IMX_GPIO_NR(1, 27) +#define CPUIMX51_QUARTA_GPIO IMX_GPIO_NR(3, 28) +#define CPUIMX51_QUARTB_GPIO IMX_GPIO_NR(3, 25) +#define CPUIMX51_QUARTC_GPIO IMX_GPIO_NR(3, 26) +#define CPUIMX51_QUARTD_GPIO IMX_GPIO_NR(3, 27) +#define CPUIMX51_QUART_XTAL 14745600 +#define CPUIMX51_QUART_REGSHIFT 17 + +/* USB_CTRL_1 */ +#define MX51_USB_CTRL_1_OFFSET 0x10 +#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25) + +#define MX51_USB_PLLDIV_12_MHZ 0x00 +#define MX51_USB_PLL_DIV_19_2_MHZ 0x01 +#define MX51_USB_PLL_DIV_24_MHZ 0x02 + +static struct plat_serial8250_port serial_platform_data[] = { + { + .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000), + .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTA_GPIO), + .irqflags = IRQF_TRIGGER_HIGH, + .uartclk = CPUIMX51_QUART_XTAL, + .regshift = CPUIMX51_QUART_REGSHIFT, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, + }, { + .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x800000), + .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTB_GPIO), + .irqflags = IRQF_TRIGGER_HIGH, + .uartclk = CPUIMX51_QUART_XTAL, + .regshift = CPUIMX51_QUART_REGSHIFT, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, + }, { + .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x1000000), + .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTC_GPIO), + .irqflags = IRQF_TRIGGER_HIGH, + .uartclk = CPUIMX51_QUART_XTAL, + .regshift = CPUIMX51_QUART_REGSHIFT, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, + }, { + .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x2000000), + .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTD_GPIO), + .irqflags = IRQF_TRIGGER_HIGH, + .uartclk = CPUIMX51_QUART_XTAL, + .regshift = CPUIMX51_QUART_REGSHIFT, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, + }, { + } +}; + +static struct platform_device serial_device = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = serial_platform_data, + }, +}; + +static struct platform_device *devices[] __initdata = { + &serial_device, +}; + +static iomux_v3_cfg_t eukrea_cpuimx51_pads[] = { + /* UART1 */ + MX51_PAD_UART1_RXD__UART1_RXD, + MX51_PAD_UART1_TXD__UART1_TXD, + MX51_PAD_UART1_RTS__UART1_RTS, + MX51_PAD_UART1_CTS__UART1_CTS, + + /* I2C2 */ + MX51_PAD_GPIO1_2__I2C2_SCL, + MX51_PAD_GPIO1_3__I2C2_SDA, + MX51_PAD_NANDF_D10__GPIO3_30, + + /* QUART IRQ */ + MX51_PAD_NANDF_D15__GPIO3_25, + MX51_PAD_NANDF_D14__GPIO3_26, + MX51_PAD_NANDF_D13__GPIO3_27, + MX51_PAD_NANDF_D12__GPIO3_28, + + /* USB HOST1 */ + MX51_PAD_USBH1_CLK__USBH1_CLK, + MX51_PAD_USBH1_DIR__USBH1_DIR, + MX51_PAD_USBH1_NXT__USBH1_NXT, + MX51_PAD_USBH1_DATA0__USBH1_DATA0, + MX51_PAD_USBH1_DATA1__USBH1_DATA1, + MX51_PAD_USBH1_DATA2__USBH1_DATA2, + MX51_PAD_USBH1_DATA3__USBH1_DATA3, + MX51_PAD_USBH1_DATA4__USBH1_DATA4, + MX51_PAD_USBH1_DATA5__USBH1_DATA5, + MX51_PAD_USBH1_DATA6__USBH1_DATA6, + MX51_PAD_USBH1_DATA7__USBH1_DATA7, + MX51_PAD_USBH1_STP__USBH1_STP, +}; + +static const struct mxc_nand_platform_data + eukrea_cpuimx51_nand_board_info __initconst = { + .width = 1, + .hw_ecc = 1, + .flash_bbt = 1, +}; + +static const struct imxuart_platform_data uart_pdata __initconst = { + .flags = IMXUART_HAVE_RTSCTS, +}; + +static const +struct imxi2c_platform_data eukrea_cpuimx51_i2c_data __initconst = { + .bitrate = 100000, +}; + +static struct i2c_board_info eukrea_cpuimx51_i2c_devices[] = { + { + I2C_BOARD_INFO("pcf8563", 0x51), + }, +}; + +/* This function is board specific as the bit mask for the plldiv will also +be different for other Freescale SoCs, thus a common bitmask is not +possible and cannot get place in /plat-mxc/ehci.c.*/ +static int initialize_otg_port(struct platform_device *pdev) +{ + u32 v; + void __iomem *usb_base; + void __iomem *usbother_base; + + usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); + if (!usb_base) + return -ENOMEM; + usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; + + /* Set the PHY clock to 19.2MHz */ + v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); + v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK; + v |= MX51_USB_PLL_DIV_19_2_MHZ; + __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); + iounmap(usb_base); + + mdelay(10); + + return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY); +} + +static int initialize_usbh1_port(struct platform_device *pdev) +{ + u32 v; + void __iomem *usb_base; + void __iomem *usbother_base; + + usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); + if (!usb_base) + return -ENOMEM; + usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; + + /* The clock for the USBH1 ULPI port will come externally from the PHY. */ + v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET); + __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET); + iounmap(usb_base); + + mdelay(10); + + return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED | + MXC_EHCI_ITC_NO_THRESHOLD); +} + +static const struct mxc_usbh_platform_data dr_utmi_config __initconst = { + .init = initialize_otg_port, + .portsc = MXC_EHCI_UTMI_16BIT, +}; + +static const struct fsl_usb2_platform_data usb_pdata __initconst = { + .operating_mode = FSL_USB2_DR_DEVICE, + .phy_mode = FSL_USB2_PHY_UTMI_WIDE, +}; + +static const struct mxc_usbh_platform_data usbh1_config __initconst = { + .init = initialize_usbh1_port, + .portsc = MXC_EHCI_MODE_ULPI, +}; + +static int otg_mode_host; + +static int __init eukrea_cpuimx51_otg_mode(char *options) +{ + if (!strcmp(options, "host")) + otg_mode_host = 1; + else if (!strcmp(options, "device")) + otg_mode_host = 0; + else + pr_info("otg_mode neither \"host\" nor \"device\". " + "Defaulting to device\n"); + return 0; +} +__setup("otg_mode=", eukrea_cpuimx51_otg_mode); + +/* + * Board specific initialization. + */ +static void __init eukrea_cpuimx51_init(void) +{ + imx51_soc_init(); + + mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads, + ARRAY_SIZE(eukrea_cpuimx51_pads)); + + imx51_add_imx_uart(0, &uart_pdata); + imx51_add_mxc_nand(&eukrea_cpuimx51_nand_board_info); + + gpio_request(CPUIMX51_QUARTA_GPIO, "quarta_irq"); + gpio_direction_input(CPUIMX51_QUARTA_GPIO); + gpio_free(CPUIMX51_QUARTA_GPIO); + gpio_request(CPUIMX51_QUARTB_GPIO, "quartb_irq"); + gpio_direction_input(CPUIMX51_QUARTB_GPIO); + gpio_free(CPUIMX51_QUARTB_GPIO); + gpio_request(CPUIMX51_QUARTC_GPIO, "quartc_irq"); + gpio_direction_input(CPUIMX51_QUARTC_GPIO); + gpio_free(CPUIMX51_QUARTC_GPIO); + gpio_request(CPUIMX51_QUARTD_GPIO, "quartd_irq"); + gpio_direction_input(CPUIMX51_QUARTD_GPIO); + gpio_free(CPUIMX51_QUARTD_GPIO); + + imx51_add_fec(NULL); + platform_add_devices(devices, ARRAY_SIZE(devices)); + + imx51_add_imx_i2c(1, &eukrea_cpuimx51_i2c_data); + i2c_register_board_info(1, eukrea_cpuimx51_i2c_devices, + ARRAY_SIZE(eukrea_cpuimx51_i2c_devices)); + + if (otg_mode_host) + imx51_add_mxc_ehci_otg(&dr_utmi_config); + else { + initialize_otg_port(NULL); + imx51_add_fsl_usb2_udc(&usb_pdata); + } + imx51_add_mxc_ehci_hs(1, &usbh1_config); + +#ifdef CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD + eukrea_mbimx51_baseboard_init(); +#endif +} + +static void __init eukrea_cpuimx51_timer_init(void) +{ + mx51_clocks_init(32768, 24000000, 22579200, 0); +} + +static struct sys_timer mxc_timer = { + .init = eukrea_cpuimx51_timer_init, +}; + +MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module") + /* Maintainer: Eric Bénard */ + .atag_offset = 0x100, + .map_io = mx51_map_io, + .init_early = imx51_init_early, + .init_irq = mx51_init_irq, + .handle_irq = imx51_handle_irq, + .timer = &mxc_timer, + .init_machine = eukrea_cpuimx51_init, +MACHINE_END diff --git a/arch/arm/mach-imx/mach-cpuimx51sd.c b/arch/arm/mach-imx/mach-cpuimx51sd.c new file mode 100644 index 0000000..52a11c1 --- /dev/null +++ b/arch/arm/mach-imx/mach-cpuimx51sd.c @@ -0,0 +1,338 @@ +/* + * + * Copyright (C) 2010 Eric Bénard + * + * based on board-mx51_babbage.c which is + * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2009-2010 Amit Kucheria + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "devices-imx51.h" +#include "cpu_op-mx51.h" + +#define USBH1_RST IMX_GPIO_NR(2, 28) +#define ETH_RST IMX_GPIO_NR(2, 31) +#define TSC2007_IRQGPIO IMX_GPIO_NR(3, 12) +#define CAN_IRQGPIO IMX_GPIO_NR(1, 1) +#define CAN_RST IMX_GPIO_NR(4, 15) +#define CAN_NCS IMX_GPIO_NR(4, 24) +#define CAN_RXOBF IMX_GPIO_NR(1, 4) +#define CAN_RX1BF IMX_GPIO_NR(1, 6) +#define CAN_TXORTS IMX_GPIO_NR(1, 7) +#define CAN_TX1RTS IMX_GPIO_NR(1, 8) +#define CAN_TX2RTS IMX_GPIO_NR(1, 9) +#define I2C_SCL IMX_GPIO_NR(4, 16) +#define I2C_SDA IMX_GPIO_NR(4, 17) + +/* USB_CTRL_1 */ +#define MX51_USB_CTRL_1_OFFSET 0x10 +#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25) + +#define MX51_USB_PLLDIV_12_MHZ 0x00 +#define MX51_USB_PLL_DIV_19_2_MHZ 0x01 +#define MX51_USB_PLL_DIV_24_MHZ 0x02 + +static iomux_v3_cfg_t eukrea_cpuimx51sd_pads[] = { + /* UART1 */ + MX51_PAD_UART1_RXD__UART1_RXD, + MX51_PAD_UART1_TXD__UART1_TXD, + MX51_PAD_UART1_RTS__UART1_RTS, + MX51_PAD_UART1_CTS__UART1_CTS, + + /* USB HOST1 */ + MX51_PAD_USBH1_CLK__USBH1_CLK, + MX51_PAD_USBH1_DIR__USBH1_DIR, + MX51_PAD_USBH1_NXT__USBH1_NXT, + MX51_PAD_USBH1_DATA0__USBH1_DATA0, + MX51_PAD_USBH1_DATA1__USBH1_DATA1, + MX51_PAD_USBH1_DATA2__USBH1_DATA2, + MX51_PAD_USBH1_DATA3__USBH1_DATA3, + MX51_PAD_USBH1_DATA4__USBH1_DATA4, + MX51_PAD_USBH1_DATA5__USBH1_DATA5, + MX51_PAD_USBH1_DATA6__USBH1_DATA6, + MX51_PAD_USBH1_DATA7__USBH1_DATA7, + MX51_PAD_USBH1_STP__USBH1_STP, + MX51_PAD_EIM_CS3__GPIO2_28, /* PHY nRESET */ + + /* FEC */ + MX51_PAD_EIM_DTACK__GPIO2_31, /* PHY nRESET */ + + /* HSI2C */ + MX51_PAD_I2C1_CLK__GPIO4_16, + MX51_PAD_I2C1_DAT__GPIO4_17, + + /* CAN */ + MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI, + MX51_PAD_CSPI1_MISO__ECSPI1_MISO, + MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK, + MX51_PAD_CSPI1_SS0__GPIO4_24, /* nCS */ + MX51_PAD_CSI2_PIXCLK__GPIO4_15, /* nReset */ + MX51_PAD_GPIO1_1__GPIO1_1, /* IRQ */ + MX51_PAD_GPIO1_4__GPIO1_4, /* Control signals */ + MX51_PAD_GPIO1_6__GPIO1_6, + MX51_PAD_GPIO1_7__GPIO1_7, + MX51_PAD_GPIO1_8__GPIO1_8, + MX51_PAD_GPIO1_9__GPIO1_9, + + /* Touchscreen */ + /* IRQ */ + NEW_PAD_CTRL(MX51_PAD_GPIO_NAND__GPIO_NAND, PAD_CTL_PUS_22K_UP | + PAD_CTL_PKE | PAD_CTL_SRE_FAST | + PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS), +}; + +static const struct imxuart_platform_data uart_pdata __initconst = { + .flags = IMXUART_HAVE_RTSCTS, +}; + +static struct tsc2007_platform_data tsc2007_info = { + .model = 2007, + .x_plate_ohms = 180, +}; + +static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = { + { + I2C_BOARD_INFO("pcf8563", 0x51), + }, { + I2C_BOARD_INFO("tsc2007", 0x49), + .type = "tsc2007", + .platform_data = &tsc2007_info, + .irq = IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO), + }, +}; + +static const struct mxc_nand_platform_data + eukrea_cpuimx51sd_nand_board_info __initconst = { + .width = 1, + .hw_ecc = 1, + .flash_bbt = 1, +}; + +/* This function is board specific as the bit mask for the plldiv will also +be different for other Freescale SoCs, thus a common bitmask is not +possible and cannot get place in /plat-mxc/ehci.c.*/ +static int initialize_otg_port(struct platform_device *pdev) +{ + u32 v; + void __iomem *usb_base; + void __iomem *usbother_base; + + usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); + if (!usb_base) + return -ENOMEM; + usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; + + /* Set the PHY clock to 19.2MHz */ + v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); + v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK; + v |= MX51_USB_PLL_DIV_19_2_MHZ; + __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); + iounmap(usb_base); + + mdelay(10); + + return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY); +} + +static int initialize_usbh1_port(struct platform_device *pdev) +{ + u32 v; + void __iomem *usb_base; + void __iomem *usbother_base; + + usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); + if (!usb_base) + return -ENOMEM; + usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; + + /* The clock for the USBH1 ULPI port will come from the PHY. */ + v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET); + __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, + usbother_base + MX51_USB_CTRL_1_OFFSET); + iounmap(usb_base); + + mdelay(10); + + return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED | + MXC_EHCI_ITC_NO_THRESHOLD); +} + +static const struct mxc_usbh_platform_data dr_utmi_config __initconst = { + .init = initialize_otg_port, + .portsc = MXC_EHCI_UTMI_16BIT, +}; + +static const struct fsl_usb2_platform_data usb_pdata __initconst = { + .operating_mode = FSL_USB2_DR_DEVICE, + .phy_mode = FSL_USB2_PHY_UTMI_WIDE, +}; + +static const struct mxc_usbh_platform_data usbh1_config __initconst = { + .init = initialize_usbh1_port, + .portsc = MXC_EHCI_MODE_ULPI, +}; + +static int otg_mode_host; + +static int __init eukrea_cpuimx51sd_otg_mode(char *options) +{ + if (!strcmp(options, "host")) + otg_mode_host = 1; + else if (!strcmp(options, "device")) + otg_mode_host = 0; + else + pr_info("otg_mode neither \"host\" nor \"device\". " + "Defaulting to device\n"); + return 0; +} +__setup("otg_mode=", eukrea_cpuimx51sd_otg_mode); + +static struct i2c_gpio_platform_data pdata = { + .sda_pin = I2C_SDA, + .sda_is_open_drain = 0, + .scl_pin = I2C_SCL, + .scl_is_open_drain = 0, + .udelay = 2, +}; + +static struct platform_device hsi2c_gpio_device = { + .name = "i2c-gpio", + .id = 0, + .dev.platform_data = &pdata, +}; + +static struct mcp251x_platform_data mcp251x_info = { + .oscillator_frequency = 24E6, +}; + +static struct spi_board_info cpuimx51sd_spi_device[] = { + { + .modalias = "mcp2515", + .max_speed_hz = 10000000, + .bus_num = 0, + .mode = SPI_MODE_0, + .chip_select = 0, + .platform_data = &mcp251x_info, + .irq = IMX_GPIO_TO_IRQ(CAN_IRQGPIO) + }, +}; + +static int cpuimx51sd_spi1_cs[] = { + CAN_NCS, +}; + +static const struct spi_imx_master cpuimx51sd_ecspi1_pdata __initconst = { + .chipselect = cpuimx51sd_spi1_cs, + .num_chipselect = ARRAY_SIZE(cpuimx51sd_spi1_cs), +}; + +static struct platform_device *platform_devices[] __initdata = { + &hsi2c_gpio_device, +}; + +static void __init eukrea_cpuimx51sd_init(void) +{ + imx51_soc_init(); + + mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads, + ARRAY_SIZE(eukrea_cpuimx51sd_pads)); + +#if defined(CONFIG_CPU_FREQ_IMX) + get_cpu_op = mx51_get_cpu_op; +#endif + + imx51_add_imx_uart(0, &uart_pdata); + imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info); + + gpio_request(ETH_RST, "eth_rst"); + gpio_set_value(ETH_RST, 1); + imx51_add_fec(NULL); + + gpio_request(CAN_IRQGPIO, "can_irq"); + gpio_direction_input(CAN_IRQGPIO); + gpio_free(CAN_IRQGPIO); + gpio_request(CAN_NCS, "can_ncs"); + gpio_direction_output(CAN_NCS, 1); + gpio_free(CAN_NCS); + gpio_request(CAN_RST, "can_rst"); + gpio_direction_output(CAN_RST, 0); + msleep(20); + gpio_set_value(CAN_RST, 1); + imx51_add_ecspi(0, &cpuimx51sd_ecspi1_pdata); + spi_register_board_info(cpuimx51sd_spi_device, + ARRAY_SIZE(cpuimx51sd_spi_device)); + + gpio_request(TSC2007_IRQGPIO, "tsc2007_irq"); + gpio_direction_input(TSC2007_IRQGPIO); + gpio_free(TSC2007_IRQGPIO); + + i2c_register_board_info(0, eukrea_cpuimx51sd_i2c_devices, + ARRAY_SIZE(eukrea_cpuimx51sd_i2c_devices)); + platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); + + if (otg_mode_host) + imx51_add_mxc_ehci_otg(&dr_utmi_config); + else { + initialize_otg_port(NULL); + imx51_add_fsl_usb2_udc(&usb_pdata); + } + + gpio_request(USBH1_RST, "usb_rst"); + gpio_direction_output(USBH1_RST, 0); + msleep(20); + gpio_set_value(USBH1_RST, 1); + imx51_add_mxc_ehci_hs(1, &usbh1_config); + +#ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD + eukrea_mbimxsd51_baseboard_init(); +#endif +} + +static void __init eukrea_cpuimx51sd_timer_init(void) +{ + mx51_clocks_init(32768, 24000000, 22579200, 0); +} + +static struct sys_timer mxc_timer = { + .init = eukrea_cpuimx51sd_timer_init, +}; + +MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD") + /* Maintainer: Eric Bénard */ + .atag_offset = 0x100, + .map_io = mx51_map_io, + .init_early = imx51_init_early, + .init_irq = mx51_init_irq, + .handle_irq = imx51_handle_irq, + .timer = &mxc_timer, + .init_machine = eukrea_cpuimx51sd_init, +MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx50_rdp.c b/arch/arm/mach-imx/mach-mx50_rdp.c new file mode 100644 index 0000000..fc3621d --- /dev/null +++ b/arch/arm/mach-imx/mach-mx50_rdp.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "devices-imx50.h" + +#define FEC_EN IMX_GPIO_NR(6, 23) +#define FEC_RESET_B IMX_GPIO_NR(4, 12) + +static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = { + /* SD1 */ + MX50_PAD_ECSPI2_SS0__GPIO_4_19, + MX50_PAD_EIM_CRE__GPIO_1_27, + MX50_PAD_SD1_CMD__SD1_CMD, + + MX50_PAD_SD1_CLK__SD1_CLK, + MX50_PAD_SD1_D0__SD1_D0, + MX50_PAD_SD1_D1__SD1_D1, + MX50_PAD_SD1_D2__SD1_D2, + MX50_PAD_SD1_D3__SD1_D3, + + /* SD2 */ + MX50_PAD_SD2_CD__GPIO_5_17, + MX50_PAD_SD2_WP__GPIO_5_16, + MX50_PAD_SD2_CMD__SD2_CMD, + MX50_PAD_SD2_CLK__SD2_CLK, + MX50_PAD_SD2_D0__SD2_D0, + MX50_PAD_SD2_D1__SD2_D1, + MX50_PAD_SD2_D2__SD2_D2, + MX50_PAD_SD2_D3__SD2_D3, + MX50_PAD_SD2_D4__SD2_D4, + MX50_PAD_SD2_D5__SD2_D5, + MX50_PAD_SD2_D6__SD2_D6, + MX50_PAD_SD2_D7__SD2_D7, + + /* SD3 */ + MX50_PAD_SD3_CMD__SD3_CMD, + MX50_PAD_SD3_CLK__SD3_CLK, + MX50_PAD_SD3_D0__SD3_D0, + MX50_PAD_SD3_D1__SD3_D1, + MX50_PAD_SD3_D2__SD3_D2, + MX50_PAD_SD3_D3__SD3_D3, + MX50_PAD_SD3_D4__SD3_D4, + MX50_PAD_SD3_D5__SD3_D5, + MX50_PAD_SD3_D6__SD3_D6, + MX50_PAD_SD3_D7__SD3_D7, + + /* PWR_INT */ + MX50_PAD_ECSPI2_MISO__GPIO_4_18, + + /* UART pad setting */ + MX50_PAD_UART1_TXD__UART1_TXD, + MX50_PAD_UART1_RXD__UART1_RXD, + MX50_PAD_UART1_RTS__UART1_RTS, + MX50_PAD_UART2_TXD__UART2_TXD, + MX50_PAD_UART2_RXD__UART2_RXD, + MX50_PAD_UART2_CTS__UART2_CTS, + MX50_PAD_UART2_RTS__UART2_RTS, + + MX50_PAD_I2C1_SCL__I2C1_SCL, + MX50_PAD_I2C1_SDA__I2C1_SDA, + MX50_PAD_I2C2_SCL__I2C2_SCL, + MX50_PAD_I2C2_SDA__I2C2_SDA, + + MX50_PAD_EPITO__USBH1_PWR, + /* Need to comment below line if + * one needs to debug owire. + */ + MX50_PAD_OWIRE__USBH1_OC, + /* using gpio to control otg pwr */ + MX50_PAD_PWM2__GPIO_6_25, + MX50_PAD_I2C3_SCL__USBOTG_OC, + + MX50_PAD_SSI_RXC__FEC_MDIO, + MX50_PAD_SSI_RXFS__FEC_MDC, + MX50_PAD_DISP_D0__FEC_TXCLK, + MX50_PAD_DISP_D1__FEC_RX_ER, + MX50_PAD_DISP_D2__FEC_RX_DV, + MX50_PAD_DISP_D3__FEC_RXD1, + MX50_PAD_DISP_D4__FEC_RXD0, + MX50_PAD_DISP_D5__FEC_TX_EN, + MX50_PAD_DISP_D6__FEC_TXD1, + MX50_PAD_DISP_D7__FEC_TXD0, + MX50_PAD_I2C3_SDA__GPIO_6_23, + MX50_PAD_ECSPI1_SCLK__GPIO_4_12, + + MX50_PAD_CSPI_SS0__CSPI_SS0, + MX50_PAD_ECSPI1_MOSI__CSPI_SS1, + MX50_PAD_CSPI_MOSI__CSPI_MOSI, + MX50_PAD_CSPI_MISO__CSPI_MISO, + + /* SGTL500_OSC_EN */ + MX50_PAD_UART1_CTS__GPIO_6_8, + + /* SGTL_AMP_SHDN */ + MX50_PAD_UART3_RXD__GPIO_6_15, + + /* Keypad */ + MX50_PAD_KEY_COL0__KEY_COL0, + MX50_PAD_KEY_ROW0__KEY_ROW0, + MX50_PAD_KEY_COL1__KEY_COL1, + MX50_PAD_KEY_ROW1__KEY_ROW1, + MX50_PAD_KEY_COL2__KEY_COL2, + MX50_PAD_KEY_ROW2__KEY_ROW2, + MX50_PAD_KEY_COL3__KEY_COL3, + MX50_PAD_KEY_ROW3__KEY_ROW3, + MX50_PAD_EIM_DA0__KEY_COL4, + MX50_PAD_EIM_DA1__KEY_ROW4, + MX50_PAD_EIM_DA2__KEY_COL5, + MX50_PAD_EIM_DA3__KEY_ROW5, + MX50_PAD_EIM_DA4__KEY_COL6, + MX50_PAD_EIM_DA5__KEY_ROW6, + MX50_PAD_EIM_DA6__KEY_COL7, + MX50_PAD_EIM_DA7__KEY_ROW7, + /*EIM pads */ + MX50_PAD_EIM_DA8__GPIO_1_8, + MX50_PAD_EIM_DA9__GPIO_1_9, + MX50_PAD_EIM_DA10__GPIO_1_10, + MX50_PAD_EIM_DA11__GPIO_1_11, + MX50_PAD_EIM_DA12__GPIO_1_12, + MX50_PAD_EIM_DA13__GPIO_1_13, + MX50_PAD_EIM_DA14__GPIO_1_14, + MX50_PAD_EIM_DA15__GPIO_1_15, + MX50_PAD_EIM_CS2__GPIO_1_16, + MX50_PAD_EIM_CS1__GPIO_1_17, + MX50_PAD_EIM_CS0__GPIO_1_18, + MX50_PAD_EIM_EB0__GPIO_1_19, + MX50_PAD_EIM_EB1__GPIO_1_20, + MX50_PAD_EIM_WAIT__GPIO_1_21, + MX50_PAD_EIM_BCLK__GPIO_1_22, + MX50_PAD_EIM_RDY__GPIO_1_23, + MX50_PAD_EIM_OE__GPIO_1_24, +}; + +/* Serial ports */ +static const struct imxuart_platform_data uart_pdata __initconst = { + .flags = IMXUART_HAVE_RTSCTS, +}; + +static const struct fec_platform_data fec_data __initconst = { + .phy = PHY_INTERFACE_MODE_RMII, +}; + +static inline void mx50_rdp_fec_reset(void) +{ + gpio_request(FEC_EN, "fec-en"); + gpio_direction_output(FEC_EN, 0); + gpio_request(FEC_RESET_B, "fec-reset_b"); + gpio_direction_output(FEC_RESET_B, 0); + msleep(1); + gpio_set_value(FEC_RESET_B, 1); +} + +static const struct imxi2c_platform_data i2c_data __initconst = { + .bitrate = 100000, +}; + +/* + * Board specific initialization. + */ +static void __init mx50_rdp_board_init(void) +{ + imx50_soc_init(); + + mxc_iomux_v3_setup_multiple_pads(mx50_rdp_pads, + ARRAY_SIZE(mx50_rdp_pads)); + + imx50_add_imx_uart(0, &uart_pdata); + imx50_add_imx_uart(1, &uart_pdata); + mx50_rdp_fec_reset(); + imx50_add_fec(&fec_data); + imx50_add_imx_i2c(0, &i2c_data); + imx50_add_imx_i2c(1, &i2c_data); + imx50_add_imx_i2c(2, &i2c_data); +} + +static void __init mx50_rdp_timer_init(void) +{ + mx50_clocks_init(32768, 24000000, 22579200); +} + +static struct sys_timer mx50_rdp_timer = { + .init = mx50_rdp_timer_init, +}; + +MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform") + .map_io = mx50_map_io, + .init_early = imx50_init_early, + .init_irq = mx50_init_irq, + .handle_irq = imx50_handle_irq, + .timer = &mx50_rdp_timer, + .init_machine = mx50_rdp_board_init, +MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx51_3ds.c b/arch/arm/mach-imx/mach-mx51_3ds.c new file mode 100644 index 0000000..0578390 --- /dev/null +++ b/arch/arm/mach-imx/mach-mx51_3ds.c @@ -0,0 +1,178 @@ +/* + * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2010 Jason Wang + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "devices-imx51.h" + +#define EXPIO_PARENT_INT gpio_to_irq(IMX_GPIO_NR(1, 6)) +#define MX51_3DS_ECSPI2_CS (GPIO_PORTC + 28) + +static iomux_v3_cfg_t mx51_3ds_pads[] = { + /* UART1 */ + MX51_PAD_UART1_RXD__UART1_RXD, + MX51_PAD_UART1_TXD__UART1_TXD, + MX51_PAD_UART1_RTS__UART1_RTS, + MX51_PAD_UART1_CTS__UART1_CTS, + + /* UART2 */ + MX51_PAD_UART2_RXD__UART2_RXD, + MX51_PAD_UART2_TXD__UART2_TXD, + MX51_PAD_EIM_D25__UART2_CTS, + MX51_PAD_EIM_D26__UART2_RTS, + + /* UART3 */ + MX51_PAD_UART3_RXD__UART3_RXD, + MX51_PAD_UART3_TXD__UART3_TXD, + MX51_PAD_EIM_D24__UART3_CTS, + MX51_PAD_EIM_D27__UART3_RTS, + + /* CPLD PARENT IRQ PIN */ + MX51_PAD_GPIO1_6__GPIO1_6, + + /* KPP */ + MX51_PAD_KEY_ROW0__KEY_ROW0, + MX51_PAD_KEY_ROW1__KEY_ROW1, + MX51_PAD_KEY_ROW2__KEY_ROW2, + MX51_PAD_KEY_ROW3__KEY_ROW3, + MX51_PAD_KEY_COL0__KEY_COL0, + MX51_PAD_KEY_COL1__KEY_COL1, + MX51_PAD_KEY_COL2__KEY_COL2, + MX51_PAD_KEY_COL3__KEY_COL3, + MX51_PAD_KEY_COL4__KEY_COL4, + MX51_PAD_KEY_COL5__KEY_COL5, + + /* eCSPI2 */ + MX51_PAD_NANDF_RB2__ECSPI2_SCLK, + MX51_PAD_NANDF_RB3__ECSPI2_MISO, + MX51_PAD_NANDF_D15__ECSPI2_MOSI, + MX51_PAD_NANDF_D12__GPIO3_28, +}; + +/* Serial ports */ +static const struct imxuart_platform_data uart_pdata __initconst = { + .flags = IMXUART_HAVE_RTSCTS, +}; + +static int mx51_3ds_board_keymap[] = { + KEY(0, 0, KEY_1), + KEY(0, 1, KEY_2), + KEY(0, 2, KEY_3), + KEY(0, 3, KEY_F1), + KEY(0, 4, KEY_UP), + KEY(0, 5, KEY_F2), + + KEY(1, 0, KEY_4), + KEY(1, 1, KEY_5), + KEY(1, 2, KEY_6), + KEY(1, 3, KEY_LEFT), + KEY(1, 4, KEY_SELECT), + KEY(1, 5, KEY_RIGHT), + + KEY(2, 0, KEY_7), + KEY(2, 1, KEY_8), + KEY(2, 2, KEY_9), + KEY(2, 3, KEY_F3), + KEY(2, 4, KEY_DOWN), + KEY(2, 5, KEY_F4), + + KEY(3, 0, KEY_0), + KEY(3, 1, KEY_OK), + KEY(3, 2, KEY_ESC), + KEY(3, 3, KEY_ENTER), + KEY(3, 4, KEY_MENU), + KEY(3, 5, KEY_BACK) +}; + +static const struct matrix_keymap_data mx51_3ds_map_data __initconst = { + .keymap = mx51_3ds_board_keymap, + .keymap_size = ARRAY_SIZE(mx51_3ds_board_keymap), +}; + +static int mx51_3ds_spi2_cs[] = { + MXC_SPI_CS(0), + MX51_3DS_ECSPI2_CS, +}; + +static const struct spi_imx_master mx51_3ds_ecspi2_pdata __initconst = { + .chipselect = mx51_3ds_spi2_cs, + .num_chipselect = ARRAY_SIZE(mx51_3ds_spi2_cs), +}; + +static struct spi_board_info mx51_3ds_spi_nor_device[] = { + { + .modalias = "m25p80", + .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 1, + .chip_select = 1, + .mode = SPI_MODE_0, + .platform_data = NULL,}, +}; + +/* + * Board specific initialization. + */ +static void __init mx51_3ds_init(void) +{ + imx51_soc_init(); + + mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads, + ARRAY_SIZE(mx51_3ds_pads)); + + imx51_add_imx_uart(0, &uart_pdata); + imx51_add_imx_uart(1, &uart_pdata); + imx51_add_imx_uart(2, &uart_pdata); + + imx51_add_ecspi(1, &mx51_3ds_ecspi2_pdata); + spi_register_board_info(mx51_3ds_spi_nor_device, + ARRAY_SIZE(mx51_3ds_spi_nor_device)); + + if (mxc_expio_init(MX51_CS5_BASE_ADDR, EXPIO_PARENT_INT)) + printk(KERN_WARNING "Init of the debugboard failed, all " + "devices on the board are unusable.\n"); + + imx51_add_sdhci_esdhc_imx(0, NULL); + imx51_add_imx_keypad(&mx51_3ds_map_data); + imx51_add_imx2_wdt(0, NULL); +} + +static void __init mx51_3ds_timer_init(void) +{ + mx51_clocks_init(32768, 24000000, 22579200, 0); +} + +static struct sys_timer mx51_3ds_timer = { + .init = mx51_3ds_timer_init, +}; + +MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board") + /* Maintainer: Freescale Semiconductor, Inc. */ + .atag_offset = 0x100, + .map_io = mx51_map_io, + .init_early = imx51_init_early, + .init_irq = mx51_init_irq, + .handle_irq = imx51_handle_irq, + .timer = &mx51_3ds_timer, + .init_machine = mx51_3ds_init, +MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx51_babbage.c b/arch/arm/mach-imx/mach-mx51_babbage.c new file mode 100644 index 0000000..5c837603 --- /dev/null +++ b/arch/arm/mach-imx/mach-mx51_babbage.c @@ -0,0 +1,429 @@ +/* + * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2009-2010 Amit Kucheria + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "devices-imx51.h" +#include "cpu_op-mx51.h" + +#define BABBAGE_USB_HUB_RESET IMX_GPIO_NR(1, 7) +#define BABBAGE_USBH1_STP IMX_GPIO_NR(1, 27) +#define BABBAGE_USB_PHY_RESET IMX_GPIO_NR(2, 5) +#define BABBAGE_FEC_PHY_RESET IMX_GPIO_NR(2, 14) +#define BABBAGE_POWER_KEY IMX_GPIO_NR(2, 21) +#define BABBAGE_ECSPI1_CS0 IMX_GPIO_NR(4, 24) +#define BABBAGE_ECSPI1_CS1 IMX_GPIO_NR(4, 25) +#define BABBAGE_SD2_CD IMX_GPIO_NR(1, 6) +#define BABBAGE_SD2_WP IMX_GPIO_NR(1, 5) + +/* USB_CTRL_1 */ +#define MX51_USB_CTRL_1_OFFSET 0x10 +#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25) + +#define MX51_USB_PLLDIV_12_MHZ 0x00 +#define MX51_USB_PLL_DIV_19_2_MHZ 0x01 +#define MX51_USB_PLL_DIV_24_MHZ 0x02 + +static struct gpio_keys_button babbage_buttons[] = { + { + .gpio = BABBAGE_POWER_KEY, + .code = BTN_0, + .desc = "PWR", + .active_low = 1, + .wakeup = 1, + }, +}; + +static const struct gpio_keys_platform_data imx_button_data __initconst = { + .buttons = babbage_buttons, + .nbuttons = ARRAY_SIZE(babbage_buttons), +}; + +static iomux_v3_cfg_t mx51babbage_pads[] = { + /* UART1 */ + MX51_PAD_UART1_RXD__UART1_RXD, + MX51_PAD_UART1_TXD__UART1_TXD, + MX51_PAD_UART1_RTS__UART1_RTS, + MX51_PAD_UART1_CTS__UART1_CTS, + + /* UART2 */ + MX51_PAD_UART2_RXD__UART2_RXD, + MX51_PAD_UART2_TXD__UART2_TXD, + + /* UART3 */ + MX51_PAD_EIM_D25__UART3_RXD, + MX51_PAD_EIM_D26__UART3_TXD, + MX51_PAD_EIM_D27__UART3_RTS, + MX51_PAD_EIM_D24__UART3_CTS, + + /* I2C1 */ + MX51_PAD_EIM_D16__I2C1_SDA, + MX51_PAD_EIM_D19__I2C1_SCL, + + /* I2C2 */ + MX51_PAD_KEY_COL4__I2C2_SCL, + MX51_PAD_KEY_COL5__I2C2_SDA, + + /* HSI2C */ + MX51_PAD_I2C1_CLK__I2C1_CLK, + MX51_PAD_I2C1_DAT__I2C1_DAT, + + /* USB HOST1 */ + MX51_PAD_USBH1_CLK__USBH1_CLK, + MX51_PAD_USBH1_DIR__USBH1_DIR, + MX51_PAD_USBH1_NXT__USBH1_NXT, + MX51_PAD_USBH1_DATA0__USBH1_DATA0, + MX51_PAD_USBH1_DATA1__USBH1_DATA1, + MX51_PAD_USBH1_DATA2__USBH1_DATA2, + MX51_PAD_USBH1_DATA3__USBH1_DATA3, + MX51_PAD_USBH1_DATA4__USBH1_DATA4, + MX51_PAD_USBH1_DATA5__USBH1_DATA5, + MX51_PAD_USBH1_DATA6__USBH1_DATA6, + MX51_PAD_USBH1_DATA7__USBH1_DATA7, + + /* USB HUB reset line*/ + MX51_PAD_GPIO1_7__GPIO1_7, + + /* USB PHY reset line */ + MX51_PAD_EIM_D21__GPIO2_5, + + /* FEC */ + MX51_PAD_EIM_EB2__FEC_MDIO, + MX51_PAD_EIM_EB3__FEC_RDATA1, + MX51_PAD_EIM_CS2__FEC_RDATA2, + MX51_PAD_EIM_CS3__FEC_RDATA3, + MX51_PAD_EIM_CS4__FEC_RX_ER, + MX51_PAD_EIM_CS5__FEC_CRS, + MX51_PAD_NANDF_RB2__FEC_COL, + MX51_PAD_NANDF_RB3__FEC_RX_CLK, + MX51_PAD_NANDF_D9__FEC_RDATA0, + MX51_PAD_NANDF_D8__FEC_TDATA0, + MX51_PAD_NANDF_CS2__FEC_TX_ER, + MX51_PAD_NANDF_CS3__FEC_MDC, + MX51_PAD_NANDF_CS4__FEC_TDATA1, + MX51_PAD_NANDF_CS5__FEC_TDATA2, + MX51_PAD_NANDF_CS6__FEC_TDATA3, + MX51_PAD_NANDF_CS7__FEC_TX_EN, + MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK, + + /* FEC PHY reset line */ + MX51_PAD_EIM_A20__GPIO2_14, + + /* SD 1 */ + MX51_PAD_SD1_CMD__SD1_CMD, + MX51_PAD_SD1_CLK__SD1_CLK, + MX51_PAD_SD1_DATA0__SD1_DATA0, + MX51_PAD_SD1_DATA1__SD1_DATA1, + MX51_PAD_SD1_DATA2__SD1_DATA2, + MX51_PAD_SD1_DATA3__SD1_DATA3, + /* CD/WP from controller */ + MX51_PAD_GPIO1_0__SD1_CD, + MX51_PAD_GPIO1_1__SD1_WP, + + /* SD 2 */ + MX51_PAD_SD2_CMD__SD2_CMD, + MX51_PAD_SD2_CLK__SD2_CLK, + MX51_PAD_SD2_DATA0__SD2_DATA0, + MX51_PAD_SD2_DATA1__SD2_DATA1, + MX51_PAD_SD2_DATA2__SD2_DATA2, + MX51_PAD_SD2_DATA3__SD2_DATA3, + /* CD/WP gpio */ + MX51_PAD_GPIO1_6__GPIO1_6, + MX51_PAD_GPIO1_5__GPIO1_5, + + /* eCSPI1 */ + MX51_PAD_CSPI1_MISO__ECSPI1_MISO, + MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI, + MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK, + MX51_PAD_CSPI1_SS0__GPIO4_24, + MX51_PAD_CSPI1_SS1__GPIO4_25, +}; + +/* Serial ports */ +static const struct imxuart_platform_data uart_pdata __initconst = { + .flags = IMXUART_HAVE_RTSCTS, +}; + +static const struct imxi2c_platform_data babbage_i2c_data __initconst = { + .bitrate = 100000, +}; + +static const struct imxi2c_platform_data babbage_hsi2c_data __initconst = { + .bitrate = 400000, +}; + +static struct gpio mx51_babbage_usbh1_gpios[] = { + { BABBAGE_USBH1_STP, GPIOF_OUT_INIT_LOW, "usbh1_stp" }, + { BABBAGE_USB_PHY_RESET, GPIOF_OUT_INIT_LOW, "usbh1_phy_reset" }, +}; + +static int gpio_usbh1_active(void) +{ + iomux_v3_cfg_t usbh1stp_gpio = MX51_PAD_USBH1_STP__GPIO1_27; + int ret; + + /* Set USBH1_STP to GPIO and toggle it */ + mxc_iomux_v3_setup_pad(usbh1stp_gpio); + ret = gpio_request_array(mx51_babbage_usbh1_gpios, + ARRAY_SIZE(mx51_babbage_usbh1_gpios)); + + if (ret) { + pr_debug("failed to get USBH1 pins: %d\n", ret); + return ret; + } + + msleep(100); + gpio_set_value(BABBAGE_USBH1_STP, 1); + gpio_set_value(BABBAGE_USB_PHY_RESET, 1); + gpio_free_array(mx51_babbage_usbh1_gpios, + ARRAY_SIZE(mx51_babbage_usbh1_gpios)); + return 0; +} + +static inline void babbage_usbhub_reset(void) +{ + int ret; + + /* Reset USB hub */ + ret = gpio_request_one(BABBAGE_USB_HUB_RESET, + GPIOF_OUT_INIT_LOW, "GPIO1_7"); + if (ret) { + printk(KERN_ERR"failed to get GPIO_USB_HUB_RESET: %d\n", ret); + return; + } + + msleep(2); + /* Deassert reset */ + gpio_set_value(BABBAGE_USB_HUB_RESET, 1); +} + +static inline void babbage_fec_reset(void) +{ + int ret; + + /* reset FEC PHY */ + ret = gpio_request_one(BABBAGE_FEC_PHY_RESET, + GPIOF_OUT_INIT_LOW, "fec-phy-reset"); + if (ret) { + printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret); + return; + } + msleep(1); + gpio_set_value(BABBAGE_FEC_PHY_RESET, 1); +} + +/* This function is board specific as the bit mask for the plldiv will also +be different for other Freescale SoCs, thus a common bitmask is not +possible and cannot get place in /plat-mxc/ehci.c.*/ +static int initialize_otg_port(struct platform_device *pdev) +{ + u32 v; + void __iomem *usb_base; + void __iomem *usbother_base; + + usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); + if (!usb_base) + return -ENOMEM; + usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; + + /* Set the PHY clock to 19.2MHz */ + v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); + v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK; + v |= MX51_USB_PLL_DIV_19_2_MHZ; + __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); + iounmap(usb_base); + + mdelay(10); + + return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY); +} + +static int initialize_usbh1_port(struct platform_device *pdev) +{ + u32 v; + void __iomem *usb_base; + void __iomem *usbother_base; + + usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); + if (!usb_base) + return -ENOMEM; + usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; + + /* The clock for the USBH1 ULPI port will come externally from the PHY. */ + v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET); + __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET); + iounmap(usb_base); + + mdelay(10); + + return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED | + MXC_EHCI_ITC_NO_THRESHOLD); +} + +static const struct mxc_usbh_platform_data dr_utmi_config __initconst = { + .init = initialize_otg_port, + .portsc = MXC_EHCI_UTMI_16BIT, +}; + +static const struct fsl_usb2_platform_data usb_pdata __initconst = { + .operating_mode = FSL_USB2_DR_DEVICE, + .phy_mode = FSL_USB2_PHY_UTMI_WIDE, +}; + +static const struct mxc_usbh_platform_data usbh1_config __initconst = { + .init = initialize_usbh1_port, + .portsc = MXC_EHCI_MODE_ULPI, +}; + +static int otg_mode_host; + +static int __init babbage_otg_mode(char *options) +{ + if (!strcmp(options, "host")) + otg_mode_host = 1; + else if (!strcmp(options, "device")) + otg_mode_host = 0; + else + pr_info("otg_mode neither \"host\" nor \"device\". " + "Defaulting to device\n"); + return 0; +} +__setup("otg_mode=", babbage_otg_mode); + +static struct spi_board_info mx51_babbage_spi_board_info[] __initdata = { + { + .modalias = "mtd_dataflash", + .max_speed_hz = 25000000, + .bus_num = 0, + .chip_select = 1, + .mode = SPI_MODE_0, + .platform_data = NULL, + }, +}; + +static int mx51_babbage_spi_cs[] = { + BABBAGE_ECSPI1_CS0, + BABBAGE_ECSPI1_CS1, +}; + +static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = { + .chipselect = mx51_babbage_spi_cs, + .num_chipselect = ARRAY_SIZE(mx51_babbage_spi_cs), +}; + +static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = { + .cd_type = ESDHC_CD_CONTROLLER, + .wp_type = ESDHC_WP_CONTROLLER, +}; + +static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = { + .cd_gpio = BABBAGE_SD2_CD, + .wp_gpio = BABBAGE_SD2_WP, + .cd_type = ESDHC_CD_GPIO, + .wp_type = ESDHC_WP_GPIO, +}; + +void __init imx51_babbage_common_init(void) +{ + mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads, + ARRAY_SIZE(mx51babbage_pads)); +} + +/* + * Board specific initialization. + */ +static void __init mx51_babbage_init(void) +{ + iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP; + iomux_v3_cfg_t power_key = NEW_PAD_CTRL(MX51_PAD_EIM_A27__GPIO2_21, + PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP); + + imx51_soc_init(); + +#if defined(CONFIG_CPU_FREQ_IMX) + get_cpu_op = mx51_get_cpu_op; +#endif + imx51_babbage_common_init(); + + imx51_add_imx_uart(0, &uart_pdata); + imx51_add_imx_uart(1, NULL); + imx51_add_imx_uart(2, &uart_pdata); + + babbage_fec_reset(); + imx51_add_fec(NULL); + + /* Set the PAD settings for the pwr key. */ + mxc_iomux_v3_setup_pad(power_key); + imx_add_gpio_keys(&imx_button_data); + + imx51_add_imx_i2c(0, &babbage_i2c_data); + imx51_add_imx_i2c(1, &babbage_i2c_data); + imx51_add_hsi2c(&babbage_hsi2c_data); + + if (otg_mode_host) + imx51_add_mxc_ehci_otg(&dr_utmi_config); + else { + initialize_otg_port(NULL); + imx51_add_fsl_usb2_udc(&usb_pdata); + } + + gpio_usbh1_active(); + imx51_add_mxc_ehci_hs(1, &usbh1_config); + /* setback USBH1_STP to be function */ + mxc_iomux_v3_setup_pad(usbh1stp); + babbage_usbhub_reset(); + + imx51_add_sdhci_esdhc_imx(0, &mx51_babbage_sd1_data); + imx51_add_sdhci_esdhc_imx(1, &mx51_babbage_sd2_data); + + spi_register_board_info(mx51_babbage_spi_board_info, + ARRAY_SIZE(mx51_babbage_spi_board_info)); + imx51_add_ecspi(0, &mx51_babbage_spi_pdata); + imx51_add_imx2_wdt(0, NULL); +} + +static void __init mx51_babbage_timer_init(void) +{ + mx51_clocks_init(32768, 24000000, 22579200, 0); +} + +static struct sys_timer mx51_babbage_timer = { + .init = mx51_babbage_timer_init, +}; + +MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board") + /* Maintainer: Amit Kucheria */ + .atag_offset = 0x100, + .map_io = mx51_map_io, + .init_early = imx51_init_early, + .init_irq = mx51_init_irq, + .handle_irq = imx51_handle_irq, + .timer = &mx51_babbage_timer, + .init_machine = mx51_babbage_init, +MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx51_efikamx.c b/arch/arm/mach-imx/mach-mx51_efikamx.c new file mode 100644 index 0000000..a9e4866 --- /dev/null +++ b/arch/arm/mach-imx/mach-mx51_efikamx.c @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2010 Linaro Limited + * + * based on code from the following + * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved. + * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "devices-imx51.h" +#include "efika.h" + +#define EFIKAMX_PCBID0 IMX_GPIO_NR(3, 16) +#define EFIKAMX_PCBID1 IMX_GPIO_NR(3, 17) +#define EFIKAMX_PCBID2 IMX_GPIO_NR(3, 11) + +#define EFIKAMX_BLUE_LED IMX_GPIO_NR(3, 13) +#define EFIKAMX_GREEN_LED IMX_GPIO_NR(3, 14) +#define EFIKAMX_RED_LED IMX_GPIO_NR(3, 15) + +#define EFIKAMX_POWER_KEY IMX_GPIO_NR(2, 31) + +/* board 1.1 doesn't have same reset gpio */ +#define EFIKAMX_RESET1_1 IMX_GPIO_NR(3, 2) +#define EFIKAMX_RESET IMX_GPIO_NR(1, 4) + +#define EFIKAMX_POWEROFF IMX_GPIO_NR(4, 13) + +#define EFIKAMX_PMIC IMX_GPIO_NR(1, 6) + +/* the pci ids pin have pull up. they're driven low according to board id */ +#define MX51_PAD_PCBID0 IOMUX_PAD(0x518, 0x130, 3, 0x0, 0, PAD_CTL_PUS_100K_UP) +#define MX51_PAD_PCBID1 IOMUX_PAD(0x51C, 0x134, 3, 0x0, 0, PAD_CTL_PUS_100K_UP) +#define MX51_PAD_PCBID2 IOMUX_PAD(0x504, 0x128, 3, 0x0, 0, PAD_CTL_PUS_100K_UP) +#define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0, 0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE) + +static iomux_v3_cfg_t mx51efikamx_pads[] = { + /* board id */ + MX51_PAD_PCBID0, + MX51_PAD_PCBID1, + MX51_PAD_PCBID2, + + /* leds */ + MX51_PAD_CSI1_D9__GPIO3_13, + MX51_PAD_CSI1_VSYNC__GPIO3_14, + MX51_PAD_CSI1_HSYNC__GPIO3_15, + + /* power key */ + MX51_PAD_PWRKEY, + + /* reset */ + MX51_PAD_DI1_PIN13__GPIO3_2, + MX51_PAD_GPIO1_4__GPIO1_4, + + /* power off */ + MX51_PAD_CSI2_VSYNC__GPIO4_13, +}; + +/* PCBID2 PCBID1 PCBID0 STATE + 1 1 1 ER1:rev1.1 + 1 1 0 ER2:rev1.2 + 1 0 1 ER3:rev1.3 + 1 0 0 ER4:rev1.4 +*/ +static void __init mx51_efikamx_board_id(void) +{ + int id; + + /* things are taking time to settle */ + msleep(150); + + gpio_request(EFIKAMX_PCBID0, "pcbid0"); + gpio_direction_input(EFIKAMX_PCBID0); + gpio_request(EFIKAMX_PCBID1, "pcbid1"); + gpio_direction_input(EFIKAMX_PCBID1); + gpio_request(EFIKAMX_PCBID2, "pcbid2"); + gpio_direction_input(EFIKAMX_PCBID2); + + id = gpio_get_value(EFIKAMX_PCBID0) ? 1 : 0; + id |= (gpio_get_value(EFIKAMX_PCBID1) ? 1 : 0) << 1; + id |= (gpio_get_value(EFIKAMX_PCBID2) ? 1 : 0) << 2; + + switch (id) { + case 7: + system_rev = 0x11; + break; + case 6: + system_rev = 0x12; + break; + case 5: + system_rev = 0x13; + break; + case 4: + system_rev = 0x14; + break; + default: + system_rev = 0x10; + break; + } + + if ((system_rev == 0x10) + || (system_rev == 0x12) + || (system_rev == 0x14)) { + printk(KERN_WARNING + "EfikaMX: Unsupported board revision 1.%u!\n", + system_rev & 0xf); + } +} + +static struct gpio_led mx51_efikamx_leds[] __initdata = { + { + .name = "efikamx:green", + .default_trigger = "default-on", + .gpio = EFIKAMX_GREEN_LED, + }, + { + .name = "efikamx:red", + .default_trigger = "ide-disk", + .gpio = EFIKAMX_RED_LED, + }, + { + .name = "efikamx:blue", + .default_trigger = "mmc0", + .gpio = EFIKAMX_BLUE_LED, + }, +}; + +static const struct gpio_led_platform_data + mx51_efikamx_leds_data __initconst = { + .leds = mx51_efikamx_leds, + .num_leds = ARRAY_SIZE(mx51_efikamx_leds), +}; + +static struct esdhc_platform_data sd_pdata = { + .cd_type = ESDHC_CD_CONTROLLER, + .wp_type = ESDHC_WP_CONTROLLER, +}; + +static struct gpio_keys_button mx51_efikamx_powerkey[] = { + { + .code = KEY_POWER, + .gpio = EFIKAMX_POWER_KEY, + .type = EV_PWR, + .desc = "Power Button (CM)", + .wakeup = 1, + .debounce_interval = 10, /* ms */ + }, +}; + +static const struct gpio_keys_platform_data mx51_efikamx_powerkey_data __initconst = { + .buttons = mx51_efikamx_powerkey, + .nbuttons = ARRAY_SIZE(mx51_efikamx_powerkey), +}; + +void mx51_efikamx_reset(void) +{ + if (system_rev == 0x11) + gpio_direction_output(EFIKAMX_RESET1_1, 0); + else + gpio_direction_output(EFIKAMX_RESET, 0); +} + +static struct regulator *pwgt1, *pwgt2, *coincell; + +static void mx51_efikamx_power_off(void) +{ + if (!IS_ERR(coincell)) + regulator_disable(coincell); + + if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) { + regulator_disable(pwgt2); + regulator_disable(pwgt1); + } + gpio_direction_output(EFIKAMX_POWEROFF, 1); +} + +static int __init mx51_efikamx_power_init(void) +{ + if (machine_is_mx51_efikamx()) { + pwgt1 = regulator_get(NULL, "pwgt1"); + pwgt2 = regulator_get(NULL, "pwgt2"); + if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) { + regulator_enable(pwgt1); + regulator_enable(pwgt2); + } + gpio_request(EFIKAMX_POWEROFF, "poweroff"); + pm_power_off = mx51_efikamx_power_off; + + /* enable coincell charger. maybe need a small power driver ? */ + coincell = regulator_get(NULL, "coincell"); + if (!IS_ERR(coincell)) { + regulator_set_voltage(coincell, 3000000, 3000000); + regulator_enable(coincell); + } + + regulator_has_full_constraints(); + } + + return 0; +} +late_initcall(mx51_efikamx_power_init); + +static void __init mx51_efikamx_init(void) +{ + imx51_soc_init(); + + mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads, + ARRAY_SIZE(mx51efikamx_pads)); + efika_board_common_init(); + + mx51_efikamx_board_id(); + + /* on < 1.2 boards both SD controllers are used */ + if (system_rev < 0x12) { + imx51_add_sdhci_esdhc_imx(0, NULL); + imx51_add_sdhci_esdhc_imx(1, &sd_pdata); + mx51_efikamx_leds[2].default_trigger = "mmc1"; + } else + imx51_add_sdhci_esdhc_imx(0, &sd_pdata); + + gpio_led_register_device(-1, &mx51_efikamx_leds_data); + imx_add_gpio_keys(&mx51_efikamx_powerkey_data); + + if (system_rev == 0x11) { + gpio_request(EFIKAMX_RESET1_1, "reset"); + gpio_direction_output(EFIKAMX_RESET1_1, 1); + } else { + gpio_request(EFIKAMX_RESET, "reset"); + gpio_direction_output(EFIKAMX_RESET, 1); + } + + /* + * enable wifi by default only on mx + * sb and mx have same wlan pin but the value to enable it are + * different :/ + */ + gpio_request(EFIKA_WLAN_EN, "wlan_en"); + gpio_direction_output(EFIKA_WLAN_EN, 0); + msleep(10); + + gpio_request(EFIKA_WLAN_RESET, "wlan_rst"); + gpio_direction_output(EFIKA_WLAN_RESET, 0); + msleep(10); + gpio_set_value(EFIKA_WLAN_RESET, 1); +} + +static void __init mx51_efikamx_timer_init(void) +{ + mx51_clocks_init(32768, 24000000, 22579200, 24576000); +} + +static struct sys_timer mx51_efikamx_timer = { + .init = mx51_efikamx_timer_init, +}; + +MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop") + /* Maintainer: Amit Kucheria */ + .atag_offset = 0x100, + .map_io = mx51_map_io, + .init_early = imx51_init_early, + .init_irq = mx51_init_irq, + .handle_irq = imx51_handle_irq, + .timer = &mx51_efikamx_timer, + .init_machine = mx51_efikamx_init, +MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx51_efikasb.c b/arch/arm/mach-imx/mach-mx51_efikasb.c new file mode 100644 index 0000000..38c4a3e --- /dev/null +++ b/arch/arm/mach-imx/mach-mx51_efikasb.c @@ -0,0 +1,290 @@ +/* + * Copyright (C) Arnaud Patard + * + * based on code from the following + * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved. + * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "devices-imx51.h" +#include "efika.h" + +#define EFIKASB_USBH2_STP IMX_GPIO_NR(2, 20) +#define EFIKASB_GREEN_LED IMX_GPIO_NR(1, 3) +#define EFIKASB_WHITE_LED IMX_GPIO_NR(2, 25) +#define EFIKASB_PCBID0 IMX_GPIO_NR(2, 28) +#define EFIKASB_PCBID1 IMX_GPIO_NR(2, 29) +#define EFIKASB_PWRKEY IMX_GPIO_NR(2, 31) +#define EFIKASB_LID IMX_GPIO_NR(3, 14) +#define EFIKASB_POWEROFF IMX_GPIO_NR(4, 13) +#define EFIKASB_RFKILL IMX_GPIO_NR(3, 1) + +#define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0, 0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE) +#define MX51_PAD_SD1_CD IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_ESDHC_PAD_CTRL) + +static iomux_v3_cfg_t mx51efikasb_pads[] = { + /* USB HOST2 */ + MX51_PAD_EIM_D16__USBH2_DATA0, + MX51_PAD_EIM_D17__USBH2_DATA1, + MX51_PAD_EIM_D18__USBH2_DATA2, + MX51_PAD_EIM_D19__USBH2_DATA3, + MX51_PAD_EIM_D20__USBH2_DATA4, + MX51_PAD_EIM_D21__USBH2_DATA5, + MX51_PAD_EIM_D22__USBH2_DATA6, + MX51_PAD_EIM_D23__USBH2_DATA7, + MX51_PAD_EIM_A24__USBH2_CLK, + MX51_PAD_EIM_A25__USBH2_DIR, + MX51_PAD_EIM_A26__USBH2_STP, + MX51_PAD_EIM_A27__USBH2_NXT, + + /* leds */ + MX51_PAD_EIM_CS0__GPIO2_25, + MX51_PAD_GPIO1_3__GPIO1_3, + + /* pcb id */ + MX51_PAD_EIM_CS3__GPIO2_28, + MX51_PAD_EIM_CS4__GPIO2_29, + + /* lid */ + MX51_PAD_CSI1_VSYNC__GPIO3_14, + + /* power key*/ + MX51_PAD_PWRKEY, + + /* wifi/bt button */ + MX51_PAD_DI1_PIN12__GPIO3_1, + + /* power off */ + MX51_PAD_CSI2_VSYNC__GPIO4_13, + + /* wdog reset */ + MX51_PAD_GPIO1_4__WDOG1_WDOG_B, + + /* BT */ + MX51_PAD_EIM_A17__GPIO2_11, + + MX51_PAD_SD1_CD, +}; + +static int initialize_usbh2_port(struct platform_device *pdev) +{ + iomux_v3_cfg_t usbh2stp = MX51_PAD_EIM_A26__USBH2_STP; + iomux_v3_cfg_t usbh2gpio = MX51_PAD_EIM_A26__GPIO2_20; + + mxc_iomux_v3_setup_pad(usbh2gpio); + gpio_request(EFIKASB_USBH2_STP, "usbh2_stp"); + gpio_direction_output(EFIKASB_USBH2_STP, 0); + msleep(1); + gpio_set_value(EFIKASB_USBH2_STP, 1); + msleep(1); + + gpio_free(EFIKASB_USBH2_STP); + mxc_iomux_v3_setup_pad(usbh2stp); + + mdelay(10); + + return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD); +} + +static struct mxc_usbh_platform_data usbh2_config __initdata = { + .init = initialize_usbh2_port, + .portsc = MXC_EHCI_MODE_ULPI, +}; + +static void __init mx51_efikasb_usb(void) +{ + usbh2_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS | + ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND); + if (usbh2_config.otg) + imx51_add_mxc_ehci_hs(2, &usbh2_config); +} + +static const struct gpio_led mx51_efikasb_leds[] __initconst = { + { + .name = "efikasb:green", + .default_trigger = "default-on", + .gpio = EFIKASB_GREEN_LED, + .active_low = 1, + }, + { + .name = "efikasb:white", + .default_trigger = "caps", + .gpio = EFIKASB_WHITE_LED, + }, +}; + +static const struct gpio_led_platform_data + mx51_efikasb_leds_data __initconst = { + .leds = mx51_efikasb_leds, + .num_leds = ARRAY_SIZE(mx51_efikasb_leds), +}; + +static struct gpio_keys_button mx51_efikasb_keys[] = { + { + .code = KEY_POWER, + .gpio = EFIKASB_PWRKEY, + .type = EV_KEY, + .desc = "Power Button", + .wakeup = 1, + .active_low = 1, + }, + { + .code = SW_LID, + .gpio = EFIKASB_LID, + .type = EV_SW, + .desc = "Lid Switch", + .active_low = 1, + }, + { + .code = KEY_RFKILL, + .gpio = EFIKASB_RFKILL, + .type = EV_KEY, + .desc = "rfkill", + .active_low = 1, + }, +}; + +static const struct gpio_keys_platform_data mx51_efikasb_keys_data __initconst = { + .buttons = mx51_efikasb_keys, + .nbuttons = ARRAY_SIZE(mx51_efikasb_keys), +}; + +static struct esdhc_platform_data sd0_pdata = { +#define EFIKASB_SD1_CD IMX_GPIO_NR(2, 27) + .cd_gpio = EFIKASB_SD1_CD, + .cd_type = ESDHC_CD_GPIO, + .wp_type = ESDHC_WP_CONTROLLER, +}; + +static struct esdhc_platform_data sd1_pdata = { + .cd_type = ESDHC_CD_CONTROLLER, + .wp_type = ESDHC_WP_CONTROLLER, +}; + +static struct regulator *pwgt1, *pwgt2; + +static void mx51_efikasb_power_off(void) +{ + gpio_set_value(EFIKA_USB_PHY_RESET, 0); + + if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) { + regulator_disable(pwgt2); + regulator_disable(pwgt1); + } + gpio_direction_output(EFIKASB_POWEROFF, 1); +} + +static int __init mx51_efikasb_power_init(void) +{ + if (machine_is_mx51_efikasb()) { + pwgt1 = regulator_get(NULL, "pwgt1"); + pwgt2 = regulator_get(NULL, "pwgt2"); + if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) { + regulator_enable(pwgt1); + regulator_enable(pwgt2); + } + gpio_request(EFIKASB_POWEROFF, "poweroff"); + pm_power_off = mx51_efikasb_power_off; + + regulator_has_full_constraints(); + } + + return 0; +} +late_initcall(mx51_efikasb_power_init); + +/* 01 R1.3 board + 10 R2.0 board */ +static void __init mx51_efikasb_board_id(void) +{ + int id; + + gpio_request(EFIKASB_PCBID0, "pcb id0"); + gpio_direction_input(EFIKASB_PCBID0); + gpio_request(EFIKASB_PCBID1, "pcb id1"); + gpio_direction_input(EFIKASB_PCBID1); + + id = gpio_get_value(EFIKASB_PCBID0) ? 1 : 0; + id |= (gpio_get_value(EFIKASB_PCBID1) ? 1 : 0) << 1; + + switch (id) { + default: + break; + case 1: + system_rev = 0x13; + break; + case 2: + system_rev = 0x20; + break; + } +} + +static void __init efikasb_board_init(void) +{ + imx51_soc_init(); + + mxc_iomux_v3_setup_multiple_pads(mx51efikasb_pads, + ARRAY_SIZE(mx51efikasb_pads)); + efika_board_common_init(); + + mx51_efikasb_board_id(); + mx51_efikasb_usb(); + imx51_add_sdhci_esdhc_imx(0, &sd0_pdata); + imx51_add_sdhci_esdhc_imx(1, &sd1_pdata); + + gpio_led_register_device(-1, &mx51_efikasb_leds_data); + imx_add_gpio_keys(&mx51_efikasb_keys_data); +} + +static void __init mx51_efikasb_timer_init(void) +{ + mx51_clocks_init(32768, 24000000, 22579200, 24576000); +} + +static struct sys_timer mx51_efikasb_timer = { + .init = mx51_efikasb_timer_init, +}; + +MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook") + .atag_offset = 0x100, + .map_io = mx51_map_io, + .init_early = imx51_init_early, + .init_irq = mx51_init_irq, + .handle_irq = imx51_handle_irq, + .init_machine = efikasb_board_init, + .timer = &mx51_efikasb_timer, +MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx53_ard.c b/arch/arm/mach-imx/mach-mx53_ard.c new file mode 100644 index 0000000..b88a2bc --- /dev/null +++ b/arch/arm/mach-imx/mach-mx53_ard.c @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "devices-imx53.h" + +#define ARD_ETHERNET_INT_B IMX_GPIO_NR(2, 31) +#define ARD_SD1_CD IMX_GPIO_NR(1, 1) +#define ARD_SD1_WP IMX_GPIO_NR(1, 9) +#define ARD_I2CPORTEXP_B IMX_GPIO_NR(2, 3) +#define ARD_VOLUMEDOWN IMX_GPIO_NR(4, 0) +#define ARD_HOME IMX_GPIO_NR(5, 10) +#define ARD_BACK IMX_GPIO_NR(5, 11) +#define ARD_PROG IMX_GPIO_NR(5, 12) +#define ARD_VOLUMEUP IMX_GPIO_NR(5, 13) + +static iomux_v3_cfg_t mx53_ard_pads[] = { + /* UART1 */ + MX53_PAD_PATA_DIOW__UART1_TXD_MUX, + MX53_PAD_PATA_DMACK__UART1_RXD_MUX, + /* WEIM for CS1 */ + MX53_PAD_EIM_EB3__GPIO2_31, /* ETHERNET_INT_B */ + MX53_PAD_EIM_D16__EMI_WEIM_D_16, + MX53_PAD_EIM_D17__EMI_WEIM_D_17, + MX53_PAD_EIM_D18__EMI_WEIM_D_18, + MX53_PAD_EIM_D19__EMI_WEIM_D_19, + MX53_PAD_EIM_D20__EMI_WEIM_D_20, + MX53_PAD_EIM_D21__EMI_WEIM_D_21, + MX53_PAD_EIM_D22__EMI_WEIM_D_22, + MX53_PAD_EIM_D23__EMI_WEIM_D_23, + MX53_PAD_EIM_D24__EMI_WEIM_D_24, + MX53_PAD_EIM_D25__EMI_WEIM_D_25, + MX53_PAD_EIM_D26__EMI_WEIM_D_26, + MX53_PAD_EIM_D27__EMI_WEIM_D_27, + MX53_PAD_EIM_D28__EMI_WEIM_D_28, + MX53_PAD_EIM_D29__EMI_WEIM_D_29, + MX53_PAD_EIM_D30__EMI_WEIM_D_30, + MX53_PAD_EIM_D31__EMI_WEIM_D_31, + MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0, + MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1, + MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2, + MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3, + MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4, + MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5, + MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6, + MX53_PAD_EIM_OE__EMI_WEIM_OE, + MX53_PAD_EIM_RW__EMI_WEIM_RW, + MX53_PAD_EIM_CS1__EMI_WEIM_CS_1, + /* SDHC1 */ + MX53_PAD_SD1_CMD__ESDHC1_CMD, + MX53_PAD_SD1_CLK__ESDHC1_CLK, + MX53_PAD_SD1_DATA0__ESDHC1_DAT0, + MX53_PAD_SD1_DATA1__ESDHC1_DAT1, + MX53_PAD_SD1_DATA2__ESDHC1_DAT2, + MX53_PAD_SD1_DATA3__ESDHC1_DAT3, + MX53_PAD_PATA_DATA8__ESDHC1_DAT4, + MX53_PAD_PATA_DATA9__ESDHC1_DAT5, + MX53_PAD_PATA_DATA10__ESDHC1_DAT6, + MX53_PAD_PATA_DATA11__ESDHC1_DAT7, + MX53_PAD_GPIO_1__GPIO1_1, + MX53_PAD_GPIO_9__GPIO1_9, + /* I2C2 */ + MX53_PAD_EIM_EB2__I2C2_SCL, + MX53_PAD_KEY_ROW3__I2C2_SDA, + /* I2C3 */ + MX53_PAD_GPIO_3__I2C3_SCL, + MX53_PAD_GPIO_16__I2C3_SDA, + /* GPIO */ + MX53_PAD_DISP0_DAT16__GPIO5_10, /* home */ + MX53_PAD_DISP0_DAT17__GPIO5_11, /* back */ + MX53_PAD_DISP0_DAT18__GPIO5_12, /* prog */ + MX53_PAD_DISP0_DAT19__GPIO5_13, /* vol up */ + MX53_PAD_GPIO_10__GPIO4_0, /* vol down */ +}; + +#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake) \ +{ \ + .gpio = gpio_num, \ + .type = EV_KEY, \ + .code = ev_code, \ + .active_low = act_low, \ + .desc = "btn " descr, \ + .wakeup = wake, \ +} + +static struct gpio_keys_button ard_buttons[] = { + GPIO_BUTTON(ARD_HOME, KEY_HOME, 1, "home", 0), + GPIO_BUTTON(ARD_BACK, KEY_BACK, 1, "back", 0), + GPIO_BUTTON(ARD_PROG, KEY_PROGRAM, 1, "program", 0), + GPIO_BUTTON(ARD_VOLUMEUP, KEY_VOLUMEUP, 1, "volume-up", 0), + GPIO_BUTTON(ARD_VOLUMEDOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0), +}; + +static const struct gpio_keys_platform_data ard_button_data __initconst = { + .buttons = ard_buttons, + .nbuttons = ARRAY_SIZE(ard_buttons), +}; + +static struct resource ard_smsc911x_resources[] = { + { + .start = MX53_CS1_64MB_BASE_ADDR, + .end = MX53_CS1_64MB_BASE_ADDR + SZ_32M - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B), + .end = IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B), + .flags = IORESOURCE_IRQ, + }, +}; + +struct smsc911x_platform_config ard_smsc911x_config = { + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, + .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, + .flags = SMSC911X_USE_32BIT, +}; + +static struct platform_device ard_smsc_lan9220_device = { + .name = "smsc911x", + .id = -1, + .num_resources = ARRAY_SIZE(ard_smsc911x_resources), + .resource = ard_smsc911x_resources, + .dev = { + .platform_data = &ard_smsc911x_config, + }, +}; + +static const struct esdhc_platform_data mx53_ard_sd1_data __initconst = { + .cd_gpio = ARD_SD1_CD, + .wp_gpio = ARD_SD1_WP, +}; + +static struct imxi2c_platform_data mx53_ard_i2c2_data = { + .bitrate = 50000, +}; + +static struct imxi2c_platform_data mx53_ard_i2c3_data = { + .bitrate = 400000, +}; + +static void __init mx53_ard_io_init(void) +{ + gpio_request(ARD_ETHERNET_INT_B, "eth-int-b"); + gpio_direction_input(ARD_ETHERNET_INT_B); + + gpio_request(ARD_I2CPORTEXP_B, "i2cptexp-rst"); + gpio_direction_output(ARD_I2CPORTEXP_B, 1); +} + +/* Config CS1 settings for ethernet controller */ +static int weim_cs_config(void) +{ + u32 reg; + void __iomem *weim_base, *iomuxc_base; + + weim_base = ioremap(MX53_WEIM_BASE_ADDR, SZ_4K); + if (!weim_base) + return -ENOMEM; + + iomuxc_base = ioremap(MX53_IOMUXC_BASE_ADDR, SZ_4K); + if (!iomuxc_base) + return -ENOMEM; + + /* CS1 timings for LAN9220 */ + writel(0x20001, (weim_base + 0x18)); + writel(0x0, (weim_base + 0x1C)); + writel(0x16000202, (weim_base + 0x20)); + writel(0x00000002, (weim_base + 0x24)); + writel(0x16002082, (weim_base + 0x28)); + writel(0x00000000, (weim_base + 0x2C)); + writel(0x00000000, (weim_base + 0x90)); + + /* specify 64 MB on CS1 and CS0 on GPR1 */ + reg = readl(iomuxc_base + 0x4); + reg &= ~0x3F; + reg |= 0x1B; + writel(reg, (iomuxc_base + 0x4)); + + iounmap(iomuxc_base); + iounmap(weim_base); + + return 0; +} + +void __init imx53_ard_common_init(void) +{ + mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads, + ARRAY_SIZE(mx53_ard_pads)); + weim_cs_config(); +} + +static struct platform_device *devices[] __initdata = { + &ard_smsc_lan9220_device, +}; + +static void __init mx53_ard_board_init(void) +{ + imx53_soc_init(); + imx53_add_imx_uart(0, NULL); + + imx53_ard_common_init(); + mx53_ard_io_init(); + platform_add_devices(devices, ARRAY_SIZE(devices)); + + imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data); + imx53_add_imx2_wdt(0, NULL); + imx53_add_imx_i2c(1, &mx53_ard_i2c2_data); + imx53_add_imx_i2c(2, &mx53_ard_i2c3_data); + imx_add_gpio_keys(&ard_button_data); + imx53_add_ahci_imx(); +} + +static void __init mx53_ard_timer_init(void) +{ + mx53_clocks_init(32768, 24000000, 22579200, 0); +} + +static struct sys_timer mx53_ard_timer = { + .init = mx53_ard_timer_init, +}; + +MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board") + .map_io = mx53_map_io, + .init_early = imx53_init_early, + .init_irq = mx53_init_irq, + .handle_irq = imx53_handle_irq, + .timer = &mx53_ard_timer, + .init_machine = mx53_ard_board_init, +MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx53_evk.c b/arch/arm/mach-imx/mach-mx53_evk.c new file mode 100644 index 0000000..c69413d --- /dev/null +++ b/arch/arm/mach-imx/mach-mx53_evk.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2010 Yong Shen. + */ + +/* + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MX53_EVK_FEC_PHY_RST IMX_GPIO_NR(7, 6) +#define EVK_ECSPI1_CS0 IMX_GPIO_NR(2, 30) +#define EVK_ECSPI1_CS1 IMX_GPIO_NR(3, 19) +#define MX53EVK_LED IMX_GPIO_NR(7, 7) + +#include "devices-imx53.h" + +static iomux_v3_cfg_t mx53_evk_pads[] = { + MX53_PAD_CSI0_DAT10__UART1_TXD_MUX, + MX53_PAD_CSI0_DAT11__UART1_RXD_MUX, + + MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX, + MX53_PAD_PATA_DMARQ__UART2_TXD_MUX, + MX53_PAD_PATA_DIOR__UART2_RTS, + MX53_PAD_PATA_INTRQ__UART2_CTS, + + MX53_PAD_PATA_CS_0__UART3_TXD_MUX, + MX53_PAD_PATA_CS_1__UART3_RXD_MUX, + + MX53_PAD_EIM_D16__ECSPI1_SCLK, + MX53_PAD_EIM_D17__ECSPI1_MISO, + MX53_PAD_EIM_D18__ECSPI1_MOSI, + + /* ecspi chip select lines */ + MX53_PAD_EIM_EB2__GPIO2_30, + MX53_PAD_EIM_D19__GPIO3_19, + /* LED */ + MX53_PAD_PATA_DA_1__GPIO7_7, +}; + +static const struct imxuart_platform_data mx53_evk_uart_pdata __initconst = { + .flags = IMXUART_HAVE_RTSCTS, +}; + +static const struct gpio_led mx53evk_leds[] __initconst = { + { + .name = "green", + .default_trigger = "heartbeat", + .gpio = MX53EVK_LED, + }, +}; + +static const struct gpio_led_platform_data mx53evk_leds_data __initconst = { + .leds = mx53evk_leds, + .num_leds = ARRAY_SIZE(mx53evk_leds), +}; + +static inline void mx53_evk_init_uart(void) +{ + imx53_add_imx_uart(0, NULL); + imx53_add_imx_uart(1, &mx53_evk_uart_pdata); + imx53_add_imx_uart(2, NULL); +} + +static const struct imxi2c_platform_data mx53_evk_i2c_data __initconst = { + .bitrate = 100000, +}; + +static inline void mx53_evk_fec_reset(void) +{ + int ret; + + /* reset FEC PHY */ + ret = gpio_request_one(MX53_EVK_FEC_PHY_RST, GPIOF_OUT_INIT_LOW, + "fec-phy-reset"); + if (ret) { + printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret); + return; + } + msleep(1); + gpio_set_value(MX53_EVK_FEC_PHY_RST, 1); +} + +static struct fec_platform_data mx53_evk_fec_pdata = { + .phy = PHY_INTERFACE_MODE_RMII, +}; + +static struct spi_board_info mx53_evk_spi_board_info[] __initdata = { + { + .modalias = "mtd_dataflash", + .max_speed_hz = 25000000, + .bus_num = 0, + .chip_select = 1, + .mode = SPI_MODE_0, + .platform_data = NULL, + }, +}; + +static int mx53_evk_spi_cs[] = { + EVK_ECSPI1_CS0, + EVK_ECSPI1_CS1, +}; + +static const struct spi_imx_master mx53_evk_spi_data __initconst = { + .chipselect = mx53_evk_spi_cs, + .num_chipselect = ARRAY_SIZE(mx53_evk_spi_cs), +}; + +void __init imx53_evk_common_init(void) +{ + mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads, + ARRAY_SIZE(mx53_evk_pads)); +} + +static void __init mx53_evk_board_init(void) +{ + imx53_soc_init(); + imx53_evk_common_init(); + + mx53_evk_init_uart(); + mx53_evk_fec_reset(); + imx53_add_fec(&mx53_evk_fec_pdata); + + imx53_add_imx_i2c(0, &mx53_evk_i2c_data); + imx53_add_imx_i2c(1, &mx53_evk_i2c_data); + + imx53_add_sdhci_esdhc_imx(0, NULL); + imx53_add_sdhci_esdhc_imx(1, NULL); + + spi_register_board_info(mx53_evk_spi_board_info, + ARRAY_SIZE(mx53_evk_spi_board_info)); + imx53_add_ecspi(0, &mx53_evk_spi_data); + imx53_add_imx2_wdt(0, NULL); + gpio_led_register_device(-1, &mx53evk_leds_data); +} + +static void __init mx53_evk_timer_init(void) +{ + mx53_clocks_init(32768, 24000000, 22579200, 0); +} + +static struct sys_timer mx53_evk_timer = { + .init = mx53_evk_timer_init, +}; + +MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board") + .map_io = mx53_map_io, + .init_early = imx53_init_early, + .init_irq = mx53_init_irq, + .handle_irq = imx53_handle_irq, + .timer = &mx53_evk_timer, + .init_machine = mx53_evk_board_init, +MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx53_loco.c b/arch/arm/mach-imx/mach-mx53_loco.c new file mode 100644 index 0000000..e64a8f7 --- /dev/null +++ b/arch/arm/mach-imx/mach-mx53_loco.c @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "devices-imx53.h" + +#define MX53_LOCO_POWER IMX_GPIO_NR(1, 8) +#define MX53_LOCO_UI1 IMX_GPIO_NR(2, 14) +#define MX53_LOCO_UI2 IMX_GPIO_NR(2, 15) +#define LOCO_FEC_PHY_RST IMX_GPIO_NR(7, 6) +#define LOCO_LED IMX_GPIO_NR(7, 7) +#define LOCO_SD3_CD IMX_GPIO_NR(3, 11) +#define LOCO_SD3_WP IMX_GPIO_NR(3, 12) +#define LOCO_SD1_CD IMX_GPIO_NR(3, 13) +#define LOCO_ACCEL_EN IMX_GPIO_NR(6, 14) + +static iomux_v3_cfg_t mx53_loco_pads[] = { + /* FEC */ + MX53_PAD_FEC_MDC__FEC_MDC, + MX53_PAD_FEC_MDIO__FEC_MDIO, + MX53_PAD_FEC_REF_CLK__FEC_TX_CLK, + MX53_PAD_FEC_RX_ER__FEC_RX_ER, + MX53_PAD_FEC_CRS_DV__FEC_RX_DV, + MX53_PAD_FEC_RXD1__FEC_RDATA_1, + MX53_PAD_FEC_RXD0__FEC_RDATA_0, + MX53_PAD_FEC_TX_EN__FEC_TX_EN, + MX53_PAD_FEC_TXD1__FEC_TDATA_1, + MX53_PAD_FEC_TXD0__FEC_TDATA_0, + /* FEC_nRST */ + MX53_PAD_PATA_DA_0__GPIO7_6, + /* FEC_nINT */ + MX53_PAD_PATA_DATA4__GPIO2_4, + /* AUDMUX5 */ + MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC, + MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD, + MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS, + MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD, + /* I2C1 */ + MX53_PAD_CSI0_DAT8__I2C1_SDA, + MX53_PAD_CSI0_DAT9__I2C1_SCL, + MX53_PAD_NANDF_CS1__GPIO6_14, /* Accelerometer Enable */ + /* I2C2 */ + MX53_PAD_KEY_COL3__I2C2_SCL, + MX53_PAD_KEY_ROW3__I2C2_SDA, + /* SD1 */ + MX53_PAD_SD1_CMD__ESDHC1_CMD, + MX53_PAD_SD1_CLK__ESDHC1_CLK, + MX53_PAD_SD1_DATA0__ESDHC1_DAT0, + MX53_PAD_SD1_DATA1__ESDHC1_DAT1, + MX53_PAD_SD1_DATA2__ESDHC1_DAT2, + MX53_PAD_SD1_DATA3__ESDHC1_DAT3, + /* SD1_CD */ + MX53_PAD_EIM_DA13__GPIO3_13, + /* SD3 */ + MX53_PAD_PATA_DATA8__ESDHC3_DAT0, + MX53_PAD_PATA_DATA9__ESDHC3_DAT1, + MX53_PAD_PATA_DATA10__ESDHC3_DAT2, + MX53_PAD_PATA_DATA11__ESDHC3_DAT3, + MX53_PAD_PATA_DATA0__ESDHC3_DAT4, + MX53_PAD_PATA_DATA1__ESDHC3_DAT5, + MX53_PAD_PATA_DATA2__ESDHC3_DAT6, + MX53_PAD_PATA_DATA3__ESDHC3_DAT7, + MX53_PAD_PATA_IORDY__ESDHC3_CLK, + MX53_PAD_PATA_RESET_B__ESDHC3_CMD, + /* SD3_CD */ + MX53_PAD_EIM_DA11__GPIO3_11, + /* SD3_WP */ + MX53_PAD_EIM_DA12__GPIO3_12, + /* VGA */ + MX53_PAD_EIM_OE__IPU_DI1_PIN7, + MX53_PAD_EIM_RW__IPU_DI1_PIN8, + /* DISPLB */ + MX53_PAD_EIM_D20__IPU_SER_DISP0_CS, + MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK, + MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN, + MX53_PAD_EIM_D23__IPU_DI0_D0_CS, + /* DISP0_POWER_EN */ + MX53_PAD_EIM_D24__GPIO3_24, + /* DISP0 DET INT */ + MX53_PAD_EIM_D31__GPIO3_31, + /* LVDS */ + MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3, + MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK, + MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2, + MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1, + MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0, + MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3, + MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2, + MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK, + MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1, + MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0, + /* I2C1 */ + MX53_PAD_CSI0_DAT8__I2C1_SDA, + MX53_PAD_CSI0_DAT9__I2C1_SCL, + /* UART1 */ + MX53_PAD_CSI0_DAT10__UART1_TXD_MUX, + MX53_PAD_CSI0_DAT11__UART1_RXD_MUX, + /* CSI0 */ + MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12, + MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13, + MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14, + MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15, + MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16, + MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17, + MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18, + MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19, + MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC, + MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC, + MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK, + /* DISPLAY */ + MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK, + MX53_PAD_DI0_PIN15__IPU_DI0_PIN15, + MX53_PAD_DI0_PIN2__IPU_DI0_PIN2, + MX53_PAD_DI0_PIN3__IPU_DI0_PIN3, + MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0, + MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1, + MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2, + MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3, + MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4, + MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5, + MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6, + MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7, + MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8, + MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9, + MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10, + MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11, + MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12, + MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13, + MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14, + MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15, + MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16, + MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17, + MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18, + MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19, + MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20, + MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21, + MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22, + MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23, + /* Audio CLK*/ + MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK, + /* PWM */ + MX53_PAD_GPIO_1__PWM2_PWMO, + /* SPDIF */ + MX53_PAD_GPIO_7__SPDIF_PLOCK, + MX53_PAD_GPIO_17__SPDIF_OUT1, + /* GPIO */ + MX53_PAD_PATA_DA_1__GPIO7_7, /* LED */ + MX53_PAD_PATA_DA_2__GPIO7_8, + MX53_PAD_PATA_DATA5__GPIO2_5, + MX53_PAD_PATA_DATA6__GPIO2_6, + MX53_PAD_PATA_DATA14__GPIO2_14, + MX53_PAD_PATA_DATA15__GPIO2_15, + MX53_PAD_PATA_INTRQ__GPIO7_2, + MX53_PAD_EIM_WAIT__GPIO5_0, + MX53_PAD_NANDF_WP_B__GPIO6_9, + MX53_PAD_NANDF_RB0__GPIO6_10, + MX53_PAD_NANDF_CS1__GPIO6_14, + MX53_PAD_NANDF_CS2__GPIO6_15, + MX53_PAD_NANDF_CS3__GPIO6_16, + MX53_PAD_GPIO_5__GPIO1_5, + MX53_PAD_GPIO_16__GPIO7_11, + MX53_PAD_GPIO_8__GPIO1_8, +}; + +#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake) \ +{ \ + .gpio = gpio_num, \ + .type = EV_KEY, \ + .code = ev_code, \ + .active_low = act_low, \ + .desc = "btn " descr, \ + .wakeup = wake, \ +} + +static struct gpio_keys_button loco_buttons[] = { + GPIO_BUTTON(MX53_LOCO_POWER, KEY_POWER, 1, "power", 0), + GPIO_BUTTON(MX53_LOCO_UI1, KEY_VOLUMEUP, 1, "volume-up", 0), + GPIO_BUTTON(MX53_LOCO_UI2, KEY_VOLUMEDOWN, 1, "volume-down", 0), +}; + +static const struct gpio_keys_platform_data loco_button_data __initconst = { + .buttons = loco_buttons, + .nbuttons = ARRAY_SIZE(loco_buttons), +}; + +static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = { + .cd_gpio = LOCO_SD1_CD, + .cd_type = ESDHC_CD_GPIO, + .wp_type = ESDHC_WP_NONE, +}; + +static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = { + .cd_gpio = LOCO_SD3_CD, + .wp_gpio = LOCO_SD3_WP, + .cd_type = ESDHC_CD_GPIO, + .wp_type = ESDHC_WP_GPIO, +}; + +static inline void mx53_loco_fec_reset(void) +{ + int ret; + + /* reset FEC PHY */ + ret = gpio_request(LOCO_FEC_PHY_RST, "fec-phy-reset"); + if (ret) { + printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret); + return; + } + gpio_direction_output(LOCO_FEC_PHY_RST, 0); + msleep(1); + gpio_set_value(LOCO_FEC_PHY_RST, 1); +} + +static struct fec_platform_data mx53_loco_fec_data = { + .phy = PHY_INTERFACE_MODE_RMII, +}; + +static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = { + .bitrate = 100000, +}; + +static const struct gpio_led mx53loco_leds[] __initconst = { + { + .name = "green", + .default_trigger = "heartbeat", + .gpio = LOCO_LED, + }, +}; + +static const struct gpio_led_platform_data mx53loco_leds_data __initconst = { + .leds = mx53loco_leds, + .num_leds = ARRAY_SIZE(mx53loco_leds), +}; + +void __init imx53_qsb_common_init(void) +{ + mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads, + ARRAY_SIZE(mx53_loco_pads)); +} + +static struct i2c_board_info mx53loco_i2c_devices[] = { + { + I2C_BOARD_INFO("mma8450", 0x1C), + }, +}; + +static void __init mx53_loco_board_init(void) +{ + int ret; + imx53_soc_init(); + imx53_qsb_common_init(); + + imx53_add_imx_uart(0, NULL); + mx53_loco_fec_reset(); + imx53_add_fec(&mx53_loco_fec_data); + imx53_add_imx2_wdt(0, NULL); + + ret = gpio_request_one(LOCO_ACCEL_EN, GPIOF_OUT_INIT_HIGH, "accel_en"); + if (ret) + pr_err("Cannot request ACCEL_EN pin: %d\n", ret); + + i2c_register_board_info(0, mx53loco_i2c_devices, + ARRAY_SIZE(mx53loco_i2c_devices)); + imx53_add_imx_i2c(0, &mx53_loco_i2c_data); + imx53_add_imx_i2c(1, &mx53_loco_i2c_data); + imx53_add_sdhci_esdhc_imx(0, &mx53_loco_sd1_data); + imx53_add_sdhci_esdhc_imx(2, &mx53_loco_sd3_data); + imx_add_gpio_keys(&loco_button_data); + gpio_led_register_device(-1, &mx53loco_leds_data); + imx53_add_ahci_imx(); +} + +static void __init mx53_loco_timer_init(void) +{ + mx53_clocks_init(32768, 24000000, 0, 0); +} + +static struct sys_timer mx53_loco_timer = { + .init = mx53_loco_timer_init, +}; + +MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board") + .map_io = mx53_map_io, + .init_early = imx53_init_early, + .init_irq = mx53_init_irq, + .handle_irq = imx53_handle_irq, + .timer = &mx53_loco_timer, + .init_machine = mx53_loco_board_init, +MACHINE_END diff --git a/arch/arm/mach-imx/mach-mx53_smd.c b/arch/arm/mach-imx/mach-mx53_smd.c new file mode 100644 index 0000000..d498573 --- /dev/null +++ b/arch/arm/mach-imx/mach-mx53_smd.c @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "devices-imx53.h" + +#define SMD_FEC_PHY_RST IMX_GPIO_NR(7, 6) +#define MX53_SMD_SATA_PWR_EN IMX_GPIO_NR(3, 3) + +static iomux_v3_cfg_t mx53_smd_pads[] = { + MX53_PAD_CSI0_DAT10__UART1_TXD_MUX, + MX53_PAD_CSI0_DAT11__UART1_RXD_MUX, + + MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX, + MX53_PAD_PATA_DMARQ__UART2_TXD_MUX, + + MX53_PAD_PATA_CS_0__UART3_TXD_MUX, + MX53_PAD_PATA_CS_1__UART3_RXD_MUX, + MX53_PAD_PATA_DA_1__UART3_CTS, + MX53_PAD_PATA_DA_2__UART3_RTS, + /* I2C1 */ + MX53_PAD_CSI0_DAT8__I2C1_SDA, + MX53_PAD_CSI0_DAT9__I2C1_SCL, + /* SD1 */ + MX53_PAD_SD1_CMD__ESDHC1_CMD, + MX53_PAD_SD1_CLK__ESDHC1_CLK, + MX53_PAD_SD1_DATA0__ESDHC1_DAT0, + MX53_PAD_SD1_DATA1__ESDHC1_DAT1, + MX53_PAD_SD1_DATA2__ESDHC1_DAT2, + MX53_PAD_SD1_DATA3__ESDHC1_DAT3, + /* SD2 */ + MX53_PAD_SD2_CMD__ESDHC2_CMD, + MX53_PAD_SD2_CLK__ESDHC2_CLK, + MX53_PAD_SD2_DATA0__ESDHC2_DAT0, + MX53_PAD_SD2_DATA1__ESDHC2_DAT1, + MX53_PAD_SD2_DATA2__ESDHC2_DAT2, + MX53_PAD_SD2_DATA3__ESDHC2_DAT3, + /* SD3 */ + MX53_PAD_PATA_DATA8__ESDHC3_DAT0, + MX53_PAD_PATA_DATA9__ESDHC3_DAT1, + MX53_PAD_PATA_DATA10__ESDHC3_DAT2, + MX53_PAD_PATA_DATA11__ESDHC3_DAT3, + MX53_PAD_PATA_DATA0__ESDHC3_DAT4, + MX53_PAD_PATA_DATA1__ESDHC3_DAT5, + MX53_PAD_PATA_DATA2__ESDHC3_DAT6, + MX53_PAD_PATA_DATA3__ESDHC3_DAT7, + MX53_PAD_PATA_IORDY__ESDHC3_CLK, + MX53_PAD_PATA_RESET_B__ESDHC3_CMD, +}; + +static const struct imxuart_platform_data mx53_smd_uart_data __initconst = { + .flags = IMXUART_HAVE_RTSCTS, +}; + +static inline void mx53_smd_init_uart(void) +{ + imx53_add_imx_uart(0, NULL); + imx53_add_imx_uart(1, NULL); + imx53_add_imx_uart(2, &mx53_smd_uart_data); +} + +static inline void mx53_smd_fec_reset(void) +{ + int ret; + + /* reset FEC PHY */ + ret = gpio_request(SMD_FEC_PHY_RST, "fec-phy-reset"); + if (ret) { + printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret); + return; + } + gpio_direction_output(SMD_FEC_PHY_RST, 0); + msleep(1); + gpio_set_value(SMD_FEC_PHY_RST, 1); +} + +static struct fec_platform_data mx53_smd_fec_data = { + .phy = PHY_INTERFACE_MODE_RMII, +}; + +static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = { + .bitrate = 100000, +}; + +static inline void mx53_smd_ahci_pwr_on(void) +{ + int ret; + + /* Enable SATA PWR */ + ret = gpio_request_one(MX53_SMD_SATA_PWR_EN, + GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "ahci-sata-pwr"); + if (ret) { + pr_err("failed to enable SATA_PWR_EN: %d\n", ret); + return; + } +} + +void __init imx53_smd_common_init(void) +{ + mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads, + ARRAY_SIZE(mx53_smd_pads)); +} + +static void __init mx53_smd_board_init(void) +{ + imx53_soc_init(); + imx53_smd_common_init(); + + mx53_smd_init_uart(); + mx53_smd_fec_reset(); + imx53_add_fec(&mx53_smd_fec_data); + imx53_add_imx2_wdt(0, NULL); + imx53_add_imx_i2c(0, &mx53_smd_i2c_data); + imx53_add_sdhci_esdhc_imx(0, NULL); + imx53_add_sdhci_esdhc_imx(1, NULL); + imx53_add_sdhci_esdhc_imx(2, NULL); + mx53_smd_ahci_pwr_on(); + imx53_add_ahci_imx(); +} + +static void __init mx53_smd_timer_init(void) +{ + mx53_clocks_init(32768, 24000000, 22579200, 0); +} + +static struct sys_timer mx53_smd_timer = { + .init = mx53_smd_timer_init, +}; + +MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board") + .map_io = mx53_map_io, + .init_early = imx53_init_early, + .init_irq = mx53_init_irq, + .handle_irq = imx53_handle_irq, + .timer = &mx53_smd_timer, + .init_machine = mx53_smd_board_init, +MACHINE_END diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c new file mode 100644 index 0000000..26eacc9 --- /dev/null +++ b/arch/arm/mach-imx/mm-imx5.c @@ -0,0 +1,190 @@ +/* + * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + * + * Create static mapping between physical to virtual memory. + */ + +#include +#include + +#include + +#include +#include +#include +#include + +static void imx5_idle(void) +{ + mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); +} + +/* + * Define the MX50 memory map. + */ +static struct map_desc mx50_io_desc[] __initdata = { + imx_map_entry(MX50, TZIC, MT_DEVICE), + imx_map_entry(MX50, SPBA0, MT_DEVICE), + imx_map_entry(MX50, AIPS1, MT_DEVICE), + imx_map_entry(MX50, AIPS2, MT_DEVICE), +}; + +/* + * Define the MX51 memory map. + */ +static struct map_desc mx51_io_desc[] __initdata = { + imx_map_entry(MX51, TZIC, MT_DEVICE), + imx_map_entry(MX51, IRAM, MT_DEVICE), + imx_map_entry(MX51, AIPS1, MT_DEVICE), + imx_map_entry(MX51, SPBA0, MT_DEVICE), + imx_map_entry(MX51, AIPS2, MT_DEVICE), +}; + +/* + * Define the MX53 memory map. + */ +static struct map_desc mx53_io_desc[] __initdata = { + imx_map_entry(MX53, TZIC, MT_DEVICE), + imx_map_entry(MX53, AIPS1, MT_DEVICE), + imx_map_entry(MX53, SPBA0, MT_DEVICE), + imx_map_entry(MX53, AIPS2, MT_DEVICE), +}; + +/* + * This function initializes the memory map. It is called during the + * system startup to create static physical to virtual memory mappings + * for the IO modules. + */ +void __init mx50_map_io(void) +{ + iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc)); +} + +void __init mx51_map_io(void) +{ + iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc)); +} + +void __init mx53_map_io(void) +{ + iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc)); +} + +void __init imx50_init_early(void) +{ + mxc_set_cpu_type(MXC_CPU_MX50); + mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR)); + mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR)); +} + +void __init imx51_init_early(void) +{ + mxc_set_cpu_type(MXC_CPU_MX51); + mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR)); + mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR)); + imx_idle = imx5_idle; +} + +void __init imx53_init_early(void) +{ + mxc_set_cpu_type(MXC_CPU_MX53); + mxc_iomux_v3_init(MX53_IO_ADDRESS(MX53_IOMUXC_BASE_ADDR)); + mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR)); +} + +void __init mx50_init_irq(void) +{ + tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR)); +} + +void __init mx51_init_irq(void) +{ + tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR)); +} + +void __init mx53_init_irq(void) +{ + tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR)); +} + +static struct sdma_script_start_addrs imx51_sdma_script __initdata = { + .ap_2_ap_addr = 642, + .uart_2_mcu_addr = 817, + .mcu_2_app_addr = 747, + .mcu_2_shp_addr = 961, + .ata_2_mcu_addr = 1473, + .mcu_2_ata_addr = 1392, + .app_2_per_addr = 1033, + .app_2_mcu_addr = 683, + .shp_2_per_addr = 1251, + .shp_2_mcu_addr = 892, +}; + +static struct sdma_platform_data imx51_sdma_pdata __initdata = { + .fw_name = "sdma-imx51.bin", + .script_addrs = &imx51_sdma_script, +}; + +static struct sdma_script_start_addrs imx53_sdma_script __initdata = { + .ap_2_ap_addr = 642, + .app_2_mcu_addr = 683, + .mcu_2_app_addr = 747, + .uart_2_mcu_addr = 817, + .shp_2_mcu_addr = 891, + .mcu_2_shp_addr = 960, + .uartsh_2_mcu_addr = 1032, + .spdif_2_mcu_addr = 1100, + .mcu_2_spdif_addr = 1134, + .firi_2_mcu_addr = 1193, + .mcu_2_firi_addr = 1290, +}; + +static struct sdma_platform_data imx53_sdma_pdata __initdata = { + .fw_name = "sdma-imx53.bin", + .script_addrs = &imx53_sdma_script, +}; + +void __init imx50_soc_init(void) +{ + /* i.mx50 has the i.mx31 type gpio */ + mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH); + mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH); + mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH); + mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH); + mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH); + mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH); +} + +void __init imx51_soc_init(void) +{ + /* i.mx51 has the i.mx31 type gpio */ + mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH); + mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH); + mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH); + mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH); + + /* i.mx51 has the i.mx35 type sdma */ + imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata); +} + +void __init imx53_soc_init(void) +{ + /* i.mx53 has the i.mx31 type gpio */ + mxc_register_gpio("imx31-gpio", 0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH); + mxc_register_gpio("imx31-gpio", 1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH); + mxc_register_gpio("imx31-gpio", 2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH); + mxc_register_gpio("imx31-gpio", 3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH); + mxc_register_gpio("imx31-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH); + mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH); + mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH); + + /* i.mx53 has the i.mx35 type sdma */ + imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata); +} diff --git a/arch/arm/mach-imx/mx51_efika.c b/arch/arm/mach-imx/mx51_efika.c new file mode 100644 index 0000000..ec6ca91 --- /dev/null +++ b/arch/arm/mach-imx/mx51_efika.c @@ -0,0 +1,632 @@ +/* + * based on code from the following + * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved. + * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "devices-imx51.h" +#include "efika.h" +#include "cpu_op-mx51.h" + +#define MX51_USB_CTRL_1_OFFSET 0x10 +#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25) +#define MX51_USB_PLL_DIV_19_2_MHZ 0x01 + +#define EFIKAMX_USB_HUB_RESET IMX_GPIO_NR(1, 5) +#define EFIKAMX_USBH1_STP IMX_GPIO_NR(1, 27) + +#define EFIKAMX_SPI_CS0 IMX_GPIO_NR(4, 24) +#define EFIKAMX_SPI_CS1 IMX_GPIO_NR(4, 25) + +#define EFIKAMX_PMIC IMX_GPIO_NR(1, 6) + +static iomux_v3_cfg_t mx51efika_pads[] = { + /* UART1 */ + MX51_PAD_UART1_RXD__UART1_RXD, + MX51_PAD_UART1_TXD__UART1_TXD, + MX51_PAD_UART1_RTS__UART1_RTS, + MX51_PAD_UART1_CTS__UART1_CTS, + + /* SD 1 */ + MX51_PAD_SD1_CMD__SD1_CMD, + MX51_PAD_SD1_CLK__SD1_CLK, + MX51_PAD_SD1_DATA0__SD1_DATA0, + MX51_PAD_SD1_DATA1__SD1_DATA1, + MX51_PAD_SD1_DATA2__SD1_DATA2, + MX51_PAD_SD1_DATA3__SD1_DATA3, + + /* SD 2 */ + MX51_PAD_SD2_CMD__SD2_CMD, + MX51_PAD_SD2_CLK__SD2_CLK, + MX51_PAD_SD2_DATA0__SD2_DATA0, + MX51_PAD_SD2_DATA1__SD2_DATA1, + MX51_PAD_SD2_DATA2__SD2_DATA2, + MX51_PAD_SD2_DATA3__SD2_DATA3, + + /* SD/MMC WP/CD */ + MX51_PAD_GPIO1_0__SD1_CD, + MX51_PAD_GPIO1_1__SD1_WP, + MX51_PAD_GPIO1_7__SD2_WP, + MX51_PAD_GPIO1_8__SD2_CD, + + /* spi */ + MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI, + MX51_PAD_CSPI1_MISO__ECSPI1_MISO, + MX51_PAD_CSPI1_SS0__GPIO4_24, + MX51_PAD_CSPI1_SS1__GPIO4_25, + MX51_PAD_CSPI1_RDY__ECSPI1_RDY, + MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK, + MX51_PAD_GPIO1_6__GPIO1_6, + + /* USB HOST1 */ + MX51_PAD_USBH1_CLK__USBH1_CLK, + MX51_PAD_USBH1_DIR__USBH1_DIR, + MX51_PAD_USBH1_NXT__USBH1_NXT, + MX51_PAD_USBH1_DATA0__USBH1_DATA0, + MX51_PAD_USBH1_DATA1__USBH1_DATA1, + MX51_PAD_USBH1_DATA2__USBH1_DATA2, + MX51_PAD_USBH1_DATA3__USBH1_DATA3, + MX51_PAD_USBH1_DATA4__USBH1_DATA4, + MX51_PAD_USBH1_DATA5__USBH1_DATA5, + MX51_PAD_USBH1_DATA6__USBH1_DATA6, + MX51_PAD_USBH1_DATA7__USBH1_DATA7, + + /* USB HUB RESET */ + MX51_PAD_GPIO1_5__GPIO1_5, + + /* WLAN */ + MX51_PAD_EIM_A22__GPIO2_16, + MX51_PAD_EIM_A16__GPIO2_10, + + /* USB PHY RESET */ + MX51_PAD_EIM_D27__GPIO2_9, +}; + +/* Serial ports */ +static const struct imxuart_platform_data uart_pdata = { + .flags = IMXUART_HAVE_RTSCTS, +}; + +/* This function is board specific as the bit mask for the plldiv will also + * be different for other Freescale SoCs, thus a common bitmask is not + * possible and cannot get place in /plat-mxc/ehci.c. + */ +static int initialize_otg_port(struct platform_device *pdev) +{ + u32 v; + void __iomem *usb_base; + void __iomem *usbother_base; + usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); + if (!usb_base) + return -ENOMEM; + usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET); + + /* Set the PHY clock to 19.2MHz */ + v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); + v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK; + v |= MX51_USB_PLL_DIV_19_2_MHZ; + __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); + iounmap(usb_base); + + mdelay(10); + + return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY); +} + +static const struct mxc_usbh_platform_data dr_utmi_config __initconst = { + .init = initialize_otg_port, + .portsc = MXC_EHCI_UTMI_16BIT, +}; + +static int initialize_usbh1_port(struct platform_device *pdev) +{ + iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP; + iomux_v3_cfg_t usbh1gpio = MX51_PAD_USBH1_STP__GPIO1_27; + u32 v; + void __iomem *usb_base; + void __iomem *socregs_base; + + mxc_iomux_v3_setup_pad(usbh1gpio); + gpio_request(EFIKAMX_USBH1_STP, "usbh1_stp"); + gpio_direction_output(EFIKAMX_USBH1_STP, 0); + msleep(1); + gpio_set_value(EFIKAMX_USBH1_STP, 1); + msleep(1); + + usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); + socregs_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET); + + /* The clock for the USBH1 ULPI port will come externally */ + /* from the PHY. */ + v = __raw_readl(socregs_base + MX51_USB_CTRL_1_OFFSET); + __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, + socregs_base + MX51_USB_CTRL_1_OFFSET); + + iounmap(usb_base); + + gpio_free(EFIKAMX_USBH1_STP); + mxc_iomux_v3_setup_pad(usbh1stp); + + mdelay(10); + + return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD); +} + +static struct mxc_usbh_platform_data usbh1_config __initdata = { + .init = initialize_usbh1_port, + .portsc = MXC_EHCI_MODE_ULPI, +}; + +static void mx51_efika_hubreset(void) +{ + gpio_request(EFIKAMX_USB_HUB_RESET, "usb_hub_rst"); + gpio_direction_output(EFIKAMX_USB_HUB_RESET, 1); + msleep(1); + gpio_set_value(EFIKAMX_USB_HUB_RESET, 0); + msleep(1); + gpio_set_value(EFIKAMX_USB_HUB_RESET, 1); +} + +static void __init mx51_efika_usb(void) +{ + mx51_efika_hubreset(); + + /* pulling it low, means no USB at all... */ + gpio_request(EFIKA_USB_PHY_RESET, "usb_phy_reset"); + gpio_direction_output(EFIKA_USB_PHY_RESET, 0); + msleep(1); + gpio_set_value(EFIKA_USB_PHY_RESET, 1); + + usbh1_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS | + ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND); + + imx51_add_mxc_ehci_otg(&dr_utmi_config); + if (usbh1_config.otg) + imx51_add_mxc_ehci_hs(1, &usbh1_config); +} + +static struct mtd_partition mx51_efika_spi_nor_partitions[] = { + { + .name = "u-boot", + .offset = 0, + .size = SZ_256K, + }, + { + .name = "config", + .offset = MTDPART_OFS_APPEND, + .size = SZ_64K, + }, +}; + +static struct flash_platform_data mx51_efika_spi_flash_data = { + .name = "spi_flash", + .parts = mx51_efika_spi_nor_partitions, + .nr_parts = ARRAY_SIZE(mx51_efika_spi_nor_partitions), + .type = "sst25vf032b", +}; + +static struct regulator_consumer_supply sw1_consumers[] = { + { + .supply = "cpu_vcc", + } +}; + +static struct regulator_consumer_supply vdig_consumers[] = { + /* sgtl5000 */ + REGULATOR_SUPPLY("VDDA", "1-000a"), + REGULATOR_SUPPLY("VDDD", "1-000a"), +}; + +static struct regulator_consumer_supply vvideo_consumers[] = { + /* sgtl5000 */ + REGULATOR_SUPPLY("VDDIO", "1-000a"), +}; + +static struct regulator_consumer_supply vsd_consumers[] = { + REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.0"), + REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.1"), +}; + +static struct regulator_consumer_supply pwgt1_consumer[] = { + { + .supply = "pwgt1", + } +}; + +static struct regulator_consumer_supply pwgt2_consumer[] = { + { + .supply = "pwgt2", + } +}; + +static struct regulator_consumer_supply coincell_consumer[] = { + { + .supply = "coincell", + } +}; + +static struct regulator_init_data sw1_init = { + .constraints = { + .name = "SW1", + .min_uV = 600000, + .max_uV = 1375000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .valid_modes_mask = 0, + .always_on = 1, + .boot_on = 1, + .state_mem = { + .uV = 850000, + .mode = REGULATOR_MODE_NORMAL, + .enabled = 1, + }, + }, + .num_consumer_supplies = ARRAY_SIZE(sw1_consumers), + .consumer_supplies = sw1_consumers, +}; + +static struct regulator_init_data sw2_init = { + .constraints = { + .name = "SW2", + .min_uV = 900000, + .max_uV = 1850000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .always_on = 1, + .boot_on = 1, + .state_mem = { + .uV = 950000, + .mode = REGULATOR_MODE_NORMAL, + .enabled = 1, + }, + } +}; + +static struct regulator_init_data sw3_init = { + .constraints = { + .name = "SW3", + .min_uV = 1100000, + .max_uV = 1850000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .always_on = 1, + .boot_on = 1, + } +}; + +static struct regulator_init_data sw4_init = { + .constraints = { + .name = "SW4", + .min_uV = 1100000, + .max_uV = 1850000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .always_on = 1, + .boot_on = 1, + } +}; + +static struct regulator_init_data viohi_init = { + .constraints = { + .name = "VIOHI", + .boot_on = 1, + .always_on = 1, + } +}; + +static struct regulator_init_data vusb_init = { + .constraints = { + .name = "VUSB", + .boot_on = 1, + .always_on = 1, + } +}; + +static struct regulator_init_data swbst_init = { + .constraints = { + .name = "SWBST", + } +}; + +static struct regulator_init_data vdig_init = { + .constraints = { + .name = "VDIG", + .min_uV = 1050000, + .max_uV = 1800000, + .valid_ops_mask = + REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, + .boot_on = 1, + .always_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(vdig_consumers), + .consumer_supplies = vdig_consumers, +}; + +static struct regulator_init_data vpll_init = { + .constraints = { + .name = "VPLL", + .min_uV = 1050000, + .max_uV = 1800000, + .valid_ops_mask = + REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, + .boot_on = 1, + .always_on = 1, + } +}; + +static struct regulator_init_data vusb2_init = { + .constraints = { + .name = "VUSB2", + .min_uV = 2400000, + .max_uV = 2775000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .boot_on = 1, + .always_on = 1, + } +}; + +static struct regulator_init_data vvideo_init = { + .constraints = { + .name = "VVIDEO", + .min_uV = 2775000, + .max_uV = 2775000, + .valid_ops_mask = + REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, + .boot_on = 1, + .apply_uV = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(vvideo_consumers), + .consumer_supplies = vvideo_consumers, +}; + +static struct regulator_init_data vaudio_init = { + .constraints = { + .name = "VAUDIO", + .min_uV = 2300000, + .max_uV = 3000000, + .valid_ops_mask = + REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, + .boot_on = 1, + } +}; + +static struct regulator_init_data vsd_init = { + .constraints = { + .name = "VSD", + .min_uV = 1800000, + .max_uV = 3150000, + .valid_ops_mask = + REGULATOR_CHANGE_VOLTAGE, + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(vsd_consumers), + .consumer_supplies = vsd_consumers, +}; + +static struct regulator_init_data vcam_init = { + .constraints = { + .name = "VCAM", + .min_uV = 2500000, + .max_uV = 3000000, + .valid_ops_mask = + REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, + .valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL, + .boot_on = 1, + } +}; + +static struct regulator_init_data vgen1_init = { + .constraints = { + .name = "VGEN1", + .min_uV = 1200000, + .max_uV = 3150000, + .valid_ops_mask = + REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, + .boot_on = 1, + .always_on = 1, + } +}; + +static struct regulator_init_data vgen2_init = { + .constraints = { + .name = "VGEN2", + .min_uV = 1200000, + .max_uV = 3150000, + .valid_ops_mask = + REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, + .boot_on = 1, + .always_on = 1, + } +}; + +static struct regulator_init_data vgen3_init = { + .constraints = { + .name = "VGEN3", + .min_uV = 1800000, + .max_uV = 2900000, + .valid_ops_mask = + REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, + .boot_on = 1, + .always_on = 1, + } +}; + +static struct regulator_init_data gpo1_init = { + .constraints = { + .name = "GPO1", + } +}; + +static struct regulator_init_data gpo2_init = { + .constraints = { + .name = "GPO2", + } +}; + +static struct regulator_init_data gpo3_init = { + .constraints = { + .name = "GPO3", + } +}; + +static struct regulator_init_data gpo4_init = { + .constraints = { + .name = "GPO4", + } +}; + +static struct regulator_init_data pwgt1_init = { + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(pwgt1_consumer), + .consumer_supplies = pwgt1_consumer, +}; + +static struct regulator_init_data pwgt2_init = { + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(pwgt2_consumer), + .consumer_supplies = pwgt2_consumer, +}; + +static struct regulator_init_data vcoincell_init = { + .constraints = { + .name = "COINCELL", + .min_uV = 3000000, + .max_uV = 3000000, + .valid_ops_mask = + REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(coincell_consumer), + .consumer_supplies = coincell_consumer, +}; + +static struct mc13xxx_regulator_init_data mx51_efika_regulators[] = { + { .id = MC13892_SW1, .init_data = &sw1_init }, + { .id = MC13892_SW2, .init_data = &sw2_init }, + { .id = MC13892_SW3, .init_data = &sw3_init }, + { .id = MC13892_SW4, .init_data = &sw4_init }, + { .id = MC13892_SWBST, .init_data = &swbst_init }, + { .id = MC13892_VIOHI, .init_data = &viohi_init }, + { .id = MC13892_VPLL, .init_data = &vpll_init }, + { .id = MC13892_VDIG, .init_data = &vdig_init }, + { .id = MC13892_VSD, .init_data = &vsd_init }, + { .id = MC13892_VUSB2, .init_data = &vusb2_init }, + { .id = MC13892_VVIDEO, .init_data = &vvideo_init }, + { .id = MC13892_VAUDIO, .init_data = &vaudio_init }, + { .id = MC13892_VCAM, .init_data = &vcam_init }, + { .id = MC13892_VGEN1, .init_data = &vgen1_init }, + { .id = MC13892_VGEN2, .init_data = &vgen2_init }, + { .id = MC13892_VGEN3, .init_data = &vgen3_init }, + { .id = MC13892_VUSB, .init_data = &vusb_init }, + { .id = MC13892_GPO1, .init_data = &gpo1_init }, + { .id = MC13892_GPO2, .init_data = &gpo2_init }, + { .id = MC13892_GPO3, .init_data = &gpo3_init }, + { .id = MC13892_GPO4, .init_data = &gpo4_init }, + { .id = MC13892_PWGT1SPI, .init_data = &pwgt1_init }, + { .id = MC13892_PWGT2SPI, .init_data = &pwgt2_init }, + { .id = MC13892_VCOINCELL, .init_data = &vcoincell_init }, +}; + +static struct mc13xxx_platform_data mx51_efika_mc13892_data = { + .flags = MC13XXX_USE_RTC, + .regulators = { + .num_regulators = ARRAY_SIZE(mx51_efika_regulators), + .regulators = mx51_efika_regulators, + }, +}; + +static struct spi_board_info mx51_efika_spi_board_info[] __initdata = { + { + .modalias = "m25p80", + .max_speed_hz = 25000000, + .bus_num = 0, + .chip_select = 1, + .platform_data = &mx51_efika_spi_flash_data, + .irq = -1, + }, + { + .modalias = "mc13892", + .max_speed_hz = 1000000, + .bus_num = 0, + .chip_select = 0, + .platform_data = &mx51_efika_mc13892_data, + .irq = IMX_GPIO_TO_IRQ(EFIKAMX_PMIC), + }, +}; + +static int mx51_efika_spi_cs[] = { + EFIKAMX_SPI_CS0, + EFIKAMX_SPI_CS1, +}; + +static const struct spi_imx_master mx51_efika_spi_pdata __initconst = { + .chipselect = mx51_efika_spi_cs, + .num_chipselect = ARRAY_SIZE(mx51_efika_spi_cs), +}; + +void __init efika_board_common_init(void) +{ + mxc_iomux_v3_setup_multiple_pads(mx51efika_pads, + ARRAY_SIZE(mx51efika_pads)); + imx51_add_imx_uart(0, &uart_pdata); + mx51_efika_usb(); + + /* FIXME: comes from original code. check this. */ + if (mx51_revision() < IMX_CHIP_REVISION_2_0) + sw2_init.constraints.state_mem.uV = 1100000; + else if (mx51_revision() == IMX_CHIP_REVISION_2_0) { + sw2_init.constraints.state_mem.uV = 1250000; + sw1_init.constraints.state_mem.uV = 1000000; + } + if (machine_is_mx51_efikasb()) + vgen1_init.constraints.max_uV = 1200000; + + gpio_request(EFIKAMX_PMIC, "pmic irq"); + gpio_direction_input(EFIKAMX_PMIC); + spi_register_board_info(mx51_efika_spi_board_info, + ARRAY_SIZE(mx51_efika_spi_board_info)); + imx51_add_ecspi(0, &mx51_efika_spi_pdata); + + imx51_add_pata_imx(); + +#if defined(CONFIG_CPU_FREQ_IMX) + get_cpu_op = mx51_get_cpu_op; +#endif +} diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c new file mode 100644 index 0000000..3d57b5d --- /dev/null +++ b/arch/arm/mach-imx/pm-imx5.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "crm-regs-imx5.h" + +static struct clk *gpc_dvfs_clk; + +/* + * set cpu low power mode before WFI instruction. This function is called + * mx5 because it can be used for mx50, mx51, and mx53. + */ +void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode) +{ + u32 plat_lpc, arm_srpgcr, ccm_clpcr; + u32 empgc0, empgc1; + int stop_mode = 0; + + /* always allow platform to issue a deep sleep mode request */ + plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) & + ~(MXC_CORTEXA8_PLAT_LPC_DSM); + ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK); + arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR); + empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR); + empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR); + + switch (mode) { + case WAIT_CLOCKED: + break; + case WAIT_UNCLOCKED: + ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET; + break; + case WAIT_UNCLOCKED_POWER_OFF: + case STOP_POWER_OFF: + plat_lpc |= MXC_CORTEXA8_PLAT_LPC_DSM + | MXC_CORTEXA8_PLAT_LPC_DBG_DSM; + if (mode == WAIT_UNCLOCKED_POWER_OFF) { + ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET; + ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY; + ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS; + stop_mode = 0; + } else { + ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET; + ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET; + ccm_clpcr |= MXC_CCM_CLPCR_VSTBY; + ccm_clpcr |= MXC_CCM_CLPCR_SBYOS; + stop_mode = 1; + } + arm_srpgcr |= MXC_SRPGCR_PCR; + + if (tzic_enable_wake(1) != 0) + return; + break; + case STOP_POWER_ON: + ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET; + break; + default: + printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode); + return; + } + + __raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC); + __raw_writel(ccm_clpcr, MXC_CCM_CLPCR); + __raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR); + + /* Enable NEON SRPG for all but MX50TO1.0. */ + if (mx50_revision() != IMX_CHIP_REVISION_1_0) + __raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR); + + if (stop_mode) { + empgc0 |= MXC_SRPGCR_PCR; + empgc1 |= MXC_SRPGCR_PCR; + + __raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR); + __raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR); + } +} + +static int mx5_suspend_prepare(void) +{ + return clk_enable(gpc_dvfs_clk); +} + +static int mx5_suspend_enter(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_MEM: + mx5_cpu_lp_set(STOP_POWER_OFF); + break; + case PM_SUSPEND_STANDBY: + mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); + break; + default: + return -EINVAL; + } + + if (state == PM_SUSPEND_MEM) { + local_flush_tlb_all(); + flush_cache_all(); + + /*clear the EMPGC0/1 bits */ + __raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR); + __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR); + } + cpu_do_idle(); + return 0; +} + +static void mx5_suspend_finish(void) +{ + clk_disable(gpc_dvfs_clk); +} + +static int mx5_pm_valid(suspend_state_t state) +{ + return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX); +} + +static const struct platform_suspend_ops mx5_suspend_ops = { + .valid = mx5_pm_valid, + .prepare = mx5_suspend_prepare, + .enter = mx5_suspend_enter, + .finish = mx5_suspend_finish, +}; + +static int __init mx5_pm_init(void) +{ + if (!cpu_is_mx51() && !cpu_is_mx53()) + return 0; + + if (gpc_dvfs_clk == NULL) + gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs"); + + if (!IS_ERR(gpc_dvfs_clk)) { + if (cpu_is_mx51()) + suspend_set_ops(&mx5_suspend_ops); + } else + return -EPERM; + + return 0; +} +device_initcall(mx5_pm_init); diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig deleted file mode 100644 index af0c212..0000000 --- a/arch/arm/mach-mx5/Kconfig +++ /dev/null @@ -1,244 +0,0 @@ -if ARCH_MX5 - -# ARCH_MX5/50/53 are left to mark places where prevent multi-soc in single -# image. So for most time, SOC_IMX50/51/53 should be used. - -config ARCH_MX51 - bool - -config ARCH_MX50 - bool - -config ARCH_MX53 - bool - -config SOC_IMX50 - bool - select CPU_V7 - select ARM_L1_CACHE_SHIFT_6 - select MXC_TZIC - select ARCH_MXC_IOMUX_V3 - select ARCH_MXC_AUDMUX_V2 - select ARCH_HAS_CPUFREQ - select ARCH_MX50 - -config SOC_IMX51 - bool - select CPU_V7 - select ARM_L1_CACHE_SHIFT_6 - select MXC_TZIC - select ARCH_MXC_IOMUX_V3 - select ARCH_MXC_AUDMUX_V2 - select ARCH_HAS_CPUFREQ - select ARCH_MX51 - -config SOC_IMX53 - bool - select CPU_V7 - select ARM_L1_CACHE_SHIFT_6 - select MXC_TZIC - select ARCH_MXC_IOMUX_V3 - select ARCH_MX53 - -#comment "i.MX50 machines:" - -config MACH_MX50_RDP - bool "Support MX50 reference design platform" - depends on BROKEN - select SOC_IMX50 - select IMX_HAVE_PLATFORM_IMX_I2C - select IMX_HAVE_PLATFORM_IMX_UART - select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - select IMX_HAVE_PLATFORM_SPI_IMX - help - Include support for MX50 reference design platform (RDP) board. This - includes specific configurations for the board and its peripherals. - -comment "i.MX51 machines:" - -config MACH_IMX51_DT - bool "Support i.MX51 platforms from device tree" - select SOC_IMX51 - select USE_OF - select MACH_MX51_BABBAGE - help - Include support for Freescale i.MX51 based platforms - using the device tree for discovery - -config MACH_MX51_BABBAGE - bool "Support MX51 BABBAGE platforms" - select SOC_IMX51 - select IMX_HAVE_PLATFORM_FSL_USB2_UDC - select IMX_HAVE_PLATFORM_IMX2_WDT - select IMX_HAVE_PLATFORM_IMX_I2C - select IMX_HAVE_PLATFORM_IMX_UART - select IMX_HAVE_PLATFORM_MXC_EHCI - select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - select IMX_HAVE_PLATFORM_SPI_IMX - help - Include support for MX51 Babbage platform, also known as MX51EVK in - u-boot. This includes specific configurations for the board and its - peripherals. - -config MACH_MX51_3DS - bool "Support MX51PDK (3DS)" - select SOC_IMX51 - select IMX_HAVE_PLATFORM_IMX2_WDT - select IMX_HAVE_PLATFORM_IMX_KEYPAD - select IMX_HAVE_PLATFORM_IMX_UART - select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - select IMX_HAVE_PLATFORM_SPI_IMX - select MXC_DEBUG_BOARD - help - Include support for MX51PDK (3DS) platform. This includes specific - configurations for the board and its peripherals. - -config MACH_EUKREA_CPUIMX51 - bool "Support Eukrea CPUIMX51 module" - select SOC_IMX51 - select IMX_HAVE_PLATFORM_FSL_USB2_UDC - select IMX_HAVE_PLATFORM_IMX_I2C - select IMX_HAVE_PLATFORM_IMX_UART - select IMX_HAVE_PLATFORM_MXC_EHCI - select IMX_HAVE_PLATFORM_MXC_NAND - select IMX_HAVE_PLATFORM_SPI_IMX - help - Include support for Eukrea CPUIMX51 platform. This includes - specific configurations for the module and its peripherals. - -choice - prompt "Baseboard" - depends on MACH_EUKREA_CPUIMX51 - default MACH_EUKREA_MBIMX51_BASEBOARD - -config MACH_EUKREA_MBIMX51_BASEBOARD - prompt "Eukrea MBIMX51 development board" - bool - select IMX_HAVE_PLATFORM_IMX_KEYPAD - select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - select LEDS_GPIO_REGISTER - help - This adds board specific devices that can be found on Eukrea's - MBIMX51 evaluation board. - -endchoice - -config MACH_EUKREA_CPUIMX51SD - bool "Support Eukrea CPUIMX51SD module" - select SOC_IMX51 - select IMX_HAVE_PLATFORM_FSL_USB2_UDC - select IMX_HAVE_PLATFORM_IMX_I2C - select IMX_HAVE_PLATFORM_IMX_UART - select IMX_HAVE_PLATFORM_MXC_EHCI - select IMX_HAVE_PLATFORM_MXC_NAND - select IMX_HAVE_PLATFORM_SPI_IMX - help - Include support for Eukrea CPUIMX51SD platform. This includes - specific configurations for the module and its peripherals. - -choice - prompt "Baseboard" - depends on MACH_EUKREA_CPUIMX51SD - default MACH_EUKREA_MBIMXSD51_BASEBOARD - -config MACH_EUKREA_MBIMXSD51_BASEBOARD - prompt "Eukrea MBIMXSD development board" - bool - select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - select LEDS_GPIO_REGISTER - help - This adds board specific devices that can be found on Eukrea's - MBIMXSD evaluation board. - -endchoice - -config MX51_EFIKA_COMMON - bool - select SOC_IMX51 - select IMX_HAVE_PLATFORM_IMX_UART - select IMX_HAVE_PLATFORM_MXC_EHCI - select IMX_HAVE_PLATFORM_PATA_IMX - select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - select IMX_HAVE_PLATFORM_SPI_IMX - select MXC_ULPI if USB_ULPI - -config MACH_MX51_EFIKAMX - bool "Support MX51 Genesi Efika MX nettop" - select LEDS_GPIO_REGISTER - select MX51_EFIKA_COMMON - help - Include support for Genesi Efika MX nettop. This includes specific - configurations for the board and its peripherals. - -config MACH_MX51_EFIKASB - bool "Support MX51 Genesi Efika Smartbook" - select LEDS_GPIO_REGISTER - select MX51_EFIKA_COMMON - help - Include support for Genesi Efika Smartbook. This includes specific - configurations for the board and its peripherals. - -comment "i.MX53 machines:" - -config MACH_IMX53_DT - bool "Support i.MX53 platforms from device tree" - select SOC_IMX53 - select USE_OF - select MACH_MX53_ARD - select MACH_MX53_EVK - select MACH_MX53_LOCO - select MACH_MX53_SMD - help - Include support for Freescale i.MX53 based platforms - using the device tree for discovery - -config MACH_MX53_EVK - bool "Support MX53 EVK platforms" - select SOC_IMX53 - select IMX_HAVE_PLATFORM_IMX2_WDT - select IMX_HAVE_PLATFORM_IMX_UART - select IMX_HAVE_PLATFORM_IMX_I2C - select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - select IMX_HAVE_PLATFORM_SPI_IMX - select LEDS_GPIO_REGISTER - help - Include support for MX53 EVK platform. This includes specific - configurations for the board and its peripherals. - -config MACH_MX53_SMD - bool "Support MX53 SMD platforms" - select SOC_IMX53 - select IMX_HAVE_PLATFORM_IMX2_WDT - select IMX_HAVE_PLATFORM_IMX_I2C - select IMX_HAVE_PLATFORM_IMX_UART - select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - help - Include support for MX53 SMD platform. This includes specific - configurations for the board and its peripherals. - -config MACH_MX53_LOCO - bool "Support MX53 LOCO platforms" - select SOC_IMX53 - select IMX_HAVE_PLATFORM_IMX2_WDT - select IMX_HAVE_PLATFORM_IMX_I2C - select IMX_HAVE_PLATFORM_IMX_UART - select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - select IMX_HAVE_PLATFORM_GPIO_KEYS - select LEDS_GPIO_REGISTER - help - Include support for MX53 LOCO platform. This includes specific - configurations for the board and its peripherals. - -config MACH_MX53_ARD - bool "Support MX53 ARD platforms" - select SOC_IMX53 - select IMX_HAVE_PLATFORM_IMX2_WDT - select IMX_HAVE_PLATFORM_IMX_I2C - select IMX_HAVE_PLATFORM_IMX_UART - select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - select IMX_HAVE_PLATFORM_GPIO_KEYS - help - Include support for MX53 ARD platform. This includes specific - configurations for the board and its peripherals. - -endif diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile deleted file mode 100644 index 0fc6080..0000000 --- a/arch/arm/mach-mx5/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# -# Makefile for the linux kernel. -# - -# Object file lists. -obj-y := cpu.o mm.o clock-mx51-mx53.o ehci.o system.o - -obj-$(CONFIG_PM) += pm-imx5.o -obj-$(CONFIG_CPU_FREQ_IMX) += cpu_op-mx51.o -obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o -obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o -obj-$(CONFIG_MACH_MX53_EVK) += board-mx53_evk.o -obj-$(CONFIG_MACH_MX53_SMD) += board-mx53_smd.o -obj-$(CONFIG_MACH_MX53_LOCO) += board-mx53_loco.o -obj-$(CONFIG_MACH_MX53_ARD) += board-mx53_ard.o -obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o -obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o -obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o -obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o -obj-$(CONFIG_MX51_EFIKA_COMMON) += mx51_efika.o -obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o -obj-$(CONFIG_MACH_MX51_EFIKASB) += board-mx51_efikasb.o -obj-$(CONFIG_MACH_MX50_RDP) += board-mx50_rdp.o - -obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o -obj-$(CONFIG_MACH_IMX53_DT) += imx53-dt.o diff --git a/arch/arm/mach-mx5/Makefile.boot b/arch/arm/mach-mx5/Makefile.boot deleted file mode 100644 index ca207ca..0000000 --- a/arch/arm/mach-mx5/Makefile.boot +++ /dev/null @@ -1,9 +0,0 @@ - zreladdr-$(CONFIG_ARCH_MX50) += 0x70008000 -params_phys-$(CONFIG_ARCH_MX50) := 0x70000100 -initrd_phys-$(CONFIG_ARCH_MX50) := 0x70800000 - zreladdr-$(CONFIG_ARCH_MX51) += 0x90008000 -params_phys-$(CONFIG_ARCH_MX51) := 0x90000100 -initrd_phys-$(CONFIG_ARCH_MX51) := 0x90800000 - zreladdr-$(CONFIG_ARCH_MX53) += 0x70008000 -params_phys-$(CONFIG_ARCH_MX53) := 0x70000100 -initrd_phys-$(CONFIG_ARCH_MX53) := 0x70800000 diff --git a/arch/arm/mach-mx5/board-cpuimx51.c b/arch/arm/mach-mx5/board-cpuimx51.c deleted file mode 100644 index 1fc1103..0000000 --- a/arch/arm/mach-mx5/board-cpuimx51.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - * - * Copyright (C) 2010 Eric Bénard - * - * based on board-mx51_babbage.c which is - * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright (C) 2009-2010 Amit Kucheria - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "devices-imx51.h" - -#define CPUIMX51_USBH1_STP IMX_GPIO_NR(1, 27) -#define CPUIMX51_QUARTA_GPIO IMX_GPIO_NR(3, 28) -#define CPUIMX51_QUARTB_GPIO IMX_GPIO_NR(3, 25) -#define CPUIMX51_QUARTC_GPIO IMX_GPIO_NR(3, 26) -#define CPUIMX51_QUARTD_GPIO IMX_GPIO_NR(3, 27) -#define CPUIMX51_QUART_XTAL 14745600 -#define CPUIMX51_QUART_REGSHIFT 17 - -/* USB_CTRL_1 */ -#define MX51_USB_CTRL_1_OFFSET 0x10 -#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25) - -#define MX51_USB_PLLDIV_12_MHZ 0x00 -#define MX51_USB_PLL_DIV_19_2_MHZ 0x01 -#define MX51_USB_PLL_DIV_24_MHZ 0x02 - -static struct plat_serial8250_port serial_platform_data[] = { - { - .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000), - .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTA_GPIO), - .irqflags = IRQF_TRIGGER_HIGH, - .uartclk = CPUIMX51_QUART_XTAL, - .regshift = CPUIMX51_QUART_REGSHIFT, - .iotype = UPIO_MEM, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, - }, { - .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x800000), - .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTB_GPIO), - .irqflags = IRQF_TRIGGER_HIGH, - .uartclk = CPUIMX51_QUART_XTAL, - .regshift = CPUIMX51_QUART_REGSHIFT, - .iotype = UPIO_MEM, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, - }, { - .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x1000000), - .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTC_GPIO), - .irqflags = IRQF_TRIGGER_HIGH, - .uartclk = CPUIMX51_QUART_XTAL, - .regshift = CPUIMX51_QUART_REGSHIFT, - .iotype = UPIO_MEM, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, - }, { - .mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x2000000), - .irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTD_GPIO), - .irqflags = IRQF_TRIGGER_HIGH, - .uartclk = CPUIMX51_QUART_XTAL, - .regshift = CPUIMX51_QUART_REGSHIFT, - .iotype = UPIO_MEM, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, - }, { - } -}; - -static struct platform_device serial_device = { - .name = "serial8250", - .id = 0, - .dev = { - .platform_data = serial_platform_data, - }, -}; - -static struct platform_device *devices[] __initdata = { - &serial_device, -}; - -static iomux_v3_cfg_t eukrea_cpuimx51_pads[] = { - /* UART1 */ - MX51_PAD_UART1_RXD__UART1_RXD, - MX51_PAD_UART1_TXD__UART1_TXD, - MX51_PAD_UART1_RTS__UART1_RTS, - MX51_PAD_UART1_CTS__UART1_CTS, - - /* I2C2 */ - MX51_PAD_GPIO1_2__I2C2_SCL, - MX51_PAD_GPIO1_3__I2C2_SDA, - MX51_PAD_NANDF_D10__GPIO3_30, - - /* QUART IRQ */ - MX51_PAD_NANDF_D15__GPIO3_25, - MX51_PAD_NANDF_D14__GPIO3_26, - MX51_PAD_NANDF_D13__GPIO3_27, - MX51_PAD_NANDF_D12__GPIO3_28, - - /* USB HOST1 */ - MX51_PAD_USBH1_CLK__USBH1_CLK, - MX51_PAD_USBH1_DIR__USBH1_DIR, - MX51_PAD_USBH1_NXT__USBH1_NXT, - MX51_PAD_USBH1_DATA0__USBH1_DATA0, - MX51_PAD_USBH1_DATA1__USBH1_DATA1, - MX51_PAD_USBH1_DATA2__USBH1_DATA2, - MX51_PAD_USBH1_DATA3__USBH1_DATA3, - MX51_PAD_USBH1_DATA4__USBH1_DATA4, - MX51_PAD_USBH1_DATA5__USBH1_DATA5, - MX51_PAD_USBH1_DATA6__USBH1_DATA6, - MX51_PAD_USBH1_DATA7__USBH1_DATA7, - MX51_PAD_USBH1_STP__USBH1_STP, -}; - -static const struct mxc_nand_platform_data - eukrea_cpuimx51_nand_board_info __initconst = { - .width = 1, - .hw_ecc = 1, - .flash_bbt = 1, -}; - -static const struct imxuart_platform_data uart_pdata __initconst = { - .flags = IMXUART_HAVE_RTSCTS, -}; - -static const -struct imxi2c_platform_data eukrea_cpuimx51_i2c_data __initconst = { - .bitrate = 100000, -}; - -static struct i2c_board_info eukrea_cpuimx51_i2c_devices[] = { - { - I2C_BOARD_INFO("pcf8563", 0x51), - }, -}; - -/* This function is board specific as the bit mask for the plldiv will also -be different for other Freescale SoCs, thus a common bitmask is not -possible and cannot get place in /plat-mxc/ehci.c.*/ -static int initialize_otg_port(struct platform_device *pdev) -{ - u32 v; - void __iomem *usb_base; - void __iomem *usbother_base; - - usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); - if (!usb_base) - return -ENOMEM; - usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; - - /* Set the PHY clock to 19.2MHz */ - v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); - v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK; - v |= MX51_USB_PLL_DIV_19_2_MHZ; - __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); - iounmap(usb_base); - - mdelay(10); - - return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY); -} - -static int initialize_usbh1_port(struct platform_device *pdev) -{ - u32 v; - void __iomem *usb_base; - void __iomem *usbother_base; - - usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); - if (!usb_base) - return -ENOMEM; - usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; - - /* The clock for the USBH1 ULPI port will come externally from the PHY. */ - v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET); - __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET); - iounmap(usb_base); - - mdelay(10); - - return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED | - MXC_EHCI_ITC_NO_THRESHOLD); -} - -static const struct mxc_usbh_platform_data dr_utmi_config __initconst = { - .init = initialize_otg_port, - .portsc = MXC_EHCI_UTMI_16BIT, -}; - -static const struct fsl_usb2_platform_data usb_pdata __initconst = { - .operating_mode = FSL_USB2_DR_DEVICE, - .phy_mode = FSL_USB2_PHY_UTMI_WIDE, -}; - -static const struct mxc_usbh_platform_data usbh1_config __initconst = { - .init = initialize_usbh1_port, - .portsc = MXC_EHCI_MODE_ULPI, -}; - -static int otg_mode_host; - -static int __init eukrea_cpuimx51_otg_mode(char *options) -{ - if (!strcmp(options, "host")) - otg_mode_host = 1; - else if (!strcmp(options, "device")) - otg_mode_host = 0; - else - pr_info("otg_mode neither \"host\" nor \"device\". " - "Defaulting to device\n"); - return 0; -} -__setup("otg_mode=", eukrea_cpuimx51_otg_mode); - -/* - * Board specific initialization. - */ -static void __init eukrea_cpuimx51_init(void) -{ - imx51_soc_init(); - - mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads, - ARRAY_SIZE(eukrea_cpuimx51_pads)); - - imx51_add_imx_uart(0, &uart_pdata); - imx51_add_mxc_nand(&eukrea_cpuimx51_nand_board_info); - - gpio_request(CPUIMX51_QUARTA_GPIO, "quarta_irq"); - gpio_direction_input(CPUIMX51_QUARTA_GPIO); - gpio_free(CPUIMX51_QUARTA_GPIO); - gpio_request(CPUIMX51_QUARTB_GPIO, "quartb_irq"); - gpio_direction_input(CPUIMX51_QUARTB_GPIO); - gpio_free(CPUIMX51_QUARTB_GPIO); - gpio_request(CPUIMX51_QUARTC_GPIO, "quartc_irq"); - gpio_direction_input(CPUIMX51_QUARTC_GPIO); - gpio_free(CPUIMX51_QUARTC_GPIO); - gpio_request(CPUIMX51_QUARTD_GPIO, "quartd_irq"); - gpio_direction_input(CPUIMX51_QUARTD_GPIO); - gpio_free(CPUIMX51_QUARTD_GPIO); - - imx51_add_fec(NULL); - platform_add_devices(devices, ARRAY_SIZE(devices)); - - imx51_add_imx_i2c(1, &eukrea_cpuimx51_i2c_data); - i2c_register_board_info(1, eukrea_cpuimx51_i2c_devices, - ARRAY_SIZE(eukrea_cpuimx51_i2c_devices)); - - if (otg_mode_host) - imx51_add_mxc_ehci_otg(&dr_utmi_config); - else { - initialize_otg_port(NULL); - imx51_add_fsl_usb2_udc(&usb_pdata); - } - imx51_add_mxc_ehci_hs(1, &usbh1_config); - -#ifdef CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD - eukrea_mbimx51_baseboard_init(); -#endif -} - -static void __init eukrea_cpuimx51_timer_init(void) -{ - mx51_clocks_init(32768, 24000000, 22579200, 0); -} - -static struct sys_timer mxc_timer = { - .init = eukrea_cpuimx51_timer_init, -}; - -MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module") - /* Maintainer: Eric Bénard */ - .atag_offset = 0x100, - .map_io = mx51_map_io, - .init_early = imx51_init_early, - .init_irq = mx51_init_irq, - .handle_irq = imx51_handle_irq, - .timer = &mxc_timer, - .init_machine = eukrea_cpuimx51_init, -MACHINE_END diff --git a/arch/arm/mach-mx5/board-cpuimx51sd.c b/arch/arm/mach-mx5/board-cpuimx51sd.c deleted file mode 100644 index 52a11c1..0000000 --- a/arch/arm/mach-mx5/board-cpuimx51sd.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * - * Copyright (C) 2010 Eric Bénard - * - * based on board-mx51_babbage.c which is - * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright (C) 2009-2010 Amit Kucheria - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "devices-imx51.h" -#include "cpu_op-mx51.h" - -#define USBH1_RST IMX_GPIO_NR(2, 28) -#define ETH_RST IMX_GPIO_NR(2, 31) -#define TSC2007_IRQGPIO IMX_GPIO_NR(3, 12) -#define CAN_IRQGPIO IMX_GPIO_NR(1, 1) -#define CAN_RST IMX_GPIO_NR(4, 15) -#define CAN_NCS IMX_GPIO_NR(4, 24) -#define CAN_RXOBF IMX_GPIO_NR(1, 4) -#define CAN_RX1BF IMX_GPIO_NR(1, 6) -#define CAN_TXORTS IMX_GPIO_NR(1, 7) -#define CAN_TX1RTS IMX_GPIO_NR(1, 8) -#define CAN_TX2RTS IMX_GPIO_NR(1, 9) -#define I2C_SCL IMX_GPIO_NR(4, 16) -#define I2C_SDA IMX_GPIO_NR(4, 17) - -/* USB_CTRL_1 */ -#define MX51_USB_CTRL_1_OFFSET 0x10 -#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25) - -#define MX51_USB_PLLDIV_12_MHZ 0x00 -#define MX51_USB_PLL_DIV_19_2_MHZ 0x01 -#define MX51_USB_PLL_DIV_24_MHZ 0x02 - -static iomux_v3_cfg_t eukrea_cpuimx51sd_pads[] = { - /* UART1 */ - MX51_PAD_UART1_RXD__UART1_RXD, - MX51_PAD_UART1_TXD__UART1_TXD, - MX51_PAD_UART1_RTS__UART1_RTS, - MX51_PAD_UART1_CTS__UART1_CTS, - - /* USB HOST1 */ - MX51_PAD_USBH1_CLK__USBH1_CLK, - MX51_PAD_USBH1_DIR__USBH1_DIR, - MX51_PAD_USBH1_NXT__USBH1_NXT, - MX51_PAD_USBH1_DATA0__USBH1_DATA0, - MX51_PAD_USBH1_DATA1__USBH1_DATA1, - MX51_PAD_USBH1_DATA2__USBH1_DATA2, - MX51_PAD_USBH1_DATA3__USBH1_DATA3, - MX51_PAD_USBH1_DATA4__USBH1_DATA4, - MX51_PAD_USBH1_DATA5__USBH1_DATA5, - MX51_PAD_USBH1_DATA6__USBH1_DATA6, - MX51_PAD_USBH1_DATA7__USBH1_DATA7, - MX51_PAD_USBH1_STP__USBH1_STP, - MX51_PAD_EIM_CS3__GPIO2_28, /* PHY nRESET */ - - /* FEC */ - MX51_PAD_EIM_DTACK__GPIO2_31, /* PHY nRESET */ - - /* HSI2C */ - MX51_PAD_I2C1_CLK__GPIO4_16, - MX51_PAD_I2C1_DAT__GPIO4_17, - - /* CAN */ - MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI, - MX51_PAD_CSPI1_MISO__ECSPI1_MISO, - MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK, - MX51_PAD_CSPI1_SS0__GPIO4_24, /* nCS */ - MX51_PAD_CSI2_PIXCLK__GPIO4_15, /* nReset */ - MX51_PAD_GPIO1_1__GPIO1_1, /* IRQ */ - MX51_PAD_GPIO1_4__GPIO1_4, /* Control signals */ - MX51_PAD_GPIO1_6__GPIO1_6, - MX51_PAD_GPIO1_7__GPIO1_7, - MX51_PAD_GPIO1_8__GPIO1_8, - MX51_PAD_GPIO1_9__GPIO1_9, - - /* Touchscreen */ - /* IRQ */ - NEW_PAD_CTRL(MX51_PAD_GPIO_NAND__GPIO_NAND, PAD_CTL_PUS_22K_UP | - PAD_CTL_PKE | PAD_CTL_SRE_FAST | - PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS), -}; - -static const struct imxuart_platform_data uart_pdata __initconst = { - .flags = IMXUART_HAVE_RTSCTS, -}; - -static struct tsc2007_platform_data tsc2007_info = { - .model = 2007, - .x_plate_ohms = 180, -}; - -static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = { - { - I2C_BOARD_INFO("pcf8563", 0x51), - }, { - I2C_BOARD_INFO("tsc2007", 0x49), - .type = "tsc2007", - .platform_data = &tsc2007_info, - .irq = IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO), - }, -}; - -static const struct mxc_nand_platform_data - eukrea_cpuimx51sd_nand_board_info __initconst = { - .width = 1, - .hw_ecc = 1, - .flash_bbt = 1, -}; - -/* This function is board specific as the bit mask for the plldiv will also -be different for other Freescale SoCs, thus a common bitmask is not -possible and cannot get place in /plat-mxc/ehci.c.*/ -static int initialize_otg_port(struct platform_device *pdev) -{ - u32 v; - void __iomem *usb_base; - void __iomem *usbother_base; - - usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); - if (!usb_base) - return -ENOMEM; - usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; - - /* Set the PHY clock to 19.2MHz */ - v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); - v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK; - v |= MX51_USB_PLL_DIV_19_2_MHZ; - __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); - iounmap(usb_base); - - mdelay(10); - - return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY); -} - -static int initialize_usbh1_port(struct platform_device *pdev) -{ - u32 v; - void __iomem *usb_base; - void __iomem *usbother_base; - - usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); - if (!usb_base) - return -ENOMEM; - usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; - - /* The clock for the USBH1 ULPI port will come from the PHY. */ - v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET); - __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, - usbother_base + MX51_USB_CTRL_1_OFFSET); - iounmap(usb_base); - - mdelay(10); - - return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED | - MXC_EHCI_ITC_NO_THRESHOLD); -} - -static const struct mxc_usbh_platform_data dr_utmi_config __initconst = { - .init = initialize_otg_port, - .portsc = MXC_EHCI_UTMI_16BIT, -}; - -static const struct fsl_usb2_platform_data usb_pdata __initconst = { - .operating_mode = FSL_USB2_DR_DEVICE, - .phy_mode = FSL_USB2_PHY_UTMI_WIDE, -}; - -static const struct mxc_usbh_platform_data usbh1_config __initconst = { - .init = initialize_usbh1_port, - .portsc = MXC_EHCI_MODE_ULPI, -}; - -static int otg_mode_host; - -static int __init eukrea_cpuimx51sd_otg_mode(char *options) -{ - if (!strcmp(options, "host")) - otg_mode_host = 1; - else if (!strcmp(options, "device")) - otg_mode_host = 0; - else - pr_info("otg_mode neither \"host\" nor \"device\". " - "Defaulting to device\n"); - return 0; -} -__setup("otg_mode=", eukrea_cpuimx51sd_otg_mode); - -static struct i2c_gpio_platform_data pdata = { - .sda_pin = I2C_SDA, - .sda_is_open_drain = 0, - .scl_pin = I2C_SCL, - .scl_is_open_drain = 0, - .udelay = 2, -}; - -static struct platform_device hsi2c_gpio_device = { - .name = "i2c-gpio", - .id = 0, - .dev.platform_data = &pdata, -}; - -static struct mcp251x_platform_data mcp251x_info = { - .oscillator_frequency = 24E6, -}; - -static struct spi_board_info cpuimx51sd_spi_device[] = { - { - .modalias = "mcp2515", - .max_speed_hz = 10000000, - .bus_num = 0, - .mode = SPI_MODE_0, - .chip_select = 0, - .platform_data = &mcp251x_info, - .irq = IMX_GPIO_TO_IRQ(CAN_IRQGPIO) - }, -}; - -static int cpuimx51sd_spi1_cs[] = { - CAN_NCS, -}; - -static const struct spi_imx_master cpuimx51sd_ecspi1_pdata __initconst = { - .chipselect = cpuimx51sd_spi1_cs, - .num_chipselect = ARRAY_SIZE(cpuimx51sd_spi1_cs), -}; - -static struct platform_device *platform_devices[] __initdata = { - &hsi2c_gpio_device, -}; - -static void __init eukrea_cpuimx51sd_init(void) -{ - imx51_soc_init(); - - mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads, - ARRAY_SIZE(eukrea_cpuimx51sd_pads)); - -#if defined(CONFIG_CPU_FREQ_IMX) - get_cpu_op = mx51_get_cpu_op; -#endif - - imx51_add_imx_uart(0, &uart_pdata); - imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info); - - gpio_request(ETH_RST, "eth_rst"); - gpio_set_value(ETH_RST, 1); - imx51_add_fec(NULL); - - gpio_request(CAN_IRQGPIO, "can_irq"); - gpio_direction_input(CAN_IRQGPIO); - gpio_free(CAN_IRQGPIO); - gpio_request(CAN_NCS, "can_ncs"); - gpio_direction_output(CAN_NCS, 1); - gpio_free(CAN_NCS); - gpio_request(CAN_RST, "can_rst"); - gpio_direction_output(CAN_RST, 0); - msleep(20); - gpio_set_value(CAN_RST, 1); - imx51_add_ecspi(0, &cpuimx51sd_ecspi1_pdata); - spi_register_board_info(cpuimx51sd_spi_device, - ARRAY_SIZE(cpuimx51sd_spi_device)); - - gpio_request(TSC2007_IRQGPIO, "tsc2007_irq"); - gpio_direction_input(TSC2007_IRQGPIO); - gpio_free(TSC2007_IRQGPIO); - - i2c_register_board_info(0, eukrea_cpuimx51sd_i2c_devices, - ARRAY_SIZE(eukrea_cpuimx51sd_i2c_devices)); - platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); - - if (otg_mode_host) - imx51_add_mxc_ehci_otg(&dr_utmi_config); - else { - initialize_otg_port(NULL); - imx51_add_fsl_usb2_udc(&usb_pdata); - } - - gpio_request(USBH1_RST, "usb_rst"); - gpio_direction_output(USBH1_RST, 0); - msleep(20); - gpio_set_value(USBH1_RST, 1); - imx51_add_mxc_ehci_hs(1, &usbh1_config); - -#ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD - eukrea_mbimxsd51_baseboard_init(); -#endif -} - -static void __init eukrea_cpuimx51sd_timer_init(void) -{ - mx51_clocks_init(32768, 24000000, 22579200, 0); -} - -static struct sys_timer mxc_timer = { - .init = eukrea_cpuimx51sd_timer_init, -}; - -MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD") - /* Maintainer: Eric Bénard */ - .atag_offset = 0x100, - .map_io = mx51_map_io, - .init_early = imx51_init_early, - .init_irq = mx51_init_irq, - .handle_irq = imx51_handle_irq, - .timer = &mxc_timer, - .init_machine = eukrea_cpuimx51sd_init, -MACHINE_END diff --git a/arch/arm/mach-mx5/board-mx50_rdp.c b/arch/arm/mach-mx5/board-mx50_rdp.c deleted file mode 100644 index fc3621d..0000000 --- a/arch/arm/mach-mx5/board-mx50_rdp.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "devices-imx50.h" - -#define FEC_EN IMX_GPIO_NR(6, 23) -#define FEC_RESET_B IMX_GPIO_NR(4, 12) - -static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = { - /* SD1 */ - MX50_PAD_ECSPI2_SS0__GPIO_4_19, - MX50_PAD_EIM_CRE__GPIO_1_27, - MX50_PAD_SD1_CMD__SD1_CMD, - - MX50_PAD_SD1_CLK__SD1_CLK, - MX50_PAD_SD1_D0__SD1_D0, - MX50_PAD_SD1_D1__SD1_D1, - MX50_PAD_SD1_D2__SD1_D2, - MX50_PAD_SD1_D3__SD1_D3, - - /* SD2 */ - MX50_PAD_SD2_CD__GPIO_5_17, - MX50_PAD_SD2_WP__GPIO_5_16, - MX50_PAD_SD2_CMD__SD2_CMD, - MX50_PAD_SD2_CLK__SD2_CLK, - MX50_PAD_SD2_D0__SD2_D0, - MX50_PAD_SD2_D1__SD2_D1, - MX50_PAD_SD2_D2__SD2_D2, - MX50_PAD_SD2_D3__SD2_D3, - MX50_PAD_SD2_D4__SD2_D4, - MX50_PAD_SD2_D5__SD2_D5, - MX50_PAD_SD2_D6__SD2_D6, - MX50_PAD_SD2_D7__SD2_D7, - - /* SD3 */ - MX50_PAD_SD3_CMD__SD3_CMD, - MX50_PAD_SD3_CLK__SD3_CLK, - MX50_PAD_SD3_D0__SD3_D0, - MX50_PAD_SD3_D1__SD3_D1, - MX50_PAD_SD3_D2__SD3_D2, - MX50_PAD_SD3_D3__SD3_D3, - MX50_PAD_SD3_D4__SD3_D4, - MX50_PAD_SD3_D5__SD3_D5, - MX50_PAD_SD3_D6__SD3_D6, - MX50_PAD_SD3_D7__SD3_D7, - - /* PWR_INT */ - MX50_PAD_ECSPI2_MISO__GPIO_4_18, - - /* UART pad setting */ - MX50_PAD_UART1_TXD__UART1_TXD, - MX50_PAD_UART1_RXD__UART1_RXD, - MX50_PAD_UART1_RTS__UART1_RTS, - MX50_PAD_UART2_TXD__UART2_TXD, - MX50_PAD_UART2_RXD__UART2_RXD, - MX50_PAD_UART2_CTS__UART2_CTS, - MX50_PAD_UART2_RTS__UART2_RTS, - - MX50_PAD_I2C1_SCL__I2C1_SCL, - MX50_PAD_I2C1_SDA__I2C1_SDA, - MX50_PAD_I2C2_SCL__I2C2_SCL, - MX50_PAD_I2C2_SDA__I2C2_SDA, - - MX50_PAD_EPITO__USBH1_PWR, - /* Need to comment below line if - * one needs to debug owire. - */ - MX50_PAD_OWIRE__USBH1_OC, - /* using gpio to control otg pwr */ - MX50_PAD_PWM2__GPIO_6_25, - MX50_PAD_I2C3_SCL__USBOTG_OC, - - MX50_PAD_SSI_RXC__FEC_MDIO, - MX50_PAD_SSI_RXFS__FEC_MDC, - MX50_PAD_DISP_D0__FEC_TXCLK, - MX50_PAD_DISP_D1__FEC_RX_ER, - MX50_PAD_DISP_D2__FEC_RX_DV, - MX50_PAD_DISP_D3__FEC_RXD1, - MX50_PAD_DISP_D4__FEC_RXD0, - MX50_PAD_DISP_D5__FEC_TX_EN, - MX50_PAD_DISP_D6__FEC_TXD1, - MX50_PAD_DISP_D7__FEC_TXD0, - MX50_PAD_I2C3_SDA__GPIO_6_23, - MX50_PAD_ECSPI1_SCLK__GPIO_4_12, - - MX50_PAD_CSPI_SS0__CSPI_SS0, - MX50_PAD_ECSPI1_MOSI__CSPI_SS1, - MX50_PAD_CSPI_MOSI__CSPI_MOSI, - MX50_PAD_CSPI_MISO__CSPI_MISO, - - /* SGTL500_OSC_EN */ - MX50_PAD_UART1_CTS__GPIO_6_8, - - /* SGTL_AMP_SHDN */ - MX50_PAD_UART3_RXD__GPIO_6_15, - - /* Keypad */ - MX50_PAD_KEY_COL0__KEY_COL0, - MX50_PAD_KEY_ROW0__KEY_ROW0, - MX50_PAD_KEY_COL1__KEY_COL1, - MX50_PAD_KEY_ROW1__KEY_ROW1, - MX50_PAD_KEY_COL2__KEY_COL2, - MX50_PAD_KEY_ROW2__KEY_ROW2, - MX50_PAD_KEY_COL3__KEY_COL3, - MX50_PAD_KEY_ROW3__KEY_ROW3, - MX50_PAD_EIM_DA0__KEY_COL4, - MX50_PAD_EIM_DA1__KEY_ROW4, - MX50_PAD_EIM_DA2__KEY_COL5, - MX50_PAD_EIM_DA3__KEY_ROW5, - MX50_PAD_EIM_DA4__KEY_COL6, - MX50_PAD_EIM_DA5__KEY_ROW6, - MX50_PAD_EIM_DA6__KEY_COL7, - MX50_PAD_EIM_DA7__KEY_ROW7, - /*EIM pads */ - MX50_PAD_EIM_DA8__GPIO_1_8, - MX50_PAD_EIM_DA9__GPIO_1_9, - MX50_PAD_EIM_DA10__GPIO_1_10, - MX50_PAD_EIM_DA11__GPIO_1_11, - MX50_PAD_EIM_DA12__GPIO_1_12, - MX50_PAD_EIM_DA13__GPIO_1_13, - MX50_PAD_EIM_DA14__GPIO_1_14, - MX50_PAD_EIM_DA15__GPIO_1_15, - MX50_PAD_EIM_CS2__GPIO_1_16, - MX50_PAD_EIM_CS1__GPIO_1_17, - MX50_PAD_EIM_CS0__GPIO_1_18, - MX50_PAD_EIM_EB0__GPIO_1_19, - MX50_PAD_EIM_EB1__GPIO_1_20, - MX50_PAD_EIM_WAIT__GPIO_1_21, - MX50_PAD_EIM_BCLK__GPIO_1_22, - MX50_PAD_EIM_RDY__GPIO_1_23, - MX50_PAD_EIM_OE__GPIO_1_24, -}; - -/* Serial ports */ -static const struct imxuart_platform_data uart_pdata __initconst = { - .flags = IMXUART_HAVE_RTSCTS, -}; - -static const struct fec_platform_data fec_data __initconst = { - .phy = PHY_INTERFACE_MODE_RMII, -}; - -static inline void mx50_rdp_fec_reset(void) -{ - gpio_request(FEC_EN, "fec-en"); - gpio_direction_output(FEC_EN, 0); - gpio_request(FEC_RESET_B, "fec-reset_b"); - gpio_direction_output(FEC_RESET_B, 0); - msleep(1); - gpio_set_value(FEC_RESET_B, 1); -} - -static const struct imxi2c_platform_data i2c_data __initconst = { - .bitrate = 100000, -}; - -/* - * Board specific initialization. - */ -static void __init mx50_rdp_board_init(void) -{ - imx50_soc_init(); - - mxc_iomux_v3_setup_multiple_pads(mx50_rdp_pads, - ARRAY_SIZE(mx50_rdp_pads)); - - imx50_add_imx_uart(0, &uart_pdata); - imx50_add_imx_uart(1, &uart_pdata); - mx50_rdp_fec_reset(); - imx50_add_fec(&fec_data); - imx50_add_imx_i2c(0, &i2c_data); - imx50_add_imx_i2c(1, &i2c_data); - imx50_add_imx_i2c(2, &i2c_data); -} - -static void __init mx50_rdp_timer_init(void) -{ - mx50_clocks_init(32768, 24000000, 22579200); -} - -static struct sys_timer mx50_rdp_timer = { - .init = mx50_rdp_timer_init, -}; - -MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform") - .map_io = mx50_map_io, - .init_early = imx50_init_early, - .init_irq = mx50_init_irq, - .handle_irq = imx50_handle_irq, - .timer = &mx50_rdp_timer, - .init_machine = mx50_rdp_board_init, -MACHINE_END diff --git a/arch/arm/mach-mx5/board-mx51_3ds.c b/arch/arm/mach-mx5/board-mx51_3ds.c deleted file mode 100644 index 0578390..0000000 --- a/arch/arm/mach-mx5/board-mx51_3ds.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright (C) 2010 Jason Wang - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "devices-imx51.h" - -#define EXPIO_PARENT_INT gpio_to_irq(IMX_GPIO_NR(1, 6)) -#define MX51_3DS_ECSPI2_CS (GPIO_PORTC + 28) - -static iomux_v3_cfg_t mx51_3ds_pads[] = { - /* UART1 */ - MX51_PAD_UART1_RXD__UART1_RXD, - MX51_PAD_UART1_TXD__UART1_TXD, - MX51_PAD_UART1_RTS__UART1_RTS, - MX51_PAD_UART1_CTS__UART1_CTS, - - /* UART2 */ - MX51_PAD_UART2_RXD__UART2_RXD, - MX51_PAD_UART2_TXD__UART2_TXD, - MX51_PAD_EIM_D25__UART2_CTS, - MX51_PAD_EIM_D26__UART2_RTS, - - /* UART3 */ - MX51_PAD_UART3_RXD__UART3_RXD, - MX51_PAD_UART3_TXD__UART3_TXD, - MX51_PAD_EIM_D24__UART3_CTS, - MX51_PAD_EIM_D27__UART3_RTS, - - /* CPLD PARENT IRQ PIN */ - MX51_PAD_GPIO1_6__GPIO1_6, - - /* KPP */ - MX51_PAD_KEY_ROW0__KEY_ROW0, - MX51_PAD_KEY_ROW1__KEY_ROW1, - MX51_PAD_KEY_ROW2__KEY_ROW2, - MX51_PAD_KEY_ROW3__KEY_ROW3, - MX51_PAD_KEY_COL0__KEY_COL0, - MX51_PAD_KEY_COL1__KEY_COL1, - MX51_PAD_KEY_COL2__KEY_COL2, - MX51_PAD_KEY_COL3__KEY_COL3, - MX51_PAD_KEY_COL4__KEY_COL4, - MX51_PAD_KEY_COL5__KEY_COL5, - - /* eCSPI2 */ - MX51_PAD_NANDF_RB2__ECSPI2_SCLK, - MX51_PAD_NANDF_RB3__ECSPI2_MISO, - MX51_PAD_NANDF_D15__ECSPI2_MOSI, - MX51_PAD_NANDF_D12__GPIO3_28, -}; - -/* Serial ports */ -static const struct imxuart_platform_data uart_pdata __initconst = { - .flags = IMXUART_HAVE_RTSCTS, -}; - -static int mx51_3ds_board_keymap[] = { - KEY(0, 0, KEY_1), - KEY(0, 1, KEY_2), - KEY(0, 2, KEY_3), - KEY(0, 3, KEY_F1), - KEY(0, 4, KEY_UP), - KEY(0, 5, KEY_F2), - - KEY(1, 0, KEY_4), - KEY(1, 1, KEY_5), - KEY(1, 2, KEY_6), - KEY(1, 3, KEY_LEFT), - KEY(1, 4, KEY_SELECT), - KEY(1, 5, KEY_RIGHT), - - KEY(2, 0, KEY_7), - KEY(2, 1, KEY_8), - KEY(2, 2, KEY_9), - KEY(2, 3, KEY_F3), - KEY(2, 4, KEY_DOWN), - KEY(2, 5, KEY_F4), - - KEY(3, 0, KEY_0), - KEY(3, 1, KEY_OK), - KEY(3, 2, KEY_ESC), - KEY(3, 3, KEY_ENTER), - KEY(3, 4, KEY_MENU), - KEY(3, 5, KEY_BACK) -}; - -static const struct matrix_keymap_data mx51_3ds_map_data __initconst = { - .keymap = mx51_3ds_board_keymap, - .keymap_size = ARRAY_SIZE(mx51_3ds_board_keymap), -}; - -static int mx51_3ds_spi2_cs[] = { - MXC_SPI_CS(0), - MX51_3DS_ECSPI2_CS, -}; - -static const struct spi_imx_master mx51_3ds_ecspi2_pdata __initconst = { - .chipselect = mx51_3ds_spi2_cs, - .num_chipselect = ARRAY_SIZE(mx51_3ds_spi2_cs), -}; - -static struct spi_board_info mx51_3ds_spi_nor_device[] = { - { - .modalias = "m25p80", - .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ - .bus_num = 1, - .chip_select = 1, - .mode = SPI_MODE_0, - .platform_data = NULL,}, -}; - -/* - * Board specific initialization. - */ -static void __init mx51_3ds_init(void) -{ - imx51_soc_init(); - - mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads, - ARRAY_SIZE(mx51_3ds_pads)); - - imx51_add_imx_uart(0, &uart_pdata); - imx51_add_imx_uart(1, &uart_pdata); - imx51_add_imx_uart(2, &uart_pdata); - - imx51_add_ecspi(1, &mx51_3ds_ecspi2_pdata); - spi_register_board_info(mx51_3ds_spi_nor_device, - ARRAY_SIZE(mx51_3ds_spi_nor_device)); - - if (mxc_expio_init(MX51_CS5_BASE_ADDR, EXPIO_PARENT_INT)) - printk(KERN_WARNING "Init of the debugboard failed, all " - "devices on the board are unusable.\n"); - - imx51_add_sdhci_esdhc_imx(0, NULL); - imx51_add_imx_keypad(&mx51_3ds_map_data); - imx51_add_imx2_wdt(0, NULL); -} - -static void __init mx51_3ds_timer_init(void) -{ - mx51_clocks_init(32768, 24000000, 22579200, 0); -} - -static struct sys_timer mx51_3ds_timer = { - .init = mx51_3ds_timer_init, -}; - -MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board") - /* Maintainer: Freescale Semiconductor, Inc. */ - .atag_offset = 0x100, - .map_io = mx51_map_io, - .init_early = imx51_init_early, - .init_irq = mx51_init_irq, - .handle_irq = imx51_handle_irq, - .timer = &mx51_3ds_timer, - .init_machine = mx51_3ds_init, -MACHINE_END diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c deleted file mode 100644 index 5c837603..0000000 --- a/arch/arm/mach-mx5/board-mx51_babbage.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright (C) 2009-2010 Amit Kucheria - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "devices-imx51.h" -#include "cpu_op-mx51.h" - -#define BABBAGE_USB_HUB_RESET IMX_GPIO_NR(1, 7) -#define BABBAGE_USBH1_STP IMX_GPIO_NR(1, 27) -#define BABBAGE_USB_PHY_RESET IMX_GPIO_NR(2, 5) -#define BABBAGE_FEC_PHY_RESET IMX_GPIO_NR(2, 14) -#define BABBAGE_POWER_KEY IMX_GPIO_NR(2, 21) -#define BABBAGE_ECSPI1_CS0 IMX_GPIO_NR(4, 24) -#define BABBAGE_ECSPI1_CS1 IMX_GPIO_NR(4, 25) -#define BABBAGE_SD2_CD IMX_GPIO_NR(1, 6) -#define BABBAGE_SD2_WP IMX_GPIO_NR(1, 5) - -/* USB_CTRL_1 */ -#define MX51_USB_CTRL_1_OFFSET 0x10 -#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25) - -#define MX51_USB_PLLDIV_12_MHZ 0x00 -#define MX51_USB_PLL_DIV_19_2_MHZ 0x01 -#define MX51_USB_PLL_DIV_24_MHZ 0x02 - -static struct gpio_keys_button babbage_buttons[] = { - { - .gpio = BABBAGE_POWER_KEY, - .code = BTN_0, - .desc = "PWR", - .active_low = 1, - .wakeup = 1, - }, -}; - -static const struct gpio_keys_platform_data imx_button_data __initconst = { - .buttons = babbage_buttons, - .nbuttons = ARRAY_SIZE(babbage_buttons), -}; - -static iomux_v3_cfg_t mx51babbage_pads[] = { - /* UART1 */ - MX51_PAD_UART1_RXD__UART1_RXD, - MX51_PAD_UART1_TXD__UART1_TXD, - MX51_PAD_UART1_RTS__UART1_RTS, - MX51_PAD_UART1_CTS__UART1_CTS, - - /* UART2 */ - MX51_PAD_UART2_RXD__UART2_RXD, - MX51_PAD_UART2_TXD__UART2_TXD, - - /* UART3 */ - MX51_PAD_EIM_D25__UART3_RXD, - MX51_PAD_EIM_D26__UART3_TXD, - MX51_PAD_EIM_D27__UART3_RTS, - MX51_PAD_EIM_D24__UART3_CTS, - - /* I2C1 */ - MX51_PAD_EIM_D16__I2C1_SDA, - MX51_PAD_EIM_D19__I2C1_SCL, - - /* I2C2 */ - MX51_PAD_KEY_COL4__I2C2_SCL, - MX51_PAD_KEY_COL5__I2C2_SDA, - - /* HSI2C */ - MX51_PAD_I2C1_CLK__I2C1_CLK, - MX51_PAD_I2C1_DAT__I2C1_DAT, - - /* USB HOST1 */ - MX51_PAD_USBH1_CLK__USBH1_CLK, - MX51_PAD_USBH1_DIR__USBH1_DIR, - MX51_PAD_USBH1_NXT__USBH1_NXT, - MX51_PAD_USBH1_DATA0__USBH1_DATA0, - MX51_PAD_USBH1_DATA1__USBH1_DATA1, - MX51_PAD_USBH1_DATA2__USBH1_DATA2, - MX51_PAD_USBH1_DATA3__USBH1_DATA3, - MX51_PAD_USBH1_DATA4__USBH1_DATA4, - MX51_PAD_USBH1_DATA5__USBH1_DATA5, - MX51_PAD_USBH1_DATA6__USBH1_DATA6, - MX51_PAD_USBH1_DATA7__USBH1_DATA7, - - /* USB HUB reset line*/ - MX51_PAD_GPIO1_7__GPIO1_7, - - /* USB PHY reset line */ - MX51_PAD_EIM_D21__GPIO2_5, - - /* FEC */ - MX51_PAD_EIM_EB2__FEC_MDIO, - MX51_PAD_EIM_EB3__FEC_RDATA1, - MX51_PAD_EIM_CS2__FEC_RDATA2, - MX51_PAD_EIM_CS3__FEC_RDATA3, - MX51_PAD_EIM_CS4__FEC_RX_ER, - MX51_PAD_EIM_CS5__FEC_CRS, - MX51_PAD_NANDF_RB2__FEC_COL, - MX51_PAD_NANDF_RB3__FEC_RX_CLK, - MX51_PAD_NANDF_D9__FEC_RDATA0, - MX51_PAD_NANDF_D8__FEC_TDATA0, - MX51_PAD_NANDF_CS2__FEC_TX_ER, - MX51_PAD_NANDF_CS3__FEC_MDC, - MX51_PAD_NANDF_CS4__FEC_TDATA1, - MX51_PAD_NANDF_CS5__FEC_TDATA2, - MX51_PAD_NANDF_CS6__FEC_TDATA3, - MX51_PAD_NANDF_CS7__FEC_TX_EN, - MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK, - - /* FEC PHY reset line */ - MX51_PAD_EIM_A20__GPIO2_14, - - /* SD 1 */ - MX51_PAD_SD1_CMD__SD1_CMD, - MX51_PAD_SD1_CLK__SD1_CLK, - MX51_PAD_SD1_DATA0__SD1_DATA0, - MX51_PAD_SD1_DATA1__SD1_DATA1, - MX51_PAD_SD1_DATA2__SD1_DATA2, - MX51_PAD_SD1_DATA3__SD1_DATA3, - /* CD/WP from controller */ - MX51_PAD_GPIO1_0__SD1_CD, - MX51_PAD_GPIO1_1__SD1_WP, - - /* SD 2 */ - MX51_PAD_SD2_CMD__SD2_CMD, - MX51_PAD_SD2_CLK__SD2_CLK, - MX51_PAD_SD2_DATA0__SD2_DATA0, - MX51_PAD_SD2_DATA1__SD2_DATA1, - MX51_PAD_SD2_DATA2__SD2_DATA2, - MX51_PAD_SD2_DATA3__SD2_DATA3, - /* CD/WP gpio */ - MX51_PAD_GPIO1_6__GPIO1_6, - MX51_PAD_GPIO1_5__GPIO1_5, - - /* eCSPI1 */ - MX51_PAD_CSPI1_MISO__ECSPI1_MISO, - MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI, - MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK, - MX51_PAD_CSPI1_SS0__GPIO4_24, - MX51_PAD_CSPI1_SS1__GPIO4_25, -}; - -/* Serial ports */ -static const struct imxuart_platform_data uart_pdata __initconst = { - .flags = IMXUART_HAVE_RTSCTS, -}; - -static const struct imxi2c_platform_data babbage_i2c_data __initconst = { - .bitrate = 100000, -}; - -static const struct imxi2c_platform_data babbage_hsi2c_data __initconst = { - .bitrate = 400000, -}; - -static struct gpio mx51_babbage_usbh1_gpios[] = { - { BABBAGE_USBH1_STP, GPIOF_OUT_INIT_LOW, "usbh1_stp" }, - { BABBAGE_USB_PHY_RESET, GPIOF_OUT_INIT_LOW, "usbh1_phy_reset" }, -}; - -static int gpio_usbh1_active(void) -{ - iomux_v3_cfg_t usbh1stp_gpio = MX51_PAD_USBH1_STP__GPIO1_27; - int ret; - - /* Set USBH1_STP to GPIO and toggle it */ - mxc_iomux_v3_setup_pad(usbh1stp_gpio); - ret = gpio_request_array(mx51_babbage_usbh1_gpios, - ARRAY_SIZE(mx51_babbage_usbh1_gpios)); - - if (ret) { - pr_debug("failed to get USBH1 pins: %d\n", ret); - return ret; - } - - msleep(100); - gpio_set_value(BABBAGE_USBH1_STP, 1); - gpio_set_value(BABBAGE_USB_PHY_RESET, 1); - gpio_free_array(mx51_babbage_usbh1_gpios, - ARRAY_SIZE(mx51_babbage_usbh1_gpios)); - return 0; -} - -static inline void babbage_usbhub_reset(void) -{ - int ret; - - /* Reset USB hub */ - ret = gpio_request_one(BABBAGE_USB_HUB_RESET, - GPIOF_OUT_INIT_LOW, "GPIO1_7"); - if (ret) { - printk(KERN_ERR"failed to get GPIO_USB_HUB_RESET: %d\n", ret); - return; - } - - msleep(2); - /* Deassert reset */ - gpio_set_value(BABBAGE_USB_HUB_RESET, 1); -} - -static inline void babbage_fec_reset(void) -{ - int ret; - - /* reset FEC PHY */ - ret = gpio_request_one(BABBAGE_FEC_PHY_RESET, - GPIOF_OUT_INIT_LOW, "fec-phy-reset"); - if (ret) { - printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret); - return; - } - msleep(1); - gpio_set_value(BABBAGE_FEC_PHY_RESET, 1); -} - -/* This function is board specific as the bit mask for the plldiv will also -be different for other Freescale SoCs, thus a common bitmask is not -possible and cannot get place in /plat-mxc/ehci.c.*/ -static int initialize_otg_port(struct platform_device *pdev) -{ - u32 v; - void __iomem *usb_base; - void __iomem *usbother_base; - - usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); - if (!usb_base) - return -ENOMEM; - usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; - - /* Set the PHY clock to 19.2MHz */ - v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); - v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK; - v |= MX51_USB_PLL_DIV_19_2_MHZ; - __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); - iounmap(usb_base); - - mdelay(10); - - return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY); -} - -static int initialize_usbh1_port(struct platform_device *pdev) -{ - u32 v; - void __iomem *usb_base; - void __iomem *usbother_base; - - usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); - if (!usb_base) - return -ENOMEM; - usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; - - /* The clock for the USBH1 ULPI port will come externally from the PHY. */ - v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET); - __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET); - iounmap(usb_base); - - mdelay(10); - - return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED | - MXC_EHCI_ITC_NO_THRESHOLD); -} - -static const struct mxc_usbh_platform_data dr_utmi_config __initconst = { - .init = initialize_otg_port, - .portsc = MXC_EHCI_UTMI_16BIT, -}; - -static const struct fsl_usb2_platform_data usb_pdata __initconst = { - .operating_mode = FSL_USB2_DR_DEVICE, - .phy_mode = FSL_USB2_PHY_UTMI_WIDE, -}; - -static const struct mxc_usbh_platform_data usbh1_config __initconst = { - .init = initialize_usbh1_port, - .portsc = MXC_EHCI_MODE_ULPI, -}; - -static int otg_mode_host; - -static int __init babbage_otg_mode(char *options) -{ - if (!strcmp(options, "host")) - otg_mode_host = 1; - else if (!strcmp(options, "device")) - otg_mode_host = 0; - else - pr_info("otg_mode neither \"host\" nor \"device\". " - "Defaulting to device\n"); - return 0; -} -__setup("otg_mode=", babbage_otg_mode); - -static struct spi_board_info mx51_babbage_spi_board_info[] __initdata = { - { - .modalias = "mtd_dataflash", - .max_speed_hz = 25000000, - .bus_num = 0, - .chip_select = 1, - .mode = SPI_MODE_0, - .platform_data = NULL, - }, -}; - -static int mx51_babbage_spi_cs[] = { - BABBAGE_ECSPI1_CS0, - BABBAGE_ECSPI1_CS1, -}; - -static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = { - .chipselect = mx51_babbage_spi_cs, - .num_chipselect = ARRAY_SIZE(mx51_babbage_spi_cs), -}; - -static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = { - .cd_type = ESDHC_CD_CONTROLLER, - .wp_type = ESDHC_WP_CONTROLLER, -}; - -static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = { - .cd_gpio = BABBAGE_SD2_CD, - .wp_gpio = BABBAGE_SD2_WP, - .cd_type = ESDHC_CD_GPIO, - .wp_type = ESDHC_WP_GPIO, -}; - -void __init imx51_babbage_common_init(void) -{ - mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads, - ARRAY_SIZE(mx51babbage_pads)); -} - -/* - * Board specific initialization. - */ -static void __init mx51_babbage_init(void) -{ - iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP; - iomux_v3_cfg_t power_key = NEW_PAD_CTRL(MX51_PAD_EIM_A27__GPIO2_21, - PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP); - - imx51_soc_init(); - -#if defined(CONFIG_CPU_FREQ_IMX) - get_cpu_op = mx51_get_cpu_op; -#endif - imx51_babbage_common_init(); - - imx51_add_imx_uart(0, &uart_pdata); - imx51_add_imx_uart(1, NULL); - imx51_add_imx_uart(2, &uart_pdata); - - babbage_fec_reset(); - imx51_add_fec(NULL); - - /* Set the PAD settings for the pwr key. */ - mxc_iomux_v3_setup_pad(power_key); - imx_add_gpio_keys(&imx_button_data); - - imx51_add_imx_i2c(0, &babbage_i2c_data); - imx51_add_imx_i2c(1, &babbage_i2c_data); - imx51_add_hsi2c(&babbage_hsi2c_data); - - if (otg_mode_host) - imx51_add_mxc_ehci_otg(&dr_utmi_config); - else { - initialize_otg_port(NULL); - imx51_add_fsl_usb2_udc(&usb_pdata); - } - - gpio_usbh1_active(); - imx51_add_mxc_ehci_hs(1, &usbh1_config); - /* setback USBH1_STP to be function */ - mxc_iomux_v3_setup_pad(usbh1stp); - babbage_usbhub_reset(); - - imx51_add_sdhci_esdhc_imx(0, &mx51_babbage_sd1_data); - imx51_add_sdhci_esdhc_imx(1, &mx51_babbage_sd2_data); - - spi_register_board_info(mx51_babbage_spi_board_info, - ARRAY_SIZE(mx51_babbage_spi_board_info)); - imx51_add_ecspi(0, &mx51_babbage_spi_pdata); - imx51_add_imx2_wdt(0, NULL); -} - -static void __init mx51_babbage_timer_init(void) -{ - mx51_clocks_init(32768, 24000000, 22579200, 0); -} - -static struct sys_timer mx51_babbage_timer = { - .init = mx51_babbage_timer_init, -}; - -MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board") - /* Maintainer: Amit Kucheria */ - .atag_offset = 0x100, - .map_io = mx51_map_io, - .init_early = imx51_init_early, - .init_irq = mx51_init_irq, - .handle_irq = imx51_handle_irq, - .timer = &mx51_babbage_timer, - .init_machine = mx51_babbage_init, -MACHINE_END diff --git a/arch/arm/mach-mx5/board-mx51_efikamx.c b/arch/arm/mach-mx5/board-mx51_efikamx.c deleted file mode 100644 index a9e4866..0000000 --- a/arch/arm/mach-mx5/board-mx51_efikamx.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (C) 2010 Linaro Limited - * - * based on code from the following - * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved. - * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "devices-imx51.h" -#include "efika.h" - -#define EFIKAMX_PCBID0 IMX_GPIO_NR(3, 16) -#define EFIKAMX_PCBID1 IMX_GPIO_NR(3, 17) -#define EFIKAMX_PCBID2 IMX_GPIO_NR(3, 11) - -#define EFIKAMX_BLUE_LED IMX_GPIO_NR(3, 13) -#define EFIKAMX_GREEN_LED IMX_GPIO_NR(3, 14) -#define EFIKAMX_RED_LED IMX_GPIO_NR(3, 15) - -#define EFIKAMX_POWER_KEY IMX_GPIO_NR(2, 31) - -/* board 1.1 doesn't have same reset gpio */ -#define EFIKAMX_RESET1_1 IMX_GPIO_NR(3, 2) -#define EFIKAMX_RESET IMX_GPIO_NR(1, 4) - -#define EFIKAMX_POWEROFF IMX_GPIO_NR(4, 13) - -#define EFIKAMX_PMIC IMX_GPIO_NR(1, 6) - -/* the pci ids pin have pull up. they're driven low according to board id */ -#define MX51_PAD_PCBID0 IOMUX_PAD(0x518, 0x130, 3, 0x0, 0, PAD_CTL_PUS_100K_UP) -#define MX51_PAD_PCBID1 IOMUX_PAD(0x51C, 0x134, 3, 0x0, 0, PAD_CTL_PUS_100K_UP) -#define MX51_PAD_PCBID2 IOMUX_PAD(0x504, 0x128, 3, 0x0, 0, PAD_CTL_PUS_100K_UP) -#define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0, 0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE) - -static iomux_v3_cfg_t mx51efikamx_pads[] = { - /* board id */ - MX51_PAD_PCBID0, - MX51_PAD_PCBID1, - MX51_PAD_PCBID2, - - /* leds */ - MX51_PAD_CSI1_D9__GPIO3_13, - MX51_PAD_CSI1_VSYNC__GPIO3_14, - MX51_PAD_CSI1_HSYNC__GPIO3_15, - - /* power key */ - MX51_PAD_PWRKEY, - - /* reset */ - MX51_PAD_DI1_PIN13__GPIO3_2, - MX51_PAD_GPIO1_4__GPIO1_4, - - /* power off */ - MX51_PAD_CSI2_VSYNC__GPIO4_13, -}; - -/* PCBID2 PCBID1 PCBID0 STATE - 1 1 1 ER1:rev1.1 - 1 1 0 ER2:rev1.2 - 1 0 1 ER3:rev1.3 - 1 0 0 ER4:rev1.4 -*/ -static void __init mx51_efikamx_board_id(void) -{ - int id; - - /* things are taking time to settle */ - msleep(150); - - gpio_request(EFIKAMX_PCBID0, "pcbid0"); - gpio_direction_input(EFIKAMX_PCBID0); - gpio_request(EFIKAMX_PCBID1, "pcbid1"); - gpio_direction_input(EFIKAMX_PCBID1); - gpio_request(EFIKAMX_PCBID2, "pcbid2"); - gpio_direction_input(EFIKAMX_PCBID2); - - id = gpio_get_value(EFIKAMX_PCBID0) ? 1 : 0; - id |= (gpio_get_value(EFIKAMX_PCBID1) ? 1 : 0) << 1; - id |= (gpio_get_value(EFIKAMX_PCBID2) ? 1 : 0) << 2; - - switch (id) { - case 7: - system_rev = 0x11; - break; - case 6: - system_rev = 0x12; - break; - case 5: - system_rev = 0x13; - break; - case 4: - system_rev = 0x14; - break; - default: - system_rev = 0x10; - break; - } - - if ((system_rev == 0x10) - || (system_rev == 0x12) - || (system_rev == 0x14)) { - printk(KERN_WARNING - "EfikaMX: Unsupported board revision 1.%u!\n", - system_rev & 0xf); - } -} - -static struct gpio_led mx51_efikamx_leds[] __initdata = { - { - .name = "efikamx:green", - .default_trigger = "default-on", - .gpio = EFIKAMX_GREEN_LED, - }, - { - .name = "efikamx:red", - .default_trigger = "ide-disk", - .gpio = EFIKAMX_RED_LED, - }, - { - .name = "efikamx:blue", - .default_trigger = "mmc0", - .gpio = EFIKAMX_BLUE_LED, - }, -}; - -static const struct gpio_led_platform_data - mx51_efikamx_leds_data __initconst = { - .leds = mx51_efikamx_leds, - .num_leds = ARRAY_SIZE(mx51_efikamx_leds), -}; - -static struct esdhc_platform_data sd_pdata = { - .cd_type = ESDHC_CD_CONTROLLER, - .wp_type = ESDHC_WP_CONTROLLER, -}; - -static struct gpio_keys_button mx51_efikamx_powerkey[] = { - { - .code = KEY_POWER, - .gpio = EFIKAMX_POWER_KEY, - .type = EV_PWR, - .desc = "Power Button (CM)", - .wakeup = 1, - .debounce_interval = 10, /* ms */ - }, -}; - -static const struct gpio_keys_platform_data mx51_efikamx_powerkey_data __initconst = { - .buttons = mx51_efikamx_powerkey, - .nbuttons = ARRAY_SIZE(mx51_efikamx_powerkey), -}; - -void mx51_efikamx_reset(void) -{ - if (system_rev == 0x11) - gpio_direction_output(EFIKAMX_RESET1_1, 0); - else - gpio_direction_output(EFIKAMX_RESET, 0); -} - -static struct regulator *pwgt1, *pwgt2, *coincell; - -static void mx51_efikamx_power_off(void) -{ - if (!IS_ERR(coincell)) - regulator_disable(coincell); - - if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) { - regulator_disable(pwgt2); - regulator_disable(pwgt1); - } - gpio_direction_output(EFIKAMX_POWEROFF, 1); -} - -static int __init mx51_efikamx_power_init(void) -{ - if (machine_is_mx51_efikamx()) { - pwgt1 = regulator_get(NULL, "pwgt1"); - pwgt2 = regulator_get(NULL, "pwgt2"); - if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) { - regulator_enable(pwgt1); - regulator_enable(pwgt2); - } - gpio_request(EFIKAMX_POWEROFF, "poweroff"); - pm_power_off = mx51_efikamx_power_off; - - /* enable coincell charger. maybe need a small power driver ? */ - coincell = regulator_get(NULL, "coincell"); - if (!IS_ERR(coincell)) { - regulator_set_voltage(coincell, 3000000, 3000000); - regulator_enable(coincell); - } - - regulator_has_full_constraints(); - } - - return 0; -} -late_initcall(mx51_efikamx_power_init); - -static void __init mx51_efikamx_init(void) -{ - imx51_soc_init(); - - mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads, - ARRAY_SIZE(mx51efikamx_pads)); - efika_board_common_init(); - - mx51_efikamx_board_id(); - - /* on < 1.2 boards both SD controllers are used */ - if (system_rev < 0x12) { - imx51_add_sdhci_esdhc_imx(0, NULL); - imx51_add_sdhci_esdhc_imx(1, &sd_pdata); - mx51_efikamx_leds[2].default_trigger = "mmc1"; - } else - imx51_add_sdhci_esdhc_imx(0, &sd_pdata); - - gpio_led_register_device(-1, &mx51_efikamx_leds_data); - imx_add_gpio_keys(&mx51_efikamx_powerkey_data); - - if (system_rev == 0x11) { - gpio_request(EFIKAMX_RESET1_1, "reset"); - gpio_direction_output(EFIKAMX_RESET1_1, 1); - } else { - gpio_request(EFIKAMX_RESET, "reset"); - gpio_direction_output(EFIKAMX_RESET, 1); - } - - /* - * enable wifi by default only on mx - * sb and mx have same wlan pin but the value to enable it are - * different :/ - */ - gpio_request(EFIKA_WLAN_EN, "wlan_en"); - gpio_direction_output(EFIKA_WLAN_EN, 0); - msleep(10); - - gpio_request(EFIKA_WLAN_RESET, "wlan_rst"); - gpio_direction_output(EFIKA_WLAN_RESET, 0); - msleep(10); - gpio_set_value(EFIKA_WLAN_RESET, 1); -} - -static void __init mx51_efikamx_timer_init(void) -{ - mx51_clocks_init(32768, 24000000, 22579200, 24576000); -} - -static struct sys_timer mx51_efikamx_timer = { - .init = mx51_efikamx_timer_init, -}; - -MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop") - /* Maintainer: Amit Kucheria */ - .atag_offset = 0x100, - .map_io = mx51_map_io, - .init_early = imx51_init_early, - .init_irq = mx51_init_irq, - .handle_irq = imx51_handle_irq, - .timer = &mx51_efikamx_timer, - .init_machine = mx51_efikamx_init, -MACHINE_END diff --git a/arch/arm/mach-mx5/board-mx51_efikasb.c b/arch/arm/mach-mx5/board-mx51_efikasb.c deleted file mode 100644 index 38c4a3e..0000000 --- a/arch/arm/mach-mx5/board-mx51_efikasb.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) Arnaud Patard - * - * based on code from the following - * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved. - * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "devices-imx51.h" -#include "efika.h" - -#define EFIKASB_USBH2_STP IMX_GPIO_NR(2, 20) -#define EFIKASB_GREEN_LED IMX_GPIO_NR(1, 3) -#define EFIKASB_WHITE_LED IMX_GPIO_NR(2, 25) -#define EFIKASB_PCBID0 IMX_GPIO_NR(2, 28) -#define EFIKASB_PCBID1 IMX_GPIO_NR(2, 29) -#define EFIKASB_PWRKEY IMX_GPIO_NR(2, 31) -#define EFIKASB_LID IMX_GPIO_NR(3, 14) -#define EFIKASB_POWEROFF IMX_GPIO_NR(4, 13) -#define EFIKASB_RFKILL IMX_GPIO_NR(3, 1) - -#define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0, 0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE) -#define MX51_PAD_SD1_CD IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_ESDHC_PAD_CTRL) - -static iomux_v3_cfg_t mx51efikasb_pads[] = { - /* USB HOST2 */ - MX51_PAD_EIM_D16__USBH2_DATA0, - MX51_PAD_EIM_D17__USBH2_DATA1, - MX51_PAD_EIM_D18__USBH2_DATA2, - MX51_PAD_EIM_D19__USBH2_DATA3, - MX51_PAD_EIM_D20__USBH2_DATA4, - MX51_PAD_EIM_D21__USBH2_DATA5, - MX51_PAD_EIM_D22__USBH2_DATA6, - MX51_PAD_EIM_D23__USBH2_DATA7, - MX51_PAD_EIM_A24__USBH2_CLK, - MX51_PAD_EIM_A25__USBH2_DIR, - MX51_PAD_EIM_A26__USBH2_STP, - MX51_PAD_EIM_A27__USBH2_NXT, - - /* leds */ - MX51_PAD_EIM_CS0__GPIO2_25, - MX51_PAD_GPIO1_3__GPIO1_3, - - /* pcb id */ - MX51_PAD_EIM_CS3__GPIO2_28, - MX51_PAD_EIM_CS4__GPIO2_29, - - /* lid */ - MX51_PAD_CSI1_VSYNC__GPIO3_14, - - /* power key*/ - MX51_PAD_PWRKEY, - - /* wifi/bt button */ - MX51_PAD_DI1_PIN12__GPIO3_1, - - /* power off */ - MX51_PAD_CSI2_VSYNC__GPIO4_13, - - /* wdog reset */ - MX51_PAD_GPIO1_4__WDOG1_WDOG_B, - - /* BT */ - MX51_PAD_EIM_A17__GPIO2_11, - - MX51_PAD_SD1_CD, -}; - -static int initialize_usbh2_port(struct platform_device *pdev) -{ - iomux_v3_cfg_t usbh2stp = MX51_PAD_EIM_A26__USBH2_STP; - iomux_v3_cfg_t usbh2gpio = MX51_PAD_EIM_A26__GPIO2_20; - - mxc_iomux_v3_setup_pad(usbh2gpio); - gpio_request(EFIKASB_USBH2_STP, "usbh2_stp"); - gpio_direction_output(EFIKASB_USBH2_STP, 0); - msleep(1); - gpio_set_value(EFIKASB_USBH2_STP, 1); - msleep(1); - - gpio_free(EFIKASB_USBH2_STP); - mxc_iomux_v3_setup_pad(usbh2stp); - - mdelay(10); - - return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD); -} - -static struct mxc_usbh_platform_data usbh2_config __initdata = { - .init = initialize_usbh2_port, - .portsc = MXC_EHCI_MODE_ULPI, -}; - -static void __init mx51_efikasb_usb(void) -{ - usbh2_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS | - ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND); - if (usbh2_config.otg) - imx51_add_mxc_ehci_hs(2, &usbh2_config); -} - -static const struct gpio_led mx51_efikasb_leds[] __initconst = { - { - .name = "efikasb:green", - .default_trigger = "default-on", - .gpio = EFIKASB_GREEN_LED, - .active_low = 1, - }, - { - .name = "efikasb:white", - .default_trigger = "caps", - .gpio = EFIKASB_WHITE_LED, - }, -}; - -static const struct gpio_led_platform_data - mx51_efikasb_leds_data __initconst = { - .leds = mx51_efikasb_leds, - .num_leds = ARRAY_SIZE(mx51_efikasb_leds), -}; - -static struct gpio_keys_button mx51_efikasb_keys[] = { - { - .code = KEY_POWER, - .gpio = EFIKASB_PWRKEY, - .type = EV_KEY, - .desc = "Power Button", - .wakeup = 1, - .active_low = 1, - }, - { - .code = SW_LID, - .gpio = EFIKASB_LID, - .type = EV_SW, - .desc = "Lid Switch", - .active_low = 1, - }, - { - .code = KEY_RFKILL, - .gpio = EFIKASB_RFKILL, - .type = EV_KEY, - .desc = "rfkill", - .active_low = 1, - }, -}; - -static const struct gpio_keys_platform_data mx51_efikasb_keys_data __initconst = { - .buttons = mx51_efikasb_keys, - .nbuttons = ARRAY_SIZE(mx51_efikasb_keys), -}; - -static struct esdhc_platform_data sd0_pdata = { -#define EFIKASB_SD1_CD IMX_GPIO_NR(2, 27) - .cd_gpio = EFIKASB_SD1_CD, - .cd_type = ESDHC_CD_GPIO, - .wp_type = ESDHC_WP_CONTROLLER, -}; - -static struct esdhc_platform_data sd1_pdata = { - .cd_type = ESDHC_CD_CONTROLLER, - .wp_type = ESDHC_WP_CONTROLLER, -}; - -static struct regulator *pwgt1, *pwgt2; - -static void mx51_efikasb_power_off(void) -{ - gpio_set_value(EFIKA_USB_PHY_RESET, 0); - - if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) { - regulator_disable(pwgt2); - regulator_disable(pwgt1); - } - gpio_direction_output(EFIKASB_POWEROFF, 1); -} - -static int __init mx51_efikasb_power_init(void) -{ - if (machine_is_mx51_efikasb()) { - pwgt1 = regulator_get(NULL, "pwgt1"); - pwgt2 = regulator_get(NULL, "pwgt2"); - if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) { - regulator_enable(pwgt1); - regulator_enable(pwgt2); - } - gpio_request(EFIKASB_POWEROFF, "poweroff"); - pm_power_off = mx51_efikasb_power_off; - - regulator_has_full_constraints(); - } - - return 0; -} -late_initcall(mx51_efikasb_power_init); - -/* 01 R1.3 board - 10 R2.0 board */ -static void __init mx51_efikasb_board_id(void) -{ - int id; - - gpio_request(EFIKASB_PCBID0, "pcb id0"); - gpio_direction_input(EFIKASB_PCBID0); - gpio_request(EFIKASB_PCBID1, "pcb id1"); - gpio_direction_input(EFIKASB_PCBID1); - - id = gpio_get_value(EFIKASB_PCBID0) ? 1 : 0; - id |= (gpio_get_value(EFIKASB_PCBID1) ? 1 : 0) << 1; - - switch (id) { - default: - break; - case 1: - system_rev = 0x13; - break; - case 2: - system_rev = 0x20; - break; - } -} - -static void __init efikasb_board_init(void) -{ - imx51_soc_init(); - - mxc_iomux_v3_setup_multiple_pads(mx51efikasb_pads, - ARRAY_SIZE(mx51efikasb_pads)); - efika_board_common_init(); - - mx51_efikasb_board_id(); - mx51_efikasb_usb(); - imx51_add_sdhci_esdhc_imx(0, &sd0_pdata); - imx51_add_sdhci_esdhc_imx(1, &sd1_pdata); - - gpio_led_register_device(-1, &mx51_efikasb_leds_data); - imx_add_gpio_keys(&mx51_efikasb_keys_data); -} - -static void __init mx51_efikasb_timer_init(void) -{ - mx51_clocks_init(32768, 24000000, 22579200, 24576000); -} - -static struct sys_timer mx51_efikasb_timer = { - .init = mx51_efikasb_timer_init, -}; - -MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook") - .atag_offset = 0x100, - .map_io = mx51_map_io, - .init_early = imx51_init_early, - .init_irq = mx51_init_irq, - .handle_irq = imx51_handle_irq, - .init_machine = efikasb_board_init, - .timer = &mx51_efikasb_timer, -MACHINE_END diff --git a/arch/arm/mach-mx5/board-mx53_ard.c b/arch/arm/mach-mx5/board-mx53_ard.c deleted file mode 100644 index b88a2bc..0000000 --- a/arch/arm/mach-mx5/board-mx53_ard.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include "devices-imx53.h" - -#define ARD_ETHERNET_INT_B IMX_GPIO_NR(2, 31) -#define ARD_SD1_CD IMX_GPIO_NR(1, 1) -#define ARD_SD1_WP IMX_GPIO_NR(1, 9) -#define ARD_I2CPORTEXP_B IMX_GPIO_NR(2, 3) -#define ARD_VOLUMEDOWN IMX_GPIO_NR(4, 0) -#define ARD_HOME IMX_GPIO_NR(5, 10) -#define ARD_BACK IMX_GPIO_NR(5, 11) -#define ARD_PROG IMX_GPIO_NR(5, 12) -#define ARD_VOLUMEUP IMX_GPIO_NR(5, 13) - -static iomux_v3_cfg_t mx53_ard_pads[] = { - /* UART1 */ - MX53_PAD_PATA_DIOW__UART1_TXD_MUX, - MX53_PAD_PATA_DMACK__UART1_RXD_MUX, - /* WEIM for CS1 */ - MX53_PAD_EIM_EB3__GPIO2_31, /* ETHERNET_INT_B */ - MX53_PAD_EIM_D16__EMI_WEIM_D_16, - MX53_PAD_EIM_D17__EMI_WEIM_D_17, - MX53_PAD_EIM_D18__EMI_WEIM_D_18, - MX53_PAD_EIM_D19__EMI_WEIM_D_19, - MX53_PAD_EIM_D20__EMI_WEIM_D_20, - MX53_PAD_EIM_D21__EMI_WEIM_D_21, - MX53_PAD_EIM_D22__EMI_WEIM_D_22, - MX53_PAD_EIM_D23__EMI_WEIM_D_23, - MX53_PAD_EIM_D24__EMI_WEIM_D_24, - MX53_PAD_EIM_D25__EMI_WEIM_D_25, - MX53_PAD_EIM_D26__EMI_WEIM_D_26, - MX53_PAD_EIM_D27__EMI_WEIM_D_27, - MX53_PAD_EIM_D28__EMI_WEIM_D_28, - MX53_PAD_EIM_D29__EMI_WEIM_D_29, - MX53_PAD_EIM_D30__EMI_WEIM_D_30, - MX53_PAD_EIM_D31__EMI_WEIM_D_31, - MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0, - MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1, - MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2, - MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3, - MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4, - MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5, - MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6, - MX53_PAD_EIM_OE__EMI_WEIM_OE, - MX53_PAD_EIM_RW__EMI_WEIM_RW, - MX53_PAD_EIM_CS1__EMI_WEIM_CS_1, - /* SDHC1 */ - MX53_PAD_SD1_CMD__ESDHC1_CMD, - MX53_PAD_SD1_CLK__ESDHC1_CLK, - MX53_PAD_SD1_DATA0__ESDHC1_DAT0, - MX53_PAD_SD1_DATA1__ESDHC1_DAT1, - MX53_PAD_SD1_DATA2__ESDHC1_DAT2, - MX53_PAD_SD1_DATA3__ESDHC1_DAT3, - MX53_PAD_PATA_DATA8__ESDHC1_DAT4, - MX53_PAD_PATA_DATA9__ESDHC1_DAT5, - MX53_PAD_PATA_DATA10__ESDHC1_DAT6, - MX53_PAD_PATA_DATA11__ESDHC1_DAT7, - MX53_PAD_GPIO_1__GPIO1_1, - MX53_PAD_GPIO_9__GPIO1_9, - /* I2C2 */ - MX53_PAD_EIM_EB2__I2C2_SCL, - MX53_PAD_KEY_ROW3__I2C2_SDA, - /* I2C3 */ - MX53_PAD_GPIO_3__I2C3_SCL, - MX53_PAD_GPIO_16__I2C3_SDA, - /* GPIO */ - MX53_PAD_DISP0_DAT16__GPIO5_10, /* home */ - MX53_PAD_DISP0_DAT17__GPIO5_11, /* back */ - MX53_PAD_DISP0_DAT18__GPIO5_12, /* prog */ - MX53_PAD_DISP0_DAT19__GPIO5_13, /* vol up */ - MX53_PAD_GPIO_10__GPIO4_0, /* vol down */ -}; - -#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake) \ -{ \ - .gpio = gpio_num, \ - .type = EV_KEY, \ - .code = ev_code, \ - .active_low = act_low, \ - .desc = "btn " descr, \ - .wakeup = wake, \ -} - -static struct gpio_keys_button ard_buttons[] = { - GPIO_BUTTON(ARD_HOME, KEY_HOME, 1, "home", 0), - GPIO_BUTTON(ARD_BACK, KEY_BACK, 1, "back", 0), - GPIO_BUTTON(ARD_PROG, KEY_PROGRAM, 1, "program", 0), - GPIO_BUTTON(ARD_VOLUMEUP, KEY_VOLUMEUP, 1, "volume-up", 0), - GPIO_BUTTON(ARD_VOLUMEDOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0), -}; - -static const struct gpio_keys_platform_data ard_button_data __initconst = { - .buttons = ard_buttons, - .nbuttons = ARRAY_SIZE(ard_buttons), -}; - -static struct resource ard_smsc911x_resources[] = { - { - .start = MX53_CS1_64MB_BASE_ADDR, - .end = MX53_CS1_64MB_BASE_ADDR + SZ_32M - 1, - .flags = IORESOURCE_MEM, - }, - { - .start = IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B), - .end = IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B), - .flags = IORESOURCE_IRQ, - }, -}; - -struct smsc911x_platform_config ard_smsc911x_config = { - .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, - .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, - .flags = SMSC911X_USE_32BIT, -}; - -static struct platform_device ard_smsc_lan9220_device = { - .name = "smsc911x", - .id = -1, - .num_resources = ARRAY_SIZE(ard_smsc911x_resources), - .resource = ard_smsc911x_resources, - .dev = { - .platform_data = &ard_smsc911x_config, - }, -}; - -static const struct esdhc_platform_data mx53_ard_sd1_data __initconst = { - .cd_gpio = ARD_SD1_CD, - .wp_gpio = ARD_SD1_WP, -}; - -static struct imxi2c_platform_data mx53_ard_i2c2_data = { - .bitrate = 50000, -}; - -static struct imxi2c_platform_data mx53_ard_i2c3_data = { - .bitrate = 400000, -}; - -static void __init mx53_ard_io_init(void) -{ - gpio_request(ARD_ETHERNET_INT_B, "eth-int-b"); - gpio_direction_input(ARD_ETHERNET_INT_B); - - gpio_request(ARD_I2CPORTEXP_B, "i2cptexp-rst"); - gpio_direction_output(ARD_I2CPORTEXP_B, 1); -} - -/* Config CS1 settings for ethernet controller */ -static int weim_cs_config(void) -{ - u32 reg; - void __iomem *weim_base, *iomuxc_base; - - weim_base = ioremap(MX53_WEIM_BASE_ADDR, SZ_4K); - if (!weim_base) - return -ENOMEM; - - iomuxc_base = ioremap(MX53_IOMUXC_BASE_ADDR, SZ_4K); - if (!iomuxc_base) - return -ENOMEM; - - /* CS1 timings for LAN9220 */ - writel(0x20001, (weim_base + 0x18)); - writel(0x0, (weim_base + 0x1C)); - writel(0x16000202, (weim_base + 0x20)); - writel(0x00000002, (weim_base + 0x24)); - writel(0x16002082, (weim_base + 0x28)); - writel(0x00000000, (weim_base + 0x2C)); - writel(0x00000000, (weim_base + 0x90)); - - /* specify 64 MB on CS1 and CS0 on GPR1 */ - reg = readl(iomuxc_base + 0x4); - reg &= ~0x3F; - reg |= 0x1B; - writel(reg, (iomuxc_base + 0x4)); - - iounmap(iomuxc_base); - iounmap(weim_base); - - return 0; -} - -void __init imx53_ard_common_init(void) -{ - mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads, - ARRAY_SIZE(mx53_ard_pads)); - weim_cs_config(); -} - -static struct platform_device *devices[] __initdata = { - &ard_smsc_lan9220_device, -}; - -static void __init mx53_ard_board_init(void) -{ - imx53_soc_init(); - imx53_add_imx_uart(0, NULL); - - imx53_ard_common_init(); - mx53_ard_io_init(); - platform_add_devices(devices, ARRAY_SIZE(devices)); - - imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data); - imx53_add_imx2_wdt(0, NULL); - imx53_add_imx_i2c(1, &mx53_ard_i2c2_data); - imx53_add_imx_i2c(2, &mx53_ard_i2c3_data); - imx_add_gpio_keys(&ard_button_data); - imx53_add_ahci_imx(); -} - -static void __init mx53_ard_timer_init(void) -{ - mx53_clocks_init(32768, 24000000, 22579200, 0); -} - -static struct sys_timer mx53_ard_timer = { - .init = mx53_ard_timer_init, -}; - -MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board") - .map_io = mx53_map_io, - .init_early = imx53_init_early, - .init_irq = mx53_init_irq, - .handle_irq = imx53_handle_irq, - .timer = &mx53_ard_timer, - .init_machine = mx53_ard_board_init, -MACHINE_END diff --git a/arch/arm/mach-mx5/board-mx53_evk.c b/arch/arm/mach-mx5/board-mx53_evk.c deleted file mode 100644 index c69413d..0000000 --- a/arch/arm/mach-mx5/board-mx53_evk.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright (C) 2010 Yong Shen. - */ - -/* - * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MX53_EVK_FEC_PHY_RST IMX_GPIO_NR(7, 6) -#define EVK_ECSPI1_CS0 IMX_GPIO_NR(2, 30) -#define EVK_ECSPI1_CS1 IMX_GPIO_NR(3, 19) -#define MX53EVK_LED IMX_GPIO_NR(7, 7) - -#include "devices-imx53.h" - -static iomux_v3_cfg_t mx53_evk_pads[] = { - MX53_PAD_CSI0_DAT10__UART1_TXD_MUX, - MX53_PAD_CSI0_DAT11__UART1_RXD_MUX, - - MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX, - MX53_PAD_PATA_DMARQ__UART2_TXD_MUX, - MX53_PAD_PATA_DIOR__UART2_RTS, - MX53_PAD_PATA_INTRQ__UART2_CTS, - - MX53_PAD_PATA_CS_0__UART3_TXD_MUX, - MX53_PAD_PATA_CS_1__UART3_RXD_MUX, - - MX53_PAD_EIM_D16__ECSPI1_SCLK, - MX53_PAD_EIM_D17__ECSPI1_MISO, - MX53_PAD_EIM_D18__ECSPI1_MOSI, - - /* ecspi chip select lines */ - MX53_PAD_EIM_EB2__GPIO2_30, - MX53_PAD_EIM_D19__GPIO3_19, - /* LED */ - MX53_PAD_PATA_DA_1__GPIO7_7, -}; - -static const struct imxuart_platform_data mx53_evk_uart_pdata __initconst = { - .flags = IMXUART_HAVE_RTSCTS, -}; - -static const struct gpio_led mx53evk_leds[] __initconst = { - { - .name = "green", - .default_trigger = "heartbeat", - .gpio = MX53EVK_LED, - }, -}; - -static const struct gpio_led_platform_data mx53evk_leds_data __initconst = { - .leds = mx53evk_leds, - .num_leds = ARRAY_SIZE(mx53evk_leds), -}; - -static inline void mx53_evk_init_uart(void) -{ - imx53_add_imx_uart(0, NULL); - imx53_add_imx_uart(1, &mx53_evk_uart_pdata); - imx53_add_imx_uart(2, NULL); -} - -static const struct imxi2c_platform_data mx53_evk_i2c_data __initconst = { - .bitrate = 100000, -}; - -static inline void mx53_evk_fec_reset(void) -{ - int ret; - - /* reset FEC PHY */ - ret = gpio_request_one(MX53_EVK_FEC_PHY_RST, GPIOF_OUT_INIT_LOW, - "fec-phy-reset"); - if (ret) { - printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret); - return; - } - msleep(1); - gpio_set_value(MX53_EVK_FEC_PHY_RST, 1); -} - -static struct fec_platform_data mx53_evk_fec_pdata = { - .phy = PHY_INTERFACE_MODE_RMII, -}; - -static struct spi_board_info mx53_evk_spi_board_info[] __initdata = { - { - .modalias = "mtd_dataflash", - .max_speed_hz = 25000000, - .bus_num = 0, - .chip_select = 1, - .mode = SPI_MODE_0, - .platform_data = NULL, - }, -}; - -static int mx53_evk_spi_cs[] = { - EVK_ECSPI1_CS0, - EVK_ECSPI1_CS1, -}; - -static const struct spi_imx_master mx53_evk_spi_data __initconst = { - .chipselect = mx53_evk_spi_cs, - .num_chipselect = ARRAY_SIZE(mx53_evk_spi_cs), -}; - -void __init imx53_evk_common_init(void) -{ - mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads, - ARRAY_SIZE(mx53_evk_pads)); -} - -static void __init mx53_evk_board_init(void) -{ - imx53_soc_init(); - imx53_evk_common_init(); - - mx53_evk_init_uart(); - mx53_evk_fec_reset(); - imx53_add_fec(&mx53_evk_fec_pdata); - - imx53_add_imx_i2c(0, &mx53_evk_i2c_data); - imx53_add_imx_i2c(1, &mx53_evk_i2c_data); - - imx53_add_sdhci_esdhc_imx(0, NULL); - imx53_add_sdhci_esdhc_imx(1, NULL); - - spi_register_board_info(mx53_evk_spi_board_info, - ARRAY_SIZE(mx53_evk_spi_board_info)); - imx53_add_ecspi(0, &mx53_evk_spi_data); - imx53_add_imx2_wdt(0, NULL); - gpio_led_register_device(-1, &mx53evk_leds_data); -} - -static void __init mx53_evk_timer_init(void) -{ - mx53_clocks_init(32768, 24000000, 22579200, 0); -} - -static struct sys_timer mx53_evk_timer = { - .init = mx53_evk_timer_init, -}; - -MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board") - .map_io = mx53_map_io, - .init_early = imx53_init_early, - .init_irq = mx53_init_irq, - .handle_irq = imx53_handle_irq, - .timer = &mx53_evk_timer, - .init_machine = mx53_evk_board_init, -MACHINE_END diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c deleted file mode 100644 index e64a8f7..0000000 --- a/arch/arm/mach-mx5/board-mx53_loco.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include "devices-imx53.h" - -#define MX53_LOCO_POWER IMX_GPIO_NR(1, 8) -#define MX53_LOCO_UI1 IMX_GPIO_NR(2, 14) -#define MX53_LOCO_UI2 IMX_GPIO_NR(2, 15) -#define LOCO_FEC_PHY_RST IMX_GPIO_NR(7, 6) -#define LOCO_LED IMX_GPIO_NR(7, 7) -#define LOCO_SD3_CD IMX_GPIO_NR(3, 11) -#define LOCO_SD3_WP IMX_GPIO_NR(3, 12) -#define LOCO_SD1_CD IMX_GPIO_NR(3, 13) -#define LOCO_ACCEL_EN IMX_GPIO_NR(6, 14) - -static iomux_v3_cfg_t mx53_loco_pads[] = { - /* FEC */ - MX53_PAD_FEC_MDC__FEC_MDC, - MX53_PAD_FEC_MDIO__FEC_MDIO, - MX53_PAD_FEC_REF_CLK__FEC_TX_CLK, - MX53_PAD_FEC_RX_ER__FEC_RX_ER, - MX53_PAD_FEC_CRS_DV__FEC_RX_DV, - MX53_PAD_FEC_RXD1__FEC_RDATA_1, - MX53_PAD_FEC_RXD0__FEC_RDATA_0, - MX53_PAD_FEC_TX_EN__FEC_TX_EN, - MX53_PAD_FEC_TXD1__FEC_TDATA_1, - MX53_PAD_FEC_TXD0__FEC_TDATA_0, - /* FEC_nRST */ - MX53_PAD_PATA_DA_0__GPIO7_6, - /* FEC_nINT */ - MX53_PAD_PATA_DATA4__GPIO2_4, - /* AUDMUX5 */ - MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC, - MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD, - MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS, - MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD, - /* I2C1 */ - MX53_PAD_CSI0_DAT8__I2C1_SDA, - MX53_PAD_CSI0_DAT9__I2C1_SCL, - MX53_PAD_NANDF_CS1__GPIO6_14, /* Accelerometer Enable */ - /* I2C2 */ - MX53_PAD_KEY_COL3__I2C2_SCL, - MX53_PAD_KEY_ROW3__I2C2_SDA, - /* SD1 */ - MX53_PAD_SD1_CMD__ESDHC1_CMD, - MX53_PAD_SD1_CLK__ESDHC1_CLK, - MX53_PAD_SD1_DATA0__ESDHC1_DAT0, - MX53_PAD_SD1_DATA1__ESDHC1_DAT1, - MX53_PAD_SD1_DATA2__ESDHC1_DAT2, - MX53_PAD_SD1_DATA3__ESDHC1_DAT3, - /* SD1_CD */ - MX53_PAD_EIM_DA13__GPIO3_13, - /* SD3 */ - MX53_PAD_PATA_DATA8__ESDHC3_DAT0, - MX53_PAD_PATA_DATA9__ESDHC3_DAT1, - MX53_PAD_PATA_DATA10__ESDHC3_DAT2, - MX53_PAD_PATA_DATA11__ESDHC3_DAT3, - MX53_PAD_PATA_DATA0__ESDHC3_DAT4, - MX53_PAD_PATA_DATA1__ESDHC3_DAT5, - MX53_PAD_PATA_DATA2__ESDHC3_DAT6, - MX53_PAD_PATA_DATA3__ESDHC3_DAT7, - MX53_PAD_PATA_IORDY__ESDHC3_CLK, - MX53_PAD_PATA_RESET_B__ESDHC3_CMD, - /* SD3_CD */ - MX53_PAD_EIM_DA11__GPIO3_11, - /* SD3_WP */ - MX53_PAD_EIM_DA12__GPIO3_12, - /* VGA */ - MX53_PAD_EIM_OE__IPU_DI1_PIN7, - MX53_PAD_EIM_RW__IPU_DI1_PIN8, - /* DISPLB */ - MX53_PAD_EIM_D20__IPU_SER_DISP0_CS, - MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK, - MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN, - MX53_PAD_EIM_D23__IPU_DI0_D0_CS, - /* DISP0_POWER_EN */ - MX53_PAD_EIM_D24__GPIO3_24, - /* DISP0 DET INT */ - MX53_PAD_EIM_D31__GPIO3_31, - /* LVDS */ - MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3, - MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK, - MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2, - MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1, - MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0, - MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3, - MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2, - MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK, - MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1, - MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0, - /* I2C1 */ - MX53_PAD_CSI0_DAT8__I2C1_SDA, - MX53_PAD_CSI0_DAT9__I2C1_SCL, - /* UART1 */ - MX53_PAD_CSI0_DAT10__UART1_TXD_MUX, - MX53_PAD_CSI0_DAT11__UART1_RXD_MUX, - /* CSI0 */ - MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12, - MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13, - MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14, - MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15, - MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16, - MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17, - MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18, - MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19, - MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC, - MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC, - MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK, - /* DISPLAY */ - MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK, - MX53_PAD_DI0_PIN15__IPU_DI0_PIN15, - MX53_PAD_DI0_PIN2__IPU_DI0_PIN2, - MX53_PAD_DI0_PIN3__IPU_DI0_PIN3, - MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0, - MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1, - MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2, - MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3, - MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4, - MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5, - MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6, - MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7, - MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8, - MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9, - MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10, - MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11, - MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12, - MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13, - MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14, - MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15, - MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16, - MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17, - MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18, - MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19, - MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20, - MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21, - MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22, - MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23, - /* Audio CLK*/ - MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK, - /* PWM */ - MX53_PAD_GPIO_1__PWM2_PWMO, - /* SPDIF */ - MX53_PAD_GPIO_7__SPDIF_PLOCK, - MX53_PAD_GPIO_17__SPDIF_OUT1, - /* GPIO */ - MX53_PAD_PATA_DA_1__GPIO7_7, /* LED */ - MX53_PAD_PATA_DA_2__GPIO7_8, - MX53_PAD_PATA_DATA5__GPIO2_5, - MX53_PAD_PATA_DATA6__GPIO2_6, - MX53_PAD_PATA_DATA14__GPIO2_14, - MX53_PAD_PATA_DATA15__GPIO2_15, - MX53_PAD_PATA_INTRQ__GPIO7_2, - MX53_PAD_EIM_WAIT__GPIO5_0, - MX53_PAD_NANDF_WP_B__GPIO6_9, - MX53_PAD_NANDF_RB0__GPIO6_10, - MX53_PAD_NANDF_CS1__GPIO6_14, - MX53_PAD_NANDF_CS2__GPIO6_15, - MX53_PAD_NANDF_CS3__GPIO6_16, - MX53_PAD_GPIO_5__GPIO1_5, - MX53_PAD_GPIO_16__GPIO7_11, - MX53_PAD_GPIO_8__GPIO1_8, -}; - -#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake) \ -{ \ - .gpio = gpio_num, \ - .type = EV_KEY, \ - .code = ev_code, \ - .active_low = act_low, \ - .desc = "btn " descr, \ - .wakeup = wake, \ -} - -static struct gpio_keys_button loco_buttons[] = { - GPIO_BUTTON(MX53_LOCO_POWER, KEY_POWER, 1, "power", 0), - GPIO_BUTTON(MX53_LOCO_UI1, KEY_VOLUMEUP, 1, "volume-up", 0), - GPIO_BUTTON(MX53_LOCO_UI2, KEY_VOLUMEDOWN, 1, "volume-down", 0), -}; - -static const struct gpio_keys_platform_data loco_button_data __initconst = { - .buttons = loco_buttons, - .nbuttons = ARRAY_SIZE(loco_buttons), -}; - -static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = { - .cd_gpio = LOCO_SD1_CD, - .cd_type = ESDHC_CD_GPIO, - .wp_type = ESDHC_WP_NONE, -}; - -static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = { - .cd_gpio = LOCO_SD3_CD, - .wp_gpio = LOCO_SD3_WP, - .cd_type = ESDHC_CD_GPIO, - .wp_type = ESDHC_WP_GPIO, -}; - -static inline void mx53_loco_fec_reset(void) -{ - int ret; - - /* reset FEC PHY */ - ret = gpio_request(LOCO_FEC_PHY_RST, "fec-phy-reset"); - if (ret) { - printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret); - return; - } - gpio_direction_output(LOCO_FEC_PHY_RST, 0); - msleep(1); - gpio_set_value(LOCO_FEC_PHY_RST, 1); -} - -static struct fec_platform_data mx53_loco_fec_data = { - .phy = PHY_INTERFACE_MODE_RMII, -}; - -static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = { - .bitrate = 100000, -}; - -static const struct gpio_led mx53loco_leds[] __initconst = { - { - .name = "green", - .default_trigger = "heartbeat", - .gpio = LOCO_LED, - }, -}; - -static const struct gpio_led_platform_data mx53loco_leds_data __initconst = { - .leds = mx53loco_leds, - .num_leds = ARRAY_SIZE(mx53loco_leds), -}; - -void __init imx53_qsb_common_init(void) -{ - mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads, - ARRAY_SIZE(mx53_loco_pads)); -} - -static struct i2c_board_info mx53loco_i2c_devices[] = { - { - I2C_BOARD_INFO("mma8450", 0x1C), - }, -}; - -static void __init mx53_loco_board_init(void) -{ - int ret; - imx53_soc_init(); - imx53_qsb_common_init(); - - imx53_add_imx_uart(0, NULL); - mx53_loco_fec_reset(); - imx53_add_fec(&mx53_loco_fec_data); - imx53_add_imx2_wdt(0, NULL); - - ret = gpio_request_one(LOCO_ACCEL_EN, GPIOF_OUT_INIT_HIGH, "accel_en"); - if (ret) - pr_err("Cannot request ACCEL_EN pin: %d\n", ret); - - i2c_register_board_info(0, mx53loco_i2c_devices, - ARRAY_SIZE(mx53loco_i2c_devices)); - imx53_add_imx_i2c(0, &mx53_loco_i2c_data); - imx53_add_imx_i2c(1, &mx53_loco_i2c_data); - imx53_add_sdhci_esdhc_imx(0, &mx53_loco_sd1_data); - imx53_add_sdhci_esdhc_imx(2, &mx53_loco_sd3_data); - imx_add_gpio_keys(&loco_button_data); - gpio_led_register_device(-1, &mx53loco_leds_data); - imx53_add_ahci_imx(); -} - -static void __init mx53_loco_timer_init(void) -{ - mx53_clocks_init(32768, 24000000, 0, 0); -} - -static struct sys_timer mx53_loco_timer = { - .init = mx53_loco_timer_init, -}; - -MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board") - .map_io = mx53_map_io, - .init_early = imx53_init_early, - .init_irq = mx53_init_irq, - .handle_irq = imx53_handle_irq, - .timer = &mx53_loco_timer, - .init_machine = mx53_loco_board_init, -MACHINE_END diff --git a/arch/arm/mach-mx5/board-mx53_smd.c b/arch/arm/mach-mx5/board-mx53_smd.c deleted file mode 100644 index d498573..0000000 --- a/arch/arm/mach-mx5/board-mx53_smd.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include "devices-imx53.h" - -#define SMD_FEC_PHY_RST IMX_GPIO_NR(7, 6) -#define MX53_SMD_SATA_PWR_EN IMX_GPIO_NR(3, 3) - -static iomux_v3_cfg_t mx53_smd_pads[] = { - MX53_PAD_CSI0_DAT10__UART1_TXD_MUX, - MX53_PAD_CSI0_DAT11__UART1_RXD_MUX, - - MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX, - MX53_PAD_PATA_DMARQ__UART2_TXD_MUX, - - MX53_PAD_PATA_CS_0__UART3_TXD_MUX, - MX53_PAD_PATA_CS_1__UART3_RXD_MUX, - MX53_PAD_PATA_DA_1__UART3_CTS, - MX53_PAD_PATA_DA_2__UART3_RTS, - /* I2C1 */ - MX53_PAD_CSI0_DAT8__I2C1_SDA, - MX53_PAD_CSI0_DAT9__I2C1_SCL, - /* SD1 */ - MX53_PAD_SD1_CMD__ESDHC1_CMD, - MX53_PAD_SD1_CLK__ESDHC1_CLK, - MX53_PAD_SD1_DATA0__ESDHC1_DAT0, - MX53_PAD_SD1_DATA1__ESDHC1_DAT1, - MX53_PAD_SD1_DATA2__ESDHC1_DAT2, - MX53_PAD_SD1_DATA3__ESDHC1_DAT3, - /* SD2 */ - MX53_PAD_SD2_CMD__ESDHC2_CMD, - MX53_PAD_SD2_CLK__ESDHC2_CLK, - MX53_PAD_SD2_DATA0__ESDHC2_DAT0, - MX53_PAD_SD2_DATA1__ESDHC2_DAT1, - MX53_PAD_SD2_DATA2__ESDHC2_DAT2, - MX53_PAD_SD2_DATA3__ESDHC2_DAT3, - /* SD3 */ - MX53_PAD_PATA_DATA8__ESDHC3_DAT0, - MX53_PAD_PATA_DATA9__ESDHC3_DAT1, - MX53_PAD_PATA_DATA10__ESDHC3_DAT2, - MX53_PAD_PATA_DATA11__ESDHC3_DAT3, - MX53_PAD_PATA_DATA0__ESDHC3_DAT4, - MX53_PAD_PATA_DATA1__ESDHC3_DAT5, - MX53_PAD_PATA_DATA2__ESDHC3_DAT6, - MX53_PAD_PATA_DATA3__ESDHC3_DAT7, - MX53_PAD_PATA_IORDY__ESDHC3_CLK, - MX53_PAD_PATA_RESET_B__ESDHC3_CMD, -}; - -static const struct imxuart_platform_data mx53_smd_uart_data __initconst = { - .flags = IMXUART_HAVE_RTSCTS, -}; - -static inline void mx53_smd_init_uart(void) -{ - imx53_add_imx_uart(0, NULL); - imx53_add_imx_uart(1, NULL); - imx53_add_imx_uart(2, &mx53_smd_uart_data); -} - -static inline void mx53_smd_fec_reset(void) -{ - int ret; - - /* reset FEC PHY */ - ret = gpio_request(SMD_FEC_PHY_RST, "fec-phy-reset"); - if (ret) { - printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret); - return; - } - gpio_direction_output(SMD_FEC_PHY_RST, 0); - msleep(1); - gpio_set_value(SMD_FEC_PHY_RST, 1); -} - -static struct fec_platform_data mx53_smd_fec_data = { - .phy = PHY_INTERFACE_MODE_RMII, -}; - -static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = { - .bitrate = 100000, -}; - -static inline void mx53_smd_ahci_pwr_on(void) -{ - int ret; - - /* Enable SATA PWR */ - ret = gpio_request_one(MX53_SMD_SATA_PWR_EN, - GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "ahci-sata-pwr"); - if (ret) { - pr_err("failed to enable SATA_PWR_EN: %d\n", ret); - return; - } -} - -void __init imx53_smd_common_init(void) -{ - mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads, - ARRAY_SIZE(mx53_smd_pads)); -} - -static void __init mx53_smd_board_init(void) -{ - imx53_soc_init(); - imx53_smd_common_init(); - - mx53_smd_init_uart(); - mx53_smd_fec_reset(); - imx53_add_fec(&mx53_smd_fec_data); - imx53_add_imx2_wdt(0, NULL); - imx53_add_imx_i2c(0, &mx53_smd_i2c_data); - imx53_add_sdhci_esdhc_imx(0, NULL); - imx53_add_sdhci_esdhc_imx(1, NULL); - imx53_add_sdhci_esdhc_imx(2, NULL); - mx53_smd_ahci_pwr_on(); - imx53_add_ahci_imx(); -} - -static void __init mx53_smd_timer_init(void) -{ - mx53_clocks_init(32768, 24000000, 22579200, 0); -} - -static struct sys_timer mx53_smd_timer = { - .init = mx53_smd_timer_init, -}; - -MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board") - .map_io = mx53_map_io, - .init_early = imx53_init_early, - .init_irq = mx53_init_irq, - .handle_irq = imx53_handle_irq, - .timer = &mx53_smd_timer, - .init_machine = mx53_smd_board_init, -MACHINE_END diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c deleted file mode 100644 index 2aacf41..0000000 --- a/arch/arm/mach-mx5/clock-mx51-mx53.c +++ /dev/null @@ -1,1673 +0,0 @@ -/* - * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright (C) 2009-2010 Amit Kucheria - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include "crm_regs.h" - -/* External clock values passed-in by the board code */ -static unsigned long external_high_reference, external_low_reference; -static unsigned long oscillator_reference, ckih2_reference; - -static struct clk osc_clk; -static struct clk pll1_main_clk; -static struct clk pll1_sw_clk; -static struct clk pll2_sw_clk; -static struct clk pll3_sw_clk; -static struct clk mx53_pll4_sw_clk; -static struct clk lp_apm_clk; -static struct clk periph_apm_clk; -static struct clk ahb_clk; -static struct clk ipg_clk; -static struct clk usboh3_clk; -static struct clk emi_fast_clk; -static struct clk ipu_clk; -static struct clk mipi_hsc1_clk; -static struct clk esdhc1_clk; -static struct clk esdhc2_clk; -static struct clk esdhc3_mx53_clk; - -#define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */ - -/* calculate best pre and post dividers to get the required divider */ -static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post, - u32 max_pre, u32 max_post) -{ - if (div >= max_pre * max_post) { - *pre = max_pre; - *post = max_post; - } else if (div >= max_pre) { - u32 min_pre, temp_pre, old_err, err; - min_pre = DIV_ROUND_UP(div, max_post); - old_err = max_pre; - for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) { - err = div % temp_pre; - if (err == 0) { - *pre = temp_pre; - break; - } - err = temp_pre - err; - if (err < old_err) { - old_err = err; - *pre = temp_pre; - } - } - *post = DIV_ROUND_UP(div, *pre); - } else { - *pre = div; - *post = 1; - } -} - -static void _clk_ccgr_setclk(struct clk *clk, unsigned mode) -{ - u32 reg = __raw_readl(clk->enable_reg); - - reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift); - reg |= mode << clk->enable_shift; - - __raw_writel(reg, clk->enable_reg); -} - -static int _clk_ccgr_enable(struct clk *clk) -{ - _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON); - return 0; -} - -static void _clk_ccgr_disable(struct clk *clk) -{ - _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF); -} - -static int _clk_ccgr_enable_inrun(struct clk *clk) -{ - _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE); - return 0; -} - -static void _clk_ccgr_disable_inwait(struct clk *clk) -{ - _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE); -} - -/* - * For the 4-to-1 muxed input clock - */ -static inline u32 _get_mux(struct clk *parent, struct clk *m0, - struct clk *m1, struct clk *m2, struct clk *m3) -{ - if (parent == m0) - return 0; - else if (parent == m1) - return 1; - else if (parent == m2) - return 2; - else if (parent == m3) - return 3; - else - BUG(); - - return -EINVAL; -} - -static inline void __iomem *_mx51_get_pll_base(struct clk *pll) -{ - if (pll == &pll1_main_clk) - return MX51_DPLL1_BASE; - else if (pll == &pll2_sw_clk) - return MX51_DPLL2_BASE; - else if (pll == &pll3_sw_clk) - return MX51_DPLL3_BASE; - else - BUG(); - - return NULL; -} - -static inline void __iomem *_mx53_get_pll_base(struct clk *pll) -{ - if (pll == &pll1_main_clk) - return MX53_DPLL1_BASE; - else if (pll == &pll2_sw_clk) - return MX53_DPLL2_BASE; - else if (pll == &pll3_sw_clk) - return MX53_DPLL3_BASE; - else if (pll == &mx53_pll4_sw_clk) - return MX53_DPLL4_BASE; - else - BUG(); - - return NULL; -} - -static inline void __iomem *_get_pll_base(struct clk *pll) -{ - if (cpu_is_mx51()) - return _mx51_get_pll_base(pll); - else - return _mx53_get_pll_base(pll); -} - -static unsigned long clk_pll_get_rate(struct clk *clk) -{ - long mfi, mfn, mfd, pdf, ref_clk, mfn_abs; - unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl; - void __iomem *pllbase; - s64 temp; - unsigned long parent_rate; - - parent_rate = clk_get_rate(clk->parent); - - pllbase = _get_pll_base(clk); - - dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); - pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM; - dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN; - - if (pll_hfsm == 0) { - dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP); - dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD); - dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN); - } else { - dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP); - dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD); - dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN); - } - pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK; - mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET; - mfi = (mfi <= 5) ? 5 : mfi; - mfd = dp_mfd & MXC_PLL_DP_MFD_MASK; - mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK; - /* Sign extend to 32-bits */ - if (mfn >= 0x04000000) { - mfn |= 0xFC000000; - mfn_abs = -mfn; - } - - ref_clk = 2 * parent_rate; - if (dbl != 0) - ref_clk *= 2; - - ref_clk /= (pdf + 1); - temp = (u64) ref_clk * mfn_abs; - do_div(temp, mfd + 1); - if (mfn < 0) - temp = -temp; - temp = (ref_clk * mfi) + temp; - - return temp; -} - -static int _clk_pll_set_rate(struct clk *clk, unsigned long rate) -{ - u32 reg; - void __iomem *pllbase; - - long mfi, pdf, mfn, mfd = 999999; - s64 temp64; - unsigned long quad_parent_rate; - unsigned long pll_hfsm, dp_ctl; - unsigned long parent_rate; - - parent_rate = clk_get_rate(clk->parent); - - pllbase = _get_pll_base(clk); - - quad_parent_rate = 4 * parent_rate; - pdf = mfi = -1; - while (++pdf < 16 && mfi < 5) - mfi = rate * (pdf+1) / quad_parent_rate; - if (mfi > 15) - return -EINVAL; - pdf--; - - temp64 = rate * (pdf+1) - quad_parent_rate * mfi; - do_div(temp64, quad_parent_rate/1000000); - mfn = (long)temp64; - - dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); - /* use dpdck0_2 */ - __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL); - pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM; - if (pll_hfsm == 0) { - reg = mfi << 4 | pdf; - __raw_writel(reg, pllbase + MXC_PLL_DP_OP); - __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD); - __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN); - } else { - reg = mfi << 4 | pdf; - __raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP); - __raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD); - __raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN); - } - - return 0; -} - -static int _clk_pll_enable(struct clk *clk) -{ - u32 reg; - void __iomem *pllbase; - int i = 0; - - pllbase = _get_pll_base(clk); - reg = __raw_readl(pllbase + MXC_PLL_DP_CTL); - if (reg & MXC_PLL_DP_CTL_UPEN) - return 0; - - reg |= MXC_PLL_DP_CTL_UPEN; - __raw_writel(reg, pllbase + MXC_PLL_DP_CTL); - - /* Wait for lock */ - do { - reg = __raw_readl(pllbase + MXC_PLL_DP_CTL); - if (reg & MXC_PLL_DP_CTL_LRF) - break; - - udelay(1); - } while (++i < MAX_DPLL_WAIT_TRIES); - - if (i == MAX_DPLL_WAIT_TRIES) { - pr_err("MX5: pll locking failed\n"); - return -EINVAL; - } - - return 0; -} - -static void _clk_pll_disable(struct clk *clk) -{ - u32 reg; - void __iomem *pllbase; - - pllbase = _get_pll_base(clk); - reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN; - __raw_writel(reg, pllbase + MXC_PLL_DP_CTL); -} - -static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent) -{ - u32 reg, step; - - reg = __raw_readl(MXC_CCM_CCSR); - - /* When switching from pll_main_clk to a bypass clock, first select a - * multiplexed clock in 'step_sel', then shift the glitchless mux - * 'pll1_sw_clk_sel'. - * - * When switching back, do it in reverse order - */ - if (parent == &pll1_main_clk) { - /* Switch to pll1_main_clk */ - reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL; - __raw_writel(reg, MXC_CCM_CCSR); - /* step_clk mux switched to lp_apm, to save power. */ - reg = __raw_readl(MXC_CCM_CCSR); - reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK; - reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM << - MXC_CCM_CCSR_STEP_SEL_OFFSET); - } else { - if (parent == &lp_apm_clk) { - step = MXC_CCM_CCSR_STEP_SEL_LP_APM; - } else if (parent == &pll2_sw_clk) { - step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED; - } else if (parent == &pll3_sw_clk) { - step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED; - } else - return -EINVAL; - - reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK; - reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET); - - __raw_writel(reg, MXC_CCM_CCSR); - /* Switch to step_clk */ - reg = __raw_readl(MXC_CCM_CCSR); - reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL; - } - __raw_writel(reg, MXC_CCM_CCSR); - return 0; -} - -static unsigned long clk_pll1_sw_get_rate(struct clk *clk) -{ - u32 reg, div; - unsigned long parent_rate; - - parent_rate = clk_get_rate(clk->parent); - - reg = __raw_readl(MXC_CCM_CCSR); - - if (clk->parent == &pll2_sw_clk) { - div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >> - MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1; - } else if (clk->parent == &pll3_sw_clk) { - div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >> - MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1; - } else - div = 1; - return parent_rate / div; -} - -static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent) -{ - u32 reg; - - reg = __raw_readl(MXC_CCM_CCSR); - - if (parent == &pll2_sw_clk) - reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL; - else - reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL; - - __raw_writel(reg, MXC_CCM_CCSR); - return 0; -} - -static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent) -{ - u32 reg; - - if (parent == &osc_clk) - reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL; - else - return -EINVAL; - - __raw_writel(reg, MXC_CCM_CCSR); - - return 0; -} - -static unsigned long clk_cpu_get_rate(struct clk *clk) -{ - u32 cacrr, div; - unsigned long parent_rate; - - parent_rate = clk_get_rate(clk->parent); - cacrr = __raw_readl(MXC_CCM_CACRR); - div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1; - - return parent_rate / div; -} - -static int clk_cpu_set_rate(struct clk *clk, unsigned long rate) -{ - u32 reg, cpu_podf; - unsigned long parent_rate; - - parent_rate = clk_get_rate(clk->parent); - cpu_podf = parent_rate / rate - 1; - /* use post divider to change freq */ - reg = __raw_readl(MXC_CCM_CACRR); - reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK; - reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET; - __raw_writel(reg, MXC_CCM_CACRR); - - return 0; -} - -static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent) -{ - u32 reg, mux; - int i = 0; - - mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL); - - reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK; - reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET; - __raw_writel(reg, MXC_CCM_CBCMR); - - /* Wait for lock */ - do { - reg = __raw_readl(MXC_CCM_CDHIPR); - if (!(reg & MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY)) - break; - - udelay(1); - } while (++i < MAX_DPLL_WAIT_TRIES); - - if (i == MAX_DPLL_WAIT_TRIES) { - pr_err("MX5: Set parent for periph_apm clock failed\n"); - return -EINVAL; - } - - return 0; -} - -static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent) -{ - u32 reg; - - reg = __raw_readl(MXC_CCM_CBCDR); - - if (parent == &pll2_sw_clk) - reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL; - else if (parent == &periph_apm_clk) - reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL; - else - return -EINVAL; - - __raw_writel(reg, MXC_CCM_CBCDR); - - return 0; -} - -static struct clk main_bus_clk = { - .parent = &pll2_sw_clk, - .set_parent = _clk_main_bus_set_parent, -}; - -static unsigned long clk_ahb_get_rate(struct clk *clk) -{ - u32 reg, div; - unsigned long parent_rate; - - parent_rate = clk_get_rate(clk->parent); - - reg = __raw_readl(MXC_CCM_CBCDR); - div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >> - MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1; - return parent_rate / div; -} - - -static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate) -{ - u32 reg, div; - unsigned long parent_rate; - int i = 0; - - parent_rate = clk_get_rate(clk->parent); - - div = parent_rate / rate; - if (div > 8 || div < 1 || ((parent_rate / div) != rate)) - return -EINVAL; - - reg = __raw_readl(MXC_CCM_CBCDR); - reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK; - reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET; - __raw_writel(reg, MXC_CCM_CBCDR); - - /* Wait for lock */ - do { - reg = __raw_readl(MXC_CCM_CDHIPR); - if (!(reg & MXC_CCM_CDHIPR_AHB_PODF_BUSY)) - break; - - udelay(1); - } while (++i < MAX_DPLL_WAIT_TRIES); - - if (i == MAX_DPLL_WAIT_TRIES) { - pr_err("MX5: clk_ahb_set_rate failed\n"); - return -EINVAL; - } - - return 0; -} - -static unsigned long _clk_ahb_round_rate(struct clk *clk, - unsigned long rate) -{ - u32 div; - unsigned long parent_rate; - - parent_rate = clk_get_rate(clk->parent); - - div = parent_rate / rate; - if (div > 8) - div = 8; - else if (div == 0) - div++; - return parent_rate / div; -} - - -static int _clk_max_enable(struct clk *clk) -{ - u32 reg; - - _clk_ccgr_enable(clk); - - /* Handshake with MAX when LPM is entered. */ - reg = __raw_readl(MXC_CCM_CLPCR); - if (cpu_is_mx51()) - reg &= ~MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS; - else if (cpu_is_mx53()) - reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS; - __raw_writel(reg, MXC_CCM_CLPCR); - - return 0; -} - -static void _clk_max_disable(struct clk *clk) -{ - u32 reg; - - _clk_ccgr_disable_inwait(clk); - - /* No Handshake with MAX when LPM is entered as its disabled. */ - reg = __raw_readl(MXC_CCM_CLPCR); - if (cpu_is_mx51()) - reg |= MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS; - else if (cpu_is_mx53()) - reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS; - __raw_writel(reg, MXC_CCM_CLPCR); -} - -static unsigned long clk_ipg_get_rate(struct clk *clk) -{ - u32 reg, div; - unsigned long parent_rate; - - parent_rate = clk_get_rate(clk->parent); - - reg = __raw_readl(MXC_CCM_CBCDR); - div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >> - MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1; - - return parent_rate / div; -} - -static unsigned long clk_ipg_per_get_rate(struct clk *clk) -{ - u32 reg, prediv1, prediv2, podf; - unsigned long parent_rate; - - parent_rate = clk_get_rate(clk->parent); - - if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) { - /* the main_bus_clk is the one before the DVFS engine */ - reg = __raw_readl(MXC_CCM_CBCDR); - prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >> - MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1; - prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >> - MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1; - podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >> - MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1; - return parent_rate / (prediv1 * prediv2 * podf); - } else if (clk->parent == &ipg_clk) - return parent_rate; - else - BUG(); -} - -static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent) -{ - u32 reg; - - reg = __raw_readl(MXC_CCM_CBCMR); - - reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL; - reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL; - - if (parent == &ipg_clk) - reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL; - else if (parent == &lp_apm_clk) - reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL; - else if (parent != &main_bus_clk) - return -EINVAL; - - __raw_writel(reg, MXC_CCM_CBCMR); - - return 0; -} - -#define clk_nfc_set_parent NULL - -static unsigned long clk_nfc_get_rate(struct clk *clk) -{ - unsigned long rate; - u32 reg, div; - - reg = __raw_readl(MXC_CCM_CBCDR); - div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >> - MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1; - rate = clk_get_rate(clk->parent) / div; - WARN_ON(rate == 0); - return rate; -} - -static unsigned long clk_nfc_round_rate(struct clk *clk, - unsigned long rate) -{ - u32 div; - unsigned long parent_rate = clk_get_rate(clk->parent); - - if (!rate) - return -EINVAL; - - div = parent_rate / rate; - - if (parent_rate % rate) - div++; - - if (div > 8) - return -EINVAL; - - return parent_rate / div; - -} - -static int clk_nfc_set_rate(struct clk *clk, unsigned long rate) -{ - u32 reg, div; - - div = clk_get_rate(clk->parent) / rate; - if (div == 0) - div++; - if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8)) - return -EINVAL; - - reg = __raw_readl(MXC_CCM_CBCDR); - reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK; - reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET; - __raw_writel(reg, MXC_CCM_CBCDR); - - while (__raw_readl(MXC_CCM_CDHIPR) & - MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){ - } - - return 0; -} - -static unsigned long get_high_reference_clock_rate(struct clk *clk) -{ - return external_high_reference; -} - -static unsigned long get_low_reference_clock_rate(struct clk *clk) -{ - return external_low_reference; -} - -static unsigned long get_oscillator_reference_clock_rate(struct clk *clk) -{ - return oscillator_reference; -} - -static unsigned long get_ckih2_reference_clock_rate(struct clk *clk) -{ - return ckih2_reference; -} - -static unsigned long clk_emi_slow_get_rate(struct clk *clk) -{ - u32 reg, div; - - reg = __raw_readl(MXC_CCM_CBCDR); - div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >> - MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1; - - return clk_get_rate(clk->parent) / div; -} - -static unsigned long _clk_ddr_hf_get_rate(struct clk *clk) -{ - unsigned long rate; - u32 reg, div; - - reg = __raw_readl(MXC_CCM_CBCDR); - div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >> - MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1; - rate = clk_get_rate(clk->parent) / div; - - return rate; -} - -/* External high frequency clock */ -static struct clk ckih_clk = { - .get_rate = get_high_reference_clock_rate, -}; - -static struct clk ckih2_clk = { - .get_rate = get_ckih2_reference_clock_rate, -}; - -static struct clk osc_clk = { - .get_rate = get_oscillator_reference_clock_rate, -}; - -/* External low frequency (32kHz) clock */ -static struct clk ckil_clk = { - .get_rate = get_low_reference_clock_rate, -}; - -static struct clk pll1_main_clk = { - .parent = &osc_clk, - .get_rate = clk_pll_get_rate, - .enable = _clk_pll_enable, - .disable = _clk_pll_disable, -}; - -/* Clock tree block diagram (WIP): - * CCM: Clock Controller Module - * - * PLL output -> | - * | CCM Switcher -> CCM_CLK_ROOT_GEN -> - * PLL bypass -> | - * - */ - -/* PLL1 SW supplies to ARM core */ -static struct clk pll1_sw_clk = { - .parent = &pll1_main_clk, - .set_parent = _clk_pll1_sw_set_parent, - .get_rate = clk_pll1_sw_get_rate, -}; - -/* PLL2 SW supplies to AXI/AHB/IP buses */ -static struct clk pll2_sw_clk = { - .parent = &osc_clk, - .get_rate = clk_pll_get_rate, - .set_rate = _clk_pll_set_rate, - .set_parent = _clk_pll2_sw_set_parent, - .enable = _clk_pll_enable, - .disable = _clk_pll_disable, -}; - -/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */ -static struct clk pll3_sw_clk = { - .parent = &osc_clk, - .set_rate = _clk_pll_set_rate, - .get_rate = clk_pll_get_rate, - .enable = _clk_pll_enable, - .disable = _clk_pll_disable, -}; - -/* PLL4 SW supplies to LVDS Display Bridge(LDB) */ -static struct clk mx53_pll4_sw_clk = { - .parent = &osc_clk, - .set_rate = _clk_pll_set_rate, - .enable = _clk_pll_enable, - .disable = _clk_pll_disable, -}; - -/* Low-power Audio Playback Mode clock */ -static struct clk lp_apm_clk = { - .parent = &osc_clk, - .set_parent = _clk_lp_apm_set_parent, -}; - -static struct clk periph_apm_clk = { - .parent = &pll1_sw_clk, - .set_parent = _clk_periph_apm_set_parent, -}; - -static struct clk cpu_clk = { - .parent = &pll1_sw_clk, - .get_rate = clk_cpu_get_rate, - .set_rate = clk_cpu_set_rate, -}; - -static struct clk ahb_clk = { - .parent = &main_bus_clk, - .get_rate = clk_ahb_get_rate, - .set_rate = _clk_ahb_set_rate, - .round_rate = _clk_ahb_round_rate, -}; - -static struct clk iim_clk = { - .parent = &ipg_clk, - .enable_reg = MXC_CCM_CCGR0, - .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET, -}; - -/* Main IP interface clock for access to registers */ -static struct clk ipg_clk = { - .parent = &ahb_clk, - .get_rate = clk_ipg_get_rate, -}; - -static struct clk ipg_perclk = { - .parent = &lp_apm_clk, - .get_rate = clk_ipg_per_get_rate, - .set_parent = _clk_ipg_per_set_parent, -}; - -static struct clk ahb_max_clk = { - .parent = &ahb_clk, - .enable_reg = MXC_CCM_CCGR0, - .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET, - .enable = _clk_max_enable, - .disable = _clk_max_disable, -}; - -static struct clk aips_tz1_clk = { - .parent = &ahb_clk, - .secondary = &ahb_max_clk, - .enable_reg = MXC_CCM_CCGR0, - .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET, - .enable = _clk_ccgr_enable, - .disable = _clk_ccgr_disable_inwait, -}; - -static struct clk aips_tz2_clk = { - .parent = &ahb_clk, - .secondary = &ahb_max_clk, - .enable_reg = MXC_CCM_CCGR0, - .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET, - .enable = _clk_ccgr_enable, - .disable = _clk_ccgr_disable_inwait, -}; - -static struct clk gpc_dvfs_clk = { - .enable_reg = MXC_CCM_CCGR5, - .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET, - .enable = _clk_ccgr_enable, - .disable = _clk_ccgr_disable, -}; - -static struct clk gpt_32k_clk = { - .id = 0, - .parent = &ckil_clk, -}; - -static struct clk dummy_clk = { - .id = 0, -}; - -static struct clk emi_slow_clk = { - .parent = &pll2_sw_clk, - .enable_reg = MXC_CCM_CCGR5, - .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET, - .enable = _clk_ccgr_enable, - .disable = _clk_ccgr_disable_inwait, - .get_rate = clk_emi_slow_get_rate, -}; - -static int clk_ipu_enable(struct clk *clk) -{ - u32 reg; - - _clk_ccgr_enable(clk); - - /* Enable handshake with IPU when certain clock rates are changed */ - reg = __raw_readl(MXC_CCM_CCDR); - reg &= ~MXC_CCM_CCDR_IPU_HS_MASK; - __raw_writel(reg, MXC_CCM_CCDR); - - /* Enable handshake with IPU when LPM is entered */ - reg = __raw_readl(MXC_CCM_CLPCR); - reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS; - __raw_writel(reg, MXC_CCM_CLPCR); - - return 0; -} - -static void clk_ipu_disable(struct clk *clk) -{ - u32 reg; - - _clk_ccgr_disable(clk); - - /* Disable handshake with IPU whe dividers are changed */ - reg = __raw_readl(MXC_CCM_CCDR); - reg |= MXC_CCM_CCDR_IPU_HS_MASK; - __raw_writel(reg, MXC_CCM_CCDR); - - /* Disable handshake with IPU when LPM is entered */ - reg = __raw_readl(MXC_CCM_CLPCR); - reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS; - __raw_writel(reg, MXC_CCM_CLPCR); -} - -static struct clk ahbmux1_clk = { - .parent = &ahb_clk, - .secondary = &ahb_max_clk, - .enable_reg = MXC_CCM_CCGR0, - .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET, - .enable = _clk_ccgr_enable, - .disable = _clk_ccgr_disable_inwait, -}; - -static struct clk ipu_sec_clk = { - .parent = &emi_fast_clk, - .secondary = &ahbmux1_clk, -}; - -static struct clk ddr_hf_clk = { - .parent = &pll1_sw_clk, - .get_rate = _clk_ddr_hf_get_rate, -}; - -static struct clk ddr_clk = { - .parent = &ddr_hf_clk, -}; - -/* clock definitions for MIPI HSC unit which has been removed - * from documentation, but not from hardware - */ -static int _clk_hsc_enable(struct clk *clk) -{ - u32 reg; - - _clk_ccgr_enable(clk); - /* Handshake with IPU when certain clock rates are changed. */ - reg = __raw_readl(MXC_CCM_CCDR); - reg &= ~MXC_CCM_CCDR_HSC_HS_MASK; - __raw_writel(reg, MXC_CCM_CCDR); - - reg = __raw_readl(MXC_CCM_CLPCR); - reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS; - __raw_writel(reg, MXC_CCM_CLPCR); - - return 0; -} - -static void _clk_hsc_disable(struct clk *clk) -{ - u32 reg; - - _clk_ccgr_disable(clk); - /* No handshake with HSC as its not enabled. */ - reg = __raw_readl(MXC_CCM_CCDR); - reg |= MXC_CCM_CCDR_HSC_HS_MASK; - __raw_writel(reg, MXC_CCM_CCDR); - - reg = __raw_readl(MXC_CCM_CLPCR); - reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS; - __raw_writel(reg, MXC_CCM_CLPCR); -} - -static struct clk mipi_hsp_clk = { - .parent = &ipu_clk, - .enable_reg = MXC_CCM_CCGR4, - .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET, - .enable = _clk_hsc_enable, - .disable = _clk_hsc_disable, - .secondary = &mipi_hsc1_clk, -}; - -#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s) \ - static struct clk name = { \ - .id = i, \ - .enable_reg = er, \ - .enable_shift = es, \ - .get_rate = pfx##_get_rate, \ - .set_rate = pfx##_set_rate, \ - .round_rate = pfx##_round_rate, \ - .set_parent = pfx##_set_parent, \ - .enable = _clk_ccgr_enable, \ - .disable = _clk_ccgr_disable, \ - .parent = p, \ - .secondary = s, \ - } - -#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s) \ - static struct clk name = { \ - .id = i, \ - .enable_reg = er, \ - .enable_shift = es, \ - .get_rate = pfx##_get_rate, \ - .set_rate = pfx##_set_rate, \ - .set_parent = pfx##_set_parent, \ - .enable = _clk_max_enable, \ - .disable = _clk_max_disable, \ - .parent = p, \ - .secondary = s, \ - } - -#define CLK_GET_RATE(name, nr, bitsname) \ -static unsigned long clk_##name##_get_rate(struct clk *clk) \ -{ \ - u32 reg, pred, podf; \ - \ - reg = __raw_readl(MXC_CCM_CSCDR##nr); \ - pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK) \ - >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \ - podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK) \ - >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \ - \ - return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), \ - (pred + 1) * (podf + 1)); \ -} - -#define CLK_SET_PARENT(name, nr, bitsname) \ -static int clk_##name##_set_parent(struct clk *clk, struct clk *parent) \ -{ \ - u32 reg, mux; \ - \ - mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, \ - &pll3_sw_clk, &lp_apm_clk); \ - reg = __raw_readl(MXC_CCM_CSCMR##nr) & \ - ~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK; \ - reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET; \ - __raw_writel(reg, MXC_CCM_CSCMR##nr); \ - \ - return 0; \ -} - -#define CLK_SET_RATE(name, nr, bitsname) \ -static int clk_##name##_set_rate(struct clk *clk, unsigned long rate) \ -{ \ - u32 reg, div, parent_rate; \ - u32 pre = 0, post = 0; \ - \ - parent_rate = clk_get_rate(clk->parent); \ - div = parent_rate / rate; \ - \ - if ((parent_rate / div) != rate) \ - return -EINVAL; \ - \ - __calc_pre_post_dividers(div, &pre, &post, \ - (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >> \ - MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1, \ - (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >> \ - MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\ - \ - /* Set sdhc1 clock divider */ \ - reg = __raw_readl(MXC_CCM_CSCDR##nr) & \ - ~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK \ - | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK); \ - reg |= (post - 1) << \ - MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \ - reg |= (pre - 1) << \ - MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \ - __raw_writel(reg, MXC_CCM_CSCDR##nr); \ - \ - return 0; \ -} - -/* UART */ -CLK_GET_RATE(uart, 1, UART) -CLK_SET_PARENT(uart, 1, UART) - -static struct clk uart_root_clk = { - .parent = &pll2_sw_clk, - .get_rate = clk_uart_get_rate, - .set_parent = clk_uart_set_parent, -}; - -/* USBOH3 */ -CLK_GET_RATE(usboh3, 1, USBOH3) -CLK_SET_PARENT(usboh3, 1, USBOH3) - -static struct clk usboh3_clk = { - .parent = &pll2_sw_clk, - .get_rate = clk_usboh3_get_rate, - .set_parent = clk_usboh3_set_parent, - .enable = _clk_ccgr_enable, - .disable = _clk_ccgr_disable, - .enable_reg = MXC_CCM_CCGR2, - .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET, -}; - -static struct clk usb_ahb_clk = { - .parent = &ipg_clk, - .enable = _clk_ccgr_enable, - .disable = _clk_ccgr_disable, - .enable_reg = MXC_CCM_CCGR2, - .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET, -}; - -static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent) -{ - u32 reg; - - reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL; - - if (parent == &pll3_sw_clk) - reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET; - - __raw_writel(reg, MXC_CCM_CSCMR1); - - return 0; -} - -static struct clk usb_phy1_clk = { - .parent = &pll3_sw_clk, - .set_parent = clk_usb_phy1_set_parent, - .enable = _clk_ccgr_enable, - .enable_reg = MXC_CCM_CCGR2, - .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET, - .disable = _clk_ccgr_disable, -}; - -/* eCSPI */ -CLK_GET_RATE(ecspi, 2, CSPI) -CLK_SET_PARENT(ecspi, 1, CSPI) - -static struct clk ecspi_main_clk = { - .parent = &pll3_sw_clk, - .get_rate = clk_ecspi_get_rate, - .set_parent = clk_ecspi_set_parent, -}; - -/* eSDHC */ -CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1) -CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1) -CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1) - -/* mx51 specific */ -CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2) -CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2) -CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2) - -static int clk_esdhc3_set_parent(struct clk *clk, struct clk *parent) -{ - u32 reg; - - reg = __raw_readl(MXC_CCM_CSCMR1); - if (parent == &esdhc1_clk) - reg &= ~MXC_CCM_CSCMR1_ESDHC3_CLK_SEL; - else if (parent == &esdhc2_clk) - reg |= MXC_CCM_CSCMR1_ESDHC3_CLK_SEL; - else - return -EINVAL; - __raw_writel(reg, MXC_CCM_CSCMR1); - - return 0; -} - -static int clk_esdhc4_set_parent(struct clk *clk, struct clk *parent) -{ - u32 reg; - - reg = __raw_readl(MXC_CCM_CSCMR1); - if (parent == &esdhc1_clk) - reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL; - else if (parent == &esdhc2_clk) - reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL; - else - return -EINVAL; - __raw_writel(reg, MXC_CCM_CSCMR1); - - return 0; -} - -/* mx53 specific */ -static int clk_esdhc2_mx53_set_parent(struct clk *clk, struct clk *parent) -{ - u32 reg; - - reg = __raw_readl(MXC_CCM_CSCMR1); - if (parent == &esdhc1_clk) - reg &= ~MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL; - else if (parent == &esdhc3_mx53_clk) - reg |= MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL; - else - return -EINVAL; - __raw_writel(reg, MXC_CCM_CSCMR1); - - return 0; -} - -CLK_GET_RATE(esdhc3_mx53, 1, ESDHC3_MX53) -CLK_SET_PARENT(esdhc3_mx53, 1, ESDHC3_MX53) -CLK_SET_RATE(esdhc3_mx53, 1, ESDHC3_MX53) - -static int clk_esdhc4_mx53_set_parent(struct clk *clk, struct clk *parent) -{ - u32 reg; - - reg = __raw_readl(MXC_CCM_CSCMR1); - if (parent == &esdhc1_clk) - reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL; - else if (parent == &esdhc3_mx53_clk) - reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL; - else - return -EINVAL; - __raw_writel(reg, MXC_CCM_CSCMR1); - - return 0; -} - -#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \ - static struct clk name = { \ - .id = i, \ - .enable_reg = er, \ - .enable_shift = es, \ - .get_rate = gr, \ - .set_rate = sr, \ - .enable = e, \ - .disable = d, \ - .parent = p, \ - .secondary = s, \ - } - -#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s) \ - DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s) - -/* Shared peripheral bus arbiter */ -DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET, - NULL, NULL, &ipg_clk, NULL); - -/* UART */ -DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET, - NULL, NULL, &ipg_clk, &aips_tz1_clk); -DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET, - NULL, NULL, &ipg_clk, &aips_tz1_clk); -DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET, - NULL, NULL, &ipg_clk, &spba_clk); -DEFINE_CLOCK(uart4_ipg_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG4_OFFSET, - NULL, NULL, &ipg_clk, &spba_clk); -DEFINE_CLOCK(uart5_ipg_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG6_OFFSET, - NULL, NULL, &ipg_clk, &spba_clk); -DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET, - NULL, NULL, &uart_root_clk, &uart1_ipg_clk); -DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET, - NULL, NULL, &uart_root_clk, &uart2_ipg_clk); -DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET, - NULL, NULL, &uart_root_clk, &uart3_ipg_clk); -DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG5_OFFSET, - NULL, NULL, &uart_root_clk, &uart4_ipg_clk); -DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG7_OFFSET, - NULL, NULL, &uart_root_clk, &uart5_ipg_clk); - -/* GPT */ -DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET, - NULL, NULL, &ipg_clk, NULL); -DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET, - NULL, NULL, &ipg_clk, &gpt_ipg_clk); - -DEFINE_CLOCK(pwm1_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG6_OFFSET, - NULL, NULL, &ipg_clk, NULL); -DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET, - NULL, NULL, &ipg_clk, NULL); - -/* I2C */ -DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET, - NULL, NULL, &ipg_perclk, NULL); -DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET, - NULL, NULL, &ipg_perclk, NULL); -DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET, - NULL, NULL, &ipg_clk, NULL); -DEFINE_CLOCK(i2c3_mx53_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET, - NULL, NULL, &ipg_perclk, NULL); - -/* FEC */ -DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET, - NULL, NULL, &ipg_clk, NULL); - -/* NFC */ -DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET, - clk_nfc, &emi_slow_clk, NULL); - -/* SSI */ -DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET, - NULL, NULL, &ipg_clk, NULL); -DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET, - NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk); -DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET, - NULL, NULL, &ipg_clk, NULL); -DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET, - NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk); -DEFINE_CLOCK(ssi3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG12_OFFSET, - NULL, NULL, &ipg_clk, NULL); -DEFINE_CLOCK(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET, - NULL, NULL, &pll3_sw_clk, &ssi3_ipg_clk); - -/* eCSPI */ -DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET, - NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable, - &ipg_clk, &spba_clk); -DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET, - NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk); -DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET, - NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable, - &ipg_clk, &aips_tz2_clk); -DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET, - NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk); - -/* CSPI */ -DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET, - NULL, NULL, &ipg_clk, &aips_tz2_clk); -DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET, - NULL, NULL, &ipg_clk, &cspi_ipg_clk); - -/* SDMA */ -DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET, - NULL, NULL, &ahb_clk, NULL); - -/* eSDHC */ -DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET, - NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL); -DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET, - clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk); -DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET, - NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL); -DEFINE_CLOCK_FULL(esdhc3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG4_OFFSET, - NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL); -DEFINE_CLOCK_FULL(esdhc4_ipg_clk, 3, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG6_OFFSET, - NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL); - -/* mx51 specific */ -DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET, - clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk); - -static struct clk esdhc3_clk = { - .id = 2, - .parent = &esdhc1_clk, - .set_parent = clk_esdhc3_set_parent, - .enable_reg = MXC_CCM_CCGR3, - .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET, - .enable = _clk_max_enable, - .disable = _clk_max_disable, - .secondary = &esdhc3_ipg_clk, -}; -static struct clk esdhc4_clk = { - .id = 3, - .parent = &esdhc1_clk, - .set_parent = clk_esdhc4_set_parent, - .enable_reg = MXC_CCM_CCGR3, - .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET, - .enable = _clk_max_enable, - .disable = _clk_max_disable, - .secondary = &esdhc4_ipg_clk, -}; - -/* mx53 specific */ -static struct clk esdhc2_mx53_clk = { - .id = 2, - .parent = &esdhc1_clk, - .set_parent = clk_esdhc2_mx53_set_parent, - .enable_reg = MXC_CCM_CCGR3, - .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET, - .enable = _clk_max_enable, - .disable = _clk_max_disable, - .secondary = &esdhc3_ipg_clk, -}; - -DEFINE_CLOCK_MAX(esdhc3_mx53_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG5_OFFSET, - clk_esdhc3_mx53, &pll2_sw_clk, &esdhc2_ipg_clk); - -static struct clk esdhc4_mx53_clk = { - .id = 3, - .parent = &esdhc1_clk, - .set_parent = clk_esdhc4_mx53_set_parent, - .enable_reg = MXC_CCM_CCGR3, - .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET, - .enable = _clk_max_enable, - .disable = _clk_max_disable, - .secondary = &esdhc4_ipg_clk, -}; - -static struct clk sata_clk = { - .parent = &ipg_clk, - .enable = _clk_max_enable, - .enable_reg = MXC_CCM_CCGR4, - .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET, - .disable = _clk_max_disable, -}; - -static struct clk ahci_phy_clk = { - .parent = &usb_phy1_clk, -}; - -static struct clk ahci_dma_clk = { - .parent = &ahb_clk, -}; - -DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk); -DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk); -DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk); - -/* IPU */ -DEFINE_CLOCK_FULL(ipu_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG5_OFFSET, - NULL, NULL, clk_ipu_enable, clk_ipu_disable, &ahb_clk, &ipu_sec_clk); - -DEFINE_CLOCK_FULL(emi_fast_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG7_OFFSET, - NULL, NULL, _clk_ccgr_enable, _clk_ccgr_disable_inwait, - &ddr_clk, NULL); - -DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET, - NULL, NULL, &pll3_sw_clk, NULL); -DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET, - NULL, NULL, &pll3_sw_clk, NULL); - -/* PATA */ -DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG0_OFFSET, - NULL, NULL, &ipg_clk, &spba_clk); - -#define _REGISTER_CLOCK(d, n, c) \ - { \ - .dev_id = d, \ - .con_id = n, \ - .clk = &c, \ - }, - -static struct clk_lookup mx51_lookups[] = { - /* i.mx51 has the i.mx21 type uart */ - _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk) - _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk) - _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk) - _REGISTER_CLOCK(NULL, "gpt", gpt_clk) - /* i.mx51 has the i.mx27 type fec */ - _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk) - _REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk) - _REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk) - _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) - _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk) - _REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk) - _REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk) - _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_ahb_clk) - _REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", usb_phy1_clk) - _REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk) - _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_ahb_clk) - _REGISTER_CLOCK("mxc-ehci.2", "usb", usboh3_clk) - _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk) - _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk) - _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk) - _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk) - _REGISTER_CLOCK("mxc_nand", NULL, nfc_clk) - _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) - _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) - _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk) - /* i.mx51 has the i.mx35 type sdma */ - _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk) - _REGISTER_CLOCK(NULL, "ckih", ckih_clk) - _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk) - _REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk) - _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk) - _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk) - /* i.mx51 has the i.mx35 type cspi */ - _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk) - _REGISTER_CLOCK("sdhci-esdhc-imx51.0", NULL, esdhc1_clk) - _REGISTER_CLOCK("sdhci-esdhc-imx51.1", NULL, esdhc2_clk) - _REGISTER_CLOCK("sdhci-esdhc-imx51.2", NULL, esdhc3_clk) - _REGISTER_CLOCK("sdhci-esdhc-imx51.3", NULL, esdhc4_clk) - _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk) - _REGISTER_CLOCK(NULL, "iim_clk", iim_clk) - _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk) - _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk) - _REGISTER_CLOCK(NULL, "mipi_hsp", mipi_hsp_clk) - _REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk) - _REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk) - _REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk) - _REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk) - _REGISTER_CLOCK("pata_imx", NULL, pata_clk) -}; - -static struct clk_lookup mx53_lookups[] = { - /* i.mx53 has the i.mx21 type uart */ - _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk) - _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk) - _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk) - _REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk) - _REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk) - _REGISTER_CLOCK(NULL, "gpt", gpt_clk) - /* i.mx53 has the i.mx25 type fec */ - _REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk) - _REGISTER_CLOCK(NULL, "iim_clk", iim_clk) - _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) - _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk) - _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_mx53_clk) - /* i.mx53 has the i.mx51 type ecspi */ - _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk) - _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk) - /* i.mx53 has the i.mx25 type cspi */ - _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk) - _REGISTER_CLOCK("sdhci-esdhc-imx53.0", NULL, esdhc1_clk) - _REGISTER_CLOCK("sdhci-esdhc-imx53.1", NULL, esdhc2_mx53_clk) - _REGISTER_CLOCK("sdhci-esdhc-imx53.2", NULL, esdhc3_mx53_clk) - _REGISTER_CLOCK("sdhci-esdhc-imx53.3", NULL, esdhc4_mx53_clk) - _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk) - _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk) - /* i.mx53 has the i.mx35 type sdma */ - _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk) - _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) - _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) - _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk) - _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk) - _REGISTER_CLOCK("pata_imx", NULL, pata_clk) - _REGISTER_CLOCK("imx53-ahci.0", "ahci", sata_clk) - _REGISTER_CLOCK("imx53-ahci.0", "ahci_phy", ahci_phy_clk) - _REGISTER_CLOCK("imx53-ahci.0", "ahci_dma", ahci_dma_clk) -}; - -static void clk_tree_init(void) -{ - u32 reg; - - ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk); - - /* - * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at - * 8MHz, its derived from lp_apm. - * - * FIXME: Verify if true for all boards - */ - reg = __raw_readl(MXC_CCM_CBCDR); - reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK; - reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK; - reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK; - reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET); - __raw_writel(reg, MXC_CCM_CBCDR); -} - -int __init mx51_clocks_init(unsigned long ckil, unsigned long osc, - unsigned long ckih1, unsigned long ckih2) -{ - int i; - - external_low_reference = ckil; - external_high_reference = ckih1; - ckih2_reference = ckih2; - oscillator_reference = osc; - - for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++) - clkdev_add(&mx51_lookups[i]); - - clk_tree_init(); - - clk_enable(&cpu_clk); - clk_enable(&main_bus_clk); - - clk_enable(&iim_clk); - imx_print_silicon_rev("i.MX51", mx51_revision()); - clk_disable(&iim_clk); - - /* move usb_phy_clk to 24MHz */ - clk_set_parent(&usb_phy1_clk, &osc_clk); - - /* set the usboh3_clk parent to pll2_sw_clk */ - clk_set_parent(&usboh3_clk, &pll2_sw_clk); - - /* Set SDHC parents to be PLL2 */ - clk_set_parent(&esdhc1_clk, &pll2_sw_clk); - clk_set_parent(&esdhc2_clk, &pll2_sw_clk); - - /* set SDHC root clock as 166.25MHZ*/ - clk_set_rate(&esdhc1_clk, 166250000); - clk_set_rate(&esdhc2_clk, 166250000); - - /* System timer */ - mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR), - MX51_INT_GPT); - return 0; -} - -int __init mx53_clocks_init(unsigned long ckil, unsigned long osc, - unsigned long ckih1, unsigned long ckih2) -{ - int i; - - external_low_reference = ckil; - external_high_reference = ckih1; - ckih2_reference = ckih2; - oscillator_reference = osc; - - for (i = 0; i < ARRAY_SIZE(mx53_lookups); i++) - clkdev_add(&mx53_lookups[i]); - - clk_tree_init(); - - clk_set_parent(&uart_root_clk, &pll3_sw_clk); - clk_enable(&cpu_clk); - clk_enable(&main_bus_clk); - - clk_enable(&iim_clk); - imx_print_silicon_rev("i.MX53", mx53_revision()); - clk_disable(&iim_clk); - - /* Set SDHC parents to be PLL2 */ - clk_set_parent(&esdhc1_clk, &pll2_sw_clk); - clk_set_parent(&esdhc3_mx53_clk, &pll2_sw_clk); - - /* set SDHC root clock as 200MHZ*/ - clk_set_rate(&esdhc1_clk, 200000000); - clk_set_rate(&esdhc3_mx53_clk, 200000000); - - /* System timer */ - mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR), - MX53_INT_GPT); - return 0; -} - -static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc, - unsigned long *ckih1, unsigned long *ckih2) -{ - struct device_node *np; - - /* retrieve the freqency of fixed clocks from device tree */ - for_each_compatible_node(np, NULL, "fixed-clock") { - u32 rate; - if (of_property_read_u32(np, "clock-frequency", &rate)) - continue; - - if (of_device_is_compatible(np, "fsl,imx-ckil")) - *ckil = rate; - else if (of_device_is_compatible(np, "fsl,imx-osc")) - *osc = rate; - else if (of_device_is_compatible(np, "fsl,imx-ckih1")) - *ckih1 = rate; - else if (of_device_is_compatible(np, "fsl,imx-ckih2")) - *ckih2 = rate; - } -} - -int __init mx51_clocks_init_dt(void) -{ - unsigned long ckil, osc, ckih1, ckih2; - - clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2); - return mx51_clocks_init(ckil, osc, ckih1, ckih2); -} - -int __init mx53_clocks_init_dt(void) -{ - unsigned long ckil, osc, ckih1, ckih2; - - clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2); - return mx53_clocks_init(ckil, osc, ckih1, ckih2); -} diff --git a/arch/arm/mach-mx5/cpu.c b/arch/arm/mach-mx5/cpu.c deleted file mode 100644 index 5c53282..0000000 --- a/arch/arm/mach-mx5/cpu.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - * - * This file contains the CPU initialization code. - */ - -#include -#include -#include -#include -#include -#include - -static int mx5_cpu_rev = -1; - -#define IIM_SREV 0x24 -#define MX50_HW_ADADIG_DIGPROG 0xB0 - -static int get_mx51_srev(void) -{ - void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR); - u32 rev = readl(iim_base + IIM_SREV) & 0xff; - - switch (rev) { - case 0x0: - return IMX_CHIP_REVISION_2_0; - case 0x10: - return IMX_CHIP_REVISION_3_0; - default: - return IMX_CHIP_REVISION_UNKNOWN; - } -} - -/* - * Returns: - * the silicon revision of the cpu - * -EINVAL - not a mx51 - */ -int mx51_revision(void) -{ - if (!cpu_is_mx51()) - return -EINVAL; - - if (mx5_cpu_rev == -1) - mx5_cpu_rev = get_mx51_srev(); - - return mx5_cpu_rev; -} -EXPORT_SYMBOL(mx51_revision); - -#ifdef CONFIG_NEON - -/* - * All versions of the silicon before Rev. 3 have broken NEON implementations. - * Dependent on link order - so the assumption is that vfp_init is called - * before us. - */ -static int __init mx51_neon_fixup(void) -{ - if (!cpu_is_mx51()) - return 0; - - if (mx51_revision() < IMX_CHIP_REVISION_3_0 && (elf_hwcap & HWCAP_NEON)) { - elf_hwcap &= ~HWCAP_NEON; - pr_info("Turning off NEON support, detected broken NEON implementation\n"); - } - return 0; -} - -late_initcall(mx51_neon_fixup); -#endif - -static int get_mx53_srev(void) -{ - void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR); - u32 rev = readl(iim_base + IIM_SREV) & 0xff; - - switch (rev) { - case 0x0: - return IMX_CHIP_REVISION_1_0; - case 0x2: - return IMX_CHIP_REVISION_2_0; - case 0x3: - return IMX_CHIP_REVISION_2_1; - default: - return IMX_CHIP_REVISION_UNKNOWN; - } -} - -/* - * Returns: - * the silicon revision of the cpu - * -EINVAL - not a mx53 - */ -int mx53_revision(void) -{ - if (!cpu_is_mx53()) - return -EINVAL; - - if (mx5_cpu_rev == -1) - mx5_cpu_rev = get_mx53_srev(); - - return mx5_cpu_rev; -} -EXPORT_SYMBOL(mx53_revision); - -static int get_mx50_srev(void) -{ - void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K); - u32 rev; - - if (!anatop) { - mx5_cpu_rev = -EINVAL; - return 0; - } - - rev = readl(anatop + MX50_HW_ADADIG_DIGPROG); - rev &= 0xff; - - iounmap(anatop); - if (rev == 0x0) - return IMX_CHIP_REVISION_1_0; - else if (rev == 0x1) - return IMX_CHIP_REVISION_1_1; - return 0; -} - -/* - * Returns: - * the silicon revision of the cpu - * -EINVAL - not a mx50 - */ -int mx50_revision(void) -{ - if (!cpu_is_mx50()) - return -EINVAL; - - if (mx5_cpu_rev == -1) - mx5_cpu_rev = get_mx50_srev(); - - return mx5_cpu_rev; -} -EXPORT_SYMBOL(mx50_revision); - -static int __init post_cpu_init(void) -{ - unsigned int reg; - void __iomem *base; - - if (cpu_is_mx51() || cpu_is_mx53()) { - if (cpu_is_mx51()) - base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR); - else - base = MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR); - - __raw_writel(0x0, base + 0x40); - __raw_writel(0x0, base + 0x44); - __raw_writel(0x0, base + 0x48); - __raw_writel(0x0, base + 0x4C); - reg = __raw_readl(base + 0x50) & 0x00FFFFFF; - __raw_writel(reg, base + 0x50); - - if (cpu_is_mx51()) - base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR); - else - base = MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR); - - __raw_writel(0x0, base + 0x40); - __raw_writel(0x0, base + 0x44); - __raw_writel(0x0, base + 0x48); - __raw_writel(0x0, base + 0x4C); - reg = __raw_readl(base + 0x50) & 0x00FFFFFF; - __raw_writel(reg, base + 0x50); - } - - return 0; -} - -postcore_initcall(post_cpu_init); diff --git a/arch/arm/mach-mx5/cpu_op-mx51.c b/arch/arm/mach-mx5/cpu_op-mx51.c deleted file mode 100644 index 9d34c3d..0000000 --- a/arch/arm/mach-mx5/cpu_op-mx51.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. - */ - -/* - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include - -static struct cpu_op mx51_cpu_op[] = { - { - .cpu_rate = 160000000,}, - { - .cpu_rate = 800000000,}, -}; - -struct cpu_op *mx51_get_cpu_op(int *op) -{ - *op = ARRAY_SIZE(mx51_cpu_op); - return mx51_cpu_op; -} diff --git a/arch/arm/mach-mx5/cpu_op-mx51.h b/arch/arm/mach-mx5/cpu_op-mx51.h deleted file mode 100644 index 97477fe..0000000 --- a/arch/arm/mach-mx5/cpu_op-mx51.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. - */ - -/* - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -extern struct cpu_op *mx51_get_cpu_op(int *op); diff --git a/arch/arm/mach-mx5/crm_regs.h b/arch/arm/mach-mx5/crm_regs.h deleted file mode 100644 index 5e11ba7..0000000 --- a/arch/arm/mach-mx5/crm_regs.h +++ /dev/null @@ -1,600 +0,0 @@ -/* - * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ -#ifndef __ARCH_ARM_MACH_MX51_CRM_REGS_H__ -#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__ - -#define MX51_CCM_BASE MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR) -#define MX51_DPLL1_BASE MX51_IO_ADDRESS(MX51_PLL1_BASE_ADDR) -#define MX51_DPLL2_BASE MX51_IO_ADDRESS(MX51_PLL2_BASE_ADDR) -#define MX51_DPLL3_BASE MX51_IO_ADDRESS(MX51_PLL3_BASE_ADDR) -#define MX51_CORTEXA8_BASE MX51_IO_ADDRESS(MX51_ARM_BASE_ADDR) -#define MX51_GPC_BASE MX51_IO_ADDRESS(MX51_GPC_BASE_ADDR) - -/*MX53*/ -#define MX53_CCM_BASE MX53_IO_ADDRESS(MX53_CCM_BASE_ADDR) -#define MX53_DPLL1_BASE MX53_IO_ADDRESS(MX53_PLL1_BASE_ADDR) -#define MX53_DPLL2_BASE MX53_IO_ADDRESS(MX53_PLL2_BASE_ADDR) -#define MX53_DPLL3_BASE MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR) -#define MX53_DPLL4_BASE MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR) - -/* PLL Register Offsets */ -#define MXC_PLL_DP_CTL 0x00 -#define MXC_PLL_DP_CONFIG 0x04 -#define MXC_PLL_DP_OP 0x08 -#define MXC_PLL_DP_MFD 0x0C -#define MXC_PLL_DP_MFN 0x10 -#define MXC_PLL_DP_MFNMINUS 0x14 -#define MXC_PLL_DP_MFNPLUS 0x18 -#define MXC_PLL_DP_HFS_OP 0x1C -#define MXC_PLL_DP_HFS_MFD 0x20 -#define MXC_PLL_DP_HFS_MFN 0x24 -#define MXC_PLL_DP_MFN_TOGC 0x28 -#define MXC_PLL_DP_DESTAT 0x2c - -/* PLL Register Bit definitions */ -#define MXC_PLL_DP_CTL_MUL_CTRL 0x2000 -#define MXC_PLL_DP_CTL_DPDCK0_2_EN 0x1000 -#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET 12 -#define MXC_PLL_DP_CTL_ADE 0x800 -#define MXC_PLL_DP_CTL_REF_CLK_DIV 0x400 -#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK (3 << 8) -#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET 8 -#define MXC_PLL_DP_CTL_HFSM 0x80 -#define MXC_PLL_DP_CTL_PRE 0x40 -#define MXC_PLL_DP_CTL_UPEN 0x20 -#define MXC_PLL_DP_CTL_RST 0x10 -#define MXC_PLL_DP_CTL_RCP 0x8 -#define MXC_PLL_DP_CTL_PLM 0x4 -#define MXC_PLL_DP_CTL_BRM0 0x2 -#define MXC_PLL_DP_CTL_LRF 0x1 - -#define MXC_PLL_DP_CONFIG_BIST 0x8 -#define MXC_PLL_DP_CONFIG_SJC_CE 0x4 -#define MXC_PLL_DP_CONFIG_AREN 0x2 -#define MXC_PLL_DP_CONFIG_LDREQ 0x1 - -#define MXC_PLL_DP_OP_MFI_OFFSET 4 -#define MXC_PLL_DP_OP_MFI_MASK (0xF << 4) -#define MXC_PLL_DP_OP_PDF_OFFSET 0 -#define MXC_PLL_DP_OP_PDF_MASK 0xF - -#define MXC_PLL_DP_MFD_OFFSET 0 -#define MXC_PLL_DP_MFD_MASK 0x07FFFFFF - -#define MXC_PLL_DP_MFN_OFFSET 0x0 -#define MXC_PLL_DP_MFN_MASK 0x07FFFFFF - -#define MXC_PLL_DP_MFN_TOGC_TOG_DIS (1 << 17) -#define MXC_PLL_DP_MFN_TOGC_TOG_EN (1 << 16) -#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET 0x0 -#define MXC_PLL_DP_MFN_TOGC_CNT_MASK 0xFFFF - -#define MXC_PLL_DP_DESTAT_TOG_SEL (1 << 31) -#define MXC_PLL_DP_DESTAT_MFN 0x07FFFFFF - -/* Register addresses of CCM*/ -#define MXC_CCM_CCR (MX51_CCM_BASE + 0x00) -#define MXC_CCM_CCDR (MX51_CCM_BASE + 0x04) -#define MXC_CCM_CSR (MX51_CCM_BASE + 0x08) -#define MXC_CCM_CCSR (MX51_CCM_BASE + 0x0C) -#define MXC_CCM_CACRR (MX51_CCM_BASE + 0x10) -#define MXC_CCM_CBCDR (MX51_CCM_BASE + 0x14) -#define MXC_CCM_CBCMR (MX51_CCM_BASE + 0x18) -#define MXC_CCM_CSCMR1 (MX51_CCM_BASE + 0x1C) -#define MXC_CCM_CSCMR2 (MX51_CCM_BASE + 0x20) -#define MXC_CCM_CSCDR1 (MX51_CCM_BASE + 0x24) -#define MXC_CCM_CS1CDR (MX51_CCM_BASE + 0x28) -#define MXC_CCM_CS2CDR (MX51_CCM_BASE + 0x2C) -#define MXC_CCM_CDCDR (MX51_CCM_BASE + 0x30) -#define MXC_CCM_CHSCDR (MX51_CCM_BASE + 0x34) -#define MXC_CCM_CSCDR2 (MX51_CCM_BASE + 0x38) -#define MXC_CCM_CSCDR3 (MX51_CCM_BASE + 0x3C) -#define MXC_CCM_CSCDR4 (MX51_CCM_BASE + 0x40) -#define MXC_CCM_CWDR (MX51_CCM_BASE + 0x44) -#define MXC_CCM_CDHIPR (MX51_CCM_BASE + 0x48) -#define MXC_CCM_CDCR (MX51_CCM_BASE + 0x4C) -#define MXC_CCM_CTOR (MX51_CCM_BASE + 0x50) -#define MXC_CCM_CLPCR (MX51_CCM_BASE + 0x54) -#define MXC_CCM_CISR (MX51_CCM_BASE + 0x58) -#define MXC_CCM_CIMR (MX51_CCM_BASE + 0x5C) -#define MXC_CCM_CCOSR (MX51_CCM_BASE + 0x60) -#define MXC_CCM_CGPR (MX51_CCM_BASE + 0x64) -#define MXC_CCM_CCGR0 (MX51_CCM_BASE + 0x68) -#define MXC_CCM_CCGR1 (MX51_CCM_BASE + 0x6C) -#define MXC_CCM_CCGR2 (MX51_CCM_BASE + 0x70) -#define MXC_CCM_CCGR3 (MX51_CCM_BASE + 0x74) -#define MXC_CCM_CCGR4 (MX51_CCM_BASE + 0x78) -#define MXC_CCM_CCGR5 (MX51_CCM_BASE + 0x7C) -#define MXC_CCM_CCGR6 (MX51_CCM_BASE + 0x80) -#define MXC_CCM_CCGR7 (MX51_CCM_BASE + 0x84) - -#define MXC_CCM_CMEOR (MX51_CCM_BASE + 0x84) - -/* Define the bits in register CCR */ -#define MXC_CCM_CCR_COSC_EN (1 << 12) -#define MXC_CCM_CCR_FPM_MULT_MASK (1 << 11) -#define MXC_CCM_CCR_CAMP2_EN (1 << 10) -#define MXC_CCM_CCR_CAMP1_EN (1 << 9) -#define MXC_CCM_CCR_FPM_EN (1 << 8) -#define MXC_CCM_CCR_OSCNT_OFFSET (0) -#define MXC_CCM_CCR_OSCNT_MASK (0xFF) - -/* Define the bits in register CCDR */ -#define MXC_CCM_CCDR_HSC_HS_MASK (0x1 << 18) -#define MXC_CCM_CCDR_IPU_HS_MASK (0x1 << 17) -#define MXC_CCM_CCDR_EMI_HS_MASK (0x1 << 16) - -/* Define the bits in register CSR */ -#define MXC_CCM_CSR_COSR_READY (1 << 5) -#define MXC_CCM_CSR_LVS_VALUE (1 << 4) -#define MXC_CCM_CSR_CAMP2_READY (1 << 3) -#define MXC_CCM_CSR_CAMP1_READY (1 << 2) -#define MXC_CCM_CSR_FPM_READY (1 << 1) -#define MXC_CCM_CSR_REF_EN_B (1 << 0) - -/* Define the bits in register CCSR */ -#define MXC_CCM_CCSR_LP_APM_SEL (0x1 << 9) -#define MXC_CCM_CCSR_STEP_SEL_OFFSET (7) -#define MXC_CCM_CCSR_STEP_SEL_MASK (0x3 << 7) -#define MXC_CCM_CCSR_STEP_SEL_LP_APM 0 -#define MXC_CCM_CCSR_STEP_SEL_PLL1_BYPASS 1 /* Only when JTAG connected? */ -#define MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED 2 -#define MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED 3 -#define MXC_CCM_CCSR_PLL2_PODF_OFFSET (5) -#define MXC_CCM_CCSR_PLL2_PODF_MASK (0x3 << 5) -#define MXC_CCM_CCSR_PLL3_PODF_OFFSET (3) -#define MXC_CCM_CCSR_PLL3_PODF_MASK (0x3 << 3) -#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL (1 << 2) /* 0: pll1_main_clk, - 1: step_clk */ -#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL (1 << 1) -#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL (1 << 0) - -/* Define the bits in register CACRR */ -#define MXC_CCM_CACRR_ARM_PODF_OFFSET (0) -#define MXC_CCM_CACRR_ARM_PODF_MASK (0x7) - -/* Define the bits in register CBCDR */ -#define MXC_CCM_CBCDR_EMI_CLK_SEL (0x1 << 26) -#define MXC_CCM_CBCDR_PERIPH_CLK_SEL (0x1 << 25) -#define MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET (30) -#define MXC_CCM_CBCDR_DDR_HF_SEL (0x1 << 30) -#define MXC_CCM_CBCDR_DDR_PODF_OFFSET (27) -#define MXC_CCM_CBCDR_DDR_PODF_MASK (0x7 << 27) -#define MXC_CCM_CBCDR_EMI_PODF_OFFSET (22) -#define MXC_CCM_CBCDR_EMI_PODF_MASK (0x7 << 22) -#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET (19) -#define MXC_CCM_CBCDR_AXI_B_PODF_MASK (0x7 << 19) -#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET (16) -#define MXC_CCM_CBCDR_AXI_A_PODF_MASK (0x7 << 16) -#define MXC_CCM_CBCDR_NFC_PODF_OFFSET (13) -#define MXC_CCM_CBCDR_NFC_PODF_MASK (0x7 << 13) -#define MXC_CCM_CBCDR_AHB_PODF_OFFSET (10) -#define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << 10) -#define MXC_CCM_CBCDR_IPG_PODF_OFFSET (8) -#define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << 8) -#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET (6) -#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK (0x3 << 6) -#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET (3) -#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK (0x7 << 3) -#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET (0) -#define MXC_CCM_CBCDR_PERCLK_PODF_MASK (0x7) - -/* Define the bits in register CBCMR */ -#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET (14) -#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14) -#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET (12) -#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK (0x3 << 12) -#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET (10) -#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK (0x3 << 10) -#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET (8) -#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK (0x3 << 8) -#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET (6) -#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK (0x3 << 6) -#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET (4) -#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK (0x3 << 4) -#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET (14) -#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << 14) -#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL (0x1 << 1) -#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL (0x1 << 0) - -/* Define the bits in register CSCMR1 */ -#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET (30) -#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK (0x3 << 30) -#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET (28) -#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK (0x3 << 28) -#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET (26) -#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL (0x1 << 26) -#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET (24) -#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK (0x3 << 24) -#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET (22) -#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK (0x3 << 22) -#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET (20) -#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK (0x3 << 20) -#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL (0x1 << 19) -#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL (0x1 << 19) -#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL (0x1 << 18) -#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET (16) -#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK (0x3 << 16) -#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_OFFSET (16) -#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_MASK (0x3 << 16) -#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET (14) -#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << 14) -#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET (12) -#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << 12) -#define MXC_CCM_CSCMR1_SSI3_CLK_SEL (0x1 << 11) -#define MXC_CCM_CSCMR1_VPU_RCLK_SEL (0x1 << 10) -#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET (8) -#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK (0x3 << 8) -#define MXC_CCM_CSCMR1_TVE_CLK_SEL (0x1 << 7) -#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL (0x1 << 6) -#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET (4) -#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK (0x3 << 4) -#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET (2) -#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK (0x3 << 2) -#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL (0x1 << 1) -#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL (0x1) - -/* Define the bits in register CSCMR2 */ -#define MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(n) (26+n*3) -#define MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(n) (0x7 << (26+n*3)) -#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET (24) -#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK (0x3 << 24) -#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET (22) -#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK (0x3 << 22) -#define MXC_CCM_CSCMR2_ESC_CLK_SEL_OFFSET (20) -#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK (0x3 << 20) -#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_OFFSET (18) -#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_MASK (0x3 << 18) -#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_OFFSET (16) -#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_MASK (0x3 << 16) -#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_OFFSET (14) -#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_MASK (0x3 << 14) -#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_OFFSET (12) -#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_MASK (0x3 << 12) -#define MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET (10) -#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK (0x3 << 10) -#define MXC_CCM_CSCMR2_SLIMBUS_COM (0x1 << 9) -#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET (6) -#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_MASK (0x7 << 6) -#define MXC_CCM_CSCMR2_SPDIF1_COM (1 << 5) -#define MXC_CCM_CSCMR2_SPDIF0_COM (1 << 4) -#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET (2) -#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK (0x3 << 2) -#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET (0) -#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK (0x3) - -/* Define the bits in register CSCDR1 */ -#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET (22) -#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK (0x7 << 22) -#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET (19) -#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK (0x7 << 19) -#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_OFFSET (22) -#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_MASK (0x7 << 22) -#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET (19) -#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK (0x7 << 19) -#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET (16) -#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK (0x7 << 16) -#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET (14) -#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK (0x3 << 14) -#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET (11) -#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK (0x7 << 11) -#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET (8) -#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK (0x7 << 8) -#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET (6) -#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK (0x3 << 6) -#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET (3) -#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK (0x7 << 3) -#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET (0) -#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x7) - -/* Define the bits in register CS1CDR and CS2CDR */ -#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET (22) -#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK (0x7 << 22) -#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET (16) -#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK (0x3F << 16) -#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET (6) -#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK (0x7 << 6) -#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET (0) -#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK (0x3F) - -#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET (22) -#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK (0x7 << 22) -#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET (16) -#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK (0x3F << 16) -#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET (6) -#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK (0x7 << 6) -#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET (0) -#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK (0x3F) - -/* Define the bits in register CDCDR */ -#define MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET (28) -#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK (0x7 << 28) -#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET (25) -#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK (0x7 << 25) -#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET (19) -#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK (0x3F << 19) -#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET (16) -#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK (0x7 << 16) -#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET (9) -#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK (0x3F << 9) -#define MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET (6) -#define MXC_CCM_CDCDR_DI_CLK_PRED_MASK (0x7 << 6) -#define MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET (3) -#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK (0x7 << 3) -#define MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET (0) -#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK (0x7) - -/* Define the bits in register CHSCCDR */ -#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_OFFSET (12) -#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_MASK (0x7 << 12) -#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET (6) -#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_MASK (0x3F << 6) -#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET (3) -#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_MASK (0x7 << 3) -#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET (0) -#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_MASK (0x7) - -/* Define the bits in register CSCDR2 */ -#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET (25) -#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK (0x7 << 25) -#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET (19) -#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK (0x3F << 19) -#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET (16) -#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK (0x7 << 16) -#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET (9) -#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK (0x3F << 9) -#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET (6) -#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK (0x7 << 6) -#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET (0) -#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK (0x3F) - -/* Define the bits in register CSCDR3 */ -#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET (16) -#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK (0x7 << 16) -#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET (9) -#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK (0x3F << 9) -#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_OFFSET (6) -#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_MASK (0x7 << 6) -#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_OFFSET (0) -#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_MASK (0x3F) - -/* Define the bits in register CSCDR4 */ -#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET (16) -#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK (0x7 << 16) -#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET (9) -#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK (0x3F << 9) -#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET (6) -#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK (0x7 << 6) -#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET (0) -#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK (0x3F) - -/* Define the bits in register CDHIPR */ -#define MXC_CCM_CDHIPR_ARM_PODF_BUSY (1 << 16) -#define MXC_CCM_CDHIPR_DDR_HF_CLK_SEL_BUSY (1 << 8) -#define MXC_CCM_CDHIPR_DDR_PODF_BUSY (1 << 7) -#define MXC_CCM_CDHIPR_EMI_CLK_SEL_BUSY (1 << 6) -#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY (1 << 5) -#define MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY (1 << 4) -#define MXC_CCM_CDHIPR_AHB_PODF_BUSY (1 << 3) -#define MXC_CCM_CDHIPR_EMI_PODF_BUSY (1 << 2) -#define MXC_CCM_CDHIPR_AXI_B_PODF_BUSY (1 << 1) -#define MXC_CCM_CDHIPR_AXI_A_PODF_BUSY (1 << 0) - -/* Define the bits in register CDCR */ -#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER (0x1 << 2) -#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET (0) -#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK (0x3) - -/* Define the bits in register CLPCR */ -#define MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS (0x1 << 23) -#define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS (0x1 << 22) -#define MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 21) -#define MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 25) -#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS (0x1 << 20) -#define MXC_CCM_CLPCR_BYPASS_EMI_LPM_HS (0x1 << 19) -#define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS (0x1 << 18) -#define MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS (0x1 << 17) -#define MXC_CCM_CLPCR_BYPASS_RNGC_LPM_HS (0x1 << 16) -#define MXC_CCM_CLPCR_COSC_PWRDOWN (0x1 << 11) -#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET (9) -#define MXC_CCM_CLPCR_STBY_COUNT_MASK (0x3 << 9) -#define MXC_CCM_CLPCR_VSTBY (0x1 << 8) -#define MXC_CCM_CLPCR_DIS_REF_OSC (0x1 << 7) -#define MXC_CCM_CLPCR_SBYOS (0x1 << 6) -#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5) -#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET (3) -#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK (0x3 << 3) -#define MXC_CCM_CLPCR_LPM_OFFSET (0) -#define MXC_CCM_CLPCR_LPM_MASK (0x3) - -/* Define the bits in register CISR */ -#define MXC_CCM_CISR_ARM_PODF_LOADED (0x1 << 25) -#define MXC_CCM_CISR_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21) -#define MXC_CCM_CISR_AHB_PODF_LOADED (0x1 << 20) -#define MXC_CCM_CISR_EMI_PODF_LOADED (0x1 << 19) -#define MXC_CCM_CISR_AXI_B_PODF_LOADED (0x1 << 18) -#define MXC_CCM_CISR_AXI_A_PODF_LOADED (0x1 << 17) -#define MXC_CCM_CISR_DIVIDER_LOADED (0x1 << 16) -#define MXC_CCM_CISR_COSC_READY (0x1 << 6) -#define MXC_CCM_CISR_CKIH2_READY (0x1 << 5) -#define MXC_CCM_CISR_CKIH_READY (0x1 << 4) -#define MXC_CCM_CISR_FPM_READY (0x1 << 3) -#define MXC_CCM_CISR_LRF_PLL3 (0x1 << 2) -#define MXC_CCM_CISR_LRF_PLL2 (0x1 << 1) -#define MXC_CCM_CISR_LRF_PLL1 (0x1) - -/* Define the bits in register CIMR */ -#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED (0x1 << 25) -#define MXC_CCM_CIMR_MASK_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21) -#define MXC_CCM_CIMR_MASK_EMI_PODF_LOADED (0x1 << 20) -#define MXC_CCM_CIMR_MASK_AXI_C_PODF_LOADED (0x1 << 19) -#define MXC_CCM_CIMR_MASK_AXI_B_PODF_LOADED (0x1 << 18) -#define MXC_CCM_CIMR_MASK_AXI_A_PODF_LOADED (0x1 << 17) -#define MXC_CCM_CIMR_MASK_DIVIDER_LOADED (0x1 << 16) -#define MXC_CCM_CIMR_MASK_COSC_READY (0x1 << 5) -#define MXC_CCM_CIMR_MASK_CKIH_READY (0x1 << 4) -#define MXC_CCM_CIMR_MASK_FPM_READY (0x1 << 3) -#define MXC_CCM_CIMR_MASK_LRF_PLL3 (0x1 << 2) -#define MXC_CCM_CIMR_MASK_LRF_PLL2 (0x1 << 1) -#define MXC_CCM_CIMR_MASK_LRF_PLL1 (0x1) - -/* Define the bits in register CCOSR */ -#define MXC_CCM_CCOSR_CKO2_EN_OFFSET (0x1 << 24) -#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET (21) -#define MXC_CCM_CCOSR_CKO2_DIV_MASK (0x7 << 21) -#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET (16) -#define MXC_CCM_CCOSR_CKO2_SEL_MASK (0x1F << 16) -#define MXC_CCM_CCOSR_CKOL_EN (0x1 << 7) -#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET (4) -#define MXC_CCM_CCOSR_CKOL_DIV_MASK (0x7 << 4) -#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET (0) -#define MXC_CCM_CCOSR_CKOL_SEL_MASK (0xF) - -/* Define the bits in registers CGPR */ -#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE (0x1 << 4) -#define MXC_CCM_CGPR_FPM_SEL (0x1 << 3) -#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_OFFSET (0) -#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_MASK (0x7) - -/* Define the bits in registers CCGRx */ -#define MXC_CCM_CCGRx_CG_MASK 0x3 -#define MXC_CCM_CCGRx_MOD_OFF 0x0 -#define MXC_CCM_CCGRx_MOD_ON 0x3 -#define MXC_CCM_CCGRx_MOD_IDLE 0x1 - -#define MXC_CCM_CCGRx_CG15_MASK (0x3 << 30) -#define MXC_CCM_CCGRx_CG14_MASK (0x3 << 28) -#define MXC_CCM_CCGRx_CG13_MASK (0x3 << 26) -#define MXC_CCM_CCGRx_CG12_MASK (0x3 << 24) -#define MXC_CCM_CCGRx_CG11_MASK (0x3 << 22) -#define MXC_CCM_CCGRx_CG10_MASK (0x3 << 20) -#define MXC_CCM_CCGRx_CG9_MASK (0x3 << 18) -#define MXC_CCM_CCGRx_CG8_MASK (0x3 << 16) -#define MXC_CCM_CCGRx_CG5_MASK (0x3 << 10) -#define MXC_CCM_CCGRx_CG4_MASK (0x3 << 8) -#define MXC_CCM_CCGRx_CG3_MASK (0x3 << 6) -#define MXC_CCM_CCGRx_CG2_MASK (0x3 << 4) -#define MXC_CCM_CCGRx_CG1_MASK (0x3 << 2) -#define MXC_CCM_CCGRx_CG0_MASK (0x3 << 0) - -#define MXC_CCM_CCGRx_CG15_OFFSET 30 -#define MXC_CCM_CCGRx_CG14_OFFSET 28 -#define MXC_CCM_CCGRx_CG13_OFFSET 26 -#define MXC_CCM_CCGRx_CG12_OFFSET 24 -#define MXC_CCM_CCGRx_CG11_OFFSET 22 -#define MXC_CCM_CCGRx_CG10_OFFSET 20 -#define MXC_CCM_CCGRx_CG9_OFFSET 18 -#define MXC_CCM_CCGRx_CG8_OFFSET 16 -#define MXC_CCM_CCGRx_CG7_OFFSET 14 -#define MXC_CCM_CCGRx_CG6_OFFSET 12 -#define MXC_CCM_CCGRx_CG5_OFFSET 10 -#define MXC_CCM_CCGRx_CG4_OFFSET 8 -#define MXC_CCM_CCGRx_CG3_OFFSET 6 -#define MXC_CCM_CCGRx_CG2_OFFSET 4 -#define MXC_CCM_CCGRx_CG1_OFFSET 2 -#define MXC_CCM_CCGRx_CG0_OFFSET 0 - -#define MXC_DPTC_LP_BASE (MX51_GPC_BASE + 0x80) -#define MXC_DPTC_GP_BASE (MX51_GPC_BASE + 0x100) -#define MXC_DVFS_CORE_BASE (MX51_GPC_BASE + 0x180) -#define MXC_DPTC_PER_BASE (MX51_GPC_BASE + 0x1C0) -#define MXC_PGC_IPU_BASE (MX51_GPC_BASE + 0x220) -#define MXC_PGC_VPU_BASE (MX51_GPC_BASE + 0x240) -#define MXC_PGC_GPU_BASE (MX51_GPC_BASE + 0x260) -#define MXC_SRPG_NEON_BASE (MX51_GPC_BASE + 0x280) -#define MXC_SRPG_ARM_BASE (MX51_GPC_BASE + 0x2A0) -#define MXC_SRPG_EMPGC0_BASE (MX51_GPC_BASE + 0x2C0) -#define MXC_SRPG_EMPGC1_BASE (MX51_GPC_BASE + 0x2D0) -#define MXC_SRPG_MEGAMIX_BASE (MX51_GPC_BASE + 0x2E0) -#define MXC_SRPG_EMI_BASE (MX51_GPC_BASE + 0x300) - -/* CORTEXA8 platform */ -#define MXC_CORTEXA8_PLAT_PVID (MX51_CORTEXA8_BASE + 0x0) -#define MXC_CORTEXA8_PLAT_GPC (MX51_CORTEXA8_BASE + 0x4) -#define MXC_CORTEXA8_PLAT_PIC (MX51_CORTEXA8_BASE + 0x8) -#define MXC_CORTEXA8_PLAT_LPC (MX51_CORTEXA8_BASE + 0xC) -#define MXC_CORTEXA8_PLAT_NEON_LPC (MX51_CORTEXA8_BASE + 0x10) -#define MXC_CORTEXA8_PLAT_ICGC (MX51_CORTEXA8_BASE + 0x14) -#define MXC_CORTEXA8_PLAT_AMC (MX51_CORTEXA8_BASE + 0x18) -#define MXC_CORTEXA8_PLAT_NMC (MX51_CORTEXA8_BASE + 0x20) -#define MXC_CORTEXA8_PLAT_NMS (MX51_CORTEXA8_BASE + 0x24) - -/* DVFS CORE */ -#define MXC_DVFSTHRS (MXC_DVFS_CORE_BASE + 0x00) -#define MXC_DVFSCOUN (MXC_DVFS_CORE_BASE + 0x04) -#define MXC_DVFSSIG1 (MXC_DVFS_CORE_BASE + 0x08) -#define MXC_DVFSSIG0 (MXC_DVFS_CORE_BASE + 0x0C) -#define MXC_DVFSGPC0 (MXC_DVFS_CORE_BASE + 0x10) -#define MXC_DVFSGPC1 (MXC_DVFS_CORE_BASE + 0x14) -#define MXC_DVFSGPBT (MXC_DVFS_CORE_BASE + 0x18) -#define MXC_DVFSEMAC (MXC_DVFS_CORE_BASE + 0x1C) -#define MXC_DVFSCNTR (MXC_DVFS_CORE_BASE + 0x20) -#define MXC_DVFSLTR0_0 (MXC_DVFS_CORE_BASE + 0x24) -#define MXC_DVFSLTR0_1 (MXC_DVFS_CORE_BASE + 0x28) -#define MXC_DVFSLTR1_0 (MXC_DVFS_CORE_BASE + 0x2C) -#define MXC_DVFSLTR1_1 (MXC_DVFS_CORE_BASE + 0x30) -#define MXC_DVFSPT0 (MXC_DVFS_CORE_BASE + 0x34) -#define MXC_DVFSPT1 (MXC_DVFS_CORE_BASE + 0x38) -#define MXC_DVFSPT2 (MXC_DVFS_CORE_BASE + 0x3C) -#define MXC_DVFSPT3 (MXC_DVFS_CORE_BASE + 0x40) - -/* GPC */ -#define MXC_GPC_CNTR (MX51_GPC_BASE + 0x0) -#define MXC_GPC_PGR (MX51_GPC_BASE + 0x4) -#define MXC_GPC_VCR (MX51_GPC_BASE + 0x8) -#define MXC_GPC_ALL_PU (MX51_GPC_BASE + 0xC) -#define MXC_GPC_NEON (MX51_GPC_BASE + 0x10) -#define MXC_GPC_PGR_ARMPG_OFFSET 8 -#define MXC_GPC_PGR_ARMPG_MASK (3 << 8) - -/* PGC */ -#define MXC_PGC_IPU_PGCR (MXC_PGC_IPU_BASE + 0x0) -#define MXC_PGC_IPU_PGSR (MXC_PGC_IPU_BASE + 0xC) -#define MXC_PGC_VPU_PGCR (MXC_PGC_VPU_BASE + 0x0) -#define MXC_PGC_VPU_PGSR (MXC_PGC_VPU_BASE + 0xC) -#define MXC_PGC_GPU_PGCR (MXC_PGC_GPU_BASE + 0x0) -#define MXC_PGC_GPU_PGSR (MXC_PGC_GPU_BASE + 0xC) - -#define MXC_PGCR_PCR 1 -#define MXC_SRPGCR_PCR 1 -#define MXC_EMPGCR_PCR 1 -#define MXC_PGSR_PSR 1 - - -#define MXC_CORTEXA8_PLAT_LPC_DSM (1 << 0) -#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM (1 << 1) - -/* SRPG */ -#define MXC_SRPG_NEON_SRPGCR (MXC_SRPG_NEON_BASE + 0x0) -#define MXC_SRPG_NEON_PUPSCR (MXC_SRPG_NEON_BASE + 0x4) -#define MXC_SRPG_NEON_PDNSCR (MXC_SRPG_NEON_BASE + 0x8) - -#define MXC_SRPG_ARM_SRPGCR (MXC_SRPG_ARM_BASE + 0x0) -#define MXC_SRPG_ARM_PUPSCR (MXC_SRPG_ARM_BASE + 0x4) -#define MXC_SRPG_ARM_PDNSCR (MXC_SRPG_ARM_BASE + 0x8) - -#define MXC_SRPG_EMPGC0_SRPGCR (MXC_SRPG_EMPGC0_BASE + 0x0) -#define MXC_SRPG_EMPGC0_PUPSCR (MXC_SRPG_EMPGC0_BASE + 0x4) -#define MXC_SRPG_EMPGC0_PDNSCR (MXC_SRPG_EMPGC0_BASE + 0x8) - -#define MXC_SRPG_EMPGC1_SRPGCR (MXC_SRPG_EMPGC1_BASE + 0x0) -#define MXC_SRPG_EMPGC1_PUPSCR (MXC_SRPG_EMPGC1_BASE + 0x4) -#define MXC_SRPG_EMPGC1_PDNSCR (MXC_SRPG_EMPGC1_BASE + 0x8) - -#define MXC_SRPG_MEGAMIX_SRPGCR (MXC_SRPG_MEGAMIX_BASE + 0x0) -#define MXC_SRPG_MEGAMIX_PUPSCR (MXC_SRPG_MEGAMIX_BASE + 0x4) -#define MXC_SRPG_MEGAMIX_PDNSCR (MXC_SRPG_MEGAMIX_BASE + 0x8) - -#define MXC_SRPGC_EMI_SRPGCR (MXC_SRPGC_EMI_BASE + 0x0) -#define MXC_SRPGC_EMI_PUPSCR (MXC_SRPGC_EMI_BASE + 0x4) -#define MXC_SRPGC_EMI_PDNSCR (MXC_SRPGC_EMI_BASE + 0x8) - -#endif /* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */ diff --git a/arch/arm/mach-mx5/devices-imx50.h b/arch/arm/mach-mx5/devices-imx50.h deleted file mode 100644 index 7216667..0000000 --- a/arch/arm/mach-mx5/devices-imx50.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include - -extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[]; -#define imx50_add_imx_uart(id, pdata) \ - imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata) - -extern const struct imx_fec_data imx50_fec_data; -#define imx50_add_fec(pdata) \ - imx_add_fec(&imx50_fec_data, pdata) - -extern const struct imx_imx_i2c_data imx50_imx_i2c_data[]; -#define imx50_add_imx_i2c(id, pdata) \ - imx_add_imx_i2c(&imx50_imx_i2c_data[id], pdata) diff --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h deleted file mode 100644 index af488bc..0000000 --- a/arch/arm/mach-mx5/devices-imx51.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2010 Pengutronix - * Uwe Kleine-Koenig - * - * 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 - -extern const struct imx_fec_data imx51_fec_data; -#define imx51_add_fec(pdata) \ - imx_add_fec(&imx51_fec_data, pdata) - -extern const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data; -#define imx51_add_fsl_usb2_udc(pdata) \ - imx_add_fsl_usb2_udc(&imx51_fsl_usb2_udc_data, pdata) - -extern const struct imx_imx_i2c_data imx51_imx_i2c_data[]; -#define imx51_add_imx_i2c(id, pdata) \ - imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata) -#define imx51_add_hsi2c(pdata) \ - imx51_add_imx_i2c(2, pdata) - -extern const struct imx_imx_ssi_data imx51_imx_ssi_data[]; -#define imx51_add_imx_ssi(id, pdata) \ - imx_add_imx_ssi(&imx51_imx_ssi_data[id], pdata) - -extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[]; -#define imx51_add_imx_uart(id, pdata) \ - imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata) - -extern const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data; -#define imx51_add_mxc_ehci_otg(pdata) \ - imx_add_mxc_ehci(&imx51_mxc_ehci_otg_data, pdata) -extern const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[]; -#define imx51_add_mxc_ehci_hs(id, pdata) \ - imx_add_mxc_ehci(&imx51_mxc_ehci_hs_data[id - 1], pdata) - -extern const struct imx_mxc_nand_data imx51_mxc_nand_data; -#define imx51_add_mxc_nand(pdata) \ - imx_add_mxc_nand(&imx51_mxc_nand_data, pdata) - -extern const struct imx_sdhci_esdhc_imx_data imx51_sdhci_esdhc_imx_data[]; -#define imx51_add_sdhci_esdhc_imx(id, pdata) \ - imx_add_sdhci_esdhc_imx(&imx51_sdhci_esdhc_imx_data[id], pdata) - -extern const struct imx_spi_imx_data imx51_cspi_data; -#define imx51_add_cspi(pdata) \ - imx_add_spi_imx(&imx51_cspi_data, pdata) - -extern const struct imx_spi_imx_data imx51_ecspi_data[]; -#define imx51_add_ecspi(id, pdata) \ - imx_add_spi_imx(&imx51_ecspi_data[id], pdata) - -extern const struct imx_imx2_wdt_data imx51_imx2_wdt_data[]; -#define imx51_add_imx2_wdt(id, pdata) \ - imx_add_imx2_wdt(&imx51_imx2_wdt_data[id]) - -extern const struct imx_mxc_pwm_data imx51_mxc_pwm_data[]; -#define imx51_add_mxc_pwm(id) \ - imx_add_mxc_pwm(&imx51_mxc_pwm_data[id]) - -extern const struct imx_imx_keypad_data imx51_imx_keypad_data; -#define imx51_add_imx_keypad(pdata) \ - imx_add_imx_keypad(&imx51_imx_keypad_data, pdata) - -extern const struct imx_pata_imx_data imx51_pata_imx_data; -#define imx51_add_pata_imx() \ - imx_add_pata_imx(&imx51_pata_imx_data) diff --git a/arch/arm/mach-mx5/devices-imx53.h b/arch/arm/mach-mx5/devices-imx53.h deleted file mode 100644 index 6e1e5d1..0000000 --- a/arch/arm/mach-mx5/devices-imx53.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2010 Yong Shen. - * - * 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 - -extern const struct imx_fec_data imx53_fec_data; -#define imx53_add_fec(pdata) \ - imx_add_fec(&imx53_fec_data, pdata) - -extern const struct imx_imx_uart_1irq_data imx53_imx_uart_data[]; -#define imx53_add_imx_uart(id, pdata) \ - imx_add_imx_uart_1irq(&imx53_imx_uart_data[id], pdata) - - -extern const struct imx_imx_i2c_data imx53_imx_i2c_data[]; -#define imx53_add_imx_i2c(id, pdata) \ - imx_add_imx_i2c(&imx53_imx_i2c_data[id], pdata) - -extern const struct imx_sdhci_esdhc_imx_data imx53_sdhci_esdhc_imx_data[]; -#define imx53_add_sdhci_esdhc_imx(id, pdata) \ - imx_add_sdhci_esdhc_imx(&imx53_sdhci_esdhc_imx_data[id], pdata) - -extern const struct imx_spi_imx_data imx53_ecspi_data[]; -#define imx53_add_ecspi(id, pdata) \ - imx_add_spi_imx(&imx53_ecspi_data[id], pdata) - -extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[]; -#define imx53_add_imx2_wdt(id, pdata) \ - imx_add_imx2_wdt(&imx53_imx2_wdt_data[id]) - -extern const struct imx_imx_ssi_data imx53_imx_ssi_data[]; -#define imx53_add_imx_ssi(id, pdata) \ - imx_add_imx_ssi(&imx53_imx_ssi_data[id], pdata) - -extern const struct imx_imx_keypad_data imx53_imx_keypad_data; -#define imx53_add_imx_keypad(pdata) \ - imx_add_imx_keypad(&imx53_imx_keypad_data, pdata) - -extern const struct imx_pata_imx_data imx53_pata_imx_data; -#define imx53_add_pata_imx() \ - imx_add_pata_imx(&imx53_pata_imx_data) - -extern struct platform_device *__init imx53_add_ahci_imx(void); diff --git a/arch/arm/mach-mx5/efika.h b/arch/arm/mach-mx5/efika.h deleted file mode 100644 index 014aa98..0000000 --- a/arch/arm/mach-mx5/efika.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _EFIKA_H -#define _EFIKA_H - -#define EFIKA_WLAN_EN IMX_GPIO_NR(2, 16) -#define EFIKA_WLAN_RESET IMX_GPIO_NR(2, 10) -#define EFIKA_USB_PHY_RESET IMX_GPIO_NR(2, 9) - -void __init efika_board_common_init(void); - -#endif diff --git a/arch/arm/mach-mx5/ehci.c b/arch/arm/mach-mx5/ehci.c deleted file mode 100644 index c17fa13..0000000 --- a/arch/arm/mach-mx5/ehci.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2009 Daniel Mack - * Copyright (C) 2010 Freescale Semiconductor, Inc. - * - * 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 - -#define MXC_OTG_OFFSET 0 -#define MXC_H1_OFFSET 0x200 -#define MXC_H2_OFFSET 0x400 - -/* USB_CTRL */ -#define MXC_OTG_UCTRL_OWIE_BIT (1 << 27) /* OTG wakeup intr enable */ -#define MXC_OTG_UCTRL_OPM_BIT (1 << 24) /* OTG power mask */ -#define MXC_H1_UCTRL_H1UIE_BIT (1 << 12) /* Host1 ULPI interrupt enable */ -#define MXC_H1_UCTRL_H1WIE_BIT (1 << 11) /* HOST1 wakeup intr enable */ -#define MXC_H1_UCTRL_H1PM_BIT (1 << 8) /* HOST1 power mask */ - -/* USB_PHY_CTRL_FUNC */ -#define MXC_OTG_PHYCTRL_OC_DIS_BIT (1 << 8) /* OTG Disable Overcurrent Event */ -#define MXC_H1_OC_DIS_BIT (1 << 5) /* UH1 Disable Overcurrent Event */ - -/* USBH2CTRL */ -#define MXC_H2_UCTRL_H2UIE_BIT (1 << 8) -#define MXC_H2_UCTRL_H2WIE_BIT (1 << 7) -#define MXC_H2_UCTRL_H2PM_BIT (1 << 4) - -#define MXC_USBCMD_OFFSET 0x140 - -/* USBCMD */ -#define MXC_UCMD_ITC_NO_THRESHOLD_MASK (~(0xff << 16)) /* Interrupt Threshold Control */ - -int mx51_initialize_usb_hw(int port, unsigned int flags) -{ - unsigned int v; - void __iomem *usb_base; - void __iomem *usbotg_base; - void __iomem *usbother_base; - int ret = 0; - - usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); - if (!usb_base) { - printk(KERN_ERR "%s(): ioremap failed\n", __func__); - return -ENOMEM; - } - - switch (port) { - case 0: /* OTG port */ - usbotg_base = usb_base + MXC_OTG_OFFSET; - break; - case 1: /* Host 1 port */ - usbotg_base = usb_base + MXC_H1_OFFSET; - break; - case 2: /* Host 2 port */ - usbotg_base = usb_base + MXC_H2_OFFSET; - break; - default: - printk(KERN_ERR"%s no such port %d\n", __func__, port); - ret = -ENOENT; - goto error; - } - usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; - - switch (port) { - case 0: /*OTG port */ - if (flags & MXC_EHCI_INTERNAL_PHY) { - v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); - - if (flags & MXC_EHCI_POWER_PINS_ENABLED) { - /* OC/USBPWR is not used */ - v |= MXC_OTG_PHYCTRL_OC_DIS_BIT; - } else { - /* OC/USBPWR is used */ - v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT; - } - __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); - - v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET); - if (flags & MXC_EHCI_WAKEUP_ENABLED) - v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */ - else - v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */ - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - v |= MXC_OTG_UCTRL_OPM_BIT; - else - v &= ~MXC_OTG_UCTRL_OPM_BIT; - __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET); - } - break; - case 1: /* Host 1 */ - /*Host ULPI */ - v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET); - if (flags & MXC_EHCI_WAKEUP_ENABLED) { - /* HOST1 wakeup/ULPI intr enable */ - v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT); - } else { - /* HOST1 wakeup/ULPI intr disable */ - v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT); - } - - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/ - else - v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/ - __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET); - - v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */ - else - v |= MXC_H1_OC_DIS_BIT; /* OC is not used */ - __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET); - - v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET); - if (flags & MXC_EHCI_ITC_NO_THRESHOLD) - /* Interrupt Threshold Control:Immediate (no threshold) */ - v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK; - __raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET); - break; - case 2: /* Host 2 ULPI */ - v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET); - if (flags & MXC_EHCI_WAKEUP_ENABLED) { - /* HOST1 wakeup/ULPI intr enable */ - v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT); - } else { - /* HOST1 wakeup/ULPI intr disable */ - v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT); - } - - if (flags & MXC_EHCI_POWER_PINS_ENABLED) - v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/ - else - v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/ - __raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET); - break; - } - -error: - iounmap(usb_base); - return ret; -} - diff --git a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c deleted file mode 100644 index a6a3ab8..0000000 --- a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * - * Copyright (C) 2010 Eric Bénard - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include "devices-imx51.h" - -#define MBIMX51_TSC2007_GPIO IMX_GPIO_NR(3, 30) -#define MBIMX51_LED0 IMX_GPIO_NR(3, 5) -#define MBIMX51_LED1 IMX_GPIO_NR(3, 6) -#define MBIMX51_LED2 IMX_GPIO_NR(3, 7) -#define MBIMX51_LED3 IMX_GPIO_NR(3, 8) - -static const struct gpio_led mbimx51_leds[] __initconst = { - { - .name = "led0", - .default_trigger = "heartbeat", - .active_low = 1, - .gpio = MBIMX51_LED0, - }, - { - .name = "led1", - .default_trigger = "nand-disk", - .active_low = 1, - .gpio = MBIMX51_LED1, - }, - { - .name = "led2", - .default_trigger = "mmc0", - .active_low = 1, - .gpio = MBIMX51_LED2, - }, - { - .name = "led3", - .default_trigger = "default-on", - .active_low = 1, - .gpio = MBIMX51_LED3, - }, -}; - -static const struct gpio_led_platform_data mbimx51_leds_info __initconst = { - .leds = mbimx51_leds, - .num_leds = ARRAY_SIZE(mbimx51_leds), -}; - -static iomux_v3_cfg_t mbimx51_pads[] = { - /* UART2 */ - MX51_PAD_UART2_RXD__UART2_RXD, - MX51_PAD_UART2_TXD__UART2_TXD, - - /* UART3 */ - MX51_PAD_UART3_RXD__UART3_RXD, - MX51_PAD_UART3_TXD__UART3_TXD, - MX51_PAD_KEY_COL4__UART3_RTS, - MX51_PAD_KEY_COL5__UART3_CTS, - - /* TSC2007 IRQ */ - MX51_PAD_NANDF_D10__GPIO3_30, - - /* LEDS */ - MX51_PAD_DISPB2_SER_DIN__GPIO3_5, - MX51_PAD_DISPB2_SER_DIO__GPIO3_6, - MX51_PAD_DISPB2_SER_CLK__GPIO3_7, - MX51_PAD_DISPB2_SER_RS__GPIO3_8, - - /* KPP */ - MX51_PAD_KEY_ROW0__KEY_ROW0, - MX51_PAD_KEY_ROW1__KEY_ROW1, - MX51_PAD_KEY_ROW2__KEY_ROW2, - MX51_PAD_KEY_ROW3__KEY_ROW3, - MX51_PAD_KEY_COL0__KEY_COL0, - MX51_PAD_KEY_COL1__KEY_COL1, - MX51_PAD_KEY_COL2__KEY_COL2, - MX51_PAD_KEY_COL3__KEY_COL3, - - /* SD 1 */ - MX51_PAD_SD1_CMD__SD1_CMD, - MX51_PAD_SD1_CLK__SD1_CLK, - MX51_PAD_SD1_DATA0__SD1_DATA0, - MX51_PAD_SD1_DATA1__SD1_DATA1, - MX51_PAD_SD1_DATA2__SD1_DATA2, - MX51_PAD_SD1_DATA3__SD1_DATA3, - - /* SD 2 */ - MX51_PAD_SD2_CMD__SD2_CMD, - MX51_PAD_SD2_CLK__SD2_CLK, - MX51_PAD_SD2_DATA0__SD2_DATA0, - MX51_PAD_SD2_DATA1__SD2_DATA1, - MX51_PAD_SD2_DATA2__SD2_DATA2, - MX51_PAD_SD2_DATA3__SD2_DATA3, -}; - -static const struct imxuart_platform_data uart_pdata __initconst = { - .flags = IMXUART_HAVE_RTSCTS, -}; - -static int mbimx51_keymap[] = { - KEY(0, 0, KEY_1), - KEY(0, 1, KEY_2), - KEY(0, 2, KEY_3), - KEY(0, 3, KEY_UP), - - KEY(1, 0, KEY_4), - KEY(1, 1, KEY_5), - KEY(1, 2, KEY_6), - KEY(1, 3, KEY_LEFT), - - KEY(2, 0, KEY_7), - KEY(2, 1, KEY_8), - KEY(2, 2, KEY_9), - KEY(2, 3, KEY_RIGHT), - - KEY(3, 0, KEY_0), - KEY(3, 1, KEY_DOWN), - KEY(3, 2, KEY_ESC), - KEY(3, 3, KEY_ENTER), -}; - -static const struct matrix_keymap_data mbimx51_map_data __initconst = { - .keymap = mbimx51_keymap, - .keymap_size = ARRAY_SIZE(mbimx51_keymap), -}; - -static int tsc2007_get_pendown_state(void) -{ - return !gpio_get_value(MBIMX51_TSC2007_GPIO); -} - -struct tsc2007_platform_data tsc2007_data = { - .model = 2007, - .x_plate_ohms = 180, - .get_pendown_state = tsc2007_get_pendown_state, -}; - -static struct i2c_board_info mbimx51_i2c_devices[] = { - { - I2C_BOARD_INFO("tsc2007", 0x49), - .irq = IMX_GPIO_TO_IRQ(MBIMX51_TSC2007_GPIO), - .platform_data = &tsc2007_data, - }, { - I2C_BOARD_INFO("tlv320aic23", 0x1a), - }, -}; - -/* - * baseboard initialization. - */ -void __init eukrea_mbimx51_baseboard_init(void) -{ - mxc_iomux_v3_setup_multiple_pads(mbimx51_pads, - ARRAY_SIZE(mbimx51_pads)); - - imx51_add_imx_uart(1, NULL); - imx51_add_imx_uart(2, &uart_pdata); - - gpio_request(MBIMX51_LED0, "LED0"); - gpio_direction_output(MBIMX51_LED0, 1); - gpio_free(MBIMX51_LED0); - gpio_request(MBIMX51_LED1, "LED1"); - gpio_direction_output(MBIMX51_LED1, 1); - gpio_free(MBIMX51_LED1); - gpio_request(MBIMX51_LED2, "LED2"); - gpio_direction_output(MBIMX51_LED2, 1); - gpio_free(MBIMX51_LED2); - gpio_request(MBIMX51_LED3, "LED3"); - gpio_direction_output(MBIMX51_LED3, 1); - gpio_free(MBIMX51_LED3); - - gpio_led_register_device(-1, &mbimx51_leds_info); - - imx51_add_imx_keypad(&mbimx51_map_data); - - gpio_request(MBIMX51_TSC2007_GPIO, "tsc2007_irq"); - gpio_direction_input(MBIMX51_TSC2007_GPIO); - irq_set_irq_type(gpio_to_irq(MBIMX51_TSC2007_GPIO), - IRQF_TRIGGER_FALLING); - i2c_register_board_info(1, mbimx51_i2c_devices, - ARRAY_SIZE(mbimx51_i2c_devices)); - - imx51_add_sdhci_esdhc_imx(0, NULL); - imx51_add_sdhci_esdhc_imx(1, NULL); -} diff --git a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c deleted file mode 100644 index d817fc8..0000000 --- a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2010 Eric Benard - eric@eukrea.com - * - * Based on pcm970-baseboard.c which is : - * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de) - * - * 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., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "devices-imx51.h" - -static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = { - /* LED */ - MX51_PAD_NANDF_D10__GPIO3_30, - /* SWITCH */ - NEW_PAD_CTRL(MX51_PAD_NANDF_D9__GPIO3_31, PAD_CTL_PUS_22K_UP | - PAD_CTL_PKE | PAD_CTL_SRE_FAST | - PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS), - /* UART2 */ - MX51_PAD_UART2_RXD__UART2_RXD, - MX51_PAD_UART2_TXD__UART2_TXD, - /* UART 3 */ - MX51_PAD_UART3_RXD__UART3_RXD, - MX51_PAD_UART3_TXD__UART3_TXD, - MX51_PAD_KEY_COL4__UART3_RTS, - MX51_PAD_KEY_COL5__UART3_CTS, - /* SD */ - MX51_PAD_SD1_CMD__SD1_CMD, - MX51_PAD_SD1_CLK__SD1_CLK, - MX51_PAD_SD1_DATA0__SD1_DATA0, - MX51_PAD_SD1_DATA1__SD1_DATA1, - MX51_PAD_SD1_DATA2__SD1_DATA2, - MX51_PAD_SD1_DATA3__SD1_DATA3, - /* SD1 CD */ - NEW_PAD_CTRL(MX51_PAD_GPIO1_0__SD1_CD, PAD_CTL_PUS_22K_UP | - PAD_CTL_PKE | PAD_CTL_SRE_FAST | - PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS), -}; - -#define GPIO_LED1 IMX_GPIO_NR(3, 30) -#define GPIO_SWITCH1 IMX_GPIO_NR(3, 31) - -static const struct gpio_led eukrea_mbimxsd_leds[] __initconst = { - { - .name = "led1", - .default_trigger = "heartbeat", - .active_low = 1, - .gpio = GPIO_LED1, - }, -}; - -static const struct gpio_led_platform_data - eukrea_mbimxsd_led_info __initconst = { - .leds = eukrea_mbimxsd_leds, - .num_leds = ARRAY_SIZE(eukrea_mbimxsd_leds), -}; - -static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = { - { - .gpio = GPIO_SWITCH1, - .code = BTN_0, - .desc = "BP1", - .active_low = 1, - .wakeup = 1, - }, -}; - -static const struct gpio_keys_platform_data - eukrea_mbimxsd_button_data __initconst = { - .buttons = eukrea_mbimxsd_gpio_buttons, - .nbuttons = ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons), -}; - -static const struct imxuart_platform_data uart_pdata __initconst = { - .flags = IMXUART_HAVE_RTSCTS, -}; - -static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = { - { - I2C_BOARD_INFO("tlv320aic23", 0x1a), - }, -}; - -/* - * system init for baseboard usage. Will be called by cpuimx51sd init. - * - * Add platform devices present on this baseboard and init - * them from CPU side as far as required to use them later on - */ -void __init eukrea_mbimxsd51_baseboard_init(void) -{ - if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads, - ARRAY_SIZE(eukrea_mbimxsd_pads))) - printk(KERN_ERR "error setting mbimxsd pads !\n"); - - imx51_add_imx_uart(1, NULL); - imx51_add_imx_uart(2, &uart_pdata); - - imx51_add_sdhci_esdhc_imx(0, NULL); - - gpio_request(GPIO_LED1, "LED1"); - gpio_direction_output(GPIO_LED1, 1); - gpio_free(GPIO_LED1); - - gpio_request(GPIO_SWITCH1, "SWITCH1"); - gpio_direction_input(GPIO_SWITCH1); - gpio_free(GPIO_SWITCH1); - - i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices, - ARRAY_SIZE(eukrea_mbimxsd_i2c_devices)); - - gpio_led_register_device(-1, &eukrea_mbimxsd_led_info); - imx_add_gpio_keys(&eukrea_mbimxsd_button_data); -} diff --git a/arch/arm/mach-mx5/imx51-dt.c b/arch/arm/mach-mx5/imx51-dt.c deleted file mode 100644 index ccc6158..0000000 --- a/arch/arm/mach-mx5/imx51-dt.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright 2011 Linaro Ltd. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Lookup table for attaching a specific name and platform_data pointer to - * devices as they get created by of_platform_populate(). Ideally this table - * would not exist, but the current clock implementation depends on some devices - * having a specific name. - */ -static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = { - OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx21-uart.0", NULL), - OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx21-uart.1", NULL), - OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx21-uart.2", NULL), - OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "imx27-fec.0", NULL), - OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx51.0", NULL), - OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx51.1", NULL), - OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx51.2", NULL), - OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx51.3", NULL), - OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL), - OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL), - OF_DEV_AUXDATA("fsl,imx51-cspi", MX51_CSPI_BASE_ADDR, "imx35-cspi.0", NULL), - OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C1_BASE_ADDR, "imx-i2c.0", NULL), - OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C2_BASE_ADDR, "imx-i2c.1", NULL), - OF_DEV_AUXDATA("fsl,imx51-sdma", MX51_SDMA_BASE_ADDR, "imx35-sdma", NULL), - OF_DEV_AUXDATA("fsl,imx51-wdt", MX51_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL), - { /* sentinel */ } -}; - -static void __init imx51_tzic_add_irq_domain(struct device_node *np, - struct device_node *interrupt_parent) -{ - irq_domain_add_simple(np, 0); -} - -static void __init imx51_gpio_add_irq_domain(struct device_node *np, - struct device_node *interrupt_parent) -{ - static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS - - 32 * 4; /* imx51 gets 4 gpio ports */ - - irq_domain_add_simple(np, gpio_irq_base); - gpio_irq_base += 32; -} - -static const struct of_device_id imx51_irq_match[] __initconst = { - { .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, }, - { .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, }, - { /* sentinel */ } -}; - -static const struct of_device_id imx51_iomuxc_of_match[] __initconst = { - { .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, }, - { /* sentinel */ } -}; - -static void __init imx51_dt_init(void) -{ - struct device_node *node; - const struct of_device_id *of_id; - void (*func)(void); - - of_irq_init(imx51_irq_match); - - node = of_find_matching_node(NULL, imx51_iomuxc_of_match); - if (node) { - of_id = of_match_node(imx51_iomuxc_of_match, node); - func = of_id->data; - func(); - of_node_put(node); - } - - of_platform_populate(NULL, of_default_bus_match_table, - imx51_auxdata_lookup, NULL); -} - -static void __init imx51_timer_init(void) -{ - mx51_clocks_init_dt(); -} - -static struct sys_timer imx51_timer = { - .init = imx51_timer_init, -}; - -static const char *imx51_dt_board_compat[] __initdata = { - "fsl,imx51-babbage", - NULL -}; - -DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)") - .map_io = mx51_map_io, - .init_early = imx51_init_early, - .init_irq = mx51_init_irq, - .handle_irq = imx51_handle_irq, - .timer = &imx51_timer, - .init_machine = imx51_dt_init, - .dt_compat = imx51_dt_board_compat, -MACHINE_END diff --git a/arch/arm/mach-mx5/imx53-dt.c b/arch/arm/mach-mx5/imx53-dt.c deleted file mode 100644 index ccaa0b8..0000000 --- a/arch/arm/mach-mx5/imx53-dt.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright 2011 Linaro Ltd. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Lookup table for attaching a specific name and platform_data pointer to - * devices as they get created by of_platform_populate(). Ideally this table - * would not exist, but the current clock implementation depends on some devices - * having a specific name. - */ -static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = { - OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART1_BASE_ADDR, "imx21-uart.0", NULL), - OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART2_BASE_ADDR, "imx21-uart.1", NULL), - OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART3_BASE_ADDR, "imx21-uart.2", NULL), - OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART4_BASE_ADDR, "imx21-uart.3", NULL), - OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART5_BASE_ADDR, "imx21-uart.4", NULL), - OF_DEV_AUXDATA("fsl,imx53-fec", MX53_FEC_BASE_ADDR, "imx25-fec.0", NULL), - OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx53.0", NULL), - OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx53.1", NULL), - OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx53.2", NULL), - OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx53.3", NULL), - OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL), - OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL), - OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL), - OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL), - OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL), - OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL), - OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL), - OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL), - { /* sentinel */ } -}; - -static void __init imx53_tzic_add_irq_domain(struct device_node *np, - struct device_node *interrupt_parent) -{ - irq_domain_add_simple(np, 0); -} - -static void __init imx53_gpio_add_irq_domain(struct device_node *np, - struct device_node *interrupt_parent) -{ - static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS - - 32 * 7; /* imx53 gets 7 gpio ports */ - - irq_domain_add_simple(np, gpio_irq_base); - gpio_irq_base += 32; -} - -static const struct of_device_id imx53_irq_match[] __initconst = { - { .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, }, - { .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, }, - { /* sentinel */ } -}; - -static const struct of_device_id imx53_iomuxc_of_match[] __initconst = { - { .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, }, - { .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, }, - { .compatible = "fsl,imx53-iomuxc-qsb", .data = imx53_qsb_common_init, }, - { .compatible = "fsl,imx53-iomuxc-smd", .data = imx53_smd_common_init, }, - { /* sentinel */ } -}; - -static void __init imx53_dt_init(void) -{ - struct device_node *node; - const struct of_device_id *of_id; - void (*func)(void); - - of_irq_init(imx53_irq_match); - - node = of_find_matching_node(NULL, imx53_iomuxc_of_match); - if (node) { - of_id = of_match_node(imx53_iomuxc_of_match, node); - func = of_id->data; - func(); - of_node_put(node); - } - - of_platform_populate(NULL, of_default_bus_match_table, - imx53_auxdata_lookup, NULL); -} - -static void __init imx53_timer_init(void) -{ - mx53_clocks_init_dt(); -} - -static struct sys_timer imx53_timer = { - .init = imx53_timer_init, -}; - -static const char *imx53_dt_board_compat[] __initdata = { - "fsl,imx53-ard", - "fsl,imx53-evk", - "fsl,imx53-qsb", - "fsl,imx53-smd", - NULL -}; - -DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)") - .map_io = mx53_map_io, - .init_early = imx53_init_early, - .init_irq = mx53_init_irq, - .handle_irq = imx53_handle_irq, - .timer = &imx53_timer, - .init_machine = imx53_dt_init, - .dt_compat = imx53_dt_board_compat, -MACHINE_END diff --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c deleted file mode 100644 index 26eacc9..0000000 --- a/arch/arm/mach-mx5/mm.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - * - * Create static mapping between physical to virtual memory. - */ - -#include -#include - -#include - -#include -#include -#include -#include - -static void imx5_idle(void) -{ - mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); -} - -/* - * Define the MX50 memory map. - */ -static struct map_desc mx50_io_desc[] __initdata = { - imx_map_entry(MX50, TZIC, MT_DEVICE), - imx_map_entry(MX50, SPBA0, MT_DEVICE), - imx_map_entry(MX50, AIPS1, MT_DEVICE), - imx_map_entry(MX50, AIPS2, MT_DEVICE), -}; - -/* - * Define the MX51 memory map. - */ -static struct map_desc mx51_io_desc[] __initdata = { - imx_map_entry(MX51, TZIC, MT_DEVICE), - imx_map_entry(MX51, IRAM, MT_DEVICE), - imx_map_entry(MX51, AIPS1, MT_DEVICE), - imx_map_entry(MX51, SPBA0, MT_DEVICE), - imx_map_entry(MX51, AIPS2, MT_DEVICE), -}; - -/* - * Define the MX53 memory map. - */ -static struct map_desc mx53_io_desc[] __initdata = { - imx_map_entry(MX53, TZIC, MT_DEVICE), - imx_map_entry(MX53, AIPS1, MT_DEVICE), - imx_map_entry(MX53, SPBA0, MT_DEVICE), - imx_map_entry(MX53, AIPS2, MT_DEVICE), -}; - -/* - * This function initializes the memory map. It is called during the - * system startup to create static physical to virtual memory mappings - * for the IO modules. - */ -void __init mx50_map_io(void) -{ - iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc)); -} - -void __init mx51_map_io(void) -{ - iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc)); -} - -void __init mx53_map_io(void) -{ - iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc)); -} - -void __init imx50_init_early(void) -{ - mxc_set_cpu_type(MXC_CPU_MX50); - mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR)); - mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR)); -} - -void __init imx51_init_early(void) -{ - mxc_set_cpu_type(MXC_CPU_MX51); - mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR)); - mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR)); - imx_idle = imx5_idle; -} - -void __init imx53_init_early(void) -{ - mxc_set_cpu_type(MXC_CPU_MX53); - mxc_iomux_v3_init(MX53_IO_ADDRESS(MX53_IOMUXC_BASE_ADDR)); - mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR)); -} - -void __init mx50_init_irq(void) -{ - tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR)); -} - -void __init mx51_init_irq(void) -{ - tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR)); -} - -void __init mx53_init_irq(void) -{ - tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR)); -} - -static struct sdma_script_start_addrs imx51_sdma_script __initdata = { - .ap_2_ap_addr = 642, - .uart_2_mcu_addr = 817, - .mcu_2_app_addr = 747, - .mcu_2_shp_addr = 961, - .ata_2_mcu_addr = 1473, - .mcu_2_ata_addr = 1392, - .app_2_per_addr = 1033, - .app_2_mcu_addr = 683, - .shp_2_per_addr = 1251, - .shp_2_mcu_addr = 892, -}; - -static struct sdma_platform_data imx51_sdma_pdata __initdata = { - .fw_name = "sdma-imx51.bin", - .script_addrs = &imx51_sdma_script, -}; - -static struct sdma_script_start_addrs imx53_sdma_script __initdata = { - .ap_2_ap_addr = 642, - .app_2_mcu_addr = 683, - .mcu_2_app_addr = 747, - .uart_2_mcu_addr = 817, - .shp_2_mcu_addr = 891, - .mcu_2_shp_addr = 960, - .uartsh_2_mcu_addr = 1032, - .spdif_2_mcu_addr = 1100, - .mcu_2_spdif_addr = 1134, - .firi_2_mcu_addr = 1193, - .mcu_2_firi_addr = 1290, -}; - -static struct sdma_platform_data imx53_sdma_pdata __initdata = { - .fw_name = "sdma-imx53.bin", - .script_addrs = &imx53_sdma_script, -}; - -void __init imx50_soc_init(void) -{ - /* i.mx50 has the i.mx31 type gpio */ - mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH); - mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH); - mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH); - mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH); - mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH); - mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH); -} - -void __init imx51_soc_init(void) -{ - /* i.mx51 has the i.mx31 type gpio */ - mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH); - mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH); - mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH); - mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH); - - /* i.mx51 has the i.mx35 type sdma */ - imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata); -} - -void __init imx53_soc_init(void) -{ - /* i.mx53 has the i.mx31 type gpio */ - mxc_register_gpio("imx31-gpio", 0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH); - mxc_register_gpio("imx31-gpio", 1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH); - mxc_register_gpio("imx31-gpio", 2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH); - mxc_register_gpio("imx31-gpio", 3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH); - mxc_register_gpio("imx31-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH); - mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH); - mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH); - - /* i.mx53 has the i.mx35 type sdma */ - imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata); -} diff --git a/arch/arm/mach-mx5/mx51_efika.c b/arch/arm/mach-mx5/mx51_efika.c deleted file mode 100644 index ec6ca91..0000000 --- a/arch/arm/mach-mx5/mx51_efika.c +++ /dev/null @@ -1,632 +0,0 @@ -/* - * based on code from the following - * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved. - * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "devices-imx51.h" -#include "efika.h" -#include "cpu_op-mx51.h" - -#define MX51_USB_CTRL_1_OFFSET 0x10 -#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25) -#define MX51_USB_PLL_DIV_19_2_MHZ 0x01 - -#define EFIKAMX_USB_HUB_RESET IMX_GPIO_NR(1, 5) -#define EFIKAMX_USBH1_STP IMX_GPIO_NR(1, 27) - -#define EFIKAMX_SPI_CS0 IMX_GPIO_NR(4, 24) -#define EFIKAMX_SPI_CS1 IMX_GPIO_NR(4, 25) - -#define EFIKAMX_PMIC IMX_GPIO_NR(1, 6) - -static iomux_v3_cfg_t mx51efika_pads[] = { - /* UART1 */ - MX51_PAD_UART1_RXD__UART1_RXD, - MX51_PAD_UART1_TXD__UART1_TXD, - MX51_PAD_UART1_RTS__UART1_RTS, - MX51_PAD_UART1_CTS__UART1_CTS, - - /* SD 1 */ - MX51_PAD_SD1_CMD__SD1_CMD, - MX51_PAD_SD1_CLK__SD1_CLK, - MX51_PAD_SD1_DATA0__SD1_DATA0, - MX51_PAD_SD1_DATA1__SD1_DATA1, - MX51_PAD_SD1_DATA2__SD1_DATA2, - MX51_PAD_SD1_DATA3__SD1_DATA3, - - /* SD 2 */ - MX51_PAD_SD2_CMD__SD2_CMD, - MX51_PAD_SD2_CLK__SD2_CLK, - MX51_PAD_SD2_DATA0__SD2_DATA0, - MX51_PAD_SD2_DATA1__SD2_DATA1, - MX51_PAD_SD2_DATA2__SD2_DATA2, - MX51_PAD_SD2_DATA3__SD2_DATA3, - - /* SD/MMC WP/CD */ - MX51_PAD_GPIO1_0__SD1_CD, - MX51_PAD_GPIO1_1__SD1_WP, - MX51_PAD_GPIO1_7__SD2_WP, - MX51_PAD_GPIO1_8__SD2_CD, - - /* spi */ - MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI, - MX51_PAD_CSPI1_MISO__ECSPI1_MISO, - MX51_PAD_CSPI1_SS0__GPIO4_24, - MX51_PAD_CSPI1_SS1__GPIO4_25, - MX51_PAD_CSPI1_RDY__ECSPI1_RDY, - MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK, - MX51_PAD_GPIO1_6__GPIO1_6, - - /* USB HOST1 */ - MX51_PAD_USBH1_CLK__USBH1_CLK, - MX51_PAD_USBH1_DIR__USBH1_DIR, - MX51_PAD_USBH1_NXT__USBH1_NXT, - MX51_PAD_USBH1_DATA0__USBH1_DATA0, - MX51_PAD_USBH1_DATA1__USBH1_DATA1, - MX51_PAD_USBH1_DATA2__USBH1_DATA2, - MX51_PAD_USBH1_DATA3__USBH1_DATA3, - MX51_PAD_USBH1_DATA4__USBH1_DATA4, - MX51_PAD_USBH1_DATA5__USBH1_DATA5, - MX51_PAD_USBH1_DATA6__USBH1_DATA6, - MX51_PAD_USBH1_DATA7__USBH1_DATA7, - - /* USB HUB RESET */ - MX51_PAD_GPIO1_5__GPIO1_5, - - /* WLAN */ - MX51_PAD_EIM_A22__GPIO2_16, - MX51_PAD_EIM_A16__GPIO2_10, - - /* USB PHY RESET */ - MX51_PAD_EIM_D27__GPIO2_9, -}; - -/* Serial ports */ -static const struct imxuart_platform_data uart_pdata = { - .flags = IMXUART_HAVE_RTSCTS, -}; - -/* This function is board specific as the bit mask for the plldiv will also - * be different for other Freescale SoCs, thus a common bitmask is not - * possible and cannot get place in /plat-mxc/ehci.c. - */ -static int initialize_otg_port(struct platform_device *pdev) -{ - u32 v; - void __iomem *usb_base; - void __iomem *usbother_base; - usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); - if (!usb_base) - return -ENOMEM; - usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET); - - /* Set the PHY clock to 19.2MHz */ - v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); - v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK; - v |= MX51_USB_PLL_DIV_19_2_MHZ; - __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); - iounmap(usb_base); - - mdelay(10); - - return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY); -} - -static const struct mxc_usbh_platform_data dr_utmi_config __initconst = { - .init = initialize_otg_port, - .portsc = MXC_EHCI_UTMI_16BIT, -}; - -static int initialize_usbh1_port(struct platform_device *pdev) -{ - iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP; - iomux_v3_cfg_t usbh1gpio = MX51_PAD_USBH1_STP__GPIO1_27; - u32 v; - void __iomem *usb_base; - void __iomem *socregs_base; - - mxc_iomux_v3_setup_pad(usbh1gpio); - gpio_request(EFIKAMX_USBH1_STP, "usbh1_stp"); - gpio_direction_output(EFIKAMX_USBH1_STP, 0); - msleep(1); - gpio_set_value(EFIKAMX_USBH1_STP, 1); - msleep(1); - - usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); - socregs_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET); - - /* The clock for the USBH1 ULPI port will come externally */ - /* from the PHY. */ - v = __raw_readl(socregs_base + MX51_USB_CTRL_1_OFFSET); - __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, - socregs_base + MX51_USB_CTRL_1_OFFSET); - - iounmap(usb_base); - - gpio_free(EFIKAMX_USBH1_STP); - mxc_iomux_v3_setup_pad(usbh1stp); - - mdelay(10); - - return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD); -} - -static struct mxc_usbh_platform_data usbh1_config __initdata = { - .init = initialize_usbh1_port, - .portsc = MXC_EHCI_MODE_ULPI, -}; - -static void mx51_efika_hubreset(void) -{ - gpio_request(EFIKAMX_USB_HUB_RESET, "usb_hub_rst"); - gpio_direction_output(EFIKAMX_USB_HUB_RESET, 1); - msleep(1); - gpio_set_value(EFIKAMX_USB_HUB_RESET, 0); - msleep(1); - gpio_set_value(EFIKAMX_USB_HUB_RESET, 1); -} - -static void __init mx51_efika_usb(void) -{ - mx51_efika_hubreset(); - - /* pulling it low, means no USB at all... */ - gpio_request(EFIKA_USB_PHY_RESET, "usb_phy_reset"); - gpio_direction_output(EFIKA_USB_PHY_RESET, 0); - msleep(1); - gpio_set_value(EFIKA_USB_PHY_RESET, 1); - - usbh1_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS | - ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND); - - imx51_add_mxc_ehci_otg(&dr_utmi_config); - if (usbh1_config.otg) - imx51_add_mxc_ehci_hs(1, &usbh1_config); -} - -static struct mtd_partition mx51_efika_spi_nor_partitions[] = { - { - .name = "u-boot", - .offset = 0, - .size = SZ_256K, - }, - { - .name = "config", - .offset = MTDPART_OFS_APPEND, - .size = SZ_64K, - }, -}; - -static struct flash_platform_data mx51_efika_spi_flash_data = { - .name = "spi_flash", - .parts = mx51_efika_spi_nor_partitions, - .nr_parts = ARRAY_SIZE(mx51_efika_spi_nor_partitions), - .type = "sst25vf032b", -}; - -static struct regulator_consumer_supply sw1_consumers[] = { - { - .supply = "cpu_vcc", - } -}; - -static struct regulator_consumer_supply vdig_consumers[] = { - /* sgtl5000 */ - REGULATOR_SUPPLY("VDDA", "1-000a"), - REGULATOR_SUPPLY("VDDD", "1-000a"), -}; - -static struct regulator_consumer_supply vvideo_consumers[] = { - /* sgtl5000 */ - REGULATOR_SUPPLY("VDDIO", "1-000a"), -}; - -static struct regulator_consumer_supply vsd_consumers[] = { - REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.0"), - REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.1"), -}; - -static struct regulator_consumer_supply pwgt1_consumer[] = { - { - .supply = "pwgt1", - } -}; - -static struct regulator_consumer_supply pwgt2_consumer[] = { - { - .supply = "pwgt2", - } -}; - -static struct regulator_consumer_supply coincell_consumer[] = { - { - .supply = "coincell", - } -}; - -static struct regulator_init_data sw1_init = { - .constraints = { - .name = "SW1", - .min_uV = 600000, - .max_uV = 1375000, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, - .valid_modes_mask = 0, - .always_on = 1, - .boot_on = 1, - .state_mem = { - .uV = 850000, - .mode = REGULATOR_MODE_NORMAL, - .enabled = 1, - }, - }, - .num_consumer_supplies = ARRAY_SIZE(sw1_consumers), - .consumer_supplies = sw1_consumers, -}; - -static struct regulator_init_data sw2_init = { - .constraints = { - .name = "SW2", - .min_uV = 900000, - .max_uV = 1850000, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, - .always_on = 1, - .boot_on = 1, - .state_mem = { - .uV = 950000, - .mode = REGULATOR_MODE_NORMAL, - .enabled = 1, - }, - } -}; - -static struct regulator_init_data sw3_init = { - .constraints = { - .name = "SW3", - .min_uV = 1100000, - .max_uV = 1850000, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, - .always_on = 1, - .boot_on = 1, - } -}; - -static struct regulator_init_data sw4_init = { - .constraints = { - .name = "SW4", - .min_uV = 1100000, - .max_uV = 1850000, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, - .always_on = 1, - .boot_on = 1, - } -}; - -static struct regulator_init_data viohi_init = { - .constraints = { - .name = "VIOHI", - .boot_on = 1, - .always_on = 1, - } -}; - -static struct regulator_init_data vusb_init = { - .constraints = { - .name = "VUSB", - .boot_on = 1, - .always_on = 1, - } -}; - -static struct regulator_init_data swbst_init = { - .constraints = { - .name = "SWBST", - } -}; - -static struct regulator_init_data vdig_init = { - .constraints = { - .name = "VDIG", - .min_uV = 1050000, - .max_uV = 1800000, - .valid_ops_mask = - REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, - .boot_on = 1, - .always_on = 1, - }, - .num_consumer_supplies = ARRAY_SIZE(vdig_consumers), - .consumer_supplies = vdig_consumers, -}; - -static struct regulator_init_data vpll_init = { - .constraints = { - .name = "VPLL", - .min_uV = 1050000, - .max_uV = 1800000, - .valid_ops_mask = - REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, - .boot_on = 1, - .always_on = 1, - } -}; - -static struct regulator_init_data vusb2_init = { - .constraints = { - .name = "VUSB2", - .min_uV = 2400000, - .max_uV = 2775000, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, - .boot_on = 1, - .always_on = 1, - } -}; - -static struct regulator_init_data vvideo_init = { - .constraints = { - .name = "VVIDEO", - .min_uV = 2775000, - .max_uV = 2775000, - .valid_ops_mask = - REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, - .boot_on = 1, - .apply_uV = 1, - }, - .num_consumer_supplies = ARRAY_SIZE(vvideo_consumers), - .consumer_supplies = vvideo_consumers, -}; - -static struct regulator_init_data vaudio_init = { - .constraints = { - .name = "VAUDIO", - .min_uV = 2300000, - .max_uV = 3000000, - .valid_ops_mask = - REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, - .boot_on = 1, - } -}; - -static struct regulator_init_data vsd_init = { - .constraints = { - .name = "VSD", - .min_uV = 1800000, - .max_uV = 3150000, - .valid_ops_mask = - REGULATOR_CHANGE_VOLTAGE, - .boot_on = 1, - }, - .num_consumer_supplies = ARRAY_SIZE(vsd_consumers), - .consumer_supplies = vsd_consumers, -}; - -static struct regulator_init_data vcam_init = { - .constraints = { - .name = "VCAM", - .min_uV = 2500000, - .max_uV = 3000000, - .valid_ops_mask = - REGULATOR_CHANGE_VOLTAGE | - REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, - .valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL, - .boot_on = 1, - } -}; - -static struct regulator_init_data vgen1_init = { - .constraints = { - .name = "VGEN1", - .min_uV = 1200000, - .max_uV = 3150000, - .valid_ops_mask = - REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, - .boot_on = 1, - .always_on = 1, - } -}; - -static struct regulator_init_data vgen2_init = { - .constraints = { - .name = "VGEN2", - .min_uV = 1200000, - .max_uV = 3150000, - .valid_ops_mask = - REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, - .boot_on = 1, - .always_on = 1, - } -}; - -static struct regulator_init_data vgen3_init = { - .constraints = { - .name = "VGEN3", - .min_uV = 1800000, - .max_uV = 2900000, - .valid_ops_mask = - REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, - .boot_on = 1, - .always_on = 1, - } -}; - -static struct regulator_init_data gpo1_init = { - .constraints = { - .name = "GPO1", - } -}; - -static struct regulator_init_data gpo2_init = { - .constraints = { - .name = "GPO2", - } -}; - -static struct regulator_init_data gpo3_init = { - .constraints = { - .name = "GPO3", - } -}; - -static struct regulator_init_data gpo4_init = { - .constraints = { - .name = "GPO4", - } -}; - -static struct regulator_init_data pwgt1_init = { - .constraints = { - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - .boot_on = 1, - }, - .num_consumer_supplies = ARRAY_SIZE(pwgt1_consumer), - .consumer_supplies = pwgt1_consumer, -}; - -static struct regulator_init_data pwgt2_init = { - .constraints = { - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - .boot_on = 1, - }, - .num_consumer_supplies = ARRAY_SIZE(pwgt2_consumer), - .consumer_supplies = pwgt2_consumer, -}; - -static struct regulator_init_data vcoincell_init = { - .constraints = { - .name = "COINCELL", - .min_uV = 3000000, - .max_uV = 3000000, - .valid_ops_mask = - REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(coincell_consumer), - .consumer_supplies = coincell_consumer, -}; - -static struct mc13xxx_regulator_init_data mx51_efika_regulators[] = { - { .id = MC13892_SW1, .init_data = &sw1_init }, - { .id = MC13892_SW2, .init_data = &sw2_init }, - { .id = MC13892_SW3, .init_data = &sw3_init }, - { .id = MC13892_SW4, .init_data = &sw4_init }, - { .id = MC13892_SWBST, .init_data = &swbst_init }, - { .id = MC13892_VIOHI, .init_data = &viohi_init }, - { .id = MC13892_VPLL, .init_data = &vpll_init }, - { .id = MC13892_VDIG, .init_data = &vdig_init }, - { .id = MC13892_VSD, .init_data = &vsd_init }, - { .id = MC13892_VUSB2, .init_data = &vusb2_init }, - { .id = MC13892_VVIDEO, .init_data = &vvideo_init }, - { .id = MC13892_VAUDIO, .init_data = &vaudio_init }, - { .id = MC13892_VCAM, .init_data = &vcam_init }, - { .id = MC13892_VGEN1, .init_data = &vgen1_init }, - { .id = MC13892_VGEN2, .init_data = &vgen2_init }, - { .id = MC13892_VGEN3, .init_data = &vgen3_init }, - { .id = MC13892_VUSB, .init_data = &vusb_init }, - { .id = MC13892_GPO1, .init_data = &gpo1_init }, - { .id = MC13892_GPO2, .init_data = &gpo2_init }, - { .id = MC13892_GPO3, .init_data = &gpo3_init }, - { .id = MC13892_GPO4, .init_data = &gpo4_init }, - { .id = MC13892_PWGT1SPI, .init_data = &pwgt1_init }, - { .id = MC13892_PWGT2SPI, .init_data = &pwgt2_init }, - { .id = MC13892_VCOINCELL, .init_data = &vcoincell_init }, -}; - -static struct mc13xxx_platform_data mx51_efika_mc13892_data = { - .flags = MC13XXX_USE_RTC, - .regulators = { - .num_regulators = ARRAY_SIZE(mx51_efika_regulators), - .regulators = mx51_efika_regulators, - }, -}; - -static struct spi_board_info mx51_efika_spi_board_info[] __initdata = { - { - .modalias = "m25p80", - .max_speed_hz = 25000000, - .bus_num = 0, - .chip_select = 1, - .platform_data = &mx51_efika_spi_flash_data, - .irq = -1, - }, - { - .modalias = "mc13892", - .max_speed_hz = 1000000, - .bus_num = 0, - .chip_select = 0, - .platform_data = &mx51_efika_mc13892_data, - .irq = IMX_GPIO_TO_IRQ(EFIKAMX_PMIC), - }, -}; - -static int mx51_efika_spi_cs[] = { - EFIKAMX_SPI_CS0, - EFIKAMX_SPI_CS1, -}; - -static const struct spi_imx_master mx51_efika_spi_pdata __initconst = { - .chipselect = mx51_efika_spi_cs, - .num_chipselect = ARRAY_SIZE(mx51_efika_spi_cs), -}; - -void __init efika_board_common_init(void) -{ - mxc_iomux_v3_setup_multiple_pads(mx51efika_pads, - ARRAY_SIZE(mx51efika_pads)); - imx51_add_imx_uart(0, &uart_pdata); - mx51_efika_usb(); - - /* FIXME: comes from original code. check this. */ - if (mx51_revision() < IMX_CHIP_REVISION_2_0) - sw2_init.constraints.state_mem.uV = 1100000; - else if (mx51_revision() == IMX_CHIP_REVISION_2_0) { - sw2_init.constraints.state_mem.uV = 1250000; - sw1_init.constraints.state_mem.uV = 1000000; - } - if (machine_is_mx51_efikasb()) - vgen1_init.constraints.max_uV = 1200000; - - gpio_request(EFIKAMX_PMIC, "pmic irq"); - gpio_direction_input(EFIKAMX_PMIC); - spi_register_board_info(mx51_efika_spi_board_info, - ARRAY_SIZE(mx51_efika_spi_board_info)); - imx51_add_ecspi(0, &mx51_efika_spi_pdata); - - imx51_add_pata_imx(); - -#if defined(CONFIG_CPU_FREQ_IMX) - get_cpu_op = mx51_get_cpu_op; -#endif -} diff --git a/arch/arm/mach-mx5/pm-imx5.c b/arch/arm/mach-mx5/pm-imx5.c deleted file mode 100644 index 98052fc..0000000 --- a/arch/arm/mach-mx5/pm-imx5.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "crm_regs.h" - -static struct clk *gpc_dvfs_clk; - -static int mx5_suspend_prepare(void) -{ - return clk_enable(gpc_dvfs_clk); -} - -static int mx5_suspend_enter(suspend_state_t state) -{ - switch (state) { - case PM_SUSPEND_MEM: - mx5_cpu_lp_set(STOP_POWER_OFF); - break; - case PM_SUSPEND_STANDBY: - mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); - break; - default: - return -EINVAL; - } - - if (state == PM_SUSPEND_MEM) { - local_flush_tlb_all(); - flush_cache_all(); - - /*clear the EMPGC0/1 bits */ - __raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR); - __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR); - } - cpu_do_idle(); - return 0; -} - -static void mx5_suspend_finish(void) -{ - clk_disable(gpc_dvfs_clk); -} - -static int mx5_pm_valid(suspend_state_t state) -{ - return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX); -} - -static const struct platform_suspend_ops mx5_suspend_ops = { - .valid = mx5_pm_valid, - .prepare = mx5_suspend_prepare, - .enter = mx5_suspend_enter, - .finish = mx5_suspend_finish, -}; - -static int __init mx5_pm_init(void) -{ - if (gpc_dvfs_clk == NULL) - gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs"); - - if (!IS_ERR(gpc_dvfs_clk)) { - if (cpu_is_mx51()) - suspend_set_ops(&mx5_suspend_ops); - } else - return -EPERM; - - return 0; -} -device_initcall(mx5_pm_init); diff --git a/arch/arm/mach-mx5/system.c b/arch/arm/mach-mx5/system.c deleted file mode 100644 index 144ebeb..0000000 --- a/arch/arm/mach-mx5/system.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. - */ - -/* - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ -#include -#include -#include -#include -#include "crm_regs.h" - -/* set cpu low power mode before WFI instruction. This function is called - * mx5 because it can be used for mx50, mx51, and mx53.*/ -void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode) -{ - u32 plat_lpc, arm_srpgcr, ccm_clpcr; - u32 empgc0, empgc1; - int stop_mode = 0; - - /* always allow platform to issue a deep sleep mode request */ - plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) & - ~(MXC_CORTEXA8_PLAT_LPC_DSM); - ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK); - arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR); - empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR); - empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR); - - switch (mode) { - case WAIT_CLOCKED: - break; - case WAIT_UNCLOCKED: - ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET; - break; - case WAIT_UNCLOCKED_POWER_OFF: - case STOP_POWER_OFF: - plat_lpc |= MXC_CORTEXA8_PLAT_LPC_DSM - | MXC_CORTEXA8_PLAT_LPC_DBG_DSM; - if (mode == WAIT_UNCLOCKED_POWER_OFF) { - ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET; - ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY; - ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS; - stop_mode = 0; - } else { - ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET; - ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET; - ccm_clpcr |= MXC_CCM_CLPCR_VSTBY; - ccm_clpcr |= MXC_CCM_CLPCR_SBYOS; - stop_mode = 1; - } - arm_srpgcr |= MXC_SRPGCR_PCR; - - if (tzic_enable_wake(1) != 0) - return; - break; - case STOP_POWER_ON: - ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET; - break; - default: - printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode); - return; - } - - __raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC); - __raw_writel(ccm_clpcr, MXC_CCM_CLPCR); - __raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR); - - /* Enable NEON SRPG for all but MX50TO1.0. */ - if (mx50_revision() != IMX_CHIP_REVISION_1_0) - __raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR); - - if (stop_mode) { - empgc0 |= MXC_SRPGCR_PCR; - empgc1 |= MXC_SRPGCR_PCR; - - __raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR); - __raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR); - } -} diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig index a08a951..fdde4d1 100644 --- a/arch/arm/plat-mxc/Kconfig +++ b/arch/arm/plat-mxc/Kconfig @@ -17,25 +17,16 @@ config ARCH_IMX_V4_V5 and ARMv5 SoCs config ARCH_IMX_V6_V7 - bool "i.MX3, i.MX6" + bool "i.MX3, i.MX5, i.MX6" select AUTO_ZRELADDR if !ZBOOT_ROM select ARM_PATCH_PHYS_VIRT help - This enables support for systems based on the Freescale i.MX3 and i.MX6 - family. - -config ARCH_MX5 - bool "i.MX50, i.MX51, i.MX53" - select AUTO_ZRELADDR - select ARM_PATCH_PHYS_VIRT - help - This enables support for machines using Freescale's i.MX50 and i.MX53 - processors. + This enables support for systems based on the Freescale i.MX3, i.MX5 + and i.MX6 family. endchoice source "arch/arm/mach-imx/Kconfig" -source "arch/arm/mach-mx5/Kconfig" endmenu -- cgit v0.10.2 From 3f07f355704bc2ae26399f17c6d5d46c9a3d78d1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 8 Nov 2011 16:40:37 +0100 Subject: ARM i.MX: Update defconfig This updates the defconfig for i.MX3, i.MX5 and i.MX6. - all these can be compiled together now, so remove mx3_defconfig and mx5_defconfig and introduce a imx_v6_v7_defconfig instead. Signed-off-by: Sascha Hauer diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig new file mode 100644 index 0000000..3a4fb2e --- /dev/null +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -0,0 +1,193 @@ +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_KERNEL_LZO=y +CONFIG_SYSVIPC=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_RELAY=y +CONFIG_EXPERT=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_MXC=y +CONFIG_MACH_MX31LILLY=y +CONFIG_MACH_MX31LITE=y +CONFIG_MACH_PCM037=y +CONFIG_MACH_PCM037_EET=y +CONFIG_MACH_MX31_3DS=y +CONFIG_MACH_MX31MOBOARD=y +CONFIG_MACH_QONG=y +CONFIG_MACH_ARMADILLO5X0=y +CONFIG_MACH_KZM_ARM11_01=y +CONFIG_MACH_PCM043=y +CONFIG_MACH_MX35_3DS=y +CONFIG_MACH_EUKREA_CPUIMX35=y +CONFIG_MACH_VPR200=y +CONFIG_MACH_IMX51_DT=y +CONFIG_MACH_MX51_3DS=y +CONFIG_MACH_EUKREA_CPUIMX51=y +CONFIG_MACH_EUKREA_CPUIMX51SD=y +CONFIG_MACH_MX51_EFIKAMX=y +CONFIG_MACH_MX51_EFIKASB=y +CONFIG_MACH_IMX53_DT=y +CONFIG_SOC_IMX6Q=y +CONFIG_MXC_PWM=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_SMP=y +CONFIG_VMSPLIT_2G=y +CONFIG_PREEMPT_VOLUNTARY=y +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" +CONFIG_VFP=y +CONFIG_NEON=y +CONFIG_BINFMT_MISC=m +CONFIG_PM_DEBUG=y +CONFIG_PM_TEST_SUSPEND=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_IPV6=y +# CONFIG_WIRELESS is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_CONNECTOR=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=65536 +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_ATA=y +CONFIG_PATA_IMX=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_FEC=y +# 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_SMC91X=y +CONFIG_SMC911X=y +CONFIG_SMSC911X=y +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_WLAN is not set +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_EVBUG=m +CONFIG_KEYBOARD_GPIO=y +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_PS2_ELANTECH=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_MMA8450=y +CONFIG_SERIO_SERPORT=m +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_I2C=y +# CONFIG_I2C_COMPAT is not set +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m +CONFIG_I2C_IMX=y +CONFIG_SPI=y +CONFIG_SPI_IMX=y +CONFIG_GPIO_SYSFS=y +# CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_IMX2_WDT=y +CONFIG_MFD_MC13XXX=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_MC13892=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_MXC=y +CONFIG_USB_STORAGE=y +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_ESDHC_IMX=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +CONFIG_RTC_MXC=y +CONFIG_DMADEVICES=y +CONFIG_IMX_SDMA=y +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_PRINT_QUOTA_WARNING is not set +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_CONFIGFS_FS=m +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_UTF8=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_FS=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_FTRACE is not set +# CONFIG_ARM_UNWIND is not set +CONFIG_SECURITYFS=y +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_LZO=m +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_CRC_CCITT=m +CONFIG_CRC_T10DIF=y +CONFIG_CRC7=m +CONFIG_LIBCRC32C=m diff --git a/arch/arm/configs/mx3_defconfig b/arch/arm/configs/mx3_defconfig deleted file mode 100644 index cb0717f..0000000 --- a/arch/arm/configs/mx3_defconfig +++ /dev/null @@ -1,144 +0,0 @@ -CONFIG_EXPERIMENTAL=y -CONFIG_SYSVIPC=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_EXPERT=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_MXC=y -CONFIG_MACH_MX31ADS_WM1133_EV1=y -CONFIG_MACH_MX31LILLY=y -CONFIG_MACH_MX31LITE=y -CONFIG_MACH_PCM037=y -CONFIG_MACH_PCM037_EET=y -CONFIG_MACH_MX31_3DS=y -CONFIG_MACH_MX31MOBOARD=y -CONFIG_MACH_QONG=y -CONFIG_MACH_ARMADILLO5X0=y -CONFIG_MACH_KZM_ARM11_01=y -CONFIG_MACH_PCM043=y -CONFIG_MACH_MX35_3DS=y -CONFIG_MACH_EUKREA_CPUIMX35=y -CONFIG_MXC_IRQ_PRIOR=y -CONFIG_MXC_PWM=y -CONFIG_ARM_ERRATA_411920=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_PREEMPT=y -CONFIG_AEABI=y -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off" -CONFIG_VFP=y -CONFIG_PM_DEBUG=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_INET_DIAG is not set -# CONFIG_IPV6 is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_FW_LOADER=m -CONFIG_MTD=y -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -CONFIG_MTD_CFI=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_MXC=y -CONFIG_MTD_UBI=y -# CONFIG_BLK_DEV is not set -CONFIG_MISC_DEVICES=y -CONFIG_EEPROM_AT24=y -CONFIG_NETDEVICES=y -CONFIG_SMSC_PHY=y -CONFIG_NET_ETHERNET=y -CONFIG_SMSC911X=y -CONFIG_DNET=y -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_KEYBOARD_ATKBD is not set -CONFIG_KEYBOARD_IMX=y -# CONFIG_INPUT_MOUSE is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set -# CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_8250=m -CONFIG_SERIAL_8250_EXTENDED=y -CONFIG_SERIAL_8250_SHARE_IRQ=y -CONFIG_SERIAL_IMX=y -CONFIG_SERIAL_IMX_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_IMX=y -CONFIG_SPI=y -CONFIG_W1=y -CONFIG_W1_MASTER_MXC=y -CONFIG_W1_SLAVE_THERM=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_IMX2_WDT=y -CONFIG_MFD_WM8350_I2C=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_WM8350=y -CONFIG_MEDIA_SUPPORT=y -CONFIG_VIDEO_DEV=y -# CONFIG_RC_CORE is not set -# CONFIG_MEDIA_TUNER_CUSTOMISE is not set -CONFIG_SOC_CAMERA=y -CONFIG_SOC_CAMERA_MT9M001=y -CONFIG_SOC_CAMERA_MT9M111=y -CONFIG_SOC_CAMERA_MT9T031=y -CONFIG_SOC_CAMERA_MT9V022=y -CONFIG_SOC_CAMERA_TW9910=y -CONFIG_SOC_CAMERA_OV772X=y -CONFIG_VIDEO_MX3=y -# CONFIG_RADIO_ADAPTERS is not set -CONFIG_FB=y -CONFIG_SOUND=y -CONFIG_SND=y -# CONFIG_SND_ARM is not set -# CONFIG_SND_SPI is not set -CONFIG_SND_SOC=y -CONFIG_SND_IMX_SOC=y -CONFIG_SND_MXC_SOC_WM1133_EV1=y -CONFIG_SND_SOC_PHYCORE_AC97=y -CONFIG_SND_SOC_EUKREA_TLV320=y -CONFIG_USB=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_MXC=y -CONFIG_USB_GADGET=m -CONFIG_USB_FSL_USB2=m -CONFIG_USB_G_SERIAL=m -CONFIG_USB_ULPI=y -CONFIG_MMC=y -CONFIG_MMC_MXC=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_MXC=y -CONFIG_DMADEVICES=y -# CONFIG_DNOTIFY is not set -CONFIG_TMPFS=y -CONFIG_JFFS2_FS=y -CONFIG_UBIFS_FS=y -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -CONFIG_NFS_V4=y -CONFIG_ROOT_NFS=y -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y -# CONFIG_CRYPTO_ANSI_CPRNG is not set diff --git a/arch/arm/configs/mx5_defconfig b/arch/arm/configs/mx5_defconfig deleted file mode 100644 index d0d8dfe..0000000 --- a/arch/arm/configs/mx5_defconfig +++ /dev/null @@ -1,184 +0,0 @@ -CONFIG_EXPERIMENTAL=y -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_KERNEL_LZO=y -CONFIG_SYSVIPC=y -CONFIG_LOG_BUF_SHIFT=18 -CONFIG_RELAY=y -CONFIG_EXPERT=y -# CONFIG_SLUB_DEBUG is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODVERSIONS=y -CONFIG_MODULE_SRCVERSION_ALL=y -# CONFIG_LBDAF is not set -# CONFIG_BLK_DEV_BSG is not set -CONFIG_ARCH_MXC=y -CONFIG_ARCH_MX5=y -CONFIG_MACH_MX51_BABBAGE=y -CONFIG_MACH_MX51_3DS=y -CONFIG_MACH_EUKREA_CPUIMX51=y -CONFIG_MACH_EUKREA_CPUIMX51SD=y -CONFIG_MACH_MX51_EFIKAMX=y -CONFIG_MACH_MX51_EFIKASB=y -CONFIG_MACH_MX53_EVK=y -CONFIG_MACH_MX53_SMD=y -CONFIG_MACH_MX53_LOCO=y -CONFIG_MACH_MX53_ARD=y -CONFIG_MXC_PWM=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_VMSPLIT_2G=y -CONFIG_PREEMPT_VOLUNTARY=y -CONFIG_AEABI=y -# CONFIG_OABI_COMPAT is not set -CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 -CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" -CONFIG_VFP=y -CONFIG_NEON=y -CONFIG_BINFMT_MISC=m -CONFIG_PM_DEBUG=y -CONFIG_PM_TEST_SUSPEND=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_IPV6 is not set -# CONFIG_WIRELESS is not set -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -# CONFIG_STANDALONE is not set -CONFIG_CONNECTOR=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=65536 -# CONFIG_SCSI_PROC_FS is not set -CONFIG_BLK_DEV_SD=y -CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y -CONFIG_SCSI_SCAN_ASYNC=y -# CONFIG_SCSI_LOWLEVEL is not set -CONFIG_ATA=y -CONFIG_PATA_IMX=y -CONFIG_NETDEVICES=y -CONFIG_MII=m -CONFIG_MARVELL_PHY=y -CONFIG_DAVICOM_PHY=y -CONFIG_QSEMI_PHY=y -CONFIG_LXT_PHY=y -CONFIG_CICADA_PHY=y -CONFIG_VITESSE_PHY=y -CONFIG_SMSC_PHY=y -CONFIG_BROADCOM_PHY=y -CONFIG_ICPLUS_PHY=y -CONFIG_REALTEK_PHY=y -CONFIG_NATIONAL_PHY=y -CONFIG_STE10XP=y -CONFIG_LSI_ET1011C_PHY=y -CONFIG_MICREL_PHY=y -CONFIG_NET_ETHERNET=y -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 is not set -# CONFIG_WLAN is not set -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -CONFIG_INPUT_EVDEV=y -CONFIG_INPUT_EVBUG=m -CONFIG_KEYBOARD_GPIO=y -CONFIG_MOUSE_PS2=m -CONFIG_MOUSE_PS2_ELANTECH=y -CONFIG_INPUT_MISC=y -CONFIG_INPUT_MMA8450=y -CONFIG_SERIO_SERPORT=m -CONFIG_VT_HW_CONSOLE_BINDING=y -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_IMX=y -CONFIG_SERIAL_IMX_CONSOLE=y -CONFIG_HW_RANDOM=y -CONFIG_I2C=y -# CONFIG_I2C_COMPAT is not set -CONFIG_I2C_CHARDEV=y -# CONFIG_I2C_HELPER_AUTO is not set -CONFIG_I2C_ALGOBIT=m -CONFIG_I2C_ALGOPCF=m -CONFIG_I2C_ALGOPCA=m -CONFIG_I2C_IMX=y -CONFIG_SPI=y -CONFIG_SPI_IMX=y -CONFIG_GPIO_SYSFS=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -CONFIG_IMX2_WDT=y -CONFIG_MFD_MC13XXX=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_MC13892=y -CONFIG_USB=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_MXC=y -CONFIG_USB_STORAGE=y -CONFIG_MMC=y -CONFIG_MMC_BLOCK=m -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMC_SDHCI_ESDHC_IMX=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_INTF_DEV_UIE_EMUL=y -CONFIG_RTC_MXC=y -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -CONFIG_EXT4_FS=y -CONFIG_EXT4_FS_POSIX_ACL=y -CONFIG_EXT4_FS_SECURITY=y -CONFIG_QUOTA=y -CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set -CONFIG_AUTOFS4_FS=y -CONFIG_FUSE_FS=y -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_UDF_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=y -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=m -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -CONFIG_NFS_V3_ACL=y -CONFIG_NFS_V4=y -CONFIG_ROOT_NFS=y -CONFIG_NLS_DEFAULT="cp437" -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ASCII=y -CONFIG_NLS_ISO8859_1=y -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_UTF8=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_FS=y -# CONFIG_SCHED_DEBUG is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -# CONFIG_FTRACE is not set -# CONFIG_ARM_UNWIND is not set -CONFIG_SECURITYFS=y -CONFIG_CRYPTO_DEFLATE=m -CONFIG_CRYPTO_LZO=m -# CONFIG_CRYPTO_ANSI_CPRNG is not set -# CONFIG_CRYPTO_HW is not set -CONFIG_CRC_CCITT=m -CONFIG_CRC_T10DIF=y -CONFIG_CRC7=m -CONFIG_LIBCRC32C=m -- cgit v0.10.2 From 4e145349a1fe16ba8689553f0ffa5b223fba5327 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 16 Nov 2011 14:38:28 -0200 Subject: [media] em28xx: Fix some Terratec entries (H5 and XS) As reported by Andreas Oberritter , changeset 33ba28eebc3e1758e6adc1fcec9e1e3151bac453 did the wrong thing. Fix it to properly reflect the entries for Terratec H5 revs 1 and 2, and restore Terratec XS entry. Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index d8c8544..7734b2c 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -11,7 +11,7 @@ 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500] 11 -> Terratec Hybrid XS (em2880) 12 -> Kworld PVR TV 2800 RF (em2820/em2840) - 13 -> Terratec Prodigy XS (em2880) [0ccd:10ad] + 13 -> Terratec Prodigy XS (em2880) 14 -> SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0 (em2820/em2840) 15 -> V-Gear PocketTV (em2800) 16 -> Hauppauge WinTV HVR 950 (em2883) [2040:6513,2040:6517,2040:651b] @@ -41,7 +41,7 @@ 40 -> Plextor ConvertX PX-TV100U (em2861) [093b:a005] 41 -> Kworld 350 U DVB-T (em2870) [eb1a:e350] 42 -> Kworld 355 U DVB-T (em2870) [eb1a:e355,eb1a:e357] - 43 -> Terratec Cinergy T XS (em2870) + 43 -> Terratec Cinergy T XS (em2870) [0ccd:0043] 44 -> Terratec Cinergy T XS (MT2060) (em2870) 45 -> Pinnacle PCTV DVB-T (em2870) 46 -> Compro, VideoMate U3 (em2870) [185b:2870] @@ -76,5 +76,5 @@ 76 -> KWorld PlusTV 340U or UB435-Q (ATSC) (em2870) [1b80:a340] 77 -> EM2874 Leadership ISDBT (em2874) 78 -> PCTV nanoStick T2 290e (em28174) - 79 -> Terratec Cinergy H5 (em2884) [0ccd:0043,0ccd:10a2] + 79 -> Terratec Cinergy H5 (em2884) [0ccd:10a2,0ccd:10ad] 80 -> PCTV DVB-S2 Stick (460e) (em28174) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 9b747c2..19a5be3 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1914,11 +1914,11 @@ struct usb_device_id em28xx_id_table[] = { { USB_DEVICE(0x0ccd, 0x0042), .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS }, { USB_DEVICE(0x0ccd, 0x0043), + .driver_info = EM2870_BOARD_TERRATEC_XS }, + { USB_DEVICE(0x0ccd, 0x10a2), /* H5 Rev. 1 */ .driver_info = EM2884_BOARD_TERRATEC_H5 }, - { USB_DEVICE(0x0ccd, 0x10a2), /* Rev. 1 */ + { USB_DEVICE(0x0ccd, 0x10ad), /* H5 Rev. 2 */ .driver_info = EM2884_BOARD_TERRATEC_H5 }, - { USB_DEVICE(0x0ccd, 0x10ad), /* Rev. 2 */ - .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS }, { USB_DEVICE(0x0ccd, 0x0084), .driver_info = EM2860_BOARD_TERRATEC_AV350 }, { USB_DEVICE(0x0ccd, 0x0096), -- cgit v0.10.2 From dbb004294a934d030a9d716692a1dd6f677fc90e Mon Sep 17 00:00:00 2001 From: Ciaran McCormick Date: Mon, 31 Oct 2011 19:29:26 +0000 Subject: dma: fix spacing for method declaration, coding style issue in iop-adma.c Signed-off-by: Ciaran McCormick Signed-off-by: Vinod Koul diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index e03f811..686dc76 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c @@ -1746,12 +1746,12 @@ static struct platform_driver iop_adma_driver = { }, }; -static int __init iop_adma_init (void) +static int __init iop_adma_init(void) { return platform_driver_register(&iop_adma_driver); } -static void __exit iop_adma_exit (void) +static void __exit iop_adma_exit(void) { platform_driver_unregister(&iop_adma_driver); return; -- cgit v0.10.2 From 8e2d41f8c85613a3739e8b2600ac2c66c08422f3 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 24 Aug 2011 08:41:09 +0200 Subject: dma i.MX: remove individual SOC dependency The individual SoC dependency in Kconfig hardly scales anymore. Instead of having such a fine grained dependency just depend on ARCH_MXC and risk that the uninformed user has to look in the help text to figure out which driver is the correct one. Signed-off-by: Sascha Hauer Cc: Vinod Koul Signed-off-by: Vinod Koul diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index ab8f469..e514c45 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -124,7 +124,7 @@ config MV_XOR config MX3_IPU bool "MX3x Image Processing Unit support" - depends on ARCH_MX3 + depends on ARCH_MXC select DMA_ENGINE default y help @@ -216,11 +216,11 @@ config PCH_DMA config IMX_SDMA tristate "i.MX SDMA support" - depends on ARCH_MX25 || ARCH_MX3 || ARCH_MX5 + depends on ARCH_MXC select DMA_ENGINE help Support the i.MX SDMA engine. This engine is integrated into - Freescale i.MX25/31/35/51 chips. + Freescale i.MX25/31/35/51/53 chips. config IMX_DMA tristate "i.MX DMA support" -- cgit v0.10.2 From e79e72be298dc4726a641686032b8296c2fb473e Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Thu, 17 Nov 2011 16:14:22 +0900 Subject: pch_dma: Change company name OKI SEMICONDUCTOR to LAPIS Semiconductor On October 1 in 2011, OKI SEMICONDUCTOR Co., Ltd. changed the company name in to LAPIS Semiconductor Co., Ltd. Signed-off-by: Tomoya MORINAGA Signed-off-by: Vinod Koul diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index e514c45..606592e 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -201,13 +201,13 @@ config PL330_DMA platform_data for a dma-pl330 device. config PCH_DMA - tristate "Intel EG20T PCH / OKI Semi IOH(ML7213/ML7223) DMA support" + tristate "Intel EG20T PCH / LAPIS Semi IOH(ML7213/ML7223) DMA support" depends on PCI && X86 select DMA_ENGINE help Enable support for Intel EG20T PCH DMA engine. - This driver also can be used for OKI SEMICONDUCTOR IOH(Input/ + This driver also can be used for LAPIS Semiconductor IOH(Input/ Output Hub), ML7213 and ML7223. ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is for MP(Media Phone) use. diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c index a6d0e3d..a9b8a79 100644 --- a/drivers/dma/pch_dma.c +++ b/drivers/dma/pch_dma.c @@ -1,7 +1,7 @@ /* * Topcliff PCH DMA controller driver * Copyright (c) 2010 Intel Corporation - * Copyright (C) 2011 OKI SEMICONDUCTOR CO., LTD. + * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd. * * 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 @@ -1057,7 +1057,7 @@ static void __exit pch_dma_exit(void) module_init(pch_dma_init); module_exit(pch_dma_exit); -MODULE_DESCRIPTION("Intel EG20T PCH / OKI SEMICONDUCTOR ML7213 IOH " +MODULE_DESCRIPTION("Intel EG20T PCH / LAPIS Semiconductor ML7213/ML7223 IOH " "DMA controller driver"); MODULE_AUTHOR("Yong Wang "); MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From ca7fe2db892dcf91b2c72ee352eda4ff867903a7 Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Thu, 17 Nov 2011 16:14:23 +0900 Subject: pch_dma: Support new device LAPIS Semiconductor ML7831 IOH ML7831 is companion chip for Intel Atom E6xx series. Signed-off-by: Tomoya MORINAGA Signed-off-by: Vinod Koul diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 606592e..7ec0d6c 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -201,18 +201,18 @@ config PL330_DMA platform_data for a dma-pl330 device. config PCH_DMA - tristate "Intel EG20T PCH / LAPIS Semi IOH(ML7213/ML7223) DMA support" + tristate "Intel EG20T PCH / LAPIS Semicon IOH(ML7213/ML7223/ML7831) DMA" depends on PCI && X86 select DMA_ENGINE help Enable support for Intel EG20T PCH DMA engine. This driver also can be used for LAPIS Semiconductor IOH(Input/ - Output Hub), ML7213 and ML7223. - ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is - for MP(Media Phone) use. - ML7213/ML7223 is companion chip for Intel Atom E6xx series. - ML7213/ML7223 is completely compatible for Intel EG20T PCH. + Output Hub), ML7213, ML7223 and ML7831. + ML7213 IOH is for IVI(In-Vehicle Infotainment) use, ML7223 IOH is + for MP(Media Phone) use and ML7831 IOH is for general purpose use. + ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series. + ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH. config IMX_SDMA tristate "i.MX SDMA support" diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c index a9b8a79..60aca37 100644 --- a/drivers/dma/pch_dma.c +++ b/drivers/dma/pch_dma.c @@ -1018,6 +1018,8 @@ static void __devexit pch_dma_remove(struct pci_dev *pdev) #define PCI_DEVICE_ID_ML7223_DMA2_4CH 0x800E #define PCI_DEVICE_ID_ML7223_DMA3_4CH 0x8017 #define PCI_DEVICE_ID_ML7223_DMA4_4CH 0x803B +#define PCI_DEVICE_ID_ML7831_DMA1_8CH 0x8810 +#define PCI_DEVICE_ID_ML7831_DMA2_4CH 0x8815 DEFINE_PCI_DEVICE_TABLE(pch_dma_id_table) = { { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_EG20T_PCH_DMA_8CH), 8 }, @@ -1030,6 +1032,8 @@ DEFINE_PCI_DEVICE_TABLE(pch_dma_id_table) = { { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA2_4CH), 4}, /* Video SPI */ { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA3_4CH), 4}, /* Security */ { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA4_4CH), 4}, /* FPGA */ + { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_DMA1_8CH), 8}, /* UART */ + { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_DMA2_4CH), 4}, /* SPI */ { 0, }, }; @@ -1057,7 +1061,7 @@ static void __exit pch_dma_exit(void) module_init(pch_dma_init); module_exit(pch_dma_exit); -MODULE_DESCRIPTION("Intel EG20T PCH / LAPIS Semiconductor ML7213/ML7223 IOH " +MODULE_DESCRIPTION("Intel EG20T PCH / LAPIS Semicon ML7213/ML7223/ML7831 IOH " "DMA controller driver"); MODULE_AUTHOR("Yong Wang "); MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 8341544c9d95610f86b560333c7b22dd1096ca4f Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 21:50:31 +0530 Subject: USB-musb: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves usb/musb driver to use new enum Signed-off-by: Vinod Koul Cc: Felipe Balbi Cc: Greg Kroah-Hartman Acked-by: Felipe Balbi Acked-by: Mian Yousaf Kaukab diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index ef4333f..f8fd0dd 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -112,7 +112,7 @@ static bool ux500_configure_channel(struct dma_channel *channel, struct musb_hw_ep *hw_ep = ux500_channel->hw_ep; struct dma_chan *dma_chan = ux500_channel->dma_chan; struct dma_async_tx_descriptor *dma_desc; - enum dma_data_direction direction; + enum dma_transfer_direction direction; struct scatterlist sg; struct dma_slave_config slave_conf; enum dma_slave_buswidth addr_width; @@ -132,7 +132,7 @@ static bool ux500_configure_channel(struct dma_channel *channel, sg_dma_address(&sg) = dma_addr; sg_dma_len(&sg) = len; - direction = ux500_channel->is_tx ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + direction = ux500_channel->is_tx ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; addr_width = (len & 0x3) ? DMA_SLAVE_BUSWIDTH_1_BYTE : DMA_SLAVE_BUSWIDTH_4_BYTES; -- cgit v0.10.2 From 55ba4e5ed4ac57b60fe56acfd324f6a87123cc34 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 14 Oct 2011 21:57:58 +0530 Subject: USB-renesas: move to dma_transfer_direction fixup usage of dma direction by introducing dma_transfer_direction, this patch moves usb/renesas driver to use new enum Signed-off-by: Vinod Koul Cc: Felipe Balbi Cc: Greg Kroah-Hartman Acked-by: Felipe Balbi Acked-by: Kuninori Morimoto diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index a34430f..051c9a9 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -591,10 +591,10 @@ static void usbhsf_dma_prepare_tasklet(unsigned long data) struct dma_async_tx_descriptor *desc; struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt); struct device *dev = usbhs_priv_to_dev(priv); - enum dma_data_direction dir; + enum dma_transfer_direction dir; dma_cookie_t cookie; - dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + dir = usbhs_pipe_is_dir_in(pipe) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV; sg_init_table(&sg, 1); sg_set_page(&sg, virt_to_page(pkt->dma), -- cgit v0.10.2 From cb97914b04e7b587cf555ec5b1c69d61014f3378 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 11 Nov 2011 15:20:34 -0800 Subject: kbuild: Add support for installing generated asm headers Generated asm headers are supposed to live in arch/*/include/generated/asm, but objhdr-y expect them to live in the same directory they are generated in. Instead of trying to cut that particular Gordian knot, introduce genhdr-y that takes this into account; the sole user of objhdr-y, linux/version.h, should be migrated over at some later date. Suggested-by: David Woodhouse Acked-by: David Woodhouse Cc: Sam Ravnborg Cc: Michal Marek Signed-off-by: H. Peter Anvin diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst index a57f5bd..d3bae5e 100644 --- a/scripts/Makefile.headersinst +++ b/scripts/Makefile.headersinst @@ -4,12 +4,16 @@ # header-y - list files to be installed. They are preprocessed # to remove __KERNEL__ section of the file # objhdr-y - Same as header-y but for generated files +# genhdr-y - Same as objhdr-y but in a generated/ directory # # ========================================================================== # called may set destination dir (when installing to asm/) _dst := $(if $(dst),$(dst),$(obj)) +# generated header directory +gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj))) + kbuild-file := $(srctree)/$(obj)/Kbuild include $(kbuild-file) @@ -33,9 +37,10 @@ wrapper-files := $(filter $(header-y), $(generic-y)) # all headers files for this dir header-y := $(filter-out $(generic-y), $(header-y)) -all-files := $(header-y) $(objhdr-y) $(wrapper-files) +all-files := $(header-y) $(objhdr-y) $(genhdr-y) $(wrapper-files) input-files := $(addprefix $(srctree)/$(obj)/,$(header-y)) \ - $(addprefix $(objtree)/$(obj)/,$(objhdr-y)) + $(addprefix $(objtree)/$(obj)/,$(objhdr-y)) \ + $(addprefix $(objtree)/$(gen)/,$(genhdr-y)) output-files := $(addprefix $(install)/, $(all-files)) # Work out what needs to be removed @@ -52,6 +57,7 @@ quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\ cmd_install = \ $(PERL) $< $(srctree)/$(obj) $(install) $(SRCARCH) $(header-y); \ $(PERL) $< $(objtree)/$(obj) $(install) $(SRCARCH) $(objhdr-y); \ + $(PERL) $< $(objtree)/$(gen) $(install) $(SRCARCH) $(genhdr-y); \ for F in $(wrapper-files); do \ echo "\#include " > $(install)/$$F; \ done; \ -- cgit v0.10.2 From 052ad274964e613a12bf8ce7c5631f70d0bc82cc Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 17 Nov 2011 13:17:35 -0800 Subject: kbuild: Add support for an "archheaders" target Add support for an "archheaders" target. This target can generate files that need to be installed for user space by "make headers_install" or "make headers_install_all". In order to support "make headers_install_all", it must be able to run without the tree having to be configured first. Cc: David Woodhouse Cc: Sam Ravnborg Cc: Michal Marek Signed-off-by: H. Peter Anvin diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index f47cdef..ab0a984 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -33,14 +33,15 @@ This document describes the Linux kernel Makefiles. === 6 Architecture Makefiles --- 6.1 Set variables to tweak the build to the architecture - --- 6.2 Add prerequisites to archprepare: - --- 6.3 List directories to visit when descending - --- 6.4 Architecture-specific boot images - --- 6.5 Building non-kbuild targets - --- 6.6 Commands useful for building a boot image - --- 6.7 Custom kbuild commands - --- 6.8 Preprocessing linker scripts - --- 6.9 Generic header files + --- 6.2 Add prerequisites to archheaders: + --- 6.3 Add prerequisites to archprepare: + --- 6.4 List directories to visit when descending + --- 6.5 Architecture-specific boot images + --- 6.6 Building non-kbuild targets + --- 6.7 Commands useful for building a boot image + --- 6.8 Custom kbuild commands + --- 6.9 Preprocessing linker scripts + --- 6.10 Generic header files === 7 Kbuild syntax for exported headers --- 7.1 header-y @@ -252,7 +253,7 @@ more details, with real examples. This will create a library lib.a based on delay.o. For kbuild to actually recognize that there is a lib.a being built, the directory shall be listed in libs-y. - See also "6.3 List directories to visit when descending". + See also "6.4 List directories to visit when descending". Use of lib-y is normally restricted to lib/ and arch/*/lib. @@ -974,7 +975,20 @@ When kbuild executes, the following steps are followed (roughly): $(KBUILD_ARFLAGS) set by the top level Makefile to "D" (deterministic mode) if this option is supported by $(AR). ---- 6.2 Add prerequisites to archprepare: +--- 6.2 Add prerequisites to archheaders: + + The archheaders: rule is used to generate header files that + may be installed into user space by "make header_install" or + "make headers_install_all". In order to support + "make headers_install_all", this target has to be able to run + on an unconfigured tree, or a tree configured for another + architecture. + + It is run before "make archprepare" when run on the + architecture itself. + + +--- 6.3 Add prerequisites to archprepare: The archprepare: rule is used to list prerequisites that need to be built before starting to descend down in the subdirectories. @@ -990,7 +1004,7 @@ When kbuild executes, the following steps are followed (roughly): generating offset header files. ---- 6.3 List directories to visit when descending +--- 6.4 List directories to visit when descending An arch Makefile cooperates with the top Makefile to define variables which specify how to build the vmlinux file. Note that there is no @@ -1019,7 +1033,7 @@ When kbuild executes, the following steps are followed (roughly): drivers-$(CONFIG_OPROFILE) += arch/sparc64/oprofile/ ---- 6.4 Architecture-specific boot images +--- 6.5 Architecture-specific boot images An arch Makefile specifies goals that take the vmlinux file, compress it, wrap it in bootstrapping code, and copy the resulting files @@ -1070,7 +1084,7 @@ When kbuild executes, the following steps are followed (roughly): When "make" is executed without arguments, bzImage will be built. ---- 6.5 Building non-kbuild targets +--- 6.6 Building non-kbuild targets extra-y @@ -1090,7 +1104,7 @@ When kbuild executes, the following steps are followed (roughly): shall be built, but shall not be linked as part of built-in.o. ---- 6.6 Commands useful for building a boot image +--- 6.7 Commands useful for building a boot image Kbuild provides a few macros that are useful when building a boot image. @@ -1112,7 +1126,7 @@ When kbuild executes, the following steps are followed (roughly): always be built. Assignments to $(targets) are without $(obj)/ prefix. if_changed may be used in conjunction with custom commands as - defined in 6.7 "Custom kbuild commands". + defined in 6.8 "Custom kbuild commands". Note: It is a typical mistake to forget the FORCE prerequisite. Another common pitfall is that whitespace is sometimes @@ -1171,7 +1185,7 @@ When kbuild executes, the following steps are followed (roughly): $(obj)/%.dtb: $(src)/%.dts $(call cmd,dtc) ---- 6.7 Custom kbuild commands +--- 6.8 Custom kbuild commands When kbuild is executing with KBUILD_VERBOSE=0, then only a shorthand of a command is normally displayed. @@ -1198,7 +1212,7 @@ When kbuild executes, the following steps are followed (roughly): will be displayed with "make KBUILD_VERBOSE=0". ---- 6.8 Preprocessing linker scripts +--- 6.9 Preprocessing linker scripts When the vmlinux image is built, the linker script arch/$(ARCH)/kernel/vmlinux.lds is used. @@ -1228,7 +1242,7 @@ When kbuild executes, the following steps are followed (roughly): The kbuild infrastructure for *lds file are used in several architecture-specific files. ---- 6.9 Generic header files +--- 6.10 Generic header files The directory include/asm-generic contains the header files that may be shared between individual architectures. diff --git a/Makefile b/Makefile index dab8610..e5e0e07 100644 --- a/Makefile +++ b/Makefile @@ -442,7 +442,7 @@ asm-generic: no-dot-config-targets := clean mrproper distclean \ cscope gtags TAGS tags help %docs check% coccicheck \ - include/linux/version.h headers_% \ + include/linux/version.h headers_% archheaders \ kernelversion %src-pkg config-targets := 0 @@ -979,7 +979,7 @@ prepare1: prepare2 include/linux/version.h include/generated/utsrelease.h \ include/config/auto.conf $(cmd_crmodverdir) -archprepare: prepare1 scripts_basic +archprepare: archheaders prepare1 scripts_basic prepare0: archprepare FORCE $(Q)$(MAKE) $(build)=. @@ -1046,8 +1046,11 @@ hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj # If we do an all arch process set dst to asm-$(hdr-arch) hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm) +PHONY += archheaders +archheaders: + PHONY += __headers -__headers: include/linux/version.h scripts_basic asm-generic FORCE +__headers: include/linux/version.h scripts_basic asm-generic archheaders FORCE $(Q)$(MAKE) $(build)=scripts build_unifdef PHONY += headers_install_all diff --git a/scripts/headers.sh b/scripts/headers.sh index 978b42b..af1ed88 100755 --- a/scripts/headers.sh +++ b/scripts/headers.sh @@ -7,6 +7,7 @@ set -e do_command() { if [ -f ${srctree}/arch/$2/include/asm/Kbuild ]; then + make ARCH=$2 KBUILD_HEADERS=$1 archheaders make ARCH=$2 KBUILD_HEADERS=$1 headers_$1 else printf "Ignoring arch: %s\n" ${arch} -- cgit v0.10.2 From b7641d2c83aa10031bf45afd82619bfaaedcbc6f Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 11 Nov 2011 15:43:02 -0800 Subject: x86-64, syscall: Adjust comment spacing and remove typo Adjust spacing for comment so that it matches the multiline comment style used in the rest of the kernel, and remove word duplication. It is not really clear what version of gcc this refers to, but the extra & doesn't cause any harm, so there is no reason to remove it. Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/syscall_64.c b/arch/x86/kernel/syscall_64.c index de87d60..0edfafa 100644 --- a/arch/x86/kernel/syscall_64.c +++ b/arch/x86/kernel/syscall_64.c @@ -21,9 +21,9 @@ extern void sys_ni_syscall(void); const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { /* - *Smells like a like a compiler bug -- it doesn't work - *when the & below is removed. - */ + * Smells like a compiler bug -- it doesn't work + * when the & below is removed. + */ [0 ... __NR_syscall_max] = &sys_ni_syscall, #include }; -- cgit v0.10.2 From e79a7fccfb2ab10f8753ac634a1c8473e870ae6c Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 11 Nov 2011 15:48:42 -0800 Subject: x86-64, ia32: Move compat_ni_syscall into C and its own file Move compat_ni_syscall out of ia32entry.S and into its own .c file. Although this is a trivial function, it is not performance-critical, and this will simplify further cleanups. Signed-off-by: H. Peter Anvin diff --git a/arch/x86/ia32/Makefile b/arch/x86/ia32/Makefile index 52d0ccf..eea9a1c 100644 --- a/arch/x86/ia32/Makefile +++ b/arch/x86/ia32/Makefile @@ -3,6 +3,7 @@ # obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o +obj-$(CONFIG_IA32_EMULATION) += nosyscall.o sysv-$(CONFIG_SYSVIPC) := ipc32.o obj-$(CONFIG_IA32_EMULATION) += $(sysv-y) diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index a6253ec..59538a77 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -453,9 +453,6 @@ ia32_badsys: movq $-ENOSYS,%rax jmp ia32_sysret -quiet_ni_syscall: - movq $-ENOSYS,%rax - ret CFI_ENDPROC .macro PTREGSCALL label, func, arg diff --git a/arch/x86/ia32/nosyscall.c b/arch/x86/ia32/nosyscall.c new file mode 100644 index 0000000..51ecd5b --- /dev/null +++ b/arch/x86/ia32/nosyscall.c @@ -0,0 +1,7 @@ +#include +#include + +long compat_ni_syscall(void) +{ + return -ENOSYS; +} -- cgit v0.10.2 From d5e553d6e0a4bdea43adae7373e3fa144b9a1aaa Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 11 Nov 2011 15:52:52 -0800 Subject: trace: Include in trace_syscalls.c Include into trace_syscalls.c, to allow for NR_syscalls to be automatically generated. Cc: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Signed-off-by: H. Peter Anvin diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index cb65454..5f35f6f 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "trace_output.h" #include "trace.h" -- cgit v0.10.2 From d181764ccf6207e02abb95fb3052639b947f4833 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 11 Nov 2011 15:55:49 -0800 Subject: x86: Machine-readable syscall tables and scripts to process them Create a simple set of syscall tables and scripts to turn them into both header files (unistd_*.h) and macros for generating the system call tables. Signed-off-by: H. Peter Anvin diff --git a/arch/x86/syscalls/Makefile b/arch/x86/syscalls/Makefile new file mode 100644 index 0000000..564b247 --- /dev/null +++ b/arch/x86/syscalls/Makefile @@ -0,0 +1,43 @@ +out := $(obj)/../include/generated/asm + +# Create output directory if not already present +_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)') + +syscall32 := $(srctree)/$(src)/syscall_32.tbl +syscall64 := $(srctree)/$(src)/syscall_64.tbl + +syshdr := $(srctree)/$(src)/syscallhdr.sh +systbl := $(srctree)/$(src)/syscalltbl.sh + +quiet_cmd_syshdr = SYSHDR $@ + cmd_syshdr = $(CONFIG_SHELL) '$(syshdr)' $< $@ \ + $(syshdr_abi_$(basetarget)) $(syshdr_pfx_$(basetarget)) +quiet_cmd_systbl = SYSTBL $@ + cmd_systbl = $(CONFIG_SHELL) '$(systbl)' $< $@ + +syshdr_abi_unistd_32 := i386 +$(out)/unistd_32.h: $(syscall32) $(syshdr) + $(call if_changed,syshdr) + +syshdr_abi_unistd_32_ia32 := i386 +syshdr_pfx_unistd_32_ia32 := ia32_ +$(out)/unistd_32_ia32.h: $(syscall32) $(syshdr) + $(call if_changed,syshdr) + +syshdr_abi_unistd_64 := 64 +$(out)/unistd_64.h: $(syscall64) $(syshdr) + $(call if_changed,syshdr) + +$(out)/syscalls_32.h: $(syscall32) $(systbl) + $(call if_changed,systbl) +$(out)/syscalls_64.h: $(syscall64) $(systbl) + $(call if_changed,systbl) + +syshdr-y += unistd_32.h unistd_64.h +syshdr-y += syscalls_32.h +syshdr-$(CONFIG_X86_64) += unistd_32_ia32.h +syshdr-$(CONFIG_X86_64) += syscalls_64.h + +targets += $(syshdr-y) + +all: $(addprefix $(out)/,$(targets)) diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl new file mode 100644 index 0000000..ce98e28 --- /dev/null +++ b/arch/x86/syscalls/syscall_32.tbl @@ -0,0 +1,357 @@ +# +# 32-bit system call numbers and entry vectors +# +# The format is: +# +# +# The abi is always "i386" for this file. +# +0 i386 restart_syscall sys_restart_syscall +1 i386 exit sys_exit +2 i386 fork ptregs_fork stub32_fork +3 i386 read sys_read +4 i386 write sys_write +5 i386 open sys_open compat_sys_open +6 i386 close sys_close +7 i386 waitpid sys_waitpid sys32_waitpid +8 i386 creat sys_creat +9 i386 link sys_link +10 i386 unlink sys_unlink +11 i386 execve ptregs_execve stub32_execve +12 i386 chdir sys_chdir +13 i386 time sys_time compat_sys_time +14 i386 mknod sys_mknod +15 i386 chmod sys_chmod +16 i386 lchown sys_lchown16 +17 i386 break +18 i386 oldstat sys_stat +19 i386 lseek sys_lseek sys32_lseek +20 i386 getpid sys_getpid +21 i386 mount sys_mount compat_sys_mount +22 i386 umount sys_oldumount +23 i386 setuid sys_setuid16 +24 i386 getuid sys_getuid16 +25 i386 stime sys_stime compat_sys_stime +26 i386 ptrace sys_ptrace compat_sys_ptrace +27 i386 alarm sys_alarm +28 i386 oldfstat sys_fstat +29 i386 pause sys_pause +30 i386 utime sys_utime compat_sys_utime +31 i386 stty +32 i386 gtty +33 i386 access sys_access +34 i386 nice sys_nice +35 i386 ftime +36 i386 sync sys_sync +37 i386 kill sys_kill sys32_kill +38 i386 rename sys_rename +39 i386 mkdir sys_mkdir +40 i386 rmdir sys_rmdir +41 i386 dup sys_dup +42 i386 pipe sys_pipe +43 i386 times sys_times compat_sys_times +44 i386 prof +45 i386 brk sys_brk +46 i386 setgid sys_setgid16 +47 i386 getgid sys_getgid16 +48 i386 signal sys_signal +49 i386 geteuid sys_geteuid16 +50 i386 getegid sys_getegid16 +51 i386 acct sys_acct +52 i386 umount2 sys_umount +53 i386 lock +54 i386 ioctl sys_ioctl compat_sys_ioctl +55 i386 fcntl sys_fcntl compat_sys_fcntl64 +56 i386 mpx +57 i386 setpgid sys_setpgid +58 i386 ulimit +59 i386 oldolduname sys_olduname +60 i386 umask sys_umask +61 i386 chroot sys_chroot +62 i386 ustat sys_ustat compat_sys_ustat +63 i386 dup2 sys_dup2 +64 i386 getppid sys_getppid +65 i386 getpgrp sys_getpgrp +66 i386 setsid sys_setsid +67 i386 sigaction sys_sigaction sys32_sigaction +68 i386 sgetmask sys_sgetmask +69 i386 ssetmask sys_ssetmask +70 i386 setreuid sys_setreuid16 +71 i386 setregid sys_setregid16 +72 i386 sigsuspend sys_sigsuspend sys32_sigsuspend +73 i386 sigpending sys_sigpending compat_sys_sigpending +74 i386 sethostname sys_sethostname +75 i386 setrlimit sys_setrlimit compat_sys_setrlimit +76 i386 getrlimit sys_old_getrlimit compat_sys_old_getrlimit +77 i386 getrusage sys_getrusage compat_sys_getrusage +78 i386 gettimeofday sys_gettimeofday compat_sys_gettimeofday +79 i386 settimeofday sys_settimeofday compat_sys_settimeofday +80 i386 getgroups sys_getgroups16 +81 i386 setgroups sys_setgroups16 +82 i386 select sys_old_select compat_sys_old_select +83 i386 symlink sys_symlink +84 i386 oldlstat sys_lstat +85 i386 readlink sys_readlink +86 i386 uselib sys_uselib +87 i386 swapon sys_swapon +88 i386 reboot sys_reboot +89 i386 readdir sys_old_readdir compat_sys_old_readdir +90 i386 mmap sys_old_mmap sys32_mmap +91 i386 munmap sys_munmap +92 i386 truncate sys_truncate +93 i386 ftruncate sys_ftruncate +94 i386 fchmod sys_fchmod +95 i386 fchown sys_fchown16 +96 i386 getpriority sys_getpriority +97 i386 setpriority sys_setpriority +98 i386 profil +99 i386 statfs sys_statfs compat_sys_statfs +100 i386 fstatfs sys_fstatfs compat_sys_fstatfs +101 i386 ioperm sys_ioperm +102 i386 socketcall sys_socketcall compat_sys_socketcall +103 i386 syslog sys_syslog +104 i386 setitimer sys_setitimer compat_sys_setitimer +105 i386 getitimer sys_getitimer compat_sys_getitimer +106 i386 stat sys_newstat compat_sys_newstat +107 i386 lstat sys_newlstat compat_sys_newlstat +108 i386 fstat sys_newfstat compat_sys_newfstat +109 i386 olduname sys_uname +110 i386 iopl ptregs_iopl stub32_iopl +111 i386 vhangup sys_vhangup +112 i386 idle +113 i386 vm86old ptregs_vm86old sys32_vm86_warning +114 i386 wait4 sys_wait4 compat_sys_wait4 +115 i386 swapoff sys_swapoff +116 i386 sysinfo sys_sysinfo compat_sys_sysinfo +117 i386 ipc sys_ipc sys32_ipc +118 i386 fsync sys_fsync +119 i386 sigreturn ptregs_sigreturn stub32_sigreturn +120 i386 clone ptregs_clone stub32_clone +121 i386 setdomainname sys_setdomainname +122 i386 uname sys_newuname +123 i386 modify_ldt sys_modify_ldt +124 i386 adjtimex sys_adjtimex compat_sys_adjtimex +125 i386 mprotect sys_mprotect sys32_mprotect +126 i386 sigprocmask sys_sigprocmask compat_sys_sigprocmask +127 i386 create_module +128 i386 init_module sys_init_module +129 i386 delete_module sys_delete_module +130 i386 get_kernel_syms +131 i386 quotactl sys_quotactl sys32_quotactl +132 i386 getpgid sys_getpgid +133 i386 fchdir sys_fchdir +134 i386 bdflush sys_bdflush +135 i386 sysfs sys_sysfs +136 i386 personality sys_personality +137 i386 afs_syscall +138 i386 setfsuid sys_setfsuid16 +139 i386 setfsgid sys_setfsgid16 +140 i386 _llseek sys_llseek +141 i386 getdents sys_getdents compat_sys_getdents +142 i386 _newselect sys_select compat_sys_select +143 i386 flock sys_flock +144 i386 msync sys_msync +145 i386 readv sys_readv compat_sys_readv +146 i386 writev sys_writev compat_sys_writev +147 i386 getsid sys_getsid +148 i386 fdatasync sys_fdatasync +149 i386 _sysctl sys_sysctl compat_sys_sysctl +150 i386 mlock sys_mlock +151 i386 munlock sys_munlock +152 i386 mlockall sys_mlockall +153 i386 munlockall sys_munlockall +154 i386 sched_setparam sys_sched_setparam +155 i386 sched_getparam sys_sched_getparam +156 i386 sched_setscheduler sys_sched_setscheduler +157 i386 sched_getscheduler sys_sched_getscheduler +158 i386 sched_yield sys_sched_yield +159 i386 sched_get_priority_max sys_sched_get_priority_max +160 i386 sched_get_priority_min sys_sched_get_priority_min +161 i386 sched_rr_get_interval sys_sched_rr_get_interval sys32_sched_rr_get_interval +162 i386 nanosleep sys_nanosleep compat_sys_nanosleep +163 i386 mremap sys_mremap +164 i386 setresuid sys_setresuid16 +165 i386 getresuid sys_getresuid16 +166 i386 vm86 ptregs_vm86 sys32_vm86_warning +167 i386 query_module +168 i386 poll sys_poll +169 i386 nfsservctl +170 i386 setresgid sys_setresgid16 +171 i386 getresgid sys_getresgid16 +172 i386 prctl sys_prctl +173 i386 rt_sigreturn ptregs_rt_sigreturn stub32_rt_sigreturn +174 i386 rt_sigaction sys_rt_sigaction sys32_rt_sigaction +175 i386 rt_sigprocmask sys_rt_sigprocmask sys32_rt_sigprocmask +176 i386 rt_sigpending sys_rt_sigpending sys32_rt_sigpending +177 i386 rt_sigtimedwait sys_rt_sigtimedwait compat_sys_rt_sigtimedwait +178 i386 rt_sigqueueinfo sys_rt_sigqueueinfo sys32_rt_sigqueueinfo +179 i386 rt_sigsuspend sys_rt_sigsuspend +180 i386 pread64 sys_pread64 sys32_pread +181 i386 pwrite64 sys_pwrite64 sys32_pwrite +182 i386 chown sys_chown16 +183 i386 getcwd sys_getcwd +184 i386 capget sys_capget +185 i386 capset sys_capset +186 i386 sigaltstack ptregs_sigaltstack stub32_sigaltstack +187 i386 sendfile sys_sendfile sys32_sendfile +188 i386 getpmsg +189 i386 putpmsg +190 i386 vfork ptregs_vfork stub32_vfork +191 i386 ugetrlimit sys_getrlimit compat_sys_getrlimit +192 i386 mmap2 sys_mmap_pgoff +193 i386 truncate64 sys_truncate64 sys32_truncate64 +194 i386 ftruncate64 sys_ftruncate64 sys32_ftruncate64 +195 i386 stat64 sys_stat64 sys32_stat64 +196 i386 lstat64 sys_lstat64 sys32_lstat64 +197 i386 fstat64 sys_fstat64 sys32_fstat64 +198 i386 lchown32 sys_lchown +199 i386 getuid32 sys_getuid +200 i386 getgid32 sys_getgid +201 i386 geteuid32 sys_geteuid +202 i386 getegid32 sys_getegid +203 i386 setreuid32 sys_setreuid +204 i386 setregid32 sys_setregid +205 i386 getgroups32 sys_getgroups +206 i386 setgroups32 sys_setgroups +207 i386 fchown32 sys_fchown +208 i386 setresuid32 sys_setresuid +209 i386 getresuid32 sys_getresuid +210 i386 setresgid32 sys_setresgid +211 i386 getresgid32 sys_getresgid +212 i386 chown32 sys_chown +213 i386 setuid32 sys_setuid +214 i386 setgid32 sys_setgid +215 i386 setfsuid32 sys_setfsuid +216 i386 setfsgid32 sys_setfsgid +217 i386 pivot_root sys_pivot_root +218 i386 mincore sys_mincore +219 i386 madvise sys_madvise +220 i386 getdents64 sys_getdents64 compat_sys_getdents64 +221 i386 fcntl64 sys_fcntl64 compat_sys_fcntl64 +# 222 is unused +# 223 is unused +224 i386 gettid sys_gettid +225 i386 readahead sys_readahead sys32_readahead +226 i386 setxattr sys_setxattr +227 i386 lsetxattr sys_lsetxattr +228 i386 fsetxattr sys_fsetxattr +229 i386 getxattr sys_getxattr +230 i386 lgetxattr sys_lgetxattr +231 i386 fgetxattr sys_fgetxattr +232 i386 listxattr sys_listxattr +233 i386 llistxattr sys_llistxattr +234 i386 flistxattr sys_flistxattr +235 i386 removexattr sys_removexattr +236 i386 lremovexattr sys_lremovexattr +237 i386 fremovexattr sys_fremovexattr +238 i386 tkill sys_tkill +239 i386 sendfile64 sys_sendfile64 +240 i386 futex sys_futex compat_sys_futex +241 i386 sched_setaffinity sys_sched_setaffinity compat_sys_sched_setaffinity +242 i386 sched_getaffinity sys_sched_getaffinity compat_sys_sched_getaffinity +243 i386 set_thread_area sys_set_thread_area +244 i386 get_thread_area sys_get_thread_area +245 i386 io_setup sys_io_setup compat_sys_io_setup +246 i386 io_destroy sys_io_destroy +247 i386 io_getevents sys_io_getevents compat_sys_io_getevents +248 i386 io_submit sys_io_submit compat_sys_io_submit +249 i386 io_cancel sys_io_cancel +250 i386 fadvise64 sys_fadvise64 sys32_fadvise64 +# 251 is available for reuse (was briefly sys_set_zone_reclaim) +252 i386 exit_group sys_exit_group +253 i386 lookup_dcookie sys_lookup_dcookie sys32_lookup_dcookie +254 i386 epoll_create sys_epoll_create +255 i386 epoll_ctl sys_epoll_ctl +256 i386 epoll_wait sys_epoll_wait +257 i386 remap_file_pages sys_remap_file_pages +258 i386 set_tid_address sys_set_tid_address +259 i386 timer_create sys_timer_create compat_sys_timer_create +260 i386 timer_settime sys_timer_settime compat_sys_timer_settime +261 i386 timer_gettime sys_timer_gettime compat_sys_timer_gettime +262 i386 timer_getoverrun sys_timer_getoverrun +263 i386 timer_delete sys_timer_delete +264 i386 clock_settime sys_clock_settime compat_sys_clock_settime +265 i386 clock_gettime sys_clock_gettime compat_sys_clock_gettime +266 i386 clock_getres sys_clock_getres compat_sys_clock_getres +267 i386 clock_nanosleep sys_clock_nanosleep compat_sys_clock_nanosleep +268 i386 statfs64 sys_statfs64 compat_sys_statfs64 +269 i386 fstatfs64 sys_fstatfs64 compat_sys_fstatfs64 +270 i386 tgkill sys_tgkill +271 i386 utimes sys_utimes compat_sys_utimes +272 i386 fadvise64_64 sys_fadvise64_64 sys32_fadvise64_64 +273 i386 vserver +274 i386 mbind sys_mbind +275 i386 get_mempolicy sys_get_mempolicy compat_sys_get_mempolicy +276 i386 set_mempolicy sys_set_mempolicy +277 i386 mq_open sys_mq_open compat_sys_mq_open +278 i386 mq_unlink sys_mq_unlink +279 i386 mq_timedsend sys_mq_timedsend compat_sys_mq_timedsend +280 i386 mq_timedreceive sys_mq_timedreceive compat_sys_mq_timedreceive +281 i386 mq_notify sys_mq_notify compat_sys_mq_notify +282 i386 mq_getsetaddr sys_mq_getsetattr compat_sys_mq_getsetattr +283 i386 kexec_load sys_kexec_load compat_sys_kexec_load +284 i386 waitid sys_waitid compat_sys_waitid +# 285 sys_setaltroot +286 i386 add_key sys_add_key +287 i386 request_key sys_request_key +288 i386 keyctl sys_keyctl +289 i386 ioprio_set sys_ioprio_set +290 i386 ioprio_get sys_ioprio_get +291 i386 inotify_init sys_inotify_init +292 i386 inotify_add_watch sys_inotify_add_watch +293 i386 inotify_rm_watch sys_inotify_rm_watch +294 i386 migrate_pages sys_migrate_pages +295 i386 openat sys_openat compat_sys_openat +296 i386 mkdirat sys_mkdirat +297 i386 mknodat sys_mknodat +298 i386 fchownat sys_fchownat +299 i386 futimesat sys_futimesat compat_sys_futimesat +300 i386 fstatat64 sys_fstatat64 sys32_fstatat +301 i386 unlinkat sys_unlinkat +302 i386 renameat sys_renameat +303 i386 linkat sys_linkat +304 i386 symlinkat sys_symlinkat +305 i386 readlinkat sys_readlinkat +306 i386 fchmodat sys_fchmodat +307 i386 faccessat sys_faccessat +308 i386 pselect6 sys_pselect6 compat_sys_pselect6 +309 i386 ppoll sys_ppoll compat_sys_ppoll +310 i386 unshare sys_unshare +311 i386 set_robust_list sys_set_robust_list compat_sys_set_robust_list +312 i386 get_robust_list sys_get_robust_list compat_sys_get_robust_list +313 i386 splice sys_splice +314 i386 sync_file_range sys_sync_file_range sys32_sync_file_range +315 i386 tee sys_tee +316 i386 vmsplice sys_vmsplice compat_sys_vmsplice +317 i386 move_pages sys_move_pages compat_sys_move_pages +318 i386 getcpu sys_getcpu +319 i386 epoll_pwait sys_epoll_pwait +320 i386 utimensat sys_utimensat compat_sys_utimensat +321 i386 signalfd sys_signalfd compat_sys_signalfd +322 i386 timerfd_create sys_timerfd_create +323 i386 eventfd sys_eventfd +324 i386 fallocate sys_fallocate sys32_fallocate +325 i386 timerfd_settime sys_timerfd_settime compat_sys_timerfd_settime +326 i386 timerfd_gettime sys_timerfd_gettime compat_sys_timerfd_gettime +327 i386 signalfd4 sys_signalfd4 compat_sys_signalfd4 +328 i386 eventfd2 sys_eventfd2 +329 i386 epoll_create1 sys_epoll_create1 +330 i386 dup3 sys_dup3 +331 i386 pipe2 sys_pipe2 +332 i386 inotify_init1 sys_inotify_init1 +333 i386 preadv sys_preadv compat_sys_preadv +334 i386 pwritev sys_pwritev compat_sys_pwritev +335 i386 rt_tgsigqueueinfo sys_rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo +336 i386 perf_event_open sys_perf_event_open +337 i386 recvmmsg sys_recvmmsg compat_sys_recvmmsg +338 i386 fanotify_init sys_fanotify_init +339 i386 fanotify_mark sys_fanotify_mark sys32_fanotify_mark +340 i386 prlimit64 sys_prlimit64 +341 i386 name_to_handle_at sys_name_to_handle_at +342 i386 open_by_handle_at sys_open_by_handle_at compat_sys_open_by_handle_at +343 i386 clock_adjtime sys_clock_adjtime compat_sys_clock_adjtime +344 i386 syncfs sys_syncfs +345 i386 sendmmsg sys_sendmmsg compat_sys_sendmmsg +346 i386 setns sys_setns +347 i386 process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv +348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl new file mode 100644 index 0000000..b440a8f --- /dev/null +++ b/arch/x86/syscalls/syscall_64.tbl @@ -0,0 +1,320 @@ +# +# 64-bit system call numbers and entry vectors +# +# The format is: +# +# +# The abi is always "64" for this file (for now.) +# +0 64 read sys_read +1 64 write sys_write +2 64 open sys_open +3 64 close sys_close +4 64 stat sys_newstat +5 64 fstat sys_newfstat +6 64 lstat sys_newlstat +7 64 poll sys_poll +8 64 lseek sys_lseek +9 64 mmap sys_mmap +10 64 mprotect sys_mprotect +11 64 munmap sys_munmap +12 64 brk sys_brk +13 64 rt_sigaction sys_rt_sigaction +14 64 rt_sigprocmask sys_rt_sigprocmask +15 64 rt_sigreturn stub_rt_sigreturn +16 64 ioctl sys_ioctl +17 64 pread64 sys_pread64 +18 64 pwrite64 sys_pwrite64 +19 64 readv sys_readv +20 64 writev sys_writev +21 64 access sys_access +22 64 pipe sys_pipe +23 64 select sys_select +24 64 sched_yield sys_sched_yield +25 64 mremap sys_mremap +26 64 msync sys_msync +27 64 mincore sys_mincore +28 64 madvise sys_madvise +29 64 shmget sys_shmget +30 64 shmat sys_shmat +31 64 shmctl sys_shmctl +32 64 dup sys_dup +33 64 dup2 sys_dup2 +34 64 pause sys_pause +35 64 nanosleep sys_nanosleep +36 64 getitimer sys_getitimer +37 64 alarm sys_alarm +38 64 setitimer sys_setitimer +39 64 getpid sys_getpid +40 64 sendfile sys_sendfile64 +41 64 socket sys_socket +42 64 connect sys_connect +43 64 accept sys_accept +44 64 sendto sys_sendto +45 64 recvfrom sys_recvfrom +46 64 sendmsg sys_sendmsg +47 64 recvmsg sys_recvmsg +48 64 shutdown sys_shutdown +49 64 bind sys_bind +50 64 listen sys_listen +51 64 getsockname sys_getsockname +52 64 getpeername sys_getpeername +53 64 socketpair sys_socketpair +54 64 setsockopt sys_setsockopt +55 64 getsockopt sys_getsockopt +56 64 clone stub_clone +57 64 fork stub_fork +58 64 vfork stub_vfork +59 64 execve stub_execve +60 64 exit sys_exit +61 64 wait4 sys_wait4 +62 64 kill sys_kill +63 64 uname sys_newuname +64 64 semget sys_semget +65 64 semop sys_semop +66 64 semctl sys_semctl +67 64 shmdt sys_shmdt +68 64 msgget sys_msgget +69 64 msgsnd sys_msgsnd +70 64 msgrcv sys_msgrcv +71 64 msgctl sys_msgctl +72 64 fcntl sys_fcntl +73 64 flock sys_flock +74 64 fsync sys_fsync +75 64 fdatasync sys_fdatasync +76 64 truncate sys_truncate +77 64 ftruncate sys_ftruncate +78 64 getdents sys_getdents +79 64 getcwd sys_getcwd +80 64 chdir sys_chdir +81 64 fchdir sys_fchdir +82 64 rename sys_rename +83 64 mkdir sys_mkdir +84 64 rmdir sys_rmdir +85 64 creat sys_creat +86 64 link sys_link +87 64 unlink sys_unlink +88 64 symlink sys_symlink +89 64 readlink sys_readlink +90 64 chmod sys_chmod +91 64 fchmod sys_fchmod +92 64 chown sys_chown +93 64 fchown sys_fchown +94 64 lchown sys_lchown +95 64 umask sys_umask +96 64 gettimeofday sys_gettimeofday +97 64 getrlimit sys_getrlimit +98 64 getrusage sys_getrusage +99 64 sysinfo sys_sysinfo +100 64 times sys_times +101 64 ptrace sys_ptrace +102 64 getuid sys_getuid +103 64 syslog sys_syslog +104 64 getgid sys_getgid +105 64 setuid sys_setuid +106 64 setgid sys_setgid +107 64 geteuid sys_geteuid +108 64 getegid sys_getegid +109 64 setpgid sys_setpgid +110 64 getppid sys_getppid +111 64 getpgrp sys_getpgrp +112 64 setsid sys_setsid +113 64 setreuid sys_setreuid +114 64 setregid sys_setregid +115 64 getgroups sys_getgroups +116 64 setgroups sys_setgroups +117 64 setresuid sys_setresuid +118 64 getresuid sys_getresuid +119 64 setresgid sys_setresgid +120 64 getresgid sys_getresgid +121 64 getpgid sys_getpgid +122 64 setfsuid sys_setfsuid +123 64 setfsgid sys_setfsgid +124 64 getsid sys_getsid +125 64 capget sys_capget +126 64 capset sys_capset +127 64 rt_sigpending sys_rt_sigpending +128 64 rt_sigtimedwait sys_rt_sigtimedwait +129 64 rt_sigqueueinfo sys_rt_sigqueueinfo +130 64 rt_sigsuspend sys_rt_sigsuspend +131 64 sigaltstack stub_sigaltstack +132 64 utime sys_utime +133 64 mknod sys_mknod +134 64 uselib +135 64 personality sys_personality +136 64 ustat sys_ustat +137 64 statfs sys_statfs +138 64 fstatfs sys_fstatfs +139 64 sysfs sys_sysfs +140 64 getpriority sys_getpriority +141 64 setpriority sys_setpriority +142 64 sched_setparam sys_sched_setparam +143 64 sched_getparam sys_sched_getparam +144 64 sched_setscheduler sys_sched_setscheduler +145 64 sched_getscheduler sys_sched_getscheduler +146 64 sched_get_priority_max sys_sched_get_priority_max +147 64 sched_get_priority_min sys_sched_get_priority_min +148 64 sched_rr_get_interval sys_sched_rr_get_interval +149 64 mlock sys_mlock +150 64 munlock sys_munlock +151 64 mlockall sys_mlockall +152 64 munlockall sys_munlockall +153 64 vhangup sys_vhangup +154 64 modify_ldt sys_modify_ldt +155 64 pivot_root sys_pivot_root +156 64 _sysctl sys_sysctl +157 64 prctl sys_prctl +158 64 arch_prctl sys_arch_prctl +159 64 adjtimex sys_adjtimex +160 64 setrlimit sys_setrlimit +161 64 chroot sys_chroot +162 64 sync sys_sync +163 64 acct sys_acct +164 64 settimeofday sys_settimeofday +165 64 mount sys_mount +166 64 umount2 sys_umount +167 64 swapon sys_swapon +168 64 swapoff sys_swapoff +169 64 reboot sys_reboot +170 64 sethostname sys_sethostname +171 64 setdomainname sys_setdomainname +172 64 iopl stub_iopl +173 64 ioperm sys_ioperm +174 64 create_module +175 64 init_module sys_init_module +176 64 delete_module sys_delete_module +177 64 get_kernel_syms +178 64 query_module +179 64 quotactl sys_quotactl +180 64 nfsservctl +181 64 getpmsg +182 64 putpmsg +183 64 afs_syscall +184 64 tuxcall +185 64 security +186 64 gettid sys_gettid +187 64 readahead sys_readahead +188 64 setxattr sys_setxattr +189 64 lsetxattr sys_lsetxattr +190 64 fsetxattr sys_fsetxattr +191 64 getxattr sys_getxattr +192 64 lgetxattr sys_lgetxattr +193 64 fgetxattr sys_fgetxattr +194 64 listxattr sys_listxattr +195 64 llistxattr sys_llistxattr +196 64 flistxattr sys_flistxattr +197 64 removexattr sys_removexattr +198 64 lremovexattr sys_lremovexattr +199 64 fremovexattr sys_fremovexattr +200 64 tkill sys_tkill +201 64 time sys_time +202 64 futex sys_futex +203 64 sched_setaffinity sys_sched_setaffinity +204 64 sched_getaffinity sys_sched_getaffinity +205 64 set_thread_area +206 64 io_setup sys_io_setup +207 64 io_destroy sys_io_destroy +208 64 io_getevents sys_io_getevents +209 64 io_submit sys_io_submit +210 64 io_cancel sys_io_cancel +211 64 get_thread_area +212 64 lookup_dcookie sys_lookup_dcookie +213 64 epoll_create sys_epoll_create +214 64 epoll_ctl_old +215 64 epoll_wait_old +216 64 remap_file_pages sys_remap_file_pages +217 64 getdents64 sys_getdents64 +218 64 set_tid_address sys_set_tid_address +219 64 restart_syscall sys_restart_syscall +220 64 semtimedop sys_semtimedop +221 64 fadvise64 sys_fadvise64 +222 64 timer_create sys_timer_create +223 64 timer_settime sys_timer_settime +224 64 timer_gettime sys_timer_gettime +225 64 timer_getoverrun sys_timer_getoverrun +226 64 timer_delete sys_timer_delete +227 64 clock_settime sys_clock_settime +228 64 clock_gettime sys_clock_gettime +229 64 clock_getres sys_clock_getres +230 64 clock_nanosleep sys_clock_nanosleep +231 64 exit_group sys_exit_group +232 64 epoll_wait sys_epoll_wait +233 64 epoll_ctl sys_epoll_ctl +234 64 tgkill sys_tgkill +235 64 utimes sys_utimes +236 64 vserver +237 64 mbind sys_mbind +238 64 set_mempolicy sys_set_mempolicy +239 64 get_mempolicy sys_get_mempolicy +240 64 mq_open sys_mq_open +241 64 mq_unlink sys_mq_unlink +242 64 mq_timedsend sys_mq_timedsend +243 64 mq_timedreceive sys_mq_timedreceive +244 64 mq_notify sys_mq_notify +245 64 mq_getsetattr sys_mq_getsetattr +246 64 kexec_load sys_kexec_load +247 64 waitid sys_waitid +248 64 add_key sys_add_key +249 64 request_key sys_request_key +250 64 keyctl sys_keyctl +251 64 ioprio_set sys_ioprio_set +252 64 ioprio_get sys_ioprio_get +253 64 inotify_init sys_inotify_init +254 64 inotify_add_watch sys_inotify_add_watch +255 64 inotify_rm_watch sys_inotify_rm_watch +256 64 migrate_pages sys_migrate_pages +257 64 openat sys_openat +258 64 mkdirat sys_mkdirat +259 64 mknodat sys_mknodat +260 64 fchownat sys_fchownat +261 64 futimesat sys_futimesat +262 64 newfstatat sys_newfstatat +263 64 unlinkat sys_unlinkat +264 64 renameat sys_renameat +265 64 linkat sys_linkat +266 64 symlinkat sys_symlinkat +267 64 readlinkat sys_readlinkat +268 64 fchmodat sys_fchmodat +269 64 faccessat sys_faccessat +270 64 pselect6 sys_pselect6 +271 64 ppoll sys_ppoll +272 64 unshare sys_unshare +273 64 set_robust_list sys_set_robust_list +274 64 get_robust_list sys_get_robust_list +275 64 splice sys_splice +276 64 tee sys_tee +277 64 sync_file_range sys_sync_file_range +278 64 vmsplice sys_vmsplice +279 64 move_pages sys_move_pages +280 64 utimensat sys_utimensat +281 64 epoll_pwait sys_epoll_pwait +282 64 signalfd sys_signalfd +283 64 timerfd_create sys_timerfd_create +284 64 eventfd sys_eventfd +285 64 fallocate sys_fallocate +286 64 timerfd_settime sys_timerfd_settime +287 64 timerfd_gettime sys_timerfd_gettime +288 64 accept4 sys_accept4 +289 64 signalfd4 sys_signalfd4 +290 64 eventfd2 sys_eventfd2 +291 64 epoll_create1 sys_epoll_create1 +292 64 dup3 sys_dup3 +293 64 pipe2 sys_pipe2 +294 64 inotify_init1 sys_inotify_init1 +295 64 preadv sys_preadv +296 64 pwritev sys_pwritev +297 64 rt_tgsigqueueinfo sys_rt_tgsigqueueinfo +298 64 perf_event_open sys_perf_event_open +299 64 recvmmsg sys_recvmmsg +300 64 fanotify_init sys_fanotify_init +301 64 fanotify_mark sys_fanotify_mark +302 64 prlimit64 sys_prlimit64 +303 64 name_to_handle_at sys_name_to_handle_at +304 64 open_by_handle_at sys_open_by_handle_at +305 64 clock_adjtime sys_clock_adjtime +306 64 syncfs sys_syncfs +307 64 sendmmsg sys_sendmmsg +308 64 setns sys_setns +309 64 getcpu sys_getcpu +310 64 process_vm_readv sys_process_vm_readv +311 64 process_vm_writev sys_process_vm_writev diff --git a/arch/x86/syscalls/syscallhdr.sh b/arch/x86/syscalls/syscallhdr.sh new file mode 100644 index 0000000..0d473ff --- /dev/null +++ b/arch/x86/syscalls/syscallhdr.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +in="$1" +out="$2" +my_abis=`echo "$3" | tr ',' ' '` +prefix="$4" +offset="$5" + +fileguard=_ASM_X86_`basename "$out" | sed \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \ + -e 's/[^A-Z0-9_]/_/g' -e 's/__/_/g'` + +in_list () { + local x + for x in $1; do + if [ x"$x" = x"$2" ]; then + return 0 + fi + done + return 1 +} + +grep '^[0-9]' "$in" | sort -n | ( + echo "#ifndef ${fileguard}" + echo "#define ${fileguard} 1" + echo "" + + while read nr abi name entry ; do + if in_list "$my_abis" "$abi"; then + echo "#define __NR_${prefix}${name}" $((nr+offset)) + fi + done + + echo "" + echo "#endif /* ${fileguard} */" +) > "$out" diff --git a/arch/x86/syscalls/syscalltbl.sh b/arch/x86/syscalls/syscalltbl.sh new file mode 100644 index 0000000..0e7f8ec --- /dev/null +++ b/arch/x86/syscalls/syscalltbl.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +in="$1" +out="$2" + +grep '^[0-9]' "$in" | sort -n | ( + while read nr abi name entry compat; do + abi=`echo "$abi" | tr '[a-z]' '[A-Z]'` + if [ -n "$compat" ]; then + echo "__SYSCALL_${abi}($nr, $entry, $compat)" + elif [ -n "$entry" ]; then + echo "__SYSCALL_${abi}($nr, $entry, $entry)" + fi + done +) > "$out" -- cgit v0.10.2 From 29dc54c673ea2531d589400badb4ada5f5f60dae Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 11 Nov 2011 15:57:53 -0800 Subject: checksyscalls: Use arch/x86/syscalls/syscall_32.tbl as source Use the new arch/x86/syscalls/syscall_32.tbl file as source instead of arch/x86/include/asm/unistd_32.h. Cc: Michal Marek Cc: Geert Uytterhoeven Cc: Sam Ravnborg Signed-off-by: H. Peter Anvin diff --git a/scripts/checksyscalls.sh b/scripts/checksyscalls.sh index 3ab316e..d24810f 100755 --- a/scripts/checksyscalls.sh +++ b/scripts/checksyscalls.sh @@ -198,11 +198,16 @@ EOF } syscall_list() { -sed -n -e '/^\#define/ s/[^_]*__NR_\([^[:space:]]*\).*/\ -\#if !defined \(__NR_\1\) \&\& !defined \(__IGNORE_\1\)\ -\#warning syscall \1 not implemented\ -\#endif/p' $1 + grep '^[0-9]' "$1" | sort -n | ( + while read nr abi name entry ; do + echo < /dev/null -- cgit v0.10.2 From 303395ac3bf3e2cb488435537d416bc840438fcb Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 11 Nov 2011 16:07:41 -0800 Subject: x86: Generate system call tables and unistd_*.h from tables Generate system call tables and unistd_*.h automatically from the tables in arch/x86/syscalls. All other information, like NR_syscalls, is auto-generated, some of which is in asm-offsets_*.c. This allows us to keep all the system call information in one place, and allows for kernel space and user space to see different information; this is currently used for the ia32 system call numbers when building the 64-bit kernel, but will be used by the x32 ABI in the near future. This also removes some gratuitious differences between i386, x86-64 and ia32; in particular, now all system call tables are generated with the same mechanism. Cc: H. J. Lu Cc: Sam Ravnborg Cc: Michal Marek Signed-off-by: H. Peter Anvin diff --git a/arch/x86/Makefile b/arch/x86/Makefile index b02e509..209ba12 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -118,6 +118,12 @@ KBUILD_CFLAGS += $(mflags-y) KBUILD_AFLAGS += $(mflags-y) ### +# Syscall table generation + +archheaders: + $(Q)$(MAKE) $(build)=arch/x86/syscalls all + +### # Kernel objects head-y := arch/x86/kernel/head_$(BITS).o diff --git a/arch/x86/ia32/Makefile b/arch/x86/ia32/Makefile index eea9a1c..455646e 100644 --- a/arch/x86/ia32/Makefile +++ b/arch/x86/ia32/Makefile @@ -3,7 +3,7 @@ # obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o -obj-$(CONFIG_IA32_EMULATION) += nosyscall.o +obj-$(CONFIG_IA32_EMULATION) += nosyscall.o syscall_ia32.o sysv-$(CONFIG_SYSVIPC) := ipc32.o obj-$(CONFIG_IA32_EMULATION) += $(sysv-y) diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 59538a77..72f853a 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -27,8 +27,6 @@ .section .entry.text, "ax" -#define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8) - .macro IA32_ARG_FIXUP noebp=0 movl %edi,%r8d .if \noebp @@ -496,357 +494,3 @@ ENTRY(ia32_ptregs_common) jmp ia32_sysret /* misbalances the return cache */ CFI_ENDPROC END(ia32_ptregs_common) - - .section .rodata,"a" - .align 8 -ia32_sys_call_table: - .quad sys_restart_syscall - .quad sys_exit - .quad stub32_fork - .quad sys_read - .quad sys_write - .quad compat_sys_open /* 5 */ - .quad sys_close - .quad sys32_waitpid - .quad sys_creat - .quad sys_link - .quad sys_unlink /* 10 */ - .quad stub32_execve - .quad sys_chdir - .quad compat_sys_time - .quad sys_mknod - .quad sys_chmod /* 15 */ - .quad sys_lchown16 - .quad quiet_ni_syscall /* old break syscall holder */ - .quad sys_stat - .quad sys32_lseek - .quad sys_getpid /* 20 */ - .quad compat_sys_mount /* mount */ - .quad sys_oldumount /* old_umount */ - .quad sys_setuid16 - .quad sys_getuid16 - .quad compat_sys_stime /* stime */ /* 25 */ - .quad compat_sys_ptrace /* ptrace */ - .quad sys_alarm - .quad sys_fstat /* (old)fstat */ - .quad sys_pause - .quad compat_sys_utime /* 30 */ - .quad quiet_ni_syscall /* old stty syscall holder */ - .quad quiet_ni_syscall /* old gtty syscall holder */ - .quad sys_access - .quad sys_nice - .quad quiet_ni_syscall /* 35 */ /* old ftime syscall holder */ - .quad sys_sync - .quad sys32_kill - .quad sys_rename - .quad sys_mkdir - .quad sys_rmdir /* 40 */ - .quad sys_dup - .quad sys_pipe - .quad compat_sys_times - .quad quiet_ni_syscall /* old prof syscall holder */ - .quad sys_brk /* 45 */ - .quad sys_setgid16 - .quad sys_getgid16 - .quad sys_signal - .quad sys_geteuid16 - .quad sys_getegid16 /* 50 */ - .quad sys_acct - .quad sys_umount /* new_umount */ - .quad quiet_ni_syscall /* old lock syscall holder */ - .quad compat_sys_ioctl - .quad compat_sys_fcntl64 /* 55 */ - .quad quiet_ni_syscall /* old mpx syscall holder */ - .quad sys_setpgid - .quad quiet_ni_syscall /* old ulimit syscall holder */ - .quad sys_olduname - .quad sys_umask /* 60 */ - .quad sys_chroot - .quad compat_sys_ustat - .quad sys_dup2 - .quad sys_getppid - .quad sys_getpgrp /* 65 */ - .quad sys_setsid - .quad sys32_sigaction - .quad sys_sgetmask - .quad sys_ssetmask - .quad sys_setreuid16 /* 70 */ - .quad sys_setregid16 - .quad sys32_sigsuspend - .quad compat_sys_sigpending - .quad sys_sethostname - .quad compat_sys_setrlimit /* 75 */ - .quad compat_sys_old_getrlimit /* old_getrlimit */ - .quad compat_sys_getrusage - .quad compat_sys_gettimeofday - .quad compat_sys_settimeofday - .quad sys_getgroups16 /* 80 */ - .quad sys_setgroups16 - .quad compat_sys_old_select - .quad sys_symlink - .quad sys_lstat - .quad sys_readlink /* 85 */ - .quad sys_uselib - .quad sys_swapon - .quad sys_reboot - .quad compat_sys_old_readdir - .quad sys32_mmap /* 90 */ - .quad sys_munmap - .quad sys_truncate - .quad sys_ftruncate - .quad sys_fchmod - .quad sys_fchown16 /* 95 */ - .quad sys_getpriority - .quad sys_setpriority - .quad quiet_ni_syscall /* old profil syscall holder */ - .quad compat_sys_statfs - .quad compat_sys_fstatfs /* 100 */ - .quad sys_ioperm - .quad compat_sys_socketcall - .quad sys_syslog - .quad compat_sys_setitimer - .quad compat_sys_getitimer /* 105 */ - .quad compat_sys_newstat - .quad compat_sys_newlstat - .quad compat_sys_newfstat - .quad sys_uname - .quad stub32_iopl /* 110 */ - .quad sys_vhangup - .quad quiet_ni_syscall /* old "idle" system call */ - .quad sys32_vm86_warning /* vm86old */ - .quad compat_sys_wait4 - .quad sys_swapoff /* 115 */ - .quad compat_sys_sysinfo - .quad sys32_ipc - .quad sys_fsync - .quad stub32_sigreturn - .quad stub32_clone /* 120 */ - .quad sys_setdomainname - .quad sys_newuname - .quad sys_modify_ldt - .quad compat_sys_adjtimex - .quad sys32_mprotect /* 125 */ - .quad compat_sys_sigprocmask - .quad quiet_ni_syscall /* create_module */ - .quad sys_init_module - .quad sys_delete_module - .quad quiet_ni_syscall /* 130 get_kernel_syms */ - .quad sys32_quotactl - .quad sys_getpgid - .quad sys_fchdir - .quad quiet_ni_syscall /* bdflush */ - .quad sys_sysfs /* 135 */ - .quad sys_personality - .quad quiet_ni_syscall /* for afs_syscall */ - .quad sys_setfsuid16 - .quad sys_setfsgid16 - .quad sys_llseek /* 140 */ - .quad compat_sys_getdents - .quad compat_sys_select - .quad sys_flock - .quad sys_msync - .quad compat_sys_readv /* 145 */ - .quad compat_sys_writev - .quad sys_getsid - .quad sys_fdatasync - .quad compat_sys_sysctl /* sysctl */ - .quad sys_mlock /* 150 */ - .quad sys_munlock - .quad sys_mlockall - .quad sys_munlockall - .quad sys_sched_setparam - .quad sys_sched_getparam /* 155 */ - .quad sys_sched_setscheduler - .quad sys_sched_getscheduler - .quad sys_sched_yield - .quad sys_sched_get_priority_max - .quad sys_sched_get_priority_min /* 160 */ - .quad sys32_sched_rr_get_interval - .quad compat_sys_nanosleep - .quad sys_mremap - .quad sys_setresuid16 - .quad sys_getresuid16 /* 165 */ - .quad sys32_vm86_warning /* vm86 */ - .quad quiet_ni_syscall /* query_module */ - .quad sys_poll - .quad quiet_ni_syscall /* old nfsservctl */ - .quad sys_setresgid16 /* 170 */ - .quad sys_getresgid16 - .quad sys_prctl - .quad stub32_rt_sigreturn - .quad sys32_rt_sigaction - .quad sys32_rt_sigprocmask /* 175 */ - .quad sys32_rt_sigpending - .quad compat_sys_rt_sigtimedwait - .quad sys32_rt_sigqueueinfo - .quad sys_rt_sigsuspend - .quad sys32_pread /* 180 */ - .quad sys32_pwrite - .quad sys_chown16 - .quad sys_getcwd - .quad sys_capget - .quad sys_capset - .quad stub32_sigaltstack - .quad sys32_sendfile - .quad quiet_ni_syscall /* streams1 */ - .quad quiet_ni_syscall /* streams2 */ - .quad stub32_vfork /* 190 */ - .quad compat_sys_getrlimit - .quad sys_mmap_pgoff - .quad sys32_truncate64 - .quad sys32_ftruncate64 - .quad sys32_stat64 /* 195 */ - .quad sys32_lstat64 - .quad sys32_fstat64 - .quad sys_lchown - .quad sys_getuid - .quad sys_getgid /* 200 */ - .quad sys_geteuid - .quad sys_getegid - .quad sys_setreuid - .quad sys_setregid - .quad sys_getgroups /* 205 */ - .quad sys_setgroups - .quad sys_fchown - .quad sys_setresuid - .quad sys_getresuid - .quad sys_setresgid /* 210 */ - .quad sys_getresgid - .quad sys_chown - .quad sys_setuid - .quad sys_setgid - .quad sys_setfsuid /* 215 */ - .quad sys_setfsgid - .quad sys_pivot_root - .quad sys_mincore - .quad sys_madvise - .quad compat_sys_getdents64 /* 220 getdents64 */ - .quad compat_sys_fcntl64 - .quad quiet_ni_syscall /* tux */ - .quad quiet_ni_syscall /* security */ - .quad sys_gettid - .quad sys32_readahead /* 225 */ - .quad sys_setxattr - .quad sys_lsetxattr - .quad sys_fsetxattr - .quad sys_getxattr - .quad sys_lgetxattr /* 230 */ - .quad sys_fgetxattr - .quad sys_listxattr - .quad sys_llistxattr - .quad sys_flistxattr - .quad sys_removexattr /* 235 */ - .quad sys_lremovexattr - .quad sys_fremovexattr - .quad sys_tkill - .quad sys_sendfile64 - .quad compat_sys_futex /* 240 */ - .quad compat_sys_sched_setaffinity - .quad compat_sys_sched_getaffinity - .quad sys_set_thread_area - .quad sys_get_thread_area - .quad compat_sys_io_setup /* 245 */ - .quad sys_io_destroy - .quad compat_sys_io_getevents - .quad compat_sys_io_submit - .quad sys_io_cancel - .quad sys32_fadvise64 /* 250 */ - .quad quiet_ni_syscall /* free_huge_pages */ - .quad sys_exit_group - .quad sys32_lookup_dcookie - .quad sys_epoll_create - .quad sys_epoll_ctl /* 255 */ - .quad sys_epoll_wait - .quad sys_remap_file_pages - .quad sys_set_tid_address - .quad compat_sys_timer_create - .quad compat_sys_timer_settime /* 260 */ - .quad compat_sys_timer_gettime - .quad sys_timer_getoverrun - .quad sys_timer_delete - .quad compat_sys_clock_settime - .quad compat_sys_clock_gettime /* 265 */ - .quad compat_sys_clock_getres - .quad compat_sys_clock_nanosleep - .quad compat_sys_statfs64 - .quad compat_sys_fstatfs64 - .quad sys_tgkill /* 270 */ - .quad compat_sys_utimes - .quad sys32_fadvise64_64 - .quad quiet_ni_syscall /* sys_vserver */ - .quad sys_mbind - .quad compat_sys_get_mempolicy /* 275 */ - .quad sys_set_mempolicy - .quad compat_sys_mq_open - .quad sys_mq_unlink - .quad compat_sys_mq_timedsend - .quad compat_sys_mq_timedreceive /* 280 */ - .quad compat_sys_mq_notify - .quad compat_sys_mq_getsetattr - .quad compat_sys_kexec_load /* reserved for kexec */ - .quad compat_sys_waitid - .quad quiet_ni_syscall /* 285: sys_altroot */ - .quad sys_add_key - .quad sys_request_key - .quad sys_keyctl - .quad sys_ioprio_set - .quad sys_ioprio_get /* 290 */ - .quad sys_inotify_init - .quad sys_inotify_add_watch - .quad sys_inotify_rm_watch - .quad sys_migrate_pages - .quad compat_sys_openat /* 295 */ - .quad sys_mkdirat - .quad sys_mknodat - .quad sys_fchownat - .quad compat_sys_futimesat - .quad sys32_fstatat /* 300 */ - .quad sys_unlinkat - .quad sys_renameat - .quad sys_linkat - .quad sys_symlinkat - .quad sys_readlinkat /* 305 */ - .quad sys_fchmodat - .quad sys_faccessat - .quad compat_sys_pselect6 - .quad compat_sys_ppoll - .quad sys_unshare /* 310 */ - .quad compat_sys_set_robust_list - .quad compat_sys_get_robust_list - .quad sys_splice - .quad sys32_sync_file_range - .quad sys_tee /* 315 */ - .quad compat_sys_vmsplice - .quad compat_sys_move_pages - .quad sys_getcpu - .quad sys_epoll_pwait - .quad compat_sys_utimensat /* 320 */ - .quad compat_sys_signalfd - .quad sys_timerfd_create - .quad sys_eventfd - .quad sys32_fallocate - .quad compat_sys_timerfd_settime /* 325 */ - .quad compat_sys_timerfd_gettime - .quad compat_sys_signalfd4 - .quad sys_eventfd2 - .quad sys_epoll_create1 - .quad sys_dup3 /* 330 */ - .quad sys_pipe2 - .quad sys_inotify_init1 - .quad compat_sys_preadv - .quad compat_sys_pwritev - .quad compat_sys_rt_tgsigqueueinfo /* 335 */ - .quad sys_perf_event_open - .quad compat_sys_recvmmsg - .quad sys_fanotify_init - .quad sys32_fanotify_mark - .quad sys_prlimit64 /* 340 */ - .quad sys_name_to_handle_at - .quad compat_sys_open_by_handle_at - .quad compat_sys_clock_adjtime - .quad sys_syncfs - .quad compat_sys_sendmmsg /* 345 */ - .quad sys_setns - .quad compat_sys_process_vm_readv - .quad compat_sys_process_vm_writev -ia32_syscall_end: diff --git a/arch/x86/ia32/syscall_ia32.c b/arch/x86/ia32/syscall_ia32.c new file mode 100644 index 0000000..d04d3db --- /dev/null +++ b/arch/x86/ia32/syscall_ia32.c @@ -0,0 +1,25 @@ +/* System call table for ia32 emulation. */ + +#include +#include +#include +#include + +#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void compat(void) ; +#include +#undef __SYSCALL_I386 + +#define __SYSCALL_I386(nr, sym, compat) [nr] = compat, + +typedef void (*sys_call_ptr_t)(void); + +extern void compat_ni_syscall(void); + +const sys_call_ptr_t ia32_sys_call_table[__NR_ia32_syscall_max+1] = { + /* + * Smells like a like a compiler bug -- it doesn't work + * when the & below is removed. + */ + [0 ... __NR_ia32_syscall_max] = &compat_ni_syscall, +#include +}; diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild index 6fa90a8..b57e6a4 100644 --- a/arch/x86/include/asm/Kbuild +++ b/arch/x86/include/asm/Kbuild @@ -19,7 +19,8 @@ header-y += processor-flags.h header-y += ptrace-abi.h header-y += sigcontext32.h header-y += ucontext.h -header-y += unistd_32.h -header-y += unistd_64.h header-y += vm86.h header-y += vsyscall.h + +genhdr-y += unistd_32.h +genhdr-y += unistd_64.h diff --git a/arch/x86/include/asm/ia32_unistd.h b/arch/x86/include/asm/ia32_unistd.h index 976f6ec..b0d5716 100644 --- a/arch/x86/include/asm/ia32_unistd.h +++ b/arch/x86/include/asm/ia32_unistd.h @@ -2,17 +2,10 @@ #define _ASM_X86_IA32_UNISTD_H /* - * This file contains the system call numbers of the ia32 port, + * This file contains the system call numbers of the ia32 compat ABI, * this is for the kernel only. - * Only add syscalls here where some part of the kernel needs to know - * the number. This should be otherwise in sync with asm-x86/unistd_32.h. -AK */ - -#define __NR_ia32_restart_syscall 0 -#define __NR_ia32_exit 1 -#define __NR_ia32_read 3 -#define __NR_ia32_write 4 -#define __NR_ia32_sigreturn 119 -#define __NR_ia32_rt_sigreturn 173 +#define __SYSCALL_ia32_NR(x) (x) +#include #endif /* _ASM_X86_IA32_UNISTD_H */ diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h index 2a58ed3..b4a3db7 100644 --- a/arch/x86/include/asm/unistd.h +++ b/arch/x86/include/asm/unistd.h @@ -1,13 +1,59 @@ +#ifndef _ASM_X86_UNISTD_H +#define _ASM_X86_UNISTD_H 1 + #ifdef __KERNEL__ # ifdef CONFIG_X86_32 -# include "unistd_32.h" + +# include +# define __ARCH_WANT_IPC_PARSE_VERSION +# define __ARCH_WANT_STAT64 +# define __ARCH_WANT_SYS_OLD_MMAP +# define __ARCH_WANT_SYS_OLD_SELECT + # else -# include "unistd_64.h" + +# include +# define __ARCH_WANT_COMPAT_SYS_TIME + # endif + +# define __ARCH_WANT_OLD_READDIR +# define __ARCH_WANT_OLD_STAT +# define __ARCH_WANT_SYS_ALARM +# define __ARCH_WANT_SYS_FADVISE64 +# define __ARCH_WANT_SYS_GETHOSTNAME +# define __ARCH_WANT_SYS_GETPGRP +# define __ARCH_WANT_SYS_LLSEEK +# define __ARCH_WANT_SYS_NICE +# define __ARCH_WANT_SYS_OLDUMOUNT +# define __ARCH_WANT_SYS_OLD_GETRLIMIT +# define __ARCH_WANT_SYS_OLD_UNAME +# define __ARCH_WANT_SYS_PAUSE +# define __ARCH_WANT_SYS_RT_SIGACTION +# define __ARCH_WANT_SYS_RT_SIGSUSPEND +# define __ARCH_WANT_SYS_SGETMASK +# define __ARCH_WANT_SYS_SIGNAL +# define __ARCH_WANT_SYS_SIGPENDING +# define __ARCH_WANT_SYS_SIGPROCMASK +# define __ARCH_WANT_SYS_SOCKETCALL +# define __ARCH_WANT_SYS_TIME +# define __ARCH_WANT_SYS_UTIME +# define __ARCH_WANT_SYS_WAITPID + +/* + * "Conditional" syscalls + * + * What we want is __attribute__((weak,alias("sys_ni_syscall"))), + * but it doesn't work on all toolchains, so we just do it by hand + */ +# define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") + #else # ifdef __i386__ -# include "unistd_32.h" +# include # else -# include "unistd_64.h" +# include # endif #endif + +#endif /* _ASM_X86_UNISTD_H */ diff --git a/arch/x86/include/asm/unistd_32.h b/arch/x86/include/asm/unistd_32.h deleted file mode 100644 index 599c77d..0000000 --- a/arch/x86/include/asm/unistd_32.h +++ /dev/null @@ -1,401 +0,0 @@ -#ifndef _ASM_X86_UNISTD_32_H -#define _ASM_X86_UNISTD_32_H - -/* - * This file contains the system call numbers. - */ - -#define __NR_restart_syscall 0 -#define __NR_exit 1 -#define __NR_fork 2 -#define __NR_read 3 -#define __NR_write 4 -#define __NR_open 5 -#define __NR_close 6 -#define __NR_waitpid 7 -#define __NR_creat 8 -#define __NR_link 9 -#define __NR_unlink 10 -#define __NR_execve 11 -#define __NR_chdir 12 -#define __NR_time 13 -#define __NR_mknod 14 -#define __NR_chmod 15 -#define __NR_lchown 16 -#define __NR_break 17 -#define __NR_oldstat 18 -#define __NR_lseek 19 -#define __NR_getpid 20 -#define __NR_mount 21 -#define __NR_umount 22 -#define __NR_setuid 23 -#define __NR_getuid 24 -#define __NR_stime 25 -#define __NR_ptrace 26 -#define __NR_alarm 27 -#define __NR_oldfstat 28 -#define __NR_pause 29 -#define __NR_utime 30 -#define __NR_stty 31 -#define __NR_gtty 32 -#define __NR_access 33 -#define __NR_nice 34 -#define __NR_ftime 35 -#define __NR_sync 36 -#define __NR_kill 37 -#define __NR_rename 38 -#define __NR_mkdir 39 -#define __NR_rmdir 40 -#define __NR_dup 41 -#define __NR_pipe 42 -#define __NR_times 43 -#define __NR_prof 44 -#define __NR_brk 45 -#define __NR_setgid 46 -#define __NR_getgid 47 -#define __NR_signal 48 -#define __NR_geteuid 49 -#define __NR_getegid 50 -#define __NR_acct 51 -#define __NR_umount2 52 -#define __NR_lock 53 -#define __NR_ioctl 54 -#define __NR_fcntl 55 -#define __NR_mpx 56 -#define __NR_setpgid 57 -#define __NR_ulimit 58 -#define __NR_oldolduname 59 -#define __NR_umask 60 -#define __NR_chroot 61 -#define __NR_ustat 62 -#define __NR_dup2 63 -#define __NR_getppid 64 -#define __NR_getpgrp 65 -#define __NR_setsid 66 -#define __NR_sigaction 67 -#define __NR_sgetmask 68 -#define __NR_ssetmask 69 -#define __NR_setreuid 70 -#define __NR_setregid 71 -#define __NR_sigsuspend 72 -#define __NR_sigpending 73 -#define __NR_sethostname 74 -#define __NR_setrlimit 75 -#define __NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */ -#define __NR_getrusage 77 -#define __NR_gettimeofday 78 -#define __NR_settimeofday 79 -#define __NR_getgroups 80 -#define __NR_setgroups 81 -#define __NR_select 82 -#define __NR_symlink 83 -#define __NR_oldlstat 84 -#define __NR_readlink 85 -#define __NR_uselib 86 -#define __NR_swapon 87 -#define __NR_reboot 88 -#define __NR_readdir 89 -#define __NR_mmap 90 -#define __NR_munmap 91 -#define __NR_truncate 92 -#define __NR_ftruncate 93 -#define __NR_fchmod 94 -#define __NR_fchown 95 -#define __NR_getpriority 96 -#define __NR_setpriority 97 -#define __NR_profil 98 -#define __NR_statfs 99 -#define __NR_fstatfs 100 -#define __NR_ioperm 101 -#define __NR_socketcall 102 -#define __NR_syslog 103 -#define __NR_setitimer 104 -#define __NR_getitimer 105 -#define __NR_stat 106 -#define __NR_lstat 107 -#define __NR_fstat 108 -#define __NR_olduname 109 -#define __NR_iopl 110 -#define __NR_vhangup 111 -#define __NR_idle 112 -#define __NR_vm86old 113 -#define __NR_wait4 114 -#define __NR_swapoff 115 -#define __NR_sysinfo 116 -#define __NR_ipc 117 -#define __NR_fsync 118 -#define __NR_sigreturn 119 -#define __NR_clone 120 -#define __NR_setdomainname 121 -#define __NR_uname 122 -#define __NR_modify_ldt 123 -#define __NR_adjtimex 124 -#define __NR_mprotect 125 -#define __NR_sigprocmask 126 -#define __NR_create_module 127 -#define __NR_init_module 128 -#define __NR_delete_module 129 -#define __NR_get_kernel_syms 130 -#define __NR_quotactl 131 -#define __NR_getpgid 132 -#define __NR_fchdir 133 -#define __NR_bdflush 134 -#define __NR_sysfs 135 -#define __NR_personality 136 -#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ -#define __NR_setfsuid 138 -#define __NR_setfsgid 139 -#define __NR__llseek 140 -#define __NR_getdents 141 -#define __NR__newselect 142 -#define __NR_flock 143 -#define __NR_msync 144 -#define __NR_readv 145 -#define __NR_writev 146 -#define __NR_getsid 147 -#define __NR_fdatasync 148 -#define __NR__sysctl 149 -#define __NR_mlock 150 -#define __NR_munlock 151 -#define __NR_mlockall 152 -#define __NR_munlockall 153 -#define __NR_sched_setparam 154 -#define __NR_sched_getparam 155 -#define __NR_sched_setscheduler 156 -#define __NR_sched_getscheduler 157 -#define __NR_sched_yield 158 -#define __NR_sched_get_priority_max 159 -#define __NR_sched_get_priority_min 160 -#define __NR_sched_rr_get_interval 161 -#define __NR_nanosleep 162 -#define __NR_mremap 163 -#define __NR_setresuid 164 -#define __NR_getresuid 165 -#define __NR_vm86 166 -#define __NR_query_module 167 -#define __NR_poll 168 -#define __NR_nfsservctl 169 -#define __NR_setresgid 170 -#define __NR_getresgid 171 -#define __NR_prctl 172 -#define __NR_rt_sigreturn 173 -#define __NR_rt_sigaction 174 -#define __NR_rt_sigprocmask 175 -#define __NR_rt_sigpending 176 -#define __NR_rt_sigtimedwait 177 -#define __NR_rt_sigqueueinfo 178 -#define __NR_rt_sigsuspend 179 -#define __NR_pread64 180 -#define __NR_pwrite64 181 -#define __NR_chown 182 -#define __NR_getcwd 183 -#define __NR_capget 184 -#define __NR_capset 185 -#define __NR_sigaltstack 186 -#define __NR_sendfile 187 -#define __NR_getpmsg 188 /* some people actually want streams */ -#define __NR_putpmsg 189 /* some people actually want streams */ -#define __NR_vfork 190 -#define __NR_ugetrlimit 191 /* SuS compliant getrlimit */ -#define __NR_mmap2 192 -#define __NR_truncate64 193 -#define __NR_ftruncate64 194 -#define __NR_stat64 195 -#define __NR_lstat64 196 -#define __NR_fstat64 197 -#define __NR_lchown32 198 -#define __NR_getuid32 199 -#define __NR_getgid32 200 -#define __NR_geteuid32 201 -#define __NR_getegid32 202 -#define __NR_setreuid32 203 -#define __NR_setregid32 204 -#define __NR_getgroups32 205 -#define __NR_setgroups32 206 -#define __NR_fchown32 207 -#define __NR_setresuid32 208 -#define __NR_getresuid32 209 -#define __NR_setresgid32 210 -#define __NR_getresgid32 211 -#define __NR_chown32 212 -#define __NR_setuid32 213 -#define __NR_setgid32 214 -#define __NR_setfsuid32 215 -#define __NR_setfsgid32 216 -#define __NR_pivot_root 217 -#define __NR_mincore 218 -#define __NR_madvise 219 -#define __NR_madvise1 219 /* delete when C lib stub is removed */ -#define __NR_getdents64 220 -#define __NR_fcntl64 221 -/* 223 is unused */ -#define __NR_gettid 224 -#define __NR_readahead 225 -#define __NR_setxattr 226 -#define __NR_lsetxattr 227 -#define __NR_fsetxattr 228 -#define __NR_getxattr 229 -#define __NR_lgetxattr 230 -#define __NR_fgetxattr 231 -#define __NR_listxattr 232 -#define __NR_llistxattr 233 -#define __NR_flistxattr 234 -#define __NR_removexattr 235 -#define __NR_lremovexattr 236 -#define __NR_fremovexattr 237 -#define __NR_tkill 238 -#define __NR_sendfile64 239 -#define __NR_futex 240 -#define __NR_sched_setaffinity 241 -#define __NR_sched_getaffinity 242 -#define __NR_set_thread_area 243 -#define __NR_get_thread_area 244 -#define __NR_io_setup 245 -#define __NR_io_destroy 246 -#define __NR_io_getevents 247 -#define __NR_io_submit 248 -#define __NR_io_cancel 249 -#define __NR_fadvise64 250 -/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */ -#define __NR_exit_group 252 -#define __NR_lookup_dcookie 253 -#define __NR_epoll_create 254 -#define __NR_epoll_ctl 255 -#define __NR_epoll_wait 256 -#define __NR_remap_file_pages 257 -#define __NR_set_tid_address 258 -#define __NR_timer_create 259 -#define __NR_timer_settime (__NR_timer_create+1) -#define __NR_timer_gettime (__NR_timer_create+2) -#define __NR_timer_getoverrun (__NR_timer_create+3) -#define __NR_timer_delete (__NR_timer_create+4) -#define __NR_clock_settime (__NR_timer_create+5) -#define __NR_clock_gettime (__NR_timer_create+6) -#define __NR_clock_getres (__NR_timer_create+7) -#define __NR_clock_nanosleep (__NR_timer_create+8) -#define __NR_statfs64 268 -#define __NR_fstatfs64 269 -#define __NR_tgkill 270 -#define __NR_utimes 271 -#define __NR_fadvise64_64 272 -#define __NR_vserver 273 -#define __NR_mbind 274 -#define __NR_get_mempolicy 275 -#define __NR_set_mempolicy 276 -#define __NR_mq_open 277 -#define __NR_mq_unlink (__NR_mq_open+1) -#define __NR_mq_timedsend (__NR_mq_open+2) -#define __NR_mq_timedreceive (__NR_mq_open+3) -#define __NR_mq_notify (__NR_mq_open+4) -#define __NR_mq_getsetattr (__NR_mq_open+5) -#define __NR_kexec_load 283 -#define __NR_waitid 284 -/* #define __NR_sys_setaltroot 285 */ -#define __NR_add_key 286 -#define __NR_request_key 287 -#define __NR_keyctl 288 -#define __NR_ioprio_set 289 -#define __NR_ioprio_get 290 -#define __NR_inotify_init 291 -#define __NR_inotify_add_watch 292 -#define __NR_inotify_rm_watch 293 -#define __NR_migrate_pages 294 -#define __NR_openat 295 -#define __NR_mkdirat 296 -#define __NR_mknodat 297 -#define __NR_fchownat 298 -#define __NR_futimesat 299 -#define __NR_fstatat64 300 -#define __NR_unlinkat 301 -#define __NR_renameat 302 -#define __NR_linkat 303 -#define __NR_symlinkat 304 -#define __NR_readlinkat 305 -#define __NR_fchmodat 306 -#define __NR_faccessat 307 -#define __NR_pselect6 308 -#define __NR_ppoll 309 -#define __NR_unshare 310 -#define __NR_set_robust_list 311 -#define __NR_get_robust_list 312 -#define __NR_splice 313 -#define __NR_sync_file_range 314 -#define __NR_tee 315 -#define __NR_vmsplice 316 -#define __NR_move_pages 317 -#define __NR_getcpu 318 -#define __NR_epoll_pwait 319 -#define __NR_utimensat 320 -#define __NR_signalfd 321 -#define __NR_timerfd_create 322 -#define __NR_eventfd 323 -#define __NR_fallocate 324 -#define __NR_timerfd_settime 325 -#define __NR_timerfd_gettime 326 -#define __NR_signalfd4 327 -#define __NR_eventfd2 328 -#define __NR_epoll_create1 329 -#define __NR_dup3 330 -#define __NR_pipe2 331 -#define __NR_inotify_init1 332 -#define __NR_preadv 333 -#define __NR_pwritev 334 -#define __NR_rt_tgsigqueueinfo 335 -#define __NR_perf_event_open 336 -#define __NR_recvmmsg 337 -#define __NR_fanotify_init 338 -#define __NR_fanotify_mark 339 -#define __NR_prlimit64 340 -#define __NR_name_to_handle_at 341 -#define __NR_open_by_handle_at 342 -#define __NR_clock_adjtime 343 -#define __NR_syncfs 344 -#define __NR_sendmmsg 345 -#define __NR_setns 346 -#define __NR_process_vm_readv 347 -#define __NR_process_vm_writev 348 - -#ifdef __KERNEL__ - -#define NR_syscalls 349 - -#define __ARCH_WANT_IPC_PARSE_VERSION -#define __ARCH_WANT_OLD_READDIR -#define __ARCH_WANT_OLD_STAT -#define __ARCH_WANT_STAT64 -#define __ARCH_WANT_SYS_ALARM -#define __ARCH_WANT_SYS_GETHOSTNAME -#define __ARCH_WANT_SYS_IPC -#define __ARCH_WANT_SYS_PAUSE -#define __ARCH_WANT_SYS_SGETMASK -#define __ARCH_WANT_SYS_SIGNAL -#define __ARCH_WANT_SYS_TIME -#define __ARCH_WANT_SYS_UTIME -#define __ARCH_WANT_SYS_WAITPID -#define __ARCH_WANT_SYS_SOCKETCALL -#define __ARCH_WANT_SYS_FADVISE64 -#define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK -#define __ARCH_WANT_SYS_NICE -#define __ARCH_WANT_SYS_OLD_GETRLIMIT -#define __ARCH_WANT_SYS_OLD_UNAME -#define __ARCH_WANT_SYS_OLD_MMAP -#define __ARCH_WANT_SYS_OLD_SELECT -#define __ARCH_WANT_SYS_OLDUMOUNT -#define __ARCH_WANT_SYS_SIGPENDING -#define __ARCH_WANT_SYS_SIGPROCMASK -#define __ARCH_WANT_SYS_RT_SIGACTION -#define __ARCH_WANT_SYS_RT_SIGSUSPEND - -/* - * "Conditional" syscalls - * - * What we want is __attribute__((weak,alias("sys_ni_syscall"))), - * but it doesn't work on all toolchains, so we just do it by hand - */ -#ifndef cond_syscall -#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") -#endif - -#endif /* __KERNEL__ */ -#endif /* _ASM_X86_UNISTD_32_H */ diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h deleted file mode 100644 index 0431f19..0000000 --- a/arch/x86/include/asm/unistd_64.h +++ /dev/null @@ -1,732 +0,0 @@ -#ifndef _ASM_X86_UNISTD_64_H -#define _ASM_X86_UNISTD_64_H - -#ifndef __SYSCALL -#define __SYSCALL(a, b) -#endif - -/* - * This file contains the system call numbers. - * - * Note: holes are not allowed. - */ - -/* at least 8 syscall per cacheline */ -#define __NR_read 0 -__SYSCALL(__NR_read, sys_read) -#define __NR_write 1 -__SYSCALL(__NR_write, sys_write) -#define __NR_open 2 -__SYSCALL(__NR_open, sys_open) -#define __NR_close 3 -__SYSCALL(__NR_close, sys_close) -#define __NR_stat 4 -__SYSCALL(__NR_stat, sys_newstat) -#define __NR_fstat 5 -__SYSCALL(__NR_fstat, sys_newfstat) -#define __NR_lstat 6 -__SYSCALL(__NR_lstat, sys_newlstat) -#define __NR_poll 7 -__SYSCALL(__NR_poll, sys_poll) - -#define __NR_lseek 8 -__SYSCALL(__NR_lseek, sys_lseek) -#define __NR_mmap 9 -__SYSCALL(__NR_mmap, sys_mmap) -#define __NR_mprotect 10 -__SYSCALL(__NR_mprotect, sys_mprotect) -#define __NR_munmap 11 -__SYSCALL(__NR_munmap, sys_munmap) -#define __NR_brk 12 -__SYSCALL(__NR_brk, sys_brk) -#define __NR_rt_sigaction 13 -__SYSCALL(__NR_rt_sigaction, sys_rt_sigaction) -#define __NR_rt_sigprocmask 14 -__SYSCALL(__NR_rt_sigprocmask, sys_rt_sigprocmask) -#define __NR_rt_sigreturn 15 -__SYSCALL(__NR_rt_sigreturn, stub_rt_sigreturn) - -#define __NR_ioctl 16 -__SYSCALL(__NR_ioctl, sys_ioctl) -#define __NR_pread64 17 -__SYSCALL(__NR_pread64, sys_pread64) -#define __NR_pwrite64 18 -__SYSCALL(__NR_pwrite64, sys_pwrite64) -#define __NR_readv 19 -__SYSCALL(__NR_readv, sys_readv) -#define __NR_writev 20 -__SYSCALL(__NR_writev, sys_writev) -#define __NR_access 21 -__SYSCALL(__NR_access, sys_access) -#define __NR_pipe 22 -__SYSCALL(__NR_pipe, sys_pipe) -#define __NR_select 23 -__SYSCALL(__NR_select, sys_select) - -#define __NR_sched_yield 24 -__SYSCALL(__NR_sched_yield, sys_sched_yield) -#define __NR_mremap 25 -__SYSCALL(__NR_mremap, sys_mremap) -#define __NR_msync 26 -__SYSCALL(__NR_msync, sys_msync) -#define __NR_mincore 27 -__SYSCALL(__NR_mincore, sys_mincore) -#define __NR_madvise 28 -__SYSCALL(__NR_madvise, sys_madvise) -#define __NR_shmget 29 -__SYSCALL(__NR_shmget, sys_shmget) -#define __NR_shmat 30 -__SYSCALL(__NR_shmat, sys_shmat) -#define __NR_shmctl 31 -__SYSCALL(__NR_shmctl, sys_shmctl) - -#define __NR_dup 32 -__SYSCALL(__NR_dup, sys_dup) -#define __NR_dup2 33 -__SYSCALL(__NR_dup2, sys_dup2) -#define __NR_pause 34 -__SYSCALL(__NR_pause, sys_pause) -#define __NR_nanosleep 35 -__SYSCALL(__NR_nanosleep, sys_nanosleep) -#define __NR_getitimer 36 -__SYSCALL(__NR_getitimer, sys_getitimer) -#define __NR_alarm 37 -__SYSCALL(__NR_alarm, sys_alarm) -#define __NR_setitimer 38 -__SYSCALL(__NR_setitimer, sys_setitimer) -#define __NR_getpid 39 -__SYSCALL(__NR_getpid, sys_getpid) - -#define __NR_sendfile 40 -__SYSCALL(__NR_sendfile, sys_sendfile64) -#define __NR_socket 41 -__SYSCALL(__NR_socket, sys_socket) -#define __NR_connect 42 -__SYSCALL(__NR_connect, sys_connect) -#define __NR_accept 43 -__SYSCALL(__NR_accept, sys_accept) -#define __NR_sendto 44 -__SYSCALL(__NR_sendto, sys_sendto) -#define __NR_recvfrom 45 -__SYSCALL(__NR_recvfrom, sys_recvfrom) -#define __NR_sendmsg 46 -__SYSCALL(__NR_sendmsg, sys_sendmsg) -#define __NR_recvmsg 47 -__SYSCALL(__NR_recvmsg, sys_recvmsg) - -#define __NR_shutdown 48 -__SYSCALL(__NR_shutdown, sys_shutdown) -#define __NR_bind 49 -__SYSCALL(__NR_bind, sys_bind) -#define __NR_listen 50 -__SYSCALL(__NR_listen, sys_listen) -#define __NR_getsockname 51 -__SYSCALL(__NR_getsockname, sys_getsockname) -#define __NR_getpeername 52 -__SYSCALL(__NR_getpeername, sys_getpeername) -#define __NR_socketpair 53 -__SYSCALL(__NR_socketpair, sys_socketpair) -#define __NR_setsockopt 54 -__SYSCALL(__NR_setsockopt, sys_setsockopt) -#define __NR_getsockopt 55 -__SYSCALL(__NR_getsockopt, sys_getsockopt) - -#define __NR_clone 56 -__SYSCALL(__NR_clone, stub_clone) -#define __NR_fork 57 -__SYSCALL(__NR_fork, stub_fork) -#define __NR_vfork 58 -__SYSCALL(__NR_vfork, stub_vfork) -#define __NR_execve 59 -__SYSCALL(__NR_execve, stub_execve) -#define __NR_exit 60 -__SYSCALL(__NR_exit, sys_exit) -#define __NR_wait4 61 -__SYSCALL(__NR_wait4, sys_wait4) -#define __NR_kill 62 -__SYSCALL(__NR_kill, sys_kill) -#define __NR_uname 63 -__SYSCALL(__NR_uname, sys_newuname) - -#define __NR_semget 64 -__SYSCALL(__NR_semget, sys_semget) -#define __NR_semop 65 -__SYSCALL(__NR_semop, sys_semop) -#define __NR_semctl 66 -__SYSCALL(__NR_semctl, sys_semctl) -#define __NR_shmdt 67 -__SYSCALL(__NR_shmdt, sys_shmdt) -#define __NR_msgget 68 -__SYSCALL(__NR_msgget, sys_msgget) -#define __NR_msgsnd 69 -__SYSCALL(__NR_msgsnd, sys_msgsnd) -#define __NR_msgrcv 70 -__SYSCALL(__NR_msgrcv, sys_msgrcv) -#define __NR_msgctl 71 -__SYSCALL(__NR_msgctl, sys_msgctl) - -#define __NR_fcntl 72 -__SYSCALL(__NR_fcntl, sys_fcntl) -#define __NR_flock 73 -__SYSCALL(__NR_flock, sys_flock) -#define __NR_fsync 74 -__SYSCALL(__NR_fsync, sys_fsync) -#define __NR_fdatasync 75 -__SYSCALL(__NR_fdatasync, sys_fdatasync) -#define __NR_truncate 76 -__SYSCALL(__NR_truncate, sys_truncate) -#define __NR_ftruncate 77 -__SYSCALL(__NR_ftruncate, sys_ftruncate) -#define __NR_getdents 78 -__SYSCALL(__NR_getdents, sys_getdents) -#define __NR_getcwd 79 -__SYSCALL(__NR_getcwd, sys_getcwd) - -#define __NR_chdir 80 -__SYSCALL(__NR_chdir, sys_chdir) -#define __NR_fchdir 81 -__SYSCALL(__NR_fchdir, sys_fchdir) -#define __NR_rename 82 -__SYSCALL(__NR_rename, sys_rename) -#define __NR_mkdir 83 -__SYSCALL(__NR_mkdir, sys_mkdir) -#define __NR_rmdir 84 -__SYSCALL(__NR_rmdir, sys_rmdir) -#define __NR_creat 85 -__SYSCALL(__NR_creat, sys_creat) -#define __NR_link 86 -__SYSCALL(__NR_link, sys_link) -#define __NR_unlink 87 -__SYSCALL(__NR_unlink, sys_unlink) - -#define __NR_symlink 88 -__SYSCALL(__NR_symlink, sys_symlink) -#define __NR_readlink 89 -__SYSCALL(__NR_readlink, sys_readlink) -#define __NR_chmod 90 -__SYSCALL(__NR_chmod, sys_chmod) -#define __NR_fchmod 91 -__SYSCALL(__NR_fchmod, sys_fchmod) -#define __NR_chown 92 -__SYSCALL(__NR_chown, sys_chown) -#define __NR_fchown 93 -__SYSCALL(__NR_fchown, sys_fchown) -#define __NR_lchown 94 -__SYSCALL(__NR_lchown, sys_lchown) -#define __NR_umask 95 -__SYSCALL(__NR_umask, sys_umask) - -#define __NR_gettimeofday 96 -__SYSCALL(__NR_gettimeofday, sys_gettimeofday) -#define __NR_getrlimit 97 -__SYSCALL(__NR_getrlimit, sys_getrlimit) -#define __NR_getrusage 98 -__SYSCALL(__NR_getrusage, sys_getrusage) -#define __NR_sysinfo 99 -__SYSCALL(__NR_sysinfo, sys_sysinfo) -#define __NR_times 100 -__SYSCALL(__NR_times, sys_times) -#define __NR_ptrace 101 -__SYSCALL(__NR_ptrace, sys_ptrace) -#define __NR_getuid 102 -__SYSCALL(__NR_getuid, sys_getuid) -#define __NR_syslog 103 -__SYSCALL(__NR_syslog, sys_syslog) - -/* at the very end the stuff that never runs during the benchmarks */ -#define __NR_getgid 104 -__SYSCALL(__NR_getgid, sys_getgid) -#define __NR_setuid 105 -__SYSCALL(__NR_setuid, sys_setuid) -#define __NR_setgid 106 -__SYSCALL(__NR_setgid, sys_setgid) -#define __NR_geteuid 107 -__SYSCALL(__NR_geteuid, sys_geteuid) -#define __NR_getegid 108 -__SYSCALL(__NR_getegid, sys_getegid) -#define __NR_setpgid 109 -__SYSCALL(__NR_setpgid, sys_setpgid) -#define __NR_getppid 110 -__SYSCALL(__NR_getppid, sys_getppid) -#define __NR_getpgrp 111 -__SYSCALL(__NR_getpgrp, sys_getpgrp) - -#define __NR_setsid 112 -__SYSCALL(__NR_setsid, sys_setsid) -#define __NR_setreuid 113 -__SYSCALL(__NR_setreuid, sys_setreuid) -#define __NR_setregid 114 -__SYSCALL(__NR_setregid, sys_setregid) -#define __NR_getgroups 115 -__SYSCALL(__NR_getgroups, sys_getgroups) -#define __NR_setgroups 116 -__SYSCALL(__NR_setgroups, sys_setgroups) -#define __NR_setresuid 117 -__SYSCALL(__NR_setresuid, sys_setresuid) -#define __NR_getresuid 118 -__SYSCALL(__NR_getresuid, sys_getresuid) -#define __NR_setresgid 119 -__SYSCALL(__NR_setresgid, sys_setresgid) - -#define __NR_getresgid 120 -__SYSCALL(__NR_getresgid, sys_getresgid) -#define __NR_getpgid 121 -__SYSCALL(__NR_getpgid, sys_getpgid) -#define __NR_setfsuid 122 -__SYSCALL(__NR_setfsuid, sys_setfsuid) -#define __NR_setfsgid 123 -__SYSCALL(__NR_setfsgid, sys_setfsgid) -#define __NR_getsid 124 -__SYSCALL(__NR_getsid, sys_getsid) -#define __NR_capget 125 -__SYSCALL(__NR_capget, sys_capget) -#define __NR_capset 126 -__SYSCALL(__NR_capset, sys_capset) - -#define __NR_rt_sigpending 127 -__SYSCALL(__NR_rt_sigpending, sys_rt_sigpending) -#define __NR_rt_sigtimedwait 128 -__SYSCALL(__NR_rt_sigtimedwait, sys_rt_sigtimedwait) -#define __NR_rt_sigqueueinfo 129 -__SYSCALL(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo) -#define __NR_rt_sigsuspend 130 -__SYSCALL(__NR_rt_sigsuspend, sys_rt_sigsuspend) -#define __NR_sigaltstack 131 -__SYSCALL(__NR_sigaltstack, stub_sigaltstack) -#define __NR_utime 132 -__SYSCALL(__NR_utime, sys_utime) -#define __NR_mknod 133 -__SYSCALL(__NR_mknod, sys_mknod) - -/* Only needed for a.out */ -#define __NR_uselib 134 -__SYSCALL(__NR_uselib, sys_ni_syscall) -#define __NR_personality 135 -__SYSCALL(__NR_personality, sys_personality) - -#define __NR_ustat 136 -__SYSCALL(__NR_ustat, sys_ustat) -#define __NR_statfs 137 -__SYSCALL(__NR_statfs, sys_statfs) -#define __NR_fstatfs 138 -__SYSCALL(__NR_fstatfs, sys_fstatfs) -#define __NR_sysfs 139 -__SYSCALL(__NR_sysfs, sys_sysfs) - -#define __NR_getpriority 140 -__SYSCALL(__NR_getpriority, sys_getpriority) -#define __NR_setpriority 141 -__SYSCALL(__NR_setpriority, sys_setpriority) -#define __NR_sched_setparam 142 -__SYSCALL(__NR_sched_setparam, sys_sched_setparam) -#define __NR_sched_getparam 143 -__SYSCALL(__NR_sched_getparam, sys_sched_getparam) -#define __NR_sched_setscheduler 144 -__SYSCALL(__NR_sched_setscheduler, sys_sched_setscheduler) -#define __NR_sched_getscheduler 145 -__SYSCALL(__NR_sched_getscheduler, sys_sched_getscheduler) -#define __NR_sched_get_priority_max 146 -__SYSCALL(__NR_sched_get_priority_max, sys_sched_get_priority_max) -#define __NR_sched_get_priority_min 147 -__SYSCALL(__NR_sched_get_priority_min, sys_sched_get_priority_min) -#define __NR_sched_rr_get_interval 148 -__SYSCALL(__NR_sched_rr_get_interval, sys_sched_rr_get_interval) - -#define __NR_mlock 149 -__SYSCALL(__NR_mlock, sys_mlock) -#define __NR_munlock 150 -__SYSCALL(__NR_munlock, sys_munlock) -#define __NR_mlockall 151 -__SYSCALL(__NR_mlockall, sys_mlockall) -#define __NR_munlockall 152 -__SYSCALL(__NR_munlockall, sys_munlockall) - -#define __NR_vhangup 153 -__SYSCALL(__NR_vhangup, sys_vhangup) - -#define __NR_modify_ldt 154 -__SYSCALL(__NR_modify_ldt, sys_modify_ldt) - -#define __NR_pivot_root 155 -__SYSCALL(__NR_pivot_root, sys_pivot_root) - -#define __NR__sysctl 156 -__SYSCALL(__NR__sysctl, sys_sysctl) - -#define __NR_prctl 157 -__SYSCALL(__NR_prctl, sys_prctl) -#define __NR_arch_prctl 158 -__SYSCALL(__NR_arch_prctl, sys_arch_prctl) - -#define __NR_adjtimex 159 -__SYSCALL(__NR_adjtimex, sys_adjtimex) - -#define __NR_setrlimit 160 -__SYSCALL(__NR_setrlimit, sys_setrlimit) - -#define __NR_chroot 161 -__SYSCALL(__NR_chroot, sys_chroot) - -#define __NR_sync 162 -__SYSCALL(__NR_sync, sys_sync) - -#define __NR_acct 163 -__SYSCALL(__NR_acct, sys_acct) - -#define __NR_settimeofday 164 -__SYSCALL(__NR_settimeofday, sys_settimeofday) - -#define __NR_mount 165 -__SYSCALL(__NR_mount, sys_mount) -#define __NR_umount2 166 -__SYSCALL(__NR_umount2, sys_umount) - -#define __NR_swapon 167 -__SYSCALL(__NR_swapon, sys_swapon) -#define __NR_swapoff 168 -__SYSCALL(__NR_swapoff, sys_swapoff) - -#define __NR_reboot 169 -__SYSCALL(__NR_reboot, sys_reboot) - -#define __NR_sethostname 170 -__SYSCALL(__NR_sethostname, sys_sethostname) -#define __NR_setdomainname 171 -__SYSCALL(__NR_setdomainname, sys_setdomainname) - -#define __NR_iopl 172 -__SYSCALL(__NR_iopl, stub_iopl) -#define __NR_ioperm 173 -__SYSCALL(__NR_ioperm, sys_ioperm) - -#define __NR_create_module 174 -__SYSCALL(__NR_create_module, sys_ni_syscall) -#define __NR_init_module 175 -__SYSCALL(__NR_init_module, sys_init_module) -#define __NR_delete_module 176 -__SYSCALL(__NR_delete_module, sys_delete_module) -#define __NR_get_kernel_syms 177 -__SYSCALL(__NR_get_kernel_syms, sys_ni_syscall) -#define __NR_query_module 178 -__SYSCALL(__NR_query_module, sys_ni_syscall) - -#define __NR_quotactl 179 -__SYSCALL(__NR_quotactl, sys_quotactl) - -#define __NR_nfsservctl 180 -__SYSCALL(__NR_nfsservctl, sys_ni_syscall) - -/* reserved for LiS/STREAMS */ -#define __NR_getpmsg 181 -__SYSCALL(__NR_getpmsg, sys_ni_syscall) -#define __NR_putpmsg 182 -__SYSCALL(__NR_putpmsg, sys_ni_syscall) - -/* reserved for AFS */ -#define __NR_afs_syscall 183 -__SYSCALL(__NR_afs_syscall, sys_ni_syscall) - -/* reserved for tux */ -#define __NR_tuxcall 184 -__SYSCALL(__NR_tuxcall, sys_ni_syscall) - -#define __NR_security 185 -__SYSCALL(__NR_security, sys_ni_syscall) - -#define __NR_gettid 186 -__SYSCALL(__NR_gettid, sys_gettid) - -#define __NR_readahead 187 -__SYSCALL(__NR_readahead, sys_readahead) -#define __NR_setxattr 188 -__SYSCALL(__NR_setxattr, sys_setxattr) -#define __NR_lsetxattr 189 -__SYSCALL(__NR_lsetxattr, sys_lsetxattr) -#define __NR_fsetxattr 190 -__SYSCALL(__NR_fsetxattr, sys_fsetxattr) -#define __NR_getxattr 191 -__SYSCALL(__NR_getxattr, sys_getxattr) -#define __NR_lgetxattr 192 -__SYSCALL(__NR_lgetxattr, sys_lgetxattr) -#define __NR_fgetxattr 193 -__SYSCALL(__NR_fgetxattr, sys_fgetxattr) -#define __NR_listxattr 194 -__SYSCALL(__NR_listxattr, sys_listxattr) -#define __NR_llistxattr 195 -__SYSCALL(__NR_llistxattr, sys_llistxattr) -#define __NR_flistxattr 196 -__SYSCALL(__NR_flistxattr, sys_flistxattr) -#define __NR_removexattr 197 -__SYSCALL(__NR_removexattr, sys_removexattr) -#define __NR_lremovexattr 198 -__SYSCALL(__NR_lremovexattr, sys_lremovexattr) -#define __NR_fremovexattr 199 -__SYSCALL(__NR_fremovexattr, sys_fremovexattr) -#define __NR_tkill 200 -__SYSCALL(__NR_tkill, sys_tkill) -#define __NR_time 201 -__SYSCALL(__NR_time, sys_time) -#define __NR_futex 202 -__SYSCALL(__NR_futex, sys_futex) -#define __NR_sched_setaffinity 203 -__SYSCALL(__NR_sched_setaffinity, sys_sched_setaffinity) -#define __NR_sched_getaffinity 204 -__SYSCALL(__NR_sched_getaffinity, sys_sched_getaffinity) -#define __NR_set_thread_area 205 -__SYSCALL(__NR_set_thread_area, sys_ni_syscall) /* use arch_prctl */ -#define __NR_io_setup 206 -__SYSCALL(__NR_io_setup, sys_io_setup) -#define __NR_io_destroy 207 -__SYSCALL(__NR_io_destroy, sys_io_destroy) -#define __NR_io_getevents 208 -__SYSCALL(__NR_io_getevents, sys_io_getevents) -#define __NR_io_submit 209 -__SYSCALL(__NR_io_submit, sys_io_submit) -#define __NR_io_cancel 210 -__SYSCALL(__NR_io_cancel, sys_io_cancel) -#define __NR_get_thread_area 211 -__SYSCALL(__NR_get_thread_area, sys_ni_syscall) /* use arch_prctl */ -#define __NR_lookup_dcookie 212 -__SYSCALL(__NR_lookup_dcookie, sys_lookup_dcookie) -#define __NR_epoll_create 213 -__SYSCALL(__NR_epoll_create, sys_epoll_create) -#define __NR_epoll_ctl_old 214 -__SYSCALL(__NR_epoll_ctl_old, sys_ni_syscall) -#define __NR_epoll_wait_old 215 -__SYSCALL(__NR_epoll_wait_old, sys_ni_syscall) -#define __NR_remap_file_pages 216 -__SYSCALL(__NR_remap_file_pages, sys_remap_file_pages) -#define __NR_getdents64 217 -__SYSCALL(__NR_getdents64, sys_getdents64) -#define __NR_set_tid_address 218 -__SYSCALL(__NR_set_tid_address, sys_set_tid_address) -#define __NR_restart_syscall 219 -__SYSCALL(__NR_restart_syscall, sys_restart_syscall) -#define __NR_semtimedop 220 -__SYSCALL(__NR_semtimedop, sys_semtimedop) -#define __NR_fadvise64 221 -__SYSCALL(__NR_fadvise64, sys_fadvise64) -#define __NR_timer_create 222 -__SYSCALL(__NR_timer_create, sys_timer_create) -#define __NR_timer_settime 223 -__SYSCALL(__NR_timer_settime, sys_timer_settime) -#define __NR_timer_gettime 224 -__SYSCALL(__NR_timer_gettime, sys_timer_gettime) -#define __NR_timer_getoverrun 225 -__SYSCALL(__NR_timer_getoverrun, sys_timer_getoverrun) -#define __NR_timer_delete 226 -__SYSCALL(__NR_timer_delete, sys_timer_delete) -#define __NR_clock_settime 227 -__SYSCALL(__NR_clock_settime, sys_clock_settime) -#define __NR_clock_gettime 228 -__SYSCALL(__NR_clock_gettime, sys_clock_gettime) -#define __NR_clock_getres 229 -__SYSCALL(__NR_clock_getres, sys_clock_getres) -#define __NR_clock_nanosleep 230 -__SYSCALL(__NR_clock_nanosleep, sys_clock_nanosleep) -#define __NR_exit_group 231 -__SYSCALL(__NR_exit_group, sys_exit_group) -#define __NR_epoll_wait 232 -__SYSCALL(__NR_epoll_wait, sys_epoll_wait) -#define __NR_epoll_ctl 233 -__SYSCALL(__NR_epoll_ctl, sys_epoll_ctl) -#define __NR_tgkill 234 -__SYSCALL(__NR_tgkill, sys_tgkill) -#define __NR_utimes 235 -__SYSCALL(__NR_utimes, sys_utimes) -#define __NR_vserver 236 -__SYSCALL(__NR_vserver, sys_ni_syscall) -#define __NR_mbind 237 -__SYSCALL(__NR_mbind, sys_mbind) -#define __NR_set_mempolicy 238 -__SYSCALL(__NR_set_mempolicy, sys_set_mempolicy) -#define __NR_get_mempolicy 239 -__SYSCALL(__NR_get_mempolicy, sys_get_mempolicy) -#define __NR_mq_open 240 -__SYSCALL(__NR_mq_open, sys_mq_open) -#define __NR_mq_unlink 241 -__SYSCALL(__NR_mq_unlink, sys_mq_unlink) -#define __NR_mq_timedsend 242 -__SYSCALL(__NR_mq_timedsend, sys_mq_timedsend) -#define __NR_mq_timedreceive 243 -__SYSCALL(__NR_mq_timedreceive, sys_mq_timedreceive) -#define __NR_mq_notify 244 -__SYSCALL(__NR_mq_notify, sys_mq_notify) -#define __NR_mq_getsetattr 245 -__SYSCALL(__NR_mq_getsetattr, sys_mq_getsetattr) -#define __NR_kexec_load 246 -__SYSCALL(__NR_kexec_load, sys_kexec_load) -#define __NR_waitid 247 -__SYSCALL(__NR_waitid, sys_waitid) -#define __NR_add_key 248 -__SYSCALL(__NR_add_key, sys_add_key) -#define __NR_request_key 249 -__SYSCALL(__NR_request_key, sys_request_key) -#define __NR_keyctl 250 -__SYSCALL(__NR_keyctl, sys_keyctl) -#define __NR_ioprio_set 251 -__SYSCALL(__NR_ioprio_set, sys_ioprio_set) -#define __NR_ioprio_get 252 -__SYSCALL(__NR_ioprio_get, sys_ioprio_get) -#define __NR_inotify_init 253 -__SYSCALL(__NR_inotify_init, sys_inotify_init) -#define __NR_inotify_add_watch 254 -__SYSCALL(__NR_inotify_add_watch, sys_inotify_add_watch) -#define __NR_inotify_rm_watch 255 -__SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch) -#define __NR_migrate_pages 256 -__SYSCALL(__NR_migrate_pages, sys_migrate_pages) -#define __NR_openat 257 -__SYSCALL(__NR_openat, sys_openat) -#define __NR_mkdirat 258 -__SYSCALL(__NR_mkdirat, sys_mkdirat) -#define __NR_mknodat 259 -__SYSCALL(__NR_mknodat, sys_mknodat) -#define __NR_fchownat 260 -__SYSCALL(__NR_fchownat, sys_fchownat) -#define __NR_futimesat 261 -__SYSCALL(__NR_futimesat, sys_futimesat) -#define __NR_newfstatat 262 -__SYSCALL(__NR_newfstatat, sys_newfstatat) -#define __NR_unlinkat 263 -__SYSCALL(__NR_unlinkat, sys_unlinkat) -#define __NR_renameat 264 -__SYSCALL(__NR_renameat, sys_renameat) -#define __NR_linkat 265 -__SYSCALL(__NR_linkat, sys_linkat) -#define __NR_symlinkat 266 -__SYSCALL(__NR_symlinkat, sys_symlinkat) -#define __NR_readlinkat 267 -__SYSCALL(__NR_readlinkat, sys_readlinkat) -#define __NR_fchmodat 268 -__SYSCALL(__NR_fchmodat, sys_fchmodat) -#define __NR_faccessat 269 -__SYSCALL(__NR_faccessat, sys_faccessat) -#define __NR_pselect6 270 -__SYSCALL(__NR_pselect6, sys_pselect6) -#define __NR_ppoll 271 -__SYSCALL(__NR_ppoll, sys_ppoll) -#define __NR_unshare 272 -__SYSCALL(__NR_unshare, sys_unshare) -#define __NR_set_robust_list 273 -__SYSCALL(__NR_set_robust_list, sys_set_robust_list) -#define __NR_get_robust_list 274 -__SYSCALL(__NR_get_robust_list, sys_get_robust_list) -#define __NR_splice 275 -__SYSCALL(__NR_splice, sys_splice) -#define __NR_tee 276 -__SYSCALL(__NR_tee, sys_tee) -#define __NR_sync_file_range 277 -__SYSCALL(__NR_sync_file_range, sys_sync_file_range) -#define __NR_vmsplice 278 -__SYSCALL(__NR_vmsplice, sys_vmsplice) -#define __NR_move_pages 279 -__SYSCALL(__NR_move_pages, sys_move_pages) -#define __NR_utimensat 280 -__SYSCALL(__NR_utimensat, sys_utimensat) -#define __NR_epoll_pwait 281 -__SYSCALL(__NR_epoll_pwait, sys_epoll_pwait) -#define __NR_signalfd 282 -__SYSCALL(__NR_signalfd, sys_signalfd) -#define __NR_timerfd_create 283 -__SYSCALL(__NR_timerfd_create, sys_timerfd_create) -#define __NR_eventfd 284 -__SYSCALL(__NR_eventfd, sys_eventfd) -#define __NR_fallocate 285 -__SYSCALL(__NR_fallocate, sys_fallocate) -#define __NR_timerfd_settime 286 -__SYSCALL(__NR_timerfd_settime, sys_timerfd_settime) -#define __NR_timerfd_gettime 287 -__SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime) -#define __NR_accept4 288 -__SYSCALL(__NR_accept4, sys_accept4) -#define __NR_signalfd4 289 -__SYSCALL(__NR_signalfd4, sys_signalfd4) -#define __NR_eventfd2 290 -__SYSCALL(__NR_eventfd2, sys_eventfd2) -#define __NR_epoll_create1 291 -__SYSCALL(__NR_epoll_create1, sys_epoll_create1) -#define __NR_dup3 292 -__SYSCALL(__NR_dup3, sys_dup3) -#define __NR_pipe2 293 -__SYSCALL(__NR_pipe2, sys_pipe2) -#define __NR_inotify_init1 294 -__SYSCALL(__NR_inotify_init1, sys_inotify_init1) -#define __NR_preadv 295 -__SYSCALL(__NR_preadv, sys_preadv) -#define __NR_pwritev 296 -__SYSCALL(__NR_pwritev, sys_pwritev) -#define __NR_rt_tgsigqueueinfo 297 -__SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo) -#define __NR_perf_event_open 298 -__SYSCALL(__NR_perf_event_open, sys_perf_event_open) -#define __NR_recvmmsg 299 -__SYSCALL(__NR_recvmmsg, sys_recvmmsg) -#define __NR_fanotify_init 300 -__SYSCALL(__NR_fanotify_init, sys_fanotify_init) -#define __NR_fanotify_mark 301 -__SYSCALL(__NR_fanotify_mark, sys_fanotify_mark) -#define __NR_prlimit64 302 -__SYSCALL(__NR_prlimit64, sys_prlimit64) -#define __NR_name_to_handle_at 303 -__SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at) -#define __NR_open_by_handle_at 304 -__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at) -#define __NR_clock_adjtime 305 -__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime) -#define __NR_syncfs 306 -__SYSCALL(__NR_syncfs, sys_syncfs) -#define __NR_sendmmsg 307 -__SYSCALL(__NR_sendmmsg, sys_sendmmsg) -#define __NR_setns 308 -__SYSCALL(__NR_setns, sys_setns) -#define __NR_getcpu 309 -__SYSCALL(__NR_getcpu, sys_getcpu) -#define __NR_process_vm_readv 310 -__SYSCALL(__NR_process_vm_readv, sys_process_vm_readv) -#define __NR_process_vm_writev 311 -__SYSCALL(__NR_process_vm_writev, sys_process_vm_writev) - -#ifndef __NO_STUBS -#define __ARCH_WANT_OLD_READDIR -#define __ARCH_WANT_OLD_STAT -#define __ARCH_WANT_SYS_ALARM -#define __ARCH_WANT_SYS_GETHOSTNAME -#define __ARCH_WANT_SYS_PAUSE -#define __ARCH_WANT_SYS_SGETMASK -#define __ARCH_WANT_SYS_SIGNAL -#define __ARCH_WANT_SYS_UTIME -#define __ARCH_WANT_SYS_WAITPID -#define __ARCH_WANT_SYS_SOCKETCALL -#define __ARCH_WANT_SYS_FADVISE64 -#define __ARCH_WANT_SYS_GETPGRP -#define __ARCH_WANT_SYS_LLSEEK -#define __ARCH_WANT_SYS_NICE -#define __ARCH_WANT_SYS_OLD_GETRLIMIT -#define __ARCH_WANT_SYS_OLD_UNAME -#define __ARCH_WANT_SYS_OLDUMOUNT -#define __ARCH_WANT_SYS_SIGPENDING -#define __ARCH_WANT_SYS_SIGPROCMASK -#define __ARCH_WANT_SYS_RT_SIGACTION -#define __ARCH_WANT_SYS_RT_SIGSUSPEND -#define __ARCH_WANT_SYS_TIME -#define __ARCH_WANT_COMPAT_SYS_TIME -#endif /* __NO_STUBS */ - -#ifdef __KERNEL__ - -#ifndef COMPILE_OFFSETS -#include -#define NR_syscalls (__NR_syscall_max + 1) -#endif - -/* - * "Conditional" syscalls - * - * What we want is __attribute__((weak,alias("sys_ni_syscall"))), - * but it doesn't work on all toolchains, so we just do it by hand - */ -#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") -#endif /* __KERNEL__ */ - -#endif /* _ASM_X86_UNISTD_64_H */ diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 8baca3c..8c473d9 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -25,7 +25,8 @@ obj-$(CONFIG_IRQ_WORK) += irq_work.o obj-y += probe_roms.o obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o -obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o +obj-y += syscall_$(BITS).o +obj-$(CONFIG_X86_64) += vsyscall_64.o obj-$(CONFIG_X86_64) += vsyscall_emu_64.o obj-y += bootflag.o e820.o obj-y += pci-dma.o quirks.o topology.o kdebugfs.o diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c index 395a10e..85d98ab 100644 --- a/arch/x86/kernel/asm-offsets_32.c +++ b/arch/x86/kernel/asm-offsets_32.c @@ -3,6 +3,11 @@ #include #include "../../../drivers/lguest/lg.h" +#define __SYSCALL_I386(nr, sym, compat) [nr] = 1, +static char syscalls[] = { +#include +}; + /* workaround for a warning with -Wmissing-prototypes */ void foo(void); @@ -76,4 +81,7 @@ void foo(void) OFFSET(LGUEST_PAGES_regs_errcode, lguest_pages, regs.errcode); OFFSET(LGUEST_PAGES_regs, lguest_pages, regs); #endif + BLANK(); + DEFINE(__NR_syscall_max, sizeof(syscalls) - 1); + DEFINE(NR_syscalls, sizeof(syscalls)); } diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index e72a119..834e897 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -1,11 +1,12 @@ #include -#define __NO_STUBS 1 -#undef __SYSCALL -#undef _ASM_X86_UNISTD_64_H -#define __SYSCALL(nr, sym) [nr] = 1, -static char syscalls[] = { -#include +#define __SYSCALL_64(nr, sym, compat) [nr] = 1, +static char syscalls_64[] = { +#include +}; +#define __SYSCALL_I386(nr, sym, compat) [nr] = 1, +static char syscalls_ia32[] = { +#include }; int main(void) @@ -72,7 +73,11 @@ int main(void) OFFSET(TSS_ist, tss_struct, x86_tss.ist); BLANK(); - DEFINE(__NR_syscall_max, sizeof(syscalls) - 1); + DEFINE(__NR_syscall_max, sizeof(syscalls_64) - 1); + DEFINE(NR_syscalls, sizeof(syscalls_64)); + + DEFINE(__NR_ia32_syscall_max, sizeof(syscalls_ia32) - 1); + DEFINE(IA32_NR_syscalls, sizeof(syscalls_ia32)); return 0; } diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index f3f6f53..1ffcda2 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -81,8 +81,6 @@ * enough to patch inline, increasing performance. */ -#define nr_syscalls ((syscall_table_size)/4) - #ifdef CONFIG_PREEMPT #define preempt_stop(clobbers) DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF #else @@ -423,7 +421,7 @@ sysenter_past_esp: testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) jnz sysenter_audit sysenter_do_call: - cmpl $(nr_syscalls), %eax + cmpl $(NR_syscalls), %eax jae syscall_badsys call *sys_call_table(,%eax,4) movl %eax,PT_EAX(%esp) @@ -504,7 +502,7 @@ ENTRY(system_call) # system call tracing in operation / emulation testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) jnz syscall_trace_entry - cmpl $(nr_syscalls), %eax + cmpl $(NR_syscalls), %eax jae syscall_badsys syscall_call: call *sys_call_table(,%eax,4) @@ -650,7 +648,7 @@ syscall_trace_entry: movl %esp, %eax call syscall_trace_enter /* What it returned is what we'll actually use. */ - cmpl $(nr_syscalls), %eax + cmpl $(NR_syscalls), %eax jnae syscall_call jmp syscall_exit END(syscall_trace_entry) @@ -690,29 +688,28 @@ END(syscall_badsys) * System calls that need a pt_regs pointer. */ #define PTREGSCALL0(name) \ - ALIGN; \ -ptregs_##name: \ +ENTRY(ptregs_##name) ; \ leal 4(%esp),%eax; \ - jmp sys_##name; + jmp sys_##name; \ +ENDPROC(ptregs_##name) #define PTREGSCALL1(name) \ - ALIGN; \ -ptregs_##name: \ +ENTRY(ptregs_##name) ; \ leal 4(%esp),%edx; \ movl (PT_EBX+4)(%esp),%eax; \ - jmp sys_##name; + jmp sys_##name; \ +ENDPROC(ptregs_##name) #define PTREGSCALL2(name) \ - ALIGN; \ -ptregs_##name: \ +ENTRY(ptregs_##name) ; \ leal 4(%esp),%ecx; \ movl (PT_ECX+4)(%esp),%edx; \ movl (PT_EBX+4)(%esp),%eax; \ - jmp sys_##name; + jmp sys_##name; \ +ENDPROC(ptregs_##name) #define PTREGSCALL3(name) \ - ALIGN; \ -ptregs_##name: \ +ENTRY(ptregs_##name) ; \ CFI_STARTPROC; \ leal 4(%esp),%eax; \ pushl_cfi %eax; \ @@ -737,8 +734,7 @@ PTREGSCALL2(vm86) PTREGSCALL1(vm86old) /* Clone is an oddball. The 4th arg is in %edi */ - ALIGN; -ptregs_clone: +ENTRY(ptregs_clone) CFI_STARTPROC leal 4(%esp),%eax pushl_cfi %eax @@ -1209,11 +1205,6 @@ return_to_handler: jmp *%ecx #endif -.section .rodata,"a" -#include "syscall_table_32.S" - -syscall_table_size=(.-sys_call_table) - /* * Some functions should be protected against kprobes */ diff --git a/arch/x86/kernel/syscall_32.c b/arch/x86/kernel/syscall_32.c new file mode 100644 index 0000000..b37a573 --- /dev/null +++ b/arch/x86/kernel/syscall_32.c @@ -0,0 +1,25 @@ +/* System call table for i386. */ + +#include +#include +#include +#include + +#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void sym(void) ; +#include +#undef __SYSCALL_I386 + +#define __SYSCALL_I386(nr, sym, compat) [nr] = sym, + +typedef asmlinkage void (*sys_call_ptr_t)(void); + +extern asmlinkage void sys_ni_syscall(void); + +const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { + /* + * Smells like a like a compiler bug -- it doesn't work + * when the & below is removed. + */ + [0 ... __NR_syscall_max] = &sys_ni_syscall, +#include +}; diff --git a/arch/x86/kernel/syscall_64.c b/arch/x86/kernel/syscall_64.c index 0edfafa..7ac7943 100644 --- a/arch/x86/kernel/syscall_64.c +++ b/arch/x86/kernel/syscall_64.c @@ -5,15 +5,11 @@ #include #include -#define __NO_STUBS +#define __SYSCALL_64(nr, sym, compat) extern asmlinkage void sym(void) ; +#include +#undef __SYSCALL_64 -#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ; -#undef _ASM_X86_UNISTD_64_H -#include - -#undef __SYSCALL -#define __SYSCALL(nr, sym) [nr] = sym, -#undef _ASM_X86_UNISTD_64_H +#define __SYSCALL_64(nr, sym, compat) [nr] = sym, typedef void (*sys_call_ptr_t)(void); @@ -25,5 +21,5 @@ const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { * when the & below is removed. */ [0 ... __NR_syscall_max] = &sys_ni_syscall, -#include +#include }; diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S deleted file mode 100644 index 9a0e312..0000000 --- a/arch/x86/kernel/syscall_table_32.S +++ /dev/null @@ -1,350 +0,0 @@ -ENTRY(sys_call_table) - .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ - .long sys_exit - .long ptregs_fork - .long sys_read - .long sys_write - .long sys_open /* 5 */ - .long sys_close - .long sys_waitpid - .long sys_creat - .long sys_link - .long sys_unlink /* 10 */ - .long ptregs_execve - .long sys_chdir - .long sys_time - .long sys_mknod - .long sys_chmod /* 15 */ - .long sys_lchown16 - .long sys_ni_syscall /* old break syscall holder */ - .long sys_stat - .long sys_lseek - .long sys_getpid /* 20 */ - .long sys_mount - .long sys_oldumount - .long sys_setuid16 - .long sys_getuid16 - .long sys_stime /* 25 */ - .long sys_ptrace - .long sys_alarm - .long sys_fstat - .long sys_pause - .long sys_utime /* 30 */ - .long sys_ni_syscall /* old stty syscall holder */ - .long sys_ni_syscall /* old gtty syscall holder */ - .long sys_access - .long sys_nice - .long sys_ni_syscall /* 35 - old ftime syscall holder */ - .long sys_sync - .long sys_kill - .long sys_rename - .long sys_mkdir - .long sys_rmdir /* 40 */ - .long sys_dup - .long sys_pipe - .long sys_times - .long sys_ni_syscall /* old prof syscall holder */ - .long sys_brk /* 45 */ - .long sys_setgid16 - .long sys_getgid16 - .long sys_signal - .long sys_geteuid16 - .long sys_getegid16 /* 50 */ - .long sys_acct - .long sys_umount /* recycled never used phys() */ - .long sys_ni_syscall /* old lock syscall holder */ - .long sys_ioctl - .long sys_fcntl /* 55 */ - .long sys_ni_syscall /* old mpx syscall holder */ - .long sys_setpgid - .long sys_ni_syscall /* old ulimit syscall holder */ - .long sys_olduname - .long sys_umask /* 60 */ - .long sys_chroot - .long sys_ustat - .long sys_dup2 - .long sys_getppid - .long sys_getpgrp /* 65 */ - .long sys_setsid - .long sys_sigaction - .long sys_sgetmask - .long sys_ssetmask - .long sys_setreuid16 /* 70 */ - .long sys_setregid16 - .long sys_sigsuspend - .long sys_sigpending - .long sys_sethostname - .long sys_setrlimit /* 75 */ - .long sys_old_getrlimit - .long sys_getrusage - .long sys_gettimeofday - .long sys_settimeofday - .long sys_getgroups16 /* 80 */ - .long sys_setgroups16 - .long sys_old_select - .long sys_symlink - .long sys_lstat - .long sys_readlink /* 85 */ - .long sys_uselib - .long sys_swapon - .long sys_reboot - .long sys_old_readdir - .long sys_old_mmap /* 90 */ - .long sys_munmap - .long sys_truncate - .long sys_ftruncate - .long sys_fchmod - .long sys_fchown16 /* 95 */ - .long sys_getpriority - .long sys_setpriority - .long sys_ni_syscall /* old profil syscall holder */ - .long sys_statfs - .long sys_fstatfs /* 100 */ - .long sys_ioperm - .long sys_socketcall - .long sys_syslog - .long sys_setitimer - .long sys_getitimer /* 105 */ - .long sys_newstat - .long sys_newlstat - .long sys_newfstat - .long sys_uname - .long ptregs_iopl /* 110 */ - .long sys_vhangup - .long sys_ni_syscall /* old "idle" system call */ - .long ptregs_vm86old - .long sys_wait4 - .long sys_swapoff /* 115 */ - .long sys_sysinfo - .long sys_ipc - .long sys_fsync - .long ptregs_sigreturn - .long ptregs_clone /* 120 */ - .long sys_setdomainname - .long sys_newuname - .long sys_modify_ldt - .long sys_adjtimex - .long sys_mprotect /* 125 */ - .long sys_sigprocmask - .long sys_ni_syscall /* old "create_module" */ - .long sys_init_module - .long sys_delete_module - .long sys_ni_syscall /* 130: old "get_kernel_syms" */ - .long sys_quotactl - .long sys_getpgid - .long sys_fchdir - .long sys_bdflush - .long sys_sysfs /* 135 */ - .long sys_personality - .long sys_ni_syscall /* reserved for afs_syscall */ - .long sys_setfsuid16 - .long sys_setfsgid16 - .long sys_llseek /* 140 */ - .long sys_getdents - .long sys_select - .long sys_flock - .long sys_msync - .long sys_readv /* 145 */ - .long sys_writev - .long sys_getsid - .long sys_fdatasync - .long sys_sysctl - .long sys_mlock /* 150 */ - .long sys_munlock - .long sys_mlockall - .long sys_munlockall - .long sys_sched_setparam - .long sys_sched_getparam /* 155 */ - .long sys_sched_setscheduler - .long sys_sched_getscheduler - .long sys_sched_yield - .long sys_sched_get_priority_max - .long sys_sched_get_priority_min /* 160 */ - .long sys_sched_rr_get_interval - .long sys_nanosleep - .long sys_mremap - .long sys_setresuid16 - .long sys_getresuid16 /* 165 */ - .long ptregs_vm86 - .long sys_ni_syscall /* Old sys_query_module */ - .long sys_poll - .long sys_ni_syscall /* Old nfsservctl */ - .long sys_setresgid16 /* 170 */ - .long sys_getresgid16 - .long sys_prctl - .long ptregs_rt_sigreturn - .long sys_rt_sigaction - .long sys_rt_sigprocmask /* 175 */ - .long sys_rt_sigpending - .long sys_rt_sigtimedwait - .long sys_rt_sigqueueinfo - .long sys_rt_sigsuspend - .long sys_pread64 /* 180 */ - .long sys_pwrite64 - .long sys_chown16 - .long sys_getcwd - .long sys_capget - .long sys_capset /* 185 */ - .long ptregs_sigaltstack - .long sys_sendfile - .long sys_ni_syscall /* reserved for streams1 */ - .long sys_ni_syscall /* reserved for streams2 */ - .long ptregs_vfork /* 190 */ - .long sys_getrlimit - .long sys_mmap_pgoff - .long sys_truncate64 - .long sys_ftruncate64 - .long sys_stat64 /* 195 */ - .long sys_lstat64 - .long sys_fstat64 - .long sys_lchown - .long sys_getuid - .long sys_getgid /* 200 */ - .long sys_geteuid - .long sys_getegid - .long sys_setreuid - .long sys_setregid - .long sys_getgroups /* 205 */ - .long sys_setgroups - .long sys_fchown - .long sys_setresuid - .long sys_getresuid - .long sys_setresgid /* 210 */ - .long sys_getresgid - .long sys_chown - .long sys_setuid - .long sys_setgid - .long sys_setfsuid /* 215 */ - .long sys_setfsgid - .long sys_pivot_root - .long sys_mincore - .long sys_madvise - .long sys_getdents64 /* 220 */ - .long sys_fcntl64 - .long sys_ni_syscall /* reserved for TUX */ - .long sys_ni_syscall - .long sys_gettid - .long sys_readahead /* 225 */ - .long sys_setxattr - .long sys_lsetxattr - .long sys_fsetxattr - .long sys_getxattr - .long sys_lgetxattr /* 230 */ - .long sys_fgetxattr - .long sys_listxattr - .long sys_llistxattr - .long sys_flistxattr - .long sys_removexattr /* 235 */ - .long sys_lremovexattr - .long sys_fremovexattr - .long sys_tkill - .long sys_sendfile64 - .long sys_futex /* 240 */ - .long sys_sched_setaffinity - .long sys_sched_getaffinity - .long sys_set_thread_area - .long sys_get_thread_area - .long sys_io_setup /* 245 */ - .long sys_io_destroy - .long sys_io_getevents - .long sys_io_submit - .long sys_io_cancel - .long sys_fadvise64 /* 250 */ - .long sys_ni_syscall - .long sys_exit_group - .long sys_lookup_dcookie - .long sys_epoll_create - .long sys_epoll_ctl /* 255 */ - .long sys_epoll_wait - .long sys_remap_file_pages - .long sys_set_tid_address - .long sys_timer_create - .long sys_timer_settime /* 260 */ - .long sys_timer_gettime - .long sys_timer_getoverrun - .long sys_timer_delete - .long sys_clock_settime - .long sys_clock_gettime /* 265 */ - .long sys_clock_getres - .long sys_clock_nanosleep - .long sys_statfs64 - .long sys_fstatfs64 - .long sys_tgkill /* 270 */ - .long sys_utimes - .long sys_fadvise64_64 - .long sys_ni_syscall /* sys_vserver */ - .long sys_mbind - .long sys_get_mempolicy - .long sys_set_mempolicy - .long sys_mq_open - .long sys_mq_unlink - .long sys_mq_timedsend - .long sys_mq_timedreceive /* 280 */ - .long sys_mq_notify - .long sys_mq_getsetattr - .long sys_kexec_load - .long sys_waitid - .long sys_ni_syscall /* 285 */ /* available */ - .long sys_add_key - .long sys_request_key - .long sys_keyctl - .long sys_ioprio_set - .long sys_ioprio_get /* 290 */ - .long sys_inotify_init - .long sys_inotify_add_watch - .long sys_inotify_rm_watch - .long sys_migrate_pages - .long sys_openat /* 295 */ - .long sys_mkdirat - .long sys_mknodat - .long sys_fchownat - .long sys_futimesat - .long sys_fstatat64 /* 300 */ - .long sys_unlinkat - .long sys_renameat - .long sys_linkat - .long sys_symlinkat - .long sys_readlinkat /* 305 */ - .long sys_fchmodat - .long sys_faccessat - .long sys_pselect6 - .long sys_ppoll - .long sys_unshare /* 310 */ - .long sys_set_robust_list - .long sys_get_robust_list - .long sys_splice - .long sys_sync_file_range - .long sys_tee /* 315 */ - .long sys_vmsplice - .long sys_move_pages - .long sys_getcpu - .long sys_epoll_pwait - .long sys_utimensat /* 320 */ - .long sys_signalfd - .long sys_timerfd_create - .long sys_eventfd - .long sys_fallocate - .long sys_timerfd_settime /* 325 */ - .long sys_timerfd_gettime - .long sys_signalfd4 - .long sys_eventfd2 - .long sys_epoll_create1 - .long sys_dup3 /* 330 */ - .long sys_pipe2 - .long sys_inotify_init1 - .long sys_preadv - .long sys_pwritev - .long sys_rt_tgsigqueueinfo /* 335 */ - .long sys_perf_event_open - .long sys_recvmmsg - .long sys_fanotify_init - .long sys_fanotify_mark - .long sys_prlimit64 /* 340 */ - .long sys_name_to_handle_at - .long sys_open_by_handle_at - .long sys_clock_adjtime - .long sys_syncfs - .long sys_sendmmsg /* 345 */ - .long sys_setns - .long sys_process_vm_readv - .long sys_process_vm_writev -- cgit v0.10.2 From b14dab792dee3245b628e046d80a7fad5573fea6 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Thu, 13 Oct 2011 12:33:30 +0530 Subject: DMAEngine: Define interleaved transfer request api Define a new api that could be used for doing fancy data transfers like interleaved to contiguous copy and vice-versa. Traditional SG_list based transfers tend to be very inefficient in such cases as where the interleave and chunk are only a few bytes, which call for a very condensed api to convey pattern of the transfer. This api supports all 4 variants of scatter-gather and contiguous transfer. Of course, neither can this api help transfers that don't lend to DMA by nature, i.e, scattered tiny read/writes with no periodic pattern. Also since now we support SLAVE channels that might not provide device_prep_slave_sg callback but device_prep_interleaved_dma, remove the BUG_ON check. Signed-off-by: Jassi Brar Acked-by: Barry Song [renamed dmaxfer_template to dma_interleaved_template did fixup after the enum dma_transfer_merge] Signed-off-by: Vinod Koul diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt index 94b7e0f..bbe6cb3 100644 --- a/Documentation/dmaengine.txt +++ b/Documentation/dmaengine.txt @@ -75,6 +75,10 @@ The slave DMA usage consists of following steps: slave_sg - DMA a list of scatter gather buffers from/to a peripheral dma_cyclic - Perform a cyclic DMA operation from/to a peripheral till the operation is explicitly stopped. + interleaved_dma - This is common to Slave as well as M2M clients. For slave + address of devices' fifo could be already known to the driver. + Various types of operations could be expressed by setting + appropriate values to the 'dma_interleaved_template' members. A non-NULL return of this transfer API represents a "descriptor" for the given transaction. @@ -89,6 +93,10 @@ The slave DMA usage consists of following steps: struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_data_direction direction); + struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)( + struct dma_chan *chan, struct dma_interleaved_template *xt, + unsigned long flags); + The peripheral driver is expected to have mapped the scatterlist for the DMA operation prior to calling device_prep_slave_sg, and must keep the scatterlist mapped until the DMA operation has completed. diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index b48967b..a6c6051 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -693,12 +693,12 @@ int dma_async_device_register(struct dma_device *device) !device->device_prep_dma_interrupt); BUG_ON(dma_has_cap(DMA_SG, device->cap_mask) && !device->device_prep_dma_sg); - BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) && - !device->device_prep_slave_sg); BUG_ON(dma_has_cap(DMA_CYCLIC, device->cap_mask) && !device->device_prep_dma_cyclic); BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) && !device->device_control); + BUG_ON(dma_has_cap(DMA_INTERLEAVE, device->cap_mask) && + !device->device_prep_interleaved_dma); BUG_ON(!device->device_alloc_chan_resources); BUG_ON(!device->device_free_chan_resources); diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index a865b3a..5532bb8 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -71,10 +71,10 @@ enum dma_transaction_type { DMA_ASYNC_TX, DMA_SLAVE, DMA_CYCLIC, -}; - + DMA_INTERLEAVE, /* last transaction type for creation of the capabilities mask */ -#define DMA_TX_TYPE_END (DMA_CYCLIC + 1) + DMA_TX_TYPE_END, +}; /** * enum dma_transfer_direction - dma transfer mode and direction indicator @@ -91,6 +91,74 @@ enum dma_transfer_direction { }; /** + * Interleaved Transfer Request + * ---------------------------- + * A chunk is collection of contiguous bytes to be transfered. + * The gap(in bytes) between two chunks is called inter-chunk-gap(ICG). + * ICGs may or maynot change between chunks. + * A FRAME is the smallest series of contiguous {chunk,icg} pairs, + * that when repeated an integral number of times, specifies the transfer. + * A transfer template is specification of a Frame, the number of times + * it is to be repeated and other per-transfer attributes. + * + * Practically, a client driver would have ready a template for each + * type of transfer it is going to need during its lifetime and + * set only 'src_start' and 'dst_start' before submitting the requests. + * + * + * | Frame-1 | Frame-2 | ~ | Frame-'numf' | + * |====....==.===...=...|====....==.===...=...| ~ |====....==.===...=...| + * + * == Chunk size + * ... ICG + */ + +/** + * struct data_chunk - Element of scatter-gather list that makes a frame. + * @size: Number of bytes to read from source. + * size_dst := fn(op, size_src), so doesn't mean much for destination. + * @icg: Number of bytes to jump after last src/dst address of this + * chunk and before first src/dst address for next chunk. + * Ignored for dst(assumed 0), if dst_inc is true and dst_sgl is false. + * Ignored for src(assumed 0), if src_inc is true and src_sgl is false. + */ +struct data_chunk { + size_t size; + size_t icg; +}; + +/** + * struct dma_interleaved_template - Template to convey DMAC the transfer pattern + * and attributes. + * @src_start: Bus address of source for the first chunk. + * @dst_start: Bus address of destination for the first chunk. + * @dir: Specifies the type of Source and Destination. + * @src_inc: If the source address increments after reading from it. + * @dst_inc: If the destination address increments after writing to it. + * @src_sgl: If the 'icg' of sgl[] applies to Source (scattered read). + * Otherwise, source is read contiguously (icg ignored). + * Ignored if src_inc is false. + * @dst_sgl: If the 'icg' of sgl[] applies to Destination (scattered write). + * Otherwise, destination is filled contiguously (icg ignored). + * Ignored if dst_inc is false. + * @numf: Number of frames in this template. + * @frame_size: Number of chunks in a frame i.e, size of sgl[]. + * @sgl: Array of {chunk,icg} pairs that make up a frame. + */ +struct dma_interleaved_template { + dma_addr_t src_start; + dma_addr_t dst_start; + enum dma_transfer_direction dir; + bool src_inc; + bool dst_inc; + bool src_sgl; + bool dst_sgl; + size_t numf; + size_t frame_size; + struct data_chunk sgl[0]; +}; + +/** * enum dma_ctrl_flags - DMA flags to augment operation preparation, * control completion, and communicate status. * @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of @@ -445,6 +513,7 @@ struct dma_tx_state { * @device_prep_dma_cyclic: prepare a cyclic dma operation suitable for audio. * The function takes a buffer of size buf_len. The callback function will * be called after period_len bytes have been transferred. + * @device_prep_interleaved_dma: Transfer expression in a generic way. * @device_control: manipulate all pending operations on a channel, returns * zero or error code * @device_tx_status: poll for transaction completion, the optional @@ -509,6 +578,9 @@ struct dma_device { struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_transfer_direction direction); + struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)( + struct dma_chan *chan, struct dma_interleaved_template *xt, + unsigned long flags); int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg); -- cgit v0.10.2 From ca21a146a45a179a2a7bc86d938a2fbf571a7510 Mon Sep 17 00:00:00 2001 From: Rongjun Ying Date: Thu, 27 Oct 2011 19:22:39 -0700 Subject: dmaengine: add CSR SiRFprimaII DMAC driver Cc: Jassi Brar Cc: Arnd Bergmann Cc: Linus Walleij Signed-off-by: Rongjun Ying Signed-off-by: Barry Song [fixed direction enums and cyclic api based on changes already merged] Signed-off-by: Vinod Koul diff --git a/MAINTAINERS b/MAINTAINERS index 4808256..1b141d7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -749,6 +749,7 @@ M: Barry Song L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-prima2/ +F: drivers/dma/sirf-dma* ARM/EBSA110 MACHINE SUPPORT M: Russell King diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 7ec0d6c..f1a2749 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -187,6 +187,13 @@ config TIMB_DMA help Enable support for the Timberdale FPGA DMA engine. +config SIRF_DMA + tristate "CSR SiRFprimaII DMA support" + depends on ARCH_PRIMA2 + select DMA_ENGINE + help + Enable support for the CSR SiRFprimaII DMA engine. + config ARCH_HAS_ASYNC_TX_FIND_CHANNEL bool diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 30cf3b1..009a222 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_IMX_SDMA) += imx-sdma.o obj-$(CONFIG_IMX_DMA) += imx-dma.o obj-$(CONFIG_MXS_DMA) += mxs-dma.o obj-$(CONFIG_TIMB_DMA) += timb_dma.o +obj-$(CONFIG_SIRF_DMA) += sirf-dma.o obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o obj-$(CONFIG_PL330_DMA) += pl330.o obj-$(CONFIG_PCH_DMA) += pch_dma.o diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c new file mode 100644 index 0000000..55ec679 --- /dev/null +++ b/drivers/dma/sirf-dma.c @@ -0,0 +1,717 @@ +/* + * DMA controller driver for CSR SiRFprimaII + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SIRFSOC_DMA_DESCRIPTORS 16 +#define SIRFSOC_DMA_CHANNELS 16 + +#define SIRFSOC_DMA_CH_ADDR 0x00 +#define SIRFSOC_DMA_CH_XLEN 0x04 +#define SIRFSOC_DMA_CH_YLEN 0x08 +#define SIRFSOC_DMA_CH_CTRL 0x0C + +#define SIRFSOC_DMA_WIDTH_0 0x100 +#define SIRFSOC_DMA_CH_VALID 0x140 +#define SIRFSOC_DMA_CH_INT 0x144 +#define SIRFSOC_DMA_INT_EN 0x148 +#define SIRFSOC_DMA_CH_LOOP_CTRL 0x150 + +#define SIRFSOC_DMA_MODE_CTRL_BIT 4 +#define SIRFSOC_DMA_DIR_CTRL_BIT 5 + +/* xlen and dma_width register is in 4 bytes boundary */ +#define SIRFSOC_DMA_WORD_LEN 4 + +struct sirfsoc_dma_desc { + struct dma_async_tx_descriptor desc; + struct list_head node; + + /* SiRFprimaII 2D-DMA parameters */ + + int xlen; /* DMA xlen */ + int ylen; /* DMA ylen */ + int width; /* DMA width */ + int dir; + bool cyclic; /* is loop DMA? */ + u32 addr; /* DMA buffer address */ +}; + +struct sirfsoc_dma_chan { + struct dma_chan chan; + struct list_head free; + struct list_head prepared; + struct list_head queued; + struct list_head active; + struct list_head completed; + dma_cookie_t completed_cookie; + unsigned long happened_cyclic; + unsigned long completed_cyclic; + + /* Lock for this structure */ + spinlock_t lock; + + int mode; +}; + +struct sirfsoc_dma { + struct dma_device dma; + struct tasklet_struct tasklet; + struct sirfsoc_dma_chan channels[SIRFSOC_DMA_CHANNELS]; + void __iomem *base; + int irq; +}; + +#define DRV_NAME "sirfsoc_dma" + +/* Convert struct dma_chan to struct sirfsoc_dma_chan */ +static inline +struct sirfsoc_dma_chan *dma_chan_to_sirfsoc_dma_chan(struct dma_chan *c) +{ + return container_of(c, struct sirfsoc_dma_chan, chan); +} + +/* Convert struct dma_chan to struct sirfsoc_dma */ +static inline struct sirfsoc_dma *dma_chan_to_sirfsoc_dma(struct dma_chan *c) +{ + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(c); + return container_of(schan, struct sirfsoc_dma, channels[c->chan_id]); +} + +/* Execute all queued DMA descriptors */ +static void sirfsoc_dma_execute(struct sirfsoc_dma_chan *schan) +{ + struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(&schan->chan); + int cid = schan->chan.chan_id; + struct sirfsoc_dma_desc *sdesc = NULL; + + /* + * lock has been held by functions calling this, so we don't hold + * lock again + */ + + sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc, + node); + /* Move the first queued descriptor to active list */ + list_move_tail(&schan->queued, &schan->active); + + /* Start the DMA transfer */ + writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 + + cid * 4); + writel_relaxed(cid | (schan->mode << SIRFSOC_DMA_MODE_CTRL_BIT) | + (sdesc->dir << SIRFSOC_DMA_DIR_CTRL_BIT), + sdma->base + cid * 0x10 + SIRFSOC_DMA_CH_CTRL); + writel_relaxed(sdesc->xlen, sdma->base + cid * 0x10 + + SIRFSOC_DMA_CH_XLEN); + writel_relaxed(sdesc->ylen, sdma->base + cid * 0x10 + + SIRFSOC_DMA_CH_YLEN); + writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_INT_EN) | + (1 << cid), sdma->base + SIRFSOC_DMA_INT_EN); + + /* + * writel has an implict memory write barrier to make sure data is + * flushed into memory before starting DMA + */ + writel(sdesc->addr >> 2, sdma->base + cid * 0x10 + SIRFSOC_DMA_CH_ADDR); + + if (sdesc->cyclic) { + writel((1 << cid) | 1 << (cid + 16) | + readl_relaxed(sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL), + sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL); + schan->happened_cyclic = schan->completed_cyclic = 0; + } +} + +/* Interrupt handler */ +static irqreturn_t sirfsoc_dma_irq(int irq, void *data) +{ + struct sirfsoc_dma *sdma = data; + struct sirfsoc_dma_chan *schan; + struct sirfsoc_dma_desc *sdesc = NULL; + u32 is; + int ch; + + is = readl(sdma->base + SIRFSOC_DMA_CH_INT); + while ((ch = fls(is) - 1) >= 0) { + is &= ~(1 << ch); + writel_relaxed(1 << ch, sdma->base + SIRFSOC_DMA_CH_INT); + schan = &sdma->channels[ch]; + + spin_lock(&schan->lock); + + sdesc = list_first_entry(&schan->active, struct sirfsoc_dma_desc, + node); + if (!sdesc->cyclic) { + /* Execute queued descriptors */ + list_splice_tail_init(&schan->active, &schan->completed); + if (!list_empty(&schan->queued)) + sirfsoc_dma_execute(schan); + } else + schan->happened_cyclic++; + + spin_unlock(&schan->lock); + } + + /* Schedule tasklet */ + tasklet_schedule(&sdma->tasklet); + + return IRQ_HANDLED; +} + +/* process completed descriptors */ +static void sirfsoc_dma_process_completed(struct sirfsoc_dma *sdma) +{ + dma_cookie_t last_cookie = 0; + struct sirfsoc_dma_chan *schan; + struct sirfsoc_dma_desc *sdesc; + struct dma_async_tx_descriptor *desc; + unsigned long flags; + unsigned long happened_cyclic; + LIST_HEAD(list); + int i; + + for (i = 0; i < sdma->dma.chancnt; i++) { + schan = &sdma->channels[i]; + + /* Get all completed descriptors */ + spin_lock_irqsave(&schan->lock, flags); + if (!list_empty(&schan->completed)) { + list_splice_tail_init(&schan->completed, &list); + spin_unlock_irqrestore(&schan->lock, flags); + + /* Execute callbacks and run dependencies */ + list_for_each_entry(sdesc, &list, node) { + desc = &sdesc->desc; + + if (desc->callback) + desc->callback(desc->callback_param); + + last_cookie = desc->cookie; + dma_run_dependencies(desc); + } + + /* Free descriptors */ + spin_lock_irqsave(&schan->lock, flags); + list_splice_tail_init(&list, &schan->free); + schan->completed_cookie = last_cookie; + spin_unlock_irqrestore(&schan->lock, flags); + } else { + /* for cyclic channel, desc is always in active list */ + sdesc = list_first_entry(&schan->active, struct sirfsoc_dma_desc, + node); + + if (!sdesc || (sdesc && !sdesc->cyclic)) { + /* without active cyclic DMA */ + spin_unlock_irqrestore(&schan->lock, flags); + continue; + } + + /* cyclic DMA */ + happened_cyclic = schan->happened_cyclic; + spin_unlock_irqrestore(&schan->lock, flags); + + desc = &sdesc->desc; + while (happened_cyclic != schan->completed_cyclic) { + if (desc->callback) + desc->callback(desc->callback_param); + schan->completed_cyclic++; + } + } + } +} + +/* DMA Tasklet */ +static void sirfsoc_dma_tasklet(unsigned long data) +{ + struct sirfsoc_dma *sdma = (void *)data; + + sirfsoc_dma_process_completed(sdma); +} + +/* Submit descriptor to hardware */ +static dma_cookie_t sirfsoc_dma_tx_submit(struct dma_async_tx_descriptor *txd) +{ + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(txd->chan); + struct sirfsoc_dma_desc *sdesc; + unsigned long flags; + dma_cookie_t cookie; + + sdesc = container_of(txd, struct sirfsoc_dma_desc, desc); + + spin_lock_irqsave(&schan->lock, flags); + + /* Move descriptor to queue */ + list_move_tail(&sdesc->node, &schan->queued); + + /* Update cookie */ + cookie = schan->chan.cookie + 1; + if (cookie <= 0) + cookie = 1; + + schan->chan.cookie = cookie; + sdesc->desc.cookie = cookie; + + spin_unlock_irqrestore(&schan->lock, flags); + + return cookie; +} + +static int sirfsoc_dma_slave_config(struct sirfsoc_dma_chan *schan, + struct dma_slave_config *config) +{ + unsigned long flags; + + if ((config->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) || + (config->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)) + return -EINVAL; + + spin_lock_irqsave(&schan->lock, flags); + schan->mode = (config->src_maxburst == 4 ? 1 : 0); + spin_unlock_irqrestore(&schan->lock, flags); + + return 0; +} + +static int sirfsoc_dma_terminate_all(struct sirfsoc_dma_chan *schan) +{ + struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(&schan->chan); + int cid = schan->chan.chan_id; + unsigned long flags; + + writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_INT_EN) & + ~(1 << cid), sdma->base + SIRFSOC_DMA_INT_EN); + writel_relaxed(1 << cid, sdma->base + SIRFSOC_DMA_CH_VALID); + + writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL) + & ~((1 << cid) | 1 << (cid + 16)), + sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL); + + spin_lock_irqsave(&schan->lock, flags); + list_splice_tail_init(&schan->active, &schan->free); + list_splice_tail_init(&schan->queued, &schan->free); + spin_unlock_irqrestore(&schan->lock, flags); + + return 0; +} + +static int sirfsoc_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg) +{ + struct dma_slave_config *config; + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); + + switch (cmd) { + case DMA_TERMINATE_ALL: + return sirfsoc_dma_terminate_all(schan); + case DMA_SLAVE_CONFIG: + config = (struct dma_slave_config *)arg; + return sirfsoc_dma_slave_config(schan, config); + + default: + break; + } + + return -ENOSYS; +} + +/* Alloc channel resources */ +static int sirfsoc_dma_alloc_chan_resources(struct dma_chan *chan) +{ + struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(chan); + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); + struct sirfsoc_dma_desc *sdesc; + unsigned long flags; + LIST_HEAD(descs); + int i; + + /* Alloc descriptors for this channel */ + for (i = 0; i < SIRFSOC_DMA_DESCRIPTORS; i++) { + sdesc = kzalloc(sizeof(*sdesc), GFP_KERNEL); + if (!sdesc) { + dev_notice(sdma->dma.dev, "Memory allocation error. " + "Allocated only %u descriptors\n", i); + break; + } + + dma_async_tx_descriptor_init(&sdesc->desc, chan); + sdesc->desc.flags = DMA_CTRL_ACK; + sdesc->desc.tx_submit = sirfsoc_dma_tx_submit; + + list_add_tail(&sdesc->node, &descs); + } + + /* Return error only if no descriptors were allocated */ + if (i == 0) + return -ENOMEM; + + spin_lock_irqsave(&schan->lock, flags); + + list_splice_tail_init(&descs, &schan->free); + spin_unlock_irqrestore(&schan->lock, flags); + + return i; +} + +/* Free channel resources */ +static void sirfsoc_dma_free_chan_resources(struct dma_chan *chan) +{ + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); + struct sirfsoc_dma_desc *sdesc, *tmp; + unsigned long flags; + LIST_HEAD(descs); + + spin_lock_irqsave(&schan->lock, flags); + + /* Channel must be idle */ + BUG_ON(!list_empty(&schan->prepared)); + BUG_ON(!list_empty(&schan->queued)); + BUG_ON(!list_empty(&schan->active)); + BUG_ON(!list_empty(&schan->completed)); + + /* Move data */ + list_splice_tail_init(&schan->free, &descs); + + spin_unlock_irqrestore(&schan->lock, flags); + + /* Free descriptors */ + list_for_each_entry_safe(sdesc, tmp, &descs, node) + kfree(sdesc); +} + +/* Send pending descriptor to hardware */ +static void sirfsoc_dma_issue_pending(struct dma_chan *chan) +{ + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); + unsigned long flags; + + spin_lock_irqsave(&schan->lock, flags); + + if (list_empty(&schan->active) && !list_empty(&schan->queued)) + sirfsoc_dma_execute(schan); + + spin_unlock_irqrestore(&schan->lock, flags); +} + +/* Check request completion status */ +static enum dma_status +sirfsoc_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie, + struct dma_tx_state *txstate) +{ + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); + unsigned long flags; + dma_cookie_t last_used; + dma_cookie_t last_complete; + + spin_lock_irqsave(&schan->lock, flags); + last_used = schan->chan.cookie; + last_complete = schan->completed_cookie; + spin_unlock_irqrestore(&schan->lock, flags); + + dma_set_tx_state(txstate, last_complete, last_used, 0); + return dma_async_is_complete(cookie, last_complete, last_used); +} + +static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved( + struct dma_chan *chan, struct dma_interleaved_template *xt, + unsigned long flags) +{ + struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(chan); + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); + struct sirfsoc_dma_desc *sdesc = NULL; + unsigned long iflags; + int ret; + + if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) { + ret = -EINVAL; + goto err_dir; + } + + /* Get free descriptor */ + spin_lock_irqsave(&schan->lock, iflags); + if (!list_empty(&schan->free)) { + sdesc = list_first_entry(&schan->free, struct sirfsoc_dma_desc, + node); + list_del(&sdesc->node); + } + spin_unlock_irqrestore(&schan->lock, iflags); + + if (!sdesc) { + /* try to free completed descriptors */ + sirfsoc_dma_process_completed(sdma); + ret = 0; + goto no_desc; + } + + /* Place descriptor in prepared list */ + spin_lock_irqsave(&schan->lock, iflags); + + /* + * Number of chunks in a frame can only be 1 for prima2 + * and ylen (number of frame - 1) must be at least 0 + */ + if ((xt->frame_size == 1) && (xt->numf > 0)) { + sdesc->cyclic = 0; + sdesc->xlen = xt->sgl[0].size / SIRFSOC_DMA_WORD_LEN; + sdesc->width = (xt->sgl[0].size + xt->sgl[0].icg) / + SIRFSOC_DMA_WORD_LEN; + sdesc->ylen = xt->numf - 1; + if (xt->dir == DMA_MEM_TO_DEV) { + sdesc->addr = xt->src_start; + sdesc->dir = 1; + } else { + sdesc->addr = xt->dst_start; + sdesc->dir = 0; + } + + list_add_tail(&sdesc->node, &schan->prepared); + } else { + pr_err("sirfsoc DMA Invalid xfer\n"); + ret = -EINVAL; + goto err_xfer; + } + spin_unlock_irqrestore(&schan->lock, iflags); + + return &sdesc->desc; +err_xfer: + spin_unlock_irqrestore(&schan->lock, iflags); +no_desc: +err_dir: + return ERR_PTR(ret); +} + +static struct dma_async_tx_descriptor * +sirfsoc_dma_prep_cyclic(struct dma_chan *chan, dma_addr_t addr, + size_t buf_len, size_t period_len, + enum dma_transfer_direction direction) +{ + struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); + struct sirfsoc_dma_desc *sdesc = NULL; + unsigned long iflags; + + /* + * we only support cycle transfer with 2 period + * If the X-length is set to 0, it would be the loop mode. + * The DMA address keeps increasing until reaching the end of a loop + * area whose size is defined by (DMA_WIDTH x (Y_LENGTH + 1)). Then + * the DMA address goes back to the beginning of this area. + * In loop mode, the DMA data region is divided into two parts, BUFA + * and BUFB. DMA controller generates interrupts twice in each loop: + * when the DMA address reaches the end of BUFA or the end of the + * BUFB + */ + if (buf_len != 2 * period_len) + return ERR_PTR(-EINVAL); + + /* Get free descriptor */ + spin_lock_irqsave(&schan->lock, iflags); + if (!list_empty(&schan->free)) { + sdesc = list_first_entry(&schan->free, struct sirfsoc_dma_desc, + node); + list_del(&sdesc->node); + } + spin_unlock_irqrestore(&schan->lock, iflags); + + if (!sdesc) + return 0; + + /* Place descriptor in prepared list */ + spin_lock_irqsave(&schan->lock, iflags); + sdesc->addr = addr; + sdesc->cyclic = 1; + sdesc->xlen = 0; + sdesc->ylen = buf_len / SIRFSOC_DMA_WORD_LEN - 1; + sdesc->width = 1; + list_add_tail(&sdesc->node, &schan->prepared); + spin_unlock_irqrestore(&schan->lock, iflags); + + return &sdesc->desc; +} + +/* + * The DMA controller consists of 16 independent DMA channels. + * Each channel is allocated to a different function + */ +bool sirfsoc_dma_filter_id(struct dma_chan *chan, void *chan_id) +{ + unsigned int ch_nr = (unsigned int) chan_id; + + if (ch_nr == chan->chan_id + + chan->device->dev_id * SIRFSOC_DMA_CHANNELS) + return true; + + return false; +} +EXPORT_SYMBOL(sirfsoc_dma_filter_id); + +static int __devinit sirfsoc_dma_probe(struct platform_device *op) +{ + struct device_node *dn = op->dev.of_node; + struct device *dev = &op->dev; + struct dma_device *dma; + struct sirfsoc_dma *sdma; + struct sirfsoc_dma_chan *schan; + struct resource res; + ulong regs_start, regs_size; + u32 id; + int ret, i; + + sdma = devm_kzalloc(dev, sizeof(*sdma), GFP_KERNEL); + if (!sdma) { + dev_err(dev, "Memory exhausted!\n"); + return -ENOMEM; + } + + if (of_property_read_u32(dn, "cell-index", &id)) { + dev_err(dev, "Fail to get DMAC index\n"); + ret = -ENODEV; + goto free_mem; + } + + sdma->irq = irq_of_parse_and_map(dn, 0); + if (sdma->irq == NO_IRQ) { + dev_err(dev, "Error mapping IRQ!\n"); + ret = -EINVAL; + goto free_mem; + } + + ret = of_address_to_resource(dn, 0, &res); + if (ret) { + dev_err(dev, "Error parsing memory region!\n"); + goto free_mem; + } + + regs_start = res.start; + regs_size = resource_size(&res); + + sdma->base = devm_ioremap(dev, regs_start, regs_size); + if (!sdma->base) { + dev_err(dev, "Error mapping memory region!\n"); + ret = -ENOMEM; + goto irq_dispose; + } + + ret = devm_request_irq(dev, sdma->irq, &sirfsoc_dma_irq, 0, DRV_NAME, + sdma); + if (ret) { + dev_err(dev, "Error requesting IRQ!\n"); + ret = -EINVAL; + goto unmap_mem; + } + + dma = &sdma->dma; + dma->dev = dev; + dma->chancnt = SIRFSOC_DMA_CHANNELS; + + dma->device_alloc_chan_resources = sirfsoc_dma_alloc_chan_resources; + dma->device_free_chan_resources = sirfsoc_dma_free_chan_resources; + dma->device_issue_pending = sirfsoc_dma_issue_pending; + dma->device_control = sirfsoc_dma_control; + dma->device_tx_status = sirfsoc_dma_tx_status; + dma->device_prep_interleaved_dma = sirfsoc_dma_prep_interleaved; + dma->device_prep_dma_cyclic = sirfsoc_dma_prep_cyclic; + + INIT_LIST_HEAD(&dma->channels); + dma_cap_set(DMA_SLAVE, dma->cap_mask); + dma_cap_set(DMA_CYCLIC, dma->cap_mask); + dma_cap_set(DMA_INTERLEAVE, dma->cap_mask); + dma_cap_set(DMA_PRIVATE, dma->cap_mask); + + for (i = 0; i < dma->chancnt; i++) { + schan = &sdma->channels[i]; + + schan->chan.device = dma; + schan->chan.cookie = 1; + schan->completed_cookie = schan->chan.cookie; + + INIT_LIST_HEAD(&schan->free); + INIT_LIST_HEAD(&schan->prepared); + INIT_LIST_HEAD(&schan->queued); + INIT_LIST_HEAD(&schan->active); + INIT_LIST_HEAD(&schan->completed); + + spin_lock_init(&schan->lock); + list_add_tail(&schan->chan.device_node, &dma->channels); + } + + tasklet_init(&sdma->tasklet, sirfsoc_dma_tasklet, (unsigned long)sdma); + + /* Register DMA engine */ + dev_set_drvdata(dev, sdma); + ret = dma_async_device_register(dma); + if (ret) + goto free_irq; + + dev_info(dev, "initialized SIRFSOC DMAC driver\n"); + + return 0; + +free_irq: + devm_free_irq(dev, sdma->irq, sdma); +irq_dispose: + irq_dispose_mapping(sdma->irq); +unmap_mem: + iounmap(sdma->base); +free_mem: + devm_kfree(dev, sdma); + return ret; +} + +static int __devexit sirfsoc_dma_remove(struct platform_device *op) +{ + struct device *dev = &op->dev; + struct sirfsoc_dma *sdma = dev_get_drvdata(dev); + + dma_async_device_unregister(&sdma->dma); + devm_free_irq(dev, sdma->irq, sdma); + irq_dispose_mapping(sdma->irq); + iounmap(sdma->base); + devm_kfree(dev, sdma); + return 0; +} + +static struct of_device_id sirfsoc_dma_match[] = { + { .compatible = "sirf,prima2-dmac", }, + {}, +}; + +static struct platform_driver sirfsoc_dma_driver = { + .probe = sirfsoc_dma_probe, + .remove = __devexit_p(sirfsoc_dma_remove), + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = sirfsoc_dma_match, + }, +}; + +static int __init sirfsoc_dma_init(void) +{ + return platform_driver_register(&sirfsoc_dma_driver); +} +module_init(sirfsoc_dma_init); + +static void __exit sirfsoc_dma_exit(void) +{ + platform_driver_unregister(&sirfsoc_dma_driver); +} +module_exit(sirfsoc_dma_exit); + +MODULE_AUTHOR("Rongjun Ying , " + "Barry Song "); +MODULE_DESCRIPTION("SIRFSOC DMA control driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/sirfsoc_dma.h b/include/linux/sirfsoc_dma.h new file mode 100644 index 0000000..29d9593 --- /dev/null +++ b/include/linux/sirfsoc_dma.h @@ -0,0 +1,6 @@ +#ifndef _SIRFSOC_DMA_H_ +#define _SIRFSOC_DMA_H_ + +bool sirfsoc_dma_filter_id(struct dma_chan *chan, void *chan_id); + +#endif -- cgit v0.10.2 From 553575f1ae048aa44682b46b3c51929a0b3ad337 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 18 Nov 2011 03:32:01 -0500 Subject: tools turbostat: recognize and run properly on IVB Signed-off-by: Len Brown diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 8b2d37b..4b05b44 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -809,6 +809,8 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model) case 0x2C: /* Westmere EP - Gulftown */ case 0x2A: /* SNB */ case 0x2D: /* SNB Xeon */ + case 0x3A: /* IVB */ + case 0x3D: /* IVB Xeon */ return 1; case 0x2E: /* Nehalem-EX Xeon - Beckton */ case 0x2F: /* Westmere-EX Xeon - Eagleton */ -- cgit v0.10.2 From a9dd5d631729eea8686703fbb25a7a9d4c75a724 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Fri, 18 Nov 2011 17:05:29 +0530 Subject: ktest: Save test output The test output may contain useful information; save it along with the already-saved buildlog, dmesg, and .config. Link: http://lkml.kernel.org/r/1321616131-21352-1-git-send-email-rabin@rab.in Signed-off-by: Rabin Vincent Signed-off-by: Steven Rostedt diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 8b4c253..e93c21c 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -103,6 +103,7 @@ my $in_patchcheck = 0; my $run_test; my $redirect; my $buildlog; +my $testlog; my $dmesg; my $monitor_fp; my $monitor_pid; @@ -1021,17 +1022,19 @@ sub fail { mkpath($faildir) or die "can't create $faildir"; } - if (-f "$output_config") { - cp "$output_config", "$faildir/config" or - die "failed to copy .config"; - } - if (-f $buildlog) { - cp $buildlog, "$faildir/buildlog" or - die "failed to move $buildlog"; - } - if (-f $dmesg) { - cp $dmesg, "$faildir/dmesg" or - die "failed to move $dmesg"; + + my %files = ( + "config" => $output_config, + "buildlog" => $buildlog, + "dmesg" => $dmesg, + "testlog" => $testlog, + ); + + while (my ($name, $source) = each(%files)) { + if (-f "$source") { + cp "$source", "$faildir/$name" or + die "failed to copy $source"; + } } doprint "*** Saved info to $faildir ***\n"; @@ -1669,7 +1672,10 @@ sub child_run_test { $poweroff_on_error = 0; $die_on_failure = 1; + $redirect = "$testlog"; run_command $run_test or $failed = 1; + undef $redirect; + exit $failed; } @@ -3169,6 +3175,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $target = "$ssh_user\@$machine"; $buildlog = "$tmpdir/buildlog-$machine"; + $testlog = "$tmpdir/testlog-$machine"; $dmesg = "$tmpdir/dmesg-$machine"; $make = "$makecmd O=$outputdir"; $output_config = "$outputdir/.config"; @@ -3205,6 +3212,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { unlink $dmesg; unlink $buildlog; + unlink $testlog; if (defined($addconfig)) { my $min = $minconfig; -- cgit v0.10.2 From de5b6e3bf5e71532057fb4f1eb8ee29c5c7f11db Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Fri, 18 Nov 2011 17:05:31 +0530 Subject: ktest: Allow success logs to be stored Add a STORE_SUCCESSES option, to allow success logs to be stored, for example to double-check or otherwise post-process the test logs. Link: http://lkml.kernel.org/r/1321616131-21352-3-git-send-email-rabin@rab.in Signed-off-by: Rabin Vincent Signed-off-by: Steven Rostedt diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index e93c21c..6ef104e 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -113,6 +113,7 @@ my $bisect_sleep_time; my $patchcheck_sleep_time; my $ignore_warnings; my $store_failures; +my $store_successes; my $test_name; my $timeout; my $booted_timeout; @@ -976,6 +977,43 @@ sub wait_for_monitor { print "** Monitor flushed **\n"; } +sub save_logs { + my ($result, $basedir) = @_; + my @t = localtime; + my $date = sprintf "%04d%02d%02d%02d%02d%02d", + 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; + + my $type = $build_type; + if ($type =~ /useconfig/) { + $type = "useconfig"; + } + + my $dir = "$machine-$test_type-$type-$result-$date"; + + $dir = "$basedir/$dir"; + + if (!-d $dir) { + mkpath($dir) or + die "can't create $dir"; + } + + my %files = ( + "config" => $output_config, + "buildlog" => $buildlog, + "dmesg" => $dmesg, + "testlog" => $testlog, + ); + + while (my ($name, $source) = each(%files)) { + if (-f "$source") { + cp "$source", "$dir/$name" or + die "failed to copy $source"; + } + } + + doprint "*** Saved info to $dir ***\n"; +} + sub fail { if ($die_on_failure) { @@ -1004,40 +1042,9 @@ sub fail { doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; - return 1 if (!defined($store_failures)); - - my @t = localtime; - my $date = sprintf "%04d%02d%02d%02d%02d%02d", - 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0]; - - my $type = $build_type; - if ($type =~ /useconfig/) { - $type = "useconfig"; - } - - my $dir = "$machine-$test_type-$type-fail-$date"; - my $faildir = "$store_failures/$dir"; - - if (!-d $faildir) { - mkpath($faildir) or - die "can't create $faildir"; - } - - my %files = ( - "config" => $output_config, - "buildlog" => $buildlog, - "dmesg" => $dmesg, - "testlog" => $testlog, - ); - - while (my ($name, $source) = each(%files)) { - if (-f "$source") { - cp "$source", "$faildir/$name" or - die "failed to copy $source"; - } - } - - doprint "*** Saved info to $faildir ***\n"; + if (defined($store_failures)) { + save_logs "fail", $store_failures; + } return 1; } @@ -1643,6 +1650,10 @@ sub success { doprint "*******************************************\n"; doprint "*******************************************\n"; + if (defined($store_successes)) { + save_logs "success", $store_successes; + } + if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) { doprint "Reboot and wait $sleep_time seconds\n"; reboot $sleep_time; @@ -3137,6 +3148,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $bisect_skip = set_test_option("BISECT_SKIP", $i); $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i); $store_failures = set_test_option("STORE_FAILURES", $i); + $store_successes = set_test_option("STORE_SUCCESSES", $i); $test_name = set_test_option("TEST_NAME", $i); $timeout = set_test_option("TIMEOUT", $i); $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index dbedfa1..42e0eb9 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -589,6 +589,12 @@ # (default undefined) #STORE_FAILURES = /home/test/failures +# Directory to store success directories on success. If this is not +# set, the .config, dmesg and bootlog will not be saved if a +# test succeeds. +# (default undefined) +#STORE_SUCCESSES = /home/test/successes + # Build without doing a make mrproper, or removing .config # (default 0) #BUILD_NOCLEAN = 0 -- cgit v0.10.2 From 97e36834f5a106459ab1b290e663a4eb6264639e Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 12 Oct 2011 12:12:36 -0400 Subject: xen/blk[front|back]: Squash blkif_request_rw and blkif_request_discard together In a union type structure to deal with the overlapping attributes in a easier manner. Suggested-by: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 15ec4db..d7104ab 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -362,7 +362,7 @@ static int xen_blkbk_map(struct blkif_request *req, { struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST]; int i; - int nseg = req->nr_segments; + int nseg = req->u.rw.nr_segments; int ret = 0; /* @@ -449,7 +449,7 @@ static void xen_blk_discard(struct xen_blkif *blkif, struct blkif_request *req) } else if (err) status = BLKIF_RSP_ERROR; - make_response(blkif, req->id, req->operation, status); + make_response(blkif, req->u.discard.id, req->operation, status); } static void xen_blk_drain_io(struct xen_blkif *blkif) @@ -644,7 +644,8 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, } /* Check that the number of segments is sane. */ - nseg = req->nr_segments; + nseg = req->u.rw.nr_segments; + if (unlikely(nseg == 0 && operation != WRITE_FLUSH && operation != REQ_DISCARD) || unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) { @@ -654,12 +655,12 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, goto fail_response; } - preq.dev = req->handle; + preq.dev = req->u.rw.handle; preq.sector_number = req->u.rw.sector_number; preq.nr_sects = 0; pending_req->blkif = blkif; - pending_req->id = req->id; + pending_req->id = req->u.rw.id; pending_req->operation = req->operation; pending_req->status = BLKIF_RSP_OKAY; pending_req->nr_pages = nseg; @@ -784,7 +785,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, xen_blkbk_unmap(pending_req); fail_response: /* Haven't submitted any bio's yet. */ - make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR); + make_response(blkif, req->u.rw.id, req->operation, BLKIF_RSP_ERROR); free_req(pending_req); msleep(1); /* back off a bit */ return -EIO; diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index dfb1b3a..dbfe7b3 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -60,58 +60,66 @@ struct blkif_common_response { char dummy; }; -/* i386 protocol version */ -#pragma pack(push, 4) - struct blkif_x86_32_request_rw { + uint8_t nr_segments; /* number of segments */ + blkif_vdev_t handle; /* only for read/write requests */ + uint64_t id; /* private guest value, echoed in resp */ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; -}; +} __attribute__((__packed__)); struct blkif_x86_32_request_discard { + uint8_t nr_segments; /* number of segments */ + blkif_vdev_t _pad1; /* was "handle" for read/write requests */ + uint64_t id; /* private guest value, echoed in resp */ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ - uint64_t nr_sectors; -}; + uint64_t nr_sectors; +} __attribute__((__packed__)); struct blkif_x86_32_request { uint8_t operation; /* BLKIF_OP_??? */ - uint8_t nr_segments; /* number of segments */ - blkif_vdev_t handle; /* only for read/write requests */ - uint64_t id; /* private guest value, echoed in resp */ union { struct blkif_x86_32_request_rw rw; struct blkif_x86_32_request_discard discard; } u; -}; +} __attribute__((__packed__)); + +/* i386 protocol version */ +#pragma pack(push, 4) struct blkif_x86_32_response { uint64_t id; /* copied from request */ uint8_t operation; /* copied from request */ int16_t status; /* BLKIF_RSP_??? */ }; #pragma pack(pop) - /* x86_64 protocol version */ struct blkif_x86_64_request_rw { + uint8_t nr_segments; /* number of segments */ + blkif_vdev_t handle; /* only for read/write requests */ + uint32_t _pad1; /* offsetof(blkif_reqest..,u.rw.id)==8 */ + uint64_t id; blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; -}; +} __attribute__((__packed__)); struct blkif_x86_64_request_discard { + uint8_t nr_segments; /* number of segments */ + blkif_vdev_t _pad1; /* was "handle" for read/write requests */ + uint32_t _pad2; /* offsetof(blkif_..,u.discard.id)==8 */ + uint64_t id; blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ - uint64_t nr_sectors; -}; + uint64_t nr_sectors; +} __attribute__((__packed__)); struct blkif_x86_64_request { uint8_t operation; /* BLKIF_OP_??? */ - uint8_t nr_segments; /* number of segments */ - blkif_vdev_t handle; /* only for read/write requests */ - uint64_t __attribute__((__aligned__(8))) id; union { struct blkif_x86_64_request_rw rw; struct blkif_x86_64_request_discard discard; } u; -}; +} __attribute__((__packed__)); + struct blkif_x86_64_response { uint64_t __attribute__((__aligned__(8))) id; uint8_t operation; /* copied from request */ @@ -237,18 +245,18 @@ static inline void blkif_get_x86_32_req(struct blkif_request *dst, { int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; dst->operation = src->operation; - dst->nr_segments = src->nr_segments; - dst->handle = src->handle; - dst->id = src->id; switch (src->operation) { case BLKIF_OP_READ: case BLKIF_OP_WRITE: case BLKIF_OP_WRITE_BARRIER: case BLKIF_OP_FLUSH_DISKCACHE: + dst->u.rw.nr_segments = src->u.rw.nr_segments; + dst->u.rw.handle = src->u.rw.handle; + dst->u.rw.id = src->u.rw.id; dst->u.rw.sector_number = src->u.rw.sector_number; barrier(); - if (n > dst->nr_segments) - n = dst->nr_segments; + if (n > dst->u.rw.nr_segments) + n = dst->u.rw.nr_segments; for (i = 0; i < n; i++) dst->u.rw.seg[i] = src->u.rw.seg[i]; break; @@ -266,18 +274,18 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst, { int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; dst->operation = src->operation; - dst->nr_segments = src->nr_segments; - dst->handle = src->handle; - dst->id = src->id; switch (src->operation) { case BLKIF_OP_READ: case BLKIF_OP_WRITE: case BLKIF_OP_WRITE_BARRIER: case BLKIF_OP_FLUSH_DISKCACHE: + dst->u.rw.nr_segments = src->u.rw.nr_segments; + dst->u.rw.handle = src->u.rw.handle; + dst->u.rw.id = src->u.rw.id; dst->u.rw.sector_number = src->u.rw.sector_number; barrier(); - if (n > dst->nr_segments) - n = dst->nr_segments; + if (n > dst->u.rw.nr_segments) + n = dst->u.rw.nr_segments; for (i = 0; i < n; i++) dst->u.rw.seg[i] = src->u.rw.seg[i]; break; diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 7b2ec59..2c2c4be 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -135,15 +135,15 @@ static int get_id_from_freelist(struct blkfront_info *info) { unsigned long free = info->shadow_free; BUG_ON(free >= BLK_RING_SIZE); - info->shadow_free = info->shadow[free].req.id; - info->shadow[free].req.id = 0x0fffffee; /* debug */ + info->shadow_free = info->shadow[free].req.u.rw.id; + info->shadow[free].req.u.rw.id = 0x0fffffee; /* debug */ return free; } static void add_id_to_freelist(struct blkfront_info *info, unsigned long id) { - info->shadow[id].req.id = info->shadow_free; + info->shadow[id].req.u.rw.id = info->shadow_free; info->shadow[id].request = NULL; info->shadow_free = id; } @@ -287,9 +287,9 @@ static int blkif_queue_request(struct request *req) id = get_id_from_freelist(info); info->shadow[id].request = req; - ring_req->id = id; + ring_req->u.rw.id = id; ring_req->u.rw.sector_number = (blkif_sector_t)blk_rq_pos(req); - ring_req->handle = info->handle; + ring_req->u.rw.handle = info->handle; ring_req->operation = rq_data_dir(req) ? BLKIF_OP_WRITE : BLKIF_OP_READ; @@ -308,13 +308,15 @@ static int blkif_queue_request(struct request *req) if (unlikely(req->cmd_flags & REQ_DISCARD)) { /* id, sector_number and handle are set above. */ ring_req->operation = BLKIF_OP_DISCARD; - ring_req->nr_segments = 0; + ring_req->u.discard.nr_segments = 0; ring_req->u.discard.nr_sectors = blk_rq_sectors(req); } else { - ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg); - BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST); + ring_req->u.rw.nr_segments = blk_rq_map_sg(req->q, req, + info->sg); + BUG_ON(ring_req->u.rw.nr_segments > + BLKIF_MAX_SEGMENTS_PER_REQUEST); - for_each_sg(info->sg, sg, ring_req->nr_segments, i) { + for_each_sg(info->sg, sg, ring_req->u.rw.nr_segments, i) { buffer_mfn = pfn_to_mfn(page_to_pfn(sg_page(sg))); fsect = sg->offset >> 9; lsect = fsect + (sg->length >> 9) - 1; @@ -705,7 +707,7 @@ static void blkif_free(struct blkfront_info *info, int suspend) static void blkif_completion(struct blk_shadow *s) { int i; - for (i = 0; i < s->req.nr_segments; i++) + for (i = 0; i < s->req.u.rw.nr_segments; i++) gnttab_end_foreign_access(s->req.u.rw.seg[i].gref, 0, 0UL); } @@ -763,7 +765,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) error = -EOPNOTSUPP; } if (unlikely(bret->status == BLKIF_RSP_ERROR && - info->shadow[id].req.nr_segments == 0)) { + info->shadow[id].req.u.rw.nr_segments == 0)) { printk(KERN_WARNING "blkfront: %s: empty write %s op failed\n", info->flush_op == BLKIF_OP_WRITE_BARRIER ? "barrier" : "flush disk cache", @@ -984,8 +986,8 @@ static int blkfront_probe(struct xenbus_device *dev, INIT_WORK(&info->work, blkif_restart_queue); for (i = 0; i < BLK_RING_SIZE; i++) - info->shadow[i].req.id = i+1; - info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; + info->shadow[i].req.u.rw.id = i+1; + info->shadow[BLK_RING_SIZE-1].req.u.rw.id = 0x0fffffff; /* Front end dir is a number, which is used as the id. */ info->handle = simple_strtoul(strrchr(dev->nodename, '/')+1, NULL, 0); @@ -1019,9 +1021,9 @@ static int blkif_recover(struct blkfront_info *info) /* Stage 2: Set up free list. */ memset(&info->shadow, 0, sizeof(info->shadow)); for (i = 0; i < BLK_RING_SIZE; i++) - info->shadow[i].req.id = i+1; + info->shadow[i].req.u.rw.id = i+1; info->shadow_free = info->ring.req_prod_pvt; - info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; + info->shadow[BLK_RING_SIZE-1].req.u.rw.id = 0x0fffffff; /* Stage 3: Find pending requests and requeue them. */ for (i = 0; i < BLK_RING_SIZE; i++) { @@ -1034,17 +1036,17 @@ static int blkif_recover(struct blkfront_info *info) *req = copy[i].req; /* We get a new request id, and must reset the shadow state. */ - req->id = get_id_from_freelist(info); - memcpy(&info->shadow[req->id], ©[i], sizeof(copy[i])); + req->u.rw.id = get_id_from_freelist(info); + memcpy(&info->shadow[req->u.rw.id], ©[i], sizeof(copy[i])); /* Rewrite any grant references invalidated by susp/resume. */ - for (j = 0; j < req->nr_segments; j++) + for (j = 0; j < req->u.rw.nr_segments; j++) gnttab_grant_foreign_access_ref( req->u.rw.seg[j].gref, info->xbdev->otherend_id, - pfn_to_mfn(info->shadow[req->id].frame[j]), - rq_data_dir(info->shadow[req->id].request)); - info->shadow[req->id].req = *req; + pfn_to_mfn(info->shadow[req->u.rw.id].frame[j]), + rq_data_dir(info->shadow[req->u.rw.id].request)); + info->shadow[req->u.rw.id].req = *req; info->ring.req_prod_pvt++; } diff --git a/include/xen/interface/io/blkif.h b/include/xen/interface/io/blkif.h index 9324488..f88e28b 100644 --- a/include/xen/interface/io/blkif.h +++ b/include/xen/interface/io/blkif.h @@ -95,6 +95,12 @@ typedef uint64_t blkif_sector_t; #define BLKIF_MAX_SEGMENTS_PER_REQUEST 11 struct blkif_request_rw { + uint8_t nr_segments; /* number of segments */ + blkif_vdev_t handle; /* only for read/write requests */ +#ifdef CONFIG_X86_64 + uint32_t _pad1; /* offsetof(blkif_request,u.rw.id) == 8 */ +#endif + uint64_t id; /* private guest value, echoed in resp */ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ struct blkif_request_segment { grant_ref_t gref; /* reference to I/O buffer frame */ @@ -102,23 +108,27 @@ struct blkif_request_rw { /* @last_sect: last sector in frame to transfer (inclusive). */ uint8_t first_sect, last_sect; } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; -}; +} __attribute__((__packed__)); struct blkif_request_discard { + uint8_t nr_segments; /* number of segments */ + blkif_vdev_t _pad1; /* only for read/write requests */ +#ifdef CONFIG_X86_64 + uint32_t _pad2; /* offsetof(blkif_req..,u.discard.id)==8*/ +#endif + uint64_t id; /* private guest value, echoed in resp */ blkif_sector_t sector_number; - uint64_t nr_sectors; -}; + uint64_t nr_sectors; + uint8_t _pad3; +} __attribute__((__packed__)); struct blkif_request { uint8_t operation; /* BLKIF_OP_??? */ - uint8_t nr_segments; /* number of segments */ - blkif_vdev_t handle; /* only for read/write requests */ - uint64_t id; /* private guest value, echoed in resp */ union { struct blkif_request_rw rw; struct blkif_request_discard discard; } u; -}; +} __attribute__((__packed__)); struct blkif_response { uint64_t id; /* copied from request */ -- cgit v0.10.2 From 5ea42986694a96542644f9cae8b122d3a00c508f Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 12 Oct 2011 16:23:30 -0400 Subject: xen/blk[front|back]: Enhance discard support with secure erasing support. Part of the blkdev_issue_discard(xx) operation is that it can also issue a secure discard operation that will permanantly remove the sectors in question. We advertise that we can support that via the 'discard-secure' attribute and on the request, if the 'secure' bit is set, we will attempt to pass in REQ_DISCARD | REQ_SECURE. CC: Li Dongyang [v1: Used 'flag' instead of 'secure:1' bit] [v2: Use 'reserved' uint8_t instead of adding a new value] [v3: Check for nseg when mapping instead of operation] Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index d7104ab..9d2261b 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -422,13 +422,16 @@ static void xen_blk_discard(struct xen_blkif *blkif, struct blkif_request *req) int status = BLKIF_RSP_OKAY; struct block_device *bdev = blkif->vbd.bdev; - if (blkif->blk_backend_type == BLKIF_BACKEND_PHY) + if (blkif->blk_backend_type == BLKIF_BACKEND_PHY) { + unsigned long secure = (blkif->vbd.discard_secure && + (req->u.discard.flag & BLKIF_DISCARD_SECURE)) ? + BLKDEV_DISCARD_SECURE : 0; /* just forward the discard request */ err = blkdev_issue_discard(bdev, req->u.discard.sector_number, req->u.discard.nr_sectors, - GFP_KERNEL, 0); - else if (blkif->blk_backend_type == BLKIF_BACKEND_FILE) { + GFP_KERNEL, secure); + } else if (blkif->blk_backend_type == BLKIF_BACKEND_FILE) { /* punch a hole in the backing file */ struct loop_device *lo = bdev->bd_disk->private_data; struct file *file = lo->lo_backing_file; @@ -643,8 +646,11 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, break; } - /* Check that the number of segments is sane. */ - nseg = req->u.rw.nr_segments; + if (unlikely(operation == REQ_DISCARD)) + nseg = 0; + else + /* Check that the number of segments is sane. */ + nseg = req->u.rw.nr_segments; if (unlikely(nseg == 0 && operation != WRITE_FLUSH && operation != REQ_DISCARD) || @@ -708,7 +714,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, * the hypercall to unmap the grants - that is all done in * xen_blkbk_unmap. */ - if (operation != REQ_DISCARD && xen_blkbk_map(req, pending_req, seg)) + if (nseg && xen_blkbk_map(req, pending_req, seg)) goto fail_flush; /* diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index dbfe7b3..d0ee7ed 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -69,7 +69,7 @@ struct blkif_x86_32_request_rw { } __attribute__((__packed__)); struct blkif_x86_32_request_discard { - uint8_t nr_segments; /* number of segments */ + uint8_t flag; /* BLKIF_DISCARD_SECURE or zero */ blkif_vdev_t _pad1; /* was "handle" for read/write requests */ uint64_t id; /* private guest value, echoed in resp */ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ @@ -104,7 +104,7 @@ struct blkif_x86_64_request_rw { } __attribute__((__packed__)); struct blkif_x86_64_request_discard { - uint8_t nr_segments; /* number of segments */ + uint8_t flag; /* BLKIF_DISCARD_SECURE or zero */ blkif_vdev_t _pad1; /* was "handle" for read/write requests */ uint32_t _pad2; /* offsetof(blkif_..,u.discard.id)==8 */ uint64_t id; @@ -164,6 +164,7 @@ struct xen_vbd { /* Cached size parameter. */ sector_t size; bool flush_support; + bool discard_secure; }; struct backend_info; @@ -261,6 +262,7 @@ static inline void blkif_get_x86_32_req(struct blkif_request *dst, dst->u.rw.seg[i] = src->u.rw.seg[i]; break; case BLKIF_OP_DISCARD: + dst->u.discard.flag = src->u.discard.flag; dst->u.discard.sector_number = src->u.discard.sector_number; dst->u.discard.nr_sectors = src->u.discard.nr_sectors; break; @@ -290,6 +292,7 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst, dst->u.rw.seg[i] = src->u.rw.seg[i]; break; case BLKIF_OP_DISCARD: + dst->u.discard.flag = src->u.discard.flag; dst->u.discard.sector_number = src->u.discard.sector_number; dst->u.discard.nr_sectors = src->u.discard.nr_sectors; break; diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index f759ad4..187fd2c 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -338,6 +338,9 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle, if (q && q->flush_flags) vbd->flush_support = true; + if (q && blk_queue_secdiscard(q)) + vbd->discard_secure = true; + DPRINTK("Successful creation of handle=%04x (dom=%u)\n", handle, blkif->domid); return 0; @@ -420,6 +423,15 @@ int xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info *be) state = 1; blkif->blk_backend_type = BLKIF_BACKEND_PHY; } + /* Optional. */ + err = xenbus_printf(xbt, dev->nodename, + "discard-secure", "%d", + blkif->vbd.discard_secure); + if (err) { + xenbus_dev_fatal(dev, err, + "writting discard-secure"); + goto kfree; + } } } else { err = PTR_ERR(type); diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 2c2c4be..351ddef 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -98,7 +98,8 @@ struct blkfront_info unsigned long shadow_free; unsigned int feature_flush; unsigned int flush_op; - unsigned int feature_discard; + unsigned int feature_discard:1; + unsigned int feature_secdiscard:1; unsigned int discard_granularity; unsigned int discard_alignment; int is_ready; @@ -305,11 +306,14 @@ static int blkif_queue_request(struct request *req) ring_req->operation = info->flush_op; } - if (unlikely(req->cmd_flags & REQ_DISCARD)) { + if (unlikely(req->cmd_flags & (REQ_DISCARD | REQ_SECURE))) { /* id, sector_number and handle are set above. */ ring_req->operation = BLKIF_OP_DISCARD; - ring_req->u.discard.nr_segments = 0; ring_req->u.discard.nr_sectors = blk_rq_sectors(req); + if ((req->cmd_flags & REQ_SECURE) && info->feature_secdiscard) + ring_req->u.discard.flag = BLKIF_DISCARD_SECURE; + else + ring_req->u.discard.flag = 0; } else { ring_req->u.rw.nr_segments = blk_rq_map_sg(req->q, req, info->sg); @@ -426,6 +430,8 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size) blk_queue_max_discard_sectors(rq, get_capacity(gd)); rq->limits.discard_granularity = info->discard_granularity; rq->limits.discard_alignment = info->discard_alignment; + if (info->feature_secdiscard) + queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, rq); } /* Hard sector size and max sectors impersonate the equiv. hardware. */ @@ -707,6 +713,8 @@ static void blkif_free(struct blkfront_info *info, int suspend) static void blkif_completion(struct blk_shadow *s) { int i; + /* Do not let BLKIF_OP_DISCARD as nr_segment is in the same place + * flag. */ for (i = 0; i < s->req.u.rw.nr_segments; i++) gnttab_end_foreign_access(s->req.u.rw.seg[i].gref, 0, 0UL); } @@ -738,7 +746,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) id = bret->id; req = info->shadow[id].request; - blkif_completion(&info->shadow[id]); + if (bret->operation != BLKIF_OP_DISCARD) + blkif_completion(&info->shadow[id]); add_id_to_freelist(info, id); @@ -751,7 +760,9 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) info->gd->disk_name); error = -EOPNOTSUPP; info->feature_discard = 0; + info->feature_secdiscard = 0; queue_flag_clear(QUEUE_FLAG_DISCARD, rq); + queue_flag_clear(QUEUE_FLAG_SECDISCARD, rq); } __blk_end_request_all(req, error); break; @@ -1039,13 +1050,15 @@ static int blkif_recover(struct blkfront_info *info) req->u.rw.id = get_id_from_freelist(info); memcpy(&info->shadow[req->u.rw.id], ©[i], sizeof(copy[i])); + if (req->operation != BLKIF_OP_DISCARD) { /* Rewrite any grant references invalidated by susp/resume. */ - for (j = 0; j < req->u.rw.nr_segments; j++) - gnttab_grant_foreign_access_ref( - req->u.rw.seg[j].gref, - info->xbdev->otherend_id, - pfn_to_mfn(info->shadow[req->u.rw.id].frame[j]), - rq_data_dir(info->shadow[req->u.rw.id].request)); + for (j = 0; j < req->u.rw.nr_segments; j++) + gnttab_grant_foreign_access_ref( + req->u.rw.seg[j].gref, + info->xbdev->otherend_id, + pfn_to_mfn(info->shadow[req->u.rw.id].frame[j]), + rq_data_dir(info->shadow[req->u.rw.id].request)); + } info->shadow[req->u.rw.id].req = *req; info->ring.req_prod_pvt++; @@ -1137,11 +1150,13 @@ static void blkfront_setup_discard(struct blkfront_info *info) char *type; unsigned int discard_granularity; unsigned int discard_alignment; + unsigned int discard_secure; type = xenbus_read(XBT_NIL, info->xbdev->otherend, "type", NULL); if (IS_ERR(type)) return; + info->feature_secdiscard = 0; if (strncmp(type, "phy", 3) == 0) { err = xenbus_gather(XBT_NIL, info->xbdev->otherend, "discard-granularity", "%u", &discard_granularity, @@ -1152,6 +1167,12 @@ static void blkfront_setup_discard(struct blkfront_info *info) info->discard_granularity = discard_granularity; info->discard_alignment = discard_alignment; } + err = xenbus_gather(XBT_NIL, info->xbdev->otherend, + "discard-secure", "%d", &discard_secure, + NULL); + if (!err) + info->feature_secdiscard = discard_secure; + } else if (strncmp(type, "file", 4) == 0) info->feature_discard = 1; diff --git a/include/xen/interface/io/blkif.h b/include/xen/interface/io/blkif.h index f88e28b..ee338bf 100644 --- a/include/xen/interface/io/blkif.h +++ b/include/xen/interface/io/blkif.h @@ -84,6 +84,21 @@ typedef uint64_t blkif_sector_t; * e07154r6-Data_Set_Management_Proposal_for_ATA-ACS2.doc * http://www.seagate.com/staticfiles/support/disc/manuals/ * Interface%20manuals/100293068c.pdf + * The backend can optionally provide three extra XenBus attributes to + * further optimize the discard functionality: + * 'discard-aligment' - Devices that support discard functionality may + * internally allocate space in units that are bigger than the exported + * logical block size. The discard-alignment parameter indicates how many bytes + * the beginning of the partition is offset from the internal allocation unit's + * natural alignment. + * 'discard-granularity' - Devices that support discard functionality may + * internally allocate space using units that are bigger than the logical block + * size. The discard-granularity parameter indicates the size of the internal + * allocation unit in bytes if reported by the device. Otherwise the + * discard-granularity will be set to match the device's physical block size. + * 'discard-secure' - All copies of the discarded sectors (potentially created + * by garbage collection) must also be erased. To use this feature, the flag + * BLKIF_DISCARD_SECURE must be set in the blkif_request_trim. */ #define BLKIF_OP_DISCARD 5 @@ -111,7 +126,8 @@ struct blkif_request_rw { } __attribute__((__packed__)); struct blkif_request_discard { - uint8_t nr_segments; /* number of segments */ + uint8_t flag; /* BLKIF_DISCARD_SECURE or zero. */ +#define BLKIF_DISCARD_SECURE (1<<0) /* ignored if discard-secure=0 */ blkif_vdev_t _pad1; /* only for read/write requests */ #ifdef CONFIG_X86_64 uint32_t _pad2; /* offsetof(blkif_req..,u.discard.id)==8*/ -- cgit v0.10.2 From 421463526fd1d8b5cb575baca12667c1005a110b Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 12 Oct 2011 17:26:47 -0400 Subject: xen/blkback: Move processing of BLKIF_OP_DISCARD from dispatch_rw_block_io .. and move it to its own function that will deal with the discard operation. Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 9d2261b..b058de7 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -416,12 +416,16 @@ static int xen_blkbk_map(struct blkif_request *req, return ret; } -static void xen_blk_discard(struct xen_blkif *blkif, struct blkif_request *req) +static int dispatch_discard_io(struct xen_blkif *blkif, + struct blkif_request *req) { int err = 0; int status = BLKIF_RSP_OKAY; struct block_device *bdev = blkif->vbd.bdev; + blkif->st_ds_req++; + + xen_blkif_get(blkif); if (blkif->blk_backend_type == BLKIF_BACKEND_PHY) { unsigned long secure = (blkif->vbd.discard_secure && (req->u.discard.flag & BLKIF_DISCARD_SECURE)) ? @@ -453,6 +457,8 @@ static void xen_blk_discard(struct xen_blkif *blkif, struct blkif_request *req) status = BLKIF_RSP_ERROR; make_response(blkif, req->u.discard.id, req->operation, status); + xen_blkif_put(blkif); + return err; } static void xen_blk_drain_io(struct xen_blkif *blkif) @@ -576,8 +582,11 @@ __do_block_io_op(struct xen_blkif *blkif) /* Apply all sanity checks to /private copy/ of request. */ barrier(); - - if (dispatch_rw_block_io(blkif, &req, pending_req)) + if (unlikely(req.operation == BLKIF_OP_DISCARD)) { + free_req(pending_req); + if (dispatch_discard_io(blkif, &req)) + break; + } else if (dispatch_rw_block_io(blkif, &req, pending_req)) break; /* Yield point for this unbounded loop. */ @@ -636,24 +645,16 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, blkif->st_f_req++; operation = WRITE_FLUSH; break; - case BLKIF_OP_DISCARD: - blkif->st_ds_req++; - operation = REQ_DISCARD; - break; default: operation = 0; /* make gcc happy */ goto fail_response; break; } - if (unlikely(operation == REQ_DISCARD)) - nseg = 0; - else - /* Check that the number of segments is sane. */ - nseg = req->u.rw.nr_segments; + /* Check that the number of segments is sane. */ + nseg = req->u.rw.nr_segments; - if (unlikely(nseg == 0 && operation != WRITE_FLUSH && - operation != REQ_DISCARD) || + if (unlikely(nseg == 0 && operation != WRITE_FLUSH) || unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) { pr_debug(DRV_PFX "Bad number of segments in request (%d)\n", nseg); @@ -714,7 +715,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, * the hypercall to unmap the grants - that is all done in * xen_blkbk_unmap. */ - if (nseg && xen_blkbk_map(req, pending_req, seg)) + if (xen_blkbk_map(req, pending_req, seg)) goto fail_flush; /* @@ -746,23 +747,16 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, /* This will be hit if the operation was a flush or discard. */ if (!bio) { - BUG_ON(operation != WRITE_FLUSH && operation != REQ_DISCARD); + BUG_ON(operation != WRITE_FLUSH); - if (operation == WRITE_FLUSH) { - bio = bio_alloc(GFP_KERNEL, 0); - if (unlikely(bio == NULL)) - goto fail_put_bio; + bio = bio_alloc(GFP_KERNEL, 0); + if (unlikely(bio == NULL)) + goto fail_put_bio; - biolist[nbio++] = bio; - bio->bi_bdev = preq.bdev; - bio->bi_private = pending_req; - bio->bi_end_io = end_block_io_op; - } else if (operation == REQ_DISCARD) { - xen_blk_discard(blkif, req); - xen_blkif_put(blkif); - free_req(pending_req); - return 0; - } + biolist[nbio++] = bio; + bio->bi_bdev = preq.bdev; + bio->bi_private = pending_req; + bio->bi_end_io = end_block_io_op; } /* -- cgit v0.10.2 From ae18be11b5ccc3be9e268592616488c5f9d987f5 Mon Sep 17 00:00:00 2001 From: Li Dongyang Date: Thu, 10 Nov 2011 15:52:06 +0800 Subject: xen-blkback: convert hole punching to discard request on loop devices As of dfaa2ef68e80c378e610e3c8c536f1c239e8d3ef, loop devices support discard request now. We could just issue a discard request, and the loop driver will punch the hole for us, so we don't need to touch the internals of loop device and punch the hole ourselves, Thanks. V0->V1: rebased on devel/for-jens-3.3 Signed-off-by: Li Dongyang Signed-off-by: Konrad Rzeszutek Wilk diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index b058de7..0088bf6 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -39,9 +39,6 @@ #include #include #include -#include -#include -#include #include #include @@ -426,27 +423,15 @@ static int dispatch_discard_io(struct xen_blkif *blkif, blkif->st_ds_req++; xen_blkif_get(blkif); - if (blkif->blk_backend_type == BLKIF_BACKEND_PHY) { + if (blkif->blk_backend_type == BLKIF_BACKEND_PHY || + blkif->blk_backend_type == BLKIF_BACKEND_FILE) { unsigned long secure = (blkif->vbd.discard_secure && (req->u.discard.flag & BLKIF_DISCARD_SECURE)) ? BLKDEV_DISCARD_SECURE : 0; - /* just forward the discard request */ err = blkdev_issue_discard(bdev, req->u.discard.sector_number, req->u.discard.nr_sectors, GFP_KERNEL, secure); - } else if (blkif->blk_backend_type == BLKIF_BACKEND_FILE) { - /* punch a hole in the backing file */ - struct loop_device *lo = bdev->bd_disk->private_data; - struct file *file = lo->lo_backing_file; - - if (file->f_op->fallocate) - err = file->f_op->fallocate(file, - FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, - req->u.discard.sector_number << 9, - req->u.discard.nr_sectors << 9); - else - err = -EOPNOTSUPP; } else err = -EOPNOTSUPP; -- cgit v0.10.2 From f14525f9e033f344996905744f41680ea2b877ce Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 18 Nov 2011 16:03:27 -0800 Subject: x86: Simplify syscallhdr.sh Simplify syscallhdr.sh by letting grep sort out the ABIs that we want, rather than relying on manual list matching. This is safe since the ABI strings already have to consist only of characters which are valid in C macro names. Suggested-by: Matt Helsley Link: http://lkml.kernel.org/r/20111118221558.GA6408@count0.beaverton.ibm.com Signed-off-by: H. Peter Anvin diff --git a/arch/x86/syscalls/syscallhdr.sh b/arch/x86/syscalls/syscallhdr.sh index 0d473ff..b3c5930 100644 --- a/arch/x86/syscalls/syscallhdr.sh +++ b/arch/x86/syscalls/syscallhdr.sh @@ -2,33 +2,20 @@ in="$1" out="$2" -my_abis=`echo "$3" | tr ',' ' '` +my_abis=`echo "($3)" | tr ',' '|'` prefix="$4" offset="$5" fileguard=_ASM_X86_`basename "$out" | sed \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \ -e 's/[^A-Z0-9_]/_/g' -e 's/__/_/g'` - -in_list () { - local x - for x in $1; do - if [ x"$x" = x"$2" ]; then - return 0 - fi - done - return 1 -} - -grep '^[0-9]' "$in" | sort -n | ( +grep -E "^[0-9A-Fa-fXx]+[[:space:]]+${my_abis}" "$in" | sort -n | ( echo "#ifndef ${fileguard}" echo "#define ${fileguard} 1" echo "" while read nr abi name entry ; do - if in_list "$my_abis" "$abi"; then - echo "#define __NR_${prefix}${name}" $((nr+offset)) - fi + echo "#define __NR_${prefix}${name}" $((nr+offset)) done echo "" -- cgit v0.10.2 From 61f1e7e20874e8f11dab69b6a4bf7616badd4fe8 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 18 Nov 2011 16:25:07 -0800 Subject: x86, syscall: Re-fix typo in comment Fix the same typo as was fixed in: b7641d2c x86-64, syscall: Adjust comment spacing and remove typo ... for the new versions of this file (32-bit and IA32 compat). Signed-off-by: H. Peter Anvin Link: http://lkml.kernel.org/r/1321569446-20433-4-git-send-email-hpa@linux.intel.com diff --git a/arch/x86/ia32/syscall_ia32.c b/arch/x86/ia32/syscall_ia32.c index d04d3db..4754ba0 100644 --- a/arch/x86/ia32/syscall_ia32.c +++ b/arch/x86/ia32/syscall_ia32.c @@ -17,7 +17,7 @@ extern void compat_ni_syscall(void); const sys_call_ptr_t ia32_sys_call_table[__NR_ia32_syscall_max+1] = { /* - * Smells like a like a compiler bug -- it doesn't work + * Smells like a compiler bug -- it doesn't work * when the & below is removed. */ [0 ... __NR_ia32_syscall_max] = &compat_ni_syscall, diff --git a/arch/x86/kernel/syscall_32.c b/arch/x86/kernel/syscall_32.c index b37a573..147fcd4 100644 --- a/arch/x86/kernel/syscall_32.c +++ b/arch/x86/kernel/syscall_32.c @@ -17,7 +17,7 @@ extern asmlinkage void sys_ni_syscall(void); const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { /* - * Smells like a like a compiler bug -- it doesn't work + * Smells like a compiler bug -- it doesn't work * when the & below is removed. */ [0 ... __NR_syscall_max] = &sys_ni_syscall, -- cgit v0.10.2 From 3f86886c72fb68088162c7e08cc7f85282f1860c Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 18 Nov 2011 17:01:19 -0800 Subject: x86, syscall: Allow syscall offset to be symbolic Allow the specified syscall offset to be symbolic, e.g. a macro. For offset system calls, this if nothing else makes the generated code easier to read. Suggested-by: H. J. Lu Link: http://lkml.kernel.org/r/1321569446-20433-7-git-send-email-hpa@linux.intel.com Signed-off-by: H. Peter Anvin diff --git a/arch/x86/syscalls/syscallhdr.sh b/arch/x86/syscalls/syscallhdr.sh index b3c5930..31fd5f1 100644 --- a/arch/x86/syscalls/syscallhdr.sh +++ b/arch/x86/syscalls/syscallhdr.sh @@ -15,7 +15,11 @@ grep -E "^[0-9A-Fa-fXx]+[[:space:]]+${my_abis}" "$in" | sort -n | ( echo "" while read nr abi name entry ; do - echo "#define __NR_${prefix}${name}" $((nr+offset)) + if [ -z "$offset" ]; then + echo "#define __NR_${prefix}${name} $nr" + else + echo "#define __NR_${prefix}${name} ($offset + $nr)" + fi done echo "" -- cgit v0.10.2 From 35621030c0bd5cb4f1a345cf2b4a97e290bc244a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 23 Sep 2011 13:03:42 -0300 Subject: [media] xc5000: Add support for get_if_frequency This is needed for devices with DRX-K and xc5000. Tested with a HVR 930C hardware. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index 88b329c..ecd1f95 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -968,6 +968,14 @@ static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq) return 0; } +static int xc5000_get_if_frequency(struct dvb_frontend *fe, u32 *freq) +{ + struct xc5000_priv *priv = fe->tuner_priv; + dprintk(1, "%s()\n", __func__); + *freq = priv->if_khz * 1000; + return 0; +} + static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw) { struct xc5000_priv *priv = fe->tuner_priv; @@ -1108,6 +1116,7 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = { .set_params = xc5000_set_params, .set_analog_params = xc5000_set_analog_params, .get_frequency = xc5000_get_frequency, + .get_if_frequency = xc5000_get_if_frequency, .get_bandwidth = xc5000_get_bandwidth, .get_status = xc5000_get_status }; -- cgit v0.10.2 From 82e7dbbd4a16274b0a7038978734fc11bbf9f4b6 Mon Sep 17 00:00:00 2001 From: Eddi De Pieri Date: Sat, 19 Nov 2011 11:37:14 -0300 Subject: [media] em28xx: initial support for HAUPPAUGE HVR-930C again With this patch I try again to add initial support for HVR930C. Tested only DVB-T, since in Italy Analog service is stopped. Actually "scan -a0 -f1", find only about 50 channel while 400 should be available. [mchehab@redhat.com: Tested with DVB-C and fixed a few whitespace issues] Tested-by: Mauro Carvalho Chehab Signed-off-by: Eddi De Pieri Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index ecd1f95..048f489 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -1004,6 +1004,8 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe) struct xc5000_priv *priv = fe->tuner_priv; int ret = 0; + mutex_lock(&xc5000_list_mutex); + if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { ret = xc5000_fwupload(fe); if (ret != XC_RESULT_SUCCESS) @@ -1023,6 +1025,8 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe) /* Default to "CABLE" mode */ ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE); + mutex_unlock(&xc5000_list_mutex); + return ret; } diff --git a/drivers/media/dvb/frontends/drxk.h b/drivers/media/dvb/frontends/drxk.h index 58baf41..e6d42e2 100644 --- a/drivers/media/dvb/frontends/drxk.h +++ b/drivers/media/dvb/frontends/drxk.h @@ -26,6 +26,8 @@ struct drxk_config { bool antenna_dvbt; u16 antenna_gpio; + int chunk_size; + const char *microcode_name; }; diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index dc13fd8..2392092 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -681,7 +681,8 @@ static int init_state(struct drxk_state *state) state->m_hasOOB = false; state->m_hasAudio = false; - state->m_ChunkSize = 124; + if (!state->m_ChunkSize) + state->m_ChunkSize = 124; state->m_oscClockFreq = 0; state->m_smartAntInverted = false; @@ -6430,6 +6431,7 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, state->no_i2c_bridge = config->no_i2c_bridge; state->antenna_gpio = config->antenna_gpio; state->antenna_dvbt = config->antenna_dvbt; + state->m_ChunkSize = config->chunk_size; /* NOTE: as more UIO bits will be used, add them to the mask */ state->UIO_mask = config->antenna_gpio; diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 19a5be3..705aedf 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -336,6 +336,24 @@ static struct em28xx_reg_seq pctv_460e[] = { { -1, -1, -1, -1}, }; +static struct em28xx_reg_seq hauppauge_930c_gpio[] = { +// xc5000 reset + {EM2874_R80_GPIO, 0x6f, 0xff, 10}, + {EM2874_R80_GPIO, 0x4f, 0xff, 10}, + {EM2874_R80_GPIO, 0x6f, 0xff, 10}, + {EM2874_R80_GPIO, 0x4f, 0xff, 10}, + { -1, -1, -1, -1}, +}; + +#if 0 +static struct em28xx_reg_seq hauppauge_930c_digital[] = { + {EM2874_R80_GPIO, 0xf6, 0xff, 10}, + {EM2874_R80_GPIO, 0xe6, 0xff, 100}, + {EM2874_R80_GPIO, 0xa6, 0xff, 10}, + { -1, -1, -1, -1}, +}; +#endif + /* * Board definitions */ @@ -892,6 +910,19 @@ struct em28xx_board em28xx_boards[] = { EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ, }, + [EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C] = { + .name = "Hauppauge WinTV HVR 930C", + .has_dvb = 1, +//#if 0 +// .tuner_type = TUNER_XC5000, +// .tuner_addr = 0x41, +// .dvb_gpio = hauppauge_930c_digital, /* FIXME: probably wrong */ + .tuner_gpio = hauppauge_930c_gpio, +//#endif + .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | + EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_400_KHZ, + }, [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = { .name = "Hauppauge WinTV HVR 900", .tda9887_conf = TDA9887_PRESENT, @@ -1975,6 +2006,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM28174_BOARD_PCTV_290E }, { USB_DEVICE(0x2013, 0x024c), .driver_info = EM28174_BOARD_PCTV_460E }, + { USB_DEVICE(0x2040, 0x1605), + .driver_info = EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C }, { }, }; MODULE_DEVICE_TABLE(usb, em28xx_id_table); @@ -2028,10 +2061,10 @@ int em28xx_tuner_callback(void *ptr, int component, int command, int arg) int rc = 0; struct em28xx *dev = ptr; - if (dev->tuner_type != TUNER_XC2028) + if (dev->tuner_type != TUNER_XC2028 && dev->tuner_type != TUNER_XC5000) return 0; - if (command != XC2028_TUNER_RESET) + if (command != XC2028_TUNER_RESET && command != XC5000_TUNER_RESET) return 0; rc = em28xx_gpio_set(dev, dev->board.tuner_gpio); diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index cef7a2d..d19939b 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -316,6 +316,14 @@ struct drxk_config terratec_h5_drxk = { .microcode_name = "dvb-usb-terratec-h5-drxk.fw", }; +struct drxk_config hauppauge_930c_drxk = { + .adr = 0x29, + .single_master = 1, + .no_i2c_bridge = 1, + .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw", + .chunk_size = 56, +}; + static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) { struct em28xx_dvb *dvb = fe->sec_priv; @@ -334,6 +342,90 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) return status; } +static void hauppauge_hvr930c_init(struct em28xx *dev) +{ + int i; + + struct em28xx_reg_seq hauppauge_hvr930c_init[] = { + {EM2874_R80_GPIO, 0xff, 0xff, 101}, //11111111 +// {0xd , 0xff, 0xff, 101}, //11111111 + {EM2874_R80_GPIO, 0xfb, 0xff, 50}, //11111011 init bit 3 + {EM2874_R80_GPIO, 0xff, 0xff, 184}, //11111111 + { -1, -1, -1, -1}, + }; + struct em28xx_reg_seq hauppauge_hvr930c_end[] = { + {EM2874_R80_GPIO, 0xef, 0xff, 1}, //11101111 + {EM2874_R80_GPIO, 0xaf, 0xff, 101}, //10101111 init bit 7 + {EM2874_R80_GPIO, 0xef, 0xff, 118}, //11101111 + + +//per il tuner? + {EM2874_R80_GPIO, 0xef, 0xff, 1}, //11101111 + {EM2874_R80_GPIO, 0xcf, 0xff, 11}, //11001111 init bit 6 + {EM2874_R80_GPIO, 0xef, 0xff, 64}, //11101111 + + {EM2874_R80_GPIO, 0xcf, 0xff, 101}, //11001111 init bit 6 + {EM2874_R80_GPIO, 0xef, 0xff, 101}, //11101111 + {EM2874_R80_GPIO, 0xcf, 0xff, 11}, //11001111 init bit 6 + {EM2874_R80_GPIO, 0xef, 0xff, 101}, //11101111 + +// {EM2874_R80_GPIO, 0x6f, 0xff, 10}, //01101111 +// {EM2874_R80_GPIO, 0x6d, 0xff, 100}, //01101101 init bit 2 + { -1, -1, -1, -1}, + }; + + struct em28xx_reg_seq hauppauge_hvr930c_end2[] = { +// {EM2874_R80_GPIO, 0x6f, 0xff, 124}, //01101111 +// {EM2874_R80_GPIO, 0x4f, 0xff, 11}, //01001111 init bit 6 +// {EM2874_R80_GPIO, 0x6f, 0xff, 1}, //01101111 +// {EM2874_R80_GPIO, 0x4f, 0xff, 10}, //01001111 init bit 6 +// {EM2874_R80_GPIO, 0x6f, 0xff, 100}, //01101111 +// {0xd , 0x42, 0xff, 101}, //11111111 + { -1, -1, -1, -1}, + }; + struct { + unsigned char r[4]; + int len; + } regs[] = { + {{ 0x06, 0x02, 0x00, 0x31 }, 4}, + {{ 0x01, 0x02 }, 2}, + {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, + {{ 0x01, 0x00 }, 2}, + {{ 0x01, 0x00, 0xff, 0xaf }, 4}, + {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, + {{ 0x01, 0x00 }, 2}, + {{ 0x01, 0x00, 0x73, 0xaf }, 4}, + {{ 0x04, 0x00 }, 2}, + {{ 0x00, 0x04 }, 2}, + {{ 0x00, 0x04, 0x00, 0x0a }, 4}, + {{ 0x04, 0x14 }, 2}, + {{ 0x04, 0x14, 0x00, 0x00 }, 4}, + }; + + em28xx_gpio_set(dev, hauppauge_hvr930c_init); + em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); + msleep(10); + em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); + msleep(10); + + dev->i2c_client.addr = 0x82 >> 1; + + for (i = 0; i < ARRAY_SIZE(regs); i++) + i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); + em28xx_gpio_set(dev, hauppauge_hvr930c_end); + + msleep(100); + + em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); + msleep(30); + + em28xx_gpio_set(dev, hauppauge_hvr930c_end2); + msleep(10); + em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45); + msleep(10); + +} + static void terratec_h5_init(struct em28xx *dev) { int i; @@ -788,6 +880,47 @@ static int em28xx_dvb_init(struct em28xx *dev) mfe_shared = 1; } break; + case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C: + hauppauge_hvr930c_init(dev); + + dvb->dont_attach_fe1 = 1; + + dvb->fe[0] = dvb_attach(drxk_attach, &hauppauge_930c_drxk, &dev->i2c_adap, &dvb->fe[1]); + if (!dvb->fe[0]) { + result = -EINVAL; + goto out_free; + } + /* FIXME: do we need a pll semaphore? */ + dvb->fe[0]->sec_priv = dvb; + sema_init(&dvb->pll_mutex, 1); + dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl; + dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; + dvb->fe[1]->id = 1; + + /* Attach xc5000 */ + struct xc5000_config cfg; + memset(&cfg, 0, sizeof(cfg)); + cfg.i2c_address = 0x61; + //cfg.if_khz = 4570; //FIXME + cfg.if_khz = 4000; //FIXME (should be ok) read from i2c traffic + + if (dvb->fe[0]->ops.i2c_gate_ctrl) + dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1); + if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap, &cfg)) { + result = -EINVAL; + goto out_free; + } + + if (dvb->fe[0]->ops.i2c_gate_ctrl) + dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); + + /* Hack - needed by drxk/tda18271c2dd */ + dvb->fe[1]->tuner_priv = dvb->fe[0]->tuner_priv; + memcpy(&dvb->fe[1]->ops.tuner_ops, + &dvb->fe[0]->ops.tuner_ops, + sizeof(dvb->fe[0]->ops.tuner_ops)); + + break; case EM2884_BOARD_TERRATEC_H5: terratec_h5_init(dev); @@ -798,7 +931,6 @@ static int em28xx_dvb_init(struct em28xx *dev) result = -EINVAL; goto out_free; } - /* FIXME: do we need a pll semaphore? */ dvb->fe[0]->sec_priv = dvb; sema_init(&dvb->pll_mutex, 1); @@ -845,6 +977,8 @@ static int em28xx_dvb_init(struct em28xx *dev) } /* define general-purpose callback pointer */ dvb->fe[0]->callback = em28xx_tuner_callback; + if (dvb->fe[1]) + dvb->fe[1]->callback = em28xx_tuner_callback; /* register everything */ result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 2a2cb7e..c16ae8f 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -38,6 +38,7 @@ #include #endif #include "tuner-xc2028.h" +#include "xc5000.h" #include "em28xx-reg.h" /* Boards supported by driver */ @@ -121,6 +122,7 @@ #define EM28174_BOARD_PCTV_290E 78 #define EM2884_BOARD_TERRATEC_H5 79 #define EM28174_BOARD_PCTV_460E 80 +#define EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C 81 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v0.10.2 From de72405f6fc1aaedc0412f88cf681ed33519c49a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 20 Nov 2011 11:23:24 -0200 Subject: [media] em28xx: Fix CodingStyle issues introduced by changeset 82e7dbb Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index 2392092..95cbc98 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -682,7 +682,7 @@ static int init_state(struct drxk_state *state) state->m_hasAudio = false; if (!state->m_ChunkSize) - state->m_ChunkSize = 124; + state->m_ChunkSize = 124; state->m_oscClockFreq = 0; state->m_smartAntInverted = false; diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 705aedf..d92e0af 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -337,9 +337,8 @@ static struct em28xx_reg_seq pctv_460e[] = { }; static struct em28xx_reg_seq hauppauge_930c_gpio[] = { -// xc5000 reset {EM2874_R80_GPIO, 0x6f, 0xff, 10}, - {EM2874_R80_GPIO, 0x4f, 0xff, 10}, + {EM2874_R80_GPIO, 0x4f, 0xff, 10}, /* xc5000 reset */ {EM2874_R80_GPIO, 0x6f, 0xff, 10}, {EM2874_R80_GPIO, 0x4f, 0xff, 10}, { -1, -1, -1, -1}, @@ -905,6 +904,8 @@ struct em28xx_board em28xx_boards[] = { .tuner_addr = 0x41, .dvb_gpio = terratec_h5_digital, /* FIXME: probably wrong */ .tuner_gpio = terratec_h5_gpio, +#else + .tuner_type = TUNER_ABSENT, #endif .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | EM28XX_I2C_CLK_WAIT_ENABLE | @@ -913,12 +914,14 @@ struct em28xx_board em28xx_boards[] = { [EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C] = { .name = "Hauppauge WinTV HVR 930C", .has_dvb = 1, -//#if 0 -// .tuner_type = TUNER_XC5000, -// .tuner_addr = 0x41, -// .dvb_gpio = hauppauge_930c_digital, /* FIXME: probably wrong */ +#if 0 /* FIXME: Add analog support */ + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x41, + .dvb_gpio = hauppauge_930c_digital, .tuner_gpio = hauppauge_930c_gpio, -//#endif +#else + .tuner_type = TUNER_ABSENT, +#endif .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ, diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index d19939b..55a90089 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -347,42 +347,27 @@ static void hauppauge_hvr930c_init(struct em28xx *dev) int i; struct em28xx_reg_seq hauppauge_hvr930c_init[] = { - {EM2874_R80_GPIO, 0xff, 0xff, 101}, //11111111 -// {0xd , 0xff, 0xff, 101}, //11111111 - {EM2874_R80_GPIO, 0xfb, 0xff, 50}, //11111011 init bit 3 - {EM2874_R80_GPIO, 0xff, 0xff, 184}, //11111111 + {EM2874_R80_GPIO, 0xff, 0xff, 0x65}, + {EM2874_R80_GPIO, 0xfb, 0xff, 0x32}, + {EM2874_R80_GPIO, 0xff, 0xff, 0xb8}, { -1, -1, -1, -1}, }; struct em28xx_reg_seq hauppauge_hvr930c_end[] = { - {EM2874_R80_GPIO, 0xef, 0xff, 1}, //11101111 - {EM2874_R80_GPIO, 0xaf, 0xff, 101}, //10101111 init bit 7 - {EM2874_R80_GPIO, 0xef, 0xff, 118}, //11101111 + {EM2874_R80_GPIO, 0xef, 0xff, 0x01}, + {EM2874_R80_GPIO, 0xaf, 0xff, 0x65}, + {EM2874_R80_GPIO, 0xef, 0xff, 0x76}, + {EM2874_R80_GPIO, 0xef, 0xff, 0x01}, + {EM2874_R80_GPIO, 0xcf, 0xff, 0x0b}, + {EM2874_R80_GPIO, 0xef, 0xff, 0x40}, + + {EM2874_R80_GPIO, 0xcf, 0xff, 0x65}, + {EM2874_R80_GPIO, 0xef, 0xff, 0x65}, + {EM2874_R80_GPIO, 0xcf, 0xff, 0x0b}, + {EM2874_R80_GPIO, 0xef, 0xff, 0x65}, - -//per il tuner? - {EM2874_R80_GPIO, 0xef, 0xff, 1}, //11101111 - {EM2874_R80_GPIO, 0xcf, 0xff, 11}, //11001111 init bit 6 - {EM2874_R80_GPIO, 0xef, 0xff, 64}, //11101111 - - {EM2874_R80_GPIO, 0xcf, 0xff, 101}, //11001111 init bit 6 - {EM2874_R80_GPIO, 0xef, 0xff, 101}, //11101111 - {EM2874_R80_GPIO, 0xcf, 0xff, 11}, //11001111 init bit 6 - {EM2874_R80_GPIO, 0xef, 0xff, 101}, //11101111 - -// {EM2874_R80_GPIO, 0x6f, 0xff, 10}, //01101111 -// {EM2874_R80_GPIO, 0x6d, 0xff, 100}, //01101101 init bit 2 { -1, -1, -1, -1}, }; - struct em28xx_reg_seq hauppauge_hvr930c_end2[] = { -// {EM2874_R80_GPIO, 0x6f, 0xff, 124}, //01101111 -// {EM2874_R80_GPIO, 0x4f, 0xff, 11}, //01001111 init bit 6 -// {EM2874_R80_GPIO, 0x6f, 0xff, 1}, //01101111 -// {EM2874_R80_GPIO, 0x4f, 0xff, 10}, //01001111 init bit 6 -// {EM2874_R80_GPIO, 0x6f, 0xff, 100}, //01101111 -// {0xd , 0x42, 0xff, 101}, //11111111 - { -1, -1, -1, -1}, - }; struct { unsigned char r[4]; int len; @@ -419,8 +404,6 @@ static void hauppauge_hvr930c_init(struct em28xx *dev) em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); msleep(30); - em28xx_gpio_set(dev, hauppauge_hvr930c_end2); - msleep(10); em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45); msleep(10); @@ -885,7 +868,9 @@ static int em28xx_dvb_init(struct em28xx *dev) dvb->dont_attach_fe1 = 1; - dvb->fe[0] = dvb_attach(drxk_attach, &hauppauge_930c_drxk, &dev->i2c_adap, &dvb->fe[1]); + dvb->fe[0] = dvb_attach(drxk_attach, + &hauppauge_930c_drxk, &dev->i2c_adap, + &dvb->fe[1]); if (!dvb->fe[0]) { result = -EINVAL; goto out_free; @@ -901,12 +886,12 @@ static int em28xx_dvb_init(struct em28xx *dev) struct xc5000_config cfg; memset(&cfg, 0, sizeof(cfg)); cfg.i2c_address = 0x61; - //cfg.if_khz = 4570; //FIXME - cfg.if_khz = 4000; //FIXME (should be ok) read from i2c traffic + cfg.if_khz = 4000; if (dvb->fe[0]->ops.i2c_gate_ctrl) dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1); - if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap, &cfg)) { + if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap, + &cfg)) { result = -EINVAL; goto out_free; } @@ -978,7 +963,7 @@ static int em28xx_dvb_init(struct em28xx *dev) /* define general-purpose callback pointer */ dvb->fe[0]->callback = em28xx_tuner_callback; if (dvb->fe[1]) - dvb->fe[1]->callback = em28xx_tuner_callback; + dvb->fe[1]->callback = em28xx_tuner_callback; /* register everything */ result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); -- cgit v0.10.2 From 20ae9742eba1bbd1f9d6658d1a1a72bc77fc741d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 20 Nov 2011 12:23:54 -0200 Subject: [media] em28xx: Add IR support for em2884 Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 679da48..2630b26 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -306,7 +306,8 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) poll_result.rc_data[0], poll_result.toggle_bit); - if (ir->dev->chip_id == CHIP_ID_EM2874) + if (ir->dev->chip_id == CHIP_ID_EM2874 || + ir->dev->chip_id == CHIP_ID_EM2884) /* The em2874 clears the readcount field every time the register is read. The em2860/2880 datasheet says that it is supposed to clear the readcount, but it doesn't. So with @@ -371,13 +372,15 @@ int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type) case CHIP_ID_EM2883: ir->get_key = default_polling_getkey; break; + case CHIP_ID_EM2884: case CHIP_ID_EM2874: case CHIP_ID_EM28174: ir->get_key = em2874_polling_getkey; em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1); break; default: - printk("Unrecognized em28xx chip id: IR not supported\n"); + printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n", + dev->chip_id); rc = -EINVAL; } -- cgit v0.10.2 From dfbbf5da6c2266580df8b8aab0b43595bed55e48 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 20 Nov 2011 12:16:25 -0200 Subject: [media] em28xx: Add IR support for HVR-930C Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/keymaps/rc-hauppauge.c b/drivers/media/rc/keymaps/rc-hauppauge.c index cd3db77..0afb23b 100644 --- a/drivers/media/rc/keymaps/rc-hauppauge.c +++ b/drivers/media/rc/keymaps/rc-hauppauge.c @@ -182,6 +182,57 @@ static struct rc_map_table rc5_hauppauge_new[] = { { 0x1d3f, KEY_HOME }, /* + * Keycodes for PT# R-005 remote bundled with Haupauge HVR-930C + * Keycodes start with address = 0x1c + */ + { 0x1c3b, KEY_GOTO }, + { 0x1c3d, KEY_POWER }, + + { 0x1c14, KEY_UP }, + { 0x1c15, KEY_DOWN }, + { 0x1c16, KEY_LEFT }, + { 0x1c17, KEY_RIGHT }, + { 0x1c25, KEY_OK }, + + { 0x1c00, KEY_0 }, + { 0x1c01, KEY_1 }, + { 0x1c02, KEY_2 }, + { 0x1c03, KEY_3 }, + { 0x1c04, KEY_4 }, + { 0x1c05, KEY_5 }, + { 0x1c06, KEY_6 }, + { 0x1c07, KEY_7 }, + { 0x1c08, KEY_8 }, + { 0x1c09, KEY_9 }, + + { 0x1c1f, KEY_EXIT }, /* BACK */ + { 0x1c0d, KEY_MENU }, + { 0x1c1c, KEY_TV }, + + { 0x1c10, KEY_VOLUMEUP }, + { 0x1c11, KEY_VOLUMEDOWN }, + + { 0x1c20, KEY_CHANNELUP }, + { 0x1c21, KEY_CHANNELDOWN }, + + { 0x1c0f, KEY_MUTE }, + { 0x1c12, KEY_PREVIOUS }, /* Prev */ + + { 0x1c36, KEY_STOP }, + { 0x1c37, KEY_RECORD }, + + { 0x1c24, KEY_LAST }, /* <| */ + { 0x1c1e, KEY_NEXT }, /* >| */ + + { 0x1c0a, KEY_TEXT }, + { 0x1c0e, KEY_SUBTITLE }, /* CC */ + + { 0x1c32, KEY_REWIND }, + { 0x1c30, KEY_PAUSE }, + { 0x1c35, KEY_PLAY }, + { 0x1c34, KEY_FASTFORWARD }, + + /* * Keycodes for the old Black Remote Controller * This one also uses RC-5 protocol * Keycodes start with address = 0x00 diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index d92e0af..f63a715 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -922,6 +922,7 @@ struct em28xx_board em28xx_boards[] = { #else .tuner_type = TUNER_ABSENT, #endif + .ir_codes = RC_MAP_HAUPPAUGE, .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ, -- cgit v0.10.2 From 6fd7dba026f17076ac4bd63a3590f993c1f5c2c6 Mon Sep 17 00:00:00 2001 From: Eddi De Pieri Date: Mon, 21 Nov 2011 06:43:52 -0300 Subject: [media] get_dvb_firmware: add support for HVR-930C firmware Signed-off-by: Eddi De Pieri Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware index e67be7a..0f15ab7 100755 --- a/Documentation/dvb/get_dvb_firmware +++ b/Documentation/dvb/get_dvb_firmware @@ -27,8 +27,8 @@ use IO::Handle; "or51211", "or51132_qam", "or51132_vsb", "bluebird", "opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718", "af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395", - "lme2510c_s7395_old", "drxk", "drxk_terratec_h5", "tda10071", - "it9135" ); + "lme2510c_s7395_old", "drxk", "drxk_terratec_h5", + "drxk_hauppauge_hvr930c", "tda10071", "it9135" ); # Check args syntax() if (scalar(@ARGV) != 1); @@ -644,6 +644,24 @@ sub drxk { "$fwfile" } +sub drxk_hauppauge_hvr930c { + my $url = "http://www.wintvcd.co.uk/drivers/"; + my $zipfile = "HVR-9x0_5_10_325_28153_SIGNED.zip"; + my $hash = "83ab82e7e9480ec8bf1ae0155ca63c88"; + my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); + my $drvfile = "HVR-900/emOEM.sys"; + my $fwfile = "dvb-usb-hauppauge-hvr930c-drxk.fw"; + + checkstandard(); + + wgetfile($zipfile, $url . $zipfile); + verify($zipfile, $hash); + unzip($zipfile, $tmpdir); + extract("$tmpdir/$drvfile", 0x117b0, 42692, "$fwfile"); + + "$fwfile" +} + sub drxk_terratec_h5 { my $url = "http://www.linuxtv.org/downloads/firmware/"; my $hash = "19000dada8e2741162ccc50cc91fa7f1"; -- cgit v0.10.2 From 41e583c22c3f907e46e329764b4606117040a1ae Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Nov 2011 20:33:29 -0800 Subject: fbdev: sh_mobile_lcdcfb: fixup LDHAJR :: HSYNPAJ needs mask LDHAJR register will be broken by hsync_pos without this patch Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index facffc2..1f49ab4 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -420,7 +420,7 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) tmp = ((display_var->xres & 7) << 24) | ((display_h_total & 7) << 16) | ((display_var->hsync_len & 7) << 8) | - hsync_pos; + (hsync_pos & 7); lcdc_write_chan(ch, LDHAJR, tmp); } -- cgit v0.10.2 From 9250741e5feedb6a5273683a940b339af59a1086 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Nov 2011 20:33:47 -0800 Subject: fbdev: sh_mipi_dsi: tidyup dsip_clk dsipck clock is controled by CLKDEV_ICK_ID() in clock-shxxx. dsi0p_clk/dsi1p_clk naming is not needed. Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Florian Tobias Schandinat diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index 995a9c3..1ebab17 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c @@ -612,8 +612,8 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("hdmi_clk", &div6_reparent_clks[DIV6_HDMI]), CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]), - CLKDEV_ICK_ID("dsi0p_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), - CLKDEV_ICK_ID("dsi1p_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), + CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), + CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), /* MSTP32 clocks */ CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */ diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index 61a846b..3da30ba 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c @@ -319,8 +319,8 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("sdhi2_clk", &div6_clks[DIV6_SDHI2]), CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]), - CLKDEV_ICK_ID("dsi0p_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), - CLKDEV_ICK_ID("dsi1p_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), + CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), + CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), /* MSTP32 clocks */ CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */ diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index 72ee96b..4aa5053 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c @@ -363,7 +363,6 @@ static int __init sh_mipi_probe(struct platform_device *pdev) struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); unsigned long rate, f_current; int idx = pdev->id, ret; - char dsip_clk[] = "dsi.p_clk"; if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata) return -ENODEV; @@ -428,8 +427,7 @@ static int __init sh_mipi_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate); - sprintf(dsip_clk, "dsi%1.1dp_clk", idx); - mipi->dsip_clk = clk_get(&pdev->dev, dsip_clk); + mipi->dsip_clk = clk_get(&pdev->dev, "dsip_clk"); if (IS_ERR(mipi->dsip_clk)) { ret = PTR_ERR(mipi->dsip_clk); goto eclkpget; -- cgit v0.10.2 From 32ba95c69f33126e297466dc706db73cc7e7a543 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Nov 2011 20:34:01 -0800 Subject: fbdev: sh_mipi_dsi: typo fix of SH_MIPI_DSI_HBPBM Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index 4aa5053..94bb1bb 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c @@ -318,7 +318,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, */ if (pdata->flags & SH_MIPI_DSI_HSABM) vmctr2 |= 0x20; - if (pdata->flags & SH_MIPI_DSI_HSPBM) + if (pdata->flags & SH_MIPI_DSI_HBPBM) vmctr2 |= 0x10; iowrite32(vmctr2, mipi->linkbase + VMCTR2); diff --git a/include/video/sh_mipi_dsi.h b/include/video/sh_mipi_dsi.h index 6cb95c9..4e2bcb5 100644 --- a/include/video/sh_mipi_dsi.h +++ b/include/video/sh_mipi_dsi.h @@ -28,7 +28,7 @@ enum sh_mipi_dsi_data_fmt { struct sh_mobile_lcdc_chan_cfg; #define SH_MIPI_DSI_HSABM (1 << 0) -#define SH_MIPI_DSI_HSPBM (1 << 1) +#define SH_MIPI_DSI_HBPBM (1 << 1) struct sh_mipi_dsi_info { enum sh_mipi_dsi_data_fmt data_format; -- cgit v0.10.2 From 3c2a659936ba1e3bbd7e5eca89255c134fafb506 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Nov 2011 20:34:12 -0800 Subject: fbdev: sh_mipi_dsi: tidyup VMCTR2 parameter expression VMCTR2 parameter will be supported more in the future. 1 << xx style is easy to understand. Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index 94bb1bb..20ccc23 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c @@ -317,9 +317,9 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, * HSA period allowed, no commands in LP */ if (pdata->flags & SH_MIPI_DSI_HSABM) - vmctr2 |= 0x20; + vmctr2 |= 1 << 5; if (pdata->flags & SH_MIPI_DSI_HBPBM) - vmctr2 |= 0x10; + vmctr2 |= 1 << 4; iowrite32(vmctr2, mipi->linkbase + VMCTR2); /* -- cgit v0.10.2 From f7b0af68bc9f5eb5291996706951661d57909137 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Nov 2011 20:34:24 -0800 Subject: fbdev: sh_mipi_dsi: add SH_MIPI_DSI_HFPBM flag Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index 20ccc23..c9fac13 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c @@ -320,6 +320,8 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, vmctr2 |= 1 << 5; if (pdata->flags & SH_MIPI_DSI_HBPBM) vmctr2 |= 1 << 4; + if (pdata->flags & SH_MIPI_DSI_HFPBM) + vmctr2 |= 1 << 3; iowrite32(vmctr2, mipi->linkbase + VMCTR2); /* diff --git a/include/video/sh_mipi_dsi.h b/include/video/sh_mipi_dsi.h index 4e2bcb5..86a72c0 100644 --- a/include/video/sh_mipi_dsi.h +++ b/include/video/sh_mipi_dsi.h @@ -29,6 +29,7 @@ struct sh_mobile_lcdc_chan_cfg; #define SH_MIPI_DSI_HSABM (1 << 0) #define SH_MIPI_DSI_HBPBM (1 << 1) +#define SH_MIPI_DSI_HFPBM (1 << 2) struct sh_mipi_dsi_info { enum sh_mipi_dsi_data_fmt data_format; -- cgit v0.10.2 From d07a9d2a5e82ed677971b2e9f3e4cbd49b9ec34e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Nov 2011 20:34:33 -0800 Subject: fbdev: sh_mipi_dsi: add SH_MIPI_DSI_BL2E flag Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index c9fac13..dfd5154 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c @@ -316,6 +316,8 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, * Non-burst mode with sync pulses: VSE and HSE are output, * HSA period allowed, no commands in LP */ + if (pdata->flags & SH_MIPI_DSI_BL2E) + vmctr2 |= 1 << 17; if (pdata->flags & SH_MIPI_DSI_HSABM) vmctr2 |= 1 << 5; if (pdata->flags & SH_MIPI_DSI_HBPBM) diff --git a/include/video/sh_mipi_dsi.h b/include/video/sh_mipi_dsi.h index 86a72c0..58b78f8 100644 --- a/include/video/sh_mipi_dsi.h +++ b/include/video/sh_mipi_dsi.h @@ -30,6 +30,7 @@ struct sh_mobile_lcdc_chan_cfg; #define SH_MIPI_DSI_HSABM (1 << 0) #define SH_MIPI_DSI_HBPBM (1 << 1) #define SH_MIPI_DSI_HFPBM (1 << 2) +#define SH_MIPI_DSI_BL2E (1 << 3) struct sh_mipi_dsi_info { enum sh_mipi_dsi_data_fmt data_format; -- cgit v0.10.2 From 26c3d7ac219e74ab3939048a32d6bd3b4a16798a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Nov 2011 20:34:43 -0800 Subject: fbdev: sh_mipi_dsi: add lane control support SH MIPI DSI can use 0-4 lane Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Florian Tobias Schandinat diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index b862e9f..e969fe9 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -324,6 +324,7 @@ static struct resource mipidsi0_resources[] = { static struct sh_mipi_dsi_info mipidsi0_info = { .data_format = MIPI_RGB888, .lcd_chan = &lcdc0_info.ch[0], + .lane = 2, .vsynw_offset = 20, .clksrc = 1, .flags = SH_MIPI_DSI_HSABM, diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 4c865ec..b7d006f 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -580,6 +580,7 @@ static struct resource mipidsi0_resources[] = { static struct sh_mipi_dsi_info mipidsi0_info = { .data_format = MIPI_RGB888, .lcd_chan = &lcdc_info.ch[0], + .lane = 2, .vsynw_offset = 17, }; diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index dfd5154..af6bec2 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c @@ -8,6 +8,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include @@ -153,6 +154,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan; u32 pctype, datatype, pixfmt, linelength, vmctr2 = 0x00e00000; bool yuv; + u32 tmp; /* * Select data format. MIPI DSI is not hot-pluggable, so, we just use @@ -253,6 +255,9 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, (!yuv && ch->interface_type != RGB24)) return -EINVAL; + if (!pdata->lane) + return -EINVAL; + /* reset DSI link */ iowrite32(0x00000001, base + SYSCTRL); /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */ @@ -269,7 +274,10 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, * ECC check enable * additionally enable first two lanes */ - iowrite32(0x00003703, base + SYSCONF); + bitmap_fill((unsigned long *)&tmp, pdata->lane); + tmp |= 0x00003700; + iowrite32(tmp, base + SYSCONF); + /* * T_wakeup = 0x7000 * T_hs-trail = 3 diff --git a/include/video/sh_mipi_dsi.h b/include/video/sh_mipi_dsi.h index 58b78f8..3d0ec50 100644 --- a/include/video/sh_mipi_dsi.h +++ b/include/video/sh_mipi_dsi.h @@ -35,6 +35,7 @@ struct sh_mobile_lcdc_chan_cfg; struct sh_mipi_dsi_info { enum sh_mipi_dsi_data_fmt data_format; struct sh_mobile_lcdc_chan_cfg *lcd_chan; + int lane; unsigned long flags; u32 clksrc; unsigned int vsynw_offset; -- cgit v0.10.2 From f832906a56bcf9c597589e9a7898c1dd2f0513b9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Nov 2011 20:34:55 -0800 Subject: fbdev: sh_mipi_dsi: add sync_pulses/sync_events/burst mode Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Florian Tobias Schandinat diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index e969fe9..6993844 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -327,7 +327,8 @@ static struct sh_mipi_dsi_info mipidsi0_info = { .lane = 2, .vsynw_offset = 20, .clksrc = 1, - .flags = SH_MIPI_DSI_HSABM, + .flags = SH_MIPI_DSI_HSABM | + SH_MIPI_DSI_SYNC_PULSES_MODE, }; static struct platform_device mipidsi0_device = { diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index b7d006f..b2e32c8 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -582,6 +582,7 @@ static struct sh_mipi_dsi_info mipidsi0_info = { .lcd_chan = &lcdc_info.ch[0], .lane = 2, .vsynw_offset = 17, + .flags = SH_MIPI_DSI_SYNC_PULSES_MODE, }; static struct platform_device mipidsi0_device = { diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index af6bec2..b8c4873 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c @@ -152,7 +152,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, { void __iomem *base = mipi->base; struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan; - u32 pctype, datatype, pixfmt, linelength, vmctr2 = 0x00e00000; + u32 pctype, datatype, pixfmt, linelength, vmctr2; bool yuv; u32 tmp; @@ -324,6 +324,13 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, * Non-burst mode with sync pulses: VSE and HSE are output, * HSA period allowed, no commands in LP */ + vmctr2 = 0; + if (pdata->flags & SH_MIPI_DSI_VSEE) + vmctr2 |= 1 << 23; + if (pdata->flags & SH_MIPI_DSI_HSEE) + vmctr2 |= 1 << 22; + if (pdata->flags & SH_MIPI_DSI_HSAE) + vmctr2 |= 1 << 21; if (pdata->flags & SH_MIPI_DSI_BL2E) vmctr2 |= 1 << 17; if (pdata->flags & SH_MIPI_DSI_HSABM) diff --git a/include/video/sh_mipi_dsi.h b/include/video/sh_mipi_dsi.h index 3d0ec50..c8225b4 100644 --- a/include/video/sh_mipi_dsi.h +++ b/include/video/sh_mipi_dsi.h @@ -31,6 +31,15 @@ struct sh_mobile_lcdc_chan_cfg; #define SH_MIPI_DSI_HBPBM (1 << 1) #define SH_MIPI_DSI_HFPBM (1 << 2) #define SH_MIPI_DSI_BL2E (1 << 3) +#define SH_MIPI_DSI_VSEE (1 << 4) +#define SH_MIPI_DSI_HSEE (1 << 5) +#define SH_MIPI_DSI_HSAE (1 << 6) + +#define SH_MIPI_DSI_SYNC_PULSES_MODE (SH_MIPI_DSI_VSEE | \ + SH_MIPI_DSI_HSEE | \ + SH_MIPI_DSI_HSAE) +#define SH_MIPI_DSI_SYNC_EVENTS_MODE (0) +#define SH_MIPI_DSI_SYNC_BURST_MODE (SH_MIPI_DSI_BL2E) struct sh_mipi_dsi_info { enum sh_mipi_dsi_data_fmt data_format; -- cgit v0.10.2 From 08750617badd03fd95f33921a5213a5632022178 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Nov 2011 20:35:05 -0800 Subject: fbdev: sh_mipi_dsi: add VMLEN1/VMLEN2 calculation VMLEN1/VMLEN2 needs blanking length which is calculated from video image size. The calculation methods are explained on [SH MIPI] - [Video Mode] - [Blanking Packet setting] But HFPLEN (= VMLEN2) is un-understandable. For example, if SH-MIPI input was RGB888 (3byte), output was RGB888 (3byte) and 3lane connection, the date goes straight. But if SH-MIPI input was RGB888 (3byte), output was RGB565 (2byte) and 4lane connection, it needs delay in HFPLEN. Then (input cycle - output cycle) * lane is necessary the delay Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index b8c4873..190e941 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c @@ -42,6 +42,7 @@ #define VMCTR1 0x0020 #define VMCTR2 0x0024 #define VMLEN1 0x0028 +#define VMLEN2 0x002c #define CMTSRTREQ 0x0070 #define CMTSRTCTR 0x00d0 @@ -153,8 +154,9 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, void __iomem *base = mipi->base; struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan; u32 pctype, datatype, pixfmt, linelength, vmctr2; + u32 tmp, top, bottom, delay; bool yuv; - u32 tmp; + int bpp; /* * Select data format. MIPI DSI is not hot-pluggable, so, we just use @@ -342,11 +344,44 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, iowrite32(vmctr2, mipi->linkbase + VMCTR2); /* - * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see - * sh_mobile_lcdc_info.ch[0].lcd_cfg[0].xres), HSALEN = 1 - default - * (unused if VMCTR2[HSABM] = 0) + * VMLEN1 = RGBLEN | HSALEN + * + * see + * Video mode - Blanking Packet setting */ - iowrite32(1 | (linelength << 16), mipi->linkbase + VMLEN1); + top = linelength << 16; /* RGBLEN */ + bottom = 0x00000001; + if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */ + bottom = (pdata->lane * ch->lcd_cfg[0].hsync_len) - 10; + iowrite32(top | bottom , mipi->linkbase + VMLEN1); + + /* + * VMLEN2 = HBPLEN | HFPLEN + * + * see + * Video mode - Blanking Packet setting + */ + top = 0x00010000; + bottom = 0x00000001; + delay = 0; + + if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */ + top = ch->lcd_cfg[0].hsync_len + ch->lcd_cfg[0].left_margin; + top = ((pdata->lane * top) - 10) << 16; + } + if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */ + bottom = ch->lcd_cfg[0].right_margin; + bottom = (pdata->lane * bottom) - 12; + } + + bpp = linelength / ch->lcd_cfg[0].xres; /* byte / pixel */ + if (pdata->lane > bpp) { + tmp = ch->lcd_cfg[0].xres / bpp; /* output cycle */ + tmp = ch->lcd_cfg[0].xres - tmp; /* (input - output) cycle */ + delay = (pdata->lane * tmp); + } + + iowrite32(top | (bottom + delay) , mipi->linkbase + VMLEN2); msleep(5); -- cgit v0.10.2 From 5e47431aabf716c9ad9eacf1a966e1fc1469c809 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Nov 2011 20:35:14 -0800 Subject: fbdev: sh_mipi_dsi: add set_dot_clock() for each platform Dot clock of SH MIPI are depends on each platform board. This patch adds set_dot_clock() function for it. Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Florian Tobias Schandinat diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index 6993844..15072c5 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -321,6 +321,36 @@ static struct resource mipidsi0_resources[] = { }, }; +#define DSI0PHYCR 0xe615006c +static int sh_mipi_set_dot_clock(struct platform_device *pdev, + void __iomem *base, + int enable) +{ + struct clk *pck; + int ret; + + pck = clk_get(&pdev->dev, "dsip_clk"); + if (IS_ERR(pck)) { + ret = PTR_ERR(pck); + goto sh_mipi_set_dot_clock_pck_err; + } + + if (enable) { + clk_set_rate(pck, clk_round_rate(pck, 24000000)); + __raw_writel(0x2a809010, DSI0PHYCR); + clk_enable(pck); + } else { + clk_disable(pck); + } + + ret = 0; + + clk_put(pck); + +sh_mipi_set_dot_clock_pck_err: + return ret; +} + static struct sh_mipi_dsi_info mipidsi0_info = { .data_format = MIPI_RGB888, .lcd_chan = &lcdc0_info.ch[0], @@ -329,6 +359,7 @@ static struct sh_mipi_dsi_info mipidsi0_info = { .clksrc = 1, .flags = SH_MIPI_DSI_HSABM | SH_MIPI_DSI_SYNC_PULSES_MODE, + .set_dot_clock = sh_mipi_set_dot_clock, }; static struct platform_device mipidsi0_device = { @@ -476,8 +507,6 @@ static void __init ag5evm_map_io(void) shmobile_setup_console(); } -#define DSI0PHYCR 0xe615006c - static void __init ag5evm_init(void) { sh73a0_pinmux_init(); @@ -558,9 +587,6 @@ static void __init ag5evm_init(void) gpio_direction_output(GPIO_PORT235, 0); lcd_backlight_reset(); - /* MIPI-DSI clock setup */ - __raw_writel(0x2a809010, DSI0PHYCR); - /* enable SDHI0 on CN15 [SD I/F] */ gpio_request(GPIO_FN_SDHICD0, NULL); gpio_request(GPIO_FN_SDHIWP0, NULL); diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index b2e32c8..73503ed 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -564,6 +564,30 @@ static struct platform_device keysc_device = { }; /* MIPI-DSI */ +#define PHYCTRL 0x0070 +static int sh_mipi_set_dot_clock(struct platform_device *pdev, + void __iomem *base, + int enable) +{ + struct clk *pck = clk_get(&pdev->dev, "dsip_clk"); + void __iomem *phy = base + PHYCTRL; + + if (IS_ERR(pck)) + return PTR_ERR(pck); + + if (enable) { + clk_set_rate(pck, clk_round_rate(pck, 24000000)); + iowrite32(ioread32(phy) | (0xb << 8), phy); + clk_enable(pck); + } else { + clk_disable(pck); + } + + clk_put(pck); + + return 0; +} + static struct resource mipidsi0_resources[] = { [0] = { .start = 0xffc60000, @@ -583,6 +607,7 @@ static struct sh_mipi_dsi_info mipidsi0_info = { .lane = 2, .vsynw_offset = 17, .flags = SH_MIPI_DSI_SYNC_PULSES_MODE, + .set_dot_clock = sh_mipi_set_dot_clock, }; static struct platform_device mipidsi0_device = { diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index 190e941..77743f4 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c @@ -53,7 +53,6 @@ struct sh_mipi { void __iomem *base; void __iomem *linkbase; struct clk *dsit_clk; - struct clk *dsip_clk; struct device *dev; void *next_board_data; @@ -307,8 +306,8 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, /* DSI-Tx bias on */ iowrite32(0x00000001, base + PHYCTRL); udelay(200); - /* Deassert resets, power on, set multiplier */ - iowrite32(0x03070b01, base + PHYCTRL); + /* Deassert resets, power on */ + iowrite32(0x03070001, base + PHYCTRL); /* setup l-bridge */ @@ -421,6 +420,9 @@ static int __init sh_mipi_probe(struct platform_device *pdev) if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata) return -ENODEV; + if (!pdata->set_dot_clock) + return -EINVAL; + mutex_lock(&array_lock); if (idx < 0) for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++) @@ -481,34 +483,10 @@ static int __init sh_mipi_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate); - mipi->dsip_clk = clk_get(&pdev->dev, "dsip_clk"); - if (IS_ERR(mipi->dsip_clk)) { - ret = PTR_ERR(mipi->dsip_clk); - goto eclkpget; - } - - f_current = clk_get_rate(mipi->dsip_clk); - /* Between 10 and 50MHz */ - rate = clk_round_rate(mipi->dsip_clk, 24000000); - if (rate > 0 && rate != f_current) - ret = clk_set_rate(mipi->dsip_clk, rate); - else - ret = rate; - if (ret < 0) - goto esetprate; - - dev_dbg(&pdev->dev, "DSI-P clk %lu -> %lu\n", f_current, rate); - - msleep(10); - ret = clk_enable(mipi->dsit_clk); if (ret < 0) goto eclkton; - ret = clk_enable(mipi->dsip_clk); - if (ret < 0) - goto eclkpon; - mipi_dsi[idx] = mipi; pm_runtime_enable(&pdev->dev); @@ -518,6 +496,10 @@ static int __init sh_mipi_probe(struct platform_device *pdev) if (ret < 0) goto emipisetup; + ret = pdata->set_dot_clock(pdev, mipi->base, 1); + if (ret < 0) + goto emipisetup; + mutex_unlock(&array_lock); platform_set_drvdata(pdev, mipi); @@ -537,13 +519,8 @@ static int __init sh_mipi_probe(struct platform_device *pdev) emipisetup: mipi_dsi[idx] = NULL; pm_runtime_disable(&pdev->dev); - clk_disable(mipi->dsip_clk); -eclkpon: clk_disable(mipi->dsit_clk); eclkton: -esetprate: - clk_put(mipi->dsip_clk); -eclkpget: esettrate: clk_put(mipi->dsit_clk); eclktget: @@ -594,10 +571,10 @@ static int __exit sh_mipi_remove(struct platform_device *pdev) pdata->lcd_chan->board_cfg.board_data = NULL; pm_runtime_disable(&pdev->dev); - clk_disable(mipi->dsip_clk); clk_disable(mipi->dsit_clk); clk_put(mipi->dsit_clk); - clk_put(mipi->dsip_clk); + pdata->set_dot_clock(pdev, mipi->base, 0); + iounmap(mipi->linkbase); if (res2) release_mem_region(res2->start, resource_size(res2)); diff --git a/include/video/sh_mipi_dsi.h b/include/video/sh_mipi_dsi.h index c8225b4..310b883 100644 --- a/include/video/sh_mipi_dsi.h +++ b/include/video/sh_mipi_dsi.h @@ -48,6 +48,9 @@ struct sh_mipi_dsi_info { unsigned long flags; u32 clksrc; unsigned int vsynw_offset; + int (*set_dot_clock)(struct platform_device *pdev, + void __iomem *base, + int enable); }; #endif -- cgit v0.10.2 From a2e6297153f8fc7185d119c59d8eed1ee7d4c74f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Nov 2011 20:35:27 -0800 Subject: fbdev: sh_mipi_dsi: add HSxxCLK support SH MIPI manual explains the calculation method of HBP/HFP. it is based on HSbyteCLK settings. SH73a0 chip can use HS6divCLK/HS4divCLK for it. This patch has compatibility to SH7372 mipi Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Florian Tobias Schandinat diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index 15072c5..7e3dd73 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -357,8 +357,9 @@ static struct sh_mipi_dsi_info mipidsi0_info = { .lane = 2, .vsynw_offset = 20, .clksrc = 1, - .flags = SH_MIPI_DSI_HSABM | - SH_MIPI_DSI_SYNC_PULSES_MODE, + .flags = SH_MIPI_DSI_HSABM | + SH_MIPI_DSI_SYNC_PULSES_MODE | + SH_MIPI_DSI_HSbyteCLK, .set_dot_clock = sh_mipi_set_dot_clock, }; diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 73503ed..904b608 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -606,7 +606,8 @@ static struct sh_mipi_dsi_info mipidsi0_info = { .lcd_chan = &lcdc_info.ch[0], .lane = 2, .vsynw_offset = 17, - .flags = SH_MIPI_DSI_SYNC_PULSES_MODE, + .flags = SH_MIPI_DSI_SYNC_PULSES_MODE | + SH_MIPI_DSI_HSbyteCLK, .set_dot_clock = sh_mipi_set_dot_clock, }; diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index 77743f4..b8aea8c 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c @@ -153,7 +153,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, void __iomem *base = mipi->base; struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan; u32 pctype, datatype, pixfmt, linelength, vmctr2; - u32 tmp, top, bottom, delay; + u32 tmp, top, bottom, delay, div; bool yuv; int bpp; @@ -364,17 +364,23 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, bottom = 0x00000001; delay = 0; + div = 1; /* HSbyteCLK is calculation base + * HS4divCLK = HSbyteCLK/2 + * HS6divCLK is not supported for now */ + if (pdata->flags & SH_MIPI_DSI_HS4divCLK) + div = 2; + if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */ top = ch->lcd_cfg[0].hsync_len + ch->lcd_cfg[0].left_margin; - top = ((pdata->lane * top) - 10) << 16; + top = ((pdata->lane * top / div) - 10) << 16; } if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */ bottom = ch->lcd_cfg[0].right_margin; - bottom = (pdata->lane * bottom) - 12; + bottom = (pdata->lane * bottom / div) - 12; } bpp = linelength / ch->lcd_cfg[0].xres; /* byte / pixel */ - if (pdata->lane > bpp) { + if ((pdata->lane / div) > bpp) { tmp = ch->lcd_cfg[0].xres / bpp; /* output cycle */ tmp = ch->lcd_cfg[0].xres - tmp; /* (input - output) cycle */ delay = (pdata->lane * tmp); diff --git a/include/video/sh_mipi_dsi.h b/include/video/sh_mipi_dsi.h index 310b883..434d56b 100644 --- a/include/video/sh_mipi_dsi.h +++ b/include/video/sh_mipi_dsi.h @@ -35,6 +35,10 @@ struct sh_mobile_lcdc_chan_cfg; #define SH_MIPI_DSI_HSEE (1 << 5) #define SH_MIPI_DSI_HSAE (1 << 6) +#define SH_MIPI_DSI_HSbyteCLK (1 << 24) +#define SH_MIPI_DSI_HS6divCLK (1 << 25) +#define SH_MIPI_DSI_HS4divCLK (1 << 26) + #define SH_MIPI_DSI_SYNC_PULSES_MODE (SH_MIPI_DSI_VSEE | \ SH_MIPI_DSI_HSEE | \ SH_MIPI_DSI_HSAE) -- cgit v0.10.2 From 7d9f88b4f427df6dab7ff92ea81f1ddb7e9c95e4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Nov 2011 20:35:36 -0800 Subject: fbdev: sh_mipi_dsi: sh_mipi has pdata instead of dev Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index b8aea8c..7e46505 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c @@ -53,7 +53,7 @@ struct sh_mipi { void __iomem *base; void __iomem *linkbase; struct clk *dsit_clk; - struct device *dev; + struct platform_device *pdev; void *next_board_data; void (*next_display_on)(void *board_data, struct fb_info *info); @@ -129,7 +129,7 @@ static void mipi_display_on(void *arg, struct fb_info *info) { struct sh_mipi *mipi = arg; - pm_runtime_get_sync(mipi->dev); + pm_runtime_get_sync(&mipi->pdev->dev); sh_mipi_dsi_enable(mipi, true); if (mipi->next_display_on) @@ -144,7 +144,7 @@ static void mipi_display_off(void *arg) mipi->next_display_off(mipi->next_board_data); sh_mipi_dsi_enable(mipi, false); - pm_runtime_put(mipi->dev); + pm_runtime_put(&mipi->pdev->dev); } static int __init sh_mipi_setup(struct sh_mipi *mipi, @@ -469,7 +469,7 @@ static int __init sh_mipi_probe(struct platform_device *pdev) goto emap2; } - mipi->dev = &pdev->dev; + mipi->pdev = pdev; mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk"); if (IS_ERR(mipi->dsit_clk)) { -- cgit v0.10.2 From c2658b70f06108361aa5024798f9c1bf47c73374 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Nov 2011 20:35:45 -0800 Subject: fbdev: sh_mipi_dsi: fixup setup timing of sh_mipi_setup() sh_mipi_setup() should be called after setting of CPG Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index 7e46505..f2c3f94 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c @@ -125,28 +125,6 @@ static void sh_mipi_shutdown(struct platform_device *pdev) sh_mipi_dsi_enable(mipi, false); } -static void mipi_display_on(void *arg, struct fb_info *info) -{ - struct sh_mipi *mipi = arg; - - pm_runtime_get_sync(&mipi->pdev->dev); - sh_mipi_dsi_enable(mipi, true); - - if (mipi->next_display_on) - mipi->next_display_on(mipi->next_board_data, info); -} - -static void mipi_display_off(void *arg) -{ - struct sh_mipi *mipi = arg; - - if (mipi->next_display_off) - mipi->next_display_off(mipi->next_board_data); - - sh_mipi_dsi_enable(mipi, false); - pm_runtime_put(&mipi->pdev->dev); -} - static int __init sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata) { @@ -414,6 +392,50 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, return 0; } +static void mipi_display_on(void *arg, struct fb_info *info) +{ + struct sh_mipi *mipi = arg; + struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data; + int ret; + + pm_runtime_get_sync(&mipi->pdev->dev); + + ret = pdata->set_dot_clock(mipi->pdev, mipi->base, 1); + if (ret < 0) + goto mipi_display_on_fail1; + + ret = sh_mipi_setup(mipi, pdata); + if (ret < 0) + goto mipi_display_on_fail2; + + sh_mipi_dsi_enable(mipi, true); + + if (mipi->next_display_on) + mipi->next_display_on(mipi->next_board_data, info); + + return; + +mipi_display_on_fail1: + pm_runtime_put_sync(&mipi->pdev->dev); +mipi_display_on_fail2: + pdata->set_dot_clock(mipi->pdev, mipi->base, 0); +} + +static void mipi_display_off(void *arg) +{ + struct sh_mipi *mipi = arg; + struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data; + + if (mipi->next_display_off) + mipi->next_display_off(mipi->next_board_data); + + sh_mipi_dsi_enable(mipi, false); + + pdata->set_dot_clock(mipi->pdev, mipi->base, 0); + + pm_runtime_put_sync(&mipi->pdev->dev); +} + static int __init sh_mipi_probe(struct platform_device *pdev) { struct sh_mipi *mipi; @@ -498,14 +520,6 @@ static int __init sh_mipi_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_resume(&pdev->dev); - ret = sh_mipi_setup(mipi, pdata); - if (ret < 0) - goto emipisetup; - - ret = pdata->set_dot_clock(pdev, mipi->base, 1); - if (ret < 0) - goto emipisetup; - mutex_unlock(&array_lock); platform_set_drvdata(pdev, mipi); @@ -522,10 +536,6 @@ static int __init sh_mipi_probe(struct platform_device *pdev) return 0; -emipisetup: - mipi_dsi[idx] = NULL; - pm_runtime_disable(&pdev->dev); - clk_disable(mipi->dsit_clk); eclkton: esettrate: clk_put(mipi->dsit_clk); @@ -579,7 +589,6 @@ static int __exit sh_mipi_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); clk_disable(mipi->dsit_clk); clk_put(mipi->dsit_clk); - pdata->set_dot_clock(pdev, mipi->base, 0); iounmap(mipi->linkbase); if (res2) -- cgit v0.10.2 From a2065a368cc2539d6a48450f367f5033c699cdc4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Nov 2011 20:35:56 -0800 Subject: fbdev: sh_mipi_dsi: fixup setup timing of SYSCONF SYSCONF should be set after PHYCTRL Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index f2c3f94..187e127 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c @@ -246,18 +246,6 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, /* setup DSI link */ /* - * Default = ULPS enable | - * Contention detection enabled | - * EoT packet transmission enable | - * CRC check enable | - * ECC check enable - * additionally enable first two lanes - */ - bitmap_fill((unsigned long *)&tmp, pdata->lane); - tmp |= 0x00003700; - iowrite32(tmp, base + SYSCONF); - - /* * T_wakeup = 0x7000 * T_hs-trail = 3 * T_hs-prepare = 3 @@ -287,6 +275,17 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, /* Deassert resets, power on */ iowrite32(0x03070001, base + PHYCTRL); + /* + * Default = ULPS enable | + * Contention detection enabled | + * EoT packet transmission enable | + * CRC check enable | + * ECC check enable + */ + bitmap_fill((unsigned long *)&tmp, pdata->lane); + tmp |= 0x00003700; + iowrite32(tmp, base + SYSCONF); + /* setup l-bridge */ /* -- cgit v0.10.2 From 97cab45583f75428773547f3bbe59fece05420d3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Nov 2011 20:36:07 -0800 Subject: fbdev: sh_mipi_dsi: fixup setup timing DSICTRL DSICTRL should be called after all mipi settings Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index 187e127..05151b8 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c @@ -265,8 +265,6 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, iowrite32(0x0fffffff, base + TATOVSET); /* Peripheral reset timeout, default 0xffffffff */ iowrite32(0x0fffffff, base + PRTOVSET); - /* Enable timeout counters */ - iowrite32(0x00000f00, base + DSICTRL); /* Interrupts not used, disable all */ iowrite32(0, base + DSIINTE); /* DSI-Tx bias on */ @@ -388,6 +386,9 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, pixfmt << 4); sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON); + /* Enable timeout counters */ + iowrite32(0x00000f00, base + DSICTRL); + return 0; } -- cgit v0.10.2 From 5345010cc8e87af7f1f48e5c816b10f96f474da1 Mon Sep 17 00:00:00 2001 From: Zac Storer Date: Thu, 17 Nov 2011 21:34:56 -0700 Subject: Drivers: video: controlfb: fixed a brace coding style issue Fixed a brace coding style issue. Signed-off-by: Zac Storer Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 7b2c40a..0c189b3 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -420,7 +420,7 @@ static int __init init_control(struct fb_info_control *p) /* Try to pick a video mode out of NVRAM if we have one. */ #ifdef CONFIG_NVRAM - if (default_cmode == CMODE_NVRAM){ + if (default_cmode == CMODE_NVRAM) { cmode = nvram_read_byte(NV_CMODE); if(cmode < CMODE_8 || cmode > CMODE_32) cmode = CMODE_8; -- cgit v0.10.2 From 2dfd7cf6ce581621c5c0103f96cca7a9924b5f94 Mon Sep 17 00:00:00 2001 From: Zac Storer Date: Thu, 17 Nov 2011 21:38:58 -0700 Subject: Drivers: video: sbuslib: fixed a brace coding style issue Fixed a brace coding style issue. Signed-off-by: Zac Storer Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c index 37d764a..3c1de98 100644 --- a/drivers/video/sbuslib.c +++ b/drivers/video/sbuslib.c @@ -76,7 +76,7 @@ int sbusfb_mmap_helper(struct sbus_mmap_map *map, map_offset = (physbase + map[i].poff) & POFF_MASK; break; } - if (!map_size){ + if (!map_size) { page += PAGE_SIZE; continue; } -- cgit v0.10.2 From 600bbf0aa2229390ba1c4ca4c5666c593ff9ef56 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 21 Nov 2011 20:12:04 -0500 Subject: ktest: Add default for ssh-user, build-target and target-image When a user runs ktest without an argument, or the argument given is not a config file that exists, ktest will ask the user a few questions to create a simple ktest config file. A few of the questions should have a default value set, that if anything it will make it easier for the user to know what is suppose to be in that value. These new values are: SSH_USER, BUILD_TARGET and TARGET_IMAGE Signed-off-by: Steven Rostedt diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 6ef104e..05f429d 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -22,7 +22,6 @@ my %default; #default opts $default{"NUM_TESTS"} = 1; -$default{"REBOOT_TYPE"} = "grub"; $default{"TEST_TYPE"} = "test"; $default{"BUILD_TYPE"} = "randconfig"; $default{"MAKE_CMD"} = "make"; @@ -51,7 +50,14 @@ $default{"REBOOT"} = "ssh \$SSH_USER\@\$MACHINE reboot"; $default{"STOP_AFTER_SUCCESS"} = 10; $default{"STOP_AFTER_FAILURE"} = 60; $default{"STOP_TEST_AFTER"} = 600; + +# required, and we will ask users if they don't have them but we keep the default +# value something that is common. +$default{"REBOOT_TYPE"} = "grub"; $default{"LOCALVERSION"} = "-test"; +$default{"SSH_USER"} = "root"; +$default{"BUILD_TARGET"} = "arch/x86/boot/bzImage"; +$default{"TARGET_IMAGE"} = "/boot/vmlinuz-test"; my $ktest_config; my $version; -- cgit v0.10.2 From 7fb3e75e1833743d5faf3adbae46b63f503c6fdf Mon Sep 17 00:00:00 2001 From: Narayanan G Date: Thu, 17 Nov 2011 17:26:41 +0530 Subject: dmaengine/ste_dma40: support pm in dma40 This patch adds power management support to the dma40 driver. The DMA registers are backed up and restored, during suspend/resume. Also flags to track the dma usage have been introduced to facilitate this. Patch also includes few other minor changes, related to formatting, comments. Signed-off-by: Narayanan G Acked-by: Linus Walleij Signed-off-by: Vinod Koul diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 15b311d5..c2cf8cf 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include @@ -32,6 +34,9 @@ /* Maximum iterations taken before giving up suspending a channel */ #define D40_SUSPEND_MAX_IT 500 +/* Milliseconds */ +#define DMA40_AUTOSUSPEND_DELAY 100 + /* Hardware requirement on LCLA alignment */ #define LCLA_ALIGNMENT 0x40000 @@ -62,6 +67,55 @@ enum d40_command { D40_DMA_SUSPENDED = 3 }; +/* + * These are the registers that has to be saved and later restored + * when the DMA hw is powered off. + * TODO: Add save/restore of D40_DREG_GCC on dma40 v3 or later, if that works. + */ +static u32 d40_backup_regs[] = { + D40_DREG_LCPA, + D40_DREG_LCLA, + D40_DREG_PRMSE, + D40_DREG_PRMSO, + D40_DREG_PRMOE, + D40_DREG_PRMOO, +}; + +#define BACKUP_REGS_SZ ARRAY_SIZE(d40_backup_regs) + +/* TODO: Check if all these registers have to be saved/restored on dma40 v3 */ +static u32 d40_backup_regs_v3[] = { + D40_DREG_PSEG1, + D40_DREG_PSEG2, + D40_DREG_PSEG3, + D40_DREG_PSEG4, + D40_DREG_PCEG1, + D40_DREG_PCEG2, + D40_DREG_PCEG3, + D40_DREG_PCEG4, + D40_DREG_RSEG1, + D40_DREG_RSEG2, + D40_DREG_RSEG3, + D40_DREG_RSEG4, + D40_DREG_RCEG1, + D40_DREG_RCEG2, + D40_DREG_RCEG3, + D40_DREG_RCEG4, +}; + +#define BACKUP_REGS_SZ_V3 ARRAY_SIZE(d40_backup_regs_v3) + +static u32 d40_backup_regs_chan[] = { + D40_CHAN_REG_SSCFG, + D40_CHAN_REG_SSELT, + D40_CHAN_REG_SSPTR, + D40_CHAN_REG_SSLNK, + D40_CHAN_REG_SDCFG, + D40_CHAN_REG_SDELT, + D40_CHAN_REG_SDPTR, + D40_CHAN_REG_SDLNK, +}; + /** * struct d40_lli_pool - Structure for keeping LLIs in memory * @@ -96,7 +150,7 @@ struct d40_lli_pool { * during a transfer. * @node: List entry. * @is_in_client_list: true if the client owns this descriptor. - * the previous one. + * @cyclic: true if this is a cyclic job * * This descriptor is used for both logical and physical transfers. */ @@ -143,6 +197,7 @@ struct d40_lcla_pool { * channels. * * @lock: A lock protection this entity. + * @reserved: True if used by secure world or otherwise. * @num: The physical channel number of this entity. * @allocated_src: Bit mapped to show which src event line's are mapped to * this physical channel. Can also be free or physically allocated. @@ -152,6 +207,7 @@ struct d40_lcla_pool { */ struct d40_phy_res { spinlock_t lock; + bool reserved; int num; u32 allocated_src; u32 allocated_dst; @@ -185,7 +241,6 @@ struct d40_base; * @src_def_cfg: Default cfg register setting for src. * @dst_def_cfg: Default cfg register setting for dst. * @log_def: Default logical channel settings. - * @lcla: Space for one dst src pair for logical channel transfers. * @lcpa: Pointer to dst and src lcpa settings. * @runtime_addr: runtime configured address. * @runtime_direction: runtime configured direction. @@ -241,6 +296,7 @@ struct d40_chan { * @dma_both: dma_device channels that can do both memcpy and slave transfers. * @dma_slave: dma_device channels that can do only do slave transfers. * @dma_memcpy: dma_device channels that can do only do memcpy transfers. + * @phy_chans: Room for all possible physical channels in system. * @log_chans: Room for all possible logical channels in system. * @lookup_log_chans: Used to map interrupt number to logical channel. Points * to log_chans entries. @@ -254,6 +310,13 @@ struct d40_chan { * @phy_lcpa: The physical address of the LCPA. * @lcpa_size: The size of the LCPA area. * @desc_slab: cache for descriptors. + * @reg_val_backup: Here the values of some hardware registers are stored + * before the DMA is powered off. They are restored when the power is back on. + * @reg_val_backup_v3: Backup of registers that only exits on dma40 v3 and + * later. + * @reg_val_backup_chan: Backup data for standard channel parameter registers. + * @gcc_pwr_off_mask: Mask to maintain the channels that can be turned off. + * @initialized: true if the dma has been initialized */ struct d40_base { spinlock_t interrupt_lock; @@ -282,6 +345,11 @@ struct d40_base { dma_addr_t phy_lcpa; resource_size_t lcpa_size; struct kmem_cache *desc_slab; + u32 reg_val_backup[BACKUP_REGS_SZ]; + u32 reg_val_backup_v3[BACKUP_REGS_SZ_V3]; + u32 *reg_val_backup_chan; + u16 gcc_pwr_off_mask; + bool initialized; }; /** @@ -479,13 +547,14 @@ static struct d40_desc *d40_desc_get(struct d40_chan *d40c) struct d40_desc *d; struct d40_desc *_d; - list_for_each_entry_safe(d, _d, &d40c->client, node) + list_for_each_entry_safe(d, _d, &d40c->client, node) { if (async_tx_test_ack(&d->txd)) { d40_desc_remove(d); desc = d; memset(desc, 0, sizeof(*desc)); break; } + } } if (!desc) @@ -740,7 +809,61 @@ static int d40_sg_2_dmalen(struct scatterlist *sgl, int sg_len, return len; } -/* Support functions for logical channels */ + +#ifdef CONFIG_PM +static void dma40_backup(void __iomem *baseaddr, u32 *backup, + u32 *regaddr, int num, bool save) +{ + int i; + + for (i = 0; i < num; i++) { + void __iomem *addr = baseaddr + regaddr[i]; + + if (save) + backup[i] = readl_relaxed(addr); + else + writel_relaxed(backup[i], addr); + } +} + +static void d40_save_restore_registers(struct d40_base *base, bool save) +{ + int i; + + /* Save/Restore channel specific registers */ + for (i = 0; i < base->num_phy_chans; i++) { + void __iomem *addr; + int idx; + + if (base->phy_res[i].reserved) + continue; + + addr = base->virtbase + D40_DREG_PCBASE + i * D40_DREG_PCDELTA; + idx = i * ARRAY_SIZE(d40_backup_regs_chan); + + dma40_backup(addr, &base->reg_val_backup_chan[idx], + d40_backup_regs_chan, + ARRAY_SIZE(d40_backup_regs_chan), + save); + } + + /* Save/Restore global registers */ + dma40_backup(base->virtbase, base->reg_val_backup, + d40_backup_regs, ARRAY_SIZE(d40_backup_regs), + save); + + /* Save/Restore registers only existing on dma40 v3 and later */ + if (base->rev >= 3) + dma40_backup(base->virtbase, base->reg_val_backup_v3, + d40_backup_regs_v3, + ARRAY_SIZE(d40_backup_regs_v3), + save); +} +#else +static void d40_save_restore_registers(struct d40_base *base, bool save) +{ +} +#endif static int d40_channel_execute_command(struct d40_chan *d40c, enum d40_command command) @@ -1013,6 +1136,7 @@ static int d40_pause(struct d40_chan *d40c) if (!d40c->busy) return 0; + pm_runtime_get_sync(d40c->base->dev); spin_lock_irqsave(&d40c->lock, flags); res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ); @@ -1025,7 +1149,8 @@ static int d40_pause(struct d40_chan *d40c) D40_DMA_RUN); } } - + pm_runtime_mark_last_busy(d40c->base->dev); + pm_runtime_put_autosuspend(d40c->base->dev); spin_unlock_irqrestore(&d40c->lock, flags); return res; } @@ -1039,7 +1164,7 @@ static int d40_resume(struct d40_chan *d40c) return 0; spin_lock_irqsave(&d40c->lock, flags); - + pm_runtime_get_sync(d40c->base->dev); if (d40c->base->rev == 0) if (chan_is_logical(d40c)) { res = d40_channel_execute_command(d40c, @@ -1057,6 +1182,8 @@ static int d40_resume(struct d40_chan *d40c) } no_suspend: + pm_runtime_mark_last_busy(d40c->base->dev); + pm_runtime_put_autosuspend(d40c->base->dev); spin_unlock_irqrestore(&d40c->lock, flags); return res; } @@ -1129,7 +1256,10 @@ static struct d40_desc *d40_queue_start(struct d40_chan *d40c) d40d = d40_first_queued(d40c); if (d40d != NULL) { - d40c->busy = true; + if (!d40c->busy) + d40c->busy = true; + + pm_runtime_get_sync(d40c->base->dev); /* Remove from queue */ d40_desc_remove(d40d); @@ -1190,6 +1320,8 @@ static void dma_tc_handle(struct d40_chan *d40c) if (d40_queue_start(d40c) == NULL) d40c->busy = false; + pm_runtime_mark_last_busy(d40c->base->dev); + pm_runtime_put_autosuspend(d40c->base->dev); } d40c->pending_tx++; @@ -1643,10 +1775,11 @@ static int d40_free_dma(struct d40_chan *d40c) return -EINVAL; } + pm_runtime_get_sync(d40c->base->dev); res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ); if (res) { chan_err(d40c, "suspend failed\n"); - return res; + goto out; } if (chan_is_logical(d40c)) { @@ -1664,13 +1797,11 @@ static int d40_free_dma(struct d40_chan *d40c) if (d40_chan_has_events(d40c)) { res = d40_channel_execute_command(d40c, D40_DMA_RUN); - if (res) { + if (res) chan_err(d40c, "Executing RUN command\n"); - return res; - } } - return 0; + goto out; } } else { (void) d40_alloc_mask_free(phy, is_src, 0); @@ -1680,13 +1811,23 @@ static int d40_free_dma(struct d40_chan *d40c) res = d40_channel_execute_command(d40c, D40_DMA_STOP); if (res) { chan_err(d40c, "Failed to stop channel\n"); - return res; + goto out; } + + if (d40c->busy) { + pm_runtime_mark_last_busy(d40c->base->dev); + pm_runtime_put_autosuspend(d40c->base->dev); + } + + d40c->busy = false; d40c->phy_chan = NULL; d40c->configured = false; d40c->base->lookup_phy_chans[phy->num] = NULL; +out: - return 0; + pm_runtime_mark_last_busy(d40c->base->dev); + pm_runtime_put_autosuspend(d40c->base->dev); + return res; } static bool d40_is_paused(struct d40_chan *d40c) @@ -2016,9 +2157,11 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) err = d40_allocate_channel(d40c); if (err) { chan_err(d40c, "Failed to allocate channel\n"); + d40c->configured = false; goto fail; } + pm_runtime_get_sync(d40c->base->dev); /* Fill in basic CFG register values */ d40_phy_cfg(&d40c->dma_cfg, &d40c->src_def_cfg, &d40c->dst_def_cfg, chan_is_logical(d40c)); @@ -2046,6 +2189,8 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) if (is_free_phy) d40_config_write(d40c); fail: + pm_runtime_mark_last_busy(d40c->base->dev); + pm_runtime_put_autosuspend(d40c->base->dev); spin_unlock_irqrestore(&d40c->lock, flags); return err; } @@ -2519,6 +2664,55 @@ failure1: return err; } +/* Suspend resume functionality */ +#ifdef CONFIG_PM +static int dma40_pm_suspend(struct device *dev) +{ + if (!pm_runtime_suspended(dev)) + return -EBUSY; + + return 0; +} + +static int dma40_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct d40_base *base = platform_get_drvdata(pdev); + + d40_save_restore_registers(base, true); + + /* Don't disable/enable clocks for v1 due to HW bugs */ + if (base->rev != 1) + writel_relaxed(base->gcc_pwr_off_mask, + base->virtbase + D40_DREG_GCC); + + return 0; +} + +static int dma40_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct d40_base *base = platform_get_drvdata(pdev); + + if (base->initialized) + d40_save_restore_registers(base, false); + + writel_relaxed(D40_DREG_GCC_ENABLE_ALL, + base->virtbase + D40_DREG_GCC); + return 0; +} + + +static const struct dev_pm_ops dma40_pm_ops = { + .suspend = dma40_pm_suspend, + .runtime_suspend = dma40_runtime_suspend, + .runtime_resume = dma40_runtime_resume, +}; +#define DMA40_PM_OPS (&dma40_pm_ops) +#else +#define DMA40_PM_OPS NULL +#endif + /* Initialization functions. */ static int __init d40_phy_res_init(struct d40_base *base) @@ -2527,6 +2721,7 @@ static int __init d40_phy_res_init(struct d40_base *base) int num_phy_chans_avail = 0; u32 val[2]; int odd_even_bit = -2; + int gcc = D40_DREG_GCC_ENA; val[0] = readl(base->virtbase + D40_DREG_PRSME); val[1] = readl(base->virtbase + D40_DREG_PRSMO); @@ -2538,9 +2733,17 @@ static int __init d40_phy_res_init(struct d40_base *base) /* Mark security only channels as occupied */ base->phy_res[i].allocated_src = D40_ALLOC_PHY; base->phy_res[i].allocated_dst = D40_ALLOC_PHY; + base->phy_res[i].reserved = true; + gcc |= D40_DREG_GCC_EVTGRP_ENA(D40_PHYS_TO_GROUP(i), + D40_DREG_GCC_SRC); + gcc |= D40_DREG_GCC_EVTGRP_ENA(D40_PHYS_TO_GROUP(i), + D40_DREG_GCC_DST); + + } else { base->phy_res[i].allocated_src = D40_ALLOC_FREE; base->phy_res[i].allocated_dst = D40_ALLOC_FREE; + base->phy_res[i].reserved = false; num_phy_chans_avail++; } spin_lock_init(&base->phy_res[i].lock); @@ -2552,6 +2755,11 @@ static int __init d40_phy_res_init(struct d40_base *base) base->phy_res[chan].allocated_src = D40_ALLOC_PHY; base->phy_res[chan].allocated_dst = D40_ALLOC_PHY; + base->phy_res[chan].reserved = true; + gcc |= D40_DREG_GCC_EVTGRP_ENA(D40_PHYS_TO_GROUP(chan), + D40_DREG_GCC_SRC); + gcc |= D40_DREG_GCC_EVTGRP_ENA(D40_PHYS_TO_GROUP(chan), + D40_DREG_GCC_DST); num_phy_chans_avail--; } @@ -2572,6 +2780,15 @@ static int __init d40_phy_res_init(struct d40_base *base) val[0] = val[0] >> 2; } + /* + * To keep things simple, Enable all clocks initially. + * The clocks will get managed later post channel allocation. + * The clocks for the event lines on which reserved channels exists + * are not managed here. + */ + writel(D40_DREG_GCC_ENABLE_ALL, base->virtbase + D40_DREG_GCC); + base->gcc_pwr_off_mask = gcc; + return num_phy_chans_avail; } @@ -2699,10 +2916,15 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) goto failure; } - base->lcla_pool.alloc_map = kzalloc(num_phy_chans * - sizeof(struct d40_desc *) * - D40_LCLA_LINK_PER_EVENT_GRP, + base->reg_val_backup_chan = kmalloc(base->num_phy_chans * + sizeof(d40_backup_regs_chan), GFP_KERNEL); + if (!base->reg_val_backup_chan) + goto failure; + + base->lcla_pool.alloc_map = + kzalloc(num_phy_chans * sizeof(struct d40_desc *) + * D40_LCLA_LINK_PER_EVENT_GRP, GFP_KERNEL); if (!base->lcla_pool.alloc_map) goto failure; @@ -2741,9 +2963,9 @@ failure: static void __init d40_hw_init(struct d40_base *base) { - static const struct d40_reg_val dma_init_reg[] = { + static struct d40_reg_val dma_init_reg[] = { /* Clock every part of the DMA block from start */ - { .reg = D40_DREG_GCC, .val = 0x0000ff01}, + { .reg = D40_DREG_GCC, .val = D40_DREG_GCC_ENABLE_ALL}, /* Interrupts on all logical channels */ { .reg = D40_DREG_LCMIS0, .val = 0xFFFFFFFF}, @@ -2960,6 +3182,12 @@ static int __init d40_probe(struct platform_device *pdev) goto failure; } + pm_runtime_irq_safe(base->dev); + pm_runtime_set_autosuspend_delay(base->dev, DMA40_AUTOSUSPEND_DELAY); + pm_runtime_use_autosuspend(base->dev); + pm_runtime_enable(base->dev); + pm_runtime_resume(base->dev); + base->initialized = true; err = d40_dmaengine_init(base, num_reserved_chans); if (err) goto failure; @@ -3013,6 +3241,7 @@ static struct platform_driver d40_driver = { .driver = { .owner = THIS_MODULE, .name = D40_NAME, + .pm = DMA40_PM_OPS, }, }; diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h index b44c4551..8d3d490 100644 --- a/drivers/dma/ste_dma40_ll.h +++ b/drivers/dma/ste_dma40_ll.h @@ -16,6 +16,8 @@ #define D40_TYPE_TO_GROUP(type) (type / 16) #define D40_TYPE_TO_EVENT(type) (type % 16) +#define D40_GROUP_SIZE 8 +#define D40_PHYS_TO_GROUP(phys) ((phys & (D40_GROUP_SIZE - 1)) / 2) /* Most bits of the CFG register are the same in log as in phy mode */ #define D40_SREG_CFG_MST_POS 15 @@ -123,6 +125,15 @@ /* DMA Register Offsets */ #define D40_DREG_GCC 0x000 +#define D40_DREG_GCC_ENA 0x1 +/* This assumes that there are only 4 event groups */ +#define D40_DREG_GCC_ENABLE_ALL 0xff01 +#define D40_DREG_GCC_EVTGRP_POS 8 +#define D40_DREG_GCC_SRC 0 +#define D40_DREG_GCC_DST 1 +#define D40_DREG_GCC_EVTGRP_ENA(x, y) \ + (1 << (D40_DREG_GCC_EVTGRP_POS + 2 * x + y)) + #define D40_DREG_PRTYP 0x004 #define D40_DREG_PRSME 0x008 #define D40_DREG_PRSMO 0x00C -- cgit v0.10.2 From e69664336d6400cc1685716ee5f04ef74e85703e Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Fri, 18 Nov 2011 16:38:02 +0800 Subject: IMX/DMA : set the DMA direction in the sdma_control() Set the right DMA direction in the sdma_control(), else we will get the wrong log when enable the DYNAMIC_DEBUG. Signed-off-by: Huang Shijie Signed-off-by: Vinod Koul diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 2e03571..d9e5933 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1102,6 +1102,7 @@ static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, sdmac->watermark_level = dmaengine_cfg->dst_maxburst; sdmac->word_size = dmaengine_cfg->dst_addr_width; } + sdmac->direction = dmaengine_cfg->direction; return sdma_config_channel(sdmac); default: return -ENOSYS; -- cgit v0.10.2 From 9147621c771c8b6a5c8985373af3a8200e8b4a41 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 22 Nov 2011 14:47:50 -0800 Subject: kbuild, headers.sh: Don't make archheaders explicitly We don't need to explicitly invoke the archheaders target because of the dependency on __headers in the Makefile. Reported-and-tested-by: Michal Marek Link: http://lkml.kernel.org/r/4ECA8991.20302@suse.cz Signed-off-by: H. Peter Anvin diff --git a/scripts/headers.sh b/scripts/headers.sh index af1ed88..978b42b 100755 --- a/scripts/headers.sh +++ b/scripts/headers.sh @@ -7,7 +7,6 @@ set -e do_command() { if [ -f ${srctree}/arch/$2/include/asm/Kbuild ]; then - make ARCH=$2 KBUILD_HEADERS=$1 archheaders make ARCH=$2 KBUILD_HEADERS=$1 headers_$1 else printf "Ignoring arch: %s\n" ${arch} -- cgit v0.10.2 From 60ec0eecfa8968d0f1188e3730979196ac28b9de Mon Sep 17 00:00:00 2001 From: Asai Thambi S P Date: Wed, 23 Nov 2011 08:29:24 +0100 Subject: mtip32xx: updates based on feedback * queue ncq commands when a non-ncq is in progress or error handling is active * merge variables 'internal_cmd_in_progress' and 'eh_active' into new variable 'flags' * get rid of read/write semaphore 'internal_sem' * new service thread to issue queued commands * use macros from ata.h for command codes * return ENOTTY for BLKFLSBUF ioctl * style changes Signed-off-by: Asai Thambi S P Signed-off-by: Sam Bradshaw Signed-off-by: Jens Axboe diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 880facb..b5d843a 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -34,6 +34,7 @@ #include #include #include +#include #include <../drivers/ata/ahci.h> #include "mtip32xx.h" @@ -99,15 +100,6 @@ struct mtip_compat_ide_task_request_s { }; #endif -static int mtip_exec_internal_command(struct mtip_port *port, - void *fis, - int fisLen, - dma_addr_t buffer, - int bufLen, - u32 opts, - gfp_t atomic, - unsigned long timeout); - /* * This function check_for_surprise_removal is called * while card is removed from the system and it will @@ -414,9 +406,9 @@ static void mtip_init_port(struct mtip_port *port) port->mmio + PORT_FIS_ADDR_HI); } - writel(port->command_list_dma & 0xffffffff, + writel(port->command_list_dma & 0xFFFFFFFF, port->mmio + PORT_LST_ADDR); - writel(port->rxfis_dma & 0xffffffff, port->mmio + PORT_FIS_ADDR); + writel(port->rxfis_dma & 0xFFFFFFFF, port->mmio + PORT_FIS_ADDR); /* Clear SError */ writel(readl(port->mmio + PORT_SCR_ERR), port->mmio + PORT_SCR_ERR); @@ -541,7 +533,7 @@ static void mtip_timeout_function(unsigned long int data) if (atomic_read(&port->commands[tag].active) && (time_after(jiffies, port->commands[tag].comp_time))) { group = tag >> 5; - bit = tag & 0x1f; + bit = tag & 0x1F; command = &port->commands[tag]; fis = (struct host_to_dev_fis *) command->command; @@ -551,7 +543,7 @@ static void mtip_timeout_function(unsigned long int data) cmdto_cnt++; if (cmdto_cnt == 1) - atomic_inc(&port->dd->eh_active); + set_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags); /* * Clear the completed bit. This should prevent @@ -589,7 +581,8 @@ static void mtip_timeout_function(unsigned long int data) "%d commands timed out: restarting port", cmdto_cnt); mtip_restart_port(port); - atomic_dec(&port->dd->eh_active); + clear_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags); + wake_up_interruptible(&port->svc_wait); } /* Restart the timer */ @@ -728,7 +721,7 @@ static void mtip_handle_tfe(struct driver_data *dd) del_timer(&port->cmd_timer); /* Set eh_active */ - atomic_inc(&dd->eh_active); + set_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags); /* Loop through all the groups */ for (group = 0; group < dd->slot_groups; group++) { @@ -835,8 +828,9 @@ static void mtip_handle_tfe(struct driver_data *dd) } print_tags(dd, "TFE tags reissued:", tagaccum); - /* Decrement eh_active */ - atomic_dec(&dd->eh_active); + /* clear eh_active */ + clear_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags); + wake_up_interruptible(&port->svc_wait); mod_timer(&port->cmd_timer, jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD)); @@ -871,7 +865,6 @@ static inline void mtip_process_sdbf(struct driver_data *dd) continue; command = &port->commands[tag]; - /* make internal callback */ if (likely(command->comp_func)) { command->comp_func( @@ -904,9 +897,8 @@ static inline void mtip_process_legacy(struct driver_data *dd, u32 port_stat) struct mtip_port *port = dd->port; struct mtip_cmd *cmd = &port->commands[MTIP_TAG_INTERNAL]; - if (port->internal_cmd_in_progress && - cmd != NULL && - !(readl(port->cmd_issue[MTIP_TAG_INTERNAL]) + if (test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) && + (cmd != NULL) && !(readl(port->cmd_issue[MTIP_TAG_INTERNAL]) & (1 << MTIP_TAG_INTERNAL))) { if (cmd->comp_func) { cmd->comp_func(port, @@ -1038,11 +1030,15 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout) to = jiffies + msecs_to_jiffies(timeout); do { + if (test_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags)) { + msleep(20); + continue; /* svc thd is actively issuing commands */ + } /* * Ignore s_active bit 0 of array element 0. * This bit will always be set */ - active = readl(port->s_active[0]) & 0xfffffffe; + active = readl(port->s_active[0]) & 0xFFFFFFFE; for (n = 1; n < port->dd->slot_groups; n++) active |= readl(port->s_active[n]); @@ -1060,9 +1056,9 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout) * * @port Pointer to the port data structure. * @fis Pointer to the FIS that describes the command. - * @fisLen Length in WORDS of the FIS. + * @fis_len Length in WORDS of the FIS. * @buffer DMA accessible for command data. - * @bufLen Length, in bytes, of the data buffer. + * @buf_len Length, in bytes, of the data buffer. * @opts Command header options, excluding the FIS length * and the number of PRD entries. * @timeout Time in ms to wait for the command to complete. @@ -1075,9 +1071,9 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout) */ static int mtip_exec_internal_command(struct mtip_port *port, void *fis, - int fisLen, + int fis_len, dma_addr_t buffer, - int bufLen, + int buf_len, u32 opts, gfp_t atomic, unsigned long timeout) @@ -1100,7 +1096,7 @@ static int mtip_exec_internal_command(struct mtip_port *port, "Internal command already active\n"); return -EBUSY; } - port->internal_cmd_in_progress = 1; + set_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags); if (atomic == GFP_KERNEL) { /* wait for io to complete if non atomic */ @@ -1108,7 +1104,8 @@ static int mtip_exec_internal_command(struct mtip_port *port, dev_warn(&port->dd->pdev->dev, "Failed to quiesce IO\n"); release_slot(port, MTIP_TAG_INTERNAL); - port->internal_cmd_in_progress = 0; + clear_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags); + wake_up_interruptible(&port->svc_wait); return -EBUSY; } @@ -1123,19 +1120,23 @@ static int mtip_exec_internal_command(struct mtip_port *port, } /* Copy the command to the command table */ - memcpy(int_cmd->command, fis, fisLen*4); + memcpy(int_cmd->command, fis, fis_len*4); /* Populate the SG list */ int_cmd->command_header->opts = - cpu_to_le32(opts | fisLen); - if (bufLen) { + __force_bit2int cpu_to_le32(opts | fis_len); + if (buf_len) { command_sg = int_cmd->command + AHCI_CMD_TBL_HDR_SZ; - command_sg->info = cpu_to_le32((bufLen-1) & 0x3fffff); - command_sg->dba = cpu_to_le32(buffer & 0xffffffff); - command_sg->dba_upper = cpu_to_le32((buffer >> 16) >> 16); + command_sg->info = + __force_bit2int cpu_to_le32((buf_len-1) & 0x3FFFFF); + command_sg->dba = + __force_bit2int cpu_to_le32(buffer & 0xFFFFFFFF); + command_sg->dba_upper = + __force_bit2int cpu_to_le32((buffer >> 16) >> 16); - int_cmd->command_header->opts |= cpu_to_le32((1 << 16)); + int_cmd->command_header->opts |= + __force_bit2int cpu_to_le32((1 << 16)); } /* Populate the command header */ @@ -1151,8 +1152,9 @@ static int mtip_exec_internal_command(struct mtip_port *port, &wait, msecs_to_jiffies(timeout)) == 0) { dev_err(&port->dd->pdev->dev, - "Internal command did not complete [%d]\n", - atomic); + "Internal command did not complete [%d] " + "within timeout of %lu ms\n", + atomic, timeout); rv = -EAGAIN; } @@ -1184,7 +1186,8 @@ static int mtip_exec_internal_command(struct mtip_port *port, /* Clear the allocated and active bits for the internal command. */ atomic_set(&int_cmd->active, 0); release_slot(port, MTIP_TAG_INTERNAL); - port->internal_cmd_in_progress = 0; + clear_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags); + wake_up_interruptible(&port->svc_wait); return rv; } @@ -1233,8 +1236,6 @@ static int mtip_get_identify(struct mtip_port *port, void __user *user_buffer) int rv = 0; struct host_to_dev_fis fis; - down_write(&port->dd->internal_sem); - /* Build the FIS. */ memset(&fis, 0, sizeof(struct host_to_dev_fis)); fis.type = 0x27; @@ -1292,7 +1293,6 @@ static int mtip_get_identify(struct mtip_port *port, void __user *user_buffer) } out: - up_write(&port->dd->internal_sem); return rv; } @@ -1310,8 +1310,6 @@ static int mtip_standby_immediate(struct mtip_port *port) int rv; struct host_to_dev_fis fis; - down_write(&port->dd->internal_sem); - /* Build the FIS. */ memset(&fis, 0, sizeof(struct host_to_dev_fis)); fis.type = 0x27; @@ -1328,8 +1326,6 @@ static int mtip_standby_immediate(struct mtip_port *port) GFP_KERNEL, 15000); - up_write(&port->dd->internal_sem); - return rv; } @@ -1430,7 +1426,7 @@ static void mtip_dump_identify(struct mtip_port *port) ((u64)sectors) * ATA_SECT_SIZE >> 20); pci_read_config_word(port->dd->pdev, PCI_REVISION_ID, &revid); - switch (revid & 0xff) { + switch (revid & 0xFF) { case 0x1: strlcpy(cbuf, "A0", 3); break; @@ -1470,15 +1466,12 @@ static inline void fill_command_sg(struct driver_data *dd, if (dma_len > 0x400000) dev_err(&dd->pdev->dev, "DMA segment length truncated\n"); - command_sg->info = cpu_to_le32((dma_len-1) & 0x3fffff); -#if (BITS_PER_LONG == 64) - *((unsigned long *) &command_sg->dba) = - cpu_to_le64(sg_dma_address(sg)); -#else - command_sg->dba = cpu_to_le32(sg_dma_address(sg)); - command_sg->dba_upper = - cpu_to_le32((sg_dma_address(sg) >> 16) >> 16); -#endif + command_sg->info = __force_bit2int + cpu_to_le32((dma_len-1) & 0x3FFFFF); + command_sg->dba = __force_bit2int + cpu_to_le32(sg_dma_address(sg)); + command_sg->dba_upper = __force_bit2int + cpu_to_le32((sg_dma_address(sg) >> 16) >> 16); command_sg++; sg++; } @@ -1495,9 +1488,6 @@ static int exec_drive_task(struct mtip_port *port, u8 *command) struct host_to_dev_fis fis; struct host_to_dev_fis *reply = (port->rxfis + RX_FIS_D2H_REG); - /* Lock the internal command semaphore. */ - down_write(&port->dd->internal_sem); - /* Build the FIS. */ memset(&fis, 0, sizeof(struct host_to_dev_fis)); fis.type = 0x27; @@ -1532,7 +1522,6 @@ static int exec_drive_task(struct mtip_port *port, u8 *command) 0, GFP_KERNEL, MTIP_IOCTL_COMMAND_TIMEOUT_MS) < 0) { - up_write(&port->dd->internal_sem); return -1; } @@ -1549,7 +1538,6 @@ static int exec_drive_task(struct mtip_port *port, u8 *command) command[4], command[5]); - up_write(&port->dd->internal_sem); return 0; } @@ -1572,9 +1560,6 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, struct host_to_dev_fis fis; struct host_to_dev_fis *reply = (port->rxfis + RX_FIS_D2H_REG); - /* Lock the internal command semaphore. */ - down_write(&port->dd->internal_sem); - /* Build the FIS. */ memset(&fis, 0, sizeof(struct host_to_dev_fis)); fis.type = 0x27; @@ -1584,8 +1569,8 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, fis.sect_count = command[3]; if (fis.command == ATA_CMD_SMART) { fis.sector = command[1]; - fis.cyl_low = 0x4f; - fis.cyl_hi = 0xc2; + fis.cyl_low = 0x4F; + fis.cyl_hi = 0xC2; } dbg_printk(MTIP_DRV_NAME @@ -1609,7 +1594,6 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, GFP_KERNEL, MTIP_IOCTL_COMMAND_TIMEOUT_MS) < 0) { - up_write(&port->dd->internal_sem); return -1; } @@ -1630,12 +1614,10 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, if (copy_to_user(user_buffer, port->sector_buffer, ATA_SECT_SIZE * command[3])) { - up_write(&port->dd->internal_sem); return -EFAULT; } } - up_write(&port->dd->internal_sem); return 0; } @@ -1658,26 +1640,28 @@ static unsigned int implicit_sector(unsigned char command, /* list of commands that have an implicit sector count of 1 */ switch (command) { - case 0xF1: - case 0xF2: - case 0xF3: - case 0xF4: - case 0xF5: - case 0xF6: - case 0xE4: - case 0xE8: + case ATA_CMD_SEC_SET_PASS: + case ATA_CMD_SEC_UNLOCK: + case ATA_CMD_SEC_ERASE_PREP: + case ATA_CMD_SEC_ERASE_UNIT: + case ATA_CMD_SEC_FREEZE_LOCK: + case ATA_CMD_SEC_DISABLE_PASS: + case ATA_CMD_PMP_READ: + case ATA_CMD_PMP_WRITE: rv = 1; break; - case 0xF9: - if (features == 0x03) + case ATA_CMD_SET_MAX: + if (features == ATA_SET_MAX_UNLOCK) rv = 1; break; - case 0xB0: - if ((features == 0xD0) || (features == 0xD1)) + case ATA_CMD_SMART: + if ((features == ATA_SMART_READ_VALUES) || + (features == ATA_SMART_READ_THRESHOLDS)) rv = 1; break; - case 0xB1: - if ((features == 0xC2) || (features == 0xC3)) + case ATA_CMD_CONF_OVERLAY: + if ((features == ATA_DCO_IDENTIFY) || + (features == ATA_DCO_SET)) rv = 1; break; } @@ -1777,9 +1761,6 @@ static int exec_drive_taskfile(struct driver_data *dd, goto abort; } - /* Lock the internal command semaphore. */ - down_write(&dd->internal_sem); - /* Build the FIS. */ memset(&fis, 0, sizeof(struct host_to_dev_fis)); @@ -1818,7 +1799,6 @@ static int exec_drive_taskfile(struct driver_data *dd, dev_warn(&dd->pdev->dev, "data movement but " "sect_count is 0\n"); - up_write(&dd->internal_sem); err = -EINVAL; goto abort; } @@ -1838,19 +1818,25 @@ static int exec_drive_taskfile(struct driver_data *dd, fis.device); switch (fis.command) { - case 0x92: /* Change timeout for Download Microcode to 60 seconds.*/ + case ATA_CMD_DOWNLOAD_MICRO: + /* Change timeout for Download Microcode to 60 seconds.*/ timeout = 60000; break; - case 0xf4: /* Change timeout for Security Erase Unit to 4 minutes.*/ + case ATA_CMD_SEC_ERASE_UNIT: + /* Change timeout for Security Erase Unit to 4 minutes.*/ timeout = 240000; break; - case 0xe0: /* Change timeout for standby immediate to 10 seconds.*/ + case ATA_CMD_STANDBYNOW1: + /* Change timeout for standby immediate to 10 seconds.*/ timeout = 10000; break; - case 0xf7: /* Change timeout for vendor unique command to 10 secs */ + case 0xF7: + case 0xFA: + /* Change timeout for vendor unique command to 10 secs */ timeout = 10000; break; - case 0xfa: /* Change timeout for vendor unique command to 10 secs */ + case ATA_CMD_SMART: + /* Change timeout for vendor unique command to 10 secs */ timeout = 10000; break; default: @@ -1873,7 +1859,6 @@ static int exec_drive_taskfile(struct driver_data *dd, 0, GFP_KERNEL, timeout) < 0) { - up_write(&dd->internal_sem); err = -EIO; goto abort; } @@ -1916,7 +1901,7 @@ static int exec_drive_taskfile(struct driver_data *dd, } /* Com rest after secure erase or lowlevel format */ - if (((fis.command == 0xF4) || + if (((fis.command == ATA_CMD_SEC_ERASE_UNIT) || ((fis.command == 0xFC) && (fis.features == 0x27 || fis.features == 0x72 || fis.features == 0x62 || fis.features == 0x26))) && @@ -1937,8 +1922,6 @@ static int exec_drive_taskfile(struct driver_data *dd, req_task->io_ports[5], req_task->io_ports[6]); - up_write(&dd->internal_sem); - if (taskout) { if (copy_to_user(buf + outtotal, outbuf, taskout)) { err = -EFAULT; @@ -2052,7 +2035,8 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd, ret = exec_drive_taskfile(dd, (void __user *) arg, &req_task, outtotal); - if (copy_to_user((void __user *) arg, &req_task, sizeof(req_task))) + if (copy_to_user((void __user *) arg, &req_task, + sizeof(req_task))) return -EFAULT; return ret; @@ -2117,13 +2101,13 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, fis->opts = 1 << 7; fis->command = (dir == READ ? ATA_CMD_FPDMA_READ : ATA_CMD_FPDMA_WRITE); - *((unsigned int *) &fis->lba_low) = (start & 0xffffff); - *((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xffffff); + *((unsigned int *) &fis->lba_low) = (start & 0xFFFFFF); + *((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xFFFFFF); fis->device = 1 << 6; if (barrier) fis->device |= FUA_BIT; - fis->features = nsect & 0xff; - fis->features_ex = (nsect >> 8) & 0xff; + fis->features = nsect & 0xFF; + fis->features_ex = (nsect >> 8) & 0xFF; fis->sect_count = ((tag << 3) | (tag >> 5)); fis->sect_cnt_ex = 0; fis->control = 0; @@ -2132,8 +2116,9 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, fill_command_sg(dd, command, nents); /* Populate the command header */ - command->command_header->opts = cpu_to_le32( - (nents << 16) | 5 | AHCI_CMD_PREFETCH); + command->command_header->opts = + __force_bit2int cpu_to_le32( + (nents << 16) | 5 | AHCI_CMD_PREFETCH); command->command_header->byte_count = 0; /* @@ -2152,10 +2137,15 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, command->async_callback = callback; /* - * Lock used to prevent this command from being issued - * if an internal command is in progress. + * To prevent this command from being issued + * if an internal command is in progress or error handling is active. */ - down_read(&port->dd->internal_sem); + if (unlikely(test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) || + test_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags))) { + set_bit(tag, port->cmds_to_issue); + set_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags); + return; + } /* Issue the command to the hardware */ mtip_issue_ncq_command(port, tag); @@ -2163,8 +2153,6 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, /* Set the command's timeout value.*/ port->commands[tag].comp_time = jiffies + msecs_to_jiffies( MTIP_NCQ_COMMAND_TIMEOUT_MS); - - up_read(&port->dd->internal_sem); } /* @@ -2400,10 +2388,9 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd) timeout = jiffies + msecs_to_jiffies(MTIP_FTL_REBUILD_TIMEOUT_MS); do { -#ifdef CONFIG_HOTPLUG if (mtip_check_surprise_removal(dd->pdev)) return -EFAULT; -#endif + if (mtip_get_identify(dd->port, NULL) < 0) return -EFAULT; @@ -2439,6 +2426,74 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd) } /* + * service thread to issue queued commands + * + * @data Pointer to the driver data structure. + * + * return value + * 0 + */ + +static int mtip_service_thread(void *data) +{ + struct driver_data *dd = (struct driver_data *)data; + unsigned long slot, slot_start, slot_wrap; + unsigned int num_cmd_slots = dd->slot_groups * 32; + struct mtip_port *port = dd->port; + + while (1) { + /* + * the condition is to check neither an internal command is + * is in progress nor error handling is active + */ + wait_event_interruptible(port->svc_wait, (port->flags) && + !test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) && + !test_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags)); + + if (kthread_should_stop()) + break; + + if (test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) { + set_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags); + slot = 1; + /* used to restrict the loop to one iteration */ + slot_start = num_cmd_slots; + slot_wrap = 0; + while (1) { + slot = find_next_bit(port->cmds_to_issue, + num_cmd_slots, slot); + if (slot_wrap == 1) { + if ((slot_start >= slot) || + (slot >= num_cmd_slots)) + break; + } + if (unlikely(slot_start == num_cmd_slots)) + slot_start = slot; + + if (unlikely(slot == num_cmd_slots)) { + slot = 1; + slot_wrap = 1; + continue; + } + + /* Issue the command to the hardware */ + mtip_issue_ncq_command(port, slot); + + /* Set the command's timeout value.*/ + port->commands[slot].comp_time = jiffies + + msecs_to_jiffies(MTIP_NCQ_COMMAND_TIMEOUT_MS); + + clear_bit(slot, port->cmds_to_issue); + } + + clear_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags); + clear_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags); + } + } + return 0; +} + +/* * Called once for each card. * * @dd Pointer to the driver data structure. @@ -2463,13 +2518,6 @@ static int mtip_hw_init(struct driver_data *dd) hba_setup(dd); - /* - * Initialize the internal semaphore - * Use a rw semaphore to enable prioritization of - * mgmnt ioctl traffic during heavy IO load - */ - init_rwsem(&dd->internal_sem); - tasklet_init(&dd->tasklet, mtip_tasklet, (unsigned long)dd); dd->port = kzalloc(sizeof(struct mtip_port), GFP_KERNEL); @@ -2541,10 +2589,11 @@ static int mtip_hw_init(struct driver_data *dd) if (readl(dd->mmio + HOST_CAP) & HOST_CAP_64) dd->port->commands[i].command_header->ctbau = - cpu_to_le32( + __force_bit2int cpu_to_le32( (dd->port->commands[i].command_dma >> 16) >> 16); - dd->port->commands[i].command_header->ctba = cpu_to_le32( - dd->port->commands[i].command_dma & 0xffffffff); + dd->port->commands[i].command_header->ctba = + __force_bit2int cpu_to_le32( + dd->port->commands[i].command_dma & 0xFFFFFFFF); /* * If this is not done, a bug is reported by the stock @@ -2597,6 +2646,8 @@ static int mtip_hw_init(struct driver_data *dd) dd->mmio + HOST_CTL); init_timer(&dd->port->cmd_timer); + init_waitqueue_head(&dd->port->svc_wait); + dd->port->cmd_timer.data = (unsigned long int) dd->port; dd->port->cmd_timer.function = mtip_timeout_function; mod_timer(&dd->port->cmd_timer, @@ -2667,12 +2718,12 @@ static int mtip_hw_exit(struct driver_data *dd) del_timer_sync(&dd->port->cmd_timer); - /* Stop the bottom half tasklet. */ - tasklet_kill(&dd->tasklet); - /* Release the IRQ. */ devm_free_irq(&dd->pdev->dev, dd->pdev->irq, dd); + /* Stop the bottom half tasklet. */ + tasklet_kill(&dd->tasklet); + /* Free the command/command header memory. */ dmam_free_coherent(&dd->pdev->dev, HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2), @@ -2835,7 +2886,7 @@ static int mtip_block_ioctl(struct block_device *dev, switch (cmd) { case BLKFLSBUF: - return 0; + return -ENOTTY; default: return mtip_hw_ioctl(dd, cmd, arg); } @@ -2870,19 +2921,20 @@ static int mtip_block_compat_ioctl(struct block_device *dev, switch (cmd) { case BLKFLSBUF: - return 0; + return -ENOTTY; case HDIO_DRIVE_TASKFILE: { - struct mtip_compat_ide_task_request_s *compat_req_task; + struct mtip_compat_ide_task_request_s __user *compat_req_task; ide_task_request_t req_task; int compat_tasksize, outtotal, ret; - compat_tasksize = sizeof(struct mtip_compat_ide_task_request_s); + compat_tasksize = + sizeof(struct mtip_compat_ide_task_request_s); compat_req_task = (struct mtip_compat_ide_task_request_s __user *) arg; if (copy_from_user(&req_task, (void __user *) arg, - compat_tasksize - (2 * sizeof(compat_long_t)))) + compat_tasksize - (2 * sizeof(compat_long_t)))) return -EFAULT; if (get_user(req_task.out_size, &compat_req_task->out_size)) @@ -2950,12 +3002,8 @@ static int mtip_block_getgeo(struct block_device *dev, geo->heads = 224; geo->sectors = 56; -#if BITS_PER_LONG == 64 - geo->cylinders = capacity / (geo->heads * geo->sectors); -#else - do_div(capacity, (geo->heads * geo->sectors)); + sector_div(capacity, (geo->heads * geo->sectors)); geo->cylinders = capacity; -#endif return 0; } @@ -2999,11 +3047,6 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio) return; } - if (unlikely(atomic_read(&dd->eh_active))) { - bio_endio(bio, -EBUSY); - return; - } - sg = mtip_hw_get_scatterlist(dd, &tag); if (likely(sg != NULL)) { blk_queue_bounce(queue, &bio); @@ -3032,7 +3075,7 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio) tag, bio_endio, bio, - bio->bi_rw & REQ_FLUSH, + bio->bi_rw & REQ_FUA, bio_data_dir(bio)); } else bio_io_error(bio); @@ -3055,6 +3098,7 @@ static int mtip_block_initialize(struct driver_data *dd) sector_t capacity; unsigned int index = 0; struct kobject *kobj; + unsigned char thd_name[16]; /* Initialize the protocol layer. */ rv = mtip_hw_init(dd); @@ -3082,6 +3126,7 @@ static int mtip_block_initialize(struct driver_data *dd) blk_queue_max_segments(dd->queue, MTIP_MAX_SG); blk_queue_physical_block_size(dd->queue, 4096); blk_queue_io_min(dd->queue, 4096); + blk_queue_flush(dd->queue, 0); dd->disk = alloc_disk(MTIP_MAX_MINORS); if (dd->disk == NULL) { @@ -3142,6 +3187,18 @@ static int mtip_block_initialize(struct driver_data *dd) kobject_put(kobj); } + sprintf(thd_name, "mtip_svc_thd_%02d", index); + + dd->mtip_svc_handler = kthread_run(mtip_service_thread, + dd, thd_name); + + if (IS_ERR(dd->mtip_svc_handler)) { + printk(KERN_ERR "mtip32xx: service thread failed to start\n"); + dd->mtip_svc_handler = NULL; + rv = -EFAULT; + goto read_capacity_error; + } + return rv; read_capacity_error: @@ -3183,6 +3240,13 @@ protocol_init_error: static int mtip_block_remove(struct driver_data *dd) { struct kobject *kobj; + + if (dd->mtip_svc_handler) { + set_bit(MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT, &dd->port->flags); + wake_up_interruptible(&dd->port->svc_wait); + kthread_stop(dd->mtip_svc_handler); + } + /* Clean up the sysfs attributes managed by the protocol layer. */ kobj = kobject_get(&disk_to_dev(dd->disk)->kobj); if (kobj) { @@ -3275,7 +3339,6 @@ static int mtip_pci_probe(struct pci_dev *pdev, atomic_set(&dd->drv_cleanup_done, true); atomic_set(&dd->resumeflag, false); - atomic_set(&dd->eh_active, 0); /* Attach the private data to this PCI device. */ pci_set_drvdata(pdev, dd); @@ -3317,7 +3380,6 @@ static int mtip_pci_probe(struct pci_dev *pdev, /* Copy the info we may need later into the private data structure. */ dd->major = mtip_major; - dd->protocol = ent->driver_data; dd->instance = instance; dd->pdev = pdev; diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index 17be4f4..933192a 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h @@ -47,11 +47,11 @@ /* ftl rebuild */ #define MTIP_FTL_REBUILD_OFFSET 142 -#define MTIP_FTL_REBUILD_MAGIC 0xed51 +#define MTIP_FTL_REBUILD_MAGIC 0xED51 #define MTIP_FTL_REBUILD_TIMEOUT_MS 2400000 /* Macro to extract the tag bit number from a tag value. */ -#define MTIP_TAG_BIT(tag) (tag & 0x1f) +#define MTIP_TAG_BIT(tag) (tag & 0x1F) /* * Macro to extract the tag index from a tag value. The index @@ -81,7 +81,7 @@ /* Driver name and version strings */ #define MTIP_DRV_NAME "mtip32xx" -#define MTIP_DRV_VERSION "1.2.6os2" +#define MTIP_DRV_VERSION "1.2.6os3" /* Maximum number of minor device numbers per device. */ #define MTIP_MAX_MINORS 16 @@ -114,6 +114,15 @@ #define dbg_printk(format, arg...) #endif +#define __force_bit2int (unsigned int __force) + +/* below are bit numbers in 'flags' defined in mtip_port */ +#define MTIP_FLAG_IC_ACTIVE_BIT 0 +#define MTIP_FLAG_EH_ACTIVE_BIT 1 +#define MTIP_FLAG_SVC_THD_ACTIVE_BIT 2 +#define MTIP_FLAG_ISSUE_CMDS_BIT 4 +#define MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT 8 + /* Register Frame Information Structure (FIS), host to device. */ struct host_to_dev_fis { /* @@ -262,7 +271,7 @@ struct mtip_cmd { unsigned long comp_time; /* command completion time, in jiffies */ - atomic_t active; /* declares if this command sent to the drive. */ + atomic_t active; /* declares if this command sent to the drive. */ }; /* Structure used to describe a port. */ @@ -278,7 +287,7 @@ struct mtip_port { void __iomem *mmio; /* Array of pointers to the memory mapped s_active registers. */ void __iomem *s_active[MTIP_MAX_SLOT_GROUPS]; - /* Array of pointers to the memory mapped completed registers. */ + /* Array of pointers to the memory mapped completed registers. */ void __iomem *completed[MTIP_MAX_SLOT_GROUPS]; /* Array of pointers to the memory mapped Command Issue registers. */ void __iomem *cmd_issue[MTIP_MAX_SLOT_GROUPS]; @@ -340,13 +349,23 @@ struct mtip_port { */ unsigned long allocated[SLOTBITS_IN_LONGS]; /* + * used to queue commands when an internal command is in progress + * or error handling is active + */ + unsigned long cmds_to_issue[SLOTBITS_IN_LONGS]; + /* * Array of command slots. Structure includes pointers to the * command header and command table, and completion function and data * pointers. */ struct mtip_cmd commands[MTIP_MAX_COMMAND_SLOTS]; - /* Non-zero if an internal command is in progress. */ - int internal_cmd_in_progress; + /* Used by mtip_service_thread to wait for an event */ + wait_queue_head_t svc_wait; + /* + * indicates the state of the port. Also, helps the service thread + * to determine its action on wake up. + */ + unsigned long flags; /* * Timer used to complete commands that have been active for too long. */ @@ -372,18 +391,11 @@ struct driver_data { int instance; /* Instance number. First device probed is 0, ... */ - int protocol; /* FIXME: Protocol ops array index. */ - struct gendisk *disk; /* Pointer to our gendisk structure. */ struct pci_dev *pdev; /* Pointer to the PCI device structure. */ struct request_queue *queue; /* Our request queue. */ - /* - * Semaphore used to lock out read/write commands during the - * execution of an internal command. - */ - struct rw_semaphore internal_sem; struct mtip_port *port; /* Pointer to the port data structure. */ @@ -403,6 +415,8 @@ struct driver_data { atomic_t resumeflag; /* Atomic variable to track suspend/resume */ atomic_t eh_active; /* Flag for error handling tracking */ + + struct task_struct *mtip_svc_handler; /* task_struct of svc thd */ }; #endif -- cgit v0.10.2 From 0e7a22de25212cfcaa0ba2c957e4e60eaa70fb9d Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 21 Nov 2011 20:39:33 -0500 Subject: ktest: When creating new config, allow the use of ${THIS_DIR} Typing in a full path when you know that the path exists within the directory your are running is tedious and unnecessary. Allow the user to use ${PWD} if they want a dynamic path name which will be the path that ktest.pl is executed from or use ${THIS_DIR} which is a variable assigned `pwd` and the the variable will exist within the config, allowing the user to change it and affect all other paths using this variable as well Signed-off-by: Steven Rostedt diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 05f429d..77b4649 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -158,11 +158,15 @@ EOF ; $config_help{"BUILD_DIR"} = << "EOF" The directory that contains the Linux source code (full path). + You can use \${PWD} that will be the path where ktest.pl is run, or use + \${THIS_DIR} which is assigned \${PWD} but may be changed later. EOF ; $config_help{"OUTPUT_DIR"} = << "EOF" The directory that the objects will be built (full path). (can not be same as BUILD_DIR) + You can use \${PWD} that will be the path where ktest.pl is run, or use + \${THIS_DIR} which is assigned \${PWD} but may be changed later. EOF ; $config_help{"BUILD_TARGET"} = << "EOF" @@ -282,7 +286,7 @@ sub get_ktest_config { next; } } - $entered_configs{$config} = process_variables($ans); + $entered_configs{$config} = ${ans}; last; } } @@ -3012,6 +3016,17 @@ if (! -f $ktest_config) { print OUT << "EOF" # Generated by ktest.pl # + +# PWD is a ktest.pl variable that will result in the process working +# directory that ktest.pl is executed in. + +# THIS_DIR is automatically assigned the PWD of the path that generated +# the config file. It is best to use this variable when assigning other +# directory paths within this directory. This allows you to easily +# move the test cases to other locations or to other machines. +# +THIS_DIR := $variable{"PWD"} + # Define each test with TEST_START # The config options below it will override the defaults TEST_START @@ -3034,7 +3049,7 @@ if ($#new_configs >= 0) { open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config"; foreach my $config (@new_configs) { print OUT "$config = $entered_configs{$config}\n"; - $opt{$config} = $entered_configs{$config}; + $opt{$config} = process_variables($entered_configs{$config}); } } -- cgit v0.10.2 From 39cac3758f62c6495d954e0d7dc1ca7e69fa565d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 23 Nov 2011 12:03:32 -0300 Subject: [media] ir-nec-decoder: Report what bit failed at debug msg Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c index 63ee722..a825318 100644 --- a/drivers/media/rc/ir-nec-decoder.c +++ b/drivers/media/rc/ir-nec-decoder.c @@ -193,8 +193,8 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) return 0; } - IR_dprintk(1, "NEC decode failed at state %d (%uus %s)\n", - data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + IR_dprintk(1, "NEC decode failed at count %d state %d (%uus %s)\n", + data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse)); data->state = STATE_INACTIVE; return -EINVAL; } -- cgit v0.10.2 From b32e724308300a6ecead0f4895f0452a06a4291d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 23 Nov 2011 12:04:08 -0300 Subject: [media] rc: Add support for decoding Sanyo protocol This protocol is found on Sanyo/Aiwa remotes. Tested with an Aiwa RC-7AS06 remote control. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index aeb7f43..4df4aff 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -87,6 +87,16 @@ config IR_RC5_SZ_DECODER uses an IR protocol that is almost standard RC-5, but not quite, as it uses an additional bit). +config IR_SANYO_DECODER + tristate "Enable IR raw decoder for the Sanyo protocol" + depends on RC_CORE + default y + + ---help--- + Enable this option if you have an infrared remote control which + uses the Sanyo protocol (Sanyo, Aiwa, Chinon remotes), + and you need software decoding support. + config IR_MCE_KBD_DECODER tristate "Enable IR raw decoder for the MCE keyboard/mouse protocol" depends on RC_CORE diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 2156e78..fb3dee2 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o +obj-$(CONFIG_IR_SANYO_DECODER) += ir-sanyo-decoder.o obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c index 27808bb5..9e841f4 100644 --- a/drivers/media/rc/ir-raw.c +++ b/drivers/media/rc/ir-raw.c @@ -355,6 +355,7 @@ static void init_decoders(struct work_struct *work) load_rc6_decode(); load_jvc_decode(); load_sony_decode(); + load_sanyo_decode(); load_mce_kbd_decode(); load_lirc_codec(); diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c new file mode 100644 index 0000000..1646730 --- /dev/null +++ b/drivers/media/rc/ir-sanyo-decoder.c @@ -0,0 +1,204 @@ +/* ir-sanyo-decoder.c - handle SANYO IR Pulse/Space protocol + * + * Copyright (C) 2011 by Mauro Carvalho Chehab + * + * 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 version 2 of the License. + * + * 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. + * + * This protocol uses the NEC protocol timings. However, data is formatted as: + * 13 bits Custom Code + * 13 bits NOT(Custom Code) + * 8 bits Key data + * 8 bits NOT(Key data) + * + * According with LIRC, this protocol is used on Sanyo, Aiwa and Chinon + * Information for this protocol is available at the Sanyo LC7461 datasheet. + */ + +#include +#include "rc-core-priv.h" + +#define SANYO_NBITS (13+13+8+8) +#define SANYO_UNIT 562500 /* ns */ +#define SANYO_HEADER_PULSE (16 * SANYO_UNIT) +#define SANYO_HEADER_SPACE (8 * SANYO_UNIT) +#define SANYO_BIT_PULSE (1 * SANYO_UNIT) +#define SANYO_BIT_0_SPACE (1 * SANYO_UNIT) +#define SANYO_BIT_1_SPACE (3 * SANYO_UNIT) +#define SANYO_REPEAT_SPACE (150 * SANYO_UNIT) +#define SANYO_TRAILER_PULSE (1 * SANYO_UNIT) +#define SANYO_TRAILER_SPACE (10 * SANYO_UNIT) /* in fact, 42 */ + +enum sanyo_state { + STATE_INACTIVE, + STATE_HEADER_SPACE, + STATE_BIT_PULSE, + STATE_BIT_SPACE, + STATE_TRAILER_PULSE, + STATE_TRAILER_SPACE, +}; + +/** + * ir_sanyo_decode() - Decode one SANYO pulse or space + * @dev: the struct rc_dev descriptor of the device + * @duration: the struct ir_raw_event descriptor of the pulse/space + * + * This function returns -EINVAL if the pulse violates the state machine + */ +static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev) +{ + struct sanyo_dec *data = &dev->raw->sanyo; + u32 scancode; + u8 address, not_address, command, not_command; + + if (!(dev->raw->enabled_protocols & RC_TYPE_SANYO)) + return 0; + + if (!is_timing_event(ev)) { + if (ev.reset) { + IR_dprintk(1, "SANYO event reset received. reset to state 0\n"); + data->state = STATE_INACTIVE; + } + return 0; + } + + IR_dprintk(2, "SANYO decode started at state %d (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + + switch (data->state) { + + case STATE_INACTIVE: + if (!ev.pulse) + break; + + if (eq_margin(ev.duration, SANYO_HEADER_PULSE, SANYO_UNIT / 2)) { + data->count = 0; + data->state = STATE_HEADER_SPACE; + return 0; + } + break; + + + case STATE_HEADER_SPACE: + if (ev.pulse) + break; + + if (eq_margin(ev.duration, SANYO_HEADER_SPACE, SANYO_UNIT / 2)) { + data->state = STATE_BIT_PULSE; + return 0; + } + + break; + + case STATE_BIT_PULSE: + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, SANYO_BIT_PULSE, SANYO_UNIT / 2)) + break; + + data->state = STATE_BIT_SPACE; + return 0; + + case STATE_BIT_SPACE: + if (ev.pulse) + break; + + if (!data->count && geq_margin(ev.duration, SANYO_REPEAT_SPACE, SANYO_UNIT / 2)) { + if (!dev->keypressed) { + IR_dprintk(1, "SANYO discarding last key repeat: event after key up\n"); + } else { + rc_repeat(dev); + IR_dprintk(1, "SANYO repeat last key\n"); + data->state = STATE_INACTIVE; + } + return 0; + } + + data->bits <<= 1; + if (eq_margin(ev.duration, SANYO_BIT_1_SPACE, SANYO_UNIT / 2)) + data->bits |= 1; + else if (!eq_margin(ev.duration, SANYO_BIT_0_SPACE, SANYO_UNIT / 2)) + break; + data->count++; + + if (data->count == SANYO_NBITS) + data->state = STATE_TRAILER_PULSE; + else + data->state = STATE_BIT_PULSE; + + return 0; + + case STATE_TRAILER_PULSE: + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, SANYO_TRAILER_PULSE, SANYO_UNIT / 2)) + break; + + data->state = STATE_TRAILER_SPACE; + return 0; + + case STATE_TRAILER_SPACE: + if (ev.pulse) + break; + + if (!geq_margin(ev.duration, SANYO_TRAILER_SPACE, SANYO_UNIT / 2)) + break; + + address = bitrev16((data->bits >> 29) & 0x1fff) >> 3; + not_address = bitrev16((data->bits >> 16) & 0x1fff) >> 3; + command = bitrev8((data->bits >> 8) & 0xff); + not_command = bitrev8((data->bits >> 0) & 0xff); + + if ((command ^ not_command) != 0xff) { + IR_dprintk(1, "SANYO checksum error: received 0x%08Lx\n", + data->bits); + data->state = STATE_INACTIVE; + return 0; + } + + scancode = address << 8 | command; + IR_dprintk(1, "SANYO scancode: 0x%06x\n", scancode); + rc_keydown(dev, scancode, 0); + data->state = STATE_INACTIVE; + return 0; + } + + IR_dprintk(1, "SANYO decode failed at count %d state %d (%uus %s)\n", + data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + data->state = STATE_INACTIVE; + return -EINVAL; +} + +static struct ir_raw_handler sanyo_handler = { + .protocols = RC_TYPE_SANYO, + .decode = ir_sanyo_decode, +}; + +static int __init ir_sanyo_decode_init(void) +{ + ir_raw_handler_register(&sanyo_handler); + + printk(KERN_INFO "IR SANYO protocol handler initialized\n"); + return 0; +} + +static void __exit ir_sanyo_decode_exit(void) +{ + ir_raw_handler_unregister(&sanyo_handler); +} + +module_init(ir_sanyo_decode_init); +module_exit(ir_sanyo_decode_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); +MODULE_DESCRIPTION("SANYO IR protocol decoder"); diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index c6ca870..b72f858 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -84,6 +84,11 @@ struct ir_raw_event_ctrl { unsigned count; unsigned wanted_bits; } rc5_sz; + struct sanyo_dec { + int state; + unsigned count; + u64 bits; + } sanyo; struct mce_kbd_dec { struct input_dev *idev; struct timer_list rx_timeout; @@ -193,6 +198,13 @@ static inline void load_jvc_decode(void) { } static inline void load_sony_decode(void) { } #endif +/* from ir-sanyo-decoder.c */ +#ifdef CONFIG_IR_SANYO_DECODER_MODULE +#define load_sanyo_decode() request_module("ir-sanyo-decoder") +#else +static inline void load_sanyo_decode(void) { } +#endif + /* from ir-mce_kbd-decoder.c */ #ifdef CONFIG_IR_MCE_KBD_DECODER_MODULE #define load_mce_kbd_decode() request_module("ir-mce_kbd-decoder") diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 666d4bb..35e2fcf0 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -735,6 +735,7 @@ static struct { { RC_TYPE_JVC, "jvc" }, { RC_TYPE_SONY, "sony" }, { RC_TYPE_RC5_SZ, "rc-5-sz" }, + { RC_TYPE_SANYO, "sanyo" }, { RC_TYPE_MCE_KBD, "mce_kbd" }, { RC_TYPE_LIRC, "lirc" }, { RC_TYPE_OTHER, "other" }, diff --git a/include/media/rc-map.h b/include/media/rc-map.h index 26a3bd0..183d701 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -18,13 +18,15 @@ #define RC_TYPE_JVC (1 << 3) /* JVC protocol */ #define RC_TYPE_SONY (1 << 4) /* Sony12/15/20 protocol */ #define RC_TYPE_RC5_SZ (1 << 5) /* RC5 variant used by Streamzap */ +#define RC_TYPE_SANYO (1 << 6) /* Sanyo protocol */ #define RC_TYPE_MCE_KBD (1 << 29) /* RC6-ish MCE keyboard/mouse */ #define RC_TYPE_LIRC (1 << 30) /* Pass raw IR to lirc userspace */ #define RC_TYPE_OTHER (1u << 31) -#define RC_TYPE_ALL (RC_TYPE_RC5 | RC_TYPE_NEC | RC_TYPE_RC6 | \ - RC_TYPE_JVC | RC_TYPE_SONY | RC_TYPE_LIRC | \ - RC_TYPE_RC5_SZ | RC_TYPE_MCE_KBD | RC_TYPE_OTHER) +#define RC_TYPE_ALL (RC_TYPE_RC5 | RC_TYPE_NEC | RC_TYPE_RC6 | \ + RC_TYPE_JVC | RC_TYPE_SONY | RC_TYPE_LIRC | \ + RC_TYPE_RC5_SZ | RC_TYPE_SANYO | RC_TYPE_MCE_KBD | \ + RC_TYPE_OTHER) struct rc_map_table { u32 scancode; -- cgit v0.10.2 From db9bc660cf4d1a09565f5db2bab9d3b86e3e32a5 Mon Sep 17 00:00:00 2001 From: lawrence rust Date: Mon, 31 Oct 2011 08:39:32 -0300 Subject: [media] ir-rc6-decoder: Support RC6-6A variable length data This patch to the IR RC6 decoder adds support for variable length mode-6A frames which can range in size from 8 to 128 bits. Please refer to the following link for a detailed explanation or RC6 frames: http://slydiman.narod.ru/scr/kb/rc6.htm This change removes the assumption that frames are fixed length (currently either 24 or 32 data bits) and actually counts the number of bits until an end of frame marker is seen. [mchehab@redhat.com: Tested with a RC-6(0) IR - 16 bits] Tested-by: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c index 140fb67..4cfdd7f 100644 --- a/drivers/media/rc/ir-rc6-decoder.c +++ b/drivers/media/rc/ir-rc6-decoder.c @@ -18,24 +18,31 @@ /* * This decoder currently supports: * RC6-0-16 (standard toggle bit in header) + * RC6-6A-20 (no toggle bit) * RC6-6A-24 (no toggle bit) * RC6-6A-32 (MCE version with toggle bit in body) */ -#define RC6_UNIT 444444 /* us */ +#define RC6_UNIT 444444 /* nanosecs */ #define RC6_HEADER_NBITS 4 /* not including toggle bit */ #define RC6_0_NBITS 16 -#define RC6_6A_SMALL_NBITS 24 -#define RC6_6A_LARGE_NBITS 32 +#define RC6_6A_32_NBITS 32 +#define RC6_6A_NBITS 128 /* Variable 8..128 */ #define RC6_PREFIX_PULSE (6 * RC6_UNIT) #define RC6_PREFIX_SPACE (2 * RC6_UNIT) #define RC6_BIT_START (1 * RC6_UNIT) #define RC6_BIT_END (1 * RC6_UNIT) #define RC6_TOGGLE_START (2 * RC6_UNIT) #define RC6_TOGGLE_END (2 * RC6_UNIT) +#define RC6_SUFFIX_SPACE (6 * RC6_UNIT) #define RC6_MODE_MASK 0x07 /* for the header bits */ #define RC6_STARTBIT_MASK 0x08 /* for the header bits */ #define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ +#define RC6_6A_LCC_MASK 0xffff0000 /* RC6-6A-32 long customer code mask */ +#define RC6_6A_MCE_CC 0x800f0000 /* MCE customer code */ +#ifndef CHAR_BIT +#define CHAR_BIT 8 /* Normally in */ +#endif enum rc6_mode { RC6_MODE_0, @@ -125,6 +132,7 @@ again: break; data->state = STATE_HEADER_BIT_START; + data->header = 0; return 0; case STATE_HEADER_BIT_START: @@ -171,20 +179,14 @@ again: data->state = STATE_BODY_BIT_START; decrease_duration(&ev, RC6_TOGGLE_END); data->count = 0; + data->body = 0; switch (rc6_mode(data)) { case RC6_MODE_0: data->wanted_bits = RC6_0_NBITS; break; case RC6_MODE_6A: - /* This might look weird, but we basically - check the value of the first body bit to - determine the number of bits in mode 6A */ - if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) || - geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) - data->wanted_bits = RC6_6A_LARGE_NBITS; - else - data->wanted_bits = RC6_6A_SMALL_NBITS; + data->wanted_bits = RC6_6A_NBITS; break; default: IR_dprintk(1, "RC6 unknown mode\n"); @@ -193,15 +195,21 @@ again: goto again; case STATE_BODY_BIT_START: - if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) - break; - - data->body <<= 1; - if (ev.pulse) - data->body |= 1; - data->count++; - data->state = STATE_BODY_BIT_END; - return 0; + if (eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) { + /* Discard LSB's that won't fit in data->body */ + if (data->count++ < CHAR_BIT * sizeof data->body) { + data->body <<= 1; + if (ev.pulse) + data->body |= 1; + } + data->state = STATE_BODY_BIT_END; + return 0; + } else if (RC6_MODE_6A == rc6_mode(data) && !ev.pulse && + geq_margin(ev.duration, RC6_SUFFIX_SPACE, RC6_UNIT / 2)) { + data->state = STATE_FINISHED; + goto again; + } + break; case STATE_BODY_BIT_END: if (!is_transition(&ev, &dev->raw->prev_ev)) @@ -221,20 +229,27 @@ again: switch (rc6_mode(data)) { case RC6_MODE_0: - scancode = data->body & 0xffff; + scancode = data->body; toggle = data->toggle; IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n", scancode, toggle); break; case RC6_MODE_6A: - if (data->wanted_bits == RC6_6A_LARGE_NBITS) { - toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0; - scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK; + if (data->count > CHAR_BIT * sizeof data->body) { + IR_dprintk(1, "RC6 too many (%u) data bits\n", + data->count); + goto out; + } + + scancode = data->body; + if (data->count == RC6_6A_32_NBITS && + (scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) { + /* MCE RC */ + toggle = (scancode & RC6_6A_MCE_TOGGLE_MASK) ? 1 : 0; + scancode &= ~RC6_6A_MCE_TOGGLE_MASK; } else { toggle = 0; - scancode = data->body & 0xffffff; } - IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n", scancode, toggle); break; -- cgit v0.10.2 From 3e54a3d1b83220d748f1a27c8999634be7a83949 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 24 Nov 2011 12:59:00 +0100 Subject: mtip32xx: uninitialized variable in mtip_quiesce_io() We recently introduce new continue in the loop which make gcc complain. In theory if MTIP_FLAG_SVC_THD_ACTIVE_BIT is set, we could hit continue over and over until eventually we time out of the loop. In that case "active" should be set as true, but right now it's uninitialized. Signed-off-by: Dan Carpenter Signed-off-by: Jens Axboe diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index b5d843a..9bc10e3 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -1026,7 +1026,8 @@ static void mtip_issue_non_ncq_command(struct mtip_port *port, int tag) static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout) { unsigned long to; - unsigned int n, active; + unsigned int n; + unsigned int active = 1; to = jiffies + msecs_to_jiffies(timeout); do { -- cgit v0.10.2 From e469183541ac108fbc9bcf8e73c2061f049be620 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 7 Nov 2011 14:44:12 -0300 Subject: [media] V4L: mt9t112: use after free in mt9t112_probe() priv gets dereferenced in mt9t112_set_params() so we should return before calling that. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/mt9t112.c b/drivers/media/video/mt9t112.c index 32114a3..7b34b11 100644 --- a/drivers/media/video/mt9t112.c +++ b/drivers/media/video/mt9t112.c @@ -1083,8 +1083,10 @@ static int mt9t112_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&priv->subdev, client, &mt9t112_subdev_ops); ret = mt9t112_camera_probe(client); - if (ret) + if (ret) { kfree(priv); + return ret; + } /* Cannot fail: using the default supported pixel code */ mt9t112_set_params(priv, &rect, V4L2_MBUS_FMT_UYVY8_2X8); -- cgit v0.10.2 From 2e962f4efa944d47bbfacdd7f93fb21a99272357 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 24 Nov 2011 08:47:51 -0300 Subject: [media] ir-sanyo-decoder.c doesn't compile I get this error when compiling for_v3.3: There is a include missing. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c index 1646730..d38fbdd 100644 --- a/drivers/media/rc/ir-sanyo-decoder.c +++ b/drivers/media/rc/ir-sanyo-decoder.c @@ -21,6 +21,7 @@ * Information for this protocol is available at the Sanyo LC7461 datasheet. */ +#include #include #include "rc-core-priv.h" -- cgit v0.10.2 From a23d9d1227f05cf96d195401fe2af2c14ea44b92 Mon Sep 17 00:00:00 2001 From: Jose Alberto Reguero Date: Sun, 16 Oct 2011 07:36:57 -0300 Subject: [media] TT CT-3650 i2c fix This patch fix a bug in the i2c code of ttusb2 driver. Signed-off-by: Jose Alberto Reguero Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c index faed393..bc50356 100644 --- a/drivers/media/dvb/dvb-usb/ttusb2.c +++ b/drivers/media/dvb/dvb-usb/ttusb2.c @@ -397,7 +397,7 @@ static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num memcpy(&obuf[3], msg[i].buf, msg[i].len); - if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) { + if (ttusb2_msg(d, CMD_I2C_XFER, obuf, obuf[1]+3, ibuf, obuf[2] + 3) < 0) { err("i2c transfer failed."); break; } -- cgit v0.10.2 From 9369cc96af2d5e093ed7f0ac9671f4b30d30af86 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 18 Oct 2011 02:12:09 -0300 Subject: [media] av7110: wrong limiter in av7110_start_feed() Smatch complains that the wrong limiter is used here: drivers/media/dvb/ttpci/av7110.c +906 dvb_feed_start_pid(12) error: buffer overflow 'npids' 5 <= 19 Here is the problem code: 905 i = dvbdmxfeed->pes_type; 906 npids[i] = (pid[i]&0x8000) ? 0 : pid[i]; "npids" is a 5 element array declared on the stack. If dvbdmxfeed->pes_type is more than 4 we probably put a (u16)0 past the end of the array. If dvbdmxfeed->pes_type is over 4 the rest of the function doesn't do anything. dvbdmxfeed->pes_type is capped at less than DMX_TS_PES_OTHER (20) in the caller function, but I changed it to less than or equal to DMX_TS_PES_PCR (4). Signed-off-by: Dan Carpenter Acked-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 3d20719..abf6b55 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -991,7 +991,7 @@ static int av7110_start_feed(struct dvb_demux_feed *feed) if (feed->type == DMX_TYPE_TS) { if ((feed->ts_type & TS_DECODER) && - (feed->pes_type < DMX_TS_PES_OTHER)) { + (feed->pes_type <= DMX_TS_PES_PCR)) { switch (demux->dmx.frontend->source) { case DMX_MEMORY_FE: if (feed->ts_type & TS_DECODER) -- cgit v0.10.2 From dbea1880368071dfa97d5e6aa4a368e7d0146a85 Mon Sep 17 00:00:00 2001 From: Andrew Vincer Date: Tue, 8 Nov 2011 12:43:45 -0300 Subject: [media] rc: Fix input deadlock and transmit error in redrat3 driver Fixed submit urb logic so hardware doesn't hang trying to transmit signal data Removed unneeded enable/disable detector commands in redrat3_transmit_ir (the hardware does this anyway) and converted arguments to unsigned as per 5588dc2 Signed-off-by: Andrew Vincer Cc: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c index 61287fc..9bff23c 100644 --- a/drivers/media/rc/redrat3.c +++ b/drivers/media/rc/redrat3.c @@ -286,12 +286,6 @@ static void redrat3_issue_async(struct redrat3_dev *rr3) rr3_ftr(rr3->dev, "Entering %s\n", __func__); - if (!rr3->det_enabled) { - dev_warn(rr3->dev, "not issuing async read, " - "detector not enabled\n"); - return; - } - memset(rr3->bulk_in_buf, 0, rr3->ep_in->wMaxPacketSize); res = usb_submit_urb(rr3->read_urb, GFP_ATOMIC); if (res) @@ -827,6 +821,7 @@ out: static void redrat3_handle_async(struct urb *urb, struct pt_regs *regs) { struct redrat3_dev *rr3; + int ret; if (!urb) return; @@ -840,15 +835,13 @@ static void redrat3_handle_async(struct urb *urb, struct pt_regs *regs) rr3_ftr(rr3->dev, "Entering %s\n", __func__); - if (!rr3->det_enabled) { - rr3_dbg(rr3->dev, "received a read callback but detector " - "disabled - ignoring\n"); - return; - } - switch (urb->status) { case 0: - redrat3_get_ir_data(rr3, urb->actual_length); + ret = redrat3_get_ir_data(rr3, urb->actual_length); + if (!ret) { + /* no error, prepare to read more */ + redrat3_issue_async(rr3); + } break; case -ECONNRESET: @@ -865,11 +858,6 @@ static void redrat3_handle_async(struct urb *urb, struct pt_regs *regs) rr3->pkttype = 0; break; } - - if (!rr3->transmitting) - redrat3_issue_async(rr3); - else - rr3_dbg(rr3->dev, "IR transmit in progress\n"); } static void redrat3_write_bulk_callback(struct urb *urb, struct pt_regs *regs) @@ -896,21 +884,24 @@ static u16 mod_freq_to_val(unsigned int mod_freq) return (u16)(65536 - (mult / mod_freq)); } -static int redrat3_set_tx_carrier(struct rc_dev *dev, u32 carrier) +static int redrat3_set_tx_carrier(struct rc_dev *rcdev, u32 carrier) { - struct redrat3_dev *rr3 = dev->priv; + struct redrat3_dev *rr3 = rcdev->priv; + struct device *dev = rr3->dev; + rr3_dbg(dev, "Setting modulation frequency to %u", carrier); rr3->carrier = carrier; return carrier; } -static int redrat3_transmit_ir(struct rc_dev *rcdev, int *txbuf, u32 n) +static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf, + unsigned count) { struct redrat3_dev *rr3 = rcdev->priv; struct device *dev = rr3->dev; struct redrat3_signal_header header; - int i, j, count, ret, ret_len, offset; + int i, j, ret, ret_len, offset; int lencheck, cur_sample_len, pipe; char *buffer = NULL, *sigdata = NULL; int *sample_lens = NULL; @@ -928,20 +919,13 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, int *txbuf, u32 n) return -EAGAIN; } - count = n / sizeof(int); if (count > (RR3_DRIVER_MAXLENS * 2)) return -EINVAL; + /* rr3 will disable rc detector on transmit */ + rr3->det_enabled = false; rr3->transmitting = true; - redrat3_disable_detector(rr3); - - if (rr3->det_enabled) { - dev_err(dev, "%s: cannot tx while rx is enabled\n", __func__); - ret = -EIO; - goto out; - } - sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL); if (!sample_lens) { ret = -ENOMEM; @@ -1055,7 +1039,7 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, int *txbuf, u32 n) if (ret < 0) dev_err(dev, "Error: control msg send failed, rc %d\n", ret); else - ret = n; + ret = count; out: kfree(sample_lens); @@ -1063,8 +1047,8 @@ out: kfree(sigdata); rr3->transmitting = false; - - redrat3_enable_detector(rr3); + /* rr3 re-enables rc detector because it was enabled before */ + rr3->det_enabled = true; return ret; } -- cgit v0.10.2 From 1ec9a35e1cfaff6983977b5db4ed2f81a0e63920 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 8 Nov 2011 19:16:04 -0300 Subject: [media] staging: as102: Add missing function argument Add missing dev argument in dev_err() call to correct an error introduced in commit 880102898f19cf9f9ba36dc9d838b5476645ce00 Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/as102/as102_drv.c b/drivers/staging/media/as102/as102_drv.c index b8adfd2..beacb2c 100644 --- a/drivers/staging/media/as102/as102_drv.c +++ b/drivers/staging/media/as102/as102_drv.c @@ -220,7 +220,7 @@ int as102_dvb_register(struct as102_dev_t *as102_dev) ret = dvb_dmx_init(&as102_dev->dvb_dmx); if (ret < 0) { - dev_err("%s: dvb_dmx_init() failed: %d\n", __func__, ret); + dev_err(dev, "%s: dvb_dmx_init() failed: %d\n", __func__, ret); goto edmxinit; } -- cgit v0.10.2 From 8503232f2e9604d844d8f52ddea2e55ccc6c38f6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 24 Nov 2011 15:01:45 -0200 Subject: [media] em28xx: Fix a few warnings due to HVR-930C addition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/video/em28xx/em28xx-cards.c:339:30: warning: ‘hauppauge_930c_gpio’ defined but not used [-Wunused-variable] drivers/media/video/em28xx/em28xx-dvb.c: In function ‘em28xx_dvb_init’: drivers/media/video/em28xx/em28xx-dvb.c:886:3: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index f63a715..5b0336b 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -336,6 +336,7 @@ static struct em28xx_reg_seq pctv_460e[] = { { -1, -1, -1, -1}, }; +#if 0 static struct em28xx_reg_seq hauppauge_930c_gpio[] = { {EM2874_R80_GPIO, 0x6f, 0xff, 10}, {EM2874_R80_GPIO, 0x4f, 0xff, 10}, /* xc5000 reset */ @@ -344,7 +345,6 @@ static struct em28xx_reg_seq hauppauge_930c_gpio[] = { { -1, -1, -1, -1}, }; -#if 0 static struct em28xx_reg_seq hauppauge_930c_digital[] = { {EM2874_R80_GPIO, 0xf6, 0xff, 10}, {EM2874_R80_GPIO, 0xe6, 0xff, 100}, diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 55a90089..ea2208e 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -864,6 +864,8 @@ static int em28xx_dvb_init(struct em28xx *dev) } break; case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C: + { + struct xc5000_config cfg; hauppauge_hvr930c_init(dev); dvb->dont_attach_fe1 = 1; @@ -883,7 +885,6 @@ static int em28xx_dvb_init(struct em28xx *dev) dvb->fe[1]->id = 1; /* Attach xc5000 */ - struct xc5000_config cfg; memset(&cfg, 0, sizeof(cfg)); cfg.i2c_address = 0x61; cfg.if_khz = 4000; @@ -906,6 +907,7 @@ static int em28xx_dvb_init(struct em28xx *dev) sizeof(dvb->fe[0]->ops.tuner_ops)); break; + } case EM2884_BOARD_TERRATEC_H5: terratec_h5_init(dev); -- cgit v0.10.2 From 4a5006f68d6b336564eb1e4cbb1f66d234958889 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 24 Nov 2011 15:04:18 -0200 Subject: [media] firedtv-avc: Fix compilation warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/dvb/firewire/firedtv-avc.c: In function ‘avc_tuner_tuneqpsk’: drivers/media/dvb/firewire/firedtv-avc.c:394:4: warning: enumeration value ‘ROLLOFF_15’ not handled in switch [-Wswitch] drivers/media/dvb/firewire/firedtv-avc.c:394:4: warning: enumeration value ‘ROLLOFF_13’ not handled in switch [-Wswitch] Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c index 489ae82..9debf0f 100644 --- a/drivers/media/dvb/firewire/firedtv-avc.c +++ b/drivers/media/dvb/firewire/firedtv-avc.c @@ -392,10 +392,11 @@ static int avc_tuner_tuneqpsk(struct firedtv *fdtv, default: c->operand[13] = 0x2; break; } switch (fdtv->fe.dtv_property_cache.rolloff) { - case ROLLOFF_AUTO: c->operand[14] = 0x2; break; case ROLLOFF_35: c->operand[14] = 0x2; break; case ROLLOFF_20: c->operand[14] = 0x0; break; case ROLLOFF_25: c->operand[14] = 0x1; break; + case ROLLOFF_AUTO: + default: c->operand[14] = 0x2; break; /* case ROLLOFF_NONE: c->operand[14] = 0xff; break; */ } switch (fdtv->fe.dtv_property_cache.pilot) { -- cgit v0.10.2 From a824f0f445ad2c86a40b4bf43acba26dfd0a98a9 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 9 Nov 2011 13:27:53 -0300 Subject: [media] video: Drop undue references to i2c-algo-bit There's one comment that has been copied from bttv to many other media/video drivers: /* init + register i2c algo-bit adapter */ Meanwhile, many drivers use hardware I2C implementations instead of relying on i2c-algo-bit, so this comment is misleading. Remove the reference to "algo-bit" from all drivers, to avoid any confusion. This is the best way to ensure that the comments won't go out of sync again. Anyone interested in the implementation details would rather look at the code itself. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c index cbdb65c..05c299f 100644 --- a/drivers/media/video/au0828/au0828-i2c.c +++ b/drivers/media/video/au0828/au0828-i2c.c @@ -348,7 +348,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) } } -/* init + register i2c algo-bit adapter */ +/* init + register i2c adapter */ int au0828_i2c_register(struct au0828_dev *dev) { dprintk(1, "%s()\n", __func__); diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c index e3952af..580c8e6 100644 --- a/drivers/media/video/bt8xx/bttv-i2c.c +++ b/drivers/media/video/bt8xx/bttv-i2c.c @@ -346,7 +346,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) } } -/* init + register i2c algo-bit adapter */ +/* init + register i2c adapter */ int __devinit init_bttv_i2c(struct bttv *btv) { strlcpy(btv->i2c_client.name, "bttv internal", I2C_NAME_SIZE); diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 040aaa8..51609d5 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -232,7 +232,7 @@ static struct i2c_algo_bit_data cx18_i2c_algo_template = { .timeout = CX18_ALGO_BIT_TIMEOUT*HZ /* jiffies */ }; -/* init + register i2c algo-bit adapter */ +/* init + register i2c adapter */ int init_cx18_i2c(struct cx18 *cx) { int i, err; diff --git a/drivers/media/video/cx18/cx18-i2c.h b/drivers/media/video/cx18/cx18-i2c.h index bdfd192..1180fdc 100644 --- a/drivers/media/video/cx18/cx18-i2c.h +++ b/drivers/media/video/cx18/cx18-i2c.h @@ -24,6 +24,6 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx); struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw); -/* init + register i2c algo-bit adapter */ +/* init + register i2c adapter */ int init_cx18_i2c(struct cx18 *cx); void exit_cx18_i2c(struct cx18 *cx); diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index 0ff7a9e..be1e21d 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -309,7 +309,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) } } -/* init + register i2c algo-bit adapter */ +/* init + register i2c adapter */ int cx23885_i2c_register(struct cx23885_i2c *bus) { struct cx23885_dev *dev = bus->dev; diff --git a/drivers/media/video/cx25821/cx25821-i2c.c b/drivers/media/video/cx25821/cx25821-i2c.c index 4d3d0ce..77fa8eb 100644 --- a/drivers/media/video/cx25821/cx25821-i2c.c +++ b/drivers/media/video/cx25821/cx25821-i2c.c @@ -300,7 +300,7 @@ static struct i2c_client cx25821_i2c_client_template = { .name = "cx25821 internal", }; -/* init + register i2c algo-bit adapter */ +/* init + register i2c adapter */ int cx25821_i2c_register(struct cx25821_i2c *bus) { struct cx25821_dev *dev = bus->dev; diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index a1fe0ab..de0f1af 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -132,7 +132,7 @@ static void do_i2c_scan(const char *name, struct i2c_client *c) } } -/* init + register i2c algo-bit adapter */ +/* init + register i2c adapter */ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) { /* Prevents usage of invalid delay values */ diff --git a/drivers/media/video/ivtv/ivtv-i2c.h b/drivers/media/video/ivtv/ivtv-i2c.h index 9332920..7b9ec1c 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.h +++ b/drivers/media/video/ivtv/ivtv-i2c.h @@ -25,7 +25,7 @@ struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv); int ivtv_i2c_register(struct ivtv *itv, unsigned idx); struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw); -/* init + register i2c algo-bit adapter */ +/* init + register i2c adapter */ int init_ivtv_i2c(struct ivtv *itv); void exit_ivtv_i2c(struct ivtv *itv); -- cgit v0.10.2 From 8798875369ca5a1862c96425ab43b67ccbccccd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alfredo=20Jes=C3=BAs=20Delaiti?= Date: Wed, 9 Nov 2011 15:13:00 -0300 Subject: [media] cx23885: add support for Mygica X8507 This patch supports card Mygica X8507 (analog part) This controller is a copy of driver card Mygica X8506 This patch depends on patch cx23885-alsa To do: FM, ISDB-t, remote control, audio for composite1, S-Video and video component. Signed-off-by: Alfredo J. Delaiti Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index c3cf089..ac03c26 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -438,6 +438,36 @@ struct cx23885_board cx23885_boards[] = { .gpio0 = 0, } }, }, + [CX23885_BOARD_MYGICA_X8507] = { + .name = "Mygica X8507", + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x61, + .tuner_bus = 1, + .porta = CX23885_ANALOG_VIDEO, + .input = { + { + .type = CX23885_VMUX_TELEVISION, + .vmux = CX25840_COMPOSITE2, + .amux = CX25840_AUDIO8, + }, + { + .type = CX23885_VMUX_COMPOSITE1, + .vmux = CX25840_COMPOSITE8, + }, + { + .type = CX23885_VMUX_SVIDEO, + .vmux = CX25840_SVIDEO_LUMA3 | + CX25840_SVIDEO_CHROMA4, + }, + { + .type = CX23885_VMUX_COMPONENT, + .vmux = CX25840_COMPONENT_ON | + CX25840_VIN1_CH1 | + CX25840_VIN6_CH2 | + CX25840_VIN7_CH3, + }, + }, + } }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -637,6 +667,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x1b55, .subdevice = 0xe2e4, .card = CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF, + }, { + .subvendor = 0x14f1, + .subdevice = 0x8502, + .card = CX23885_BOARD_MYGICA_X8507, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -1068,6 +1102,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) break; case CX23885_BOARD_MYGICA_X8506: case CX23885_BOARD_MAGICPRO_PROHDTVE2: + case CX23885_BOARD_MYGICA_X8507: /* GPIO-0 (0)Analog / (1)Digital TV */ /* GPIO-1 reset XC5000 */ /* GPIO-2 reset LGS8GL5 / LGS8G75 */ @@ -1468,6 +1503,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID: case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_MPX885: + case CX23885_BOARD_MYGICA_X8507: dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[2].i2c_adap, "cx25840", 0x88 >> 1, NULL); diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index e730b92..7415524 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -492,7 +492,8 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) dev->input = input; if (dev->board == CX23885_BOARD_MYGICA_X8506 || - dev->board == CX23885_BOARD_MAGICPRO_PROHDTVE2) { + dev->board == CX23885_BOARD_MAGICPRO_PROHDTVE2 || + dev->board == CX23885_BOARD_MYGICA_X8507) { /* Select Analog TV */ if (INPUT(input)->type == CX23885_VMUX_TELEVISION) cx23885_gpio_clear(dev, GPIO_0); diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index b49036f..519f40d 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -87,6 +87,7 @@ #define CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF 30 #define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000 31 #define CX23885_BOARD_MPX885 32 +#define CX23885_BOARD_MYGICA_X8507 33 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 -- cgit v0.10.2 From 4da621b69e5c0ac139c5240230c21da74253d2b9 Mon Sep 17 00:00:00 2001 From: Heungjun Kim Date: Fri, 11 Nov 2011 08:05:33 -0300 Subject: [media] MAINTAINERS: Add m5mols driver maintainers Add the maintainers for the m5mols driver Signed-off-by: HeungJun, Kim Signed-off-by: Kyungmin Park Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab diff --git a/MAINTAINERS b/MAINTAINERS index 071a996..879b02c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2836,6 +2836,14 @@ L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/fujitsu-laptop.c +FUJITSU M-5MO LS CAMERA ISP DRIVER +M: Kyungmin Park +M: Heungjun Kim +L: linux-media@vger.kernel.org +S: Maintained +F: drivers/media/video/m5mols/ +F: include/media/m5mols.h + FUSE: FILESYSTEM IN USERSPACE M: Miklos Szeredi L: fuse-devel@lists.sourceforge.net -- cgit v0.10.2 From 022568f05891b6a371f0fdbab9abccf9239276a2 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sun, 13 Nov 2011 12:16:40 -0300 Subject: [media] Fix typos in VIDEO_CX231XX_DVB Kconfig entry Commit ede676c72d ("[...] add digital support for PV SBTVD hybrid") added "select MEDIA_TUNER_NXP18271" to the VIDEO_CX231XX_DVB Kconfig entry. But there's no Kconfig symbol MEDIA_TUNER_NXP18271. That should have been MEDIA_TUNER_TDA18271. (The code added in that commit uses tda18271_attach, which is only available if MEDIA_TUNER_TDA18271 is set.) The selects of MEDIA_TUNER_XC5000 and MEDIA_TUNER_TDA18271 should only be done if MEDIA_TUNER_CUSTOMISE isn't set. Signed-off-by: Paul Bolle Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig index ae85a7a..c74ce9e 100644 --- a/drivers/media/video/cx231xx/Kconfig +++ b/drivers/media/video/cx231xx/Kconfig @@ -42,8 +42,8 @@ config VIDEO_CX231XX_DVB tristate "DVB/ATSC Support for Cx231xx based TV cards" depends on VIDEO_CX231XX && DVB_CORE select VIDEOBUF_DVB - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_NXP18271 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE select DVB_MB86A20S if !DVB_FE_CUSTOMISE ---help--- -- cgit v0.10.2 From 522fdf731946301ab7a5ecf854cbe89462397b81 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 13 Nov 2011 00:19:56 -0300 Subject: [media] tda18218: implement .get_if_frequency() Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/tuners/tda18218.c b/drivers/media/common/tuners/tda18218.c index aacfe23..1c86595 100644 --- a/drivers/media/common/tuners/tda18218.c +++ b/drivers/media/common/tuners/tda18218.c @@ -141,19 +141,21 @@ static int tda18218_set_params(struct dvb_frontend *fe, switch (params->u.ofdm.bandwidth) { case BANDWIDTH_6_MHZ: LP_Fc = 0; - LO_Frac = params->frequency + 4000000; + priv->if_frequency = 4000000; break; case BANDWIDTH_7_MHZ: LP_Fc = 1; - LO_Frac = params->frequency + 3500000; + priv->if_frequency = 3500000; break; case BANDWIDTH_8_MHZ: default: LP_Fc = 2; - LO_Frac = params->frequency + 4000000; + priv->if_frequency = 4000000; break; } + LO_Frac = params->frequency + priv->if_frequency; + /* band-pass filter */ if (LO_Frac < 188000000) BP_Filter = 3; @@ -206,6 +208,14 @@ error: return ret; } +static int tda18218_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct tda18218_priv *priv = fe->tuner_priv; + *frequency = priv->if_frequency; + dbg("%s: if=%d", __func__, *frequency); + return 0; +} + static int tda18218_sleep(struct dvb_frontend *fe) { struct tda18218_priv *priv = fe->tuner_priv; @@ -268,6 +278,8 @@ static const struct dvb_tuner_ops tda18218_tuner_ops = { .sleep = tda18218_sleep, .set_params = tda18218_set_params, + + .get_if_frequency = tda18218_get_if_frequency, }; struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe, diff --git a/drivers/media/common/tuners/tda18218_priv.h b/drivers/media/common/tuners/tda18218_priv.h index 904e536..dc52b72 100644 --- a/drivers/media/common/tuners/tda18218_priv.h +++ b/drivers/media/common/tuners/tda18218_priv.h @@ -100,6 +100,8 @@ struct tda18218_priv { struct tda18218_config *cfg; struct i2c_adapter *i2c; + u32 if_frequency; + u8 regs[TDA18218_NUM_REGS]; }; -- cgit v0.10.2 From 6d42b218b43f300d0787df7984c8f789de24c6e7 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 13 Nov 2011 00:26:17 -0300 Subject: [media] af9013: use .get_if_frequency() when possible Get IF frequency from tuner if tuner provides it. Remove TDA18271 and TDA18218 IF frequency hacks since both tuners provides .get_if_frequency(). Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c index 345311c..f4276e4 100644 --- a/drivers/media/dvb/frontends/af9013.c +++ b/drivers/media/dvb/frontends/af9013.c @@ -303,7 +303,8 @@ error: return ret; } -static int af9013_set_freq_ctrl(struct af9013_state *state, fe_bandwidth_t bw) +static int af9013_set_freq_ctrl(struct af9013_state *state, + struct dvb_frontend *fe) { int ret; u16 addr; @@ -324,37 +325,13 @@ static int af9013_set_freq_ctrl(struct af9013_state *state, fe_bandwidth_t bw) bfs_spec_inv = state->config.rf_spec_inv ? 1 : -1; } - adc_freq = state->config.adc_clock * 1000; - if_sample_freq = state->config.tuner_if * 1000; + adc_freq = state->config.adc_clock * 1000; - /* TDA18271 uses different sampling freq for every bw */ - if (state->config.tuner == AF9013_TUNER_TDA18271) { - switch (bw) { - case BANDWIDTH_6_MHZ: - if_sample_freq = 3300000; /* 3.3 MHz */ - break; - case BANDWIDTH_7_MHZ: - if_sample_freq = 3500000; /* 3.5 MHz */ - break; - case BANDWIDTH_8_MHZ: - default: - if_sample_freq = 4000000; /* 4.0 MHz */ - break; - } - } else if (state->config.tuner == AF9013_TUNER_TDA18218) { - switch (bw) { - case BANDWIDTH_6_MHZ: - if_sample_freq = 3000000; /* 3 MHz */ - break; - case BANDWIDTH_7_MHZ: - if_sample_freq = 3500000; /* 3.5 MHz */ - break; - case BANDWIDTH_8_MHZ: - default: - if_sample_freq = 4000000; /* 4 MHz */ - break; - } - } + /* get used IF frequency */ + if (fe->ops.tuner_ops.get_if_frequency) + fe->ops.tuner_ops.get_if_frequency(fe, &if_sample_freq); + else + if_sample_freq = state->config.tuner_if * 1000; while (if_sample_freq > (adc_freq / 2)) if_sample_freq = if_sample_freq - adc_freq; @@ -639,7 +616,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe, goto error; /* program frequency control */ - ret = af9013_set_freq_ctrl(state, params->u.ofdm.bandwidth); + ret = af9013_set_freq_ctrl(state, fe); if (ret) goto error; -- cgit v0.10.2 From 055327c55a7b74b25bf3e178da353982e6eef487 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 13 Nov 2011 00:44:57 -0300 Subject: [media] mt2060: implement .get_if_frequency() Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/tuners/mt2060.c b/drivers/media/common/tuners/mt2060.c index 2d0e768..2ecaa53 100644 --- a/drivers/media/common/tuners/mt2060.c +++ b/drivers/media/common/tuners/mt2060.c @@ -300,6 +300,12 @@ static int mt2060_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) return 0; } +static int mt2060_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + *frequency = IF2 * 1000; + return 0; +} + static int mt2060_init(struct dvb_frontend *fe) { struct mt2060_priv *priv = fe->tuner_priv; @@ -356,7 +362,8 @@ static const struct dvb_tuner_ops mt2060_tuner_ops = { .set_params = mt2060_set_params, .get_frequency = mt2060_get_frequency, - .get_bandwidth = mt2060_get_bandwidth + .get_bandwidth = mt2060_get_bandwidth, + .get_if_frequency = mt2060_get_if_frequency, }; /* This functions tries to identify a MT2060 tuner by reading the PART/REV register. This is hasty. */ -- cgit v0.10.2 From ed9405140e1ad1602352d525afede193ebfd67d7 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 13 Nov 2011 01:07:42 -0300 Subject: [media] qt1010: implement .get_if_frequency() Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/tuners/qt1010.c b/drivers/media/common/tuners/qt1010.c index 9f5dba2..cd461c2 100644 --- a/drivers/media/common/tuners/qt1010.c +++ b/drivers/media/common/tuners/qt1010.c @@ -423,6 +423,12 @@ static int qt1010_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) return 0; } +static int qt1010_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + *frequency = 36125000; + return 0; +} + static const struct dvb_tuner_ops qt1010_tuner_ops = { .info = { .name = "Quantek QT1010", @@ -437,7 +443,8 @@ static const struct dvb_tuner_ops qt1010_tuner_ops = { .set_params = qt1010_set_params, .get_frequency = qt1010_get_frequency, - .get_bandwidth = qt1010_get_bandwidth + .get_bandwidth = qt1010_get_bandwidth, + .get_if_frequency = qt1010_get_if_frequency, }; struct dvb_frontend * qt1010_attach(struct dvb_frontend *fe, -- cgit v0.10.2 From 835bf82ce4b64e280ca6c4da67c819a1065693bc Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 13 Nov 2011 11:20:08 -0300 Subject: [media] tda18212: implement .get_if_frequency() Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/tuners/tda18212.c b/drivers/media/common/tuners/tda18212.c index 6374a1e..b1750d2 100644 --- a/drivers/media/common/tuners/tda18212.c +++ b/drivers/media/common/tuners/tda18212.c @@ -25,6 +25,8 @@ struct tda18212_priv { struct tda18212_config *cfg; struct i2c_adapter *i2c; + + u32 if_frequency; }; #define dbg(fmt, arg...) \ @@ -235,6 +237,9 @@ static int tda18212_set_params(struct dvb_frontend *fe, if (ret) goto error; + /* actual IF rounded as it is on register */ + priv->if_frequency = buf[3] * 50 * 1000; + exit: if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ @@ -246,6 +251,15 @@ error: goto exit; } +static int tda18212_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct tda18212_priv *priv = fe->tuner_priv; + + *frequency = priv->if_frequency; + + return 0; +} + static int tda18212_release(struct dvb_frontend *fe) { kfree(fe->tuner_priv); @@ -265,6 +279,7 @@ static const struct dvb_tuner_ops tda18212_tuner_ops = { .release = tda18212_release, .set_params = tda18212_set_params, + .get_if_frequency = tda18212_get_if_frequency, }; struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe, -- cgit v0.10.2 From 8cffcc78996c25a04423e294faa1bb5bba3e420e Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 13 Nov 2011 11:22:58 -0300 Subject: [media] tda18212: round IF frequency to close hardware value Chip configures IF frequency resolution of 50 kHz. Round it nearest. Off-by 50 kHz is almost nothing in real life... Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/tuners/tda18212.c b/drivers/media/common/tuners/tda18212.c index b1750d2..f52282e 100644 --- a/drivers/media/common/tuners/tda18212.c +++ b/drivers/media/common/tuners/tda18212.c @@ -227,7 +227,7 @@ static int tda18212_set_params(struct dvb_frontend *fe, buf[0] = 0x02; buf[1] = bw_params[i][1]; buf[2] = 0x03; /* default value */ - buf[3] = if_khz / 50; + buf[3] = DIV_ROUND_CLOSEST(if_khz, 50); buf[4] = ((c->frequency / 1000) >> 16) & 0xff; buf[5] = ((c->frequency / 1000) >> 8) & 0xff; buf[6] = ((c->frequency / 1000) >> 0) & 0xff; -- cgit v0.10.2 From fda23faaff3b28a987c22da5f3a17b9f3d4acef8 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 13 Nov 2011 14:41:25 -0300 Subject: [media] cxd2820r: switch to .get_if_frequency() All tuners used with cxd2820r offers IF frequency so switch that. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index c64eb56..df46015 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c @@ -366,13 +366,6 @@ static struct isl6423_config anysee_isl6423_config = { static struct cxd2820r_config anysee_cxd2820r_config = { .i2c_address = 0x6d, /* (0xda >> 1) */ .ts_mode = 0x38, - .if_dvbt_6 = 3550, - .if_dvbt_7 = 3700, - .if_dvbt_8 = 4150, - .if_dvbt2_6 = 3250, - .if_dvbt2_7 = 4000, - .if_dvbt2_8 = 4000, - .if_dvbc = 5000, }; /* diff --git a/drivers/media/dvb/frontends/cxd2820r.h b/drivers/media/dvb/frontends/cxd2820r.h index 03cab7b..cf0f546 100644 --- a/drivers/media/dvb/frontends/cxd2820r.h +++ b/drivers/media/dvb/frontends/cxd2820r.h @@ -63,19 +63,6 @@ struct cxd2820r_config { */ bool spec_inv; - /* IFs for all used modes. - * Default: none, must set - * Values: - */ - u16 if_dvbt_6; - u16 if_dvbt_7; - u16 if_dvbt_8; - u16 if_dvbt2_5; - u16 if_dvbt2_6; - u16 if_dvbt2_7; - u16 if_dvbt2_8; - u16 if_dvbc; - /* GPIOs for all used modes. * Default: none, disabled * Values: diff --git a/drivers/media/dvb/frontends/cxd2820r_c.c b/drivers/media/dvb/frontends/cxd2820r_c.c index b85f501..c412877 100644 --- a/drivers/media/dvb/frontends/cxd2820r_c.c +++ b/drivers/media/dvb/frontends/cxd2820r_c.c @@ -28,6 +28,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe, struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i; u8 buf[2]; + u32 if_freq; u16 if_ctl; u64 num; struct reg_val_mask tab[] = { @@ -70,7 +71,17 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe, priv->delivery_system = SYS_DVBC_ANNEX_AC; priv->ber_running = 0; /* tune stops BER counter */ - num = priv->cfg.if_dvbc; + /* program IF frequency */ + if (fe->ops.tuner_ops.get_if_frequency) { + ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq); + if (ret) + goto error; + } else + if_freq = 0; + + dbg("%s: if_freq=%d", __func__, if_freq); + + num = if_freq / 1000; /* Hz => kHz */ num *= 0x4000; if_ctl = cxd2820r_div_u64_round_closest(num, 41000); buf[0] = (if_ctl >> 8) & 0x3f; diff --git a/drivers/media/dvb/frontends/cxd2820r_t.c b/drivers/media/dvb/frontends/cxd2820r_t.c index a04f9c8..86e17e6 100644 --- a/drivers/media/dvb/frontends/cxd2820r_t.c +++ b/drivers/media/dvb/frontends/cxd2820r_t.c @@ -27,7 +27,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe, struct cxd2820r_priv *priv = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i; - u32 if_khz, if_ctl; + u32 if_freq, if_ctl; u64 num; u8 buf[3], bw_param; u8 bw_params1[][5] = { @@ -80,17 +80,14 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe, switch (c->bandwidth_hz) { case 6000000: - if_khz = priv->cfg.if_dvbt_6; i = 0; bw_param = 2; break; case 7000000: - if_khz = priv->cfg.if_dvbt_7; i = 1; bw_param = 1; break; case 8000000: - if_khz = priv->cfg.if_dvbt_8; i = 2; bw_param = 0; break; @@ -98,7 +95,17 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe, return -EINVAL; } - num = if_khz; + /* program IF frequency */ + if (fe->ops.tuner_ops.get_if_frequency) { + ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq); + if (ret) + goto error; + } else + if_freq = 0; + + dbg("%s: if_freq=%d", __func__, if_freq); + + num = if_freq / 1000; /* Hz => kHz */ num *= 0x1000000; if_ctl = cxd2820r_div_u64_round_closest(num, 41000); buf[0] = ((if_ctl >> 16) & 0xff); diff --git a/drivers/media/dvb/frontends/cxd2820r_t2.c b/drivers/media/dvb/frontends/cxd2820r_t2.c index 6548588..8635b07 100644 --- a/drivers/media/dvb/frontends/cxd2820r_t2.c +++ b/drivers/media/dvb/frontends/cxd2820r_t2.c @@ -27,7 +27,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe, struct cxd2820r_priv *priv = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i; - u32 if_khz, if_ctl; + u32 if_freq, if_ctl; u64 num; u8 buf[3], bw_param; u8 bw_params1[][5] = { @@ -93,22 +93,18 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe, switch (c->bandwidth_hz) { case 5000000: - if_khz = priv->cfg.if_dvbt2_5; i = 0; bw_param = 3; break; case 6000000: - if_khz = priv->cfg.if_dvbt2_6; i = 1; bw_param = 2; break; case 7000000: - if_khz = priv->cfg.if_dvbt2_7; i = 2; bw_param = 1; break; case 8000000: - if_khz = priv->cfg.if_dvbt2_8; i = 3; bw_param = 0; break; @@ -116,7 +112,17 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe, return -EINVAL; } - num = if_khz; + /* program IF frequency */ + if (fe->ops.tuner_ops.get_if_frequency) { + ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq); + if (ret) + goto error; + } else + if_freq = 0; + + dbg("%s: if_freq=%d", __func__, if_freq); + + num = if_freq / 1000; /* Hz => kHz */ num *= 0x1000000; if_ctl = cxd2820r_div_u64_round_closest(num, 41000); buf[0] = ((if_ctl >> 16) & 0xff); diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index ea2208e..eb41e25 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -500,13 +500,6 @@ static struct tda10023_config em28xx_tda10023_config = { static struct cxd2820r_config em28xx_cxd2820r_config = { .i2c_address = (0xd8 >> 1), .ts_mode = CXD2820R_TS_SERIAL, - .if_dvbt_6 = 3300, - .if_dvbt_7 = 3500, - .if_dvbt_8 = 4000, - .if_dvbt2_6 = 3300, - .if_dvbt2_7 = 3500, - .if_dvbt2_8 = 4000, - .if_dvbc = 5000, /* enable LNA for DVB-T2 and DVB-C */ .gpio_dvbt2[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, -- cgit v0.10.2 From 13d723ba98545c451bb40711e718087d28985b0f Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 13 Nov 2011 15:21:58 -0300 Subject: [media] cxd2820r: check bandwidth earlier for DVB-T/T2 It is param that could be potentially unsupported and due to that it is good idea to check it very first. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/cxd2820r_t.c b/drivers/media/dvb/frontends/cxd2820r_t.c index 86e17e6..b1450ac 100644 --- a/drivers/media/dvb/frontends/cxd2820r_t.c +++ b/drivers/media/dvb/frontends/cxd2820r_t.c @@ -26,7 +26,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe, { struct cxd2820r_priv *priv = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; - int ret, i; + int ret, i, bw_i; u32 if_freq, if_ctl; u64 num; u8 buf[3], bw_param; @@ -57,6 +57,23 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe, dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz); + switch (c->bandwidth_hz) { + case 6000000: + bw_i = 0; + bw_param = 2; + break; + case 7000000: + bw_i = 1; + bw_param = 1; + break; + case 8000000: + bw_i = 2; + bw_param = 0; + break; + default: + return -EINVAL; + } + /* update GPIOs */ ret = cxd2820r_gpio(fe); if (ret) @@ -78,23 +95,6 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe, priv->delivery_system = SYS_DVBT; priv->ber_running = 0; /* tune stops BER counter */ - switch (c->bandwidth_hz) { - case 6000000: - i = 0; - bw_param = 2; - break; - case 7000000: - i = 1; - bw_param = 1; - break; - case 8000000: - i = 2; - bw_param = 0; - break; - default: - return -EINVAL; - } - /* program IF frequency */ if (fe->ops.tuner_ops.get_if_frequency) { ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq); @@ -116,7 +116,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe, if (ret) goto error; - ret = cxd2820r_wr_regs(priv, 0x0009f, bw_params1[i], 5); + ret = cxd2820r_wr_regs(priv, 0x0009f, bw_params1[bw_i], 5); if (ret) goto error; @@ -124,7 +124,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe, if (ret) goto error; - ret = cxd2820r_wr_regs(priv, 0x000d9, bw_params2[i], 2); + ret = cxd2820r_wr_regs(priv, 0x000d9, bw_params2[bw_i], 2); if (ret) goto error; diff --git a/drivers/media/dvb/frontends/cxd2820r_t2.c b/drivers/media/dvb/frontends/cxd2820r_t2.c index 8635b07..e21fc97 100644 --- a/drivers/media/dvb/frontends/cxd2820r_t2.c +++ b/drivers/media/dvb/frontends/cxd2820r_t2.c @@ -26,7 +26,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe, { struct cxd2820r_priv *priv = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; - int ret, i; + int ret, i, bw_i; u32 if_freq, if_ctl; u64 num; u8 buf[3], bw_param; @@ -71,6 +71,27 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe, dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz); + switch (c->bandwidth_hz) { + case 5000000: + bw_i = 0; + bw_param = 3; + break; + case 6000000: + bw_i = 1; + bw_param = 2; + break; + case 7000000: + bw_i = 2; + bw_param = 1; + break; + case 8000000: + bw_i = 3; + bw_param = 0; + break; + default: + return -EINVAL; + } + /* update GPIOs */ ret = cxd2820r_gpio(fe); if (ret) @@ -91,27 +112,6 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe, priv->delivery_system = SYS_DVBT2; - switch (c->bandwidth_hz) { - case 5000000: - i = 0; - bw_param = 3; - break; - case 6000000: - i = 1; - bw_param = 2; - break; - case 7000000: - i = 2; - bw_param = 1; - break; - case 8000000: - i = 3; - bw_param = 0; - break; - default: - return -EINVAL; - } - /* program IF frequency */ if (fe->ops.tuner_ops.get_if_frequency) { ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq); @@ -133,7 +133,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe, if (ret) goto error; - ret = cxd2820r_wr_regs(priv, 0x0209f, bw_params1[i], 5); + ret = cxd2820r_wr_regs(priv, 0x0209f, bw_params1[bw_i], 5); if (ret) goto error; -- cgit v0.10.2 From dc56905fc75cd03aaf05499a93b29755193a159e Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 13 Nov 2011 15:53:04 -0300 Subject: [media] ce6230: remove experimental from Kconfig I have been working many years without problems. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 3e316f2..8e7e3a8 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -341,7 +341,7 @@ config DVB_USB_AF9015 config DVB_USB_CE6230 tristate "Intel CE6230 DVB-T USB2.0 support" - depends on DVB_USB && EXPERIMENTAL + depends on DVB_USB select DVB_ZL10353 select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE help -- cgit v0.10.2 From e50f20e1712bc3ebf9cf4c8fc9e6d743ee54626a Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 13 Nov 2011 15:55:18 -0300 Subject: [media] ce168: remove experimental from Kconfig I have been working many years without problems. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 8e7e3a8..9f203c6 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -355,7 +355,7 @@ config DVB_USB_FRIIO config DVB_USB_EC168 tristate "E3C EC168 DVB-T USB2.0 support" - depends on DVB_USB && EXPERIMENTAL + depends on DVB_USB select DVB_EC100 select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE help -- cgit v0.10.2 From 37e22142891773fb883bbef435f2ebbb5670c0b0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 14 Nov 2011 14:20:49 -0300 Subject: [media] board-dm646x-evm.c: wrong register used in setup_vpif_input_channel_mode The function setup_vpif_input_channel_mode() used the VSCLKDIS register instead of VIDCLKCTL. This meant that when in HD mode videoport channel 0 used a different clock from channel 1. Clearly a copy-and-paste error. Signed-off-by: Hans Verkuil Acked-by: Manjunath Hadli Signed-off-by: Mauro Carvalho Chehab diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index e574d7f..635bf77 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -564,7 +564,7 @@ static int setup_vpif_input_channel_mode(int mux_mode) int val; u32 value; - if (!vpif_vsclkdis_reg || !cpld_client) + if (!vpif_vidclkctl_reg || !cpld_client) return -ENXIO; val = i2c_smbus_read_byte(cpld_client); @@ -572,7 +572,7 @@ static int setup_vpif_input_channel_mode(int mux_mode) return val; spin_lock_irqsave(&vpif_reg_lock, flags); - value = __raw_readl(vpif_vsclkdis_reg); + value = __raw_readl(vpif_vidclkctl_reg); if (mux_mode) { val &= VPIF_INPUT_TWO_CHANNEL; value |= VIDCH1CLK; @@ -580,7 +580,7 @@ static int setup_vpif_input_channel_mode(int mux_mode) val |= VPIF_INPUT_ONE_CHANNEL; value &= ~VIDCH1CLK; } - __raw_writel(value, vpif_vsclkdis_reg); + __raw_writel(value, vpif_vidclkctl_reg); spin_unlock_irqrestore(&vpif_reg_lock, flags); err = i2c_smbus_write_byte(cpld_client, val); -- cgit v0.10.2 From 9105b8b200410383d0854bbe237ee385d7d33ba6 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 16 Nov 2011 01:49:41 -0300 Subject: [media] staging: lirc_serial: Fix init/exit order Currently the module init function registers a platform_device and only then allocates its IRQ and I/O region. This allows allocation to race with the device's suspend() function. Instead, allocate resources in the platform driver's probe() function and free them in the remove() function. The module exit function removes the platform device before the character device that provides access to it. Change it to reverse the order of initialisation. Signed-off-by: Ben Hutchings Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c index 8a060a8..8637631 100644 --- a/drivers/staging/media/lirc/lirc_serial.c +++ b/drivers/staging/media/lirc/lirc_serial.c @@ -836,7 +836,7 @@ static int hardware_init_port(void) return 0; } -static int init_port(void) +static int __devinit lirc_serial_probe(struct platform_device *dev) { int i, nlow, nhigh, result; @@ -913,6 +913,18 @@ static int init_port(void) return 0; } +static int __devexit lirc_serial_remove(struct platform_device *dev) +{ + free_irq(irq, (void *)&hardware); + + if (iommap != 0) + release_mem_region(iommap, 8 << ioshift); + else + release_region(io, 8); + + return 0; +} + static int set_use_inc(void *data) { unsigned long flags; @@ -1076,16 +1088,6 @@ static struct lirc_driver driver = { static struct platform_device *lirc_serial_dev; -static int __devinit lirc_serial_probe(struct platform_device *dev) -{ - return 0; -} - -static int __devexit lirc_serial_remove(struct platform_device *dev) -{ - return 0; -} - static int lirc_serial_suspend(struct platform_device *dev, pm_message_t state) { @@ -1188,10 +1190,6 @@ static int __init lirc_serial_init_module(void) { int result; - result = lirc_serial_init(); - if (result) - return result; - switch (type) { case LIRC_HOMEBREW: case LIRC_IRDEO: @@ -1211,8 +1209,7 @@ static int __init lirc_serial_init_module(void) break; #endif default: - result = -EINVAL; - goto exit_serial_exit; + return -EINVAL; } if (!softcarrier) { switch (type) { @@ -1228,37 +1225,26 @@ static int __init lirc_serial_init_module(void) } } - result = init_port(); - if (result < 0) - goto exit_serial_exit; + result = lirc_serial_init(); + if (result) + return result; + driver.features = hardware[type].features; driver.dev = &lirc_serial_dev->dev; driver.minor = lirc_register_driver(&driver); if (driver.minor < 0) { printk(KERN_ERR LIRC_DRIVER_NAME ": register_chrdev failed!\n"); - result = -EIO; - goto exit_release; + lirc_serial_exit(); + return -EIO; } return 0; -exit_release: - release_region(io, 8); -exit_serial_exit: - lirc_serial_exit(); - return result; } static void __exit lirc_serial_exit_module(void) { - lirc_serial_exit(); - - free_irq(irq, (void *)&hardware); - - if (iommap != 0) - release_mem_region(iommap, 8 << ioshift); - else - release_region(io, 8); lirc_unregister_driver(driver.minor); + lirc_serial_exit(); dprintk("cleaned up module\n"); } -- cgit v0.10.2 From c8e57e1b766c2321aa76ee5e6878c69bd2313d62 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 16 Nov 2011 01:52:11 -0300 Subject: [media] staging: lirc_serial: Free resources on failure paths of lirc_serial_probe() Failure to allocate the I/O region leaves the IRQ allocated. A later failure leaves them both allocated. Reported-by: Torsten Crass Signed-off-by: Ben Hutchings Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c index 8637631..d833772 100644 --- a/drivers/staging/media/lirc/lirc_serial.c +++ b/drivers/staging/media/lirc/lirc_serial.c @@ -875,11 +875,14 @@ static int __devinit lirc_serial_probe(struct platform_device *dev) ": or compile the serial port driver as module and\n"); printk(KERN_WARNING LIRC_DRIVER_NAME ": make sure this module is loaded first\n"); - return -EBUSY; + result = -EBUSY; + goto exit_free_irq; } - if (hardware_init_port() < 0) - return -EINVAL; + if (hardware_init_port() < 0) { + result = -EINVAL; + goto exit_release_region; + } /* Initialize pulse/space widths */ init_timing_params(duty_cycle, freq); @@ -911,6 +914,16 @@ static int __devinit lirc_serial_probe(struct platform_device *dev) dprintk("Interrupt %d, port %04x obtained\n", irq, io); return 0; + +exit_release_region: + if (iommap != 0) + release_mem_region(iommap, 8 << ioshift); + else + release_region(io, 8); +exit_free_irq: + free_irq(irq, (void *)&hardware); + + return result; } static int __devexit lirc_serial_remove(struct platform_device *dev) -- cgit v0.10.2 From 1ff1d88e862948ae5bfe490248c023ff8ac2855d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 16 Nov 2011 01:53:25 -0300 Subject: [media] staging: lirc_serial: Fix deadlock on resume failure A resume function cannot remove the device it is resuming! Signed-off-by: Ben Hutchings Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c index d833772..befe626 100644 --- a/drivers/staging/media/lirc/lirc_serial.c +++ b/drivers/staging/media/lirc/lirc_serial.c @@ -1127,10 +1127,8 @@ static int lirc_serial_resume(struct platform_device *dev) { unsigned long flags; - if (hardware_init_port() < 0) { - lirc_serial_exit(); + if (hardware_init_port() < 0) return -EINVAL; - } spin_lock_irqsave(&hardware[type].lock, flags); /* Enable Interrupt */ -- cgit v0.10.2 From 9b98d60679711753e548be15c6bef5239db6ed64 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 16 Nov 2011 01:53:35 -0300 Subject: [media] staging: lirc_serial: Fix bogus error codes Device not found? ENODEV, not EINVAL. Write to read-only device? EPERM, not EBADF. Invalid argument? EINVAL, not ENOSYS. Unsupported ioctl? ENOIOCTLCMD, not ENOSYS. Another function returned an error code? Use that, don't replace it. Signed-off-by: Ben Hutchings Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c index befe626..6f5257e 100644 --- a/drivers/staging/media/lirc/lirc_serial.c +++ b/drivers/staging/media/lirc/lirc_serial.c @@ -773,7 +773,7 @@ static int hardware_init_port(void) /* we fail, there's nothing here */ printk(KERN_ERR LIRC_DRIVER_NAME ": port existence test " "failed, cannot continue\n"); - return -EINVAL; + return -ENODEV; } @@ -879,10 +879,9 @@ static int __devinit lirc_serial_probe(struct platform_device *dev) goto exit_free_irq; } - if (hardware_init_port() < 0) { - result = -EINVAL; + result = hardware_init_port(); + if (result < 0) goto exit_release_region; - } /* Initialize pulse/space widths */ init_timing_params(duty_cycle, freq); @@ -980,7 +979,7 @@ static ssize_t lirc_write(struct file *file, const char *buf, int *wbuf; if (!(hardware[type].features & LIRC_CAN_SEND_PULSE)) - return -EBADF; + return -EPERM; count = n / sizeof(int); if (n % sizeof(int) || count % 2 == 0) @@ -1031,11 +1030,11 @@ static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) return result; /* only LIRC_MODE_PULSE supported */ if (value != LIRC_MODE_PULSE) - return -ENOSYS; + return -EINVAL; break; case LIRC_GET_LENGTH: - return -ENOSYS; + return -ENOIOCTLCMD; break; case LIRC_SET_SEND_DUTY_CYCLE: @@ -1126,9 +1125,11 @@ static void lirc_serial_exit(void); static int lirc_serial_resume(struct platform_device *dev) { unsigned long flags; + int result; - if (hardware_init_port() < 0) - return -EINVAL; + result = hardware_init_port(); + if (result < 0) + return result; spin_lock_irqsave(&hardware[type].lock, flags); /* Enable Interrupt */ @@ -1161,7 +1162,7 @@ static int __init lirc_serial_init(void) /* Init read buffer. */ result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN); if (result < 0) - return -ENOMEM; + return result; result = platform_driver_register(&lirc_serial_driver); if (result) { @@ -1247,7 +1248,7 @@ static int __init lirc_serial_init_module(void) printk(KERN_ERR LIRC_DRIVER_NAME ": register_chrdev failed!\n"); lirc_serial_exit(); - return -EIO; + return driver.minor; } return 0; } -- cgit v0.10.2 From affc9a0d59ac49bd304e2137bd5e4ffdd6fdfa52 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 16 Nov 2011 01:54:04 -0300 Subject: [media] staging: lirc_serial: Do not assume error codes returned by request_irq() lirc_serial_probe() must fail if request_irq() returns an error, even if it isn't EBUSY or EINVAL, Signed-off-by: Ben Hutchings Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c index 6f5257e..0ca308a 100644 --- a/drivers/staging/media/lirc/lirc_serial.c +++ b/drivers/staging/media/lirc/lirc_serial.c @@ -843,18 +843,15 @@ static int __devinit lirc_serial_probe(struct platform_device *dev) result = request_irq(irq, irq_handler, (share_irq ? IRQF_SHARED : 0), LIRC_DRIVER_NAME, (void *)&hardware); - - switch (result) { - case -EBUSY: - printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq); - return -EBUSY; - case -EINVAL: - printk(KERN_ERR LIRC_DRIVER_NAME - ": Bad irq number or handler\n"); - return -EINVAL; - default: - break; - }; + if (result < 0) { + if (result == -EBUSY) + printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", + irq); + else if (result == -EINVAL) + printk(KERN_ERR LIRC_DRIVER_NAME + ": Bad irq number or handler\n"); + return result; + } /* Reserve io region. */ /* -- cgit v0.10.2 From bd93b3ad275501f50935a420cb26f598093d91a0 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 16 Nov 2011 05:14:03 -0300 Subject: [media] media/radio/tef6862: fix checking return value of i2c_master_send i2c_master_send returns negative errno, or else the number of bytes written. Signed-off-by: Axel Lin Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/radio/tef6862.c b/drivers/media/radio/tef6862.c index 0991e19..3408685 100644 --- a/drivers/media/radio/tef6862.c +++ b/drivers/media/radio/tef6862.c @@ -118,9 +118,11 @@ static int tef6862_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) i2cmsg[2] = pll & 0xff; err = i2c_master_send(client, i2cmsg, sizeof(i2cmsg)); - if (!err) - state->freq = f->frequency; - return err; + if (err != sizeof(i2cmsg)) + return err < 0 ? err : -EIO; + + state->freq = f->frequency; + return 0; } static int tef6862_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) -- cgit v0.10.2 From 767f1d437db41e888f5da2a79cafd4a11b319cfd Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:21 -0300 Subject: [media] cx25821-alsa.c: Line up comments Line up comments to the same column. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-alsa.c b/drivers/media/video/cx25821/cx25821-alsa.c index 09e99de..259324a 100644 --- a/drivers/media/video/cx25821/cx25821-alsa.c +++ b/drivers/media/video/cx25821/cx25821-alsa.c @@ -234,15 +234,15 @@ static int _cx25821_stop_audio_dma(struct cx25821_audio_dev *chip) */ static char *cx25821_aud_irqs[32] = { "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */ - NULL, /* reserved */ + NULL, /* reserved */ "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */ - NULL, /* reserved */ - "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */ - NULL, /* reserved */ - "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */ - NULL, /* reserved */ - "opc_err", "par_err", "rip_err", /* 16-18 */ - "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */ + NULL, /* reserved */ + "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */ + NULL, /* reserved */ + "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */ + NULL, /* reserved */ + "opc_err", "par_err", "rip_err", /* 16-18 */ + "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */ }; /* -- cgit v0.10.2 From 0ef80072014720b79596f9582112034cfe949fd3 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:22 -0300 Subject: [media] cx25821-alsa.c: Add braces to else clause Add curly braces around else clause because corresponding if has them. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-alsa.c b/drivers/media/video/cx25821/cx25821-alsa.c index 259324a..92a8694 100644 --- a/drivers/media/video/cx25821/cx25821-alsa.c +++ b/drivers/media/video/cx25821/cx25821-alsa.c @@ -317,8 +317,9 @@ static irqreturn_t cx25821_irq(int irq, void *dev_id) cx25821_aud_irq(chip, audint_status, audint_mask); break; - } else + } else { goto out; + } } handled = 1; -- cgit v0.10.2 From 4d9304c63e654abb8238e40c316e0cd92823ecf4 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:23 -0300 Subject: [media] cx25821-alsa.c: Fix indent Delete unnecessary space before indented statement. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-alsa.c b/drivers/media/video/cx25821/cx25821-alsa.c index 92a8694..680a993 100644 --- a/drivers/media/video/cx25821/cx25821-alsa.c +++ b/drivers/media/video/cx25821/cx25821-alsa.c @@ -687,7 +687,7 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) } err = snd_card_create(index[devno], id[devno], THIS_MODULE, - sizeof(struct cx25821_audio_dev), &card); + sizeof(struct cx25821_audio_dev), &card); if (err < 0) { pr_info("DEBUG ERROR: cannot create snd_card_new in %s\n", __func__); -- cgit v0.10.2 From e5f10621788881e2b53fd7c2717c83aff3813212 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:24 -0300 Subject: [media] cx25821-alsa.c: Change line endings Change obscure line endings to less obscure ones. (improve readability) Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-alsa.c b/drivers/media/video/cx25821/cx25821-alsa.c index 680a993..6142ae2 100644 --- a/drivers/media/video/cx25821/cx25821-alsa.c +++ b/drivers/media/video/cx25821/cx25821-alsa.c @@ -176,8 +176,7 @@ static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip) /* Set the input mode to 16-bit */ tmp = cx_read(AUD_A_CFG); - cx_write(AUD_A_CFG, - tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE | + cx_write(AUD_A_CFG, tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE | FLD_AUD_CLK_ENABLE); /* @@ -188,9 +187,8 @@ static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip) */ /* Enables corresponding bits at AUD_INT_STAT */ - cx_write(AUD_A_INT_MSK, - FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF | FLD_AUD_DST_SYNC | - FLD_AUD_DST_OPC_ERR); + cx_write(AUD_A_INT_MSK, FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF | + FLD_AUD_DST_SYNC | FLD_AUD_DST_OPC_ERR); /* Clean any pending interrupt bits already set */ cx_write(AUD_A_INT_STAT, ~0); @@ -200,8 +198,8 @@ static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip) /* Turn on audio downstream fifo and risc enable 0x101 */ tmp = cx_read(AUD_INT_DMA_CTL); - cx_set(AUD_INT_DMA_CTL, - tmp | (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN)); + cx_set(AUD_INT_DMA_CTL, tmp | + (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN)); mdelay(100); return 0; @@ -220,9 +218,8 @@ static int _cx25821_stop_audio_dma(struct cx25821_audio_dev *chip) /* disable irqs */ cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT); - cx_clear(AUD_A_INT_MSK, - AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | AUD_INT_DN_RISCI2 | - AUD_INT_DN_RISCI1); + cx_clear(AUD_A_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | + AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1); return 0; } @@ -258,10 +255,8 @@ static void cx25821_aud_irq(struct cx25821_audio_dev *chip, u32 status, cx_write(AUD_A_INT_STAT, status); if (debug > 1 || (status & mask & ~0xff)) - cx25821_print_irqbits(dev->name, "irq aud", - cx25821_aud_irqs, - ARRAY_SIZE(cx25821_aud_irqs), status, - mask); + cx25821_print_irqbits(dev->name, "irq aud", cx25821_aud_irqs, + ARRAY_SIZE(cx25821_aud_irqs), status, mask); /* risc op code error */ if (status & AUD_INT_OPC_ERR) { @@ -270,8 +265,7 @@ static void cx25821_aud_irq(struct cx25821_audio_dev *chip, u32 status, cx_clear(AUD_INT_DMA_CTL, FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN); cx25821_sram_channel_dump_audio(dev, - &cx25821_sram_channels - [AUDIO_SRAM_CHANNEL]); + &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]); } if (status & AUD_INT_DN_SYNC) { pr_warn("WARNING %s: Downstream sync error!\n", dev->name); @@ -362,9 +356,8 @@ static int dsp_buffer_free(struct cx25821_audio_dev *chip) */ #define DEFAULT_FIFO_SIZE 384 static struct snd_pcm_hardware snd_cx25821_digital_hw = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID, + .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID, .formats = SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_48000, @@ -397,8 +390,8 @@ static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream) return -ENODEV; } - err = - snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS); + err = snd_pcm_hw_constraint_pow2(runtime, 0, + SNDRV_PCM_HW_PARAM_PERIODS); if (err < 0) goto _error; @@ -469,8 +462,7 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, dma = &buf->dma; videobuf_dma_init(dma); ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, - (PAGE_ALIGN(chip->dma_size) >> - PAGE_SHIFT)); + (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT)); if (ret < 0) goto error; @@ -478,10 +470,8 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, if (ret < 0) goto error; - ret = - cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist, - chip->period_size, chip->num_periods, - 1); + ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist, + chip->period_size, chip->num_periods, 1); if (ret < 0) { pr_info("DEBUG: ERROR after cx25821_risc_databuffer_audio()\n"); goto error; @@ -712,8 +702,8 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) IRQF_SHARED, chip->dev->name, chip); if (err < 0) { - pr_err("ERROR %s: can't get IRQ %d for ALSA\n", - chip->dev->name, dev->pci->irq); + pr_err("ERROR %s: can't get IRQ %d for ALSA\n", chip->dev->name, + dev->pci->irq); goto error; } @@ -731,8 +721,8 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) chip->iobase, chip->irq); strcpy(card->mixername, "CX25821"); - pr_info("%s/%i: ALSA support for cx25821 boards\n", - card->driver, devno); + pr_info("%s/%i: ALSA support for cx25821 boards\n", card->driver, + devno); err = snd_card_register(card); if (err < 0) { -- cgit v0.10.2 From 81f4c8dddc804c4ecd0fdcf903d545053ef2857f Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:25 -0300 Subject: [media] cx25821-audio-upstream.c: Fix indent Change wrong indent (with spaces and less than 7 columns) of statements to tabs. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-audio-upstream.c b/drivers/media/video/cx25821/cx25821-audio-upstream.c index c20d6de..44cb183 100644 --- a/drivers/media/video/cx25821/cx25821-audio-upstream.c +++ b/drivers/media/video/cx25821/cx25821-audio-upstream.c @@ -107,7 +107,7 @@ static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev, { unsigned int line; struct sram_channel *sram_ch = - dev->channels[dev->_audio_upstream_channel].sram_channels; + dev->channels[dev->_audio_upstream_channel].sram_channels; int offset = 0; /* scan lines */ @@ -193,7 +193,7 @@ int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev, /* Recalculate virtual address based on frame index */ rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE / 4 + - (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4); + (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4); } return 0; @@ -218,7 +218,7 @@ void cx25821_free_memory_audio(struct cx25821_dev *dev) void cx25821_stop_upstream_audio(struct cx25821_dev *dev) { struct sram_channel *sram_ch = - dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels; + dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels; u32 tmp = 0; if (!dev->_audio_is_running) { @@ -286,14 +286,14 @@ int cx25821_get_audio_data(struct cx25821_dev *dev, } else { if (!(myfile->f_op)) { pr_err("%s(): File has no file operations registered!\n", - __func__); + __func__); filp_close(myfile, NULL); return -EIO; } if (!myfile->f_op->read) { pr_err("%s(): File has no READ operations registered!\n", - __func__); + __func__); filp_close(myfile, NULL); return -EIO; } @@ -312,7 +312,7 @@ int cx25821_get_audio_data(struct cx25821_dev *dev, && dev->_audiodata_buf_virt_addr != NULL) { memcpy((void *)(dev->_audiodata_buf_virt_addr + frame_offset / 4), mybuf, - vfs_read_retval); + vfs_read_retval); } file_offset += vfs_read_retval; @@ -345,7 +345,7 @@ static void cx25821_audioups_handler(struct work_struct *work) if (!dev) { pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n", - __func__); + __func__); return; } @@ -370,19 +370,19 @@ int cx25821_openfile_audio(struct cx25821_dev *dev, if (IS_ERR(myfile)) { const int open_errno = -PTR_ERR(myfile); pr_err("%s(): ERROR opening file(%s) with errno = %d!\n", - __func__, dev->_audiofilename, open_errno); + __func__, dev->_audiofilename, open_errno); return PTR_ERR(myfile); } else { if (!(myfile->f_op)) { pr_err("%s(): File has no file operations registered!\n", - __func__); + __func__); filp_close(myfile, NULL); return -EIO; } if (!myfile->f_op->read) { pr_err("%s(): File has no READ operations registered!\n", - __func__); + __func__); filp_close(myfile, NULL); return -EIO; } @@ -454,7 +454,7 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, if (!dev->_risc_virt_addr) { printk(KERN_DEBUG - pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning\n")); + pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning\n")); return -ENOMEM; } /* Clear out memory at address */ @@ -469,7 +469,7 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, if (!dev->_audiodata_buf_virt_addr) { printk(KERN_DEBUG - pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning\n")); + pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning\n")); return -ENOMEM; } /* Clear out memory at address */ @@ -485,7 +485,7 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, dev->_audio_lines_count); if (ret < 0) { printk(KERN_DEBUG - pr_fmt("ERROR creating audio upstream RISC programs!\n")); + pr_fmt("ERROR creating audio upstream RISC programs!\n")); goto error; } @@ -533,9 +533,9 @@ int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, if (dev->_risc_virt_start_addr != NULL) { risc_phys_jump_addr = - dev->_risc_phys_start_addr + - RISC_SYNC_INSTRUCTION_SIZE + - AUDIO_RISC_DMA_BUF_SIZE; + dev->_risc_phys_start_addr + + RISC_SYNC_INSTRUCTION_SIZE + + AUDIO_RISC_DMA_BUF_SIZE; rp = cx25821_risc_field_upstream_audio(dev, dev->_risc_virt_start_addr + 1, @@ -632,7 +632,7 @@ static void cx25821_wait_fifo_enable(struct cx25821_dev *dev, /* 10 millisecond timeout */ if (count++ > 1000) { pr_err("ERROR: %s() fifo is NOT turned on. Timeout!\n", - __func__); + __func__); return; } @@ -726,7 +726,7 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) if (!dev->_irq_audio_queues) { printk(KERN_DEBUG - pr_fmt("ERROR: create_singlethread_workqueue() for Audio FAILED!\n")); + pr_fmt("ERROR: create_singlethread_workqueue() for Audio FAILED!\n")); return -ENOMEM; } @@ -764,8 +764,8 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) _line_size, 0); dev->audio_upstream_riscbuf_size = - AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS + - RISC_SYNC_INSTRUCTION_SIZE; + AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS + + RISC_SYNC_INSTRUCTION_SIZE; dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS; /* Allocating buffers and prepare RISC program */ @@ -773,7 +773,7 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) _line_size); if (retval < 0) { pr_err("%s: Failed to set up Audio upstream buffers!\n", - dev->name); + dev->name); goto error; } /* Start RISC engine */ -- cgit v0.10.2 From 64dcb194969d8d4447911e69f8b633ff2b87be40 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:26 -0300 Subject: [media] cx25821-audio-upstream.c: Move operators Move operator of complex expression to the end of the lines to preserve consistency. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-audio-upstream.c b/drivers/media/video/cx25821/cx25821-audio-upstream.c index 44cb183..a221b95 100644 --- a/drivers/media/video/cx25821/cx25821-audio-upstream.c +++ b/drivers/media/video/cx25821/cx25821-audio-upstream.c @@ -398,9 +398,9 @@ int cx25821_openfile_audio(struct cx25821_dev *dev, vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); - if (vfs_read_retval > 0 - && vfs_read_retval == line_size - && dev->_audiodata_buf_virt_addr != NULL) { + if (vfs_read_retval > 0 && + vfs_read_retval == line_size && + dev->_audiodata_buf_virt_addr != NULL) { memcpy((void *)(dev-> _audiodata_buf_virt_addr + offset / 4), mybuf, -- cgit v0.10.2 From 72a52fc3254512c5bcc70a03f33571cd50ee33a1 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:27 -0300 Subject: [media] cx25821-audio-upstream.c: Change line endings Change obscure line endings to less obscure ones. (improve readability) Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-audio-upstream.c b/drivers/media/video/cx25821/cx25821-audio-upstream.c index a221b95..4dc2a24 100644 --- a/drivers/media/video/cx25821/cx25821-audio-upstream.c +++ b/drivers/media/video/cx25821/cx25821-audio-upstream.c @@ -175,10 +175,8 @@ int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev, } rp = cx25821_risc_field_upstream_audio(dev, rp, - dev-> - _audiodata_buf_phys_addr - + databuf_offset, bpl, - fifo_enable); + dev->_audiodata_buf_phys_addr + databuf_offset, + bpl, fifo_enable); if (USE_RISC_NOOP_AUDIO) { for (i = 0; i < NUM_NO_OPS; i++) @@ -305,8 +303,8 @@ int cx25821_get_audio_data(struct cx25821_dev *dev, for (i = 0; i < dev->_audio_lines_count; i++) { pos = file_offset; - vfs_read_retval = - vfs_read(myfile, mybuf, line_size, &pos); + vfs_read_retval = vfs_read(myfile, mybuf, line_size, + &pos); if (vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_audiodata_buf_virt_addr != NULL) { @@ -328,8 +326,8 @@ int cx25821_get_audio_data(struct cx25821_dev *dev, if (i > 0) dev->_audioframe_count++; - dev->_audiofile_status = - (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + dev->_audiofile_status = (vfs_read_retval == line_size) ? + IN_PROGRESS : END_OF_FILE; set_fs(old_fs); filp_close(myfile, NULL); @@ -340,8 +338,8 @@ int cx25821_get_audio_data(struct cx25821_dev *dev, static void cx25821_audioups_handler(struct work_struct *work) { - struct cx25821_dev *dev = - container_of(work, struct cx25821_dev, _audio_work_entry); + struct cx25821_dev *dev = container_of(work, struct cx25821_dev, + _audio_work_entry); if (!dev) { pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n", @@ -395,8 +393,8 @@ int cx25821_openfile_audio(struct cx25821_dev *dev, for (i = 0; i < dev->_audio_lines_count; i++) { pos = offset; - vfs_read_retval = - vfs_read(myfile, mybuf, line_size, &pos); + vfs_read_retval = vfs_read(myfile, mybuf, + line_size, &pos); if (vfs_read_retval > 0 && vfs_read_retval == line_size && @@ -423,8 +421,8 @@ int cx25821_openfile_audio(struct cx25821_dev *dev, break; } - dev->_audiofile_status = - (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + dev->_audiofile_status = (vfs_read_retval == line_size) ? + IN_PROGRESS : END_OF_FILE; set_fs(old_fs); myfile->f_pos = 0; @@ -444,9 +442,8 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, cx25821_free_memory_audio(dev); - dev->_risc_virt_addr = - pci_alloc_consistent(dev->pci, dev->audio_upstream_riscbuf_size, - &dma_addr); + dev->_risc_virt_addr = pci_alloc_consistent(dev->pci, + dev->audio_upstream_riscbuf_size, &dma_addr); dev->_risc_virt_start_addr = dev->_risc_virt_addr; dev->_risc_phys_start_addr = dma_addr; dev->_risc_phys_addr = dma_addr; @@ -461,9 +458,8 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, memset(dev->_risc_virt_addr, 0, dev->_audiorisc_size); /* For Audio Data buffer allocation */ - dev->_audiodata_buf_virt_addr = - pci_alloc_consistent(dev->pci, dev->audio_upstream_databuf_size, - &data_dma_addr); + dev->_audiodata_buf_virt_addr = pci_alloc_consistent(dev->pci, + dev->audio_upstream_databuf_size, &data_dma_addr); dev->_audiodata_buf_phys_addr = data_dma_addr; dev->_audiodata_buf_size = dev->audio_upstream_databuf_size; @@ -480,9 +476,8 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, return ret; /* Creating RISC programs */ - ret = - cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl, - dev->_audio_lines_count); + ret = cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl, + dev->_audio_lines_count); if (ret < 0) { printk(KERN_DEBUG pr_fmt("ERROR creating audio upstream RISC programs!\n")); @@ -661,9 +656,9 @@ int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev, /* Set the input mode to 16-bit */ tmp = cx_read(sram_ch->aud_cfg); - tmp |= - FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE | - FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | FLD_AUD_SONY_MODE; + tmp |= FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE | + FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | + FLD_AUD_SONY_MODE; cx_write(sram_ch->aud_cfg, tmp); /* Read and write back the interrupt status register to clear it */ @@ -678,12 +673,11 @@ int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev, tmp = cx_read(sram_ch->int_msk); cx_write(sram_ch->int_msk, tmp |= _intr_msk); - err = - request_irq(dev->pci->irq, cx25821_upstream_irq_audio, + err = request_irq(dev->pci->irq, cx25821_upstream_irq_audio, IRQF_SHARED, dev->name, dev); if (err < 0) { - pr_err("%s: can't get upstream IRQ %d\n", - dev->name, dev->pci->irq); + pr_err("%s: can't get upstream IRQ %d\n", dev->name, + dev->pci->irq); goto fail_irq; } -- cgit v0.10.2 From 8e249581611bfc98c1ec18b6e124b613b6b6db1b Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:28 -0300 Subject: [media] cx25821-audio.h: Line up defines Line up defines to the same column. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-audio.h b/drivers/media/video/cx25821/cx25821-audio.h index 8eb55b7..57bdced 100644 --- a/drivers/media/video/cx25821/cx25821-audio.h +++ b/drivers/media/video/cx25821/cx25821-audio.h @@ -23,12 +23,12 @@ #ifndef __CX25821_AUDIO_H__ #define __CX25821_AUDIO_H__ -#define USE_RISC_NOOP 1 -#define LINES_PER_BUFFER 15 -#define AUDIO_LINE_SIZE 128 +#define USE_RISC_NOOP 1 +#define LINES_PER_BUFFER 15 +#define AUDIO_LINE_SIZE 128 /* Number of buffer programs to use at once. */ -#define NUMBER_OF_PROGRAMS 8 +#define NUMBER_OF_PROGRAMS 8 /* * Max size of the RISC program for a buffer. - worst case is 2 writes per line -- cgit v0.10.2 From 6f1f0e85da9be5a2ffddf42751400f619b503d62 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:29 -0300 Subject: [media] cx25821-audio.h: Fix multiline defines Change column of line continuation character ('\') and fix indent of multiline defines. Also line up remaining constant defines. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-audio.h b/drivers/media/video/cx25821/cx25821-audio.h index 57bdced..1fc2d24 100644 --- a/drivers/media/video/cx25821/cx25821-audio.h +++ b/drivers/media/video/cx25821/cx25821-audio.h @@ -35,27 +35,28 @@ * Space is also added for the 4 no-op instructions added on the end. */ #ifndef USE_RISC_NOOP -#define MAX_BUFFER_PROGRAM_SIZE \ - (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE * 4) +#define MAX_BUFFER_PROGRAM_SIZE \ + (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE * 4) #endif /* MAE 12 July 2005 Try to use NOOP RISC instruction instead */ #ifdef USE_RISC_NOOP -#define MAX_BUFFER_PROGRAM_SIZE \ - (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \ - RISC_NOOP_INSTRUCTION_SIZE * 4) +#define MAX_BUFFER_PROGRAM_SIZE \ + (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \ + RISC_NOOP_INSTRUCTION_SIZE * 4) #endif /* Sizes of various instructions in bytes. Used when adding instructions. */ -#define RISC_WRITE_INSTRUCTION_SIZE 12 -#define RISC_JUMP_INSTRUCTION_SIZE 12 -#define RISC_SKIP_INSTRUCTION_SIZE 4 -#define RISC_SYNC_INSTRUCTION_SIZE 4 -#define RISC_WRITECR_INSTRUCTION_SIZE 16 -#define RISC_NOOP_INSTRUCTION_SIZE 4 - -#define MAX_AUDIO_DMA_BUFFER_SIZE \ -(MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + RISC_SYNC_INSTRUCTION_SIZE) +#define RISC_WRITE_INSTRUCTION_SIZE 12 +#define RISC_JUMP_INSTRUCTION_SIZE 12 +#define RISC_SKIP_INSTRUCTION_SIZE 4 +#define RISC_SYNC_INSTRUCTION_SIZE 4 +#define RISC_WRITECR_INSTRUCTION_SIZE 16 +#define RISC_NOOP_INSTRUCTION_SIZE 4 + +#define MAX_AUDIO_DMA_BUFFER_SIZE \ + (MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + \ + RISC_SYNC_INSTRUCTION_SIZE) #endif -- cgit v0.10.2 From 744992c01162d8a51e667454bd7a886b6e28008e Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:30 -0300 Subject: [media] cx25821-cards.c: Fix indent Fix indent of statement to use tab instead of spaces. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-cards.c b/drivers/media/video/cx25821/cx25821-cards.c index 6ace603..99988c9 100644 --- a/drivers/media/video/cx25821/cx25821-cards.c +++ b/drivers/media/video/cx25821/cx25821-cards.c @@ -67,6 +67,6 @@ void cx25821_card_setup(struct cx25821_dev *dev) if (dev->i2c_bus[0].i2c_rc == 0) { dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, - sizeof(eeprom)); + sizeof(eeprom)); } } -- cgit v0.10.2 From 43365d5d135eef910fcc1f211d9668e561517b0c Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:31 -0300 Subject: [media] cx25821-core.c: Delete empty line Delete redundant empty line. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-core.c b/drivers/media/video/cx25821/cx25821-core.c index a7fa38f..f3f6c76 100644 --- a/drivers/media/video/cx25821/cx25821-core.c +++ b/drivers/media/video/cx25821/cx25821-core.c @@ -1512,6 +1512,5 @@ static void __exit cx25821_fini(void) pci_unregister_driver(&cx25821_pci_driver); } - module_init(cx25821_init); module_exit(cx25821_fini); -- cgit v0.10.2 From c14ea5e59f80082fc58bfabe300ae5a6560f7958 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:32 -0300 Subject: [media] cx25821-core.c: Fix indent Change indent of statements that indented with spaces to indent with tabs. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-core.c b/drivers/media/video/cx25821/cx25821-core.c index f3f6c76..35f543d 100644 --- a/drivers/media/video/cx25821/cx25821-core.c +++ b/drivers/media/video/cx25821/cx25821-core.c @@ -869,7 +869,7 @@ static int cx25821_get_resources(struct cx25821_dev *dev) return 0; pr_err("%s: can't get MMIO memory @ 0x%llx\n", - dev->name, (unsigned long long)pci_resource_start(dev->pci, 0)); + dev->name, (unsigned long long)pci_resource_start(dev->pci, 0)); return -EBUSY; } @@ -994,7 +994,7 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) * cx25821_i2c_register(&dev->i2c_bus[2]); */ CX25821_INFO("i2c register! bus->i2c_rc = %d\n", - dev->i2c_bus[0].i2c_rc); + dev->i2c_bus[0].i2c_rc); cx25821_card_setup(dev); @@ -1224,7 +1224,7 @@ static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist, /* scanline needs to be split */ todo = bpl; *(rp++) = cpu_to_le32(RISC_WRITE | sol | - (sg_dma_len(sg) - offset)); + (sg_dma_len(sg) - offset)); *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); *(rp++) = cpu_to_le32(0); /* bits 63-32 */ todo -= (sg_dma_len(sg) - offset); @@ -1232,7 +1232,7 @@ static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist, sg++; while (todo > sg_dma_len(sg)) { *(rp++) = cpu_to_le32(RISC_WRITE | - sg_dma_len(sg)); + sg_dma_len(sg)); *(rp++) = cpu_to_le32(sg_dma_address(sg)); *(rp++) = cpu_to_le32(0); /* bits 63-32 */ todo -= sg_dma_len(sg); -- cgit v0.10.2 From 3f0bfe5bbd63279fbb278659e9709b90040bfb20 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:33 -0300 Subject: [media] cx25821-core.c: Change line endings Change obscure line endings to less obscure ones. (improve readability) Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-core.c b/drivers/media/video/cx25821/cx25821-core.c index 35f543d..f617474 100644 --- a/drivers/media/video/cx25821/cx25821-core.c +++ b/drivers/media/video/cx25821/cx25821-core.c @@ -804,8 +804,8 @@ void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select, u32 format) { if (channel_select <= 7 && channel_select >= 0) { - cx_write(dev->channels[channel_select]. - sram_channels->pix_frmt, format); + cx_write(dev->channels[channel_select].sram_channels->pix_frmt, + format); dev->channels[channel_select].pixel_formats = format; } } @@ -855,17 +855,15 @@ static void cx25821_initialize(struct cx25821_dev *dev) } cx25821_sram_channel_setup_audio(dev, - dev->channels[SRAM_CH08].sram_channels, - 128, 0); + dev->channels[SRAM_CH08].sram_channels, 128, 0); cx25821_gpio_init(dev); } static int cx25821_get_resources(struct cx25821_dev *dev) { - if (request_mem_region - (pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0), - dev->name)) + if (request_mem_region(pci_resource_start(dev->pci, 0), + pci_resource_len(dev->pci, 0), dev->name)) return 0; pr_err("%s: can't get MMIO memory @ 0x%llx\n", @@ -972,8 +970,7 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0)); if (!dev->lmmio) { - CX25821_ERR - ("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n"); + CX25821_ERR("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n"); cx25821_iounmap(dev); return -ENOMEM; } @@ -1004,9 +1001,8 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) cx25821_video_register(dev); /* register IOCTL device */ - dev->ioctl_dev = - cx25821_vdev_init(dev, dev->pci, &cx25821_videoioctl_template, - "video"); + dev->ioctl_dev = cx25821_vdev_init(dev, dev->pci, + &cx25821_videoioctl_template, "video"); if (video_register_device (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) { @@ -1103,16 +1099,15 @@ static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist, } if (bpl <= sg_dma_len(sg) - offset) { /* fits into current chunk */ - *(rp++) = - cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL | bpl); + *(rp++) = cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL | + bpl); *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); *(rp++) = cpu_to_le32(0); /* bits 63-32 */ offset += bpl; } else { /* scanline needs to be split */ todo = bpl; - *(rp++) = - cpu_to_le32(RISC_WRITE | RISC_SOL | + *(rp++) = cpu_to_le32(RISC_WRITE | RISC_SOL | (sg_dma_len(sg) - offset)); *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); *(rp++) = cpu_to_le32(0); /* bits 63-32 */ @@ -1120,8 +1115,8 @@ static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist, offset = 0; sg++; while (todo > sg_dma_len(sg)) { - *(rp++) = - cpu_to_le32(RISC_WRITE | sg_dma_len(sg)); + *(rp++) = cpu_to_le32(RISC_WRITE | + sg_dma_len(sg)); *(rp++) = cpu_to_le32(sg_dma_address(sg)); *(rp++) = cpu_to_le32(0); /* bits 63-32 */ todo -= sg_dma_len(sg); @@ -1160,8 +1155,8 @@ int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, can cause next bpl to start close to a page border. First DMA region may be smaller than PAGE_SIZE */ /* write and jump need and extra dword */ - instructions = - fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); + instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + + lines); instructions += 2; rc = btcx_riscmem_alloc(pci, risc, instructions * 12); @@ -1215,8 +1210,8 @@ static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist, if (bpl <= sg_dma_len(sg) - offset) { /* fits into current chunk */ - *(rp++) = - cpu_to_le32(RISC_WRITE | sol | RISC_EOL | bpl); + *(rp++) = cpu_to_le32(RISC_WRITE | sol | RISC_EOL | + bpl); *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); *(rp++) = cpu_to_le32(0); /* bits 63-32 */ offset += bpl; @@ -1339,8 +1334,8 @@ static irqreturn_t cx25821_irq(int irq, void *dev_id) sram_channels->int_stat); if (vid_status) - handled += - cx25821_video_irq(dev, i, vid_status); + handled += cx25821_video_irq(dev, i, + vid_status); cx_write(PCI_INT_STAT, mask[i]); } @@ -1427,9 +1422,8 @@ static int __devinit cx25821_initdev(struct pci_dev *pci_dev, goto fail_irq; } - err = - request_irq(pci_dev->irq, cx25821_irq, IRQF_SHARED, - dev->name, dev); + err = request_irq(pci_dev->irq, cx25821_irq, + IRQF_SHARED, dev->name, dev); if (err < 0) { pr_err("%s: can't get IRQ %d\n", dev->name, pci_dev->irq); -- cgit v0.10.2 From 654d075d5db3220af1385980acba8f9417c0f36a Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:34 -0300 Subject: [media] cx25821-i2c.c: Change line endings Change obscure line endings to less obscure ones. (improve readability) Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-i2c.c b/drivers/media/video/cx25821/cx25821-i2c.c index 77fa8eb..12d7300 100644 --- a/drivers/media/video/cx25821/cx25821-i2c.c +++ b/drivers/media/video/cx25821/cx25821-i2c.c @@ -252,8 +252,8 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && msgs[i].addr == msgs[i + 1].addr) { /* write then read from same address */ - retval = - i2c_sendbytes(i2c_adap, &msgs[i], msgs[i + 1].len); + retval = i2c_sendbytes(i2c_adap, &msgs[i], + msgs[i + 1].len); if (retval < 0) goto err; @@ -276,10 +276,8 @@ err: static u32 cx25821_functionality(struct i2c_adapter *adap) { - return I2C_FUNC_SMBUS_EMUL | - I2C_FUNC_I2C | - I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA; + return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA; } static struct i2c_algorithm cx25821_i2c_algo_template = { -- cgit v0.10.2 From bc8b5dcaf5939045d89efa737b1ef583171e2436 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:35 -0300 Subject: [media] cx25821-medusa-defines.h: Fix typo Fix typo in comment in word 'decoder'. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-medusa-defines.h b/drivers/media/video/cx25821/cx25821-medusa-defines.h index 60d197f..07a6141 100644 --- a/drivers/media/video/cx25821/cx25821-medusa-defines.h +++ b/drivers/media/video/cx25821/cx25821-medusa-defines.h @@ -23,7 +23,7 @@ #ifndef _MEDUSA_DEF_H_ #define _MEDUSA_DEF_H_ -/* Video deocder that we supported */ +/* Video decoder that we supported */ #define VDEC_A 0 #define VDEC_B 1 #define VDEC_C 2 -- cgit v0.10.2 From 7618aa0e46564aeaa7a48588fac4bc21a78f666b Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:36 -0300 Subject: [media] cx25821-medusa-defines.h: Line up defines Line up constant defines to the same column. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-medusa-defines.h b/drivers/media/video/cx25821/cx25821-medusa-defines.h index 07a6141..7a9e647 100644 --- a/drivers/media/video/cx25821/cx25821-medusa-defines.h +++ b/drivers/media/video/cx25821/cx25821-medusa-defines.h @@ -34,9 +34,9 @@ #define VDEC_H 7 /* end of display sequence */ -#define END_OF_SEQ 0xF; +#define END_OF_SEQ 0xF; /* registry string size */ -#define MAX_REGISTRY_SZ 40; +#define MAX_REGISTRY_SZ 40; #endif -- cgit v0.10.2 From f70a6566d3fb0dd7ebf7dd4db127550f3c52d775 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:37 -0300 Subject: [media] cx25821-medusa-reg.h: Line up defines Line up constant defines to the same column. (also delete unnecessary spaces in comments) Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-medusa-reg.h b/drivers/media/video/cx25821/cx25821-medusa-reg.h index 1c1c228..c98ac94 100644 --- a/drivers/media/video/cx25821/cx25821-medusa-reg.h +++ b/drivers/media/video/cx25821/cx25821-medusa-reg.h @@ -28,22 +28,22 @@ #define HOST_REGISTER2 0x0001 /* Chip Configuration Registers */ -#define CHIP_CTRL 0x0100 -#define AFE_AB_CTRL 0x0104 -#define AFE_CD_CTRL 0x0108 -#define AFE_EF_CTRL 0x010C -#define AFE_GH_CTRL 0x0110 +#define CHIP_CTRL 0x0100 +#define AFE_AB_CTRL 0x0104 +#define AFE_CD_CTRL 0x0108 +#define AFE_EF_CTRL 0x010C +#define AFE_GH_CTRL 0x0110 #define DENC_AB_CTRL 0x0114 -#define BYP_AB_CTRL 0x0118 -#define MON_A_CTRL 0x011C -#define DISP_SEQ_A 0x0120 -#define DISP_SEQ_B 0x0124 -#define DISP_AB_CNT 0x0128 -#define DISP_CD_CNT 0x012C -#define DISP_EF_CNT 0x0130 -#define DISP_GH_CNT 0x0134 -#define DISP_IJ_CNT 0x0138 -#define PIN_OE_CTRL 0x013C +#define BYP_AB_CTRL 0x0118 +#define MON_A_CTRL 0x011C +#define DISP_SEQ_A 0x0120 +#define DISP_SEQ_B 0x0124 +#define DISP_AB_CNT 0x0128 +#define DISP_CD_CNT 0x012C +#define DISP_EF_CNT 0x0130 +#define DISP_GH_CNT 0x0134 +#define DISP_IJ_CNT 0x0138 +#define PIN_OE_CTRL 0x013C #define PIN_SPD_CTRL 0x0140 #define PIN_SPD_CTRL2 0x0144 #define IRQ_STAT_CTRL 0x0148 @@ -51,8 +51,8 @@ #define POWER_CTRL_CD 0x0150 #define POWER_CTRL_EF 0x0154 #define POWER_CTRL_GH 0x0158 -#define TUNE_CTRL 0x015C -#define BIAS_CTRL 0x0160 +#define TUNE_CTRL 0x015C +#define BIAS_CTRL 0x0160 #define AFE_AB_DIAG_CTRL 0x0164 #define AFE_CD_DIAG_CTRL 0x0168 #define AFE_EF_DIAG_CTRL 0x016C @@ -61,17 +61,17 @@ #define PLL_CD_DIAG_CTRL 0x0178 #define PLL_EF_DIAG_CTRL 0x017C #define PLL_GH_DIAG_CTRL 0x0180 -#define TEST_CTRL 0x0184 -#define BIST_STAT 0x0188 -#define BIST_STAT2 0x018C -#define BIST_VID_PLL_AB_STAT 0x0190 -#define BIST_VID_PLL_CD_STAT 0x0194 -#define BIST_VID_PLL_EF_STAT 0x0198 -#define BIST_VID_PLL_GH_STAT 0x019C +#define TEST_CTRL 0x0184 +#define BIST_STAT 0x0188 +#define BIST_STAT2 0x018C +#define BIST_VID_PLL_AB_STAT 0x0190 +#define BIST_VID_PLL_CD_STAT 0x0194 +#define BIST_VID_PLL_EF_STAT 0x0198 +#define BIST_VID_PLL_GH_STAT 0x019C #define DLL_DIAG_CTRL 0x01A0 #define DEV_CH_ID_CTRL 0x01A4 #define ABIST_CTRL_STATUS 0x01A8 -#define ABIST_FREQ 0x01AC +#define ABIST_FREQ 0x01AC #define ABIST_GOERT_SHIFT 0x01B0 #define ABIST_COEF12 0x01B4 #define ABIST_COEF34 0x01B8 @@ -92,357 +92,357 @@ #define ABIST_CLAMP_E 0x01F4 #define ABIST_CLAMP_F 0x01F8 -/* Digital Video Encoder A Registers */ -#define DENC_A_REG_1 0x0200 -#define DENC_A_REG_2 0x0204 -#define DENC_A_REG_3 0x0208 -#define DENC_A_REG_4 0x020C -#define DENC_A_REG_5 0x0210 -#define DENC_A_REG_6 0x0214 -#define DENC_A_REG_7 0x0218 -#define DENC_A_REG_8 0x021C +/* Digital Video Encoder A Registers */ +#define DENC_A_REG_1 0x0200 +#define DENC_A_REG_2 0x0204 +#define DENC_A_REG_3 0x0208 +#define DENC_A_REG_4 0x020C +#define DENC_A_REG_5 0x0210 +#define DENC_A_REG_6 0x0214 +#define DENC_A_REG_7 0x0218 +#define DENC_A_REG_8 0x021C -/* Digital Video Encoder B Registers */ -#define DENC_B_REG_1 0x0300 -#define DENC_B_REG_2 0x0304 -#define DENC_B_REG_3 0x0308 -#define DENC_B_REG_4 0x030C -#define DENC_B_REG_5 0x0310 -#define DENC_B_REG_6 0x0314 -#define DENC_B_REG_7 0x0318 -#define DENC_B_REG_8 0x031C +/* Digital Video Encoder B Registers */ +#define DENC_B_REG_1 0x0300 +#define DENC_B_REG_2 0x0304 +#define DENC_B_REG_3 0x0308 +#define DENC_B_REG_4 0x030C +#define DENC_B_REG_5 0x0310 +#define DENC_B_REG_6 0x0314 +#define DENC_B_REG_7 0x0318 +#define DENC_B_REG_8 0x031C -/* Video Decoder A Registers */ -#define MODE_CTRL 0x1000 -#define OUT_CTRL1 0x1004 -#define OUT_CTRL_NS 0x1008 -#define GEN_STAT 0x100C -#define INT_STAT_MASK 0x1010 -#define LUMA_CTRL 0x1014 -#define CHROMA_CTRL 0x1018 -#define CRUSH_CTRL 0x101C -#define HORIZ_TIM_CTRL 0x1020 -#define VERT_TIM_CTRL 0x1024 -#define MISC_TIM_CTRL 0x1028 -#define FIELD_COUNT 0x102C -#define HSCALE_CTRL 0x1030 -#define VSCALE_CTRL 0x1034 -#define MAN_VGA_CTRL 0x1038 -#define MAN_AGC_CTRL 0x103C -#define DFE_CTRL1 0x1040 -#define DFE_CTRL2 0x1044 -#define DFE_CTRL3 0x1048 -#define PLL_CTRL 0x104C -#define PLL_CTRL_FAST 0x1050 -#define HTL_CTRL 0x1054 -#define SRC_CFG 0x1058 -#define SC_STEP_SIZE 0x105C -#define SC_CONVERGE_CTRL 0x1060 -#define SC_LOOP_CTRL 0x1064 -#define COMB_2D_HFS_CFG 0x1068 -#define COMB_2D_HFD_CFG 0x106C -#define COMB_2D_LF_CFG 0x1070 -#define COMB_2D_BLEND 0x1074 -#define COMB_MISC_CTRL 0x1078 +/* Video Decoder A Registers */ +#define MODE_CTRL 0x1000 +#define OUT_CTRL1 0x1004 +#define OUT_CTRL_NS 0x1008 +#define GEN_STAT 0x100C +#define INT_STAT_MASK 0x1010 +#define LUMA_CTRL 0x1014 +#define CHROMA_CTRL 0x1018 +#define CRUSH_CTRL 0x101C +#define HORIZ_TIM_CTRL 0x1020 +#define VERT_TIM_CTRL 0x1024 +#define MISC_TIM_CTRL 0x1028 +#define FIELD_COUNT 0x102C +#define HSCALE_CTRL 0x1030 +#define VSCALE_CTRL 0x1034 +#define MAN_VGA_CTRL 0x1038 +#define MAN_AGC_CTRL 0x103C +#define DFE_CTRL1 0x1040 +#define DFE_CTRL2 0x1044 +#define DFE_CTRL3 0x1048 +#define PLL_CTRL 0x104C +#define PLL_CTRL_FAST 0x1050 +#define HTL_CTRL 0x1054 +#define SRC_CFG 0x1058 +#define SC_STEP_SIZE 0x105C +#define SC_CONVERGE_CTRL 0x1060 +#define SC_LOOP_CTRL 0x1064 +#define COMB_2D_HFS_CFG 0x1068 +#define COMB_2D_HFD_CFG 0x106C +#define COMB_2D_LF_CFG 0x1070 +#define COMB_2D_BLEND 0x1074 +#define COMB_MISC_CTRL 0x1078 #define COMB_FLAT_THRESH_CTRL 0x107C -#define COMB_TEST 0x1080 -#define BP_MISC_CTRL 0x1084 -#define VCR_DET_CTRL 0x1088 -#define NOISE_DET_CTRL 0x108C +#define COMB_TEST 0x1080 +#define BP_MISC_CTRL 0x1084 +#define VCR_DET_CTRL 0x1088 +#define NOISE_DET_CTRL 0x108C #define COMB_FLAT_NOISE_CTRL 0x1090 -#define VERSION 0x11F8 -#define SOFT_RST_CTRL 0x11FC +#define VERSION 0x11F8 +#define SOFT_RST_CTRL 0x11FC -/* Video Decoder B Registers */ -#define VDEC_B_MODE_CTRL 0x1200 -#define VDEC_B_OUT_CTRL1 0x1204 -#define VDEC_B_OUT_CTRL_NS 0x1208 -#define VDEC_B_GEN_STAT 0x120C +/* Video Decoder B Registers */ +#define VDEC_B_MODE_CTRL 0x1200 +#define VDEC_B_OUT_CTRL1 0x1204 +#define VDEC_B_OUT_CTRL_NS 0x1208 +#define VDEC_B_GEN_STAT 0x120C #define VDEC_B_INT_STAT_MASK 0x1210 -#define VDEC_B_LUMA_CTRL 0x1214 -#define VDEC_B_CHROMA_CTRL 0x1218 -#define VDEC_B_CRUSH_CTRL 0x121C +#define VDEC_B_LUMA_CTRL 0x1214 +#define VDEC_B_CHROMA_CTRL 0x1218 +#define VDEC_B_CRUSH_CTRL 0x121C #define VDEC_B_HORIZ_TIM_CTRL 0x1220 #define VDEC_B_VERT_TIM_CTRL 0x1224 #define VDEC_B_MISC_TIM_CTRL 0x1228 -#define VDEC_B_FIELD_COUNT 0x122C -#define VDEC_B_HSCALE_CTRL 0x1230 -#define VDEC_B_VSCALE_CTRL 0x1234 -#define VDEC_B_MAN_VGA_CTRL 0x1238 -#define VDEC_B_MAN_AGC_CTRL 0x123C -#define VDEC_B_DFE_CTRL1 0x1240 -#define VDEC_B_DFE_CTRL2 0x1244 -#define VDEC_B_DFE_CTRL3 0x1248 -#define VDEC_B_PLL_CTRL 0x124C +#define VDEC_B_FIELD_COUNT 0x122C +#define VDEC_B_HSCALE_CTRL 0x1230 +#define VDEC_B_VSCALE_CTRL 0x1234 +#define VDEC_B_MAN_VGA_CTRL 0x1238 +#define VDEC_B_MAN_AGC_CTRL 0x123C +#define VDEC_B_DFE_CTRL1 0x1240 +#define VDEC_B_DFE_CTRL2 0x1244 +#define VDEC_B_DFE_CTRL3 0x1248 +#define VDEC_B_PLL_CTRL 0x124C #define VDEC_B_PLL_CTRL_FAST 0x1250 -#define VDEC_B_HTL_CTRL 0x1254 -#define VDEC_B_SRC_CFG 0x1258 -#define VDEC_B_SC_STEP_SIZE 0x125C +#define VDEC_B_HTL_CTRL 0x1254 +#define VDEC_B_SRC_CFG 0x1258 +#define VDEC_B_SC_STEP_SIZE 0x125C #define VDEC_B_SC_CONVERGE_CTRL 0x1260 -#define VDEC_B_SC_LOOP_CTRL 0x1264 +#define VDEC_B_SC_LOOP_CTRL 0x1264 #define VDEC_B_COMB_2D_HFS_CFG 0x1268 #define VDEC_B_COMB_2D_HFD_CFG 0x126C #define VDEC_B_COMB_2D_LF_CFG 0x1270 #define VDEC_B_COMB_2D_BLEND 0x1274 #define VDEC_B_COMB_MISC_CTRL 0x1278 -#define VDEC_B_COMB_FLAT_THRESH_CTRL 0x127C -#define VDEC_B_COMB_TEST 0x1280 -#define VDEC_B_BP_MISC_CTRL 0x1284 -#define VDEC_B_VCR_DET_CTRL 0x1288 +#define VDEC_B_COMB_FLAT_THRESH_CTRL 0x127C +#define VDEC_B_COMB_TEST 0x1280 +#define VDEC_B_BP_MISC_CTRL 0x1284 +#define VDEC_B_VCR_DET_CTRL 0x1288 #define VDEC_B_NOISE_DET_CTRL 0x128C #define VDEC_B_COMB_FLAT_NOISE_CTRL 0x1290 -#define VDEC_B_VERSION 0x13F8 +#define VDEC_B_VERSION 0x13F8 #define VDEC_B_SOFT_RST_CTRL 0x13FC /* Video Decoder C Registers */ -#define VDEC_C_MODE_CTRL 0x1400 -#define VDEC_C_OUT_CTRL1 0x1404 -#define VDEC_C_OUT_CTRL_NS 0x1408 -#define VDEC_C_GEN_STAT 0x140C +#define VDEC_C_MODE_CTRL 0x1400 +#define VDEC_C_OUT_CTRL1 0x1404 +#define VDEC_C_OUT_CTRL_NS 0x1408 +#define VDEC_C_GEN_STAT 0x140C #define VDEC_C_INT_STAT_MASK 0x1410 -#define VDEC_C_LUMA_CTRL 0x1414 -#define VDEC_C_CHROMA_CTRL 0x1418 -#define VDEC_C_CRUSH_CTRL 0x141C +#define VDEC_C_LUMA_CTRL 0x1414 +#define VDEC_C_CHROMA_CTRL 0x1418 +#define VDEC_C_CRUSH_CTRL 0x141C #define VDEC_C_HORIZ_TIM_CTRL 0x1420 #define VDEC_C_VERT_TIM_CTRL 0x1424 #define VDEC_C_MISC_TIM_CTRL 0x1428 -#define VDEC_C_FIELD_COUNT 0x142C -#define VDEC_C_HSCALE_CTRL 0x1430 -#define VDEC_C_VSCALE_CTRL 0x1434 -#define VDEC_C_MAN_VGA_CTRL 0x1438 -#define VDEC_C_MAN_AGC_CTRL 0x143C -#define VDEC_C_DFE_CTRL1 0x1440 -#define VDEC_C_DFE_CTRL2 0x1444 -#define VDEC_C_DFE_CTRL3 0x1448 -#define VDEC_C_PLL_CTRL 0x144C +#define VDEC_C_FIELD_COUNT 0x142C +#define VDEC_C_HSCALE_CTRL 0x1430 +#define VDEC_C_VSCALE_CTRL 0x1434 +#define VDEC_C_MAN_VGA_CTRL 0x1438 +#define VDEC_C_MAN_AGC_CTRL 0x143C +#define VDEC_C_DFE_CTRL1 0x1440 +#define VDEC_C_DFE_CTRL2 0x1444 +#define VDEC_C_DFE_CTRL3 0x1448 +#define VDEC_C_PLL_CTRL 0x144C #define VDEC_C_PLL_CTRL_FAST 0x1450 -#define VDEC_C_HTL_CTRL 0x1454 -#define VDEC_C_SRC_CFG 0x1458 -#define VDEC_C_SC_STEP_SIZE 0x145C +#define VDEC_C_HTL_CTRL 0x1454 +#define VDEC_C_SRC_CFG 0x1458 +#define VDEC_C_SC_STEP_SIZE 0x145C #define VDEC_C_SC_CONVERGE_CTRL 0x1460 -#define VDEC_C_SC_LOOP_CTRL 0x1464 +#define VDEC_C_SC_LOOP_CTRL 0x1464 #define VDEC_C_COMB_2D_HFS_CFG 0x1468 #define VDEC_C_COMB_2D_HFD_CFG 0x146C #define VDEC_C_COMB_2D_LF_CFG 0x1470 #define VDEC_C_COMB_2D_BLEND 0x1474 #define VDEC_C_COMB_MISC_CTRL 0x1478 -#define VDEC_C_COMB_FLAT_THRESH_CTRL 0x147C -#define VDEC_C_COMB_TEST 0x1480 -#define VDEC_C_BP_MISC_CTRL 0x1484 -#define VDEC_C_VCR_DET_CTRL 0x1488 +#define VDEC_C_COMB_FLAT_THRESH_CTRL 0x147C +#define VDEC_C_COMB_TEST 0x1480 +#define VDEC_C_BP_MISC_CTRL 0x1484 +#define VDEC_C_VCR_DET_CTRL 0x1488 #define VDEC_C_NOISE_DET_CTRL 0x148C #define VDEC_C_COMB_FLAT_NOISE_CTRL 0x1490 -#define VDEC_C_VERSION 0x15F8 +#define VDEC_C_VERSION 0x15F8 #define VDEC_C_SOFT_RST_CTRL 0x15FC /* Video Decoder D Registers */ -#define VDEC_D_MODE_CTRL 0x1600 -#define VDEC_D_OUT_CTRL1 0x1604 -#define VDEC_D_OUT_CTRL_NS 0x1608 -#define VDEC_D_GEN_STAT 0x160C +#define VDEC_D_MODE_CTRL 0x1600 +#define VDEC_D_OUT_CTRL1 0x1604 +#define VDEC_D_OUT_CTRL_NS 0x1608 +#define VDEC_D_GEN_STAT 0x160C #define VDEC_D_INT_STAT_MASK 0x1610 -#define VDEC_D_LUMA_CTRL 0x1614 -#define VDEC_D_CHROMA_CTRL 0x1618 -#define VDEC_D_CRUSH_CTRL 0x161C +#define VDEC_D_LUMA_CTRL 0x1614 +#define VDEC_D_CHROMA_CTRL 0x1618 +#define VDEC_D_CRUSH_CTRL 0x161C #define VDEC_D_HORIZ_TIM_CTRL 0x1620 #define VDEC_D_VERT_TIM_CTRL 0x1624 #define VDEC_D_MISC_TIM_CTRL 0x1628 -#define VDEC_D_FIELD_COUNT 0x162C -#define VDEC_D_HSCALE_CTRL 0x1630 -#define VDEC_D_VSCALE_CTRL 0x1634 -#define VDEC_D_MAN_VGA_CTRL 0x1638 -#define VDEC_D_MAN_AGC_CTRL 0x163C -#define VDEC_D_DFE_CTRL1 0x1640 -#define VDEC_D_DFE_CTRL2 0x1644 -#define VDEC_D_DFE_CTRL3 0x1648 -#define VDEC_D_PLL_CTRL 0x164C +#define VDEC_D_FIELD_COUNT 0x162C +#define VDEC_D_HSCALE_CTRL 0x1630 +#define VDEC_D_VSCALE_CTRL 0x1634 +#define VDEC_D_MAN_VGA_CTRL 0x1638 +#define VDEC_D_MAN_AGC_CTRL 0x163C +#define VDEC_D_DFE_CTRL1 0x1640 +#define VDEC_D_DFE_CTRL2 0x1644 +#define VDEC_D_DFE_CTRL3 0x1648 +#define VDEC_D_PLL_CTRL 0x164C #define VDEC_D_PLL_CTRL_FAST 0x1650 -#define VDEC_D_HTL_CTRL 0x1654 -#define VDEC_D_SRC_CFG 0x1658 -#define VDEC_D_SC_STEP_SIZE 0x165C +#define VDEC_D_HTL_CTRL 0x1654 +#define VDEC_D_SRC_CFG 0x1658 +#define VDEC_D_SC_STEP_SIZE 0x165C #define VDEC_D_SC_CONVERGE_CTRL 0x1660 -#define VDEC_D_SC_LOOP_CTRL 0x1664 +#define VDEC_D_SC_LOOP_CTRL 0x1664 #define VDEC_D_COMB_2D_HFS_CFG 0x1668 #define VDEC_D_COMB_2D_HFD_CFG 0x166C #define VDEC_D_COMB_2D_LF_CFG 0x1670 #define VDEC_D_COMB_2D_BLEND 0x1674 #define VDEC_D_COMB_MISC_CTRL 0x1678 -#define VDEC_D_COMB_FLAT_THRESH_CTRL 0x167C -#define VDEC_D_COMB_TEST 0x1680 -#define VDEC_D_BP_MISC_CTRL 0x1684 -#define VDEC_D_VCR_DET_CTRL 0x1688 +#define VDEC_D_COMB_FLAT_THRESH_CTRL 0x167C +#define VDEC_D_COMB_TEST 0x1680 +#define VDEC_D_BP_MISC_CTRL 0x1684 +#define VDEC_D_VCR_DET_CTRL 0x1688 #define VDEC_D_NOISE_DET_CTRL 0x168C #define VDEC_D_COMB_FLAT_NOISE_CTRL 0x1690 -#define VDEC_D_VERSION 0x17F8 +#define VDEC_D_VERSION 0x17F8 #define VDEC_D_SOFT_RST_CTRL 0x17FC /* Video Decoder E Registers */ -#define VDEC_E_MODE_CTRL 0x1800 -#define VDEC_E_OUT_CTRL1 0x1804 -#define VDEC_E_OUT_CTRL_NS 0x1808 -#define VDEC_E_GEN_STAT 0x180C +#define VDEC_E_MODE_CTRL 0x1800 +#define VDEC_E_OUT_CTRL1 0x1804 +#define VDEC_E_OUT_CTRL_NS 0x1808 +#define VDEC_E_GEN_STAT 0x180C #define VDEC_E_INT_STAT_MASK 0x1810 -#define VDEC_E_LUMA_CTRL 0x1814 -#define VDEC_E_CHROMA_CTRL 0x1818 -#define VDEC_E_CRUSH_CTRL 0x181C +#define VDEC_E_LUMA_CTRL 0x1814 +#define VDEC_E_CHROMA_CTRL 0x1818 +#define VDEC_E_CRUSH_CTRL 0x181C #define VDEC_E_HORIZ_TIM_CTRL 0x1820 #define VDEC_E_VERT_TIM_CTRL 0x1824 #define VDEC_E_MISC_TIM_CTRL 0x1828 -#define VDEC_E_FIELD_COUNT 0x182C -#define VDEC_E_HSCALE_CTRL 0x1830 -#define VDEC_E_VSCALE_CTRL 0x1834 -#define VDEC_E_MAN_VGA_CTRL 0x1838 -#define VDEC_E_MAN_AGC_CTRL 0x183C -#define VDEC_E_DFE_CTRL1 0x1840 -#define VDEC_E_DFE_CTRL2 0x1844 -#define VDEC_E_DFE_CTRL3 0x1848 -#define VDEC_E_PLL_CTRL 0x184C +#define VDEC_E_FIELD_COUNT 0x182C +#define VDEC_E_HSCALE_CTRL 0x1830 +#define VDEC_E_VSCALE_CTRL 0x1834 +#define VDEC_E_MAN_VGA_CTRL 0x1838 +#define VDEC_E_MAN_AGC_CTRL 0x183C +#define VDEC_E_DFE_CTRL1 0x1840 +#define VDEC_E_DFE_CTRL2 0x1844 +#define VDEC_E_DFE_CTRL3 0x1848 +#define VDEC_E_PLL_CTRL 0x184C #define VDEC_E_PLL_CTRL_FAST 0x1850 -#define VDEC_E_HTL_CTRL 0x1854 -#define VDEC_E_SRC_CFG 0x1858 -#define VDEC_E_SC_STEP_SIZE 0x185C +#define VDEC_E_HTL_CTRL 0x1854 +#define VDEC_E_SRC_CFG 0x1858 +#define VDEC_E_SC_STEP_SIZE 0x185C #define VDEC_E_SC_CONVERGE_CTRL 0x1860 -#define VDEC_E_SC_LOOP_CTRL 0x1864 +#define VDEC_E_SC_LOOP_CTRL 0x1864 #define VDEC_E_COMB_2D_HFS_CFG 0x1868 #define VDEC_E_COMB_2D_HFD_CFG 0x186C #define VDEC_E_COMB_2D_LF_CFG 0x1870 #define VDEC_E_COMB_2D_BLEND 0x1874 #define VDEC_E_COMB_MISC_CTRL 0x1878 -#define VDEC_E_COMB_FLAT_THRESH_CTRL 0x187C -#define VDEC_E_COMB_TEST 0x1880 -#define VDEC_E_BP_MISC_CTRL 0x1884 -#define VDEC_E_VCR_DET_CTRL 0x1888 +#define VDEC_E_COMB_FLAT_THRESH_CTRL 0x187C +#define VDEC_E_COMB_TEST 0x1880 +#define VDEC_E_BP_MISC_CTRL 0x1884 +#define VDEC_E_VCR_DET_CTRL 0x1888 #define VDEC_E_NOISE_DET_CTRL 0x188C #define VDEC_E_COMB_FLAT_NOISE_CTRL 0x1890 -#define VDEC_E_VERSION 0x19F8 +#define VDEC_E_VERSION 0x19F8 #define VDEC_E_SOFT_RST_CTRL 0x19FC /* Video Decoder F Registers */ -#define VDEC_F_MODE_CTRL 0x1A00 -#define VDEC_F_OUT_CTRL1 0x1A04 -#define VDEC_F_OUT_CTRL_NS 0x1A08 -#define VDEC_F_GEN_STAT 0x1A0C +#define VDEC_F_MODE_CTRL 0x1A00 +#define VDEC_F_OUT_CTRL1 0x1A04 +#define VDEC_F_OUT_CTRL_NS 0x1A08 +#define VDEC_F_GEN_STAT 0x1A0C #define VDEC_F_INT_STAT_MASK 0x1A10 -#define VDEC_F_LUMA_CTRL 0x1A14 -#define VDEC_F_CHROMA_CTRL 0x1A18 -#define VDEC_F_CRUSH_CTRL 0x1A1C +#define VDEC_F_LUMA_CTRL 0x1A14 +#define VDEC_F_CHROMA_CTRL 0x1A18 +#define VDEC_F_CRUSH_CTRL 0x1A1C #define VDEC_F_HORIZ_TIM_CTRL 0x1A20 #define VDEC_F_VERT_TIM_CTRL 0x1A24 #define VDEC_F_MISC_TIM_CTRL 0x1A28 -#define VDEC_F_FIELD_COUNT 0x1A2C -#define VDEC_F_HSCALE_CTRL 0x1A30 -#define VDEC_F_VSCALE_CTRL 0x1A34 -#define VDEC_F_MAN_VGA_CTRL 0x1A38 -#define VDEC_F_MAN_AGC_CTRL 0x1A3C -#define VDEC_F_DFE_CTRL1 0x1A40 -#define VDEC_F_DFE_CTRL2 0x1A44 -#define VDEC_F_DFE_CTRL3 0x1A48 -#define VDEC_F_PLL_CTRL 0x1A4C +#define VDEC_F_FIELD_COUNT 0x1A2C +#define VDEC_F_HSCALE_CTRL 0x1A30 +#define VDEC_F_VSCALE_CTRL 0x1A34 +#define VDEC_F_MAN_VGA_CTRL 0x1A38 +#define VDEC_F_MAN_AGC_CTRL 0x1A3C +#define VDEC_F_DFE_CTRL1 0x1A40 +#define VDEC_F_DFE_CTRL2 0x1A44 +#define VDEC_F_DFE_CTRL3 0x1A48 +#define VDEC_F_PLL_CTRL 0x1A4C #define VDEC_F_PLL_CTRL_FAST 0x1A50 -#define VDEC_F_HTL_CTRL 0x1A54 -#define VDEC_F_SRC_CFG 0x1A58 -#define VDEC_F_SC_STEP_SIZE 0x1A5C +#define VDEC_F_HTL_CTRL 0x1A54 +#define VDEC_F_SRC_CFG 0x1A58 +#define VDEC_F_SC_STEP_SIZE 0x1A5C #define VDEC_F_SC_CONVERGE_CTRL 0x1A60 -#define VDEC_F_SC_LOOP_CTRL 0x1A64 +#define VDEC_F_SC_LOOP_CTRL 0x1A64 #define VDEC_F_COMB_2D_HFS_CFG 0x1A68 #define VDEC_F_COMB_2D_HFD_CFG 0x1A6C #define VDEC_F_COMB_2D_LF_CFG 0x1A70 #define VDEC_F_COMB_2D_BLEND 0x1A74 #define VDEC_F_COMB_MISC_CTRL 0x1A78 -#define VDEC_F_COMB_FLAT_THRESH_CTRL 0x1A7C -#define VDEC_F_COMB_TEST 0x1A80 -#define VDEC_F_BP_MISC_CTRL 0x1A84 -#define VDEC_F_VCR_DET_CTRL 0x1A88 +#define VDEC_F_COMB_FLAT_THRESH_CTRL 0x1A7C +#define VDEC_F_COMB_TEST 0x1A80 +#define VDEC_F_BP_MISC_CTRL 0x1A84 +#define VDEC_F_VCR_DET_CTRL 0x1A88 #define VDEC_F_NOISE_DET_CTRL 0x1A8C #define VDEC_F_COMB_FLAT_NOISE_CTRL 0x1A90 -#define VDEC_F_VERSION 0x1BF8 +#define VDEC_F_VERSION 0x1BF8 #define VDEC_F_SOFT_RST_CTRL 0x1BFC /* Video Decoder G Registers */ -#define VDEC_G_MODE_CTRL 0x1C00 -#define VDEC_G_OUT_CTRL1 0x1C04 -#define VDEC_G_OUT_CTRL_NS 0x1C08 -#define VDEC_G_GEN_STAT 0x1C0C +#define VDEC_G_MODE_CTRL 0x1C00 +#define VDEC_G_OUT_CTRL1 0x1C04 +#define VDEC_G_OUT_CTRL_NS 0x1C08 +#define VDEC_G_GEN_STAT 0x1C0C #define VDEC_G_INT_STAT_MASK 0x1C10 -#define VDEC_G_LUMA_CTRL 0x1C14 -#define VDEC_G_CHROMA_CTRL 0x1C18 -#define VDEC_G_CRUSH_CTRL 0x1C1C +#define VDEC_G_LUMA_CTRL 0x1C14 +#define VDEC_G_CHROMA_CTRL 0x1C18 +#define VDEC_G_CRUSH_CTRL 0x1C1C #define VDEC_G_HORIZ_TIM_CTRL 0x1C20 #define VDEC_G_VERT_TIM_CTRL 0x1C24 #define VDEC_G_MISC_TIM_CTRL 0x1C28 -#define VDEC_G_FIELD_COUNT 0x1C2C -#define VDEC_G_HSCALE_CTRL 0x1C30 -#define VDEC_G_VSCALE_CTRL 0x1C34 -#define VDEC_G_MAN_VGA_CTRL 0x1C38 -#define VDEC_G_MAN_AGC_CTRL 0x1C3C -#define VDEC_G_DFE_CTRL1 0x1C40 -#define VDEC_G_DFE_CTRL2 0x1C44 -#define VDEC_G_DFE_CTRL3 0x1C48 -#define VDEC_G_PLL_CTRL 0x1C4C +#define VDEC_G_FIELD_COUNT 0x1C2C +#define VDEC_G_HSCALE_CTRL 0x1C30 +#define VDEC_G_VSCALE_CTRL 0x1C34 +#define VDEC_G_MAN_VGA_CTRL 0x1C38 +#define VDEC_G_MAN_AGC_CTRL 0x1C3C +#define VDEC_G_DFE_CTRL1 0x1C40 +#define VDEC_G_DFE_CTRL2 0x1C44 +#define VDEC_G_DFE_CTRL3 0x1C48 +#define VDEC_G_PLL_CTRL 0x1C4C #define VDEC_G_PLL_CTRL_FAST 0x1C50 -#define VDEC_G_HTL_CTRL 0x1C54 -#define VDEC_G_SRC_CFG 0x1C58 -#define VDEC_G_SC_STEP_SIZE 0x1C5C +#define VDEC_G_HTL_CTRL 0x1C54 +#define VDEC_G_SRC_CFG 0x1C58 +#define VDEC_G_SC_STEP_SIZE 0x1C5C #define VDEC_G_SC_CONVERGE_CTRL 0x1C60 -#define VDEC_G_SC_LOOP_CTRL 0x1C64 +#define VDEC_G_SC_LOOP_CTRL 0x1C64 #define VDEC_G_COMB_2D_HFS_CFG 0x1C68 #define VDEC_G_COMB_2D_HFD_CFG 0x1C6C #define VDEC_G_COMB_2D_LF_CFG 0x1C70 #define VDEC_G_COMB_2D_BLEND 0x1C74 #define VDEC_G_COMB_MISC_CTRL 0x1C78 -#define VDEC_G_COMB_FLAT_THRESH_CTRL 0x1C7C -#define VDEC_G_COMB_TEST 0x1C80 -#define VDEC_G_BP_MISC_CTRL 0x1C84 -#define VDEC_G_VCR_DET_CTRL 0x1C88 +#define VDEC_G_COMB_FLAT_THRESH_CTRL 0x1C7C +#define VDEC_G_COMB_TEST 0x1C80 +#define VDEC_G_BP_MISC_CTRL 0x1C84 +#define VDEC_G_VCR_DET_CTRL 0x1C88 #define VDEC_G_NOISE_DET_CTRL 0x1C8C #define VDEC_G_COMB_FLAT_NOISE_CTRL 0x1C90 -#define VDEC_G_VERSION 0x1DF8 +#define VDEC_G_VERSION 0x1DF8 #define VDEC_G_SOFT_RST_CTRL 0x1DFC -/* Video Decoder H Registers */ -#define VDEC_H_MODE_CTRL 0x1E00 -#define VDEC_H_OUT_CTRL1 0x1E04 -#define VDEC_H_OUT_CTRL_NS 0x1E08 -#define VDEC_H_GEN_STAT 0x1E0C +/* Video Decoder H Registers */ +#define VDEC_H_MODE_CTRL 0x1E00 +#define VDEC_H_OUT_CTRL1 0x1E04 +#define VDEC_H_OUT_CTRL_NS 0x1E08 +#define VDEC_H_GEN_STAT 0x1E0C #define VDEC_H_INT_STAT_MASK 0x1E1E -#define VDEC_H_LUMA_CTRL 0x1E14 -#define VDEC_H_CHROMA_CTRL 0x1E18 -#define VDEC_H_CRUSH_CTRL 0x1E1C +#define VDEC_H_LUMA_CTRL 0x1E14 +#define VDEC_H_CHROMA_CTRL 0x1E18 +#define VDEC_H_CRUSH_CTRL 0x1E1C #define VDEC_H_HORIZ_TIM_CTRL 0x1E20 #define VDEC_H_VERT_TIM_CTRL 0x1E24 #define VDEC_H_MISC_TIM_CTRL 0x1E28 -#define VDEC_H_FIELD_COUNT 0x1E2C -#define VDEC_H_HSCALE_CTRL 0x1E30 -#define VDEC_H_VSCALE_CTRL 0x1E34 -#define VDEC_H_MAN_VGA_CTRL 0x1E38 -#define VDEC_H_MAN_AGC_CTRL 0x1E3C -#define VDEC_H_DFE_CTRL1 0x1E40 -#define VDEC_H_DFE_CTRL2 0x1E44 -#define VDEC_H_DFE_CTRL3 0x1E48 -#define VDEC_H_PLL_CTRL 0x1E4C +#define VDEC_H_FIELD_COUNT 0x1E2C +#define VDEC_H_HSCALE_CTRL 0x1E30 +#define VDEC_H_VSCALE_CTRL 0x1E34 +#define VDEC_H_MAN_VGA_CTRL 0x1E38 +#define VDEC_H_MAN_AGC_CTRL 0x1E3C +#define VDEC_H_DFE_CTRL1 0x1E40 +#define VDEC_H_DFE_CTRL2 0x1E44 +#define VDEC_H_DFE_CTRL3 0x1E48 +#define VDEC_H_PLL_CTRL 0x1E4C #define VDEC_H_PLL_CTRL_FAST 0x1E50 -#define VDEC_H_HTL_CTRL 0x1E54 -#define VDEC_H_SRC_CFG 0x1E58 -#define VDEC_H_SC_STEP_SIZE 0x1E5C +#define VDEC_H_HTL_CTRL 0x1E54 +#define VDEC_H_SRC_CFG 0x1E58 +#define VDEC_H_SC_STEP_SIZE 0x1E5C #define VDEC_H_SC_CONVERGE_CTRL 0x1E60 -#define VDEC_H_SC_LOOP_CTRL 0x1E64 +#define VDEC_H_SC_LOOP_CTRL 0x1E64 #define VDEC_H_COMB_2D_HFS_CFG 0x1E68 #define VDEC_H_COMB_2D_HFD_CFG 0x1E6C #define VDEC_H_COMB_2D_LF_CFG 0x1E70 #define VDEC_H_COMB_2D_BLEND 0x1E74 #define VDEC_H_COMB_MISC_CTRL 0x1E78 -#define VDEC_H_COMB_FLAT_THRESH_CTRL 0x1E7C -#define VDEC_H_COMB_TEST 0x1E80 -#define VDEC_H_BP_MISC_CTRL 0x1E84 -#define VDEC_H_VCR_DET_CTRL 0x1E88 +#define VDEC_H_COMB_FLAT_THRESH_CTRL 0x1E7C +#define VDEC_H_COMB_TEST 0x1E80 +#define VDEC_H_BP_MISC_CTRL 0x1E84 +#define VDEC_H_VCR_DET_CTRL 0x1E88 #define VDEC_H_NOISE_DET_CTRL 0x1E8C #define VDEC_H_COMB_FLAT_NOISE_CTRL 0x1E90 -#define VDEC_H_VERSION 0x1FF8 +#define VDEC_H_VERSION 0x1FF8 #define VDEC_H_SOFT_RST_CTRL 0x1FFC /*****************************************************************************/ /* LUMA_CTRL register fields */ -#define VDEC_A_BRITE_CTRL 0x1014 +#define VDEC_A_BRITE_CTRL 0x1014 #define VDEC_A_CNTRST_CTRL 0x1015 #define VDEC_A_PEAK_SEL 0x1016 -- cgit v0.10.2 From 09c35440308138059e23a9a8e04f053094fb81a8 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:38 -0300 Subject: [media] cx25821-medusa-video.c: Fix comment Delete part of the comment that is not checked in code. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-medusa-video.c b/drivers/media/video/cx25821/cx25821-medusa-video.c index fc780d0..48c62c9 100644 --- a/drivers/media/video/cx25821/cx25821-medusa-video.c +++ b/drivers/media/video/cx25821/cx25821-medusa-video.c @@ -499,7 +499,7 @@ void medusa_set_resolution(struct cx25821_dev *dev, int width, mutex_lock(&dev->lock); - /* validate the width - cannot be negative */ + /* validate the width */ if (width > MAX_WIDTH) { pr_info("%s(): width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n", __func__, width, MAX_WIDTH); -- cgit v0.10.2 From 49faae869fb1647b8201859602e11bed18230702 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:39 -0300 Subject: [media] cx25821-medusa-video.c: Move operators Plase operators in complex expressions at the end of the lines to preserve consistency. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-medusa-video.c b/drivers/media/video/cx25821/cx25821-medusa-video.c index 48c62c9..1ae0e8a 100644 --- a/drivers/media/video/cx25821/cx25821-medusa-video.c +++ b/drivers/media/video/cx25821/cx25821-medusa-video.c @@ -654,8 +654,8 @@ int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder) u32 val = 0, tmp = 0; mutex_lock(&dev->lock); - if ((brightness > VIDEO_PROCAMP_MAX) - || (brightness < VIDEO_PROCAMP_MIN)) { + if ((brightness > VIDEO_PROCAMP_MAX) || + (brightness < VIDEO_PROCAMP_MIN)) { mutex_unlock(&dev->lock); return -1; } @@ -743,8 +743,8 @@ int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder) mutex_lock(&dev->lock); - if ((saturation > VIDEO_PROCAMP_MAX) - || (saturation < VIDEO_PROCAMP_MIN)) { + if ((saturation > VIDEO_PROCAMP_MAX) || + (saturation < VIDEO_PROCAMP_MIN)) { mutex_unlock(&dev->lock); return -1; } -- cgit v0.10.2 From 14098bc73080fcb945423a4fd36eec0a89fb35bd Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:40 -0300 Subject: [media] cx25821-medusa-video.c: Change line endings Change obscure line endings to less obscure ones. (improve readability) Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-medusa-video.c b/drivers/media/video/cx25821/cx25821-medusa-video.c index 1ae0e8a..298a68d 100644 --- a/drivers/media/video/cx25821/cx25821-medusa-video.c +++ b/drivers/media/video/cx25821/cx25821-medusa-video.c @@ -99,82 +99,67 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev) for (i = 0; i < MAX_DECODERS; i++) { /* set video format NTSC-M */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), - &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + MODE_CTRL + (0x200 * i), &tmp); value &= 0xFFFFFFF0; /* enable the fast locking mode bit[16] */ value |= 0x10001; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), - value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + MODE_CTRL + (0x200 * i), value); /* resolution NTSC 720x480 */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], - HORIZ_TIM_CTRL + (0x200 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + HORIZ_TIM_CTRL + (0x200 * i), &tmp); value &= 0x00C00C00; value |= 0x612D0074; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - HORIZ_TIM_CTRL + (0x200 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + HORIZ_TIM_CTRL + (0x200 * i), value); - value = - cx25821_i2c_read(&dev->i2c_bus[0], - VERT_TIM_CTRL + (0x200 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + VERT_TIM_CTRL + (0x200 * i), &tmp); value &= 0x00C00C00; value |= 0x1C1E001A; /* vblank_cnt + 2 to get camera ID */ - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - VERT_TIM_CTRL + (0x200 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + VERT_TIM_CTRL + (0x200 * i), value); /* chroma subcarrier step size */ - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - SC_STEP_SIZE + (0x200 * i), 0x43E00000); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + SC_STEP_SIZE + (0x200 * i), 0x43E00000); /* enable VIP optional active */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], - OUT_CTRL_NS + (0x200 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + OUT_CTRL_NS + (0x200 * i), &tmp); value &= 0xFFFBFFFF; value |= 0x00040000; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - OUT_CTRL_NS + (0x200 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + OUT_CTRL_NS + (0x200 * i), value); /* enable VIP optional active (VIP_OPT_AL) for direct output. */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), - &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + OUT_CTRL1 + (0x200 * i), &tmp); value &= 0xFFFBFFFF; value |= 0x00040000; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), - value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + OUT_CTRL1 + (0x200 * i), value); /* * clear VPRES_VERT_EN bit, fixes the chroma run away problem * when the input switching rate < 16 fields */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], - MISC_TIM_CTRL + (0x200 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + MISC_TIM_CTRL + (0x200 * i), &tmp); /* disable special play detection */ value = setBitAtPos(value, 14); value = clearBitAtPos(value, 15); - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - MISC_TIM_CTRL + (0x200 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + MISC_TIM_CTRL + (0x200 * i), value); /* set vbi_gate_en to 0 */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), - &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + DFE_CTRL1 + (0x200 * i), &tmp); value = clearBitAtPos(value, 29); - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), - value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + DFE_CTRL1 + (0x200 * i), value); /* Enable the generation of blue field output if no video */ medusa_enable_bluefield_output(dev, i, 1); @@ -182,61 +167,49 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev) for (i = 0; i < MAX_ENCODERS; i++) { /* NTSC hclock */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], - DENC_A_REG_1 + (0x100 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_1 + (0x100 * i), &tmp); value &= 0xF000FC00; value |= 0x06B402D0; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - DENC_A_REG_1 + (0x100 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_1 + (0x100 * i), value); /* burst begin and burst end */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], - DENC_A_REG_2 + (0x100 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_2 + (0x100 * i), &tmp); value &= 0xFF000000; value |= 0x007E9054; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - DENC_A_REG_2 + (0x100 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_2 + (0x100 * i), value); - value = - cx25821_i2c_read(&dev->i2c_bus[0], - DENC_A_REG_3 + (0x100 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_3 + (0x100 * i), &tmp); value &= 0xFC00FE00; value |= 0x00EC00F0; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - DENC_A_REG_3 + (0x100 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_3 + (0x100 * i), value); /* set NTSC vblank, no phase alternation, 7.5 IRE pedestal */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], - DENC_A_REG_4 + (0x100 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_4 + (0x100 * i), &tmp); value &= 0x00FCFFFF; value |= 0x13020000; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - DENC_A_REG_4 + (0x100 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_4 + (0x100 * i), value); - value = - cx25821_i2c_read(&dev->i2c_bus[0], - DENC_A_REG_5 + (0x100 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_5 + (0x100 * i), &tmp); value &= 0xFFFF0000; value |= 0x0000E575; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - DENC_A_REG_5 + (0x100 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_5 + (0x100 * i), value); - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - DENC_A_REG_6 + (0x100 * i), 0x009A89C1); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_6 + (0x100 * i), 0x009A89C1); /* Subcarrier Increment */ - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - DENC_A_REG_7 + (0x100 * i), 0x21F07C1F); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_7 + (0x100 * i), 0x21F07C1F); } /* set picture resolutions */ @@ -261,34 +234,27 @@ static int medusa_PALCombInit(struct cx25821_dev *dev, int dec) u32 value = 0, tmp = 0; /* Setup for 2D threshold */ - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG + (0x200 * dec), - 0x20002861); - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG + (0x200 * dec), - 0x20002861); - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG + (0x200 * dec), - 0x200A1023); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + COMB_2D_HFS_CFG + (0x200 * dec), 0x20002861); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + COMB_2D_HFD_CFG + (0x200 * dec), 0x20002861); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + COMB_2D_LF_CFG + (0x200 * dec), 0x200A1023); /* Setup flat chroma and luma thresholds */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], - COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp); value &= 0x06230000; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - COMB_FLAT_THRESH_CTRL + (0x200 * dec), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + COMB_FLAT_THRESH_CTRL + (0x200 * dec), value); /* set comb 2D blend */ - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND + (0x200 * dec), - 0x210F0F0F); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + COMB_2D_BLEND + (0x200 * dec), 0x210F0F0F); /* COMB MISC CONTROL */ - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL + (0x200 * dec), - 0x41120A7F); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + COMB_MISC_CTRL + (0x200 * dec), 0x41120A7F); return ret_val; } @@ -304,83 +270,68 @@ static int medusa_initialize_pal(struct cx25821_dev *dev) for (i = 0; i < MAX_DECODERS; i++) { /* set video format PAL-BDGHI */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), - &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + MODE_CTRL + (0x200 * i), &tmp); value &= 0xFFFFFFF0; /* enable the fast locking mode bit[16] */ value |= 0x10004; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), - value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + MODE_CTRL + (0x200 * i), value); /* resolution PAL 720x576 */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], - HORIZ_TIM_CTRL + (0x200 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + HORIZ_TIM_CTRL + (0x200 * i), &tmp); value &= 0x00C00C00; value |= 0x632D007D; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - HORIZ_TIM_CTRL + (0x200 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + HORIZ_TIM_CTRL + (0x200 * i), value); /* vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], - VERT_TIM_CTRL + (0x200 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + VERT_TIM_CTRL + (0x200 * i), &tmp); value &= 0x00C00C00; value |= 0x28240026; /* vblank_cnt + 2 to get camera ID */ - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - VERT_TIM_CTRL + (0x200 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + VERT_TIM_CTRL + (0x200 * i), value); /* chroma subcarrier step size */ - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - SC_STEP_SIZE + (0x200 * i), 0x5411E2D0); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + SC_STEP_SIZE + (0x200 * i), 0x5411E2D0); /* enable VIP optional active */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], - OUT_CTRL_NS + (0x200 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + OUT_CTRL_NS + (0x200 * i), &tmp); value &= 0xFFFBFFFF; value |= 0x00040000; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - OUT_CTRL_NS + (0x200 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + OUT_CTRL_NS + (0x200 * i), value); /* enable VIP optional active (VIP_OPT_AL) for direct output. */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), - &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + OUT_CTRL1 + (0x200 * i), &tmp); value &= 0xFFFBFFFF; value |= 0x00040000; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), - value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + OUT_CTRL1 + (0x200 * i), value); /* * clear VPRES_VERT_EN bit, fixes the chroma run away problem * when the input switching rate < 16 fields */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], - MISC_TIM_CTRL + (0x200 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + MISC_TIM_CTRL + (0x200 * i), &tmp); /* disable special play detection */ value = setBitAtPos(value, 14); value = clearBitAtPos(value, 15); - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - MISC_TIM_CTRL + (0x200 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + MISC_TIM_CTRL + (0x200 * i), value); /* set vbi_gate_en to 0 */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), - &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + DFE_CTRL1 + (0x200 * i), &tmp); value = clearBitAtPos(value, 29); - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), - value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + DFE_CTRL1 + (0x200 * i), value); medusa_PALCombInit(dev, i); @@ -390,62 +341,50 @@ static int medusa_initialize_pal(struct cx25821_dev *dev) for (i = 0; i < MAX_ENCODERS; i++) { /* PAL hclock */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], - DENC_A_REG_1 + (0x100 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_1 + (0x100 * i), &tmp); value &= 0xF000FC00; value |= 0x06C002D0; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - DENC_A_REG_1 + (0x100 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_1 + (0x100 * i), value); /* burst begin and burst end */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], - DENC_A_REG_2 + (0x100 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_2 + (0x100 * i), &tmp); value &= 0xFF000000; value |= 0x007E9754; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - DENC_A_REG_2 + (0x100 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_2 + (0x100 * i), value); /* hblank and vactive */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], - DENC_A_REG_3 + (0x100 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_3 + (0x100 * i), &tmp); value &= 0xFC00FE00; value |= 0x00FC0120; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - DENC_A_REG_3 + (0x100 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_3 + (0x100 * i), value); /* set PAL vblank, phase alternation, 0 IRE pedestal */ - value = - cx25821_i2c_read(&dev->i2c_bus[0], - DENC_A_REG_4 + (0x100 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_4 + (0x100 * i), &tmp); value &= 0x00FCFFFF; value |= 0x14010000; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - DENC_A_REG_4 + (0x100 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_4 + (0x100 * i), value); - value = - cx25821_i2c_read(&dev->i2c_bus[0], - DENC_A_REG_5 + (0x100 * i), &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_5 + (0x100 * i), &tmp); value &= 0xFFFF0000; value |= 0x0000F078; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - DENC_A_REG_5 + (0x100 * i), value); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_5 + (0x100 * i), value); - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - DENC_A_REG_6 + (0x100 * i), 0x00A493CF); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_6 + (0x100 * i), 0x00A493CF); /* Subcarrier Increment */ - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - DENC_A_REG_7 + (0x100 * i), 0x2A098ACB); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_7 + (0x100 * i), 0x2A098ACB); } /* set picture resolutions */ @@ -543,12 +482,10 @@ void medusa_set_resolution(struct cx25821_dev *dev, int width, for (; decoder < decoder_count; decoder++) { /* write scaling values for each decoder */ - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - HSCALE_CTRL + (0x200 * decoder), hscale); - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], - VSCALE_CTRL + (0x200 * decoder), vscale); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + HSCALE_CTRL + (0x200 * decoder), hscale); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], + VSCALE_CTRL + (0x200 * decoder), vscale); } mutex_unlock(&dev->lock); @@ -606,8 +543,8 @@ static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, } /* Map to Medusa register setting */ -static int mapM(int srcMin, - int srcMax, int srcVal, int dstMin, int dstMax, int *dstVal) +static int mapM(int srcMin, int srcMax, int srcVal, int dstMin, int dstMax, + int *dstVal) { int numerator; int denominator; @@ -659,18 +596,14 @@ int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder) mutex_unlock(&dev->lock); return -1; } - ret_val = - mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness, - SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); + ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness, + SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); value = convert_to_twos(value, 8); - val = - cx25821_i2c_read(&dev->i2c_bus[0], - VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp); + val = cx25821_i2c_read(&dev->i2c_bus[0], + VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp); val &= 0xFFFFFF00; - ret_val |= - cx25821_i2c_write(&dev->i2c_bus[0], - VDEC_A_BRITE_CTRL + (0x200 * decoder), - val | value); + ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], + VDEC_A_BRITE_CTRL + (0x200 * decoder), val | value); mutex_unlock(&dev->lock); return ret_val; } @@ -688,17 +621,13 @@ int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder) return -1; } - ret_val = - mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast, - UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); - val = - cx25821_i2c_read(&dev->i2c_bus[0], - VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp); + ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast, + UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); + val = cx25821_i2c_read(&dev->i2c_bus[0], + VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp); val &= 0xFFFFFF00; - ret_val |= - cx25821_i2c_write(&dev->i2c_bus[0], - VDEC_A_CNTRST_CTRL + (0x200 * decoder), - val | value); + ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], + VDEC_A_CNTRST_CTRL + (0x200 * decoder), val | value); mutex_unlock(&dev->lock); return ret_val; @@ -717,19 +646,16 @@ int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder) return -1; } - ret_val = - mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, SIGNED_BYTE_MIN, - SIGNED_BYTE_MAX, &value); + ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, + SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); value = convert_to_twos(value, 8); - val = - cx25821_i2c_read(&dev->i2c_bus[0], - VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp); + val = cx25821_i2c_read(&dev->i2c_bus[0], + VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp); val &= 0xFFFFFF00; - ret_val |= - cx25821_i2c_write(&dev->i2c_bus[0], - VDEC_A_HUE_CTRL + (0x200 * decoder), val | value); + ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], + VDEC_A_HUE_CTRL + (0x200 * decoder), val | value); mutex_unlock(&dev->lock); return ret_val; @@ -749,27 +675,20 @@ int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder) return -1; } - ret_val = - mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation, - UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); + ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation, + UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); - val = - cx25821_i2c_read(&dev->i2c_bus[0], - VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp); + val = cx25821_i2c_read(&dev->i2c_bus[0], + VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp); val &= 0xFFFFFF00; - ret_val |= - cx25821_i2c_write(&dev->i2c_bus[0], - VDEC_A_USAT_CTRL + (0x200 * decoder), - val | value); - - val = - cx25821_i2c_read(&dev->i2c_bus[0], - VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp); + ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], + VDEC_A_USAT_CTRL + (0x200 * decoder), val | value); + + val = cx25821_i2c_read(&dev->i2c_bus[0], + VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp); val &= 0xFFFFFF00; - ret_val |= - cx25821_i2c_write(&dev->i2c_bus[0], - VDEC_A_VSAT_CTRL + (0x200 * decoder), - val | value); + ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], + VDEC_A_VSAT_CTRL + (0x200 * decoder), val | value); mutex_unlock(&dev->lock); return ret_val; @@ -830,9 +749,8 @@ int medusa_video_init(struct cx25821_dev *dev) /* select AFE clock to output mode */ value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); value &= 0x83FFFFFF; - ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, - value | 0x10000000); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, + value | 0x10000000); if (ret_val < 0) goto error; -- cgit v0.10.2 From 3940de7482be50f7071224c0f7812c6db1e132bd Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:41 -0300 Subject: [media] cx25821-video-upstream-ch2.c: Line up comments Line up comments to match indent of surrounding statements. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c index 2a724dd..94e235f 100644 --- a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c +++ b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c @@ -173,7 +173,7 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev, fifo_enable = FIFO_DISABLE; - /* Even field */ + /* Even field */ rp = cx25821_risc_field_upstream_ch2(dev, rp, dev->_data_buf_phys_addr_ch2 + databuf_offset, bottom_offset, 0x200, bpl, singlefield_lines, @@ -189,9 +189,9 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev, } /* - Loop to 2ndFrameRISC or to Start of - Risc program & generate IRQ - */ + * Loop to 2ndFrameRISC or to Start of + * Risc program & generate IRQ + */ *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); *(rp++) = cpu_to_le32(risc_phys_jump_addr); *(rp++) = cpu_to_le32(0); -- cgit v0.10.2 From 2a4492d8223b7fef53d293b30db2141dcefb6de1 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:42 -0300 Subject: [media] cx25821-video-upstream-ch2.c: Fix indent Change indent of statements with (less than 8) spaces to indent with tabs. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c index 94e235f..af816a8 100644 --- a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c +++ b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c @@ -85,7 +85,7 @@ static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev, { unsigned int line, i; struct sram_channel *sram_ch = - dev->channels[dev->_channel2_upstream_select].sram_channels; + dev->channels[dev->_channel2_upstream_select].sram_channels; int dist_betwn_starts = bpl * 2; /* sync instruction */ @@ -203,7 +203,7 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev, void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) { struct sram_channel *sram_ch = - dev->channels[VID_UPSTREAM_SRAM_CHANNEL_J].sram_channels; + dev->channels[VID_UPSTREAM_SRAM_CHANNEL_J].sram_channels; u32 tmp = 0; if (!dev->_is_running_ch2) { @@ -325,7 +325,7 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) && dev->_data_buf_virt_addr_ch2 != NULL) { memcpy((void *)(dev->_data_buf_virt_addr_ch2 + frame_offset / 4), mybuf, - vfs_read_retval); + vfs_read_retval); } file_offset += vfs_read_retval; @@ -419,7 +419,7 @@ int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) memcpy((void *)(dev-> _data_buf_virt_addr_ch2 + offset / 4), mybuf, - vfs_read_retval); + vfs_read_retval); } offset += vfs_read_retval; @@ -563,8 +563,8 @@ int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, else line_size_in_bytes = Y422_LINE_SZ; risc_phys_jump_addr = - dev->_dma_phys_start_addr_ch2 + - odd_risc_prog_size; + dev->_dma_phys_start_addr_ch2 + + odd_risc_prog_size; rp = cx25821_update_riscprogram_ch2(dev, dev->_dma_virt_start_addr_ch2, -- cgit v0.10.2 From 3a59fab41b9935b2e52118b331e71078aec97676 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:43 -0300 Subject: [media] cx25821-video-upsstream-ch2.c: Move operators Move operators in complex expressions to the end of the lines to preserve consistency. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c index af816a8..53927e8 100644 --- a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c +++ b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c @@ -65,9 +65,8 @@ static __le32 *cx25821_update_riscprogram_ch2(struct cx25821_dev *dev, *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2 + offset); *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - if ((lines <= NTSC_FIELD_HEIGHT) - || (line < (NTSC_FIELD_HEIGHT - 1)) - || !(dev->_isNTSC_ch2)) { + if ((lines <= NTSC_FIELD_HEIGHT) || + (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC_ch2)) { offset += dist_betwn_starts; } } @@ -103,9 +102,8 @@ static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev, *(rp++) = cpu_to_le32(databuf_phys_addr + offset); *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - if ((lines <= NTSC_FIELD_HEIGHT) - || (line < (NTSC_FIELD_HEIGHT - 1)) - || !(dev->_isNTSC_ch2)) { + if ((lines <= NTSC_FIELD_HEIGHT) || + (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC_ch2)) { offset += dist_betwn_starts; } @@ -413,9 +411,9 @@ int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); - if (vfs_read_retval > 0 - && vfs_read_retval == line_size - && dev->_data_buf_virt_addr_ch2 != NULL) { + if (vfs_read_retval > 0 && + vfs_read_retval == line_size && + dev->_data_buf_virt_addr_ch2 != NULL) { memcpy((void *)(dev-> _data_buf_virt_addr_ch2 + offset / 4), mybuf, -- cgit v0.10.2 From df253423d41d377b353964b8a3343df4507fda7c Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:44 -0300 Subject: [media] cx25821-video-upstream-ch2.c: Remove braces Remove unnecessary curly braces around single if statement. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c index 53927e8..1e452b8 100644 --- a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c +++ b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c @@ -610,11 +610,9 @@ static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id) vid_status = cx_read(sram_ch->int_stat); /* Only deal with our interrupt */ - if (vid_status) { - handled = - cx25821_video_upstream_irq_ch2(dev, channel_num, - vid_status); - } + if (vid_status) + handled = cx25821_video_upstream_irq_ch2(dev, channel_num, + vid_status); if (handled < 0) cx25821_stop_upstream_video_ch2(dev); -- cgit v0.10.2 From 85b7982d16397d8677e96c0f2b1776c50bf0cfc5 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:45 -0300 Subject: [media] cx25821-video-upstream-ch2.c: Change line endings Change obscure line endings to less obscure ones. (improve readability) Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c index 1e452b8..6401ce8 100644 --- a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c +++ b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c @@ -260,9 +260,8 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) struct file *myfile; int frame_index_temp = dev->_frame_index_ch2; int i = 0; - int line_size = - (dev->_pixel_format_ch2 == - PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; + int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? + Y411_LINE_SZ : Y422_LINE_SZ; int frame_size = 0; int frame_offset = 0; ssize_t vfs_read_retval = 0; @@ -275,14 +274,11 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) return 0; if (dev->_isNTSC_ch2) { - frame_size = - (line_size == - Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : - FRAME_SIZE_NTSC_Y422; + frame_size = (line_size == Y411_LINE_SZ) ? + FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; } else { - frame_size = - (line_size == - Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; + frame_size = (line_size == Y411_LINE_SZ) ? + FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; } frame_offset = (frame_index_temp > 0) ? frame_size : 0; @@ -316,8 +312,8 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) for (i = 0; i < dev->_lines_count_ch2; i++) { pos = file_offset; - vfs_read_retval = - vfs_read(myfile, mybuf, line_size, &pos); + vfs_read_retval = vfs_read(myfile, mybuf, line_size, + &pos); if (vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr_ch2 != NULL) { @@ -339,8 +335,8 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) if (i > 0) dev->_frame_count_ch2++; - dev->_file_status_ch2 = - (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + dev->_file_status_ch2 = (vfs_read_retval == line_size) ? + IN_PROGRESS : END_OF_FILE; set_fs(old_fs); filp_close(myfile, NULL); @@ -351,8 +347,8 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) static void cx25821_vidups_handler_ch2(struct work_struct *work) { - struct cx25821_dev *dev = - container_of(work, struct cx25821_dev, _irq_work_entry_ch2); + struct cx25821_dev *dev = container_of(work, struct cx25821_dev, + _irq_work_entry_ch2); if (!dev) { pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n", @@ -360,18 +356,16 @@ static void cx25821_vidups_handler_ch2(struct work_struct *work) return; } - cx25821_get_frame_ch2(dev, - dev->channels[dev-> - _channel2_upstream_select].sram_channels); + cx25821_get_frame_ch2(dev, dev->channels[dev-> + _channel2_upstream_select].sram_channels); } int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) { struct file *myfile; int i = 0, j = 0; - int line_size = - (dev->_pixel_format_ch2 == - PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; + int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? + Y411_LINE_SZ : Y422_LINE_SZ; ssize_t vfs_read_retval = 0; char mybuf[line_size]; loff_t pos; @@ -408,8 +402,8 @@ int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) for (i = 0; i < dev->_lines_count_ch2; i++) { pos = offset; - vfs_read_retval = - vfs_read(myfile, mybuf, line_size, &pos); + vfs_read_retval = vfs_read(myfile, mybuf, + line_size, &pos); if (vfs_read_retval > 0 && vfs_read_retval == line_size && @@ -436,8 +430,8 @@ int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) break; } - dev->_file_status_ch2 = - (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + dev->_file_status_ch2 = (vfs_read_retval == line_size) ? + IN_PROGRESS : END_OF_FILE; set_fs(old_fs); myfile->f_pos = 0; @@ -461,9 +455,8 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, dev->_dma_phys_addr_ch2); } - dev->_dma_virt_addr_ch2 = - pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, - &dma_addr); + dev->_dma_virt_addr_ch2 = pci_alloc_consistent(dev->pci, + dev->upstream_riscbuf_size_ch2, &dma_addr); dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2; dev->_dma_phys_start_addr_ch2 = dma_addr; dev->_dma_phys_addr_ch2 = dma_addr; @@ -483,9 +476,8 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, dev->_data_buf_phys_addr_ch2); } /* For Video Data buffer allocation */ - dev->_data_buf_virt_addr_ch2 = - pci_alloc_consistent(dev->pci, dev->upstream_databuf_size_ch2, - &data_dma_addr); + dev->_data_buf_virt_addr_ch2 = pci_alloc_consistent(dev->pci, + dev->upstream_databuf_size_ch2, &data_dma_addr); dev->_data_buf_phys_addr_ch2 = data_dma_addr; dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2; @@ -687,8 +679,7 @@ int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev, tmp = cx_read(sram_ch->int_msk); cx_write(sram_ch->int_msk, tmp |= _intr_msk); - err = - request_irq(dev->pci->irq, cx25821_upstream_irq_ch2, + err = request_irq(dev->pci->irq, cx25821_upstream_irq_ch2, IRQF_SHARED, dev->name, dev); if (err < 0) { pr_err("%s: can't get upstream IRQ %d\n", @@ -748,12 +739,11 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, dev->_file_status_ch2 = RESET_STATUS; dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576; dev->_pixel_format_ch2 = pixel_format; - dev->_line_size_ch2 = - (dev->_pixel_format_ch2 == - PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; + dev->_line_size_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_422) ? + (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; - risc_buffer_size = - dev->_isNTSC_ch2 ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; + risc_buffer_size = dev->_isNTSC_ch2 ? + NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; if (dev->input_filename_ch2) { str_length = strlen(dev->input_filename_ch2); @@ -778,15 +768,13 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, /* Default if filename is empty string */ if (strcmp(dev->input_filename_ch2, "") == 0) { if (dev->_isNTSC_ch2) { - dev->_filename_ch2 = - (dev->_pixel_format_ch2 == - PIXEL_FRMT_411) ? "/root/vid411.yuv" : - "/root/vidtest.yuv"; + dev->_filename_ch2 = (dev->_pixel_format_ch2 == + PIXEL_FRMT_411) ? "/root/vid411.yuv" : + "/root/vidtest.yuv"; } else { - dev->_filename_ch2 = - (dev->_pixel_format_ch2 == - PIXEL_FRMT_411) ? "/root/pal411.yuv" : - "/root/pal422.yuv"; + dev->_filename_ch2 = (dev->_pixel_format_ch2 == + PIXEL_FRMT_411) ? "/root/pal411.yuv" : + "/root/pal422.yuv"; } } -- cgit v0.10.2 From 16f0fda705371d880d79c0bd44fc301a45a1deb7 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:46 -0300 Subject: [media] cx25821-video-upstream.c: Remove braces Delete curly braces around single if-else statements. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-video-upstream.c b/drivers/media/video/cx25821/cx25821-video-upstream.c index c0b8006..61b5397 100644 --- a/drivers/media/video/cx25821/cx25821-video-upstream.c +++ b/drivers/media/video/cx25821/cx25821-video-upstream.c @@ -326,16 +326,12 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) if (dev->_file_status == END_OF_FILE) return 0; - if (dev->_isNTSC) { - frame_size = - (line_size == - Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : - FRAME_SIZE_NTSC_Y422; - } else { - frame_size = - (line_size == - Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; - } + if (dev->_isNTSC) + frame_size = (line_size == Y411_LINE_SZ) ? + FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; + else + frame_size = (line_size == Y411_LINE_SZ) ? + FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; frame_offset = (frame_index_temp > 0) ? frame_size : 0; file_offset = dev->_frame_count * frame_size; @@ -507,10 +503,9 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, dma_addr_t dma_addr; dma_addr_t data_dma_addr; - if (dev->_dma_virt_addr != NULL) { + if (dev->_dma_virt_addr != NULL) pci_free_consistent(dev->pci, dev->upstream_riscbuf_size, - dev->_dma_virt_addr, dev->_dma_phys_addr); - } + dev->_dma_virt_addr, dev->_dma_phys_addr); dev->_dma_virt_addr = pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size, @@ -528,11 +523,10 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, /* Clear memory at address */ memset(dev->_dma_virt_addr, 0, dev->_risc_size); - if (dev->_data_buf_virt_addr != NULL) { + if (dev->_data_buf_virt_addr != NULL) pci_free_consistent(dev->pci, dev->upstream_databuf_size, - dev->_data_buf_virt_addr, - dev->_data_buf_phys_addr); - } + dev->_data_buf_virt_addr, + dev->_data_buf_phys_addr); /* For Video Data buffer allocation */ dev->_data_buf_virt_addr = pci_alloc_consistent(dev->pci, dev->upstream_databuf_size, @@ -672,10 +666,9 @@ static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id) vid_status = cx_read(sram_ch->int_stat); /* Only deal with our interrupt */ - if (vid_status) { - handled = - cx25821_video_upstream_irq(dev, channel_num, vid_status); - } + if (vid_status) + handled = cx25821_video_upstream_irq(dev, channel_num, + vid_status); if (handled < 0) cx25821_stop_upstream_video_ch1(dev); -- cgit v0.10.2 From 2c68e933a9ff2e51c319aee7e841c89ab833bc8a Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:47 -0300 Subject: [media] cx25821-video-upstream.c: Fix indent Change indent of statements to use tabs and to improve readability. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-video-upstream.c b/drivers/media/video/cx25821/cx25821-video-upstream.c index 61b5397..0259a40 100644 --- a/drivers/media/video/cx25821/cx25821-video-upstream.c +++ b/drivers/media/video/cx25821/cx25821-video-upstream.c @@ -136,7 +136,7 @@ static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp, { unsigned int line, i; struct sram_channel *sram_ch = - dev->channels[dev->_channel_upstream_select].sram_channels; + dev->channels[dev->_channel_upstream_select].sram_channels; int dist_betwn_starts = bpl * 2; /* sync instruction */ @@ -214,13 +214,9 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, if (UNSET != top_offset) { fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; rp = cx25821_risc_field_upstream(dev, rp, - dev-> - _data_buf_phys_addr + - databuf_offset, - top_offset, 0, bpl, - odd_num_lines, - fifo_enable, - ODD_FIELD); + dev->_data_buf_phys_addr + + databuf_offset, top_offset, 0, bpl, + odd_num_lines, fifo_enable, ODD_FIELD); } fifo_enable = FIFO_DISABLE; @@ -255,7 +251,7 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) { struct sram_channel *sram_ch = - dev->channels[VID_UPSTREAM_SRAM_CHANNEL_I].sram_channels; + dev->channels[VID_UPSTREAM_SRAM_CHANNEL_I].sram_channels; u32 tmp = 0; if (!dev->_is_running) { @@ -829,14 +825,12 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, if (strcmp(dev->input_filename, "") == 0) { if (dev->_isNTSC) { dev->_filename = - (dev->_pixel_format == - PIXEL_FRMT_411) ? "/root/vid411.yuv" : - "/root/vidtest.yuv"; + (dev->_pixel_format == PIXEL_FRMT_411) ? + "/root/vid411.yuv" : "/root/vidtest.yuv"; } else { dev->_filename = - (dev->_pixel_format == - PIXEL_FRMT_411) ? "/root/pal411.yuv" : - "/root/pal422.yuv"; + (dev->_pixel_format == PIXEL_FRMT_411) ? + "/root/pal411.yuv" : "/root/pal422.yuv"; } } -- cgit v0.10.2 From 8eb1fdfff0c939f3f5c6b48a6e54996e7ac0ad91 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:48 -0300 Subject: [media] cx25821-video-upstream.c: Change line endings Change obscure line endings to less obscure ones. (improve readability) Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-video-upstream.c b/drivers/media/video/cx25821/cx25821-video-upstream.c index 0259a40..1032263 100644 --- a/drivers/media/video/cx25821/cx25821-video-upstream.c +++ b/drivers/media/video/cx25821/cx25821-video-upstream.c @@ -194,15 +194,12 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, if (dev->_isNTSC) { odd_num_lines = singlefield_lines + 1; risc_program_size = FRAME1_VID_PROG_SIZE; - frame_size = - (bpl == - Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : - FRAME_SIZE_NTSC_Y422; + frame_size = (bpl == Y411_LINE_SZ) ? + FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; } else { risc_program_size = PAL_VID_PROG_SIZE; - frame_size = - (bpl == - Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; + frame_size = (bpl == Y411_LINE_SZ) ? + FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; } /* Virtual address of Risc buffer program */ @@ -230,8 +227,8 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, if (frame == 0) { risc_flag = RISC_CNT_RESET; - risc_phys_jump_addr = - dev->_dma_phys_start_addr + risc_program_size; + risc_phys_jump_addr = dev->_dma_phys_start_addr + + risc_program_size; } else { risc_phys_jump_addr = dev->_dma_phys_start_addr; risc_flag = RISC_CNT_INC; @@ -308,9 +305,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) struct file *myfile; int frame_index_temp = dev->_frame_index; int i = 0; - int line_size = - (dev->_pixel_format == - PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; + int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ? + Y411_LINE_SZ : Y422_LINE_SZ; int frame_size = 0; int frame_offset = 0; ssize_t vfs_read_retval = 0; @@ -361,8 +357,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) for (i = 0; i < dev->_lines_count; i++) { pos = file_offset; - vfs_read_retval = - vfs_read(myfile, mybuf, line_size, &pos); + vfs_read_retval = vfs_read(myfile, mybuf, line_size, + &pos); if (vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr != NULL) { @@ -384,8 +380,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) if (i > 0) dev->_frame_count++; - dev->_file_status = - (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + dev->_file_status = (vfs_read_retval == line_size) ? + IN_PROGRESS : END_OF_FILE; set_fs(old_fs); filp_close(myfile, NULL); @@ -396,8 +392,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) static void cx25821_vidups_handler(struct work_struct *work) { - struct cx25821_dev *dev = - container_of(work, struct cx25821_dev, _irq_work_entry); + struct cx25821_dev *dev = container_of(work, struct cx25821_dev, + _irq_work_entry); if (!dev) { pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n", @@ -405,18 +401,16 @@ static void cx25821_vidups_handler(struct work_struct *work) return; } - cx25821_get_frame(dev, - dev->channels[dev->_channel_upstream_select]. - sram_channels); + cx25821_get_frame(dev, dev->channels[dev->_channel_upstream_select]. + sram_channels); } int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) { struct file *myfile; int i = 0, j = 0; - int line_size = - (dev->_pixel_format == - PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; + int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ? + Y411_LINE_SZ : Y422_LINE_SZ; ssize_t vfs_read_retval = 0; char mybuf[line_size]; loff_t pos; @@ -453,8 +447,8 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) for (i = 0; i < dev->_lines_count; i++) { pos = offset; - vfs_read_retval = - vfs_read(myfile, mybuf, line_size, &pos); + vfs_read_retval = vfs_read(myfile, mybuf, + line_size, &pos); if (vfs_read_retval > 0 && vfs_read_retval == line_size @@ -481,8 +475,8 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) break; } - dev->_file_status = - (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + dev->_file_status = (vfs_read_retval == line_size) ? + IN_PROGRESS : END_OF_FILE; set_fs(old_fs); myfile->f_pos = 0; @@ -503,9 +497,8 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, pci_free_consistent(dev->pci, dev->upstream_riscbuf_size, dev->_dma_virt_addr, dev->_dma_phys_addr); - dev->_dma_virt_addr = - pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size, - &dma_addr); + dev->_dma_virt_addr = pci_alloc_consistent(dev->pci, + dev->upstream_riscbuf_size, &dma_addr); dev->_dma_virt_start_addr = dev->_dma_virt_addr; dev->_dma_phys_start_addr = dma_addr; dev->_dma_phys_addr = dma_addr; @@ -524,9 +517,8 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, dev->_data_buf_virt_addr, dev->_data_buf_phys_addr); /* For Video Data buffer allocation */ - dev->_data_buf_virt_addr = - pci_alloc_consistent(dev->pci, dev->upstream_databuf_size, - &data_dma_addr); + dev->_data_buf_virt_addr = pci_alloc_consistent(dev->pci, + dev->upstream_databuf_size, &data_dma_addr); dev->_data_buf_phys_addr = data_dma_addr; dev->_data_buf_size = dev->upstream_databuf_size; @@ -543,9 +535,8 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, return ret; /* Create RISC programs */ - ret = - cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl, - dev->_lines_count); + ret = cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl, + dev->_lines_count); if (ret < 0) { pr_info("Failed creating Video Upstream Risc programs!\n"); goto error; @@ -736,8 +727,7 @@ int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, tmp = cx_read(sram_ch->int_msk); cx_write(sram_ch->int_msk, tmp |= _intr_msk); - err = - request_irq(dev->pci->irq, cx25821_upstream_irq, + err = request_irq(dev->pci->irq, cx25821_upstream_irq, IRQF_SHARED, dev->name, dev); if (err < 0) { pr_err("%s: can't get upstream IRQ %d\n", @@ -796,12 +786,11 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, dev->_file_status = RESET_STATUS; dev->_lines_count = dev->_isNTSC ? 480 : 576; dev->_pixel_format = pixel_format; - dev->_line_size = - (dev->_pixel_format == - PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; + dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ? + (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; - risc_buffer_size = - dev->_isNTSC ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; + risc_buffer_size = dev->_isNTSC ? + NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; if (dev->input_filename) { str_length = strlen(dev->input_filename); @@ -839,13 +828,11 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, dev->_file_status = RESET_STATUS; dev->_lines_count = dev->_isNTSC ? 480 : 576; dev->_pixel_format = pixel_format; - dev->_line_size = - (dev->_pixel_format == - PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; + dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ? + (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; - retval = - cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size, - 0); + retval = cx25821_sram_channel_setup_upstream(dev, sram_ch, + dev->_line_size, 0); /* setup fifo + format */ cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format); -- cgit v0.10.2 From 7e7beb8c255e91bfb4701f2757036c8fbe5a6592 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:49 -0300 Subject: [media] cx25821-video.c: Delete empty line Delete unnecessary empty line. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-video.c b/drivers/media/video/cx25821/cx25821-video.c index 4d6907c..79c4553 100644 --- a/drivers/media/video/cx25821/cx25821-video.c +++ b/drivers/media/video/cx25821/cx25821-video.c @@ -528,7 +528,6 @@ int cx25821_video_register(struct cx25821_dev *dev) #endif mutex_unlock(&dev->lock); - return 0; fail_unreg: -- cgit v0.10.2 From 1316b63ccde5bed161c6e346cc8f1752bd5c83cc Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:50 -0300 Subject: [media] cx25821-video.c: Change spaces Change double spaces between lexemes into single spaces. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-video.c b/drivers/media/video/cx25821/cx25821-video.c index 79c4553..df4f5b1 100644 --- a/drivers/media/video/cx25821/cx25821-video.c +++ b/drivers/media/video/cx25821/cx25821-video.c @@ -1931,9 +1931,9 @@ static long video_ioctl_set(struct file *file, unsigned int cmd, static long cx25821_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int ret = 0; + int ret = 0; - struct cx25821_fh *fh = file->private_data; + struct cx25821_fh *fh = file->private_data; /* check to see if it's the video upstream */ if (fh->channel_id == SRAM_CH09) { -- cgit v0.10.2 From a1937e191906c612e5675e52dd86c5a4b1d44a81 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:51 -0300 Subject: [media] cx25821-video.c: Fix assignment Change double assignment in one statement into two assignment statements. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-video.c b/drivers/media/video/cx25821/cx25821-video.c index df4f5b1..4cca7ee 100644 --- a/drivers/media/video/cx25821/cx25821-video.c +++ b/drivers/media/video/cx25821/cx25821-video.c @@ -1622,7 +1622,8 @@ int cx25821_vidioc_cropcap(struct file *file, void *priv, if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - cropcap->bounds.top = cropcap->bounds.left = 0; + cropcap->bounds.top = 0; + cropcap->bounds.left = 0; cropcap->bounds.width = 720; cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480; cropcap->pixelaspect.numerator = -- cgit v0.10.2 From 4a33b6f8bdf3b5a17737f66eef79b595cf3541a3 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:52 -0300 Subject: [media] cx25821-video.c: Fix definitions Change multiple definitions in one statement into multiple statements with one definition per statement. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-video.c b/drivers/media/video/cx25821/cx25821-video.c index 4cca7ee..278e06b 100644 --- a/drivers/media/video/cx25821/cx25821-video.c +++ b/drivers/media/video/cx25821/cx25821-video.c @@ -1829,8 +1829,11 @@ static long video_ioctl_set(struct file *file, unsigned int cmd, struct downstream_user_struct *data_from_user; int command; int width = 720; - int selected_channel = 0, pix_format = 0, i = 0; - int cif_enable = 0, cif_width = 0; + int selected_channel = 0; + int pix_format = 0; + int i = 0; + int cif_enable = 0; + int cif_width = 0; u32 value = 0; data_from_user = (struct downstream_user_struct *)arg; -- cgit v0.10.2 From cd52b2cf9bd60b1887e2ade2a2e12f155240fa9d Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:53 -0300 Subject: [media] cx25821-video.c: Move operators Move operator in complex expression to the end of the line to preserve consistency. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-video.c b/drivers/media/video/cx25821/cx25821-video.c index 278e06b..4bd7d71 100644 --- a/drivers/media/video/cx25821/cx25821-video.c +++ b/drivers/media/video/cx25821/cx25821-video.c @@ -616,8 +616,8 @@ int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, if (channel_opened >= 0 && channel_opened <= 7) { if (dev->channels[channel_opened] .use_cif_resolution) { - if (dev->tvnorm & V4L2_STD_PAL_BG - || dev->tvnorm & V4L2_STD_PAL_DK) + if (dev->tvnorm & V4L2_STD_PAL_BG || + dev->tvnorm & V4L2_STD_PAL_DK) bpl_local = 352 << 1; else bpl_local = -- cgit v0.10.2 From f253981406c9f9f79d6439fc2bd31fd1a10f68cb Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:54 -0300 Subject: [media] cx25821-video.c: Fix indent Fix indent of statements to improve readability. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-video.c b/drivers/media/video/cx25821/cx25821-video.c index 4bd7d71..fce203c 100644 --- a/drivers/media/video/cx25821/cx25821-video.c +++ b/drivers/media/video/cx25821/cx25821-video.c @@ -118,12 +118,12 @@ void cx25821_dump_video_queue(struct cx25821_dev *dev, if (!list_empty(&q->active)) { list_for_each(item, &q->active) - buf = list_entry(item, struct cx25821_buffer, vb.queue); + buf = list_entry(item, struct cx25821_buffer, vb.queue); } if (!list_empty(&q->queued)) { list_for_each(item, &q->queued) - buf = list_entry(item, struct cx25821_buffer, vb.queue); + buf = list_entry(item, struct cx25821_buffer, vb.queue); } } @@ -484,8 +484,7 @@ int cx25821_video_register(struct cx25821_dev *dev) cx25821_init_controls(dev, i); cx25821_risc_stopper(dev->pci, &dev->channels[i].vidq.stopper, - dev->channels[i].sram_channels->dma_ctl, - 0x11, 0); + dev->channels[i].sram_channels->dma_ctl, 0x11, 0); dev->channels[i].sram_channels = &cx25821_sram_channels[i]; dev->channels[i].video_dev = NULL; @@ -557,7 +556,7 @@ int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, struct cx25821_fh *fh = q->priv_data; struct cx25821_dev *dev = fh->dev; struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); + container_of(vb, struct cx25821_buffer, vb); int rc, init_buffer = 0; u32 line0_offset, line1_offset; struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); @@ -684,7 +683,7 @@ void cx25821_buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); + container_of(vb, struct cx25821_buffer, vb); cx25821_free_buffer(q, buf); } @@ -722,7 +721,7 @@ int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma) static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); + container_of(vb, struct cx25821_buffer, vb); struct cx25821_buffer *prev; struct cx25821_fh *fh = vq->priv_data; struct cx25821_dev *dev = fh->dev; @@ -813,7 +812,7 @@ static int video_open(struct file *file) for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) { if (h->channels[i].video_dev && - h->channels[i].video_dev->minor == minor) { + h->channels[i].video_dev->minor == minor) { dev = h; ch_id = i; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -1453,38 +1452,38 @@ static const struct v4l2_queryctrl no_ctl = { static struct v4l2_queryctrl cx25821_ctls[] = { /* --- video --- */ { - .id = V4L2_CID_BRIGHTNESS, - .name = "Brightness", - .minimum = 0, - .maximum = 10000, - .step = 1, - .default_value = 6200, - .type = V4L2_CTRL_TYPE_INTEGER, - }, { - .id = V4L2_CID_CONTRAST, - .name = "Contrast", - .minimum = 0, - .maximum = 10000, - .step = 1, - .default_value = 5000, - .type = V4L2_CTRL_TYPE_INTEGER, - }, { - .id = V4L2_CID_SATURATION, - .name = "Saturation", - .minimum = 0, - .maximum = 10000, - .step = 1, - .default_value = 5000, - .type = V4L2_CTRL_TYPE_INTEGER, - }, { - .id = V4L2_CID_HUE, - .name = "Hue", - .minimum = 0, - .maximum = 10000, - .step = 1, - .default_value = 5000, - .type = V4L2_CTRL_TYPE_INTEGER, - } + .id = V4L2_CID_BRIGHTNESS, + .name = "Brightness", + .minimum = 0, + .maximum = 10000, + .step = 1, + .default_value = 6200, + .type = V4L2_CTRL_TYPE_INTEGER, + }, { + .id = V4L2_CID_CONTRAST, + .name = "Contrast", + .minimum = 0, + .maximum = 10000, + .step = 1, + .default_value = 5000, + .type = V4L2_CTRL_TYPE_INTEGER, + }, { + .id = V4L2_CID_SATURATION, + .name = "Saturation", + .minimum = 0, + .maximum = 10000, + .step = 1, + .default_value = 5000, + .type = V4L2_CTRL_TYPE_INTEGER, + }, { + .id = V4L2_CID_HUE, + .name = "Hue", + .minimum = 0, + .maximum = 10000, + .step = 1, + .default_value = 5000, + .type = V4L2_CTRL_TYPE_INTEGER, + } }; static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls); -- cgit v0.10.2 From 0abfefbe497d8d2a173f70aa3beac89a01fc1f51 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:55 -0300 Subject: [media] cx25821-video.c: Change line endings Change obscure line endings to less obscure ones. (improve readability) Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-video.c b/drivers/media/video/cx25821/cx25821-video.c index fce203c..ffd8bc7 100644 --- a/drivers/media/video/cx25821/cx25821-video.c +++ b/drivers/media/video/cx25821/cx25821-video.c @@ -140,8 +140,8 @@ void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, break; } - buf = - list_entry(q->active.next, struct cx25821_buffer, vb.queue); + buf = list_entry(q->active.next, struct cx25821_buffer, + vb.queue); /* count comes from the hw and it is 16bit wide -- * this trick handles wrap-arounds correctly for @@ -318,8 +318,8 @@ int cx25821_restart_video_queue(struct cx25821_dev *dev, struct list_head *item; if (!list_empty(&q->active)) { - buf = - list_entry(q->active.next, struct cx25821_buffer, vb.queue); + buf = list_entry(q->active.next, struct cx25821_buffer, + vb.queue); cx25821_start_video_dma(dev, q, buf, channel); @@ -337,8 +337,8 @@ int cx25821_restart_video_queue(struct cx25821_dev *dev, if (list_empty(&q->queued)) return 0; - buf = - list_entry(q->queued.next, struct cx25821_buffer, vb.queue); + buf = list_entry(q->queued.next, struct cx25821_buffer, + vb.queue); if (NULL == prev) { list_move_tail(&buf->vb.queue, &q->active); @@ -375,8 +375,8 @@ void cx25821_vid_timeout(unsigned long data) spin_lock_irqsave(&dev->slock, flags); while (!list_empty(&q->active)) { - buf = - list_entry(q->active.next, struct cx25821_buffer, vb.queue); + buf = list_entry(q->active.next, struct cx25821_buffer, + vb.queue); list_del(&buf->vb.queue); buf->vb.state = VIDEOBUF_ERROR; @@ -498,15 +498,14 @@ int cx25821_video_register(struct cx25821_dev *dev) dev->channels[i].timeout_data.dev = dev; dev->channels[i].timeout_data.channel = &cx25821_sram_channels[i]; - dev->channels[i].vidq.timeout.function = - cx25821_vid_timeout; + dev->channels[i].vidq.timeout.function = cx25821_vid_timeout; dev->channels[i].vidq.timeout.data = (unsigned long)&dev->channels[i].timeout_data; init_timer(&dev->channels[i].vidq.timeout); /* register v4l devices */ - dev->channels[i].video_dev = cx25821_vdev_init(dev, - dev->pci, &cx25821_video_device, "video"); + dev->channels[i].video_dev = cx25821_vdev_init(dev, dev->pci, + &cx25821_video_device, "video"); err = video_register_device(dev->channels[i].video_dev, VFL_TYPE_GRABBER, video_nr[dev->nr]); @@ -619,10 +618,9 @@ int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, dev->tvnorm & V4L2_STD_PAL_DK) bpl_local = 352 << 1; else - bpl_local = - dev->channels[channel_opened]. - cif_width << - 1; + bpl_local = dev->channels[ + channel_opened]. + cif_width << 1; } } } @@ -846,11 +844,10 @@ static int video_open(struct file *file) v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio); - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), fh, NULL); + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, &dev->pci->dev, + &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, sizeof(struct cx25821_buffer), + fh, NULL); dprintk(1, "post videobuf_queue_init()\n"); mutex_unlock(&cx25821_devlist_mutex); @@ -1166,8 +1163,8 @@ int cx25821_vidioc_querycap(struct file *file, void *priv, strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); cap->version = CX25821_VERSION_CODE; - cap->capabilities = - V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING; if (UNSET != dev->tuner_type) cap->capabilities |= V4L2_CAP_TUNER; return 0; @@ -1897,8 +1894,8 @@ static long video_ioctl_set(struct file *file, unsigned int cmd, } if (selected_channel <= 7 && selected_channel >= 0) { - dev->channels[selected_channel]. - use_cif_resolution = cif_enable; + dev->channels[selected_channel].use_cif_resolution = + cif_enable; dev->channels[selected_channel].cif_width = width; } else { for (i = 0; i < VID_CHANNEL_NUM; i++) { -- cgit v0.10.2 From c7855ee531efa77d3837e22a0354d20f64d67446 Mon Sep 17 00:00:00 2001 From: "Leonid V. Fedorenchik" Date: Sat, 22 Oct 2011 01:43:56 -0300 Subject: [media] cx25821.h: Line up defines Line up constant defines to the same column. Signed-off-by: Leonid V. Fedorenchik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821.h b/drivers/media/video/cx25821/cx25821.h index 2d2d009..b9aa801 100644 --- a/drivers/media/video/cx25821/cx25821.h +++ b/drivers/media/video/cx25821/cx25821.h @@ -67,7 +67,7 @@ #define MAX_CAMERAS 16 /* Max number of inputs by card */ -#define MAX_CX25821_INPUT 8 +#define MAX_CX25821_INPUT 8 #define INPUT(nr) (&cx25821_boards[dev->board].input[nr]) #define RESOURCE_VIDEO0 1 #define RESOURCE_VIDEO1 2 @@ -85,7 +85,7 @@ #define BUFFER_TIMEOUT (HZ) /* 0.5 seconds */ -#define UNKNOWN_BOARD 0 +#define UNKNOWN_BOARD 0 #define CX25821_BOARD 1 /* Currently supported by the driver */ -- cgit v0.10.2 From 98680557f3ce7eadae0ceda4484fd6c7a13ba3be Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 9 Nov 2011 08:26:32 -0300 Subject: [media] easycap: cleanup function usage 1. Remove declarations of none global functions from easycap.h and make them static in the c-files. 2. Reorder static functions to reduce number of forward declarations. 3. Remove unused functions. Signed-off-by: Tomas Winkler Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/easycap/easycap.h b/drivers/staging/media/easycap/easycap.h index 7b256a9..899e572 100644 --- a/drivers/staging/media/easycap/easycap.h +++ b/drivers/staging/media/easycap/easycap.h @@ -470,71 +470,49 @@ struct easycap { */ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ long easycap_unlocked_ioctl(struct file *, unsigned int, unsigned long); -int easycap_dqbuf(struct easycap *, int); -int submit_video_urbs(struct easycap *); -int kill_video_urbs(struct easycap *); -int field2frame(struct easycap *); -int redaub(struct easycap *, void *, void *, - int, int, u8, u8, bool); -void easycap_testcard(struct easycap *, int); -int fillin_formats(void); -int newinput(struct easycap *, int); -int adjust_standard(struct easycap *, v4l2_std_id); -int adjust_format(struct easycap *, u32, u32, u32, - int, bool); -int adjust_brightness(struct easycap *, int); -int adjust_contrast(struct easycap *, int); -int adjust_saturation(struct easycap *, int); -int adjust_hue(struct easycap *, int); -int adjust_volume(struct easycap *, int); +int easycap_dqbuf(struct easycap *, int); +int submit_video_urbs(struct easycap *); +int kill_video_urbs(struct easycap *); +void easycap_testcard(struct easycap *, int); +int fillin_formats(void); +int newinput(struct easycap *, int); + +int adjust_standard(struct easycap *, v4l2_std_id); +int adjust_format(struct easycap *, u32, u32, u32, int, bool); +int adjust_brightness(struct easycap *, int); +int adjust_contrast(struct easycap *, int); +int adjust_saturation(struct easycap *, int); +int adjust_hue(struct easycap *, int); /*---------------------------------------------------------------------------*/ /* * AUDIO FUNCTION PROTOTYPES */ /*---------------------------------------------------------------------------*/ -int easycap_alsa_probe(struct easycap *); -void easycap_alsa_complete(struct urb *); - -int easycap_sound_setup(struct easycap *); -int submit_audio_urbs(struct easycap *); -int kill_audio_urbs(struct easycap *); -void easyoss_testtone(struct easycap *, int); -int audio_setup(struct easycap *); +int easycap_alsa_probe(struct easycap *); +void easycap_alsa_complete(struct urb *); +int audio_setup(struct easycap *); /*---------------------------------------------------------------------------*/ /* * LOW-LEVEL FUNCTION PROTOTYPES */ /*---------------------------------------------------------------------------*/ -int audio_gainget(struct usb_device *); -int audio_gainset(struct usb_device *, s8); - -int set_interface(struct usb_device *, u16); -int wakeup_device(struct usb_device *); -int confirm_resolution(struct usb_device *); -int confirm_stream(struct usb_device *); - -int setup_stk(struct usb_device *, bool); -int setup_saa(struct usb_device *, bool); -int setup_vt(struct usb_device *); -int check_stk(struct usb_device *, bool); -int check_saa(struct usb_device *, bool); -int ready_saa(struct usb_device *); -int merit_saa(struct usb_device *); -int check_vt(struct usb_device *); -int select_input(struct usb_device *, int, int); -int set_resolution(struct usb_device *, - u16, u16, u16, u16); - -int read_saa(struct usb_device *, u16); -int read_stk(struct usb_device *, u32); -int write_saa(struct usb_device *, u16, u16); -int write_000(struct usb_device *, u16, u16); -int start_100(struct usb_device *); -int stop_100(struct usb_device *); -int write_300(struct usb_device *); -int read_vt(struct usb_device *, u16); -int write_vt(struct usb_device *, u16, u16); -int isdongle(struct easycap *); +int audio_gainset(struct usb_device *, s8); + +int wakeup_device(struct usb_device *); + +int setup_stk(struct usb_device *, bool); +int setup_saa(struct usb_device *, bool); +int ready_saa(struct usb_device *); +int merit_saa(struct usb_device *); +int check_vt(struct usb_device *); +int select_input(struct usb_device *, int, int); +int set_resolution(struct usb_device *, u16, u16, u16, u16); + +int read_saa(struct usb_device *, u16); +int write_saa(struct usb_device *, u16, u16); +int start_100(struct usb_device *); +int stop_100(struct usb_device *); +int isdongle(struct easycap *); /*---------------------------------------------------------------------------*/ diff --git a/drivers/staging/media/easycap/easycap_ioctl.c b/drivers/staging/media/easycap/easycap_ioctl.c index c99addf..f5bc741 100644 --- a/drivers/staging/media/easycap/easycap_ioctl.c +++ b/drivers/staging/media/easycap/easycap_ioctl.c @@ -854,7 +854,7 @@ int adjust_hue(struct easycap *peasycap, int value) return -ENOENT; } /*****************************************************************************/ -int adjust_volume(struct easycap *peasycap, int value) +static int adjust_volume(struct easycap *peasycap, int value) { s8 mood; int i1; diff --git a/drivers/staging/media/easycap/easycap_low.c b/drivers/staging/media/easycap/easycap_low.c index 0385735..02bb2e5 100644 --- a/drivers/staging/media/easycap/easycap_low.c +++ b/drivers/staging/media/easycap/easycap_low.c @@ -40,6 +40,7 @@ #include "easycap.h" + #define GET(X, Y, Z) do { \ int __rc; \ *(Z) = (u16)0; \ @@ -355,101 +356,6 @@ static int wait_i2c(struct usb_device *p) } /****************************************************************************/ -int confirm_resolution(struct usb_device *p) -{ - u8 get0, get1, get2, get3, get4, get5, get6, get7; - - if (!p) - return -ENODEV; - GET(p, 0x0110, &get0); - GET(p, 0x0111, &get1); - GET(p, 0x0112, &get2); - GET(p, 0x0113, &get3); - GET(p, 0x0114, &get4); - GET(p, 0x0115, &get5); - GET(p, 0x0116, &get6); - GET(p, 0x0117, &get7); - JOT(8, "0x%03X, 0x%03X, " - "0x%03X, 0x%03X, " - "0x%03X, 0x%03X, " - "0x%03X, 0x%03X\n", - get0, get1, get2, get3, get4, get5, get6, get7); - JOT(8, "....cf PAL_720x526: " - "0x%03X, 0x%03X, " - "0x%03X, 0x%03X, " - "0x%03X, 0x%03X, " - "0x%03X, 0x%03X\n", - 0x000, 0x000, 0x001, 0x000, 0x5A0, 0x005, 0x121, 0x001); - JOT(8, "....cf PAL_704x526: " - "0x%03X, 0x%03X, " - "0x%03X, 0x%03X, " - "0x%03X, 0x%03X, " - "0x%03X, 0x%03X\n", - 0x004, 0x000, 0x001, 0x000, 0x584, 0x005, 0x121, 0x001); - JOT(8, "....cf VGA_640x480: " - "0x%03X, 0x%03X, " - "0x%03X, 0x%03X, " - "0x%03X, 0x%03X, " - "0x%03X, 0x%03X\n", - 0x008, 0x000, 0x020, 0x000, 0x508, 0x005, 0x110, 0x001); - return 0; -} -/****************************************************************************/ -int confirm_stream(struct usb_device *p) -{ - u16 get2; - u8 igot; - - if (!p) - return -ENODEV; - GET(p, 0x0100, &igot); get2 = 0x80 & igot; - if (0x80 == get2) - JOT(8, "confirm_stream: OK\n"); - else - JOT(8, "confirm_stream: STUCK\n"); - return 0; -} -/****************************************************************************/ -int setup_stk(struct usb_device *p, bool ntsc) -{ - int i; - const struct stk1160config *cfg; - if (!p) - return -ENODEV; - cfg = (ntsc) ? stk1160configNTSC : stk1160configPAL; - for (i = 0; cfg[i].reg != 0xFFF; i++) - SET(p, cfg[i].reg, cfg[i].set); - - write_300(p); - - return 0; -} -/****************************************************************************/ -int setup_saa(struct usb_device *p, bool ntsc) -{ - int i, ir; - const struct saa7113config *cfg; - if (!p) - return -ENODEV; - cfg = (ntsc) ? saa7113configNTSC : saa7113configPAL; - for (i = 0; cfg[i].reg != 0xFF; i++) - ir = write_saa(p, cfg[i].reg, cfg[i].set); - return 0; -} -/****************************************************************************/ -int write_000(struct usb_device *p, u16 set2, u16 set0) -{ - u8 igot0, igot2; - - if (!p) - return -ENODEV; - GET(p, 0x0002, &igot2); - GET(p, 0x0000, &igot0); - SET(p, 0x0002, set2); - SET(p, 0x0000, set0); - return 0; -} -/****************************************************************************/ int write_saa(struct usb_device *p, u16 reg0, u16 set0) { if (!p) @@ -470,8 +376,7 @@ int write_saa(struct usb_device *p, u16 reg0, u16 set0) * REGISTER 504: TARGET ADDRESS ON VT1612A */ /*--------------------------------------------------------------------------*/ -int -write_vt(struct usb_device *p, u16 reg0, u16 set0) +static int write_vt(struct usb_device *p, u16 reg0, u16 set0) { u8 igot; u16 got502, got503; @@ -508,7 +413,7 @@ write_vt(struct usb_device *p, u16 reg0, u16 set0) * REGISTER 504: TARGET ADDRESS ON VT1612A */ /*--------------------------------------------------------------------------*/ -int read_vt(struct usb_device *p, u16 reg0) +static int read_vt(struct usb_device *p, u16 reg0) { u8 igot; u16 got502, got503; @@ -532,7 +437,7 @@ int read_vt(struct usb_device *p, u16 reg0) * THESE APPEAR TO HAVE NO EFFECT ON EITHER VIDEO OR AUDIO. */ /*--------------------------------------------------------------------------*/ -int write_300(struct usb_device *p) +static int write_300(struct usb_device *p) { if (!p) return -ENODEV; @@ -545,32 +450,32 @@ int write_300(struct usb_device *p) return 0; } /****************************************************************************/ -/*--------------------------------------------------------------------------*/ -/* - * NOTE: THE FOLLOWING IS NOT CHECKED: - * REGISTER 0x0F, WHICH IS INVOLVED IN CHROMINANCE AUTOMATIC GAIN CONTROL. - */ -/*--------------------------------------------------------------------------*/ -int check_saa(struct usb_device *p, bool ntsc) +/****************************************************************************/ +int setup_stk(struct usb_device *p, bool ntsc) { - int i, ir, rc = 0; - struct saa7113config const *cfg; + int i; + const struct stk1160config *cfg; if (!p) return -ENODEV; + cfg = (ntsc) ? stk1160configNTSC : stk1160configPAL; + for (i = 0; cfg[i].reg != 0xFFF; i++) + SET(p, cfg[i].reg, cfg[i].set); - cfg = (ntsc) ? saa7113configNTSC : saa7113configPAL; - for (i = 0; cfg[i].reg != 0xFF; i++) { - if (0x0F == cfg[i].reg) - continue; - ir = read_saa(p, cfg[i].reg); - if (ir != cfg[i].set) { - SAY("SAA register 0x%02X has 0x%02X, expected 0x%02X\n", - cfg[i].reg, ir, cfg[i].set); - rc--; - } - } + write_300(p); - return (rc < -8) ? rc : 0; + return 0; +} +/****************************************************************************/ +int setup_saa(struct usb_device *p, bool ntsc) +{ + int i, ir; + const struct saa7113config *cfg; + if (!p) + return -ENODEV; + cfg = (ntsc) ? saa7113configNTSC : saa7113configPAL; + for (i = 0; cfg[i].reg != 0xFF; i++) + ir = write_saa(p, cfg[i].reg, cfg[i].set); + return 0; } /****************************************************************************/ int merit_saa(struct usb_device *p) @@ -629,44 +534,6 @@ int ready_saa(struct usb_device *p) return 0; } /****************************************************************************/ -/*--------------------------------------------------------------------------*/ -/* - * NOTE: THE FOLLOWING ARE NOT CHECKED: - * REGISTERS 0x000, 0x002: FUNCTIONALITY IS NOT KNOWN - * REGISTER 0x100: ACCEPT ALSO (0x80 | stk1160config....[.].set) - */ -/*--------------------------------------------------------------------------*/ -int check_stk(struct usb_device *p, bool ntsc) -{ - int i, ir; - const struct stk1160config *cfg; - - if (!p) - return -ENODEV; - cfg = (ntsc) ? stk1160configNTSC : stk1160configPAL; - - for (i = 0; 0xFFF != cfg[i].reg; i++) { - if (0x000 == cfg[i].reg || 0x002 == cfg[i].reg) - continue; - - - ir = read_stk(p, cfg[i].reg); - if (0x100 == cfg[i].reg) { - if ((ir != (0xFF & cfg[i].set)) && - (ir != (0x80 | (0xFF & cfg[i].set))) && - (0xFFFF != cfg[i].set)) { - SAY("STK reg[0x%03X]=0x%02X expected 0x%02X\n", - cfg[i].reg, ir, cfg[i].set); - } - continue; - } - if ((ir != (0xFF & cfg[i].set)) && (0xFFFF != cfg[i].set)) - SAY("STK register 0x%03X has 0x%02X,expected 0x%02X\n", - cfg[i].reg, ir, cfg[i].set); - } - return 0; -} -/****************************************************************************/ int read_saa(struct usb_device *p, u16 reg0) { u8 igot; @@ -682,7 +549,7 @@ int read_saa(struct usb_device *p, u16 reg0) return igot; } /****************************************************************************/ -int read_stk(struct usb_device *p, u32 reg0) +static int read_stk(struct usb_device *p, u32 reg0) { u8 igot; @@ -692,27 +559,7 @@ int read_stk(struct usb_device *p, u32 reg0) GET(p, reg0, &igot); return igot; } -/****************************************************************************/ -/*--------------------------------------------------------------------------*/ -/* - * HARDWARE USERSPACE INPUT NUMBER PHYSICAL INPUT DRIVER input VALUE - * - * CVBS+S-VIDEO 0 or 1 CVBS 1 - * FOUR-CVBS 0 or 1 CVBS1 1 - * FOUR-CVBS 2 CVBS2 2 - * FOUR-CVBS 3 CVBS3 3 - * FOUR-CVBS 4 CVBS4 4 - * CVBS+S-VIDEO 5 S-VIDEO 5 - * - * WHEN 5==input THE ARGUMENT mode MUST ALSO BE SUPPLIED: - * - * mode 7 => GAIN TO BE SET EXPLICITLY USING REGISTER 0x05 (UNTESTED) - * mode 9 => USE AUTOMATIC GAIN CONTROL (DEFAULT) - * -*/ -/*---------------------------------------------------------------------------*/ -int -select_input(struct usb_device *p, int input, int mode) +int select_input(struct usb_device *p, int input, int mode) { int ir; @@ -1115,15 +962,3 @@ int audio_gainset(struct usb_device *pusb_device, s8 loud) return 0; } /*****************************************************************************/ -int audio_gainget(struct usb_device *pusb_device) -{ - int igot; - - if (!pusb_device) - return -ENODEV; - igot = read_vt(pusb_device, 0x001C); - if (0 > igot) - SAY("ERROR: failed to read VT1612A register 0x1C\n"); - return igot; -} -/*****************************************************************************/ diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c index a45c0b5..94fd116 100644 --- a/drivers/staging/media/easycap/easycap_main.c +++ b/drivers/staging/media/easycap/easycap_main.c @@ -66,6 +66,10 @@ struct easycap_dongle easycapdc60_dongle[DONGLE_MANY]; static struct mutex mutex_dongle; static void easycap_complete(struct urb *purb); static int reset(struct easycap *peasycap); +static int field2frame(struct easycap *peasycap); +static int redaub(struct easycap *peasycap, + void *pad, void *pex, int much, int more, + u8 mask, u8 margin, bool isuy); const char *strerror(int err) { @@ -1211,8 +1215,7 @@ int easycap_dqbuf(struct easycap *peasycap, int mode) * CHOOSES THE OPTION V4L2_FIELD_INTERLACED. */ /*---------------------------------------------------------------------------*/ -int -field2frame(struct easycap *peasycap) +static int field2frame(struct easycap *peasycap) { void *pex, *pad; @@ -1601,9 +1604,9 @@ field2frame(struct easycap *peasycap) * REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE. BEWARE. */ /*---------------------------------------------------------------------------*/ -int -redaub(struct easycap *peasycap, void *pad, void *pex, int much, int more, - u8 mask, u8 margin, bool isuy) +static int redaub(struct easycap *peasycap, + void *pad, void *pex, int much, int more, + u8 mask, u8 margin, bool isuy) { static s32 ay[256], bu[256], rv[256], gu[256], gv[256]; u8 *pcache; diff --git a/drivers/staging/media/easycap/easycap_sound.c b/drivers/staging/media/easycap/easycap_sound.c index b22bb39..70813a5e 100644 --- a/drivers/staging/media/easycap/easycap_sound.c +++ b/drivers/staging/media/easycap/easycap_sound.c @@ -56,6 +56,152 @@ static const struct snd_pcm_hardware alsa_hardware = { }; +/*---------------------------------------------------------------------------*/ +/* + * SUBMIT ALL AUDIO URBS. + */ +/*---------------------------------------------------------------------------*/ +static int submit_audio_urbs(struct easycap *peasycap) +{ + struct data_urb *pdata_urb; + struct urb *purb; + struct list_head *plist_head; + int j, isbad, nospc, m, rc; + int isbuf; + + if (!peasycap) { + SAY("ERROR: peasycap is NULL\n"); + return -EFAULT; + } + if (!peasycap->purb_audio_head) { + SAM("ERROR: peasycap->urb_audio_head uninitialized\n"); + return -EFAULT; + } + if (!peasycap->pusb_device) { + SAM("ERROR: peasycap->pusb_device is NULL\n"); + return -EFAULT; + } + + if (peasycap->audio_isoc_streaming) { + JOM(4, "already streaming audio urbs\n"); + return 0; + } + + JOM(4, "initial submission of all audio urbs\n"); + rc = usb_set_interface(peasycap->pusb_device, + peasycap->audio_interface, + peasycap->audio_altsetting_on); + JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", + peasycap->audio_interface, + peasycap->audio_altsetting_on, rc); + + isbad = 0; + nospc = 0; + m = 0; + list_for_each(plist_head, peasycap->purb_audio_head) { + pdata_urb = list_entry(plist_head, struct data_urb, list_head); + if (pdata_urb && pdata_urb->purb) { + purb = pdata_urb->purb; + isbuf = pdata_urb->isbuf; + + purb->interval = 1; + purb->dev = peasycap->pusb_device; + purb->pipe = usb_rcvisocpipe(peasycap->pusb_device, + peasycap->audio_endpointnumber); + purb->transfer_flags = URB_ISO_ASAP; + purb->transfer_buffer = peasycap->audio_isoc_buffer[isbuf].pgo; + purb->transfer_buffer_length = peasycap->audio_isoc_buffer_size; + purb->complete = easycap_alsa_complete; + purb->context = peasycap; + purb->start_frame = 0; + purb->number_of_packets = peasycap->audio_isoc_framesperdesc; + for (j = 0; j < peasycap->audio_isoc_framesperdesc; j++) { + purb->iso_frame_desc[j].offset = j * peasycap->audio_isoc_maxframesize; + purb->iso_frame_desc[j].length = peasycap->audio_isoc_maxframesize; + } + + rc = usb_submit_urb(purb, GFP_KERNEL); + if (rc) { + isbad++; + SAM("ERROR: usb_submit_urb() failed" + " for urb with rc: -%s: %d\n", + strerror(rc), rc); + } else { + m++; + } + } else { + isbad++; + } + } + if (nospc) { + SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc); + SAM("..... possibly inadequate USB bandwidth\n"); + peasycap->audio_eof = 1; + } + if (isbad) { + JOM(4, "attempting cleanup instead of submitting\n"); + list_for_each(plist_head, (peasycap->purb_audio_head)) { + pdata_urb = list_entry(plist_head, struct data_urb, list_head); + if (pdata_urb && pdata_urb->purb) + usb_kill_urb(pdata_urb->purb); + } + peasycap->audio_isoc_streaming = 0; + } else { + peasycap->audio_isoc_streaming = m; + JOM(4, "submitted %i audio urbs\n", m); + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +/* + * COMMON AUDIO INITIALIZATION + */ +/*---------------------------------------------------------------------------*/ +static int easycap_sound_setup(struct easycap *peasycap) +{ + int rc; + + JOM(4, "starting initialization\n"); + + if (!peasycap) { + SAY("ERROR: peasycap is NULL.\n"); + return -EFAULT; + } + if (!peasycap->pusb_device) { + SAM("ERROR: peasycap->pusb_device is NULL\n"); + return -ENODEV; + } + JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device); + + rc = audio_setup(peasycap); + JOM(8, "audio_setup() returned %i\n", rc); + + if (!peasycap->pusb_device) { + SAM("ERROR: peasycap->pusb_device has become NULL\n"); + return -ENODEV; + } +/*---------------------------------------------------------------------------*/ + if (!peasycap->pusb_device) { + SAM("ERROR: peasycap->pusb_device has become NULL\n"); + return -ENODEV; + } + rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, + peasycap->audio_altsetting_on); + JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, + peasycap->audio_altsetting_on, rc); + + rc = wakeup_device(peasycap->pusb_device); + JOM(8, "wakeup_device() returned %i\n", rc); + + peasycap->audio_eof = 0; + peasycap->audio_idle = 0; + + submit_audio_urbs(peasycap); + + JOM(4, "finished initialization\n"); + return 0; +} /*****************************************************************************/ /*---------------------------------------------------------------------------*/ /* @@ -615,202 +761,3 @@ int easycap_alsa_probe(struct easycap *peasycap) return 0; } -/*****************************************************************************/ -/*****************************************************************************/ -/*****************************************************************************/ -/*****************************************************************************/ -/*****************************************************************************/ -/*****************************************************************************/ -/*---------------------------------------------------------------------------*/ -/* - * COMMON AUDIO INITIALIZATION - */ -/*---------------------------------------------------------------------------*/ -int -easycap_sound_setup(struct easycap *peasycap) -{ - int rc; - - JOM(4, "starting initialization\n"); - - if (!peasycap) { - SAY("ERROR: peasycap is NULL.\n"); - return -EFAULT; - } - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - return -ENODEV; - } - JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device); - - rc = audio_setup(peasycap); - JOM(8, "audio_setup() returned %i\n", rc); - - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device has become NULL\n"); - return -ENODEV; - } -/*---------------------------------------------------------------------------*/ - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device has become NULL\n"); - return -ENODEV; - } - rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, - peasycap->audio_altsetting_on); - JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, - peasycap->audio_altsetting_on, rc); - - rc = wakeup_device(peasycap->pusb_device); - JOM(8, "wakeup_device() returned %i\n", rc); - - peasycap->audio_eof = 0; - peasycap->audio_idle = 0; - - submit_audio_urbs(peasycap); - - JOM(4, "finished initialization\n"); - return 0; -} -/*****************************************************************************/ -/*---------------------------------------------------------------------------*/ -/* - * SUBMIT ALL AUDIO URBS. - */ -/*---------------------------------------------------------------------------*/ -int -submit_audio_urbs(struct easycap *peasycap) -{ - struct data_urb *pdata_urb; - struct urb *purb; - struct list_head *plist_head; - int j, isbad, nospc, m, rc; - int isbuf; - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - if (!peasycap->purb_audio_head) { - SAM("ERROR: peasycap->urb_audio_head uninitialized\n"); - return -EFAULT; - } - if (!peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - return -EFAULT; - } - - if (peasycap->audio_isoc_streaming) { - JOM(4, "already streaming audio urbs\n"); - return 0; - } - - JOM(4, "initial submission of all audio urbs\n"); - rc = usb_set_interface(peasycap->pusb_device, - peasycap->audio_interface, - peasycap->audio_altsetting_on); - JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", - peasycap->audio_interface, - peasycap->audio_altsetting_on, rc); - - isbad = 0; - nospc = 0; - m = 0; - list_for_each(plist_head, peasycap->purb_audio_head) { - pdata_urb = list_entry(plist_head, struct data_urb, list_head); - if (pdata_urb && pdata_urb->purb) { - purb = pdata_urb->purb; - isbuf = pdata_urb->isbuf; - - purb->interval = 1; - purb->dev = peasycap->pusb_device; - purb->pipe = usb_rcvisocpipe(peasycap->pusb_device, - peasycap->audio_endpointnumber); - purb->transfer_flags = URB_ISO_ASAP; - purb->transfer_buffer = peasycap->audio_isoc_buffer[isbuf].pgo; - purb->transfer_buffer_length = peasycap->audio_isoc_buffer_size; - purb->complete = easycap_alsa_complete; - purb->context = peasycap; - purb->start_frame = 0; - purb->number_of_packets = peasycap->audio_isoc_framesperdesc; - for (j = 0; j < peasycap->audio_isoc_framesperdesc; j++) { - purb->iso_frame_desc[j].offset = j * peasycap->audio_isoc_maxframesize; - purb->iso_frame_desc[j].length = peasycap->audio_isoc_maxframesize; - } - - rc = usb_submit_urb(purb, GFP_KERNEL); - if (rc) { - isbad++; - SAM("ERROR: usb_submit_urb() failed" - " for urb with rc: -%s: %d\n", - strerror(rc), rc); - } else { - m++; - } - } else { - isbad++; - } - } - if (nospc) { - SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc); - SAM("..... possibly inadequate USB bandwidth\n"); - peasycap->audio_eof = 1; - } - if (isbad) { - JOM(4, "attempting cleanup instead of submitting\n"); - list_for_each(plist_head, (peasycap->purb_audio_head)) { - pdata_urb = list_entry(plist_head, struct data_urb, list_head); - if (pdata_urb && pdata_urb->purb) - usb_kill_urb(pdata_urb->purb); - } - peasycap->audio_isoc_streaming = 0; - } else { - peasycap->audio_isoc_streaming = m; - JOM(4, "submitted %i audio urbs\n", m); - } - - return 0; -} -/*****************************************************************************/ -/*---------------------------------------------------------------------------*/ -/* - * KILL ALL AUDIO URBS. - */ -/*---------------------------------------------------------------------------*/ -int -kill_audio_urbs(struct easycap *peasycap) -{ - int m; - struct list_head *plist_head; - struct data_urb *pdata_urb; - - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } - - if (!peasycap->audio_isoc_streaming) { - JOM(8, "%i=audio_isoc_streaming, no audio urbs killed\n", - peasycap->audio_isoc_streaming); - return 0; - } - - if (!peasycap->purb_audio_head) { - SAM("ERROR: peasycap->purb_audio_head is NULL\n"); - return -EFAULT; - } - - peasycap->audio_isoc_streaming = 0; - JOM(4, "killing audio urbs\n"); - m = 0; - list_for_each(plist_head, (peasycap->purb_audio_head)) { - pdata_urb = list_entry(plist_head, struct data_urb, list_head); - if (pdata_urb && pdata_urb->purb) { - usb_kill_urb(pdata_urb->purb); - m++; - } - } - JOM(4, "%i audio urbs killed\n", m); - - return 0; -} -/*****************************************************************************/ -- cgit v0.10.2 From 47cefc21ef4ce2c8caec931a2dbe7fef1727fc31 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 9 Nov 2011 08:26:33 -0300 Subject: [media] easycap: remove linux/version.h include from easycap_ioctl.c Signed-off-by: Tomas Winkler Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/easycap/easycap_ioctl.c b/drivers/staging/media/easycap/easycap_ioctl.c index f5bc741..acb9c84 100644 --- a/drivers/staging/media/easycap/easycap_ioctl.c +++ b/drivers/staging/media/easycap/easycap_ioctl.c @@ -25,7 +25,6 @@ */ /*****************************************************************************/ -#include #include "easycap.h" /*--------------------------------------------------------------------------*/ -- cgit v0.10.2 From 7dbb3920252dcb3662e934b134ccb5129f62cbad Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 9 Nov 2011 08:26:34 -0300 Subject: [media] easycap: compress initialization tables 1. saa and stk initialization tables are less then 256 entries 2. stk table can fit into u16 and saa into u8 size before text data bss dec hex filename 105687 1072 1134800 1241559 12f1d7 easycap.ko size after text data bss dec hex filename 97919 1072 1134800 1233791 12d37f easycap.ko Signed-off-by: Tomas Winkler Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/easycap/easycap_low.c b/drivers/staging/media/easycap/easycap_low.c index 02bb2e5..ef37de8 100644 --- a/drivers/staging/media/easycap/easycap_low.c +++ b/drivers/staging/media/easycap/easycap_low.c @@ -60,9 +60,9 @@ /*--------------------------------------------------------------------------*/ static const struct stk1160config { - int reg; - int set; -} stk1160configPAL[256] = { + u16 reg; + u16 set; +} stk1160configPAL[] = { {0x000, 0x0098}, {0x002, 0x0093}, @@ -104,7 +104,7 @@ static const struct stk1160config { {0xFFF, 0xFFFF} }; /*--------------------------------------------------------------------------*/ -static const struct stk1160config stk1160configNTSC[256] = { +static const struct stk1160config stk1160configNTSC[] = { {0x000, 0x0098}, {0x002, 0x0093}, @@ -147,9 +147,9 @@ static const struct stk1160config stk1160configNTSC[256] = { }; /*--------------------------------------------------------------------------*/ static const struct saa7113config { - int reg; - int set; -} saa7113configPAL[256] = { + u8 reg; + u8 set; +} saa7113configPAL[] = { {0x01, 0x08}, {0x02, 0x80}, {0x03, 0x33}, @@ -203,7 +203,7 @@ static const struct saa7113config { {0xFF, 0xFF} }; /*--------------------------------------------------------------------------*/ -static const struct saa7113config saa7113configNTSC[256] = { +static const struct saa7113config saa7113configNTSC[] = { {0x01, 0x08}, {0x02, 0x80}, {0x03, 0x33}, -- cgit v0.10.2 From 101dca425da49edb3093000d72490216fa322911 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 9 Nov 2011 08:26:35 -0300 Subject: [media] easycap: streamline the code change statements of types if (err) return err else do something and if (ok) do something else return err into if (err) return err do something Signed-off-by: Tomas Winkler Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/easycap/easycap_ioctl.c b/drivers/staging/media/easycap/easycap_ioctl.c index acb9c84..ccab5ca 100644 --- a/drivers/staging/media/easycap/easycap_ioctl.c +++ b/drivers/staging/media/easycap/easycap_ioctl.c @@ -666,16 +666,15 @@ int adjust_brightness(struct easycap *peasycap, int value) peasycap->inputset[peasycap->input].brightness_ok = 1; } else JOM(8, "%i=peasycap->input\n", peasycap->input); + mood = 0x00FF & (unsigned int)peasycap->brightness; - if (!write_saa(peasycap->pusb_device, 0x0A, mood)) { - SAM("adjusting brightness to 0x%02X\n", mood); - return 0; - } else { + if (write_saa(peasycap->pusb_device, 0x0A, mood)) { SAM("WARNING: failed to adjust brightness " "to 0x%02X\n", mood); return -ENOENT; } - break; + SAM("adjusting brightness to 0x%02X\n", mood); + return 0; } i1++; } @@ -725,15 +724,13 @@ int adjust_contrast(struct easycap *peasycap, int value) JOM(8, "%i=peasycap->input\n", peasycap->input); mood = 0x00FF & (unsigned int) (peasycap->contrast - 128); - if (!write_saa(peasycap->pusb_device, 0x0B, mood)) { - SAM("adjusting contrast to 0x%02X\n", mood); - return 0; - } else { + if (write_saa(peasycap->pusb_device, 0x0B, mood)) { SAM("WARNING: failed to adjust contrast to " "0x%02X\n", mood); return -ENOENT; } - break; + SAM("adjusting contrast to 0x%02X\n", mood); + return 0; } i1++; } @@ -783,14 +780,13 @@ int adjust_saturation(struct easycap *peasycap, int value) } else JOM(8, "%i=peasycap->input\n", peasycap->input); mood = 0x00FF & (unsigned int) (peasycap->saturation - 128); - if (!write_saa(peasycap->pusb_device, 0x0C, mood)) { - SAM("adjusting saturation to 0x%02X\n", mood); - return 0; - } else { + if (write_saa(peasycap->pusb_device, 0x0C, mood)) { SAM("WARNING: failed to adjust saturation to " "0x%02X\n", mood); return -ENOENT; } + SAM("adjusting saturation to 0x%02X\n", mood); + return 0; break; } i1++; @@ -838,13 +834,12 @@ int adjust_hue(struct easycap *peasycap, int value) JOM(8, "%i=peasycap->input\n", peasycap->input); i2 = peasycap->hue - 128; mood = 0x00FF & ((int) i2); - if (!write_saa(peasycap->pusb_device, 0x0D, mood)) { - SAM("adjusting hue to 0x%02X\n", mood); - return 0; - } else { + if (write_saa(peasycap->pusb_device, 0x0D, mood)) { SAM("WARNING: failed to adjust hue to 0x%02X\n", mood); return -ENOENT; } + SAM("adjusting hue to 0x%02X\n", mood); + return 0; break; } i1++; @@ -885,14 +880,12 @@ static int adjust_volume(struct easycap *peasycap, int value) ((31 < peasycap->volume) ? 31 : (s8) peasycap->volume); if (!audio_gainset(peasycap->pusb_device, mood)) { - SAM("adjusting volume to 0x%02X\n", mood); - return 0; - } else { SAM("WARNING: failed to adjust volume to " "0x%2X\n", mood); return -ENOENT; } - break; + SAM("adjusting volume to 0x%02X\n", mood); + return 0; } i1++; } diff --git a/drivers/staging/media/easycap/easycap_low.c b/drivers/staging/media/easycap/easycap_low.c index ef37de8..212830b 100644 --- a/drivers/staging/media/easycap/easycap_low.c +++ b/drivers/staging/media/easycap/easycap_low.c @@ -514,22 +514,22 @@ int ready_saa(struct usb_device *p) msleep(marktime); j++; } + if (max == j) return -1; + + if (0x20 & rc) { + rate = 2; + JOT(8, "hardware detects 60 Hz\n"); + } else { + rate = 0; + JOT(8, "hardware detects 50 Hz\n"); + } + if (0x80 & rc) + JOT(8, "hardware detects interlacing\n"); else { - if (0x20 & rc) { - rate = 2; - JOT(8, "hardware detects 60 Hz\n"); - } else { - rate = 0; - JOT(8, "hardware detects 50 Hz\n"); - } - if (0x80 & rc) - JOT(8, "hardware detects interlacing\n"); - else { - rate++; - JOT(8, "hardware detects no interlacing\n"); - } + rate++; + JOT(8, "hardware detects no interlacing\n"); } return 0; } diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c index 94fd116..044c762 100644 --- a/drivers/staging/media/easycap/easycap_main.c +++ b/drivers/staging/media/easycap/easycap_main.c @@ -165,14 +165,13 @@ static int easycap_open(struct inode *inode, struct file *file) if (!peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device is NULL\n"); return -EFAULT; - } else { - JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device); } + + JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device); + file->private_data = peasycap; rc = wakeup_device(peasycap->pusb_device); - if (0 == rc) - JOM(8, "wakeup_device() OK\n"); - else { + if (rc) { SAM("ERROR: wakeup_device() rc = %i\n", rc); if (-ENODEV == rc) SAM("ERROR: wakeup_device() returned -ENODEV\n"); @@ -180,6 +179,7 @@ static int easycap_open(struct inode *inode, struct file *file) SAM("ERROR: wakeup_device() rc = %i\n", rc); return rc; } + JOM(8, "wakeup_device() OK\n"); peasycap->input = 0; rc = reset(peasycap); if (rc) { @@ -987,11 +987,11 @@ static unsigned int easycap_poll(struct file *file, poll_table *wait) rc = easycap_dqbuf(peasycap, 0); peasycap->polled = 1; mutex_unlock(&easycapdc60_dongle[kd].mutex_video); - if (0 == rc) - return POLLIN | POLLRDNORM; - else + if (rc) return POLLERR; - } + + return POLLIN | POLLRDNORM; +} /*****************************************************************************/ /*---------------------------------------------------------------------------*/ /* @@ -2920,6 +2920,7 @@ static int easycap_usb_probe(struct usb_interface *intf, SAY("ERROR: usb_host_interface not found\n"); return -EFAULT; } + interface = &alt->desc; if (!interface) { SAY("ERROR: intf_descriptor is NULL\n"); @@ -2979,38 +2980,30 @@ static int easycap_usb_probe(struct usb_interface *intf, if (mutex_lock_interruptible(&mutex_dongle)) { SAY("ERROR: cannot down mutex_dongle\n"); return -ERESTARTSYS; - } else { -/*---------------------------------------------------------------------------*/ - /* - * FOR INTERFACES 1 AND 2 THE POINTER peasycap WILL NEED TO - * TO BE THE SAME AS THAT ALLOCATED NOW FOR INTERFACE 0. - * - * NORMALLY ndong WILL NOT HAVE CHANGED SINCE INTERFACE 0 WAS - * PROBED, BUT THIS MAY NOT BE THE CASE IF, FOR EXAMPLE, TWO - * EASYCAPs ARE PLUGGED IN SIMULTANEOUSLY. - */ -/*---------------------------------------------------------------------------*/ - for (ndong = 0; ndong < DONGLE_MANY; ndong++) { - if ((!easycapdc60_dongle[ndong].peasycap) && - (!mutex_is_locked(&easycapdc60_dongle - [ndong].mutex_video)) && - (!mutex_is_locked(&easycapdc60_dongle - [ndong].mutex_audio))) { - easycapdc60_dongle[ndong].peasycap = peasycap; - peasycap->isdongle = ndong; - JOM(8, "intf[%i]: peasycap-->easycap" - "_dongle[%i].peasycap\n", - bInterfaceNumber, ndong); - break; - } - } - if (DONGLE_MANY <= ndong) { - SAM("ERROR: too many dongles\n"); - mutex_unlock(&mutex_dongle); - return -ENOMEM; + } + + for (ndong = 0; ndong < DONGLE_MANY; ndong++) { + if ((!easycapdc60_dongle[ndong].peasycap) && + (!mutex_is_locked(&easycapdc60_dongle + [ndong].mutex_video)) && + (!mutex_is_locked(&easycapdc60_dongle + [ndong].mutex_audio))) { + easycapdc60_dongle[ndong].peasycap = peasycap; + peasycap->isdongle = ndong; + JOM(8, "intf[%i]: peasycap-->easycap" + "_dongle[%i].peasycap\n", + bInterfaceNumber, ndong); + break; } + } + + if (DONGLE_MANY <= ndong) { + SAM("ERROR: too many dongles\n"); mutex_unlock(&mutex_dongle); + return -ENOMEM; } + mutex_unlock(&mutex_dongle); + peasycap->allocation_video_struct = sizeof(struct easycap); peasycap->allocation_video_page = 0; peasycap->allocation_video_urb = 0; @@ -3393,11 +3386,10 @@ static int easycap_usb_probe(struct usb_interface *intf, if (!isokalt) { SAM("ERROR: no viable video_altsetting_on\n"); return -ENOENT; - } else { - peasycap->video_altsetting_on = okalt[isokalt - 1]; - JOM(4, "%i=video_altsetting_on <====\n", - peasycap->video_altsetting_on); } + peasycap->video_altsetting_on = okalt[isokalt - 1]; + JOM(4, "%i=video_altsetting_on <====\n", + peasycap->video_altsetting_on); /*---------------------------------------------------------------------------*/ /* * DECIDE THE VIDEO STREAMING PARAMETERS @@ -3483,8 +3475,9 @@ static int easycap_usb_probe(struct usb_interface *intf, SAM("ERROR: Could not allocate frame " "buffer %i page %i\n", k, m); return -ENOMEM; - } else - peasycap->allocation_video_page += 1; + } + + peasycap->allocation_video_page += 1; peasycap->frame_buffer[k][m].pgo = pbuf; } peasycap->frame_buffer[k][m].pto = @@ -3513,11 +3506,11 @@ static int easycap_usb_probe(struct usb_interface *intf, SAM("ERROR: Could not allocate field" " buffer %i page %i\n", k, m); return -ENOMEM; - } - else - peasycap->allocation_video_page += 1; - peasycap->field_buffer[k][m].pgo = pbuf; } + + peasycap->allocation_video_page += 1; + peasycap->field_buffer[k][m].pgo = pbuf; + } peasycap->field_buffer[k][m].pto = peasycap->field_buffer[k][m].pgo; } @@ -3541,9 +3534,9 @@ static int easycap_usb_probe(struct usb_interface *intf, SAM("ERROR: Could not allocate isoc video buffer " "%i\n", k); return -ENOMEM; - } else - peasycap->allocation_video_page += - BIT(VIDEO_ISOC_ORDER); + } + peasycap->allocation_video_page += + BIT(VIDEO_ISOC_ORDER); peasycap->video_isoc_buffer[k].pgo = pbuf; peasycap->video_isoc_buffer[k].pto = @@ -3572,15 +3565,17 @@ static int easycap_usb_probe(struct usb_interface *intf, SAM("ERROR: usb_alloc_urb returned NULL for buffer " "%i\n", k); return -ENOMEM; - } else - peasycap->allocation_video_urb += 1; + } + + peasycap->allocation_video_urb += 1; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL); if (!pdata_urb) { SAM("ERROR: Could not allocate struct data_urb.\n"); return -ENOMEM; - } else - peasycap->allocation_video_struct += + } + + peasycap->allocation_video_struct += sizeof(struct data_urb); pdata_urb->purb = purb; @@ -3697,13 +3692,12 @@ static int easycap_usb_probe(struct usb_interface *intf, err("Not able to register with videodev"); videodev_release(&(peasycap->video_device)); return -ENODEV; - } else { - (peasycap->registered_video)++; - SAM("registered with videodev: %i=minor\n", - peasycap->video_device.minor); - peasycap->minor = peasycap->video_device.minor; } -/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ + + peasycap->registered_video++; + SAM("registered with videodev: %i=minor\n", + peasycap->video_device.minor); + peasycap->minor = peasycap->video_device.minor; break; } @@ -3737,11 +3731,10 @@ static int easycap_usb_probe(struct usb_interface *intf, if (!isokalt) { SAM("ERROR: no viable audio_altsetting_on\n"); return -ENOENT; - } else { - peasycap->audio_altsetting_on = okalt[isokalt - 1]; - JOM(4, "%i=audio_altsetting_on <====\n", - peasycap->audio_altsetting_on); } + peasycap->audio_altsetting_on = okalt[isokalt - 1]; + JOM(4, "%i=audio_altsetting_on <====\n", + peasycap->audio_altsetting_on); peasycap->audio_endpointnumber = okepn[isokalt - 1]; JOM(4, "%i=audio_endpointnumber\n", peasycap->audio_endpointnumber); @@ -3850,8 +3843,8 @@ static int easycap_usb_probe(struct usb_interface *intf, SAM("ERROR: Could not allocate isoc audio buffer " "%i\n", k); return -ENOMEM; - } else - peasycap->allocation_audio_page += + } + peasycap->allocation_audio_page += BIT(AUDIO_ISOC_ORDER); peasycap->audio_isoc_buffer[k].pgo = pbuf; -- cgit v0.10.2 From 7dfdae8e32a26ef3b3aa8d114d2fed93d7680169 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 9 Nov 2011 08:26:36 -0300 Subject: [media] easycap: drop initializations to 0 in the probe functions peasycap was allocated using kzalloc so drop all to zero initializations Signed-off-by: Tomas Winkler Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c index 044c762..8da1682 100644 --- a/drivers/staging/media/easycap/easycap_main.c +++ b/drivers/staging/media/easycap/easycap_main.c @@ -3005,11 +3005,6 @@ static int easycap_usb_probe(struct usb_interface *intf, mutex_unlock(&mutex_dongle); peasycap->allocation_video_struct = sizeof(struct easycap); - peasycap->allocation_video_page = 0; - peasycap->allocation_video_urb = 0; - peasycap->allocation_audio_struct = 0; - peasycap->allocation_audio_page = 0; - peasycap->allocation_audio_urb = 0; /*---------------------------------------------------------------------------*/ /* @@ -3019,7 +3014,6 @@ static int easycap_usb_probe(struct usb_interface *intf, peasycap->pusb_device = usbdev; peasycap->pusb_interface = intf; - peasycap->ilk = 0; peasycap->microphone = false; peasycap->video_interface = -1; @@ -3038,11 +3032,6 @@ static int easycap_usb_probe(struct usb_interface *intf, peasycap->frame_buffer_many = FRAME_BUFFER_MANY; - for (k = 0; k < INPUT_MANY; k++) - peasycap->lost[k] = 0; - peasycap->skip = 0; - peasycap->skipped = 0; - peasycap->offerfields = 0; /*---------------------------------------------------------------------------*/ /* * DYNAMICALLY FILL IN THE AVAILABLE FORMATS ... @@ -3054,22 +3043,10 @@ static int easycap_usb_probe(struct usb_interface *intf, return -EFAULT; } JOM(4, "%i formats available\n", rc); -/*---------------------------------------------------------------------------*/ -/* - * ... AND POPULATE easycap.inputset[] -*/ -/*---------------------------------------------------------------------------*/ - /* FIXME: maybe we just use memset 0 */ + + /* ... AND POPULATE easycap.inputset[] */ + inputset = peasycap->inputset; - for (k = 0; k < INPUT_MANY; k++) { - inputset[k].input_ok = 0; - inputset[k].standard_offset_ok = 0; - inputset[k].format_offset_ok = 0; - inputset[k].brightness_ok = 0; - inputset[k].contrast_ok = 0; - inputset[k].saturation_ok = 0; - inputset[k].hue_ok = 0; - } fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN; m = 0; -- cgit v0.10.2 From 8b1fad2f046fb825046fee3a41885a70123de988 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 9 Nov 2011 08:26:37 -0300 Subject: [media] easycap: use usb_kill_urb wrapper functions 1. kill_video_usb can be used in all places where video urbs are killed and reduce code repetition 2. remove unnecessary check for easycap == NULL in the function as it is always checked by the calling function 3. rename the function to easycap_video_kill_urb to reduce possibility of name conflict 4. implement also easycap_audio_kill_urb 5. simplify freeing urbs Signed-off-by: Tomas Winkler Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/easycap/easycap.h b/drivers/staging/media/easycap/easycap.h index 899e572..1d98d31 100644 --- a/drivers/staging/media/easycap/easycap.h +++ b/drivers/staging/media/easycap/easycap.h @@ -472,7 +472,7 @@ struct easycap { long easycap_unlocked_ioctl(struct file *, unsigned int, unsigned long); int easycap_dqbuf(struct easycap *, int); int submit_video_urbs(struct easycap *); -int kill_video_urbs(struct easycap *); +int easycap_video_kill_urbs(struct easycap *); void easycap_testcard(struct easycap *, int); int fillin_formats(void); int newinput(struct easycap *, int); @@ -489,6 +489,7 @@ int adjust_hue(struct easycap *, int); */ /*---------------------------------------------------------------------------*/ int easycap_alsa_probe(struct easycap *); +int easycap_audio_kill_urbs(struct easycap *); void easycap_alsa_complete(struct urb *); int audio_setup(struct easycap *); /*---------------------------------------------------------------------------*/ diff --git a/drivers/staging/media/easycap/easycap_ioctl.c b/drivers/staging/media/easycap/easycap_ioctl.c index ccab5ca..90d4384 100644 --- a/drivers/staging/media/easycap/easycap_ioctl.c +++ b/drivers/staging/media/easycap/easycap_ioctl.c @@ -124,7 +124,7 @@ int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id) } if (peasycap->video_isoc_streaming) { resubmit = true; - kill_video_urbs(peasycap); + easycap_video_kill_urbs(peasycap); } else resubmit = false; /*--------------------------------------------------------------------------*/ @@ -557,7 +557,7 @@ int adjust_format(struct easycap *peasycap, peasycap->bytesperpixel * peasycap->width * peasycap->height; if (peasycap->video_isoc_streaming) { resubmit = true; - kill_video_urbs(peasycap); + easycap_video_kill_urbs(peasycap); } else resubmit = false; /*---------------------------------------------------------------------------*/ diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c index 8da1682..c147c61 100644 --- a/drivers/staging/media/easycap/easycap_main.c +++ b/drivers/staging/media/easycap/easycap_main.c @@ -401,7 +401,7 @@ newinput(struct easycap *peasycap, int input) peasycap->audio_idle = 1; if (peasycap->video_isoc_streaming) { resubmit = true; - kill_video_urbs(peasycap); + easycap_video_kill_urbs(peasycap); } else { resubmit = false; } @@ -620,43 +620,53 @@ int submit_video_urbs(struct easycap *peasycap) peasycap->video_eof = 1; } - if (isbad) { - JOM(4, "attempting cleanup instead of submitting\n"); - list_for_each(plist_head, (peasycap->purb_video_head)) { - pdata_urb = list_entry(plist_head, - struct data_urb, list_head); - if (pdata_urb) { - purb = pdata_urb->purb; - if (purb) - usb_kill_urb(purb); - } - } - peasycap->video_isoc_streaming = 0; - } else { + if (isbad) + easycap_video_kill_urbs(peasycap); + else peasycap->video_isoc_streaming = 1; - JOM(4, "submitted %i video urbs\n", m); - } } else { JOM(4, "already streaming video urbs\n"); } return 0; } /*****************************************************************************/ -int kill_video_urbs(struct easycap *peasycap) +int easycap_audio_kill_urbs(struct easycap *peasycap) { int m; struct list_head *plist_head; struct data_urb *pdata_urb; - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); + if (!peasycap->audio_isoc_streaming) + return 0; + + if (!peasycap->purb_audio_head) { + SAM("ERROR: peasycap->purb_audio_head is NULL\n"); return -EFAULT; } - if (!peasycap->video_isoc_streaming) { - JOM(8, "%i=video_isoc_streaming, no video urbs killed\n", - peasycap->video_isoc_streaming); - return 0; + + peasycap->audio_isoc_streaming = 0; + m = 0; + list_for_each(plist_head, peasycap->purb_audio_head) { + pdata_urb = list_entry(plist_head, struct data_urb, list_head); + if (pdata_urb && pdata_urb->purb) { + usb_kill_urb(pdata_urb->purb); + m++; + } } + + JOM(4, "%i audio urbs killed\n", m); + + return 0; +} +int easycap_video_kill_urbs(struct easycap *peasycap) +{ + int m; + struct list_head *plist_head; + struct data_urb *pdata_urb; + + if (!peasycap->video_isoc_streaming) + return 0; + if (!peasycap->purb_video_head) { SAM("ERROR: peasycap->purb_video_head is NULL\n"); return -EFAULT; @@ -694,8 +704,8 @@ static int videodev_release(struct video_device *pvideo_device) SAY("ending unsuccessfully\n"); return -EFAULT; } - if (0 != kill_video_urbs(peasycap)) { - SAM("ERROR: kill_video_urbs() failed\n"); + if (easycap_video_kill_urbs(peasycap)) { + SAM("ERROR: easycap_video_kill_urbs() failed\n"); return -EFAULT; } JOM(4, "ending successfully\n"); @@ -738,20 +748,15 @@ static void easycap_delete(struct kref *pkref) */ /*---------------------------------------------------------------------------*/ if (peasycap->purb_video_head) { - JOM(4, "freeing video urbs\n"); m = 0; - list_for_each(plist_head, (peasycap->purb_video_head)) { + list_for_each(plist_head, peasycap->purb_video_head) { pdata_urb = list_entry(plist_head, struct data_urb, list_head); - if (!pdata_urb) { - JOM(4, "ERROR: pdata_urb is NULL\n"); - } else { - if (pdata_urb->purb) { - usb_free_urb(pdata_urb->purb); - pdata_urb->purb = NULL; - peasycap->allocation_video_urb -= 1; - m++; - } + if (pdata_urb && pdata_urb->purb) { + usb_free_urb(pdata_urb->purb); + pdata_urb->purb = NULL; + peasycap->allocation_video_urb--; + m++; } } @@ -767,7 +772,6 @@ static void easycap_delete(struct kref *pkref) peasycap->allocation_video_struct -= sizeof(struct data_urb); kfree(pdata_urb); - pdata_urb = NULL; m++; } } @@ -832,15 +836,11 @@ static void easycap_delete(struct kref *pkref) list_for_each(plist_head, (peasycap->purb_audio_head)) { pdata_urb = list_entry(plist_head, struct data_urb, list_head); - if (!pdata_urb) - JOM(4, "ERROR: pdata_urb is NULL\n"); - else { - if (pdata_urb->purb) { - usb_free_urb(pdata_urb->purb); - pdata_urb->purb = NULL; - peasycap->allocation_audio_urb -= 1; - m++; - } + if (pdata_urb && pdata_urb->purb) { + usb_free_urb(pdata_urb->purb); + pdata_urb->purb = NULL; + peasycap->allocation_audio_urb--; + m++; } } JOM(4, "%i audio urbs freed\n", m); @@ -855,7 +855,6 @@ static void easycap_delete(struct kref *pkref) peasycap->allocation_audio_struct -= sizeof(struct data_urb); kfree(pdata_urb); - pdata_urb = NULL; m++; } } @@ -1084,7 +1083,7 @@ int easycap_dqbuf(struct easycap *peasycap, int mode) JOM(8, " ... failed returning -EIO\n"); peasycap->video_eof = 1; peasycap->audio_eof = 1; - kill_video_urbs(peasycap); + easycap_video_kill_urbs(peasycap); return -EIO; } peasycap->status = 0; @@ -1094,7 +1093,7 @@ int easycap_dqbuf(struct easycap *peasycap, int mode) #endif /*PERSEVERE*/ peasycap->video_eof = 1; peasycap->audio_eof = 1; - kill_video_urbs(peasycap); + easycap_video_kill_urbs(peasycap); JOM(8, "returning -EIO\n"); return -EIO; } @@ -1147,7 +1146,7 @@ int easycap_dqbuf(struct easycap *peasycap, int mode) JOM(8, " ... failed returning -EIO\n"); peasycap->video_eof = 1; peasycap->audio_eof = 1; - kill_video_urbs(peasycap); + easycap_video_kill_urbs(peasycap); return -EIO; } peasycap->status = 0; @@ -1157,7 +1156,7 @@ int easycap_dqbuf(struct easycap *peasycap, int mode) #endif /*PERSEVERE*/ peasycap->video_eof = 1; peasycap->audio_eof = 1; - kill_video_urbs(peasycap); + easycap_video_kill_urbs(peasycap); JOM(8, "returning -EIO\n"); return -EIO; } @@ -3969,12 +3968,9 @@ static void easycap_usb_disconnect(struct usb_interface *pusb_interface) { struct usb_host_interface *pusb_host_interface; struct usb_interface_descriptor *pusb_interface_descriptor; - u8 bInterfaceNumber; struct easycap *peasycap; - - struct list_head *plist_head; - struct data_urb *pdata_urb; - int minor, m, kd; + int minor, kd; + u8 bInterfaceNumber; JOT(4, "\n"); @@ -4009,45 +4005,14 @@ static void easycap_usb_disconnect(struct usb_interface *pusb_interface) peasycap->audio_eof = 1; wake_up_interruptible(&(peasycap->wq_video)); wake_up_interruptible(&(peasycap->wq_audio)); -/*---------------------------------------------------------------------------*/ + switch (bInterfaceNumber) { - case 0: { - if (peasycap->purb_video_head) { - JOM(4, "killing video urbs\n"); - m = 0; - list_for_each(plist_head, peasycap->purb_video_head) { - pdata_urb = list_entry(plist_head, - struct data_urb, list_head); - if (pdata_urb) { - if (pdata_urb->purb) { - usb_kill_urb(pdata_urb->purb); - m++; - } - } - } - JOM(4, "%i video urbs killed\n", m); - } + case 0: + easycap_video_kill_urbs(peasycap); break; - } -/*---------------------------------------------------------------------------*/ - case 2: { - if (peasycap->purb_audio_head) { - JOM(4, "killing audio urbs\n"); - m = 0; - list_for_each(plist_head, peasycap->purb_audio_head) { - pdata_urb = list_entry(plist_head, - struct data_urb, list_head); - if (pdata_urb) { - if (pdata_urb->purb) { - usb_kill_urb(pdata_urb->purb); - m++; - } - } - } - JOM(4, "%i audio urbs killed\n", m); - } + case 2: + easycap_audio_kill_urbs(peasycap); break; - } default: break; } diff --git a/drivers/staging/media/easycap/easycap_sound.c b/drivers/staging/media/easycap/easycap_sound.c index 70813a5e..f7f9a76 100644 --- a/drivers/staging/media/easycap/easycap_sound.c +++ b/drivers/staging/media/easycap/easycap_sound.c @@ -138,18 +138,11 @@ static int submit_audio_urbs(struct easycap *peasycap) SAM("..... possibly inadequate USB bandwidth\n"); peasycap->audio_eof = 1; } - if (isbad) { - JOM(4, "attempting cleanup instead of submitting\n"); - list_for_each(plist_head, (peasycap->purb_audio_head)) { - pdata_urb = list_entry(plist_head, struct data_urb, list_head); - if (pdata_urb && pdata_urb->purb) - usb_kill_urb(pdata_urb->purb); - } - peasycap->audio_isoc_streaming = 0; - } else { + + if (isbad) + easycap_audio_kill_urbs(peasycap); + else peasycap->audio_isoc_streaming = m; - JOM(4, "submitted %i audio urbs\n", m); - } return 0; } -- cgit v0.10.2 From 4329f3c6a5fb4ed2332c7552894e7e4b8efef194 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 9 Nov 2011 08:26:38 -0300 Subject: [media] easycap: easycap_usb_driver should be static to easycap_main.c Signed-off-by: Tomas Winkler Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/easycap/easycap.h b/drivers/staging/media/easycap/easycap.h index 1d98d31..9e9638c 100644 --- a/drivers/staging/media/easycap/easycap.h +++ b/drivers/staging/media/easycap/easycap.h @@ -567,7 +567,6 @@ extern bool easycap_readback; extern const struct easycap_standard easycap_standard[]; extern struct easycap_format easycap_format[]; extern struct v4l2_queryctrl easycap_control[]; -extern struct usb_driver easycap_usb_driver; extern struct easycap_dongle easycapdc60_dongle[]; #endif /* !__EASYCAP_H__ */ diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c index c147c61..f7af1d2 100644 --- a/drivers/staging/media/easycap/easycap_main.c +++ b/drivers/staging/media/easycap/easycap_main.c @@ -4150,7 +4150,7 @@ static struct usb_device_id easycap_usb_device_id_table[] = { }; MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table); -struct usb_driver easycap_usb_driver = { +static struct usb_driver easycap_usb_driver = { .name = "easycap", .id_table = easycap_usb_device_id_table, .probe = easycap_usb_probe, -- cgit v0.10.2 From a5b6ee06b21eaee64f100be8591fd51917bdbe36 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 9 Nov 2011 08:26:39 -0300 Subject: [media] easycap: remove unused members of struct easycap Signed-off-by: Tomas Winkler Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/easycap/easycap.h b/drivers/staging/media/easycap/easycap.h index 9e9638c..3a081ab 100644 --- a/drivers/staging/media/easycap/easycap.h +++ b/drivers/staging/media/easycap/easycap.h @@ -324,8 +324,6 @@ struct easycap { int lost[INPUT_MANY]; int merit[180]; - long long int dnbydt; - int video_interface; int video_altsetting_on; int video_altsetting_off; @@ -353,7 +351,6 @@ struct easycap { u8 *pcache; int video_mt; int audio_mt; - long long audio_bytes; u32 isequence; int vma_many; @@ -450,9 +447,6 @@ struct easycap { * SOUND PROPERTIES */ /*---------------------------------------------------------------------------*/ - - int audio_buffer_many; - int allocation_audio_urb; int allocation_audio_page; int allocation_audio_struct; -- cgit v0.10.2 From 96bec7dd72511e3c16588d9af52da2cc937f7ea1 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 9 Nov 2011 08:26:40 -0300 Subject: [media] easycap: add easycap prefix to global functions names Add easycap prefix to global function to reduce possibility of name collision. Signed-off-by: Tomas Winkler Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/easycap/easycap.h b/drivers/staging/media/easycap/easycap.h index 3a081ab..b0e54f78 100644 --- a/drivers/staging/media/easycap/easycap.h +++ b/drivers/staging/media/easycap/easycap.h @@ -463,13 +463,16 @@ struct easycap { * VIDEO FUNCTION PROTOTYPES */ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +int easycap_newinput(struct easycap *, int); +void easycap_testcard(struct easycap *, int); +int easycap_isdongle(struct easycap *); + long easycap_unlocked_ioctl(struct file *, unsigned int, unsigned long); -int easycap_dqbuf(struct easycap *, int); -int submit_video_urbs(struct easycap *); + +int easycap_video_dqbuf(struct easycap *, int); +int easycap_video_submit_urbs(struct easycap *); int easycap_video_kill_urbs(struct easycap *); -void easycap_testcard(struct easycap *, int); -int fillin_formats(void); -int newinput(struct easycap *, int); +int easycap_video_fillin_formats(void); int adjust_standard(struct easycap *, v4l2_std_id); int adjust_format(struct easycap *, u32, u32, u32, int, bool); @@ -485,15 +488,15 @@ int adjust_hue(struct easycap *, int); int easycap_alsa_probe(struct easycap *); int easycap_audio_kill_urbs(struct easycap *); void easycap_alsa_complete(struct urb *); -int audio_setup(struct easycap *); /*---------------------------------------------------------------------------*/ /* * LOW-LEVEL FUNCTION PROTOTYPES */ /*---------------------------------------------------------------------------*/ -int audio_gainset(struct usb_device *, s8); +int easycap_audio_gainset(struct usb_device *, s8); +int easycap_audio_setup(struct easycap *); -int wakeup_device(struct usb_device *); +int easycap_wakeup_device(struct usb_device *); int setup_stk(struct usb_device *, bool); int setup_saa(struct usb_device *, bool); @@ -507,7 +510,6 @@ int read_saa(struct usb_device *, u16); int write_saa(struct usb_device *, u16, u16); int start_100(struct usb_device *); int stop_100(struct usb_device *); -int isdongle(struct easycap *); /*---------------------------------------------------------------------------*/ diff --git a/drivers/staging/media/easycap/easycap_ioctl.c b/drivers/staging/media/easycap/easycap_ioctl.c index 90d4384..9413b37 100644 --- a/drivers/staging/media/easycap/easycap_ioctl.c +++ b/drivers/staging/media/easycap/easycap_ioctl.c @@ -330,7 +330,7 @@ int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id) "from 0x%02X to 0x%02X\n", reg, itwas, isnow); } if (resubmit) - submit_video_urbs(peasycap); + easycap_video_submit_urbs(peasycap); return 0; } /*****************************************************************************/ @@ -621,7 +621,7 @@ int adjust_format(struct easycap *peasycap, } /*---------------------------------------------------------------------------*/ if (resubmit) - submit_video_urbs(peasycap); + easycap_video_submit_urbs(peasycap); return peasycap_best_format - easycap_format; } @@ -879,7 +879,7 @@ static int adjust_volume(struct easycap *peasycap, int value) mood = (16 > peasycap->volume) ? 16 : ((31 < peasycap->volume) ? 31 : (s8) peasycap->volume); - if (!audio_gainset(peasycap->pusb_device, mood)) { + if (!easycap_audio_gainset(peasycap->pusb_device, mood)) { SAM("WARNING: failed to adjust volume to " "0x%2X\n", mood); return -ENOENT; @@ -963,7 +963,7 @@ long easycap_unlocked_ioctl(struct file *file, SAM("ERROR: peasycap->pusb_device is NULL\n"); return -EFAULT; } - kd = isdongle(peasycap); + kd = easycap_isdongle(peasycap); if (0 <= kd && DONGLE_MANY > kd) { if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) { SAY("ERROR: cannot lock " @@ -978,7 +978,7 @@ long easycap_unlocked_ioctl(struct file *file, * IF NECESSARY, BAIL OUT. */ /*---------------------------------------------------------------------------*/ - if (kd != isdongle(peasycap)) + if (kd != easycap_isdongle(peasycap)) return -ERESTARTSYS; if (!file) { SAY("ERROR: file is NULL\n"); @@ -1218,7 +1218,7 @@ long easycap_unlocked_ioctl(struct file *file, return -EINVAL; } - rc = newinput(peasycap, (int)index); + rc = easycap_newinput(peasycap, (int)index); if (0 == rc) { JOM(8, "newinput(.,%i) OK\n", (int)index); } else { @@ -2201,7 +2201,7 @@ long easycap_unlocked_ioctl(struct file *file, if (!peasycap->polled) { do { - rcdq = easycap_dqbuf(peasycap, 0); + rcdq = easycap_video_dqbuf(peasycap, 0); if (-EIO == rcdq) { JOM(8, "returning -EIO because " "dqbuf() returned -EIO\n"); @@ -2305,7 +2305,7 @@ long easycap_unlocked_ioctl(struct file *file, mutex_unlock(&easycapdc60_dongle[kd].mutex_video); return -EFAULT; } - submit_video_urbs(peasycap); + easycap_video_submit_urbs(peasycap); peasycap->video_idle = 0; peasycap->audio_idle = 0; peasycap->video_eof = 0; diff --git a/drivers/staging/media/easycap/easycap_low.c b/drivers/staging/media/easycap/easycap_low.c index 212830b..59fdb8f 100644 --- a/drivers/staging/media/easycap/easycap_low.c +++ b/drivers/staging/media/easycap/easycap_low.c @@ -724,10 +724,11 @@ int stop_100(struct usb_device *p) /****************************************************************************/ /****************************************************************************/ /*****************************************************************************/ -int wakeup_device(struct usb_device *pusb_device) +int easycap_wakeup_device(struct usb_device *pusb_device) { if (!pusb_device) return -ENODEV; + return usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), USB_REQ_SET_FEATURE, USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, @@ -735,8 +736,7 @@ int wakeup_device(struct usb_device *pusb_device) 0, NULL, 0, 50000); } /*****************************************************************************/ -int -audio_setup(struct easycap *peasycap) +int easycap_audio_setup(struct easycap *peasycap) { struct usb_device *pusb_device; u8 buffer[1]; @@ -817,7 +817,7 @@ audio_setup(struct easycap *peasycap) * SELECT AUDIO SOURCE "LINE IN" AND SET THE AUDIO GAIN. */ /*---------------------------------------------------------------------------*/ - if (0 != audio_gainset(pusb_device, peasycap->gain)) + if (easycap_audio_gainset(pusb_device, peasycap->gain)) SAY("ERROR: audio_gainset() failed\n"); check_vt(pusb_device); return 0; @@ -894,7 +894,7 @@ int check_vt(struct usb_device *pusb_device) * 31 12.0 22.5 34.5 */ /*---------------------------------------------------------------------------*/ -int audio_gainset(struct usb_device *pusb_device, s8 loud) +int easycap_audio_gainset(struct usb_device *pusb_device, s8 loud) { int igot; u8 tmp; diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c index f7af1d2..ce23beb 100644 --- a/drivers/staging/media/easycap/easycap_main.c +++ b/drivers/staging/media/easycap/easycap_main.c @@ -129,7 +129,7 @@ const char *strerror(int err) * THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap */ /*---------------------------------------------------------------------------*/ -int isdongle(struct easycap *peasycap) +int easycap_isdongle(struct easycap *peasycap) { int k; if (!peasycap) @@ -170,7 +170,7 @@ static int easycap_open(struct inode *inode, struct file *file) JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device); file->private_data = peasycap; - rc = wakeup_device(peasycap->pusb_device); + rc = easycap_wakeup_device(peasycap->pusb_device); if (rc) { SAM("ERROR: wakeup_device() rc = %i\n", rc); if (-ENODEV == rc) @@ -307,7 +307,7 @@ static int reset(struct easycap *peasycap) peasycap->saturation = -8192; peasycap->hue = -8192; - rc = newinput(peasycap, input); + rc = easycap_newinput(peasycap, input); if (rc) { SAM("ERROR: newinput(.,%i) rc = %i\n", rc, input); @@ -368,8 +368,7 @@ static int reset(struct easycap *peasycap) * SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE. */ /*---------------------------------------------------------------------------*/ -int -newinput(struct easycap *peasycap, int input) +int easycap_newinput(struct easycap *peasycap, int input) { int rc, k, m, mood, off; int inputnow, video_idlenow, audio_idlenow; @@ -536,7 +535,7 @@ newinput(struct easycap *peasycap, int input) return -EFAULT; } if (resubmit) - submit_video_urbs(peasycap); + easycap_video_submit_urbs(peasycap); peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1; peasycap->video_idle = video_idlenow; @@ -546,7 +545,7 @@ newinput(struct easycap *peasycap, int input) return 0; } /*****************************************************************************/ -int submit_video_urbs(struct easycap *peasycap) +int easycap_video_submit_urbs(struct easycap *peasycap) { struct data_urb *pdata_urb; struct urb *purb; @@ -741,7 +740,7 @@ static void easycap_delete(struct kref *pkref) SAM("ERROR: peasycap is NULL: cannot perform deletions\n"); return; } - kd = isdongle(peasycap); + kd = easycap_isdongle(peasycap); /*---------------------------------------------------------------------------*/ /* * FREE VIDEO. @@ -943,7 +942,7 @@ static unsigned int easycap_poll(struct file *file, poll_table *wait) return -EFAULT; } /*---------------------------------------------------------------------------*/ - kd = isdongle(peasycap); + kd = easycap_isdongle(peasycap); if (0 <= kd && DONGLE_MANY > kd) { if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) { SAY("ERROR: cannot down dongle[%i].mutex_video\n", kd); @@ -955,7 +954,7 @@ static unsigned int easycap_poll(struct file *file, poll_table *wait) * peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL. * IF NECESSARY, BAIL OUT. */ - if (kd != isdongle(peasycap)) { + if (kd != easycap_isdongle(peasycap)) { mutex_unlock(&easycapdc60_dongle[kd].mutex_video); return -ERESTARTSYS; } @@ -983,7 +982,7 @@ static unsigned int easycap_poll(struct file *file, poll_table *wait) */ return -ERESTARTSYS; /*---------------------------------------------------------------------------*/ - rc = easycap_dqbuf(peasycap, 0); + rc = easycap_video_dqbuf(peasycap, 0); peasycap->polled = 1; mutex_unlock(&easycapdc60_dongle[kd].mutex_video); if (rc) @@ -997,7 +996,7 @@ static unsigned int easycap_poll(struct file *file, poll_table *wait) * IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING. */ /*---------------------------------------------------------------------------*/ -int easycap_dqbuf(struct easycap *peasycap, int mode) +int easycap_video_dqbuf(struct easycap *peasycap, int mode) { int input, ifield, miss, rc; @@ -3036,7 +3035,7 @@ static int easycap_usb_probe(struct usb_interface *intf, * DYNAMICALLY FILL IN THE AVAILABLE FORMATS ... */ /*---------------------------------------------------------------------------*/ - rc = fillin_formats(); + rc = easycap_video_fillin_formats(); if (0 > rc) { SAM("ERROR: fillin_formats() rc = %i\n", rc); return -EFAULT; @@ -4025,7 +4024,7 @@ static void easycap_usb_disconnect(struct usb_interface *pusb_interface) * AN EasyCAP IS UNPLUGGED WHILE THE URBS ARE RUNNING. BEWARE. */ /*--------------------------------------------------------------------------*/ - kd = isdongle(peasycap); + kd = easycap_isdongle(peasycap); switch (bInterfaceNumber) { case 0: { if (0 <= kd && DONGLE_MANY > kd) { diff --git a/drivers/staging/media/easycap/easycap_settings.c b/drivers/staging/media/easycap/easycap_settings.c index 70f59b1..3f5f5b3 100644 --- a/drivers/staging/media/easycap/easycap_settings.c +++ b/drivers/staging/media/easycap/easycap_settings.c @@ -313,7 +313,7 @@ const struct easycap_standard easycap_standard[] = { struct easycap_format easycap_format[1 + SETTINGS_MANY]; -int fillin_formats(void) +int easycap_video_fillin_formats(void) { const char *name1, *name2, *name3, *name4; struct v4l2_format *fmt; diff --git a/drivers/staging/media/easycap/easycap_sound.c b/drivers/staging/media/easycap/easycap_sound.c index f7f9a76..353b6b7 100644 --- a/drivers/staging/media/easycap/easycap_sound.c +++ b/drivers/staging/media/easycap/easycap_sound.c @@ -61,7 +61,7 @@ static const struct snd_pcm_hardware alsa_hardware = { * SUBMIT ALL AUDIO URBS. */ /*---------------------------------------------------------------------------*/ -static int submit_audio_urbs(struct easycap *peasycap) +static int easycap_audio_submit_urbs(struct easycap *peasycap) { struct data_urb *pdata_urb; struct urb *purb; @@ -69,10 +69,6 @@ static int submit_audio_urbs(struct easycap *peasycap) int j, isbad, nospc, m, rc; int isbuf; - if (!peasycap) { - SAY("ERROR: peasycap is NULL\n"); - return -EFAULT; - } if (!peasycap->purb_audio_head) { SAM("ERROR: peasycap->urb_audio_head uninitialized\n"); return -EFAULT; @@ -167,7 +163,7 @@ static int easycap_sound_setup(struct easycap *peasycap) } JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device); - rc = audio_setup(peasycap); + rc = easycap_audio_setup(peasycap); JOM(8, "audio_setup() returned %i\n", rc); if (!peasycap->pusb_device) { @@ -184,13 +180,13 @@ static int easycap_sound_setup(struct easycap *peasycap) JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, peasycap->audio_altsetting_on, rc); - rc = wakeup_device(peasycap->pusb_device); + rc = easycap_wakeup_device(peasycap->pusb_device); JOM(8, "wakeup_device() returned %i\n", rc); peasycap->audio_eof = 0; peasycap->audio_idle = 0; - submit_audio_urbs(peasycap); + easycap_audio_submit_urbs(peasycap); JOM(4, "finished initialization\n"); return 0; @@ -203,8 +199,7 @@ static int easycap_sound_setup(struct easycap *peasycap) * IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO. */ /*---------------------------------------------------------------------------*/ -void -easycap_alsa_complete(struct urb *purb) +void easycap_alsa_complete(struct urb *purb) { struct easycap *peasycap; struct snd_pcm_substream *pss; -- cgit v0.10.2 From 0b217d2125acc039d2f3a94f01821472fbbb75b6 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 9 Nov 2011 08:26:41 -0300 Subject: [media] easycap: drop usb_class_driver Drop usb_class_driver and collaterals as it is not used Signed-off-by: Tomas Winkler Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/easycap/easycap.h b/drivers/staging/media/easycap/easycap.h index b0e54f78..a007e74 100644 --- a/drivers/staging/media/easycap/easycap.h +++ b/drivers/staging/media/easycap/easycap.h @@ -98,7 +98,6 @@ #define EASYCAP_DRIVER_VERSION "0.9.01" #define EASYCAP_DRIVER_DESCRIPTION "easycapdc60" -#define USB_SKEL_MINOR_BASE 192 #define DONGLE_MANY 8 #define INPUT_MANY 6 /*---------------------------------------------------------------------------*/ diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c index ce23beb..525a6b6 100644 --- a/drivers/staging/media/easycap/easycap_main.c +++ b/drivers/staging/media/easycap/easycap_main.c @@ -113,16 +113,6 @@ const char *strerror(int err) #undef ERRNOSTR } -/*---------------------------------------------------------------------------*/ -/* - * PARAMETERS USED WHEN REGISTERING THE VIDEO INTERFACE - * - * NOTE: SOME KERNELS IGNORE usb_class_driver.minor_base, AS MENTIONED BY - * CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGE 253. - * THIS IS THE CASE FOR OpenSUSE. - */ -/*---------------------------------------------------------------------------*/ -/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ /****************************************************************************/ /*---------------------------------------------------------------------------*/ /* @@ -2856,20 +2846,7 @@ static void easycap_complete(struct urb *purb) } return; } -static const struct file_operations easycap_fops = { - .owner = THIS_MODULE, - .open = easycap_open, - .unlocked_ioctl = easycap_unlocked_ioctl, - .poll = easycap_poll, - .mmap = easycap_mmap, - .llseek = no_llseek, -}; -static const struct usb_class_driver easycap_class = { - .name = "usb/easycap%d", - .fops = &easycap_fops, - .minor_base = USB_SKEL_MINOR_BASE, -}; -/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ + static const struct v4l2_file_operations v4l2_fops = { .owner = THIS_MODULE, .open = easycap_open_noinode, -- cgit v0.10.2 From a6ff0a06d8634a07db52dbc006fd9ce4c438c1e3 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 9 Nov 2011 08:26:42 -0300 Subject: [media] easycap: fix warnings: variable set but not used Signed-off-by: Tomas Winkler Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/easycap/easycap_low.c b/drivers/staging/media/easycap/easycap_low.c index 59fdb8f..0380bab 100644 --- a/drivers/staging/media/easycap/easycap_low.c +++ b/drivers/staging/media/easycap/easycap_low.c @@ -468,13 +468,17 @@ int setup_stk(struct usb_device *p, bool ntsc) /****************************************************************************/ int setup_saa(struct usb_device *p, bool ntsc) { - int i, ir; + int i, rc; const struct saa7113config *cfg; if (!p) return -ENODEV; cfg = (ntsc) ? saa7113configNTSC : saa7113configPAL; - for (i = 0; cfg[i].reg != 0xFF; i++) - ir = write_saa(p, cfg[i].reg, cfg[i].set); + for (i = 0; cfg[i].reg != 0xFF; i++) { + rc = write_saa(p, cfg[i].reg, cfg[i].set); + if (rc) + dev_err(&p->dev, + "Failed to set SAA register %d", cfg[i].reg); + } return 0; } /****************************************************************************/ diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c index 525a6b6..8ff5f38 100644 --- a/drivers/staging/media/easycap/easycap_main.c +++ b/drivers/staging/media/easycap/easycap_main.c @@ -1199,8 +1199,6 @@ int easycap_video_dqbuf(struct easycap *peasycap, int mode) * WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH * odd==false IS TRANSFERRED TO THE FRAME BUFFER. * - * THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM - * CHOOSES THE OPTION V4L2_FIELD_INTERLACED. */ /*---------------------------------------------------------------------------*/ static int field2frame(struct easycap *peasycap) @@ -1212,7 +1210,7 @@ static int field2frame(struct easycap *peasycap) int rc, bytesperpixel, multiplier; int much, more, over, rump, caches, input; u8 mask, margin; - bool odd, isuy, decimatepixel, offerfields, badinput; + bool odd, isuy, decimatepixel, badinput; if (!peasycap) { SAY("ERROR: peasycap is NULL\n"); @@ -1228,8 +1226,6 @@ static int field2frame(struct easycap *peasycap) peasycap->field_buffer[peasycap->field_read][0].input, peasycap->field_read, peasycap->frame_fill); JOM(8, "===== %i=bytesperpixel\n", peasycap->bytesperpixel); - if (peasycap->offerfields) - JOM(8, "===== offerfields\n"); /*---------------------------------------------------------------------------*/ /* @@ -1251,7 +1247,6 @@ static int field2frame(struct easycap *peasycap) #endif /*EASYCAP_TESTCARD*/ /*---------------------------------------------------------------------------*/ - offerfields = peasycap->offerfields; bytesperpixel = peasycap->bytesperpixel; decimatepixel = peasycap->decimatepixel; diff --git a/drivers/staging/media/easycap/easycap_sound.c b/drivers/staging/media/easycap/easycap_sound.c index 353b6b7..8c8bcae 100644 --- a/drivers/staging/media/easycap/easycap_sound.c +++ b/drivers/staging/media/easycap/easycap_sound.c @@ -592,7 +592,6 @@ static int easycap_alsa_ack(struct snd_pcm_substream *pss) static int easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd) { struct easycap *peasycap; - int retval; JOT(4, "%i=cmd cf %i=START %i=STOP\n", cmd, SNDRV_PCM_TRIGGER_START, SNDRV_PCM_TRIGGER_STOP); @@ -615,7 +614,7 @@ static int easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd) break; } default: - retval = -EINVAL; + return -EINVAL; } return 0; } -- cgit v0.10.2 From a1ed02e9f1a0fa34e5b5e978209204033bb9cf4f Mon Sep 17 00:00:00 2001 From: Andreas Oberritter Date: Wed, 16 Nov 2011 11:06:50 -0300 Subject: [media] em28xx: Add Terratec Cinergy HTC Stick Signed-off-by: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 5b0336b..1704da0 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -927,6 +927,19 @@ struct em28xx_board em28xx_boards[] = { EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ, }, + [EM2884_BOARD_CINERGY_HTC_STICK] = { + .name = "Terratec Cinergy HTC Stick", + .has_dvb = 1, +#if 0 + .tuner_type = TUNER_PHILIPS_TDA8290, + .tuner_addr = 0x41, + .dvb_gpio = terratec_h5_digital, /* FIXME: probably wrong */ + .tuner_gpio = terratec_h5_gpio, +#endif + .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | + EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_400_KHZ, + }, [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = { .name = "Hauppauge WinTV HVR 900", .tda9887_conf = TDA9887_PRESENT, @@ -1960,6 +1973,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2860_BOARD_TERRATEC_GRABBY }, { USB_DEVICE(0x0ccd, 0x10AF), .driver_info = EM2860_BOARD_TERRATEC_GRABBY }, + { USB_DEVICE(0x0ccd, 0x00b2), + .driver_info = EM2884_BOARD_CINERGY_HTC_STICK }, { USB_DEVICE(0x0fd9, 0x0033), .driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE}, { USB_DEVICE(0x185b, 0x2870), diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index eb41e25..7f0592c 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -902,6 +902,7 @@ static int em28xx_dvb_init(struct em28xx *dev) break; } case EM2884_BOARD_TERRATEC_H5: + case EM2884_BOARD_CINERGY_HTC_STICK: terratec_h5_init(dev); dvb->dont_attach_fe1 = 1; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index c16ae8f..b1199ef 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -123,6 +123,7 @@ #define EM2884_BOARD_TERRATEC_H5 79 #define EM28174_BOARD_PCTV_460E 80 #define EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C 81 +#define EM2884_BOARD_CINERGY_HTC_STICK 82 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v0.10.2 From dd7aaa4d9d97a8571bcfa498e90b9daf540db1cf Mon Sep 17 00:00:00 2001 From: Gianluca Gennari Date: Thu, 17 Nov 2011 12:35:05 -0300 Subject: [media] staging: as102: Add support for Sky Italia Digital Key based on the same chip Add support for the Sky Italia Digital Key, an USB dongle offered by Sky Italia to its customers for use with their satellite set-top-boxes. This is the "green led" model based on the Abilis as102 chip, while the so called "blue led" model is based on the Avermedia A867 design. Cc: Devin Heitmueller Signed-off-by: Sylwester Nawrocki Signed-off-by: Gianluca Gennari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/as102/as102_usb_drv.c b/drivers/staging/media/as102/as102_usb_drv.c index 9faab5b..7bcb28c 100644 --- a/drivers/staging/media/as102/as102_usb_drv.c +++ b/drivers/staging/media/as102/as102_usb_drv.c @@ -42,6 +42,7 @@ static struct usb_device_id as102_usb_id_table[] = { { USB_DEVICE(PCTV_74E_USB_VID, PCTV_74E_USB_PID) }, { USB_DEVICE(ELGATO_EYETV_DTT_USB_VID, ELGATO_EYETV_DTT_USB_PID) }, { USB_DEVICE(NBOX_DVBT_DONGLE_USB_VID, NBOX_DVBT_DONGLE_USB_PID) }, + { USB_DEVICE(SKY_IT_DIGITAL_KEY_USB_VID, SKY_IT_DIGITAL_KEY_USB_PID) }, { } /* Terminating entry */ }; @@ -52,6 +53,7 @@ static const char * const as102_device_names[] = { AS102_PCTV_74E, AS102_ELGATO_EYETV_DTT_NAME, AS102_NBOX_DVBT_DONGLE_NAME, + AS102_SKY_IT_DIGITAL_KEY_NAME, NULL /* Terminating entry */ }; diff --git a/drivers/staging/media/as102/as102_usb_drv.h b/drivers/staging/media/as102/as102_usb_drv.h index 35925b7..fc2884a 100644 --- a/drivers/staging/media/as102/as102_usb_drv.h +++ b/drivers/staging/media/as102/as102_usb_drv.h @@ -47,6 +47,11 @@ #define NBOX_DVBT_DONGLE_USB_VID 0x0b89 #define NBOX_DVBT_DONGLE_USB_PID 0x0007 +/* Sky Italia: Digital Key (green led) */ +#define AS102_SKY_IT_DIGITAL_KEY_NAME "Sky IT Digital Key (green led)" +#define SKY_IT_DIGITAL_KEY_USB_VID 0x2137 +#define SKY_IT_DIGITAL_KEY_USB_PID 0x0001 + void as102_urb_stream_irq(struct urb *urb); struct as10x_usb_token_cmd_t { -- cgit v0.10.2 From 2e802861403c95ad6a566ff6d7a1a1a45d29c30e Mon Sep 17 00:00:00 2001 From: Olivier Grenie Date: Fri, 5 Aug 2011 10:39:15 -0300 Subject: [media] dib7000p/dib0090: update the driver This patch intends to update the dib7000p and dib0090 driver in order to improve the performances. Signed-off-by: Olivier Grenie Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index f313182..771dfda 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -2092,6 +2092,14 @@ static int dib7090_agc_startup(struct dvb_frontend *fe, struct dvb_frontend_para return 0; } +static int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart) +{ + deb_info("AGC restart callback: %d", restart); + if (restart == 0) /* before AGC startup */ + dib0090_set_dc_servo(fe, 1); + return 0; +} + static struct dib0090_wbd_slope dib7090_wbd_table[] = { { 380, 81, 850, 64, 540, 4}, { 860, 51, 866, 21, 375, 4}, diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c index b174d1c..9030f3d 100644 --- a/drivers/media/dvb/frontends/dib0090.c +++ b/drivers/media/dvb/frontends/dib0090.c @@ -1112,13 +1112,21 @@ void dib0090_pwm_gain_reset(struct dvb_frontend *fe) else dib0090_write_reg(state, 0x32, (0 << 11)); - dib0090_write_reg(state, 0x04, 0x01); + dib0090_write_reg(state, 0x04, 0x03); dib0090_write_reg(state, 0x39, (1 << 10)); } } EXPORT_SYMBOL(dib0090_pwm_gain_reset); +void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff) +{ + struct dib0090_state *state = fe->tuner_priv; + if (DC_servo_cutoff < 4) + dib0090_write_reg(state, 0x04, DC_servo_cutoff); +} +EXPORT_SYMBOL(dib0090_set_dc_servo); + static u32 dib0090_get_slow_adc_val(struct dib0090_state *state) { u16 adc_val = dib0090_read_reg(state, 0x1d); @@ -1505,7 +1513,10 @@ static int dib0090_reset(struct dvb_frontend *fe) dib0090_set_EFUSE(state); /* Congigure in function of the crystal */ - if (state->config->io.clock_khz >= 24000) + if (state->config->force_crystal_mode != 0) + dib0090_write_reg(state, 0x14, + state->config->force_crystal_mode & 3); + else if (state->config->io.clock_khz >= 24000) dib0090_write_reg(state, 0x14, 1); else dib0090_write_reg(state, 0x14, 2); diff --git a/drivers/media/dvb/frontends/dib0090.h b/drivers/media/dvb/frontends/dib0090.h index 13d8524..648318a 100644 --- a/drivers/media/dvb/frontends/dib0090.h +++ b/drivers/media/dvb/frontends/dib0090.h @@ -71,6 +71,8 @@ struct dib0090_config { u8 fref_clock_ratio; u16 force_cband_input; struct dib0090_wbd_slope *wbd; + u8 is_dib7090e; + u8 force_crystal_mode; }; #if defined(CONFIG_DVB_TUNER_DIB0090) || (defined(CONFIG_DVB_TUNER_DIB0090_MODULE) && defined(MODULE)) @@ -83,6 +85,7 @@ extern int dib0090_gain_control(struct dvb_frontend *fe); extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe); extern int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state); extern void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt); +extern void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff); #else static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0090_config *config) { @@ -134,6 +137,11 @@ static inline void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); } + +static inline void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); +} #endif #endif diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index ce8534f..08e62a4 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -70,6 +70,8 @@ struct dib7000p_state { u8 i2c_write_buffer[4]; u8 i2c_read_buffer[2]; struct mutex i2c_buffer_lock; + + u8 input_mode_mpeg; }; enum dib7000p_power_mode { @@ -78,8 +80,18 @@ enum dib7000p_power_mode { DIB7000P_POWER_INTERFACE_ONLY, }; +/* dib7090 specific fonctions */ +#define MPEG_ON_DIBTX 1 +#define DIV_ON_DIBTX 2 +#define ADC_ON_DIBTX 3 +#define DEMOUT_ON_HOSTBUS 4 +#define DIBTX_ON_HOSTBUS 5 +#define MPEG_ON_HOSTBUS 6 + static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode); static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff); +static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode); +static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode); static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) { @@ -276,17 +288,23 @@ static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_p dib7000p_write_word(state, 774, reg_774); dib7000p_write_word(state, 775, reg_775); dib7000p_write_word(state, 776, reg_776); - dib7000p_write_word(state, 899, reg_899); dib7000p_write_word(state, 1280, reg_1280); + if (state->version != SOC7090) + dib7000p_write_word(state, 899, reg_899); return 0; } static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no) { - u16 reg_908 = dib7000p_read_word(state, 908), reg_909 = dib7000p_read_word(state, 909); + u16 reg_908 = 0, reg_909 = 0; u16 reg; + if (state->version != SOC7090) { + reg_908 = dib7000p_read_word(state, 908); + reg_909 = dib7000p_read_word(state, 909); + } + switch (no) { case DIBX000_SLOW_ADC_ON: if (state->version == SOC7090) { @@ -342,8 +360,10 @@ static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_ad reg_909 |= (state->cfg.disable_sample_and_hold & 1) << 4; reg_908 |= (state->cfg.enable_current_mirror & 1) << 7; - dib7000p_write_word(state, 908, reg_908); - dib7000p_write_word(state, 909, reg_909); + if (state->version != SOC7090) { + dib7000p_write_word(state, 908, reg_908); + dib7000p_write_word(state, 909, reg_909); + } } static int dib7000p_set_bandwidth(struct dib7000p_state *state, u32 bw) @@ -519,7 +539,7 @@ static u16 dib7000p_defaults[] = { // auto search configuration 3, 2, 0x0004, - 0x1000, + (1<<3)|(1<<11)|(1<<12)|(1<<13), 0x0814, /* Equal Lock */ 12, 6, @@ -595,13 +615,6 @@ static u16 dib7000p_defaults[] = { 1, 235, 0x0062, - 2, 901, - 0x0006, - (3 << 10) | (1 << 6), - - 1, 905, - 0x2c8e, - 0, }; @@ -618,15 +631,18 @@ static int dib7000p_demod_reset(struct dib7000p_state *state) dib7000p_write_word(state, 770, 0xffff); dib7000p_write_word(state, 771, 0xffff); dib7000p_write_word(state, 772, 0x001f); - dib7000p_write_word(state, 898, 0x0003); dib7000p_write_word(state, 1280, 0x001f - ((1 << 4) | (1 << 3))); dib7000p_write_word(state, 770, 0); dib7000p_write_word(state, 771, 0); dib7000p_write_word(state, 772, 0); - dib7000p_write_word(state, 898, 0); dib7000p_write_word(state, 1280, 0); + if (state->version != SOC7090) { + dib7000p_write_word(state, 898, 0x0003); + dib7000p_write_word(state, 898, 0); + } + /* default */ dib7000p_reset_pll(state); @@ -640,7 +656,7 @@ static int dib7000p_demod_reset(struct dib7000p_state *state) dib7000p_write_word(state, 42, (1<<5) | 3); /* P_iqc_thsat_ipc = 1 ; P_iqc_win2 = 3 */ dib7000p_write_word(state, 43, 0x2d4); /*-300 fag P_iqc_dect_min = -280 */ dib7000p_write_word(state, 44, 300); /* 300 fag P_iqc_dect_min = +280 */ - dib7000p_write_word(state, 273, (1<<6) | 30); + dib7000p_write_word(state, 273, (0<<6) | 30); } if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0) dprintk("OUTPUT_MODE could not be reset."); @@ -655,7 +671,7 @@ static int dib7000p_demod_reset(struct dib7000p_state *state) dib7000p_set_bandwidth(state, 8000); if (state->version == SOC7090) { - dib7000p_write_word(state, 36, 0x5755);/* P_iqc_impnc_on =1 & P_iqc_corr_inh = 1 for impulsive noise */ + dib7000p_write_word(state, 36, 0x0755);/* P_iqc_impnc_on =1 & P_iqc_corr_inh = 1 for impulsive noise */ } else { if (state->cfg.tuner_is_baseband) dib7000p_write_word(state, 36, 0x0755); @@ -664,6 +680,11 @@ static int dib7000p_demod_reset(struct dib7000p_state *state) } dib7000p_write_tab(state, dib7000p_defaults); + if (state->version != SOC7090) { + dib7000p_write_word(state, 901, 0x0006); + dib7000p_write_word(state, 902, (3 << 10) | (1 << 6)); + dib7000p_write_word(state, 905, 0x2c8e); + } dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); @@ -1080,9 +1101,12 @@ static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dvb_fron dib7000p_set_channel(state, &schan, 7); factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth); - if (factor >= 5000) - factor = 1; - else + if (factor >= 5000) { + if (state->version == SOC7090) + factor = 2; + else + factor = 1; + } else factor = 6; value = 30 * internal * factor; @@ -1323,7 +1347,7 @@ static int dib7000p_sleep(struct dvb_frontend *demod) { struct dib7000p_state *state = demod->demodulator_priv; if (state->version == SOC7090) - return dib7090_set_output_mode(demod, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); + return dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); } @@ -1445,10 +1469,9 @@ static int dib7000p_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_pa struct dib7000p_state *state = fe->demodulator_priv; int time, ret; - if (state->version == SOC7090) { + if (state->version == SOC7090) dib7090_set_diversity_in(fe, 0); - dib7090_set_output_mode(fe, OUTMODE_HIGH_Z); - } else + else dib7000p_set_output_mode(state, OUTMODE_HIGH_Z); /* maybe the parameter has been changed */ @@ -1485,9 +1508,13 @@ static int dib7000p_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_pa ret = dib7000p_tune(fe, fep); /* make this a config parameter */ - if (state->version == SOC7090) + if (state->version == SOC7090) { dib7090_set_output_mode(fe, state->cfg.output_mode); - else + if (state->cfg.enMpegOutput == 0) { + dib7090_setDibTxMux(state, MPEG_ON_DIBTX); + dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS); + } + } else dib7000p_set_output_mode(state, state->cfg.output_mode); return ret; @@ -1933,10 +1960,10 @@ static int dib7090_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[] apb_address = 915; break; case 0x27: - apb_address = 916; + apb_address = 917; break; case 0x28: - apb_address = 917; + apb_address = 916; break; case 0x1d: i = ((dib7000p_read_word(state, 72) >> 12) & 0x3); @@ -2031,12 +2058,7 @@ static u32 dib7090_calcSyncFreq(u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 static int dib7090_cfg_DibTx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 synchroMode, u32 syncWord, u32 syncSize) { - u8 index_buf; - u16 rx_copy_buf[22]; - dprintk("Configure DibStream Tx"); - for (index_buf = 0; index_buf < 22; index_buf++) - rx_copy_buf[index_buf] = dib7000p_read_word(state, 1536+index_buf); dib7000p_write_word(state, 1615, 1); dib7000p_write_word(state, 1603, P_Kin); @@ -2048,9 +2070,6 @@ static int dib7090_cfg_DibTx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout dib7000p_write_word(state, 1612, syncSize); dib7000p_write_word(state, 1615, 0); - for (index_buf = 0; index_buf < 22; index_buf++) - dib7000p_write_word(state, 1536+index_buf, rx_copy_buf[index_buf]); - return 0; } @@ -2077,109 +2096,121 @@ static int dib7090_cfg_DibRx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout return 0; } -static int dib7090_enDivOnHostBus(struct dib7000p_state *state) -{ - u16 reg; - - dprintk("Enable Diversity on host bus"); - reg = (1 << 8) | (1 << 5); - dib7000p_write_word(state, 1288, reg); - - return dib7090_cfg_DibTx(state, 5, 5, 0, 0, 0, 0); -} - -static int dib7090_enAdcOnHostBus(struct dib7000p_state *state) -{ - u16 reg; - - dprintk("Enable ADC on host bus"); - reg = (1 << 7) | (1 << 5); - dib7000p_write_word(state, 1288, reg); - - return dib7090_cfg_DibTx(state, 20, 5, 10, 0, 0, 0); -} - -static int dib7090_enMpegOnHostBus(struct dib7000p_state *state) +static void dib7090_enMpegMux(struct dib7000p_state *state, int onoff) { - u16 reg; - - dprintk("Enable Mpeg on host bus"); - reg = (1 << 9) | (1 << 5); - dib7000p_write_word(state, 1288, reg); + u16 reg_1287 = dib7000p_read_word(state, 1287); - return dib7090_cfg_DibTx(state, 8, 5, 0, 0, 0, 0); -} + switch (onoff) { + case 1: + reg_1287 &= ~(1<<7); + break; + case 0: + reg_1287 |= (1<<7); + break; + } -static int dib7090_enMpegInput(struct dib7000p_state *state) -{ - dprintk("Enable Mpeg input"); - return dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0); /*outputRate = 8 */ + dib7000p_write_word(state, 1287, reg_1287); } -static int dib7090_enMpegMux(struct dib7000p_state *state, u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2) +static void dib7090_configMpegMux(struct dib7000p_state *state, + u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2) { - u16 reg = (1 << 7) | ((pulseWidth & 0x1f) << 2) | ((enSerialMode & 0x1) << 1) | (enSerialClkDiv2 & 0x1); - dprintk("Enable Mpeg mux"); - dib7000p_write_word(state, 1287, reg); - reg &= ~(1 << 7); - dib7000p_write_word(state, 1287, reg); + dib7090_enMpegMux(state, 0); - reg = (1 << 4); - dib7000p_write_word(state, 1288, reg); + /* If the input mode is MPEG do not divide the serial clock */ + if ((enSerialMode == 1) && (state->input_mode_mpeg == 1)) + enSerialClkDiv2 = 0; - return 0; + dib7000p_write_word(state, 1287, ((pulseWidth & 0x1f) << 2) + | ((enSerialMode & 0x1) << 1) + | (enSerialClkDiv2 & 0x1)); + + dib7090_enMpegMux(state, 1); } -static int dib7090_disableMpegMux(struct dib7000p_state *state) +static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode) { - u16 reg; - - dprintk("Disable Mpeg mux"); - dib7000p_write_word(state, 1288, 0); + u16 reg_1288 = dib7000p_read_word(state, 1288) & ~(0x7 << 7); - reg = dib7000p_read_word(state, 1287); - reg &= ~(1 << 7); - dib7000p_write_word(state, 1287, reg); - - return 0; + switch (mode) { + case MPEG_ON_DIBTX: + dprintk("SET MPEG ON DIBSTREAM TX"); + dib7090_cfg_DibTx(state, 8, 5, 0, 0, 0, 0); + reg_1288 |= (1<<9); + break; + case DIV_ON_DIBTX: + dprintk("SET DIV_OUT ON DIBSTREAM TX"); + dib7090_cfg_DibTx(state, 5, 5, 0, 0, 0, 0); + reg_1288 |= (1<<8); + break; + case ADC_ON_DIBTX: + dprintk("SET ADC_OUT ON DIBSTREAM TX"); + dib7090_cfg_DibTx(state, 20, 5, 10, 0, 0, 0); + reg_1288 |= (1<<7); + break; + default: + break; + } + dib7000p_write_word(state, 1288, reg_1288); } -static int dib7090_set_input_mode(struct dvb_frontend *fe, int mode) +static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode) { - struct dib7000p_state *state = fe->demodulator_priv; + u16 reg_1288 = dib7000p_read_word(state, 1288) & ~(0x7 << 4); switch (mode) { - case INPUT_MODE_DIVERSITY: - dprintk("Enable diversity INPUT"); - dib7090_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0); + case DEMOUT_ON_HOSTBUS: + dprintk("SET DEM OUT OLD INTERF ON HOST BUS"); + dib7090_enMpegMux(state, 0); + reg_1288 |= (1<<6); + break; + case DIBTX_ON_HOSTBUS: + dprintk("SET DIBSTREAM TX ON HOST BUS"); + dib7090_enMpegMux(state, 0); + reg_1288 |= (1<<5); break; - case INPUT_MODE_MPEG: - dprintk("Enable Mpeg INPUT"); - dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0); /*outputRate = 8 */ + case MPEG_ON_HOSTBUS: + dprintk("SET MPEG MUX ON HOST BUS"); + reg_1288 |= (1<<4); break; - case INPUT_MODE_OFF: default: - dprintk("Disable INPUT"); - dib7090_cfg_DibRx(state, 0, 0, 0, 0, 0, 0, 0); break; } - return 0; + dib7000p_write_word(state, 1288, reg_1288); } -static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff) +int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff) { + struct dib7000p_state *state = fe->demodulator_priv; + u16 reg_1287; + switch (onoff) { - case 0: /* only use the internal way - not the diversity input */ - dib7090_set_input_mode(fe, INPUT_MODE_MPEG); - break; - case 1: /* both ways */ - case 2: /* only the diversity input */ - dib7090_set_input_mode(fe, INPUT_MODE_DIVERSITY); - break; + case 0: /* only use the internal way - not the diversity input */ + dprintk("%s mode OFF : by default Enable Mpeg INPUT", __func__); + dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0); + + /* Do not divide the serial clock of MPEG MUX */ + /* in SERIAL MODE in case input mode MPEG is used */ + reg_1287 = dib7000p_read_word(state, 1287); + /* enSerialClkDiv2 == 1 ? */ + if ((reg_1287 & 0x1) == 1) { + /* force enSerialClkDiv2 = 0 */ + reg_1287 &= ~0x1; + dib7000p_write_word(state, 1287, reg_1287); + } + state->input_mode_mpeg = 1; + break; + case 1: /* both ways */ + case 2: /* only the diversity input */ + dprintk("%s ON : Enable diversity INPUT", __func__); + dib7090_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0); + state->input_mode_mpeg = 0; + break; } + dib7000p_set_diversity_in(&state->demod, onoff); return 0; } @@ -2204,69 +2235,63 @@ static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode) case OUTMODE_MPEG2_SERIAL: if (prefer_mpeg_mux_use) { - dprintk("Sip 7090P setting output mode TS_SERIAL using Mpeg Mux"); - dib7090_enMpegOnHostBus(state); - dib7090_enMpegInput(state); - if (state->cfg.enMpegOutput == 1) - dib7090_enMpegMux(state, 3, 1, 1); - - } else { /* Use Smooth block */ - dprintk("Sip 7090P setting output mode TS_SERIAL using Smooth bloc"); - dib7090_disableMpegMux(state); - dib7000p_write_word(state, 1288, (1 << 6)); - outreg |= (2 << 6) | (0 << 1); + dprintk("setting output mode TS_SERIAL using Mpeg Mux"); + dib7090_configMpegMux(state, 3, 1, 1); + dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS); + } else {/* Use Smooth block */ + dprintk("setting output mode TS_SERIAL using Smooth bloc"); + dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS); + outreg |= (2<<6) | (0 << 1); } break; case OUTMODE_MPEG2_PAR_GATED_CLK: if (prefer_mpeg_mux_use) { - dprintk("Sip 7090P setting output mode TS_PARALLEL_GATED using Mpeg Mux"); - dib7090_enMpegOnHostBus(state); - dib7090_enMpegInput(state); - if (state->cfg.enMpegOutput == 1) - dib7090_enMpegMux(state, 2, 0, 0); - } else { /* Use Smooth block */ - dprintk("Sip 7090P setting output mode TS_PARALLEL_GATED using Smooth block"); - dib7090_disableMpegMux(state); - dib7000p_write_word(state, 1288, (1 << 6)); - outreg |= (0 << 6); + dprintk("setting output mode TS_PARALLEL_GATED using Mpeg Mux"); + dib7090_configMpegMux(state, 2, 0, 0); + dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS); + } else { /* Use Smooth block */ + dprintk("setting output mode TS_PARALLEL_GATED using Smooth block"); + dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS); + outreg |= (0<<6); } break; case OUTMODE_MPEG2_PAR_CONT_CLK: /* Using Smooth block only */ - dprintk("Sip 7090P setting output mode TS_PARALLEL_CONT using Smooth block"); - dib7090_disableMpegMux(state); - dib7000p_write_word(state, 1288, (1 << 6)); - outreg |= (1 << 6); + dprintk("setting output mode TS_PARALLEL_CONT using Smooth block"); + dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS); + outreg |= (1<<6); break; case OUTMODE_MPEG2_FIFO: /* Using Smooth block because not supported by new Mpeg Mux bloc */ - dprintk("Sip 7090P setting output mode TS_FIFO using Smooth block"); - dib7090_disableMpegMux(state); - dib7000p_write_word(state, 1288, (1 << 6)); - outreg |= (5 << 6); + dprintk("setting output mode TS_FIFO using Smooth block"); + dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS); + outreg |= (5<<6); smo_mode |= (3 << 1); fifo_threshold = 512; break; case OUTMODE_DIVERSITY: - dprintk("Sip 7090P setting output mode MODE_DIVERSITY"); - dib7090_disableMpegMux(state); - dib7090_enDivOnHostBus(state); + dprintk("setting output mode MODE_DIVERSITY"); + dib7090_setDibTxMux(state, DIV_ON_DIBTX); + dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS); break; case OUTMODE_ANALOG_ADC: - dprintk("Sip 7090P setting output mode MODE_ANALOG_ADC"); - dib7090_enAdcOnHostBus(state); + dprintk("setting output mode MODE_ANALOG_ADC"); + dib7090_setDibTxMux(state, ADC_ON_DIBTX); + dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS); break; } + if (mode != OUTMODE_HIGH_Z) + outreg |= (1 << 10); if (state->cfg.output_mpeg2_in_188_bytes) smo_mode |= (1 << 5); ret |= dib7000p_write_word(state, 235, smo_mode); ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */ - ret |= dib7000p_write_word(state, 1286, outreg | (1 << 10)); /* allways set Dout active = 1 !!! */ + ret |= dib7000p_write_word(state, 1286, outreg); return ret; } @@ -2296,13 +2321,6 @@ int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff) } EXPORT_SYMBOL(dib7090_tuner_sleep); -int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart) -{ - dprintk("AGC restart callback: %d", restart); - return 0; -} -EXPORT_SYMBOL(dib7090_agc_restart); - int dib7090_get_adc_power(struct dvb_frontend *fe) { return dib7000p_get_adc_power(fe); diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h index 0179f94..58f907c 100644 --- a/drivers/media/dvb/frontends/dib7000p.h +++ b/drivers/media/dvb/frontends/dib7000p.h @@ -56,7 +56,6 @@ extern int dib7000p_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff); extern int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff); extern int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw); extern u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf); -extern int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart); extern int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff); extern int dib7090_get_adc_power(struct dvb_frontend *fe); extern struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe); @@ -122,12 +121,6 @@ static inline u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf) return 0; } -static inline int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart) -{ - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); - return -ENODEV; -} - static inline int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -- cgit v0.10.2 From 6724a2f4f7a6cb9251641a46e1ab06bb85adf1b5 Mon Sep 17 00:00:00 2001 From: Olivier Grenie Date: Fri, 5 Aug 2011 13:49:33 -0300 Subject: [media] dib7090: add the reference board TFE7090E The intend of this patch is to add the support for the DiBcom reference board TFE7090E. Signed-off-by: Olivier Grenie Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 771dfda..aeab321 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1518,7 +1518,7 @@ static int dib8096_set_param_override(struct dvb_frontend *fe, if (ret < 0) return ret; - target = (dib0090_get_wbd_offset(fe) * 8 * 18 / 33 + 1) / 2; + target = (dib0090_get_wbd_target(fe) * 8 * 18 / 33 + 1) / 2; dib8000_set_wbd_ref(fe, target); @@ -2079,7 +2079,7 @@ static int dib7090_agc_startup(struct dvb_frontend *fe, struct dvb_frontend_para memset(&pll, 0, sizeof(struct dibx000_bandwidth_config)); dib0090_pwm_gain_reset(fe); - target = (dib0090_get_wbd_offset(fe) * 8 + 1) / 2; + target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2; dib7000p_set_wbd_ref(fe, target); if (dib7090p_get_best_sampling(fe, &adc) == 0) { @@ -2100,6 +2100,41 @@ static int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart) return 0; } +static int dib7090e_update_lna(struct dvb_frontend *fe, u16 agc_global) +{ + u16 agc1 = 0, agc2, wbd = 0, wbd_target, wbd_offset, threshold_agc1; + s16 wbd_delta; + + if ((fe->dtv_property_cache.frequency) < 400000000) + threshold_agc1 = 25000; + else + threshold_agc1 = 30000; + + wbd_target = (dib0090_get_wbd_target(fe)*8+1)/2; + wbd_offset = dib0090_get_wbd_offset(fe); + dib7000p_get_agc_values(fe, NULL, &agc1, &agc2, &wbd); + wbd_delta = (s16)wbd - (((s16)wbd_offset+10)*4) ; + + deb_info("update lna, agc_global=%d agc1=%d agc2=%d", + agc_global, agc1, agc2); + deb_info("update lna, wbd=%d wbd target=%d wbd offset=%d wbd delta=%d", + wbd, wbd_target, wbd_offset, wbd_delta); + + if ((agc1 < threshold_agc1) && (wbd_delta > 0)) { + dib0090_set_switch(fe, 1, 1, 1); + dib0090_set_vga(fe, 0); + dib0090_update_rframp_7090(fe, 0); + dib0090_update_tuning_table_7090(fe, 0); + } else { + dib0090_set_vga(fe, 1); + dib0090_update_rframp_7090(fe, 1); + dib0090_update_tuning_table_7090(fe, 1); + dib0090_set_switch(fe, 0, 0, 0); + } + + return 0; +} + static struct dib0090_wbd_slope dib7090_wbd_table[] = { { 380, 81, 850, 64, 540, 4}, { 860, 51, 866, 21, 375, 4}, @@ -2108,6 +2143,15 @@ static struct dib0090_wbd_slope dib7090_wbd_table[] = { { 0xFFFF, 0, 0, 0, 0, 0}, }; +static struct dib0090_wbd_slope dib7090e_wbd_table[] = { + { 380, 81, 850, 64, 540, 4}, + { 700, 51, 866, 21, 320, 4}, + { 860, 48, 666, 18, 330, 6}, + {1700, 0, 250, 0, 100, 6}, + {2600, 0, 250, 0, 100, 6}, + { 0xFFFF, 0, 0, 0, 0, 0}, +}; + struct dibx000_agc_config dib7090_agc_config[2] = { { .band_caps = BAND_UHF, @@ -2286,6 +2330,34 @@ static struct dib7000p_config tfe7090pvr_dib7000p_config[2] = { } }; +static struct dib7000p_config tfe7090e_dib7000p_config = { + .output_mpeg2_in_188_bytes = 1, + .hostbus_diversity = 1, + .tuner_is_baseband = 1, + .update_lna = dib7090e_update_lna, + + .agc_config_count = 2, + .agc = dib7090_agc_config, + + .bw = &dib7090_clock_config_12_mhz, + + .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, + .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, + .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, + + .pwm_freq_div = 0, + + .agc_control = dib7090_agc_restart, + + .spur_protect = 0, + .disable_sample_and_hold = 0, + .enable_current_mirror = 0, + .diversity_delay = 0, + + .output_mode = OUTMODE_MPEG2_FIFO, + .enMpegOutput = 1, +}; + static const struct dib0090_config nim7090_dib0090_config = { .io.clock_khz = 12000, .io.pll_bypass = 0, @@ -2320,6 +2392,42 @@ static const struct dib0090_config nim7090_dib0090_config = { .in_soc = 1, }; +static const struct dib0090_config tfe7090e_dib0090_config = { + .io.clock_khz = 12000, + .io.pll_bypass = 0, + .io.pll_range = 0, + .io.pll_prediv = 3, + .io.pll_loopdiv = 6, + .io.adc_clock_ratio = 0, + .io.pll_int_loop_filt = 0, + .reset = dib7090_tuner_sleep, + .sleep = dib7090_tuner_sleep, + + .freq_offset_khz_uhf = 0, + .freq_offset_khz_vhf = 0, + + .get_adc_power = dib7090_get_adc_power, + + .clkouttobamse = 1, + .analog_output = 0, + + .wbd_vhf_offset = 0, + .wbd_cband_offset = 0, + .use_pwm_agc = 1, + .clkoutdrive = 0, + + .fref_clock_ratio = 0, + + .wbd = dib7090e_wbd_table, + + .ls_cfg_pad_drv = 0, + .data_tx_drv = 0, + .low_if = NULL, + .in_soc = 1, + .force_cband_input = 1, + .is_dib7090e = 1, +}; + static const struct dib0090_config tfe7090pvr_dib0090_config[2] = { { .io.clock_khz = 12000, @@ -2512,6 +2620,49 @@ static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap) return 0; } +static int tfe7090e_frontend_attach(struct dvb_usb_adapter *adap) +{ + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); + msleep(20); + dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); + + msleep(20); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); + msleep(20); + dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); + + if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, + 1, 0x10, &tfe7090e_dib7000p_config) != 0) { + err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", + __func__); + return -ENODEV; + } + adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, + 0x80, &tfe7090e_dib7000p_config); + + return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; +} + +static int tfe7090e_tuner_attach(struct dvb_usb_adapter *adap) +{ + struct dib0700_adapter_state *st = adap->priv; + struct i2c_adapter *tun_i2c = + dib7090_get_i2c_tuner(adap->fe_adap[0].fe); + + if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, + &tfe7090e_dib0090_config) == NULL) + return -ENODEV; + + dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1); + + st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; + adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup; + return 0; +} + /* STK7070PD */ static struct dib7000p_config stk7070pd_dib7000p_config[2] = { { @@ -2968,6 +3119,7 @@ struct usb_device_id dib0700_usb_id_table[] = { /* 75 */{ USB_DEVICE(USB_VID_MEDION, USB_PID_CREATIX_CTX1921) }, { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV340E) }, { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV340E_SE) }, + { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7090E) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -4033,6 +4185,46 @@ struct dvb_usb_device_properties dib0700_devices[] = { RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, + }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, + .num_adapters = 1, + .adapter = { + { + .num_frontends = 1, + .fe = {{ + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk70x0p_pid_filter, + .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, + .frontend_attach = tfe7090e_frontend_attach, + .tuner_attach = tfe7090e_tuner_attach, + + DIB0700_DEFAULT_STREAMING_CONFIG(0x02), + } }, + + .size_of_priv = + sizeof(struct dib0700_adapter_state), + }, + }, + + .num_device_descs = 1, + .devices = { + { "DiBcom TFE7090E reference design", + { &dib0700_usb_id_table[78], NULL }, + { NULL }, + }, + }, + + .rc.core = { + .rc_interval = DEFAULT_RC_INTERVAL, + .rc_codes = RC_MAP_DIB0700_RC5_TABLE, + .module_name = "dib0700", + .rc_query = dib0700_rc_query_old_firmware, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, + .change_protocol = dib0700_change_protocol, + }, }, }; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 0040aa2..908a616 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -113,6 +113,7 @@ #define USB_PID_DIBCOM_STK7770P 0x1e80 #define USB_PID_DIBCOM_NIM7090 0x1bb2 #define USB_PID_DIBCOM_TFE7090PVR 0x1bb4 +#define USB_PID_DIBCOM_TFE7090E 0x1bb7 #define USB_PID_DIBCOM_NIM9090M 0x2383 #define USB_PID_DIBCOM_NIM9090MD 0x2384 #define USB_PID_DPOSH_M9206_COLD 0x9206 diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c index 9030f3d..26c6c61 100644 --- a/drivers/media/dvb/frontends/dib0090.c +++ b/drivers/media/dvb/frontends/dib0090.c @@ -717,6 +717,34 @@ static const u16 rf_ramp_pwm_cband_7090[] = { (0 << 10) | 109, /* RF_RAMP4, LNA 4 */ }; +static const uint16_t rf_ramp_pwm_cband_7090e_sensitivity[] = { + 186, + 40, + 746, + (10 << 10) | 345, + (0 << 10) | 746, + (0 << 10) | 0, + (0 << 10) | 0, + (28 << 10) | 200, + (0 << 10) | 345, + (20 << 10) | 0, + (0 << 10) | 200, +}; + +static const uint16_t rf_ramp_pwm_cband_7090e_aci[] = { + 86, + 40, + 345, + (0 << 10) | 0, + (0 << 10) | 0, + (0 << 10) | 0, + (0 << 10) | 0, + (28 << 10) | 200, + (0 << 10) | 345, + (20 << 10) | 0, + (0 << 10) | 200, +}; + static const u16 rf_ramp_pwm_cband_8090[] = { 345, /* max RF gain in 10th of dB */ 29, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ @@ -1076,8 +1104,16 @@ void dib0090_pwm_gain_reset(struct dvb_frontend *fe) dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs); if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1) dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_8090); - else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1) - dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090); + else if (state->identity.version == SOC_7090_P1G_11R1 + || state->identity.version == SOC_7090_P1G_21R1) { + if (state->config->is_dib7090e) { + if (state->rf_ramp == NULL) + dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090e_sensitivity); + else + dib0090_set_rframp_pwm(state, state->rf_ramp); + } else + dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090); + } } else { dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband); dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal); @@ -1313,7 +1349,7 @@ void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * EXPORT_SYMBOL(dib0090_get_current_gain); -u16 dib0090_get_wbd_offset(struct dvb_frontend *fe) +u16 dib0090_get_wbd_target(struct dvb_frontend *fe) { struct dib0090_state *state = fe->tuner_priv; u32 f_MHz = state->fe->dtv_property_cache.frequency / 1000000; @@ -1350,9 +1386,57 @@ u16 dib0090_get_wbd_offset(struct dvb_frontend *fe) return state->wbd_offset + wbd_tcold; } +EXPORT_SYMBOL(dib0090_get_wbd_target); +u16 dib0090_get_wbd_offset(struct dvb_frontend *fe) +{ + struct dib0090_state *state = fe->tuner_priv; + return state->wbd_offset; +} EXPORT_SYMBOL(dib0090_get_wbd_offset); +int dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3) +{ + struct dib0090_state *state = fe->tuner_priv; + + dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xfff8) + | ((sw3 & 1) << 2) | ((sw2 & 1) << 1) | (sw1 & 1)); + + return 0; +} +EXPORT_SYMBOL(dib0090_set_switch); + +int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff) +{ + struct dib0090_state *state = fe->tuner_priv; + + dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x7fff) + | ((onoff & 1) << 15)); + return 0; +} +EXPORT_SYMBOL(dib0090_set_vga); + +int dib0090_update_rframp_7090(struct dvb_frontend *fe, u8 cfg_sensitivity) +{ + struct dib0090_state *state = fe->tuner_priv; + + if ((!state->identity.p1g) || (!state->identity.in_soc) + || ((state->identity.version != SOC_7090_P1G_21R1) + && (state->identity.version != SOC_7090_P1G_11R1))) { + dprintk("%s() function can only be used for dib7090P", __func__); + return -ENODEV; + } + + if (cfg_sensitivity) + state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_sensitivity; + else + state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_aci; + dib0090_pwm_gain_reset(fe); + + return 0; +} +EXPORT_SYMBOL(dib0090_update_rframp_7090); + static const u16 dib0090_defaults[] = { 25, 0x01, @@ -1962,6 +2046,52 @@ static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = { #endif }; +static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_sensitivity[] = { +#ifdef CONFIG_BAND_CBAND + { 300000, 0 , 3, 0x8105, 0x2c0, 0x2d12, 0xb84e, EN_CAB }, + { 380000, 0 , 10, 0x810F, 0x2c0, 0x2d12, 0xb84e, EN_CAB }, + { 600000, 0 , 10, 0x815E, 0x280, 0x2d12, 0xb84e, EN_CAB }, + { 660000, 0 , 5, 0x85E3, 0x280, 0x2d12, 0xb84e, EN_CAB }, + { 720000, 0 , 5, 0x852E, 0x280, 0x2d12, 0xb84e, EN_CAB }, + { 860000, 0 , 4, 0x85E5, 0x280, 0x2d12, 0xb84e, EN_CAB }, +#endif +}; + +int dib0090_update_tuning_table_7090(struct dvb_frontend *fe, + u8 cfg_sensitivity) +{ + struct dib0090_state *state = fe->tuner_priv; + const struct dib0090_tuning *tune = + dib0090_tuning_table_cband_7090e_sensitivity; + const struct dib0090_tuning dib0090_tuning_table_cband_7090e_aci[] = { + { 300000, 0 , 3, 0x8165, 0x2c0, 0x2d12, 0xb84e, EN_CAB }, + { 650000, 0 , 4, 0x815B, 0x280, 0x2d12, 0xb84e, EN_CAB }, + { 860000, 0 , 5, 0x84EF, 0x280, 0x2d12, 0xb84e, EN_CAB }, + }; + + if ((!state->identity.p1g) || (!state->identity.in_soc) + || ((state->identity.version != SOC_7090_P1G_21R1) + && (state->identity.version != SOC_7090_P1G_11R1))) { + dprintk("%s() function can only be used for dib7090", __func__); + return -ENODEV; + } + + if (cfg_sensitivity) + tune = dib0090_tuning_table_cband_7090e_sensitivity; + else + tune = dib0090_tuning_table_cband_7090e_aci; + + while (state->rf_request > tune->max_freq) + tune++; + + dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x8000) + | (tune->lna_bias & 0x7fff)); + dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xf83f) + | ((tune->lna_tune << 6) & 0x07c0)); + return 0; +} +EXPORT_SYMBOL(dib0090_update_tuning_table_7090); + static int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state) { int ret = 0; @@ -2210,12 +2340,18 @@ static int dib0090_tune(struct dvb_frontend *fe) if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF || state->current_band & BAND_UHF) { state->current_band = BAND_CBAND; - tune = dib0090_tuning_table_cband_7090; + if (state->config->is_dib7090e) + tune = dib0090_tuning_table_cband_7090e_sensitivity; + else + tune = dib0090_tuning_table_cband_7090; } } else { /* Use the CBAND input for all band under UHF */ if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) { state->current_band = BAND_CBAND; - tune = dib0090_tuning_table_cband_7090; + if (state->config->is_dib7090e) + tune = dib0090_tuning_table_cband_7090e_sensitivity; + else + tune = dib0090_tuning_table_cband_7090; } } } else diff --git a/drivers/media/dvb/frontends/dib0090.h b/drivers/media/dvb/frontends/dib0090.h index 648318a..781dc49 100644 --- a/drivers/media/dvb/frontends/dib0090.h +++ b/drivers/media/dvb/frontends/dib0090.h @@ -80,14 +80,21 @@ extern struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c extern struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config); extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast); extern void dib0090_pwm_gain_reset(struct dvb_frontend *fe); -extern u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner); +extern u16 dib0090_get_wbd_target(struct dvb_frontend *tuner); +extern u16 dib0090_get_wbd_offset(struct dvb_frontend *fe); extern int dib0090_gain_control(struct dvb_frontend *fe); extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe); extern int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state); extern void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt); extern void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff); +extern int dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3); +extern int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff); +extern int dib0090_update_rframp_7090(struct dvb_frontend *fe, + u8 cfg_sensitivity); +extern int dib0090_update_tuning_table_7090(struct dvb_frontend *fe, + u8 cfg_sensitivity); #else -static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0090_config *config) +static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; @@ -109,7 +116,13 @@ static inline void dib0090_pwm_gain_reset(struct dvb_frontend *fe) printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); } -static inline u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner) +static inline u16 dib0090_get_wbd_target(struct dvb_frontend *tuner) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return 0; +} + +static inline u16 dib0090_get_wbd_offset(struct dvb_frontend *fe) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return 0; @@ -142,6 +155,33 @@ static inline void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cut { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); } + +static inline int dib0090_set_switch(struct dvb_frontend *fe, + u8 sw1, u8 sw2, u8 sw3) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} + +static inline int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} + +static inline int dib0090_update_rframp_7090(struct dvb_frontend *fe, + u8 cfg_sensitivity) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} + +static inline int dib0090_update_tuning_table_7090(struct dvb_frontend *fe, + u8 cfg_sensitivity) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} #endif #endif diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index 08e62a4..2b52542 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -418,6 +418,24 @@ int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value) } EXPORT_SYMBOL(dib7000p_set_wbd_ref); +int dib7000p_get_agc_values(struct dvb_frontend *fe, + u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd) +{ + struct dib7000p_state *state = fe->demodulator_priv; + + if (agc_global != NULL) + *agc_global = dib7000p_read_word(state, 394); + if (agc1 != NULL) + *agc1 = dib7000p_read_word(state, 392); + if (agc2 != NULL) + *agc2 = dib7000p_read_word(state, 393); + if (wbd != NULL) + *wbd = dib7000p_read_word(state, 397); + + return 0; +} +EXPORT_SYMBOL(dib7000p_get_agc_values); + static void dib7000p_reset_pll(struct dib7000p_state *state) { struct dibx000_bandwidth_config *bw = &state->cfg.bw[0]; diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h index 58f907c..b61b03a 100644 --- a/drivers/media/dvb/frontends/dib7000p.h +++ b/drivers/media/dvb/frontends/dib7000p.h @@ -60,6 +60,8 @@ extern int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff); extern int dib7090_get_adc_power(struct dvb_frontend *fe); extern struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe); extern int dib7090_slave_reset(struct dvb_frontend *fe); +extern int dib7000p_get_agc_values(struct dvb_frontend *fe, + u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd); #else static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg) { @@ -144,6 +146,13 @@ static inline int dib7090_slave_reset(struct dvb_frontend *fe) printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; } + +static inline int dib7000p_get_agc_values(struct dvb_frontend *fe, + u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} #endif #endif -- cgit v0.10.2 From a685dbbc65e1e0f266e69a538dfd65a2f10fcc91 Mon Sep 17 00:00:00 2001 From: Olivier Grenie Date: Fri, 5 Aug 2011 14:10:40 -0300 Subject: [media] DiBcom: correct warnings The intend of this patch is to correct some warnings given. Signed-off-by: Olivier Grenie Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index aeab321..d82740a 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1328,7 +1328,7 @@ static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap) } /* STK8096GP */ -struct dibx000_agc_config dib8090_agc_config[2] = { +static struct dibx000_agc_config dib8090_agc_config[2] = { { BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, @@ -2152,7 +2152,7 @@ static struct dib0090_wbd_slope dib7090e_wbd_table[] = { { 0xFFFF, 0, 0, 0, 0, 0}, }; -struct dibx000_agc_config dib7090_agc_config[2] = { +static struct dibx000_agc_config dib7090_agc_config[2] = { { .band_caps = BAND_UHF, /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c index 26c6c61..2b30ab2 100644 --- a/drivers/media/dvb/frontends/dib0090.c +++ b/drivers/media/dvb/frontends/dib0090.c @@ -1522,7 +1522,7 @@ static void dib0090_set_default_config(struct dib0090_state *state, const u16 * #define POLY_MIN (u8) 0 #define POLY_MAX (u8) 8 -void dib0090_set_EFUSE(struct dib0090_state *state) +static void dib0090_set_EFUSE(struct dib0090_state *state) { u8 c, h, n; u16 e2, e4; diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index 2b52542..3ab695b 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -1876,7 +1876,8 @@ static int w7090p_tuner_rw_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg m return num; } -int dib7090p_rw_on_apb(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num, u16 apb_address) +static int dib7090p_rw_on_apb(struct i2c_adapter *i2c_adap, + struct i2c_msg msg[], int num, u16 apb_address) { struct dib7000p_state *state = i2c_get_adapdata(i2c_adap); u16 word; -- cgit v0.10.2 From 1f6bfcc752445ea03cb63c0c6bf5ee54d0fa73d5 Mon Sep 17 00:00:00 2001 From: Olivier Grenie Date: Mon, 4 Jul 2011 12:33:54 -0300 Subject: [media] DiB8000: improve the tuning and the SNR monitoring This patches improves the tuning of the dib8000 and correct the monitoringr of the SNR.The patch allows to faster detect that there is no ISDB-T channel on the wanted frequency. Signed-off-by: Olivier Grenie Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c index fe284d5..96c6a61 100644 --- a/drivers/media/dvb/frontends/dib8000.c +++ b/drivers/media/dvb/frontends/dib8000.c @@ -2215,7 +2215,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par ((state->fe[0]->dtv_property_cache.layer[1].segment_count == 0) || ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (2 << 0)) == 0)) && ((state->fe[0]->dtv_property_cache.layer[2].segment_count == 0) || ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (3 << 0)) == 0)))) { - int i = 80000; + int i = 100; u8 found = 0; u8 tune_failed = 0; @@ -2243,6 +2243,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par default: dprintk("unhandled autosearch result"); case 1: + tune_failed |= (1 << index_frontend); dprintk("autosearch failed for the frontend%i", index_frontend); break; } @@ -2401,7 +2402,7 @@ static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr) for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) snr_master += dib8000_get_snr(state->fe[index_frontend]); - if (snr_master != 0) { + if ((snr_master >> 16) != 0) { snr_master = 10*intlog10(snr_master>>16); *snr = snr_master / ((1 << 24) / 10); } -- cgit v0.10.2 From b293f304c52c4e7a3473dad4d4d0f3bc3c3cd32f Mon Sep 17 00:00:00 2001 From: Olivier Grenie Date: Tue, 9 Aug 2011 04:48:25 -0300 Subject: [media] dib7090: add the reference board TFE7790E The intend of this patch is to add the support for the DiBcom reference board TFE7790E. Signed-off-by: Olivier Grenie Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index d82740a..845b11a 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -2428,6 +2428,71 @@ static const struct dib0090_config tfe7090e_dib0090_config = { .is_dib7090e = 1, }; +static struct dib7000p_config tfe7790e_dib7000p_config = { + .output_mpeg2_in_188_bytes = 1, + .hostbus_diversity = 1, + .tuner_is_baseband = 1, + .update_lna = dib7090e_update_lna, + + .agc_config_count = 2, + .agc = dib7090_agc_config, + + .bw = &dib7090_clock_config_12_mhz, + + .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, + .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, + .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, + + .pwm_freq_div = 0, + + .agc_control = dib7090_agc_restart, + + .spur_protect = 0, + .disable_sample_and_hold = 0, + .enable_current_mirror = 0, + .diversity_delay = 0, + + .output_mode = OUTMODE_MPEG2_PAR_GATED_CLK, + .enMpegOutput = 1, +}; + +static const struct dib0090_config tfe7790e_dib0090_config = { + .io.clock_khz = 12000, + .io.pll_bypass = 0, + .io.pll_range = 0, + .io.pll_prediv = 3, + .io.pll_loopdiv = 6, + .io.adc_clock_ratio = 0, + .io.pll_int_loop_filt = 0, + .reset = dib7090_tuner_sleep, + .sleep = dib7090_tuner_sleep, + + .freq_offset_khz_uhf = 0, + .freq_offset_khz_vhf = 0, + + .get_adc_power = dib7090_get_adc_power, + + .clkouttobamse = 1, + .analog_output = 0, + + .wbd_vhf_offset = 0, + .wbd_cband_offset = 0, + .use_pwm_agc = 1, + .clkoutdrive = 0, + + .fref_clock_ratio = 0, + + .wbd = dib7090e_wbd_table, + + .ls_cfg_pad_drv = 0, + .data_tx_drv = 0, + .low_if = NULL, + .in_soc = 1, + .force_cband_input = 1, + .is_dib7090e = 1, + .force_crystal_mode = 1, +}; + static const struct dib0090_config tfe7090pvr_dib0090_config[2] = { { .io.clock_khz = 12000, @@ -2646,6 +2711,54 @@ static int tfe7090e_frontend_attach(struct dvb_usb_adapter *adap) return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; } +static int tfe7790e_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct dib0700_state *st = adap->dev->priv; + + /* The TFE7790E requires the dib0700 to not be in master mode */ + st->disable_streaming_master_mode = 1; + + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); + msleep(20); + dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); + msleep(20); + dib0700_ctrl_clock(adap->dev, 72, 1); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); + msleep(20); + dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); + + if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, + 1, 0x10, &tfe7790e_dib7000p_config) != 0) { + err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", + __func__); + return -ENODEV; + } + adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, + 0x80, &tfe7790e_dib7000p_config); + + return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; +} + +static int tfe7790e_tuner_attach(struct dvb_usb_adapter *adap) +{ + struct dib0700_adapter_state *st = adap->priv; + struct i2c_adapter *tun_i2c = + dib7090_get_i2c_tuner(adap->fe_adap[0].fe); + + if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, + &tfe7790e_dib0090_config) == NULL) + return -ENODEV; + + dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1); + + st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; + adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup; + return 0; +} + static int tfe7090e_tuner_attach(struct dvb_usb_adapter *adap) { struct dib0700_adapter_state *st = adap->priv; @@ -3120,6 +3233,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV340E) }, { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV340E_SE) }, { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7090E) }, + { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7790E) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -4225,6 +4339,46 @@ struct dvb_usb_device_properties dib0700_devices[] = { RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, + }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, + .num_adapters = 1, + .adapter = { + { + .num_frontends = 1, + .fe = {{ + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk70x0p_pid_filter, + .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, + .frontend_attach = tfe7790e_frontend_attach, + .tuner_attach = tfe7790e_tuner_attach, + + DIB0700_DEFAULT_STREAMING_CONFIG(0x03), + } }, + + .size_of_priv = + sizeof(struct dib0700_adapter_state), + }, + }, + + .num_device_descs = 1, + .devices = { + { "DiBcom TFE7790E reference design", + { &dib0700_usb_id_table[79], NULL }, + { NULL }, + }, + }, + + .rc.core = { + .rc_interval = DEFAULT_RC_INTERVAL, + .rc_codes = RC_MAP_DIB0700_RC5_TABLE, + .module_name = "dib0700", + .rc_query = dib0700_rc_query_old_firmware, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, + .change_protocol = dib0700_change_protocol, + }, }, }; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 908a616..3f437eb 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -114,6 +114,7 @@ #define USB_PID_DIBCOM_NIM7090 0x1bb2 #define USB_PID_DIBCOM_TFE7090PVR 0x1bb4 #define USB_PID_DIBCOM_TFE7090E 0x1bb7 +#define USB_PID_DIBCOM_TFE7790E 0x1e6e #define USB_PID_DIBCOM_NIM9090M 0x2383 #define USB_PID_DIBCOM_NIM9090MD 0x2384 #define USB_PID_DPOSH_M9206_COLD 0x9206 -- cgit v0.10.2 From 0c32dbd74fa947a922b9df125ac8795ce761fa8a Mon Sep 17 00:00:00 2001 From: Olivier Grenie Date: Wed, 10 Aug 2011 05:17:18 -0300 Subject: [media] add the support for DiBcom dib8096P The purpose of this patch is to support the DiBcom chip dib8096P. Signed-off-by: Olivier Grenie Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 845b11a..b7b4b65 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1279,7 +1279,7 @@ static int stk807x_frontend_attach(struct dvb_usb_adapter *adap) dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, - 0x80); + 0x80, 0); adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib807x_dib8000_config[0]); @@ -1308,7 +1308,7 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap) dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); /* initialize IC 0 */ - dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80); + dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80, 0); adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib807x_dib8000_config[0]); @@ -1319,7 +1319,7 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap) static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap) { /* initialize IC 1 */ - dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82); + dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82, 0); adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, &dib807x_dib8000_config[1]); @@ -1578,7 +1578,7 @@ static int stk809x_frontend_attach(struct dvb_usb_adapter *adap) msleep(10); dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); - dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80); + dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80, 0); adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]); @@ -1629,7 +1629,7 @@ static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap) msleep(20); dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); - dib8000_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80); + dib8000_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80, 0); adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]); if (adap->fe_adap[0].fe == NULL) diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index 3ab695b..b5f3fb4 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -81,13 +81,6 @@ enum dib7000p_power_mode { }; /* dib7090 specific fonctions */ -#define MPEG_ON_DIBTX 1 -#define DIV_ON_DIBTX 2 -#define ADC_ON_DIBTX 3 -#define DEMOUT_ON_HOSTBUS 4 -#define DIBTX_ON_HOSTBUS 5 -#define MPEG_ON_HOSTBUS 6 - static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode); static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff); static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode); diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c index 96c6a61..b8da0c9 100644 --- a/drivers/media/dvb/frontends/dib8000.c +++ b/drivers/media/dvb/frontends/dib8000.c @@ -81,11 +81,15 @@ struct dib8000_state { u8 i2c_write_buffer[4]; u8 i2c_read_buffer[2]; struct mutex i2c_buffer_lock; + u8 input_mode_mpeg; + + u16 tuner_enable; + struct i2c_adapter dib8096p_tuner_adap; }; enum dib8000_power_mode { - DIB8000M_POWER_ALL = 0, - DIB8000M_POWER_INTERFACE_ONLY, + DIB8000_POWER_ALL = 0, + DIB8000_POWER_INTERFACE_ONLY, }; static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg) @@ -428,20 +432,31 @@ static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_pow /* by default everything is going to be powered off */ u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0xffff, reg_900 = (dib8000_read_word(state, 900) & 0xfffc) | 0x3, + reg_1280; + + if (state->revision != 0x8090) reg_1280 = (dib8000_read_word(state, 1280) & 0x00ff) | 0xff00; + else + reg_1280 = (dib8000_read_word(state, 1280) & 0x707f) | 0x8f80; /* now, depending on the requested mode, we power on */ switch (mode) { /* power up everything in the demod */ - case DIB8000M_POWER_ALL: + case DIB8000_POWER_ALL: reg_774 = 0x0000; reg_775 = 0x0000; reg_776 = 0x0000; reg_900 &= 0xfffc; - reg_1280 &= 0x00ff; + if (state->revision != 0x8090) + reg_1280 &= 0x00ff; + else + reg_1280 &= 0x707f; break; - case DIB8000M_POWER_INTERFACE_ONLY: - reg_1280 &= 0x00ff; + case DIB8000_POWER_INTERFACE_ONLY: + if (state->revision != 0x8090) + reg_1280 &= 0x00ff; + else + reg_1280 &= 0xfa7b; break; } @@ -453,19 +468,67 @@ static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_pow dib8000_write_word(state, 1280, reg_1280); } +static int dib8000_init_sdram(struct dib8000_state *state) +{ + u16 reg = 0; + dprintk("Init sdram"); + + reg = dib8000_read_word(state, 274)&0xfff0; + /* P_dintlv_delay_ram = 7 because of MobileSdram */ + dib8000_write_word(state, 274, reg | 0x7); + + dib8000_write_word(state, 1803, (7<<2)); + + reg = dib8000_read_word(state, 1280); + /* force restart P_restart_sdram */ + dib8000_write_word(state, 1280, reg | (1<<2)); + + /* release restart P_restart_sdram */ + dib8000_write_word(state, 1280, reg); + + return 0; +} + static int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_states no) { int ret = 0; - u16 reg_907 = dib8000_read_word(state, 907), reg_908 = dib8000_read_word(state, 908); + u16 reg, reg_907 = dib8000_read_word(state, 907); + u16 reg_908 = dib8000_read_word(state, 908); switch (no) { case DIBX000_SLOW_ADC_ON: - reg_908 |= (1 << 1) | (1 << 0); - ret |= dib8000_write_word(state, 908, reg_908); - reg_908 &= ~(1 << 1); + if (state->revision != 0x8090) { + reg_908 |= (1 << 1) | (1 << 0); + ret |= dib8000_write_word(state, 908, reg_908); + reg_908 &= ~(1 << 1); + } else { + reg = dib8000_read_word(state, 1925); + /* en_slowAdc = 1 & reset_sladc = 1 */ + dib8000_write_word(state, 1925, reg | + (1<<4) | (1<<2)); + + /* read acces to make it works... strange ... */ + reg = dib8000_read_word(state, 1925); + msleep(20); + /* en_slowAdc = 1 & reset_sladc = 0 */ + dib8000_write_word(state, 1925, reg & ~(1<<4)); + + reg = dib8000_read_word(state, 921) & ~((0x3 << 14) + | (0x3 << 12)); + /* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ; + (Vin2 = Vcm) */ + dib8000_write_word(state, 921, reg | (1 << 14) + | (3 << 12)); + } break; case DIBX000_SLOW_ADC_OFF: + if (state->revision == 0x8090) { + reg = dib8000_read_word(state, 1925); + /* reset_sladc = 1 en_slowAdc = 0 */ + dib8000_write_word(state, 1925, + (reg & ~(1<<2)) | (1<<4)); + } reg_908 |= (1 << 1) | (1 << 0); break; @@ -521,7 +584,12 @@ static int dib8000_set_bandwidth(struct dvb_frontend *fe, u32 bw) static int dib8000_sad_calib(struct dib8000_state *state) { -/* internal */ + if (state->revision == 0x8090) { + dprintk("%s: the sad calibration is not needed for the dib8096P", + __func__); + return 0; + } + /* internal */ dib8000_write_word(state, 923, (0 << 1) | (0 << 0)); dib8000_write_word(state, 924, 776); // 0.625*3.3 / 4096 @@ -546,48 +614,129 @@ EXPORT_SYMBOL(dib8000_set_wbd_ref); static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw) { dprintk("ifreq: %d %x, inversion: %d", bw->ifreq, bw->ifreq, bw->ifreq >> 25); - dib8000_write_word(state, 23, (u16) (((bw->internal * 1000) >> 16) & 0xffff)); /* P_sec_len */ - dib8000_write_word(state, 24, (u16) ((bw->internal * 1000) & 0xffff)); + if (state->revision != 0x8090) { + dib8000_write_word(state, 23, + (u16) (((bw->internal * 1000) >> 16) & 0xffff)); + dib8000_write_word(state, 24, + (u16) ((bw->internal * 1000) & 0xffff)); + } else { + dib8000_write_word(state, 23, (u16) (((bw->internal / 2 * 1000) >> 16) & 0xffff)); + dib8000_write_word(state, 24, + (u16) ((bw->internal / 2 * 1000) & 0xffff)); + } dib8000_write_word(state, 27, (u16) ((bw->ifreq >> 16) & 0x01ff)); dib8000_write_word(state, 28, (u16) (bw->ifreq & 0xffff)); dib8000_write_word(state, 26, (u16) ((bw->ifreq >> 25) & 0x0003)); - dib8000_write_word(state, 922, bw->sad_cfg); + if (state->revision != 0x8090) + dib8000_write_word(state, 922, bw->sad_cfg); } static void dib8000_reset_pll(struct dib8000_state *state) { const struct dibx000_bandwidth_config *pll = state->cfg.pll; - u16 clk_cfg1; - - // clk_cfg0 - dib8000_write_word(state, 901, (pll->pll_prediv << 8) | (pll->pll_ratio << 0)); - - // clk_cfg1 - clk_cfg1 = (1 << 10) | (0 << 9) | (pll->IO_CLK_en_core << 8) | - (pll->bypclk_div << 5) | (pll->enable_refdiv << 4) | (1 << 3) | - (pll->pll_range << 1) | (pll->pll_reset << 0); - - dib8000_write_word(state, 902, clk_cfg1); - clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3); - dib8000_write_word(state, 902, clk_cfg1); - - dprintk("clk_cfg1: 0x%04x", clk_cfg1); /* 0x507 1 0 1 000 0 0 11 1 */ - - /* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */ - if (state->cfg.pll->ADClkSrc == 0) - dib8000_write_word(state, 904, (0 << 15) | (0 << 12) | (0 << 10) | - (pll->modulo << 8) | (pll->ADClkSrc << 7) | (0 << 1)); - else if (state->cfg.refclksel != 0) - dib8000_write_word(state, 904, (0 << 15) | (1 << 12) | - ((state->cfg.refclksel & 0x3) << 10) | (pll->modulo << 8) | - (pll->ADClkSrc << 7) | (0 << 1)); - else - dib8000_write_word(state, 904, (0 << 15) | (1 << 12) | (3 << 10) | (pll->modulo << 8) | (pll->ADClkSrc << 7) | (0 << 1)); + u16 clk_cfg1, reg; + + if (state->revision != 0x8090) { + dib8000_write_word(state, 901, + (pll->pll_prediv << 8) | (pll->pll_ratio << 0)); + + clk_cfg1 = (1 << 10) | (0 << 9) | (pll->IO_CLK_en_core << 8) | + (pll->bypclk_div << 5) | (pll->enable_refdiv << 4) | + (1 << 3) | (pll->pll_range << 1) | + (pll->pll_reset << 0); + + dib8000_write_word(state, 902, clk_cfg1); + clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3); + dib8000_write_word(state, 902, clk_cfg1); + + dprintk("clk_cfg1: 0x%04x", clk_cfg1); + + /* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */ + if (state->cfg.pll->ADClkSrc == 0) + dib8000_write_word(state, 904, + (0 << 15) | (0 << 12) | (0 << 10) | + (pll->modulo << 8) | + (pll->ADClkSrc << 7) | (0 << 1)); + else if (state->cfg.refclksel != 0) + dib8000_write_word(state, 904, (0 << 15) | (1 << 12) | + ((state->cfg.refclksel & 0x3) << 10) | + (pll->modulo << 8) | + (pll->ADClkSrc << 7) | (0 << 1)); + else + dib8000_write_word(state, 904, (0 << 15) | (1 << 12) | + (3 << 10) | (pll->modulo << 8) | + (pll->ADClkSrc << 7) | (0 << 1)); + } else { + dib8000_write_word(state, 1856, (!pll->pll_reset<<13) | + (pll->pll_range<<12) | (pll->pll_ratio<<6) | + (pll->pll_prediv)); + + reg = dib8000_read_word(state, 1857); + dib8000_write_word(state, 1857, reg|(!pll->pll_bypass<<15)); + + reg = dib8000_read_word(state, 1858); /* Force clk out pll /2 */ + dib8000_write_word(state, 1858, reg | 1); + + dib8000_write_word(state, 904, (pll->modulo << 8)); + } dib8000_reset_pll_common(state, pll); } +int dib8000_update_pll(struct dvb_frontend *fe, + struct dibx000_bandwidth_config *pll) +{ + struct dib8000_state *state = fe->demodulator_priv; + u16 reg_1857, reg_1856 = dib8000_read_word(state, 1856); + u8 loopdiv, prediv; + u32 internal, xtal; + + /* get back old values */ + prediv = reg_1856 & 0x3f; + loopdiv = (reg_1856 >> 6) & 0x3f; + + if ((pll != NULL) && (pll->pll_prediv != prediv || + pll->pll_ratio != loopdiv)) { + dprintk("Updating pll (prediv: old = %d new = %d ; loopdiv : old = %d new = %d)", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio); + reg_1856 &= 0xf000; + reg_1857 = dib8000_read_word(state, 1857); + /* disable PLL */ + dib8000_write_word(state, 1857, reg_1857 & ~(1 << 15)); + + dib8000_write_word(state, 1856, reg_1856 | + ((pll->pll_ratio & 0x3f) << 6) | + (pll->pll_prediv & 0x3f)); + + /* write new system clk into P_sec_len */ + internal = dib8000_read32(state, 23) / 1000; + dprintk("Old Internal = %d", internal); + xtal = 2 * (internal / loopdiv) * prediv; + internal = 1000 * (xtal/pll->pll_prediv) * pll->pll_ratio; + dprintk("Xtal = %d , New Fmem = %d New Fdemod = %d, New Fsampling = %d", xtal, internal/1000, internal/2000, internal/8000); + dprintk("New Internal = %d", internal); + + dib8000_write_word(state, 23, + (u16) (((internal / 2) >> 16) & 0xffff)); + dib8000_write_word(state, 24, (u16) ((internal / 2) & 0xffff)); + /* enable PLL */ + dib8000_write_word(state, 1857, reg_1857 | (1 << 15)); + + while (((dib8000_read_word(state, 1856)>>15)&0x1) != 1) + dprintk("Waiting for PLL to lock"); + + /* verify */ + reg_1856 = dib8000_read_word(state, 1856); + dprintk("PLL Updated with prediv = %d and loopdiv = %d", + reg_1856&0x3f, (reg_1856>>6)&0x3f); + + return 0; + } + return -EINVAL; +} +EXPORT_SYMBOL(dib8000_update_pll); + + static int dib8000_reset_gpio(struct dib8000_state *st) { /* reset the GPIOs */ @@ -721,9 +870,6 @@ static const u16 dib8000_defaults[] = { (3 << 5) | /* P_ctrl_pre_freq_step=3 */ (1 << 0), /* P_pre_freq_win_len=1 */ - 1, 903, - (0 << 4) | 2, // P_divclksel=0 P_divbitsel=2 (was clk=3,bit=1 for MPW) - 0, }; @@ -740,7 +886,8 @@ static u16 dib8000_identify(struct i2c_device *client) } value = dib8000_i2c_read16(client, 897); - if (value != 0x8000 && value != 0x8001 && value != 0x8002) { + if (value != 0x8000 && value != 0x8001 && + value != 0x8002 && value != 0x8090) { dprintk("wrong Device ID (%x)", value); return 0; } @@ -755,6 +902,9 @@ static u16 dib8000_identify(struct i2c_device *client) case 0x8002: dprintk("found DiB8000C"); break; + case 0x8090: + dprintk("found DiB8096P"); + break; } return value; } @@ -763,17 +913,19 @@ static int dib8000_reset(struct dvb_frontend *fe) { struct dib8000_state *state = fe->demodulator_priv; - dib8000_write_word(state, 1287, 0x0003); /* sram lead in, rdy */ - if ((state->revision = dib8000_identify(&state->i2c)) == 0) return -EINVAL; + /* sram lead in, rdy */ + if (state->revision != 0x8090) + dib8000_write_word(state, 1287, 0x0003); + if (state->revision == 0x8000) dprintk("error : dib8000 MA not supported"); dibx000_reset_i2c_master(&state->i2c_master); - dib8000_set_power_mode(state, DIB8000M_POWER_ALL); + dib8000_set_power_mode(state, DIB8000_POWER_ALL); /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */ dib8000_set_adc_state(state, DIBX000_VBG_ENABLE); @@ -782,8 +934,10 @@ static int dib8000_reset(struct dvb_frontend *fe) dib8000_write_word(state, 770, 0xffff); dib8000_write_word(state, 771, 0xffff); dib8000_write_word(state, 772, 0xfffc); - dib8000_write_word(state, 898, 0x000c); // sad - dib8000_write_word(state, 1280, 0x004d); + if (state->revision == 0x8090) + dib8000_write_word(state, 1280, 0x0045); + else + dib8000_write_word(state, 1280, 0x004d); dib8000_write_word(state, 1281, 0x000c); dib8000_write_word(state, 770, 0x0000); @@ -794,19 +948,25 @@ static int dib8000_reset(struct dvb_frontend *fe) dib8000_write_word(state, 1281, 0x0000); /* drives */ - if (state->cfg.drives) - dib8000_write_word(state, 906, state->cfg.drives); - else { - dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal."); - dib8000_write_word(state, 906, 0x2d98); // min drive SDRAM - not optimal - adjust + if (state->revision != 0x8090) { + if (state->cfg.drives) + dib8000_write_word(state, 906, state->cfg.drives); + else { + dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal."); + /* min drive SDRAM - not optimal - adjust */ + dib8000_write_word(state, 906, 0x2d98); + } } dib8000_reset_pll(state); + if (state->revision != 0x8090) + dib8000_write_word(state, 898, 0x0004); if (dib8000_reset_gpio(state) != 0) dprintk("GPIO reset was not successful."); - if (dib8000_set_output_mode(fe, OUTMODE_HIGH_Z) != 0) + if ((state->revision != 0x8090) && + (dib8000_set_output_mode(fe, OUTMODE_HIGH_Z) != 0)) dprintk("OUTPUT_MODE could not be resetted."); state->current_agc = NULL; @@ -832,6 +992,8 @@ static int dib8000_reset(struct dvb_frontend *fe) l = *n++; } } + if (state->revision != 0x8090) + dib8000_write_word(state, 903, (0 << 4) | 2); state->isdbt_cfg_loaded = 0; //div_cfg override for special configs @@ -844,10 +1006,12 @@ static int dib8000_reset(struct dvb_frontend *fe) dib8000_set_bandwidth(fe, 6000); dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON); - dib8000_sad_calib(state); - dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF); + if (state->revision != 0x8090) { + dib8000_sad_calib(state); + dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF); + } - dib8000_set_power_mode(state, DIB8000M_POWER_INTERFACE_ONLY); + dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY); return 0; } @@ -879,6 +1043,8 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band) { struct dibx000_agc_config *agc = NULL; int i; + u16 reg; + if (state->current_band == band && state->current_agc != NULL) return 0; state->current_band = band; @@ -914,6 +1080,12 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band) dib8000_write_word(state, 106, state->wbd_ref); else // use default dib8000_write_word(state, 106, agc->wbd_ref); + + if (state->revision == 0x8090) { + reg = dib8000_read_word(state, 922) & (0x3 << 2); + dib8000_write_word(state, 922, reg | (agc->wbd_sel << 2)); + } + dib8000_write_word(state, 107, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8)); dib8000_write_word(state, 108, agc->agc1_max); dib8000_write_word(state, 109, agc->agc1_min); @@ -925,7 +1097,10 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band) dib8000_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2); dib8000_write_word(state, 75, agc->agc1_pt3); - dib8000_write_word(state, 923, (dib8000_read_word(state, 923) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); /*LB : 929 -> 923 */ + if (state->revision != 0x8090) + dib8000_write_word(state, 923, + (dib8000_read_word(state, 923) & 0xffe3) | + (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); return 0; } @@ -968,14 +1143,30 @@ static int dib8000_agc_startup(struct dvb_frontend *fe) { struct dib8000_state *state = fe->demodulator_priv; enum frontend_tune_state *tune_state = &state->tune_state; - int ret = 0; + u16 reg, upd_demod_gain_period = 0x8000; switch (*tune_state) { case CT_AGC_START: // set power-up level: interf+analog+AGC - dib8000_set_adc_state(state, DIBX000_ADC_ON); + if (state->revision != 0x8090) + dib8000_set_adc_state(state, DIBX000_ADC_ON); + else { + dib8000_set_power_mode(state, DIB8000_POWER_ALL); + + reg = dib8000_read_word(state, 1947)&0xff00; + dib8000_write_word(state, 1946, + upd_demod_gain_period & 0xFFFF); + /* bit 14 = enDemodGain */ + dib8000_write_word(state, 1947, reg | (1<<14) | + ((upd_demod_gain_period >> 16) & 0xFF)); + + /* enable adc i & q */ + reg = dib8000_read_word(state, 1920); + dib8000_write_word(state, 1920, (reg | 0x3) & + (~(1 << 7))); + } if (dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))) != 0) { *tune_state = CT_AGC_STOP; @@ -1026,6 +1217,579 @@ static int dib8000_agc_startup(struct dvb_frontend *fe) } +static void dib8096p_host_bus_drive(struct dib8000_state *state, u8 drive) +{ + u16 reg; + + drive &= 0x7; + + /* drive host bus 2, 3, 4 */ + reg = dib8000_read_word(state, 1798) & + ~(0x7 | (0x7 << 6) | (0x7 << 12)); + reg |= (drive<<12) | (drive<<6) | drive; + dib8000_write_word(state, 1798, reg); + + /* drive host bus 5,6 */ + reg = dib8000_read_word(state, 1799) & ~((0x7 << 2) | (0x7 << 8)); + reg |= (drive<<8) | (drive<<2); + dib8000_write_word(state, 1799, reg); + + /* drive host bus 7, 8, 9 */ + reg = dib8000_read_word(state, 1800) & + ~(0x7 | (0x7 << 6) | (0x7 << 12)); + reg |= (drive<<12) | (drive<<6) | drive; + dib8000_write_word(state, 1800, reg); + + /* drive host bus 10, 11 */ + reg = dib8000_read_word(state, 1801) & ~((0x7 << 2) | (0x7 << 8)); + reg |= (drive<<8) | (drive<<2); + dib8000_write_word(state, 1801, reg); + + /* drive host bus 12, 13, 14 */ + reg = dib8000_read_word(state, 1802) & + ~(0x7 | (0x7 << 6) | (0x7 << 12)); + reg |= (drive<<12) | (drive<<6) | drive; + dib8000_write_word(state, 1802, reg); +} + +static u32 dib8096p_calcSyncFreq(u32 P_Kin, u32 P_Kout, + u32 insertExtSynchro, u32 syncSize) +{ + u32 quantif = 3; + u32 nom = (insertExtSynchro * P_Kin+syncSize); + u32 denom = P_Kout; + u32 syncFreq = ((nom << quantif) / denom); + + if ((syncFreq & ((1 << quantif) - 1)) != 0) + syncFreq = (syncFreq >> quantif) + 1; + else + syncFreq = (syncFreq >> quantif); + + if (syncFreq != 0) + syncFreq = syncFreq - 1; + + return syncFreq; +} + +static void dib8096p_cfg_DibTx(struct dib8000_state *state, u32 P_Kin, + u32 P_Kout, u32 insertExtSynchro, u32 synchroMode, + u32 syncWord, u32 syncSize) +{ + dprintk("Configure DibStream Tx"); + + dib8000_write_word(state, 1615, 1); + dib8000_write_word(state, 1603, P_Kin); + dib8000_write_word(state, 1605, P_Kout); + dib8000_write_word(state, 1606, insertExtSynchro); + dib8000_write_word(state, 1608, synchroMode); + dib8000_write_word(state, 1609, (syncWord >> 16) & 0xffff); + dib8000_write_word(state, 1610, syncWord & 0xffff); + dib8000_write_word(state, 1612, syncSize); + dib8000_write_word(state, 1615, 0); +} + +static void dib8096p_cfg_DibRx(struct dib8000_state *state, u32 P_Kin, + u32 P_Kout, u32 synchroMode, u32 insertExtSynchro, + u32 syncWord, u32 syncSize, u32 dataOutRate) +{ + u32 syncFreq; + + dprintk("Configure DibStream Rx synchroMode = %d", synchroMode); + + if ((P_Kin != 0) && (P_Kout != 0)) { + syncFreq = dib8096p_calcSyncFreq(P_Kin, P_Kout, + insertExtSynchro, syncSize); + dib8000_write_word(state, 1542, syncFreq); + } + + dib8000_write_word(state, 1554, 1); + dib8000_write_word(state, 1536, P_Kin); + dib8000_write_word(state, 1537, P_Kout); + dib8000_write_word(state, 1539, synchroMode); + dib8000_write_word(state, 1540, (syncWord >> 16) & 0xffff); + dib8000_write_word(state, 1541, syncWord & 0xffff); + dib8000_write_word(state, 1543, syncSize); + dib8000_write_word(state, 1544, dataOutRate); + dib8000_write_word(state, 1554, 0); +} + +static void dib8096p_enMpegMux(struct dib8000_state *state, int onoff) +{ + u16 reg_1287; + + reg_1287 = dib8000_read_word(state, 1287); + + switch (onoff) { + case 1: + reg_1287 &= ~(1 << 8); + break; + case 0: + reg_1287 |= (1 << 8); + break; + } + + dib8000_write_word(state, 1287, reg_1287); +} + +static void dib8096p_configMpegMux(struct dib8000_state *state, + u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2) +{ + u16 reg_1287; + + dprintk("Enable Mpeg mux"); + + dib8096p_enMpegMux(state, 0); + + /* If the input mode is MPEG do not divide the serial clock */ + if ((enSerialMode == 1) && (state->input_mode_mpeg == 1)) + enSerialClkDiv2 = 0; + + reg_1287 = ((pulseWidth & 0x1f) << 3) | + ((enSerialMode & 0x1) << 2) | (enSerialClkDiv2 & 0x1); + dib8000_write_word(state, 1287, reg_1287); + + dib8096p_enMpegMux(state, 1); +} + +static void dib8096p_setDibTxMux(struct dib8000_state *state, int mode) +{ + u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 7); + + switch (mode) { + case MPEG_ON_DIBTX: + dprintk("SET MPEG ON DIBSTREAM TX"); + dib8096p_cfg_DibTx(state, 8, 5, 0, 0, 0, 0); + reg_1288 |= (1 << 9); break; + case DIV_ON_DIBTX: + dprintk("SET DIV_OUT ON DIBSTREAM TX"); + dib8096p_cfg_DibTx(state, 5, 5, 0, 0, 0, 0); + reg_1288 |= (1 << 8); break; + case ADC_ON_DIBTX: + dprintk("SET ADC_OUT ON DIBSTREAM TX"); + dib8096p_cfg_DibTx(state, 20, 5, 10, 0, 0, 0); + reg_1288 |= (1 << 7); break; + default: + break; + } + dib8000_write_word(state, 1288, reg_1288); +} + +static void dib8096p_setHostBusMux(struct dib8000_state *state, int mode) +{ + u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 4); + + switch (mode) { + case DEMOUT_ON_HOSTBUS: + dprintk("SET DEM OUT OLD INTERF ON HOST BUS"); + dib8096p_enMpegMux(state, 0); + reg_1288 |= (1 << 6); + break; + case DIBTX_ON_HOSTBUS: + dprintk("SET DIBSTREAM TX ON HOST BUS"); + dib8096p_enMpegMux(state, 0); + reg_1288 |= (1 << 5); + break; + case MPEG_ON_HOSTBUS: + dprintk("SET MPEG MUX ON HOST BUS"); + reg_1288 |= (1 << 4); + break; + default: + break; + } + dib8000_write_word(state, 1288, reg_1288); +} + +static int dib8096p_set_diversity_in(struct dvb_frontend *fe, int onoff) +{ + struct dib8000_state *state = fe->demodulator_priv; + u16 reg_1287; + + switch (onoff) { + case 0: /* only use the internal way - not the diversity input */ + dprintk("%s mode OFF : by default Enable Mpeg INPUT", + __func__); + /* outputRate = 8 */ + dib8096p_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0); + + /* Do not divide the serial clock of MPEG MUX in + SERIAL MODE in case input mode MPEG is used */ + reg_1287 = dib8000_read_word(state, 1287); + /* enSerialClkDiv2 == 1 ? */ + if ((reg_1287 & 0x1) == 1) { + /* force enSerialClkDiv2 = 0 */ + reg_1287 &= ~0x1; + dib8000_write_word(state, 1287, reg_1287); + } + state->input_mode_mpeg = 1; + break; + case 1: /* both ways */ + case 2: /* only the diversity input */ + dprintk("%s ON : Enable diversity INPUT", __func__); + dib8096p_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0); + state->input_mode_mpeg = 0; + break; + } + + dib8000_set_diversity_in(state->fe[0], onoff); + return 0; +} + +static int dib8096p_set_output_mode(struct dvb_frontend *fe, int mode) +{ + struct dib8000_state *state = fe->demodulator_priv; + u16 outreg, smo_mode, fifo_threshold; + u8 prefer_mpeg_mux_use = 1; + int ret = 0; + + dib8096p_host_bus_drive(state, 1); + + fifo_threshold = 1792; + smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1); + outreg = dib8000_read_word(state, 1286) & + ~((1 << 10) | (0x7 << 6) | (1 << 1)); + + switch (mode) { + case OUTMODE_HIGH_Z: + outreg = 0; + break; + + case OUTMODE_MPEG2_SERIAL: + if (prefer_mpeg_mux_use) { + dprintk("dib8096P setting output mode TS_SERIAL using Mpeg Mux"); + dib8096p_configMpegMux(state, 3, 1, 1); + dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS); + } else {/* Use Smooth block */ + dprintk("dib8096P setting output mode TS_SERIAL using Smooth bloc"); + dib8096p_setHostBusMux(state, + DEMOUT_ON_HOSTBUS); + outreg |= (2 << 6) | (0 << 1); + } + break; + + case OUTMODE_MPEG2_PAR_GATED_CLK: + if (prefer_mpeg_mux_use) { + dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Mpeg Mux"); + dib8096p_configMpegMux(state, 2, 0, 0); + dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS); + } else { /* Use Smooth block */ + dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Smooth block"); + dib8096p_setHostBusMux(state, + DEMOUT_ON_HOSTBUS); + outreg |= (0 << 6); + } + break; + + case OUTMODE_MPEG2_PAR_CONT_CLK: /* Using Smooth block only */ + dprintk("dib8096P setting output mode TS_PARALLEL_CONT using Smooth block"); + dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS); + outreg |= (1 << 6); + break; + + case OUTMODE_MPEG2_FIFO: + /* Using Smooth block because not supported + by new Mpeg Mux bloc */ + dprintk("dib8096P setting output mode TS_FIFO using Smooth block"); + dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS); + outreg |= (5 << 6); + smo_mode |= (3 << 1); + fifo_threshold = 512; + break; + + case OUTMODE_DIVERSITY: + dprintk("dib8096P setting output mode MODE_DIVERSITY"); + dib8096p_setDibTxMux(state, DIV_ON_DIBTX); + dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS); + break; + + case OUTMODE_ANALOG_ADC: + dprintk("dib8096P setting output mode MODE_ANALOG_ADC"); + dib8096p_setDibTxMux(state, ADC_ON_DIBTX); + dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS); + break; + } + + if (mode != OUTMODE_HIGH_Z) + outreg |= (1<<10); + + dprintk("output_mpeg2_in_188_bytes = %d", + state->cfg.output_mpeg2_in_188_bytes); + if (state->cfg.output_mpeg2_in_188_bytes) + smo_mode |= (1 << 5); + + ret |= dib8000_write_word(state, 299, smo_mode); + /* synchronous fread */ + ret |= dib8000_write_word(state, 299 + 1, fifo_threshold); + ret |= dib8000_write_word(state, 1286, outreg); + + return ret; +} + +static int map_addr_to_serpar_number(struct i2c_msg *msg) +{ + if (msg->buf[0] <= 15) + msg->buf[0] -= 1; + else if (msg->buf[0] == 17) + msg->buf[0] = 15; + else if (msg->buf[0] == 16) + msg->buf[0] = 17; + else if (msg->buf[0] == 19) + msg->buf[0] = 16; + else if (msg->buf[0] >= 21 && msg->buf[0] <= 25) + msg->buf[0] -= 3; + else if (msg->buf[0] == 28) + msg->buf[0] = 23; + else if (msg->buf[0] == 99) + msg->buf[0] = 99; + else + return -EINVAL; + return 0; +} + +static int dib8096p_tuner_write_serpar(struct i2c_adapter *i2c_adap, + struct i2c_msg msg[], int num) +{ + struct dib8000_state *state = i2c_get_adapdata(i2c_adap); + u8 n_overflow = 1; + u16 i = 1000; + u16 serpar_num = msg[0].buf[0]; + + while (n_overflow == 1 && i) { + n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1; + i--; + if (i == 0) + dprintk("Tuner ITF: write busy (overflow)"); + } + dib8000_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f)); + dib8000_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]); + + return num; +} + +static int dib8096p_tuner_read_serpar(struct i2c_adapter *i2c_adap, + struct i2c_msg msg[], int num) +{ + struct dib8000_state *state = i2c_get_adapdata(i2c_adap); + u8 n_overflow = 1, n_empty = 1; + u16 i = 1000; + u16 serpar_num = msg[0].buf[0]; + u16 read_word; + + while (n_overflow == 1 && i) { + n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1; + i--; + if (i == 0) + dprintk("TunerITF: read busy (overflow)"); + } + dib8000_write_word(state, 1985, (0<<6) | (serpar_num&0x3f)); + + i = 1000; + while (n_empty == 1 && i) { + n_empty = dib8000_read_word(state, 1984)&0x1; + i--; + if (i == 0) + dprintk("TunerITF: read busy (empty)"); + } + + read_word = dib8000_read_word(state, 1987); + msg[1].buf[0] = (read_word >> 8) & 0xff; + msg[1].buf[1] = (read_word) & 0xff; + + return num; +} + +static int dib8096p_tuner_rw_serpar(struct i2c_adapter *i2c_adap, + struct i2c_msg msg[], int num) +{ + if (map_addr_to_serpar_number(&msg[0]) == 0) { + if (num == 1) /* write */ + return dib8096p_tuner_write_serpar(i2c_adap, msg, 1); + else /* read */ + return dib8096p_tuner_read_serpar(i2c_adap, msg, 2); + } + return num; +} + +static int dib8096p_rw_on_apb(struct i2c_adapter *i2c_adap, + struct i2c_msg msg[], int num, u16 apb_address) +{ + struct dib8000_state *state = i2c_get_adapdata(i2c_adap); + u16 word; + + if (num == 1) { /* write */ + dib8000_write_word(state, apb_address, + ((msg[0].buf[1] << 8) | (msg[0].buf[2]))); + } else { + word = dib8000_read_word(state, apb_address); + msg[1].buf[0] = (word >> 8) & 0xff; + msg[1].buf[1] = (word) & 0xff; + } + return num; +} + +static int dib8096p_tuner_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msg[], int num) +{ + struct dib8000_state *state = i2c_get_adapdata(i2c_adap); + u16 apb_address = 0, word; + int i = 0; + + switch (msg[0].buf[0]) { + case 0x12: + apb_address = 1920; + break; + case 0x14: + apb_address = 1921; + break; + case 0x24: + apb_address = 1922; + break; + case 0x1a: + apb_address = 1923; + break; + case 0x22: + apb_address = 1924; + break; + case 0x33: + apb_address = 1926; + break; + case 0x34: + apb_address = 1927; + break; + case 0x35: + apb_address = 1928; + break; + case 0x36: + apb_address = 1929; + break; + case 0x37: + apb_address = 1930; + break; + case 0x38: + apb_address = 1931; + break; + case 0x39: + apb_address = 1932; + break; + case 0x2a: + apb_address = 1935; + break; + case 0x2b: + apb_address = 1936; + break; + case 0x2c: + apb_address = 1937; + break; + case 0x2d: + apb_address = 1938; + break; + case 0x2e: + apb_address = 1939; + break; + case 0x2f: + apb_address = 1940; + break; + case 0x30: + apb_address = 1941; + break; + case 0x31: + apb_address = 1942; + break; + case 0x32: + apb_address = 1943; + break; + case 0x3e: + apb_address = 1944; + break; + case 0x3f: + apb_address = 1945; + break; + case 0x40: + apb_address = 1948; + break; + case 0x25: + apb_address = 936; + break; + case 0x26: + apb_address = 937; + break; + case 0x27: + apb_address = 938; + break; + case 0x28: + apb_address = 939; + break; + case 0x1d: + /* get sad sel request */ + i = ((dib8000_read_word(state, 921) >> 12)&0x3); + word = dib8000_read_word(state, 924+i); + msg[1].buf[0] = (word >> 8) & 0xff; + msg[1].buf[1] = (word) & 0xff; + return num; + case 0x1f: + if (num == 1) { /* write */ + word = (u16) ((msg[0].buf[1] << 8) | + msg[0].buf[2]); + /* in the VGAMODE Sel are located on bit 0/1 */ + word &= 0x3; + word = (dib8000_read_word(state, 921) & + ~(3<<12)) | (word<<12); + /* Set the proper input */ + dib8000_write_word(state, 921, word); + return num; + } + } + + if (apb_address != 0) /* R/W acces via APB */ + return dib8096p_rw_on_apb(i2c_adap, msg, num, apb_address); + else /* R/W access via SERPAR */ + return dib8096p_tuner_rw_serpar(i2c_adap, msg, num); + + return 0; +} + +static u32 dib8096p_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm dib8096p_tuner_xfer_algo = { + .master_xfer = dib8096p_tuner_xfer, + .functionality = dib8096p_i2c_func, +}; + +struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe) +{ + struct dib8000_state *st = fe->demodulator_priv; + return &st->dib8096p_tuner_adap; +} +EXPORT_SYMBOL(dib8096p_get_i2c_tuner); + +int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff) +{ + struct dib8000_state *state = fe->demodulator_priv; + u16 en_cur_state; + + dprintk("sleep dib8096p: %d", onoff); + + en_cur_state = dib8000_read_word(state, 1922); + + /* LNAs and MIX are ON and therefore it is a valid configuration */ + if (en_cur_state > 0xff) + state->tuner_enable = en_cur_state ; + + if (onoff) + en_cur_state &= 0x00ff; + else { + if (state->tuner_enable != 0) + en_cur_state = state->tuner_enable; + } + + dib8000_write_word(state, 1922, en_cur_state); + + return 0; +} +EXPORT_SYMBOL(dib8096p_tuner_sleep); + static const s32 lut_1000ln_mant[] = { 908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600 @@ -1051,6 +1815,26 @@ s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode) } EXPORT_SYMBOL(dib8000_get_adc_power); +int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ) +{ + struct dib8000_state *state = fe->demodulator_priv; + int val = 0; + + switch (IQ) { + case 1: + val = dib8000_read_word(state, 403); + break; + case 0: + val = dib8000_read_word(state, 404); + break; + } + if (val & 0x200) + val -= 1024; + + return val; +} +EXPORT_SYMBOL(dib8090p_get_dc_power); + static void dib8000_update_timf(struct dib8000_state *state) { u32 timf = state->timf = dib8000_read32(state, 435); @@ -1060,6 +1844,26 @@ static void dib8000_update_timf(struct dib8000_state *state) dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default); } +u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf) +{ + struct dib8000_state *state = fe->demodulator_priv; + + switch (op) { + case DEMOD_TIMF_SET: + state->timf = timf; + break; + case DEMOD_TIMF_UPDATE: + dib8000_update_timf(state); + break; + case DEMOD_TIMF_GET: + break; + } + dib8000_set_bandwidth(state->fe[0], 6000); + + return state->timf; +} +EXPORT_SYMBOL(dib8000_ctrl_timf); + static const u16 adc_target_16dB[11] = { (1 << 13) - 825 - 117, (1 << 13) - 837 - 117, @@ -1086,6 +1890,9 @@ static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosear u16 init_prbs = 0xfff; u16 ana_gain = 0; + if (state->revision == 0x8090) + dib8000_init_sdram(state); + if (state->ber_monitored_layer != LAYER_ALL) dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer); else @@ -1418,7 +2225,10 @@ static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosear dprintk("nbseg_diff = %X (%d)", seg_diff_mask, seg_diff_mask); state->differential_constellation = (seg_diff_mask != 0); - dib8000_set_diversity_in(state->fe[0], state->diversity_onoff); + if (state->revision != 0x8090) + dib8000_set_diversity_in(state->fe[0], state->diversity_onoff); + else + dib8096p_set_diversity_in(state->fe[0], state->diversity_onoff); if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) { if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1) @@ -1870,7 +2680,7 @@ static int dib8000_tune(struct dvb_frontend *fe) { struct dib8000_state *state = fe->demodulator_priv; int ret = 0; - u16 value, mode = fft_to_mode(state); + u16 lock, value, mode = fft_to_mode(state); // we are already tuned - just resuming from suspend if (state == NULL) @@ -1924,7 +2734,11 @@ static int dib8000_tune(struct dvb_frontend *fe) } // we achieved a coff_cpil_lock - it's time to update the timf - if ((dib8000_read_word(state, 568) >> 11) & 0x1) + if (state->revision != 0x8090) + lock = dib8000_read_word(state, 568); + else + lock = dib8000_read_word(state, 570); + if ((lock >> 11) & 0x1) dib8000_update_timf(state); //now that tune is finished, lock0 should lock on fec_mpeg to output this lock on MP_LOCK. It's changed in autosearch start @@ -1946,11 +2760,14 @@ static int dib8000_wakeup(struct dvb_frontend *fe) u8 index_frontend; int ret; - dib8000_set_power_mode(state, DIB8000M_POWER_ALL); + dib8000_set_power_mode(state, DIB8000_POWER_ALL); dib8000_set_adc_state(state, DIBX000_ADC_ON); if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) dprintk("could not start Slow ADC"); + if (state->revision != 0x8090) + dib8000_sad_calib(state); + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { ret = state->fe[index_frontend]->ops.init(state->fe[index_frontend]); if (ret < 0) @@ -1972,8 +2789,9 @@ static int dib8000_sleep(struct dvb_frontend *fe) return ret; } - dib8000_set_output_mode(fe, OUTMODE_HIGH_Z); - dib8000_set_power_mode(state, DIB8000M_POWER_INTERFACE_ONLY); + if (state->revision != 0x8090) + dib8000_set_output_mode(fe, OUTMODE_HIGH_Z); + dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY); return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF); } @@ -2028,7 +2846,10 @@ static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par fe->dtv_property_cache.isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1; - val = dib8000_read_word(state, 570); + if (state->revision == 0x8090) + val = dib8000_read_word(state, 572); + else + val = dib8000_read_word(state, 570); fe->dtv_property_cache.inversion = (val & 0x40) >> 6; switch ((val & 0x30) >> 4) { case 1: @@ -2158,7 +2979,12 @@ static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_ISDBT; memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties)); - dib8000_set_output_mode(state->fe[index_frontend], OUTMODE_HIGH_Z); + if (state->revision != 0x8090) + dib8000_set_output_mode(state->fe[index_frontend], + OUTMODE_HIGH_Z); + else + dib8096p_set_output_mode(state->fe[index_frontend], + OUTMODE_HIGH_Z); if (state->fe[index_frontend]->ops.tuner_ops.set_params) state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend], fep); @@ -2269,14 +3095,37 @@ static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par ret = dib8000_tune(state->fe[index_frontend]); /* set output mode and diversity input */ - dib8000_set_output_mode(state->fe[0], state->cfg.output_mode); - for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - dib8000_set_output_mode(state->fe[index_frontend], OUTMODE_DIVERSITY); - dib8000_set_diversity_in(state->fe[index_frontend-1], 1); - } + if (state->revision != 0x8090) { + dib8000_set_output_mode(state->fe[0], state->cfg.output_mode); + for (index_frontend = 1; + (index_frontend < MAX_NUMBER_OF_FRONTENDS) && + (state->fe[index_frontend] != NULL); + index_frontend++) { + dib8000_set_output_mode(state->fe[index_frontend], + OUTMODE_DIVERSITY); + dib8000_set_diversity_in(state->fe[index_frontend-1], 1); + } - /* turn off the diversity of the last chip */ - dib8000_set_diversity_in(state->fe[index_frontend-1], 0); + /* turn off the diversity of the last chip */ + dib8000_set_diversity_in(state->fe[index_frontend-1], 0); + } else { + dib8096p_set_output_mode(state->fe[0], state->cfg.output_mode); + if (state->cfg.enMpegOutput == 0) { + dib8096p_setDibTxMux(state, MPEG_ON_DIBTX); + dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS); + } + for (index_frontend = 1; + (index_frontend < MAX_NUMBER_OF_FRONTENDS) && + (state->fe[index_frontend] != NULL); + index_frontend++) { + dib8096p_set_output_mode(state->fe[index_frontend], + OUTMODE_DIVERSITY); + dib8096p_set_diversity_in(state->fe[index_frontend-1], 1); + } + + /* turn off the diversity of the last chip */ + dib8096p_set_diversity_in(state->fe[index_frontend-1], 0); + } return ret; } @@ -2285,15 +3134,22 @@ static u16 dib8000_read_lock(struct dvb_frontend *fe) { struct dib8000_state *state = fe->demodulator_priv; + if (state->revision == 0x8090) + return dib8000_read_word(state, 570); return dib8000_read_word(state, 568); } static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat) { struct dib8000_state *state = fe->demodulator_priv; - u16 lock_slave = 0, lock = dib8000_read_word(state, 568); + u16 lock_slave = 0, lock; u8 index_frontend; + if (state->revision == 0x8090) + lock = dib8000_read_word(state, 570); + else + lock = dib8000_read_word(state, 568); + for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) lock_slave |= dib8000_read_lock(state->fe[index_frontend]); @@ -2331,14 +3187,26 @@ static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat) static int dib8000_read_ber(struct dvb_frontend *fe, u32 * ber) { struct dib8000_state *state = fe->demodulator_priv; - *ber = (dib8000_read_word(state, 560) << 16) | dib8000_read_word(state, 561); // 13 segments + + /* 13 segments */ + if (state->revision == 0x8090) + *ber = (dib8000_read_word(state, 562) << 16) | + dib8000_read_word(state, 563); + else + *ber = (dib8000_read_word(state, 560) << 16) | + dib8000_read_word(state, 561); return 0; } static int dib8000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) { struct dib8000_state *state = fe->demodulator_priv; - *unc = dib8000_read_word(state, 565); // packet error on 13 seg + + /* packet error on 13 seg */ + if (state->revision == 0x8090) + *unc = dib8000_read_word(state, 567); + else + *unc = dib8000_read_word(state, 565); return 0; } @@ -2371,14 +3239,20 @@ static u32 dib8000_get_snr(struct dvb_frontend *fe) u32 n, s, exp; u16 val; - val = dib8000_read_word(state, 542); + if (state->revision != 0x8090) + val = dib8000_read_word(state, 542); + else + val = dib8000_read_word(state, 544); n = (val >> 6) & 0xff; exp = (val & 0x3f); if ((exp & 0x20) != 0) exp -= 0x40; n <<= exp+16; - val = dib8000_read_word(state, 543); + if (state->revision != 0x8090) + val = dib8000_read_word(state, 543); + else + val = dib8000_read_word(state, 545); s = (val >> 6) & 0xff; exp = (val & 0x3f); if ((exp & 0x20) != 0) @@ -2459,7 +3333,8 @@ struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int sla EXPORT_SYMBOL(dib8000_get_slave_frontend); -int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr) +int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, + u8 default_addr, u8 first_addr, u8 is_dib8096p) { int k = 0, ret = 0; u8 new_addr = 0; @@ -2489,9 +3364,12 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau new_addr = first_addr + (k << 1); client.addr = new_addr; - dib8000_i2c_write16(&client, 1287, 0x0003); /* sram lead in, rdy */ - if (dib8000_identify(&client) == 0) { + if (!is_dib8096p) dib8000_i2c_write16(&client, 1287, 0x0003); /* sram lead in, rdy */ + if (dib8000_identify(&client) == 0) { + /* sram lead in, rdy */ + if (!is_dib8096p) + dib8000_i2c_write16(&client, 1287, 0x0003); client.addr = default_addr; if (dib8000_identify(&client) == 0) { dprintk("#%d: not identified", k); @@ -2550,6 +3428,7 @@ static void dib8000_release(struct dvb_frontend *fe) dvb_frontend_detach(st->fe[index_frontend]); dibx000_exit_i2c_master(&st->i2c_master); + i2c_del_adapter(&st->dib8096p_tuner_adap); kfree(st->fe[0]); kfree(st); } @@ -2652,6 +3531,15 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr); + /* init 8096p tuner adapter */ + strncpy(state->dib8096p_tuner_adap.name, "DiB8096P tuner interface", + sizeof(state->dib8096p_tuner_adap.name)); + state->dib8096p_tuner_adap.algo = &dib8096p_tuner_xfer_algo; + state->dib8096p_tuner_adap.algo_data = NULL; + state->dib8096p_tuner_adap.dev.parent = state->i2c.adap->dev.parent; + i2c_set_adapdata(&state->dib8096p_tuner_adap, state); + i2c_add_adapter(&state->dib8096p_tuner_adap); + dib8000_reset(fe); dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5)); /* ber_rs_len = 3 */ diff --git a/drivers/media/dvb/frontends/dib8000.h b/drivers/media/dvb/frontends/dib8000.h index 617f9eb..39591bb 100644 --- a/drivers/media/dvb/frontends/dib8000.h +++ b/drivers/media/dvb/frontends/dib8000.h @@ -32,6 +32,7 @@ struct dib8000_config { u8 div_cfg; u8 output_mode; u8 refclksel; + u8 enMpegOutput:1; }; #define DEFAULT_DIB8000_I2C_ADDRESS 18 @@ -40,7 +41,8 @@ struct dib8000_config { extern struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg); extern struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); -extern int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr); +extern int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, + u8 default_addr, u8 first_addr, u8 is_dib8096p); extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val); extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value); @@ -50,6 +52,13 @@ extern int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_st extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe); extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe); extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode); +extern struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe); +extern int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff); +extern int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ); +extern u32 dib8000_ctrl_timf(struct dvb_frontend *fe, + uint8_t op, uint32_t timf); +extern int dib8000_update_pll(struct dvb_frontend *fe, + struct dibx000_bandwidth_config *pll); extern int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave); extern int dib8000_remove_slave_frontend(struct dvb_frontend *fe); extern struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index); @@ -66,7 +75,9 @@ static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe return NULL; } -static inline int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr) +static inline int dib8000_i2c_enumeration(struct i2c_adapter *host, + int no_of_demods, u8 default_addr, u8 first_addr, + u8 is_dib8096p) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; @@ -109,11 +120,38 @@ static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); } +static inline struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +static inline int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return 0; +} static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return 0; } +static inline int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return 0; +} +static inline u32 dib8000_ctrl_timf(struct dvb_frontend *fe, + uint8_t op, uint32_t timf) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return 0; +} +static inline int dib8000_update_pll(struct dvb_frontend *fe, + struct dibx000_bandwidth_config *pll) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} static inline int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h index 5e01147..02e6431 100644 --- a/drivers/media/dvb/frontends/dibx000_common.h +++ b/drivers/media/dvb/frontends/dibx000_common.h @@ -276,4 +276,11 @@ struct dibSubbandSelection { #define DEMOD_TIMF_GET 0x01 #define DEMOD_TIMF_UPDATE 0x02 +#define MPEG_ON_DIBTX 1 +#define DIV_ON_DIBTX 2 +#define ADC_ON_DIBTX 3 +#define DEMOUT_ON_HOSTBUS 4 +#define DIBTX_ON_HOSTBUS 5 +#define MPEG_ON_HOSTBUS 6 + #endif -- cgit v0.10.2 From 88f3a3584c74af84cd0476ee94af6234b50ce697 Mon Sep 17 00:00:00 2001 From: Olivier Grenie Date: Wed, 10 Aug 2011 05:28:38 -0300 Subject: [media] dib8096P: add the reference board TFE8096P The intend of this patch is to add the support for the DiBcom reference board TFE8096P. Signed-off-by: Olivier Grenie Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index b7b4b65..823c356 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1641,6 +1641,261 @@ static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap) return fe_slave == NULL ? -ENODEV : 0; } +/* TFE8096P */ +static struct dibx000_agc_config dib8096p_agc_config[2] = { + { + .band_caps = BAND_UHF, + /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, + P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, + P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, + P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, + P_agc_write=0 */ + .setup = (0 << 15) | (0 << 14) | (5 << 11) + | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) + | (0 << 4) | (5 << 1) | (0 << 0), + + .inv_gain = 684, + .time_stabiliz = 10, + + .alpha_level = 0, + .thlock = 118, + + .wbd_inv = 0, + .wbd_ref = 1200, + .wbd_sel = 3, + .wbd_alpha = 5, + + .agc1_max = 65535, + .agc1_min = 0, + + .agc2_max = 32767, + .agc2_min = 0, + + .agc1_pt1 = 0, + .agc1_pt2 = 0, + .agc1_pt3 = 105, + .agc1_slope1 = 0, + .agc1_slope2 = 156, + .agc2_pt1 = 105, + .agc2_pt2 = 255, + .agc2_slope1 = 54, + .agc2_slope2 = 0, + + .alpha_mant = 28, + .alpha_exp = 26, + .beta_mant = 31, + .beta_exp = 51, + + .perform_agc_softsplit = 0, + } , { + .band_caps = BAND_FM | BAND_VHF | BAND_CBAND, + /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, + P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, + P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, + P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, + P_agc_write=0 */ + .setup = (0 << 15) | (0 << 14) | (5 << 11) + | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) + | (0 << 4) | (5 << 1) | (0 << 0), + + .inv_gain = 732, + .time_stabiliz = 10, + + .alpha_level = 0, + .thlock = 118, + + .wbd_inv = 0, + .wbd_ref = 1200, + .wbd_sel = 3, + .wbd_alpha = 5, + + .agc1_max = 65535, + .agc1_min = 0, + + .agc2_max = 32767, + .agc2_min = 0, + + .agc1_pt1 = 0, + .agc1_pt2 = 0, + .agc1_pt3 = 98, + .agc1_slope1 = 0, + .agc1_slope2 = 167, + .agc2_pt1 = 98, + .agc2_pt2 = 255, + .agc2_slope1 = 52, + .agc2_slope2 = 0, + + .alpha_mant = 28, + .alpha_exp = 26, + .beta_mant = 31, + .beta_exp = 51, + + .perform_agc_softsplit = 0, + } +}; + +static struct dibx000_bandwidth_config dib8096p_clock_config_12_mhz = { + 108000, 13500, + 1, 9, 1, 0, 0, + 0, 0, 0, 0, 2, + (3 << 14) | (1 << 12) | (524 << 0), + (0 << 25) | 0, + 20199729, + 12000000, +}; + +static struct dib8000_config tfe8096p_dib8000_config = { + .output_mpeg2_in_188_bytes = 1, + .hostbus_diversity = 1, + .update_lna = NULL, + + .agc_config_count = 2, + .agc = dib8096p_agc_config, + .pll = &dib8096p_clock_config_12_mhz, + + .gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS, + .gpio_val = DIB8000_GPIO_DEFAULT_VALUES, + .gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS, + + .agc_control = NULL, + .diversity_delay = 48, + .output_mode = OUTMODE_MPEG2_FIFO, + .enMpegOutput = 1, +}; + +static struct dib0090_wbd_slope dib8096p_wbd_table[] = { + { 380, 81, 850, 64, 540, 4}, + { 860, 51, 866, 21, 375, 4}, + {1700, 0, 250, 0, 100, 6}, + {2600, 0, 250, 0, 100, 6}, + { 0xFFFF, 0, 0, 0, 0, 0}, +}; + +static const struct dib0090_config tfe8096p_dib0090_config = { + .io.clock_khz = 12000, + .io.pll_bypass = 0, + .io.pll_range = 0, + .io.pll_prediv = 3, + .io.pll_loopdiv = 6, + .io.adc_clock_ratio = 0, + .io.pll_int_loop_filt = 0, + .reset = dib8096p_tuner_sleep, + .sleep = dib8096p_tuner_sleep, + + .freq_offset_khz_uhf = -143, + .freq_offset_khz_vhf = -143, + + .get_adc_power = dib8090_get_adc_power, + + .clkouttobamse = 1, + .analog_output = 0, + + .wbd_vhf_offset = 0, + .wbd_cband_offset = 0, + .use_pwm_agc = 1, + .clkoutdrive = 0, + + .fref_clock_ratio = 1, + + .wbd = dib8096p_wbd_table, + + .ls_cfg_pad_drv = 0, + .data_tx_drv = 0, + .low_if = NULL, + .in_soc = 1, + .force_cband_input = 0, +}; + +struct dibx090p_adc { + u32 freq; /* RF freq MHz */ + u32 timf; /* New Timf */ + u32 pll_loopdiv; /* New prediv */ + u32 pll_prediv; /* New loopdiv */ +}; + +struct dibx090p_adc dib8090p_adc_tab[] = { + { 50000, 17043521, 16, 3}, /* 64 MHz */ + {878000, 20199729, 9, 1}, /* 60 MHz */ + {0xffffffff, 0, 0, 0}, /* 60 MHz */ +}; + +static int dib8096p_agc_startup(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fep) +{ + struct dvb_usb_adapter *adap = fe->dvb->priv; + struct dib0700_adapter_state *state = adap->priv; + struct dibx000_bandwidth_config pll; + u16 target; + int better_sampling_freq = 0, ret; + struct dibx090p_adc *adc_table = &dib8090p_adc_tab[0]; + + ret = state->set_param_save(fe, fep); + if (ret < 0) + return ret; + memset(&pll, 0, sizeof(struct dibx000_bandwidth_config)); + + dib0090_pwm_gain_reset(fe); + /* dib0090_get_wbd_target is returning any possible + temperature compensated wbd-target */ + target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2; + dib8000_set_wbd_ref(fe, target); + + + while (fep->frequency / 1000 > adc_table->freq) { + better_sampling_freq = 1; + adc_table++; + } + + if ((adc_table->freq != 0xffffffff) && better_sampling_freq) { + pll.pll_ratio = adc_table->pll_loopdiv; + pll.pll_prediv = adc_table->pll_prediv; + dib8000_update_pll(fe, &pll); + dib8000_ctrl_timf(fe, DEMOD_TIMF_SET, adc_table->timf); + } + return 0; +} + +static int tfe8096p_frontend_attach(struct dvb_usb_adapter *adap) +{ + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); + msleep(20); + dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); + + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); + + dib0700_ctrl_clock(adap->dev, 72, 1); + + msleep(20); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); + msleep(20); + dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); + + dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80, 1); + + adap->fe_adap[0].fe = dvb_attach(dib8000_attach, + &adap->dev->i2c_adap, 0x80, &tfe8096p_dib8000_config); + + return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; +} + +static int tfe8096p_tuner_attach(struct dvb_usb_adapter *adap) +{ + struct dib0700_adapter_state *st = adap->priv; + struct i2c_adapter *tun_i2c = dib8096p_get_i2c_tuner(adap->fe_adap[0].fe); + + if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, + &tfe8096p_dib0090_config) == NULL) + return -ENODEV; + + dib8000_set_gpio(adap->fe_adap[0].fe, 8, 0, 1); + + st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; + adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096p_agc_startup; + return 0; +} + /* STK9090M */ static int dib90x0_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff) { @@ -3234,6 +3489,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV340E_SE) }, { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7090E) }, { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7790E) }, +/* 80 */{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE8096P) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -4379,6 +4635,47 @@ struct dvb_usb_device_properties dib0700_devices[] = { RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, + }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, + .num_adapters = 1, + .adapter = { + { + .num_frontends = 1, + .fe = {{ + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk80xx_pid_filter, + .pid_filter_ctrl = stk80xx_pid_filter_ctrl, + .frontend_attach = tfe8096p_frontend_attach, + .tuner_attach = tfe8096p_tuner_attach, + + DIB0700_DEFAULT_STREAMING_CONFIG(0x02), + + } }, + + .size_of_priv = + sizeof(struct dib0700_adapter_state), + }, + }, + + .num_device_descs = 1, + .devices = { + { "DiBcom TFE8096P reference design", + { &dib0700_usb_id_table[80], NULL }, + { NULL }, + }, + }, + + .rc.core = { + .rc_interval = DEFAULT_RC_INTERVAL, + .rc_codes = RC_MAP_DIB0700_RC5_TABLE, + .module_name = "dib0700", + .rc_query = dib0700_rc_query_old_firmware, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, + .change_protocol = dib0700_change_protocol, + }, }, }; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 3f437eb..18be4b1 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -109,6 +109,7 @@ #define USB_PID_DIBCOM_STK807XPVR 0x1f98 #define USB_PID_DIBCOM_STK8096GP 0x1fa0 #define USB_PID_DIBCOM_NIM8096MD 0x1fa8 +#define USB_PID_DIBCOM_TFE8096P 0x1f9C #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 #define USB_PID_DIBCOM_STK7770P 0x1e80 #define USB_PID_DIBCOM_NIM7090 0x1bb2 -- cgit v0.10.2 From d1190024f0277a225c5926dbeb23306eb55035be Mon Sep 17 00:00:00 2001 From: Olivier Grenie Date: Mon, 29 Aug 2011 10:58:47 -0300 Subject: [media] dib9090: limit the I2C speed The intend of this patch is to limit the maximum I2C speed. Signed-off-by: Olivier Grenie Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 823c356..d0174fd 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -2138,7 +2138,7 @@ static int dib9090_tuner_attach(struct dvb_usb_adapter *adap) i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0); if (dib01x0_pmu_update(i2c, data_dib190, 10) != 0) return -ENODEV; - dib0700_set_i2c_speed(adap->dev, 2000); + dib0700_set_i2c_speed(adap->dev, 1500); if (dib9000_firmware_post_pll_init(adap->fe_adap[0].fe) < 0) return -ENODEV; release_firmware(state->frontend_firmware); @@ -2217,7 +2217,8 @@ static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap) i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0); if (dib01x0_pmu_update(i2c, data_dib190, 10) < 0) return -ENODEV; - dib0700_set_i2c_speed(adap->dev, 2000); + + dib0700_set_i2c_speed(adap->dev, 1500); if (dib9000_firmware_post_pll_init(adap->fe_adap[0].fe) < 0) return -ENODEV; @@ -2230,7 +2231,7 @@ static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap) if (dvb_attach(dib0090_fw_register, fe_slave, i2c, &nim9090md_dib0090_config[1]) == NULL) return -ENODEV; fe_slave->dvb = adap->fe_adap[0].fe->dvb; - dib9000_fw_set_component_bus_speed(adap->fe_adap[0].fe, 2000); + dib9000_fw_set_component_bus_speed(adap->fe_adap[0].fe, 1500); if (dib9000_firmware_post_pll_init(fe_slave) < 0) return -ENODEV; } -- cgit v0.10.2 From 53090aada474fe10052602ca3f46701591b666a5 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Thu, 17 Nov 2011 18:43:40 -0300 Subject: [media] drxd: Use kmemdup rather than duplicating its implementation The semantic patch that makes this change is available in scripts/coccinelle/api/memdup.cocci. Signed-off-by: Thomas Meyer Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/drxd_hard.c b/drivers/media/dvb/frontends/drxd_hard.c index 88e46f4..beb6775 100644 --- a/drivers/media/dvb/frontends/drxd_hard.c +++ b/drivers/media/dvb/frontends/drxd_hard.c @@ -914,14 +914,13 @@ static int load_firmware(struct drxd_state *state, const char *fw_name) return -EIO; } - state->microcode = kmalloc(fw->size, GFP_KERNEL); + state->microcode = kmemdup(fw->data, fw->size, GFP_KERNEL); if (state->microcode == NULL) { release_firmware(fw); printk(KERN_ERR "drxd: firmware load failure: no memory\n"); return -ENOMEM; } - memcpy(state->microcode, fw->data, fw->size); state->microcode_length = fw->size; release_firmware(fw); return 0; -- cgit v0.10.2 From 68dd9dd4113a7d2bd329590091a3f97fee3fd659 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Thu, 17 Nov 2011 18:43:40 -0300 Subject: [media] dw2102: Use kmemdup rather than duplicating its implementation The semantic patch that makes this change is available in scripts/coccinelle/api/memdup.cocci. Signed-off-by: Thomas Meyer Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index f103ec1..41cff37 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c @@ -1859,12 +1859,11 @@ static struct dvb_usb_device_properties su3000_properties = { static int dw2102_probe(struct usb_interface *intf, const struct usb_device_id *id) { - p1100 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL); + p1100 = kmemdup(&s6x0_properties, + sizeof(struct dvb_usb_device_properties), GFP_KERNEL); if (!p1100) return -ENOMEM; /* copy default structure */ - memcpy(p1100, &s6x0_properties, - sizeof(struct dvb_usb_device_properties)); /* fill only different fields */ p1100->firmware = "dvb-usb-p1100.fw"; p1100->devices[0] = d1100; @@ -1872,13 +1871,12 @@ static int dw2102_probe(struct usb_interface *intf, p1100->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table); p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach; - s660 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL); + s660 = kmemdup(&s6x0_properties, + sizeof(struct dvb_usb_device_properties), GFP_KERNEL); if (!s660) { kfree(p1100); return -ENOMEM; } - memcpy(s660, &s6x0_properties, - sizeof(struct dvb_usb_device_properties)); s660->firmware = "dvb-usb-s660.fw"; s660->num_device_descs = 3; s660->devices[0] = d660; @@ -1886,14 +1884,13 @@ static int dw2102_probe(struct usb_interface *intf, s660->devices[2] = d480_2; s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach; - p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL); + p7500 = kmemdup(&s6x0_properties, + sizeof(struct dvb_usb_device_properties), GFP_KERNEL); if (!p7500) { kfree(p1100); kfree(s660); return -ENOMEM; } - memcpy(p7500, &s6x0_properties, - sizeof(struct dvb_usb_device_properties)); p7500->firmware = "dvb-usb-p7500.fw"; p7500->devices[0] = d7500; p7500->rc.legacy.rc_map_table = rc_map_tbs_table; -- cgit v0.10.2 From 82c80f8371835f861bdbe50eefa5f49888d23210 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Thu, 17 Nov 2011 18:43:40 -0300 Subject: [media] v4l: Casting (void *) value returned by kmalloc is useless The semantic patch that makes this change is available in scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci. Signed-off-by: Thomas Meyer Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 52a0a37..4d7391e 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -708,7 +708,7 @@ static int vino_allocate_buffer(struct vino_framebuffer *fb, size, count); /* allocate memory for table with virtual (page) addresses */ - fb->desc_table.virtual = (unsigned long *) + fb->desc_table.virtual = kmalloc(count * sizeof(unsigned long), GFP_KERNEL); if (!fb->desc_table.virtual) return -ENOMEM; -- cgit v0.10.2 From 0ceaec188e7784c7f9ab5fca110fecb790837dbc Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Thu, 17 Nov 2011 19:12:18 -0300 Subject: [media] cx25821: Use kmemdup rather than duplicating its implementation The semantic patch that makes this change is available in scripts/coccinelle/api/memdup.cocci. Signed-off-by: Thomas Meyer Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx25821/cx25821-audio-upstream.c b/drivers/media/video/cx25821/cx25821-audio-upstream.c index 4dc2a24..20c7ca3 100644 --- a/drivers/media/video/cx25821/cx25821-audio-upstream.c +++ b/drivers/media/video/cx25821/cx25821-audio-upstream.c @@ -733,25 +733,22 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) if (dev->input_audiofilename) { str_length = strlen(dev->input_audiofilename); - dev->_audiofilename = kmalloc(str_length + 1, GFP_KERNEL); + dev->_audiofilename = kmemdup(dev->input_audiofilename, + str_length + 1, GFP_KERNEL); if (!dev->_audiofilename) goto error; - memcpy(dev->_audiofilename, dev->input_audiofilename, - str_length + 1); - /* Default if filename is empty string */ if (strcmp(dev->input_audiofilename, "") == 0) dev->_audiofilename = "/root/audioGOOD.wav"; } else { str_length = strlen(_defaultAudioName); - dev->_audiofilename = kmalloc(str_length + 1, GFP_KERNEL); + dev->_audiofilename = kmemdup(_defaultAudioName, + str_length + 1, GFP_KERNEL); if (!dev->_audiofilename) goto error; - - memcpy(dev->_audiofilename, _defaultAudioName, str_length + 1); } retval = cx25821_sram_channel_setup_upstream_audio(dev, sram_ch, diff --git a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c index 6401ce8..5a157cf 100644 --- a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c +++ b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c @@ -747,22 +747,18 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, if (dev->input_filename_ch2) { str_length = strlen(dev->input_filename_ch2); - dev->_filename_ch2 = kmalloc(str_length + 1, GFP_KERNEL); + dev->_filename_ch2 = kmemdup(dev->input_filename_ch2, + str_length + 1, GFP_KERNEL); if (!dev->_filename_ch2) goto error; - - memcpy(dev->_filename_ch2, dev->input_filename_ch2, - str_length + 1); } else { str_length = strlen(dev->_defaultname_ch2); - dev->_filename_ch2 = kmalloc(str_length + 1, GFP_KERNEL); + dev->_filename_ch2 = kmemdup(dev->_defaultname_ch2, + str_length + 1, GFP_KERNEL); if (!dev->_filename_ch2) goto error; - - memcpy(dev->_filename_ch2, dev->_defaultname_ch2, - str_length + 1); } /* Default if filename is empty string */ diff --git a/drivers/media/video/cx25821/cx25821-video-upstream.c b/drivers/media/video/cx25821/cx25821-video-upstream.c index 1032263..21e7d65 100644 --- a/drivers/media/video/cx25821/cx25821-video-upstream.c +++ b/drivers/media/video/cx25821/cx25821-video-upstream.c @@ -794,20 +794,18 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, if (dev->input_filename) { str_length = strlen(dev->input_filename); - dev->_filename = kmalloc(str_length + 1, GFP_KERNEL); + dev->_filename = kmemdup(dev->input_filename, str_length + 1, + GFP_KERNEL); if (!dev->_filename) goto error; - - memcpy(dev->_filename, dev->input_filename, str_length + 1); } else { str_length = strlen(dev->_defaultname); - dev->_filename = kmalloc(str_length + 1, GFP_KERNEL); + dev->_filename = kmemdup(dev->_defaultname, str_length + 1, + GFP_KERNEL); if (!dev->_filename) goto error; - - memcpy(dev->_filename, dev->_defaultname, str_length + 1); } /* Default if filename is empty string */ -- cgit v0.10.2 From 6d00c9aa2bb98909de21eaaf767b9ed76fe26f86 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Thu, 17 Nov 2011 18:43:40 -0300 Subject: [media] pwc: Use kmemdup rather than duplicating its implementation The semantic patch that makes this change is available in scripts/coccinelle/api/memdup.cocci. Signed-off-by: Thomas Meyer Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c index 3977add..b42c239 100644 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ b/drivers/media/video/pwc/pwc-ctrl.c @@ -113,10 +113,9 @@ static int _send_control_msg(struct pwc_device *pdev, void *kbuf = NULL; if (buflen) { - kbuf = kmalloc(buflen, GFP_KERNEL); /* not allowed on stack */ + kbuf = kmemdup(buf, buflen, GFP_KERNEL); /* not allowed on stack */ if (kbuf == NULL) return -ENOMEM; - memcpy(kbuf, buf, buflen); } rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), -- cgit v0.10.2 From 7e5219d18e93dd23e834a53b1ea73ead19cfeeb1 Mon Sep 17 00:00:00 2001 From: Pete Date: Fri, 18 Nov 2011 15:00:15 -0300 Subject: [media] go7007: Fix 2250 urb type commit a846d8fce9e8be30046be3c512982bd0345e7015 The 2250 board uses bulk endpoint for interrupt handling, and should use a bulk urb instead of an int urb. Signed-off-by: Pete Eberlein Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c index 3db3b0a..cffb0b3 100644 --- a/drivers/staging/media/go7007/go7007-usb.c +++ b/drivers/staging/media/go7007/go7007-usb.c @@ -1054,7 +1054,13 @@ static int go7007_usb_probe(struct usb_interface *intf, else go->hpi_ops = &go7007_usb_onboard_hpi_ops; go->hpi_context = usb; - usb_fill_int_urb(usb->intr_urb, usb->usbdev, + if (go->board_id == GO7007_BOARDID_SENSORAY_2250) + usb_fill_bulk_urb(usb->intr_urb, usb->usbdev, + usb_rcvbulkpipe(usb->usbdev, 4), + usb->intr_urb->transfer_buffer, 2*sizeof(u16), + go7007_usb_readinterrupt_complete, go); + else + usb_fill_int_urb(usb->intr_urb, usb->usbdev, usb_rcvintpipe(usb->usbdev, 4), usb->intr_urb->transfer_buffer, 2*sizeof(u16), go7007_usb_readinterrupt_complete, go, 8); -- cgit v0.10.2 From 146d35b00db270054378de17ca33eb54b0b78311 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 12 Oct 2011 06:58:44 -0300 Subject: [media] V4L spec: fix typo and missing CAP_RDS documentation For some reason the V4L2_TUNER_CAP_RDS_CONTROLS/BLOCK_IO capabilities were never documented in the proper table. In addition, then RDS interface section incorrectly referred to them as V4L2_TUNER_SUB_RDS_... instead of CAP_RDS_... This is now fixed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/DocBook/media/v4l/dev-rds.xml b/Documentation/DocBook/media/v4l/dev-rds.xml index 2427f54..7644b2e 100644 --- a/Documentation/DocBook/media/v4l/dev-rds.xml +++ b/Documentation/DocBook/media/v4l/dev-rds.xml @@ -29,10 +29,10 @@ returned by the &VIDIOC-QUERYCAP; ioctl. Any tuner that supports RDS will set the V4L2_TUNER_CAP_RDS flag in the capability field of &v4l2-tuner;. If the driver only passes RDS blocks without interpreting the data -the V4L2_TUNER_SUB_RDS_BLOCK_IO flag has to be +the V4L2_TUNER_CAP_RDS_BLOCK_IO flag has to be set, see Reading RDS data. For future use the -flag V4L2_TUNER_SUB_RDS_CONTROLS has also been +flag V4L2_TUNER_CAP_RDS_CONTROLS has also been defined. However, a driver for a radio tuner with this capability does not yet exist, so if you are planning to write such a driver you should discuss this on the linux-media mailing list: &v4l-ml;. @@ -52,9 +52,9 @@ field of &v4l2-modulator;. In order to enable the RDS transmission one must set the V4L2_TUNER_SUB_RDS bit in the txsubchans field of &v4l2-modulator;. If the driver only passes RDS blocks without interpreting the data -the V4L2_TUNER_SUB_RDS_BLOCK_IO flag has to be set. If the +the V4L2_TUNER_CAP_RDS_BLOCK_IO flag has to be set. If the tuner is capable of handling RDS entities like program identification codes and radio -text, the flag V4L2_TUNER_SUB_RDS_CONTROLS should be set, +text, the flag V4L2_TUNER_CAP_RDS_CONTROLS should be set, see Writing RDS data and FM Transmitter Control Reference.
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml index bd98c73..b23a4b0 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml @@ -318,6 +318,16 @@ standard. RDS capture is supported. This capability is only valid for radio tuners. + + V4L2_TUNER_CAP_RDS_BLOCK_IO + 0x0100 + The RDS data is passed as unparsed RDS blocks. + + + V4L2_TUNER_CAP_RDS_CONTROLS + 0x0200 + The RDS data is parsed by the hardware and set via controls. + -- cgit v0.10.2 From 0fb6ec6b1c185a1d99bf238880cc265d72ab111b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 7 Nov 2011 08:30:20 -0300 Subject: [media] V4L2 Spec: clarify usage of V4L2_FBUF_FLAG_PRIMARY As per discussion during the 2011 V4L-DVB workshop. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml b/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml index 0557182..109d729 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml @@ -295,7 +295,8 @@ set this field to zero. The device is capable of non-destructive overlays. When the driver clears this flag, only destructive overlays are supported. There are no drivers yet which support both destructive and -non-destructive overlays. +non-destructive overlays. Video Output Overlays are in practice always +non-destructive. V4L2_FBUF_CAP_CHROMAKEY @@ -356,7 +357,9 @@ with the chroma-key colors are replaced by video pixels, which is exactly opposi V4L2_FBUF_FLAG_PRIMARY 0x0001 The framebuffer is the primary graphics surface. -In other words, the overlay is destructive. [?] +In other words, the overlay is destructive. This flag is typically set by any +driver that doesn't have the V4L2_FBUF_CAP_EXTERNOVERLAY +capability and it is cleared otherwise. V4L2_FBUF_FLAG_OVERLAY @@ -366,9 +369,8 @@ size as the capture. [?] The purpose of -V4L2_FBUF_FLAG_PRIMARY and V4L2_FBUF_FLAG_OVERLAY was never quite clear. -Most drivers seem to ignore these flags. For compatibility with the +Most drivers seem to ignore this flag. For compatibility with the bttv driver applications should set the V4L2_FBUF_FLAG_OVERLAY flag. -- cgit v0.10.2 From 43599f31ab93bc2c17db615be20ce56261392292 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 7 Nov 2011 12:44:28 -0300 Subject: [media] v4l2 framework doc: clarify locking high-latency devices. Thanks to Hans de Goede for our discussions on this topic. Signed-off-by: Hans Verkuil Thanks-to: Hans de Goede Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index f8dcabf..659b2ba 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -612,6 +612,12 @@ You can set a pointer to a mutex_lock in struct video_device. Usually this will be either a top-level mutex or a mutex per device node. If you want finer-grained locking then you have to set it to NULL and do you own locking. +It is up to the driver developer to decide which method to use. However, if +your driver has high-latency operations (for example, changing the exposure +of a USB webcam might take a long time), then you might be better off with +doing your own locking if you want to allow the user to do other things with +the device while waiting for the high-latency command to finish. + If a lock is specified then all file operations will be serialized on that lock. If you use videobuf then you must pass the same lock to the videobuf queue initialize function: if videobuf has to wait for a frame to arrive, then @@ -619,6 +625,11 @@ it will temporarily unlock the lock and relock it afterwards. If your driver also waits in the code, then you should do the same to allow other processes to access the device node while the first process is waiting for something. +In the case of videobuf2 you will need to implement the wait_prepare and +wait_finish callbacks to unlock/lock if applicable. In particular, if you use +the lock in struct video_device then you must unlock/lock this mutex in +wait_prepare and wait_finish. + The implementation of a hotplug disconnect should also take the lock before calling v4l2_device_disconnect. -- cgit v0.10.2 From b698c784bfacc909b05e043d8fca08281fe154bb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 9 Nov 2011 10:53:01 -0300 Subject: [media] V4L2 spec: fix the description of V4L2_FBUF_CAP_SRC_CHROMAKEY V4L2_FBUF_CAP_SRC_CHROMAKEY is the opposite of V4L2_FBUF_CAP_CHROMAKEY, but according to the documentation it was the same. The terms 'video' and 'framebuffer' were accidentally swapped in the text. Signed-off-by: Hans Verkuil CC: Vaibhav Hiremath Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml b/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml index 109d729..93817f3 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml @@ -340,8 +340,8 @@ blending makes no sense for destructive overlays. V4L2_FBUF_CAP_SRC_CHROMAKEY 0x0080 - The device supports Source Chroma-keying. Framebuffer pixels -with the chroma-key colors are replaced by video pixels, which is exactly opposite of + The device supports Source Chroma-keying. Video pixels +with the chroma-key colors are replaced by framebuffer pixels, which is exactly opposite of V4L2_FBUF_CAP_CHROMAKEY -- cgit v0.10.2 From 75c1ca364d0d5d70ad12c5dac40bbe6598624cab Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 23 Nov 2011 02:45:40 -0300 Subject: [media] radio: NUL terminate a user string We pass this to fm_tx_set_radio_text() which expects a NUL terminated string. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c index 4f5c43d..077d369 100644 --- a/drivers/media/radio/wl128x/fmdrv_v4l2.c +++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c @@ -84,6 +84,7 @@ static ssize_t fm_v4l2_fops_write(struct file *file, const char __user * buf, struct fmdev *fmdev; ret = copy_from_user(&rds, buf, sizeof(rds)); + rds.text[sizeof(rds.text) - 1] = '\0'; fmdbg("(%d)type: %d, text %s, af %d\n", ret, rds.text_type, rds.text, rds.af_freq); if (ret) -- cgit v0.10.2 From 67114fe6103183190fb0a24f58e5695a80beb2ec Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Thu, 17 Nov 2011 23:43:40 +0100 Subject: nfsd4: Use kmemdup rather than duplicating its implementation The semantic patch that makes this change is available in scripts/coccinelle/api/memdup.cocci. Signed-off-by: Thomas Meyer Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index a84978c..6ab6779 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -986,12 +986,11 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name) clp = kzalloc(sizeof(struct nfs4_client), GFP_KERNEL); if (clp == NULL) return NULL; - clp->cl_name.data = kmalloc(name.len, GFP_KERNEL); + clp->cl_name.data = kmemdup(name.data, name.len, GFP_KERNEL); if (clp->cl_name.data == NULL) { kfree(clp); return NULL; } - memcpy(clp->cl_name.data, name.data, name.len); clp->cl_name.len = name.len; return clp; } diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index b6fa792..0ec5a1b 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -215,10 +215,9 @@ defer_free(struct nfsd4_compoundargs *argp, static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes) { if (p == argp->tmp) { - p = kmalloc(nbytes, GFP_KERNEL); + p = kmemdup(argp->tmp, nbytes, GFP_KERNEL); if (!p) return NULL; - memcpy(p, argp->tmp, nbytes); } else { BUG_ON(p != argp->tmpp); argp->tmpp = NULL; -- cgit v0.10.2 From 87d466e503ab1e071eac4bd89c46eb3cb53246a1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 24 Nov 2011 05:06:21 -0300 Subject: [media] staging/media: lirc_imon: add a __user annotation This silences the following Sparse warnings: lirc_imon.c:404:32: warning: incorrect type in argument 1 (different address spaces) lirc_imon.c:404:32: expected void const [noderef] * lirc_imon.c:404:32: got char const *buf lirc_imon.c:117:28: warning: incorrect type in initializer (incompatible argument 2 (different address spaces)) lirc_imon.c:117:28: expected long ( *write )( ... ) lirc_imon.c:117:28: got long ( static [toplevel] * )( ... ) Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c index f5308d5..c1654b1 100644 --- a/drivers/staging/media/lirc/lirc_imon.c +++ b/drivers/staging/media/lirc/lirc_imon.c @@ -63,7 +63,7 @@ static int display_open(struct inode *inode, struct file *file); static int display_close(struct inode *inode, struct file *file); /* VFD write operation */ -static ssize_t vfd_write(struct file *file, const char *buf, +static ssize_t vfd_write(struct file *file, const char __user *buf, size_t n_bytes, loff_t *pos); /* LIRC driver function prototypes */ @@ -369,7 +369,7 @@ static int send_packet(struct imon_context *context) * than 32 bytes are provided spaces will be appended to * generate a full screen. */ -static ssize_t vfd_write(struct file *file, const char *buf, +static ssize_t vfd_write(struct file *file, const char __user *buf, size_t n_bytes, loff_t *pos) { int i; -- cgit v0.10.2 From d95d7b91b4c6e3dfe94c07cd04993f60c887073d Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Thu, 24 Nov 2011 19:16:35 -0300 Subject: [media] V4L: omap1_camera: fix missing include Otherwise compilation breaks with: ... after apparently no longer included recursively from other header files. Signed-off-by: Janusz Krzysztofik Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/omap1_camera.c b/drivers/media/video/omap1_camera.c index e87ae2f..6a6cf38 100644 --- a/drivers/media/video/omap1_camera.c +++ b/drivers/media/video/omap1_camera.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include -- cgit v0.10.2 From 61e183f8306934a9f66557f69f1f0f56f18dca06 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 17 Nov 2011 16:01:29 +0530 Subject: dmaengine/dw_dmac: Reconfigure interrupt and chan_cfg register on resume In S2R all DMA registers are reset by hardware and thus they are required to be reprogrammed. The channels which aren't reprogrammed are channel configuration and interrupt enable registers, which are currently programmed at chan_alloc time. This patch creates another routine to initialize a channel. It will try to initialize channel on every dwc_dostart() call. If channel is already initialised then it simply returns, otherwise it configures registers. This routine will also initialize registers on wakeup from S2R, as we mark channels as uninitialized on suspend. Signed-off-by: Viresh Kumar Signed-off-by: Vinod Koul diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index decca1c..9b592b0 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -166,6 +166,38 @@ dwc_assign_cookie(struct dw_dma_chan *dwc, struct dw_desc *desc) return cookie; } +static void dwc_initialize(struct dw_dma_chan *dwc) +{ + struct dw_dma *dw = to_dw_dma(dwc->chan.device); + struct dw_dma_slave *dws = dwc->chan.private; + u32 cfghi = DWC_CFGH_FIFO_MODE; + u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority); + + if (dwc->initialized == true) + return; + + if (dws) { + /* + * We need controller-specific data to set up slave + * transfers. + */ + BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev); + + cfghi = dws->cfg_hi; + cfglo |= dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK; + } + + channel_writel(dwc, CFG_LO, cfglo); + channel_writel(dwc, CFG_HI, cfghi); + + /* Enable interrupts */ + channel_set_bit(dw, MASK.XFER, dwc->mask); + channel_set_bit(dw, MASK.BLOCK, dwc->mask); + channel_set_bit(dw, MASK.ERROR, dwc->mask); + + dwc->initialized = true; +} + /*----------------------------------------------------------------------*/ /* Called with dwc->lock held and bh disabled */ @@ -189,6 +221,8 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) return; } + dwc_initialize(dwc); + channel_writel(dwc, LLP, first->txd.phys); channel_writel(dwc, CTL_LO, DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN); @@ -959,10 +993,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) struct dw_dma_chan *dwc = to_dw_dma_chan(chan); struct dw_dma *dw = to_dw_dma(chan->device); struct dw_desc *desc; - struct dw_dma_slave *dws; int i; - u32 cfghi; - u32 cfglo; unsigned long flags; dev_vdbg(chan2dev(chan), "alloc_chan_resources\n"); @@ -975,26 +1006,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) dwc->completed = chan->cookie = 1; - cfghi = DWC_CFGH_FIFO_MODE; - cfglo = 0; - - dws = chan->private; - if (dws) { - /* - * We need controller-specific data to set up slave - * transfers. - */ - BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev); - - cfghi = dws->cfg_hi; - cfglo = dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK; - } - - cfglo |= DWC_CFGL_CH_PRIOR(dwc->priority); - - channel_writel(dwc, CFG_LO, cfglo); - channel_writel(dwc, CFG_HI, cfghi); - /* * NOTE: some controllers may have additional features that we * need to initialize here, like "scatter-gather" (which @@ -1026,11 +1037,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) i = ++dwc->descs_allocated; } - /* Enable interrupts */ - channel_set_bit(dw, MASK.XFER, dwc->mask); - channel_set_bit(dw, MASK.BLOCK, dwc->mask); - channel_set_bit(dw, MASK.ERROR, dwc->mask); - spin_unlock_irqrestore(&dwc->lock, flags); dev_dbg(chan2dev(chan), @@ -1058,6 +1064,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan) spin_lock_irqsave(&dwc->lock, flags); list_splice_init(&dwc->free_list, &list); dwc->descs_allocated = 0; + dwc->initialized = false; /* Disable interrupts */ channel_clear_bit(dw, MASK.XFER, dwc->mask); @@ -1335,6 +1342,8 @@ EXPORT_SYMBOL(dw_dma_cyclic_free); static void dw_dma_off(struct dw_dma *dw) { + int i; + dma_writel(dw, CFG, 0); channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask); @@ -1345,6 +1354,9 @@ static void dw_dma_off(struct dw_dma *dw) while (dma_readl(dw, CFG) & DW_CFG_DMA_EN) cpu_relax(); + + for (i = 0; i < dw->dma.chancnt; i++) + dw->chan[i].initialized = false; } static int __init dw_probe(struct platform_device *pdev) @@ -1533,6 +1545,7 @@ static int dw_suspend_noirq(struct device *dev) dw_dma_off(platform_get_drvdata(pdev)); clk_disable(dw->clk); + return 0; } diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h index c341951..5eef694 100644 --- a/drivers/dma/dw_dmac_regs.h +++ b/drivers/dma/dw_dmac_regs.h @@ -140,6 +140,7 @@ struct dw_dma_chan { u8 mask; u8 priority; bool paused; + bool initialized; spinlock_t lock; -- cgit v0.10.2 From d5613947addb1e1096a3be29dfe817905e385469 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Mon, 28 Nov 2011 08:51:16 +0530 Subject: dmaengine: timb_dma: fix the spare warinings Sparse warns: drivers/dma/timb_dma.c:168:17: warning: mixing different enum types drivers/dma/timb_dma.c:168:17: int enum dma_transfer_direction versus drivers/dma/timb_dma.c:168:17: int enum dma_data_direction drivers/dma/timb_dma.c:172:32: warning: mixing different enum types drivers/dma/timb_dma.c:172:32: int enum dma_transfer_direction versus drivers/dma/timb_dma.c:172:32: int enum dma_data_direction Reported-by: Dan Carpenter Signed-off-by: Vinod Koul diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c index 8c88072..d142ae1 100644 --- a/drivers/dma/timb_dma.c +++ b/drivers/dma/timb_dma.c @@ -166,10 +166,10 @@ static void __td_unmap_desc(struct timb_dma_chan *td_chan, const u8 *dma_desc, if (single) dma_unmap_single(chan2dev(&td_chan->chan), addr, len, - td_chan->direction); + DMA_TO_DEVICE); else dma_unmap_page(chan2dev(&td_chan->chan), addr, len, - td_chan->direction); + DMA_TO_DEVICE); } static void __td_unmap_descs(struct timb_dma_desc *td_desc, bool single) @@ -398,7 +398,7 @@ static struct timb_dma_desc *td_alloc_init_desc(struct timb_dma_chan *td_chan) td_desc->txd.flags = DMA_CTRL_ACK; td_desc->txd.phys = dma_map_single(chan2dmadev(chan), - td_desc->desc_list, td_desc->desc_list_len, DMA_MEM_TO_DEV); + td_desc->desc_list, td_desc->desc_list_len, DMA_TO_DEVICE); err = dma_mapping_error(chan2dmadev(chan), td_desc->txd.phys); if (err) { @@ -419,7 +419,7 @@ static void td_free_desc(struct timb_dma_desc *td_desc) { dev_dbg(chan2dev(td_desc->txd.chan), "Freeing desc: %p\n", td_desc); dma_unmap_single(chan2dmadev(td_desc->txd.chan), td_desc->txd.phys, - td_desc->desc_list_len, DMA_MEM_TO_DEV); + td_desc->desc_list_len, DMA_TO_DEVICE); kfree(td_desc->desc_list); kfree(td_desc); -- cgit v0.10.2 From 28c7a19d230228ab9ae61c300c5003a2400fadd3 Mon Sep 17 00:00:00 2001 From: Narayanan G Date: Tue, 22 Nov 2011 13:56:55 +0530 Subject: dmaengine/ste_dma40: Add support to use lcla area from esram This patch provides an option of having the lcla (link address) in ESRAM instead of allocating it. The bool value (use_esram_lcla) in the stedma40_platform_data if set to true, then the lcla address would be taken from platform resources. Also, the corresponding esram regulator is managed in the suspend/resume functions. Signed-off-by: Narayanan G Signed-off-by: Vinod Koul diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h index 38b041a..3177bed 100644 --- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h +++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h @@ -153,6 +153,7 @@ struct stedma40_platform_data { struct stedma40_chan_cfg *memcpy_conf_phy; struct stedma40_chan_cfg *memcpy_conf_log; int disabled_channels[STEDMA40_MAX_PHYS]; + bool use_esram_lcla; }; #ifdef CONFIG_STE_DMA40 diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index c2cf8cf..aff128a 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -304,6 +304,7 @@ struct d40_chan { * to phy_chans entries. * @plat_data: Pointer to provided platform_data which is the driver * configuration. + * @lcpa_regulator: Pointer to hold the regulator for the esram bank for lcla. * @phy_res: Vector containing all physical channels. * @lcla_pool: lcla pool settings and data. * @lcpa_base: The virtual mapped address of LCPA. @@ -338,6 +339,7 @@ struct d40_base { struct d40_chan **lookup_log_chans; struct d40_chan **lookup_phy_chans; struct stedma40_platform_data *plat_data; + struct regulator *lcpa_regulator; /* Physical half channels */ struct d40_phy_res *phy_res; struct d40_lcla_pool lcla_pool; @@ -605,6 +607,7 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc) bool cyclic = desc->cyclic; int curr_lcla = -EINVAL; int first_lcla = 0; + bool use_esram_lcla = chan->base->plat_data->use_esram_lcla; bool linkback; /* @@ -677,11 +680,16 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc) &lli->src[lli_current], next_lcla, flags); - dma_sync_single_range_for_device(chan->base->dev, - pool->dma_addr, lcla_offset, - 2 * sizeof(struct d40_log_lli), - DMA_TO_DEVICE); - + /* + * Cache maintenance is not needed if lcla is + * mapped in esram + */ + if (!use_esram_lcla) { + dma_sync_single_range_for_device(chan->base->dev, + pool->dma_addr, lcla_offset, + 2 * sizeof(struct d40_log_lli), + DMA_TO_DEVICE); + } curr_lcla = next_lcla; if (curr_lcla == -EINVAL || curr_lcla == first_lcla) { @@ -2668,10 +2676,15 @@ failure1: #ifdef CONFIG_PM static int dma40_pm_suspend(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); + struct d40_base *base = platform_get_drvdata(pdev); + int ret = 0; if (!pm_runtime_suspended(dev)) return -EBUSY; - return 0; + if (base->lcpa_regulator) + ret = regulator_disable(base->lcpa_regulator); + return ret; } static int dma40_runtime_suspend(struct device *dev) @@ -2702,11 +2715,23 @@ static int dma40_runtime_resume(struct device *dev) return 0; } +static int dma40_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct d40_base *base = platform_get_drvdata(pdev); + int ret = 0; + + if (base->lcpa_regulator) + ret = regulator_enable(base->lcpa_regulator); + + return ret; +} static const struct dev_pm_ops dma40_pm_ops = { .suspend = dma40_pm_suspend, .runtime_suspend = dma40_runtime_suspend, .runtime_resume = dma40_runtime_resume, + .resume = dma40_resume, }; #define DMA40_PM_OPS (&dma40_pm_ops) #else @@ -3165,11 +3190,31 @@ static int __init d40_probe(struct platform_device *pdev) d40_err(&pdev->dev, "Failed to ioremap LCPA region\n"); goto failure; } + /* If lcla has to be located in ESRAM we don't need to allocate */ + if (base->plat_data->use_esram_lcla) { + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "lcla_esram"); + if (!res) { + ret = -ENOENT; + d40_err(&pdev->dev, + "No \"lcla_esram\" memory resource\n"); + goto failure; + } + base->lcla_pool.base = ioremap(res->start, + resource_size(res)); + if (!base->lcla_pool.base) { + ret = -ENOMEM; + d40_err(&pdev->dev, "Failed to ioremap LCLA region\n"); + goto failure; + } + writel(res->start, base->virtbase + D40_DREG_LCLA); - ret = d40_lcla_allocate(base); - if (ret) { - d40_err(&pdev->dev, "Failed to allocate LCLA area\n"); - goto failure; + } else { + ret = d40_lcla_allocate(base); + if (ret) { + d40_err(&pdev->dev, "Failed to allocate LCLA area\n"); + goto failure; + } } spin_lock_init(&base->lcla_pool.lock); @@ -3187,6 +3232,26 @@ static int __init d40_probe(struct platform_device *pdev) pm_runtime_use_autosuspend(base->dev); pm_runtime_enable(base->dev); pm_runtime_resume(base->dev); + + if (base->plat_data->use_esram_lcla) { + + base->lcpa_regulator = regulator_get(base->dev, "lcla_esram"); + if (IS_ERR(base->lcpa_regulator)) { + d40_err(&pdev->dev, "Failed to get lcpa_regulator\n"); + base->lcpa_regulator = NULL; + goto failure; + } + + ret = regulator_enable(base->lcpa_regulator); + if (ret) { + d40_err(&pdev->dev, + "Failed to enable lcpa_regulator\n"); + regulator_put(base->lcpa_regulator); + base->lcpa_regulator = NULL; + goto failure; + } + } + base->initialized = true; err = d40_dmaengine_init(base, num_reserved_chans); if (err) @@ -3204,6 +3269,11 @@ failure: if (base->virtbase) iounmap(base->virtbase); + if (base->lcla_pool.base && base->plat_data->use_esram_lcla) { + iounmap(base->lcla_pool.base); + base->lcla_pool.base = NULL; + } + if (base->lcla_pool.dma_addr) dma_unmap_single(base->dev, base->lcla_pool.dma_addr, SZ_1K * base->num_phy_chans, @@ -3226,6 +3296,11 @@ failure: clk_put(base->clk); } + if (base->lcpa_regulator) { + regulator_disable(base->lcpa_regulator); + regulator_put(base->lcpa_regulator); + } + kfree(base->lcla_pool.alloc_map); kfree(base->lookup_log_chans); kfree(base->lookup_phy_chans); -- cgit v0.10.2 From 0ab88a01832d529c48e2a51f3d24662c143df39a Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 22 Nov 2011 11:55:52 +0100 Subject: dmaengine: at_hdmac: add const to struct platform_device_id definition Signed-off-by: Nicolas Ferre Signed-off-by: Vinod Koul diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 3b0c28f..3b44f24 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1191,7 +1191,7 @@ static const struct of_device_id atmel_dma_dt_ids[] = { MODULE_DEVICE_TABLE(of, atmel_dma_dt_ids); #endif -static struct platform_device_id atdma_devtypes[] = { +static const struct platform_device_id atdma_devtypes[] = { { .name = "at91sam9rl_dma", .driver_data = ATDMA_DEVTYPE_SAM9RL, -- cgit v0.10.2 From dcc817346d311bbd9dac6fc9d6bddb552134851c Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 22 Nov 2011 11:55:53 +0100 Subject: dmaengine: at_hdmac: empty entry shape modification Trivial form modification to unify structure look. Signed-off-by: Nicolas Ferre Signed-off-by: Vinod Koul diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 3b44f24..30ec030 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1185,7 +1185,9 @@ static const struct of_device_id atmel_dma_dt_ids[] = { }, { .compatible = "atmel,at91sam9g45-dma", .data = (void *)ATDMA_DEVTYPE_SAM9G45 - }, { /* sentinel */ } + }, { + /* sentinel */ + } }; MODULE_DEVICE_TABLE(of, atmel_dma_dt_ids); -- cgit v0.10.2 From 02f88be9488a3d831f073c1161b1e5feacb9d3ec Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 22 Nov 2011 11:55:54 +0100 Subject: dmaengine: at_hdmac: simplify device selection from platform data or DT Using a configuration structure simplify the finding of SoC dependent parameters. Both platform data and device tree ids are using these structures. This will separate data from code and remove the need for an enum. Idea from Grant Likely. Signed-off-by: Nicolas Ferre Signed-off-by: Vinod Koul diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 30ec030..97f87b2 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1177,14 +1177,22 @@ static void atc_free_chan_resources(struct dma_chan *chan) /*-- Module Management -----------------------------------------------*/ +/* cap_mask is a multi-u32 bitfield, fill it with proper C code. */ +static struct at_dma_platform_data at91sam9rl_config = { + .nr_channels = 2, +}; +static struct at_dma_platform_data at91sam9g45_config = { + .nr_channels = 8, +}; + #if defined(CONFIG_OF) static const struct of_device_id atmel_dma_dt_ids[] = { { .compatible = "atmel,at91sam9rl-dma", - .data = (void *)ATDMA_DEVTYPE_SAM9RL + .data = &at91sam9rl_config, }, { .compatible = "atmel,at91sam9g45-dma", - .data = (void *)ATDMA_DEVTYPE_SAM9G45 + .data = &at91sam9g45_config, }, { /* sentinel */ } @@ -1196,26 +1204,27 @@ MODULE_DEVICE_TABLE(of, atmel_dma_dt_ids); static const struct platform_device_id atdma_devtypes[] = { { .name = "at91sam9rl_dma", - .driver_data = ATDMA_DEVTYPE_SAM9RL, + .driver_data = (unsigned long) &at91sam9rl_config, }, { .name = "at91sam9g45_dma", - .driver_data = ATDMA_DEVTYPE_SAM9G45, + .driver_data = (unsigned long) &at91sam9g45_config, }, { /* sentinel */ } }; -static inline enum atdma_devtype __init at_dma_get_driver_data( - struct platform_device *pdev) +static inline struct at_dma_platform_data * __init at_dma_get_driver_data( + struct platform_device *pdev) { if (pdev->dev.of_node) { const struct of_device_id *match; match = of_match_node(atmel_dma_dt_ids, pdev->dev.of_node); if (match == NULL) - return ATDMA_DEVTYPE_UNDEFINED; - return (enum atdma_devtype)match->data; + return NULL; + return match->data; } - return platform_get_device_id(pdev)->driver_data; + return (struct at_dma_platform_data *) + platform_get_device_id(pdev)->driver_data; } /** @@ -1242,26 +1251,17 @@ static int __init at_dma_probe(struct platform_device *pdev) int irq; int err; int i; - u32 nr_channels; - dma_cap_mask_t cap_mask = {}; - enum atdma_devtype atdmatype; + struct at_dma_platform_data *plat_dat; - dma_cap_set(DMA_MEMCPY, cap_mask); + /* setup platform data for each SoC */ + dma_cap_set(DMA_MEMCPY, at91sam9rl_config.cap_mask); + dma_cap_set(DMA_MEMCPY, at91sam9g45_config.cap_mask); + dma_cap_set(DMA_SLAVE, at91sam9g45_config.cap_mask); /* get DMA parameters from controller type */ - atdmatype = at_dma_get_driver_data(pdev); - - switch (atdmatype) { - case ATDMA_DEVTYPE_SAM9RL: - nr_channels = 2; - break; - case ATDMA_DEVTYPE_SAM9G45: - nr_channels = 8; - dma_cap_set(DMA_SLAVE, cap_mask); - break; - default: - return -EINVAL; - } + plat_dat = at_dma_get_driver_data(pdev); + if (!plat_dat) + return -ENODEV; io = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!io) @@ -1272,15 +1272,14 @@ static int __init at_dma_probe(struct platform_device *pdev) return irq; size = sizeof(struct at_dma); - size += nr_channels * sizeof(struct at_dma_chan); + size += plat_dat->nr_channels * sizeof(struct at_dma_chan); atdma = kzalloc(size, GFP_KERNEL); if (!atdma) return -ENOMEM; /* discover transaction capabilities */ - atdma->dma_common.cap_mask = cap_mask; - atdma->all_chan_mask = (1 << nr_channels) - 1; - atdma->devtype = atdmatype; + atdma->dma_common.cap_mask = plat_dat->cap_mask; + atdma->all_chan_mask = (1 << plat_dat->nr_channels) - 1; size = resource_size(io); if (!request_mem_region(io->start, size, pdev->dev.driver->name)) { @@ -1326,7 +1325,7 @@ static int __init at_dma_probe(struct platform_device *pdev) /* initialize channels related values */ INIT_LIST_HEAD(&atdma->dma_common.channels); - for (i = 0; i < nr_channels; i++) { + for (i = 0; i < plat_dat->nr_channels; i++) { struct at_dma_chan *atchan = &atdma->chan[i]; atchan->chan_common.device = &atdma->dma_common; @@ -1371,7 +1370,7 @@ static int __init at_dma_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n", dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "", dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask) ? "slave " : "", - nr_channels); + plat_dat->nr_channels); dma_async_device_register(&atdma->dma_common); diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index d7d6737..dcaedfc 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h @@ -248,12 +248,6 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan) /*-- Controller ------------------------------------------------------*/ -enum atdma_devtype { - ATDMA_DEVTYPE_UNDEFINED = 0, - ATDMA_DEVTYPE_SAM9RL, /* compatible with SAM9RL DMA controller */ - ATDMA_DEVTYPE_SAM9G45, /* compatible with SAM9G45 DMA controller */ -}; - /** * struct at_dma - internal representation of an Atmel HDMA Controller * @chan_common: common dmaengine dma_device object members @@ -267,7 +261,6 @@ enum atdma_devtype { */ struct at_dma { struct dma_device dma_common; - enum atdma_devtype devtype; void __iomem *regs; struct clk *clk; u32 save_imr; -- cgit v0.10.2 From 75f064f220bde2fab9e932b27eee8372b65372c9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 28 Nov 2011 19:38:54 -0200 Subject: [media] tm6000: Add a few missing bits to alsa There are some properties found on em28xx, but not on tm6000. Add them, in order to be more consistent. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tm6000/tm6000-alsa.c b/drivers/media/video/tm6000/tm6000-alsa.c index 7d675c72..ddffd67 100644 --- a/drivers/media/video/tm6000/tm6000-alsa.c +++ b/drivers/media/video/tm6000/tm6000-alsa.c @@ -146,20 +146,21 @@ static int dsp_buffer_alloc(struct snd_pcm_substream *substream, int size) #define DEFAULT_FIFO_SIZE 4096 static struct snd_pcm_hardware snd_tm6000_digital_hw = { - .info = SNDRV_PCM_INFO_MMAP | + .info = SNDRV_PCM_INFO_BATCH | + SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID, .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT, .rate_min = 48000, .rate_max = 48000, .channels_min = 2, .channels_max = 2, .period_bytes_min = 64, .period_bytes_max = 12544, - .periods_min = 1, + .periods_min = 2, .periods_max = 98, .buffer_bytes_max = 62720 * 8, }; @@ -181,6 +182,7 @@ static int snd_tm6000_pcm_open(struct snd_pcm_substream *substream) chip->substream = substream; runtime->hw = snd_tm6000_digital_hw; + snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); return 0; _error: @@ -347,9 +349,13 @@ static int snd_tm6000_card_trigger(struct snd_pcm_substream *substream, int cmd) int err = 0; switch (cmd) { + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ + case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ case SNDRV_PCM_TRIGGER_START: atomic_set(&core->stream_started, 1); break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ + case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ case SNDRV_PCM_TRIGGER_STOP: atomic_set(&core->stream_started, 0); break; @@ -371,6 +377,14 @@ static snd_pcm_uframes_t snd_tm6000_pointer(struct snd_pcm_substream *substream) return chip->buf_pos; } +static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, + unsigned long offset) +{ + void *pageptr = subs->runtime->dma_area + offset; + + return vmalloc_to_page(pageptr); +} + /* * operators */ @@ -383,6 +397,7 @@ static struct snd_pcm_ops snd_tm6000_pcm_ops = { .prepare = snd_tm6000_prepare, .trigger = snd_tm6000_card_trigger, .pointer = snd_tm6000_pointer, + .page = snd_pcm_get_vmalloc_page, }; /* -- cgit v0.10.2 From 32f6f3ac5468bbbe0263d29daa16f38d04c2274f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 24 Nov 2011 12:20:12 -0300 Subject: [media] tm6000: Fix tm6010 audio standard selection A V4L2 standards mask may contain several standards. A more restricted mask with just one standard is used when user needs to bind to an specific standard that can't be auto-detect among a more generic mask. So, Improve the autodetection logic to detect the correct audio standard most of the time. Based on a patch made by Dmitri Belimov . Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tm6000/tm6000-core.c b/drivers/media/video/tm6000/tm6000-core.c index 9783616..55d097e 100644 --- a/drivers/media/video/tm6000/tm6000-core.c +++ b/drivers/media/video/tm6000/tm6000-core.c @@ -696,11 +696,13 @@ int tm6000_set_audio_rinput(struct tm6000_core *dev) if (dev->dev_type == TM6010) { /* Audio crossbar setting, default SIF1 */ u8 areg_f0; + u8 areg_07 = 0x10; switch (dev->rinput.amux) { case TM6000_AMUX_SIF1: case TM6000_AMUX_SIF2: areg_f0 = 0x03; + areg_07 = 0x30; break; case TM6000_AMUX_ADC1: areg_f0 = 0x00; @@ -720,6 +722,9 @@ int tm6000_set_audio_rinput(struct tm6000_core *dev) /* Set audio input crossbar */ tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, areg_f0, 0x0f); + /* Mux overflow workaround */ + tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL, + areg_07, 0xf0); } else { u8 areg_eb; /* Audio setting, default LINE1 */ diff --git a/drivers/media/video/tm6000/tm6000-stds.c b/drivers/media/video/tm6000/tm6000-stds.c index 9a4145dc..9dc0831 100644 --- a/drivers/media/video/tm6000/tm6000-stds.c +++ b/drivers/media/video/tm6000/tm6000-stds.c @@ -361,82 +361,51 @@ static int tm6000_set_audio_std(struct tm6000_core *dev) return 0; } - switch (tm6010_a_mode) { + /* + * STD/MN shouldn't be affected by tm6010_a_mode, as there's just one + * audio standard for each V4L2_STD type. + */ + if ((dev->norm & V4L2_STD_NTSC) == V4L2_STD_NTSC_M_KR) { + areg_05 |= 0x04; + } else if ((dev->norm & V4L2_STD_NTSC) == V4L2_STD_NTSC_M_JP) { + areg_05 |= 0x43; + } else if (dev->norm & V4L2_STD_MN) { + areg_05 |= 0x22; + } else switch (tm6010_a_mode) { /* auto */ case 0: - switch (dev->norm) { - case V4L2_STD_NTSC_M_KR: + if ((dev->norm & V4L2_STD_SECAM) == V4L2_STD_SECAM_L) areg_05 |= 0x00; - break; - case V4L2_STD_NTSC_M_JP: - areg_05 |= 0x40; - break; - case V4L2_STD_NTSC_M: - case V4L2_STD_PAL_M: - case V4L2_STD_PAL_N: - areg_05 |= 0x20; - break; - case V4L2_STD_PAL_Nc: - areg_05 |= 0x60; - break; - case V4L2_STD_SECAM_L: - areg_05 |= 0x00; - break; - case V4L2_STD_DK: + else /* Other PAL/SECAM standards */ areg_05 |= 0x10; - break; - } break; /* A2 */ case 1: - switch (dev->norm) { - case V4L2_STD_B: - case V4L2_STD_GH: - areg_05 = 0x05; - break; - case V4L2_STD_DK: + if (dev->norm & V4L2_STD_DK) areg_05 = 0x09; - break; - } + else + areg_05 = 0x05; break; /* NICAM */ case 2: - switch (dev->norm) { - case V4L2_STD_B: - case V4L2_STD_GH: - areg_05 = 0x07; - break; - case V4L2_STD_DK: + if (dev->norm & V4L2_STD_DK) { areg_05 = 0x06; - break; - case V4L2_STD_PAL_I: + } else if (dev->norm & V4L2_STD_PAL_I) { areg_05 = 0x08; - break; - case V4L2_STD_SECAM_L: + } else if (dev->norm & V4L2_STD_SECAM_L) { areg_05 = 0x0a; areg_02 = 0x02; - break; + } else { + areg_05 = 0x07; } nicam_flag = 1; break; /* other */ case 3: - switch (dev->norm) { - /* DK3_A2 */ - case V4L2_STD_DK: + if (dev->norm & V4L2_STD_DK) { areg_05 = 0x0b; - break; - /* Korea */ - case V4L2_STD_NTSC_M_KR: - areg_05 = 0x04; - break; - /* EIAJ */ - case V4L2_STD_NTSC_M_JP: - areg_05 = 0x03; - break; - default: + } else { areg_05 = 0x02; - break; } break; } @@ -557,10 +526,16 @@ int tm6000_set_standard(struct tm6000_core *dev) case TM6000_AMUX_ADC1: tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x00, 0x0f); + /* Mux overflow workaround */ + tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL, + 0x10, 0xf0); break; case TM6000_AMUX_ADC2: tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x08, 0x0f); + /* Mux overflow workaround */ + tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL, + 0x10, 0xf0); break; case TM6000_AMUX_SIF1: reg_08_e2 |= 0x02; @@ -570,6 +545,9 @@ int tm6000_set_standard(struct tm6000_core *dev) tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3); tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x02, 0x0f); + /* Mux overflow workaround */ + tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL, + 0x30, 0xf0); break; case TM6000_AMUX_SIF2: reg_08_e2 |= 0x02; @@ -579,6 +557,9 @@ int tm6000_set_standard(struct tm6000_core *dev) tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf7); tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x02, 0x0f); + /* Mux overflow workaround */ + tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL, + 0x30, 0xf0); break; default: break; -- cgit v0.10.2 From 078a68c11fe0580a23754fac25a6d9896719278e Mon Sep 17 00:00:00 2001 From: Stefan Ringel Date: Mon, 28 Nov 2011 15:46:16 -0300 Subject: [media] tm6000: remove experimental depends Signed-off-by: Stefan Ringel Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tm6000/Kconfig b/drivers/media/video/tm6000/Kconfig index 114eec8..a43b77a 100644 --- a/drivers/media/video/tm6000/Kconfig +++ b/drivers/media/video/tm6000/Kconfig @@ -1,6 +1,6 @@ config VIDEO_TM6000 tristate "TV Master TM5600/6000/6010 driver" - depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB && EXPERIMENTAL + depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB select VIDEO_TUNER select MEDIA_TUNER_XC2028 select MEDIA_TUNER_XC5000 @@ -16,7 +16,7 @@ config VIDEO_TM6000 config VIDEO_TM6000_ALSA tristate "TV Master TM5600/6000/6010 audio support" - depends on VIDEO_TM6000 && SND && EXPERIMENTAL + depends on VIDEO_TM6000 && SND select SND_PCM ---help--- This is a video4linux driver for direct (DMA) audio for @@ -27,7 +27,7 @@ config VIDEO_TM6000_ALSA config VIDEO_TM6000_DVB tristate "DVB Support for tm6000 based TV cards" - depends on VIDEO_TM6000 && DVB_CORE && USB && EXPERIMENTAL + depends on VIDEO_TM6000 && DVB_CORE && USB select DVB_ZL10353 ---help--- This adds support for DVB cards based on the tm5600/tm6000 chip. -- cgit v0.10.2 From c00ecc97bc638919ff35117290b4fab01354e8d7 Mon Sep 17 00:00:00 2001 From: Stefan Ringel Date: Mon, 28 Nov 2011 15:46:17 -0300 Subject: [media] tm6000: bugfix at tm6000_set_reg_mask() register setting Signed-off-by: Stefan Ringel Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tm6000/tm6000-core.c b/drivers/media/video/tm6000/tm6000-core.c index 55d097e..5d7d045 100644 --- a/drivers/media/video/tm6000/tm6000-core.c +++ b/drivers/media/video/tm6000/tm6000-core.c @@ -125,14 +125,14 @@ int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value, u8 new_index; rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req, - value, index, buf, 1); + value, 0, buf, 1); if (rc < 0) return rc; new_index = (buf[0] & ~mask) | (index & mask); - if (new_index == index) + if (new_index == buf[0]) return 0; return tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR, -- cgit v0.10.2 From 8159c184cf58ac78fc868d776fa2062d1162b6e5 Mon Sep 17 00:00:00 2001 From: Stefan Ringel Date: Mon, 28 Nov 2011 15:46:18 -0300 Subject: [media] tm6000: bugfix at interrupt reset Signed-off-by: Stefan Ringel Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tm6000/tm6000-core.c b/drivers/media/video/tm6000/tm6000-core.c index 5d7d045..b16b46a 100644 --- a/drivers/media/video/tm6000/tm6000-core.c +++ b/drivers/media/video/tm6000/tm6000-core.c @@ -599,55 +599,6 @@ int tm6000_init(struct tm6000_core *dev) return rc; } -int tm6000_reset(struct tm6000_core *dev) -{ - int pipe; - int err; - - msleep(500); - - err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 0); - if (err < 0) { - tm6000_err("failed to select interface %d, alt. setting 0\n", - dev->isoc_in.bInterfaceNumber); - return err; - } - - err = usb_reset_configuration(dev->udev); - if (err < 0) { - tm6000_err("failed to reset configuration\n"); - return err; - } - - if ((dev->quirks & TM6000_QUIRK_NO_USB_DELAY) == 0) - msleep(5); - - /* - * Not all devices have int_in defined - */ - if (!dev->int_in.endp) - return 0; - - err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 2); - if (err < 0) { - tm6000_err("failed to select interface %d, alt. setting 2\n", - dev->isoc_in.bInterfaceNumber); - return err; - } - - msleep(5); - - pipe = usb_rcvintpipe(dev->udev, - dev->int_in.endp->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); - - err = usb_clear_halt(dev->udev, pipe); - if (err < 0) { - tm6000_err("usb_clear_halt failed: %d\n", err); - return err; - } - - return 0; -} int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate) { diff --git a/drivers/media/video/tm6000/tm6000-video.c b/drivers/media/video/tm6000/tm6000-video.c index 1e5ace0..4db3535 100644 --- a/drivers/media/video/tm6000/tm6000-video.c +++ b/drivers/media/video/tm6000/tm6000-video.c @@ -1609,12 +1609,25 @@ static int tm6000_release(struct file *file) tm6000_uninit_isoc(dev); + /* Stop interrupt USB pipe */ + tm6000_ir_int_stop(dev); + + usb_reset_configuration(dev->udev); + + if (&dev->int_in) + usb_set_interface(dev->udev, + dev->isoc_in.bInterfaceNumber, + 2); + else + usb_set_interface(dev->udev, + dev->isoc_in.bInterfaceNumber, + 0); + + /* Start interrupt USB pipe */ + tm6000_ir_int_start(dev); + if (!fh->radio) videobuf_mmap_free(&fh->vb_vidq); - - err = tm6000_reset(dev); - if (err < 0) - dev_err(&vdev->dev, "reset failed: %d\n", err); } kfree(fh); -- cgit v0.10.2 From de2a20baff364b8dd19371acc1dc0b138e0b08b9 Mon Sep 17 00:00:00 2001 From: Stefan Ringel Date: Mon, 28 Nov 2011 15:46:19 -0300 Subject: [media] tm6000: bugfix at bulk transfer Signed-off-by: Stefan Ringel Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tm6000/tm6000-dvb.c b/drivers/media/video/tm6000/tm6000-dvb.c index 5e6c129..db6a561 100644 --- a/drivers/media/video/tm6000/tm6000-dvb.c +++ b/drivers/media/video/tm6000/tm6000-dvb.c @@ -89,9 +89,19 @@ static void tm6000_urb_received(struct urb *urb) int ret; struct tm6000_core *dev = urb->context; - if (urb->status != 0) + switch (urb->status) { + case 0: + case -ETIMEDOUT: + break; + case -ENOENT: + case -ECONNRESET: + case -ESHUTDOWN: + return; + default: print_err_status(dev, 0, urb->status); - else if (urb->actual_length > 0) + } + + if (urb->actual_length > 0) dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer, urb->actual_length); @@ -151,7 +161,7 @@ static int tm6000_start_stream(struct tm6000_core *dev) printk(KERN_ERR "tm6000: pipe resetted\n"); /* mutex_lock(&tm6000_driver.open_close_mutex); */ - ret = usb_submit_urb(dvb->bulk_urb, GFP_KERNEL); + ret = usb_submit_urb(dvb->bulk_urb, GFP_ATOMIC); /* mutex_unlock(&tm6000_driver.open_close_mutex); */ if (ret) { -- cgit v0.10.2 From edcfdd919a1c8afbf500be0dbfa9b68f40b4c219 Mon Sep 17 00:00:00 2001 From: Stefan Ringel Date: Mon, 28 Nov 2011 15:46:20 -0300 Subject: [media] tm6000: bugfix data check beholder use a map with 3 bytes, but many rc maps have 2 bytes, so I add a workaround for beholder rc. Signed-off-by: Stefan Ringel Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tm6000/tm6000-input.c b/drivers/media/video/tm6000/tm6000-input.c index 405d127..ae7772e 100644 --- a/drivers/media/video/tm6000/tm6000-input.c +++ b/drivers/media/video/tm6000/tm6000-input.c @@ -178,9 +178,21 @@ static int default_polling_getkey(struct tm6000_IR *ir, poll_result->rc_data = ir->urb_data[0]; break; case RC_TYPE_NEC: - if (ir->urb_data[1] == ((ir->key_addr >> 8) & 0xff)) { + switch (dev->model) { + case 10: + case 11: + case 14: + case 15: + if (ir->urb_data[1] == + ((ir->key_addr >> 8) & 0xff)) { + poll_result->rc_data = + ir->urb_data[0] + | ir->urb_data[1] << 8; + } + break; + default: poll_result->rc_data = ir->urb_data[0] - | ir->urb_data[1] << 8; + | ir->urb_data[1] << 8; } break; default: @@ -238,8 +250,6 @@ static void tm6000_ir_handle_key(struct tm6000_IR *ir) return; } - dprintk("ir->get_key result data=%04x\n", poll_result.rc_data); - if (ir->pwled) { if (ir->pwledcnt >= PWLED_OFF) { ir->pwled = 0; @@ -250,6 +260,7 @@ static void tm6000_ir_handle_key(struct tm6000_IR *ir) } if (ir->key) { + dprintk("ir->get_key result data=%04x\n", poll_result.rc_data); rc_keydown(ir->rc, poll_result.rc_data, 0); ir->key = 0; ir->pwled = 1; @@ -333,7 +344,7 @@ int tm6000_ir_int_start(struct tm6000_core *dev) ir->int_urb->transfer_buffer, size, tm6000_ir_urb_received, dev, dev->int_in.endp->desc.bInterval); - err = usb_submit_urb(ir->int_urb, GFP_KERNEL); + err = usb_submit_urb(ir->int_urb, GFP_ATOMIC); if (err) { kfree(ir->int_urb->transfer_buffer); usb_free_urb(ir->int_urb); -- cgit v0.10.2 From 36d36b884c745c507d9b3f60eb42925749f7d758 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 28 Nov 2011 21:58:54 -0200 Subject: [media] tm6000: Warning cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/video/tm6000/tm6000-video.c: In function ‘tm6000_release’: drivers/media/video/tm6000/tm6000-video.c:1608:7: warning: unused variable ‘err’ [-Wunused-variable] Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tm6000/tm6000-video.c b/drivers/media/video/tm6000/tm6000-video.c index 4db3535..436fd67 100644 --- a/drivers/media/video/tm6000/tm6000-video.c +++ b/drivers/media/video/tm6000/tm6000-video.c @@ -1605,8 +1605,6 @@ static int tm6000_release(struct file *file) res_free(dev, fh); if (!dev->users) { - int err; - tm6000_uninit_isoc(dev); /* Stop interrupt USB pipe */ -- cgit v0.10.2 From 15a295ec31fbef374ebda5f286a908e498a4579a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 29 Nov 2011 11:35:55 -0300 Subject: [media] tm6000: Fix IR register names IR registers 0xd9 to 0xdf were badly named, making harder to check what's the register accessed at the RC code. Fix the name convention. No functional changes on this patch. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tm6000/tm6000-core.c b/drivers/media/video/tm6000/tm6000-core.c index b16b46a..6c1fdb5 100644 --- a/drivers/media/video/tm6000/tm6000-core.c +++ b/drivers/media/video/tm6000/tm6000-core.c @@ -536,16 +536,16 @@ static struct reg_init tm6010_init_tab[] = { { TM6010_REQ05_R18_IMASK7, 0x00 }, - { TM6010_REQ07_RD8_IR_LEADER1, 0xaa }, - { TM6010_REQ07_RD8_IR_LEADER0, 0x30 }, - { TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20 }, - { TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0 }, + { TM6010_REQ07_RDC_IR_LEADER1, 0xaa }, + { TM6010_REQ07_RDD_IR_LEADER0, 0x30 }, + { TM6010_REQ07_RDE_IR_PULSE_CNT1, 0x20 }, + { TM6010_REQ07_RDF_IR_PULSE_CNT0, 0xd0 }, { REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 }, { TM6010_REQ07_RD8_IR, 0x2f }, /* set remote wakeup key:any key wakeup */ { TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe }, - { TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff }, + { TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff }, }; int tm6000_init(struct tm6000_core *dev) diff --git a/drivers/media/video/tm6000/tm6000-input.c b/drivers/media/video/tm6000/tm6000-input.c index ae7772e..8b07b72 100644 --- a/drivers/media/video/tm6000/tm6000-input.c +++ b/drivers/media/video/tm6000/tm6000-input.c @@ -100,17 +100,17 @@ static int tm6000_ir_config(struct tm6000_IR *ir) case RC_TYPE_NEC: /* Setup IR decoder for NEC standard 12MHz system clock */ /* IR_LEADER_CNT = 0.9ms */ - tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER1, 0xaa); - tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER0, 0x30); + tm6000_set_reg(dev, TM6010_REQ07_RDC_IR_LEADER1, 0xaa); + tm6000_set_reg(dev, TM6010_REQ07_RDD_IR_LEADER0, 0x30); /* IR_PULSE_CNT = 0.7ms */ - tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20); - tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0); + tm6000_set_reg(dev, TM6010_REQ07_RDE_IR_PULSE_CNT1, 0x20); + tm6000_set_reg(dev, TM6010_REQ07_RDF_IR_PULSE_CNT0, 0xd0); /* Remote WAKEUP = enable */ tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe); /* IR_WKUP_SEL = Low byte in decoded IR data */ - tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff); + tm6000_set_reg(dev, TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff); /* IR_WKU_ADD code */ - tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_ADD, 0xff); + tm6000_set_reg(dev, TM6010_REQ07_RDB_IR_WAKEUP_ADD, 0xff); tm6000_flash_led(dev, 0); msleep(100); tm6000_flash_led(dev, 1); diff --git a/drivers/media/video/tm6000/tm6000-regs.h b/drivers/media/video/tm6000/tm6000-regs.h index 7f491b6..a38c251 100644 --- a/drivers/media/video/tm6000/tm6000-regs.h +++ b/drivers/media/video/tm6000/tm6000-regs.h @@ -284,19 +284,19 @@ enum { /* ONLY for TM6010 */ #define TM6010_REQ07_RD8_IR 0x07, 0xd8 /* ONLY for TM6010 */ -#define TM6010_REQ07_RD8_IR_BSIZE 0x07, 0xd9 +#define TM6010_REQ07_RD9_IR_BSIZE 0x07, 0xd9 /* ONLY for TM6010 */ -#define TM6010_REQ07_RD8_IR_WAKEUP_SEL 0x07, 0xda +#define TM6010_REQ07_RDA_IR_WAKEUP_SEL 0x07, 0xda /* ONLY for TM6010 */ -#define TM6010_REQ07_RD8_IR_WAKEUP_ADD 0x07, 0xdb +#define TM6010_REQ07_RDB_IR_WAKEUP_ADD 0x07, 0xdb /* ONLY for TM6010 */ -#define TM6010_REQ07_RD8_IR_LEADER1 0x07, 0xdc +#define TM6010_REQ07_RDC_IR_LEADER1 0x07, 0xdc /* ONLY for TM6010 */ -#define TM6010_REQ07_RD8_IR_LEADER0 0x07, 0xdd +#define TM6010_REQ07_RDD_IR_LEADER0 0x07, 0xdd /* ONLY for TM6010 */ -#define TM6010_REQ07_RD8_IR_PULSE_CNT1 0x07, 0xde +#define TM6010_REQ07_RDE_IR_PULSE_CNT1 0x07, 0xde /* ONLY for TM6010 */ -#define TM6010_REQ07_RD8_IR_PULSE_CNT0 0x07, 0xdf +#define TM6010_REQ07_RDF_IR_PULSE_CNT0 0x07, 0xdf /* ONLY for TM6010 */ #define TM6010_REQ07_RE0_DVIDEO_SOURCE 0x07, 0xe0 /* ONLY for TM6010 */ -- cgit v0.10.2 From 884b0515dcbcd9e574d385c97f80243805b5b0f3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 29 Nov 2011 13:33:52 -0300 Subject: [media] tuner-xc2028: Better report signal strength Fix lock bit to better indicate signal strength, from 4096 to 65535. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c index 3acbaa0..e531267 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/common/tuners/tuner-xc2028.c @@ -891,7 +891,7 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength) /* Frequency is locked */ if (frq_lock == 1) - signal = 32768; + signal = 1 << 11; /* Get SNR of the video signal */ rc = xc2028_get_reg(priv, 0x0040, &signal); -- cgit v0.10.2 From f9fa905bde6f2e8354eee35c08362dded08e3c1e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 30 Nov 2011 12:58:51 -0300 Subject: [media] tm6000: add IR support for HVR-900H Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tm6000/tm6000-cards.c b/drivers/media/video/tm6000/tm6000-cards.c index ec2578a..0b54132 100644 --- a/drivers/media/video/tm6000/tm6000-cards.c +++ b/drivers/media/video/tm6000/tm6000-cards.c @@ -351,6 +351,7 @@ static struct tm6000_board tm6000_boards[] = { .tuner_addr = 0xc2 >> 1, .demod_addr = 0x1e >> 1, .type = TM6010, + .ir_codes = RC_MAP_HAUPPAUGE, .caps = { .has_tuner = 1, .has_dvb = 1, -- cgit v0.10.2 From 4a83b0115066ae5a8111938df97231e65d0f88e3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 29 Nov 2011 11:30:30 -0300 Subject: [media] tm6000: rewrite IR support The IR support were broken on my tests with HVR-900H. Also, there were several issues on the current implementation. This patch is a major rewrite of the IR support for this - Improve debug messages; - Don't do polling for interrrupt based IR; - Add proper support for RC-5 protocol; - Always provide 16 bits for NEC and RC-5; - Fix polling code; - Split polling functions from URB Interrupt ones; - Don't hardcode the XTAL reference for tm6000 IR; - If a URB submit fails, retries after 100ms; - etc. Tested on Hauppauge HVR-900H, with RC-5 and NEC remotes. Issues on IR handling, on this device: - Repeat events aren't detected (neither on NEC or RC-5); - NEC codes are always provided with 16 bits. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tm6000/tm6000-core.c b/drivers/media/video/tm6000/tm6000-core.c index 6c1fdb5..fa37b5f 100644 --- a/drivers/media/video/tm6000/tm6000-core.c +++ b/drivers/media/video/tm6000/tm6000-core.c @@ -541,7 +541,7 @@ static struct reg_init tm6010_init_tab[] = { { TM6010_REQ07_RDE_IR_PULSE_CNT1, 0x20 }, { TM6010_REQ07_RDF_IR_PULSE_CNT0, 0xd0 }, { REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 }, - { TM6010_REQ07_RD8_IR, 0x2f }, + { TM6010_REQ07_RD8_IR, 0x0f }, /* set remote wakeup key:any key wakeup */ { TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe }, diff --git a/drivers/media/video/tm6000/tm6000-input.c b/drivers/media/video/tm6000/tm6000-input.c index 8b07b72..6eaf770 100644 --- a/drivers/media/video/tm6000/tm6000-input.c +++ b/drivers/media/video/tm6000/tm6000-input.c @@ -31,22 +31,25 @@ static unsigned int ir_debug; module_param(ir_debug, int, 0644); -MODULE_PARM_DESC(ir_debug, "enable debug message [IR]"); +MODULE_PARM_DESC(ir_debug, "debug message level"); static unsigned int enable_ir = 1; module_param(enable_ir, int, 0644); MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)"); -/* number of 50ms for ON-OFF-ON power led */ -/* show IR activity */ -#define PWLED_OFF 2 +static unsigned int ir_clock_mhz = 12; +module_param(ir_clock_mhz, int, 0644); +MODULE_PARM_DESC(enable_ir, "ir clock, in MHz"); + +#define URB_SUBMIT_DELAY 100 /* ms - Delay to submit an URB request on retrial and init */ +#define URB_INT_LED_DELAY 100 /* ms - Delay to turn led on again on int mode */ #undef dprintk -#define dprintk(fmt, arg...) \ - if (ir_debug) { \ +#define dprintk(level, fmt, arg...) do {\ + if (ir_debug >= level) \ printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ - } + } while (0) struct tm6000_ir_poll_result { u16 rc_data; @@ -62,20 +65,15 @@ struct tm6000_IR { int polling; struct delayed_work work; u8 wait:1; - u8 key:1; - u8 pwled:1; - u8 pwledcnt; + u8 pwled:2; + u8 submit_urb:1; u16 key_addr; struct urb *int_urb; - u8 *urb_data; - - int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *); /* IR device properties */ u64 rc_type; }; - void tm6000_ir_wait(struct tm6000_core *dev, u8 state) { struct tm6000_IR *ir = dev->ir; @@ -83,62 +81,84 @@ void tm6000_ir_wait(struct tm6000_core *dev, u8 state) if (!dev->ir) return; + dprintk(2, "%s: %i\n",__func__, ir->wait); + if (state) ir->wait = 1; else ir->wait = 0; } - static int tm6000_ir_config(struct tm6000_IR *ir) { struct tm6000_core *dev = ir->dev; - u8 buf[10]; - int rc; + u32 pulse = 0, leader = 0; + + dprintk(2, "%s\n",__func__); + + /* + * The IR decoder supports RC-5 or NEC, with a configurable timing. + * The timing configuration there is not that accurate, as it uses + * approximate values. The NEC spec mentions a 562.5 unit period, + * and RC-5 uses a 888.8 period. + * Currently, driver assumes a clock provided by a 12 MHz XTAL, but + * a modprobe parameter can adjust it. + * Adjustments are required for other timings. + * It seems that the 900ms timing for NEC is used to detect a RC-5 + * IR, in order to discard such decoding + */ switch (ir->rc_type) { case RC_TYPE_NEC: - /* Setup IR decoder for NEC standard 12MHz system clock */ - /* IR_LEADER_CNT = 0.9ms */ - tm6000_set_reg(dev, TM6010_REQ07_RDC_IR_LEADER1, 0xaa); - tm6000_set_reg(dev, TM6010_REQ07_RDD_IR_LEADER0, 0x30); - /* IR_PULSE_CNT = 0.7ms */ - tm6000_set_reg(dev, TM6010_REQ07_RDE_IR_PULSE_CNT1, 0x20); - tm6000_set_reg(dev, TM6010_REQ07_RDF_IR_PULSE_CNT0, 0xd0); - /* Remote WAKEUP = enable */ - tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe); - /* IR_WKUP_SEL = Low byte in decoded IR data */ - tm6000_set_reg(dev, TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff); - /* IR_WKU_ADD code */ - tm6000_set_reg(dev, TM6010_REQ07_RDB_IR_WAKEUP_ADD, 0xff); - tm6000_flash_led(dev, 0); - msleep(100); - tm6000_flash_led(dev, 1); + leader = 900; /* ms */ + pulse = 700; /* ms - the actual value would be 562 */ break; default: - /* hack */ - buf[0] = 0xff; - buf[1] = 0xff; - buf[2] = 0xf2; - buf[3] = 0x2b; - buf[4] = 0x20; - buf[5] = 0x35; - buf[6] = 0x60; - buf[7] = 0x04; - buf[8] = 0xc0; - buf[9] = 0x08; - - rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a); - msleep(100); - - if (rc < 0) { - printk(KERN_INFO "IR configuration failed"); - return rc; - } + case RC_TYPE_RC5: + leader = 900; /* ms - from the NEC decoding */ + pulse = 1780; /* ms - The actual value would be 1776 */ break; } + pulse = ir_clock_mhz * pulse; + leader = ir_clock_mhz * leader; + if (ir->rc_type == RC_TYPE_NEC) + leader = leader | 0x8000; + + dprintk(2, "%s: %s, %d MHz, leader = 0x%04x, pulse = 0x%06x \n", + __func__, + (ir->rc_type == RC_TYPE_NEC) ? "NEC" : "RC-5", + ir_clock_mhz, leader, pulse); + + /* Remote WAKEUP = enable, normal mode, from IR decoder output */ + tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe); + + /* Enable IR reception on non-busrt mode */ + tm6000_set_reg(dev, TM6010_REQ07_RD8_IR, 0x2f); + + /* IR_WKUP_SEL = Low byte in decoded IR data */ + tm6000_set_reg(dev, TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff); + /* IR_WKU_ADD code */ + tm6000_set_reg(dev, TM6010_REQ07_RDB_IR_WAKEUP_ADD, 0xff); + + tm6000_set_reg(dev, TM6010_REQ07_RDC_IR_LEADER1, leader >> 8); + tm6000_set_reg(dev, TM6010_REQ07_RDD_IR_LEADER0, leader); + + tm6000_set_reg(dev, TM6010_REQ07_RDE_IR_PULSE_CNT1, pulse >> 8); + tm6000_set_reg(dev, TM6010_REQ07_RDF_IR_PULSE_CNT0, pulse); + + if (!ir->polling) + tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); + else + tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1); + msleep(10); + + /* Shows that IR is working via the LED */ + tm6000_flash_led(dev, 0); + msleep(100); + tm6000_flash_led(dev, 1); + ir->pwled = 1; + return 0; } @@ -146,143 +166,124 @@ static void tm6000_ir_urb_received(struct urb *urb) { struct tm6000_core *dev = urb->context; struct tm6000_IR *ir = dev->ir; + struct tm6000_ir_poll_result poll_result; + char *buf; int rc; - if (urb->status != 0) - printk(KERN_INFO "not ready\n"); - else if (urb->actual_length > 0) { - memcpy(ir->urb_data, urb->transfer_buffer, urb->actual_length); + dprintk(2, "%s\n",__func__); + if (urb->status < 0 || urb->actual_length <= 0) { + printk(KERN_INFO "tm6000: IR URB failure: status: %i, length %i\n", + urb->status, urb->actual_length); + ir->submit_urb = 1; + schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY)); + return; + } + buf = urb->transfer_buffer; - dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0], - ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]); + if (ir_debug) + print_hex_dump(KERN_DEBUG, "tm6000: IR data: ", + DUMP_PREFIX_OFFSET,16, 1, + buf, urb->actual_length, false); - ir->key = 1; - } + poll_result.rc_data = buf[0]; + if (urb->actual_length > 1) + poll_result.rc_data |= buf[1] << 8; + + dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data); + rc_keydown(ir->rc, poll_result.rc_data, 0); rc = usb_submit_urb(urb, GFP_ATOMIC); + /* + * Flash the led. We can't do it here, as it is running on IRQ context. + * So, use the scheduler to do it, in a few ms. + */ + ir->pwled = 2; + schedule_delayed_work(&ir->work, msecs_to_jiffies(10)); } -static int default_polling_getkey(struct tm6000_IR *ir, - struct tm6000_ir_poll_result *poll_result) +static void tm6000_ir_handle_key(struct work_struct *work) { + struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work); struct tm6000_core *dev = ir->dev; + struct tm6000_ir_poll_result poll_result; int rc; u8 buf[2]; - if (ir->wait && !&dev->int_in) - return 0; - - if (&dev->int_in) { - switch (ir->rc_type) { - case RC_TYPE_RC5: - poll_result->rc_data = ir->urb_data[0]; - break; - case RC_TYPE_NEC: - switch (dev->model) { - case 10: - case 11: - case 14: - case 15: - if (ir->urb_data[1] == - ((ir->key_addr >> 8) & 0xff)) { - poll_result->rc_data = - ir->urb_data[0] - | ir->urb_data[1] << 8; - } - break; - default: - poll_result->rc_data = ir->urb_data[0] - | ir->urb_data[1] << 8; - } - break; - default: - poll_result->rc_data = ir->urb_data[0] - | ir->urb_data[1] << 8; - break; - } - } else { - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); - msleep(10); - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1); - msleep(10); - - if (ir->rc_type == RC_TYPE_RC5) { - rc = tm6000_read_write_usb(dev, USB_DIR_IN | - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - REQ_02_GET_IR_CODE, 0, 0, buf, 1); - - msleep(10); - - dprintk("read data=%02x\n", buf[0]); - if (rc < 0) - return rc; + if (ir->wait) + return; - poll_result->rc_data = buf[0]; - } else { - rc = tm6000_read_write_usb(dev, USB_DIR_IN | - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - REQ_02_GET_IR_CODE, 0, 0, buf, 2); + dprintk(3, "%s\n",__func__); - msleep(10); + rc = tm6000_read_write_usb(dev, USB_DIR_IN | + USB_TYPE_VENDOR | USB_RECIP_DEVICE, + REQ_02_GET_IR_CODE, 0, 0, buf, 2); + if (rc < 0) + return; - dprintk("read data=%04x\n", buf[0] | buf[1] << 8); - if (rc < 0) - return rc; + if (rc > 1) + poll_result.rc_data = buf[0] | buf[1] << 8; + else + poll_result.rc_data = buf[0]; - poll_result->rc_data = buf[0] | buf[1] << 8; + /* Check if something was read */ + if ((poll_result.rc_data & 0xff) == 0xff) { + if (!ir->pwled) { + tm6000_flash_led(dev, 1); + ir->pwled = 1; } - if ((poll_result->rc_data & 0x00ff) != 0xff) - ir->key = 1; + return; } - return 0; + + dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data); + rc_keydown(ir->rc, poll_result.rc_data, 0); + tm6000_flash_led(dev, 0); + ir->pwled = 0; + + /* Re-schedule polling */ + schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); } -static void tm6000_ir_handle_key(struct tm6000_IR *ir) +static void tm6000_ir_int_work(struct work_struct *work) { + struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work); struct tm6000_core *dev = ir->dev; - int result; - struct tm6000_ir_poll_result poll_result; + int rc; - /* read the registers containing the IR status */ - result = ir->get_key(ir, &poll_result); - if (result < 0) { - printk(KERN_INFO "ir->get_key() failed %d\n", result); - return; - } + dprintk(3, "%s, submit_urb = %d, pwled = %d\n",__func__, ir->submit_urb, + ir->pwled); - if (ir->pwled) { - if (ir->pwledcnt >= PWLED_OFF) { - ir->pwled = 0; - ir->pwledcnt = 0; - tm6000_flash_led(dev, 1); - } else - ir->pwledcnt += 1; + if (ir->submit_urb) { + dprintk(3, "Resubmit urb\n"); + tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); + + rc = usb_submit_urb(ir->int_urb, GFP_ATOMIC); + if (rc < 0) { + printk(KERN_ERR "tm6000: Can't submit an IR interrupt. Error %i\n", + rc); + /* Retry in 100 ms */ + schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY)); + return; + } + ir->submit_urb = 0; } - if (ir->key) { - dprintk("ir->get_key result data=%04x\n", poll_result.rc_data); - rc_keydown(ir->rc, poll_result.rc_data, 0); - ir->key = 0; - ir->pwled = 1; - ir->pwledcnt = 0; + /* Led is enabled only if USB submit doesn't fail */ + if (ir->pwled == 2) { tm6000_flash_led(dev, 0); + ir->pwled = 0; + schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_INT_LED_DELAY)); + } else if (!ir->pwled) { + tm6000_flash_led(dev, 1); + ir->pwled = 1; } - return; -} - -static void tm6000_ir_work(struct work_struct *work) -{ - struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work); - - tm6000_ir_handle_key(ir); - schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); } static int tm6000_ir_start(struct rc_dev *rc) { struct tm6000_IR *ir = rc->priv; - INIT_DELAYED_WORK(&ir->work, tm6000_ir_work); + dprintk(2, "%s\n",__func__); + schedule_delayed_work(&ir->work, 0); return 0; @@ -292,6 +293,8 @@ static void tm6000_ir_stop(struct rc_dev *rc) { struct tm6000_IR *ir = rc->priv; + dprintk(2, "%s\n",__func__); + cancel_delayed_work_sync(&ir->work); } @@ -302,10 +305,11 @@ static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type) if (!ir) return 0; + dprintk(2, "%s\n",__func__); + if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC)) ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff); - ir->get_key = default_polling_getkey; ir->rc_type = rc_type; tm6000_ir_config(ir); @@ -313,17 +317,19 @@ static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type) return 0; } -int tm6000_ir_int_start(struct tm6000_core *dev) +static int __tm6000_ir_int_start(struct rc_dev *rc) { - struct tm6000_IR *ir = dev->ir; + struct tm6000_IR *ir = rc->priv; + struct tm6000_core *dev = ir->dev; int pipe, size; int err = -ENOMEM; - if (!ir) return -ENODEV; - ir->int_urb = usb_alloc_urb(0, GFP_KERNEL); + dprintk(2, "%s\n",__func__); + + ir->int_urb = usb_alloc_urb(0, GFP_ATOMIC); if (!ir->int_urb) return -ENOMEM; @@ -332,42 +338,53 @@ int tm6000_ir_int_start(struct tm6000_core *dev) & USB_ENDPOINT_NUMBER_MASK); size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); - dprintk("IR max size: %d\n", size); + dprintk(1, "IR max size: %d\n", size); - ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); + ir->int_urb->transfer_buffer = kzalloc(size, GFP_ATOMIC); if (ir->int_urb->transfer_buffer == NULL) { usb_free_urb(ir->int_urb); return err; } - dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval); + dprintk(1, "int interval: %d\n", dev->int_in.endp->desc.bInterval); + usb_fill_int_urb(ir->int_urb, dev->udev, pipe, ir->int_urb->transfer_buffer, size, tm6000_ir_urb_received, dev, dev->int_in.endp->desc.bInterval); - err = usb_submit_urb(ir->int_urb, GFP_ATOMIC); - if (err) { - kfree(ir->int_urb->transfer_buffer); - usb_free_urb(ir->int_urb); - return err; - } - ir->urb_data = kzalloc(size, GFP_KERNEL); + + ir->submit_urb = 1; + schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY)); return 0; } -void tm6000_ir_int_stop(struct tm6000_core *dev) +static void __tm6000_ir_int_stop(struct rc_dev *rc) { - struct tm6000_IR *ir = dev->ir; + struct tm6000_IR *ir = rc->priv; - if (!ir) + if (!ir || !ir->int_urb) return; + dprintk(2, "%s\n",__func__); + usb_kill_urb(ir->int_urb); kfree(ir->int_urb->transfer_buffer); usb_free_urb(ir->int_urb); ir->int_urb = NULL; - kfree(ir->urb_data); - ir->urb_data = NULL; +} + +int tm6000_ir_int_start(struct tm6000_core *dev) +{ + struct tm6000_IR *ir = dev->ir; + + return __tm6000_ir_int_start(ir->rc); +} + +void tm6000_ir_int_stop(struct tm6000_core *dev) +{ + struct tm6000_IR *ir = dev->ir; + + __tm6000_ir_int_stop(ir->rc); } int tm6000_ir_init(struct tm6000_core *dev) @@ -385,7 +402,9 @@ int tm6000_ir_init(struct tm6000_core *dev) if (!dev->ir_codes) return 0; - ir = kzalloc(sizeof(*ir), GFP_KERNEL); + dprintk(2, "%s\n",__func__); + + ir = kzalloc(sizeof(*ir), GFP_ATOMIC); rc = rc_allocate_device(); if (!ir || !rc) goto out; @@ -395,19 +414,22 @@ int tm6000_ir_init(struct tm6000_core *dev) dev->ir = ir; ir->rc = rc; - /* input einrichten */ + /* input setup */ rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC; rc->priv = ir; rc->change_protocol = tm6000_ir_change_protocol; - rc->open = tm6000_ir_start; - rc->close = tm6000_ir_stop; + if (&dev->int_in) { + rc->open = __tm6000_ir_int_start; + rc->close = __tm6000_ir_int_stop; + INIT_DELAYED_WORK(&ir->work, tm6000_ir_int_work); + } else { + rc->open = tm6000_ir_start; + rc->close = tm6000_ir_stop; + ir->polling = 50; + INIT_DELAYED_WORK(&ir->work, tm6000_ir_handle_key); + } rc->driver_type = RC_DRIVER_SCANCODE; - ir->polling = 50; - ir->pwled = 0; - ir->pwledcnt = 0; - - snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)", dev->name); @@ -426,15 +448,6 @@ int tm6000_ir_init(struct tm6000_core *dev) rc->driver_name = "tm6000"; rc->dev.parent = &dev->udev->dev; - if (&dev->int_in) { - dprintk("IR over int\n"); - - err = tm6000_ir_int_start(dev); - - if (err) - goto out; - } - /* ir register */ err = rc_register_device(rc); if (err) @@ -458,10 +471,19 @@ int tm6000_ir_fini(struct tm6000_core *dev) if (!ir) return 0; + dprintk(2, "%s\n",__func__); + rc_unregister_device(ir->rc); - if (ir->int_urb) - tm6000_ir_int_stop(dev); + if (!ir->polling) + __tm6000_ir_int_stop(ir->rc); + + tm6000_ir_stop(ir->rc); + + /* Turn off the led */ + tm6000_flash_led(dev, 0); + ir->pwled = 0; + kfree(ir); dev->ir = NULL; -- cgit v0.10.2 From 8afc539c4a3df5da4e90c36cf21e2bc7a2572149 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 30 Nov 2011 13:26:10 -0300 Subject: [media] tm6000: Allow auto-detecting tm6000 devices Now that the tm6000 driver is on a good shape, we can enable device autodetection, based on the USB ID. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tm6000/tm6000-cards.c b/drivers/media/video/tm6000/tm6000-cards.c index 0b54132..3873ce4 100644 --- a/drivers/media/video/tm6000/tm6000-cards.c +++ b/drivers/media/video/tm6000/tm6000-cards.c @@ -640,6 +640,7 @@ static struct usb_device_id tm6000_id_table[] = { { USB_DEVICE(0x6000, 0xdec3), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER_LITE }, { } }; +MODULE_DEVICE_TABLE(usb, tm6000_id_table); /* Control power led for show some activity */ void tm6000_flash_led(struct tm6000_core *dev, u8 state) -- cgit v0.10.2 From 9f711a80c5d0048e85c129f23281d9c0634e7010 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 30 Nov 2011 14:55:28 -0200 Subject: [media] tm6000: Use a 16 scancode bitmask for IR This should allow using 24 or 32 bits NEC IR decoding tables with those devices. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tm6000/tm6000-input.c b/drivers/media/video/tm6000/tm6000-input.c index 6eaf770..e3467d4 100644 --- a/drivers/media/video/tm6000/tm6000-input.c +++ b/drivers/media/video/tm6000/tm6000-input.c @@ -416,6 +416,8 @@ int tm6000_ir_init(struct tm6000_core *dev) /* input setup */ rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC; + /* Neded, in order to support NEC remotes with 24 or 32 bits */ + rc->scanmask = 0xffff; rc->priv = ir; rc->change_protocol = tm6000_ir_change_protocol; if (&dev->int_in) { -- cgit v0.10.2 From 6740a932882f43056b8545e5b0b85511975d0a7c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 30 Nov 2011 14:54:05 -0300 Subject: [media] tm6000: automatically load alsa and dvb modules All devices should support alsa module. Devices with DVB will auto-load the dvb module. This way, tm6000-based devices should now have hot plugin. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tm6000/tm6000-cards.c b/drivers/media/video/tm6000/tm6000-cards.c index 3873ce4..6b74259 100644 --- a/drivers/media/video/tm6000/tm6000-cards.c +++ b/drivers/media/video/tm6000/tm6000-cards.c @@ -1052,6 +1052,33 @@ static void use_alternative_detection_method(struct tm6000_core *dev) tm6000_boards[model].name, model); } +#if defined(CONFIG_MODULES) && defined(MODULE) +static void request_module_async(struct work_struct *work) +{ + struct tm6000_core *dev = container_of(work, struct tm6000_core, + request_module_wk); + + request_module("tm6000-alsa"); + + if (dev->caps.has_dvb) + request_module("tm6000-dvb"); +} + +static void request_modules(struct tm6000_core *dev) +{ + INIT_WORK(&dev->request_module_wk, request_module_async); + schedule_work(&dev->request_module_wk); +} + +static void flush_request_modules(struct tm6000_core *dev) +{ + flush_work_sync(&dev->request_module_wk); +} +#else +#define request_modules(dev) +#define flush_request_modules(dev) +#endif /* CONFIG_MODULES */ + static int tm6000_init_dev(struct tm6000_core *dev) { struct v4l2_frequency f; @@ -1114,6 +1141,8 @@ static int tm6000_init_dev(struct tm6000_core *dev) tm6000_ir_init(dev); + request_modules(dev); + mutex_unlock(&dev->lock); return 0; @@ -1326,6 +1355,8 @@ static void tm6000_usb_disconnect(struct usb_interface *interface) printk(KERN_INFO "tm6000: disconnecting %s\n", dev->name); + flush_request_modules(dev); + tm6000_ir_fini(dev); if (dev->gpio.power_led) { diff --git a/drivers/media/video/tm6000/tm6000.h b/drivers/media/video/tm6000/tm6000.h index 2777e51..27ba659 100644 --- a/drivers/media/video/tm6000/tm6000.h +++ b/drivers/media/video/tm6000/tm6000.h @@ -188,6 +188,9 @@ struct tm6000_core { /* Device Capabilities*/ struct tm6000_capabilities caps; + /* Used to load alsa/dvb */ + struct work_struct request_module_wk; + /* Tuner configuration */ int tuner_type; /* type of the tuner */ int tuner_addr; /* tuner address */ -- cgit v0.10.2 From 2a887d27708a4f9f3b5ad8258f9e19a150b58f03 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 30 Nov 2011 14:57:28 -0300 Subject: [media] tm6000: fix OOPS at tm6000_ir_int_stop() and tm6000_ir_int_start() [ 3755.608233] BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 [ 3755.616360] IP: [] tm6000_ir_int_stop+0x10/0x1b [tm6000] Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tm6000/tm6000-input.c b/drivers/media/video/tm6000/tm6000-input.c index e3467d4..af4bcf5 100644 --- a/drivers/media/video/tm6000/tm6000-input.c +++ b/drivers/media/video/tm6000/tm6000-input.c @@ -377,6 +377,9 @@ int tm6000_ir_int_start(struct tm6000_core *dev) { struct tm6000_IR *ir = dev->ir; + if (!ir) + return; + return __tm6000_ir_int_start(ir->rc); } @@ -384,6 +387,9 @@ void tm6000_ir_int_stop(struct tm6000_core *dev) { struct tm6000_IR *ir = dev->ir; + if (!ir || !ir->rc) + return; + __tm6000_ir_int_stop(ir->rc); } -- cgit v0.10.2 From a47161a55e40203e5dae6d04df3b159551377365 Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Sun, 20 Nov 2011 19:15:39 +0100 Subject: OMAPDSS: add FocalTech ETM070003DH6 display support Add data for the FocalTech ETM070003DH6 display to the generic_dpi_panel display driver. Signed-off-by: Ilya Yanok Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c index 519c47d..593f831 100644 --- a/drivers/video/omap2/displays/panel-generic-dpi.c +++ b/drivers/video/omap2/displays/panel-generic-dpi.c @@ -297,6 +297,26 @@ static struct panel_config generic_dpi_panels[] = { .name = "apollon", }, + /* FocalTech ETM070003DH6 */ + { + { + .x_res = 800, + .y_res = 480, + + .pixel_clock = 28000, + + .hsw = 48, + .hfp = 40, + .hbp = 40, + + .vsw = 3, + .vfp = 13, + .vbp = 29, + }, + .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | + OMAP_DSS_LCD_IHS, + .name = "focaltech_etm070003dh6", + }, }; struct panel_drv_data { -- cgit v0.10.2 From a702c85906390282e2aabb6cb30e448e23ee1599 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 12 Oct 2011 10:10:21 +0300 Subject: OMAPDSS: DSI: flush posted write when entering ULPS Flush posted write between writing the ULPS enable bits and waiting for the interrupt. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 5abf8e7e..1331f92 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -3561,6 +3561,9 @@ static int dsi_enter_ulps(struct platform_device *dsidev) REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (1 << 0) | (1 << 1) | (1 << 2), 7, 5); + /* flush posted write and wait for SCP interface to finish the write */ + dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2); + if (wait_for_completion_timeout(&completion, msecs_to_jiffies(1000)) == 0) { DSSERR("ULPS enable timeout\n"); @@ -3575,6 +3578,9 @@ static int dsi_enter_ulps(struct platform_device *dsidev) REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2), 7, 5); + /* flush posted write and wait for SCP interface to finish the write */ + dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2); + dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS); dsi_if_enable(dsidev, false); -- cgit v0.10.2 From 968f8e97a3291a3c7c9a2dee1a85a092de638f65 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 12 Oct 2011 10:13:14 +0300 Subject: OMAPDSS: DSI: flush posted write in send_bta Flush posted write after setting the bit to send the BTA to ensure the BTA is sent right away, as the code in dsi_vc_send_bta_sync() waits for an interrupt caused indirectly by sending the BTA. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 1331f92..4b1c074 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -2913,6 +2913,9 @@ static int dsi_vc_send_bta(struct platform_device *dsidev, int channel) REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */ + /* flush posted write */ + dsi_read_reg(dsidev, DSI_VC_CTRL(channel)); + return 0; } -- cgit v0.10.2 From b6a44e7748527d01b0c2f9a67686babaf0a5e53b Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 12 Oct 2011 10:17:02 +0300 Subject: OMAPDSS: DISPC: Flush posted writes when enabling outputs Flush posted write in _enable_lcd_out() and _enable_digit_out(). This ensures the the lcd/digit bit is written before the code starts waiting for interrupts about enabling/disabling the output. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 5c81533..5bbd838 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1916,10 +1916,14 @@ static void dispc_disable_isr(void *data, u32 mask) static void _enable_lcd_out(enum omap_channel channel, bool enable) { - if (channel == OMAP_DSS_CHANNEL_LCD2) + if (channel == OMAP_DSS_CHANNEL_LCD2) { REG_FLD_MOD(DISPC_CONTROL2, enable ? 1 : 0, 0, 0); - else + /* flush posted write */ + dispc_read_reg(DISPC_CONTROL2); + } else { REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); + dispc_read_reg(DISPC_CONTROL); + } } static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable) @@ -1967,6 +1971,8 @@ static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable) static void _enable_digit_out(bool enable) { REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1); + /* flush posted write */ + dispc_read_reg(DISPC_CONTROL); } static void dispc_mgr_enable_digit_out(bool enable) -- cgit v0.10.2 From d982085050e67da24a57ec04eb3701eb4805118a Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 12 Oct 2011 15:05:59 +0300 Subject: OMAPDSS: DSI: count with number of lanes DSI driver currently counts used lanes and number of supported lanes by using the number of data lanes (i.e. excluding clock lane). This patch changes this to use the number of all lanes so that the following lane config patches are cleaner. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 4b1c074..6a110b2 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -327,7 +327,7 @@ struct dsi_data { unsigned long fint_min, fint_max; unsigned long lpdiv_max; - int num_data_lanes; + unsigned num_lanes_supported; unsigned scp_clk_refcount; }; @@ -2029,19 +2029,8 @@ static int dsi_cio_power(struct platform_device *dsidev, return 0; } -/* Number of data lanes present on DSI interface */ -static inline int dsi_get_num_data_lanes(struct platform_device *dsidev) -{ - /* DSI on OMAP3 doesn't have register DSI_GNQ, set number - * of data lanes as 2 by default */ - if (dss_has_feature(FEAT_DSI_GNQ)) - return REG_GET(dsidev, DSI_GNQ, 11, 9); /* NB_DATA_LANES */ - else - return 2; -} - -/* Number of data lanes used by the dss device */ -static inline int dsi_get_num_data_lanes_dssdev(struct omap_dss_device *dssdev) +/* Number of lanes used by the dss device */ +static inline int dsi_get_num_lanes_used(struct omap_dss_device *dssdev) { int num_data_lanes = 0; @@ -2054,7 +2043,7 @@ static inline int dsi_get_num_data_lanes_dssdev(struct omap_dss_device *dssdev) if (dssdev->phy.dsi.data4_lane != 0) num_data_lanes++; - return num_data_lanes; + return num_data_lanes + 1; } static unsigned dsi_get_line_buf_size(struct platform_device *dsidev) @@ -2092,7 +2081,7 @@ static void dsi_set_lane_config(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); u32 r; - int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev); + int num_lanes_used = dsi_get_num_lanes_used(dssdev); int clk_lane = dssdev->phy.dsi.clk_lane; int data1_lane = dssdev->phy.dsi.data1_lane; @@ -2108,14 +2097,14 @@ static void dsi_set_lane_config(struct omap_dss_device *dssdev) r = FLD_MOD(r, data1_pol, 7, 7); r = FLD_MOD(r, data2_lane, 10, 8); r = FLD_MOD(r, data2_pol, 11, 11); - if (num_data_lanes_dssdev > 2) { + if (num_lanes_used > 3) { int data3_lane = dssdev->phy.dsi.data3_lane; int data3_pol = dssdev->phy.dsi.data3_pol; r = FLD_MOD(r, data3_lane, 14, 12); r = FLD_MOD(r, data3_pol, 15, 15); } - if (num_data_lanes_dssdev > 3) { + if (num_lanes_used > 4) { int data4_lane = dssdev->phy.dsi.data4_lane; int data4_pol = dssdev->phy.dsi.data4_pol; @@ -2247,7 +2236,7 @@ static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev, int data4_pol = dssdev->phy.dsi.data4_pol; u32 l = 0; - u8 lptxscp_start = dsi->num_data_lanes == 2 ? 22 : 26; + u8 lptxscp_start = dsi->num_lanes_supported == 3 ? 22 : 26; if (lanes & DSI_CLK_P) l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 0 : 1)); @@ -2385,7 +2374,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); int r; - int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev); + int num_lanes_used = dsi_get_num_lanes_used(dssdev); u32 l; DSSDBGF(); @@ -2430,10 +2419,10 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) * manually. */ - if (num_data_lanes_dssdev > 2) + if (num_lanes_used > 3) lane_mask |= DSI_DATA3_P; - if (num_data_lanes_dssdev > 3) + if (num_lanes_used > 4) lane_mask |= DSI_DATA4_P; dsi_cio_enable_lane_override(dssdev, lane_mask); @@ -3852,7 +3841,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) unsigned ddr_clk_pre, ddr_clk_post; unsigned enter_hs_mode_lat, exit_hs_mode_lat; unsigned ths_eot; - int ndl = dsi_get_num_data_lanes_dssdev(dssdev); + int ndl = dsi_get_num_lanes_used(dssdev) - 1; u32 r; r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); @@ -4552,9 +4541,9 @@ int dsi_init_display(struct omap_dss_device *dssdev) dsi->vdds_dsi_reg = vdds_dsi; } - if (dsi_get_num_data_lanes_dssdev(dssdev) > dsi->num_data_lanes) { - DSSERR("DSI%d can't support more than %d data lanes\n", - dsi_module + 1, dsi->num_data_lanes); + if (dsi_get_num_lanes_used(dssdev) > dsi->num_lanes_supported) { + DSSERR("DSI%d can't support more than %d lanes\n", + dsi_module + 1, dsi->num_lanes_supported); return -EINVAL; } @@ -4780,7 +4769,13 @@ static int omap_dsihw_probe(struct platform_device *dsidev) dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); - dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev); + /* DSI on OMAP3 doesn't have register DSI_GNQ, set number + * of data to 3 by default */ + if (dss_has_feature(FEAT_DSI_GNQ)) + /* NB_DATA_LANES */ + dsi->num_lanes_supported = 1 + REG_GET(dsidev, DSI_GNQ, 11, 9); + else + dsi->num_lanes_supported = 3; dsi_runtime_put(dsidev); -- cgit v0.10.2 From 739a7f46cbf6dc3d4f899e4b566196d99403457a Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 13 Oct 2011 11:22:06 +0300 Subject: OMAPDSS: DSI: Parse lane config Parse the lane configuration from the device data into internal lane config format. This will be used in the following patches to clean up the lane handling. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 6a110b2..aea110c 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -203,6 +203,21 @@ struct dsi_reg { u16 idx; }; typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); #define DSI_MAX_NR_ISRS 2 +#define DSI_MAX_NR_LANES 5 + +enum dsi_lane_function { + DSI_LANE_UNUSED = 0, + DSI_LANE_CLK, + DSI_LANE_DATA1, + DSI_LANE_DATA2, + DSI_LANE_DATA3, + DSI_LANE_DATA4, +}; + +struct dsi_lane_config { + enum dsi_lane_function function; + u8 polarity; +}; struct dsi_isr_data { omap_dsi_isr_t isr; @@ -329,6 +344,9 @@ struct dsi_data { unsigned num_lanes_supported; + struct dsi_lane_config lanes[DSI_MAX_NR_LANES]; + unsigned num_lanes_used; + unsigned scp_clk_refcount; }; @@ -2077,6 +2095,65 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev) } } +static int dsi_parse_lane_config(struct omap_dss_device *dssdev) +{ + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + u8 lanes[DSI_MAX_NR_LANES]; + u8 polarities[DSI_MAX_NR_LANES]; + int num_lanes, i; + + static const enum dsi_lane_function functions[] = { + DSI_LANE_CLK, + DSI_LANE_DATA1, + DSI_LANE_DATA2, + DSI_LANE_DATA3, + DSI_LANE_DATA4, + }; + + lanes[0] = dssdev->phy.dsi.clk_lane; + lanes[1] = dssdev->phy.dsi.data1_lane; + lanes[2] = dssdev->phy.dsi.data2_lane; + lanes[3] = dssdev->phy.dsi.data3_lane; + lanes[4] = dssdev->phy.dsi.data4_lane; + polarities[0] = dssdev->phy.dsi.clk_pol; + polarities[1] = dssdev->phy.dsi.data1_pol; + polarities[2] = dssdev->phy.dsi.data2_pol; + polarities[3] = dssdev->phy.dsi.data3_pol; + polarities[4] = dssdev->phy.dsi.data4_pol; + + num_lanes = 0; + + for (i = 0; i < dsi->num_lanes_supported; ++i) + dsi->lanes[i].function = DSI_LANE_UNUSED; + + for (i = 0; i < dsi->num_lanes_supported; ++i) { + int num; + + if (lanes[i] == DSI_LANE_UNUSED) + break; + + num = lanes[i] - 1; + + if (num >= dsi->num_lanes_supported) + return -EINVAL; + + if (dsi->lanes[num].function != DSI_LANE_UNUSED) + return -EINVAL; + + dsi->lanes[num].function = functions[i]; + dsi->lanes[num].polarity = polarities[i]; + num_lanes++; + } + + if (num_lanes < 2 || num_lanes > dsi->num_lanes_supported) + return -EINVAL; + + dsi->num_lanes_used = num_lanes; + + return 0; +} + static void dsi_set_lane_config(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); @@ -4328,6 +4405,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) int dsi_module = dsi_get_dsidev_id(dsidev); int r; + r = dsi_parse_lane_config(dssdev); + if (r) { + DSSERR("illegal lane config"); + goto err0; + } + r = dsi_pll_init(dsidev, true, true); if (r) goto err0; -- cgit v0.10.2 From 48368395f670ac8cc60288674de940a38693412e Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 13 Oct 2011 11:22:39 +0300 Subject: OMAPDSS: DSI: Use new lane config in dsi_set_lane_config Use the new lane config in dsi_set_lane_config(). Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index aea110c..ba8d6b3 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -2154,59 +2154,53 @@ static int dsi_parse_lane_config(struct omap_dss_device *dssdev) return 0; } -static void dsi_set_lane_config(struct omap_dss_device *dssdev) +static int dsi_set_lane_config(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + static const u8 offsets[] = { 0, 4, 8, 12, 16 }; + static const enum dsi_lane_function functions[] = { + DSI_LANE_CLK, + DSI_LANE_DATA1, + DSI_LANE_DATA2, + DSI_LANE_DATA3, + DSI_LANE_DATA4, + }; u32 r; - int num_lanes_used = dsi_get_num_lanes_used(dssdev); - - int clk_lane = dssdev->phy.dsi.clk_lane; - int data1_lane = dssdev->phy.dsi.data1_lane; - int data2_lane = dssdev->phy.dsi.data2_lane; - int clk_pol = dssdev->phy.dsi.clk_pol; - int data1_pol = dssdev->phy.dsi.data1_pol; - int data2_pol = dssdev->phy.dsi.data2_pol; + int i; r = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1); - r = FLD_MOD(r, clk_lane, 2, 0); - r = FLD_MOD(r, clk_pol, 3, 3); - r = FLD_MOD(r, data1_lane, 6, 4); - r = FLD_MOD(r, data1_pol, 7, 7); - r = FLD_MOD(r, data2_lane, 10, 8); - r = FLD_MOD(r, data2_pol, 11, 11); - if (num_lanes_used > 3) { - int data3_lane = dssdev->phy.dsi.data3_lane; - int data3_pol = dssdev->phy.dsi.data3_pol; - - r = FLD_MOD(r, data3_lane, 14, 12); - r = FLD_MOD(r, data3_pol, 15, 15); + + for (i = 0; i < dsi->num_lanes_used; ++i) { + unsigned offset = offsets[i]; + unsigned polarity, lane_number; + unsigned t; + + for (t = 0; t < dsi->num_lanes_supported; ++t) + if (dsi->lanes[t].function == functions[i]) + break; + + if (t == dsi->num_lanes_supported) + return -EINVAL; + + lane_number = t; + polarity = dsi->lanes[t].polarity; + + r = FLD_MOD(r, lane_number + 1, offset + 2, offset); + r = FLD_MOD(r, polarity, offset + 3, offset + 3); } - if (num_lanes_used > 4) { - int data4_lane = dssdev->phy.dsi.data4_lane; - int data4_pol = dssdev->phy.dsi.data4_pol; - r = FLD_MOD(r, data4_lane, 18, 16); - r = FLD_MOD(r, data4_pol, 19, 19); + /* clear the unused lanes */ + for (; i < dsi->num_lanes_supported; ++i) { + unsigned offset = offsets[i]; + + r = FLD_MOD(r, 0, offset + 2, offset); + r = FLD_MOD(r, 0, offset + 3, offset + 3); } - dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r); - /* The configuration of the DSI complex I/O (number of data lanes, - position, differential order) should not be changed while - DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for - the hardware to take into account a new configuration of the complex - I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to - follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, - then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set - DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the - DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the - DSI complex I/O configuration is unknown. */ + dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r); - /* - REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0); - REG_FLD_MOD(dsidev, DSI_CTRL, 0, 0, 0); - REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); - REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0); - */ + return 0; } static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns) @@ -2473,7 +2467,9 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) goto err_scp_clk_dom; } - dsi_set_lane_config(dssdev); + r = dsi_set_lane_config(dssdev); + if (r) + goto err_scp_clk_dom; /* set TX STOP MODE timer to maximum for this operation */ l = dsi_read_reg(dsidev, DSI_TIMING1); -- cgit v0.10.2 From 85f17e8e2c8d5f9266ca28f05cbc57598eddb05a Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 13 Oct 2011 15:12:23 +0300 Subject: OMAPDSS: DSI: use lane config in dsi_get_lane_mask Use the new lane config in dsi_get_lane_mask(). Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index ba8d6b3..1a209a2 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -2422,22 +2422,20 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) return 0; } +/* return bitmask of enabled lanes, lane0 being the lsb */ static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev) { - unsigned lanes = 0; + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + unsigned mask = 0; + int i; - if (dssdev->phy.dsi.clk_lane != 0) - lanes |= 1 << (dssdev->phy.dsi.clk_lane - 1); - if (dssdev->phy.dsi.data1_lane != 0) - lanes |= 1 << (dssdev->phy.dsi.data1_lane - 1); - if (dssdev->phy.dsi.data2_lane != 0) - lanes |= 1 << (dssdev->phy.dsi.data2_lane - 1); - if (dssdev->phy.dsi.data3_lane != 0) - lanes |= 1 << (dssdev->phy.dsi.data3_lane - 1); - if (dssdev->phy.dsi.data4_lane != 0) - lanes |= 1 << (dssdev->phy.dsi.data4_lane - 1); + for (i = 0; i < dsi->num_lanes_supported; ++i) { + if (dsi->lanes[i].function != DSI_LANE_UNUSED) + mask |= 1 << i; + } - return lanes; + return mask; } static int dsi_cio_init(struct omap_dss_device *dssdev) -- cgit v0.10.2 From 8dc0766fcf3b84ec83aa601acabf21f2c98ca253 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 13 Oct 2011 15:26:50 +0300 Subject: OMAPDSS: DSI: use lane config in dsi_cio_wait_tx_clk_esc_reset Use the new lane config in dsi_cio_wait_tx_clk_esc_reset(). This also extends the function to support 5 lanes on OMAP4, instead of 3 lanes. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 1a209a2..52cf97f 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -2365,51 +2365,40 @@ static void dsi_cio_disable_lane_override(struct platform_device *dsidev) static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); - int t; - int bits[3]; - bool in_use[3]; - - if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) { - bits[0] = 28; - bits[1] = 27; - bits[2] = 26; - } else { - bits[0] = 24; - bits[1] = 25; - bits[2] = 26; - } - - in_use[0] = false; - in_use[1] = false; - in_use[2] = false; + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + int t, i; + bool in_use[DSI_MAX_NR_LANES]; + static const u8 offsets_old[] = { 28, 27, 26 }; + static const u8 offsets_new[] = { 24, 25, 26, 27, 28 }; + const u8 *offsets; + + if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) + offsets = offsets_old; + else + offsets = offsets_new; - if (dssdev->phy.dsi.clk_lane != 0) - in_use[dssdev->phy.dsi.clk_lane - 1] = true; - if (dssdev->phy.dsi.data1_lane != 0) - in_use[dssdev->phy.dsi.data1_lane - 1] = true; - if (dssdev->phy.dsi.data2_lane != 0) - in_use[dssdev->phy.dsi.data2_lane - 1] = true; + for (i = 0; i < dsi->num_lanes_supported; ++i) + in_use[i] = dsi->lanes[i].function != DSI_LANE_UNUSED; t = 100000; while (true) { u32 l; - int i; int ok; l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); ok = 0; - for (i = 0; i < 3; ++i) { - if (!in_use[i] || (l & (1 << bits[i]))) + for (i = 0; i < dsi->num_lanes_supported; ++i) { + if (!in_use[i] || (l & (1 << offsets[i]))) ok++; } - if (ok == 3) + if (ok == dsi->num_lanes_supported) break; if (--t == 0) { - for (i = 0; i < 3; ++i) { - if (!in_use[i] || (l & (1 << bits[i]))) + for (i = 0; i < dsi->num_lanes_supported; ++i) { + if (!in_use[i] || (l & (1 << offsets[i]))) continue; DSSERR("CIO TXCLKESC%d domain not coming " \ -- cgit v0.10.2 From 9b4362f2b5ad6d0cf6b5754000b8db80d0592e89 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 13 Oct 2011 16:06:43 +0300 Subject: OMAPDSS: DSI: use lane config in dsi_cio_enable_lane_override Use the new lane config in dsi_cio_enable_lane_override(). The function parameters are also slightly changed. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 52cf97f..dee9525 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -238,19 +238,6 @@ enum dsi_vc_source { DSI_VC_SOURCE_VP, }; -enum dsi_lane { - DSI_CLK_P = 1 << 0, - DSI_CLK_N = 1 << 1, - DSI_DATA1_P = 1 << 2, - DSI_DATA1_N = 1 << 3, - DSI_DATA2_P = 1 << 4, - DSI_DATA2_N = 1 << 5, - DSI_DATA3_P = 1 << 6, - DSI_DATA3_N = 1 << 7, - DSI_DATA4_P = 1 << 8, - DSI_DATA4_N = 1 << 9, -}; - struct dsi_update_region { u16 x, y, w, h; struct omap_dss_device *device; @@ -2290,49 +2277,28 @@ static void dsi_cio_timings(struct platform_device *dsidev) dsi_write_reg(dsidev, DSI_DSIPHY_CFG2, r); } +/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */ static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev, - enum dsi_lane lanes) + unsigned mask_p, unsigned mask_n) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - int clk_lane = dssdev->phy.dsi.clk_lane; - int data1_lane = dssdev->phy.dsi.data1_lane; - int data2_lane = dssdev->phy.dsi.data2_lane; - int data3_lane = dssdev->phy.dsi.data3_lane; - int data4_lane = dssdev->phy.dsi.data4_lane; - int clk_pol = dssdev->phy.dsi.clk_pol; - int data1_pol = dssdev->phy.dsi.data1_pol; - int data2_pol = dssdev->phy.dsi.data2_pol; - int data3_pol = dssdev->phy.dsi.data3_pol; - int data4_pol = dssdev->phy.dsi.data4_pol; - - u32 l = 0; + int i; + u32 l; u8 lptxscp_start = dsi->num_lanes_supported == 3 ? 22 : 26; - if (lanes & DSI_CLK_P) - l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 0 : 1)); - if (lanes & DSI_CLK_N) - l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 1 : 0)); - - if (lanes & DSI_DATA1_P) - l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 0 : 1)); - if (lanes & DSI_DATA1_N) - l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 1 : 0)); - - if (lanes & DSI_DATA2_P) - l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 0 : 1)); - if (lanes & DSI_DATA2_N) - l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 1 : 0)); - - if (lanes & DSI_DATA3_P) - l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 0 : 1)); - if (lanes & DSI_DATA3_N) - l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 1 : 0)); - - if (lanes & DSI_DATA4_P) - l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 0 : 1)); - if (lanes & DSI_DATA4_N) - l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 1 : 0)); + l = 0; + + for (i = 0; i < dsi->num_lanes_supported; ++i) { + unsigned p = dsi->lanes[i].polarity; + + if (mask_p & (1 << i)) + l |= 1 << (i * 2 + (p ? 0 : 1)); + + if (mask_n & (1 << i)) + l |= 1 << (i * 2 + (p ? 1 : 0)); + } + /* * Bits in REGLPTXSCPDAT4TO0DXDY: * 17: DY0 18: DX0 @@ -2432,7 +2398,6 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); int r; - int num_lanes_used = dsi_get_num_lanes_used(dssdev); u32 l; DSSDBGF(); @@ -2467,7 +2432,8 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) dsi_write_reg(dsidev, DSI_TIMING1, l); if (dsi->ulps_enabled) { - u32 lane_mask = DSI_CLK_P | DSI_DATA1_P | DSI_DATA2_P; + unsigned mask_p; + int i; DSSDBG("manual ulps exit\n"); @@ -2476,16 +2442,19 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) * ULPS exit sequence, as after reset the DSS HW thinks * that we are not in ULPS mode, and refuses to send the * sequence. So we need to send the ULPS exit sequence - * manually. + * manually by setting positive lines high and negative lines + * low for 1ms. */ - if (num_lanes_used > 3) - lane_mask |= DSI_DATA3_P; + mask_p = 0; - if (num_lanes_used > 4) - lane_mask |= DSI_DATA4_P; + for (i = 0; i < dsi->num_lanes_supported; ++i) { + if (dsi->lanes[i].function == DSI_LANE_UNUSED) + continue; + mask_p |= 1 << i; + } - dsi_cio_enable_lane_override(dssdev, lane_mask); + dsi_cio_enable_lane_override(dssdev, mask_p, 0); } r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON); -- cgit v0.10.2 From db18644f90e664bf30f58cf9b8bc879598bff62f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 13 Oct 2011 16:12:29 +0300 Subject: OMAPDSS: DSI: remove dsi_get_num_lanes_used There's no longer need for the dsi_get_num_lanes_used function, so it can be removed. The lane check in dsi_init_display() can be removed as the validity of the config will be verified when parsing it. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index dee9525..2b375c6 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -2034,23 +2034,6 @@ static int dsi_cio_power(struct platform_device *dsidev, return 0; } -/* Number of lanes used by the dss device */ -static inline int dsi_get_num_lanes_used(struct omap_dss_device *dssdev) -{ - int num_data_lanes = 0; - - if (dssdev->phy.dsi.data1_lane != 0) - num_data_lanes++; - if (dssdev->phy.dsi.data2_lane != 0) - num_data_lanes++; - if (dssdev->phy.dsi.data3_lane != 0) - num_data_lanes++; - if (dssdev->phy.dsi.data4_lane != 0) - num_data_lanes++; - - return num_data_lanes + 1; -} - static unsigned dsi_get_line_buf_size(struct platform_device *dsidev) { int val; @@ -3863,6 +3846,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) static void dsi_proto_timings(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail; unsigned tclk_pre, tclk_post; unsigned ths_prepare, ths_prepare_ths_zero, ths_zero; @@ -3870,7 +3854,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) unsigned ddr_clk_pre, ddr_clk_post; unsigned enter_hs_mode_lat, exit_hs_mode_lat; unsigned ths_eot; - int ndl = dsi_get_num_lanes_used(dssdev) - 1; + int ndl = dsi->num_lanes_used - 1; u32 r; r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); @@ -4554,7 +4538,6 @@ int dsi_init_display(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - int dsi_module = dsi_get_dsidev_id(dsidev); DSSDBG("DSI init\n"); @@ -4576,12 +4559,6 @@ int dsi_init_display(struct omap_dss_device *dssdev) dsi->vdds_dsi_reg = vdds_dsi; } - if (dsi_get_num_lanes_used(dssdev) > dsi->num_lanes_supported) { - DSSERR("DSI%d can't support more than %d lanes\n", - dsi_module + 1, dsi->num_lanes_supported); - return -EINVAL; - } - return 0; } -- cgit v0.10.2 From 522a0c2fe58fb6eb145cce07a303857b08322a2b Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 13 Oct 2011 16:18:52 +0300 Subject: OMAPDSS: DSI: fix lane handling when entering ULPS The current code always enters ULPS for 3 lanes. This is not right, as there could be only 2 lanes used, and on OMAP4 we have 5 lanes. Fix the code to put all used lanes into ULPS. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 2b375c6..22055db 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -3517,7 +3517,8 @@ static int dsi_enter_ulps(struct platform_device *dsidev) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); DECLARE_COMPLETION_ONSTACK(completion); - int r; + int r, i; + unsigned mask; DSSDBGF(); @@ -3560,10 +3561,16 @@ static int dsi_enter_ulps(struct platform_device *dsidev) if (r) return r; + mask = 0; + + for (i = 0; i < dsi->num_lanes_supported; ++i) { + if (dsi->lanes[i].function == DSI_LANE_UNUSED) + continue; + mask |= 1 << i; + } /* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */ /* LANEx_ULPS_SIG2 */ - REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (1 << 0) | (1 << 1) | (1 << 2), - 7, 5); + REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, mask, 9, 5); /* flush posted write and wait for SCP interface to finish the write */ dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2); @@ -3579,8 +3586,7 @@ static int dsi_enter_ulps(struct platform_device *dsidev) DSI_CIO_IRQ_ULPSACTIVENOT_ALL0); /* Reset LANEx_ULPS_SIG2 */ - REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2), - 7, 5); + REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, 0, 9, 5); /* flush posted write and wait for SCP interface to finish the write */ dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2); -- cgit v0.10.2 From 3b98409eb7508ce534243312c3a9ac8543c06808 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 13 Oct 2011 19:06:49 +0300 Subject: OMAPDSS: DSI: improve wait_for_bit_change We sometimes get timeout when disabling the DSI interface with video mode. It looks like the disable will stall until the current frame has been finished, and this can take multiple milliseconds. wait_for_bit_change() currently uses a busyloop to wait for a bit to change. This is used in multiple places. The problem is, we don't have clear understanding how long particular operations can take, so the function needs to support longer waits. Improve wait_for_bit_change() to first busy loop for 100 times to see if the bit changes almost right away. If the bit hasn't changed, move to a loop with a sleep of 1ms, and poll for 500ms. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 22055db..a01a011 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -418,14 +418,29 @@ static void dsi_completion_handler(void *data, u32 mask) static inline int wait_for_bit_change(struct platform_device *dsidev, const struct dsi_reg idx, int bitnum, int value) { - int t = 100000; + unsigned long timeout; + ktime_t wait; + int t; + + /* first busyloop to see if the bit changes right away */ + t = 100; + while (t-- > 0) { + if (REG_GET(dsidev, idx, bitnum, bitnum) == value) + return value; + } + + /* then loop for 500ms, sleeping for 1ms in between */ + timeout = jiffies + msecs_to_jiffies(500); + while (time_before(jiffies, timeout)) { + if (REG_GET(dsidev, idx, bitnum, bitnum) == value) + return value; - while (REG_GET(dsidev, idx, bitnum, bitnum) != value) { - if (--t == 0) - return !value; + wait = ns_to_ktime(1000 * 1000); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_hrtimeout(&wait, HRTIMER_MODE_REL); } - return value; + return !value; } u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) -- cgit v0.10.2 From 6cc78aa9843155c89faa93231332a8b3817020df Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 13 Oct 2011 19:22:43 +0300 Subject: OMAPDSS: DSI: disable DDR_CLK_ALWAYS_ON when entering ULPS ULPS cannot be entered if the DDR clk is enabled. Thus disable the DDR clk before entering ULPS. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index a01a011..9bcb5c2 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -3544,9 +3544,11 @@ static int dsi_enter_ulps(struct platform_device *dsidev) if (dsi->ulps_enabled) return 0; + /* DDR_CLK_ALWAYS_ON */ if (REG_GET(dsidev, DSI_CLK_CTRL, 13, 13)) { - DSSERR("DDR_CLK_ALWAYS_ON enabled when entering ULPS\n"); - return -EIO; + dsi_if_enable(dsidev, 0); + REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13); + dsi_if_enable(dsidev, 1); } dsi_sync_vc(dsidev, 0); -- cgit v0.10.2 From 8754595796a45e88411b68005bc98310c8c6ae76 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 15 Nov 2011 10:56:11 +0200 Subject: OMAPDSS: DISPC: add missing prototype dispc_mgr_is_enabled() was missing a prototype in dss.h Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 6308fc5..3310f10 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -414,6 +414,7 @@ void dispc_mgr_set_cpr_coef(enum omap_channel channel, struct omap_dss_cpr_coefs *coefs); bool dispc_mgr_go_busy(enum omap_channel channel); void dispc_mgr_go(enum omap_channel channel); +bool dispc_mgr_is_enabled(enum omap_channel channel); void dispc_mgr_enable(enum omap_channel channel, bool enable); bool dispc_mgr_is_channel_enabled(enum omap_channel channel); void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode); -- cgit v0.10.2 From 714ad3ac505bba711f961bb8013644c9d8fb486a Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 27 Oct 2011 13:11:31 +0300 Subject: OMAPDSS: Remove old fifomerge hacks Once in a time omapdss had basic support for fifomerge. Fifomerge was removed as the implementation didn't work properly, and a proper implementation is a complex problem. However, some unused fifo-merge related code was left behind. This patch removes those. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 6e63845..1be5f47 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -1313,8 +1313,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) struct manager_cache_data *mc; int i; struct omap_overlay *ovl; - int num_planes_enabled = 0; - bool use_fifomerge; unsigned long flags; int r; @@ -1347,11 +1345,8 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) continue; } - if (!ovl->info_dirty) { - if (oc->enabled) - ++num_planes_enabled; + if (!ovl->info_dirty) continue; - } dssdev = ovl->manager->device; @@ -1375,8 +1370,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) oc->channel = ovl->manager->id; oc->enabled = true; - - ++num_planes_enabled; } /* Configure managers */ @@ -1406,21 +1399,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; } - /* XXX TODO: Try to get fifomerge working. The problem is that it - * affects both managers, not individually but at the same time. This - * means the change has to be well synchronized. I guess the proper way - * is to have a two step process for fifo merge: - * fifomerge enable: - * 1. disable other planes, leaving one plane enabled - * 2. wait until the planes are disabled on HW - * 3. config merged fifo thresholds, enable fifomerge - * fifomerge disable: - * 1. config unmerged fifo thresholds, disable fifomerge - * 2. wait until fifo changes are in HW - * 3. enable planes - */ - use_fifomerge = false; - /* Configure overlay fifos */ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { struct omap_dss_device *dssdev; @@ -1436,8 +1414,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) dssdev = ovl->manager->device; size = dispc_ovl_get_fifo_size(ovl->id); - if (use_fifomerge) - size *= 3; burst_size = dispc_ovl_get_burst_size(ovl->id); -- cgit v0.10.2 From b952b553d23912b0b4a496b3e695db5e60c7a99a Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 31 Oct 2011 13:47:30 +0200 Subject: OMAPDSS: remove L4_EXAMPLE code Some old example code has been left lying around. Remove the example code. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 3310f10..7d2b6dd 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -192,9 +192,6 @@ void dss_init_overlays(struct platform_device *pdev); void dss_uninit_overlays(struct platform_device *pdev); int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev); void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); -#ifdef L4_EXAMPLE -void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr); -#endif void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); /* DSS */ diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index ab8e40e..d15b826 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -641,15 +641,6 @@ void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr) mgr->overlays = dispc_overlays; } -#ifdef L4_EXAMPLE -static struct omap_overlay *l4_overlays[1]; -void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr) -{ - mgr->num_overlays = 1; - mgr->overlays = l4_overlays; -} -#endif - void dss_init_overlays(struct platform_device *pdev) { int i, r; @@ -716,33 +707,6 @@ void dss_init_overlays(struct platform_device *pdev) dispc_overlays[i] = ovl; } - -#ifdef L4_EXAMPLE - { - struct omap_overlay *ovl; - ovl = kzalloc(sizeof(*ovl), GFP_KERNEL); - - BUG_ON(ovl == NULL); - - ovl->name = "l4"; - ovl->supported_modes = OMAP_DSS_COLOR_RGB24U; - - ovl->set_manager = &omap_dss_set_manager; - ovl->unset_manager = &omap_dss_unset_manager; - ovl->set_overlay_info = &dss_ovl_set_overlay_info; - ovl->get_overlay_info = &dss_ovl_get_overlay_info; - - omap_dss_add_overlay(ovl); - - r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, - &pdev->dev.kobj, "overlayl4"); - - if (r) - DSSERR("failed to create sysfs file\n"); - - l4_overlays[0] = ovl; - } -#endif } /* connect overlays to the new device, if not already connected. if force -- cgit v0.10.2 From f427984e896fde6ae03056cf1f8ac5d4a99275d4 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 28 Oct 2011 15:26:26 +0300 Subject: OMAPDSS: DISPC: make dispc_ovl_set_channel_out() public Make dispc_ovl_set_channel_out() public so that later patches can handle changing overlay's manager. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 5bbd838..5130f88 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -875,8 +875,7 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane, REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); } -static void dispc_ovl_set_channel_out(enum omap_plane plane, - enum omap_channel channel) +void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel) { int shift; u32 val; diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 7d2b6dd..f899f0f 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -402,6 +402,8 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, bool ilace, enum omap_channel channel, bool replication, u32 fifo_low, u32 fifo_high); int dispc_ovl_enable(enum omap_plane plane, bool enable); +void dispc_ovl_set_channel_out(enum omap_plane plane, + enum omap_channel channel); void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable); -- cgit v0.10.2 From 6f04e1bfc36c5865dc5679f85e25b6613be86298 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 31 Oct 2011 08:58:52 +0200 Subject: OMAPDSS: DISPC: make dispc_ovl_set_fifo_threshold() public Make dispc_ovl_set_fifo_threshold() public so that later patches can handle overlay fifo configuration. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 5130f88..8249731 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1056,8 +1056,7 @@ u32 dispc_ovl_get_fifo_size(enum omap_plane plane) return dispc.fifo_size[plane]; } -static void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, - u32 high) +void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) { u8 hi_start, hi_end, lo_start, lo_end; u32 unit; diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index f899f0f..313a7ca 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -396,6 +396,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, struct dispc_clock_info *cinfo); +void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); u32 dispc_ovl_get_fifo_size(enum omap_plane plane); u32 dispc_ovl_get_burst_size(enum omap_plane plane); int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, -- cgit v0.10.2 From 8760db5406fb7b92f900d6c98eea198695476467 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 3 Nov 2011 16:17:37 +0200 Subject: OMAPDSS: remove partial update from the overlay manager Partial update for manual update displays has never worked quite well: * The HW has limitations on the update area, and the x and width need to be even. * Showing a part of a scaled overlay causes artifacts. * Makes the management of dispc very complex Considering the above points and the fact that partial update is not used anywhere, this and the following patches remove the partial update support. This will greatly simplify the following re-write of the apply mechanism to get proper locking and additional features like fifo-merge. This patch removes the partial update from the manager.c. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 9bcb5c2..773a496 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -4206,8 +4206,6 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev, dsi_perf_mark_setup(dsidev); - dss_setup_partial_planes(dssdev, x, y, w, h, - enlarge_update_area); dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h); return 0; diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 313a7ca..7f6a612 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -182,9 +182,6 @@ void default_get_overlay_fifo_thresholds(enum omap_plane plane, int dss_init_overlay_managers(struct platform_device *pdev); void dss_uninit_overlay_managers(struct platform_device *pdev); int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl); -void dss_setup_partial_planes(struct omap_dss_device *dssdev, - u16 *x, u16 *y, u16 *w, u16 *h, - bool enlarge_update_area); void dss_start_update(struct omap_dss_device *dssdev); /* overlay */ diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 1be5f47..c616f85 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -530,13 +530,6 @@ struct manager_cache_data { bool manual_update; bool do_manual_update; - - /* manual update region */ - u16 x, y, w, h; - - /* enlarge the update area if the update area contains scaled - * overlays */ - bool enlarge_update_area; }; static struct { @@ -762,65 +755,11 @@ static int overlay_enabled(struct omap_overlay *ovl) return ovl->info.enabled && ovl->manager && ovl->manager->device; } -/* Is rect1 a subset of rect2? */ -static bool rectangle_subset(int x1, int y1, int w1, int h1, - int x2, int y2, int w2, int h2) -{ - if (x1 < x2 || y1 < y2) - return false; - - if (x1 + w1 > x2 + w2) - return false; - - if (y1 + h1 > y2 + h2) - return false; - - return true; -} - -/* Do rect1 and rect2 overlap? */ -static bool rectangle_intersects(int x1, int y1, int w1, int h1, - int x2, int y2, int w2, int h2) -{ - if (x1 >= x2 + w2) - return false; - - if (x2 >= x1 + w1) - return false; - - if (y1 >= y2 + h2) - return false; - - if (y2 >= y1 + h1) - return false; - - return true; -} - -static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc) -{ - struct omap_overlay_info *oi = &oc->info; - - if (oi->out_width != 0 && oi->width != oi->out_width) - return true; - - if (oi->out_height != 0 && oi->height != oi->out_height) - return true; - - return false; -} - static int configure_overlay(enum omap_plane plane) { struct overlay_cache_data *c; - struct manager_cache_data *mc; - struct omap_overlay_info *oi, new_oi; - struct omap_overlay_manager_info *mi; - u16 outw, outh; - u16 x, y, w, h; - u32 paddr; + struct omap_overlay_info *oi; int r; - u16 orig_w, orig_h, orig_outw, orig_outh; DSSDBGF("%d", plane); @@ -832,120 +771,7 @@ static int configure_overlay(enum omap_plane plane) return 0; } - mc = &dss_cache.manager_cache[c->channel]; - mi = &mc->info; - - x = oi->pos_x; - y = oi->pos_y; - w = oi->width; - h = oi->height; - outw = oi->out_width == 0 ? oi->width : oi->out_width; - outh = oi->out_height == 0 ? oi->height : oi->out_height; - paddr = oi->paddr; - - orig_w = w; - orig_h = h; - orig_outw = outw; - orig_outh = outh; - - if (mc->manual_update && mc->do_manual_update) { - unsigned bpp; - unsigned scale_x_m = w, scale_x_d = outw; - unsigned scale_y_m = h, scale_y_d = outh; - - /* If the overlay is outside the update region, disable it */ - if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h, - x, y, outw, outh)) { - dispc_ovl_enable(plane, 0); - return 0; - } - - switch (oi->color_mode) { - case OMAP_DSS_COLOR_NV12: - bpp = 8; - break; - case OMAP_DSS_COLOR_RGB16: - case OMAP_DSS_COLOR_ARGB16: - case OMAP_DSS_COLOR_YUV2: - case OMAP_DSS_COLOR_UYVY: - case OMAP_DSS_COLOR_RGBA16: - case OMAP_DSS_COLOR_RGBX16: - case OMAP_DSS_COLOR_ARGB16_1555: - case OMAP_DSS_COLOR_XRGB16_1555: - bpp = 16; - break; - - case OMAP_DSS_COLOR_RGB24P: - bpp = 24; - break; - - case OMAP_DSS_COLOR_RGB24U: - case OMAP_DSS_COLOR_ARGB32: - case OMAP_DSS_COLOR_RGBA32: - case OMAP_DSS_COLOR_RGBX32: - bpp = 32; - break; - - default: - BUG(); - } - - if (mc->x > oi->pos_x) { - x = 0; - outw -= (mc->x - oi->pos_x); - paddr += (mc->x - oi->pos_x) * - scale_x_m / scale_x_d * bpp / 8; - } else { - x = oi->pos_x - mc->x; - } - - if (mc->y > oi->pos_y) { - y = 0; - outh -= (mc->y - oi->pos_y); - paddr += (mc->y - oi->pos_y) * - scale_y_m / scale_y_d * - oi->screen_width * bpp / 8; - } else { - y = oi->pos_y - mc->y; - } - - if (mc->w < (x + outw)) - outw -= (x + outw) - (mc->w); - - if (mc->h < (y + outh)) - outh -= (y + outh) - (mc->h); - - w = w * outw / orig_outw; - h = h * outh / orig_outh; - - /* YUV mode overlay's input width has to be even and the - * algorithm above may adjust the width to be odd. - * - * Here we adjust the width if needed, preferring to increase - * the width if the original width was bigger. - */ - if ((w & 1) && - (oi->color_mode == OMAP_DSS_COLOR_YUV2 || - oi->color_mode == OMAP_DSS_COLOR_UYVY)) { - if (orig_w > w) - w += 1; - else - w -= 1; - } - } - - new_oi = *oi; - - /* update new_oi members which could have been possibly updated */ - new_oi.pos_x = x; - new_oi.pos_y = y; - new_oi.width = w; - new_oi.height = h; - new_oi.out_width = outw; - new_oi.out_height = outh; - new_oi.paddr = paddr; - - r = dispc_ovl_setup(plane, &new_oi, c->ilace, c->channel, + r = dispc_ovl_setup(plane, oi, c->ilace, c->channel, c->replication, c->fifo_low, c->fifo_high); if (r) { /* this shouldn't happen */ @@ -1070,170 +896,23 @@ static int configure_dispc(void) return r; } -/* Make the coordinates even. There are some strange problems with OMAP and - * partial DSI update when the update widths are odd. */ -static void make_even(u16 *x, u16 *w) -{ - u16 x1, x2; - - x1 = *x; - x2 = *x + *w; - - x1 &= ~1; - x2 = ALIGN(x2, 2); - - *x = x1; - *w = x2 - x1; -} - -/* Configure dispc for partial update. Return possibly modified update - * area */ -void dss_setup_partial_planes(struct omap_dss_device *dssdev, - u16 *xi, u16 *yi, u16 *wi, u16 *hi, bool enlarge_update_area) +void dss_start_update(struct omap_dss_device *dssdev) { - struct overlay_cache_data *oc; struct manager_cache_data *mc; - struct omap_overlay_info *oi; + struct overlay_cache_data *oc; const int num_ovls = dss_feat_get_num_ovls(); + const int num_mgrs = dss_feat_get_num_mgrs(); struct omap_overlay_manager *mgr; int i; - u16 x, y, w, h; - unsigned long flags; - bool area_changed; - - x = *xi; - y = *yi; - w = *wi; - h = *hi; - - DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n", - *xi, *yi, *wi, *hi); mgr = dssdev->manager; - if (!mgr) { - DSSDBG("no manager\n"); - return; - } - - make_even(&x, &w); - - spin_lock_irqsave(&dss_cache.lock, flags); - - /* - * Execute the outer loop until the inner loop has completed - * once without increasing the update area. This will ensure that - * all scaled overlays end up completely within the update area. - */ - do { - area_changed = false; - - /* We need to show the whole overlay if it is scaled. So look - * for those, and make the update area larger if found. - * Also mark the overlay cache dirty */ - for (i = 0; i < num_ovls; ++i) { - unsigned x1, y1, x2, y2; - unsigned outw, outh; - - oc = &dss_cache.overlay_cache[i]; - oi = &oc->info; - - if (oc->channel != mgr->id) - continue; - - oc->dirty = true; - - if (!enlarge_update_area) - continue; - - if (!oc->enabled) - continue; - - if (!dispc_is_overlay_scaled(oc)) - continue; - - outw = oi->out_width == 0 ? - oi->width : oi->out_width; - outh = oi->out_height == 0 ? - oi->height : oi->out_height; - - /* is the overlay outside the update region? */ - if (!rectangle_intersects(x, y, w, h, - oi->pos_x, oi->pos_y, - outw, outh)) - continue; - - /* if the overlay totally inside the update region? */ - if (rectangle_subset(oi->pos_x, oi->pos_y, outw, outh, - x, y, w, h)) - continue; - - if (x > oi->pos_x) - x1 = oi->pos_x; - else - x1 = x; - - if (y > oi->pos_y) - y1 = oi->pos_y; - else - y1 = y; - - if ((x + w) < (oi->pos_x + outw)) - x2 = oi->pos_x + outw; - else - x2 = x + w; - - if ((y + h) < (oi->pos_y + outh)) - y2 = oi->pos_y + outh; - else - y2 = y + h; - - x = x1; - y = y1; - w = x2 - x1; - h = y2 - y1; - - make_even(&x, &w); - - DSSDBG("changing upd area due to ovl(%d) " - "scaling %d,%d %dx%d\n", - i, x, y, w, h); - - area_changed = true; - } - } while (area_changed); - mc = &dss_cache.manager_cache[mgr->id]; - mc->do_manual_update = true; - mc->enlarge_update_area = enlarge_update_area; - mc->x = x; - mc->y = y; - mc->w = w; - mc->h = h; + mc->do_manual_update = true; configure_dispc(); - mc->do_manual_update = false; - spin_unlock_irqrestore(&dss_cache.lock, flags); - - *xi = x; - *yi = y; - *wi = w; - *hi = h; -} - -void dss_start_update(struct omap_dss_device *dssdev) -{ - struct manager_cache_data *mc; - struct overlay_cache_data *oc; - const int num_ovls = dss_feat_get_num_ovls(); - const int num_mgrs = dss_feat_get_num_mgrs(); - struct omap_overlay_manager *mgr; - int i; - - mgr = dssdev->manager; - for (i = 0; i < num_ovls; ++i) { oc = &dss_cache.overlay_cache[i]; if (oc->channel != mgr->id) diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 1130c60..814bb95 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -784,7 +784,6 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, if (*w == 0 || *h == 0) return -EINVAL; - dss_setup_partial_planes(dssdev, x, y, w, h, true); dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h); return 0; -- cgit v0.10.2 From 5476e74a03f4be972708162050c8ac7fe150449f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 3 Nov 2011 16:34:20 +0200 Subject: OMAPDSS: remove partial update from DSI Partial update for manual update displays has never worked quite well: * The HW has limitations on the update area, and the x and width need to be even. * Showing a part of a scaled overlay causes artifacts. * Makes the management of dispc very complex Considering the above points and the fact that partial update is not used anywhere, this and the following patches remove the partial update support. This will greatly simplify the following re-write of the apply mechanism to get proper locking and additional features like fifo-merge. This patch removes the partial update from the dsi.c. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 80c3f6a..0aa6c5d 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -1394,12 +1394,8 @@ static irqreturn_t taal_te_isr(int irq, void *data) if (old) { cancel_delayed_work(&td->te_timeout_work); - r = omap_dsi_update(dssdev, td->channel, - td->update_region.x, - td->update_region.y, - td->update_region.w, - td->update_region.h, - taal_framedone_cb, dssdev); + r = omap_dsi_update(dssdev, td->channel, taal_framedone_cb, + dssdev); if (r) goto err; } @@ -1444,10 +1440,6 @@ static int taal_update(struct omap_dss_device *dssdev, goto err; } - r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h, true); - if (r) - goto err; - r = taal_set_update_window(td, x, y, w, h); if (r) goto err; @@ -1462,8 +1454,8 @@ static int taal_update(struct omap_dss_device *dssdev, msecs_to_jiffies(250)); atomic_set(&td->do_update, 1); } else { - r = omap_dsi_update(dssdev, td->channel, x, y, w, h, - taal_framedone_cb, dssdev); + r = omap_dsi_update(dssdev, td->channel, taal_framedone_cb, + dssdev); if (r) goto err; } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 773a496..6fc82a4 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -238,11 +238,6 @@ enum dsi_vc_source { DSI_VC_SOURCE_VP, }; -struct dsi_update_region { - u16 x, y, w, h; - struct omap_dss_device *device; -}; - struct dsi_irq_stats { unsigned long last_reset; unsigned irq_count; @@ -292,7 +287,9 @@ struct dsi_data { struct dsi_isr_tables isr_tables_copy; int update_channel; - struct dsi_update_region update_region; +#ifdef DEBUG + unsigned update_bytes; +#endif bool te_enabled; bool ulps_enabled; @@ -474,7 +471,6 @@ static void dsi_perf_mark_start(struct platform_device *dsidev) static void dsi_perf_show(struct platform_device *dsidev, const char *name) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - struct omap_dss_device *dssdev = dsi->update_region.device; ktime_t t, setup_time, trans_time; u32 total_bytes; u32 setup_us, trans_us, total_us; @@ -496,9 +492,7 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name) total_us = setup_us + trans_us; - total_bytes = dsi->update_region.w * - dsi->update_region.h * - dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; + total_bytes = dsi->update_bytes; printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " "%u bytes, %u kbytes/sec\n", @@ -4040,7 +4034,7 @@ void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel) EXPORT_SYMBOL(dsi_video_mode_disable); static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, - u16 x, u16 y, u16 w, u16 h) + u16 w, u16 h) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); @@ -4055,8 +4049,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, const unsigned channel = dsi->update_channel; const unsigned line_buf_size = dsi_get_line_buf_size(dsidev); - DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", - x, y, w, h); + DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h); dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP); @@ -4180,64 +4173,27 @@ static void dsi_framedone_irq_callback(void *data, u32 mask) #endif } -int omap_dsi_prepare_update(struct omap_dss_device *dssdev, - u16 *x, u16 *y, u16 *w, u16 *h, - bool enlarge_update_area) +int omap_dsi_update(struct omap_dss_device *dssdev, int channel, + void (*callback)(int, void *), void *data) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); u16 dw, dh; - dssdev->driver->get_resolution(dssdev, &dw, &dh); - - if (*x > dw || *y > dh) - return -EINVAL; - - if (*x + *w > dw) - return -EINVAL; - - if (*y + *h > dh) - return -EINVAL; - - if (*w == 1) - return -EINVAL; - - if (*w == 0 || *h == 0) - return -EINVAL; - dsi_perf_mark_setup(dsidev); - dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h); - - return 0; -} -EXPORT_SYMBOL(omap_dsi_prepare_update); - -int omap_dsi_update(struct omap_dss_device *dssdev, - int channel, - u16 x, u16 y, u16 w, u16 h, - void (*callback)(int, void *), void *data) -{ - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); - struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - dsi->update_channel = channel; - /* OMAP DSS cannot send updates of odd widths. - * omap_dsi_prepare_update() makes the widths even, but add a BUG_ON - * here to make sure we catch erroneous updates. Otherwise we'll only - * see rather obscure HW error happening, as DSS halts. */ - BUG_ON(x % 2 == 1); - dsi->framedone_callback = callback; dsi->framedone_data = data; - dsi->update_region.x = x; - dsi->update_region.y = y; - dsi->update_region.w = w; - dsi->update_region.h = h; - dsi->update_region.device = dssdev; + dssdev->driver->get_resolution(dssdev, &dw, &dh); - dsi_update_screen_dispc(dssdev, x, y, w, h); +#ifdef DEBUG + dsi->update_bytes = dw * dh * + dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; +#endif + dsi_update_screen_dispc(dssdev, dw, dh); return 0; } @@ -4250,6 +4206,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) int r; if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { + u16 dw, dh; u32 irq; struct omap_video_timings timings = { .hsw = 1, @@ -4260,6 +4217,10 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) .vbp = 0, }; + dssdev->driver->get_resolution(dssdev, &dw, &dh); + timings.x_res = dw; + timings.y_res = dh; + irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 378c7ed..60bf426 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -662,12 +662,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel, bool enable); int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable); -int omap_dsi_prepare_update(struct omap_dss_device *dssdev, - u16 *x, u16 *y, u16 *w, u16 *h, - bool enlarge_update_area); -int omap_dsi_update(struct omap_dss_device *dssdev, - int channel, - u16 x, u16 y, u16 w, u16 h, +int omap_dsi_update(struct omap_dss_device *dssdev, int channel, void (*callback)(int, void *), void *data); int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel); int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id); -- cgit v0.10.2 From 6331709bcafe578f63c837a8d726ce8ffdfe0895 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 3 Nov 2011 16:45:07 +0200 Subject: OMAPDSS: remove partial update from panel-taal Partial update for manual update displays has never worked quite well: * The HW has limitations on the update area, and the x and width need to be even. * Showing a part of a scaled overlay causes artifacts. * Makes the management of dispc very complex Considering the above points and the fact that partial update is not used anywhere, this and the following patches remove the partial update support. This will greatly simplify the following re-write of the apply mechanism to get proper locking and additional features like fifo-merge. This patch removes the partial update from the panel-taal.c. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 0aa6c5d..dd64bd1 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -198,12 +198,6 @@ struct taal_data { bool te_enabled; atomic_t do_update; - struct { - u16 x; - u16 y; - u16 w; - u16 h; - } update_region; int channel; struct delayed_work te_timeout_work; @@ -1440,16 +1434,14 @@ static int taal_update(struct omap_dss_device *dssdev, goto err; } - r = taal_set_update_window(td, x, y, w, h); + /* XXX no need to send this every frame, but dsi break if not done */ + r = taal_set_update_window(td, 0, 0, + td->panel_config->timings.x_res, + td->panel_config->timings.y_res); if (r) goto err; if (td->te_enabled && panel_data->use_ext_te) { - td->update_region.x = x; - td->update_region.y = y; - td->update_region.w = w; - td->update_region.h = h; - barrier(); schedule_delayed_work(&td->te_timeout_work, msecs_to_jiffies(250)); atomic_set(&td->do_update, 1); -- cgit v0.10.2 From 1cb0017813e82c740ef7b60bdaa0aa74eaab6a76 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 18 Nov 2011 11:14:01 +0200 Subject: OMAPDSS: pass ovl manager to dss_start_update dss_start_update() takes currently the dss device as a parameter. Change the parameter to ovl manager, as that is what the dss_start_update() actually needs. Change the name of the function to dss_mgr_start_update() to reflect the change. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 6fc82a4..101e3b8 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -4097,7 +4097,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, msecs_to_jiffies(250)); BUG_ON(r == 0); - dss_start_update(dssdev); + dss_mgr_start_update(dssdev->manager); if (dsi->te_enabled) { /* disable LP_RX_TO, so that we can receive TE. Time to wait diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 7f6a612..39d4837 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -182,7 +182,7 @@ void default_get_overlay_fifo_thresholds(enum omap_plane plane, int dss_init_overlay_managers(struct platform_device *pdev); void dss_uninit_overlay_managers(struct platform_device *pdev); int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl); -void dss_start_update(struct omap_dss_device *dssdev); +void dss_mgr_start_update(struct omap_overlay_manager *mgr); /* overlay */ void dss_init_overlays(struct platform_device *pdev); diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index c616f85..268704b 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -896,17 +896,14 @@ static int configure_dispc(void) return r; } -void dss_start_update(struct omap_dss_device *dssdev) +void dss_mgr_start_update(struct omap_overlay_manager *mgr) { struct manager_cache_data *mc; struct overlay_cache_data *oc; const int num_ovls = dss_feat_get_num_ovls(); const int num_mgrs = dss_feat_get_num_mgrs(); - struct omap_overlay_manager *mgr; int i; - mgr = dssdev->manager; - mc = &dss_cache.manager_cache[mgr->id]; mc->do_manual_update = true; @@ -929,7 +926,7 @@ void dss_start_update(struct omap_dss_device *dssdev) mc->shadow_dirty = false; } - dssdev->manager->enable(dssdev->manager); + mgr->enable(mgr); } static void dss_apply_irq_handler(void *data, u32 mask) -- cgit v0.10.2 From cf0736681e569b0d3803d68d4f6d00f544f3426a Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 3 Nov 2011 16:08:27 +0200 Subject: OMAPDSS: DISPC: handle 0 out_width/out_height in ovl_setup() Overlay out_width/height are set to 0 when scaling is not used by the users of omapdss. Currently ovl_setup() expects the caller of ovl_setup() to convert those zero values to width or height. This patch makes ovl_setup() accept zero values for out_width/height, making calling ovl_setup() a bit simpler as the overlay_info can be just passed to this function without modifications. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 8249731..f054972 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1781,6 +1781,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, s32 pix_inc; u16 frame_height = oi->height; unsigned int field_offset = 0; + u16 outw, outh; DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> " "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d " @@ -1792,25 +1793,28 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, if (oi->paddr == 0) return -EINVAL; - if (ilace && oi->height == oi->out_height) + outw = oi->out_width == 0 ? oi->width : oi->out_width; + outh = oi->out_height == 0 ? oi->height : oi->out_height; + + if (ilace && oi->height == outh) fieldmode = 1; if (ilace) { if (fieldmode) oi->height /= 2; oi->pos_y /= 2; - oi->out_height /= 2; + outh /= 2; DSSDBG("adjusting for ilace: height %d, pos_y %d, " "out_height %d\n", - oi->height, oi->pos_y, oi->out_height); + oi->height, oi->pos_y, outh); } if (!dss_feat_color_mode_supported(plane, oi->color_mode)) return -EINVAL; r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height, - oi->out_width, oi->out_height, oi->color_mode, + outw, outh, oi->color_mode, &five_taps); if (r) return r; @@ -1828,10 +1832,10 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, * so the integer part must be added to the base address of the * bottom field. */ - if (!oi->height || oi->height == oi->out_height) + if (!oi->height || oi->height == outh) field_offset = 0; else - field_offset = oi->height / oi->out_height / 2; + field_offset = oi->height / outh / 2; } /* Fields are independent but interleaved in memory. */ @@ -1867,7 +1871,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, dispc_ovl_set_pix_inc(plane, pix_inc); DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width, - oi->height, oi->out_width, oi->out_height); + oi->height, outw, outh); dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); @@ -1875,10 +1879,10 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { dispc_ovl_set_scaling(plane, oi->width, oi->height, - oi->out_width, oi->out_height, + outw, outh, ilace, five_taps, fieldmode, oi->color_mode, oi->rotation); - dispc_ovl_set_vid_size(plane, oi->out_width, oi->out_height); + dispc_ovl_set_vid_size(plane, outw, outh); dispc_ovl_set_vid_color_conv(plane, cconv); } -- cgit v0.10.2 From 3ba2a1c01546a4980e7b7742445560ae4afd1fc1 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 3 Nov 2011 16:52:06 +0200 Subject: OMAPDSS: handle ilace/replication when configuring overlay Move the configuration of interlace and replication from omap_dss_mgr_apply() to configure_overlay(). This removes the need to store the values into the cache data. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 268704b..d8d0d11 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -510,8 +510,6 @@ struct overlay_cache_data { struct omap_overlay_info info; enum omap_channel channel; - bool replication; - bool ilace; u32 fifo_low; u32 fifo_high; @@ -757,8 +755,10 @@ static int overlay_enabled(struct omap_overlay *ovl) static int configure_overlay(enum omap_plane plane) { + struct omap_overlay *ovl; struct overlay_cache_data *c; struct omap_overlay_info *oi; + bool ilace, replication; int r; DSSDBGF("%d", plane); @@ -771,8 +771,14 @@ static int configure_overlay(enum omap_plane plane) return 0; } - r = dispc_ovl_setup(plane, oi, c->ilace, c->channel, - c->replication, c->fifo_low, c->fifo_high); + ovl = omap_dss_get_overlay(plane); + + replication = dss_use_replication(ovl->manager->device, oi->color_mode); + + ilace = ovl->manager->device->type == OMAP_DISPLAY_TYPE_VENC; + + r = dispc_ovl_setup(plane, oi, ilace, c->channel, + replication, c->fifo_low, c->fifo_high); if (r) { /* this shouldn't happen */ DSSERR("dispc_ovl_setup failed for ovl %d\n", plane); @@ -1038,11 +1044,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) oc->dirty = true; oc->info = ovl->info; - oc->replication = - dss_use_replication(dssdev, ovl->info.color_mode); - - oc->ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC; - oc->channel = ovl->manager->id; oc->enabled = true; -- cgit v0.10.2 From f38545da53d98055d8b2f58fe156c86626f3427e Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 3 Nov 2011 17:00:07 +0200 Subject: OMAPDSS: separate FIFO threshold setup from ovl_setup Overlay FIFO thresholds are configured with ovl_setup, with all the other overlay attributes. This patch separates FIFO threshold setup so that we can later configure FIFO thresholds only when needed. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index f054972..094bb6e 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1769,8 +1769,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, } int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, - bool ilace, enum omap_channel channel, bool replication, - u32 fifo_low, u32 fifo_high) + bool ilace, enum omap_channel channel, bool replication) { struct omap_overlay *ovl = omap_dss_get_overlay(plane); bool five_taps = false; @@ -1784,11 +1783,11 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, u16 outw, outh; DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> " - "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d " - "fifo_low %d fifo high %d\n", plane, oi->paddr, oi->p_uv_addr, + "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d\n", + plane, oi->paddr, oi->p_uv_addr, oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height, oi->color_mode, oi->rotation, - oi->mirror, ilace, channel, replication, fifo_low, fifo_high); + oi->mirror, ilace, channel, replication); if (oi->paddr == 0) return -EINVAL; @@ -1896,7 +1895,6 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, dispc_ovl_set_channel_out(plane, channel); dispc_ovl_enable_replication(plane, replication); - dispc_ovl_set_fifo_threshold(plane, fifo_low, fifo_high); return 0; } diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 39d4837..d56e916 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -397,8 +397,7 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); u32 dispc_ovl_get_fifo_size(enum omap_plane plane); u32 dispc_ovl_get_burst_size(enum omap_plane plane); int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, - bool ilace, enum omap_channel channel, bool replication, - u32 fifo_low, u32 fifo_high); + bool ilace, enum omap_channel channel, bool replication); int dispc_ovl_enable(enum omap_plane plane, bool enable); void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel); diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index d8d0d11..31637ba 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -777,8 +777,7 @@ static int configure_overlay(enum omap_plane plane) ilace = ovl->manager->device->type == OMAP_DISPLAY_TYPE_VENC; - r = dispc_ovl_setup(plane, oi, ilace, c->channel, - replication, c->fifo_low, c->fifo_high); + r = dispc_ovl_setup(plane, oi, ilace, c->channel, replication); if (r) { /* this shouldn't happen */ DSSERR("dispc_ovl_setup failed for ovl %d\n", plane); @@ -786,6 +785,8 @@ static int configure_overlay(enum omap_plane plane) return r; } + dispc_ovl_set_fifo_threshold(plane, c->fifo_low, c->fifo_high); + dispc_ovl_enable(plane, 1); return 0; -- cgit v0.10.2 From 2cc5d1af5ad0a130fa5812f99bca18e0cdadbd36 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 3 Nov 2011 17:03:44 +0200 Subject: OMAPDSS: separate overlay channel from ovl_setup Overlay channel is configured with ovl_setup, with all the other overlay attriutes. This patch separates overlay channel setup so that we can later configure the channel only when needed. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 094bb6e..b66cf15 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -922,6 +922,39 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel) dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); } +static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane) +{ + int shift; + u32 val; + enum omap_channel channel; + + switch (plane) { + case OMAP_DSS_GFX: + shift = 8; + break; + case OMAP_DSS_VIDEO1: + case OMAP_DSS_VIDEO2: + case OMAP_DSS_VIDEO3: + shift = 16; + break; + default: + BUG(); + } + + val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); + + if (dss_has_feature(FEAT_MGR_LCD2)) { + if (FLD_GET(val, 31, 30) == 0) + channel = FLD_GET(val, shift, shift); + else + channel = OMAP_DSS_CHANNEL_LCD2; + } else { + channel = FLD_GET(val, shift, shift); + } + + return channel; +} + static void dispc_ovl_set_burst_size(enum omap_plane plane, enum omap_burst_size burst_size) { @@ -1769,7 +1802,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, } int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, - bool ilace, enum omap_channel channel, bool replication) + bool ilace, bool replication) { struct omap_overlay *ovl = omap_dss_get_overlay(plane); bool five_taps = false; @@ -1781,6 +1814,9 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, u16 frame_height = oi->height; unsigned int field_offset = 0; u16 outw, outh; + enum omap_channel channel; + + channel = dispc_ovl_get_channel_out(plane); DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> " "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d\n", @@ -1892,8 +1928,6 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha); dispc_ovl_setup_global_alpha(plane, oi->global_alpha); - dispc_ovl_set_channel_out(plane, channel); - dispc_ovl_enable_replication(plane, replication); return 0; diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index d56e916..11c72d1 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -397,7 +397,7 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); u32 dispc_ovl_get_fifo_size(enum omap_plane plane); u32 dispc_ovl_get_burst_size(enum omap_plane plane); int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, - bool ilace, enum omap_channel channel, bool replication); + bool ilace, bool replication); int dispc_ovl_enable(enum omap_plane plane, bool enable); void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel); diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 31637ba..ec98e17 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -777,7 +777,9 @@ static int configure_overlay(enum omap_plane plane) ilace = ovl->manager->device->type == OMAP_DISPLAY_TYPE_VENC; - r = dispc_ovl_setup(plane, oi, ilace, c->channel, replication); + dispc_ovl_set_channel_out(plane, c->channel); + + r = dispc_ovl_setup(plane, oi, ilace, replication); if (r) { /* this shouldn't happen */ DSSERR("dispc_ovl_setup failed for ovl %d\n", plane); -- cgit v0.10.2 From c64dca40c5cf1cc61355411dcfb90949e57afdf0 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 4 Nov 2011 18:14:20 +0200 Subject: OMAPDSS: setup manager with dispc_mgr_setup() Change manager configuration to be similar to overlay configuration by creating dispc_mgr_setup() which takes omap_overlay_manager_info as parameter. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index b66cf15..9c070a2 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -996,7 +996,7 @@ void dispc_enable_gamma_table(bool enable) REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9); } -void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable) +static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable) { u16 reg; @@ -1010,7 +1010,7 @@ void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable) REG_FLD_MOD(reg, enable, 15, 15); } -void dispc_mgr_set_cpr_coef(enum omap_channel channel, +static void dispc_mgr_set_cpr_coef(enum omap_channel channel, struct omap_dss_cpr_coefs *coefs) { u32 coef_r, coef_g, coef_b; @@ -2164,7 +2164,7 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode) } -void dispc_mgr_set_default_color(enum omap_channel channel, u32 color) +static void dispc_mgr_set_default_color(enum omap_channel channel, u32 color) { dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color); } @@ -2182,7 +2182,7 @@ u32 dispc_mgr_get_default_color(enum omap_channel channel) return l; } -void dispc_mgr_set_trans_key(enum omap_channel ch, +static void dispc_mgr_set_trans_key(enum omap_channel ch, enum omap_dss_trans_key_type type, u32 trans_key) { @@ -2215,7 +2215,7 @@ void dispc_mgr_get_trans_key(enum omap_channel ch, *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch)); } -void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable) +static void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable) { if (ch == OMAP_DSS_CHANNEL_LCD) REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); @@ -2225,7 +2225,8 @@ void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable) REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10); } -void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable) +static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, + bool enable) { if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) return; @@ -2269,6 +2270,19 @@ bool dispc_mgr_trans_key_enabled(enum omap_channel ch) return enabled; } +void dispc_mgr_setup(enum omap_channel channel, + struct omap_overlay_manager_info *info) +{ + dispc_mgr_set_default_color(channel, info->default_color); + dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key); + dispc_mgr_enable_trans_key(channel, info->trans_enabled); + dispc_mgr_enable_alpha_fixed_zorder(channel, + info->partial_alpha_enabled); + if (dss_has_feature(FEAT_CPR)) { + dispc_mgr_enable_cpr(channel, info->cpr_enable); + dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs); + } +} void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines) { diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 11c72d1..a802257 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -405,9 +405,6 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable); void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height); -void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable); -void dispc_mgr_set_cpr_coef(enum omap_channel channel, - struct omap_dss_cpr_coefs *coefs); bool dispc_mgr_go_busy(enum omap_channel channel); void dispc_mgr_go(enum omap_channel channel); bool dispc_mgr_is_enabled(enum omap_channel channel); @@ -418,16 +415,10 @@ void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable); void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines); void dispc_mgr_set_lcd_display_type(enum omap_channel channel, enum omap_lcd_display_type type); -void dispc_mgr_set_default_color(enum omap_channel channel, u32 color); u32 dispc_mgr_get_default_color(enum omap_channel channel); -void dispc_mgr_set_trans_key(enum omap_channel ch, - enum omap_dss_trans_key_type type, - u32 trans_key); void dispc_mgr_get_trans_key(enum omap_channel ch, enum omap_dss_trans_key_type *type, u32 *trans_key); -void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable); -void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable); bool dispc_mgr_trans_key_enabled(enum omap_channel ch); bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch); void dispc_mgr_set_lcd_timings(enum omap_channel channel, @@ -440,6 +431,8 @@ int dispc_mgr_set_clock_div(enum omap_channel channel, struct dispc_clock_info *cinfo); int dispc_mgr_get_clock_div(enum omap_channel channel, struct dispc_clock_info *cinfo); +void dispc_mgr_setup(enum omap_channel channel, + struct omap_overlay_manager_info *info); /* VENC */ #ifdef CONFIG_OMAP2_DSS_VENC diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index ec98e17..3421955 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -803,14 +803,7 @@ static void configure_manager(enum omap_channel channel) /* picking info from the cache */ mi = &dss_cache.manager_cache[channel].info; - dispc_mgr_set_default_color(channel, mi->default_color); - dispc_mgr_set_trans_key(channel, mi->trans_key_type, mi->trans_key); - dispc_mgr_enable_trans_key(channel, mi->trans_enabled); - dispc_mgr_enable_alpha_fixed_zorder(channel, mi->partial_alpha_enabled); - if (dss_has_feature(FEAT_CPR)) { - dispc_mgr_enable_cpr(channel, mi->cpr_enable); - dispc_mgr_set_cpr_coef(channel, &mi->cpr_coefs); - } + dispc_mgr_setup(channel, mi); } /* configure_dispc() tries to write values from cache to shadow registers. -- cgit v0.10.2 From c3f96fee1eb8d541b4b5bb841f57bd453c70f12d Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 4 Nov 2011 18:14:11 +0200 Subject: OMAPDSS: DISPC: remove unused functions Remove unused functions: dispc_mgr_get_default_color dispc_mgr_get_trans_key dispc_mgr_trans_key_enabled dispc_mgr_alpha_fixed_zorder_enabled Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 9c070a2..1264c2d 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -2169,19 +2169,6 @@ static void dispc_mgr_set_default_color(enum omap_channel channel, u32 color) dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color); } -u32 dispc_mgr_get_default_color(enum omap_channel channel) -{ - u32 l; - - BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT && - channel != OMAP_DSS_CHANNEL_LCD && - channel != OMAP_DSS_CHANNEL_LCD2); - - l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel)); - - return l; -} - static void dispc_mgr_set_trans_key(enum omap_channel ch, enum omap_dss_trans_key_type type, u32 trans_key) @@ -2196,25 +2183,6 @@ static void dispc_mgr_set_trans_key(enum omap_channel ch, dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key); } -void dispc_mgr_get_trans_key(enum omap_channel ch, - enum omap_dss_trans_key_type *type, - u32 *trans_key) -{ - if (type) { - if (ch == OMAP_DSS_CHANNEL_LCD) - *type = REG_GET(DISPC_CONFIG, 11, 11); - else if (ch == OMAP_DSS_CHANNEL_DIGIT) - *type = REG_GET(DISPC_CONFIG, 13, 13); - else if (ch == OMAP_DSS_CHANNEL_LCD2) - *type = REG_GET(DISPC_CONFIG2, 11, 11); - else - BUG(); - } - - if (trans_key) - *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch)); -} - static void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable) { if (ch == OMAP_DSS_CHANNEL_LCD) @@ -2237,39 +2205,6 @@ static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); } -bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch) -{ - bool enabled; - - if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) - return false; - - if (ch == OMAP_DSS_CHANNEL_LCD) - enabled = REG_GET(DISPC_CONFIG, 18, 18); - else if (ch == OMAP_DSS_CHANNEL_DIGIT) - enabled = REG_GET(DISPC_CONFIG, 19, 19); - else - BUG(); - - return enabled; -} - -bool dispc_mgr_trans_key_enabled(enum omap_channel ch) -{ - bool enabled; - - if (ch == OMAP_DSS_CHANNEL_LCD) - enabled = REG_GET(DISPC_CONFIG, 10, 10); - else if (ch == OMAP_DSS_CHANNEL_DIGIT) - enabled = REG_GET(DISPC_CONFIG, 12, 12); - else if (ch == OMAP_DSS_CHANNEL_LCD2) - enabled = REG_GET(DISPC_CONFIG2, 10, 10); - else - BUG(); - - return enabled; -} - void dispc_mgr_setup(enum omap_channel channel, struct omap_overlay_manager_info *info) { diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index a802257..5ac7243 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -415,12 +415,6 @@ void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable); void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines); void dispc_mgr_set_lcd_display_type(enum omap_channel channel, enum omap_lcd_display_type type); -u32 dispc_mgr_get_default_color(enum omap_channel channel); -void dispc_mgr_get_trans_key(enum omap_channel ch, - enum omap_dss_trans_key_type *type, - u32 *trans_key); -bool dispc_mgr_trans_key_enabled(enum omap_channel ch); -bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch); void dispc_mgr_set_lcd_timings(enum omap_channel channel, struct omap_video_timings *timings); void dispc_mgr_set_pol_freq(enum omap_channel channel, -- cgit v0.10.2 From 550a8f646c76f27ede10265b8e4c9d54c9f4af27 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 4 Nov 2011 13:00:10 +0200 Subject: OMAPDSS: remove unneeded dss_ovl_wait_for_go() There's an unnecessary wrapper function, dss_ovl_wait_for_go(), which does nothing else than call dss_mgr_wait_for_go_ovl(). The dss_ovl_wait_for_go() function can be removed. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index d15b826..0ab14fa 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -548,11 +548,6 @@ static void dss_ovl_get_overlay_info(struct omap_overlay *ovl, *info = ovl->info; } -static int dss_ovl_wait_for_go(struct omap_overlay *ovl) -{ - return dss_mgr_wait_for_go_ovl(ovl); -} - static int omap_dss_set_manager(struct omap_overlay *ovl, struct omap_overlay_manager *mgr) { @@ -689,7 +684,7 @@ void dss_init_overlays(struct platform_device *pdev) ovl->unset_manager = &omap_dss_unset_manager; ovl->set_overlay_info = &dss_ovl_set_overlay_info; ovl->get_overlay_info = &dss_ovl_get_overlay_info; - ovl->wait_for_go = &dss_ovl_wait_for_go; + ovl->wait_for_go = &dss_mgr_wait_for_go_ovl; ovl->caps = dss_feat_get_overlay_caps(ovl->id); ovl->supported_modes = -- cgit v0.10.2 From 32eaa5841021c8d812a4f62898a6e8617d648846 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 4 Nov 2011 09:04:15 +0200 Subject: OMAPDSS: add ovl/mgr_manual_update() helpers Add helper functions ovl_manual_update() and mgr_manual_update() which return whether the overlay or manager is used with a manual update display. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 3421955..8423cf8 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -538,7 +538,15 @@ static struct { bool irq_enabled; } dss_cache; +static bool ovl_manual_update(struct omap_overlay *ovl) +{ + return ovl->manager->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; +} +static bool mgr_manual_update(struct omap_overlay_manager *mgr) +{ + return mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; +} static int omap_dss_set_device(struct omap_overlay_manager *mgr, struct omap_dss_device *dssdev) @@ -627,7 +635,7 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) return 0; - if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) + if (mgr_manual_update(mgr)) return 0; if (dssdev->type == OMAP_DISPLAY_TYPE_VENC @@ -696,7 +704,7 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) return 0; - if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) + if (ovl_manual_update(ovl)) return 0; if (dssdev->type == OMAP_DISPLAY_TYPE_VENC @@ -1047,8 +1055,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) /* Configure managers */ list_for_each_entry(mgr, &manager_list, list) { - struct omap_dss_device *dssdev; - mc = &dss_cache.manager_cache[mgr->id]; if (mgr->device_changed) { @@ -1062,14 +1068,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) if (!mgr->device) continue; - dssdev = mgr->device; - mgr->info_dirty = false; mc->dirty = true; mc->info = mgr->info; - mc->manual_update = - dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; + mc->manual_update = mgr_manual_update(mgr); } /* Configure overlay fifos */ -- cgit v0.10.2 From 209285012c792d3a0f758c7ace30af0ee4bc08a3 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 4 Nov 2011 09:19:35 +0200 Subject: OMAPDSS: split omap_dss_mgr_apply() to smaller funcs Split omap_dss_mgr_apply() into smaller functions for clarity. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 8423cf8..d0d2315 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -993,107 +993,92 @@ end: spin_unlock(&dss_cache.lock); } -static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) +static int omap_dss_mgr_apply_ovl(struct omap_overlay *ovl) { struct overlay_cache_data *oc; - struct manager_cache_data *mc; - int i; - struct omap_overlay *ovl; - unsigned long flags; - int r; - - DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name); + struct omap_dss_device *dssdev; - r = dispc_runtime_get(); - if (r) - return r; + oc = &dss_cache.overlay_cache[ovl->id]; - spin_lock_irqsave(&dss_cache.lock, flags); + if (ovl->manager_changed) { + ovl->manager_changed = false; + ovl->info_dirty = true; + } - /* Configure overlays */ - for (i = 0; i < omap_dss_get_num_overlays(); ++i) { - struct omap_dss_device *dssdev; + if (!overlay_enabled(ovl)) { + if (oc->enabled) { + oc->enabled = false; + oc->dirty = true; + } + return 0; + } - ovl = omap_dss_get_overlay(i); + if (!ovl->info_dirty) + return 0; - oc = &dss_cache.overlay_cache[ovl->id]; + dssdev = ovl->manager->device; - if (ovl->manager_changed) { - ovl->manager_changed = false; - ovl->info_dirty = true; + if (dss_check_overlay(ovl, dssdev)) { + if (oc->enabled) { + oc->enabled = false; + oc->dirty = true; } + return -EINVAL; + } - if (!overlay_enabled(ovl)) { - if (oc->enabled) { - oc->enabled = false; - oc->dirty = true; - } - continue; - } + ovl->info_dirty = false; + oc->dirty = true; + oc->info = ovl->info; - if (!ovl->info_dirty) - continue; + oc->channel = ovl->manager->id; - dssdev = ovl->manager->device; + oc->enabled = true; - if (dss_check_overlay(ovl, dssdev)) { - if (oc->enabled) { - oc->enabled = false; - oc->dirty = true; - } - continue; - } + return 0; +} - ovl->info_dirty = false; - oc->dirty = true; - oc->info = ovl->info; +static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr) +{ + struct manager_cache_data *mc; - oc->channel = ovl->manager->id; + mc = &dss_cache.manager_cache[mgr->id]; - oc->enabled = true; + if (mgr->device_changed) { + mgr->device_changed = false; + mgr->info_dirty = true; } - /* Configure managers */ - list_for_each_entry(mgr, &manager_list, list) { - mc = &dss_cache.manager_cache[mgr->id]; - - if (mgr->device_changed) { - mgr->device_changed = false; - mgr->info_dirty = true; - } + if (!mgr->info_dirty) + return; - if (!mgr->info_dirty) - continue; + if (!mgr->device) + return; - if (!mgr->device) - continue; + mgr->info_dirty = false; + mc->dirty = true; + mc->info = mgr->info; - mgr->info_dirty = false; - mc->dirty = true; - mc->info = mgr->info; - - mc->manual_update = mgr_manual_update(mgr); - } - - /* Configure overlay fifos */ - for (i = 0; i < omap_dss_get_num_overlays(); ++i) { - struct omap_dss_device *dssdev; - u32 size, burst_size; + mc->manual_update = mgr_manual_update(mgr); +} - ovl = omap_dss_get_overlay(i); +static void omap_dss_mgr_apply_ovl_fifos(struct omap_overlay *ovl) +{ + struct overlay_cache_data *oc; + struct omap_dss_device *dssdev; + u32 size, burst_size; - oc = &dss_cache.overlay_cache[ovl->id]; + oc = &dss_cache.overlay_cache[ovl->id]; - if (!oc->enabled) - continue; + if (!oc->enabled) + return; - dssdev = ovl->manager->device; + dssdev = ovl->manager->device; - size = dispc_ovl_get_fifo_size(ovl->id); + size = dispc_ovl_get_fifo_size(ovl->id); - burst_size = dispc_ovl_get_burst_size(ovl->id); + burst_size = dispc_ovl_get_burst_size(ovl->id); - switch (dssdev->type) { + switch (dssdev->type) { case OMAP_DISPLAY_TYPE_DPI: case OMAP_DISPLAY_TYPE_DBI: case OMAP_DISPLAY_TYPE_SDI: @@ -1112,7 +1097,42 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) #endif default: BUG(); - } + } +} + +static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) +{ + int i, r; + unsigned long flags; + + DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name); + + r = dispc_runtime_get(); + if (r) + return r; + + spin_lock_irqsave(&dss_cache.lock, flags); + + /* Configure overlays */ + for (i = 0; i < omap_dss_get_num_overlays(); ++i) { + struct omap_overlay *ovl; + + ovl = omap_dss_get_overlay(i); + + omap_dss_mgr_apply_ovl(ovl); + } + + /* Configure managers */ + list_for_each_entry(mgr, &manager_list, list) + omap_dss_mgr_apply_mgr(mgr); + + /* Configure overlay fifos */ + for (i = 0; i < omap_dss_get_num_overlays(); ++i) { + struct omap_overlay *ovl; + + ovl = omap_dss_get_overlay(i); + + omap_dss_mgr_apply_ovl_fifos(ovl); } r = 0; -- cgit v0.10.2 From d2bbb9bbd1503e8b5235fe316e7ee0c7f41daf7e Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 4 Nov 2011 09:23:10 +0200 Subject: OMAPDSS: apply affects only one overlay manager omap_dss_mgr_apply currently applies settings to all overlays and overlay managers. The reason for this was to support cases where configuration changes affecting multiple managers are made. However, the current code doesn't support changing such configurations, so the functionality is not needed. Change the apply to affect only the manager given as an argument, and the overlays attached to that manager. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index d0d2315..d2bdd65 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -1114,23 +1114,28 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) spin_lock_irqsave(&dss_cache.lock, flags); /* Configure overlays */ - for (i = 0; i < omap_dss_get_num_overlays(); ++i) { + for (i = 0; i < mgr->num_overlays; ++i) { struct omap_overlay *ovl; - ovl = omap_dss_get_overlay(i); + ovl = mgr->overlays[i]; + + if (ovl->manager != mgr) + continue; omap_dss_mgr_apply_ovl(ovl); } - /* Configure managers */ - list_for_each_entry(mgr, &manager_list, list) - omap_dss_mgr_apply_mgr(mgr); + /* Configure manager */ + omap_dss_mgr_apply_mgr(mgr); /* Configure overlay fifos */ - for (i = 0; i < omap_dss_get_num_overlays(); ++i) { + for (i = 0; i < mgr->num_overlays; ++i) { struct omap_overlay *ovl; - ovl = omap_dss_get_overlay(i); + ovl = mgr->overlays[i]; + + if (ovl->manager != mgr) + continue; omap_dss_mgr_apply_ovl_fifos(ovl); } -- cgit v0.10.2 From 58f2554807a7dc627f1583d1d4363b85758cf685 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 4 Nov 2011 09:48:54 +0200 Subject: OMAPDSS: create apply.c Create a new file, apply.c, and move code about handling the apply-mechanism and configuration of the managers and overlays from manager.c to apply.c. Not all related code is moved in this patch, but only the core apply/configure functions. The later patches move rest of the code from overlay.c and manager.c, adding necessary locking at the same time. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile index bd34ac5..8594522 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_OMAP2_DSS) += omapdss.o -omapdss-y := core.o dss.o dss_features.o dispc.o display.o manager.o overlay.o +omapdss-y := core.o dss.o dss_features.o dispc.o display.o manager.o overlay.o \ + apply.o omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c new file mode 100644 index 0000000..c634c98 --- /dev/null +++ b/drivers/video/omap2/dss/apply.c @@ -0,0 +1,656 @@ +/* + * Copyright (C) 2011 Texas Instruments + * Author: Tomi Valkeinen + * + * 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 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, see . + */ + +#define DSS_SUBSYS_NAME "APPLY" + +#include +#include +#include +#include + +#include