]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
MUSB: PM cleanup
authorDavid Brownell <dbrownell@users.sourceforge.net>
Fri, 8 Sep 2006 07:48:43 +0000 (10:48 +0300)
committerTony Lindgren <tony@atomide.com>
Fri, 8 Sep 2006 07:48:43 +0000 (10:48 +0300)
Second pass over TUSB power related code:

  - Add new field in board-specific platform data, giving a nonzero floor to
    the amount of VBUS power that peripherals could draw; pass that to the
    platform code.

  - Implement the call letting gadget drivers say how much VBUS power their
    current configuration may draw, and use that to initialize appropriately
    (pure-peripheral vs OTG modes) on USB reset and disconnect.

  - Provide TUSB-specific hook into OTG transceiver logic to support that
    VBUS call; and _only_ change the VBUS usage through that call.

  - Remove obsolete comment and bitmask declarations.

On one board I measured 36 mA (at 5.1V) coming from VBUS not the battery
using the default gadget drivers in non-OTG TUSB configuration.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musbdefs.h
drivers/usb/musb/plat_uds.c
drivers/usb/musb/tusb6010.c
drivers/usb/musb/tusb6010.h
include/linux/usb/musb.h

index f6297cbc8248d7454ab0b32758e6011c6f33bbe9..c1652124ebb5c9e55aeaa6f20185112aebcc227a 100644 (file)
@@ -1513,6 +1513,15 @@ static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
 }
 #endif
 
+static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+{
+       struct musb     *musb = gadget_to_musb(gadget);
+
+       if (!musb->xceiv.set_power)
+               return -EOPNOTSUPP;
+       return otg_set_power(&musb->xceiv, mA);
+}
+
 static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on)
 {
        struct musb     *musb = gadget_to_musb(gadget);
@@ -1537,7 +1546,7 @@ static const struct usb_gadget_ops musb_gadget_operations = {
        .wakeup                 = musb_gadget_wakeup,
        .set_selfpowered        = musb_gadget_set_self_powered,
        //.vbus_session         = musb_gadget_vbus_session,
-       //.vbus_draw            = musb_gadget_vbus_draw,
+       .vbus_draw              = musb_gadget_vbus_draw,
        .pullup                 = musb_gadget_pullup,
 };
 
@@ -1925,6 +1934,9 @@ void musb_g_disconnect(struct musb *pThis)
 {
        DBG(3, "devctl %02x\n", musb_readb(pThis->pRegs, MGC_O_HDRC_DEVCTL));
 
+       /* don't draw vbus until new b-default session */
+       (void) musb_gadget_vbus_draw(&pThis->g, 0);
+
        pThis->g.speed = USB_SPEED_UNKNOWN;
        if (pThis->pGadgetDriver && pThis->pGadgetDriver->disconnect) {
                spin_unlock(&pThis->Lock);
@@ -2002,4 +2014,8 @@ __acquires(pThis->Lock)
                pThis->g.is_a_peripheral = 1;
        } else
                WARN_ON(1);
+
+       /* start with default limits on VBUS power draw */
+       (void) musb_gadget_vbus_draw(&pThis->g,
+                       is_otg_enabled(pThis) ? 8 : 100);
 }
index 032357d964855e9ba5e1f5b4f4c2fa3a38abb137..a4512a62c06d5c416501441564d82844e3de0305 100644 (file)
@@ -448,6 +448,8 @@ struct musb {
 
        s8 bFailCode;           /* one of MUSB_ERR_* failure code */
 
+       u8                      min_power;      /* vbus for periph, in mA/2 */
+
        /* active means connected and not suspended */
        unsigned is_active:1;
 
index 2fb0d530375ed0dba834c35752c5afb9539d449e..919fd0c0a8d908d9a6b6616accf7fc15d618dc6a 100644 (file)
@@ -1601,6 +1601,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        spin_lock_init(&pThis->Lock);
        pThis->board_mode = plat->mode;
        pThis->board_set_power = plat->set_power;
+       pThis->min_power = plat->min_power;
 
        /* assume vbus is off */
 
index 2b35d40f29a2b459fe9f534b5ea4052ece2029f3..9f145e5c1650fc050957ace0ccd1da996b55279f 100644 (file)
@@ -143,23 +143,36 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf)
        }
 }
 
-/*
- * Enables TUSB6010 to use VBUS as power source in peripheral mode.
- * In host mode, a local battery must power the TUSB chip as well as
- * (through the charge pump) VBUS.  For OTG peripherals, the battery
- * must power the chip until it enters a confguration that's allowed
- * to draw enough current (call it 100mA).
+/* This is used by gadget drivers, and OTG transceiver logic, allowing
+ * at most mA current to be drawn from VBUS during a Default-B session
+ * (that is, while VBUS exceeds 4.4V).  In Default-A (including pure host
+ * mode), or low power Default-B sessions, something else supplies power.
  */
-static inline void tusb_enable_vbus_charge(struct musb *musb)
+static int tusb_set_power(struct otg_transceiver *x, unsigned mA)
 {
+       struct musb     *musb = container_of(x, struct musb, xceiv);
        void __iomem    *base = musb->ctrl_base;
        u32             reg;
 
-       musb_writel(base, TUSB_PRCM_WAKEUP_MASK, 0xffff);
+       /* tps65030 seems to consume max 100mA, with maybe 60mA available
+        * (measured on one board) for things other than tps and tusb.
+        *
+        * REVISIT we could use VBUS to supply only _one_ of { 1.5V, 3.3V }.
+        * The actual current usage would be very board-specific.  For now,
+        * it's simpler to just use an aggregate (also board-specific).
+        */
+       if (x->default_a || mA < (musb->min_power << 1))
+               mA = 0;
+
        reg = musb_readl(base, TUSB_PRCM_MNGMT);
-       reg &= ~TUSB_PRCM_MNGMT_SUSPEND_MASK;
-       reg |= TUSB_PRCM_MNGMT_CPEN_MASK;
+       if (mA)
+               reg |= TUSB_PRCM_MNGMT_15_SW_EN | TUSB_PRCM_MNGMT_33_SW_EN;
+       else
+               reg &= ~(TUSB_PRCM_MNGMT_15_SW_EN | TUSB_PRCM_MNGMT_33_SW_EN);
        musb_writel(base, TUSB_PRCM_MNGMT, reg);
+
+       DBG(3, "draw max %d mA VBUS\n", mA);
+       return 0;
 }
 
 /* workaround for issue 13:  change clock during chip idle
@@ -184,7 +197,7 @@ void tusb_set_clock_source(struct musb *musb, int mode)
  * Idle TUSB6010 until next wake-up event; NOR access always wakes.
  * Other code ensures that we idle unless we're connected _and_ the
  * USB link is not suspended ... and tells us the relevant wakeup
- * events.
+ * events.  SW_EN for voltage is handled separately.
  */
 static void tusb_allow_idle(struct musb *musb, u32 wakeup_enables)
 {
@@ -197,9 +210,7 @@ static void tusb_allow_idle(struct musb *musb, u32 wakeup_enables)
        musb_writel(base, TUSB_PRCM_WAKEUP_MASK, ~wakeup_enables);
 
        reg = musb_readl(base, TUSB_PRCM_MNGMT);
-       reg &= ~( TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN
-                       | TUSB_PRCM_MNGMT_15_SW_EN
-                       | TUSB_PRCM_MNGMT_33_SW_EN );
+       reg &= ~TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN; /* REVISIT leave alone? */
        reg |= TUSB_PRCM_MNGMT_OTG_SESS_END_EN
                        | TUSB_PRCM_MNGMT_PM_IDLE
                        | TUSB_PRCM_MNGMT_DEV_IDLE;
@@ -318,12 +329,6 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *base)
                /* no vbus ~= disconnect */
                if (!is_host_enabled(musb) || !musb->xceiv.default_a) {
 
-                       /* REVISIT in B-Default state machine, use VBUS power
-                        * for the USB link when (a) non-OTG, since 100 mA is
-                        * always available; or (b) OTG after SET_CONFIGURATION
-                        * enabling 100+ (?) mA draw.
-                        */
-
                        /* REVISIT use the b_sess_valid comparator, not
                         * lowpower one; TUSB_DEV_OTG_STAT_SESS_VALID ?
                         */
@@ -671,6 +676,7 @@ int __devinit musb_platform_init(struct musb *musb)
                return -ENODEV;
        }
        musb->isr = tusb_interrupt;
+       musb->xceiv.set_power = tusb_set_power;
 
        setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
 
index e59d6eed37ab881fa589d71a35b28974ef901075..cf30f89a00be29208d42dfff8d5bfb171806084f 100644 (file)
 #define                TUSB_PRCM_MNGMT_PM_IDLE                 (1 << 1)
 #define                TUSB_PRCM_MNGMT_DEV_IDLE                (1 << 0)
 
-#define                TUSB_PRCM_MNGMT_PM_CLEAR_MASK   \
-                       ( TUSB_PRCM_MNGMT_15_SW_EN \
-                       | TUSB_PRCM_MNGMT_33_SW_EN \
-                       | TUSB_PRCM_MNGMT_PM_IDLE \
-                       | TUSB_PRCM_MNGMT_DEV_IDLE )
-#define                TUSB_PRCM_MNGMT_CPEN_MASK       \
-                       ( TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN \
-                       | TUSB_PRCM_MNGMT_15_SW_EN \
-                       | TUSB_PRCM_MNGMT_33_SW_EN )
-#define                TUSB_PRCM_MNGMT_SUSPEND_MASK    \
-                       ( TUSB_PRCM_MNGMT_OTG_SESS_END_EN \
-                       | TUSB_PRCM_MNGMT_PM_IDLE \
-                       | TUSB_PRCM_MNGMT_DEV_IDLE )
-
 /* Wake-up source clear and mask registers */
 #define TUSB_PRCM_WAKEUP_SOURCE                (TUSB_SYS_REG_BASE + 0x020)
 #define TUSB_PRCM_WAKEUP_CLEAR         (TUSB_SYS_REG_BASE + 0x028)
index a451c2f022fbbec19002ba5f95aa52907fd06f33..e7d942b8bd385b714c7be93133dbcf52329aff00 100644 (file)
@@ -27,6 +27,9 @@ struct musb_hdrc_platform_data {
        /* (HOST or OTG) mA/2 power supplied on (default = 8mA) */
        u8              power;
 
+       /* (PERIPHERAL) mA/2 max power consumed (default = 100mA) */
+       u8              min_power;
+
        /* (HOST or OTG) msec/2 after VBUS on till power good */
        u8              potpgt;