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:
Patrick Turley
2010-02-03 10:30:36 -06:00
committed by Matt Sealey
parent 37dccd44a7
commit 109668b58c
3 changed files with 375 additions and 27 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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;