From 32540ba237411244f04ef783bf0fa61041ab592d Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sat, 19 Dec 2015 00:34:31 +0800 Subject: usb: chipidea: debug: use list_for_each_entry Use list_for_each_entry() instead of list_for_each() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/debug.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/usb/chipidea') diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index a4f7db2e18dd..de5c5092d078 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c @@ -172,7 +172,6 @@ static int ci_requests_show(struct seq_file *s, void *data) { struct ci_hdrc *ci = s->private; unsigned long flags; - struct list_head *ptr = NULL; struct ci_hw_req *req = NULL; struct td_node *node, *tmpnode; unsigned i, j, qsize = sizeof(struct ci_hw_td)/sizeof(u32); @@ -184,9 +183,7 @@ static int ci_requests_show(struct seq_file *s, void *data) spin_lock_irqsave(&ci->lock, flags); for (i = 0; i < ci->hw_ep_max; i++) - list_for_each(ptr, &ci->ci_hw_ep[i].qh.queue) { - req = list_entry(ptr, struct ci_hw_req, queue); - + list_for_each_entry(req, &ci->ci_hw_ep[i].qh.queue, queue) { list_for_each_entry_safe(node, tmpnode, &req->tds, td) { seq_printf(s, "EP=%02i: TD=%08X %s\n", i % (ci->hw_ep_max / 2), -- cgit v1.2.3 From 3c724888d2b1e085cd45343dee5f233aec705439 Mon Sep 17 00:00:00 2001 From: Alan Date: Mon, 15 Feb 2016 19:09:46 +0000 Subject: chipidea: error on overflow for port_test_write The write value is 8bit, but currently writing a larger number (eg a doubled digit) is not errored but instead gets cast and sets off an action probably undesired. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/debug.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/usb/chipidea') diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index de5c5092d078..6d23eede4d8c 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c @@ -100,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); -- cgit v1.2.3 From 81345722a55be4af2afdabd724e73ac491265d7a Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 29 Dec 2015 16:41:08 +0000 Subject: usb: chipidea: add CI_HDRC_TURN_VBUS_EARLY_ON for imx23 Until now the imx23 uses the imx27 platform flag. But the imx23 needs the flag CI_HDRC_TURN_VBUS_EARLY_ON, too. So fix this by adding a separate platform flag. Suggested-by: Peter Chen Signed-off-by: Stefan Wahren Signed-off-by: Peter Chen --- drivers/usb/chipidea/ci_hdrc_imx.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/usb/chipidea') diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index f14f4ab47ebb..b4605dd14d15 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -28,6 +28,11 @@ struct ci_hdrc_imx_platform_flag { bool runtime_pm; }; +static const struct ci_hdrc_imx_platform_flag imx23_usb_data = { + .flags = CI_HDRC_TURN_VBUS_EARLY_ON | + CI_HDRC_DISABLE_STREAMING, +}; + static const struct ci_hdrc_imx_platform_flag imx27_usb_data = { CI_HDRC_DISABLE_STREAMING, }; @@ -66,6 +71,7 @@ static const struct ci_hdrc_imx_platform_flag imx7d_usb_data = { }; static const struct of_device_id ci_hdrc_imx_dt_ids[] = { + { .compatible = "fsl,imx23-usb", .data = &imx23_usb_data}, { .compatible = "fsl,imx28-usb", .data = &imx28_usb_data}, { .compatible = "fsl,imx27-usb", .data = &imx27_usb_data}, { .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data}, -- cgit v1.2.3 From 34d5732dd61f65143098a949fd3dc15af9a112cc Mon Sep 17 00:00:00 2001 From: Li Jun Date: Thu, 21 Jan 2016 15:39:14 +0800 Subject: usb: chipidea: udc: remove unused value assignment retval is assigned to be -EOVERFLOW but is overwritten later before it's used, remove this unused value assignment. Signed-off-by: Li Jun Signed-off-by: Peter Chen --- drivers/usb/chipidea/udc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/usb/chipidea') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 3eafa2c9a2ba..00250ab38ddb 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -819,7 +819,6 @@ static int _ep_queue(struct usb_ep *ep, struct usb_request *req, ci->ep0out : ci->ep0in; if (!list_empty(&hwep->qh.queue)) { _ep_nuke(hwep); - retval = -EOVERFLOW; dev_warn(hwep->ci->dev, "endpoint ctrl %X nuked\n", _usb_addr(hwep)); } -- cgit v1.2.3 From aa7381876cf74d77fd48cb9569444f905cdb31c8 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Mon, 1 Feb 2016 14:23:44 +0800 Subject: usb: chipidea: add system interface for ttctrl.ttha In chipidea IP RTL, there is a very limited design for siTD, the detail like below: There is no Max Packet Size at siTD, so it uses one constant for both Max Packet Size for packet and the packet size for the last transaction when considering schedule. If the ttctrl.ttha does not match against Hub Address field in siTD, this constant is 188 bytes, else this constant is 1023 bytes. If the ttctrl.ttha is non-zero value, RTL will use 188 as this constant, so it will lose the data if the packet size is larger than 188 bytes, eg, if we playback a wav which format is 48khz, 16 bits, 2 channels, the packet size will be 192bytes, but the controller will only send 188 bytes for this packet, the noise will be heared using USB audio card. The use case is single transaction, but higher frame rate. If the ttctr.ttha is zero value, we can send 1023 bytes within one transaction, but the controller will not accept the coming tranaction if it considers the schedule time is less than 1023 bytes. So the limitation is we can't schedule as many as transactions within frame. If the total bytes is already 256 bytes for previous transactions within frame, it can't accept another transaction. The use case is multiple transactions, but less frame rate. Signed-off-by: Peter Chen --- drivers/usb/chipidea/core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/usb/chipidea') diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 7404064b9bbc..69426e644d17 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -721,6 +721,9 @@ static int ci_get_platdata(struct device *dev, return ret; } + if (of_find_property(dev->of_node, "non-zero-ttctrl-ttha", NULL)) + platdata->flags |= CI_HDRC_SET_NON_ZERO_TTHA; + ext_id = ERR_PTR(-ENODEV); ext_vbus = ERR_PTR(-ENODEV); if (of_property_read_bool(dev->of_node, "extcon")) { -- cgit v1.2.3 From 1bc7da87c7410c6990c3251589e3854e64c55af2 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Fri, 29 Jan 2016 16:47:24 +0800 Subject: Revert "usb: chipidea: imx: enable CI_HDRC_SET_NON_ZERO_TTHA" This reverts commit e765bfb73ff7. In the most of cases, we only use one transaction per frame and the frame rate may be high, If the platforms want to support multiple transactions but less frame rate cases like [1] and [2], it can set "non-zero-ttctrl-ttha" at dts. [1] http://www.spinics.net/lists/linux-usb/msg123125.html [2] http://www.spinics.net/lists/linux-usb/msg118679.html Signed-off-by: Peter Chen --- drivers/usb/chipidea/ci_hdrc_imx.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/usb/chipidea') diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index b4605dd14d15..1622b0dbc25a 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -250,7 +250,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) struct ci_hdrc_platform_data pdata = { .name = dev_name(&pdev->dev), .capoffset = DEF_CAPOFFSET, - .flags = CI_HDRC_SET_NON_ZERO_TTHA, }; int ret; const struct of_device_id *of_id; -- cgit v1.2.3 From d3d8425a21ed1b14bc896f827ee495e06bff2504 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 27 Jan 2016 16:55:45 -0800 Subject: usb: chipidea: imx: avoid EPROBE_DEFER printed as error Avoid printing an error if adding the device failes with return value EPROBE_DEFFER. This may happen e.g. due to missing GPIO for the vbus-supply regulator. Signed-off-by: Stefan Agner Signed-off-by: Peter Chen --- drivers/usb/chipidea/ci_hdrc_imx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/usb/chipidea') diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index 1622b0dbc25a..9ce8c9f91674 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -307,9 +307,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) &pdata); if (IS_ERR(data->ci_pdev)) { ret = PTR_ERR(data->ci_pdev); - dev_err(&pdev->dev, - "Can't register ci_hdrc platform device, err=%d\n", - ret); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "ci_hdrc_add_device failed, err=%d\n", ret); goto err_clk; } -- cgit v1.2.3 From d6da40af0ead4dc6cb69071c1ec44a823144927d Mon Sep 17 00:00:00 2001 From: Li Jun Date: Fri, 19 Feb 2016 10:04:43 +0800 Subject: usb: chipidea: udc: bypass otg status selector handling to gadget driver Since gadget driver will handle this request, so controller driver bypass it. Acked-by: Peter Chen Signed-off-by: Li Jun Signed-off-by: Felipe Balbi --- drivers/usb/chipidea/udc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/usb/chipidea') diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 00250ab38ddb..065f5d97aa67 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1067,7 +1067,8 @@ __acquires(ci->lock) } break; case USB_REQ_GET_STATUS: - if (type != (USB_DIR_IN|USB_RECIP_DEVICE) && + if ((type != (USB_DIR_IN|USB_RECIP_DEVICE) || + le16_to_cpu(req.wIndex) == OTG_STS_SELECTOR) && type != (USB_DIR_IN|USB_RECIP_ENDPOINT) && type != (USB_DIR_IN|USB_RECIP_INTERFACE)) goto delegate; -- cgit v1.2.3 From 2dfb46be1a231888e8d51b97573f592e408d5199 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Fri, 19 Feb 2016 10:04:45 +0800 Subject: usb: chipidea: otg: set host_request_flag for gadget Set host_request_flag if the current peripheral wants to take host role via changing a_bus_req or b_bus_req by user application. Acked-by: Peter Chen Signed-off-by: Li Jun Signed-off-by: Felipe Balbi --- drivers/usb/chipidea/otg_fsm.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/usb/chipidea') diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c index ba90dc66703d..cb28e763f0b8 100644 --- a/drivers/usb/chipidea/otg_fsm.c +++ b/drivers/usb/chipidea/otg_fsm.c @@ -66,6 +66,11 @@ set_a_bus_req(struct device *dev, struct device_attribute *attr, return count; } ci->fsm.a_bus_req = 1; + if (ci->fsm.otg->state == OTG_STATE_A_PERIPHERAL) { + ci->gadget.host_request_flag = 1; + mutex_unlock(&ci->fsm.lock); + return count; + } } ci_otg_queue_work(ci); @@ -144,8 +149,14 @@ set_b_bus_req(struct device *dev, struct device_attribute *attr, mutex_lock(&ci->fsm.lock); if (buf[0] == '0') ci->fsm.b_bus_req = 0; - else if (buf[0] == '1') + else if (buf[0] == '1') { ci->fsm.b_bus_req = 1; + if (ci->fsm.otg->state == OTG_STATE_B_PERIPHERAL) { + ci->gadget.host_request_flag = 1; + mutex_unlock(&ci->fsm.lock); + return count; + } + } ci_otg_queue_work(ci); mutex_unlock(&ci->fsm.lock); -- cgit v1.2.3 From 75d2f754e2d8937890336803ae27e3503f192705 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Fri, 19 Feb 2016 10:04:46 +0800 Subject: usb: chipidea: otg: enable HNP polling support for gadget and host Enable HNP polling support for chipidea gadget and allocate memory for host request flag when otg fsm init. Acked-by: Peter Chen Signed-off-by: Li Jun Signed-off-by: Felipe Balbi --- drivers/usb/chipidea/otg_fsm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/usb/chipidea') diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c index cb28e763f0b8..9a963a749467 100644 --- a/drivers/usb/chipidea/otg_fsm.c +++ b/drivers/usb/chipidea/otg_fsm.c @@ -797,6 +797,10 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci) ci->fsm.id = hw_read_otgsc(ci, OTGSC_ID) ? 1 : 0; ci->fsm.otg->state = OTG_STATE_UNDEFINED; ci->fsm.ops = &ci_otg_ops; + ci->gadget.hnp_polling_support = 1; + ci->fsm.host_req_flag = devm_kzalloc(ci->dev, 1, GFP_KERNEL); + if (!ci->fsm.host_req_flag) + return -ENOMEM; mutex_init(&ci->fsm.lock); -- cgit v1.2.3 From 4a75754751a02cd12cd598e02ded226c3ea2fc23 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Fri, 19 Feb 2016 10:04:49 +0800 Subject: usb: chipidea: otg: add A idle to B disconnect timer B-device detects that bus is idle for more than TB_AIDL_BDIS min and begins HNP by turning off pullup on DP, this allows the bus to discharge to the SE0 state. This timer was missed and failed with PET test: 6.8.5 B-UUT HNP of USB OTG and EH automated compliance plan v1.2, this patch is to fix this timing issue. Acked-by: Peter Chen Signed-off-by: Li Jun Signed-off-by: Felipe Balbi --- drivers/usb/chipidea/otg_fsm.c | 12 ++++++++++-- drivers/usb/chipidea/otg_fsm.h | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/usb/chipidea') diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c index 9a963a749467..de8e22ec3902 100644 --- a/drivers/usb/chipidea/otg_fsm.c +++ b/drivers/usb/chipidea/otg_fsm.c @@ -209,6 +209,7 @@ static unsigned otg_timer_ms[] = { TA_AIDL_BDIS, TB_ASE0_BRST, TA_BIDL_ADIS, + TB_AIDL_BDIS, TB_SE0_SRP, TB_SRP_FAIL, 0, @@ -320,6 +321,12 @@ static int a_bidl_adis_tmout(struct ci_hdrc *ci) return 0; } +static int b_aidl_bdis_tmout(struct ci_hdrc *ci) +{ + ci->fsm.a_bus_suspend = 1; + return 0; +} + static int b_se0_srp_tmout(struct ci_hdrc *ci) { ci->fsm.b_se0_srp = 1; @@ -364,6 +371,7 @@ static int (*otg_timer_handlers[])(struct ci_hdrc *) = { a_aidl_bdis_tmout, /* A_AIDL_BDIS */ b_ase0_brst_tmout, /* B_ASE0_BRST */ a_bidl_adis_tmout, /* A_BIDL_ADIS */ + b_aidl_bdis_tmout, /* B_AIDL_BDIS */ b_se0_srp_tmout, /* B_SE0_SRP */ b_srp_fail_tmout, /* B_SRP_FAIL */ NULL, /* A_WAIT_ENUM */ @@ -655,9 +663,9 @@ static void ci_otg_fsm_event(struct ci_hdrc *ci) break; case OTG_STATE_B_PERIPHERAL: if ((intr_sts & USBi_SLI) && port_conn && otg_bsess_vld) { - fsm->a_bus_suspend = 1; - ci_otg_queue_work(ci); + ci_otg_add_timer(ci, B_AIDL_BDIS); } else if (intr_sts & USBi_PCI) { + ci_otg_del_timer(ci, B_AIDL_BDIS); if (fsm->a_bus_suspend == 1) fsm->a_bus_suspend = 0; } diff --git a/drivers/usb/chipidea/otg_fsm.h b/drivers/usb/chipidea/otg_fsm.h index 262d6ef8df7c..6366fe398ba6 100644 --- a/drivers/usb/chipidea/otg_fsm.h +++ b/drivers/usb/chipidea/otg_fsm.h @@ -62,6 +62,8 @@ /* SSEND time before SRP */ #define TB_SSEND_SRP (1500) /* minimum 1.5 sec, section:5.1.2 */ +#define TB_AIDL_BDIS (20) /* 4ms ~ 150ms, section 5.2.1 */ + #if IS_ENABLED(CONFIG_USB_OTG_FSM) int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci); -- cgit v1.2.3