summaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/musb')
-rw-r--r--drivers/usb/musb/musb_cppi41.c4
-rw-r--r--drivers/usb/musb/musb_dsps.c61
-rw-r--r--drivers/usb/musb/musb_gadget.c15
-rw-r--r--drivers/usb/musb/musb_host.c2
-rw-r--r--drivers/usb/musb/ux500_dma.c4
5 files changed, 61 insertions, 25 deletions
diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c
index e64701d15401..ae959746f77f 100644
--- a/drivers/usb/musb/musb_cppi41.c
+++ b/drivers/usb/musb/musb_cppi41.c
@@ -150,8 +150,10 @@ static void cppi41_dma_callback(void *private_data)
remain_bytes,
direction,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (WARN_ON(!dma_desc))
+ if (WARN_ON(!dma_desc)) {
+ spin_unlock_irqrestore(&musb->lock, flags);
return;
+ }
dma_desc->callback = cppi41_dma_callback;
dma_desc->callback_param = channel;
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 4ffbaace7913..4047cbb91bac 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -44,6 +44,7 @@
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <linux/usb/of.h>
#include "musb_core.h"
@@ -230,6 +231,8 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
glue->last_timer = jiffies;
return;
}
+ if (musb->port_mode == MUSB_PORT_MODE_HOST)
+ return;
if (time_after(glue->last_timer, timeout) &&
timer_pending(&glue->timer)) {
@@ -313,7 +316,6 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
jiffies + wrp->poll_seconds * HZ);
WARNING("VBUS error workaround (delay coming)\n");
} else if (drvvbus) {
- musb->is_active = 1;
MUSB_HST_MODE(musb);
musb->xceiv->otg->default_a = 1;
musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
@@ -361,8 +363,8 @@ static int dsps_musb_init(struct musb *musb)
return -EINVAL;
reg_base = devm_ioremap_resource(dev, r);
- if (!musb->ctrl_base)
- return -EINVAL;
+ if (IS_ERR(reg_base))
+ return PTR_ERR(reg_base);
musb->ctrl_base = reg_base;
/* NOP driver needs change if supporting dual instance */
@@ -425,35 +427,51 @@ static int get_int_prop(struct device_node *dn, const char *s)
return val;
}
+static int get_musb_port_mode(struct device *dev)
+{
+ enum usb_dr_mode mode;
+
+ mode = of_usb_get_dr_mode(dev->of_node);
+ switch (mode) {
+ case USB_DR_MODE_HOST:
+ return MUSB_PORT_MODE_HOST;
+
+ case USB_DR_MODE_PERIPHERAL:
+ return MUSB_PORT_MODE_GADGET;
+
+ case USB_DR_MODE_UNKNOWN:
+ case USB_DR_MODE_OTG:
+ default:
+ return MUSB_PORT_MODE_DUAL_ROLE;
+ };
+}
+
static int dsps_create_musb_pdev(struct dsps_glue *glue,
struct platform_device *parent)
{
struct musb_hdrc_platform_data pdata;
struct resource resources[2];
+ struct resource *res;
struct device *dev = &parent->dev;
struct musb_hdrc_config *config;
struct platform_device *musb;
struct device_node *dn = parent->dev.of_node;
- struct device_node *child_node;
int ret;
- child_node = of_get_child_by_name(dn, "usb");
- if (!child_node)
- return -EINVAL;
-
memset(resources, 0, sizeof(resources));
- ret = of_address_to_resource(child_node, 0, &resources[0]);
- if (ret) {
+ res = platform_get_resource_byname(parent, IORESOURCE_MEM, "mc");
+ if (!res) {
dev_err(dev, "failed to get memory.\n");
- return ret;
+ return -EINVAL;
}
+ resources[0] = *res;
- ret = of_irq_to_resource(child_node, 0, &resources[1]);
- if (ret == 0) {
+ res = platform_get_resource_byname(parent, IORESOURCE_IRQ, "mc");
+ if (!res) {
dev_err(dev, "failed to get irq.\n");
- ret = -EINVAL;
- return ret;
+ return -EINVAL;
}
+ resources[1] = *res;
/* allocate the child platform device */
musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
@@ -465,7 +483,7 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue,
musb->dev.parent = dev;
musb->dev.dma_mask = &musb_dmamask;
musb->dev.coherent_dma_mask = musb_dmamask;
- musb->dev.of_node = of_node_get(child_node);
+ musb->dev.of_node = of_node_get(dn);
glue->musb = musb;
@@ -485,11 +503,12 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue,
pdata.config = config;
pdata.platform_ops = &dsps_ops;
- config->num_eps = get_int_prop(child_node, "num-eps");
- config->ram_bits = get_int_prop(child_node, "ram-bits");
- pdata.mode = get_int_prop(child_node, "port-mode");
- pdata.power = get_int_prop(child_node, "power");
- config->multipoint = of_property_read_bool(child_node, "multipoint");
+ config->num_eps = get_int_prop(dn, "mentor,num-eps");
+ config->ram_bits = get_int_prop(dn, "mentor,ram-bits");
+ pdata.mode = get_musb_port_mode(dev);
+ /* DT keeps this entry in mA, musb expects it as per USB spec */
+ pdata.power = get_int_prop(dn, "mentor,power") / 2;
+ config->multipoint = of_property_read_bool(dn, "mentor,multipoint");
ret = platform_device_add_data(musb, &pdata, sizeof(pdata));
if (ret) {
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 4376f51f5ef1..9a08679d204d 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -76,13 +76,21 @@ static inline void map_dma_buffer(struct musb_request *request,
return;
if (request->request.dma == DMA_ADDR_INVALID) {
- request->request.dma = dma_map_single(
+ dma_addr_t dma_addr;
+ int ret;
+
+ dma_addr = dma_map_single(
musb->controller,
request->request.buf,
request->request.length,
request->tx
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
+ ret = dma_mapping_error(musb->controller, dma_addr);
+ if (ret)
+ return;
+
+ request->request.dma = dma_addr;
request->map_state = MUSB_MAPPED;
} else {
dma_sync_single_for_device(musb->controller,
@@ -1804,6 +1812,8 @@ err:
void musb_gadget_cleanup(struct musb *musb)
{
+ if (musb->port_mode == MUSB_PORT_MODE_HOST)
+ return;
usb_del_gadget_udc(&musb->g);
}
@@ -1929,7 +1939,8 @@ static int musb_gadget_stop(struct usb_gadget *g,
stop_activity(musb, driver);
otg_set_peripheral(musb->xceiv->otg, NULL);
- dev_dbg(musb->controller, "unregistering driver %s\n", driver->function);
+ dev_dbg(musb->controller, "unregistering driver %s\n",
+ driver ? driver->function : "(removed)");
musb->is_active = 0;
musb->gadget_driver = NULL;
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index a9695f5a92fb..9a2b8c85f19a 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -2628,6 +2628,8 @@ int musb_host_alloc(struct musb *musb)
void musb_host_cleanup(struct musb *musb)
{
+ if (musb->port_mode == MUSB_PORT_MODE_GADGET)
+ return;
usb_remove_hcd(musb->hcd);
musb->hcd = NULL;
}
diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c
index e51dd9b88e71..3700e9713258 100644
--- a/drivers/usb/musb/ux500_dma.c
+++ b/drivers/usb/musb/ux500_dma.c
@@ -333,7 +333,9 @@ static int ux500_dma_controller_start(struct ux500_dma_controller *controller)
if (!ux500_channel->dma_chan)
ux500_channel->dma_chan =
dma_request_channel(mask,
- data->dma_filter,
+ data ?
+ data->dma_filter :
+ NULL,
param_array[ch_num]);
if (!ux500_channel->dma_chan) {
OpenPOWER on IntegriCloud