|
@@ -38,6 +38,7 @@ struct isp1760_hcd {
|
|
unsigned i_thresh;
|
|
unsigned i_thresh;
|
|
unsigned long reset_done;
|
|
unsigned long reset_done;
|
|
unsigned long next_statechange;
|
|
unsigned long next_statechange;
|
|
|
|
+ unsigned int devflags;
|
|
};
|
|
};
|
|
|
|
|
|
static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd)
|
|
static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd)
|
|
@@ -378,9 +379,31 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
|
|
{
|
|
{
|
|
struct isp1760_hcd *priv = hcd_to_priv(hcd);
|
|
struct isp1760_hcd *priv = hcd_to_priv(hcd);
|
|
int result;
|
|
int result;
|
|
- u32 scratch;
|
|
|
|
|
|
+ u32 scratch, hwmode;
|
|
|
|
+
|
|
|
|
+ /* Setup HW Mode Control: This assumes a level active-low interrupt */
|
|
|
|
+ hwmode = HW_DATA_BUS_32BIT;
|
|
|
|
+
|
|
|
|
+ if (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16)
|
|
|
|
+ hwmode &= ~HW_DATA_BUS_32BIT;
|
|
|
|
+ if (priv->devflags & ISP1760_FLAG_ANALOG_OC)
|
|
|
|
+ hwmode |= HW_ANA_DIGI_OC;
|
|
|
|
+ if (priv->devflags & ISP1760_FLAG_DACK_POL_HIGH)
|
|
|
|
+ hwmode |= HW_DACK_POL_HIGH;
|
|
|
|
+ if (priv->devflags & ISP1760_FLAG_DREQ_POL_HIGH)
|
|
|
|
+ hwmode |= HW_DREQ_POL_HIGH;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * We have to set this first in case we're in 16-bit mode.
|
|
|
|
+ * Write it twice to ensure correct upper bits if switching
|
|
|
|
+ * to 16-bit mode.
|
|
|
|
+ */
|
|
|
|
+ isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
|
|
|
|
+ isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
|
|
|
|
|
|
isp1760_writel(0xdeadbabe, hcd->regs + HC_SCRATCH_REG);
|
|
isp1760_writel(0xdeadbabe, hcd->regs + HC_SCRATCH_REG);
|
|
|
|
+ /* Change bus pattern */
|
|
|
|
+ scratch = isp1760_readl(hcd->regs + HC_CHIP_ID_REG);
|
|
scratch = isp1760_readl(hcd->regs + HC_SCRATCH_REG);
|
|
scratch = isp1760_readl(hcd->regs + HC_SCRATCH_REG);
|
|
if (scratch != 0xdeadbabe) {
|
|
if (scratch != 0xdeadbabe) {
|
|
printk(KERN_ERR "ISP1760: Scratch test failed.\n");
|
|
printk(KERN_ERR "ISP1760: Scratch test failed.\n");
|
|
@@ -403,17 +426,29 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
|
|
|
|
|
|
/* Step 11 passed */
|
|
/* Step 11 passed */
|
|
|
|
|
|
- isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_REG);
|
|
|
|
- isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_ENABLE);
|
|
|
|
|
|
+ isp1760_info(priv, "bus width: %d, oc: %s\n",
|
|
|
|
+ (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16) ?
|
|
|
|
+ 16 : 32, (priv->devflags & ISP1760_FLAG_ANALOG_OC) ?
|
|
|
|
+ "analog" : "digital");
|
|
|
|
|
|
/* ATL reset */
|
|
/* ATL reset */
|
|
- scratch = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
|
|
|
|
- isp1760_writel(scratch | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL);
|
|
|
|
|
|
+ isp1760_writel(hwmode | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL);
|
|
mdelay(10);
|
|
mdelay(10);
|
|
- isp1760_writel(scratch, hcd->regs + HC_HW_MODE_CTRL);
|
|
|
|
|
|
+ isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
|
|
|
|
|
|
- isp1760_writel(PORT1_POWER | PORT1_INIT2, hcd->regs + HC_PORT1_CTRL);
|
|
|
|
- mdelay(10);
|
|
|
|
|
|
+ isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_REG);
|
|
|
|
+ isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_ENABLE);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * PORT 1 Control register of the ISP1760 is the OTG control
|
|
|
|
+ * register on ISP1761.
|
|
|
|
+ */
|
|
|
|
+ if (!(priv->devflags & ISP1760_FLAG_ISP1761) &&
|
|
|
|
+ !(priv->devflags & ISP1760_FLAG_PORT1_DIS)) {
|
|
|
|
+ isp1760_writel(PORT1_POWER | PORT1_INIT2,
|
|
|
|
+ hcd->regs + HC_PORT1_CTRL);
|
|
|
|
+ mdelay(10);
|
|
|
|
+ }
|
|
|
|
|
|
priv->hcs_params = isp1760_readl(hcd->regs + HC_HCSPARAMS);
|
|
priv->hcs_params = isp1760_readl(hcd->regs + HC_HCSPARAMS);
|
|
|
|
|
|
@@ -453,8 +488,7 @@ static int isp1760_run(struct usb_hcd *hcd)
|
|
hcd->state = HC_STATE_RUNNING;
|
|
hcd->state = HC_STATE_RUNNING;
|
|
isp1760_enable_interrupts(hcd);
|
|
isp1760_enable_interrupts(hcd);
|
|
temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
|
|
temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
|
|
- temp |= FINAL_HW_CONFIG;
|
|
|
|
- isp1760_writel(temp, hcd->regs + HC_HW_MODE_CTRL);
|
|
|
|
|
|
+ isp1760_writel(temp | HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
|
|
|
|
|
|
command = isp1760_readl(hcd->regs + HC_USBCMD);
|
|
command = isp1760_readl(hcd->regs + HC_USBCMD);
|
|
command &= ~(CMD_LRESET|CMD_RESET);
|
|
command &= ~(CMD_LRESET|CMD_RESET);
|
|
@@ -2112,6 +2146,7 @@ static int isp1760_get_frame(struct usb_hcd *hcd)
|
|
static void isp1760_stop(struct usb_hcd *hcd)
|
|
static void isp1760_stop(struct usb_hcd *hcd)
|
|
{
|
|
{
|
|
struct isp1760_hcd *priv = hcd_to_priv(hcd);
|
|
struct isp1760_hcd *priv = hcd_to_priv(hcd);
|
|
|
|
+ u32 temp;
|
|
|
|
|
|
isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, 1,
|
|
isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, 1,
|
|
NULL, 0);
|
|
NULL, 0);
|
|
@@ -2120,7 +2155,8 @@ static void isp1760_stop(struct usb_hcd *hcd)
|
|
spin_lock_irq(&priv->lock);
|
|
spin_lock_irq(&priv->lock);
|
|
ehci_reset(priv);
|
|
ehci_reset(priv);
|
|
/* Disable IRQ */
|
|
/* Disable IRQ */
|
|
- isp1760_writel(HW_DATA_BUS_32BIT, hcd->regs + HC_HW_MODE_CTRL);
|
|
|
|
|
|
+ temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
|
|
|
|
+ isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
|
|
spin_unlock_irq(&priv->lock);
|
|
spin_unlock_irq(&priv->lock);
|
|
|
|
|
|
isp1760_writel(0, hcd->regs + HC_CONFIGFLAG);
|
|
isp1760_writel(0, hcd->regs + HC_CONFIGFLAG);
|
|
@@ -2128,10 +2164,11 @@ static void isp1760_stop(struct usb_hcd *hcd)
|
|
|
|
|
|
static void isp1760_shutdown(struct usb_hcd *hcd)
|
|
static void isp1760_shutdown(struct usb_hcd *hcd)
|
|
{
|
|
{
|
|
- u32 command;
|
|
|
|
|
|
+ u32 command, temp;
|
|
|
|
|
|
isp1760_stop(hcd);
|
|
isp1760_stop(hcd);
|
|
- isp1760_writel(HW_DATA_BUS_32BIT, hcd->regs + HC_HW_MODE_CTRL);
|
|
|
|
|
|
+ temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
|
|
|
|
+ isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
|
|
|
|
|
|
command = isp1760_readl(hcd->regs + HC_USBCMD);
|
|
command = isp1760_readl(hcd->regs + HC_USBCMD);
|
|
command &= ~CMD_RUN;
|
|
command &= ~CMD_RUN;
|
|
@@ -2183,7 +2220,8 @@ void deinit_kmem_cache(void)
|
|
}
|
|
}
|
|
|
|
|
|
struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
|
|
struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
|
|
- u64 irqflags, struct device *dev, const char *busname)
|
|
|
|
|
|
+ u64 irqflags, struct device *dev, const char *busname,
|
|
|
|
+ unsigned int devflags)
|
|
{
|
|
{
|
|
struct usb_hcd *hcd;
|
|
struct usb_hcd *hcd;
|
|
struct isp1760_hcd *priv;
|
|
struct isp1760_hcd *priv;
|
|
@@ -2200,6 +2238,7 @@ struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
|
|
return ERR_PTR(-ENOMEM);
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
priv = hcd_to_priv(hcd);
|
|
priv = hcd_to_priv(hcd);
|
|
|
|
+ priv->devflags = devflags;
|
|
init_memory(priv);
|
|
init_memory(priv);
|
|
hcd->regs = ioremap(res_start, res_len);
|
|
hcd->regs = ioremap(res_start, res_len);
|
|
if (!hcd->regs) {
|
|
if (!hcd->regs) {
|