Merge tag 'usb-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB patches from Greg Kroah-Hartman: "Here's the big USB merge for 3.9-rc1 Nothing major, lots of gadget fixes, and of course, xhci stuff. All of this has been in linux-next for a while, with the exception of the last 3 patches, which were reverts of patches in the tree that caused problems, they went in yesterday." * tag 'usb-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (190 commits) Revert "USB: EHCI: make ehci-vt8500 a separate driver" Revert "USB: EHCI: make ehci-orion a separate driver" Revert "USB: update host controller Kconfig entries" USB: update host controller Kconfig entries USB: EHCI: make ehci-orion a separate driver USB: EHCI: make ehci-vt8500 a separate driver USB: usb-storage: unusual_devs update for Super TOP SATA bridge USB: ehci-omap: Fix autoloading of module USB: ehci-omap: Don't free gpios that we didn't request USB: option: add Huawei "ACM" devices using protocol = vendor USB: serial: fix null-pointer dereferences on disconnect USB: option: add Yota / Megafon M100-1 4g modem drivers/usb: add missing GENERIC_HARDIRQS dependencies USB: storage: properly handle the endian issues of idProduct testusb: remove all mentions of 'usbfs' usb: gadget: imx_udc: make it depend on BROKEN usb: omap_control_usb: fix compile warning ARM: OMAP: USB: Add phy binding information ARM: OMAP2: MUSB: Specify omap4 has mailbox ARM: OMAP: devices: create device for usb part of control module ...
This commit is contained in:
@@ -420,7 +420,7 @@ static void mv_otg_work(struct work_struct *work)
|
||||
struct usb_otg *otg;
|
||||
int old_state;
|
||||
|
||||
mvotg = container_of((struct delayed_work *)work, struct mv_otg, work);
|
||||
mvotg = container_of(to_delayed_work(work), struct mv_otg, work);
|
||||
|
||||
run:
|
||||
/* work queue is single thread, or we need spin_lock to protect */
|
||||
@@ -662,18 +662,9 @@ static struct attribute_group inputs_attr_group = {
|
||||
int mv_otg_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct mv_otg *mvotg = platform_get_drvdata(pdev);
|
||||
int clk_i;
|
||||
|
||||
sysfs_remove_group(&mvotg->pdev->dev.kobj, &inputs_attr_group);
|
||||
|
||||
if (mvotg->irq)
|
||||
free_irq(mvotg->irq, mvotg);
|
||||
|
||||
if (mvotg->pdata->vbus)
|
||||
free_irq(mvotg->pdata->vbus->irq, mvotg);
|
||||
if (mvotg->pdata->id)
|
||||
free_irq(mvotg->pdata->id->irq, mvotg);
|
||||
|
||||
if (mvotg->qwork) {
|
||||
flush_workqueue(mvotg->qwork);
|
||||
destroy_workqueue(mvotg->qwork);
|
||||
@@ -681,21 +672,9 @@ int mv_otg_remove(struct platform_device *pdev)
|
||||
|
||||
mv_otg_disable(mvotg);
|
||||
|
||||
if (mvotg->cap_regs)
|
||||
iounmap(mvotg->cap_regs);
|
||||
|
||||
if (mvotg->phy_regs)
|
||||
iounmap(mvotg->phy_regs);
|
||||
|
||||
for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++)
|
||||
clk_put(mvotg->clk[clk_i]);
|
||||
|
||||
usb_remove_phy(&mvotg->phy);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
kfree(mvotg->phy.otg);
|
||||
kfree(mvotg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -714,17 +693,15 @@ static int mv_otg_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum;
|
||||
mvotg = kzalloc(size, GFP_KERNEL);
|
||||
mvotg = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
|
||||
if (!mvotg) {
|
||||
dev_err(&pdev->dev, "failed to allocate memory!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
otg = kzalloc(sizeof *otg, GFP_KERNEL);
|
||||
if (!otg) {
|
||||
kfree(mvotg);
|
||||
otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
|
||||
if (!otg)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, mvotg);
|
||||
|
||||
@@ -733,18 +710,18 @@ static int mv_otg_probe(struct platform_device *pdev)
|
||||
|
||||
mvotg->clknum = pdata->clknum;
|
||||
for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) {
|
||||
mvotg->clk[clk_i] = clk_get(&pdev->dev, pdata->clkname[clk_i]);
|
||||
mvotg->clk[clk_i] = devm_clk_get(&pdev->dev,
|
||||
pdata->clkname[clk_i]);
|
||||
if (IS_ERR(mvotg->clk[clk_i])) {
|
||||
retval = PTR_ERR(mvotg->clk[clk_i]);
|
||||
goto err_put_clk;
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
|
||||
if (!mvotg->qwork) {
|
||||
dev_dbg(&pdev->dev, "cannot create workqueue for OTG\n");
|
||||
retval = -ENOMEM;
|
||||
goto err_put_clk;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&mvotg->work, mv_otg_work);
|
||||
@@ -772,7 +749,7 @@ static int mv_otg_probe(struct platform_device *pdev)
|
||||
goto err_destroy_workqueue;
|
||||
}
|
||||
|
||||
mvotg->phy_regs = ioremap(r->start, resource_size(r));
|
||||
mvotg->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
|
||||
if (mvotg->phy_regs == NULL) {
|
||||
dev_err(&pdev->dev, "failed to map phy I/O memory\n");
|
||||
retval = -EFAULT;
|
||||
@@ -784,21 +761,21 @@ static int mv_otg_probe(struct platform_device *pdev)
|
||||
if (r == NULL) {
|
||||
dev_err(&pdev->dev, "no I/O memory resource defined\n");
|
||||
retval = -ENODEV;
|
||||
goto err_unmap_phyreg;
|
||||
goto err_destroy_workqueue;
|
||||
}
|
||||
|
||||
mvotg->cap_regs = ioremap(r->start, resource_size(r));
|
||||
mvotg->cap_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
|
||||
if (mvotg->cap_regs == NULL) {
|
||||
dev_err(&pdev->dev, "failed to map I/O memory\n");
|
||||
retval = -EFAULT;
|
||||
goto err_unmap_phyreg;
|
||||
goto err_destroy_workqueue;
|
||||
}
|
||||
|
||||
/* we will acces controller register, so enable the udc controller */
|
||||
retval = mv_otg_enable_internal(mvotg);
|
||||
if (retval) {
|
||||
dev_err(&pdev->dev, "mv otg enable error %d\n", retval);
|
||||
goto err_unmap_capreg;
|
||||
goto err_destroy_workqueue;
|
||||
}
|
||||
|
||||
mvotg->op_regs =
|
||||
@@ -806,9 +783,9 @@ static int mv_otg_probe(struct platform_device *pdev)
|
||||
+ (readl(mvotg->cap_regs) & CAPLENGTH_MASK));
|
||||
|
||||
if (pdata->id) {
|
||||
retval = request_threaded_irq(pdata->id->irq, NULL,
|
||||
mv_otg_inputs_irq,
|
||||
IRQF_ONESHOT, "id", mvotg);
|
||||
retval = devm_request_threaded_irq(&pdev->dev, pdata->id->irq,
|
||||
NULL, mv_otg_inputs_irq,
|
||||
IRQF_ONESHOT, "id", mvotg);
|
||||
if (retval) {
|
||||
dev_info(&pdev->dev,
|
||||
"Failed to request irq for ID\n");
|
||||
@@ -818,9 +795,9 @@ static int mv_otg_probe(struct platform_device *pdev)
|
||||
|
||||
if (pdata->vbus) {
|
||||
mvotg->clock_gating = 1;
|
||||
retval = request_threaded_irq(pdata->vbus->irq, NULL,
|
||||
mv_otg_inputs_irq,
|
||||
IRQF_ONESHOT, "vbus", mvotg);
|
||||
retval = devm_request_threaded_irq(&pdev->dev, pdata->vbus->irq,
|
||||
NULL, mv_otg_inputs_irq,
|
||||
IRQF_ONESHOT, "vbus", mvotg);
|
||||
if (retval) {
|
||||
dev_info(&pdev->dev,
|
||||
"Failed to request irq for VBUS, "
|
||||
@@ -844,7 +821,7 @@ static int mv_otg_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
mvotg->irq = r->start;
|
||||
if (request_irq(mvotg->irq, mv_otg_irq, IRQF_SHARED,
|
||||
if (devm_request_irq(&pdev->dev, mvotg->irq, mv_otg_irq, IRQF_SHARED,
|
||||
driver_name, mvotg)) {
|
||||
dev_err(&pdev->dev, "Request irq %d for OTG failed\n",
|
||||
mvotg->irq);
|
||||
@@ -857,14 +834,14 @@ static int mv_otg_probe(struct platform_device *pdev)
|
||||
if (retval < 0) {
|
||||
dev_err(&pdev->dev, "can't register transceiver, %d\n",
|
||||
retval);
|
||||
goto err_free_irq;
|
||||
goto err_disable_clk;
|
||||
}
|
||||
|
||||
retval = sysfs_create_group(&pdev->dev.kobj, &inputs_attr_group);
|
||||
if (retval < 0) {
|
||||
dev_dbg(&pdev->dev,
|
||||
"Can't register sysfs attr group: %d\n", retval);
|
||||
goto err_set_transceiver;
|
||||
goto err_remove_phy;
|
||||
}
|
||||
|
||||
spin_lock_init(&mvotg->wq_lock);
|
||||
@@ -879,30 +856,15 @@ static int mv_otg_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
|
||||
err_set_transceiver:
|
||||
err_remove_phy:
|
||||
usb_remove_phy(&mvotg->phy);
|
||||
err_free_irq:
|
||||
free_irq(mvotg->irq, mvotg);
|
||||
err_disable_clk:
|
||||
if (pdata->vbus)
|
||||
free_irq(pdata->vbus->irq, mvotg);
|
||||
if (pdata->id)
|
||||
free_irq(pdata->id->irq, mvotg);
|
||||
mv_otg_disable_internal(mvotg);
|
||||
err_unmap_capreg:
|
||||
iounmap(mvotg->cap_regs);
|
||||
err_unmap_phyreg:
|
||||
iounmap(mvotg->phy_regs);
|
||||
err_destroy_workqueue:
|
||||
flush_workqueue(mvotg->qwork);
|
||||
destroy_workqueue(mvotg->qwork);
|
||||
err_put_clk:
|
||||
for (clk_i--; clk_i >= 0; clk_i--)
|
||||
clk_put(mvotg->clk[clk_i]);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
kfree(otg);
|
||||
kfree(mvotg);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@@ -76,6 +76,25 @@ static void mxs_phy_shutdown(struct usb_phy *phy)
|
||||
clk_disable_unprepare(mxs_phy->clk);
|
||||
}
|
||||
|
||||
static int mxs_phy_suspend(struct usb_phy *x, int suspend)
|
||||
{
|
||||
struct mxs_phy *mxs_phy = to_mxs_phy(x);
|
||||
|
||||
if (suspend) {
|
||||
writel_relaxed(0xffffffff, x->io_priv + HW_USBPHY_PWD);
|
||||
writel_relaxed(BM_USBPHY_CTRL_CLKGATE,
|
||||
x->io_priv + HW_USBPHY_CTRL_SET);
|
||||
clk_disable_unprepare(mxs_phy->clk);
|
||||
} else {
|
||||
clk_prepare_enable(mxs_phy->clk);
|
||||
writel_relaxed(BM_USBPHY_CTRL_CLKGATE,
|
||||
x->io_priv + HW_USBPHY_CTRL_CLR);
|
||||
writel_relaxed(0, x->io_priv + HW_USBPHY_PWD);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxs_phy_on_connect(struct usb_phy *phy,
|
||||
enum usb_device_speed speed)
|
||||
{
|
||||
@@ -137,6 +156,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
|
||||
mxs_phy->phy.label = DRIVER_NAME;
|
||||
mxs_phy->phy.init = mxs_phy_init;
|
||||
mxs_phy->phy.shutdown = mxs_phy_shutdown;
|
||||
mxs_phy->phy.set_suspend = mxs_phy_suspend;
|
||||
mxs_phy->phy.notify_connect = mxs_phy_on_connect;
|
||||
mxs_phy->phy.notify_disconnect = mxs_phy_on_disconnect;
|
||||
|
||||
|
@@ -13,11 +13,14 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/usb/otg.h>
|
||||
|
||||
static LIST_HEAD(phy_list);
|
||||
static LIST_HEAD(phy_bind_list);
|
||||
static DEFINE_SPINLOCK(phy_lock);
|
||||
|
||||
static struct usb_phy *__usb_find_phy(struct list_head *list,
|
||||
@@ -35,6 +38,38 @@ static struct usb_phy *__usb_find_phy(struct list_head *list,
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static struct usb_phy *__usb_find_phy_dev(struct device *dev,
|
||||
struct list_head *list, u8 index)
|
||||
{
|
||||
struct usb_phy_bind *phy_bind = NULL;
|
||||
|
||||
list_for_each_entry(phy_bind, list, list) {
|
||||
if (!(strcmp(phy_bind->dev_name, dev_name(dev))) &&
|
||||
phy_bind->index == index) {
|
||||
if (phy_bind->phy)
|
||||
return phy_bind->phy;
|
||||
else
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
}
|
||||
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static struct usb_phy *__of_usb_find_phy(struct device_node *node)
|
||||
{
|
||||
struct usb_phy *phy;
|
||||
|
||||
list_for_each_entry(phy, &phy_list, head) {
|
||||
if (node != phy->dev->of_node)
|
||||
continue;
|
||||
|
||||
return phy;
|
||||
}
|
||||
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static void devm_usb_phy_release(struct device *dev, void *res)
|
||||
{
|
||||
struct usb_phy *phy = *(struct usb_phy **)res;
|
||||
@@ -110,6 +145,133 @@ err0:
|
||||
}
|
||||
EXPORT_SYMBOL(usb_get_phy);
|
||||
|
||||
/**
|
||||
* devm_usb_get_phy_by_phandle - find the USB PHY by phandle
|
||||
* @dev - device that requests this phy
|
||||
* @phandle - name of the property holding the phy phandle value
|
||||
* @index - the index of the phy
|
||||
*
|
||||
* Returns the phy driver associated with the given phandle value,
|
||||
* after getting a refcount to it, -ENODEV if there is no such phy or
|
||||
* -EPROBE_DEFER if there is a phandle to the phy, but the device is
|
||||
* not yet loaded. While at that, it also associates the device with
|
||||
* the phy using devres. On driver detach, release function is invoked
|
||||
* on the devres data, then, devres data is freed.
|
||||
*
|
||||
* For use by USB host and peripheral drivers.
|
||||
*/
|
||||
struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
|
||||
const char *phandle, u8 index)
|
||||
{
|
||||
struct usb_phy *phy = ERR_PTR(-ENOMEM), **ptr;
|
||||
unsigned long flags;
|
||||
struct device_node *node;
|
||||
|
||||
if (!dev->of_node) {
|
||||
dev_dbg(dev, "device does not have a device node entry\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
node = of_parse_phandle(dev->of_node, phandle, index);
|
||||
if (!node) {
|
||||
dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle,
|
||||
dev->of_node->full_name);
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr) {
|
||||
dev_dbg(dev, "failed to allocate memory for devres\n");
|
||||
goto err0;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&phy_lock, flags);
|
||||
|
||||
phy = __of_usb_find_phy(node);
|
||||
if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
|
||||
phy = ERR_PTR(-EPROBE_DEFER);
|
||||
devres_free(ptr);
|
||||
goto err1;
|
||||
}
|
||||
|
||||
*ptr = phy;
|
||||
devres_add(dev, ptr);
|
||||
|
||||
get_device(phy->dev);
|
||||
|
||||
err1:
|
||||
spin_unlock_irqrestore(&phy_lock, flags);
|
||||
|
||||
err0:
|
||||
of_node_put(node);
|
||||
|
||||
return phy;
|
||||
}
|
||||
EXPORT_SYMBOL(devm_usb_get_phy_by_phandle);
|
||||
|
||||
/**
|
||||
* usb_get_phy_dev - find the USB PHY
|
||||
* @dev - device that requests this phy
|
||||
* @index - the index of the phy
|
||||
*
|
||||
* Returns the phy driver, after getting a refcount to it; or
|
||||
* -ENODEV if there is no such phy. The caller is responsible for
|
||||
* calling usb_put_phy() to release that count.
|
||||
*
|
||||
* For use by USB host and peripheral drivers.
|
||||
*/
|
||||
struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
|
||||
{
|
||||
struct usb_phy *phy = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&phy_lock, flags);
|
||||
|
||||
phy = __usb_find_phy_dev(dev, &phy_bind_list, index);
|
||||
if (IS_ERR(phy)) {
|
||||
pr_err("unable to find transceiver\n");
|
||||
goto err0;
|
||||
}
|
||||
|
||||
get_device(phy->dev);
|
||||
|
||||
err0:
|
||||
spin_unlock_irqrestore(&phy_lock, flags);
|
||||
|
||||
return phy;
|
||||
}
|
||||
EXPORT_SYMBOL(usb_get_phy_dev);
|
||||
|
||||
/**
|
||||
* devm_usb_get_phy_dev - find the USB PHY using device ptr and index
|
||||
* @dev - device that requests this phy
|
||||
* @index - the index of the phy
|
||||
*
|
||||
* Gets the phy using usb_get_phy_dev(), and associates a device with it using
|
||||
* devres. On driver detach, release function is invoked on the devres data,
|
||||
* then, devres data is freed.
|
||||
*
|
||||
* For use by USB host and peripheral drivers.
|
||||
*/
|
||||
struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index)
|
||||
{
|
||||
struct usb_phy **ptr, *phy;
|
||||
|
||||
ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
|
||||
phy = usb_get_phy_dev(dev, index);
|
||||
if (!IS_ERR(phy)) {
|
||||
*ptr = phy;
|
||||
devres_add(dev, ptr);
|
||||
} else
|
||||
devres_free(ptr);
|
||||
|
||||
return phy;
|
||||
}
|
||||
EXPORT_SYMBOL(devm_usb_get_phy_dev);
|
||||
|
||||
/**
|
||||
* devm_usb_put_phy - release the USB PHY
|
||||
* @dev - device that wants to release this phy
|
||||
@@ -184,6 +346,36 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(usb_add_phy);
|
||||
|
||||
/**
|
||||
* usb_add_phy_dev - declare the USB PHY
|
||||
* @x: the USB phy to be used; or NULL
|
||||
*
|
||||
* This call is exclusively for use by phy drivers, which
|
||||
* coordinate the activities of drivers for host and peripheral
|
||||
* controllers, and in some cases for VBUS current regulation.
|
||||
*/
|
||||
int usb_add_phy_dev(struct usb_phy *x)
|
||||
{
|
||||
struct usb_phy_bind *phy_bind;
|
||||
unsigned long flags;
|
||||
|
||||
if (!x->dev) {
|
||||
dev_err(x->dev, "no device provided for PHY\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&phy_lock, flags);
|
||||
list_for_each_entry(phy_bind, &phy_bind_list, list)
|
||||
if (!(strcmp(phy_bind->phy_dev_name, dev_name(x->dev))))
|
||||
phy_bind->phy = x;
|
||||
|
||||
list_add_tail(&x->head, &phy_list);
|
||||
|
||||
spin_unlock_irqrestore(&phy_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(usb_add_phy_dev);
|
||||
|
||||
/**
|
||||
* usb_remove_phy - remove the OTG PHY
|
||||
* @x: the USB OTG PHY to be removed;
|
||||
@@ -193,14 +385,55 @@ EXPORT_SYMBOL(usb_add_phy);
|
||||
void usb_remove_phy(struct usb_phy *x)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct usb_phy_bind *phy_bind;
|
||||
|
||||
spin_lock_irqsave(&phy_lock, flags);
|
||||
if (x)
|
||||
if (x) {
|
||||
list_for_each_entry(phy_bind, &phy_bind_list, list)
|
||||
if (phy_bind->phy == x)
|
||||
phy_bind->phy = NULL;
|
||||
list_del(&x->head);
|
||||
}
|
||||
spin_unlock_irqrestore(&phy_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(usb_remove_phy);
|
||||
|
||||
/**
|
||||
* usb_bind_phy - bind the phy and the controller that uses the phy
|
||||
* @dev_name: the device name of the device that will bind to the phy
|
||||
* @index: index to specify the port number
|
||||
* @phy_dev_name: the device name of the phy
|
||||
*
|
||||
* Fills the phy_bind structure with the dev_name and phy_dev_name. This will
|
||||
* be used when the phy driver registers the phy and when the controller
|
||||
* requests this phy.
|
||||
*
|
||||
* To be used by platform specific initialization code.
|
||||
*/
|
||||
int __init usb_bind_phy(const char *dev_name, u8 index,
|
||||
const char *phy_dev_name)
|
||||
{
|
||||
struct usb_phy_bind *phy_bind;
|
||||
unsigned long flags;
|
||||
|
||||
phy_bind = kzalloc(sizeof(*phy_bind), GFP_KERNEL);
|
||||
if (!phy_bind) {
|
||||
pr_err("phy_bind(): No memory for phy_bind");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
phy_bind->dev_name = dev_name;
|
||||
phy_bind->phy_dev_name = phy_dev_name;
|
||||
phy_bind->index = index;
|
||||
|
||||
spin_lock_irqsave(&phy_lock, flags);
|
||||
list_add_tail(&phy_bind->list, &phy_bind_list);
|
||||
spin_unlock_irqrestore(&phy_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_bind_phy);
|
||||
|
||||
const char *otg_state_string(enum usb_otg_state state)
|
||||
{
|
||||
switch (state) {
|
||||
|
@@ -610,6 +610,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)
|
||||
twl->phy.dev = twl->dev;
|
||||
twl->phy.label = "twl4030";
|
||||
twl->phy.otg = otg;
|
||||
twl->phy.type = USB_PHY_TYPE_USB2;
|
||||
twl->phy.set_suspend = twl4030_set_suspend;
|
||||
|
||||
otg->phy = &twl->phy;
|
||||
@@ -624,7 +625,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "ldo init failed\n");
|
||||
return err;
|
||||
}
|
||||
usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2);
|
||||
usb_add_phy_dev(&twl->phy);
|
||||
|
||||
platform_set_drvdata(pdev, twl);
|
||||
if (device_create_file(&pdev->dev, &dev_attr_vbus))
|
||||
|
Reference in New Issue
Block a user