From fe3702054f6412aea04373ceb9d27a4a417ff3f0 Mon Sep 17 00:00:00 2001 From: Juha Yrjola Date: Sun, 18 Jun 2006 20:36:06 +0300 Subject: [PATCH] OMAP: Fix USB on Nokia 770 Also removed unused ochi_omap_host_enable() function. Signed-off-by: Juha Yrjola --- drivers/cbus/tahvo-usb.c | 130 ++++++++++++++++++++++++++--------- drivers/usb/host/ohci-omap.c | 45 ++---------- 2 files changed, 101 insertions(+), 74 deletions(-) diff --git a/drivers/cbus/tahvo-usb.c b/drivers/cbus/tahvo-usb.c index aef8481f35c..371b4980ac7 100644 --- a/drivers/cbus/tahvo-usb.c +++ b/drivers/cbus/tahvo-usb.c @@ -3,7 +3,11 @@ * * Tahvo USB transeiver * - * Copyright (C) 2005 Nokia Corporation + * Copyright (C) 2005-2006 Nokia Corporation + * + * Parts copied from drivers/i2c/chips/isp1301_omap.c + * Copyright (C) 2004 Texas Instruments + * Copyright (C) 2004 David Brownell * * Written by Juha Yrjölä , * Tony Lindgren , and @@ -85,8 +89,6 @@ #define TAHVO_MODE(tu) TAHVO_MODE_HOST #endif -extern int ohci_omap_host_enable(struct usb_bus *host, int enable); - struct tahvo_usb { struct platform_device *pt_dev; struct otg_transceiver otg; @@ -130,14 +132,12 @@ static irqreturn_t omap_otg_irq(int irq, void *arg, struct pt_regs *regs) } else if (otg_irq & A_VBUS_ERR) { OTG_IRQ_SRC_REG = A_VBUS_ERR; } else if (otg_irq & DRIVER_SWITCH) { - if ((!(OTG_CTRL_REG & OTG_DRIVER_SEL)) && tu->otg.host && tu->otg.state == OTG_STATE_A_HOST) { /* role is host */ usb_bus_start_enum(tu->otg.host, tu->otg.host->otg_port); } - OTG_IRQ_SRC_REG = DRIVER_SWITCH; } else return IRQ_NONE; @@ -155,7 +155,6 @@ static int omap_otg_init(void) return -ENODEV; } #endif - /* some of these values are board-specific... */ OTG_SYSCON_2_REG |= OTG_EN /* for B-device: */ @@ -223,6 +222,47 @@ static DEVICE_ATTR(vbus_state, 0444, vbus_state_show, NULL); int vbus_active = 0; +#if 0 + +static int host_suspend(struct tahvo_usb *tu) +{ + struct device *dev; + + if (!tu->otg.host) + return -ENODEV; + + /* Currently ASSUMES only the OTG port matters; + * other ports could be active... + */ + dev = tu->otg.host->controller; + return dev->driver->suspend(dev, PMSG_SUSPEND); +} + +static int host_resume(struct tahvo_usb *tu) +{ + struct device *dev; + + if (!tu->otg.host) + return -ENODEV; + + dev = tu->otg.host->controller; + return dev->driver->resume(dev); +} + +#else + +static int host_suspend(struct tahvo_usb *tu) +{ + return 0; +} + +static int host_resume(struct tahvo_usb *tu) +{ + return 0; +} + +#endif + static void check_vbus_state(struct tahvo_usb *tu) { int reg, prev_state; @@ -244,32 +284,27 @@ static void check_vbus_state(struct tahvo_usb *tu) case OTG_STATE_A_IDLE: /* Session is now valid assuming the USB hub is driving Vbus */ tu->otg.state = OTG_STATE_A_HOST; - if (tu->otg.host) - ohci_omap_host_enable(tu->otg.host, 1); + host_resume(tu); break; default: break; } printk("USB cable connected\n"); } else { - vbus_active = 0; switch (tu->otg.state) { case OTG_STATE_B_PERIPHERAL: - OTG_CTRL_REG = (OTG_CTRL_REG & ~OTG_BSESSVLD) | OTG_BSESSEND; if (tu->otg.gadget) usb_gadget_vbus_disconnect(tu->otg.gadget); tu->otg.state = OTG_STATE_B_IDLE; break; case OTG_STATE_A_HOST: tu->otg.state = OTG_STATE_A_IDLE; - if (tu->otg.host) - ohci_omap_host_enable(tu->otg.host, 0); - break; default: break; } printk("USB cable disconnected\n"); + vbus_active = 0; } prev_state = tu->vbus_state; @@ -280,11 +315,16 @@ static void check_vbus_state(struct tahvo_usb *tu) static void tahvo_usb_become_host(struct tahvo_usb *tu) { + u32 l; + /* Clear system and transceiver controlled bits * also mark the A-session is always valid */ omap_otg_init(); - OTG_CTRL_REG = (OTG_CTRL_REG & ~(OTG_CTRL_XCVR_MASK|OTG_CTRL_SYS_MASK)) - | OTG_ASESSVLD; + + l = OTG_CTRL_REG; + l &= ~(OTG_CTRL_XCVR_MASK|OTG_CTRL_SYS_MASK); + l |= OTG_ASESSVLD; + OTG_CTRL_REG = l; /* Power up the transceiver in USB host mode */ tahvo_write_reg(TAHVO_REG_USBR, USBR_REGOUT | USBR_NSUSPEND | @@ -296,8 +336,7 @@ static void tahvo_usb_become_host(struct tahvo_usb *tu) static void tahvo_usb_stop_host(struct tahvo_usb *tu) { - if (tu->otg.host) - ohci_omap_host_enable(tu->otg.host, 0); + host_suspend(tu); tu->otg.state = OTG_STATE_A_IDLE; } @@ -307,7 +346,7 @@ static void tahvo_usb_become_peripheral(struct tahvo_usb *tu) * and enable ID to mark peripheral mode and * BSESSEND to mark no Vbus */ omap_otg_init(); - OTG_CTRL_REG = (OTG_CTRL_REG & ~(OTG_CTRL_XCVR_MASK|OTG_CTRL_SYS_MASK)) + OTG_CTRL_REG = (OTG_CTRL_REG & ~(OTG_CTRL_XCVR_MASK|OTG_CTRL_SYS_MASK|OTG_BSESSVLD)) | OTG_ID | OTG_BSESSEND; /* Power up transceiver and set it in USB perhiperal mode */ @@ -328,24 +367,29 @@ static void tahvo_usb_stop_peripheral(struct tahvo_usb *tu) static void tahvo_usb_power_off(struct tahvo_usb *tu) { + u32 l; int id; /* Disable gadget controller if any */ if (tu->otg.gadget) usb_gadget_vbus_disconnect(tu->otg.gadget); - if (tu->otg.host) - ohci_omap_host_enable(tu->otg.host, 0); + host_suspend(tu); /* Disable OTG and interrupts */ if (TAHVO_MODE(tu) == TAHVO_MODE_PERIPHERAL) id = OTG_ID; - else id = 0; - OTG_CTRL_REG = (OTG_CTRL_REG & ~(OTG_CTRL_XCVR_MASK|OTG_CTRL_SYS_MASK)) | id; + else + id = 0; + l = OTG_CTRL_REG; + l &= ~(OTG_CTRL_XCVR_MASK | OTG_CTRL_SYS_MASK | OTG_BSESSVLD); + l |= id | OTG_BSESSEND; + OTG_CTRL_REG = l; OTG_IRQ_EN_REG = 0; -#if 0 + OTG_SYSCON_2_REG &= ~OTG_EN; -#endif + + OTG_SYSCON_1_REG |= OTG_IDLE_EN; /* Power off transceiver */ tahvo_write_reg(TAHVO_REG_USBR, 0); @@ -355,6 +399,10 @@ static void tahvo_usb_power_off(struct tahvo_usb *tu) static int tahvo_usb_set_power(struct otg_transceiver *dev, unsigned mA) { + struct tahvo_usb *tu = container_of(dev, struct tahvo_usb, otg); + + dev_dbg(&tu->pt_dev->dev, "set_power %d mA\n", mA); + if (dev->state == OTG_STATE_B_PERIPHERAL) { /* REVISIT: Can Tahvo charge battery from VBUS? */ } @@ -363,8 +411,11 @@ static int tahvo_usb_set_power(struct otg_transceiver *dev, unsigned mA) static int tahvo_usb_set_suspend(struct otg_transceiver *dev, int suspend) { + struct tahvo_usb *tu = container_of(dev, struct tahvo_usb, otg); u16 w; + dev_dbg(&tu->pt_dev->dev, "set_suspend\n"); + w = tahvo_read_reg(TAHVO_REG_USBR); if (suspend) w &= ~USBR_NSUSPEND; @@ -380,6 +431,8 @@ static int tahvo_usb_start_srp(struct otg_transceiver *dev) struct tahvo_usb *tu = container_of(dev, struct tahvo_usb, otg); u32 otg_ctrl; + dev_dbg(&tu->pt_dev->dev, "start_srp\n"); + if (!dev || tu->otg.state != OTG_STATE_B_IDLE) return -ENODEV; @@ -392,13 +445,14 @@ static int tahvo_usb_start_srp(struct otg_transceiver *dev) OTG_CTRL_REG = otg_ctrl; tu->otg.state = OTG_STATE_B_SRP_INIT; - pr_debug("otg: SRP, %s ... %06x\n", state_name(tu), OTG_CTRL_REG); - return 0; } -static int tahvo_usb_start_hnp(struct otg_transceiver *dev) +static int tahvo_usb_start_hnp(struct otg_transceiver *otg) { + struct tahvo_usb *tu = container_of(otg, struct tahvo_usb, otg); + + dev_dbg(&tu->pt_dev->dev, "start_hnp\n"); #ifdef CONFIG_USB_OTG /* REVISIT: Add this for OTG */ #endif @@ -409,26 +463,30 @@ static int tahvo_usb_set_host(struct otg_transceiver *otg, struct usb_bus *host) { struct tahvo_usb *tu = container_of(otg, struct tahvo_usb, otg); - if (!otg) + dev_dbg(&tu->pt_dev->dev, "set_host %p\n", host); + + if (otg == NULL) return -ENODEV; #if defined(CONFIG_USB_OTG) || !defined(CONFIG_USB_GADGET_OMAP) mutex_lock(&tu->serialize); - if (!host) { + if (host == NULL) { if (TAHVO_MODE(tu) == TAHVO_MODE_HOST) tahvo_usb_power_off(tu); - tu->otg.host = 0; + tu->otg.host = NULL; mutex_unlock(&tu->serialize); return 0; } + OTG_SYSCON_1_REG &= ~(OTG_IDLE_EN | HST_IDLE_EN | DEV_IDLE_EN); + if (TAHVO_MODE(tu) == TAHVO_MODE_HOST) { - tu->otg.host = 0; + tu->otg.host = NULL; tahvo_usb_become_host(tu); } else - ohci_omap_host_enable(host, 0); + host_suspend(tu); tu->otg.host = host; @@ -445,6 +503,8 @@ static int tahvo_usb_set_peripheral(struct otg_transceiver *otg, struct usb_gadg { struct tahvo_usb *tu = container_of(otg, struct tahvo_usb, otg); + dev_dbg(&tu->pt_dev->dev, "set_peripheral %p\n", gadget); + if (!otg) return -ENODEV; @@ -455,7 +515,7 @@ static int tahvo_usb_set_peripheral(struct otg_transceiver *otg, struct usb_gadg if (!gadget) { if (TAHVO_MODE(tu) == TAHVO_MODE_PERIPHERAL) tahvo_usb_power_off(tu); - tu->otg.gadget = 0; + tu->otg.gadget = NULL; mutex_unlock(&tu->serialize); return 0; } @@ -552,6 +612,8 @@ static int tahvo_usb_probe(struct device *dev) struct tahvo_usb *tu; int ret; + dev_dbg(dev, "probe\n"); + /* Create driver data */ tu = kmalloc(sizeof(*tu), GFP_KERNEL); if (!tu) @@ -618,6 +680,8 @@ static int tahvo_usb_probe(struct device *dev) static int tahvo_usb_remove(struct device *dev) { + dev_dbg(dev, "remove\n"); + tahvo_free_irq(TAHVO_INT_VBUSON); flush_scheduled_work(); otg_set_transceiver(0); diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 1401844bc48..b17f8f22ffa 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -257,6 +257,10 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev) } ohci_writel(ohci, rh, &ohci->regs->roothub.a); distrust_firmware = 0; + } else if (machine_is_nokia770()) { + /* We require a self-powered hub, which should have + * plenty of power. */ + ohci_to_hcd(ohci)->power_budget = 0; } /* FIXME khubd hub requests should manage power switching */ @@ -281,47 +285,6 @@ static void omap_stop_hc(struct platform_device *pdev) void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *); -/* configure so an HC device and id are always provided */ -/* always called with process context; sleeping is OK */ - - -int ohci_omap_host_enable(struct usb_bus *host, int enable) -{ - struct usb_hcd *hcd; - struct ohci_hcd *ohci; - int retval; - - if (host_enabled == enable) - return 0; - - host_enabled = enable; - - if (!host_initialized) - return 0; - - hcd = (struct usb_hcd *)host->hcpriv; - ohci = hcd_to_ohci(hcd); - if (enable) { - omap_ohci_clock_power(1); - if ((retval = ohci_init(ohci)) < 0) { - dev_err(hcd->self.controller, "init error %d\n", - retval); - return retval; - } - if ((retval = hcd->driver->start(hcd)) < 0) { - dev_err(hcd->self.controller, "startup error %d\n", - retval); - return retval; - } - } else { - usb_disconnect(&hcd->self.root_hub); - hcd->driver->stop(hcd); - omap_ohci_clock_power(0); - } - - return 0; -} - /** * usb_hcd_omap_probe - initialize OMAP-based HCDs * Context: !in_interrupt() -- 2.41.1