aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/isp1760-hcd.c
diff options
context:
space:
mode:
authorNate Case <ncase@xes-inc.com>2008-06-17 12:11:38 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-07-21 18:16:33 -0400
commit3faefc88c1a32b0b4a00b9089fab5d917996b16c (patch)
tree705994b76bea1968e3ae7d4149bd77139374220c /drivers/usb/host/isp1760-hcd.c
parent6d243e5c76b632a94d54cac2fe7fe8c0b41cd482 (diff)
USB: isp1760: Support board-specific hardware configurations
This adds support for hardware configurations that don't match the chip default register settings (e.g., 16-bit data bus, DACK and DREQ pulled up instead of down, analog overcurrent mode). These settings are passed in via the OF device tree. The PCI interface still assumes the same default values. Signed-off-by: Nate Case <ncase@xes-inc.com> Acked-by: Olof Johansson <olof@lixom.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/isp1760-hcd.c')
-rw-r--r--drivers/usb/host/isp1760-hcd.c67
1 files changed, 53 insertions, 14 deletions
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
index d318af39c27f..c858f2adb929 100644
--- a/drivers/usb/host/isp1760-hcd.c
+++ b/drivers/usb/host/isp1760-hcd.c
@@ -38,6 +38,7 @@ struct isp1760_hcd {
38 unsigned i_thresh; 38 unsigned i_thresh;
39 unsigned long reset_done; 39 unsigned long reset_done;
40 unsigned long next_statechange; 40 unsigned long next_statechange;
41 unsigned int devflags;
41}; 42};
42 43
43static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd) 44static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd)
@@ -378,9 +379,31 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
378{ 379{
379 struct isp1760_hcd *priv = hcd_to_priv(hcd); 380 struct isp1760_hcd *priv = hcd_to_priv(hcd);
380 int result; 381 int result;
381 u32 scratch; 382 u32 scratch, hwmode;
383
384 /* Setup HW Mode Control: This assumes a level active-low interrupt */
385 hwmode = HW_DATA_BUS_32BIT;
386
387 if (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16)
388 hwmode &= ~HW_DATA_BUS_32BIT;
389 if (priv->devflags & ISP1760_FLAG_ANALOG_OC)
390 hwmode |= HW_ANA_DIGI_OC;
391 if (priv->devflags & ISP1760_FLAG_DACK_POL_HIGH)
392 hwmode |= HW_DACK_POL_HIGH;
393 if (priv->devflags & ISP1760_FLAG_DREQ_POL_HIGH)
394 hwmode |= HW_DREQ_POL_HIGH;
395
396 /*
397 * We have to set this first in case we're in 16-bit mode.
398 * Write it twice to ensure correct upper bits if switching
399 * to 16-bit mode.
400 */
401 isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
402 isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
382 403
383 isp1760_writel(0xdeadbabe, hcd->regs + HC_SCRATCH_REG); 404 isp1760_writel(0xdeadbabe, hcd->regs + HC_SCRATCH_REG);
405 /* Change bus pattern */
406 scratch = isp1760_readl(hcd->regs + HC_CHIP_ID_REG);
384 scratch = isp1760_readl(hcd->regs + HC_SCRATCH_REG); 407 scratch = isp1760_readl(hcd->regs + HC_SCRATCH_REG);
385 if (scratch != 0xdeadbabe) { 408 if (scratch != 0xdeadbabe) {
386 printk(KERN_ERR "ISP1760: Scratch test failed.\n"); 409 printk(KERN_ERR "ISP1760: Scratch test failed.\n");
@@ -403,17 +426,29 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
403 426
404 /* Step 11 passed */ 427 /* Step 11 passed */
405 428
406 isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_REG); 429 isp1760_info(priv, "bus width: %d, oc: %s\n",
407 isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_ENABLE); 430 (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16) ?
431 16 : 32, (priv->devflags & ISP1760_FLAG_ANALOG_OC) ?
432 "analog" : "digital");
408 433
409 /* ATL reset */ 434 /* ATL reset */
410 scratch = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL); 435 isp1760_writel(hwmode | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL);
411 isp1760_writel(scratch | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL);
412 mdelay(10); 436 mdelay(10);
413 isp1760_writel(scratch, hcd->regs + HC_HW_MODE_CTRL); 437 isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
414 438
415 isp1760_writel(PORT1_POWER | PORT1_INIT2, hcd->regs + HC_PORT1_CTRL); 439 isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_REG);
416 mdelay(10); 440 isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_ENABLE);
441
442 /*
443 * PORT 1 Control register of the ISP1760 is the OTG control
444 * register on ISP1761.
445 */
446 if (!(priv->devflags & ISP1760_FLAG_ISP1761) &&
447 !(priv->devflags & ISP1760_FLAG_PORT1_DIS)) {
448 isp1760_writel(PORT1_POWER | PORT1_INIT2,
449 hcd->regs + HC_PORT1_CTRL);
450 mdelay(10);
451 }
417 452
418 priv->hcs_params = isp1760_readl(hcd->regs + HC_HCSPARAMS); 453 priv->hcs_params = isp1760_readl(hcd->regs + HC_HCSPARAMS);
419 454
@@ -453,8 +488,7 @@ static int isp1760_run(struct usb_hcd *hcd)
453 hcd->state = HC_STATE_RUNNING; 488 hcd->state = HC_STATE_RUNNING;
454 isp1760_enable_interrupts(hcd); 489 isp1760_enable_interrupts(hcd);
455 temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL); 490 temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
456 temp |= FINAL_HW_CONFIG; 491 isp1760_writel(temp | HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
457 isp1760_writel(temp, hcd->regs + HC_HW_MODE_CTRL);
458 492
459 command = isp1760_readl(hcd->regs + HC_USBCMD); 493 command = isp1760_readl(hcd->regs + HC_USBCMD);
460 command &= ~(CMD_LRESET|CMD_RESET); 494 command &= ~(CMD_LRESET|CMD_RESET);
@@ -2112,6 +2146,7 @@ static int isp1760_get_frame(struct usb_hcd *hcd)
2112static void isp1760_stop(struct usb_hcd *hcd) 2146static void isp1760_stop(struct usb_hcd *hcd)
2113{ 2147{
2114 struct isp1760_hcd *priv = hcd_to_priv(hcd); 2148 struct isp1760_hcd *priv = hcd_to_priv(hcd);
2149 u32 temp;
2115 2150
2116 isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, 1, 2151 isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, 1,
2117 NULL, 0); 2152 NULL, 0);
@@ -2120,7 +2155,8 @@ static void isp1760_stop(struct usb_hcd *hcd)
2120 spin_lock_irq(&priv->lock); 2155 spin_lock_irq(&priv->lock);
2121 ehci_reset(priv); 2156 ehci_reset(priv);
2122 /* Disable IRQ */ 2157 /* Disable IRQ */
2123 isp1760_writel(HW_DATA_BUS_32BIT, hcd->regs + HC_HW_MODE_CTRL); 2158 temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
2159 isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
2124 spin_unlock_irq(&priv->lock); 2160 spin_unlock_irq(&priv->lock);
2125 2161
2126 isp1760_writel(0, hcd->regs + HC_CONFIGFLAG); 2162 isp1760_writel(0, hcd->regs + HC_CONFIGFLAG);
@@ -2128,10 +2164,11 @@ static void isp1760_stop(struct usb_hcd *hcd)
2128 2164
2129static void isp1760_shutdown(struct usb_hcd *hcd) 2165static void isp1760_shutdown(struct usb_hcd *hcd)
2130{ 2166{
2131 u32 command; 2167 u32 command, temp;
2132 2168
2133 isp1760_stop(hcd); 2169 isp1760_stop(hcd);
2134 isp1760_writel(HW_DATA_BUS_32BIT, hcd->regs + HC_HW_MODE_CTRL); 2170 temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
2171 isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
2135 2172
2136 command = isp1760_readl(hcd->regs + HC_USBCMD); 2173 command = isp1760_readl(hcd->regs + HC_USBCMD);
2137 command &= ~CMD_RUN; 2174 command &= ~CMD_RUN;
@@ -2183,7 +2220,8 @@ void deinit_kmem_cache(void)
2183} 2220}
2184 2221
2185struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, 2222struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
2186 u64 irqflags, struct device *dev, const char *busname) 2223 u64 irqflags, struct device *dev, const char *busname,
2224 unsigned int devflags)
2187{ 2225{
2188 struct usb_hcd *hcd; 2226 struct usb_hcd *hcd;
2189 struct isp1760_hcd *priv; 2227 struct isp1760_hcd *priv;
@@ -2200,6 +2238,7 @@ struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
2200 return ERR_PTR(-ENOMEM); 2238 return ERR_PTR(-ENOMEM);
2201 2239
2202 priv = hcd_to_priv(hcd); 2240 priv = hcd_to_priv(hcd);
2241 priv->devflags = devflags;
2203 init_memory(priv); 2242 init_memory(priv);
2204 hcd->regs = ioremap(res_start, res_len); 2243 hcd->regs = ioremap(res_start, res_len);
2205 if (!hcd->regs) { 2244 if (!hcd->regs) {