diff options
| author | Meizu OpenSource <patchwork@meizu.com> | 2016-08-15 10:19:42 +0800 |
|---|---|---|
| committer | Meizu OpenSource <patchwork@meizu.com> | 2016-08-15 10:19:42 +0800 |
| commit | d2e1446d81725c351dc73a03b397ce043fb18452 (patch) | |
| tree | 4dbc616b7f92aea39cd697a9084205ddb805e344 /include/linux/musb | |
first commit
Diffstat (limited to 'include/linux/musb')
| -rw-r--r-- | include/linux/musb/mtk_musb.h | 88 | ||||
| -rw-r--r-- | include/linux/musb/mtk_qmu.h | 324 | ||||
| -rw-r--r-- | include/linux/musb/musb.h | 132 | ||||
| -rw-r--r-- | include/linux/musb/musb_core.h | 601 | ||||
| -rw-r--r-- | include/linux/musb/musb_debug.h | 100 | ||||
| -rw-r--r-- | include/linux/musb/musb_dma.h | 171 | ||||
| -rw-r--r-- | include/linux/musb/musb_gadget.h | 125 | ||||
| -rw-r--r-- | include/linux/musb/musb_host.h | 111 | ||||
| -rw-r--r-- | include/linux/musb/musb_io.h | 231 | ||||
| -rw-r--r-- | include/linux/musb/musb_qmu.h | 21 | ||||
| -rw-r--r-- | include/linux/musb/musbhsdma.h | 97 |
11 files changed, 2001 insertions, 0 deletions
diff --git a/include/linux/musb/mtk_musb.h b/include/linux/musb/mtk_musb.h new file mode 100644 index 000000000..2473d1130 --- /dev/null +++ b/include/linux/musb/mtk_musb.h @@ -0,0 +1,88 @@ +#ifndef __MUSB_MTK_MUSB_H__ +#define __MUSB_MTK_MUSB_H__ + +#ifdef CONFIG_OF +extern struct musb *mtk_musb; +#define USBPHY_READ8(offset) readb((void __iomem *)(((unsigned long)mtk_musb->xceiv->io_priv)+0x800+offset)) +#define USBPHY_WRITE8(offset, value) writeb(value, (void __iomem *)(((unsigned long)mtk_musb->xceiv->io_priv)+0x800+offset)) +#define USBPHY_SET8(offset, mask) USBPHY_WRITE8(offset, (USBPHY_READ8(offset)) | (mask)) +#define USBPHY_CLR8(offset, mask) USBPHY_WRITE8(offset, (USBPHY_READ8(offset)) & (~mask)) + +#define USBPHY_READ16(offset) readw((void __iomem *)(((unsigned long)mtk_musb->xceiv->io_priv)+0x800+offset)) +#define USBPHY_WRITE16(offset, value) writew(value, (void __iomem *)(((unsigned long)mtk_musb->xceiv->io_priv)+0x800+offset)) +#define USBPHY_SET16(offset, mask) USBPHY_WRITE16(offset, (USBPHY_READ16(offset)) | (mask)) +#define USBPHY_CLR16(offset, mask) USBPHY_WRITE16(offset, (USBPHY_READ16(offset)) & (~mask)) + +#define USBPHY_READ32(offset) readl((void __iomem *)(((unsigned long)mtk_musb->xceiv->io_priv)+0x800+offset)) +#define USBPHY_WRITE32(offset, value) writel(value, (void __iomem *)(((unsigned long)mtk_musb->xceiv->io_priv)+0x800+offset)) +#define USBPHY_SET32(offset, mask) USBPHY_WRITE32(offset, (USBPHY_READ32(offset)) | (mask)) +#define USBPHY_CLR32(offset, mask) USBPHY_WRITE32(offset, (USBPHY_READ32(offset)) & (~mask)) + +#ifdef MTK_UART_USB_SWITCH +#define UART2_BASE 0x11003000 +#endif + +#else + +#include <mach/mt_reg_base.h> + +#define USBPHY_READ8(offset) readb((void __iomem *)(USB_SIF_BASE+0x800+offset)) +#define USBPHY_WRITE8(offset, value) writeb(value, (void __iomem *)(USB_SIF_BASE+0x800+offset)) +#define USBPHY_SET8(offset, mask) USBPHY_WRITE8(offset, (USBPHY_READ8(offset)) | (mask)) +#define USBPHY_CLR8(offset, mask) USBPHY_WRITE8(offset, (USBPHY_READ8(offset)) & (~mask)) + +#define USBPHY_READ16(offset) readw((void __iomem *)(USB_SIF_BASE+0x800+offset)) +#define USBPHY_WRITE16(offset, value) writew(value, (void __iomem *)(USB_SIF_BASE+0x800+offset)) +#define USBPHY_SET16(offset, mask) USBPHY_WRITE16(offset, (USBPHY_READ16(offset)) | (mask)) +#define USBPHY_CLR16(offset, mask) USBPHY_WRITE16(offset, (USBPHY_READ16(offset)) & (~mask)) + +#define USBPHY_READ32(offset) readl((void __iomem *)(USB_SIF_BASE+0x800+offset)) +#define USBPHY_WRITE32(offset, value) writel(value, (void __iomem *)(USB_SIF_BASE+0x800+offset)) +#define USBPHY_SET32(offset, mask) USBPHY_WRITE32(offset, (USBPHY_READ32(offset)) | (mask)) +#define USBPHY_CLR32(offset, mask) USBPHY_WRITE32(offset, (USBPHY_READ32(offset)) & (~mask)) + +#endif +struct musb; + +typedef enum { + USB_SUSPEND = 0, + USB_UNCONFIGURED, + USB_CONFIGURED +} usb_state_enum; + +/* USB phy and clock */ +extern void usb_phy_poweron(void); +extern void usb_phy_recover(void); +extern void usb_phy_savecurrent(void); +extern void usb_phy_context_restore(void); +extern void usb_phy_context_save(void); +extern bool usb_enable_clock(bool enable); + +/* general USB */ +extern bool mt_usb_is_device(void); +extern void mt_usb_connect(void); +extern void mt_usb_disconnect(void); +/* ALPS00775710 */ +/* extern bool usb_iddig_state(void); */ +/* ALPS00775710 */ +extern bool usb_cable_connected(void); +extern void pmic_chrdet_int_en(int is_on); +extern void musb_platform_reset(struct musb *musb); +extern void musb_sync_with_bat(struct musb *musb, int usb_state); + +extern bool is_saving_mode(void); + +/* USB switch charger */ +extern bool is_switch_charger(void); + +/* host and otg */ +extern void mt_usb_otg_init(struct musb *musb); +extern void mt_usb_init_drvvbus(void); +extern void mt_usb_set_vbus(struct musb *musb, int is_on); +extern int mt_usb_get_vbus_status(struct musb *musb); +extern void mt_usb_iddig_int(struct musb *musb); +extern void switch_int_to_device(struct musb *musb); +extern void switch_int_to_host(struct musb *musb); +extern void switch_int_to_host_and_mask(struct musb *musb); +extern void musb_session_restart(struct musb *musb); +#endif diff --git a/include/linux/musb/mtk_qmu.h b/include/linux/musb/mtk_qmu.h new file mode 100644 index 000000000..4eea9cdfe --- /dev/null +++ b/include/linux/musb/mtk_qmu.h @@ -0,0 +1,324 @@ +#ifndef _MTK_QMU_H_ +#define _MTK_QMU_H_ + +#ifdef MUSB_QMU_SUPPORT + +/* for musb_read/write api */ +#include "mtk_musb.h" +#include "musb_debug.h" +#include "musb_io.h" + +#include <linux/dmapool.h> + +/* CUSTOM SETTING */ +#define GPD_LEN_ALIGNED (64) /* > gpd len (16) and cache line size aligned */ +#define GPD_EXT_LEN (48) /* GPD_LEN_ALIGNED - 16(should be sizeof(TGPD) */ +#define GPD_SZ (16) +#define MAX_GPD_NUM 36 +#define RXQ_NUM 8 +#define TXQ_NUM 8 +#define MAX_QMU_EP RXQ_NUM +#define TXQ 0 +#define RXQ 1 + +/* QMU SETTING */ +#define NO_ZLP 0 +#define HW_MODE 1 +#define GPD_MODE 2 +//#define TXZLP GPD_MODE +//#define TXZLP HW_MODE +#define TXZLP NO_ZLP + +//#define CFG_RX_ZLP_EN +//#define CFG_RX_COZ_EN + +#define CFG_CS_CHECK +//#define CFG_EMPTY_CHECK + +/* TGPD */ +typedef struct _TGPD +{ + u8 flag; + u8 chksum; + u16 DataBufferLen; /*Rx Allow Length*/ + + /* address field, 32-bit long */ + u32 pNext; + u32 pBuf; + + u16 bufLen; + u8 ExtLength; + u8 ZTepFlag; +}TGPD, *PGPD; + +typedef struct _GPD_RANGE { + PGPD pNext; + PGPD pStart; + PGPD pEnd; +}GPD_R, *RGPD; + +extern int mtk_qmu_dbg_level; /* refer to musb_core.c */ +static inline int mtk_dbg_level(unsigned level) +{ + return mtk_qmu_dbg_level >= level; +} + +#define LOG_EMERG 0 +#define LOG_ALERT 1 +#define LOG_CRIT 2 +#define LOG_ERR 3 +#define LOG_WARN 4 +#define LOG_NOTICE 5 +#define LOG_INFO 6 +#define LOG_DBG 7 + +#define QMU_DBG_ON + +#ifdef QMU_DBG_ON +#define QMU_ERR(format, args...) do {if(mtk_dbg_level(LOG_ERR)){printk(KERN_WARNING "QMU_ERR,<%s %d>, " format , __func__, __LINE__ , ## args);}}while(0) +#define QMU_WARN(format, args...) do {if(mtk_dbg_level(LOG_WARN)){printk(KERN_WARNING "QMU_WARN,<%s %d>, " format , __func__, __LINE__ , ## args);}}while(0) +#define QMU_INFO(format, args...) do {if(mtk_dbg_level(LOG_INFO)){printk(KERN_WARNING "QMU_INFO,<%s %d>, " format , __func__, __LINE__ , ## args);}}while(0) +#define QMU_DBG(format, args...) do {if(mtk_dbg_level(LOG_DBG)){printk(KERN_WARNING "QMU_DBG,<%s %d>, " format , __func__, __LINE__ , ## args);}}while(0) +#else +#define QMU_ERR(format, args...) do {}while(0) +#define QMU_WARN(format, args...) do {}while(0) +#define QMU_INFO(format, args...) do {}while(0) +#define QMU_DBG(format, args...) do {}while(0) +#endif + + + +/* QMU macros */ +#define USB_HW_QMU_OFF 0x0000 +#define USB_HW_QUCS_OFF 0x0300 +#define USB_HW_QIRQ_OFF 0x0400 +#define USB_HW_QDBG_OFF 0x04F0 + +#define MGC_O_QMU_QCR0 0x0000 +#define MGC_O_QMU_QCR2 0x0008 +#define MGC_O_QMU_QCR3 0x000C + +#define MGC_O_QMU_RQCSR0 0x0010 +#define MGC_O_QMU_RQSAR0 0x0014 +#define MGC_O_QMU_RQCPR0 0x0018 +#define MGC_O_QMU_RQCSR(n) (MGC_O_QMU_RQCSR0+0x0010*((n)-1)) +#define MGC_O_QMU_RQSAR(n) (MGC_O_QMU_RQSAR0+0x0010*((n)-1)) +#define MGC_O_QMU_RQCPR(n) (MGC_O_QMU_RQCPR0+0x0010*((n)-1)) + +#define MGC_O_QMU_RQTR_BASE 0x0090 +#define MGC_O_QMU_RQTR(n) (MGC_O_QMU_RQTR_BASE+0x4*((n)-1)) +#define MGC_O_QMU_RQLDPR0 0x0100 +#define MGC_O_QMU_RQLDPR(n) (MGC_O_QMU_RQLDPR0+0x4*((n)-1)) + +#define MGC_O_QMU_TQCSR0 0x0200 +#define MGC_O_QMU_TQSAR0 0x0204 +#define MGC_O_QMU_TQCPR0 0x0208 +#define MGC_O_QMU_TQCSR(n) (MGC_O_QMU_TQCSR0+0x0010*((n)-1)) +#define MGC_O_QMU_TQSAR(n) (MGC_O_QMU_TQSAR0+0x0010*((n)-1)) +#define MGC_O_QMU_TQCPR(n) (MGC_O_QMU_TQCPR0+0x0010*((n)-1)) + +#define MGC_O_QMU_QAR 0x0300 +#define MGC_O_QUCS_USBGCSR 0x0000 +#define MGC_O_QIRQ_QISAR 0x0000 +#define MGC_O_QIRQ_QIMR 0x0004 +#define MGC_O_QIRQ_QIMCR 0x0008 +#define MGC_O_QIRQ_QIMSR 0x000C +#define MGC_O_QIRQ_IOCDISR 0x0030 +#define MGC_O_QIRQ_TEPEMPR 0x0060 +#define MGC_O_QIRQ_TEPEMPMR 0x0064 +#define MGC_O_QIRQ_TEPEMPMCR 0x0068 +#define MGC_O_QIRQ_TEPEMPMSR 0x006C +#define MGC_O_QIRQ_REPEMPR 0x0070 +#define MGC_O_QIRQ_REPEMPMR 0x0074 +#define MGC_O_QIRQ_REPEMPMCR 0x0078 +#define MGC_O_QIRQ_REPEMPMSR 0x007C + +#define MGC_O_QIRQ_RQEIR 0x0090 +#define MGC_O_QIRQ_RQEIMR 0x0094 +#define MGC_O_QIRQ_RQEIMCR 0x0098 +#define MGC_O_QIRQ_RQEIMSR 0x009C +#define MGC_O_QIRQ_REPEIR 0x00A0 +#define MGC_O_QIRQ_REPEIMR 0x00A4 +#define MGC_O_QIRQ_REPEIMCR 0x00A8 +#define MGC_O_QIRQ_REPEIMSR 0x00AC +#define MGC_O_QIRQ_TQEIR 0x00B0 +#define MGC_O_QIRQ_TQEIMR 0x00B4 +#define MGC_O_QIRQ_TQEIMCR 0x00B8 +#define MGC_O_QIRQ_TQEIMSR 0x00BC +#define MGC_O_QIRQ_TEPEIR 0x00C0 +#define MGC_O_QIRQ_TEPEIMR 0x00C4 +#define MGC_O_QIRQ_TEPEIMCR 0x00C8 +#define MGC_O_QIRQ_TEPEIMSR 0x00CC + +#define MGC_O_QDBG_DFCR 0x0000 +#define MGC_O_QDBG_DFMR 0x0004 + +/* brief Queue Control value Definition */ +#define DQMU_QUE_START 0x00000001 +#define DQMU_QUE_RESUME 0x00000002 +#define DQMU_QUE_STOP 0x00000004 +#define DQMU_QUE_ACTIVE 0x00008000 + +/*brief USB QMU Special Control USBGCSR value Definition*/ +#define USB_QMU_Tx0_EN 0x00000001 +#define USB_QMU_Tx_EN(n) (USB_QMU_Tx0_EN<<((n)-1)) +#define USB_QMU_Rx0_EN 0x00010000 +#define USB_QMU_Rx_EN(n) (USB_QMU_Rx0_EN<<((n)-1)) +#define USB_QMU_HIFEVT_EN 0x00000100 +#define USB_QMU_HIFCMD_EN 0x01000000 +#define DQMU_SW_RESET 0x00010000 +#define DQMU_CS16B_EN 0x80000000 +#define DQMU_TQ0CS_EN 0x00010000 +#define DQMU_TQCS_EN(n) (DQMU_TQ0CS_EN<<((n)-1)) +#define DQMU_RQ0CS_EN 0x00000001 +#define DQMU_RQCS_EN(n) (DQMU_RQ0CS_EN<<((n)-1)) +#define DQMU_TX0_ZLP 0x01000000 +#define DQMU_TX_ZLP(n) (DQMU_TX0_ZLP<<((n)-1)) +#define DQMU_TX0_MULTIPLE 0x00010000 +#define DQMU_TX_MULTIPLE(n) (DQMU_TX0_MULTIPLE<<((n)-1)) +#define DQMU_RX0_MULTIPLE 0x00010000 +#define DQMU_RX_MULTIPLE(n) (DQMU_RX0_MULTIPLE<<((n)-1)) +#define DQMU_RX0_ZLP 0x01000000 +#define DQMU_RX_ZLP(n) (DQMU_RX0_ZLP<<((n)-1)) +#define DQMU_RX0_COZ 0x00000100 +#define DQMU_RX_COZ(n) (DQMU_RX0_COZ<<((n)-1)) + +#define DQMU_M_TXEP_ERR 0x10000000 +#define DQMU_M_TXQ_ERR 0x08000000 +#define DQMU_M_RXEP_ERR 0x04000000 +#define DQMU_M_RXQ_ERR 0x02000000 +#define DQMU_M_RQ_EMPTY 0x00020000 +#define DQMU_M_TQ_EMPTY 0x00010000 +#define DQMU_M_RX0_EMPTY 0x00000001 +#define DQMU_M_RX_EMPTY(n) (DQMU_M_RX0_EMPTY<<((n)-1)) +#define DQMU_M_TX0_EMPTY 0x00000001 +#define DQMU_M_TX_EMPTY(n) (DQMU_M_TX0_EMPTY<<((n)-1)) +#define DQMU_M_RX0_DONE 0x00000100 +#define DQMU_M_RX_DONE(n) (DQMU_M_RX0_DONE<<((n)-1)) +#define DQMU_M_TX0_DONE 0x00000001 +#define DQMU_M_TX_DONE(n) (DQMU_M_TX0_DONE<<((n)-1)) + +#define DQMU_M_RX0_ZLP_ERR 0x01000000 +#define DQMU_M_RX_ZLP_ERR(n) (DQMU_M_RX0_ZLP_ERR<<((n)-1)) +#define DQMU_M_RX0_LEN_ERR 0x00000100 +#define DQMU_M_RX_LEN_ERR(n) (DQMU_M_RX0_LEN_ERR<<((n)-1)) +#define DQMU_M_RX0_GPDCS_ERR 0x00000001 +#define DQMU_M_RX_GPDCS_ERR(n) (DQMU_M_RX0_GPDCS_ERR<<((n)-1)) + +#define DQMU_M_TX0_LEN_ERR 0x00010000 +#define DQMU_M_TX_LEN_ERR(n) (DQMU_M_TX0_LEN_ERR<<((n)-1)) +#define DQMU_M_TX0_GPDCS_ERR 0x00000100 +#define DQMU_M_TX_GPDCS_ERR(n) (DQMU_M_TX0_GPDCS_ERR<<((n)-1)) +#define DQMU_M_TX0_BDCS_ERR 0x00000001 +#define DQMU_M_TX_BDCS_ERR(n) (DQMU_M_TX0_BDCS_ERR<<((n)-1)) + +#define DQMU_M_TX0_EP_ERR 0x00000001 +#define DQMU_M_TX_EP_ERR(n) (DQMU_M_TX0_EP_ERR<<((n)-1)) + +#define DQMU_M_RX0_EP_ERR 0x00000001 +#define DQMU_M_RX_EP_ERR(n) (DQMU_M_RX0_EP_ERR<<((n)-1)) +#define DQMU_M_RQ_DIS_IOC(n) (0x100<<((n)-1)) + +#define MGC_ReadQMU8(base,_offset) \ + musb_readb(base, (USB_HW_QMU_OFF + _offset)) + +#define MGC_ReadQUCS8(base,_offset) \ + musb_readb(base, (USB_HW_QUCS_OFF + _offset)) + +#define MGC_ReadQIRQ8(base,_offset) \ + musb_readb(base, (USB_HW_QIRQ_OFF + _offset)) + +#define MGC_ReadQMU16(base,_offset) \ + musb_readw(base, (USB_HW_QMU_OFF + _offset)) + +#define MGC_ReadQUCS16(base,_offset) \ + musb_readw(base,(USB_HW_QUCS_OFF + _offset)) + +#define MGC_ReadQIRQ16(base,_offset) \ + musb_readw(base, (USB_HW_QIRQ_OFF + _offset)) +#define MGC_ReadQMU32(base,_offset) \ + musb_readl(base, (USB_HW_QMU_OFF + _offset)) + +#define MGC_ReadQUCS32(base,_offset) \ + musb_readl(base, (USB_HW_QUCS_OFF + _offset)) + +#define MGC_ReadQIRQ32(base,_offset) \ + musb_readl(base, (USB_HW_QIRQ_OFF + _offset)) + +#define MGC_WriteQMU32(base,_offset, _data) \ + musb_writel(base, (USB_HW_QMU_OFF + _offset), _data) + +#define MGC_WriteQUCS32(base,_offset, _data) \ + musb_writel(base, (USB_HW_QUCS_OFF + _offset), _data) + +#define MGC_WriteQIRQ32(base,_offset, _data) \ + musb_writel(base,(USB_HW_QIRQ_OFF + _offset), _data) + +u8 PDU_calcCksum(u8 *data, int len); + +/* brief Define DMAQ GPD format */ +#define TGPD_FLAGS_HWO 0x01 +#define TGPD_IS_FLAGS_HWO(_pd) (((TGPD *)_pd)->flag & TGPD_FLAGS_HWO) +#define TGPD_SET_FLAGS_HWO(_pd) (((TGPD *)_pd)->flag |= TGPD_FLAGS_HWO) +#define TGPD_CLR_FLAGS_HWO(_pd) (((TGPD *)_pd)->flag &= (~TGPD_FLAGS_HWO)) +#define TGPD_FORMAT_BDP 0x02 +#define TGPD_IS_FORMAT_BDP(_pd) (((TGPD *)_pd)->flag & TGPD_FORMAT_BDP) +#define TGPD_SET_FORMAT_BDP(_pd) (((TGPD *)_pd)->flag |= TGPD_FORMAT_BDP) +#define TGPD_CLR_FORMAT_BDP(_pd) (((TGPD *)_pd)->flag &= (~TGPD_FORMAT_BDP)) + +#define TGPD_SET_FLAG(_pd, _flag) ((TGPD *)_pd)->flag = (((TGPD *)_pd)->flag&(~TGPD_FLAGS_HWO))|(_flag) +#define TGPD_GET_FLAG(_pd) (((TGPD *)_pd)->flag & TGPD_FLAGS_HWO) +#define TGPD_SET_CHKSUM(_pd, _n) ((TGPD *)_pd)->chksum = PDU_calcCksum((u8 *)_pd, _n) +#define TGPD_SET_CHKSUM_HWO(_pd, _n) ((TGPD *)_pd)->chksum = PDU_calcCksum((u8 *)_pd, _n)-1 +#define TGPD_GET_CHKSUM(_pd) ((TGPD *)_pd)->chksum +#define TGPD_SET_FORMAT(_pd, _fmt) ((TGPD *)_pd)->flag = (((TGPD *)_pd)->flag&(~TGPD_FORMAT_BDP))|(_fmt) +#define TGPD_GET_FORMAT(_pd) ((((TGPD *)_pd)->flag & TGPD_FORMAT_BDP)>>1) +#define TGPD_SET_DataBUF_LEN(_pd, _len) ((TGPD *)_pd)->DataBufferLen = _len +#define TGPD_ADD_DataBUF_LEN(_pd, _len) ((TGPD *)_pd)->DataBufferLen += _len +#define TGPD_GET_DataBUF_LEN(_pd) ((TGPD *)_pd)->DataBufferLen +#define TGPD_SET_NEXT(_pd, _next) ((TGPD *)_pd)->pNext = (u32)(unsigned long)((TGPD *)_next) +#define TGPD_GET_NEXT(_pd) (TGPD *)(unsigned long)((TGPD *)_pd)->pNext + +#define TGPD_SET_DATA(_pd, _data) ((TGPD *)_pd)->pBuf = (u32)(unsigned long)_data +#define TGPD_GET_DATA(_pd) (u8 *)(unsigned long)((TGPD *)_pd)->pBuf +#define TGPD_SET_BUF_LEN(_pd, _len) ((TGPD *)_pd)->bufLen = _len +#define TGPD_ADD_BUF_LEN(_pd, _len) ((TGPD *)_pd)->bufLen += _len +#define TGPD_GET_BUF_LEN(_pd) ((TGPD *)_pd)->bufLen +#define TGPD_SET_EXT_LEN(_pd, _len) ((TGPD *)_pd)->ExtLength = _len +#define TGPD_GET_EXT_LEN(_pd) ((TGPD *)_pd)->ExtLength +#define TGPD_SET_EPaddr(_pd, _EP) ((TGPD *)_pd)->ZTepFlag =(((TGPD *)_pd)->ZTepFlag&0xF0)|(_EP) +#define TGPD_GET_EPaddr(_pd) ((TGPD *)_pd)->ZTepFlag & 0x0F + +#define TGPD_FORMAT_TGL 0x10 +#define TGPD_IS_FORMAT_TGL(_pd) (((TGPD *)_pd)->ZTepFlag & TGPD_FORMAT_TGL) +#define TGPD_SET_FORMAT_TGL(_pd) (((TGPD *)_pd)->ZTepFlag |=TGPD_FORMAT_TGL) +#define TGPD_CLR_FORMAT_TGL(_pd) (((TGPD *)_pd)->ZTepFlag &= (~TGPD_FORMAT_TGL)) +#define TGPD_FORMAT_ZLP 0x20 +#define TGPD_IS_FORMAT_ZLP(_pd) (((TGPD *)_pd)->ZTepFlag & TGPD_FORMAT_ZLP) +#define TGPD_SET_FORMAT_ZLP(_pd) (((TGPD *)_pd)->ZTepFlag |=TGPD_FORMAT_ZLP) +#define TGPD_CLR_FORMAT_ZLP(_pd) (((TGPD *)_pd)->ZTepFlag &= (~TGPD_FORMAT_ZLP)) + +#define TGPD_SET_TGL(_pd, _TGL) ((TGPD *)_pd)->ZTepFlag |=(( _TGL) ? 0x10: 0x00) +#define TGPD_GET_TGL(_pd) ((TGPD *)_pd)->ZTepFlag & 0x10 ? 1:0 +#define TGPD_SET_ZLP(_pd, _ZLP) ((TGPD *)_pd)->ZTepFlag |= ((_ZLP) ? 0x20: 0x00) +#define TGPD_GET_ZLP(_pd) ((TGPD *)_pd)->ZTepFlag & 0x20 ? 1:0 + +#define TGPD_FLAG_IOC 0x80 +#define TGPD_SET_IOC(_pd) (((TGPD *)_pd)->flag |= TGPD_FLAG_IOC) + +extern void qmu_destroy_gpd_pool(struct device *dev); +extern int qmu_init_gpd_pool(struct device *dev); +extern void qmu_reset_gpd_pool(u32 ep_num, u8 isRx); +extern bool mtk_is_qmu_enabled(u8 EP_Num, u8 isRx); +extern void mtk_qmu_enable(struct musb *musb, u8 EP_Num, u8 isRx); +extern void mtk_qmu_insert_task(u8 EP_Num, u8 isRx, u8* buf, u32 length, u8 zlp); +extern void mtk_qmu_resume(u8 EP_Num, u8 isRx); +extern void qmu_done_rx(struct musb *musb, u8 ep_num); +extern void qmu_done_tx(struct musb *musb, u8 ep_num); +extern void mtk_disable_q(struct musb *musb, u8 ep_num, u8 isRx); +extern void mtk_qmu_irq_err(struct musb *musb, u32 qisar); +extern void flush_ep_csr(struct musb *musb, u8 ep_num, u8 isRx); +extern void mtk_qmu_stop(u8 ep_num, u8 isRx); + +#endif +#endif diff --git a/include/linux/musb/musb.h b/include/linux/musb/musb.h new file mode 100644 index 000000000..e9234567b --- /dev/null +++ b/include/linux/musb/musb.h @@ -0,0 +1,132 @@ +/* + * This is used to for host and peripheral modes of the driver for + * Inventra (Multidrop) Highspeed Dual-Role Controllers: (M)HDRC. + * + * Board initialization should put one of these into dev->platform_data, + * probably on some platform_device named "musb-hdrc". It encapsulates + * key configuration differences between boards. + */ + +#ifndef __LINUX_USB_MUSB_H +#define __LINUX_USB_MUSB_H + +/* The USB role is defined by the connector used on the board, so long as + * standards are being followed. (Developer boards sometimes won't.) + */ +enum musb_mode { + MUSB_UNDEFINED = 0, + MUSB_HOST, /* A or Mini-A connector */ + MUSB_PERIPHERAL, /* B or Mini-B connector */ + MUSB_OTG /* Mini-AB connector */ +}; + +struct clk; + +enum musb_fifo_style { + MUSB_FIFO_RXTX, /* add MUSB_ prefix to avoid confilicts with musbfsh.h, gang */ + MUSB_FIFO_TX, + MUSB_FIFO_RX +} __attribute__ ((packed)); + +enum musb_buf_mode { + MUSB_BUF_SINGLE, /* add MUSB_ prefix to avoid confilicts with musbfsh.h, gang */ + MUSB_BUF_DOUBLE +} __attribute__ ((packed)); + +enum musb_ep_mode { + EP_CONT, + EP_INT, + EP_BULK, + EP_ISO +} __attribute__ ((packed)); + +struct musb_fifo_cfg { + u8 hw_ep_num; + enum musb_fifo_style style; + enum musb_buf_mode mode; + u16 maxpacket; + enum musb_ep_mode ep_mode; +}; + +#define MUSB_EP_FIFO(ep, st, m, pkt) \ +{ \ + .hw_ep_num = ep, \ + .style = st, \ + .mode = m, \ + .maxpacket = pkt, \ +} + +#define MUSB_EP_FIFO_SINGLE(ep, st, pkt) \ + MUSB_EP_FIFO(ep, st, BUF_SINGLE, pkt) + +#define MUSB_EP_FIFO_DOUBLE(ep, st, pkt) \ + MUSB_EP_FIFO(ep, st, BUF_DOUBLE, pkt) + +struct musb_hdrc_eps_bits { + const char name[16]; + u8 bits; +}; + +struct musb_hdrc_config { + struct musb_fifo_cfg *fifo_cfg; /* board fifo configuration */ + unsigned fifo_cfg_size; /* size of the fifo configuration */ + + /* MUSB configuration-specific details */ + unsigned multipoint:1; /* multipoint device */ + unsigned dyn_fifo:1 __deprecated; /* supports dynamic fifo sizing */ + unsigned soft_con:1 __deprecated; /* soft connect required */ + unsigned utm_16:1 __deprecated; /* utm data witdh is 16 bits */ + unsigned big_endian:1; /* true if CPU uses big-endian */ + unsigned mult_bulk_tx:1; /* Tx ep required for multbulk pkts */ + unsigned mult_bulk_rx:1; /* Rx ep required for multbulk pkts */ + unsigned high_iso_tx:1; /* Tx ep required for HB iso */ + unsigned high_iso_rx:1; /* Rx ep required for HD iso */ + unsigned dma:1 __deprecated; /* supports DMA */ + unsigned vendor_req:1 __deprecated; /* vendor registers required */ + + u8 num_eps; /* number of endpoints _with_ ep0 */ + u8 dma_channels __deprecated; /* number of dma channels */ + u8 dyn_fifo_size; /* dynamic size in bytes */ + u8 vendor_ctrl __deprecated; /* vendor control reg width */ + u8 vendor_stat __deprecated; /* vendor status reg witdh */ + u8 dma_req_chan __deprecated; /* bitmask for required dma channels */ + u8 ram_bits; /* ram address size */ + + struct musb_hdrc_eps_bits *eps_bits __deprecated; +}; + +struct musb_hdrc_platform_data { + /* MUSB_HOST, MUSB_PERIPHERAL, or MUSB_OTG */ + u8 mode; + + /* for clk_get() */ + const char *clock; + + /* (HOST or OTG) switch VBUS on/off */ + int (*set_vbus) (struct device *dev, int is_on); + + /* (HOST or OTG) mA/2 power supplied on (default = 8mA) */ + u8 power; + + /* (PERIPHERAL) mA/2 max power consumed (default = 100mA) */ + u8 min_power; + + /* (HOST or OTG) msec/2 after VBUS on till power good */ + u8 potpgt; + + /* (HOST or OTG) program PHY for external Vbus */ + unsigned extvbus:1; + + /* Power the device on or off */ + int (*set_power) (int state); + + /* MUSB configuration-specific details */ + struct musb_hdrc_config *config; + + /* Architecture specific board data */ + void *board_data; + + /* Platform specific struct musb_ops pointer */ + const void *platform_ops; +}; +#endif /* __LINUX_USB_MUSB_H */ diff --git a/include/linux/musb/musb_core.h b/include/linux/musb/musb_core.h new file mode 100644 index 000000000..88d719f63 --- /dev/null +++ b/include/linux/musb/musb_core.h @@ -0,0 +1,601 @@ +/* + * MUSB OTG driver defines + * + * Copyright 2005 Mentor Graphics Corporation + * Copyright (C) 2005-2006 by Texas Instruments + * Copyright (C) 2006-2007 Nokia Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * 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 AUTHORS 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. + * + */ + +#ifndef __MUSB_CORE_H__ +#define __MUSB_CORE_H__ + +#include <linux/slab.h> +#include <linux/list.h> +#include <linux/interrupt.h> +#include <linux/errno.h> +#include <linux/timer.h> +#include <linux/device.h> +#include <linux/usb/ch9.h> +#include <linux/usb/gadget.h> +#include <linux/usb.h> +#include <linux/usb/otg.h> +#include <linux/musb/musb.h> +#include <linux/wakelock.h> +#include <linux/version.h> +#include <mach/mt_typedefs.h> + +#ifdef MUSB_QMU_SUPPORT +#include "mtk_qmu.h" +#endif + +#define SHARE_IRQ -1 + +struct musb; +struct musb_hw_ep; +struct musb_ep; +extern volatile bool usb_is_host; + +/* Helper defines for struct musb->hwvers */ +#define MUSB_HWVERS_MAJOR(x) ((x >> 10) & 0x1f) +#define MUSB_HWVERS_MINOR(x) (x & 0x3ff) +#define MUSB_HWVERS_RC 0x8000 +#define MUSB_HWVERS_1300 0x52C +#define MUSB_HWVERS_1400 0x590 +#define MUSB_HWVERS_1800 0x720 +#define MUSB_HWVERS_1900 0x784 +#define MUSB_HWVERS_2000 0x800 +#define MUSB_HUB_SUPPORT 0x4000 +#include "mtk_musb.h" + +#include "musb_debug.h" +#include "musb_dma.h" + +#include "musb_io.h" +#include <mach/mt_musb_reg.h> + +#include "musb_gadget.h" +#include <linux/usb/hcd.h> +#include "musb_host.h" +#ifdef CONFIG_OF + +enum { + usb0 = 0, + usb_sif, + usb_acm_temp_device, +}; +#endif + + +#ifdef ENABLE_STORAGE_LOGGER +#define USB_LOGGER(msg_id, func_name, ...) \ + do { \ + if (unlikely(is_dump_musb())) { \ + ADD_USB_TRACE(msg_id, func_name, __VA_ARGS__); \ + } \ + } while (0) +#else +#define USB_LOGGER(msg_id, func_name, args...) do {} while (0) +#endif + +/* NOTE: otg and peripheral-only state machines start at B_IDLE. + * OTG or host-only go to A_IDLE when ID is sensed. + */ +#define is_peripheral_active(m) (!(m)->is_host) +#define is_host_active(m) ((m)->is_host) + +#ifdef CONFIG_PROC_FS +#include <linux/fs.h> +#define MUSB_CONFIG_PROC_FS +#endif + +/****************************** PERIPHERAL ROLE *****************************/ + +extern irqreturn_t musb_g_ep0_irq(struct musb *); +extern void musb_g_tx(struct musb *, u8); +extern void musb_g_rx(struct musb *, u8); +extern void musb_g_reset(struct musb *); +extern void musb_g_suspend(struct musb *); +extern void musb_g_resume(struct musb *); +extern void musb_g_wakeup(struct musb *); +extern void musb_g_disconnect(struct musb *); + +/****************************** HOST ROLE ***********************************/ +extern irqreturn_t musb_h_ep0_irq(struct musb *); +extern void musb_host_tx(struct musb *, u8); +extern void musb_host_rx(struct musb *, u8); + +/****************************** CONSTANTS ********************************/ + +#ifndef MUSB_C_NUM_EPS +#define MUSB_C_NUM_EPS ((u8)16) +#endif + +#ifndef MUSB_MAX_END0_PACKET +#define MUSB_MAX_END0_PACKET ((u16)MUSB_EP0_FIFOSIZE) +#endif + +/* host side ep0 states */ +enum musb_h_ep0_state { + MUSB_EP0_IDLE, + MUSB_EP0_START, /* expect ack of setup */ + MUSB_EP0_IN, /* expect IN DATA */ + MUSB_EP0_OUT, /* expect ack of OUT DATA */ + MUSB_EP0_STATUS, /* expect ack of STATUS */ +} __attribute__ ((packed)); + +/* peripheral side ep0 states */ +enum musb_g_ep0_state { + MUSB_EP0_STAGE_IDLE, /* idle, waiting for SETUP */ + MUSB_EP0_STAGE_SETUP, /* received SETUP */ + MUSB_EP0_STAGE_TX, /* IN data */ + MUSB_EP0_STAGE_RX, /* OUT data */ + MUSB_EP0_STAGE_STATUSIN, /* (after OUT data) */ + MUSB_EP0_STAGE_STATUSOUT, /* (after IN data) */ + MUSB_EP0_STAGE_ACKWAIT, /* after zlp, before statusin */ +} __attribute__ ((packed)); + +/* + * OTG protocol constants. See USB OTG 1.3 spec, + * sections 5.5 "Device Timings" and 6.6.5 "Timers". + */ +#define OTG_TIME_A_WAIT_VRISE 100 /* msec (max) */ +#define OTG_TIME_A_WAIT_BCON 1100 /* min 1 second */ +#define OTG_TIME_A_AIDL_BDIS 200 /* min 200 msec */ +#if defined(CONFIG_USBIF_COMPLIANCE) +#define OTG_TIME_B_ASE0_BRST 155 /* min 3.125 ms */ +#else +#define OTG_TIME_B_ASE0_BRST 100 /* min 3.125 ms */ +#endif + + + +/*************************** REGISTER ACCESS ********************************/ + +#define musb_ep_select(_mbase, _epnum) \ + musb_writeb((_mbase), MUSB_INDEX, (_epnum)) +#define MUSB_EP_OFFSET MUSB_INDEXED_OFFSET + +/****************************** FUNCTIONS ********************************/ + +#define MUSB_HST_MODE(_musb)\ + { (_musb)->is_host = true; } +#define MUSB_DEV_MODE(_musb) \ + { (_musb)->is_host = false; } + +#define test_devctl_hst_mode(_x) \ + (musb_readb((_x)->mregs, MUSB_DEVCTL)&MUSB_DEVCTL_HM) + +#define MUSB_MODE(musb) ((musb)->is_host ? "Host" : "Peripheral") + +typedef enum { + funcWriteb = 0, + funcWritew, + funcWritel, + funcInterrupt +} writeFunc_enum; + +void dumpTime(writeFunc_enum func, int epnum); + +/******************************** TYPES *************************************/ + +/** + * struct musb_platform_ops - Operations passed to musb_core by HW glue layer + * @init: turns on clocks, sets up platform-specific registers, etc + * @exit: undoes @init + * @set_mode: forcefully changes operating mode + * @try_ilde: tries to idle the IP + * @vbus_status: returns vbus status if possible + * @set_vbus: forces vbus status + * @adjust_channel_params: pre check for standard dma channel_program func + */ +struct musb_platform_ops { + int (*init) (struct musb *musb); + int (*exit) (struct musb *musb); + + void (*enable) (struct musb *musb); + void (*disable) (struct musb *musb); + + int (*set_mode) (struct musb *musb, u8 mode); + void (*try_idle) (struct musb *musb, unsigned long timeout); + + int (*vbus_status) (struct musb *musb); + void (*set_vbus) (struct musb *musb, int on); + + int (*adjust_channel_params) (struct dma_channel *channel, + u16 packet_sz, u8 *mode, dma_addr_t *dma_addr, u32 *len); +}; + +/* + * struct musb_hw_ep - endpoint hardware (bidirectional) + * + * Ordered slightly for better cacheline locality. + */ +struct musb_hw_ep { + struct musb *musb; + void __iomem *fifo; + void __iomem *regs; + + /* index in musb->endpoints[] */ + u8 epnum; + enum musb_ep_mode ep_mode; + + /* hardware configuration, possibly dynamic */ + bool is_shared_fifo; + bool tx_double_buffered; + bool rx_double_buffered; + u16 max_packet_sz_tx; + u16 max_packet_sz_rx; + + struct dma_channel *tx_channel; + struct dma_channel *rx_channel; + + void __iomem *target_regs; + + /* currently scheduled peripheral endpoint */ + struct musb_qh *in_qh; + struct musb_qh *out_qh; + + u8 rx_reinit; + u8 tx_reinit; + + /* peripheral side */ + struct musb_ep ep_in; /* TX */ + struct musb_ep ep_out; /* RX */ +}; + +static inline struct musb_request *next_in_request(struct musb_hw_ep *hw_ep) +{ + return next_request(&hw_ep->ep_in); +} + +static inline struct musb_request *next_out_request(struct musb_hw_ep *hw_ep) +{ + return next_request(&hw_ep->ep_out); +} + +struct musb_csr_regs { + /* FIFO registers */ + u16 txmaxp, txcsr, rxmaxp, rxcsr; + u16 rxfifoadd, txfifoadd; + u8 txtype, txinterval, rxtype, rxinterval; + u8 rxfifosz, txfifosz; + u8 txfunaddr, txhubaddr, txhubport; + u8 rxfunaddr, rxhubaddr, rxhubport; +}; + +struct musb_context_registers { + + u8 power; + u8 intrusbe; + u16 frame; + u8 index, testmode; + + u8 devctl, busctl, misc; + u32 otg_interfsel; + u32 l1_int; + + struct musb_csr_regs index_regs[MUSB_C_NUM_EPS]; +}; + +/* + * struct musb - Driver instance data. + */ +struct musb { + struct semaphore musb_lock; + /* device lock */ + spinlock_t lock; + + const struct musb_platform_ops *ops; + struct musb_context_registers context; + + irqreturn_t(*isr) (int, void *); + struct work_struct irq_work; + struct work_struct otg_notifier_work; + u16 hwvers; + struct delayed_work id_pin_work; + + struct musb_fifo_cfg *fifo_cfg; + unsigned fifo_cfg_size; + struct musb_fifo_cfg *fifo_cfg_host; + unsigned fifo_cfg_host_size; + u32 fifo_size; + + u16 intrrxe; + u16 intrtxe; +/* this hub status bit is reserved by USB 2.0 and not seen by usbcore */ +#define MUSB_PORT_STAT_RESUME (1 << 31) + + u32 port1_status; + + unsigned long rh_timer; + + enum musb_h_ep0_state ep0_stage; + + /* bulk traffic normally dedicates endpoint hardware, and each + * direction has its own ring of host side endpoints. + * we try to progress the transfer at the head of each endpoint's + * queue until it completes or NAKs too much; then we try the next + * endpoint. + */ + struct musb_hw_ep *bulk_ep; + + struct list_head control; /* of musb_qh */ + struct list_head in_bulk; /* of musb_qh */ + struct list_head out_bulk; /* of musb_qh */ + + struct timer_list otg_timer; +#if defined(CONFIG_USBIF_COMPLIANCE) + struct timer_list otg_vbus_polling_timer; +#endif + struct notifier_block nb; + + struct dma_controller *dma_controller; + + struct device *controller; + void __iomem *ctrl_base; + void __iomem *mregs; + + /* passed down from chip/board specific irq handlers */ + u8 int_usb; + u16 int_rx; + u16 int_tx; + +#ifdef MUSB_QMU_SUPPORT + u32 int_queue; +#ifdef QMU_TASKLET + u32 qmu_done_intr; + struct tasklet_struct qmu_done; +#endif +#endif + + struct usb_phy *xceiv; + u8 xceiv_event; + + int nIrq; + int dma_irq; + unsigned irq_wake:1; + + struct musb_hw_ep endpoints[MUSB_C_NUM_EPS]; +#define control_ep endpoints + +#define VBUSERR_RETRY_COUNT 3 + u16 vbuserr_retry; + u16 epmask; + u8 nr_endpoints; + + int (*board_set_power) (int state); + + u8 min_power; /* vbus for periph, in mA/2 */ + + bool is_host; + bool in_ipo_off; + + int a_wait_bcon; /* VBUS timeout in msecs */ + unsigned long idle_timeout; /* Next timeout in jiffies */ + + /* active means connected and not suspended */ + unsigned is_active:1; + + unsigned is_multipoint:1; + unsigned ignore_disconnect:1; /* during bus resets */ + + unsigned hb_iso_rx:1; /* high bandwidth iso rx? */ + unsigned hb_iso_tx:1; /* high bandwidth iso tx? */ + unsigned dyn_fifo:1; /* dynamic FIFO supported? */ + + unsigned bulk_split:1; +#define can_bulk_split(musb, type) \ + (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_split) + + unsigned bulk_combine:1; +#define can_bulk_combine(musb, type) \ + (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_combine) + + /* is_suspended means USB B_PERIPHERAL suspend */ + unsigned is_suspended:1; + + /* may_wakeup means remote wakeup is enabled */ + unsigned may_wakeup:1; + + /* is_self_powered is reported in device status and the + * config descriptor. is_bus_powered means B_PERIPHERAL + * draws some VBUS current; both can be true. + */ + unsigned is_self_powered:1; + unsigned is_bus_powered:1; + + unsigned set_address:1; + unsigned test_mode:1; + unsigned softconnect:1; + + u8 address; + u8 test_mode_nr; + u16 ackpend; /* ep0 */ + enum musb_g_ep0_state ep0_state; + struct usb_gadget g; /* the gadget */ + struct usb_gadget_driver *gadget_driver; /* its driver */ + struct wake_lock usb_lock; + + /* + * FIXME: Remove this flag. + * + * This is only added to allow Blackfin to work + * with current driver. For some unknown reason + * Blackfin doesn't work with double buffering + * and that's enabled by default. + * + * We added this flag to forcefully disable double + * buffering until we get it working. + */ + unsigned double_buffer_not_ok:1; + + struct musb_hdrc_config *config; + +#ifdef MUSB_CONFIG_PROC_FS + struct proc_dir_entry *proc_entry; +#endif + int xceiv_old_state; +#ifdef CONFIG_DEBUG_FS + struct dentry *debugfs_root; +#endif + bool power; + bool is_ready:1; + bool usb_if; + u16 fifo_addr; +#if defined(CONFIG_USBIF_COMPLIANCE) + bool srp_drvvbus; + enum usb_otg_event otg_event; +#endif +}; + +static inline struct musb *gadget_to_musb(struct usb_gadget *g) +{ + return container_of(g, struct musb, g); +} + +static inline int musb_read_fifosize(struct musb *musb, struct musb_hw_ep *hw_ep, u8 epnum) +{ + void __iomem *mbase = musb->mregs; + u8 reg = 0; + + /* read from core using indexed model */ + reg = musb_readb(mbase, MUSB_EP_OFFSET(epnum, MUSB_FIFOSIZE)); + /* 0's returned when no more endpoints */ + if (!reg) + return -ENODEV; + + musb->nr_endpoints++; + musb->epmask |= (1 << epnum); + + hw_ep->max_packet_sz_tx = 1 << (reg & 0x0f); + + /* shared TX/RX FIFO? */ + if ((reg & 0xf0) == 0xf0) { + hw_ep->max_packet_sz_rx = hw_ep->max_packet_sz_tx; + hw_ep->is_shared_fifo = true; + return 0; + } else { + hw_ep->max_packet_sz_rx = 1 << ((reg & 0xf0) >> 4); + hw_ep->is_shared_fifo = false; + } + + return 0; +} + +static inline void musb_configure_ep0(struct musb *musb) +{ + musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE; + musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE; + musb->endpoints[0].is_shared_fifo = true; +} + + +/***************************** Glue it together *****************************/ + +extern const char musb_driver_name[]; + +extern void musb_start(struct musb *musb); +extern void musb_stop(struct musb *musb); +extern int musb_get_id(struct device *dev, gfp_t gfp_mask); +extern void musb_put_id(struct device *dev, int id); + +extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src); +extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst); + +extern void musb_load_testpacket(struct musb *); +extern void musb_generic_disable(struct musb *); +extern irqreturn_t musb_interrupt(struct musb *); +extern irqreturn_t dma_controller_irq(int irq, void *private_data); + +extern void musb_hnp_stop(struct musb *musb); + +static inline void musb_platform_set_vbus(struct musb *musb, int is_on) +{ + if (musb->ops->set_vbus) + musb->ops->set_vbus(musb, is_on); +} + +static inline void musb_platform_enable(struct musb *musb) +{ + if (musb->ops->enable) + musb->ops->enable(musb); +} + +static inline void musb_platform_disable(struct musb *musb) +{ + if (musb->ops->disable) + musb->ops->disable(musb); +} + +static inline int musb_platform_set_mode(struct musb *musb, u8 mode) +{ + if (!musb->ops->set_mode) + return 0; + + return musb->ops->set_mode(musb, mode); +} + +static inline void musb_platform_try_idle(struct musb *musb, unsigned long timeout) +{ + if (musb->ops->try_idle) + musb->ops->try_idle(musb, timeout); +} + +static inline int musb_platform_get_vbus_status(struct musb *musb) +{ + if (!musb->ops->vbus_status) + return 0; + + return musb->ops->vbus_status(musb); +} + +static inline int musb_platform_init(struct musb *musb) +{ + if (!musb->ops->init) + return -EINVAL; + + return musb->ops->init(musb); +} + +static inline int musb_platform_exit(struct musb *musb) +{ + if (!musb->ops->exit) + return -EINVAL; + + return musb->ops->exit(musb); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) +static inline const char *otg_state_string(enum usb_otg_state state) +{ + return usb_otg_state_string(state); +} +#endif + +#endif /* __MUSB_CORE_H__ */ diff --git a/include/linux/musb/musb_debug.h b/include/linux/musb/musb_debug.h new file mode 100644 index 000000000..24c380603 --- /dev/null +++ b/include/linux/musb/musb_debug.h @@ -0,0 +1,100 @@ +/* + * MUSB OTG driver debug defines + * + * Copyright 2005 Mentor Graphics Corporation + * Copyright (C) 2005-2006 by Texas Instruments + * Copyright (C) 2006-2007 Nokia Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * 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 AUTHORS 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. + * + */ + +#ifndef __MUSB_LINUX_DEBUG_H__ +#define __MUSB_LINUX_DEBUG_H__ + +#define yprintk(facility, format, args...) \ + do { printk(facility "%s %d: " format , \ + __func__, __LINE__ , ## args); } while (0) + +/* workaroud for redefine warning in usb_dump.c */ +#ifdef WARNING +#undef WARNING +#endif + +#ifdef INFO +#undef INFO +#endif + +#ifdef ERR +#undef ERR +#endif + +#define WARNING(fmt, args...) yprintk(KERN_WARNING, fmt, ## args) +#define INFO(fmt, args...) yprintk(KERN_INFO, fmt, ## args) +#define ERR(fmt, args...) yprintk(KERN_ERR, fmt, ## args) + +#define xprintk(level, format, args...) do { \ + if (_dbg_level(level)) { \ + if (musb_uart_debug) {\ + printk(KERN_EMERG "[MUSB]%s %d: " format , \ + __func__, __LINE__ , ## args); \ + } \ + else{\ + printk(KERN_DEBUG "[MUSB]%s %d: " format , \ + __func__, __LINE__ , ## args); \ + } \ + } } while (0) + +extern unsigned musb_debug; +extern unsigned musb_uart_debug; + +static inline int _dbg_level(unsigned level) +{ + return level <= musb_debug; +} + +#ifdef DBG +#undef DBG +#endif +#define DBG(level, fmt, args...) xprintk(level, fmt, ## args) + +/* extern const char *otg_state_string(struct musb *); */ + +#ifdef CONFIG_USB_MTK_DEBUG_FS +extern int musb_init_debugfs(struct musb *musb); +extern void musb_exit_debugfs(struct musb *musb); +#else +static inline int musb_init_debugfs(struct musb *musb) +{ + return 0; +} + +static inline void musb_exit_debugfs(struct musb *musb) +{ +} +#endif + +#endif /* __MUSB_LINUX_DEBUG_H__ */ diff --git a/include/linux/musb/musb_dma.h b/include/linux/musb/musb_dma.h new file mode 100644 index 000000000..720341148 --- /dev/null +++ b/include/linux/musb/musb_dma.h @@ -0,0 +1,171 @@ +/* + * MUSB OTG driver DMA controller abstraction + * + * Copyright 2005 Mentor Graphics Corporation + * Copyright (C) 2005-2006 by Texas Instruments + * Copyright (C) 2006-2007 Nokia Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * 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 AUTHORS 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. + * + */ + +#ifndef __MUSB_DMA_H__ +#define __MUSB_DMA_H__ + +struct musb_hw_ep; + +/* + * DMA Controller Abstraction + * + * DMA Controllers are abstracted to allow use of a variety of different + * implementations of DMA, as allowed by the Inventra USB cores. On the + * host side, usbcore sets up the DMA mappings and flushes caches; on the + * peripheral side, the gadget controller driver does. Responsibilities + * of a DMA controller driver include: + * + * - Handling the details of moving multiple USB packets + * in cooperation with the Inventra USB core, including especially + * the correct RX side treatment of short packets and buffer-full + * states (both of which terminate transfers). + * + * - Knowing the correlation between dma channels and the + * Inventra core's local endpoint resources and data direction. + * + * - Maintaining a list of allocated/available channels. + * + * - Updating channel status on interrupts, + * whether shared with the Inventra core or separate. + */ + +#define DMA_ADDR_INVALID (~(dma_addr_t)0) + +#ifndef CONFIG_MUSB_PIO_ONLY +#define is_dma_capable() (1) +#else +#define is_dma_capable() (0) +#endif + +/* Anomaly 05000456 - USB Receive Interrupt Is Not Generated in DMA Mode 1 + * Only allow DMA mode 1 to be used when the USB will actually generate the + * interrupts we expect. + */ +/* + * DMA channel status ... updated by the dma controller driver whenever that + * status changes, and protected by the overall controller spinlock. + */ +enum dma_channel_status { + /* unallocated */ + MUSB_DMA_STATUS_UNKNOWN, + /* allocated ... but not busy, no errors */ + MUSB_DMA_STATUS_FREE, + /* busy ... transactions are active */ + MUSB_DMA_STATUS_BUSY, + /* transaction(s) aborted due to ... dma or memory bus error */ + MUSB_DMA_STATUS_BUS_ABORT, + /* transaction(s) aborted due to ... core error or USB fault */ + MUSB_DMA_STATUS_CORE_ABORT +}; + +struct dma_controller; + +/** + * struct dma_channel - A DMA channel. + * @private_data: channel-private data + * @max_len: the maximum number of bytes the channel can move in one + * transaction (typically representing many USB maximum-sized packets) + * @actual_len: how many bytes have been transferred + * @prog_len: how many bytes have been programmed for transfer + * @status: current channel status (updated e.g. on interrupt) + * @desired_mode: true if mode 1 is desired; false if mode 0 is desired + * + * channels are associated with an endpoint for the duration of at least + * one usb transfer. + */ +struct dma_channel { + void *private_data; + /* FIXME not void* private_data, but a dma_controller * */ + size_t max_len; + size_t actual_len; + size_t prog_len; + enum dma_channel_status status; + bool desired_mode; +}; + +/* + * dma_channel_status - return status of dma channel + * @c: the channel + * + * Returns the software's view of the channel status. If that status is BUSY + * then it's possible that the hardware has completed (or aborted) a transfer, + * so the driver needs to update that status. + */ +static inline enum dma_channel_status dma_channel_status(struct dma_channel *c) +{ + return (is_dma_capable() && c) ? c->status : MUSB_DMA_STATUS_UNKNOWN; +} + +/** + * struct dma_controller - A DMA Controller. + * @start: call this to start a DMA controller; + * return 0 on success, else negative errno + * @stop: call this to stop a DMA controller + * return 0 on success, else negative errno + * @channel_alloc: call this to allocate a DMA channel + * @channel_release: call this to release a DMA channel + * @channel_abort: call this to abort a pending DMA transaction, + * returning it to FREE (but allocated) state + * @channel_pause: This function pauses the ongoing DMA transfer + * @channel_resume: This function resumes the ongoing DMA transfer + * @tx_status: Gets the residue of an ongoing DMA transfer + * @check_resiudue: checks if the residue of an ongoing DMA + * transfer is valid + * Controllers manage dma channels. + */ +struct dma_controller { + int (*start) (struct dma_controller *); + int (*stop) (struct dma_controller *); + struct dma_channel *(*channel_alloc) (struct dma_controller *, + struct musb_hw_ep *, u8 is_tx); + void (*channel_release) (struct dma_channel *); + int (*channel_program) (struct dma_channel *channel, + u16 maxpacket, u8 mode, dma_addr_t dma_addr, u32 length); + int (*channel_abort) (struct dma_channel *); + int (*channel_pause) (struct dma_channel *); + int (*channel_resume) (struct dma_channel *); + int (*tx_status) (struct dma_channel *); + int (*check_residue) (struct dma_channel *, u32 residue); + int (*is_compatible) (struct dma_channel *channel, u16 maxpacket, void *buf, u32 length); +}; + +/* called after channel_program(), may indicate a fault */ +extern void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit); + + +extern struct dma_controller *dma_controller_create(struct musb *, void __iomem *); + +extern void dma_controller_destroy(struct dma_controller *); + +#endif /* __MUSB_DMA_H__ */ diff --git a/include/linux/musb/musb_gadget.h b/include/linux/musb/musb_gadget.h new file mode 100644 index 000000000..b90bc6a5c --- /dev/null +++ b/include/linux/musb/musb_gadget.h @@ -0,0 +1,125 @@ +/* + * MUSB OTG driver peripheral defines + * + * Copyright 2005 Mentor Graphics Corporation + * Copyright (C) 2005-2006 by Texas Instruments + * Copyright (C) 2006-2007 Nokia Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * 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 AUTHORS 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. + * + */ + +#ifndef __MUSB_GADGET_H +#define __MUSB_GADGET_H + +#include <linux/list.h> + +enum buffer_map_state { + UN_MAPPED = 0, + PRE_MAPPED, + MUSB_MAPPED +}; + +struct musb_request { + struct usb_request request; + struct list_head list; + struct musb_ep *ep; + struct musb *musb; + u8 tx; /* endpoint direction */ + u8 epnum; + enum buffer_map_state map_state; +}; + +static inline struct musb_request *to_musb_request(struct usb_request *req) +{ + return req ? container_of(req, struct musb_request, request) : NULL; +} + +extern struct usb_request *musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags); +extern void musb_free_request(struct usb_ep *ep, struct usb_request *req); + + +/* + * struct musb_ep - peripheral side view of endpoint rx or tx side + */ +struct musb_ep { + /* stuff towards the head is basically write-once. */ + struct usb_ep end_point; + char name[12]; + struct musb_hw_ep *hw_ep; + struct musb *musb; + u16 fifo_size; + enum musb_buf_mode fifo_mode; + u8 current_epnum; + + /* ... when enabled/disabled ... */ + u8 type; + u8 is_in; + u16 packet_sz; + const struct usb_endpoint_descriptor *desc; + struct dma_channel *dma; + + /* later things are modified based on usage */ + struct list_head req_list; + + u8 wedged; + + /* true if lock must be dropped but req_list may not be advanced */ + u8 busy; + + u8 hb_mult; + + /* true if packet is received in fifo and req_list is empty */ + u8 rx_pending; +}; + +static inline struct musb_ep *to_musb_ep(struct usb_ep *ep) +{ + return ep ? container_of(ep, struct musb_ep, end_point) : NULL; +} + +static inline struct musb_request *next_request(struct musb_ep *ep) +{ + struct list_head *queue = &ep->req_list; + + if (list_empty(queue)) + return NULL; + return container_of(queue->next, struct musb_request, list); +} + +extern void musb_g_tx(struct musb *musb, u8 epnum); +extern void musb_g_rx(struct musb *musb, u8 epnum); + +extern const struct usb_ep_ops musb_g_ep0_ops; + +extern int musb_gadget_setup(struct musb *); +extern void musb_gadget_cleanup(struct musb *); + +extern void musb_g_giveback(struct musb_ep *, struct usb_request *, int); + +extern void musb_ep_restart(struct musb *, struct musb_request *); + +#endif /* __MUSB_GADGET_H */ diff --git a/include/linux/musb/musb_host.h b/include/linux/musb/musb_host.h new file mode 100644 index 000000000..7c8270ddd --- /dev/null +++ b/include/linux/musb/musb_host.h @@ -0,0 +1,111 @@ +/* + * MUSB OTG driver host defines + * + * Copyright 2005 Mentor Graphics Corporation + * Copyright (C) 2005-2006 by Texas Instruments + * Copyright (C) 2006-2007 Nokia Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * 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 AUTHORS 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. + * + */ + +#ifndef _MUSB_HOST_H +#define _MUSB_HOST_H + +#include <linux/scatterlist.h> + +static inline struct usb_hcd *musb_to_hcd(struct musb *musb) +{ + return container_of((void *)musb, struct usb_hcd, hcd_priv); +} + +static inline struct musb *hcd_to_musb(struct usb_hcd *hcd) +{ + return (struct musb *)(hcd->hcd_priv); +} + +/* stored in "usb_host_endpoint.hcpriv" for scheduled endpoints */ +struct musb_qh { + struct usb_host_endpoint *hep; /* usbcore info */ + struct usb_device *dev; + struct musb_hw_ep *hw_ep; /* current binding */ + + struct list_head ring; /* of musb_qh */ + /* struct musb_qh *next; *//* for periodic tree */ + u8 mux; /* qh multiplexed to hw_ep */ + + unsigned offset; /* in urb->transfer_buffer */ + unsigned segsize; /* current xfer fragment */ + + u8 type_reg; /* {rx,tx} type register */ + u8 intv_reg; /* {rx,tx} interval register */ + u8 addr_reg; /* device address register */ + u8 h_addr_reg; /* hub address register */ + u8 h_port_reg; /* hub port register */ + + u8 is_ready; /* safe to modify hw_ep */ + u8 type; /* XFERTYPE_* */ + u8 epnum; + u8 hb_mult; /* high bandwidth pkts per uf */ + u16 maxpacket; + u16 frame; /* for periodic schedule */ + unsigned iso_idx; /* in urb->iso_frame_desc[] */ + struct sg_mapping_iter sg_miter; /* for highmem in PIO mode */ +}; + +/* map from control or bulk queue head to the first qh on that ring */ +static inline struct musb_qh *first_qh(struct list_head *q) +{ + if (list_empty(q)) + return NULL; + return list_entry(q->next, struct musb_qh, ring); +} + +void musb_h_pre_disable(struct musb *musb); + +extern void musb_root_disconnect(struct musb *musb); + +struct usb_hcd; + +extern int musb_hub_status_data(struct usb_hcd *hcd, char *buf); +extern int musb_hub_control(struct usb_hcd *hcd, + u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength); + +extern const struct hc_driver musb_hc_driver; + +static inline struct urb *next_urb(struct musb_qh *qh) +{ + struct list_head *queue; + + if (!qh) + return NULL; + queue = &qh->hep->urb_list; + if (list_empty(queue)) + return NULL; + return list_entry(queue->next, struct urb, urb_list); +} + +#endif /* _MUSB_HOST_H */ diff --git a/include/linux/musb/musb_io.h b/include/linux/musb/musb_io.h new file mode 100644 index 000000000..38da79b43 --- /dev/null +++ b/include/linux/musb/musb_io.h @@ -0,0 +1,231 @@ +/* + * MUSB OTG driver register I/O + * + * Copyright 2005 Mentor Graphics Corporation + * Copyright (C) 2005-2006 by Texas Instruments + * Copyright (C) 2006-2007 Nokia Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * 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 AUTHORS 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. + * + */ + +#ifndef __MUSB_LINUX_PLATFORM_ARCH_H__ +#define __MUSB_LINUX_PLATFORM_ARCH_H__ + +#include <linux/io.h> +#include <linux/spinlock.h> + +extern bool mtk_usb_power; +extern bool usb_enable_clock(bool enable); +extern spinlock_t usb_io_lock; + +static inline u16 musb_readw(const void __iomem *addr, unsigned offset) +{ + u16 rc = 0; + + if (mtk_usb_power) { + rc = readw(addr + offset); + } else { + unsigned long flags = 0; + spin_lock_irqsave(&usb_io_lock, flags); + usb_enable_clock(true); + DBG(0, "[MUSB]:access %s function when usb clock is off 0x%X\n", __func__, offset); + rc = readw(addr + offset); + usb_enable_clock(false); + spin_unlock_irqrestore(&usb_io_lock, flags); + } + return rc; +} + +static inline u32 musb_readl(const void __iomem *addr, unsigned offset) +{ + u32 rc = 0; + + if (mtk_usb_power) { + rc = readl(addr + offset); + } else { + unsigned long flags = 0; + spin_lock_irqsave(&usb_io_lock, flags); + usb_enable_clock(true); + DBG(0, "[MUSB]:access %s function when usb clock is off 0x%X\n", __func__, offset); + rc = readl(addr + offset); + usb_enable_clock(false); + spin_unlock_irqrestore(&usb_io_lock, flags); + } + return rc; +} + + +static inline void musb_writew(void __iomem *addr, unsigned offset, u16 data) +{ + if (mtk_usb_power) { + writew(data, addr + offset); + } else { + unsigned long flags = 0; + spin_lock_irqsave(&usb_io_lock, flags); + usb_enable_clock(true); + DBG(0, "[MUSB]:access %s function when usb clock is off 0x%X\n", __func__, offset); + writew(data, addr + offset); + usb_enable_clock(false); + spin_unlock_irqrestore(&usb_io_lock, flags); + } +} + +static inline void musb_writel(void __iomem *addr, unsigned offset, u32 data) +{ + if (mtk_usb_power) { + writel(data, addr + offset); + } else { + unsigned long flags = 0; + spin_lock_irqsave(&usb_io_lock, flags); + usb_enable_clock(true); + DBG(0, "[MUSB]:access %s function when usb clock is off 0x%X\n", __func__, offset); + writel(data, addr + offset); + usb_enable_clock(false); + spin_unlock_irqrestore(&usb_io_lock, flags); + } +} + +static inline u8 musb_readb(const void __iomem *addr, unsigned offset) +{ + u8 rc = 0; + + if (mtk_usb_power) { + rc = readb(addr + offset); + } else { + unsigned long flags = 0; + spin_lock_irqsave(&usb_io_lock, flags); + usb_enable_clock(true); + DBG(0, "[MUSB]:access %s function when usb clock is off 0x%X\n", __func__, offset); + rc = readb(addr + offset); + usb_enable_clock(false); + spin_unlock_irqrestore(&usb_io_lock, flags); + } + return rc; +} + +static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data) +{ + if (mtk_usb_power) { + writeb(data, addr + offset); + } else { + unsigned long flags = 0; + spin_lock_irqsave(&usb_io_lock, flags); + usb_enable_clock(true); + DBG(0, "[MUSB]:access %s function when usb clock is off 0x%X\n", __func__, offset); + writeb(data, addr + offset); + usb_enable_clock(false); + spin_unlock_irqrestore(&usb_io_lock, flags); + } +} + +#if 0 +struct musb_reg { + u8(*_readb) (u32 addr, u32 offset); + u16(*_readw) (u32 addr, u32 offset); + u32(*_readl) (u32 addr, u32 offset); + void (*_writeb) (u32 addr, u32 offset, u8 data); + void (*_writew) (u32 addr, u32 offset, u16 data); + void (*_writel) (u32 addr, u32 offset, u32 data); +}; +/* NOTE: these offsets are all in bytes */ + +static inline u16 power_on_readw(const void __iomem *addr, unsigned offset) +{ + return __raw_readw(addr + offset); +} + +static inline u32 power_on_readl(const void __iomem *addr, unsigned offset) +{ + return __raw_readl(addr + offset); +} + + +static inline void power_on_writew(void __iomem *addr, unsigned offset, u16 data) +{ + __raw_writew(data, addr + offset); +} + +static inline void power_on_writel(void __iomem *addr, unsigned offset, u32 data) +{ + __raw_writel(data, addr + offset); +} + +static inline u8 power_on_readb(const void __iomem *addr, unsigned offset) +{ + return __raw_readb(addr + offset); +} + +static inline void power_on_writeb(void __iomem *addr, unsigned offset, u8 data) +{ + __raw_writeb(data, addr + offset); +} + + +static inline u16 power_off_readw(const void __iomem *addr, unsigned offset) +{ + printk("MUSB:access %s function when usb clock is off\n", __func__); + return 0; +} + +static inline u32 power_off_readl(const void __iomem *addr, unsigned offset) +{ + printk("MUSB:access %s function when usb clock is off\n", __func__); + return 0; +} + + +static inline void power_off_writew(void __iomem *addr, unsigned offset, u16 data) +{ + printk("MUSB:access %s function when usb clock is off\n", __func__); +} + +static inline void power_off_writel(void __iomem *addr, unsigned offset, u32 data) +{ + printk("MUSB:access %s function when usb clock is off\n", __func__); +} + +static inline u8 power_off_readb(const void __iomem *addr, unsigned offset) +{ + printk("MUSB:access %s function when usb clock is off\n", __func__); + return 0; +} + +static inline void power_off_writeb(void __iomem *addr, unsigned offset, u8 data) +{ + printk("MUSB:access %s function when usb clock is off\n", __func__); +} + +extern struct musb_reg musb_reg; +#define musb_readb musb_reg._readb +#define musb_readw musb_reg._readl +#define musb_readl musb_reg._readw +#define musb_writeb musb_reg._writeb +#define musb_writew musb_reg._writew +#define musb_writel musb_reg._writel +#endif + +#endif diff --git a/include/linux/musb/musb_qmu.h b/include/linux/musb/musb_qmu.h new file mode 100644 index 000000000..3364244fa --- /dev/null +++ b/include/linux/musb/musb_qmu.h @@ -0,0 +1,21 @@ +#ifndef _MUSB_QMU_H_ +#define _MUSB_QMU_H_ + +#ifdef MUSB_QMU_SUPPORT +#include "musb_core.h" /* for struct musb */ + +extern int musb_qmu_init(struct musb *musb); +extern void musb_qmu_exit(struct musb *musb); +extern void musb_kick_D_CmdQ(struct musb *musb, struct musb_request *request); +extern void musb_disable_q_all(struct musb *musb); +extern irqreturn_t musb_q_irq(struct musb *musb); +extern void musb_flush_qmu(u32 ep_num, u8 isRx); +extern void musb_restart_qmu(struct musb *musb, u32 ep_num, u8 isRx); +extern bool musb_is_qmu_stop(u32 ep_num, u8 isRx); +extern void musb_tx_zlp_qmu(struct musb *musb, u32 ep_num); + +/*FIXME, not good layer present */ +extern void mtk_qmu_enable(struct musb *musb, u8 EP_Num, u8 isRx); + +#endif +#endif diff --git a/include/linux/musb/musbhsdma.h b/include/linux/musb/musbhsdma.h new file mode 100644 index 000000000..200deb70f --- /dev/null +++ b/include/linux/musb/musbhsdma.h @@ -0,0 +1,97 @@ +/* + * MUSB OTG driver - support for Mentor's DMA controller + * + * Copyright 2005 Mentor Graphics Corporation + * Copyright (C) 2005-2007 by Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * 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 AUTHORS 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. + * + */ + +#define MUSB_HSDMA_BASE 0x200 +#define MUSB_HSDMA_INTR (MUSB_HSDMA_BASE + 0) +#define MUSB_HSDMA_CONTROL 0x4 +#define MUSB_HSDMA_ADDRESS 0x8 +#define MUSB_HSDMA_COUNT 0xc + +#define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset) \ + (MUSB_HSDMA_BASE + (_bchannel << 4) + _offset) + +#define musb_read_hsdma_addr(mbase, bchannel) \ + musb_readl(mbase, \ + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS)) + +#define musb_write_hsdma_addr(mbase, bchannel, addr) \ + musb_writel(mbase, \ + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), \ + addr) + +#define musb_read_hsdma_count(mbase, bchannel) \ + musb_readl(mbase, \ + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT)) + +#define musb_write_hsdma_count(mbase, bchannel, len) \ + musb_writel(mbase, \ + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), \ + len) +/* control register (16-bit): */ +#define MUSB_HSDMA_ENABLE_SHIFT 0 +#define MUSB_HSDMA_TRANSMIT_SHIFT 1 +#define MUSB_HSDMA_MODE1_SHIFT 2 +#define MUSB_HSDMA_IRQENABLE_SHIFT 3 +#define MUSB_HSDMA_ENDPOINT_SHIFT 4 +#define MUSB_HSDMA_BUSERROR_SHIFT 8 +#define MUSB_HSDMA_BURSTMODE_SHIFT 9 +#define MUSB_HSDMA_BURSTMODE (3 << MUSB_HSDMA_BURSTMODE_SHIFT) +#define MUSB_HSDMA_BURSTMODE_UNSPEC 0 +#define MUSB_HSDMA_BURSTMODE_INCR4 1 +#define MUSB_HSDMA_BURSTMODE_INCR8 2 +#define MUSB_HSDMA_BURSTMODE_INCR16 3 + +#define MUSB_HSDMA_CHANNELS 8 + +struct musb_dma_controller; + +struct musb_dma_channel { + struct dma_channel channel; + struct musb_dma_controller *controller; + u32 start_addr; + u32 len; + u16 max_packet_sz; + u8 idx; + u8 epnum; + u8 transmit; +}; + +struct musb_dma_controller { + struct dma_controller controller; + struct musb_dma_channel channel[MUSB_HSDMA_CHANNELS]; + void *private_data; + void __iomem *base; + u8 channel_count; + u8 used_channels; + u8 irq; +}; |
