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