mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-04 20:19:47 +08:00 
			
		
		
		
	USB: musb: enable low level DMA operation for Blackfin
- DMA registers in Blackfin have different layout - DMA interrupt flags need to be cleared by software Signed-off-by: Bryan Wu <cooloney@kernel.org> Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
		
							parent
							
								
									2c557a4a98
								
							
						
					
					
						commit
						6995eb68aa
					
				| @ -34,58 +34,7 @@ | ||||
| #include <linux/interrupt.h> | ||||
| #include <linux/platform_device.h> | ||||
| #include "musb_core.h" | ||||
| 
 | ||||
| #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) | ||||
| #include "omap2430.h" | ||||
| #endif | ||||
| 
 | ||||
| #define MUSB_HSDMA_BASE		0x200 | ||||
| #define MUSB_HSDMA_INTR		(MUSB_HSDMA_BASE + 0) | ||||
| #define MUSB_HSDMA_CONTROL		0x4 | ||||
| #define MUSB_HSDMA_ADDRESS		0x8 | ||||
| #define MUSB_HSDMA_COUNT		0xc | ||||
| 
 | ||||
| #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset)		\ | ||||
| 		(MUSB_HSDMA_BASE + (_bchannel << 4) + _offset) | ||||
| 
 | ||||
| /* control register (16-bit): */ | ||||
| #define MUSB_HSDMA_ENABLE_SHIFT		0 | ||||
| #define MUSB_HSDMA_TRANSMIT_SHIFT		1 | ||||
| #define MUSB_HSDMA_MODE1_SHIFT		2 | ||||
| #define MUSB_HSDMA_IRQENABLE_SHIFT		3 | ||||
| #define MUSB_HSDMA_ENDPOINT_SHIFT		4 | ||||
| #define MUSB_HSDMA_BUSERROR_SHIFT		8 | ||||
| #define MUSB_HSDMA_BURSTMODE_SHIFT		9 | ||||
| #define MUSB_HSDMA_BURSTMODE		(3 << MUSB_HSDMA_BURSTMODE_SHIFT) | ||||
| #define MUSB_HSDMA_BURSTMODE_UNSPEC	0 | ||||
| #define MUSB_HSDMA_BURSTMODE_INCR4	1 | ||||
| #define MUSB_HSDMA_BURSTMODE_INCR8	2 | ||||
| #define MUSB_HSDMA_BURSTMODE_INCR16	3 | ||||
| 
 | ||||
| #define MUSB_HSDMA_CHANNELS		8 | ||||
| 
 | ||||
| struct musb_dma_controller; | ||||
| 
 | ||||
| struct musb_dma_channel { | ||||
| 	struct dma_channel		channel; | ||||
| 	struct musb_dma_controller	*controller; | ||||
| 	u32				start_addr; | ||||
| 	u32				len; | ||||
| 	u16				max_packet_sz; | ||||
| 	u8				idx; | ||||
| 	u8				epnum; | ||||
| 	u8				transmit; | ||||
| }; | ||||
| 
 | ||||
| struct musb_dma_controller { | ||||
| 	struct dma_controller		controller; | ||||
| 	struct musb_dma_channel		channel[MUSB_HSDMA_CHANNELS]; | ||||
| 	void				*private_data; | ||||
| 	void __iomem			*base; | ||||
| 	u8				channel_count; | ||||
| 	u8				used_channels; | ||||
| 	u8				irq; | ||||
| }; | ||||
| #include "musbhsdma.h" | ||||
| 
 | ||||
| static int dma_controller_start(struct dma_controller *c) | ||||
| { | ||||
| @ -203,12 +152,8 @@ static void configure_channel(struct dma_channel *channel, | ||||
| 				: 0); | ||||
| 
 | ||||
| 	/* address/count */ | ||||
| 	musb_writel(mbase, | ||||
| 		MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), | ||||
| 		dma_addr); | ||||
| 	musb_writel(mbase, | ||||
| 		MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), | ||||
| 		len); | ||||
| 	musb_write_hsdma_addr(mbase, bchannel, dma_addr); | ||||
| 	musb_write_hsdma_count(mbase, bchannel, len); | ||||
| 
 | ||||
| 	/* control (this should start things) */ | ||||
| 	musb_writew(mbase, | ||||
| @ -279,13 +224,8 @@ static int dma_channel_abort(struct dma_channel *channel) | ||||
| 		musb_writew(mbase, | ||||
| 			MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL), | ||||
| 			0); | ||||
| 		musb_writel(mbase, | ||||
| 			MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), | ||||
| 			0); | ||||
| 		musb_writel(mbase, | ||||
| 			MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), | ||||
| 			0); | ||||
| 
 | ||||
| 		musb_write_hsdma_addr(mbase, bchannel, 0); | ||||
| 		musb_write_hsdma_count(mbase, bchannel, 0); | ||||
| 		channel->status = MUSB_DMA_STATUS_FREE; | ||||
| 	} | ||||
| 
 | ||||
| @ -333,10 +273,8 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) | ||||
| 			} else { | ||||
| 				u8 devctl; | ||||
| 
 | ||||
| 				addr = musb_readl(mbase, | ||||
| 						MUSB_HSDMA_CHANNEL_OFFSET( | ||||
| 							bchannel, | ||||
| 							MUSB_HSDMA_ADDRESS)); | ||||
| 				addr = musb_read_hsdma_addr(mbase, | ||||
| 						bchannel); | ||||
| 				channel->actual_len = addr | ||||
| 					- musb_channel->start_addr; | ||||
| 
 | ||||
| @ -375,6 +313,12 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| #ifdef CONFIG_BLACKFIN | ||||
| 	/* Clear DMA interrup flags */ | ||||
| 	musb_writeb(mbase, MUSB_HSDMA_INTR, int_hsdma); | ||||
| #endif | ||||
| 
 | ||||
| 	retval = IRQ_HANDLED; | ||||
| done: | ||||
| 	spin_unlock_irqrestore(&musb->lock, flags); | ||||
|  | ||||
							
								
								
									
										149
									
								
								drivers/usb/musb/musbhsdma.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								drivers/usb/musb/musbhsdma.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,149 @@ | ||||
| /*
 | ||||
|  * MUSB OTG driver - support for Mentor's DMA controller | ||||
|  * | ||||
|  * Copyright 2005 Mentor Graphics Corporation | ||||
|  * Copyright (C) 2005-2007 by Texas Instruments | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License | ||||
|  * version 2 as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||||
|  * 02110-1301 USA | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED | ||||
|  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN | ||||
|  * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||
|  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||||
|  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||||
|  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||
|  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) | ||||
| #include "omap2430.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifndef CONFIG_BLACKFIN | ||||
| 
 | ||||
| #define MUSB_HSDMA_BASE		0x200 | ||||
| #define MUSB_HSDMA_INTR		(MUSB_HSDMA_BASE + 0) | ||||
| #define MUSB_HSDMA_CONTROL		0x4 | ||||
| #define MUSB_HSDMA_ADDRESS		0x8 | ||||
| #define MUSB_HSDMA_COUNT		0xc | ||||
| 
 | ||||
| #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset)		\ | ||||
| 		(MUSB_HSDMA_BASE + (_bchannel << 4) + _offset) | ||||
| 
 | ||||
| #define musb_read_hsdma_addr(mbase, bchannel)	\ | ||||
| 	musb_readl(mbase,	\ | ||||
| 		   MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS)) | ||||
| 
 | ||||
| #define musb_write_hsdma_addr(mbase, bchannel, addr) \ | ||||
| 	musb_writel(mbase, \ | ||||
| 		    MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), \ | ||||
| 		    addr) | ||||
| 
 | ||||
| #define musb_write_hsdma_count(mbase, bchannel, len) \ | ||||
| 	musb_writel(mbase, \ | ||||
| 		    MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), \ | ||||
| 		    len) | ||||
| #else | ||||
| 
 | ||||
| #define MUSB_HSDMA_BASE		0x400 | ||||
| #define MUSB_HSDMA_INTR		(MUSB_HSDMA_BASE + 0) | ||||
| #define MUSB_HSDMA_CONTROL		0x04 | ||||
| #define MUSB_HSDMA_ADDR_LOW		0x08 | ||||
| #define MUSB_HSDMA_ADDR_HIGH		0x0C | ||||
| #define MUSB_HSDMA_COUNT_LOW		0x10 | ||||
| #define MUSB_HSDMA_COUNT_HIGH		0x14 | ||||
| 
 | ||||
| #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset)		\ | ||||
| 		(MUSB_HSDMA_BASE + (_bchannel * 0x20) + _offset) | ||||
| 
 | ||||
| static inline u32 musb_read_hsdma_addr(void __iomem *mbase, u8 bchannel) | ||||
| { | ||||
| 	u32 addr = musb_readw(mbase, | ||||
| 		MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_HIGH)); | ||||
| 
 | ||||
| 	addr = addr << 16; | ||||
| 
 | ||||
| 	addr |= musb_readw(mbase, | ||||
| 		MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_LOW)); | ||||
| 
 | ||||
| 	return addr; | ||||
| } | ||||
| 
 | ||||
| static inline void musb_write_hsdma_addr(void __iomem *mbase, | ||||
| 				u8 bchannel, dma_addr_t dma_addr) | ||||
| { | ||||
| 	musb_writew(mbase, | ||||
| 		MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_LOW), | ||||
| 		((u16)((u32) dma_addr & 0xFFFF))); | ||||
| 	musb_writew(mbase, | ||||
| 		MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_HIGH), | ||||
| 		((u16)(((u32) dma_addr >> 16) & 0xFFFF))); | ||||
| } | ||||
| 
 | ||||
| static inline void musb_write_hsdma_count(void __iomem *mbase, | ||||
| 				u8 bchannel, u32 len) | ||||
| { | ||||
| 	musb_writew(mbase, | ||||
| 		MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_LOW), | ||||
| 		((u16)((u32) len & 0xFFFF))); | ||||
| 	musb_writew(mbase, | ||||
| 		MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_HIGH), | ||||
| 		((u16)(((u32) len >> 16) & 0xFFFF))); | ||||
| } | ||||
| 
 | ||||
| #endif /* CONFIG_BLACKFIN */ | ||||
| 
 | ||||
| /* control register (16-bit): */ | ||||
| #define MUSB_HSDMA_ENABLE_SHIFT		0 | ||||
| #define MUSB_HSDMA_TRANSMIT_SHIFT	1 | ||||
| #define MUSB_HSDMA_MODE1_SHIFT		2 | ||||
| #define MUSB_HSDMA_IRQENABLE_SHIFT	3 | ||||
| #define MUSB_HSDMA_ENDPOINT_SHIFT	4 | ||||
| #define MUSB_HSDMA_BUSERROR_SHIFT	8 | ||||
| #define MUSB_HSDMA_BURSTMODE_SHIFT	9 | ||||
| #define MUSB_HSDMA_BURSTMODE		(3 << MUSB_HSDMA_BURSTMODE_SHIFT) | ||||
| #define MUSB_HSDMA_BURSTMODE_UNSPEC	0 | ||||
| #define MUSB_HSDMA_BURSTMODE_INCR4	1 | ||||
| #define MUSB_HSDMA_BURSTMODE_INCR8	2 | ||||
| #define MUSB_HSDMA_BURSTMODE_INCR16	3 | ||||
| 
 | ||||
| #define MUSB_HSDMA_CHANNELS		8 | ||||
| 
 | ||||
| struct musb_dma_controller; | ||||
| 
 | ||||
| struct musb_dma_channel { | ||||
| 	struct dma_channel		channel; | ||||
| 	struct musb_dma_controller	*controller; | ||||
| 	u32				start_addr; | ||||
| 	u32				len; | ||||
| 	u16				max_packet_sz; | ||||
| 	u8				idx; | ||||
| 	u8				epnum; | ||||
| 	u8				transmit; | ||||
| }; | ||||
| 
 | ||||
| struct musb_dma_controller { | ||||
| 	struct dma_controller		controller; | ||||
| 	struct musb_dma_channel		channel[MUSB_HSDMA_CHANNELS]; | ||||
| 	void				*private_data; | ||||
| 	void __iomem			*base; | ||||
| 	u8				channel_count; | ||||
| 	u8				used_channels; | ||||
| 	u8				irq; | ||||
| }; | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Bryan Wu
						Bryan Wu