Commit ca2a650f authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma

Pull slave-dma updates from Vinod Koul:
 - new driver for BCM2835 used in R-pi
 - new driver for MOXA ART
 - dma_get_any_slave_channel API for DT based systems
 - minor fixes and updates spread acrooss driver

[ The fsl-ssi dual fifo mode support addition clashed badly with the
  other changes to fsl-ssi that came in through the sound merge.  I did
  a very rough cut at fixing up the conflict, but Nicolin Chen (author
  of both sides) will need to verify and check things ]

* 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma: (36 commits)
  dmaengine: mmp_pdma: fix mismerge
  dma: pl08x: Export pl08x_filter_id
  acpi-dma: align documentation with kernel-doc format
  dma: fix vchan_cookie_complete() debug print
  DMA: dmatest: extend the "device" module parameter to 32 characters
  drivers/dma: fix error return code
  dma: omap: Set debug level to debugging messages
  dmaengine: fix kernel-doc style typos for few comments
  dma: tegra: add support for Tegra148/124
  dma: dw: use %pad instead of casting dma_addr_t
  dma: dw: join split up messages
  dma: dw: fix style of multiline comment
  dmaengine: k3dma: fix sparse warnings
  dma: pl330: Use dma_get_slave_channel() in the of xlate callback
  dma: pl330: Differentiate between submitted and issued descriptors
  dmaengine: sirf: Add device_slave_caps interface
  DMA: Freescale: change BWC from 256 bytes to 1024 bytes
  dmaengine: Add MOXA ART DMA engine driver
  dmaengine: Add DMA_PRIVATE to BCM2835 driver
  dma: imx-sdma: Assign a default script number for ROM firmware cases
  ...
parents e9e352e9 15cec530
* BCM2835 DMA controller
The BCM2835 DMA controller has 16 channels in total.
Only the lower 13 channels have an associated IRQ.
Some arbitrary channels are used by the firmware
(1,3,6,7 in the current firmware version).
The channels 0,2 and 3 have special functionality
and should not be used by the driver.
Required properties:
- compatible: Should be "brcm,bcm2835-dma".
- reg: Should contain DMA registers location and length.
- interrupts: Should contain the DMA interrupts associated
to the DMA channels in ascending order.
- #dma-cells: Must be <1>, the cell in the dmas property of the
client device represents the DREQ number.
- brcm,dma-channel-mask: Bit mask representing the channels
not used by the firmware in ascending order,
i.e. first channel corresponds to LSB.
Example:
dma: dma@7e007000 {
compatible = "brcm,bcm2835-dma";
reg = <0x7e007000 0xf00>;
interrupts = <1 16>,
<1 17>,
<1 18>,
<1 19>,
<1 20>,
<1 21>,
<1 22>,
<1 23>,
<1 24>,
<1 25>,
<1 26>,
<1 27>,
<1 28>;
#dma-cells = <1>;
brcm,dma-channel-mask = <0x7f35>;
};
DMA clients connected to the BCM2835 DMA controller must use the format
described in the dma.txt file, using a two-cell specifier for each channel.
Example:
bcm2835_i2s: i2s@7e203000 {
compatible = "brcm,bcm2835-i2s";
reg = < 0x7e203000 0x20>,
< 0x7e101098 0x02>;
dmas = <&dma 2>,
<&dma 3>;
dma-names = "tx", "rx";
};
...@@ -42,6 +42,7 @@ The full ID of peripheral types can be found below. ...@@ -42,6 +42,7 @@ The full ID of peripheral types can be found below.
19 IPU Memory 19 IPU Memory
20 ASRC 20 ASRC
21 ESAI 21 ESAI
22 SSI Dual FIFO (needs firmware ver >= 2)
The third cell specifies the transfer priority as below. The third cell specifies the transfer priority as below.
......
MOXA ART DMA Controller
See dma.txt first
Required properties:
- compatible : Must be "moxa,moxart-dma"
- reg : Should contain registers location and length
- interrupts : Should contain an interrupt-specifier for the sole
interrupt generated by the device
- #dma-cells : Should be 1, a single cell holding a line request number
Example:
dma: dma@90500000 {
compatible = "moxa,moxart-dma";
reg = <0x90500080 0x40>;
interrupts = <24 0>;
#dma-cells = <1>;
};
Clients:
DMA clients connected to the MOXA ART DMA controller must use the format
described in the dma.txt file, using a two-cell specifier for each channel:
a phandle plus one integer cells.
The two cells in order are:
1. A phandle pointing to the DMA controller.
2. Peripheral identifier for the hardware handshaking interface.
Example:
Use specific request line passing from dma
For example, MMC request line is 5
sdhci: sdhci@98e00000 {
compatible = "moxa,moxart-sdhci";
reg = <0x98e00000 0x5C>;
interrupts = <5 0>;
clocks = <&clk_apb>;
dmas = <&dma 5>,
<&dma 5>;
dma-names = "tx", "rx";
};
...@@ -306,6 +306,12 @@ config DMA_OMAP ...@@ -306,6 +306,12 @@ config DMA_OMAP
select DMA_ENGINE select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS select DMA_VIRTUAL_CHANNELS
config DMA_BCM2835
tristate "BCM2835 DMA engine support"
depends on (ARCH_BCM2835 || MACH_BCM2708)
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
config TI_CPPI41 config TI_CPPI41
tristate "AM33xx CPPI41 DMA support" tristate "AM33xx CPPI41 DMA support"
depends on ARCH_OMAP depends on ARCH_OMAP
...@@ -336,6 +342,14 @@ config K3_DMA ...@@ -336,6 +342,14 @@ config K3_DMA
Support the DMA engine for Hisilicon K3 platform Support the DMA engine for Hisilicon K3 platform
devices. devices.
config MOXART_DMA
tristate "MOXART DMA support"
depends on ARCH_MOXART
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
help
Enable support for the MOXA ART SoC DMA controller.
config DMA_ENGINE config DMA_ENGINE
bool bool
......
...@@ -38,7 +38,9 @@ obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o ...@@ -38,7 +38,9 @@ obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o
obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o
obj-$(CONFIG_DMA_OMAP) += omap-dma.o obj-$(CONFIG_DMA_OMAP) += omap-dma.o
obj-$(CONFIG_DMA_BCM2835) += bcm2835-dma.o
obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o
obj-$(CONFIG_TI_CPPI41) += cppi41.o obj-$(CONFIG_TI_CPPI41) += cppi41.o
obj-$(CONFIG_K3_DMA) += k3dma.o obj-$(CONFIG_K3_DMA) += k3dma.o
obj-$(CONFIG_MOXART_DMA) += moxart-dma.o
...@@ -30,11 +30,12 @@ static DEFINE_MUTEX(acpi_dma_lock); ...@@ -30,11 +30,12 @@ static DEFINE_MUTEX(acpi_dma_lock);
* @adev: ACPI device to match with * @adev: ACPI device to match with
* @adma: struct acpi_dma of the given DMA controller * @adma: struct acpi_dma of the given DMA controller
* *
* Returns 1 on success, 0 when no information is available, or appropriate
* errno value on error.
*
* In order to match a device from DSDT table to the corresponding CSRT device * In order to match a device from DSDT table to the corresponding CSRT device
* we use MMIO address and IRQ. * we use MMIO address and IRQ.
*
* Return:
* 1 on success, 0 when no information is available, or appropriate errno value
* on error.
*/ */
static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp, static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp,
struct acpi_device *adev, struct acpi_dma *adma) struct acpi_device *adev, struct acpi_dma *adma)
...@@ -101,7 +102,6 @@ static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp, ...@@ -101,7 +102,6 @@ static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp,
* *
* We are using this table to get the request line range of the specific DMA * We are using this table to get the request line range of the specific DMA
* controller to be used later. * controller to be used later.
*
*/ */
static void acpi_dma_parse_csrt(struct acpi_device *adev, struct acpi_dma *adma) static void acpi_dma_parse_csrt(struct acpi_device *adev, struct acpi_dma *adma)
{ {
...@@ -141,10 +141,11 @@ static void acpi_dma_parse_csrt(struct acpi_device *adev, struct acpi_dma *adma) ...@@ -141,10 +141,11 @@ static void acpi_dma_parse_csrt(struct acpi_device *adev, struct acpi_dma *adma)
* @data pointer to controller specific data to be used by * @data pointer to controller specific data to be used by
* translation function * translation function
* *
* Returns 0 on success or appropriate errno value on error.
*
* Allocated memory should be freed with appropriate acpi_dma_controller_free() * Allocated memory should be freed with appropriate acpi_dma_controller_free()
* call. * call.
*
* Return:
* 0 on success or appropriate errno value on error.
*/ */
int acpi_dma_controller_register(struct device *dev, int acpi_dma_controller_register(struct device *dev,
struct dma_chan *(*acpi_dma_xlate) struct dma_chan *(*acpi_dma_xlate)
...@@ -188,6 +189,9 @@ EXPORT_SYMBOL_GPL(acpi_dma_controller_register); ...@@ -188,6 +189,9 @@ EXPORT_SYMBOL_GPL(acpi_dma_controller_register);
* @dev: struct device of DMA controller * @dev: struct device of DMA controller
* *
* Memory allocated by acpi_dma_controller_register() is freed here. * Memory allocated by acpi_dma_controller_register() is freed here.
*
* Return:
* 0 on success or appropriate errno value on error.
*/ */
int acpi_dma_controller_free(struct device *dev) int acpi_dma_controller_free(struct device *dev)
{ {
...@@ -225,6 +229,9 @@ static void devm_acpi_dma_release(struct device *dev, void *res) ...@@ -225,6 +229,9 @@ static void devm_acpi_dma_release(struct device *dev, void *res)
* Managed acpi_dma_controller_register(). DMA controller registered by this * Managed acpi_dma_controller_register(). DMA controller registered by this
* function are automatically freed on driver detach. See * function are automatically freed on driver detach. See
* acpi_dma_controller_register() for more information. * acpi_dma_controller_register() for more information.
*
* Return:
* 0 on success or appropriate errno value on error.
*/ */
int devm_acpi_dma_controller_register(struct device *dev, int devm_acpi_dma_controller_register(struct device *dev,
struct dma_chan *(*acpi_dma_xlate) struct dma_chan *(*acpi_dma_xlate)
...@@ -267,8 +274,6 @@ EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_free); ...@@ -267,8 +274,6 @@ EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_free);
* @adma: struct acpi_dma of DMA controller * @adma: struct acpi_dma of DMA controller
* @dma_spec: dma specifier to update * @dma_spec: dma specifier to update
* *
* Returns 0, if no information is avaiable, -1 on mismatch, and 1 otherwise.
*
* Accordingly to ACPI 5.0 Specification Table 6-170 "Fixed DMA Resource * Accordingly to ACPI 5.0 Specification Table 6-170 "Fixed DMA Resource
* Descriptor": * Descriptor":
* DMA Request Line bits is a platform-relative number uniquely * DMA Request Line bits is a platform-relative number uniquely
...@@ -276,6 +281,9 @@ EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_free); ...@@ -276,6 +281,9 @@ EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_free);
* mapping is done in a controller-specific OS driver. * mapping is done in a controller-specific OS driver.
* That's why we can safely adjust slave_id when the appropriate controller is * That's why we can safely adjust slave_id when the appropriate controller is
* found. * found.
*
* Return:
* 0, if no information is avaiable, -1 on mismatch, and 1 otherwise.
*/ */
static int acpi_dma_update_dma_spec(struct acpi_dma *adma, static int acpi_dma_update_dma_spec(struct acpi_dma *adma,
struct acpi_dma_spec *dma_spec) struct acpi_dma_spec *dma_spec)
...@@ -334,7 +342,8 @@ static int acpi_dma_parse_fixed_dma(struct acpi_resource *res, void *data) ...@@ -334,7 +342,8 @@ static int acpi_dma_parse_fixed_dma(struct acpi_resource *res, void *data)
* @dev: struct device to get DMA request from * @dev: struct device to get DMA request from
* @index: index of FixedDMA descriptor for @dev * @index: index of FixedDMA descriptor for @dev
* *
* Returns pointer to appropriate dma channel on success or NULL on error. * Return:
* Pointer to appropriate dma channel on success or NULL on error.
*/ */
struct dma_chan *acpi_dma_request_slave_chan_by_index(struct device *dev, struct dma_chan *acpi_dma_request_slave_chan_by_index(struct device *dev,
size_t index) size_t index)
...@@ -403,7 +412,8 @@ EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_index); ...@@ -403,7 +412,8 @@ EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_index);
* translate the names "tx" and "rx" here based on the most common case where * translate the names "tx" and "rx" here based on the most common case where
* the first FixedDMA descriptor is TX and second is RX. * the first FixedDMA descriptor is TX and second is RX.
* *
* Returns pointer to appropriate dma channel on success or NULL on error. * Return:
* Pointer to appropriate dma channel on success or NULL on error.
*/ */
struct dma_chan *acpi_dma_request_slave_chan_by_name(struct device *dev, struct dma_chan *acpi_dma_request_slave_chan_by_name(struct device *dev,
const char *name) const char *name)
...@@ -427,8 +437,10 @@ EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_name); ...@@ -427,8 +437,10 @@ EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_name);
* @adma: pointer to ACPI DMA controller data * @adma: pointer to ACPI DMA controller data
* *
* A simple translation function for ACPI based devices. Passes &struct * A simple translation function for ACPI based devices. Passes &struct
* dma_spec to the DMA controller driver provided filter function. Returns * dma_spec to the DMA controller driver provided filter function.
* pointer to the channel if found or %NULL otherwise. *
* Return:
* Pointer to the channel if found or %NULL otherwise.
*/ */
struct dma_chan *acpi_dma_simple_xlate(struct acpi_dma_spec *dma_spec, struct dma_chan *acpi_dma_simple_xlate(struct acpi_dma_spec *dma_spec,
struct acpi_dma *adma) struct acpi_dma *adma)
......
...@@ -83,6 +83,7 @@ ...@@ -83,6 +83,7 @@
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/dmapool.h> #include <linux/dmapool.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/export.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -1771,6 +1772,7 @@ bool pl08x_filter_id(struct dma_chan *chan, void *chan_id) ...@@ -1771,6 +1772,7 @@ bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
return false; return false;
} }
EXPORT_SYMBOL_GPL(pl08x_filter_id);
/* /*
* Just check that the device is there and active * Just check that the device is there and active
...@@ -2167,7 +2169,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -2167,7 +2169,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
/* Register slave channels */ /* Register slave channels */
ret = pl08x_dma_init_virtual_channels(pl08x, &pl08x->slave, ret = pl08x_dma_init_virtual_channels(pl08x, &pl08x->slave,
pl08x->pd->num_slave_channels, true); pl08x->pd->num_slave_channels, true);
if (ret <= 0) { if (ret < 0) {
dev_warn(&pl08x->adev->dev, dev_warn(&pl08x->adev->dev,
"%s failed to enumerate slave channels - %d\n", "%s failed to enumerate slave channels - %d\n",
__func__, ret); __func__, ret);
......
This diff is collapsed.
...@@ -972,8 +972,10 @@ static int cppi41_dma_probe(struct platform_device *pdev) ...@@ -972,8 +972,10 @@ static int cppi41_dma_probe(struct platform_device *pdev)
goto err_chans; goto err_chans;
irq = irq_of_parse_and_map(dev->of_node, 0); irq = irq_of_parse_and_map(dev->of_node, 0);
if (!irq) if (!irq) {
ret = -EINVAL;
goto err_irq; goto err_irq;
}
cppi_writel(USBSS_IRQ_PD_COMP, cdd->usbss_mem + USBSS_IRQ_ENABLER); cppi_writel(USBSS_IRQ_PD_COMP, cdd->usbss_mem + USBSS_IRQ_ENABLER);
......
...@@ -31,7 +31,7 @@ module_param_string(channel, test_channel, sizeof(test_channel), ...@@ -31,7 +31,7 @@ module_param_string(channel, test_channel, sizeof(test_channel),
S_IRUGO | S_IWUSR); S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)"); MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)");
static char test_device[20]; static char test_device[32];
module_param_string(device, test_device, sizeof(test_device), module_param_string(device, test_device, sizeof(test_device),
S_IRUGO | S_IWUSR); S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)"); MODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)");
...@@ -89,7 +89,7 @@ MODULE_PARM_DESC(verbose, "Enable \"success\" result messages (default: off)"); ...@@ -89,7 +89,7 @@ MODULE_PARM_DESC(verbose, "Enable \"success\" result messages (default: off)");
struct dmatest_params { struct dmatest_params {
unsigned int buf_size; unsigned int buf_size;
char channel[20]; char channel[20];
char device[20]; char device[32];
unsigned int threads_per_chan; unsigned int threads_per_chan;
unsigned int max_channels; unsigned int max_channels;
unsigned int iterations; unsigned int iterations;
......
...@@ -218,8 +218,10 @@ static inline void dwc_do_single_block(struct dw_dma_chan *dwc, ...@@ -218,8 +218,10 @@ static inline void dwc_do_single_block(struct dw_dma_chan *dwc,
struct dw_dma *dw = to_dw_dma(dwc->chan.device); struct dw_dma *dw = to_dw_dma(dwc->chan.device);
u32 ctllo; u32 ctllo;
/* Software emulation of LLP mode relies on interrupts to continue /*
* multi block transfer. */ * Software emulation of LLP mode relies on interrupts to continue
* multi block transfer.
*/
ctllo = desc->lli.ctllo | DWC_CTLL_INT_EN; ctllo = desc->lli.ctllo | DWC_CTLL_INT_EN;
channel_writel(dwc, SAR, desc->lli.sar); channel_writel(dwc, SAR, desc->lli.sar);
...@@ -253,8 +255,7 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) ...@@ -253,8 +255,7 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first)
&dwc->flags); &dwc->flags);
if (was_soft_llp) { if (was_soft_llp) {
dev_err(chan2dev(&dwc->chan), dev_err(chan2dev(&dwc->chan),
"BUG: Attempted to start new LLP transfer " "BUG: Attempted to start new LLP transfer inside ongoing one\n");
"inside ongoing one\n");
return; return;
} }
...@@ -420,8 +421,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) ...@@ -420,8 +421,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
return; return;
} }
dev_vdbg(chan2dev(&dwc->chan), "%s: llp=0x%llx\n", __func__, dev_vdbg(chan2dev(&dwc->chan), "%s: llp=%pad\n", __func__, &llp);
(unsigned long long)llp);
list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) { list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) {
/* Initial residue value */ /* Initial residue value */
...@@ -567,9 +567,9 @@ static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc, ...@@ -567,9 +567,9 @@ static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc,
unlikely(status_xfer & dwc->mask)) { unlikely(status_xfer & dwc->mask)) {
int i; int i;
dev_err(chan2dev(&dwc->chan), "cyclic DMA unexpected %s " dev_err(chan2dev(&dwc->chan),
"interrupt, stopping DMA transfer\n", "cyclic DMA unexpected %s interrupt, stopping DMA transfer\n",
status_xfer ? "xfer" : "error"); status_xfer ? "xfer" : "error");
spin_lock_irqsave(&dwc->lock, flags); spin_lock_irqsave(&dwc->lock, flags);
...@@ -711,9 +711,8 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, ...@@ -711,9 +711,8 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
u32 ctllo; u32 ctllo;
dev_vdbg(chan2dev(chan), dev_vdbg(chan2dev(chan),
"%s: d0x%llx s0x%llx l0x%zx f0x%lx\n", __func__, "%s: d%pad s%pad l0x%zx f0x%lx\n", __func__,
(unsigned long long)dest, (unsigned long long)src, &dest, &src, len, flags);
len, flags);
if (unlikely(!len)) { if (unlikely(!len)) {
dev_dbg(chan2dev(chan), "%s: length is zero!\n", __func__); dev_dbg(chan2dev(chan), "%s: length is zero!\n", __func__);
...@@ -1401,9 +1400,9 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, ...@@ -1401,9 +1400,9 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
/* Let's make a cyclic list */ /* Let's make a cyclic list */
last->lli.llp = cdesc->desc[0]->txd.phys; last->lli.llp = cdesc->desc[0]->txd.phys;
dev_dbg(chan2dev(&dwc->chan), "cyclic prepared buf 0x%llx len %zu " dev_dbg(chan2dev(&dwc->chan),
"period %zu periods %d\n", (unsigned long long)buf_addr, "cyclic prepared buf %pad len %zu period %zu periods %d\n",
buf_len, period_len, periods); &buf_addr, buf_len, period_len, periods);
cdesc->periods = periods; cdesc->periods = periods;
dwc->cdesc = cdesc; dwc->cdesc = cdesc;
...@@ -1603,9 +1602,11 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) ...@@ -1603,9 +1602,11 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
dev_dbg(chip->dev, "DWC_PARAMS[%d]: 0x%08x\n", i, dev_dbg(chip->dev, "DWC_PARAMS[%d]: 0x%08x\n", i,
dwc_params); dwc_params);
/* Decode maximum block size for given channel. The /*
* Decode maximum block size for given channel. The
* stored 4 bit value represents blocks from 0x00 for 3 * stored 4 bit value represents blocks from 0x00 for 3
* up to 0x0a for 4095. */ * up to 0x0a for 4095.
*/
dwc->block_size = dwc->block_size =
(4 << ((max_blk_size >> 4 * i) & 0xf)) - 1; (4 << ((max_blk_size >> 4 * i) & 0xf)) - 1;
dwc->nollp = dwc->nollp =
......
...@@ -699,8 +699,8 @@ static int edma_alloc_chan_resources(struct dma_chan *chan) ...@@ -699,8 +699,8 @@ static int edma_alloc_chan_resources(struct dma_chan *chan)
echan->alloced = true; echan->alloced = true;
echan->slot[0] = echan->ch_num; echan->slot[0] = echan->ch_num;
dev_info(dev, "allocated channel for %u:%u\n", dev_dbg(dev, "allocated channel for %u:%u\n",
EDMA_CTLR(echan->ch_num), EDMA_CHAN_SLOT(echan->ch_num)); EDMA_CTLR(echan->ch_num), EDMA_CHAN_SLOT(echan->ch_num));
return 0; return 0;
...@@ -736,7 +736,7 @@ static void edma_free_chan_resources(struct dma_chan *chan) ...@@ -736,7 +736,7 @@ static void edma_free_chan_resources(struct dma_chan *chan)
echan->alloced = false; echan->alloced = false;
} }
dev_info(dev, "freeing channel for %u\n", echan->ch_num); dev_dbg(dev, "freeing channel for %u\n", echan->ch_num);
} }
/* Send pending descriptor to hardware */ /* Send pending descriptor to hardware */
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
* channel is allowed to transfer before the DMA engine pauses * channel is allowed to transfer before the DMA engine pauses
* the current channel and switches to the next channel * the current channel and switches to the next channel
*/ */
#define FSL_DMA_MR_BWC 0x08000000 #define FSL_DMA_MR_BWC 0x0A000000
/* Special MR definition for MPC8349 */ /* Special MR definition for MPC8349 */
#define FSL_DMA_MR_EOTIE 0x00000080 #define FSL_DMA_MR_EOTIE 0x00000080
......
...@@ -323,6 +323,7 @@ struct sdma_engine { ...@@ -323,6 +323,7 @@ struct sdma_engine {
struct clk *clk_ipg; struct clk *clk_ipg;
struct clk *clk_ahb; struct clk *clk_ahb;
spinlock_t channel_0_lock; spinlock_t channel_0_lock;
u32 script_number;
struct sdma_script_start_addrs *script_addrs; struct sdma_script_start_addrs *script_addrs;
const struct sdma_driver_data *drvdata; const struct sdma_driver_data *drvdata;
}; };
...@@ -724,6 +725,10 @@ static void sdma_get_pc(struct sdma_channel *sdmac, ...@@ -724,6 +725,10 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
per_2_emi = sdma->script_addrs->app_2_mcu_addr; per_2_emi = sdma->script_addrs->app_2_mcu_addr;
emi_2_per = sdma->script_addrs->mcu_2_app_addr; emi_2_per = sdma->script_addrs->mcu_2_app_addr;
break; break;
case IMX_DMATYPE_SSI_DUAL:
per_2_emi = sdma->script_addrs->ssish_2_mcu_addr;
emi_2_per = sdma->script_addrs->mcu_2_ssish_addr;
break;
case IMX_DMATYPE_SSI_SP: case IMX_DMATYPE_SSI_SP:
case IMX_DMATYPE_MMC: case IMX_DMATYPE_MMC:
case IMX_DMATYPE_SDHC: case IMX_DMATYPE_SDHC:
...@@ -1238,6 +1243,7 @@ static void sdma_issue_pending(struct dma_chan *chan) ...@@ -1238,6 +1243,7 @@ static void sdma_issue_pending(struct dma_chan *chan)
} }
#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1 34 #define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1 34
#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2 38
static void sdma_add_scripts(struct sdma_engine *sdma, static void sdma_add_scripts(struct sdma_engine *sdma,
const struct sdma_script_start_addrs *addr) const struct sdma_script_start_addrs *addr)
...@@ -1246,7 +1252,11 @@ static void sdma_add_scripts(struct sdma_engine *sdma, ...@@ -1246,7 +1252,11 @@ static void sdma_add_scripts(struct sdma_engine *sdma,
s32 *saddr_arr = (u32 *)sdma->script_addrs; s32 *saddr_arr = (u32 *)sdma->script_addrs;
int i; int i;
for (i = 0; i < SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; i++) /* use the default firmware in ROM if missing external firmware */
if (!sdma->script_number)
sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1;
for (i = 0; i < sdma->script_number; i++)
if (addr_arr[i] > 0) if (addr_arr[i] > 0)
saddr_arr[i] = addr_arr[i]; saddr_arr[i] = addr_arr[i];
} }
...@@ -1272,6 +1282,17 @@ static void sdma_load_firmware(const struct firmware *fw, void *context) ...@@ -1272,6 +1282,17 @@ static void sdma_load_firmware(const struct firmware *fw, void *context)
goto err_firmware; goto err_firmware;
if (header->ram_code_start + header->ram_code_size > fw->size) if (header->ram_code_start + header->ram_code_size > fw->size)
goto err_firmware; goto err_firmware;
switch (header->version_major) {
case 1:
sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1;
break;
case 2:
sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2;
break;
default:
dev_err(sdma->dev, "unknown firmware version\n");
goto err_firmware;
}
addr = (void *)header + header->script_addrs_start; addr = (void *)header + header->script_addrs_start;
ram_code = (void *)header + header->ram_code_start; ram_code = (void *)header + header->ram_code_start;
......
...@@ -477,7 +477,7 @@ static struct dma_async_tx_descriptor *k3_dma_prep_slave_sg( ...@@ -477,7 +477,7 @@ static struct dma_async_tx_descriptor *k3_dma_prep_slave_sg(
dma_addr_t addr, src = 0, dst = 0; dma_addr_t addr, src = 0, dst = 0;
int num = sglen, i; int num = sglen, i;
if (sgl == 0) if (sgl == NULL)
return NULL; return NULL;
for_each_sg(sgl, sg, sglen, i) { for_each_sg(sgl, sg, sglen, i) {
...@@ -817,7 +817,7 @@ static int k3_dma_resume(struct device *dev) ...@@ -817,7 +817,7 @@ static int k3_dma_resume(struct device *dev)
return 0; return 0;
} }
SIMPLE_DEV_PM_OPS(k3_dma_pmops, k3_dma_suspend, k3_dma_resume); static SIMPLE_DEV_PM_OPS(k3_dma_pmops, k3_dma_suspend, k3_dma_resume);
static struct platform_driver k3_pdma_driver = { static struct platform_driver k3_pdma_driver = {
.driver = { .driver = {
......
This diff is collapsed.
...@@ -121,11 +121,13 @@ struct mmp_tdma_chan { ...@@ -121,11 +121,13 @@ struct mmp_tdma_chan {
int idx; int idx;
enum mmp_tdma_type type; enum mmp_tdma_type type;
int irq; int irq;
unsigned long reg_base; void __iomem *reg_base;
size_t buf_len; size_t buf_len;
size_t period_len; size_t period_len;
size_t pos; size_t pos;
struct gen_pool *pool;
}; };
#define TDMA_CHANNEL_NUM 2 #define TDMA_CHANNEL_NUM 2
...@@ -182,7 +184,7 @@ static void mmp_tdma_pause_chan(struct mmp_tdma_chan *tdmac) ...@@ -182,7 +184,7 @@ static void mmp_tdma_pause_chan(struct mmp_tdma_chan *tdmac)
static int mmp_tdma_config_chan(struct mmp_tdma_chan *tdmac) static int mmp_tdma_config_chan(struct mmp_tdma_chan *tdmac)
{ {
unsigned int tdcr; unsigned int tdcr = 0;
mmp_tdma_disable_chan(tdmac); mmp_tdma_disable_chan(tdmac);
...@@ -324,7 +326,7 @@ static void mmp_tdma_free_descriptor(struct mmp_tdma_chan *tdmac) ...@@ -324,7 +326,7 @@ static void mmp_tdma_free_descriptor(struct mmp_tdma_chan *tdmac)
struct gen_pool *gpool; struct gen_pool *gpool;
int size = tdmac->desc_num * sizeof(struct mmp_tdma_desc); int size = tdmac->desc_num * sizeof(struct mmp_tdma_desc);
gpool = sram_get_gpool("asram"); gpool = tdmac->pool;
if (tdmac->desc_arr) if (tdmac->desc_arr)
gen_pool_free(gpool, (unsigned long)tdmac->desc_arr, gen_pool_free(gpool, (unsigned long)tdmac->desc_arr,
size); size);
...@@ -374,7 +376,7 @@ struct mmp_tdma_desc *mmp_tdma_alloc_descriptor(struct mmp_tdma_chan *tdmac) ...@@ -374,7 +376,7 @@ struct mmp_tdma_desc *mmp_tdma_alloc_descriptor(struct mmp_tdma_chan *tdmac)
struct gen_pool *gpool; struct gen_pool *gpool;
int size = tdmac->desc_num * sizeof(struct mmp_tdma_desc); int size = tdmac->desc_num * sizeof(struct mmp_tdma_desc);
gpool = sram_get_gpool("asram"); gpool = tdmac->pool;
if (!gpool) if (!gpool)
return NULL; return NULL;
...@@ -505,7 +507,8 @@ static int mmp_tdma_remove(struct platform_device *pdev) ...@@ -505,7 +507,8 @@ static int mmp_tdma_remove(struct platform_device *pdev)
} }
static int mmp_tdma_chan_init(struct mmp_tdma_device *tdev, static int mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
int idx, int irq, int type) int idx, int irq,
int type, struct gen_pool *pool)
{ {
struct mmp_tdma_chan *tdmac; struct mmp_tdma_chan *tdmac;
...@@ -526,7 +529,8 @@ static int mmp_tdma_chan_init(struct mmp_tdma_device *tdev, ...@@ -526,7 +529,8 @@ static int mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
tdmac->chan.device = &tdev->device; tdmac->chan.device = &tdev->device;
tdmac->idx = idx; tdmac->idx = idx;
tdmac->type = type; tdmac->type = type;
tdmac->reg_base = (unsigned long)tdev->base + idx * 4; tdmac->reg_base = tdev->base + idx * 4;
tdmac->pool = pool;
tdmac->status = DMA_COMPLETE; tdmac->status = DMA_COMPLETE;
tdev->tdmac[tdmac->idx] = tdmac; tdev->tdmac[tdmac->idx] = tdmac;
tasklet_init(&tdmac->tasklet, dma_do_tasklet, (unsigned long)tdmac); tasklet_init(&tdmac->tasklet, dma_do_tasklet, (unsigned long)tdmac);
...@@ -553,6 +557,7 @@ static int mmp_tdma_probe(struct platform_device *pdev) ...@@ -553,6 +557,7 @@ static int mmp_tdma_probe(struct platform_device *pdev)
int i, ret; int i, ret;
int irq = 0, irq_num = 0; int irq = 0, irq_num = 0;
int chan_num = TDMA_CHANNEL_NUM; int chan_num = TDMA_CHANNEL_NUM;
struct gen_pool *pool;
of_id = of_match_device(mmp_tdma_dt_ids, &pdev->dev); of_id = of_match_device(mmp_tdma_dt_ids, &pdev->dev);
if (of_id) if (of_id)
...@@ -579,6 +584,15 @@ static int mmp_tdma_probe(struct platform_device *pdev) ...@@ -579,6 +584,15 @@ static int mmp_tdma_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&tdev->device.channels); INIT_LIST_HEAD(&tdev->device.channels);
if (pdev->dev.of_node)
pool = of_get_named_gen_pool(pdev->dev.of_node, "asram", 0);
else
pool = sram_get_gpool("asram");
if (!pool) {
dev_err(&pdev->dev, "asram pool not available\n");
return -ENOMEM;
}
if (irq_num != chan_num) { if (irq_num != chan_num) {
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
ret = devm_request_irq(&pdev->dev, irq, ret = devm_request_irq(&pdev->dev, irq,
...@@ -590,7 +604,7 @@ static int mmp_tdma_probe(struct platform_device *pdev) ...@@ -590,7 +604,7 @@ static int mmp_tdma_probe(struct platform_device *pdev)
/* initialize channel parameters */ /* initialize channel parameters */
for (i = 0; i < chan_num; i++) { for (i = 0; i < chan_num; i++) {
irq = (irq_num != chan_num) ? 0 : platform_get_irq(pdev, i); irq = (irq_num != chan_num) ? 0 : platform_get_irq(pdev, i);
ret = mmp_tdma_chan_init(tdev, i, irq, type); ret = mmp_tdma_chan_init(tdev, i, irq, type, pool);
if (ret) if (ret)
return ret; return ret;
} }
......
This diff is collapsed.
...@@ -190,7 +190,7 @@ static int omap_dma_alloc_chan_resources(struct dma_chan *chan) ...@@ -190,7 +190,7 @@ static int omap_dma_alloc_chan_resources(struct dma_chan *chan)
{ {
struct omap_chan *c = to_omap_dma_chan(chan); struct omap_chan *c = to_omap_dma_chan(chan);
dev_info(c->vc.chan.device->dev, "allocating channel for %u\n", c->dma_sig); dev_dbg(c->vc.chan.device->dev, "allocating channel for %u\n", c->dma_sig);
return omap_request_dma(c->dma_sig, "DMA engine", return omap_request_dma(c->dma_sig, "DMA engine",
omap_dma_callback, c, &c->dma_ch); omap_dma_callback, c, &c->dma_ch);
...@@ -203,7 +203,7 @@ static void omap_dma_free_chan_resources(struct dma_chan *chan) ...@@ -203,7 +203,7 @@ static void omap_dma_free_chan_resources(struct dma_chan *chan)
vchan_free_chan_resources(&c->vc); vchan_free_chan_resources(&c->vc);
omap_free_dma(c->dma_ch); omap_free_dma(c->dma_ch);
dev_info(c->vc.chan.device->dev, "freeing channel for %u\n", c->dma_sig); dev_dbg(c->vc.chan.device->dev, "freeing channel for %u\n", c->dma_sig);
} }
static size_t omap_dma_sg_size(struct omap_sg *sg) static size_t omap_dma_sg_size(struct omap_sg *sg)
......
...@@ -543,7 +543,9 @@ struct dma_pl330_chan { ...@@ -543,7 +543,9 @@ struct dma_pl330_chan {
/* DMA-Engine Channel */ /* DMA-Engine Channel */
struct dma_chan chan; struct dma_chan chan;
/* List of to be xfered descriptors */ /* List of submitted descriptors */
struct list_head submitted_list;
/* List of issued descriptors */
struct list_head work_list; struct list_head work_list;
/* List of completed descriptors */ /* List of completed descriptors */
struct list_head completed_list; struct list_head completed_list;
...@@ -578,12 +580,16 @@ struct dma_pl330_dmac { ...@@ -578,12 +580,16 @@ struct dma_pl330_dmac {
/* DMA-Engine Device */ /* DMA-Engine Device */
struct dma_device ddma; struct dma_device ddma;
/* Holds info about sg limitations */
struct device_dma_parameters dma_parms;
/* Pool of descriptors available for the DMAC's channels */ /* Pool of descriptors available for the DMAC's channels */
struct list_head desc_pool; struct list_head desc_pool;
/* To protect desc_pool manipulation */ /* To protect desc_pool manipulation */
spinlock_t pool_lock; spinlock_t pool_lock;
/* Peripheral channels connected to this DMAC */ /* Peripheral channels connected to this DMAC */
unsigned int num_peripherals;
struct dma_pl330_chan *peripherals; /* keep at end */ struct dma_pl330_chan *peripherals; /* keep at end */
}; };
...@@ -606,11 +612,6 @@ struct dma_pl330_desc { ...@@ -606,11 +612,6 @@ struct dma_pl330_desc {
struct dma_pl330_chan *pchan; struct dma_pl330_chan *pchan;
}; };
struct dma_pl330_filter_args {
struct dma_pl330_dmac *pdmac;
unsigned int chan_id;
};
static inline void _callback(struct pl330_req *r, enum pl330_op_err err) static inline void _callback(struct pl330_req *r, enum pl330_op_err err)
{ {
if (r && r->xfer_cb) if (r && r->xfer_cb)
...@@ -2298,16 +2299,6 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err) ...@@ -2298,16 +2299,6 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
tasklet_schedule(&pch->task); tasklet_schedule(&pch->task);
} }
static bool pl330_dt_filter(struct dma_chan *chan, void *param)
{
struct dma_pl330_filter_args *fargs = param;
if (chan->device != &fargs->pdmac->ddma)
return false;
return (chan->chan_id == fargs->chan_id);
}
bool pl330_filter(struct dma_chan *chan, void *param) bool pl330_filter(struct dma_chan *chan, void *param)
{ {
u8 *peri_id; u8 *peri_id;
...@@ -2325,23 +2316,16 @@ static struct dma_chan *of_dma_pl330_xlate(struct of_phandle_args *dma_spec, ...@@ -2325,23 +2316,16 @@ static struct dma_chan *of_dma_pl330_xlate(struct of_phandle_args *dma_spec,
{ {
int count = dma_spec->args_count; int count = dma_spec->args_count;
struct dma_pl330_dmac *pdmac = ofdma->of_dma_data; struct dma_pl330_dmac *pdmac = ofdma->of_dma_data;
struct dma_pl330_filter_args fargs; unsigned int chan_id;
dma_cap_mask_t cap;
if (!pdmac)
return NULL;
if (count != 1) if (count != 1)
return NULL; return NULL;
fargs.pdmac = pdmac; chan_id = dma_spec->args[0];
fargs.chan_id = dma_spec->args[0]; if (chan_id >= pdmac->num_peripherals)
return NULL;
dma_cap_zero(cap);
dma_cap_set(DMA_SLAVE, cap);
dma_cap_set(DMA_CYCLIC, cap);
return dma_request_channel(cap, pl330_dt_filter, &fargs); return dma_get_slave_channel(&pdmac->peripherals[chan_id].chan);
} }
static int pl330_alloc_chan_resources(struct dma_chan *chan) static int pl330_alloc_chan_resources(struct dma_chan *chan)
...@@ -2385,6 +2369,11 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned ...@@ -2385,6 +2369,11 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH); pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
/* Mark all desc done */ /* Mark all desc done */
list_for_each_entry(desc, &pch->submitted_list, node) {
desc->status = FREE;
dma_cookie_complete(&desc->txd);
}
list_for_each_entry(desc, &pch->work_list , node) { list_for_each_entry(desc, &pch->work_list , node) {
desc->status = FREE; desc->status = FREE;
dma_cookie_complete(&desc->txd); dma_cookie_complete(&desc->txd);
...@@ -2395,6 +2384,7 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned ...@@ -2395,6 +2384,7 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
dma_cookie_complete(&desc->txd); dma_cookie_complete(&desc->txd);
} }
list_splice_tail_init(&pch->submitted_list, &pdmac->desc_pool);
list_splice_tail_init(&pch->work_list, &pdmac->desc_pool); list_splice_tail_init(&pch->work_list, &pdmac->desc_pool);
list_splice_tail_init(&pch->completed_list, &pdmac->desc_pool); list_splice_tail_init(&pch->completed_list, &pdmac->desc_pool);
spin_unlock_irqrestore(&pch->lock, flags); spin_unlock_irqrestore(&pch->lock, flags);
...@@ -2453,7 +2443,14 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, ...@@ -2453,7 +2443,14 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
static void pl330_issue_pending(struct dma_chan *chan) static void pl330_issue_pending(struct dma_chan *chan)
{ {
pl330_tasklet((unsigned long) to_pchan(chan)); struct dma_pl330_chan *pch = to_pchan(chan);
unsigned long flags;
spin_lock_irqsave(&pch->lock, flags);
list_splice_tail_init(&pch->submitted_list, &pch->work_list);
spin_unlock_irqrestore(&pch->lock, flags);
pl330_tasklet((unsigned long)pch);
} }
/* /*
...@@ -2480,11 +2477,11 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx) ...@@ -2480,11 +2477,11 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx)
dma_cookie_assign(&desc->txd); dma_cookie_assign(&desc->txd);
list_move_tail(&desc->node, &pch->work_list); list_move_tail(&desc->node, &pch->submitted_list);
} }
cookie = dma_cookie_assign(&last->txd); cookie = dma_cookie_assign(&last->txd);
list_add_tail(&last->node, &pch->work_list); list_add_tail(&last->node, &pch->submitted_list);
spin_unlock_irqrestore(&pch->lock, flags); spin_unlock_irqrestore(&pch->lock, flags);
return cookie; return cookie;
...@@ -2960,6 +2957,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -2960,6 +2957,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
else else
num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan); num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan);
pdmac->num_peripherals = num_chan;
pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL);
if (!pdmac->peripherals) { if (!pdmac->peripherals) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -2974,6 +2973,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -2974,6 +2973,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
else else
pch->chan.private = adev->dev.of_node; pch->chan.private = adev->dev.of_node;
INIT_LIST_HEAD(&pch->submitted_list);
INIT_LIST_HEAD(&pch->work_list); INIT_LIST_HEAD(&pch->work_list);
INIT_LIST_HEAD(&pch->completed_list); INIT_LIST_HEAD(&pch->completed_list);
spin_lock_init(&pch->lock); spin_lock_init(&pch->lock);
...@@ -3021,6 +3021,9 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -3021,6 +3021,9 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
"unable to register DMA to the generic DT DMA helpers\n"); "unable to register DMA to the generic DT DMA helpers\n");
} }
} }
adev->dev.dma_parms = &pdmac->dma_parms;
/* /*
* This is the limit for transfers with a buswidth of 1, larger * This is the limit for transfers with a buswidth of 1, larger
* buswidths will have larger limits. * buswidths will have larger limits.
......
...@@ -4114,6 +4114,7 @@ static int ppc440spe_adma_probe(struct platform_device *ofdev) ...@@ -4114,6 +4114,7 @@ static int ppc440spe_adma_probe(struct platform_device *ofdev)
regs = ioremap(res.start, resource_size(&res)); regs = ioremap(res.start, resource_size(&res));
if (!regs) { if (!regs) {
dev_err(&ofdev->dev, "failed to ioremap regs!\n"); dev_err(&ofdev->dev, "failed to ioremap regs!\n");
ret = -ENOMEM;
goto err_regs_alloc; goto err_regs_alloc;
} }
......
...@@ -640,6 +640,25 @@ bool sirfsoc_dma_filter_id(struct dma_chan *chan, void *chan_id) ...@@ -640,6 +640,25 @@ bool sirfsoc_dma_filter_id(struct dma_chan *chan, void *chan_id)
} }
EXPORT_SYMBOL(sirfsoc_dma_filter_id); EXPORT_SYMBOL(sirfsoc_dma_filter_id);
#define SIRFSOC_DMA_BUSWIDTHS \
(BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) | \
BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \
BIT(DMA_SLAVE_BUSWIDTH_8_BYTES))
static int sirfsoc_dma_device_slave_caps(struct dma_chan *dchan,
struct dma_slave_caps *caps)
{
caps->src_addr_widths = SIRFSOC_DMA_BUSWIDTHS;
caps->dstn_addr_widths = SIRFSOC_DMA_BUSWIDTHS;
caps->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
caps->cmd_pause = true;
caps->cmd_terminate = true;
return 0;
}
static int sirfsoc_dma_probe(struct platform_device *op) static int sirfsoc_dma_probe(struct platform_device *op)
{ {
struct device_node *dn = op->dev.of_node; struct device_node *dn = op->dev.of_node;
...@@ -712,6 +731,7 @@ static int sirfsoc_dma_probe(struct platform_device *op) ...@@ -712,6 +731,7 @@ static int sirfsoc_dma_probe(struct platform_device *op)
dma->device_tx_status = sirfsoc_dma_tx_status; dma->device_tx_status = sirfsoc_dma_tx_status;
dma->device_prep_interleaved_dma = sirfsoc_dma_prep_interleaved; dma->device_prep_interleaved_dma = sirfsoc_dma_prep_interleaved;
dma->device_prep_dma_cyclic = sirfsoc_dma_prep_cyclic; dma->device_prep_dma_cyclic = sirfsoc_dma_prep_cyclic;
dma->device_slave_caps = sirfsoc_dma_device_slave_caps;
INIT_LIST_HEAD(&dma->channels); INIT_LIST_HEAD(&dma->channels);
dma_cap_set(DMA_SLAVE, dma->cap_mask); dma_cap_set(DMA_SLAVE, dma->cap_mask);
......
...@@ -100,6 +100,11 @@ ...@@ -100,6 +100,11 @@
#define TEGRA_APBDMA_APBSEQ_DATA_SWAP BIT(27) #define TEGRA_APBDMA_APBSEQ_DATA_SWAP BIT(27)
#define TEGRA_APBDMA_APBSEQ_WRAP_WORD_1 (1 << 16) #define TEGRA_APBDMA_APBSEQ_WRAP_WORD_1 (1 << 16)
/* Tegra148 specific registers */
#define TEGRA_APBDMA_CHAN_WCOUNT 0x20
#define TEGRA_APBDMA_CHAN_WORD_TRANSFER 0x24
/* /*
* If any burst is in flight and DMA paused then this is the time to complete * If any burst is in flight and DMA paused then this is the time to complete
* on-flight burst and update DMA status register. * on-flight burst and update DMA status register.
...@@ -109,21 +114,22 @@ ...@@ -109,21 +114,22 @@
/* Channel base address offset from APBDMA base address */ /* Channel base address offset from APBDMA base address */
#define TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET 0x1000 #define TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET 0x1000
/* DMA channel register space size */
#define TEGRA_APBDMA_CHANNEL_REGISTER_SIZE 0x20
struct tegra_dma; struct tegra_dma;
/* /*
* tegra_dma_chip_data Tegra chip specific DMA data * tegra_dma_chip_data Tegra chip specific DMA data
* @nr_channels: Number of channels available in the controller. * @nr_channels: Number of channels available in the controller.
* @channel_reg_size: Channel register size/stride.
* @max_dma_count: Maximum DMA transfer count supported by DMA controller. * @max_dma_count: Maximum DMA transfer count supported by DMA controller.
* @support_channel_pause: Support channel wise pause of dma. * @support_channel_pause: Support channel wise pause of dma.
* @support_separate_wcount_reg: Support separate word count register.
*/ */
struct tegra_dma_chip_data { struct tegra_dma_chip_data {
int nr_channels; int nr_channels;
int channel_reg_size;
int max_dma_count; int max_dma_count;
bool support_channel_pause; bool support_channel_pause;
bool support_separate_wcount_reg;
}; };
/* DMA channel registers */ /* DMA channel registers */
...@@ -133,6 +139,7 @@ struct tegra_dma_channel_regs { ...@@ -133,6 +139,7 @@ struct tegra_dma_channel_regs {
unsigned long apb_ptr; unsigned long apb_ptr;
unsigned long ahb_seq; unsigned long ahb_seq;
unsigned long apb_seq; unsigned long apb_seq;
unsigned long wcount;
}; };
/* /*
...@@ -426,6 +433,8 @@ static void tegra_dma_start(struct tegra_dma_channel *tdc, ...@@ -426,6 +433,8 @@ static void tegra_dma_start(struct tegra_dma_channel *tdc,
tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, ch_regs->apb_ptr); tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, ch_regs->apb_ptr);
tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBSEQ, ch_regs->ahb_seq); tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBSEQ, ch_regs->ahb_seq);
tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, ch_regs->ahb_ptr); tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, ch_regs->ahb_ptr);
if (tdc->tdma->chip_data->support_separate_wcount_reg)
tdc_write(tdc, TEGRA_APBDMA_CHAN_WCOUNT, ch_regs->wcount);
/* Start DMA */ /* Start DMA */
tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR,
...@@ -465,6 +474,9 @@ static void tegra_dma_configure_for_next(struct tegra_dma_channel *tdc, ...@@ -465,6 +474,9 @@ static void tegra_dma_configure_for_next(struct tegra_dma_channel *tdc,
/* Safe to program new configuration */ /* Safe to program new configuration */
tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, nsg_req->ch_regs.apb_ptr); tdc_write(tdc, TEGRA_APBDMA_CHAN_APBPTR, nsg_req->ch_regs.apb_ptr);
tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, nsg_req->ch_regs.ahb_ptr); tdc_write(tdc, TEGRA_APBDMA_CHAN_AHBPTR, nsg_req->ch_regs.ahb_ptr);
if (tdc->tdma->chip_data->support_separate_wcount_reg)
tdc_write(tdc, TEGRA_APBDMA_CHAN_WCOUNT,
nsg_req->ch_regs.wcount);
tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR, tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR,
nsg_req->ch_regs.csr | TEGRA_APBDMA_CSR_ENB); nsg_req->ch_regs.csr | TEGRA_APBDMA_CSR_ENB);
nsg_req->configured = true; nsg_req->configured = true;
...@@ -718,6 +730,7 @@ static void tegra_dma_terminate_all(struct dma_chan *dc) ...@@ -718,6 +730,7 @@ static void tegra_dma_terminate_all(struct dma_chan *dc)
struct tegra_dma_desc *dma_desc; struct tegra_dma_desc *dma_desc;
unsigned long flags; unsigned long flags;
unsigned long status; unsigned long status;
unsigned long wcount;
bool was_busy; bool was_busy;
spin_lock_irqsave(&tdc->lock, flags); spin_lock_irqsave(&tdc->lock, flags);
...@@ -738,6 +751,10 @@ static void tegra_dma_terminate_all(struct dma_chan *dc) ...@@ -738,6 +751,10 @@ static void tegra_dma_terminate_all(struct dma_chan *dc)
tdc->isr_handler(tdc, true); tdc->isr_handler(tdc, true);
status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS); status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS);
} }
if (tdc->tdma->chip_data->support_separate_wcount_reg)
wcount = tdc_read(tdc, TEGRA_APBDMA_CHAN_WORD_TRANSFER);
else
wcount = status;
was_busy = tdc->busy; was_busy = tdc->busy;
tegra_dma_stop(tdc); tegra_dma_stop(tdc);
...@@ -746,7 +763,7 @@ static void tegra_dma_terminate_all(struct dma_chan *dc) ...@@ -746,7 +763,7 @@ static void tegra_dma_terminate_all(struct dma_chan *dc)
sgreq = list_first_entry(&tdc->pending_sg_req, sgreq = list_first_entry(&tdc->pending_sg_req,
typeof(*sgreq), node); typeof(*sgreq), node);
sgreq->dma_desc->bytes_transferred += sgreq->dma_desc->bytes_transferred +=
get_current_xferred_count(tdc, sgreq, status); get_current_xferred_count(tdc, sgreq, wcount);
} }
tegra_dma_resume(tdc); tegra_dma_resume(tdc);
...@@ -908,6 +925,17 @@ static int get_transfer_param(struct tegra_dma_channel *tdc, ...@@ -908,6 +925,17 @@ static int get_transfer_param(struct tegra_dma_channel *tdc,
return -EINVAL; return -EINVAL;
} }
static void tegra_dma_prep_wcount(struct tegra_dma_channel *tdc,
struct tegra_dma_channel_regs *ch_regs, u32 len)
{
u32 len_field = (len - 4) & 0xFFFC;
if (tdc->tdma->chip_data->support_separate_wcount_reg)
ch_regs->wcount = len_field;
else
ch_regs->csr |= len_field;
}
static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg( static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
struct dma_chan *dc, struct scatterlist *sgl, unsigned int sg_len, struct dma_chan *dc, struct scatterlist *sgl, unsigned int sg_len,
enum dma_transfer_direction direction, unsigned long flags, enum dma_transfer_direction direction, unsigned long flags,
...@@ -991,7 +1019,8 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg( ...@@ -991,7 +1019,8 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
sg_req->ch_regs.apb_ptr = apb_ptr; sg_req->ch_regs.apb_ptr = apb_ptr;
sg_req->ch_regs.ahb_ptr = mem; sg_req->ch_regs.ahb_ptr = mem;
sg_req->ch_regs.csr = csr | ((len - 4) & 0xFFFC); sg_req->ch_regs.csr = csr;
tegra_dma_prep_wcount(tdc, &sg_req->ch_regs, len);
sg_req->ch_regs.apb_seq = apb_seq; sg_req->ch_regs.apb_seq = apb_seq;
sg_req->ch_regs.ahb_seq = ahb_seq; sg_req->ch_regs.ahb_seq = ahb_seq;
sg_req->configured = false; sg_req->configured = false;
...@@ -1120,7 +1149,8 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( ...@@ -1120,7 +1149,8 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
ahb_seq |= get_burst_size(tdc, burst_size, slave_bw, len); ahb_seq |= get_burst_size(tdc, burst_size, slave_bw, len);
sg_req->ch_regs.apb_ptr = apb_ptr; sg_req->ch_regs.apb_ptr = apb_ptr;
sg_req->ch_regs.ahb_ptr = mem; sg_req->ch_regs.ahb_ptr = mem;
sg_req->ch_regs.csr = csr | ((len - 4) & 0xFFFC); sg_req->ch_regs.csr = csr;
tegra_dma_prep_wcount(tdc, &sg_req->ch_regs, len);
sg_req->ch_regs.apb_seq = apb_seq; sg_req->ch_regs.apb_seq = apb_seq;
sg_req->ch_regs.ahb_seq = ahb_seq; sg_req->ch_regs.ahb_seq = ahb_seq;
sg_req->configured = false; sg_req->configured = false;
...@@ -1234,27 +1264,45 @@ static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec, ...@@ -1234,27 +1264,45 @@ static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
/* Tegra20 specific DMA controller information */ /* Tegra20 specific DMA controller information */
static const struct tegra_dma_chip_data tegra20_dma_chip_data = { static const struct tegra_dma_chip_data tegra20_dma_chip_data = {
.nr_channels = 16, .nr_channels = 16,
.channel_reg_size = 0x20,
.max_dma_count = 1024UL * 64, .max_dma_count = 1024UL * 64,
.support_channel_pause = false, .support_channel_pause = false,
.support_separate_wcount_reg = false,
}; };
/* Tegra30 specific DMA controller information */ /* Tegra30 specific DMA controller information */
static const struct tegra_dma_chip_data tegra30_dma_chip_data = { static const struct tegra_dma_chip_data tegra30_dma_chip_data = {
.nr_channels = 32, .nr_channels = 32,
.channel_reg_size = 0x20,
.max_dma_count = 1024UL * 64, .max_dma_count = 1024UL * 64,
.support_channel_pause = false, .support_channel_pause = false,
.support_separate_wcount_reg = false,
}; };
/* Tegra114 specific DMA controller information */ /* Tegra114 specific DMA controller information */
static const struct tegra_dma_chip_data tegra114_dma_chip_data = { static const struct tegra_dma_chip_data tegra114_dma_chip_data = {
.nr_channels = 32, .nr_channels = 32,
.channel_reg_size = 0x20,
.max_dma_count = 1024UL * 64, .max_dma_count = 1024UL * 64,
.support_channel_pause = true, .support_channel_pause = true,
.support_separate_wcount_reg = false,
};
/* Tegra148 specific DMA controller information */
static const struct tegra_dma_chip_data tegra148_dma_chip_data = {
.nr_channels = 32,
.channel_reg_size = 0x40,
.max_dma_count = 1024UL * 64,
.support_channel_pause = true,
.support_separate_wcount_reg = true,
}; };
static const struct of_device_id tegra_dma_of_match[] = { static const struct of_device_id tegra_dma_of_match[] = {
{ {
.compatible = "nvidia,tegra148-apbdma",
.data = &tegra148_dma_chip_data,
}, {
.compatible = "nvidia,tegra114-apbdma", .compatible = "nvidia,tegra114-apbdma",
.data = &tegra114_dma_chip_data, .data = &tegra114_dma_chip_data,
}, { }, {
...@@ -1348,7 +1396,7 @@ static int tegra_dma_probe(struct platform_device *pdev) ...@@ -1348,7 +1396,7 @@ static int tegra_dma_probe(struct platform_device *pdev)
struct tegra_dma_channel *tdc = &tdma->channels[i]; struct tegra_dma_channel *tdc = &tdma->channels[i];
tdc->chan_base_offset = TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET + tdc->chan_base_offset = TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET +
i * TEGRA_APBDMA_CHANNEL_REGISTER_SIZE; i * cdata->channel_reg_size;
res = platform_get_resource(pdev, IORESOURCE_IRQ, i); res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
if (!res) { if (!res) {
......
...@@ -84,10 +84,12 @@ static inline bool vchan_issue_pending(struct virt_dma_chan *vc) ...@@ -84,10 +84,12 @@ static inline bool vchan_issue_pending(struct virt_dma_chan *vc)
static inline void vchan_cookie_complete(struct virt_dma_desc *vd) static inline void vchan_cookie_complete(struct virt_dma_desc *vd)
{ {
struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan); struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan);
dma_cookie_t cookie;
cookie = vd->tx.cookie;
dma_cookie_complete(&vd->tx); dma_cookie_complete(&vd->tx);
dev_vdbg(vc->chan.device->dev, "txd %p[%x]: marked complete\n", dev_vdbg(vc->chan.device->dev, "txd %p[%x]: marked complete\n",
vd, vd->tx.cookie); vd, cookie);
list_add_tail(&vd->node, &vc->desc_completed); list_add_tail(&vd->node, &vc->desc_completed);
tasklet_schedule(&vc->task); tasklet_schedule(&vc->task);
......
...@@ -257,7 +257,7 @@ struct dma_chan_percpu { ...@@ -257,7 +257,7 @@ struct dma_chan_percpu {
* @dev: class device for sysfs * @dev: class device for sysfs
* @device_node: used to add this to the device chan list * @device_node: used to add this to the device chan list
* @local: per-cpu pointer to a struct dma_chan_percpu * @local: per-cpu pointer to a struct dma_chan_percpu
* @client-count: how many clients are using this channel * @client_count: how many clients are using this channel
* @table_count: number of appearances in the mem-to-mem allocation table * @table_count: number of appearances in the mem-to-mem allocation table
* @private: private data for certain client-channel associations * @private: private data for certain client-channel associations
*/ */
...@@ -279,10 +279,10 @@ struct dma_chan { ...@@ -279,10 +279,10 @@ struct dma_chan {
/** /**
* struct dma_chan_dev - relate sysfs device node to backing channel device * struct dma_chan_dev - relate sysfs device node to backing channel device
* @chan - driver channel device * @chan: driver channel device
* @device - sysfs device * @device: sysfs device
* @dev_id - parent dma_device dev_id * @dev_id: parent dma_device dev_id
* @idr_ref - reference count to gate release of dma_device dev_id * @idr_ref: reference count to gate release of dma_device dev_id
*/ */
struct dma_chan_dev { struct dma_chan_dev {
struct dma_chan *chan; struct dma_chan *chan;
...@@ -306,9 +306,8 @@ enum dma_slave_buswidth { ...@@ -306,9 +306,8 @@ enum dma_slave_buswidth {
/** /**
* struct dma_slave_config - dma slave channel runtime config * struct dma_slave_config - dma slave channel runtime config
* @direction: whether the data shall go in or out on this slave * @direction: whether the data shall go in or out on this slave
* channel, right now. DMA_TO_DEVICE and DMA_FROM_DEVICE are * channel, right now. DMA_MEM_TO_DEV and DMA_DEV_TO_MEM are
* legal values, DMA_BIDIRECTIONAL is not acceptable since we * legal values.
* need to differentiate source and target addresses.
* @src_addr: this is the physical address where DMA slave data * @src_addr: this is the physical address where DMA slave data
* should be read (RX), if the source is memory this argument is * should be read (RX), if the source is memory this argument is
* ignored. * ignored.
......
...@@ -43,6 +43,11 @@ struct sdma_script_start_addrs { ...@@ -43,6 +43,11 @@ struct sdma_script_start_addrs {
s32 dptc_dvfs_addr; s32 dptc_dvfs_addr;
s32 utra_addr; s32 utra_addr;
s32 ram_code_start_addr; s32 ram_code_start_addr;
/* End of v1 array */
s32 mcu_2_ssish_addr;
s32 ssish_2_mcu_addr;
s32 hdmi_dma_addr;
/* End of v2 array */
}; };
/** /**
......
...@@ -39,6 +39,7 @@ enum sdma_peripheral_type { ...@@ -39,6 +39,7 @@ enum sdma_peripheral_type {
IMX_DMATYPE_IPU_MEMORY, /* IPU Memory */ IMX_DMATYPE_IPU_MEMORY, /* IPU Memory */
IMX_DMATYPE_ASRC, /* ASRC */ IMX_DMATYPE_ASRC, /* ASRC */
IMX_DMATYPE_ESAI, /* ESAI */ IMX_DMATYPE_ESAI, /* ESAI */
IMX_DMATYPE_SSI_DUAL, /* SSI Dual FIFO */
}; };
enum imx_dma_prio { enum imx_dma_prio {
......
/* /*
* linux/arch/arm/mach-mmp/include/mach/sram.h
*
* SRAM Memory Management * SRAM Memory Management
* *
* Copyright (c) 2011 Marvell Semiconductors Inc. * Copyright (c) 2011 Marvell Semiconductors Inc.
...@@ -11,8 +9,8 @@ ...@@ -11,8 +9,8 @@
* *
*/ */
#ifndef __ASM_ARCH_SRAM_H #ifndef __DMA_MMP_TDMA_H
#define __ASM_ARCH_SRAM_H #define __DMA_MMP_TDMA_H
#include <linux/genalloc.h> #include <linux/genalloc.h>
...@@ -32,4 +30,4 @@ struct sram_platdata { ...@@ -32,4 +30,4 @@ struct sram_platdata {
extern struct gen_pool *sram_get_gpool(char *pool_name); extern struct gen_pool *sram_get_gpool(char *pool_name);
#endif /* __ASM_ARCH_SRAM_H */ #endif /* __DMA_MMP_TDMA_H */
/* /*
* arch/arm/plat-orion/include/plat/mv_xor.h
*
* Marvell XOR platform device data definition file. * Marvell XOR platform device data definition file.
*/ */
#ifndef __PLAT_MV_XOR_H #ifndef __DMA_MV_XOR_H
#define __PLAT_MV_XOR_H #define __DMA_MV_XOR_H
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/mbus.h> #include <linux/mbus.h>
......
...@@ -164,6 +164,7 @@ struct fsl_ssi_private { ...@@ -164,6 +164,7 @@ struct fsl_ssi_private {
bool baudclk_locked; bool baudclk_locked;
bool irq_stats; bool irq_stats;
bool offline_config; bool offline_config;
bool use_dual_fifo;
u8 i2s_mode; u8 i2s_mode;
spinlock_t baudclk_lock; spinlock_t baudclk_lock;
struct clk *baudclk; struct clk *baudclk;
...@@ -721,6 +722,12 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) ...@@ -721,6 +722,12 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
CCSR_SSI_SxCCR_DC(2)); CCSR_SSI_SxCCR_DC(2));
} }
if (ssi_private->use_dual_fifo) {
write_ssi_mask(&ssi->srcr, 0, CCSR_SSI_SRCR_RFEN1);
write_ssi_mask(&ssi->stcr, 0, CCSR_SSI_STCR_TFEN1);
write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_TCH_EN);
}
return 0; return 0;
} }
...@@ -752,6 +759,15 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, ...@@ -752,6 +759,15 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags); spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
} }
/* When using dual fifo mode, it is safer to ensure an even period
* size. If appearing to an odd number while DMA always starts its
* task from fifo0, fifo1 would be neglected at the end of each
* period. But SSI would still access fifo1 with an invalid data.
*/
if (ssi_private->use_dual_fifo)
snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2);
return 0; return 0;
} }
...@@ -1370,7 +1386,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) ...@@ -1370,7 +1386,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
if (hw_type == FSL_SSI_MX21 || hw_type == FSL_SSI_MX51 || if (hw_type == FSL_SSI_MX21 || hw_type == FSL_SSI_MX51 ||
hw_type == FSL_SSI_MX35) { hw_type == FSL_SSI_MX35) {
u32 dma_events[2]; u32 dma_events[2], dmas[4];
ssi_private->ssi_on_imx = true; ssi_private->ssi_on_imx = true;
ssi_private->clk = devm_clk_get(&pdev->dev, NULL); ssi_private->clk = devm_clk_get(&pdev->dev, NULL);
...@@ -1426,6 +1442,16 @@ static int fsl_ssi_probe(struct platform_device *pdev) ...@@ -1426,6 +1442,16 @@ static int fsl_ssi_probe(struct platform_device *pdev)
goto error_clk; goto error_clk;
} }
} }
/* Should this be merge with the above? */
if (!of_property_read_u32_array(pdev->dev.of_node, "dmas", dmas, 4)
&& dmas[2] == IMX_DMATYPE_SSI_DUAL) {
ssi_private->use_dual_fifo = true;
/* When using dual fifo mode, we need to keep watermark
* as even numbers due to dma script limitation.
*/
ssi_private->dma_params_tx.maxburst &= ~0x1;
ssi_private->dma_params_rx.maxburst &= ~0x1;
}
shared = of_device_is_compatible(of_get_parent(np), shared = of_device_is_compatible(of_get_parent(np),
"fsl,spba-bus"); "fsl,spba-bus");
......
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