Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0316ca63 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Felipe Balbi
Browse files

usb: isp1760: Add device controller support



The ISP1761 is a dual-mode host and device controller backward
compatible on the host side with the ISP1760. Add support for the device
controller.

Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 9a66e132
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -109,6 +109,13 @@ config USB_GR_UDC
          Select this to support Aeroflex Gaisler GRUSBDC cores from the GRLIB
	  VHDL IP core library.

config USB_ISP1761_UDC
	boolean "NXP ISP1761 USB Device Controller"
	depends on USB_ISP1760_HCD
	help
	   The NXP ISP1761 is a dual-role high-speed USB host and device
	   controller.

config USB_OMAP
	tristate "OMAP USB Device Controller"
	depends on ARCH_OMAP1
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
CFLAGS_xhci-trace.o := -I$(src)

isp1760-y := isp1760-core.o isp1760-hcd.o isp1760-if.o
isp1760-$(CONFIG_USB_ISP1761_UDC) += isp1760-udc.o

fhci-y := fhci-hcd.o fhci-hub.o fhci-q.o
fhci-y += fhci-mem.o fhci-tds.o fhci-sched.o
+45 −5
Original line number Diff line number Diff line
@@ -24,9 +24,11 @@
#include "isp1760-core.h"
#include "isp1760-hcd.h"
#include "isp1760-regs.h"
#include "isp1760-udc.h"

static void isp1760_init_core(struct isp1760_device *isp)
{
	u32 otgctrl;
	u32 hwmode;

	/* Low-level chip reset */
@@ -59,6 +61,17 @@ static void isp1760_init_core(struct isp1760_device *isp)
	if (isp->devflags & ISP1760_FLAG_INTR_EDGE_TRIG)
		hwmode |= HW_INTR_EDGE_TRIG;

	/*
	 * The ISP1761 has a dedicated DC IRQ line but supports sharing the HC
	 * IRQ line for both the host and device controllers. Hardcode IRQ
	 * sharing for now and disable the DC interrupts globally to avoid
	 * spurious interrupts during HCD registration.
	 */
	if (isp->devflags & ISP1760_FLAG_ISP1761) {
		isp1760_write32(isp->regs, DC_MODE, 0);
		hwmode |= HW_COMN_IRQ;
	}

	/*
	 * We have to set this first in case we're in 16-bit mode.
	 * Write it twice to ensure correct upper bits if switching
@@ -68,18 +81,33 @@ static void isp1760_init_core(struct isp1760_device *isp)
	isp1760_write32(isp->regs, HC_HW_MODE_CTRL, hwmode);

	/*
	 * PORT 1 Control register of the ISP1760 is the OTG control register on
	 * ISP1761. Since there is no OTG or device controller support in this
	 * driver, we use port 1 as a "normal" USB host port on both chips.
	 * PORT 1 Control register of the ISP1760 is the OTG control register
	 * on ISP1761.
	 *
	 * TODO: Really support OTG. For now we configure port 1 in device mode
	 * when OTG is requested.
	 */
	isp1760_write32(isp->regs, HC_PORT1_CTRL, PORT1_POWER | PORT1_INIT2);
	usleep_range(10000, 11000);
	if ((isp->devflags & ISP1760_FLAG_ISP1761) &&
	    (isp->devflags & ISP1760_FLAG_OTG_EN))
		otgctrl = ((HW_DM_PULLDOWN | HW_DP_PULLDOWN) << 16)
			| HW_OTG_DISABLE;
	else
		otgctrl = (HW_SW_SEL_HC_DC << 16)
			| (HW_VBUS_DRV | HW_SEL_CP_EXT);

	isp1760_write32(isp->regs, HC_PORT1_CTRL, otgctrl);

	dev_info(isp->dev, "bus width: %u, oc: %s\n",
		 isp->devflags & ISP1760_FLAG_BUS_WIDTH_16 ? 16 : 32,
		 isp->devflags & ISP1760_FLAG_ANALOG_OC ? "analog" : "digital");
}

void isp1760_set_pullup(struct isp1760_device *isp, bool enable)
{
	isp1760_write32(isp->regs, HW_OTG_CTRL_SET,
			enable ? HW_DP_PULLUP : HW_DP_PULLUP << 16);
}

int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
		     struct device *dev, unsigned int devflags)
{
@@ -114,6 +142,15 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
	if (ret < 0)
		return ret;

	if (devflags & ISP1760_FLAG_ISP1761) {
		ret = isp1760_udc_register(isp, irq, irqflags | IRQF_SHARED |
					   IRQF_DISABLED);
		if (ret < 0) {
			isp1760_hcd_unregister(&isp->hcd);
			return ret;
		}
	}

	dev_set_drvdata(dev, isp);

	return 0;
@@ -123,6 +160,9 @@ void isp1760_unregister(struct device *dev)
{
	struct isp1760_device *isp = dev_get_drvdata(dev);

	if (isp->devflags & ISP1760_FLAG_ISP1761)
		isp1760_udc_unregister(isp);

	isp1760_hcd_unregister(&isp->hcd);
}

+4 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/ioport.h>

#include "isp1760-hcd.h"
#include "isp1760-udc.h"

struct device;
struct gpio_desc;
@@ -45,12 +46,15 @@ struct isp1760_device {
	struct gpio_desc *rst_gpio;

	struct isp1760_hcd hcd;
	struct isp1760_udc udc;
};

int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
		     struct device *dev, unsigned int devflags);
void isp1760_unregister(struct device *dev);

void isp1760_set_pullup(struct isp1760_device *isp, bool enable);

static inline u32 isp1760_read32(void __iomem *base, u32 reg)
{
	return readl(base + reg);
+110 −0
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@
#ifndef _ISP1760_REGS_H_
#define _ISP1760_REGS_H_

/* -----------------------------------------------------------------------------
 * Host Controller
 */

/* EHCI capability registers */
#define HC_CAPLENGTH		0x000
#define HC_LENGTH(p)		(((p) >> 00) & 0x00ff)	/* bits 7:0 */
@@ -70,6 +74,9 @@
#define HC_HW_MODE_CTRL		0x300
#define ALL_ATX_RESET		(1 << 31)
#define HW_ANA_DIGI_OC		(1 << 15)
#define HW_DEV_DMA		(1 << 11)
#define HW_COMN_IRQ		(1 << 10)
#define HW_COMN_DMA		(1 << 9)
#define HW_DATA_BUS_32BIT	(1 << 8)
#define HW_DACK_POL_HIGH	(1 << 6)
#define HW_DREQ_POL_HIGH	(1 << 5)
@@ -98,6 +105,17 @@
#define PORT1_INIT2		(1 << 23)
#define HW_OTG_CTRL_SET		0x374
#define HW_OTG_CTRL_CLR		0x376
#define HW_OTG_DISABLE		(1 << 10)
#define HW_OTG_SE0_EN		(1 << 9)
#define HW_BDIS_ACON_EN		(1 << 8)
#define HW_SW_SEL_HC_DC		(1 << 7)
#define HW_VBUS_CHRG		(1 << 6)
#define HW_VBUS_DISCHRG		(1 << 5)
#define HW_VBUS_DRV		(1 << 4)
#define HW_SEL_CP_EXT		(1 << 3)
#define HW_DM_PULLDOWN		(1 << 2)
#define HW_DP_PULLDOWN		(1 << 1)
#define HW_DP_PULLUP		(1 << 0)

/* Interrupt Register */
#define HC_INTERRUPT_REG	0x310
@@ -117,4 +135,96 @@
#define HC_INT_IRQ_MASK_AND_REG	0x328
#define HC_ATL_IRQ_MASK_AND_REG	0x32c

/* -----------------------------------------------------------------------------
 * Peripheral Controller
 */

/* Initialization Registers */
#define DC_ADDRESS			0x0200
#define DC_DEVEN			(1 << 7)

#define DC_MODE				0x020c
#define DC_DMACLKON			(1 << 9)
#define DC_VBUSSTAT			(1 << 8)
#define DC_CLKAON			(1 << 7)
#define DC_SNDRSU			(1 << 6)
#define DC_GOSUSP			(1 << 5)
#define DC_SFRESET			(1 << 4)
#define DC_GLINTENA			(1 << 3)
#define DC_WKUPCS			(1 << 2)

#define DC_INTCONF			0x0210
#define DC_CDBGMOD_ACK_NAK		(0 << 6)
#define DC_CDBGMOD_ACK			(1 << 6)
#define DC_CDBGMOD_ACK_1NAK		(2 << 6)
#define DC_DDBGMODIN_ACK_NAK		(0 << 4)
#define DC_DDBGMODIN_ACK		(1 << 4)
#define DC_DDBGMODIN_ACK_1NAK		(2 << 4)
#define DC_DDBGMODOUT_ACK_NYET_NAK	(0 << 2)
#define DC_DDBGMODOUT_ACK_NYET		(1 << 2)
#define DC_DDBGMODOUT_ACK_NYET_1NAK	(2 << 2)
#define DC_INTLVL			(1 << 1)
#define DC_INTPOL			(1 << 0)

#define DC_DEBUG			0x0212
#define DC_INTENABLE			0x0214
#define DC_IEPTX(n)			(1 << (11 + 2 * (n)))
#define DC_IEPRX(n)			(1 << (10 + 2 * (n)))
#define DC_IEPRXTX(n)			(3 << (10 + 2 * (n)))
#define DC_IEP0SETUP			(1 << 8)
#define DC_IEVBUS			(1 << 7)
#define DC_IEDMA			(1 << 6)
#define DC_IEHS_STA			(1 << 5)
#define DC_IERESM			(1 << 4)
#define DC_IESUSP			(1 << 3)
#define DC_IEPSOF			(1 << 2)
#define DC_IESOF			(1 << 1)
#define DC_IEBRST			(1 << 0)

/* Data Flow Registers */
#define DC_EPINDEX			0x022c
#define DC_EP0SETUP			(1 << 5)
#define DC_ENDPIDX(n)			((n) << 1)
#define DC_EPDIR			(1 << 0)

#define DC_CTRLFUNC			0x0228
#define DC_CLBUF			(1 << 4)
#define DC_VENDP			(1 << 3)
#define DC_DSEN				(1 << 2)
#define DC_STATUS			(1 << 1)
#define DC_STALL			(1 << 0)

#define DC_DATAPORT			0x0220
#define DC_BUFLEN			0x021c
#define DC_DATACOUNT_MASK		0xffff
#define DC_BUFSTAT			0x021e
#define DC_EPMAXPKTSZ			0x0204

#define DC_EPTYPE			0x0208
#define DC_NOEMPKT			(1 << 4)
#define DC_EPENABLE			(1 << 3)
#define DC_DBLBUF			(1 << 2)
#define DC_ENDPTYP_ISOC			(1 << 0)
#define DC_ENDPTYP_BULK			(2 << 0)
#define DC_ENDPTYP_INTERRUPT		(3 << 0)

/* DMA Registers */
#define DC_DMACMD			0x0230
#define DC_DMATXCOUNT			0x0234
#define DC_DMACONF			0x0238
#define DC_DMAHW			0x023c
#define DC_DMAINTREASON			0x0250
#define DC_DMAINTEN			0x0254
#define DC_DMAEP			0x0258
#define DC_DMABURSTCOUNT		0x0264

/* General Registers */
#define DC_INTERRUPT			0x0218
#define DC_CHIPID			0x0270
#define DC_FRAMENUM			0x0274
#define DC_SCRATCH			0x0278
#define DC_UNLOCKDEV			0x027c
#define DC_INTPULSEWIDTH		0x0280
#define DC_TESTMODE			0x0284

#endif
Loading