提交 c9721438 编写于 作者: K Kishon Vijay Abraham I 提交者: Felipe Balbi

usb: musb: twl: use mailbox API to send VBUS or ID events

The atomic notifier from twl4030/twl6030 to notifiy VBUS and ID events,
is replaced by a direct call to omap musb blue.
Signed-off-by: NKishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: NFelipe Balbi <balbi@ti.com>
上级 1e5acb8d
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/usb/musb-omap.h>
#include "musb_core.h" #include "musb_core.h"
#include "omap2430.h" #include "omap2430.h"
...@@ -41,11 +42,13 @@ ...@@ -41,11 +42,13 @@
struct omap2430_glue { struct omap2430_glue {
struct device *dev; struct device *dev;
struct platform_device *musb; struct platform_device *musb;
u8 xceiv_event; enum omap_musb_vbus_id_status status;
struct work_struct omap_musb_mailbox_work; struct work_struct omap_musb_mailbox_work;
}; };
#define glue_to_musb(g) platform_get_drvdata(g->musb) #define glue_to_musb(g) platform_get_drvdata(g->musb)
struct omap2430_glue *_glue;
static struct timer_list musb_idle_timer; static struct timer_list musb_idle_timer;
static void musb_do_idle(unsigned long _musb) static void musb_do_idle(unsigned long _musb)
...@@ -225,54 +228,58 @@ static inline void omap2430_low_level_init(struct musb *musb) ...@@ -225,54 +228,58 @@ static inline void omap2430_low_level_init(struct musb *musb)
musb_writel(musb->mregs, OTG_FORCESTDBY, l); musb_writel(musb->mregs, OTG_FORCESTDBY, l);
} }
static int musb_otg_notifications(struct notifier_block *nb, void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
unsigned long event, void *unused)
{ {
struct musb *musb = container_of(nb, struct musb, nb); struct omap2430_glue *glue = _glue;
struct device *dev = musb->controller; struct musb *musb = glue_to_musb(glue);
struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
glue->xceiv_event = event; glue->status = status;
schedule_work(&glue->omap_musb_mailbox_work); if (!musb) {
dev_err(glue->dev, "musb core is not yet ready\n");
return;
}
return NOTIFY_OK; schedule_work(&glue->omap_musb_mailbox_work);
} }
EXPORT_SYMBOL_GPL(omap_musb_mailbox);
static void omap_musb_mailbox_work(struct work_struct *data_notifier_work) static void omap_musb_set_mailbox(struct omap2430_glue *glue)
{ {
struct omap2430_glue *glue = container_of(data_notifier_work,
struct omap2430_glue, omap_musb_mailbox_work);
struct musb *musb = glue_to_musb(glue); struct musb *musb = glue_to_musb(glue);
struct device *dev = musb->controller; struct device *dev = musb->controller;
struct musb_hdrc_platform_data *pdata = dev->platform_data; struct musb_hdrc_platform_data *pdata = dev->platform_data;
struct omap_musb_board_data *data = pdata->board_data; struct omap_musb_board_data *data = pdata->board_data;
switch (glue->xceiv_event) { switch (glue->status) {
case USB_EVENT_ID: case OMAP_MUSB_ID_GROUND:
dev_dbg(musb->controller, "ID GND\n"); dev_dbg(dev, "ID GND\n");
musb->xceiv->last_event = USB_EVENT_ID;
if (!is_otg_enabled(musb) || musb->gadget_driver) { if (!is_otg_enabled(musb) || musb->gadget_driver) {
pm_runtime_get_sync(musb->controller); pm_runtime_get_sync(dev);
usb_phy_init(musb->xceiv); usb_phy_init(musb->xceiv);
omap2430_musb_set_vbus(musb, 1); omap2430_musb_set_vbus(musb, 1);
} }
break; break;
case USB_EVENT_VBUS: case OMAP_MUSB_VBUS_VALID:
dev_dbg(musb->controller, "VBUS Connect\n"); dev_dbg(dev, "VBUS Connect\n");
musb->xceiv->last_event = USB_EVENT_VBUS;
if (musb->gadget_driver) if (musb->gadget_driver)
pm_runtime_get_sync(musb->controller); pm_runtime_get_sync(dev);
usb_phy_init(musb->xceiv); usb_phy_init(musb->xceiv);
break; break;
case USB_EVENT_NONE: case OMAP_MUSB_ID_FLOAT:
dev_dbg(musb->controller, "VBUS Disconnect\n"); case OMAP_MUSB_VBUS_OFF:
dev_dbg(dev, "VBUS Disconnect\n");
musb->xceiv->last_event = USB_EVENT_NONE;
if (is_otg_enabled(musb) || is_peripheral_enabled(musb)) if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
if (musb->gadget_driver) { if (musb->gadget_driver) {
pm_runtime_mark_last_busy(musb->controller); pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(musb->controller); pm_runtime_put_autosuspend(dev);
} }
if (data->interface_type == MUSB_INTERFACE_UTMI) { if (data->interface_type == MUSB_INTERFACE_UTMI) {
...@@ -282,15 +289,24 @@ static void omap_musb_mailbox_work(struct work_struct *data_notifier_work) ...@@ -282,15 +289,24 @@ static void omap_musb_mailbox_work(struct work_struct *data_notifier_work)
usb_phy_shutdown(musb->xceiv); usb_phy_shutdown(musb->xceiv);
break; break;
default: default:
dev_dbg(musb->controller, "ID float\n"); dev_dbg(dev, "ID float\n");
} }
} }
static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
{
struct omap2430_glue *glue = container_of(mailbox_work,
struct omap2430_glue, omap_musb_mailbox_work);
omap_musb_set_mailbox(glue);
}
static int omap2430_musb_init(struct musb *musb) static int omap2430_musb_init(struct musb *musb)
{ {
u32 l; u32 l;
int status = 0; int status = 0;
struct device *dev = musb->controller; struct device *dev = musb->controller;
struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
struct musb_hdrc_platform_data *plat = dev->platform_data; struct musb_hdrc_platform_data *plat = dev->platform_data;
struct omap_musb_board_data *data = plat->board_data; struct omap_musb_board_data *data = plat->board_data;
...@@ -330,14 +346,11 @@ static int omap2430_musb_init(struct musb *musb) ...@@ -330,14 +346,11 @@ static int omap2430_musb_init(struct musb *musb)
musb_readl(musb->mregs, OTG_INTERFSEL), musb_readl(musb->mregs, OTG_INTERFSEL),
musb_readl(musb->mregs, OTG_SIMENABLE)); musb_readl(musb->mregs, OTG_SIMENABLE));
musb->nb.notifier_call = musb_otg_notifications;
status = usb_register_notifier(musb->xceiv, &musb->nb);
if (status)
dev_dbg(musb->controller, "notification register failed\n");
setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
if (glue->status != OMAP_MUSB_UNKNOWN)
omap_musb_set_mailbox(glue);
pm_runtime_put_noidle(musb->controller); pm_runtime_put_noidle(musb->controller);
return 0; return 0;
...@@ -350,12 +363,13 @@ static void omap2430_musb_enable(struct musb *musb) ...@@ -350,12 +363,13 @@ static void omap2430_musb_enable(struct musb *musb)
u8 devctl; u8 devctl;
unsigned long timeout = jiffies + msecs_to_jiffies(1000); unsigned long timeout = jiffies + msecs_to_jiffies(1000);
struct device *dev = musb->controller; struct device *dev = musb->controller;
struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
struct musb_hdrc_platform_data *pdata = dev->platform_data; struct musb_hdrc_platform_data *pdata = dev->platform_data;
struct omap_musb_board_data *data = pdata->board_data; struct omap_musb_board_data *data = pdata->board_data;
switch (musb->xceiv->last_event) { switch (glue->status) {
case USB_EVENT_ID: case OMAP_MUSB_ID_GROUND:
usb_phy_init(musb->xceiv); usb_phy_init(musb->xceiv);
if (data->interface_type != MUSB_INTERFACE_UTMI) if (data->interface_type != MUSB_INTERFACE_UTMI)
break; break;
...@@ -374,7 +388,7 @@ static void omap2430_musb_enable(struct musb *musb) ...@@ -374,7 +388,7 @@ static void omap2430_musb_enable(struct musb *musb)
} }
break; break;
case USB_EVENT_VBUS: case OMAP_MUSB_VBUS_VALID:
usb_phy_init(musb->xceiv); usb_phy_init(musb->xceiv);
break; break;
...@@ -385,7 +399,10 @@ static void omap2430_musb_enable(struct musb *musb) ...@@ -385,7 +399,10 @@ static void omap2430_musb_enable(struct musb *musb)
static void omap2430_musb_disable(struct musb *musb) static void omap2430_musb_disable(struct musb *musb)
{ {
if (musb->xceiv->last_event) struct device *dev = musb->controller;
struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
if (glue->status != OMAP_MUSB_UNKNOWN)
usb_phy_shutdown(musb->xceiv); usb_phy_shutdown(musb->xceiv);
} }
...@@ -439,11 +456,18 @@ static int __devinit omap2430_probe(struct platform_device *pdev) ...@@ -439,11 +456,18 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
glue->dev = &pdev->dev; glue->dev = &pdev->dev;
glue->musb = musb; glue->musb = musb;
glue->status = OMAP_MUSB_UNKNOWN;
pdata->platform_ops = &omap2430_ops; pdata->platform_ops = &omap2430_ops;
platform_set_drvdata(pdev, glue); platform_set_drvdata(pdev, glue);
/*
* REVISIT if we ever have two instances of the wrapper, we will be
* in big trouble
*/
_glue = glue;
INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work); INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
ret = platform_device_add_resources(musb, pdev->resource, ret = platform_device_add_resources(musb, pdev->resource,
...@@ -552,7 +576,7 @@ static int __init omap2430_init(void) ...@@ -552,7 +576,7 @@ static int __init omap2430_init(void)
{ {
return platform_driver_register(&omap2430_driver); return platform_driver_register(&omap2430_driver);
} }
module_init(omap2430_init); subsys_initcall(omap2430_init);
static void __exit omap2430_exit(void) static void __exit omap2430_exit(void)
{ {
......
...@@ -33,11 +33,11 @@ ...@@ -33,11 +33,11 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/usb/otg.h> #include <linux/usb/otg.h>
#include <linux/usb/musb-omap.h>
#include <linux/usb/ulpi.h> #include <linux/usb/ulpi.h>
#include <linux/i2c/twl.h> #include <linux/i2c/twl.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/notifier.h>
#include <linux/slab.h> #include <linux/slab.h>
/* Register defines */ /* Register defines */
...@@ -159,7 +159,7 @@ struct twl4030_usb { ...@@ -159,7 +159,7 @@ struct twl4030_usb {
enum twl4030_usb_mode usb_mode; enum twl4030_usb_mode usb_mode;
int irq; int irq;
u8 linkstat; enum omap_musb_vbus_id_status linkstat;
bool vbus_supplied; bool vbus_supplied;
u8 asleep; u8 asleep;
bool irq_enabled; bool irq_enabled;
...@@ -246,10 +246,11 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits) ...@@ -246,10 +246,11 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl) static enum omap_musb_vbus_id_status
twl4030_usb_linkstat(struct twl4030_usb *twl)
{ {
int status; int status;
int linkstat = USB_EVENT_NONE; enum omap_musb_vbus_id_status linkstat = OMAP_MUSB_UNKNOWN;
struct usb_otg *otg = twl->phy.otg; struct usb_otg *otg = twl->phy.otg;
twl->vbus_supplied = false; twl->vbus_supplied = false;
...@@ -273,24 +274,24 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl) ...@@ -273,24 +274,24 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl)
twl->vbus_supplied = true; twl->vbus_supplied = true;
if (status & BIT(2)) if (status & BIT(2))
linkstat = USB_EVENT_ID; linkstat = OMAP_MUSB_ID_GROUND;
else else
linkstat = USB_EVENT_VBUS; linkstat = OMAP_MUSB_VBUS_VALID;
} else } else {
linkstat = USB_EVENT_NONE; if (twl->linkstat != OMAP_MUSB_UNKNOWN)
linkstat = OMAP_MUSB_VBUS_OFF;
}
dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
status, status, linkstat); status, status, linkstat);
twl->phy.last_event = linkstat;
/* REVISIT this assumes host and peripheral controllers /* REVISIT this assumes host and peripheral controllers
* are registered, and that both are active... * are registered, and that both are active...
*/ */
spin_lock_irq(&twl->lock); spin_lock_irq(&twl->lock);
twl->linkstat = linkstat; twl->linkstat = linkstat;
if (linkstat == USB_EVENT_ID) { if (linkstat == OMAP_MUSB_ID_GROUND) {
otg->default_a = true; otg->default_a = true;
twl->phy.state = OTG_STATE_A_IDLE; twl->phy.state = OTG_STATE_A_IDLE;
} else { } else {
...@@ -501,10 +502,10 @@ static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL); ...@@ -501,10 +502,10 @@ static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL);
static irqreturn_t twl4030_usb_irq(int irq, void *_twl) static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
{ {
struct twl4030_usb *twl = _twl; struct twl4030_usb *twl = _twl;
int status; enum omap_musb_vbus_id_status status;
status = twl4030_usb_linkstat(twl); status = twl4030_usb_linkstat(twl);
if (status >= 0) { if (status > 0) {
/* FIXME add a set_power() method so that B-devices can /* FIXME add a set_power() method so that B-devices can
* configure the charger appropriately. It's not always * configure the charger appropriately. It's not always
* correct to consume VBUS power, and how much current to * correct to consume VBUS power, and how much current to
...@@ -516,13 +517,13 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) ...@@ -516,13 +517,13 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
* USB_LINK_VBUS state. musb_hdrc won't care until it * USB_LINK_VBUS state. musb_hdrc won't care until it
* starts to handle softconnect right. * starts to handle softconnect right.
*/ */
if (status == USB_EVENT_NONE) if (status == OMAP_MUSB_VBUS_OFF ||
status == OMAP_MUSB_ID_FLOAT)
twl4030_phy_suspend(twl, 0); twl4030_phy_suspend(twl, 0);
else else
twl4030_phy_resume(twl); twl4030_phy_resume(twl);
atomic_notifier_call_chain(&twl->phy.notifier, status, omap_musb_mailbox(twl->linkstat);
twl->phy.otg->gadget);
} }
sysfs_notify(&twl->dev->kobj, NULL, "vbus"); sysfs_notify(&twl->dev->kobj, NULL, "vbus");
...@@ -531,11 +532,12 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) ...@@ -531,11 +532,12 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
static void twl4030_usb_phy_init(struct twl4030_usb *twl) static void twl4030_usb_phy_init(struct twl4030_usb *twl)
{ {
int status; enum omap_musb_vbus_id_status status;
status = twl4030_usb_linkstat(twl); status = twl4030_usb_linkstat(twl);
if (status >= 0) { if (status > 0) {
if (status == USB_EVENT_NONE) { if (status == OMAP_MUSB_VBUS_OFF ||
status == OMAP_MUSB_ID_FLOAT) {
__twl4030_phy_power(twl, 0); __twl4030_phy_power(twl, 0);
twl->asleep = 1; twl->asleep = 1;
} else { } else {
...@@ -543,8 +545,7 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl) ...@@ -543,8 +545,7 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl)
twl->asleep = 0; twl->asleep = 0;
} }
atomic_notifier_call_chain(&twl->phy.notifier, status, omap_musb_mailbox(twl->linkstat);
twl->phy.otg->gadget);
} }
sysfs_notify(&twl->dev->kobj, NULL, "vbus"); sysfs_notify(&twl->dev->kobj, NULL, "vbus");
} }
...@@ -613,6 +614,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) ...@@ -613,6 +614,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
twl->usb_mode = pdata->usb_mode; twl->usb_mode = pdata->usb_mode;
twl->vbus_supplied = false; twl->vbus_supplied = false;
twl->asleep = 1; twl->asleep = 1;
twl->linkstat = OMAP_MUSB_UNKNOWN;
twl->phy.dev = twl->dev; twl->phy.dev = twl->dev;
twl->phy.label = "twl4030"; twl->phy.label = "twl4030";
...@@ -639,8 +641,6 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) ...@@ -639,8 +641,6 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
if (device_create_file(&pdev->dev, &dev_attr_vbus)) if (device_create_file(&pdev->dev, &dev_attr_vbus))
dev_warn(&pdev->dev, "could not create sysfs file\n"); dev_warn(&pdev->dev, "could not create sysfs file\n");
ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
/* Our job is to use irqs and status from the power module /* Our job is to use irqs and status from the power module
* to keep the transceiver disabled when nothing's connected. * to keep the transceiver disabled when nothing's connected.
* *
......
...@@ -26,10 +26,10 @@ ...@@ -26,10 +26,10 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/usb/otg.h> #include <linux/usb/otg.h>
#include <linux/usb/musb-omap.h>
#include <linux/i2c/twl.h> #include <linux/i2c/twl.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/notifier.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -100,7 +100,7 @@ struct twl6030_usb { ...@@ -100,7 +100,7 @@ struct twl6030_usb {
int irq1; int irq1;
int irq2; int irq2;
u8 linkstat; enum omap_musb_vbus_id_status linkstat;
u8 asleep; u8 asleep;
bool irq_enabled; bool irq_enabled;
bool vbus_enable; bool vbus_enable;
...@@ -147,7 +147,7 @@ static int twl6030_phy_init(struct usb_phy *x) ...@@ -147,7 +147,7 @@ static int twl6030_phy_init(struct usb_phy *x)
dev = twl->dev; dev = twl->dev;
pdata = dev->platform_data; pdata = dev->platform_data;
if (twl->linkstat == USB_EVENT_ID) if (twl->linkstat == OMAP_MUSB_ID_GROUND)
pdata->phy_power(twl->dev, 1, 1); pdata->phy_power(twl->dev, 1, 1);
else else
pdata->phy_power(twl->dev, 0, 1); pdata->phy_power(twl->dev, 0, 1);
...@@ -235,13 +235,13 @@ static ssize_t twl6030_usb_vbus_show(struct device *dev, ...@@ -235,13 +235,13 @@ static ssize_t twl6030_usb_vbus_show(struct device *dev,
spin_lock_irqsave(&twl->lock, flags); spin_lock_irqsave(&twl->lock, flags);
switch (twl->linkstat) { switch (twl->linkstat) {
case USB_EVENT_VBUS: case OMAP_MUSB_VBUS_VALID:
ret = snprintf(buf, PAGE_SIZE, "vbus\n"); ret = snprintf(buf, PAGE_SIZE, "vbus\n");
break; break;
case USB_EVENT_ID: case OMAP_MUSB_ID_GROUND:
ret = snprintf(buf, PAGE_SIZE, "id\n"); ret = snprintf(buf, PAGE_SIZE, "id\n");
break; break;
case USB_EVENT_NONE: case OMAP_MUSB_VBUS_OFF:
ret = snprintf(buf, PAGE_SIZE, "none\n"); ret = snprintf(buf, PAGE_SIZE, "none\n");
break; break;
default: default:
...@@ -257,7 +257,7 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) ...@@ -257,7 +257,7 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
{ {
struct twl6030_usb *twl = _twl; struct twl6030_usb *twl = _twl;
struct usb_otg *otg = twl->phy.otg; struct usb_otg *otg = twl->phy.otg;
int status; enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
u8 vbus_state, hw_state; u8 vbus_state, hw_state;
hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
...@@ -268,22 +268,20 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) ...@@ -268,22 +268,20 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
if (vbus_state & VBUS_DET) { if (vbus_state & VBUS_DET) {
regulator_enable(twl->usb3v3); regulator_enable(twl->usb3v3);
twl->asleep = 1; twl->asleep = 1;
status = USB_EVENT_VBUS; status = OMAP_MUSB_VBUS_VALID;
otg->default_a = false; otg->default_a = false;
twl->phy.state = OTG_STATE_B_IDLE; twl->phy.state = OTG_STATE_B_IDLE;
twl->linkstat = status; twl->linkstat = status;
twl->phy.last_event = status; omap_musb_mailbox(status);
atomic_notifier_call_chain(&twl->phy.notifier,
status, otg->gadget);
} else { } else {
status = USB_EVENT_NONE; if (twl->linkstat != OMAP_MUSB_UNKNOWN) {
twl->linkstat = status; status = OMAP_MUSB_VBUS_OFF;
twl->phy.last_event = status; twl->linkstat = status;
atomic_notifier_call_chain(&twl->phy.notifier, omap_musb_mailbox(status);
status, otg->gadget); if (twl->asleep) {
if (twl->asleep) { regulator_disable(twl->usb3v3);
regulator_disable(twl->usb3v3); twl->asleep = 0;
twl->asleep = 0; }
} }
} }
} }
...@@ -296,7 +294,7 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) ...@@ -296,7 +294,7 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
{ {
struct twl6030_usb *twl = _twl; struct twl6030_usb *twl = _twl;
struct usb_otg *otg = twl->phy.otg; struct usb_otg *otg = twl->phy.otg;
int status = USB_EVENT_NONE; enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
u8 hw_state; u8 hw_state;
hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
...@@ -308,13 +306,11 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) ...@@ -308,13 +306,11 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1); twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1);
twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
0x10); 0x10);
status = USB_EVENT_ID; status = OMAP_MUSB_ID_GROUND;
otg->default_a = true; otg->default_a = true;
twl->phy.state = OTG_STATE_A_IDLE; twl->phy.state = OTG_STATE_A_IDLE;
twl->linkstat = status; twl->linkstat = status;
twl->phy.last_event = status; omap_musb_mailbox(status);
atomic_notifier_call_chain(&twl->phy.notifier, status,
otg->gadget);
} else { } else {
twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR,
0x10); 0x10);
...@@ -419,6 +415,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) ...@@ -419,6 +415,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
twl->irq1 = platform_get_irq(pdev, 0); twl->irq1 = platform_get_irq(pdev, 0);
twl->irq2 = platform_get_irq(pdev, 1); twl->irq2 = platform_get_irq(pdev, 1);
twl->features = pdata->features; twl->features = pdata->features;
twl->linkstat = OMAP_MUSB_UNKNOWN;
twl->phy.dev = twl->dev; twl->phy.dev = twl->dev;
twl->phy.label = "twl6030"; twl->phy.label = "twl6030";
...@@ -449,8 +446,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) ...@@ -449,8 +446,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
if (device_create_file(&pdev->dev, &dev_attr_vbus)) if (device_create_file(&pdev->dev, &dev_attr_vbus))
dev_warn(&pdev->dev, "could not create sysfs file\n"); dev_warn(&pdev->dev, "could not create sysfs file\n");
ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
twl->irq_enabled = true; twl->irq_enabled = true;
......
/*
* Copyright (C) 2011-2012 by Texas Instruments
*
* The Inventra Controller Driver for Linux is free software; you
* can redistribute it and/or modify it under the terms of the GNU
* General Public License version 2 as published by the Free Software
* Foundation.
*/
#ifndef __MUSB_OMAP_H__
#define __MUSB_OMAP_H__
enum omap_musb_vbus_id_status {
OMAP_MUSB_UNKNOWN = 0,
OMAP_MUSB_ID_GROUND,
OMAP_MUSB_ID_FLOAT,
OMAP_MUSB_VBUS_VALID,
OMAP_MUSB_VBUS_OFF,
};
#if (defined(CONFIG_USB_MUSB_OMAP2PLUS) || \
defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE))
void omap_musb_mailbox(enum omap_musb_vbus_id_status status);
#else
static inline void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
{
}
#endif
#endif /* __MUSB_OMAP_H__ */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册