summaryrefslogtreecommitdiff
path: root/drivers/usb/chipidea
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/chipidea')
-rw-r--r--drivers/usb/chipidea/Kconfig5
-rw-r--r--drivers/usb/chipidea/Makefile5
-rw-r--r--drivers/usb/chipidea/ci.h3
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c6
-rw-r--r--drivers/usb/chipidea/ci_hdrc_msm.c3
-rw-r--r--drivers/usb/chipidea/ci_hdrc_pci.c4
-rw-r--r--drivers/usb/chipidea/core.c59
-rw-r--r--drivers/usb/chipidea/debug.c4
-rw-r--r--drivers/usb/chipidea/debug.h30
-rw-r--r--drivers/usb/chipidea/host.c2
-rw-r--r--drivers/usb/chipidea/otg_fsm.c26
-rw-r--r--drivers/usb/chipidea/otg_fsm.h2
-rw-r--r--drivers/usb/chipidea/udc.c31
13 files changed, 81 insertions, 99 deletions
diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig
index 5619b8ca3..3644a3500 100644
--- a/drivers/usb/chipidea/Kconfig
+++ b/drivers/usb/chipidea/Kconfig
@@ -37,9 +37,4 @@ config USB_CHIPIDEA_HOST
Say Y here to enable host controller functionality of the
ChipIdea driver.
-config USB_CHIPIDEA_DEBUG
- bool "ChipIdea driver debug"
- help
- Say Y here to enable debugging output of the ChipIdea driver.
-
endif
diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile
index 4decb12f2..518e44547 100644
--- a/drivers/usb/chipidea/Makefile
+++ b/drivers/usb/chipidea/Makefile
@@ -1,11 +1,8 @@
-ccflags-$(CONFIG_USB_CHIPIDEA_DEBUG) := -DDEBUG
-
obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc.o
-ci_hdrc-y := core.o otg.o
+ci_hdrc-y := core.o otg.o debug.o
ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o
ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o
-ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o
ci_hdrc-$(CONFIG_USB_OTG_FSM) += otg_fsm.o
# Glue/Bridge layers go here
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 41d7cf6d6..cd4145590 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -433,4 +433,7 @@ int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
void ci_platform_configure(struct ci_hdrc *ci);
+int dbg_create_files(struct ci_hdrc *ci);
+
+void dbg_remove_files(struct ci_hdrc *ci);
#endif /* __DRIVERS_USB_CHIPIDEA_CI_H */
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 5a048b7b9..f14f4ab47 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -345,6 +345,11 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
return 0;
}
+static void ci_hdrc_imx_shutdown(struct platform_device *pdev)
+{
+ ci_hdrc_imx_remove(pdev);
+}
+
#ifdef CONFIG_PM
static int imx_controller_suspend(struct device *dev)
{
@@ -462,6 +467,7 @@ static const struct dev_pm_ops ci_hdrc_imx_pm_ops = {
static struct platform_driver ci_hdrc_imx_driver = {
.probe = ci_hdrc_imx_probe,
.remove = ci_hdrc_imx_remove,
+ .shutdown = ci_hdrc_imx_shutdown,
.driver = {
.name = "imx_usb",
.of_match_table = ci_hdrc_imx_dt_ids,
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index d79ecc08a..3889809fd 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -25,7 +25,8 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
case CI_HDRC_CONTROLLER_RESET_EVENT:
dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
writel(0, USB_AHBBURST);
- writel(0, USB_AHBMODE);
+ /* use AHB transactor, allow posted data writes */
+ writel(0x8, USB_AHBMODE);
usb_phy_init(ci->usb_phy);
break;
case CI_HDRC_CONTROLLER_STOPPED_EVENT:
diff --git a/drivers/usb/chipidea/ci_hdrc_pci.c b/drivers/usb/chipidea/ci_hdrc_pci.c
index b59195edf..b635ab674 100644
--- a/drivers/usb/chipidea/ci_hdrc_pci.c
+++ b/drivers/usb/chipidea/ci_hdrc_pci.c
@@ -85,8 +85,8 @@ static int ci_hdrc_pci_probe(struct pci_dev *pdev,
/* register a nop PHY */
ci->phy = usb_phy_generic_register();
- if (!ci->phy)
- return -ENOMEM;
+ if (IS_ERR(ci->phy))
+ return PTR_ERR(ci->phy);
memset(res, 0, sizeof(res));
res[0].start = pci_resource_start(pdev, 0);
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 965d0e240..7404064b9 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -23,7 +23,6 @@
* - BUS: bus glue code, bus abstraction layer
*
* Compile Options
- * - CONFIG_USB_CHIPIDEA_DEBUG: enable debug facilities
* - STALL_IN: non-empty bulk-in pipes cannot be halted
* if defined mass storage compliance succeeds but with warnings
* => case 4: Hi > Dn
@@ -71,7 +70,6 @@
#include "udc.h"
#include "bits.h"
#include "host.h"
-#include "debug.h"
#include "otg.h"
#include "otg_fsm.h"
@@ -688,52 +686,39 @@ static int ci_get_platdata(struct device *dev,
if (usb_get_maximum_speed(dev) == USB_SPEED_FULL)
platdata->flags |= CI_HDRC_FORCE_FULLSPEED;
- if (of_find_property(dev->of_node, "phy-clkgate-delay-us", NULL))
- of_property_read_u32(dev->of_node, "phy-clkgate-delay-us",
+ of_property_read_u32(dev->of_node, "phy-clkgate-delay-us",
&platdata->phy_clkgate_delay_us);
platdata->itc_setting = 1;
- if (of_find_property(dev->of_node, "itc-setting", NULL)) {
- ret = of_property_read_u32(dev->of_node, "itc-setting",
- &platdata->itc_setting);
- if (ret) {
- dev_err(dev,
- "failed to get itc-setting\n");
- return ret;
- }
- }
- if (of_find_property(dev->of_node, "ahb-burst-config", NULL)) {
- ret = of_property_read_u32(dev->of_node, "ahb-burst-config",
- &platdata->ahb_burst_config);
- if (ret) {
- dev_err(dev,
- "failed to get ahb-burst-config\n");
- return ret;
- }
+ of_property_read_u32(dev->of_node, "itc-setting",
+ &platdata->itc_setting);
+
+ ret = of_property_read_u32(dev->of_node, "ahb-burst-config",
+ &platdata->ahb_burst_config);
+ if (!ret) {
platdata->flags |= CI_HDRC_OVERRIDE_AHB_BURST;
+ } else if (ret != -EINVAL) {
+ dev_err(dev, "failed to get ahb-burst-config\n");
+ return ret;
}
- if (of_find_property(dev->of_node, "tx-burst-size-dword", NULL)) {
- ret = of_property_read_u32(dev->of_node, "tx-burst-size-dword",
- &platdata->tx_burst_size);
- if (ret) {
- dev_err(dev,
- "failed to get tx-burst-size-dword\n");
- return ret;
- }
+ ret = of_property_read_u32(dev->of_node, "tx-burst-size-dword",
+ &platdata->tx_burst_size);
+ if (!ret) {
platdata->flags |= CI_HDRC_OVERRIDE_TX_BURST;
+ } else if (ret != -EINVAL) {
+ dev_err(dev, "failed to get tx-burst-size-dword\n");
+ return ret;
}
- if (of_find_property(dev->of_node, "rx-burst-size-dword", NULL)) {
- ret = of_property_read_u32(dev->of_node, "rx-burst-size-dword",
- &platdata->rx_burst_size);
- if (ret) {
- dev_err(dev,
- "failed to get rx-burst-size-dword\n");
- return ret;
- }
+ ret = of_property_read_u32(dev->of_node, "rx-burst-size-dword",
+ &platdata->rx_burst_size);
+ if (!ret) {
platdata->flags |= CI_HDRC_OVERRIDE_RX_BURST;
+ } else if (ret != -EINVAL) {
+ dev_err(dev, "failed to get rx-burst-size-dword\n");
+ return ret;
}
ext_id = ERR_PTR(-ENODEV);
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c
index 58c8485a0..df47110ba 100644
--- a/drivers/usb/chipidea/debug.c
+++ b/drivers/usb/chipidea/debug.c
@@ -15,7 +15,6 @@
#include "ci.h"
#include "udc.h"
#include "bits.h"
-#include "debug.h"
#include "otg.h"
/**
@@ -101,6 +100,9 @@ static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf,
if (sscanf(buf, "%u", &mode) != 1)
return -EINVAL;
+ if (mode > 255)
+ return -EBADRQC;
+
pm_runtime_get_sync(ci->dev);
spin_lock_irqsave(&ci->lock, flags);
ret = hw_port_test_set(ci, mode);
diff --git a/drivers/usb/chipidea/debug.h b/drivers/usb/chipidea/debug.h
deleted file mode 100644
index e16478c4a..000000000
--- a/drivers/usb/chipidea/debug.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * debug.h - ChipIdea USB driver debug interfaces
- *
- * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
- *
- * Author: David Lopo
- *
- * This program 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 __DRIVERS_USB_CHIPIDEA_DEBUG_H
-#define __DRIVERS_USB_CHIPIDEA_DEBUG_H
-
-#ifdef CONFIG_USB_CHIPIDEA_DEBUG
-int dbg_create_files(struct ci_hdrc *ci);
-void dbg_remove_files(struct ci_hdrc *ci);
-#else
-static inline int dbg_create_files(struct ci_hdrc *ci)
-{
- return 0;
-}
-
-static inline void dbg_remove_files(struct ci_hdrc *ci)
-{
-}
-#endif
-
-#endif /* __DRIVERS_USB_CHIPIDEA_DEBUG_H */
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 3d2430440..053bac9d9 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -190,6 +190,8 @@ static void host_stop(struct ci_hdrc *ci)
(ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON))
regulator_disable(ci->platdata->reg_vbus);
}
+ ci->hcd = NULL;
+ ci->otg.host = NULL;
}
diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c
index 00ab59d45..ba90dc667 100644
--- a/drivers/usb/chipidea/otg_fsm.c
+++ b/drivers/usb/chipidea/otg_fsm.c
@@ -485,20 +485,30 @@ static void ci_otg_loc_conn(struct otg_fsm *fsm, int on)
/*
* Generate SOF by host.
- * This is controlled through suspend/resume the port.
* In host mode, controller will automatically send SOF.
* Suspend will block the data on the port.
+ *
+ * This is controlled through usbcore by usb autosuspend,
+ * so the usb device class driver need support autosuspend,
+ * otherwise the bus suspend will not happen.
*/
static void ci_otg_loc_sof(struct otg_fsm *fsm, int on)
{
- struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
+ struct usb_device *udev;
- if (on)
- hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_FPR,
- PORTSC_FPR);
- else
- hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_SUSP,
- PORTSC_SUSP);
+ if (!fsm->otg->host)
+ return;
+
+ udev = usb_hub_find_child(fsm->otg->host->root_hub, 1);
+ if (!udev)
+ return;
+
+ if (on) {
+ usb_disable_autosuspend(udev);
+ } else {
+ pm_runtime_set_autosuspend_delay(&udev->dev, 0);
+ usb_enable_autosuspend(udev);
+ }
}
/*
diff --git a/drivers/usb/chipidea/otg_fsm.h b/drivers/usb/chipidea/otg_fsm.h
index 2689375ae..262d6ef8d 100644
--- a/drivers/usb/chipidea/otg_fsm.h
+++ b/drivers/usb/chipidea/otg_fsm.h
@@ -62,7 +62,7 @@
/* SSEND time before SRP */
#define TB_SSEND_SRP (1500) /* minimum 1.5 sec, section:5.1.2 */
-#ifdef CONFIG_USB_OTG_FSM
+#if IS_ENABLED(CONFIG_USB_OTG_FSM)
int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci);
int ci_otg_fsm_work(struct ci_hdrc *ci);
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 391a1225b..3eafa2c9a 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -26,7 +26,6 @@
#include "ci.h"
#include "udc.h"
#include "bits.h"
-#include "debug.h"
#include "otg.h"
#include "otg_fsm.h"
@@ -349,14 +348,13 @@ static int add_td_to_list(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq,
if (node == NULL)
return -ENOMEM;
- node->ptr = dma_pool_alloc(hwep->td_pool, GFP_ATOMIC,
+ node->ptr = dma_pool_zalloc(hwep->td_pool, GFP_ATOMIC,
&node->dma);
if (node->ptr == NULL) {
kfree(node);
return -ENOMEM;
}
- memset(node->ptr, 0, sizeof(struct ci_hw_td));
node->ptr->token = cpu_to_le32(length << __ffs(TD_TOTAL_BYTES));
node->ptr->token &= cpu_to_le32(TD_TOTAL_BYTES);
node->ptr->token |= cpu_to_le32(TD_STATUS_ACTIVE);
@@ -404,9 +402,9 @@ static inline u8 _usb_addr(struct ci_hw_ep *ep)
}
/**
- * _hardware_queue: configures a request at hardware level
- * @gadget: gadget
+ * _hardware_enqueue: configures a request at hardware level
* @hwep: endpoint
+ * @hwreq: request
*
* This function returns an error code
*/
@@ -435,19 +433,28 @@ static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
if (hwreq->req.dma % PAGE_SIZE)
pages--;
- if (rest == 0)
- add_td_to_list(hwep, hwreq, 0);
+ if (rest == 0) {
+ ret = add_td_to_list(hwep, hwreq, 0);
+ if (ret < 0)
+ goto done;
+ }
while (rest > 0) {
unsigned count = min(hwreq->req.length - hwreq->req.actual,
(unsigned)(pages * CI_HDRC_PAGE_SIZE));
- add_td_to_list(hwep, hwreq, count);
+ ret = add_td_to_list(hwep, hwreq, count);
+ if (ret < 0)
+ goto done;
+
rest -= count;
}
if (hwreq->req.zero && hwreq->req.length && hwep->dir == TX
- && (hwreq->req.length % hwep->ep.maxpacket == 0))
- add_td_to_list(hwep, hwreq, 0);
+ && (hwreq->req.length % hwep->ep.maxpacket == 0)) {
+ ret = add_td_to_list(hwep, hwreq, 0);
+ if (ret < 0)
+ goto done;
+ }
firstnode = list_first_entry(&hwreq->tds, struct td_node, td);
@@ -788,8 +795,12 @@ static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
/**
* _ep_queue: queues (submits) an I/O request to an endpoint
+ * @ep: endpoint
+ * @req: request
+ * @gfp_flags: GFP flags (not used)
*
* Caller must hold lock
+ * This function returns an error code
*/
static int _ep_queue(struct usb_ep *ep, struct usb_request *req,
gfp_t __maybe_unused gfp_flags)