diff options
| author | Kuo-Jung Su <dantesu@faraday-tech.com> | 2013-05-15 15:29:23 +0800 | 
|---|---|---|
| committer | Marek Vasut <marex@denx.de> | 2013-06-12 22:22:51 +0200 | 
| commit | e82a316d7f9425943d86c1ed61c5cf57b0d5b188 (patch) | |
| tree | f32a19b18dde2c92c54c86018f88689057e9f6fb | |
| parent | aa1550588cc60549bf3a97dc6dccb7de4c022aa6 (diff) | |
| download | olio-uboot-2014.01-e82a316d7f9425943d86c1ed61c5cf57b0d5b188.tar.xz olio-uboot-2014.01-e82a316d7f9425943d86c1ed61c5cf57b0d5b188.zip | |
usb: ehci: add Faraday USB 2.0 EHCI support
This patch adds support to both Faraday FUSBH200 and FOTG210,
the differences between Faraday EHCI and standard EHCI are
listed bellow:
1. The PORTSC starts at 0x30 instead of 0x44.
2. The CONFIGFLAG(0x40) is not only un-implemented, and
   also has its address space removed.
3. Faraday EHCI is a TDI design, but it doesn't
   compatible with the general TDI implementation
   found at both U-Boot and Linux.
4. The ISOC descriptors differ from standard EHCI in
   several ways. But since U-boot doesn't support ISOC,
   we don't have to worry about that.
Signed-off-by: Kuo-Jung Su <dantesu@faraday-tech.com>
CC: Marek Vasut <marex@denx.de>
| -rw-r--r-- | common/usb_hub.c | 7 | ||||
| -rw-r--r-- | drivers/usb/host/Makefile | 1 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-faraday.c | 148 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-hcd.c | 5 | ||||
| -rw-r--r-- | include/usb/fotg210.h | 364 | ||||
| -rw-r--r-- | include/usb/fusbh200.h | 61 | 
6 files changed, 585 insertions, 1 deletions
| diff --git a/common/usb_hub.c b/common/usb_hub.c index fc3a8c177..774ba6387 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -489,7 +489,11 @@ static int usb_hub_configure(struct usb_device *dev)  			      i + 1, portstatus);  			usb_clear_port_feature(dev, i + 1,  						USB_PORT_FEAT_C_ENABLE); - +			/* +			 * The following hack causes a ghost device problem +			 * to Faraday EHCI +			 */ +#ifndef CONFIG_USB_EHCI_FARADAY  			/* EM interference sometimes causes bad shielded USB  			 * devices to be shutdown by the hub, this hack enables  			 * them again. Works at least with mouse driver */ @@ -501,6 +505,7 @@ static int usb_hub_configure(struct usb_device *dev)  				      "re-enabling...\n", i + 1);  				      usb_hub_port_connect_change(dev, i);  			} +#endif  		}  		if (portstatus & USB_PORT_STAT_SUSPEND) {  			debug("port %d suspend change\n", i + 1); diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 87a59704d..98f2a104b 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -43,6 +43,7 @@ COBJS-$(CONFIG_USB_EHCI_FSL) += ehci-mpc512x.o  else  COBJS-$(CONFIG_USB_EHCI_FSL) += ehci-fsl.o  endif +COBJS-$(CONFIG_USB_EHCI_FARADAY) += ehci-faraday.o  COBJS-$(CONFIG_USB_EHCI_EXYNOS) += ehci-exynos.o  COBJS-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o  COBJS-$(CONFIG_USB_EHCI_MXS) += ehci-mxs.o diff --git a/drivers/usb/host/ehci-faraday.c b/drivers/usb/host/ehci-faraday.c new file mode 100644 index 000000000..86add36ce --- /dev/null +++ b/drivers/usb/host/ehci-faraday.c @@ -0,0 +1,148 @@ +/* + * Faraday USB 2.0 EHCI Controller + * + * (C) Copyright 2010 Faraday Technology + * Dante Su <dantesu@faraday-tech.com> + * + * This file is released under the terms of GPL v2 and any later version. + * See the file COPYING in the root directory of the source tree for details. + */ + +#include <common.h> +#include <asm/io.h> +#include <usb.h> +#include <usb/fusbh200.h> +#include <usb/fotg210.h> + +#include "ehci.h" + +#ifndef CONFIG_USB_EHCI_BASE_LIST +#define CONFIG_USB_EHCI_BASE_LIST	{ CONFIG_USB_EHCI_BASE } +#endif + +union ehci_faraday_regs { +	struct fusbh200_regs usb; +	struct fotg210_regs  otg; +}; + +static inline int ehci_is_fotg2xx(union ehci_faraday_regs *regs) +{ +	return !readl(®s->usb.easstr); +} + +/* + * Create the appropriate control structures to manage + * a new EHCI host controller. + */ +int ehci_hcd_init(int index, struct ehci_hccr **ret_hccr, +		struct ehci_hcor **ret_hcor) +{ +	struct ehci_hccr *hccr; +	struct ehci_hcor *hcor; +	union ehci_faraday_regs *regs; +	uint32_t base_list[] = CONFIG_USB_EHCI_BASE_LIST; + +	if (index < 0 || index >= ARRAY_SIZE(base_list)) +		return -1; +	regs = (void __iomem *)base_list[index]; +	hccr = (struct ehci_hccr *)®s->usb.hccr; +	hcor = (struct ehci_hcor *)®s->usb.hcor; + +	if (ehci_is_fotg2xx(regs)) { +		/* A-device bus reset */ +		/* ... Power off A-device */ +		setbits_le32(®s->otg.otgcsr, OTGCSR_A_BUSDROP); +		/* ... Drop vbus and bus traffic */ +		clrbits_le32(®s->otg.otgcsr, OTGCSR_A_BUSREQ); +		mdelay(1); +		/* ... Power on A-device */ +		clrbits_le32(®s->otg.otgcsr, OTGCSR_A_BUSDROP); +		/* ... Drive vbus and bus traffic */ +		setbits_le32(®s->otg.otgcsr, OTGCSR_A_BUSREQ); +		mdelay(1); +		/* Disable OTG & DEV interrupts, triggered at level-high */ +		writel(IMR_IRQLH | IMR_OTG | IMR_DEV, ®s->otg.imr); +		/* Clear all interrupt status */ +		writel(ISR_HOST | ISR_OTG | ISR_DEV, ®s->otg.isr); +	} else { +		/* Interrupt=level-high */ +		setbits_le32(®s->usb.bmcsr, BMCSR_IRQLH); +		/* VBUS on */ +		clrbits_le32(®s->usb.bmcsr, BMCSR_VBUS_OFF); +		/* Disable all interrupts */ +		writel(0x00, ®s->usb.bmier); +		writel(0x1f, ®s->usb.bmisr); +	} + +	*ret_hccr = hccr; +	*ret_hcor = hcor; + +	return 0; +} + +/* + * Destroy the appropriate control structures corresponding + * the the EHCI host controller. + */ +int ehci_hcd_stop(int index) +{ +	return 0; +} + +/* + * This ehci_set_usbmode() overrides the weak function + * in "ehci-hcd.c". + */ +void ehci_set_usbmode(int index) +{ +	/* nothing needs to be done */ +} + +/* + * This ehci_get_port_speed() overrides the weak function + * in "ehci-hcd.c". + */ +int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) +{ +	int spd, ret = PORTSC_PSPD_HS; +	union ehci_faraday_regs *regs = (void __iomem *)((ulong)hcor - 0x10); + +	if (ehci_is_fotg2xx(regs)) +		spd = OTGCSR_SPD(readl(®s->otg.otgcsr)); +	else +		spd = BMCSR_SPD(readl(®s->usb.bmcsr)); + +	switch (spd) { +	case 0:    /* full speed */ +		ret = PORTSC_PSPD_FS; +		break; +	case 1:    /* low  speed */ +		ret = PORTSC_PSPD_LS; +		break; +	case 2:    /* high speed */ +		ret = PORTSC_PSPD_HS; +		break; +	default: +		printf("ehci-faraday: invalid device speed\n"); +		break; +	} + +	return ret; +} + +/* + * This ehci_get_portsc_register() overrides the weak function + * in "ehci-hcd.c". + */ +uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port) +{ +	/* Faraday EHCI has one and only one portsc register */ +	if (port) { +		/* Printing the message would cause a scan failure! */ +		debug("The request port(%d) is not configured\n", port); +		return NULL; +	} + +	/* Faraday EHCI PORTSC register offset is 0x20 from hcor */ +	return (uint32_t *)((uint8_t *)hcor + 0x20); +} diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 7e8e85c2b..28b600790 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -589,10 +589,12 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,  		dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(token);  	} else {  		dev->act_len = 0; +#ifndef CONFIG_USB_EHCI_FARADAY  		debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n",  		      dev->devnum, ehci_readl(&ctrl->hcor->or_usbsts),  		      ehci_readl(&ctrl->hcor->or_portsc[0]),  		      ehci_readl(&ctrl->hcor->or_portsc[1])); +#endif  	}  	free(qtd); @@ -980,10 +982,13 @@ int usb_lowlevel_init(int index, void **controller)  	cmd |= CMD_RUN;  	ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd); +#ifndef CONFIG_USB_EHCI_FARADAY  	/* take control over the ports */  	cmd = ehci_readl(&ehcic[index].hcor->or_configflag);  	cmd |= FLAG_CF;  	ehci_writel(&ehcic[index].hcor->or_configflag, cmd); +#endif +  	/* unblock posted write */  	cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd);  	mdelay(5); diff --git a/include/usb/fotg210.h b/include/usb/fotg210.h new file mode 100644 index 000000000..2d2d2431b --- /dev/null +++ b/include/usb/fotg210.h @@ -0,0 +1,364 @@ +/* + * Faraday USB 2.0 OTG Controller + * + * (C) Copyright 2010 Faraday Technology + * Dante Su <dantesu@faraday-tech.com> + * + * This file is released under the terms of GPL v2 and any later version. + * See the file COPYING in the root directory of the source tree for details. + */ + +#ifndef _FOTG210_H +#define _FOTG210_H + +struct fotg210_regs { +	/* USB Host Controller */ +	struct { +		uint32_t data[4]; +	} hccr;			/* 0x00 - 0x0f: hccr */ +	struct { +		uint32_t data[9]; +	} hcor;			/* 0x10 - 0x33: hcor */ +	uint32_t rsvd1[3]; +	uint32_t miscr;	/* 0x40: Miscellaneous Register */ +	uint32_t rsvd2[15]; +	/* USB OTG Controller */ +	uint32_t otgcsr;/* 0x80: OTG Control Status Register */ +	uint32_t otgisr;/* 0x84: OTG Interrupt Status Register */ +	uint32_t otgier;/* 0x88: OTG Interrupt Enable Register */ +	uint32_t rsvd3[13]; +	uint32_t isr;	/* 0xC0: Global Interrupt Status Register */ +	uint32_t imr;	/* 0xC4: Global Interrupt Mask Register */ +	uint32_t rsvd4[14]; +	/* USB Device Controller */ +	uint32_t dev_ctrl;/* 0x100: Device Control Register */ +	uint32_t dev_addr;/* 0x104: Device Address Register */ +	uint32_t dev_test;/* 0x108: Device Test Register */ +	uint32_t sof_fnr; /* 0x10c: SOF Frame Number Register */ +	uint32_t sof_mtr; /* 0x110: SOF Mask Timer Register */ +	uint32_t phy_tmsr;/* 0x114: PHY Test Mode Selector Register */ +	uint32_t rsvd5[2]; +	uint32_t cxfifo;/* 0x120: CX FIFO Register */ +	uint32_t idle;	/* 0x124: IDLE Counter Register */ +	uint32_t rsvd6[2]; +	uint32_t gimr;	/* 0x130: Group Interrupt Mask Register */ +	uint32_t gimr0; /* 0x134: Group Interrupt Mask Register 0 */ +	uint32_t gimr1; /* 0x138: Group Interrupt Mask Register 1 */ +	uint32_t gimr2; /* 0x13c: Group Interrupt Mask Register 2 */ +	uint32_t gisr;	/* 0x140: Group Interrupt Status Register */ +	uint32_t gisr0; /* 0x144: Group Interrupt Status Register 0 */ +	uint32_t gisr1; /* 0x148: Group Interrupt Status Register 1 */ +	uint32_t gisr2; /* 0x14c: Group Interrupt Status Register 2 */ +	uint32_t rxzlp; /* 0x150: Receive Zero-Length-Packet Register */ +	uint32_t txzlp; /* 0x154: Transfer Zero-Length-Packet Register */ +	uint32_t isoeasr;/* 0x158: ISOC Error/Abort Status Register */ +	uint32_t rsvd7[1]; +	uint32_t iep[8]; /* 0x160 - 0x17f: IN Endpoint Register */ +	uint32_t oep[8]; /* 0x180 - 0x19f: OUT Endpoint Register */ +	uint32_t epmap14;/* 0x1a0: Endpoint Map Register (EP1 ~ 4) */ +	uint32_t epmap58;/* 0x1a4: Endpoint Map Register (EP5 ~ 8) */ +	uint32_t fifomap;/* 0x1a8: FIFO Map Register */ +	uint32_t fifocfg; /* 0x1ac: FIFO Configuration Register */ +	uint32_t fifocsr[4];/* 0x1b0 - 0x1bf: FIFO Control Status Register */ +	uint32_t dma_fifo; /* 0x1c0: DMA Target FIFO Register */ +	uint32_t rsvd8[1]; +	uint32_t dma_ctrl; /* 0x1c8: DMA Control Register */ +	uint32_t dma_addr; /* 0x1cc: DMA Address Register */ +	uint32_t ep0_data; /* 0x1d0: EP0 Setup Packet PIO Register */ +}; + +/* Miscellaneous Register */ +#define MISCR_SUSPEND  (1 << 6) /* Put transceiver in suspend mode */ +#define MISCR_EOF2(x)  (((x) & 0x3) << 4) /* EOF 2 Timing */ +#define MISCR_EOF1(x)  (((x) & 0x3) << 2) /* EOF 1 Timing */ +#define MISCR_ASST(x)  (((x) & 0x3) << 0) /* Async. Sched. Sleep Timer */ + +/* OTG Control Status Register */ +#define OTGCSR_SPD_HIGH     (2 << 22) /* Speed of the attached device (host) */ +#define OTGCSR_SPD_LOW      (1 << 22) +#define OTGCSR_SPD_FULL     (0 << 22) +#define OTGCSR_SPD_MASK     (3 << 22) +#define OTGCSR_SPD_SHIFT    22 +#define OTGCSR_SPD(x)       (((x) >> 22) & 0x03) +#define OTGCSR_DEV_A        (0 << 21) /* Acts as A-device */ +#define OTGCSR_DEV_B        (1 << 21) /* Acts as B-device */ +#define OTGCSR_ROLE_H       (0 << 20) /* Acts as Host */ +#define OTGCSR_ROLE_D       (1 << 20) /* Acts as Device */ +#define OTGCSR_A_VBUS_VLD   (1 << 19) /* A-device VBUS Valid */ +#define OTGCSR_A_SESS_VLD   (1 << 18) /* A-device Session Valid */ +#define OTGCSR_B_SESS_VLD   (1 << 17) /* B-device Session Valid */ +#define OTGCSR_B_SESS_END   (1 << 16) /* B-device Session End */ +#define OTGCSR_HFT_LONG     (1 << 11) /* HDISCON noise filter = 270 us*/ +#define OTGCSR_HFT          (0 << 11) /* HDISCON noise filter = 135 us*/ +#define OTGCSR_VFT_LONG     (1 << 10) /* VBUS noise filter = 472 us*/ +#define OTGCSR_VFT          (0 << 10) /* VBUS noise filter = 135 us*/ +#define OTGCSR_IDFT_LONG    (1 << 9)  /* ID noise filter = 4 ms*/ +#define OTGCSR_IDFT         (0 << 9)  /* ID noise filter = 3 ms*/ +#define OTGCSR_A_SRPR_VBUS  (0 << 8)  /* A-device: SRP responds to VBUS */ +#define OTGCSR_A_SRPR_DATA  (1 << 8)  /* A-device: SRP responds to DATA-LINE */ +#define OTGCSR_A_SRP_EN     (1 << 7)  /* A-device SRP detection enabled */ +#define OTGCSR_A_HNP        (1 << 6)  /* Set role=A-device with HNP enabled */ +#define OTGCSR_A_BUSDROP    (1 << 5)  /* A-device drop bus (power-down) */ +#define OTGCSR_A_BUSREQ     (1 << 4)  /* A-device request bus */ +#define OTGCSR_B_VBUS_DISC  (1 << 2)  /* B-device discharges VBUS */ +#define OTGCSR_B_HNP        (1 << 1)  /* B-device enable HNP */ +#define OTGCSR_B_BUSREQ     (1 << 0)  /* B-device request bus */ + +/* OTG Interrupt Status Register */ +#define OTGISR_APRM         (1 << 12) /* Mini-A plug removed */ +#define OTGISR_BPRM         (1 << 11) /* Mini-B plug removed */ +#define OTGISR_OVD          (1 << 10) /* over-current detected */ +#define OTGISR_IDCHG        (1 << 9)  /* ID(A/B) changed */ +#define OTGISR_RLCHG        (1 << 8)  /* Role(Host/Device) changed */ +#define OTGISR_BSESSEND     (1 << 6)  /* B-device Session End */ +#define OTGISR_AVBUSERR     (1 << 5)  /* A-device VBUS Error */ +#define OTGISR_ASRP         (1 << 4)  /* A-device SRP detected */ +#define OTGISR_BSRP         (1 << 0)  /* B-device SRP complete */ + +/* OTG Interrupt Enable Register */ +#define OTGIER_APRM         (1 << 12) /* Mini-A plug removed */ +#define OTGIER_BPRM         (1 << 11) /* Mini-B plug removed */ +#define OTGIER_OVD          (1 << 10) /* over-current detected */ +#define OTGIER_IDCHG        (1 << 9)  /* ID(A/B) changed */ +#define OTGIER_RLCHG        (1 << 8)  /* Role(Host/Device) changed */ +#define OTGIER_BSESSEND     (1 << 6)  /* B-device Session End */ +#define OTGIER_AVBUSERR     (1 << 5)  /* A-device VBUS Error */ +#define OTGIER_ASRP         (1 << 4)  /* A-device SRP detected */ +#define OTGIER_BSRP         (1 << 0)  /* B-device SRP complete */ + +/* Global Interrupt Status Register (W1C) */ +#define ISR_HOST            (1 << 2)  /* USB Host interrupt */ +#define ISR_OTG             (1 << 1)  /* USB OTG interrupt */ +#define ISR_DEV             (1 << 0)  /* USB Device interrupt */ +#define ISR_MASK            0x07 + +/* Global Interrupt Mask Register */ +#define IMR_IRQLH           (1 << 3)  /* Interrupt triggered at level-high */ +#define IMR_IRQLL           (0 << 3)  /* Interrupt triggered at level-low */ +#define IMR_HOST            (1 << 2)  /* USB Host interrupt */ +#define IMR_OTG             (1 << 1)  /* USB OTG interrupt */ +#define IMR_DEV             (1 << 0)  /* USB Device interrupt */ +#define IMR_MASK            0x0f + +/* Device Control Register */ +#define DEVCTRL_FS_FORCED   (1 << 9)  /* Forced to be Full-Speed Mode */ +#define DEVCTRL_HS          (1 << 6)  /* High Speed Mode */ +#define DEVCTRL_FS          (0 << 6)  /* Full Speed Mode */ +#define DEVCTRL_EN          (1 << 5)  /* Chip Enable */ +#define DEVCTRL_RESET       (1 << 4)  /* Chip Software Reset */ +#define DEVCTRL_SUSPEND     (1 << 3)  /* Enter Suspend Mode */ +#define DEVCTRL_GIRQ_EN     (1 << 2)  /* Global Interrupt Enabled */ +#define DEVCTRL_HALFSPD     (1 << 1)  /* Half speed mode for FPGA test */ +#define DEVCTRL_RWAKEUP     (1 << 0)  /* Enable remote wake-up */ + +/* Device Address Register */ +#define DEVADDR_CONF        (1 << 7)  /* SET_CONFIGURATION has been executed */ +#define DEVADDR_ADDR(x)     ((x) & 0x7f) +#define DEVADDR_ADDR_MASK   0x7f + +/* Device Test Register */ +#define DEVTEST_NOSOF       (1 << 6)  /* Do not generate SOF */ +#define DEVTEST_TST_MODE    (1 << 5)  /* Enter Test Mode */ +#define DEVTEST_TST_NOTS    (1 << 4)  /* Do not toggle sequence */ +#define DEVTEST_TST_NOCRC   (1 << 3)  /* Do not append CRC */ +#define DEVTEST_TST_CLREA   (1 << 2)  /* Clear External Side Address */ +#define DEVTEST_TST_CXLP    (1 << 1)  /* EP0 loopback test */ +#define DEVTEST_TST_CLRFF   (1 << 0)  /* Clear FIFO */ + +/* SOF Frame Number Register */ +#define SOFFNR_UFN(x)       (((x) >> 11) & 0x7) /* SOF Micro-Frame Number */ +#define SOFFNR_FNR(x)       ((x) & 0x7ff) /* SOF Frame Number */ + +/* SOF Mask Timer Register */ +#define SOFMTR_TMR(x)       ((x) & 0xffff) + +/* PHY Test Mode Selector Register */ +#define PHYTMSR_TST_PKT     (1 << 4) /* Packet send test */ +#define PHYTMSR_TST_SE0NAK  (1 << 3) /* High-Speed quiescent state */ +#define PHYTMSR_TST_KSTA    (1 << 2) /* High-Speed K state */ +#define PHYTMSR_TST_JSTA    (1 << 1) /* High-Speed J state */ +#define PHYTMSR_UNPLUG      (1 << 0) /* Enable soft-detachment */ + +/* CX FIFO Register */ +#define CXFIFO_BYTES(x)     (((x) >> 24) & 0x7f) /* CX/EP0 FIFO byte count */ +#define CXFIFO_FIFOE(x)     (1 << (((x) & 0x03) + 8)) /* EPx FIFO empty */ +#define CXFIFO_FIFOE_FIFO0  (1 << 8) +#define CXFIFO_FIFOE_FIFO1  (1 << 9) +#define CXFIFO_FIFOE_FIFO2  (1 << 10) +#define CXFIFO_FIFOE_FIFO3  (1 << 11) +#define CXFIFO_FIFOE_MASK   (0x0f << 8) +#define CXFIFO_CXFIFOE      (1 << 5) /* CX FIFO empty */ +#define CXFIFO_CXFIFOF      (1 << 4) /* CX FIFO full */ +#define CXFIFO_CXFIFOCLR    (1 << 3) /* CX FIFO clear */ +#define CXFIFO_CXSTALL      (1 << 2) /* CX Stall */ +#define CXFIFO_TSTPKTFIN    (1 << 1) /* Test packet data transfer finished */ +#define CXFIFO_CXFIN        (1 << 0) /* CX data transfer finished */ + +/* IDLE Counter Register */ +#define IDLE_MS(x)          ((x) & 0x07) /* PHY suspend delay = x ms */ + +/* Group Interrupt Mask(Disable) Register */ +#define GIMR_GRP2           (1 << 2) /* Disable interrupt group 2 */ +#define GIMR_GRP1           (1 << 1) /* Disable interrupt group 1 */ +#define GIMR_GRP0           (1 << 0) /* Disable interrupt group 0 */ +#define GIMR_MASK           0x07 + +/* Group Interrupt Mask(Disable) Register 0 (CX) */ +#define GIMR0_CXABORT       (1 << 5) /* CX command abort interrupt */ +#define GIMR0_CXERR         (1 << 4) /* CX command error interrupt */ +#define GIMR0_CXEND         (1 << 3) /* CX command end interrupt */ +#define GIMR0_CXOUT         (1 << 2) /* EP0-OUT packet interrupt */ +#define GIMR0_CXIN          (1 << 1) /* EP0-IN packet interrupt */ +#define GIMR0_CXSETUP       (1 << 0) /* EP0-SETUP packet interrupt */ +#define GIMR0_MASK          0x3f + +/* Group Interrupt Mask(Disable) Register 1 (FIFO) */ +#define GIMR1_FIFO_IN(x)    (1 << (((x) & 3) + 16))    /* FIFOx IN */ +#define GIMR1_FIFO_TX(x)    GIMR1_FIFO_IN(x) +#define GIMR1_FIFO_OUT(x)   (1 << (((x) & 3) * 2))     /* FIFOx OUT */ +#define GIMR1_FIFO_SPK(x)   (1 << (((x) & 3) * 2 + 1)) /* FIFOx SHORT PACKET */ +#define GIMR1_FIFO_RX(x)    (GIMR1_FIFO_OUT(x) | GIMR1_FIFO_SPK(x)) +#define GIMR1_MASK          0xf00ff + +/* Group Interrupt Mask(Disable) Register 2 (Device) */ +#define GIMR2_WAKEUP        (1 << 10) /* Device waked up */ +#define GIMR2_IDLE          (1 << 9)  /* Device idle */ +#define GIMR2_DMAERR        (1 << 8)  /* DMA error */ +#define GIMR2_DMAFIN        (1 << 7)  /* DMA finished */ +#define GIMR2_ZLPRX         (1 << 6)  /* Zero-Length-Packet Rx Interrupt */ +#define GIMR2_ZLPTX         (1 << 5)  /* Zero-Length-Packet Tx Interrupt */ +#define GIMR2_ISOCABT       (1 << 4)  /* ISOC Abort Interrupt */ +#define GIMR2_ISOCERR       (1 << 3)  /* ISOC Error Interrupt */ +#define GIMR2_RESUME        (1 << 2)  /* Resume state change Interrupt */ +#define GIMR2_SUSPEND       (1 << 1)  /* Suspend state change Interrupt */ +#define GIMR2_RESET         (1 << 0)  /* Reset Interrupt */ +#define GIMR2_MASK          0x7ff + +/* Group Interrupt Status Register */ +#define GISR_GRP2           (1 << 2) /* Interrupt group 2 */ +#define GISR_GRP1           (1 << 1) /* Interrupt group 1 */ +#define GISR_GRP0           (1 << 0) /* Interrupt group 0 */ + +/* Group Interrupt Status Register 0 (CX) */ +#define GISR0_CXABORT       (1 << 5) /* CX command abort interrupt */ +#define GISR0_CXERR         (1 << 4) /* CX command error interrupt */ +#define GISR0_CXEND         (1 << 3) /* CX command end interrupt */ +#define GISR0_CXOUT         (1 << 2) /* EP0-OUT packet interrupt */ +#define GISR0_CXIN          (1 << 1) /* EP0-IN packet interrupt */ +#define GISR0_CXSETUP       (1 << 0) /* EP0-SETUP packet interrupt */ + +/* Group Interrupt Status Register 1 (FIFO) */ +#define GISR1_IN_FIFO(x)    (1 << (((x) & 0x03) + 16))    /* FIFOx IN */ +#define GISR1_OUT_FIFO(x)   (1 << (((x) & 0x03) * 2))     /* FIFOx OUT */ +#define GISR1_SPK_FIFO(x)   (1 << (((x) & 0x03) * 2 + 1)) /* FIFOx SPK */ +#define GISR1_RX_FIFO(x)    (3 << (((x) & 0x03) * 2))     /* FIFOx OUT/SPK */ + +/* Group Interrupt Status Register 2 (Device) */ +#define GISR2_WAKEUP        (1 << 10) /* Device waked up */ +#define GISR2_IDLE          (1 << 9)  /* Device idle */ +#define GISR2_DMAERR        (1 << 8)  /* DMA error */ +#define GISR2_DMAFIN        (1 << 7)  /* DMA finished */ +#define GISR2_ZLPRX         (1 << 6)  /* Zero-Length-Packet Rx Interrupt */ +#define GISR2_ZLPTX         (1 << 5)  /* Zero-Length-Packet Tx Interrupt */ +#define GISR2_ISOCABT       (1 << 4)  /* ISOC Abort Interrupt */ +#define GISR2_ISOCERR       (1 << 3)  /* ISOC Error Interrupt */ +#define GISR2_RESUME        (1 << 2)  /* Resume state change Interrupt */ +#define GISR2_SUSPEND       (1 << 1)  /* Suspend state change Interrupt */ +#define GISR2_RESET         (1 << 0)  /* Reset Interrupt */ + +/* Receive Zero-Length-Packet Register */ +#define RXZLP_EP(x)         (1 << ((x) - 1)) /* EPx ZLP rx interrupt */ + +/* Transfer Zero-Length-Packet Register */ +#define TXZLP_EP(x)         (1 << ((x) - 1)) /* EPx ZLP tx interrupt */ + +/* ISOC Error/Abort Status Register */ +#define ISOEASR_EP(x)       (0x10001 << ((x) - 1)) /* EPx ISOC Error/Abort */ + +/* IN Endpoint Register */ +#define IEP_SENDZLP         (1 << 15)     /* Send Zero-Length-Packet */ +#define IEP_TNRHB(x)        (((x) & 0x03) << 13) \ +	/* Transaction Number for High-Bandwidth EP(ISOC) */ +#define IEP_RESET           (1 << 12)     /* Reset Toggle Sequence */ +#define IEP_STALL           (1 << 11)     /* Stall */ +#define IEP_MAXPS(x)        ((x) & 0x7ff) /* Max. packet size */ + +/* OUT Endpoint Register */ +#define OEP_RESET           (1 << 12)     /* Reset Toggle Sequence */ +#define OEP_STALL           (1 << 11)     /* Stall */ +#define OEP_MAXPS(x)        ((x) & 0x7ff) /* Max. packet size */ + +/* Endpoint Map Register (EP1 ~ EP4) */ +#define EPMAP14_SET_IN(ep, fifo) \ +	((fifo) & 3) << (((ep) - 1) << 3 + 0) +#define EPMAP14_SET_OUT(ep, fifo) \ +	((fifo) & 3) << (((ep) - 1) << 3 + 4) +#define EPMAP14_SET(ep, in, out) \ +	do { \ +		EPMAP14_SET_IN(ep, in); \ +		EPMAP14_SET_OUT(ep, out); \ +	} while (0) + +#define EPMAP14_DEFAULT     0x33221100 /* EP1->FIFO0, EP2->FIFO1... */ + +/* Endpoint Map Register (EP5 ~ EP8) */ +#define EPMAP58_SET_IN(ep, fifo) \ +	((fifo) & 3) << (((ep) - 5) << 3 + 0) +#define EPMAP58_SET_OUT(ep, fifo) \ +	((fifo) & 3) << (((ep) - 5) << 3 + 4) +#define EPMAP58_SET(ep, in, out) \ +	do { \ +		EPMAP58_SET_IN(ep, in); \ +		EPMAP58_SET_OUT(ep, out); \ +	} while (0) + +#define EPMAP58_DEFAULT     0x00000000 /* All EPx->FIFO0 */ + +/* FIFO Map Register */ +#define FIFOMAP_BIDIR       (2 << 4) +#define FIFOMAP_IN          (1 << 4) +#define FIFOMAP_OUT         (0 << 4) +#define FIFOMAP_DIR_MASK    0x30 +#define FIFOMAP_EP(x)       ((x) & 0x0f) +#define FIFOMAP_EP_MASK     0x0f +#define FIFOMAP_CFG_MASK    0x3f +#define FIFOMAP_DEFAULT     0x04030201 /* FIFO0->EP1, FIFO1->EP2... */ +#define FIFOMAP(fifo, cfg)  (((cfg) & 0x3f) << (((fifo) & 3) << 3)) + +/* FIFO Configuration Register */ +#define FIFOCFG_EN          (1 << 5) +#define FIFOCFG_BLKSZ_1024  (1 << 4) +#define FIFOCFG_BLKSZ_512   (0 << 4) +#define FIFOCFG_3BLK        (2 << 2) +#define FIFOCFG_2BLK        (1 << 2) +#define FIFOCFG_1BLK        (0 << 2) +#define FIFOCFG_NBLK_MASK   3 +#define FIFOCFG_NBLK_SHIFT  2 +#define FIFOCFG_INTR        (3 << 0) +#define FIFOCFG_BULK        (2 << 0) +#define FIFOCFG_ISOC        (1 << 0) +#define FIFOCFG_RSVD        (0 << 0)  /* Reserved */ +#define FIFOCFG_TYPE_MASK   3 +#define FIFOCFG_TYPE_SHIFT  0 +#define FIFOCFG_CFG_MASK    0x3f +#define FIFOCFG(fifo, cfg)  (((cfg) & 0x3f) << (((fifo) & 3) << 3)) + +/* FIFO Control Status Register */ +#define FIFOCSR_RESET       (1 << 12) /* FIFO Reset */ +#define FIFOCSR_BYTES(x)    ((x) & 0x7ff) /* Length(bytes) for OUT-EP/FIFO */ + +/* DMA Target FIFO Register */ +#define DMAFIFO_CX          (1 << 4) /* DMA FIFO = CX FIFO */ +#define DMAFIFO_FIFO(x)     (1 << ((x) & 0x3)) /* DMA FIFO = FIFOx */ + +/* DMA Control Register */ +#define DMACTRL_LEN(x)      (((x) & 0x1ffff) << 8) /* DMA length (Bytes) */ +#define DMACTRL_LEN_SHIFT   8 +#define DMACTRL_CLRFF       (1 << 4) /* Clear FIFO upon DMA abort */ +#define DMACTRL_ABORT       (1 << 3) /* DMA abort */ +#define DMACTRL_IO2IO       (1 << 2) /* IO to IO */ +#define DMACTRL_FIFO2MEM    (0 << 1) /* FIFO to Memory */ +#define DMACTRL_MEM2FIFO    (1 << 1) /* Memory to FIFO */ +#define DMACTRL_START       (1 << 0) /* DMA start */ + +#endif diff --git a/include/usb/fusbh200.h b/include/usb/fusbh200.h new file mode 100644 index 000000000..8a9c488cb --- /dev/null +++ b/include/usb/fusbh200.h @@ -0,0 +1,61 @@ +/* + * Faraday USB 2.0 EHCI Controller + * + * (C) Copyright 2010 Faraday Technology + * Dante Su <dantesu@faraday-tech.com> + * + * This file is released under the terms of GPL v2 and any later version. + * See the file COPYING in the root directory of the source tree for details. + */ + +#ifndef _FUSBH200_H +#define _FUSBH200_H + +struct fusbh200_regs { +	struct { +		uint32_t data[4]; +	} hccr;			/* 0x00 - 0x0f: hccr */ +	struct { +		uint32_t data[9]; +	} hcor;			/* 0x10 - 0x33: hcor */ +	uint32_t easstr;/* 0x34: EOF&Async. Sched. Sleep Timer Register */ +	uint32_t rsvd[2]; +	uint32_t bmcsr;	/* 0x40: Bus Monitor Control Status Register */ +	uint32_t bmisr;	/* 0x44: Bus Monitor Interrupt Status Register */ +	uint32_t bmier; /* 0x48: Bus Monitor Interrupt Enable Register */ +}; + +/* EOF & Async. Schedule Sleep Timer Register */ +#define EASSTR_RUNNING  (1 << 6) /* Put transceiver in running/resume mode */ +#define EASSTR_SUSPEND  (0 << 6) /* Put transceiver in suspend mode */ +#define EASSTR_EOF2(x)  (((x) & 0x3) << 4) /* EOF 2 Timing */ +#define EASSTR_EOF1(x)  (((x) & 0x3) << 2) /* EOF 1 Timing */ +#define EASSTR_ASST(x)  (((x) & 0x3) << 0) /* Async. Sched. Sleep Timer */ + +/* Bus Monitor Control Status Register */ +#define BMCSR_SPD_HIGH  (2 << 9) /* Speed of the attached device */ +#define BMCSR_SPD_LOW   (1 << 9) +#define BMCSR_SPD_FULL  (0 << 9) +#define BMCSR_SPD_MASK  (3 << 9) +#define BMCSR_SPD_SHIFT 9 +#define BMCSR_SPD(x)    ((x >> 9) & 0x03) +#define BMCSR_VBUS      (1 << 8) /* VBUS Valid */ +#define BMCSR_VBUS_OFF  (1 << 4) /* VBUS Off */ +#define BMCSR_VBUS_ON   (0 << 4) /* VBUS On */ +#define BMCSR_IRQLH     (1 << 3) /* IRQ triggered at level-high */ +#define BMCSR_IRQLL     (0 << 3) /* IRQ triggered at level-low */ +#define BMCSR_HALFSPD   (1 << 2) /* Half speed mode for FPGA test */ +#define BMCSR_HFT_LONG  (1 << 1) /* HDISCON noise filter = 270 us*/ +#define BMCSR_HFT       (0 << 1) /* HDISCON noise filter = 135 us*/ +#define BMCSR_VFT_LONG  (1 << 1) /* VBUS noise filter = 472 us*/ +#define BMCSR_VFT       (0 << 1) /* VBUS noise filter = 135 us*/ + +/* Bus Monitor Interrupt Status Register */ +/* Bus Monitor Interrupt Enable Register */ +#define BMISR_DMAERR    (1 << 4) /* DMA error */ +#define BMISR_DMA       (1 << 3) /* DMA complete */ +#define BMISR_DEVRM     (1 << 2) /* device removed */ +#define BMISR_OVD       (1 << 1) /* over-current detected */ +#define BMISR_VBUSERR   (1 << 0) /* VBUS error */ + +#endif |