mirror of
https://github.com/genesi/linux-legacy.git
synced 2026-09-18 12:44:18 +00:00
ENGR00120756 [MX28_BSP] Pin control and DMA code needs more comments
Added comments to the above-mentioned code. Signed-off-by: Patrick Turley <patrick.turley@freescale.com>
This commit is contained in:
committed by
Matt Sealey
parent
37dccd44a7
commit
109668b58c
@@ -33,8 +33,27 @@
|
||||
|
||||
static void *mxs_dma_pool;
|
||||
static int mxs_dma_alignment = MXS_DMA_ALIGNMENT;
|
||||
|
||||
/*
|
||||
* The mutex that arbitrates access to the array of structures that represent
|
||||
* all the DMA channels in the system (see mxs_dma_channels, below).
|
||||
*/
|
||||
|
||||
static DEFINE_MUTEX(mxs_dma_mutex);
|
||||
|
||||
/*
|
||||
* The list of DMA drivers that manage various DMA channels. A DMA device
|
||||
* driver registers to manage DMA channels by calling mxs_dma_device_register().
|
||||
*/
|
||||
|
||||
static LIST_HEAD(mxs_dma_devices);
|
||||
|
||||
/*
|
||||
* The array of struct mxs_dma_chan that represent every DMA channel in the
|
||||
* system. The index of the structure in the array indicates the specific DMA
|
||||
* hardware it represents (see mach-mx28/include/mach/dma.h).
|
||||
*/
|
||||
|
||||
static struct mxs_dma_chan mxs_dma_channels[MAX_DMA_CHANNELS];
|
||||
|
||||
int mxs_dma_request(int channel, struct device *dev, const char *name)
|
||||
|
||||
@@ -27,6 +27,13 @@
|
||||
|
||||
#define MXS_DMA_ALIGNMENT 8
|
||||
|
||||
/**
|
||||
* struct mxs_dma_cmd_bits - MXS DMA hardware command bits.
|
||||
*
|
||||
* This structure describes the in-memory layout of the command bits in a DMA
|
||||
* command. See the appropriate reference manual for a detailed description
|
||||
* of what these bits mean to the DMA hardware.
|
||||
*/
|
||||
struct mxs_dma_cmd_bits {
|
||||
unsigned int command:2;
|
||||
#define NO_DMA_XFER 0x00
|
||||
@@ -46,6 +53,14 @@ struct mxs_dma_cmd_bits {
|
||||
unsigned int bytes:16;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mxs_dma_cmd - MXS DMA hardware command.
|
||||
*
|
||||
* This structure describes the in-memory layout of an entire DMA command,
|
||||
* including space for the maximum number of PIO accesses. See the appropriate
|
||||
* reference manual for a detailed description of what these fields mean to the
|
||||
* DMA hardware.
|
||||
*/
|
||||
struct mxs_dma_cmd {
|
||||
unsigned long next;
|
||||
union {
|
||||
@@ -59,17 +74,66 @@ struct mxs_dma_cmd {
|
||||
unsigned long pio_words[DMA_PIO_WORDS];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mxs_dma_desc - MXS DMA command descriptor.
|
||||
*
|
||||
* This structure incorporates an MXS DMA hardware command structure, along
|
||||
* with metadata.
|
||||
*
|
||||
* @cmd: The MXS DMA hardware command block.
|
||||
* @flags: Flags that represent the state of this DMA descriptor.
|
||||
* @address: The physical address of this descriptor.
|
||||
* @buffer: A convenient place for software to put the virtual address of the
|
||||
* associated data buffer (the physical address of the buffer
|
||||
* appears in the DMA command). The MXS platform DMA software doesn't
|
||||
* use this field -- it is provided as a convenience.
|
||||
* @node: Links this structure into a list.
|
||||
*/
|
||||
struct mxs_dma_desc {
|
||||
struct mxs_dma_cmd cmd;
|
||||
unsigned int flags;
|
||||
#define MXS_DMA_DESC_READY 0x80000000
|
||||
/* address is desc physcial address */
|
||||
dma_addr_t address;
|
||||
/* buffer address */
|
||||
void *buffer;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mxs_dma_chan - MXS DMA channel
|
||||
*
|
||||
* This structure represents a single DMA channel. The MXS platform code
|
||||
* maintains an array of these structures to represent every DMA channel in the
|
||||
* system (see mxs_dma_channels).
|
||||
*
|
||||
* @name: A human-readable string that describes how this channel is
|
||||
* being used or what software "owns" it. This field is set when
|
||||
* when the channel is reserved by mxs_dma_request().
|
||||
* @dev: A pointer to a struct device *, cast to an unsigned long, and
|
||||
* representing the software that "owns" the channel. This field
|
||||
* is set when when the channel is reserved by mxs_dma_request().
|
||||
* @lock: Arbitrates access to this channel.
|
||||
* @dma: A pointer to a struct mxs_dma_device representing the driver
|
||||
* code that operates this channel.
|
||||
* @flags: Flag bits that represent the state of this channel.
|
||||
* @active_num: If the channel is not busy, this value is zero. If the channel
|
||||
* is busy, this field contains the number of DMA command
|
||||
* descriptors at the head of the active list that the hardware
|
||||
* has been told to process. This value is set at the moment the
|
||||
* channel is enabled by mxs_dma_enable(). More descriptors may
|
||||
* arrive after the channel is enabled, so the number of
|
||||
* descriptors on the active list may be greater than this value.
|
||||
* In fact, it should always be active_num + pending_num.
|
||||
* @pending_num: The number of DMA command descriptors at the tail of the
|
||||
* active list that the hardware has not been told to process.
|
||||
* @active: The list of DMA command descriptors either currently being
|
||||
* processed by the hardware or waiting to be processed.
|
||||
* Descriptors being processed appear at the head of the list,
|
||||
* while pending descriptors appear at the tail. The total number
|
||||
* should always be active_num + pending_num.
|
||||
* @done: The list of DMA command descriptors that have either been
|
||||
* processed by the DMA hardware or aborted by a call to
|
||||
* mxs_dma_disable().
|
||||
*/
|
||||
struct mxs_dma_chan {
|
||||
const char *name;
|
||||
unsigned long dev;
|
||||
@@ -87,7 +151,14 @@ struct mxs_dma_chan {
|
||||
struct list_head done;
|
||||
};
|
||||
|
||||
/* dma controller devices */
|
||||
/**
|
||||
* struct mxs_dma_device - DMA channel driver interface.
|
||||
*
|
||||
* This structure represents the driver that operates a DMA channel. Every
|
||||
* struct mxs_dma_chan contains a pointer to a structure of this type, which is
|
||||
* installed when the driver registers to "own" the channel (see
|
||||
* mxs_dma_device_register()).
|
||||
*/
|
||||
struct mxs_dma_device {
|
||||
struct list_head node;
|
||||
const char *name;
|
||||
@@ -112,65 +183,297 @@ struct mxs_dma_device {
|
||||
void (*set_target) (struct mxs_dma_device *, unsigned int, int);
|
||||
};
|
||||
|
||||
/**
|
||||
* mxs_dma_device_register - Register a DMA driver.
|
||||
*
|
||||
* This function registers a driver for a contiguous group of DMA channels (the
|
||||
* ordering of DMA channels is specified by the globally unique DMA channel
|
||||
* numbers given in mach/dma.h).
|
||||
*
|
||||
* @pdev: A pointer to a structure that represents the driver. This structure
|
||||
* contains fields that specify the first DMA channel number and the
|
||||
* number of channels.
|
||||
*/
|
||||
extern int mxs_dma_device_register(struct mxs_dma_device *pdev);
|
||||
|
||||
/* request a dma channel */
|
||||
/**
|
||||
* mxs_dma_request - Request to reserve a DMA channel.
|
||||
*
|
||||
* @channel: The channel number. This is one of the globally unique DMA channel
|
||||
* numbers given in mach/dma.h.
|
||||
* @dev: A pointer to a struct device representing the channel "owner."
|
||||
* @name: A human-readable string that identifies the channel owner or the
|
||||
* purpose of the channel.
|
||||
*/
|
||||
extern int mxs_dma_request(int channel, struct device *dev, const char *name);
|
||||
/* Release a dma channel */
|
||||
|
||||
/**
|
||||
* mxs_dma_release - Release a DMA channel.
|
||||
*
|
||||
* This function releases a DMA channel from its current owner.
|
||||
*
|
||||
* The channel will NOT be released if it's marked "busy" (see
|
||||
* mxs_dma_enable()).
|
||||
*
|
||||
* @channel: The channel number. This is one of the globally unique DMA channel
|
||||
* numbers given in mach/dma.h.
|
||||
* @dev: A pointer to a struct device representing the channel "owner." If
|
||||
* this doesn't match the owner given to mxs_dma_request(), the
|
||||
* channel will NOT be released.
|
||||
*/
|
||||
extern void mxs_dma_release(int channel, struct device *dev);
|
||||
|
||||
/* Enable dma transfer */
|
||||
/**
|
||||
* mxs_dma_enable - Enable a DMA channel.
|
||||
*
|
||||
* If the given channel has any DMA descriptors on its active list, this
|
||||
* function causes the DMA hardware to begin processing them.
|
||||
*
|
||||
* This function marks the DMA channel as "busy," whether or not there are any
|
||||
* descriptors to process.
|
||||
*
|
||||
* @channel: The channel number. This is one of the globally unique DMA channel
|
||||
* numbers given in mach/dma.h.
|
||||
*/
|
||||
extern int mxs_dma_enable(int channel);
|
||||
|
||||
/*
|
||||
* Disable dma transfer and the desc will be putted into done list
|
||||
* Before calling mxs_dma_release, mxs_dma_get_cooked must called to
|
||||
* take dma desc back.
|
||||
/**
|
||||
* mxs_dma_disable - Disable a DMA channel.
|
||||
*
|
||||
* This function shuts down a DMA channel and marks it as "not busy." Any
|
||||
* descriptors on the active list are immediately moved to the head of the
|
||||
* "done" list, whether or not they have actually been processed by the
|
||||
* hardware. The "ready" flags of these descriptors are NOT cleared, so they
|
||||
* still appear to be active.
|
||||
*
|
||||
* This function immediately shuts down a DMA channel's hardware, aborting any
|
||||
* I/O that may be in progress, potentially leaving I/O hardware in an undefined
|
||||
* state. It is unwise to call this function if there is ANY chance the hardware
|
||||
* is still processing a command.
|
||||
*
|
||||
* @channel: The channel number. This is one of the globally unique DMA channel
|
||||
* numbers given in mach/dma.h.
|
||||
*/
|
||||
extern void mxs_dma_disable(int channel);
|
||||
/* reset dma channel */
|
||||
|
||||
/**
|
||||
* mxs_dma_reset - Resets the DMA channel hardware.
|
||||
*
|
||||
* @channel: The channel number. This is one of the globally unique DMA channel
|
||||
* numbers given in mach/dma.h.
|
||||
*/
|
||||
extern void mxs_dma_reset(int channel);
|
||||
/* freeze dma channel */
|
||||
|
||||
/**
|
||||
* mxs_dma_freeze - 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.
|
||||
*
|
||||
* @channel: The channel number. This is one of the globally unique DMA channel
|
||||
* numbers given in mach/dma.h.
|
||||
*/
|
||||
extern void mxs_dma_freeze(int channel);
|
||||
/* unfreeze dma channel */
|
||||
|
||||
/**
|
||||
* mxs_dma_unfreeze - Unfreeze a DMA channel.
|
||||
*
|
||||
* This function reverses the effect of mxs_dma_freeze(), enabling the DMA
|
||||
* channel to continue from where it was frozen.
|
||||
*
|
||||
* @channel: The channel number. This is one of the globally unique DMA channel
|
||||
* numbers given in mach/dma.h.
|
||||
*/
|
||||
extern void mxs_dma_unfreeze(int channel);
|
||||
/*
|
||||
* Called to task back the done desc. if head is NULL, they will be
|
||||
* put into done list. And must called mxs_dma_get_cooked to take
|
||||
* them back
|
||||
|
||||
/**
|
||||
* mxs_dma_cooked - Clean up processed DMA descriptors.
|
||||
*
|
||||
* This function removes processed DMA descriptors from the "active" list. Pass
|
||||
* in a non-NULL list head to get the descriptors moved to your list. Pass NULL
|
||||
* to get the descriptors moved to the channel's "done" list. Descriptors on
|
||||
* the "done" list can be retrieved with mxs_dma_get_cooked().
|
||||
*
|
||||
* This function marks the DMA channel as "not busy" if no unprocessed
|
||||
* descriptors remain on the "active" list.
|
||||
*
|
||||
* @channel: The channel number. This is one of the globally unique DMA channel
|
||||
* numbers given in mach/dma.h.
|
||||
* @head: If this is not NULL, it is the list to which the processed
|
||||
* descriptors should be moved. If this list is NULL, the descriptors
|
||||
* will be moved to the "done" list.
|
||||
*/
|
||||
extern int mxs_dma_cooked(int channel, struct list_head *head);
|
||||
|
||||
/* Read the dma semaphore to check if there are pending dma desc */
|
||||
/**
|
||||
* mxs_dma_read_semaphore - 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.
|
||||
*
|
||||
* @channel: The channel number. This is one of the globally unique DMA channel
|
||||
* numbers given in mach/dma.h.
|
||||
*/
|
||||
extern int mxs_dma_read_semaphore(int channel);
|
||||
/* check dma irq is pending */
|
||||
|
||||
/**
|
||||
* mxs_dma_irq_is_pending - Check if a DMA interrupt is pending.
|
||||
*
|
||||
* @channel: The channel number. This is one of the globally unique DMA channel
|
||||
* numbers given in mach/dma.h.
|
||||
*/
|
||||
extern int mxs_dma_irq_is_pending(int channel);
|
||||
/* enable or disable dma irq */
|
||||
|
||||
/**
|
||||
* mxs_dma_enable_irq - Enable or disable DMA interrupt.
|
||||
*
|
||||
* This function enables the given DMA channel to interrupt the CPU.
|
||||
*
|
||||
* @channel: The channel number. This is one of the globally unique DMA channel
|
||||
* numbers given in mach/dma.h.
|
||||
* @en: True if the interrupt for this channel should be enabled. False
|
||||
* otherwise.
|
||||
*/
|
||||
extern void mxs_dma_enable_irq(int channel, int en);
|
||||
/* clear dma irq */
|
||||
|
||||
/**
|
||||
* mxs_dma_ack_irq - 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.
|
||||
*
|
||||
* @channel: The channel number. This is one of the globally unique DMA channel
|
||||
* numbers given in mach/dma.h.
|
||||
*/
|
||||
extern void mxs_dma_ack_irq(int channel);
|
||||
|
||||
/* Used to configure channel related device selection:NOUSED in i.MX28 */
|
||||
/**
|
||||
* mxs_dma_set_target - Set the target for a DMA channel.
|
||||
*
|
||||
* This function is NOT used on the i.MX28.
|
||||
*
|
||||
* @channel: The channel number. This is one of the globally unique DMA channel
|
||||
* numbers given in mach/dma.h.
|
||||
* @target: Indicates the target for the channel.
|
||||
*/
|
||||
extern void mxs_dma_set_target(int channel, int target);
|
||||
|
||||
/* mxs dma utility functions */
|
||||
extern struct mxs_dma_desc *mxs_dma_alloc_desc(void);
|
||||
extern void mxs_dma_free_desc(struct mxs_dma_desc *);
|
||||
|
||||
/**
|
||||
* mxs_dma_cmd_address - Return the address of the command within a descriptor.
|
||||
*
|
||||
* @desc: The DMA descriptor of interest.
|
||||
*/
|
||||
static inline unsigned int mxs_dma_cmd_address(struct mxs_dma_desc *desc)
|
||||
{
|
||||
return desc->address += offsetof(struct mxs_dma_desc, cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* mxs_dma_desc_pending - 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_cooked(). The "ready" flag is NOT cleared if the descriptor is
|
||||
* aborted by a call to mxs_dma_disable().
|
||||
*
|
||||
* @desc: The DMA descriptor of interest.
|
||||
*/
|
||||
static inline int mxs_dma_desc_pending(struct mxs_dma_desc *pdesc)
|
||||
{
|
||||
return pdesc->flags & MXS_DMA_DESC_READY;
|
||||
}
|
||||
|
||||
/* Add a dma desc to channel*/
|
||||
/**
|
||||
* mxs_dma_desc_append - Add a DMA descriptor to a channel.
|
||||
*
|
||||
* If the descriptor list for this channel is not empty, this function sets the
|
||||
* CHAIN bit and the NEXTCMD_ADDR fields in the last descriptor's DMA command so
|
||||
* it will chain to the new descriptor's command.
|
||||
*
|
||||
* Then, this function marks the new descriptor as "ready," adds it to the end
|
||||
* of the active descriptor list, and increments the count of pending
|
||||
* descriptors.
|
||||
*
|
||||
* The MXS platform DMA software imposes some rules on DMA commands to maintain
|
||||
* important invariants. These rules are NOT checked, but they must be carefully
|
||||
* applied by software that uses MXS DMA channels.
|
||||
*
|
||||
* Invariant:
|
||||
* The DMA channel's hardware semaphore must reflect the number of DMA
|
||||
* commands the hardware will process, but has not yet finished.
|
||||
*
|
||||
* Explanation:
|
||||
* A DMA channel begins processing commands when its hardware semaphore is
|
||||
* written with a value greater than zero, and it stops processing commands
|
||||
* when the semaphore returns to zero.
|
||||
*
|
||||
* When a channel finishes a DMA command, it will decrement its semaphore if
|
||||
* the DECREMENT_SEMAPHORE bit is set in that command's flags bits.
|
||||
*
|
||||
* In principle, it's not necessary for the DECREMENT_SEMAPHORE to be set,
|
||||
* unless it suits the purposes of the software. For example, one could
|
||||
* construct a series of five DMA commands, with the DECREMENT_SEMAPHORE
|
||||
* bit set only in the last one. Then, setting the DMA channel's hardware
|
||||
* semaphore to one would cause the entire series of five commands to be
|
||||
* processed. However, this example would violate the invariant given above.
|
||||
*
|
||||
* Rule:
|
||||
* ALL DMA commands MUST have the DECREMENT_SEMAPHORE bit set so that the DMA
|
||||
* channel's hardware semaphore will be decremented EVERY time a command is
|
||||
* processed.
|
||||
*
|
||||
* @channel: The channel number. This is one of the globally unique DMA channel
|
||||
* numbers given in mach/dma.h.
|
||||
* @pdesc: A pointer to the new descriptor.
|
||||
*/
|
||||
extern int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc);
|
||||
/* Add a list of dma desc to channel*/
|
||||
|
||||
/**
|
||||
* mxs_dma_desc_add_list - Add a list of DMA descriptors to a channel.
|
||||
*
|
||||
* This function marks all the new descriptors as "ready," adds them to the end
|
||||
* of the active descriptor list, and adds the length of the list to the count
|
||||
* of pending descriptors.
|
||||
*
|
||||
* See mxs_dma_desc_append() for important rules that apply to incoming DMA
|
||||
* descriptors.
|
||||
*
|
||||
* @channel: The channel number. This is one of the globally unique DMA channel
|
||||
* numbers given in mach/dma.h.
|
||||
* @head: A pointer to the head of the list of DMA descriptors to add.
|
||||
*/
|
||||
extern int mxs_dma_desc_add_list(int channel, struct list_head *head);
|
||||
/* Take the working done desc back */
|
||||
|
||||
/**
|
||||
* mxs_dma_desc_get_cooked - Retrieve processed DMA descriptors.
|
||||
*
|
||||
* This function moves all the descriptors from the DMA channel's "done" list to
|
||||
* the head of the given list.
|
||||
*
|
||||
* @channel: The channel number. This is one of the globally unique DMA channel
|
||||
* numbers given in mach/dma.h.
|
||||
* @head: A pointer to the head of the list that will receive the
|
||||
* descriptors on the "done" list.
|
||||
*/
|
||||
extern int mxs_dma_get_cooked(int channel, struct list_head *head);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -73,8 +73,34 @@ enum pad_voltage {
|
||||
PAD_3_3V,
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure to define a group of pins and their parameters
|
||||
/**
|
||||
* struct pin_desc - Describes the configuration of a pin.
|
||||
*
|
||||
* @name: A human-readable name that identifies the pin.
|
||||
* @id: A number that identifies the pin (use a macro from a chip-
|
||||
* specific header file -- e.g., "PINID_PWM0").
|
||||
* @fun: The function for which to configure this pin.
|
||||
* @strength: The drive strength for this pin. Note that this field should be
|
||||
* ignored and the driver hardware should *not* be configured if the
|
||||
* "drive" field is not set.
|
||||
* @voltage: The voltage rail for this pin. Note that this field should be
|
||||
* ignored and the driver hardware should *not* be configured if the
|
||||
* "drive" field is not set.
|
||||
* @pullup: If set, indicates whether the pullup is enabled. Note that this
|
||||
* field should be ignored and the pullup should *not* be configured
|
||||
* if the "pull" field is not set.
|
||||
* @drive: If set, indicates that the driver hardware for this pin should be
|
||||
* configured. This field does *not* indicate *how* the driver
|
||||
* hardware should be configured -- only whether or not it should
|
||||
* be. See the "strength" and "voltage" fields for information about
|
||||
* how to configure the driver hardware.
|
||||
* @pull: If set, indicates that the pullup for this pin should be
|
||||
* configured. This field does *not* indicate *how* the pullup
|
||||
* should be configured -- only whether or not it should be. See the
|
||||
* "pullup" field for information about how to configure the pullup.
|
||||
* @input: For GPIO pins only, this indicates whether the pin is an input.
|
||||
* @data: The data field is used when the pin is configured to GPIO output
|
||||
* mode. When data is 0, the pin's output will be 0.
|
||||
*/
|
||||
struct pin_desc {
|
||||
char *name;
|
||||
|
||||
Reference in New Issue
Block a user