From: Steve L. <slo...@us...> - 2002-05-29 00:23:19
|
Update of /cvsroot/linux-mips/linux/include/asm-mips In directory usw-pr-cvs1:/tmp/cvs-serv21710/include/asm-mips Modified Files: au1000.h au1000_dma.h Added Files: au1000_usbdev.h Log Message: Updates to Au1x00 USB slave support. Split into device layer and two function-layer drivers, a TTY driver and a raw bidirectional block driver. Only one IN/OUT block endpoint pair is working correctly now, so both function-layer drivers have only one bidirectional port. --- NEW FILE: au1000_usbdev.h --- /* * BRIEF MODULE DESCRIPTION * Au1000 USB Device-Side Driver * * Copyright 2001 MontaVista Software Inc. * Author: MontaVista Software, Inc. * st...@mv... or so...@mv... * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * 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 AUTHOR 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. * * 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., * 675 Mass Ave, Cambridge, MA 02139, USA. */ #define USBDEV_REV 0x0110 // BCD #define USBDEV_EP0_MAX_PACKET_SIZE 64 typedef enum { ATTACHED = 0, POWERED, DEFAULT, ADDRESS, CONFIGURED } usbdev_state_t; typedef enum { CB_NEW_STATE = 0, CB_PKT_COMPLETE } usbdev_cb_type_t; typedef struct usbdev_pkt { int ep_addr; // ep addr this packet routed to int size; // size of payload in bytes unsigned status; // packet status struct usbdev_pkt* next; // function layer can't touch this u8 payload[0]; // the payload } usbdev_pkt_t; #define PKT_STATUS_ACK (1<<0) #define PKT_STATUS_NAK (1<<1) #define PKT_STATUS_SU (1<<2) extern int usbdev_init(struct usb_device_descriptor* dev_desc, struct usb_config_descriptor* config_desc, struct usb_interface_descriptor* if_desc, struct usb_endpoint_descriptor* ep_desc, struct usb_string_descriptor* str_desc[], void (*cb)(usbdev_cb_type_t, unsigned long, void *), void* cb_data); extern void usbdev_exit(void); extern int usbdev_alloc_packet (int ep_addr, int data_size, usbdev_pkt_t** pkt); extern int usbdev_send_packet (int ep_addr, usbdev_pkt_t* pkt); extern int usbdev_receive_packet(int ep_addr, usbdev_pkt_t** pkt); extern int usbdev_get_byte_count(int ep_addr); Index: au1000.h =================================================================== RCS file: /cvsroot/linux-mips/linux/include/asm-mips/au1000.h,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- au1000.h 1 May 2002 18:00:31 -0000 1.19 +++ au1000.h 29 May 2002 00:23:17 -0000 1.20 @@ -56,24 +56,6 @@ mdelay(ms); } -void static inline outb_sync(u8 val, int reg) -{ - *(volatile u8 *)(reg) = val; - au_sync(); -} - -void static inline outw_sync(u16 val, int reg) -{ - *(volatile u16 *)(reg) = val; - au_sync(); -} - -void static inline outl_sync(u32 val, int reg) -{ - *(volatile u32 *)(reg) = val; - au_sync(); -} - void static inline au_writeb(u8 val, int reg) { *(volatile u8 *)(reg) = val; Index: au1000_dma.h =================================================================== RCS file: /cvsroot/linux-mips/linux/include/asm-mips/au1000_dma.h,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- au1000_dma.h 1 May 2002 18:00:31 -0000 1.9 +++ au1000_dma.h 29 May 2002 00:23:17 -0000 1.10 @@ -45,6 +45,7 @@ /* DMA Channel Register Offsets */ #define DMA_MODE_SET 0x00000000 +#define DMA_MODE_READ DMA_MODE_SET #define DMA_MODE_CLEAR 0x00000004 /* DMA Mode register bits follow */ #define DMA_DAH_MASK (0x0f << 20) @@ -102,15 +103,21 @@ struct dma_chan { int dev_id; // this channel is allocated if >=0, free otherwise unsigned int io; - int irq; const char *dev_str; + int irq; + void *irq_dev; unsigned int fifo_addr; unsigned int mode; }; /* These are in arch/mips/au1000/common/dma.c */ extern struct dma_chan au1000_dma_table[]; -extern int request_au1000_dma(int dev_id, const char *dev_str); +extern int request_au1000_dma(int dev_id, + const char *dev_str, + void (*irqhandler)(int, void *, + struct pt_regs *), + unsigned long irqflags, + void *irq_dev_id); extern void free_au1000_dma(unsigned int dmanr); extern int au1000_dma_read_proc(char *buf, char **start, off_t fpos, int length, int *eof, void *data); @@ -146,61 +153,92 @@ struct dma_chan *chan = get_dma_chan(dmanr); if (!chan) return; - outl_sync(DMA_BE0, chan->io + DMA_MODE_SET); + au_writel(DMA_BE0, chan->io + DMA_MODE_SET); } static __inline__ void enable_dma_buffer1(unsigned int dmanr) { struct dma_chan *chan = get_dma_chan(dmanr); if (!chan) return; - outl_sync(DMA_BE1, chan->io + DMA_MODE_SET); + au_writel(DMA_BE1, chan->io + DMA_MODE_SET); } static __inline__ void enable_dma_buffers(unsigned int dmanr) { struct dma_chan *chan = get_dma_chan(dmanr); if (!chan) return; - outl_sync(DMA_BE0 | DMA_BE1, chan->io + DMA_MODE_SET); + au_writel(DMA_BE0 | DMA_BE1, chan->io + DMA_MODE_SET); } -/* enable/disable a specific DMA channel */ -static __inline__ void enable_dma(unsigned int dmanr) +static __inline__ void start_dma(unsigned int dmanr) { struct dma_chan *chan = get_dma_chan(dmanr); if (!chan) return; - // set device FIFO address - outl_sync(virt_to_phys((void *) chan->fifo_addr), - chan->io + DMA_PERIPHERAL_ADDR); - - outl_sync(chan->mode | (chan->dev_id << DMA_DID_BIT) | DMA_IE | DMA_GO, - chan->io + DMA_MODE_SET); + au_writel(DMA_GO, chan->io + DMA_MODE_SET); } #define DMA_HALT_POLL 0x5000 -static __inline__ void disable_dma(unsigned int dmanr) +static __inline__ void halt_dma(unsigned int dmanr) { - int i; struct dma_chan *chan = get_dma_chan(dmanr); + int i; if (!chan) return; - outl_sync(DMA_D1 | DMA_D0 | DMA_GO, chan->io + DMA_MODE_CLEAR); - + au_writel(DMA_GO, chan->io + DMA_MODE_CLEAR); // poll the halt bit for (i = 0; i < DMA_HALT_POLL; i++) - if (au_readl(chan->io + DMA_MODE_SET) & DMA_HALT) + if (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT) break; - if (i == DMA_HALT_POLL) { - printk(KERN_INFO "disable_dma: HALT poll expired!\n"); - } else { - // now we can disable the buffers - outl_sync(~DMA_GO, chan->io + DMA_MODE_CLEAR); - } + if (i == DMA_HALT_POLL) + printk(KERN_INFO "halt_dma: HALT poll expired!\n"); +} + + +static __inline__ void disable_dma(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + if (!chan) + return; + + halt_dma(dmanr); + + // now we can disable the buffers + au_writel(~DMA_GO, chan->io + DMA_MODE_CLEAR); +} + +static __inline__ int dma_halted(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + if (!chan) + return 1; + return (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT) ? 1 : 0; } +/* initialize a DMA channel */ +static __inline__ void init_dma(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + u32 mode; + if (!chan) + return; + + disable_dma(dmanr); + + // set device FIFO address + au_writel(virt_to_phys((void *) chan->fifo_addr), + chan->io + DMA_PERIPHERAL_ADDR); + + mode = chan->mode | (chan->dev_id << DMA_DID_BIT); + if (chan->irq) + mode |= DMA_IE; + + au_writel(~mode, chan->io + DMA_MODE_CLEAR); + au_writel(mode, chan->io + DMA_MODE_SET); +} /* * set mode for a specific DMA channel @@ -233,7 +271,7 @@ struct dma_chan *chan = get_dma_chan(dmanr); if (!chan) return -1; - return (au_readl(chan->io + DMA_MODE_SET) & DMA_AB) ? 1 : 0; + return (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? 1 : 0; } @@ -252,7 +290,7 @@ if (chan->dev_id != DMA_ID_GP04 && chan->dev_id != DMA_ID_GP05) return; - outl_sync(virt_to_phys((void *) a), + au_writel(virt_to_phys((void *) a), chan->io + DMA_PERIPHERAL_ADDR); } @@ -264,14 +302,14 @@ struct dma_chan *chan = get_dma_chan(dmanr); if (!chan) return; - outl_sync(DMA_D0, chan->io + DMA_MODE_CLEAR); + au_writel(DMA_D0, chan->io + DMA_MODE_CLEAR); } static __inline__ void clear_dma_done1(unsigned int dmanr) { struct dma_chan *chan = get_dma_chan(dmanr); if (!chan) return; - outl_sync(DMA_D1, chan->io + DMA_MODE_CLEAR); + au_writel(DMA_D1, chan->io + DMA_MODE_CLEAR); } /* @@ -289,7 +327,7 @@ struct dma_chan *chan = get_dma_chan(dmanr); if (!chan) return; - outl_sync(a, chan->io + DMA_BUFFER0_START); + au_writel(a, chan->io + DMA_BUFFER0_START); } /* @@ -300,7 +338,7 @@ struct dma_chan *chan = get_dma_chan(dmanr); if (!chan) return; - outl_sync(a, chan->io + DMA_BUFFER1_START); + au_writel(a, chan->io + DMA_BUFFER1_START); } @@ -314,7 +352,7 @@ if (!chan) return; count &= DMA_COUNT_MASK; - outl_sync(count, chan->io + DMA_BUFFER0_COUNT); + au_writel(count, chan->io + DMA_BUFFER0_COUNT); } /* @@ -327,7 +365,7 @@ if (!chan) return; count &= DMA_COUNT_MASK; - outl_sync(count, chan->io + DMA_BUFFER1_COUNT); + au_writel(count, chan->io + DMA_BUFFER1_COUNT); } /* @@ -340,8 +378,8 @@ if (!chan) return; count &= DMA_COUNT_MASK; - outl_sync(count, chan->io + DMA_BUFFER0_COUNT); - outl_sync(count, chan->io + DMA_BUFFER1_COUNT); + au_writel(count, chan->io + DMA_BUFFER0_COUNT); + au_writel(count, chan->io + DMA_BUFFER1_COUNT); } /* @@ -354,7 +392,7 @@ if (!chan) return 0; - return au_readl(chan->io + DMA_MODE_SET) & (DMA_D0 | DMA_D1); + return au_readl(chan->io + DMA_MODE_READ) & (DMA_D0 | DMA_D1); } @@ -380,8 +418,8 @@ if (!chan) return 0; - curBufCntReg = (au_readl(chan->io + DMA_MODE_SET) & DMA_AB) ? - DMA_BUFFER1_COUNT : DMA_BUFFER0_COUNT; + curBufCntReg = (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? + DMA_BUFFER1_COUNT : DMA_BUFFER0_COUNT; count = au_readl(chan->io + curBufCntReg) & DMA_COUNT_MASK; |