/drivers/usb/gadget/pch_udc.c
C | 3087 lines | 2039 code | 265 blank | 783 comment | 320 complexity | e1df545378b6ab3992ceae4f705b6272 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
- *
- * 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; version 2 of the License.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
- */
- #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- #include <linux/delay.h>
- #include <linux/errno.h>
- #include <linux/list.h>
- #include <linux/interrupt.h>
- #include <linux/usb/ch9.h>
- #include <linux/usb/gadget.h>
- /* Address offset of Registers */
- #define UDC_EP_REG_SHIFT 0x20 /* Offset to next EP */
- #define UDC_EPCTL_ADDR 0x00 /* Endpoint control */
- #define UDC_EPSTS_ADDR 0x04 /* Endpoint status */
- #define UDC_BUFIN_FRAMENUM_ADDR 0x08 /* buffer size in / frame number out */
- #define UDC_BUFOUT_MAXPKT_ADDR 0x0C /* buffer size out / maxpkt in */
- #define UDC_SUBPTR_ADDR 0x10 /* setup buffer pointer */
- #define UDC_DESPTR_ADDR 0x14 /* Data descriptor pointer */
- #define UDC_CONFIRM_ADDR 0x18 /* Write/Read confirmation */
- #define UDC_DEVCFG_ADDR 0x400 /* Device configuration */
- #define UDC_DEVCTL_ADDR 0x404 /* Device control */
- #define UDC_DEVSTS_ADDR 0x408 /* Device status */
- #define UDC_DEVIRQSTS_ADDR 0x40C /* Device irq status */
- #define UDC_DEVIRQMSK_ADDR 0x410 /* Device irq mask */
- #define UDC_EPIRQSTS_ADDR 0x414 /* Endpoint irq status */
- #define UDC_EPIRQMSK_ADDR 0x418 /* Endpoint irq mask */
- #define UDC_DEVLPM_ADDR 0x41C /* LPM control / status */
- #define UDC_CSR_BUSY_ADDR 0x4f0 /* UDC_CSR_BUSY Status register */
- #define UDC_SRST_ADDR 0x4fc /* SOFT RESET register */
- #define UDC_CSR_ADDR 0x500 /* USB_DEVICE endpoint register */
- /* Endpoint control register */
- /* Bit position */
- #define UDC_EPCTL_MRXFLUSH (1 << 12)
- #define UDC_EPCTL_RRDY (1 << 9)
- #define UDC_EPCTL_CNAK (1 << 8)
- #define UDC_EPCTL_SNAK (1 << 7)
- #define UDC_EPCTL_NAK (1 << 6)
- #define UDC_EPCTL_P (1 << 3)
- #define UDC_EPCTL_F (1 << 1)
- #define UDC_EPCTL_S (1 << 0)
- #define UDC_EPCTL_ET_SHIFT 4
- /* Mask patern */
- #define UDC_EPCTL_ET_MASK 0x00000030
- /* Value for ET field */
- #define UDC_EPCTL_ET_CONTROL 0
- #define UDC_EPCTL_ET_ISO 1
- #define UDC_EPCTL_ET_BULK 2
- #define UDC_EPCTL_ET_INTERRUPT 3
- /* Endpoint status register */
- /* Bit position */
- #define UDC_EPSTS_XFERDONE (1 << 27)
- #define UDC_EPSTS_RSS (1 << 26)
- #define UDC_EPSTS_RCS (1 << 25)
- #define UDC_EPSTS_TXEMPTY (1 << 24)
- #define UDC_EPSTS_TDC (1 << 10)
- #define UDC_EPSTS_HE (1 << 9)
- #define UDC_EPSTS_MRXFIFO_EMP (1 << 8)
- #define UDC_EPSTS_BNA (1 << 7)
- #define UDC_EPSTS_IN (1 << 6)
- #define UDC_EPSTS_OUT_SHIFT 4
- /* Mask patern */
- #define UDC_EPSTS_OUT_MASK 0x00000030
- #define UDC_EPSTS_ALL_CLR_MASK 0x1F0006F0
- /* Value for OUT field */
- #define UDC_EPSTS_OUT_SETUP 2
- #define UDC_EPSTS_OUT_DATA 1
- /* Device configuration register */
- /* Bit position */
- #define UDC_DEVCFG_CSR_PRG (1 << 17)
- #define UDC_DEVCFG_SP (1 << 3)
- /* SPD Valee */
- #define UDC_DEVCFG_SPD_HS 0x0
- #define UDC_DEVCFG_SPD_FS 0x1
- #define UDC_DEVCFG_SPD_LS 0x2
- /* Device control register */
- /* Bit position */
- #define UDC_DEVCTL_THLEN_SHIFT 24
- #define UDC_DEVCTL_BRLEN_SHIFT 16
- #define UDC_DEVCTL_CSR_DONE (1 << 13)
- #define UDC_DEVCTL_SD (1 << 10)
- #define UDC_DEVCTL_MODE (1 << 9)
- #define UDC_DEVCTL_BREN (1 << 8)
- #define UDC_DEVCTL_THE (1 << 7)
- #define UDC_DEVCTL_DU (1 << 4)
- #define UDC_DEVCTL_TDE (1 << 3)
- #define UDC_DEVCTL_RDE (1 << 2)
- #define UDC_DEVCTL_RES (1 << 0)
- /* Device status register */
- /* Bit position */
- #define UDC_DEVSTS_TS_SHIFT 18
- #define UDC_DEVSTS_ENUM_SPEED_SHIFT 13
- #define UDC_DEVSTS_ALT_SHIFT 8
- #define UDC_DEVSTS_INTF_SHIFT 4
- #define UDC_DEVSTS_CFG_SHIFT 0
- /* Mask patern */
- #define UDC_DEVSTS_TS_MASK 0xfffc0000
- #define UDC_DEVSTS_ENUM_SPEED_MASK 0x00006000
- #define UDC_DEVSTS_ALT_MASK 0x00000f00
- #define UDC_DEVSTS_INTF_MASK 0x000000f0
- #define UDC_DEVSTS_CFG_MASK 0x0000000f
- /* value for maximum speed for SPEED field */
- #define UDC_DEVSTS_ENUM_SPEED_FULL 1
- #define UDC_DEVSTS_ENUM_SPEED_HIGH 0
- #define UDC_DEVSTS_ENUM_SPEED_LOW 2
- #define UDC_DEVSTS_ENUM_SPEED_FULLX 3
- /* Device irq register */
- /* Bit position */
- #define UDC_DEVINT_RWKP (1 << 7)
- #define UDC_DEVINT_ENUM (1 << 6)
- #define UDC_DEVINT_SOF (1 << 5)
- #define UDC_DEVINT_US (1 << 4)
- #define UDC_DEVINT_UR (1 << 3)
- #define UDC_DEVINT_ES (1 << 2)
- #define UDC_DEVINT_SI (1 << 1)
- #define UDC_DEVINT_SC (1 << 0)
- /* Mask patern */
- #define UDC_DEVINT_MSK 0x7f
- /* Endpoint irq register */
- /* Bit position */
- #define UDC_EPINT_IN_SHIFT 0
- #define UDC_EPINT_OUT_SHIFT 16
- #define UDC_EPINT_IN_EP0 (1 << 0)
- #define UDC_EPINT_OUT_EP0 (1 << 16)
- /* Mask patern */
- #define UDC_EPINT_MSK_DISABLE_ALL 0xffffffff
- /* UDC_CSR_BUSY Status register */
- /* Bit position */
- #define UDC_CSR_BUSY (1 << 0)
- /* SOFT RESET register */
- /* Bit position */
- #define UDC_PSRST (1 << 1)
- #define UDC_SRST (1 << 0)
- /* USB_DEVICE endpoint register */
- /* Bit position */
- #define UDC_CSR_NE_NUM_SHIFT 0
- #define UDC_CSR_NE_DIR_SHIFT 4
- #define UDC_CSR_NE_TYPE_SHIFT 5
- #define UDC_CSR_NE_CFG_SHIFT 7
- #define UDC_CSR_NE_INTF_SHIFT 11
- #define UDC_CSR_NE_ALT_SHIFT 15
- #define UDC_CSR_NE_MAX_PKT_SHIFT 19
- /* Mask patern */
- #define UDC_CSR_NE_NUM_MASK 0x0000000f
- #define UDC_CSR_NE_DIR_MASK 0x00000010
- #define UDC_CSR_NE_TYPE_MASK 0x00000060
- #define UDC_CSR_NE_CFG_MASK 0x00000780
- #define UDC_CSR_NE_INTF_MASK 0x00007800
- #define UDC_CSR_NE_ALT_MASK 0x00078000
- #define UDC_CSR_NE_MAX_PKT_MASK 0x3ff80000
- #define PCH_UDC_CSR(ep) (UDC_CSR_ADDR + ep*4)
- #define PCH_UDC_EPINT(in, num)\
- (1 << (num + (in ? UDC_EPINT_IN_SHIFT : UDC_EPINT_OUT_SHIFT)))
- /* Index of endpoint */
- #define UDC_EP0IN_IDX 0
- #define UDC_EP0OUT_IDX 1
- #define UDC_EPIN_IDX(ep) (ep * 2)
- #define UDC_EPOUT_IDX(ep) (ep * 2 + 1)
- #define PCH_UDC_EP0 0
- #define PCH_UDC_EP1 1
- #define PCH_UDC_EP2 2
- #define PCH_UDC_EP3 3
- /* Number of endpoint */
- #define PCH_UDC_EP_NUM 32 /* Total number of EPs (16 IN,16 OUT) */
- #define PCH_UDC_USED_EP_NUM 4 /* EP number of EP's really used */
- /* Length Value */
- #define PCH_UDC_BRLEN 0x0F /* Burst length */
- #define PCH_UDC_THLEN 0x1F /* Threshold length */
- /* Value of EP Buffer Size */
- #define UDC_EP0IN_BUFF_SIZE 16
- #define UDC_EPIN_BUFF_SIZE 256
- #define UDC_EP0OUT_BUFF_SIZE 16
- #define UDC_EPOUT_BUFF_SIZE 256
- /* Value of EP maximum packet size */
- #define UDC_EP0IN_MAX_PKT_SIZE 64
- #define UDC_EP0OUT_MAX_PKT_SIZE 64
- #define UDC_BULK_MAX_PKT_SIZE 512
- /* DMA */
- #define DMA_DIR_RX 1 /* DMA for data receive */
- #define DMA_DIR_TX 2 /* DMA for data transmit */
- #define DMA_ADDR_INVALID (~(dma_addr_t)0)
- #define UDC_DMA_MAXPACKET 65536 /* maximum packet size for DMA */
- /**
- * struct pch_udc_data_dma_desc - Structure to hold DMA descriptor information
- * for data
- * @status: Status quadlet
- * @reserved: Reserved
- * @dataptr: Buffer descriptor
- * @next: Next descriptor
- */
- struct pch_udc_data_dma_desc {
- u32 status;
- u32 reserved;
- u32 dataptr;
- u32 next;
- };
- /**
- * struct pch_udc_stp_dma_desc - Structure to hold DMA descriptor information
- * for control data
- * @status: Status
- * @reserved: Reserved
- * @data12: First setup word
- * @data34: Second setup word
- */
- struct pch_udc_stp_dma_desc {
- u32 status;
- u32 reserved;
- struct usb_ctrlrequest request;
- } __attribute((packed));
- /* DMA status definitions */
- /* Buffer status */
- #define PCH_UDC_BUFF_STS 0xC0000000