📄 usbs_sa11x0.c
字号:
//==========================================================================//// usbs_sa11x0.c//// Device driver for the SA11x0 USB port.////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.//// eCos 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 or (at your option) any later version.//// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): bartv// Contributors: bartv// Date: 2000-10-04//// This code implements support for the on-chip USB port on the SA11x0// family of processors. The code has been developed on the SA1110 and// may or may not work on other members of the SA11x0 family. There// have problems with the USB support on certain revisions of the silicon,// so the errata sheet appropriate to the specific processor being used// should be consulted. There also appear to be problems which do not// appear on any errata, which this code attempts to work around.////####DESCRIPTIONEND####//==========================================================================#include <cyg/infra/cyg_type.h>#include <cyg/infra/cyg_ass.h>#include <cyg/infra/cyg_trac.h>#include <cyg/infra/diag.h>#include <pkgconf/hal_arm.h>#include <pkgconf/devs_usb_sa11x0.h>#include <cyg/hal/drv_api.h>#include <cyg/hal/hal_arch.h>#include <cyg/hal/hal_io.h>#include <cyg/hal/hal_cache.h>#include <cyg/hal/hal_sa11x0.h>#include <cyg/error/codes.h>#include <cyg/io/usb/usb.h>#include <cyg/io/usb/usbs.h>// Debugging support. By default this driver operates mostly at// DSR level, with the ISR doing a minimal amount of processing.// However is also possible to run most of the code at thread-level,// This is subject to some restrictions because the USB standard// imposes timing constraints, e.g. some control operations such// as SET-ADDRESS have to complete within 50ms. However it is// very useful for debugging, specifically it allows you to put// printf()'s in various places.//// Right now these configuration options are not exported to the// user because running at DSR level is likely to be good enough// for everybody not actively debugging this code. The options// could be exported if necessary.//#define CYGPKG_DEVS_USB_SA11X0_THREAD#undef CYGPKG_DEVS_USB_SA11X0_THREAD#ifdef CYGPKG_DEVS_USB_SA11X0_THREAD // Default stack size should be CYGNUM_HAL_STACK_SIZE_TYPICAL# define CYGNUM_DEVS_USB_SA11X0_THREAD_STACK_SIZE 4096# define CYGNUM_DEVS_USB_SA11X0_THREAD_PRIORITY 7# include <cyg/kernel/kapi.h>#endif#if 0# define DBG(a) diag_printf a#else# define DBG(a)#endif#undef FAILURES#ifdef FAILURESstatic volatile int ep1_failure = 7;#endif#undef STATS#ifdef STATSint ep1_receives = 0;int ep1_errors = 0;int ep2_transmits = 0;int ep2_errors = 0;# define INCR_STAT(a) (a) += 1# define SET_STAT(a, b) (a) = (b)#else# define INCR_STAT(a)# define SET_STAT(a, b)#endif// ----------------------------------------------------------------------------// Serial port 0 on the SA11x0 provides a USB slave connection (aka a// USB device controller or UDC). The functionality is somewhat// limited, there are just three endpoints.//// Endpoint 0 can only be used for control messages. It has an 8 byte// fifo which cannot be connected to a DMA engine. Hence incoming// control packets have to be limited to 8 bytes by the enumeration// data. The endpoint has to be managed at a low-level, i.e. the// incoming request has to be extracted from the fifo, processed, and// any response put back into the fifo within the permitted USB// response times.//// Endpoint 1 can only be used for host->slave bulk OUT transfers. It// has a 20 byte receive fifo, and it can be hooked up to any of the// six DMA engines. Since bulk transfers will typically involve 64// byte packets, most applications will require the use of DMA.//// Endpoint 2 can only be used for slave-host bulk IN transfers. There// is a 16 byte transmit fifo so small messages can be transferred in// software. The fifo can also be hooked up to DMA, which is a more// likely scenario.//// Start with definitions of the hardware. The use of a structure and// a const base pointer should allow the compiler to do base/offset// addressing and keep the hardware base address in a register. This// is better than defining each hardware register via a separate// address. Although the registers are only a byte wide, the peripheral// bus only supports word accesses.//// The USBS_CONTROL etc. macros allow for an alternative way of// accessing the hardware if a better approach is presented, without// having to rewrite all the code. Macros that correspond to registers// are actually addresses, making it easier in the code to distinguish// them from bit values: the & and * operators will just cancel out.typedef struct usbs_sa11x0_hardware { volatile int control; volatile int address; volatile int out_size; volatile int in_size; volatile int ep0_control; volatile int ep1_control; volatile int ep2_control; volatile int ep0_data; volatile int ep0_write_count; int dummy1; volatile int fifo; int dummy2; volatile int status;} usbs_sa11x0_hardware;static usbs_sa11x0_hardware* const usbs_sa11x0_base = (usbs_sa11x0_hardware* const) 0x80000000;#define USBS_CONTROL (&(usbs_sa11x0_base->control))#define USBS_ADDRESS (&(usbs_sa11x0_base->address))#define USBS_OUT_SIZE (&(usbs_sa11x0_base->out_size))#define USBS_IN_SIZE (&(usbs_sa11x0_base->in_size))#define EP0_CONTROL (&(usbs_sa11x0_base->ep0_control))#define EP1_CONTROL (&(usbs_sa11x0_base->ep1_control))#define EP2_CONTROL (&(usbs_sa11x0_base->ep2_control))#define EP0_DATA (&(usbs_sa11x0_base->ep0_data))#define EP0_WRITE_COUNT (&(usbs_sa11x0_base->ep0_write_count))#define EP1_DATA (&(usbs_sa11x0_base->fifo))#define EP2_DATA (&(usbs_sa11x0_base->fifo))#define USBS_STATUS (&(usbs_sa11x0_base->status))#define CONTROL_DISABLE (1 << 0)#define CONTROL_ACTIVE (1 << 1)// The meaning of bit 2 changed, see errata#define CONTROL_RESUME_INTR (1 << 2)#define CONTROL_EP0_INTR (1 << 3)#define CONTROL_EP1_INTR (1 << 4)#define CONTROL_EP2_INTR (1 << 5)// The meaning of bit 6 also changed, see errata#define CONTROL_SUSPEND_INTR (1 << 6)#define CONTROL_RESET_INTR (1 << 7)// Getting the control register settings right is a little bit tricky.// Bit 0 is the disable bit so touching that is dangerous, and the// other bits have inverted meanings i.e. 0 enables interrupts. The// following macro encapsulates this.#define CONTROL_ALL_INTR 0x00FC#define CONTROL_INTR_ENABLE(bits) ((~(bits)) & CONTROL_ALL_INTR)#define CONTROL_INTR_CLEAR(bits) ((bits) & CONTROL_ALL_INTR)// All the endpoint interrupt numbers can be handled en masse,// but some of the endpoints may be disabled.#if defined(CYGPKG_DEVS_USB_SA11X0_EP1) && defined(CYGPKG_DEVS_USB_SA11X0_EP2)# define CONTROL_EP_INTR_BITS (CONTROL_EP0_INTR | CONTROL_EP1_INTR | CONTROL_EP2_INTR)#elif defined(CYGPKG_DEVS_USB_SA11X0_EP1)# define CONTROL_EP_INTR_BITS (CONTROL_EP0_INTR | CONTROL_EP1_INTR)#elif defined(CYGPKG_DEVS_USB_SA11X0_EP2)# define CONTROL_EP_INTR_BITS (CONTROL_EP0_INTR | CONTROL_EP2_INTR)#else# define CONTROL_EP_INTR_BITS (CONTROL_EP0_INTR)#endif#define EP0_OUT_READY (1 << 0)#define EP0_IN_READY (1 << 1)#define EP0_SENT_STALL (1 << 2)#define EP0_FORCE_STALL (1 << 3)#define EP0_DATA_END (1 << 4)#define EP0_SETUP_END (1 << 5)#define EP0_SERVICED_OPR (1 << 6)#define EP0_SERVICED_SETUP_END (1 << 7)#define EP1_FIFO_SERVICE (1 << 0)#define EP1_PACKET_COMPLETE (1 << 1)#define EP1_PACKET_ERROR (1 << 2)#define EP1_SENT_STALL (1 << 3)#define EP1_FORCE_STALL (1 << 4)#define EP1_FIFO_NOT_EMPTY (1 << 5)#define EP2_FIFO_SERVICE (1 << 0)#define EP2_PACKET_COMPLETE (1 << 1)#define EP2_PACKET_ERROR (1 << 2)#define EP2_PACKET_UNDERRUN (1 << 3)#define EP2_SENT_STALL (1 << 4)#define EP2_FORCE_STALL (1 << 5)#define STATUS_EP0_INTR (1 << 0)#define STATUS_EP1_INTR (1 << 1)#define STATUS_EP2_INTR (1 << 2)#define STATUS_SUSPEND_INTR (1 << 3)#define STATUS_RESUME_INTR (1 << 4)#define STATUS_RESET_INTR (1 << 5)#define EP0_FIFO_SIZE 8#define EP0_MTU 8#define EP1_FIFO_SIZE 20#ifdef CYGNUM_DEVS_USB_SA11X0_EP1_DMA_CHANNEL# define EP1_MTU 64#else# define EP1_MTU 16#endif#define EP2_FIFO_SIZE 16#ifdef CYGNUM_DEVS_USB_SA11X0_EP2_DMA_CHANNEL# define EP2_MTU 64#else# define EP2_MTU 16#endif#if defined(CYGNUM_DEVS_USB_SA11X0_EP1_DMA_CHANNEL) || defined(CYGNUM_DEVS_USB_SA11X0_EP2_DMA_CHANNEL)typedef struct usbs_sa11x0_dma { volatile int address; volatile int control_set; volatile int control_clear; volatile int status; volatile int buf_a_address; // Absolute, not remapped volatile int buf_a_size; volatile int buf_b_address; // Absolute, not remapped volatile int buf_b_size;} usbs_sa11x0_dma;#define DMA_CONTROL_RUN (1 << 0)#define DMA_CONTROL_INTR_ENABLE (1 << 1)#define DMA_STATUS_ERROR (1 << 2)#define DMA_STATUS_DONE_A (1 << 3)#define DMA_CONTROL_START_A (1 << 4)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -