You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'dmaengine-4.16-rc1' of git://git.infradead.org/users/vkoul/slave-dma
Pull dmaengine updates from Vinod Koul:
"This time is smallish update with updates mainly to drivers:
- updates to xilinx and zynqmp dma controllers
- update reside calculation for rcar controller
- more RSTify fixes for documentation
- add support for race free transfer termination and updating for
users for that
- support for new rev of hidma with addition new APIs to get device
match data in ACPI/OF
- random updates to bunch of other drivers"
* tag 'dmaengine-4.16-rc1' of git://git.infradead.org/users/vkoul/slave-dma: (47 commits)
dmaengine: dmatest: fix container_of member in dmatest_callback
dmaengine: stm32-dmamux: Remove unnecessary platform_get_resource() error check
dmaengine: sprd: statify 'sprd_dma_prep_dma_memcpy'
dmaengine: qcom_hidma: simplify DT resource parsing
dmaengine: xilinx_dma: Free BD consistent memory
dmaengine: xilinx_dma: Fix warning variable prev set but not used
dmaengine: xilinx_dma: properly configure the SG mode bit in the driver for cdma
dmaengine: doc: format struct fields using monospace
dmaengine: doc: fix bullet list formatting
dmaengine: ti-dma-crossbar: Fix event mapping for TPCC_EVT_MUX_60_63
dmaengine: cppi41: Fix channel queues array size check
dmaengine: imx-sdma: Add MODULE_FIRMWARE
dmaengine: xilinx_dma: Fix typos
dmaengine: xilinx_dma: Differentiate probe based on the ip type
dmaengine: xilinx_dma: fix style issues from checkpatch
dmaengine: xilinx_dma: Fix kernel doc warnings
dmaengine: xilinx_dma: Fix race condition in the driver for multiple descriptor scenario
dmaeninge: xilinx_dma: Fix bug in multiple frame stores scenario in vdma
dmaengine: xilinx_dma: Check for channel idle state before submitting dma descriptor
dmaengine: zynqmp_dma: Fix race condition in the probe
...
This commit is contained in:
@@ -47,8 +47,8 @@ When the OS is not in control of the management interface (i.e. it's a guest),
|
||||
the channel nodes appear on their own, not under a management node.
|
||||
|
||||
Required properties:
|
||||
- compatible: must contain "qcom,hidma-1.0" for initial HW or "qcom,hidma-1.1"
|
||||
for MSI capable HW.
|
||||
- compatible: must contain "qcom,hidma-1.0" for initial HW or
|
||||
"qcom,hidma-1.1"/"qcom,hidma-1.2" for MSI capable HW.
|
||||
- reg: Addresses for the transfer and event channel
|
||||
- interrupts: Should contain the event interrupt
|
||||
- desc-count: Number of asynchronous requests this channel can handle
|
||||
|
||||
@@ -111,40 +111,36 @@ The first thing you need to do in your driver is to allocate this
|
||||
structure. Any of the usual memory allocators will do, but you'll also
|
||||
need to initialize a few fields in there:
|
||||
|
||||
- channels: should be initialized as a list using the
|
||||
- ``channels``: should be initialized as a list using the
|
||||
INIT_LIST_HEAD macro for example
|
||||
|
||||
- src_addr_widths:
|
||||
- ``src_addr_widths``:
|
||||
should contain a bitmask of the supported source transfer width
|
||||
|
||||
- dst_addr_widths:
|
||||
- ``dst_addr_widths``:
|
||||
should contain a bitmask of the supported destination transfer width
|
||||
|
||||
- directions:
|
||||
- ``directions``:
|
||||
should contain a bitmask of the supported slave directions
|
||||
(i.e. excluding mem2mem transfers)
|
||||
|
||||
- residue_granularity:
|
||||
- ``residue_granularity``:
|
||||
granularity of the transfer residue reported to dma_set_residue.
|
||||
This can be either:
|
||||
|
||||
- Granularity of the transfer residue reported to dma_set_residue.
|
||||
This can be either:
|
||||
- Descriptor:
|
||||
your device doesn't support any kind of residue
|
||||
reporting. The framework will only know that a particular
|
||||
transaction descriptor is done.
|
||||
|
||||
- Descriptor
|
||||
- Segment:
|
||||
your device is able to report which chunks have been transferred
|
||||
|
||||
- Your device doesn't support any kind of residue
|
||||
reporting. The framework will only know that a particular
|
||||
transaction descriptor is done.
|
||||
- Burst:
|
||||
your device is able to report which burst have been transferred
|
||||
|
||||
- Segment
|
||||
|
||||
- Your device is able to report which chunks have been transferred
|
||||
|
||||
- Burst
|
||||
|
||||
- Your device is able to report which burst have been transferred
|
||||
|
||||
- dev: should hold the pointer to the ``struct device`` associated
|
||||
to your current driver instance.
|
||||
- ``dev``: should hold the pointer to the ``struct device`` associated
|
||||
to your current driver instance.
|
||||
|
||||
Supported transaction types
|
||||
---------------------------
|
||||
|
||||
@@ -785,6 +785,24 @@ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_match_device);
|
||||
|
||||
void *acpi_get_match_data(const struct device *dev)
|
||||
{
|
||||
const struct acpi_device_id *match;
|
||||
|
||||
if (!dev->driver)
|
||||
return NULL;
|
||||
|
||||
if (!dev->driver->acpi_match_table)
|
||||
return NULL;
|
||||
|
||||
match = acpi_match_device(dev->driver->acpi_match_table, dev);
|
||||
if (!match)
|
||||
return NULL;
|
||||
|
||||
return (void *)match->driver_data;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_get_match_data);
|
||||
|
||||
int acpi_match_device_ids(struct acpi_device *device,
|
||||
const struct acpi_device_id *ids)
|
||||
{
|
||||
|
||||
@@ -1271,9 +1271,17 @@ static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *
|
||||
acpi_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
|
||||
const struct device *dev)
|
||||
{
|
||||
return acpi_get_match_data(dev);
|
||||
}
|
||||
|
||||
#define DECLARE_ACPI_FWNODE_OPS(ops) \
|
||||
const struct fwnode_operations ops = { \
|
||||
.device_is_available = acpi_fwnode_device_is_available, \
|
||||
.device_get_match_data = acpi_fwnode_device_get_match_data, \
|
||||
.property_present = acpi_fwnode_property_present, \
|
||||
.property_read_int_array = \
|
||||
acpi_fwnode_property_read_int_array, \
|
||||
|
||||
@@ -1340,3 +1340,10 @@ int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
|
||||
return fwnode_call_int_op(fwnode, graph_parse_endpoint, endpoint);
|
||||
}
|
||||
EXPORT_SYMBOL(fwnode_graph_parse_endpoint);
|
||||
|
||||
void *device_get_match_data(struct device *dev)
|
||||
{
|
||||
return fwnode_call_ptr_op(dev_fwnode(dev), device_get_match_data,
|
||||
dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_get_match_data);
|
||||
|
||||
@@ -2182,7 +2182,7 @@ static int pl08x_terminate_all(struct dma_chan *chan)
|
||||
}
|
||||
/* Dequeue jobs and free LLIs */
|
||||
if (plchan->at) {
|
||||
pl08x_desc_free(&plchan->at->vd);
|
||||
vchan_terminate_vdesc(&plchan->at->vd);
|
||||
plchan->at = NULL;
|
||||
}
|
||||
/* Dequeue jobs not yet fired as well */
|
||||
@@ -2193,6 +2193,13 @@ static int pl08x_terminate_all(struct dma_chan *chan)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pl08x_synchronize(struct dma_chan *chan)
|
||||
{
|
||||
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
|
||||
|
||||
vchan_synchronize(&plchan->vc);
|
||||
}
|
||||
|
||||
static int pl08x_pause(struct dma_chan *chan)
|
||||
{
|
||||
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
|
||||
@@ -2773,6 +2780,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
pl08x->memcpy.device_pause = pl08x_pause;
|
||||
pl08x->memcpy.device_resume = pl08x_resume;
|
||||
pl08x->memcpy.device_terminate_all = pl08x_terminate_all;
|
||||
pl08x->memcpy.device_synchronize = pl08x_synchronize;
|
||||
pl08x->memcpy.src_addr_widths = PL80X_DMA_BUSWIDTHS;
|
||||
pl08x->memcpy.dst_addr_widths = PL80X_DMA_BUSWIDTHS;
|
||||
pl08x->memcpy.directions = BIT(DMA_MEM_TO_MEM);
|
||||
@@ -2802,6 +2810,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
pl08x->slave.device_pause = pl08x_pause;
|
||||
pl08x->slave.device_resume = pl08x_resume;
|
||||
pl08x->slave.device_terminate_all = pl08x_terminate_all;
|
||||
pl08x->slave.device_synchronize = pl08x_synchronize;
|
||||
pl08x->slave.src_addr_widths = PL80X_DMA_BUSWIDTHS;
|
||||
pl08x->slave.dst_addr_widths = PL80X_DMA_BUSWIDTHS;
|
||||
pl08x->slave.directions =
|
||||
|
||||
@@ -812,7 +812,7 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan)
|
||||
* c->desc is NULL and exit.)
|
||||
*/
|
||||
if (c->desc) {
|
||||
bcm2835_dma_desc_free(&c->desc->vd);
|
||||
vchan_terminate_vdesc(&c->desc->vd);
|
||||
c->desc = NULL;
|
||||
bcm2835_dma_abort(c->chan_base);
|
||||
|
||||
@@ -836,6 +836,13 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bcm2835_dma_synchronize(struct dma_chan *chan)
|
||||
{
|
||||
struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
|
||||
|
||||
vchan_synchronize(&c->vc);
|
||||
}
|
||||
|
||||
static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id,
|
||||
int irq, unsigned int irq_flags)
|
||||
{
|
||||
@@ -942,6 +949,7 @@ static int bcm2835_dma_probe(struct platform_device *pdev)
|
||||
od->ddev.device_prep_dma_memcpy = bcm2835_dma_prep_dma_memcpy;
|
||||
od->ddev.device_config = bcm2835_dma_slave_config;
|
||||
od->ddev.device_terminate_all = bcm2835_dma_terminate_all;
|
||||
od->ddev.device_synchronize = bcm2835_dma_synchronize;
|
||||
od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
|
||||
od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
|
||||
od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV) |
|
||||
|
||||
@@ -934,7 +934,7 @@ static bool cpp41_dma_filter_fn(struct dma_chan *chan, void *param)
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(am335x_usb_queues_rx) !=
|
||||
ARRAY_SIZE(am335x_usb_queues_tx));
|
||||
if (WARN_ON(cchan->port_num > ARRAY_SIZE(am335x_usb_queues_rx)))
|
||||
if (WARN_ON(cchan->port_num >= ARRAY_SIZE(am335x_usb_queues_rx)))
|
||||
return false;
|
||||
|
||||
cchan->q_num = queues[cchan->port_num].submit;
|
||||
|
||||
@@ -511,7 +511,7 @@ static int jz4780_dma_terminate_all(struct dma_chan *chan)
|
||||
/* Clear the DMA status and stop the transfer. */
|
||||
jz4780_dma_writel(jzdma, JZ_DMA_REG_DCS(jzchan->id), 0);
|
||||
if (jzchan->desc) {
|
||||
jz4780_dma_desc_free(&jzchan->desc->vdesc);
|
||||
vchan_terminate_vdesc(&jzchan->desc->vdesc);
|
||||
jzchan->desc = NULL;
|
||||
}
|
||||
|
||||
@@ -523,6 +523,13 @@ static int jz4780_dma_terminate_all(struct dma_chan *chan)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void jz4780_dma_synchronize(struct dma_chan *chan)
|
||||
{
|
||||
struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(chan);
|
||||
|
||||
vchan_synchronize(&jzchan->vchan);
|
||||
}
|
||||
|
||||
static int jz4780_dma_config(struct dma_chan *chan,
|
||||
struct dma_slave_config *config)
|
||||
{
|
||||
@@ -813,6 +820,7 @@ static int jz4780_dma_probe(struct platform_device *pdev)
|
||||
dd->device_prep_dma_memcpy = jz4780_dma_prep_dma_memcpy;
|
||||
dd->device_config = jz4780_dma_config;
|
||||
dd->device_terminate_all = jz4780_dma_terminate_all;
|
||||
dd->device_synchronize = jz4780_dma_synchronize;
|
||||
dd->device_tx_status = jz4780_dma_tx_status;
|
||||
dd->device_issue_pending = jz4780_dma_issue_pending;
|
||||
dd->src_addr_widths = JZ_DMA_BUSWIDTHS;
|
||||
|
||||
@@ -355,7 +355,7 @@ static void dmatest_callback(void *arg)
|
||||
{
|
||||
struct dmatest_done *done = arg;
|
||||
struct dmatest_thread *thread =
|
||||
container_of(arg, struct dmatest_thread, done_wait);
|
||||
container_of(done, struct dmatest_thread, test_done);
|
||||
if (!thread->done) {
|
||||
done->done = true;
|
||||
wake_up_all(done->wait);
|
||||
|
||||
+2
-5
@@ -860,11 +860,8 @@ static int edma_terminate_all(struct dma_chan *chan)
|
||||
/* Move the cyclic channel back to default queue */
|
||||
if (!echan->tc && echan->edesc->cyclic)
|
||||
edma_assign_channel_eventq(echan, EVENTQ_DEFAULT);
|
||||
/*
|
||||
* free the running request descriptor
|
||||
* since it is not in any of the vdesc lists
|
||||
*/
|
||||
edma_desc_free(&echan->edesc->vdesc);
|
||||
|
||||
vchan_terminate_vdesc(&echan->edesc->vdesc);
|
||||
echan->edesc = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -694,7 +694,6 @@ static unsigned int mdc_get_new_events(struct mdc_chan *mchan)
|
||||
static int mdc_terminate_all(struct dma_chan *chan)
|
||||
{
|
||||
struct mdc_chan *mchan = to_mdc_chan(chan);
|
||||
struct mdc_tx_desc *mdesc;
|
||||
unsigned long flags;
|
||||
LIST_HEAD(head);
|
||||
|
||||
@@ -703,21 +702,28 @@ static int mdc_terminate_all(struct dma_chan *chan)
|
||||
mdc_chan_writel(mchan, MDC_CONTROL_AND_STATUS_CANCEL,
|
||||
MDC_CONTROL_AND_STATUS);
|
||||
|
||||
mdesc = mchan->desc;
|
||||
mchan->desc = NULL;
|
||||
if (mchan->desc) {
|
||||
vchan_terminate_vdesc(&mchan->desc->vd);
|
||||
mchan->desc = NULL;
|
||||
}
|
||||
vchan_get_all_descriptors(&mchan->vc, &head);
|
||||
|
||||
mdc_get_new_events(mchan);
|
||||
|
||||
spin_unlock_irqrestore(&mchan->vc.lock, flags);
|
||||
|
||||
if (mdesc)
|
||||
mdc_desc_free(&mdesc->vd);
|
||||
vchan_dma_desc_free_list(&mchan->vc, &head);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mdc_synchronize(struct dma_chan *chan)
|
||||
{
|
||||
struct mdc_chan *mchan = to_mdc_chan(chan);
|
||||
|
||||
vchan_synchronize(&mchan->vc);
|
||||
}
|
||||
|
||||
static int mdc_slave_config(struct dma_chan *chan,
|
||||
struct dma_slave_config *config)
|
||||
{
|
||||
@@ -952,6 +958,7 @@ static int mdc_dma_probe(struct platform_device *pdev)
|
||||
mdma->dma_dev.device_tx_status = mdc_tx_status;
|
||||
mdma->dma_dev.device_issue_pending = mdc_issue_pending;
|
||||
mdma->dma_dev.device_terminate_all = mdc_terminate_all;
|
||||
mdma->dma_dev.device_synchronize = mdc_synchronize;
|
||||
mdma->dma_dev.device_config = mdc_slave_config;
|
||||
|
||||
mdma->dma_dev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
|
||||
|
||||
@@ -1939,4 +1939,10 @@ module_platform_driver(sdma_driver);
|
||||
|
||||
MODULE_AUTHOR("Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>");
|
||||
MODULE_DESCRIPTION("i.MX SDMA driver");
|
||||
#if IS_ENABLED(CONFIG_SOC_IMX6Q)
|
||||
MODULE_FIRMWARE("imx/sdma/sdma-imx6q.bin");
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SOC_IMX7D)
|
||||
MODULE_FIRMWARE("imx/sdma/sdma-imx7d.bin");
|
||||
#endif
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
+9
-1
@@ -719,7 +719,7 @@ static int k3_dma_terminate_all(struct dma_chan *chan)
|
||||
c->phy = NULL;
|
||||
p->vchan = NULL;
|
||||
if (p->ds_run) {
|
||||
k3_dma_free_desc(&p->ds_run->vd);
|
||||
vchan_terminate_vdesc(&p->ds_run->vd);
|
||||
p->ds_run = NULL;
|
||||
}
|
||||
p->ds_done = NULL;
|
||||
@@ -730,6 +730,13 @@ static int k3_dma_terminate_all(struct dma_chan *chan)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void k3_dma_synchronize(struct dma_chan *chan)
|
||||
{
|
||||
struct k3_dma_chan *c = to_k3_chan(chan);
|
||||
|
||||
vchan_synchronize(&c->vc);
|
||||
}
|
||||
|
||||
static int k3_dma_transfer_pause(struct dma_chan *chan)
|
||||
{
|
||||
struct k3_dma_chan *c = to_k3_chan(chan);
|
||||
@@ -868,6 +875,7 @@ static int k3_dma_probe(struct platform_device *op)
|
||||
d->slave.device_pause = k3_dma_transfer_pause;
|
||||
d->slave.device_resume = k3_dma_transfer_resume;
|
||||
d->slave.device_terminate_all = k3_dma_terminate_all;
|
||||
d->slave.device_synchronize = k3_dma_synchronize;
|
||||
d->slave.copy_align = DMAENGINE_ALIGN_8_BYTES;
|
||||
|
||||
/* init virtual channel */
|
||||
|
||||
@@ -480,9 +480,7 @@ static int mic_dma_setup_irq(struct mic_dma_chan *ch)
|
||||
to_mbus_hw_ops(ch)->request_threaded_irq(to_mbus_device(ch),
|
||||
mic_dma_intr_handler, mic_dma_thread_fn,
|
||||
"mic dma_channel", ch, ch->ch_num);
|
||||
if (IS_ERR(ch->cookie))
|
||||
return PTR_ERR(ch->cookie);
|
||||
return 0;
|
||||
return PTR_ERR_OR_ZERO(ch->cookie);
|
||||
}
|
||||
|
||||
static inline void mic_dma_free_irq(struct mic_dma_chan *ch)
|
||||
|
||||
@@ -1311,7 +1311,7 @@ static int omap_dma_terminate_all(struct dma_chan *chan)
|
||||
* c->desc is NULL and exit.)
|
||||
*/
|
||||
if (c->desc) {
|
||||
omap_dma_desc_free(&c->desc->vd);
|
||||
vchan_terminate_vdesc(&c->desc->vd);
|
||||
c->desc = NULL;
|
||||
/* Avoid stopping the dma twice */
|
||||
if (!c->paused)
|
||||
|
||||
+19
-22
@@ -50,6 +50,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/of_dma.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/acpi.h>
|
||||
@@ -104,6 +105,10 @@ static unsigned int nr_desc_prm;
|
||||
module_param(nr_desc_prm, uint, 0644);
|
||||
MODULE_PARM_DESC(nr_desc_prm, "number of descriptors (default: 0)");
|
||||
|
||||
enum hidma_cap {
|
||||
HIDMA_MSI_CAP = 1,
|
||||
HIDMA_IDENTITY_CAP,
|
||||
};
|
||||
|
||||
/* process completed descriptors */
|
||||
static void hidma_process_completed(struct hidma_chan *mchan)
|
||||
@@ -736,25 +741,12 @@ static int hidma_request_msi(struct hidma_dev *dmadev,
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool hidma_msi_capable(struct device *dev)
|
||||
static bool hidma_test_capability(struct device *dev, enum hidma_cap test_cap)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(dev);
|
||||
const char *of_compat;
|
||||
int ret = -EINVAL;
|
||||
enum hidma_cap cap;
|
||||
|
||||
if (!adev || acpi_disabled) {
|
||||
ret = device_property_read_string(dev, "compatible",
|
||||
&of_compat);
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
ret = strcmp(of_compat, "qcom,hidma-1.1");
|
||||
} else {
|
||||
#ifdef CONFIG_ACPI
|
||||
ret = strcmp(acpi_device_hid(adev), "QCOM8062");
|
||||
#endif
|
||||
}
|
||||
return ret == 0;
|
||||
cap = (enum hidma_cap) device_get_match_data(dev);
|
||||
return cap ? ((cap & test_cap) > 0) : 0;
|
||||
}
|
||||
|
||||
static int hidma_probe(struct platform_device *pdev)
|
||||
@@ -834,8 +826,7 @@ static int hidma_probe(struct platform_device *pdev)
|
||||
* Determine the MSI capability of the platform. Old HW doesn't
|
||||
* support MSI.
|
||||
*/
|
||||
msi = hidma_msi_capable(&pdev->dev);
|
||||
|
||||
msi = hidma_test_capability(&pdev->dev, HIDMA_MSI_CAP);
|
||||
device_property_read_u32(&pdev->dev, "desc-count",
|
||||
&dmadev->nr_descriptors);
|
||||
|
||||
@@ -848,7 +839,10 @@ static int hidma_probe(struct platform_device *pdev)
|
||||
if (!dmadev->nr_descriptors)
|
||||
dmadev->nr_descriptors = HIDMA_NR_DEFAULT_DESC;
|
||||
|
||||
dmadev->chidx = readl(dmadev->dev_trca + 0x28);
|
||||
if (hidma_test_capability(&pdev->dev, HIDMA_IDENTITY_CAP))
|
||||
dmadev->chidx = readl(dmadev->dev_trca + 0x40);
|
||||
else
|
||||
dmadev->chidx = readl(dmadev->dev_trca + 0x28);
|
||||
|
||||
/* Set DMA mask to 64 bits. */
|
||||
rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
|
||||
@@ -953,7 +947,8 @@ static int hidma_remove(struct platform_device *pdev)
|
||||
#if IS_ENABLED(CONFIG_ACPI)
|
||||
static const struct acpi_device_id hidma_acpi_ids[] = {
|
||||
{"QCOM8061"},
|
||||
{"QCOM8062"},
|
||||
{"QCOM8062", HIDMA_MSI_CAP},
|
||||
{"QCOM8063", (HIDMA_MSI_CAP | HIDMA_IDENTITY_CAP)},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, hidma_acpi_ids);
|
||||
@@ -961,7 +956,9 @@ MODULE_DEVICE_TABLE(acpi, hidma_acpi_ids);
|
||||
|
||||
static const struct of_device_id hidma_match[] = {
|
||||
{.compatible = "qcom,hidma-1.0",},
|
||||
{.compatible = "qcom,hidma-1.1",},
|
||||
{.compatible = "qcom,hidma-1.1", .data = (void *)(HIDMA_MSI_CAP),},
|
||||
{.compatible = "qcom,hidma-1.2",
|
||||
.data = (void *)(HIDMA_MSI_CAP | HIDMA_IDENTITY_CAP),},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, hidma_match);
|
||||
|
||||
@@ -393,6 +393,8 @@ static int hidma_ll_reset(struct hidma_lldev *lldev)
|
||||
*/
|
||||
static void hidma_ll_int_handler_internal(struct hidma_lldev *lldev, int cause)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
|
||||
if (cause & HIDMA_ERR_INT_MASK) {
|
||||
dev_err(lldev->dev, "error 0x%x, disabling...\n",
|
||||
cause);
|
||||
@@ -410,6 +412,10 @@ static void hidma_ll_int_handler_internal(struct hidma_lldev *lldev, int cause)
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&lldev->lock, irqflags);
|
||||
writel_relaxed(cause, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
|
||||
spin_unlock_irqrestore(&lldev->lock, irqflags);
|
||||
|
||||
/*
|
||||
* Fine tuned for this HW...
|
||||
*
|
||||
@@ -421,9 +427,6 @@ static void hidma_ll_int_handler_internal(struct hidma_lldev *lldev, int cause)
|
||||
* Try to consume as many EVREs as possible.
|
||||
*/
|
||||
hidma_handle_tre_completion(lldev);
|
||||
|
||||
/* We consumed TREs or there are pending TREs or EVREs. */
|
||||
writel_relaxed(cause, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
|
||||
}
|
||||
|
||||
irqreturn_t hidma_ll_inthandler(int chirq, void *arg)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/module.h>
|
||||
@@ -356,59 +357,29 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
|
||||
{
|
||||
struct platform_device *pdev_parent = of_find_device_by_node(np);
|
||||
struct platform_device_info pdevinfo;
|
||||
struct of_phandle_args out_irq;
|
||||
struct device_node *child;
|
||||
struct resource *res = NULL;
|
||||
const __be32 *cell;
|
||||
int ret = 0, size, i, num;
|
||||
u64 addr, addr_size;
|
||||
struct resource *res;
|
||||
int ret = 0;
|
||||
|
||||
/* allocate a resource array */
|
||||
res = kcalloc(3, sizeof(*res), GFP_KERNEL);
|
||||
if (!res)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_available_child_of_node(np, child) {
|
||||
struct resource *res_iter;
|
||||
struct platform_device *new_pdev;
|
||||
|
||||
cell = of_get_property(child, "reg", &size);
|
||||
if (!cell) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
size /= sizeof(*cell);
|
||||
num = size /
|
||||
(of_n_addr_cells(child) + of_n_size_cells(child)) + 1;
|
||||
|
||||
/* allocate a resource array */
|
||||
res = kcalloc(num, sizeof(*res), GFP_KERNEL);
|
||||
if (!res) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* read each reg value */
|
||||
i = 0;
|
||||
res_iter = res;
|
||||
while (i < size) {
|
||||
addr = of_read_number(&cell[i],
|
||||
of_n_addr_cells(child));
|
||||
i += of_n_addr_cells(child);
|
||||
|
||||
addr_size = of_read_number(&cell[i],
|
||||
of_n_size_cells(child));
|
||||
i += of_n_size_cells(child);
|
||||
|
||||
res_iter->start = addr;
|
||||
res_iter->end = res_iter->start + addr_size - 1;
|
||||
res_iter->flags = IORESOURCE_MEM;
|
||||
res_iter++;
|
||||
}
|
||||
|
||||
ret = of_irq_parse_one(child, 0, &out_irq);
|
||||
if (ret)
|
||||
ret = of_address_to_resource(child, 0, &res[0]);
|
||||
if (!ret)
|
||||
goto out;
|
||||
|
||||
res_iter->start = irq_create_of_mapping(&out_irq);
|
||||
res_iter->name = "hidma event irq";
|
||||
res_iter->flags = IORESOURCE_IRQ;
|
||||
ret = of_address_to_resource(child, 1, &res[1]);
|
||||
if (!ret)
|
||||
goto out;
|
||||
|
||||
ret = of_irq_to_resource(child, 0, &res[2]);
|
||||
if (ret <= 0)
|
||||
goto out;
|
||||
|
||||
memset(&pdevinfo, 0, sizeof(pdevinfo));
|
||||
pdevinfo.fwnode = &child->fwnode;
|
||||
@@ -416,7 +387,7 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
|
||||
pdevinfo.name = child->name;
|
||||
pdevinfo.id = object_counter++;
|
||||
pdevinfo.res = res;
|
||||
pdevinfo.num_res = num;
|
||||
pdevinfo.num_res = 3;
|
||||
pdevinfo.data = NULL;
|
||||
pdevinfo.size_data = 0;
|
||||
pdevinfo.dma_mask = DMA_BIT_MASK(64);
|
||||
@@ -434,8 +405,6 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
|
||||
*/
|
||||
of_msi_configure(&new_pdev->dev, child);
|
||||
of_node_put(child);
|
||||
kfree(res);
|
||||
res = NULL;
|
||||
}
|
||||
out:
|
||||
kfree(res);
|
||||
|
||||
@@ -732,7 +732,7 @@ static int s3c24xx_dma_terminate_all(struct dma_chan *chan)
|
||||
|
||||
/* Dequeue current job */
|
||||
if (s3cchan->at) {
|
||||
s3c24xx_dma_desc_free(&s3cchan->at->vd);
|
||||
vchan_terminate_vdesc(&s3cchan->at->vd);
|
||||
s3cchan->at = NULL;
|
||||
}
|
||||
|
||||
@@ -744,6 +744,13 @@ unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void s3c24xx_dma_synchronize(struct dma_chan *chan)
|
||||
{
|
||||
struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan);
|
||||
|
||||
vchan_synchronize(&s3cchan->vc);
|
||||
}
|
||||
|
||||
static void s3c24xx_dma_free_chan_resources(struct dma_chan *chan)
|
||||
{
|
||||
/* Ensure all queued descriptors are freed */
|
||||
@@ -1282,6 +1289,7 @@ static int s3c24xx_dma_probe(struct platform_device *pdev)
|
||||
s3cdma->memcpy.device_issue_pending = s3c24xx_dma_issue_pending;
|
||||
s3cdma->memcpy.device_config = s3c24xx_dma_set_runtime_config;
|
||||
s3cdma->memcpy.device_terminate_all = s3c24xx_dma_terminate_all;
|
||||
s3cdma->memcpy.device_synchronize = s3c24xx_dma_synchronize;
|
||||
|
||||
/* Initialize slave engine for SoC internal dedicated peripherals */
|
||||
dma_cap_set(DMA_SLAVE, s3cdma->slave.cap_mask);
|
||||
@@ -1296,6 +1304,7 @@ static int s3c24xx_dma_probe(struct platform_device *pdev)
|
||||
s3cdma->slave.device_prep_dma_cyclic = s3c24xx_dma_prep_dma_cyclic;
|
||||
s3cdma->slave.device_config = s3c24xx_dma_set_runtime_config;
|
||||
s3cdma->slave.device_terminate_all = s3c24xx_dma_terminate_all;
|
||||
s3cdma->slave.device_synchronize = s3c24xx_dma_synchronize;
|
||||
s3cdma->slave.filter.map = pdata->slave_map;
|
||||
s3cdma->slave.filter.mapcnt = pdata->slavecnt;
|
||||
s3cdma->slave.filter.fn = s3c24xx_dma_filter;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user