diff options
author | Patrick Turley <patrick.turley@freescale.com> | 2010-02-03 10:30:36 -0600 |
---|---|---|
committer | Alejandro Gonzalez <alex.gonzalez@digi.com> | 2010-05-25 11:13:36 +0200 |
commit | 71843f08f749a29f671f5ae41a29eafb98777636 (patch) | |
tree | 003b2b8eb1d2e89579aafe7ff0b75be4b69b53f5 /arch/arm/plat-mxs | |
parent | 18bc83e1b9ebb015bfd359f0dda9568f55748f1b (diff) |
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>
Signed-off-by: Alejandro Gonzalez <alex.gonzalez@digi.com>
Diffstat (limited to 'arch/arm/plat-mxs')
-rw-r--r-- | arch/arm/plat-mxs/dmaengine.c | 19 | ||||
-rw-r--r-- | arch/arm/plat-mxs/include/mach/dmaengine.h | 353 | ||||
-rw-r--r-- | arch/arm/plat-mxs/include/mach/pinctrl.h | 30 |
3 files changed, 375 insertions, 27 deletions
diff --git a/arch/arm/plat-mxs/dmaengine.c b/arch/arm/plat-mxs/dmaengine.c index c3e592c1bdff..eaa522e13079 100644 --- a/arch/arm/plat-mxs/dmaengine.c +++ b/arch/arm/plat-mxs/dmaengine.c @@ -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) diff --git a/arch/arm/plat-mxs/include/mach/dmaengine.h b/arch/arm/plat-mxs/include/mach/dmaengine.h index 2771aca50e17..1071f4e6f674 100644 --- a/arch/arm/plat-mxs/include/mach/dmaengine.h +++ b/arch/arm/plat-mxs/include/mach/dmaengine.h @@ -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 diff --git a/arch/arm/plat-mxs/include/mach/pinctrl.h b/arch/arm/plat-mxs/include/mach/pinctrl.h index a636caf4cd82..b9dd38056eb4 100644 --- a/arch/arm/plat-mxs/include/mach/pinctrl.h +++ b/arch/arm/plat-mxs/include/mach/pinctrl.h @@ -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; |