www.pudn.com > Linux2410_usb.rar > m8xxhci.h
/*
* MPC8xx Host Controller Interface driver for USB.
* Brad Parker, brad@heeltoe.com
*
* designed for the EmbeddedPlanet RPX lite board
* (C) Copyright 2000 Embedded Planet
* http://www.embeddedplanet.com
*
*/
#define M8XXHCI_HCI_VERS 0x0102
#define CPMVEC_USB CPMVEC_SCC1
#ifdef CONFIG_RPXLITE_CW
/* CSR bits moved on rev CW boards */
#undef BCSR0_USBDISABLE
#undef BCSR0_USBHISPEED
#undef BCSR0_USBPWREN
#define BCSR0_USBDISABLE ((uint)0x00008000)
#define BCSR0_USBHISPEED ((uint)0x00004000)
#define BCSR0_USBPWREN ((uint)0x00002000)
#define BCSR0_ENUSBCLK ((uint)0x00001000)
#define BCSR0_ENPA5HDR ((uint)0x00000800)
#endif
#ifdef CONFIG_RPXLITE_DW
/* This bit added for DW boards */
#define BCSR0_BRG1TOPC15 ((uint)0x00000400)
#endif
#define BD_USB_TC ((ushort)0x0400) /* transmit crc after last */
#define BD_USB_CNF ((ushort)0x0200) /* wait for handshake */
#define BD_USB_LSP ((ushort)0x0100) /* low speed */
#define BD_USB_DATA0 ((ushort)0x0080) /* send data0 pid */
#define BD_USB_DATA1 ((ushort)0x00c0) /* send data1 pid */
#define BD_USB_RX_PID ((ushort)0x00c0) /* rx pid type bits */
#define BD_USB_RX_DATA0 ((ushort)0x0000) /* rx data0 pid */
#define BD_USB_RX_DATA1 ((ushort)0x0040) /* rx data1 pid */
#define BD_USB_RX_SETUP ((ushort)0x0080) /* rx setup pid */
/* tx errors */
#define BD_USB_NAK ((ushort)0x0010) /* NAK received */
#define BD_USB_STAL ((ushort)0x0008) /* STALL received */
#define BD_USB_TO ((ushort)0x0004) /* timeout */
#define BD_USB_UN ((ushort)0x0002) /* usb underrun */
/* rx errors */
#define BD_USB_NONOCT ((ushort)0x0010) /* non-octet aligned pkt */
#define BD_USB_AB ((ushort)0x0008) /* frame aborted */
#define BD_USB_CRC ((ushort)0x0004) /* crc error */
/* FCR bits */
#define FCR_LE 0x08 /* little endian */
#define FCR_BE 0x18 /* big endian */
/* USEPx bits */
#define USEP_TM_CONTROL 0x0000
#define USEP_TM_INTERRUPT 0x0100
#define USEP_TM_BULK 0x0200
#define USEP_TM_ISOCHRONOUS 0x0300
#define USEP_MF_ENABLED 0x0020
#define USEP_RTE_ENABLED 0x0010
#define USEP_THS_NORMAL 0x0000
#define USEP_THS_IGNORE 0x0004
#define USEP_RHS_NORMAL 0x0000
#define USEP_RHS_IGNORE 0x0001
/* USMOD bits */
#define USMOD_LSS 0x80
#define USMOD_RESUME 0x40
#define USMOD_TEST 0x04
#define USMOD_HOST 0x02
#define USMOD_EN 0x01
/* USBER bits */
#define BER_RESET 0x0200
#define BER_IDLE 0x0100
#define BER_TXE3 0x0080
#define BER_TXE2 0x0040
#define BER_TXE1 0x0020
#define BER_TXE0 0x0010
#define BER_SOF 0x0008
#define BER_BSY 0x0004
#define BER_TXB 0x0002
#define BER_RXB 0x0001
/* USB tokens */
#define SOF 0xa5
#define OUT 0xe1
#define IN 0x69
#define SETUP 0x2d
#define DATA0 0xc3
#define DATA1 0x4b
#define ACK 0xd2
/* Rx & Tx ring sizes */
/* note: usb dictates that we need to be able to rx 64 byte frames;
* the CPM wants to put 2 bytes of CRC at the end and requires that
* the rx buffers be on a 4 byte boundary. So, we add 4 bytes of
* padding to the 64 byte min.
*/
#if 0 /* small, for debug */
#define CPM_USB_RX_PAGES 1
#define CPM_USB_RX_FRSIZE (64+4)
#define CPM_USB_RX_FRPPG (PAGE_SIZE / CPM_USB_RX_FRSIZE)
#define RX_RING_SIZE (CPM_USB_RX_FRPPG * CPM_USB_RX_PAGES)
#define TX_RING_SIZE 10
#endif
#if 0 /* med, for debug */
#define CPM_USB_RX_PAGES 1
#define CPM_USB_RX_FRSIZE (64+4)
#define CPM_USB_RX_FRPPG (PAGE_SIZE / CPM_USB_RX_FRSIZE)
#define RX_RING_SIZE (CPM_USB_RX_FRPPG * CPM_USB_RX_PAGES)
#define TX_RING_SIZE 64
#endif
#if 1
#define CPM_USB_RX_PAGES 8
#define CPM_USB_RX_FRSIZE (1024)
#define CPM_USB_RX_FRPPG (PAGE_SIZE / CPM_USB_RX_FRSIZE)
#define RX_RING_SIZE (CPM_USB_RX_FRPPG * CPM_USB_RX_PAGES)
#define TX_RING_SIZE 40
#endif
/* this is the max size we tell the CPM */
#define MAX_RBE (CPM_USB_RX_FRSIZE) /* max receive buffer size (bytes) */
/* MPC850 USB parameter RAM */
typedef struct usbpr {
ushort usb_epbptr[4];
uint usb_rstate;
uint usb_rptr;
ushort usb_frame_n;
ushort usb_rbcnt;
uint usb_rtemp;
} usbpr_t;
/* USB endpoint parameter block */
typedef struct epb {
ushort epb_rbase;
ushort epb_tbase;
u_char epb_rfcr;
u_char epb_tfcr;
ushort epb_mrblr;
ushort epb_rbptr;
ushort epb_tbptr;
uint epb_tstate;
uint epb_tptr;
ushort epb_tcrc;
ushort epb_tbcnt;
} epb_t;
/* MPC850 USB registers - mapped onto SCC1 address space */
typedef struct usbregs {
u_char usb_usmod;
u_char usb_usadr;
u_char usb_uscom;
char res0;
ushort usb_usep[4];
char res1[4];
ushort usb_usber;
ushort res2;
ushort usb_usbmr;
u_char res3;
u_char usb_usbs;
u_char res4[8];
} usbregs_t;
/* bits in parallel i/o port registers that have to be cleared to
* configure the pins for SCC1 USB use.
*/
#define PA_DR4 ((ushort)0x0800)
#define PA_DR5 ((ushort)0x0400)
#define PA_DR6 ((ushort)0x0200)
#define PA_DR7 ((ushort)0x0100)
#define PA_USB_RXD ((ushort)0x0001)
#define PA_USB_OE ((ushort)0x0002)
#define PB_DR28 ((ushort)0x0008)
#define PC_DR5 ((ushort)0x0400)
#define PC_DR12 ((ushort)0x0008)
#define PC_DR13 ((ushort)0x0004)
#define PC_USB_RXP ((ushort)0x0010)
#define PC_USB_RXN ((ushort)0x0020)
#define PC_USB_TXP ((ushort)0x0100)
#define PC_USB_TXN ((ushort)0x0200)
#define PC_USB_SOF ((ushort)0x0001) /* bit 15, dreq0* */
struct m8xxhci_device {
struct usb_device *usb;
char busy[2][16];
char busy_count[2][16];
};
#define MAX_EP_BUSYS 100/*10*/
#define m8xxhci_to_usb(m8xxhci) ((m8xxhci)->usb)
#define usb_to_m8xxhci(usb) ((struct m8xxhci_device *)(usb)->hcpriv)
#include
/* queue entry */
struct m8xxhci_qe {
int inuse; /* Inuse? */
int retries;
#define MAX_QE_RETRIES 3
int busys; /* # times busy */
#define MAX_QE_STALLED 5
#define MAX_QE_BUSYS 10
int frames; /* # frames as active */
int qtype;
int qstate;
#define QS_SETUP 1
#define QS_SETUP2 2
#define QS_SETUP3 3
#define QS_INTR 4
#define QS_BULK 5
#define QS_ISO 6
unsigned int pipe; /* pipe info given */
u_char devnum;
u_char endpoint;
void *cmd;
void *data;
int whichdata; /* data0/1 marker */
int data_len; /* size of whole xfer */
int recv_len; /* IN/size recv so far */
int send_len; /* OUT/size sent so far */
int status;
int maxpacketsize; /* max in/out size */
int reschedule; /* flag - needs reschedule */
int shortread; /* flag - short read */
int iso_ptr; /* index into urb->iso_frame_desc */
int frame_no;
u_char *iso_data; /* ptr to data for current iso frame */
u_char ph[3]; /* temp packet header */
wait_queue_head_t wakeup;
struct usb_device *dev;
struct urb *urb;
struct m8xxhci_qe *next; /* for delay list */
struct m8xxhci_frame *on_frame_list;
struct list_head frame_list;
struct list_head qe_list;
int delta; /* delay (in ms) till this is due */
};
#define Q_ISO 0
#define Q_INTR 1
#define Q_CTRL 2
#define Q_BULK 3
#define MAX_Q_TYPES 4
struct m8xxhci_frame {
int total_bytes;
int bytes[MAX_Q_TYPES];
struct list_head heads[MAX_Q_TYPES];
};
#define BYTES_PER_USB_FRAME 1280 /*1500*/
/* cumulative percentages, for enforcing max % of frame by class */
static int frame_cumul_class_quota[MAX_Q_TYPES] = {
(BYTES_PER_USB_FRAME * 90) / 100, /* iso 90% */
(BYTES_PER_USB_FRAME * 90) / 100, /* interrupt 90% */
BYTES_PER_USB_FRAME, /* control remaining 10% */
BYTES_PER_USB_FRAME /* bulk remaining% */
};
/* Virtual Root HUB */
struct virt_root_hub {
int devnum; /* Address of Root Hub endpoint */
void * urb;
void * int_addr;
int send;
int interval;
u32 feature;
u32 hub_status;
u32 port_status;
struct timer_list rh_int_timer;
};
/* hub_status bits */
#define RH_HS_LPS 0x00000001 /* local power status */
#define RH_HS_LPSC 0x00010000 /* local power status change */
/* port_status bits */
#define RH_PS_CCS 0x00000001 /* current connect status */
#define RH_PS_PES 0x00000002 /* port enable status*/
#define RH_PS_PSS 0x00000004 /* port suspend status */
#define RH_PS_PRS 0x00000010 /* port reset status */
#define RH_PS_PPS 0x00000100 /* port power status */
#define RH_PS_LSDA 0x00000200 /* low speed device attached */
#define RH_PS_CSC 0x00010000 /* connect status change */
#define RH_PS_PESC 0x00020000 /* port enable status change */
#define RH_PS_PSSC 0x00040000 /* port suspend status change */
#define RH_PS_PRSC 0x00100000 /* port reset status change */
/*
* this doesn't really need to be a structure, since we can only have
* one mcp usb controller, but it makes things more tidy...
*/
struct m8xxhci_private {
volatile usbregs_t *usbregs;
struct usb_bus *bus;
struct virt_root_hub rh;/* virtual root hub */
int disabled;
epb_t *epbptr[4]; /* epb ptr */
cbd_t *rbase; /* rx ring bd ptr */
cbd_t *tbase; /* tx ring bd ptr */
int rxnext; /* index of next rx to be filled */
int txlast; /* index of last tx bd fill */
int txnext; /* index of next available tx bd */
int txfree; /* count of free tx bds */
int frame_no; /* frame # send in next SOF */
u_char sof_pkt[3]; /* temp buffer for sof frames */
int need_sof; /* 1ms interrupt could not send flag */
int ms_count;
int need_query;
#define M8XXHCI_MAXQE 32
struct m8xxhci_qe queues[MAX_Q_TYPES][M8XXHCI_MAXQE];
struct list_head qe_list[MAX_Q_TYPES];
struct m8xxhci_qe *active_qe;
int xmit_state[MAX_Q_TYPES];
#define XS_IDLE 0
#define XS_SETUP 1
#define XS_IN 2
struct m8xxhci_qe *tx_bd_qe[TX_RING_SIZE];
int port_state;
#define PS_INIT 0
#define PS_DISCONNECTED 1
#define PS_CONNECTED 2
#define PS_READY 3
#define PS_MISSING 4
int hw_features;
#define HF_LOWSPEED 1
struct list_head urb_list; /* active urb list.. */
struct m8xxhci_frame frames[2];
struct m8xxhci_frame *current_frame;
struct m8xxhci_frame *next_frame;
/* stats */
struct {
ulong isrs;
ulong cpm_interrupts;
ulong tmr_interrupts;
ulong rxb;
ulong txb;
ulong bsy;
ulong sof;
ulong txe[4];
ulong idle;
ulong reset;
ulong tx_err;
ulong tx_nak;
ulong tx_stal;
ulong tx_to;
ulong tx_un;
ulong rx_err;
ulong rx_crc;
ulong rx_abort;
ulong rx_nonoct;
ulong rx_mismatch;
ulong retransmit;
ulong tx_restart;
ulong rh_send_irqs;
ulong completes[MAX_Q_TYPES];
} stats;
};