|
@@ -52,6 +52,47 @@ int mxs_dma_validate_chan(int channel)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Return the address of the command within a descriptor.
|
|
|
+ */
|
|
|
+static unsigned int mxs_dma_cmd_address(struct mxs_dma_desc *desc)
|
|
|
+{
|
|
|
+ return desc->address + offsetof(struct mxs_dma_desc, cmd);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Read a DMA channel's hardware semaphore.
|
|
|
+ *
|
|
|
+ * As used by the MXS platform's DMA software, the DMA channel's hardware
|
|
|
+ * semaphore reflects the number of DMA commands the hardware will process, but
|
|
|
+ * has not yet finished. This is a volatile value read directly from hardware,
|
|
|
+ * so it must be be viewed as immediately stale.
|
|
|
+ *
|
|
|
+ * If the channel is not marked busy, or has finished processing all its
|
|
|
+ * commands, this value should be zero.
|
|
|
+ *
|
|
|
+ * See mxs_dma_append() for details on how DMA command blocks must be configured
|
|
|
+ * to maintain the expected behavior of the semaphore's value.
|
|
|
+ */
|
|
|
+static int mxs_dma_read_semaphore(int channel)
|
|
|
+{
|
|
|
+ struct mx28_apbh_regs *apbh_regs =
|
|
|
+ (struct mx28_apbh_regs *)MXS_APBH_BASE;
|
|
|
+ uint32_t tmp;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = mxs_dma_validate_chan(channel);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ tmp = readl(&apbh_regs->ch[channel].hw_apbh_ch_sema);
|
|
|
+
|
|
|
+ tmp &= APBH_CHn_SEMA_PHORE_MASK;
|
|
|
+ tmp >>= APBH_CHn_SEMA_PHORE_OFFSET;
|
|
|
+
|
|
|
+ return tmp;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Enable a DMA channel.
|
|
|
*
|
|
@@ -61,7 +102,7 @@ int mxs_dma_validate_chan(int channel)
|
|
|
* This function marks the DMA channel as "busy," whether or not there are any
|
|
|
* descriptors to process.
|
|
|
*/
|
|
|
-int mxs_dma_enable(int channel)
|
|
|
+static int mxs_dma_enable(int channel)
|
|
|
{
|
|
|
struct mx28_apbh_regs *apbh_regs =
|
|
|
(struct mx28_apbh_regs *)MXS_APBH_BASE;
|
|
@@ -132,7 +173,7 @@ int mxs_dma_enable(int channel)
|
|
|
* state. It is unwise to call this function if there is ANY chance the hardware
|
|
|
* is still processing a command.
|
|
|
*/
|
|
|
-int mxs_dma_disable(int channel)
|
|
|
+static int mxs_dma_disable(int channel)
|
|
|
{
|
|
|
struct mxs_dma_chan *pchan;
|
|
|
struct mx28_apbh_regs *apbh_regs =
|
|
@@ -162,7 +203,7 @@ int mxs_dma_disable(int channel)
|
|
|
/*
|
|
|
* Resets the DMA channel hardware.
|
|
|
*/
|
|
|
-int mxs_dma_reset(int channel)
|
|
|
+static int mxs_dma_reset(int channel)
|
|
|
{
|
|
|
struct mx28_apbh_regs *apbh_regs =
|
|
|
(struct mx28_apbh_regs *)MXS_APBH_BASE;
|
|
@@ -178,91 +219,12 @@ int mxs_dma_reset(int channel)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Freeze a DMA channel.
|
|
|
- *
|
|
|
- * This function causes the channel to continuously fail arbitration for bus
|
|
|
- * access, which halts all forward progress without losing any state. A call to
|
|
|
- * mxs_dma_unfreeze() will cause the channel to continue its current operation
|
|
|
- * with no ill effect.
|
|
|
- */
|
|
|
-int mxs_dma_freeze(int channel)
|
|
|
-{
|
|
|
- struct mx28_apbh_regs *apbh_regs =
|
|
|
- (struct mx28_apbh_regs *)MXS_APBH_BASE;
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = mxs_dma_validate_chan(channel);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
-
|
|
|
- writel(1 << (channel + APBH_CHANNEL_CTRL_FREEZE_CHANNEL_OFFSET),
|
|
|
- &apbh_regs->hw_apbh_channel_ctrl_set);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Unfreeze a DMA channel.
|
|
|
- *
|
|
|
- * This function reverses the effect of mxs_dma_freeze(), enabling the DMA
|
|
|
- * channel to continue from where it was frozen.
|
|
|
- */
|
|
|
-int mxs_dma_unfreeze(int channel)
|
|
|
-{
|
|
|
- struct mx28_apbh_regs *apbh_regs =
|
|
|
- (struct mx28_apbh_regs *)MXS_APBH_BASE;
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = mxs_dma_validate_chan(channel);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
-
|
|
|
- writel(1 << (channel + APBH_CHANNEL_CTRL_FREEZE_CHANNEL_OFFSET),
|
|
|
- &apbh_regs->hw_apbh_channel_ctrl_clr);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Read a DMA channel's hardware semaphore.
|
|
|
- *
|
|
|
- * As used by the MXS platform's DMA software, the DMA channel's hardware
|
|
|
- * semaphore reflects the number of DMA commands the hardware will process, but
|
|
|
- * has not yet finished. This is a volatile value read directly from hardware,
|
|
|
- * so it must be be viewed as immediately stale.
|
|
|
- *
|
|
|
- * If the channel is not marked busy, or has finished processing all its
|
|
|
- * commands, this value should be zero.
|
|
|
- *
|
|
|
- * See mxs_dma_append() for details on how DMA command blocks must be configured
|
|
|
- * to maintain the expected behavior of the semaphore's value.
|
|
|
- */
|
|
|
-int mxs_dma_read_semaphore(int channel)
|
|
|
-{
|
|
|
- struct mx28_apbh_regs *apbh_regs =
|
|
|
- (struct mx28_apbh_regs *)MXS_APBH_BASE;
|
|
|
- uint32_t tmp;
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = mxs_dma_validate_chan(channel);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
-
|
|
|
- tmp = readl(&apbh_regs->ch[channel].hw_apbh_ch_sema);
|
|
|
-
|
|
|
- tmp &= APBH_CHn_SEMA_PHORE_MASK;
|
|
|
- tmp >>= APBH_CHn_SEMA_PHORE_OFFSET;
|
|
|
-
|
|
|
- return tmp;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Enable or disable DMA interrupt.
|
|
|
*
|
|
|
* This function enables the given DMA channel to interrupt the CPU.
|
|
|
*/
|
|
|
-int mxs_dma_enable_irq(int channel, int enable)
|
|
|
+static int mxs_dma_enable_irq(int channel, int enable)
|
|
|
{
|
|
|
struct mx28_apbh_regs *apbh_regs =
|
|
|
(struct mx28_apbh_regs *)MXS_APBH_BASE;
|
|
@@ -282,33 +244,13 @@ int mxs_dma_enable_irq(int channel, int enable)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Check if a DMA interrupt is pending.
|
|
|
- */
|
|
|
-int mxs_dma_irq_is_pending(int channel)
|
|
|
-{
|
|
|
- struct mx28_apbh_regs *apbh_regs =
|
|
|
- (struct mx28_apbh_regs *)MXS_APBH_BASE;
|
|
|
- uint32_t tmp;
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = mxs_dma_validate_chan(channel);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
-
|
|
|
- tmp = readl(&apbh_regs->hw_apbh_ctrl1);
|
|
|
- tmp |= readl(&apbh_regs->hw_apbh_ctrl2);
|
|
|
-
|
|
|
- return (tmp >> channel) & 1;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Clear DMA interrupt.
|
|
|
*
|
|
|
* The software that is using the DMA channel must register to receive its
|
|
|
* interrupts and, when they arrive, must call this function to clear them.
|
|
|
*/
|
|
|
-int mxs_dma_ack_irq(int channel)
|
|
|
+static int mxs_dma_ack_irq(int channel)
|
|
|
{
|
|
|
struct mx28_apbh_regs *apbh_regs =
|
|
|
(struct mx28_apbh_regs *)MXS_APBH_BASE;
|
|
@@ -327,7 +269,7 @@ int mxs_dma_ack_irq(int channel)
|
|
|
/*
|
|
|
* Request to reserve a DMA channel
|
|
|
*/
|
|
|
-int mxs_dma_request(int channel)
|
|
|
+static int mxs_dma_request(int channel)
|
|
|
{
|
|
|
struct mxs_dma_chan *pchan;
|
|
|
|
|
@@ -359,7 +301,7 @@ int mxs_dma_request(int channel)
|
|
|
* The channel will NOT be released if it's marked "busy" (see
|
|
|
* mxs_dma_enable()).
|
|
|
*/
|
|
|
-int mxs_dma_release(int channel)
|
|
|
+static int mxs_dma_release(int channel)
|
|
|
{
|
|
|
struct mxs_dma_chan *pchan;
|
|
|
int ret;
|
|
@@ -410,32 +352,6 @@ void mxs_dma_desc_free(struct mxs_dma_desc *pdesc)
|
|
|
free(pdesc);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Return the address of the command within a descriptor.
|
|
|
- */
|
|
|
-unsigned int mxs_dma_cmd_address(struct mxs_dma_desc *desc)
|
|
|
-{
|
|
|
- return desc->address + offsetof(struct mxs_dma_desc, cmd);
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Check if descriptor is on a channel's active list.
|
|
|
- *
|
|
|
- * This function returns the state of a descriptor's "ready" flag. This flag is
|
|
|
- * usually set only if the descriptor appears on a channel's active list. The
|
|
|
- * descriptor may or may not have already been processed by the hardware.
|
|
|
- *
|
|
|
- * The "ready" flag is set when the descriptor is submitted to a channel by a
|
|
|
- * call to mxs_dma_append() or mxs_dma_append_list(). The "ready" flag is
|
|
|
- * cleared when a processed descriptor is moved off the active list by a call
|
|
|
- * to mxs_dma_finish(). The "ready" flag is NOT cleared if the descriptor is
|
|
|
- * aborted by a call to mxs_dma_disable().
|
|
|
- */
|
|
|
-int mxs_dma_desc_pending(struct mxs_dma_desc *pdesc)
|
|
|
-{
|
|
|
- return pdesc->flags & MXS_DMA_DESC_READY;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Add a DMA descriptor to a channel.
|
|
|
*
|
|
@@ -508,31 +424,6 @@ int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Retrieve processed DMA descriptors.
|
|
|
- *
|
|
|
- * This function moves all the descriptors from the DMA channel's "done" list to
|
|
|
- * the head of the given list.
|
|
|
- */
|
|
|
-int mxs_dma_get_finished(int channel, struct list_head *head)
|
|
|
-{
|
|
|
- struct mxs_dma_chan *pchan;
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = mxs_dma_validate_chan(channel);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
-
|
|
|
- if (head == NULL)
|
|
|
- return 0;
|
|
|
-
|
|
|
- pchan = mxs_dma_channels + channel;
|
|
|
-
|
|
|
- list_splice(&pchan->done, head);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Clean up processed DMA descriptors.
|
|
|
*
|
|
@@ -544,7 +435,7 @@ int mxs_dma_get_finished(int channel, struct list_head *head)
|
|
|
* This function marks the DMA channel as "not busy" if no unprocessed
|
|
|
* descriptors remain on the "active" list.
|
|
|
*/
|
|
|
-int mxs_dma_finish(int channel, struct list_head *head)
|
|
|
+static int mxs_dma_finish(int channel, struct list_head *head)
|
|
|
{
|
|
|
int sem;
|
|
|
struct mxs_dma_chan *pchan;
|
|
@@ -590,7 +481,7 @@ int mxs_dma_finish(int channel, struct list_head *head)
|
|
|
/*
|
|
|
* Wait for DMA channel to complete
|
|
|
*/
|
|
|
-int mxs_dma_wait_complete(uint32_t timeout, unsigned int chan)
|
|
|
+static int mxs_dma_wait_complete(uint32_t timeout, unsigned int chan)
|
|
|
{
|
|
|
struct mx28_apbh_regs *apbh_regs =
|
|
|
(struct mx28_apbh_regs *)MXS_APBH_BASE;
|