Commit 8516f52f authored by Vinod Koul's avatar Vinod Koul Committed by Vinod Koul

Merge branch 'next' into v3.1-rc4

Fixed trivial conflicts  in  drivers/dma/amba-pl08x.c
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
parents c6a389f1 7b4b88e0
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
* OneNAND features. * OneNAND features.
*/ */
#ifndef ASM_PL080_H
#define ASM_PL080_H
#define PL080_INT_STATUS (0x00) #define PL080_INT_STATUS (0x00)
#define PL080_TC_STATUS (0x04) #define PL080_TC_STATUS (0x04)
#define PL080_TC_CLEAR (0x08) #define PL080_TC_CLEAR (0x08)
...@@ -138,3 +141,4 @@ struct pl080s_lli { ...@@ -138,3 +141,4 @@ struct pl080s_lli {
u32 control1; u32 control1;
}; };
#endif /* ASM_PL080_H */
This diff is collapsed.
This diff is collapsed.
...@@ -204,6 +204,9 @@ enum atc_status { ...@@ -204,6 +204,9 @@ enum atc_status {
* @status: transmit status information from irq/prep* functions * @status: transmit status information from irq/prep* functions
* to tasklet (use atomic operations) * to tasklet (use atomic operations)
* @tasklet: bottom half to finish transaction work * @tasklet: bottom half to finish transaction work
* @save_cfg: configuration register that is saved on suspend/resume cycle
* @save_dscr: for cyclic operations, preserve next descriptor address in
* the cyclic list on suspend/resume cycle
* @lock: serializes enqueue/dequeue operations to descriptors lists * @lock: serializes enqueue/dequeue operations to descriptors lists
* @completed_cookie: identifier for the most recently completed operation * @completed_cookie: identifier for the most recently completed operation
* @active_list: list of descriptors dmaengine is being running on * @active_list: list of descriptors dmaengine is being running on
...@@ -218,6 +221,8 @@ struct at_dma_chan { ...@@ -218,6 +221,8 @@ struct at_dma_chan {
u8 mask; u8 mask;
unsigned long status; unsigned long status;
struct tasklet_struct tasklet; struct tasklet_struct tasklet;
u32 save_cfg;
u32 save_dscr;
spinlock_t lock; spinlock_t lock;
...@@ -248,6 +253,7 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan) ...@@ -248,6 +253,7 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan)
* @chan_common: common dmaengine dma_device object members * @chan_common: common dmaengine dma_device object members
* @ch_regs: memory mapped register base * @ch_regs: memory mapped register base
* @clk: dma controller clock * @clk: dma controller clock
* @save_imr: interrupt mask register that is saved on suspend/resume cycle
* @all_chan_mask: all channels availlable in a mask * @all_chan_mask: all channels availlable in a mask
* @dma_desc_pool: base of DMA descriptor region (DMA address) * @dma_desc_pool: base of DMA descriptor region (DMA address)
* @chan: channels table to store at_dma_chan structures * @chan: channels table to store at_dma_chan structures
...@@ -256,6 +262,7 @@ struct at_dma { ...@@ -256,6 +262,7 @@ struct at_dma {
struct dma_device dma_common; struct dma_device dma_common;
void __iomem *regs; void __iomem *regs;
struct clk *clk; struct clk *clk;
u32 save_imr;
u8 all_chan_mask; u8 all_chan_mask;
...@@ -355,6 +362,23 @@ static inline int atc_chan_is_enabled(struct at_dma_chan *atchan) ...@@ -355,6 +362,23 @@ static inline int atc_chan_is_enabled(struct at_dma_chan *atchan)
return !!(dma_readl(atdma, CHSR) & atchan->mask); return !!(dma_readl(atdma, CHSR) & atchan->mask);
} }
/**
* atc_chan_is_paused - test channel pause/resume status
* @atchan: channel we want to test status
*/
static inline int atc_chan_is_paused(struct at_dma_chan *atchan)
{
return test_bit(ATC_IS_PAUSED, &atchan->status);
}
/**
* atc_chan_is_cyclic - test if given channel has cyclic property set
* @atchan: channel we want to test status
*/
static inline int atc_chan_is_cyclic(struct at_dma_chan *atchan)
{
return test_bit(ATC_IS_CYCLIC, &atchan->status);
}
/** /**
* set_desc_eol - set end-of-link to descriptor so it will end transfer * set_desc_eol - set end-of-link to descriptor so it will end transfer
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/freezer.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -251,6 +252,7 @@ static int dmatest_func(void *data) ...@@ -251,6 +252,7 @@ static int dmatest_func(void *data)
int i; int i;
thread_name = current->comm; thread_name = current->comm;
set_freezable_with_signal();
ret = -ENOMEM; ret = -ENOMEM;
...@@ -305,7 +307,8 @@ static int dmatest_func(void *data) ...@@ -305,7 +307,8 @@ static int dmatest_func(void *data)
dma_addr_t dma_srcs[src_cnt]; dma_addr_t dma_srcs[src_cnt];
dma_addr_t dma_dsts[dst_cnt]; dma_addr_t dma_dsts[dst_cnt];
struct completion cmp; struct completion cmp;
unsigned long tmo = msecs_to_jiffies(timeout); unsigned long start, tmo, end = 0 /* compiler... */;
bool reload = true;
u8 align = 0; u8 align = 0;
total_tests++; total_tests++;
...@@ -404,7 +407,17 @@ static int dmatest_func(void *data) ...@@ -404,7 +407,17 @@ static int dmatest_func(void *data)
} }
dma_async_issue_pending(chan); dma_async_issue_pending(chan);
tmo = wait_for_completion_timeout(&cmp, tmo); do {
start = jiffies;
if (reload)
end = start + msecs_to_jiffies(timeout);
else if (end <= start)
end = start + 1;
tmo = wait_for_completion_interruptible_timeout(&cmp,
end - start);
reload = try_to_freeze();
} while (tmo == -ERESTARTSYS);
status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
if (tmo == 0) { if (tmo == 0) {
...@@ -477,6 +490,8 @@ static int dmatest_func(void *data) ...@@ -477,6 +490,8 @@ static int dmatest_func(void *data)
pr_notice("%s: terminating after %u tests, %u failures (status %d)\n", pr_notice("%s: terminating after %u tests, %u failures (status %d)\n",
thread_name, total_tests, failed_tests, ret); thread_name, total_tests, failed_tests, ret);
/* terminate all transfers on specified channels */
chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
if (iterations > 0) if (iterations > 0)
while (!kthread_should_stop()) { while (!kthread_should_stop()) {
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit); DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit);
...@@ -499,6 +514,10 @@ static void dmatest_cleanup_channel(struct dmatest_chan *dtc) ...@@ -499,6 +514,10 @@ static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
list_del(&thread->node); list_del(&thread->node);
kfree(thread); kfree(thread);
} }
/* terminate all transfers on specified channels */
dtc->chan->device->device_control(dtc->chan, DMA_TERMINATE_ALL, 0);
kfree(dtc); kfree(dtc);
} }
......
...@@ -318,6 +318,7 @@ struct sdma_engine { ...@@ -318,6 +318,7 @@ struct sdma_engine {
dma_addr_t context_phys; dma_addr_t context_phys;
struct dma_device dma_device; struct dma_device dma_device;
struct clk *clk; struct clk *clk;
struct mutex channel_0_lock;
struct sdma_script_start_addrs *script_addrs; struct sdma_script_start_addrs *script_addrs;
}; };
...@@ -415,11 +416,15 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size, ...@@ -415,11 +416,15 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
dma_addr_t buf_phys; dma_addr_t buf_phys;
int ret; int ret;
mutex_lock(&sdma->channel_0_lock);
buf_virt = dma_alloc_coherent(NULL, buf_virt = dma_alloc_coherent(NULL,
size, size,
&buf_phys, GFP_KERNEL); &buf_phys, GFP_KERNEL);
if (!buf_virt) if (!buf_virt) {
return -ENOMEM; ret = -ENOMEM;
goto err_out;
}
bd0->mode.command = C0_SETPM; bd0->mode.command = C0_SETPM;
bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD; bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
...@@ -433,6 +438,9 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size, ...@@ -433,6 +438,9 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
dma_free_coherent(NULL, size, buf_virt, buf_phys); dma_free_coherent(NULL, size, buf_virt, buf_phys);
err_out:
mutex_unlock(&sdma->channel_0_lock);
return ret; return ret;
} }
...@@ -656,6 +664,8 @@ static int sdma_load_context(struct sdma_channel *sdmac) ...@@ -656,6 +664,8 @@ static int sdma_load_context(struct sdma_channel *sdmac)
dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", sdmac->event_mask0); dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", sdmac->event_mask0);
dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", sdmac->event_mask1); dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", sdmac->event_mask1);
mutex_lock(&sdma->channel_0_lock);
memset(context, 0, sizeof(*context)); memset(context, 0, sizeof(*context));
context->channel_state.pc = load_address; context->channel_state.pc = load_address;
...@@ -676,6 +686,8 @@ static int sdma_load_context(struct sdma_channel *sdmac) ...@@ -676,6 +686,8 @@ static int sdma_load_context(struct sdma_channel *sdmac)
ret = sdma_run_channel(&sdma->channel[0]); ret = sdma_run_channel(&sdma->channel[0]);
mutex_unlock(&sdma->channel_0_lock);
return ret; return ret;
} }
...@@ -1131,18 +1143,17 @@ static void sdma_add_scripts(struct sdma_engine *sdma, ...@@ -1131,18 +1143,17 @@ static void sdma_add_scripts(struct sdma_engine *sdma,
saddr_arr[i] = addr_arr[i]; saddr_arr[i] = addr_arr[i];
} }
static int __init sdma_get_firmware(struct sdma_engine *sdma, static void sdma_load_firmware(const struct firmware *fw, void *context)
const char *fw_name)
{ {
const struct firmware *fw; struct sdma_engine *sdma = context;
const struct sdma_firmware_header *header; const struct sdma_firmware_header *header;
int ret;
const struct sdma_script_start_addrs *addr; const struct sdma_script_start_addrs *addr;
unsigned short *ram_code; unsigned short *ram_code;
ret = request_firmware(&fw, fw_name, sdma->dev); if (!fw) {
if (ret) dev_err(sdma->dev, "firmware not found\n");
return ret; return;
}
if (fw->size < sizeof(*header)) if (fw->size < sizeof(*header))
goto err_firmware; goto err_firmware;
...@@ -1172,6 +1183,16 @@ static int __init sdma_get_firmware(struct sdma_engine *sdma, ...@@ -1172,6 +1183,16 @@ static int __init sdma_get_firmware(struct sdma_engine *sdma,
err_firmware: err_firmware:
release_firmware(fw); release_firmware(fw);
}
static int __init sdma_get_firmware(struct sdma_engine *sdma,
const char *fw_name)
{
int ret;
ret = request_firmware_nowait(THIS_MODULE,
FW_ACTION_HOTPLUG, fw_name, sdma->dev,
GFP_KERNEL, sdma, sdma_load_firmware);
return ret; return ret;
} }
...@@ -1269,11 +1290,14 @@ static int __init sdma_probe(struct platform_device *pdev) ...@@ -1269,11 +1290,14 @@ static int __init sdma_probe(struct platform_device *pdev)
struct sdma_platform_data *pdata = pdev->dev.platform_data; struct sdma_platform_data *pdata = pdev->dev.platform_data;
int i; int i;
struct sdma_engine *sdma; struct sdma_engine *sdma;
s32 *saddr_arr;
sdma = kzalloc(sizeof(*sdma), GFP_KERNEL); sdma = kzalloc(sizeof(*sdma), GFP_KERNEL);
if (!sdma) if (!sdma)
return -ENOMEM; return -ENOMEM;
mutex_init(&sdma->channel_0_lock);
sdma->dev = &pdev->dev; sdma->dev = &pdev->dev;
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
...@@ -1310,6 +1334,11 @@ static int __init sdma_probe(struct platform_device *pdev) ...@@ -1310,6 +1334,11 @@ static int __init sdma_probe(struct platform_device *pdev)
goto err_alloc; goto err_alloc;
} }
/* initially no scripts available */
saddr_arr = (s32 *)sdma->script_addrs;
for (i = 0; i < SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; i++)
saddr_arr[i] = -EINVAL;
if (of_id) if (of_id)
pdev->id_entry = of_id->data; pdev->id_entry = of_id->data;
sdma->devtype = pdev->id_entry->driver_data; sdma->devtype = pdev->id_entry->driver_data;
......
...@@ -130,6 +130,23 @@ struct mxs_dma_engine { ...@@ -130,6 +130,23 @@ struct mxs_dma_engine {
struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS]; struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS];
}; };
static inline void mxs_dma_clkgate(struct mxs_dma_chan *mxs_chan, int enable)
{
struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
int chan_id = mxs_chan->chan.chan_id;
int set_clr = enable ? MXS_CLR_ADDR : MXS_SET_ADDR;
/* enable apbh channel clock */
if (dma_is_apbh()) {
if (apbh_is_old())
writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
mxs_dma->base + HW_APBHX_CTRL0 + set_clr);
else
writel(1 << chan_id,
mxs_dma->base + HW_APBHX_CTRL0 + set_clr);
}
}
static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan) static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan)
{ {
struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
...@@ -148,38 +165,21 @@ static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan) ...@@ -148,38 +165,21 @@ static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan)
struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
int chan_id = mxs_chan->chan.chan_id; int chan_id = mxs_chan->chan.chan_id;
/* clkgate needs to be enabled before writing other registers */
mxs_dma_clkgate(mxs_chan, 1);
/* set cmd_addr up */ /* set cmd_addr up */
writel(mxs_chan->ccw_phys, writel(mxs_chan->ccw_phys,
mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id)); mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id));
/* enable apbh channel clock */
if (dma_is_apbh()) {
if (apbh_is_old())
writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
else
writel(1 << chan_id,
mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
}
/* write 1 to SEMA to kick off the channel */ /* write 1 to SEMA to kick off the channel */
writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(chan_id)); writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(chan_id));
} }
static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan) static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan)
{ {
struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
int chan_id = mxs_chan->chan.chan_id;
/* disable apbh channel clock */ /* disable apbh channel clock */
if (dma_is_apbh()) { mxs_dma_clkgate(mxs_chan, 0);
if (apbh_is_old())
writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
else
writel(1 << chan_id,
mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
}
mxs_chan->status = DMA_SUCCESS; mxs_chan->status = DMA_SUCCESS;
} }
...@@ -338,7 +338,10 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan) ...@@ -338,7 +338,10 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
if (ret) if (ret)
goto err_clk; goto err_clk;
/* clkgate needs to be enabled for reset to finish */
mxs_dma_clkgate(mxs_chan, 1);
mxs_dma_reset_chan(mxs_chan); mxs_dma_reset_chan(mxs_chan);
mxs_dma_clkgate(mxs_chan, 0);
dma_async_tx_descriptor_init(&mxs_chan->desc, chan); dma_async_tx_descriptor_init(&mxs_chan->desc, chan);
mxs_chan->desc.tx_submit = mxs_dma_tx_submit; mxs_chan->desc.tx_submit = mxs_dma_tx_submit;
......
...@@ -47,6 +47,9 @@ enum { ...@@ -47,6 +47,9 @@ enum {
* @muxval: a number usually used to poke into some mux regiser to * @muxval: a number usually used to poke into some mux regiser to
* mux in the signal to this channel * mux in the signal to this channel
* @cctl_opt: default options for the channel control register * @cctl_opt: default options for the channel control register
* @device_fc: Flow Controller Settings for ccfg register. Only valid for slave
* channels. Fill with 'true' if peripheral should be flow controller. Direction
* will be selected at Runtime.
* @addr: source/target address in physical memory for this DMA channel, * @addr: source/target address in physical memory for this DMA channel,
* can be the address of a FIFO register for burst requests for example. * can be the address of a FIFO register for burst requests for example.
* This can be left undefined if the PrimeCell API is used for configuring * This can be left undefined if the PrimeCell API is used for configuring
...@@ -65,6 +68,7 @@ struct pl08x_channel_data { ...@@ -65,6 +68,7 @@ struct pl08x_channel_data {
int max_signal; int max_signal;
u32 muxval; u32 muxval;
u32 cctl; u32 cctl;
bool device_fc;
dma_addr_t addr; dma_addr_t addr;
bool circular_buffer; bool circular_buffer;
bool single; bool single;
...@@ -77,13 +81,11 @@ struct pl08x_channel_data { ...@@ -77,13 +81,11 @@ struct pl08x_channel_data {
* @addr: current address * @addr: current address
* @maxwidth: the maximum width of a transfer on this bus * @maxwidth: the maximum width of a transfer on this bus
* @buswidth: the width of this bus in bytes: 1, 2 or 4 * @buswidth: the width of this bus in bytes: 1, 2 or 4
* @fill_bytes: bytes required to fill to the next bus memory boundary
*/ */
struct pl08x_bus_data { struct pl08x_bus_data {
dma_addr_t addr; dma_addr_t addr;
u8 maxwidth; u8 maxwidth;
u8 buswidth; u8 buswidth;
size_t fill_bytes;
}; };
/** /**
...@@ -105,8 +107,16 @@ struct pl08x_phy_chan { ...@@ -105,8 +107,16 @@ struct pl08x_phy_chan {
/** /**
* struct pl08x_txd - wrapper for struct dma_async_tx_descriptor * struct pl08x_txd - wrapper for struct dma_async_tx_descriptor
* @tx: async tx descriptor
* @node: node for txd list for channels
* @src_addr: src address of txd
* @dst_addr: dst address of txd
* @len: transfer len in bytes
* @direction: direction of transfer
* @llis_bus: DMA memory address (physical) start for the LLIs * @llis_bus: DMA memory address (physical) start for the LLIs
* @llis_va: virtual memory address start for the LLIs * @llis_va: virtual memory address start for the LLIs
* @cctl: control reg values for current txd
* @ccfg: config reg values for current txd
*/ */
struct pl08x_txd { struct pl08x_txd {
struct dma_async_tx_descriptor tx; struct dma_async_tx_descriptor tx;
......
...@@ -24,8 +24,7 @@ ...@@ -24,8 +24,7 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/dma-direction.h> #include <linux/dma-direction.h>
#include <linux/scatterlist.h>
struct scatterlist;
/** /**
* typedef dma_cookie_t - an opaque DMA cookie * typedef dma_cookie_t - an opaque DMA cookie
...@@ -519,6 +518,16 @@ static inline int dmaengine_slave_config(struct dma_chan *chan, ...@@ -519,6 +518,16 @@ static inline int dmaengine_slave_config(struct dma_chan *chan,
(unsigned long)config); (unsigned long)config);
} }
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)
{
struct scatterlist sg;
sg_init_one(&sg, buf, len);
return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags);
}
static inline int dmaengine_terminate_all(struct dma_chan *chan) static inline int dmaengine_terminate_all(struct dma_chan *chan)
{ {
return dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0); return dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment