Commit 51775f2d authored by Juha Yrjola's avatar Juha Yrjola

Merge 65.200.49.170:linux-omap

parents 9c3d91f8 0a05d267
......@@ -229,6 +229,11 @@ static void davinci_vbus_power(struct musb *musb, int is_on, int sleeping)
sleeping ? "immediate" : "deferred");
}
static void davinci_set_vbus(struct musb *musb, int is_on)
{
return davinci_vbus_power(musb, is_on, 0);
}
static irqreturn_t davinci_interrupt(int irq, void *__hci, struct pt_regs *r)
{
unsigned long flags;
......@@ -334,6 +339,9 @@ int __devinit musb_platform_init(struct musb *musb)
#endif
davinci_vbus_power(musb, musb->board_mode == MUSB_HOST, 1);
if (is_host_enabled(musb))
musb->board_set_vbus = davinci_set_vbus;
/* reset the controller */
musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1);
......
......@@ -60,4 +60,6 @@ static inline int _dbg_level(unsigned l)
#define DBG(level,fmt,args...) xprintk(level,KERN_DEBUG,fmt, ## args)
extern const char *otg_state_string(struct musb *);
#endif // __MUSB_LINUX_DEBUG_H__
......@@ -1598,8 +1598,6 @@ init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 bEnd, int is_in)
ep->end_point.ops = &musb_ep_ops;
list_add_tail(&ep->end_point.ep_list, &musb->g.ep_list);
}
DBG(4, "periph: %s, maxpacket %d\n", ep->end_point.name,
ep->end_point.maxpacket);
}
/*
......@@ -1634,8 +1632,6 @@ static inline void __devinit musb_g_init_endpoints(struct musb *pThis)
}
}
}
DBG(2, "initialized %d (max %d) endpoints\n", count,
MUSB_C_NUM_EPS * 2 - 1);
}
/* called once during driver setup to initialize and link into
......@@ -1656,10 +1652,6 @@ int __devinit musb_gadget_setup(struct musb *pThis)
pThis->g.ops = &musb_gadget_operations;
pThis->g.is_dualspeed = 1;
pThis->g.speed = USB_SPEED_UNKNOWN;
#ifdef CONFIG_USB_MUSB_OTG
if (pThis->board_mode == MUSB_OTG)
pThis->g.is_otg = 1;
#endif
/* this "gadget" abstracts/virtualizes the controller */
strcpy(pThis->g.dev.bus_id, "gadget");
......@@ -1762,11 +1754,12 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
* hosts only see fully functional devices.
*/
if (!is_otg_enabled(pThis))
musb_start(pThis);
spin_unlock_irqrestore(&pThis->Lock, flags);
#ifdef CONFIG_USB_MUSB_OTG
if (pThis->board_mode == MUSB_OTG) {
if (is_otg_enabled(pThis)) {
DBG(3, "OTG startup...\n");
/* REVISIT: funcall to other code, which also
......@@ -1784,7 +1777,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
spin_unlock_irqrestore(&pThis->Lock, flags);
}
}
#endif
}
return retval;
......@@ -1872,15 +1864,14 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
retval = -EINVAL;
spin_unlock_irqrestore(&musb->Lock, flags);
#ifdef CONFIG_USB_MUSB_OTG
if (retval == 0 && musb->board_mode == MUSB_OTG) {
if (is_otg_enabled(musb) && retval == 0) {
usb_remove_hcd(musb_to_hcd(musb));
/* FIXME we need to be able to register another
* gadget driver here and have everything work;
* that currently misbehaves.
*/
}
#endif
return retval;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
......@@ -2002,13 +1993,16 @@ __acquires(pThis->Lock)
pThis->g.a_alt_hnp_support = 0;
pThis->g.a_hnp_support = 0;
if (is_otg_enabled(pThis))
pThis->g.is_otg = !!musb_otg;
/* Normal reset, as B-Device;
* or else after HNP, as A-Device
*/
if (devctl & MGC_M_DEVCTL_BDEVICE) {
pThis->xceiv.state = OTG_STATE_B_PERIPHERAL;
pThis->g.is_a_peripheral = 0;
} else if (is_otg_enabled(pThis) && pThis->board_mode == MUSB_OTG) {
} else if (is_otg_enabled(pThis) && musb_otg) {
pThis->xceiv.state = OTG_STATE_A_PERIPHERAL;
pThis->g.is_a_peripheral = 1;
} else
......@@ -2016,5 +2010,5 @@ __acquires(pThis->Lock)
/* start with default limits on VBUS power draw */
(void) musb_gadget_vbus_draw(&pThis->g,
is_otg_enabled(pThis) ? 8 : 100);
(is_otg_enabled(pThis) && musb_otg) ? 8 : 100);
}
......@@ -48,9 +48,9 @@
#include "davinci.h"
static const char *state_string(enum usb_otg_state state)
const char *otg_state_string(struct musb *musb)
{
switch (state) {
switch (musb->xceiv.state) {
case OTG_STATE_A_IDLE: return "a_idle";
case OTG_STATE_A_WAIT_VRISE: return "a_wait_vrise";
case OTG_STATE_A_WAIT_BCON: return "a_wait_bcon";
......@@ -485,8 +485,9 @@ static int dump_header_stats(struct musb *pThis, char *buffer)
return count;
buffer += count;
code = sprintf(buffer, "OTG state: %s\n",
state_string(pThis->xceiv.state));
code = sprintf(buffer, "OTG state: %s; %sactive\n",
otg_state_string(pThis),
pThis->is_active ? "" : "in");
if (code < 0)
return code;
buffer += code;
......@@ -544,7 +545,7 @@ static int dump_header_stats(struct musb *pThis, char *buffer)
#ifdef CONFIG_USB_TUSB6010
code = sprintf(buffer,
"TUSB6010: devconf %08x, phy enable %08x drive %08x"
"\n\totg %08x timer %08x"
"\n\totg %03x timer %08x"
"\n\tprcm conf %08x mgmt %08x; intmask %08x"
"\n",
musb_readl(pThis->ctrl_base, TUSB_DEV_CONF),
......
......@@ -41,6 +41,8 @@
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/usb_ch9.h>
#include <linux/usb_gadget.h>
#include <linux/usb.h>
#include <linux/usb_otg.h>
#include <linux/usb/musb.h>
......@@ -67,13 +69,17 @@ struct musb_ep;
#include "plat_arc.h"
#include "musbhdrc.h"
#include "musb_gadget.h"
#include "../core/hcd.h"
#include "musb_host.h"
#include "otg.h"
/* REVISIT tune this */
#define MIN_DMA_REQUEST 1 /* use PIO below this xfer size */
#ifdef CONFIG_USB_MUSB_OTG
#include "otg.h"
#define is_peripheral_enabled(musb) ((musb)->board_mode != MUSB_HOST)
#define is_host_enabled(musb) ((musb)->board_mode != MUSB_PERIPHERAL)
......@@ -82,15 +88,8 @@ struct musb_ep;
/* NOTE: otg and peripheral-only state machines start at B_IDLE.
* OTG or host-only go to A_IDLE when ID is sensed.
*/
#define is_peripheral_active(m) (is_peripheral_capable() && !(m)->bIsHost)
#define is_host_active(m) (is_host_capable() && (m)->bIsHost)
/* for some reason, the "select USB_GADGET_MUSB_HDRC" doesn't really
* override that choice selection (often USB_GADGET_DUMMY_HCD).
*/
#ifndef CONFIG_USB_GADGET_MUSB_HDRC
#error bogus Kconfig output ... select CONFIG_USB_GADGET_MUSB_HDRC
#endif
#define is_peripheral_active(m) (!(m)->bIsHost)
#define is_host_active(m) ((m)->bIsHost)
#else
#define is_peripheral_enabled(musb) is_peripheral_capable()
......@@ -101,6 +100,15 @@ struct musb_ep;
#define is_host_active(musb) is_host_capable()
#endif
#if defined(CONFIG_USB_MUSB_OTG) || defined(CONFIG_USB_MUSB_PERIPHERAL)
/* for some reason, the "select USB_GADGET_MUSB_HDRC" doesn't always
* override that choice selection (often USB_GADGET_DUMMY_HCD).
*/
#ifndef CONFIG_USB_GADGET_MUSB_HDRC
#error bogus Kconfig output ... select CONFIG_USB_GADGET_MUSB_HDRC
#endif
#endif /* need MUSB gadget selection */
#ifdef CONFIG_PROC_FS
#include <linux/fs.h>
......@@ -111,9 +119,6 @@ struct musb_ep;
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
#include <linux/usb_gadget.h>
#include "musb_gadget.h"
#define is_peripheral_capable() (1)
extern irqreturn_t musb_g_ep0_irq(struct musb *);
......@@ -129,8 +134,6 @@ extern void musb_g_disconnect(struct musb *);
#define is_peripheral_capable() (0)
static inline irqreturn_t musb_g_ep0_irq(struct musb *m) { return IRQ_NONE; }
static inline void musb_g_tx(struct musb *m, u8 e) {}
static inline void musb_g_rx(struct musb *m, u8 e) {}
static inline void musb_g_reset(struct musb *m) {}
static inline void musb_g_suspend(struct musb *m) {}
static inline void musb_g_resume(struct musb *m) {}
......@@ -142,10 +145,6 @@ static inline void musb_g_disconnect(struct musb *m) {}
#ifdef CONFIG_USB_MUSB_HDRC_HCD
#include <linux/usb.h>
#include "../core/hcd.h"
#include "musb_host.h"
#define is_host_capable() (1)
extern irqreturn_t musb_h_ep0_irq(struct musb *);
......@@ -160,8 +159,6 @@ static inline irqreturn_t musb_h_ep0_irq(struct musb *m) { return IRQ_NONE; }
static inline void musb_host_tx(struct musb *m, u8 e) {}
static inline void musb_host_rx(struct musb *m, u8 e) {}
static inline void musb_root_disconnect(struct musb *musb) { BUG(); }
#endif
......@@ -399,9 +396,13 @@ struct musb {
struct list_head in_bulk; /* of musb_qh */
struct list_head out_bulk; /* of musb_qh */
struct musb_qh *periodic[32]; /* tree of interrupt+iso */
#endif
/* called with IRQs blocked; ON/nonzero implies starting a session,
* and waiting at least a_wait_vrise_tmout.
*/
void (*board_set_vbus)(struct musb *, int is_on);
struct dma_controller *pDmaController;
struct device *controller;
......@@ -489,6 +490,11 @@ struct musb {
#endif
};
static inline void musb_set_vbus(struct musb *musb, int is_on)
{
musb->board_set_vbus(musb, is_on);
}
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
static inline struct musb *gadget_to_musb(struct usb_gadget *g)
{
......
......@@ -55,6 +55,9 @@
* Finally, it provides the necessary bus control service.
*/
/* sysfs flag to seletively force peripheral-only operation */
extern int musb_otg;
/****************************** CONSTANTS ********************************/
/*
......
......@@ -171,6 +171,19 @@ MODULE_LICENSE("GPL");
/*-------------------------------------------------------------------------*/
#ifdef CONFIG_USB_MUSB_OTG
/* For debugging/prototyping: allow disabling host side support on boards
* with Mini-AB (or Mini-A) connectors, making peripheral side support look
* like pure peripherals (not reporting OTG capabilities, and able to
* draw a full 100mA unit load).
*/
int musb_otg = 1;
module_param(musb_otg, bool, 0600);
MODULE_PARM_DESC(musb_otg, "enable/disable OTG capabilities");
#endif
static inline struct musb *dev_to_musb(struct device *dev)
{
#ifdef CONFIG_USB_MUSB_HDRC_HCD
......@@ -416,6 +429,7 @@ static irqreturn_t musb_stage0_irq(struct musb * pThis, u8 bIntrUSB,
pThis->bEnd0Stage = MGC_END0_START;
pThis->xceiv.state = OTG_STATE_A_IDLE;
MUSB_HST_MODE(pThis);
musb_set_vbus(pThis, 1);
handled = IRQ_HANDLED;
......@@ -454,12 +468,9 @@ static irqreturn_t musb_stage0_irq(struct musb * pThis, u8 bIntrUSB,
}; s; }),
pThis->vbuserr_retry);
/* after hw goes to A_IDLE, try connecting again */
pThis->xceiv.state = OTG_STATE_A_IDLE;
if (pThis->vbuserr_retry--)
musb_writeb(pBase, MGC_O_HDRC_DEVCTL,
MGC_M_DEVCTL_SESSION);
return IRQ_HANDLED;
/* go through A_WAIT_VFALL then start a new session */
musb_set_vbus(pThis, 0);
handled = IRQ_HANDLED;
} else
pThis->vbuserr_retry = VBUSERR_RETRY_COUNT;
......@@ -498,14 +509,10 @@ static irqreturn_t musb_stage0_irq(struct musb * pThis, u8 bIntrUSB,
pThis->xceiv.state = OTG_STATE_B_HOST;
break;
default:
DBG(2, "connect in state %d\n", pThis->xceiv.state);
/* FALLTHROUGH */
case OTG_STATE_A_WAIT_BCON:
case OTG_STATE_A_WAIT_VRISE:
pThis->xceiv.state = OTG_STATE_A_HOST;
break;
}
DBG(1, "CONNECT (host state %d)\n", pThis->xceiv.state);
DBG(1, "CONNECT (%s)\n", otg_state_string(pThis));
otg_input_changed(pThis, devctl, FALSE, TRUE, FALSE);
}
#endif /* CONFIG_USB_MUSB_HDRC_HCD */
......@@ -635,12 +642,8 @@ static irqreturn_t musb_stage2_irq(struct musb * pThis, u8 bIntrUSB,
/* peripheral suspend, may trigger HNP */
if (!(devctl & MGC_M_DEVCTL_HM)) {
musb_g_suspend(pThis);
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
pThis->is_active = is_otg_enabled(pThis)
&& pThis->xceiv.gadget->b_hnp_enable;
#else
pThis->is_active = 0;
#endif
otg_input_changed(pThis, devctl, FALSE, FALSE, TRUE);
} else
pThis->is_active = 0;
......@@ -654,37 +657,46 @@ static irqreturn_t musb_stage2_irq(struct musb * pThis, u8 bIntrUSB,
/*
* Program the HDRC to start (enable interrupts, dma, etc.).
*/
void musb_start(struct musb * pThis)
void musb_start(struct musb *musb)
{
void __iomem *pBase = pThis->pRegs;
u8 state;
void __iomem *regs = musb->pRegs;
u8 devctl;
DBG(2, "<==\n");
/* TODO: always set ISOUPDATE in POWER (periph mode) and leave it on! */
/* Set INT enable registers, enable interrupts */
musb_writew(pBase, MGC_O_HDRC_INTRTXE, pThis->wEndMask);
musb_writew(pBase, MGC_O_HDRC_INTRRXE, pThis->wEndMask & 0xfffe);
musb_writeb(pBase, MGC_O_HDRC_INTRUSBE, 0xf7);
musb_writew(regs, MGC_O_HDRC_INTRTXE, musb->wEndMask);
musb_writew(regs, MGC_O_HDRC_INTRRXE, musb->wEndMask & 0xfffe);
musb_writeb(regs, MGC_O_HDRC_INTRUSBE, 0xf7);
musb_writeb(pBase, MGC_O_HDRC_TESTMODE, 0);
musb_writeb(regs, MGC_O_HDRC_TESTMODE, 0);
musb_platform_enable(pThis);
musb_platform_enable(musb);
/* enable high-speed/low-power and start session */
musb_writeb(pBase, MGC_O_HDRC_POWER,
musb_writeb(regs, MGC_O_HDRC_POWER,
MGC_M_POWER_SOFTCONN | MGC_M_POWER_HSENAB);
switch (pThis->board_mode) {
musb->is_active = 0;
switch (musb->board_mode) {
case MUSB_HOST:
musb_set_vbus(musb, 1);
break;
case MUSB_OTG:
musb_writeb(pBase, MGC_O_HDRC_DEVCTL, MGC_M_DEVCTL_SESSION);
/* session started after:
* (a) ID-grounded irq, host mode;
* (b) vbus present/connect IRQ, peripheral mode;
* (c) peripheral initiates, using SRP
*/
break;
case MUSB_PERIPHERAL:
state = musb_readb(pBase, MGC_O_HDRC_DEVCTL);
musb_writeb(pBase, MGC_O_HDRC_DEVCTL,
state & ~MGC_M_DEVCTL_SESSION);
devctl = musb_readb(regs, MGC_O_HDRC_DEVCTL);
if ((devctl & MGC_M_DEVCTL_VBUS) == MGC_M_DEVCTL_VBUS)
musb->is_active = 1;
musb_writeb(regs, MGC_O_HDRC_DEVCTL,
devctl & ~MGC_M_DEVCTL_SESSION);
break;
}
}
......@@ -962,7 +974,7 @@ static const struct fifo_cfg __devinitdata ep0_cfg = {
static int __devinit ep_config_from_table(struct musb *musb)
{
const struct fifo_cfg *cfg;
unsigned n;
unsigned i, n;
int offset;
struct musb_hw_ep *hw_ep = musb->aLocalEnd;
......@@ -999,13 +1011,13 @@ static int __devinit ep_config_from_table(struct musb *musb)
offset = fifo_setup(musb, hw_ep, &ep0_cfg, 0);
// assert(offset > 0)
while (n--) {
for (i = 0; i < n; i++) {
u8 epn = cfg->hw_ep_num;
if (epn >= MUSB_C_NUM_EPS) {
pr_debug( "%s: invalid ep %d\n",
musb_driver_name, epn);
return -EINVAL;
continue;
}
offset = fifo_setup(musb, hw_ep + epn, cfg++, offset);
if (offset < 0) {
......@@ -1019,7 +1031,7 @@ static int __devinit ep_config_from_table(struct musb *musb)
printk(KERN_DEBUG "%s: %d/%d max ep, %d/%d memory\n",
musb_driver_name,
musb->bEndCount, MUSB_C_NUM_EPS * 2 - 1,
n + 1, MUSB_C_NUM_EPS * 2 - 1,
offset, DYN_FIFO_SIZE);
#ifdef CONFIG_USB_MUSB_HDRC_HCD
......@@ -1350,11 +1362,14 @@ irqreturn_t musb_interrupt(struct musb *musb)
// MGC_SelectEnd(musb->pRegs, ep_num);
/* REVISIT just retval = ep->rx_irq(...) */
retval = IRQ_HANDLED;
if (devctl & MGC_M_DEVCTL_HM)
if (devctl & MGC_M_DEVCTL_HM) {
if (is_host_capable())
musb_host_rx(musb, ep_num);
else
} else {
if (is_peripheral_capable())
musb_g_rx(musb, ep_num);
}
}
reg >>= 1;
ep_num++;
......@@ -1368,11 +1383,14 @@ irqreturn_t musb_interrupt(struct musb *musb)
// MGC_SelectEnd(musb->pRegs, ep_num);
/* REVISIT just retval |= ep->tx_irq(...) */
retval = IRQ_HANDLED;
if (devctl & MGC_M_DEVCTL_HM)
if (devctl & MGC_M_DEVCTL_HM) {
if (is_host_capable())
musb_host_tx(musb, ep_num);
else
} else {
if (is_peripheral_capable())
musb_g_tx(musb, ep_num);
}
}
reg >>= 1;
ep_num++;
}
......@@ -1410,18 +1428,24 @@ void musb_dma_completion(struct musb *musb, u8 bLocalEnd, u8 bTransmit)
} else {
/* endpoints 1..15 */
if (bTransmit) {
if (devctl & MGC_M_DEVCTL_HM)
if (devctl & MGC_M_DEVCTL_HM) {
if (is_host_capable())
musb_host_tx(musb, bLocalEnd);
else
} else {
if (is_peripheral_capable())
musb_g_tx(musb, bLocalEnd);
}
} else {
/* receive */
if (devctl & MGC_M_DEVCTL_HM)
if (devctl & MGC_M_DEVCTL_HM) {
if (is_host_capable())
musb_host_rx(musb, bLocalEnd);
else
} else {
if (is_peripheral_capable())
musb_g_rx(musb, bLocalEnd);
}
}
}
}
#else
......
This diff is collapsed.
......@@ -75,6 +75,7 @@
#define TUSB_DEV_OTG_STAT_VBUS_VALID (1 << 5)
#define TUSB_DEV_OTG_STAT_VBUS_SENSE (1 << 4)
#define TUSB_DEV_OTG_STAT_ID_STATUS (1 << 3)
#define TUSB_DEV_OTG_STAT_HOST_DISCON (1 << 2)
#define TUSB_DEV_OTG_STAT_LINE_STATE (3 << 0)
#define TUSB_DEV_OTG_STAT_DP_ENABLE (1 << 1)
#define TUSB_DEV_OTG_STAT_DM_ENABLE (1 << 0)
......
......@@ -51,6 +51,9 @@ static void musb_port_suspend(struct musb *musb, u8 bSuspend)
u8 power;
void __iomem *pBase = musb->pRegs;
if (!is_host_active(musb))
return;
power = musb_readb(pBase, MGC_O_HDRC_POWER);
if (bSuspend) {
......@@ -181,12 +184,11 @@ int musb_hub_control(
int retval = 0;
unsigned long flags;
if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)
|| !is_host_active(musb)))
if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
return -ESHUTDOWN;
/* hub features: always zero, setting is a NOP
* port features: reported, sometimes updated
* port features: reported, sometimes updated when host is active
* no indicators
*/
spin_lock_irqsave(&musb->Lock, flags);
......@@ -212,6 +214,9 @@ int musb_hub_control(
musb_port_suspend(musb, FALSE);
break;
case USB_PORT_FEAT_POWER:
if (!(is_otg_enabled(musb) && hcd->self.is_b_host))
musb_set_vbus(musb, 0);
break;
case USB_PORT_FEAT_C_CONNECTION:
case USB_PORT_FEAT_C_ENABLE:
case USB_PORT_FEAT_C_OVER_CURRENT:
......@@ -276,6 +281,7 @@ int musb_hub_control(
* initialization logic, e.g. for OTG, or change any
* logic relating to VBUS power-up.
*/
if (!(is_otg_enabled(musb) && hcd->self.is_b_host))
musb_start(musb);
break;
case USB_PORT_FEAT_RESET:
......@@ -285,6 +291,9 @@ int musb_hub_control(
musb_port_suspend(musb, TRUE);
break;
case USB_PORT_FEAT_TEST:
if (unlikely(is_host_active(musb)))
goto error;
wIndex >>= 8;
switch (wIndex) {
case 1:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment