From e46fed9fb3a12b1070e2cc5ad03a21b84f94408d Mon Sep 17 00:00:00 2001 From: "Felipe F. Tonello" Date: Fri, 18 Sep 2015 18:30:19 +0100 Subject: usb: chipidea: udc: _ep_queue and _hw_queue cleanup Update comments to reflect current state of functions. Signed-off-by: Felipe F. Tonello Signed-off-by: Peter Chen diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index b292b45..d917b3f 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -403,9 +403,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 */ @@ -787,8 +787,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) -- cgit v0.10.2 From 779debdf26d4b49598e61e0c28ac97146a2b96fe Mon Sep 17 00:00:00 2001 From: "Felipe F. Tonello" Date: Tue, 27 Oct 2015 10:36:32 +0000 Subject: usb: chipidea: udc: improve error handling on _hardware_enqueue _hardware_enqueue() didn't check for errors when using add_td_to_list() which can fail if dma_pool_alloc fails, thus causing a kernel panic when lastnode->ptr is NULL. Signed-off-by: Felipe F. Tonello Signed-off-by: Peter Chen diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index d917b3f..b1e7b71 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -434,19 +434,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); -- cgit v0.10.2 From 9d8c850d02b01f3e0157a8f9859fe3f04cab68fe Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Fri, 23 Oct 2015 10:33:58 +0800 Subject: usb: chipidea: support debugfs without CONFIG_USB_CHIPIDEA_DEBUG Since we need to mount debugfs to show/store the things we want to debug, it is duplicated to add another configuration to enable it. Meanwhile, with CONFIG_USB_CHIPIDEA_DEBUG, we can't support chipidea debugfs at runtime. Signed-off-by: Peter Chen Cc: Jun Li diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile index 4decb12..c437d5f 100644 --- a/drivers/usb/chipidea/Makefile +++ b/drivers/usb/chipidea/Makefile @@ -2,10 +2,9 @@ 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 41d7cf6..cd41455 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/core.c b/drivers/usb/chipidea/core.c index 965d0e2..18e77e0 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -71,7 +71,6 @@ #include "udc.h" #include "bits.h" #include "host.h" -#include "debug.h" #include "otg.h" #include "otg_fsm.h" diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index 58c8485..a4f7db2 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" /** diff --git a/drivers/usb/chipidea/debug.h b/drivers/usb/chipidea/debug.h deleted file mode 100644 index e16478c..0000000 --- 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/udc.c b/drivers/usb/chipidea/udc.c index b1e7b71..3eafa2c 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" -- cgit v0.10.2 From 383da2450c7150b4c470dab3759ab86532c65b78 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Tue, 27 Oct 2015 16:08:30 +0800 Subject: usb: chipidea: delete static debug support Since we have dynamic debug support, delete static debug for chipidea Signed-off-by: Peter Chen diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig index 5619b8c..3644a35 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 c437d5f..518e445 100644 --- a/drivers/usb/chipidea/Makefile +++ b/drivers/usb/chipidea/Makefile @@ -1,5 +1,3 @@ -ccflags-$(CONFIG_USB_CHIPIDEA_DEBUG) := -DDEBUG - obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc.o ci_hdrc-y := core.o otg.o debug.o -- cgit v0.10.2 From 3a35d59a69398b3b522d449404669624486d2b68 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Tue, 3 Nov 2015 16:21:20 +0800 Subject: usb: chipidea: clean up CONFIG_USB_CHIPIDEA_DEBUG reference Since this configuration option has deleted, cleans up all its references. Signed-off-by: Peter Chen Reported-by: Valentin Rothberg diff --git a/Documentation/usb/chipidea.txt b/Documentation/usb/chipidea.txt index 3f848c1..05f735a 100644 --- a/Documentation/usb/chipidea.txt +++ b/Documentation/usb/chipidea.txt @@ -7,8 +7,8 @@ with 2 Freescale i.MX6Q sabre SD boards. --------------------------------------- Select CONFIG_USB_OTG_FSM, rebuild kernel Image and modules. If you want to check some internal variables for otg fsm, -select CONFIG_USB_CHIPIDEA_DEBUG, there are 2 files which -can show otg fsm variables and some controller registers value: +mount debugfs, there are 2 files which can show otg fsm +variables and some controller registers value: cat /sys/kernel/debug/ci_hdrc.0/otg cat /sys/kernel/debug/ci_hdrc.0/registers diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 18e77e0..3a237d0 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 -- cgit v0.10.2 From b09b5224fe86b3c9adef1bd9f0bd81800e8ff0b3 Mon Sep 17 00:00:00 2001 From: Andreas Fenkart Date: Thu, 12 Nov 2015 14:14:40 +0100 Subject: usb: chipidea: implement platform shutdown callback disable wakeup irq during shutdown, otherwise kexec fails for kernels that setup irq handlers before resetting the hardware Signed-off-by: Andreas Fenkart Signed-off-by: Peter Chen diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index 5a048b7..f14f4ab 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, -- cgit v0.10.2 From 4b19b78aa6f1f57a997d93fa05df6724792a85ba Mon Sep 17 00:00:00 2001 From: Saurabh Sengar Date: Wed, 18 Nov 2015 09:40:12 +0530 Subject: usb: chipidea: removing of_find_property call to of_find_property() before of_property_read_u32() is unnecessary. of_property_read_u32() anyway calls to of_find_property() only. Signed-off-by: Saurabh Sengar Signed-off-by: Peter Chen diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 3a237d0..7404064 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -686,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); -- cgit v0.10.2 From 43a404577a93d236913b67e41758adf5b9a8f45d Mon Sep 17 00:00:00 2001 From: Li Jun Date: Tue, 15 Dec 2015 17:47:47 +0800 Subject: usb: chipidea: host: set host to be null after hcd is freed Set ci->hcd and ci->otg.host to be null in host_stop since the hcd already freed. Signed-off-by: Li Jun Signed-off-by: Peter Chen diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 3d24304..053bac9 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; } -- cgit v0.10.2 From 8c100e74409ad3bbcb8a1ccdff4540fc0aa7a0fc Mon Sep 17 00:00:00 2001 From: Li Jun Date: Tue, 15 Dec 2015 17:51:29 +0800 Subject: usb: chipidea: otg: use usb autosuspend to suspend bus for HNP Directly manipulate the controller regsiter to suspend the usb bus for HNP is not the proper way, this should be done through the usbcore by usb autosuspend. So to start HNP, autosuspend support should be added for OTG devices interface driver if it's not enabled. Signed-off-by: Li Jun Signed-off-by: Peter Chen diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c index 00ab59d..ba90dc6 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); + } } /* -- cgit v0.10.2