Beispiel #1
0
/* set/clear the stall and toggle bits for non-ep0 */
void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set)
{
	struct mtu3 *mtu = mep->mtu;
	void __iomem *mbase = mtu->mac_base;
	u8 epnum = mep->epnum;
	u32 csr;

	if (mep->is_in) {	/* TX */
		csr = mtu3_readl(mbase, MU3D_EP_TXCR0(epnum)) & TX_W1C_BITS;
		if (set)
			csr |= TX_SENDSTALL;
		else
			csr = (csr & (~TX_SENDSTALL)) | TX_SENTSTALL;
		mtu3_writel(mbase, MU3D_EP_TXCR0(epnum), csr);
	} else {	/* RX */
		csr = mtu3_readl(mbase, MU3D_EP_RXCR0(epnum)) & RX_W1C_BITS;
		if (set)
			csr |= RX_SENDSTALL;
		else
			csr = (csr & (~RX_SENDSTALL)) | RX_SENTSTALL;
		mtu3_writel(mbase, MU3D_EP_RXCR0(epnum), csr);
	}

	if (!set) {
		mtu3_ep_reset(mep);
		mep->flags &= ~MTU3_EP_STALL;
	} else {
		mep->flags |= MTU3_EP_STALL;
	}

	dev_dbg(mtu->dev, "%s: %s\n", mep->name,
		set ? "SEND STALL" : "CLEAR STALL, with EP RESET");
}
Beispiel #2
0
/* for non-ep0 */
int mtu3_config_ep(struct mtu3 *mtu, struct mtu3_ep *mep,
			int interval, int burst, int mult)
{
	void __iomem *mbase = mtu->mac_base;
	int epnum = mep->epnum;
	u32 csr0, csr1, csr2;
	int fifo_sgsz, fifo_addr;
	int num_pkts;

	fifo_addr = ep_fifo_alloc(mep, mep->maxp);
	if (fifo_addr < 0) {
		dev_err(mtu->dev, "alloc ep fifo failed(%d)\n", mep->maxp);
		return -ENOMEM;
	}
	fifo_sgsz = ilog2(mep->fifo_seg_size);
	dev_dbg(mtu->dev, "%s fifosz: %x(%x/%x)\n", __func__, fifo_sgsz,
		mep->fifo_seg_size, mep->fifo_size);

	if (mep->is_in) {
		csr0 = TX_TXMAXPKTSZ(mep->maxp);
		csr0 |= TX_DMAREQEN;

		num_pkts = (burst + 1) * (mult + 1) - 1;
		csr1 = TX_SS_BURST(burst) | TX_SLOT(mep->slot);
		csr1 |= TX_MAX_PKT(num_pkts) | TX_MULT(mult);

		csr2 = TX_FIFOADDR(fifo_addr >> 4);
		csr2 |= TX_FIFOSEGSIZE(fifo_sgsz);

		switch (mep->type) {
		case USB_ENDPOINT_XFER_BULK:
			csr1 |= TX_TYPE(TYPE_BULK);
			break;
		case USB_ENDPOINT_XFER_ISOC:
			csr1 |= TX_TYPE(TYPE_ISO);
			csr2 |= TX_BINTERVAL(interval);
			break;
		case USB_ENDPOINT_XFER_INT:
			csr1 |= TX_TYPE(TYPE_INT);
			csr2 |= TX_BINTERVAL(interval);
			break;
		}

		/* Enable QMU Done interrupt */
		mtu3_setbits(mbase, U3D_QIESR0, QMU_TX_DONE_INT(epnum));

		mtu3_writel(mbase, MU3D_EP_TXCR0(epnum), csr0);
		mtu3_writel(mbase, MU3D_EP_TXCR1(epnum), csr1);
		mtu3_writel(mbase, MU3D_EP_TXCR2(epnum), csr2);

		dev_dbg(mtu->dev, "U3D_TX%d CSR0:%#x, CSR1:%#x, CSR2:%#x\n",
			epnum, mtu3_readl(mbase, MU3D_EP_TXCR0(epnum)),
			mtu3_readl(mbase, MU3D_EP_TXCR1(epnum)),
			mtu3_readl(mbase, MU3D_EP_TXCR2(epnum)));
	} else {
Beispiel #3
0
/* only port0 supports dual-role mode */
static int ssusb_port0_switch(struct ssusb_mtk *ssusb,
	int version, bool tohost)
{
	void __iomem *ibase = ssusb->ippc_base;
	u32 value;

	dev_dbg(ssusb->dev, "%s (switch u%d port0 to %s)\n", __func__,
		version, tohost ? "host" : "device");

	if (version == USB2_PORT) {
		/* 1. power off and disable u2 port0 */
		value = mtu3_readl(ibase, SSUSB_U2_CTRL(0));
		value |= SSUSB_U2_PORT_PDN | SSUSB_U2_PORT_DIS;
		mtu3_writel(ibase, SSUSB_U2_CTRL(0), value);

		/* 2. power on, enable u2 port0 and select its mode */
		value = mtu3_readl(ibase, SSUSB_U2_CTRL(0));
		value &= ~(SSUSB_U2_PORT_PDN | SSUSB_U2_PORT_DIS);
		value = tohost ? (value | SSUSB_U2_PORT_HOST_SEL) :
			(value & (~SSUSB_U2_PORT_HOST_SEL));
		mtu3_writel(ibase, SSUSB_U2_CTRL(0), value);
	} else {
		/* 1. power off and disable u3 port0 */
		value = mtu3_readl(ibase, SSUSB_U3_CTRL(0));
		value |= SSUSB_U3_PORT_PDN | SSUSB_U3_PORT_DIS;
		mtu3_writel(ibase, SSUSB_U3_CTRL(0), value);

		/* 2. power on, enable u3 port0 and select its mode */
		value = mtu3_readl(ibase, SSUSB_U3_CTRL(0));
		value &= ~(SSUSB_U3_PORT_PDN | SSUSB_U3_PORT_DIS);
		value = tohost ? (value | SSUSB_U3_PORT_HOST_SEL) :
			(value & (~SSUSB_U3_PORT_HOST_SEL));
		mtu3_writel(ibase, SSUSB_U3_CTRL(0), value);
	}

	return 0;
}
Beispiel #4
0
void mtu3_start(struct mtu3 *mtu)
{
	void __iomem *mbase = mtu->mac_base;

	dev_dbg(mtu->dev, "%s devctl 0x%x\n", __func__,
		mtu3_readl(mbase, U3D_DEVICE_CONTROL));

	mtu3_clrbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN);

	/*
	 * When disable U2 port, USB2_CSR's register will be reset to
	 * default value after re-enable it again(HS is enabled by default).
	 * So if force mac to work as FS, disable HS function.
	 */
	if (mtu->max_speed == USB_SPEED_FULL)
		mtu3_clrbits(mbase, U3D_POWER_MANAGEMENT, HS_ENABLE);

	/* Initialize the default interrupts */
	mtu3_intr_enable(mtu);
	mtu->is_active = 1;

	if (mtu->softconnect)
		mtu3_dev_on_off(mtu, 1);
}