diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-01-26 15:36:28 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-01-26 15:36:28 +0100 |
commit | bc46e23c34259c842a138f10acc371e4e2cdb287 (patch) | |
tree | 4f6d6938f824abae24e0bb9c563cf07522a19c89 | |
parent | 6969408de2681e1f9dfaed0b311d067ce3c75474 (diff) | |
parent | e42a5dbb8a3d14f5a35bffa3bf7dcb87883f767a (diff) |
Merge tag 'usb-for-v4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
Felipe writes:
USB: changes for v4.11
Here's the big pull request for the Gadget
API. Again the majority of changes sit in dwc2
driver. Most important changes contain a workaround
for GOTGCTL being wrong, a sleep-inside-spinlock fix
and the big series of cleanups on dwc2.
One important thing on dwc3 is that we don't anymore
need gadget drivers to cope with unaligned OUT
transfers for us. We have support for appending one
extra chained TRB to align transfer ourselves.
Apart from these, the usual set of typos,
non-critical fixes, etc.
65 files changed, 2296 insertions, 2213 deletions
diff --git a/Documentation/devicetree/bindings/usb/dwc3-st.txt b/Documentation/devicetree/bindings/usb/dwc3-st.txt index 01c71b1258f4..50dee3b44665 100644 --- a/Documentation/devicetree/bindings/usb/dwc3-st.txt +++ b/Documentation/devicetree/bindings/usb/dwc3-st.txt @@ -20,10 +20,10 @@ See: Documentation/devicetree/bindings/reset/reset.txt with 'reg' property - pinctl-names : A pinctrl state named "default" must be defined -See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt +See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt - pinctrl-0 : Pin control group -See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt +See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt - ranges : allows valid 1:1 translation between child's address space and parent's address space diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt index e3e6983288e3..f658f394c2d3 100644 --- a/Documentation/devicetree/bindings/usb/dwc3.txt +++ b/Documentation/devicetree/bindings/usb/dwc3.txt @@ -56,6 +56,10 @@ Optional properties: - <DEPRECATED> tx-fifo-resize: determines if the FIFO *has* to be reallocated. + - in addition all properties from usb-xhci.txt from the current directory are + supported as well + + This is usually a subnode to DWC3 glue to which it is connected. dwc3@4a030000 { diff --git a/Documentation/devicetree/bindings/usb/ehci-st.txt b/Documentation/devicetree/bindings/usb/ehci-st.txt index fb45fa5770bb..410d922cfdd7 100644 --- a/Documentation/devicetree/bindings/usb/ehci-st.txt +++ b/Documentation/devicetree/bindings/usb/ehci-st.txt @@ -7,7 +7,7 @@ Required properties: - interrupts : one EHCI interrupt should be described here - pinctrl-names : a pinctrl state named "default" must be defined - pinctrl-0 : phandle referencing pin configuration of the USB controller -See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt +See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt - clocks : phandle list of usb clocks - clock-names : should be "ic" for interconnect clock and "clk48" See: Documentation/devicetree/bindings/clock/clock-bindings.txt diff --git a/Documentation/devicetree/bindings/usb/mt8173-mtu3.txt b/Documentation/devicetree/bindings/usb/mt8173-mtu3.txt index 8c976cdd5776..1d7c3bc677f7 100644 --- a/Documentation/devicetree/bindings/usb/mt8173-mtu3.txt +++ b/Documentation/devicetree/bindings/usb/mt8173-mtu3.txt @@ -30,7 +30,7 @@ Optional properties: "id_float" and "id_ground" are optinal which depends on "mediatek,enable-manual-drd" - pinctrl-0 : pin control group - See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt + See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt - maximum-speed : valid arguments are "super-speed", "high-speed" and "full-speed"; refer to usb/generic.txt diff --git a/Documentation/devicetree/bindings/usb/mt8173-xhci.txt b/Documentation/devicetree/bindings/usb/mt8173-xhci.txt index ab8bb27e854c..0acfc8acbea1 100644 --- a/Documentation/devicetree/bindings/usb/mt8173-xhci.txt +++ b/Documentation/devicetree/bindings/usb/mt8173-xhci.txt @@ -38,7 +38,7 @@ Optional properties: - usb3-lpm-capable : supports USB3.0 LPM - pinctrl-names : a pinctrl state named "default" must be defined - pinctrl-0 : pin control group - See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt + See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt Example: usb30: usb@11270000 { @@ -68,7 +68,7 @@ usb30: usb@11270000 { In the case, xhci is added as subnode to mtu3. An example and the DT binding details of mtu3 can be found in: -Documentation/devicetree/bindings/usb/mtu3.txt +Documentation/devicetree/bindings/usb/mt8173-mtu3.txt Required properties: - compatible : should contain "mediatek,mt8173-xhci" diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.txt b/Documentation/devicetree/bindings/usb/qcom,dwc3.txt index 39acb084bce9..73cc0963e823 100644 --- a/Documentation/devicetree/bindings/usb/qcom,dwc3.txt +++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.txt @@ -18,7 +18,7 @@ A child node must exist to represent the core DWC3 IP block. The name of the node is not important. The content of the node is defined in dwc3.txt. Phy documentation is provided in the following places: -Documentation/devicetree/bindings/phy/qcom,dwc3-usb-phy.txt +Documentation/devicetree/bindings/phy/qcom-dwc3-usb-phy.txt Example device nodes: diff --git a/Documentation/usb/gadget-testing.txt b/Documentation/usb/gadget-testing.txt index 581960574889..fb0cc4df1765 100644 --- a/Documentation/usb/gadget-testing.txt +++ b/Documentation/usb/gadget-testing.txt @@ -632,6 +632,8 @@ The uac2 function provides these attributes in its function directory: p_chmask - playback channel mask p_srate - playback sampling rate p_ssize - playback sample size (bytes) + req_number - the number of pre-allocated request for both capture + and playback The attributes have sane default values. diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 11d8ae9aead1..1b6612c2cdda 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -104,7 +104,7 @@ static int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg) gr = &hsotg->gr_backup; if (!gr->valid) { dev_err(hsotg->dev, "%s: no global registers to restore\n", - __func__); + __func__); return -EINVAL; } gr->valid = false; @@ -155,21 +155,21 @@ int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore) ret = dwc2_restore_global_registers(hsotg); if (ret) { dev_err(hsotg->dev, "%s: failed to restore registers\n", - __func__); + __func__); return ret; } if (dwc2_is_host_mode(hsotg)) { ret = dwc2_restore_host_registers(hsotg); if (ret) { dev_err(hsotg->dev, "%s: failed to restore host registers\n", - __func__); + __func__); return ret; } } else { ret = dwc2_restore_device_registers(hsotg); if (ret) { dev_err(hsotg->dev, "%s: failed to restore device registers\n", - __func__); + __func__); return ret; } } @@ -195,7 +195,7 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg) ret = dwc2_backup_global_registers(hsotg); if (ret) { dev_err(hsotg->dev, "%s: failed to backup global registers\n", - __func__); + __func__); return ret; } @@ -203,14 +203,14 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg) ret = dwc2_backup_host_registers(hsotg); if (ret) { dev_err(hsotg->dev, "%s: failed to backup host registers\n", - __func__); + __func__); return ret; } } else { ret = dwc2_backup_device_registers(hsotg); if (ret) { dev_err(hsotg->dev, "%s: failed to backup device registers\n", - __func__); + __func__); return ret; } } @@ -313,7 +313,7 @@ static bool dwc2_iddig_filter_enabled(struct dwc2_hsotg *hsotg) * Do core a soft reset of the core. Be careful with this because it * resets all the internal state machines of the core. */ -int dwc2_core_reset(struct dwc2_hsotg *hsotg) +int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait) { u32 greset; int count = 0; @@ -369,7 +369,7 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg) } } while (!(greset & GRSTCTL_AHBIDLE)); - if (wait_for_host_mode) + if (wait_for_host_mode && !skip_wait) dwc2_wait_for_mode(hsotg, true); return 0; @@ -455,7 +455,7 @@ void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg) dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG); if (dwc2_iddig_filter_enabled(hsotg)) - usleep_range(100000, 110000); + msleep(100); } /* @@ -500,7 +500,7 @@ int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg) { int retval; - retval = dwc2_core_reset(hsotg); + retval = dwc2_core_reset(hsotg, false); if (retval) return retval; @@ -541,7 +541,7 @@ void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg) addr = hsotg->regs + HAINTMSK; dev_dbg(hsotg->dev, "HAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, dwc2_readl(addr)); - if (hsotg->params.dma_desc_enable > 0) { + if (hsotg->params.dma_desc_enable) { addr = hsotg->regs + HFLBADDR; dev_dbg(hsotg->dev, "HFLBADDR @0x%08lX : 0x%08X\n", (unsigned long)addr, dwc2_readl(addr)); @@ -571,7 +571,7 @@ void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg) addr = hsotg->regs + HCDMA(i); dev_dbg(hsotg->dev, "HCDMA @0x%08lX : 0x%08X\n", (unsigned long)addr, dwc2_readl(addr)); - if (hsotg->params.dma_desc_enable > 0) { + if (hsotg->params.dma_desc_enable) { addr = hsotg->regs + HCDMAB(i); dev_dbg(hsotg->dev, "HCDMAB @0x%08lX : 0x%08X\n", (unsigned long)addr, dwc2_readl(addr)); @@ -751,11 +751,6 @@ bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host) return dwc2_force_mode(hsotg, host); } -u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg) -{ - return hsotg->params.otg_ver == 1 ? 0x0200 : 0x0103; -} - bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg) { if (dwc2_readl(hsotg->regs + GSNPSID) == 0xffffffff) @@ -793,7 +788,7 @@ void dwc2_disable_global_interrupts(struct dwc2_hsotg *hsotg) } /* Returns the controller's GHWCFG2.OTG_MODE. */ -unsigned dwc2_op_mode(struct dwc2_hsotg *hsotg) +unsigned int dwc2_op_mode(struct dwc2_hsotg *hsotg) { u32 ghwcfg2 = dwc2_readl(hsotg->regs + GHWCFG2); @@ -804,7 +799,7 @@ unsigned dwc2_op_mode(struct dwc2_hsotg *hsotg) /* Returns true if the controller is capable of DRD. */ bool dwc2_hw_is_otg(struct dwc2_hsotg *hsotg) { - unsigned op_mode = dwc2_op_mode(hsotg); + unsigned int op_mode = dwc2_op_mode(hsotg); return (op_mode == GHWCFG2_OP_MODE_HNP_SRP_CAPABLE) || (op_mode == GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE) || @@ -814,7 +809,7 @@ bool dwc2_hw_is_otg(struct dwc2_hsotg *hsotg) /* Returns true if the controller is host-only. */ bool dwc2_hw_is_host(struct dwc2_hsotg *hsotg) { - unsigned op_mode = dwc2_op_mode(hsotg); + unsigned int op_mode = dwc2_op_mode(hsotg); return (op_mode == GHWCFG2_OP_MODE_SRP_CAPABLE_HOST) || (op_mode == GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST); @@ -823,7 +818,7 @@ bool dwc2_hw_is_host(struct dwc2_hsotg *hsotg) /* Returns true if the controller is device-only. */ bool dwc2_hw_is_device(struct dwc2_hsotg *hsotg) { - unsigned op_mode = dwc2_op_mode(hsotg); + unsigned int op_mode = dwc2_op_mode(hsotg); return (op_mode == GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) || (op_mode == GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE); diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 302b8f5f7d27..1a7e83005082 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -127,6 +127,8 @@ static const char * const dwc2_hsotg_supply_names[] = { "vusb_a", /* analog USB supply, 1.1V */ }; +#define DWC2_NUM_SUPPLIES ARRAY_SIZE(dwc2_hsotg_supply_names) + /* * EP0_MPS_LIMIT * @@ -246,7 +248,8 @@ struct dwc2_hsotg_req { void *saved_req_buf; }; -#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) +#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \ + IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) #define call_gadget(_hs, _entry) \ do { \ if ((_hs)->gadget.speed != USB_SPEED_UNKNOWN && \ @@ -271,13 +274,6 @@ enum dwc2_lx_state { DWC2_L3, /* Off state */ }; -/* - * Gadget periodic tx fifo sizes as used by legacy driver - * EP0 is not included - */ -#define DWC2_G_P_LEGACY_TX_FIFO_SIZE {256, 256, 256, 256, 768, 768, 768, \ - 768, 0, 0, 0, 0, 0, 0, 0} - /* Gadget ep0 states */ enum dwc2_ep0_state { DWC2_EP0_SETUP, @@ -295,9 +291,6 @@ enum dwc2_ep0_state { * 1 - SRP Only capable * 2 - No HNP/SRP capable (always available) * Defaults to best available option (0, 1, then 2) - * @otg_ver: OTG version supported - * 0 - 1.3 (default) - * 1 - 2.0 * @host_dma: Specifies whether to use slave or DMA mode for accessing * the data FIFOs. The driver will automatically detect the * value for this parameter if none is specified. @@ -444,6 +437,11 @@ enum dwc2_ep0_state { * in DWORDS with possible values from from * 16-32768 (default: 256, 256, 256, 256, 768, * 768, 768, 768, 0, 0, 0, 0, 0, 0, 0). + * @change_speed_quirk: Change speed configuration to DWC2_SPEED_PARAM_FULL + * while full&low speed device connect. And change speed + * back to DWC2_SPEED_PARAM_HIGH while device is gone. + * 0 - No (default) + * 1 - Yes * * The following parameters may be specified when starting the module. These * parameters define how the DWC_otg controller should be configured. A @@ -452,63 +450,48 @@ enum dwc2_ep0_state { * default described above. */ struct dwc2_core_params { - /* - * Don't add any non-int members here, this will break - * dwc2_set_all_params! - */ - int otg_cap; + u8 otg_cap; #define DWC2_CAP_PARAM_HNP_SRP_CAPABLE 0 #define DWC2_CAP_PARAM_SRP_ONLY_CAPABLE 1 #define DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE 2 - int otg_ver; - int dma_desc_enable; - int dma_desc_fs_enable; - int speed; -#define DWC2_SPEED_PARAM_HIGH 0 -#define DWC2_SPEED_PARAM_FULL 1 -#define DWC2_SPEED_PARAM_LOW 2 - - int enable_dynamic_fifo; - int en_multiple_tx_fifo; - int host_rx_fifo_size; - int host_nperio_tx_fifo_size; - int host_perio_tx_fifo_size; - int max_transfer_size; - int max_packet_count; - int host_channels; - int phy_type; + u8 phy_type; #define DWC2_PHY_TYPE_PARAM_FS 0 #define DWC2_PHY_TYPE_PARAM_UTMI 1 #define DWC2_PHY_TYPE_PARAM_ULPI 2 - int phy_utmi_width; - int phy_ulpi_ddr; - int phy_ulpi_ext_vbus; -#define DWC2_PHY_ULPI_INTERNAL_VBUS 0 -#define DWC2_PHY_ULPI_EXTERNAL_VBUS 1 - - int i2c_enable; - int ulpi_fs_ls; - int host_support_fs_ls_low_power; - int host_ls_low_power_phy_clk; -#define DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0 -#define DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1 - - int ts_dline; - int reload_ctl; - int ahbcfg; - int uframe_sched; - int external_id_pin_ctl; - int hibernation; + u8 speed; +#define DWC2_SPEED_PARAM_HIGH 0 +#define DWC2_SPEED_PARAM_FULL 1 +#define DWC2_SPEED_PARAM_LOW 2 - /* - * The following parameters are *only* set via device - * properties and cannot be set directly in this structure. - */ + u8 phy_utmi_width; + bool phy_ulpi_ddr; + bool phy_ulpi_ext_vbus; + bool enable_dynamic_fifo; + bool en_multiple_tx_fifo; + bool i2c_enable; + bool ulpi_fs_ls; + bool ts_dline; + bool reload_ctl; + bool uframe_sched; + bool external_id_pin_ctl; + bool hibernation; + u16 max_packet_count; + u32 max_transfer_size; + u32 ahbcfg; /* Host parameters */ bool host_dma; + bool dma_desc_enable; + bool dma_desc_fs_enable; + bool host_support_fs_ls_low_power; + bool host_ls_low_power_phy_clk; + + u8 host_channels; + u16 host_rx_fifo_size; + u16 host_nperio_tx_fifo_size; + u16 host_perio_tx_fifo_size; /* Gadget parameters */ bool g_dma; @@ -516,6 +499,8 @@ struct dwc2_core_params { u32 g_rx_fifo_size; u32 g_np_tx_fifo_size; u32 g_tx_fifo_size[MAX_EPS_CHANNELS]; + + bool change_speed_quirk; }; /** @@ -603,8 +588,8 @@ struct dwc2_hw_params { #define DWC2_CTRL_BUFF_SIZE 8 /** - * struct dwc2_gregs_backup - Holds global registers state before entering partial - * power down + * struct dwc2_gregs_backup - Holds global registers state before + * entering partial power down * @gotgctl: Backup of GOTGCTL register * @gintmsk: Backup of GINTMSK register * @gahbcfg: Backup of GAHBCFG register @@ -634,8 +619,8 @@ struct dwc2_gregs_backup { }; /** - * struct dwc2_dregs_backup - Holds device registers state before entering partial - * power down + * struct dwc2_dregs_backup - Holds device registers state before + * entering partial power down * @dcfg: Backup of DCFG register * @dctl: Backup of DCTL register * @daintmsk: Backup of DAINTMSK register @@ -664,8 +649,8 @@ struct dwc2_dregs_backup { }; /** - * struct dwc2_hregs_backup - Holds host registers state before entering partial - * power down + * struct dwc2_hregs_backup - Holds host registers state before + * entering partial power down * @hcfg: Backup of HCFG register * @haintmsk: Backup of HAINTMSK register * @hcintmsk: Backup of HCINTMSK register @@ -782,9 +767,10 @@ struct dwc2_hregs_backup { * @gadget_enabled Peripheral mode sub-driver initialization indicator. * @ll_hw_enabled Status of low-level hardware resources. * @phy: The otg phy transceiver structure for phy control. - * @uphy: The otg phy transceiver structure for old USB phy control. - * @plat: The platform specific configuration data. This can be removed once - * all SoCs support usb transceiver. + * @uphy: The otg phy transceiver structure for old USB phy + * control. + * @plat: The platform specific configuration data. This can be + * removed once all SoCs support usb transceiver. * @supplies: Definition of USB power supplies * @phyif: PHY interface width * @lock: Spinlock that protects all the driver data structures @@ -921,7 +907,7 @@ struct dwc2_hsotg { struct phy *phy; struct usb_phy *uphy; struct dwc2_hsotg_plat *plat; - struct regulator_bulk_data supplies[ARRAY_SIZE(dwc2_hsotg_supply_names)]; + struct regulator_bulk_data supplies[DWC2_NUM_SUPPLIES]; u32 phyif; spinlock_t lock; @@ -947,6 +933,7 @@ struct dwc2_hsotg { /* DWC OTG HW Release versions */ #define DWC2_CORE_REV_2_71a 0x4f54271a #define DWC2_CORE_REV_2_90a 0x4f54290a +#define DWC2_CORE_REV_2_91a 0x4f54291a #define DWC2_CORE_REV_2_92a 0x4f54292a #define DWC2_CORE_REV_2_94a 0x4f54294a #define DWC2_CORE_REV_3_00a 0x4f54300a @@ -1033,7 +1020,8 @@ struct dwc2_hsotg { #endif #endif /* CONFIG_USB_DWC2_HOST || CONFIG_USB_DWC2_DUAL_ROLE */ -#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) +#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \ + IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) /* Gadget structures */ struct usb_gadget_driver *driver; int fifo_mem; @@ -1101,37 +1089,37 @@ static inline bool dwc2_is_hs_iot(struct dwc2_hsotg *hsotg) * The following functions support initialization of the core driver component * and the DWC_otg controller */ -extern int dwc2_core_reset(struct dwc2_hsotg *hsotg); -extern int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg); -extern int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg); -extern int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore); +int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait); +int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg); +int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg); +int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore); bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host); void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg); void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg); -extern bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg); +bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg); /* * Common core Functions. * The following functions support managing the DWC_otg controller in either * device or host mode. */ -extern void dwc2_read_packet(struct dwc2_hsotg *hsotg, u8 *dest, u16 bytes); -extern void dwc2_flush_tx_fifo(struct dwc2_hsotg *hsotg, const int num); -extern void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg); +void dwc2_read_packet(struct dwc2_hsotg *hsotg, u8 *dest, u16 bytes); +void dwc2_flush_tx_fifo(struct dwc2_hsotg *hsotg, const int num); +void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg); -extern void dwc2_enable_global_interrupts(struct dwc2_hsotg *hcd); -extern void dwc2_disable_global_interrupts(struct dwc2_hsotg *hcd); +void dwc2_enable_global_interrupts(struct dwc2_hsotg *hcd); +void dwc2_disable_global_interrupts(struct dwc2_hsotg *hcd); /* This function should be called on every hardware interrupt. */ -extern irqreturn_t dwc2_handle_common_intr(int irq, void *dev); +irqreturn_t dwc2_handle_common_intr(int irq, void *dev); /* The device ID match table */ extern const struct of_device_id dwc2_of_match_table[]; -extern int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg); -extern int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg); +int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg); +int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg); /* Parameters */ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg); @@ -1145,7 +1133,7 @@ int dwc2_init_params(struct dwc2_hsotg *hsotg); * are read in and cached so they always read directly from the * GHWCFG2 register. */ -unsigned dwc2_op_mode(struct dwc2_hsotg *hsotg); +unsigned int dwc2_op_mode(struct dwc2_hsotg *hsotg); bool dwc2_hw_is_otg(struct dwc2_hsotg *hsotg); bool dwc2_hw_is_host(struct dwc2_hsotg *hsotg); bool dwc2_hw_is_device(struct dwc2_hsotg *hsotg); @@ -1157,6 +1145,7 @@ static inline int dwc2_is_host_mode(struct dwc2_hsotg *hsotg) { return (dwc2_readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) != 0; } + static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg) { return (dwc2_readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) == 0; @@ -1165,29 +1154,28 @@ static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg) /* * Dump core registers and SPRAM */ -extern void dwc2_dump_dev_registers(struct dwc2_hsotg *hsotg); -extern void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg); -extern void dwc2_dump_global_registers(struct dwc2_hsotg *hsotg); - -/* - * Return OTG version - either 1.3 or 2.0 - */ -extern u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg); +void dwc2_dump_dev_registers(struct dwc2_hsotg *hsotg); +void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg); +void dwc2_dump_global_registers(struct dwc2_hsotg *hsotg); /* Gadget defines */ -#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) -extern int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg); -extern int dwc2_hsotg_suspend(struct dwc2_hsotg *dwc2); -extern int dwc2_hsotg_resume(struct dwc2_hsotg *dwc2); -extern int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq); -extern void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2, - bool reset); -extern void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg); -extern void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2); -extern int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode); +#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \ + IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) +int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg); +int dwc2_hsotg_suspend(struct dwc2_hsotg *dwc2); +int dwc2_hsotg_resume(struct dwc2_hsotg *dwc2); +int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq); +void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2, + bool reset); +void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg); +void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2); +int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode); #define dwc2_is_device_connected(hsotg) (hsotg->connected) int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg); int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg); +int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg); +int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg); +int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg); #else static inline int dwc2_hsotg_remove(struct dwc2_hsotg *dwc2) { return 0; } @@ -1198,25 +1186,31 @@ static inline int dwc2_hsotg_resume(struct dwc2_hsotg *dwc2) static inline int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) { return 0; } static inline void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2, - bool reset) {} + bool reset) {} static inline void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg) {} static inline void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2) {} static inline int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, - int testmode) + int testmode) { return 0; } #define dwc2_is_device_connected(hsotg) (0) static inline int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) { return 0; } static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg) { return 0; } +static inline int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg) +{ return 0; } +static inline int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg) +{ return 0; } +static inline int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg) +{ return 0; } #endif #if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) -extern int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg); -extern int dwc2_hcd_get_future_frame_number(struct dwc2_hsotg *hsotg, int us); -extern void dwc2_hcd_connect(struct dwc2_hsotg *hsotg); -extern void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, bool force); -extern void dwc2_hcd_start(struct dwc2_hsotg *hsotg); +int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg); +int dwc2_hcd_get_future_frame_number(struct dwc2_hsotg *hsotg, int us); +void dwc2_hcd_connect(struct dwc2_hsotg *hsotg); +void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, bool force); +void dwc2_hcd_start(struct dwc2_hsotg *hsotg); int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg); int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg); #else @@ -1229,7 +1223,7 @@ static inline void dwc2_hcd_connect(struct dwc2_hsotg *hsotg) {} static inline void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, bool force) {} static inline void dwc2_hcd_start(struct dwc2_hsotg *hsotg) {} static inline void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) {} -static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) +static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg) { return 0; } static inline int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg) { return 0; } diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c index 5b228ba6045f..b8bcb007c92a 100644 --- a/drivers/usb/dwc2/core_intr.c +++ b/drivers/usb/dwc2/core_intr.c @@ -159,9 +159,8 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) " ++OTG Interrupt: Session Request Success Status Change++\n"); gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); if (gotgctl & GOTGCTL_SESREQSCS) { - if (hsotg->params.phy_type == - DWC2_PHY_TYPE_PARAM_FS - && hsotg->params.i2c_enable > 0) { + if (hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS && + hsotg->params.i2c_enable) { hsotg->srp_success = 1; } else { /* Clear Session Request */ @@ -317,7 +316,7 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg) dwc2_writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS); dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n", - hsotg->lx_state); + hsotg->lx_state); if (dwc2_is_device_mode(hsotg)) { if (hsotg->lx_state == DWC2_L2) { @@ -437,7 +436,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) /* Ignore suspend request before enumeration */ if (!dwc2_is_device_connected(hsotg)) { dev_dbg(hsotg->dev, - "ignore suspend request before enumeration\n"); + "ignore suspend request before enumeration\n"); return; } @@ -445,7 +444,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) if (ret) { if (ret != -ENOTSUPP) dev_err(hsotg->dev, - "enter hibernation failed\n"); + "enter hibernation failed\n"); goto skip_power_saving; } diff --git a/drivers/usb/dwc2/debug.h b/drivers/usb/dwc2/debug.h index 12dbd1daec87..8222783e6822 100644 --- a/drivers/usb/dwc2/debug.h +++ b/drivers/usb/dwc2/debug.h @@ -17,8 +17,8 @@ #include "core.h" #ifdef CONFIG_DEBUG_FS -extern int dwc2_debugfs_init(struct dwc2_hsotg *); -extern void dwc2_debugfs_exit(struct dwc2_hsotg *); +int dwc2_debugfs_init(struct dwc2_hsotg *hsotg); +void dwc2_debugfs_exit(struct dwc2_hsotg *hsotg); #else static inline int dwc2_debugfs_init(struct dwc2_hsotg *hsotg) { return 0; } diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c index 0a130916a91c..794b959a7c8c 100644 --- a/drivers/usb/dwc2/debugfs.c +++ b/drivers/usb/dwc2/debugfs.c @@ -137,7 +137,7 @@ static int state_show(struct seq_file *seq, void *v) int idx; seq_printf(seq, "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n", - dwc2_readl(regs + DCFG), + dwc2_readl(regs + DCFG), dwc2_readl(regs + DCTL), dwc2_readl(regs + DSTS)); @@ -338,23 +338,23 @@ static void dwc2_hsotg_create_debug(struct dwc2_hsotg *hsotg) { struct dentry *root; struct dentry *file; - unsigned epidx; + unsigned int epidx; root = hsotg->debug_root; /* create general state file */ - file = debugfs_create_file("state", S_IRUGO, root, hsotg, &state_fops); + file = debugfs_create_file("state", 0444, root, hsotg, &state_fops); if (IS_ERR(file)) dev_err(hsotg->dev, "%s: failed to create state\n", __func__); - file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, hsotg, - &testmode_fops); + file = debugfs_create_file("testmode", 0644, root, hsotg, + &testmode_fops); if (IS_ERR(file)) dev_err(hsotg->dev, "%s: failed to create testmode\n", - __func__); + __func__); - file = debugfs_create_file("fifo", S_IRUGO, root, hsotg, &fifo_fops); + file = debugfs_create_file("fifo", 0444, root, hsotg, &fifo_fops); if (IS_ERR(file)) dev_err(hsotg->dev, "%s: failed to create fifo\n", __func__); @@ -364,8 +364,8 @@ static void dwc2_hsotg_create_debug(struct dwc2_hsotg *hsotg) ep = hsotg->eps_out[epidx]; if (ep) { - file = debugfs_create_file(ep->name, S_IRUGO, - root, ep, &ep_fops); + file = debugfs_create_file(ep->name, 0444, + root, ep, &ep_fops); if (IS_ERR(file)) dev_err(hsotg->dev, "failed to create %s debug file\n", ep->name); @@ -377,8 +377,8 @@ static void dwc2_hsotg_create_debug(struct dwc2_hsotg *hsotg) ep = hsotg->eps_in[epidx]; if (ep) { - file = debugfs_create_file(ep->name, S_IRUGO, - root, ep, &ep_fops); + file = debugfs_create_file(ep->name, 0444, + root, ep, &ep_fops); if (IS_ERR(file)) dev_err(hsotg->dev, "failed to create %s debug file\n", ep->name); @@ -725,6 +725,143 @@ static const struct debugfs_reg32 dwc2_regs[] = { dump_register(HCDMAB(15)), }; +#define print_param(_seq, _ptr, _param) \ +seq_printf((_seq), "%-30s: %d\n", #_param, (_ptr)->_param) + +#define print_param_hex(_seq, _ptr, _param) \ +seq_printf((_seq), "%-30s: 0x%x\n", #_param, (_ptr)->_param) + +static int params_show(struct seq_file *seq, void *v) +{ + struct dwc2_hsotg *hsotg = seq->private; + struct dwc2_core_params *p = &hsotg->params; + int i; + + print_param(seq, p, otg_cap); + print_param(seq, p, dma_desc_enable); + print_param(seq, p, dma_desc_fs_enable); + print_param(seq, p, speed); + print_param(seq, p, enable_dynamic_fifo); + print_param(seq, p, en_multiple_tx_fifo); + print_param(seq, p, host_rx_fifo_size); + print_param(seq, p, host_nperio_tx_fifo_size); + print_param(seq, p, host_perio_tx_fifo_size); + print_param(seq, p, max_transfer_size); + print_param(seq, p, max_packet_count); + print_param(seq, p, host_channels); + print_param(seq, p, phy_type); + print_param(seq, p, phy_utmi_width); + print_param(seq, p, phy_ulpi_ddr); + print_param(seq, p, phy_ulpi_ext_vbus); + print_param(seq, p, i2c_enable); + print_param(seq, p, ulpi_fs_ls); + print_param(seq, p, host_support_fs_ls_low_power); + print_param(seq, p, host_ls_low_power_phy_clk); + print_param(seq, p, ts_dline); + print_param(seq, p, reload_ctl); + print_param_hex(seq, p, ahbcfg); + print_param(seq, p, uframe_sched); + print_param(seq, p, external_id_pin_ctl); + print_param(seq, p, hibernation); + print_param(seq, p, host_dma); + print_param(seq, p, g_dma); + print_param(seq, p, g_dma_desc); + print_param(seq, p, g_rx_fifo_size); + print_param(seq, p, g_np_tx_fifo_size); + + for (i = 0; i < MAX_EPS_CHANNELS; i++) { + char str[32]; + + snprintf(str, 32, "g_tx_fifo_size[%d]", i); + seq_printf(seq, "%-30s: %d\n", str, p->g_tx_fifo_size[i]); + } + + return 0; +} + +static int params_open(struct inode *inode, struct file *file) +{ + return single_open(file, params_show, inode->i_private); +} + +static const struct file_operations params_fops = { + .owner = THIS_MODULE, + .open = params_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int hw_params_show(struct seq_file *seq, void *v) +{ + struct dwc2_hsotg *hsotg = seq->private; + struct dwc2_hw_params *hw = &hsotg->hw_params; + + print_param(seq, hw, op_mode); + print_param(seq, hw, arch); + print_param(seq, hw, dma_desc_enable); + print_param(seq, hw, enable_dynamic_fifo); + print_param(seq, hw, en_multiple_tx_fifo); + print_param(seq, hw, rx_fifo_size); + print_param(seq, hw, host_nperio_tx_fifo_size); + print_param(seq, hw, dev_nperio_tx_fifo_size); + print_param(seq, hw, host_perio_tx_fifo_size); + print_param(seq, hw, nperio_tx_q_depth); + print_param(seq, hw, host_perio_tx_q_depth); + print_param(seq, hw, dev_token_q_depth); + print_param(seq, hw, max_transfer_size); + print_param(seq, hw, max_packet_count); + print_param(seq, hw, host_channels); + print_param(seq, hw, hs_phy_type); + print_param(seq, hw, fs_phy_type); + print_param(seq, hw, i2c_enable); + print_param(seq, hw, num_dev_ep); + print_param(seq, hw, num_dev_perio_in_ep); + print_param(seq, hw, total_fifo_size); + print_param(seq, hw, power_optimized); + print_param(seq, hw, utmi_phy_data_width); + print_param_hex(seq, hw, snpsid); + print_param_hex(seq, hw, dev_ep_dirs); + + return 0; +} + +static int hw_params_open(struct inode *inode, struct file *file) +{ + return single_open(file, hw_params_show, inode->i_private); +} + +static const struct file_operations hw_params_fops = { + .owner = THIS_MODULE, + .open = hw_params_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int dr_mode_show(struct seq_file *seq, void *v) +{ + struct dwc2_hsotg *hsotg = seq->private; + const char *dr_mode = ""; + + device_property_read_string(hsotg->dev, "dr_mode", &dr_mode); + seq_printf(seq, "%s\n", dr_mode); + return 0; +} + +static int dr_mode_open(struct inode *inode, struct file *file) +{ + return single_open(file, dr_mode_show, inode->i_private); +} + +static const struct file_operations dr_mode_fops = { + .owner = THIS_MODULE, + .open = dr_mode_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + int dwc2_debugfs_init(struct dwc2_hsotg *hsotg) { int ret; @@ -736,6 +873,25 @@ int dwc2_debugfs_init(struct dwc2_hsotg *hsotg) goto err0; } + file = debugfs_create_file("params", 0444, + hsotg->debug_root, + hsotg, ¶ms_fops); + if (IS_ERR(file)) + dev_err(hsotg->dev, "%s: failed to create params\n", __func__); + + file = debugfs_create_file("hw_params", 0444, + hsotg->debug_root, + hsotg, &hw_params_fops); + if (IS_ERR(file)) + dev_err(hsotg->dev, "%s: failed to create hw_params\n", + __func__); + + file = debugfs_create_file("dr_mode", 0444, + hsotg->debug_root, + hsotg, &dr_mode_fops); + if (IS_ERR(file)) + dev_err(hsotg->dev, "%s: failed to create dr_mode\n", __func__); + /* Add gadget debugfs nodes */ dwc2_hsotg_create_debug(hsotg); @@ -750,8 +906,8 @@ int dwc2_debugfs_init(struct dwc2_hsotg *hsotg) hsotg->regset->nregs = ARRAY_SIZE(dwc2_regs); hsotg->regset->base = hsotg->regs; - file = debugfs_create_regset32("regdump", S_IRUGO, hsotg->debug_root, - hsotg->regset); + file = debugfs_create_regset32("regdump", 0444, hsotg->debug_root, + hsotg->regset); if (!file) { ret = -ENOMEM; goto err1; diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 77c5fcf3a5bf..bc3b3fda5000 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -171,7 +171,7 @@ static void dwc2_hsotg_disable_gsint(struct dwc2_hsotg *hsotg, u32 ints) * request. */ static void dwc2_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg, - unsigned int ep, unsigned int dir_in, + unsigned int ep, unsigned int dir_in, unsigned int en) { unsigned long flags; @@ -192,6 +192,99 @@ static void dwc2_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg, } /** + * dwc2_hsotg_tx_fifo_count - return count of TX FIFOs in device mode + */ +int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg) +{ + if (hsotg->hw_params.en_multiple_tx_fifo) + /* In dedicated FIFO mode we need count of IN EPs */ + return (dwc2_readl(hsotg->regs + GHWCFG4) & + GHWCFG4_NUM_IN_EPS_MASK) >> GHWCFG4_NUM_IN_EPS_SHIFT; + else + /* In shared FIFO mode we need count of Periodic IN EPs */ + return hsotg->hw_params.num_dev_perio_in_ep; +} + +/** + * dwc2_hsotg_ep_info_size - return Endpoint Info Control block size in DWORDs + */ +static int dwc2_hsotg_ep_info_size(struct dwc2_hsotg *hsotg) +{ + int val = 0; + int i; + u32 ep_dirs; + + /* + * Don't need additional space for ep info control registers in + * slave mode. + */ + if (!using_dma(hsotg)) { + dev_dbg(hsotg->dev, "Buffer DMA ep info size 0\n"); + return 0; + } + + /* + * Buffer DMA mode - 1 location per endpoit + * Descriptor DMA mode - 4 locations per endpoint + */ + ep_dirs = hsotg->hw_params.dev_ep_dirs; + + for (i = 0; i <= hsotg->hw_params.num_dev_ep; i++) { + val += ep_dirs & 3 ? 1 : 2; + ep_dirs >>= 2; + } + + if (using_desc_dma(hsotg)) + val = val * 4; + + return val; +} + +/** + * dwc2_hsotg_tx_fifo_total_depth - return total FIFO depth available for + * device mode TX FIFOs + */ +int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg) +{ + int ep_info_size; + int addr; + int tx_addr_max; + u32 np_tx_fifo_size; + + np_tx_fifo_size = min_t(u32, hsotg->hw_params.dev_nperio_tx_fifo_size, + hsotg->params.g_np_tx_fifo_size); + + /* Get Endpoint Info Control block size in DWORDs. */ + ep_info_size = dwc2_hsotg_ep_info_size(hsotg); + tx_addr_max = hsotg->hw_params.total_fifo_size - ep_info_size; + + addr = hsotg->params.g_rx_fifo_size + np_tx_fifo_size; + if (tx_addr_max <= addr) + return 0; + + return tx_addr_max - addr; +} + +/** + * dwc2_hsotg_tx_fifo_average_depth - returns average depth of device mode + * TX FIFOs + */ +int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg) +{ + int tx_fifo_count; + int tx_fifo_depth; + + tx_fifo_depth = dwc2_hsotg_tx_fifo_total_depth(hsotg); + + tx_fifo_count = dwc2_hsotg_tx_fifo_count(hsotg); + + if (!tx_fifo_count) + return tx_fifo_depth; + else + return tx_fifo_depth / tx_fifo_count; +} + +/** * dwc2_hsotg_init_fifo - initialise non-periodic FIFOs * @hsotg: The device instance. */ @@ -241,6 +334,9 @@ static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg) val = dwc2_readl(hsotg->regs + DPTXFSIZN(ep)); } + dwc2_writel(hsotg->hw_params.total_fifo_size | + addr << GDFIFOCFG_EPINFOBASE_SHIFT, + hsotg->regs + GDFIFOCFG); /* * according to p428 of the design guide, we need to ensure that * all fifos are flushed before continuing @@ -277,11 +373,11 @@ static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg) * Allocate a new USB request structure appropriate for the specified endpoint */ static struct usb_request *dwc2_hsotg_ep_alloc_request(struct usb_ep *ep, - gfp_t flags) + gfp_t flags) { struct dwc2_hsotg_req *req; - req = kzalloc(sizeof(struct dwc2_hsotg_req), flags); + req = kzalloc(sizeof(*req), flags); if (!req) return NULL; @@ -312,10 +408,11 @@ static inline int is_ep_periodic(struct dwc2_hsotg_ep *hs_ep) * of a request to ensure the buffer is ready for access by the caller. */ static void dwc2_hsotg_unmap_dma(struct dwc2_hsotg *hsotg, - struct dwc2_hsotg_ep *hs_ep, + struct dwc2_hsotg_ep *hs_ep, struct dwc2_hsotg_req *hs_req) { struct usb_request *req = &hs_req->req; + usb_gadget_unmap_request(&hsotg->gadget, req, hs_ep->dir_in); } @@ -384,7 +481,7 @@ fail: * This routine is only needed for PIO */ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg, - struct dwc2_hsotg_ep *hs_ep, + struct dwc2_hsotg_ep *hs_ep, struct dwc2_hsotg_req *hs_req) { bool periodic = is_ep_periodic(hs_ep); @@ -466,7 +563,7 @@ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg, max_transfer = hs_ep->ep.maxpacket * hs_ep->mc; dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, max_transfer %d\n", - __func__, gnptxsts, can_write, to_write, max_transfer); + __func__, gnptxsts, can_write, to_write, max_transfer); /* * limit to 512 bytes of data, it seems at least on the non-periodic @@ -487,7 +584,7 @@ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg, /* it's needed only when we do not use dedicated fifos */ if (!hsotg->dedicated_fifos) dwc2_hsotg_en_gsint(hsotg, - periodic ? GINTSTS_PTXFEMP : + periodic ? GINTSTS_PTXFEMP : GINTSTS_NPTXFEMP); } @@ -516,12 +613,12 @@ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg, /* it's needed only when we do not use dedicated fifos */ if (!hsotg->dedicated_fifos) dwc2_hsotg_en_gsint(hsotg, - periodic ? GINTSTS_PTXFEMP : + periodic ? GINTSTS_PTXFEMP : GINTSTS_NPTXFEMP); } dev_dbg(hsotg->dev, "write %d/%d, can_write %d, done %d\n", - to_write, hs_req->req.length, can_write, buf_pos); + to_write, hs_req->req.length, can_write, buf_pos); if (to_write <= 0) return -ENOSPC; @@ -547,17 +644,17 @@ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg, * Return the maximum data that can be queued in one go on a given endpoint * so that transfers that are too long can be split. */ -static unsigned get_ep_limit(struct dwc2_hsotg_ep *hs_ep) +static unsigned int get_ep_limit(struct dwc2_hsotg_ep *hs_ep) { int index = hs_ep->index; - unsigned maxsize; - unsigned maxpkt; + unsigned int maxsize; + unsigned int maxpkt; if (index != 0) { maxsize = DXEPTSIZ_XFERSIZE_LIMIT + 1; maxpkt = DXEPTSIZ_PKTCNT_LIMIT + 1; } else { - maxsize = 64+64; + maxsize = 64 + 64; if (hs_ep->dir_in) maxpkt = DIEPTSIZ0_PKTCNT_LIMIT + 1; else @@ -580,11 +677,11 @@ static unsigned get_ep_limit(struct dwc2_hsotg_ep *hs_ep) } /** -* dwc2_hsotg_read_frameno - read current frame number -* @hsotg: The device instance -* -* Return the current frame number -*/ + * dwc2_hsotg_read_frameno - read current frame number + * @hsotg: The device instance + * + * Return the current frame number + */ static u32 dwc2_hsotg_read_frameno(struct dwc2_hsotg *hsotg) { u32 dsts; @@ -874,7 +971,7 @@ static void dwc2_gadget_start_isoc_ddma(struct dwc2_hsotg_ep *hs_ep) * appropriately, and writing any data to the FIFOs. */ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg, - struct dwc2_hsotg_ep *hs_ep, + struct dwc2_hsotg_ep *hs_ep, struct dwc2_hsotg_req *hs_req, bool continuing) { @@ -885,9 +982,9 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg, u32 epsize_reg; u32 epsize; u32 ctrl; - unsigned length; - unsigned packets; - unsigned maxreq; + unsigned int length; + unsigned int packets; + unsigned int maxreq; unsigned int dma_reg; if (index != 0) { @@ -966,7 +1063,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg, if (dir_in && ureq->zero && !continuing) { /* Test if zlp is actually required. */ if ((ureq->length >= hs_ep->ep.maxpacket) && - !(ureq->length % hs_ep->ep.maxpacket)) + !(ureq->length % hs_ep->ep.maxpacket)) hs_ep->send_zlp = 1; } @@ -1070,7 +1167,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg, /* check ep is enabled */ if (!(dwc2_readl(hsotg->regs + epctrl_reg) & DXEPCTL_EPENA)) dev_dbg(hsotg->dev, - "ep%d: failed to become enabled (DXEPCTL=0x%08x)?\n", + "ep%d: failed to become enabled (DXEPCTL=0x%08x)?\n", index, dwc2_readl(hsotg->regs + epctrl_reg)); dev_dbg(hsotg->dev, "%s: DXEPCTL=0x%08x\n", @@ -1093,7 +1190,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg, * cleanup on completion. */ static int dwc2_hsotg_map_dma(struct dwc2_hsotg *hsotg, - struct dwc2_hsotg_ep *hs_ep, + struct dwc2_hsotg_ep *hs_ep, struct usb_request *req) { int ret; @@ -1112,7 +1209,8 @@ dma_error: } static int dwc2_hsotg_handle_unaligned_buf_start(struct dwc2_hsotg *hsotg, - struct dwc2_hsotg_ep *hs_ep, struct dwc2_hsotg_req *hs_req) + struct dwc2_hsotg_ep *hs_ep, + struct dwc2_hsotg_req *hs_req) { void *req_buf = hs_req->req.buf; @@ -1123,7 +1221,7 @@ static int dwc2_hsotg_handle_unaligned_buf_start(struct dwc2_hsotg *hsotg, WARN_ON(hs_req->saved_req_buf); dev_dbg(hsotg->dev, "%s: %s: buf=%p length=%d\n", __func__, - hs_ep->ep.name, req_buf, hs_req->req.length); + hs_ep->ep.name, req_buf, hs_req->req.length); hs_req->req.buf = kmalloc(hs_req->req.length, GFP_ATOMIC); if (!hs_req->req.buf) { @@ -1142,8 +1240,10 @@ static int dwc2_hsotg_handle_unaligned_buf_start(struct dwc2_hsotg *hsotg, return 0; } -static void dwc2_hsotg_handle_unaligned_buf_complete(struct dwc2_hsotg *hsotg, - struct dwc2_hsotg_ep *hs_ep, struct dwc2_hsotg_req *hs_req) +static void +dwc2_hsotg_handle_unaligned_buf_complete(struct dwc2_hsotg *hsotg, + struct dwc2_hsotg_ep *hs_ep, + struct dwc2_hsotg_req *hs_req) { /* If dma is not being used or buffer was aligned */ if (!using_dma(hsotg) || !hs_req->saved_req_buf) @@ -1155,7 +1255,7 @@ static void dwc2_hsotg_handle_unaligned_buf_complete(struct dwc2_hsotg *hsotg, /* Copy data from bounce buffer on successful out transfer */ if (!hs_ep->dir_in && !hs_req->req.status) memcpy(hs_req->saved_req_buf, hs_req->req.buf, - hs_req->req.actual); + hs_req->req.actual); /* Free bounce buffer */ kfree(hs_req->req.buf); @@ -1224,7 +1324,7 @@ static int dwc2_gadget_set_ep0_desc_chain(struct dwc2_hsotg *hsotg, } static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, - gfp_t gfp_flags) + gfp_t gfp_flags) { struct dwc2_hsotg_req *hs_req = our_req(req); struct dwc2_hsotg_ep *hs_ep = our_ep(ep); @@ -1239,7 +1339,7 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, /* Prevent new request submission when controller is suspended */ if (hs->lx_state == DWC2_L2) { dev_dbg(hs->dev, "%s: don't submit request while suspended\n", - __func__); + __func__); return -EAGAIN; } @@ -1300,7 +1400,7 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, } static int dwc2_hsotg_ep_queue_lock(struct usb_ep *ep, struct usb_request *req, - gfp_t gfp_flags) + gfp_t gfp_flags) { struct dwc2_hsotg_ep *hs_ep = our_ep(ep); struct dwc2_hsotg *hs = hs_ep->parent; @@ -1315,7 +1415,7 @@ static int dwc2_hsotg_ep_queue_lock(struct usb_ep *ep, struct usb_request *req, } static void dwc2_hsotg_ep_free_request(struct usb_ep *ep, - struct usb_request *req) + struct usb_request *req) { struct dwc2_hsotg_req *hs_req = our_req(req); @@ -1331,7 +1431,7 @@ static void dwc2_hsotg_ep_free_request(struct usb_ep *ep, * submitted that need cleaning up. */ static void dwc2_hsotg_complete_oursetup(struct usb_ep *ep, - struct usb_request *req) + struct usb_request *req) { struct dwc2_hsotg_ep *hs_ep = our_ep(ep); struct dwc2_hsotg *hsotg = hs_ep->parent; @@ -1350,7 +1450,7 @@ static void dwc2_hsotg_complete_oursetup(struct usb_ep *ep, * structure, or return NULL if it is not a valid endpoint. */ static struct dwc2_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg, - u32 windex) + u32 windex) { struct dwc2_hsotg_ep *ep; int dir = (windex & USB_DIR_IN) ? 1 : 0; @@ -1407,7 +1507,7 @@ int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode) * an internal method of sending replies to certain control requests, etc. */ static int dwc2_hsotg_send_reply(struct dwc2_hsotg *hsotg, - struct dwc2_hsotg_ep *ep, + struct dwc2_hsotg_ep *ep, void *buff, int length) { @@ -1450,7 +1550,7 @@ static int dwc2_hsotg_send_reply(struct dwc2_hsotg *hsotg, * @ctrl: USB control request */ static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg, - struct usb_ctrlrequest *ctrl) + struct usb_ctrlrequest *ctrl) { struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0]; struct dwc2_hsotg_ep *ep; @@ -1466,8 +1566,11 @@ static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg, switch (ctrl->bRequestType & USB_RECIP_MASK) { case USB_RECIP_DEVICE: - reply = cpu_to_le16(0); /* bit 0 => self powered, - * bit 1 => remote wakeup */ + /* + * bit 0 => self powered + * bit 1 => remote wakeup + */ + reply = cpu_to_le16(0); break; case USB_RECIP_INTERFACE: @@ -1555,7 +1658,7 @@ static void dwc2_gadget_start_next_request(struct dwc2_hsotg_ep *hs_ep) * @ctrl: USB control request */ static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg, - struct usb_ctrlrequest *ctrl) + struct usb_ctrlrequest *ctrl) { struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0]; struct dwc2_hsotg_req *hs_req; @@ -1640,9 +1743,8 @@ static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg, } /* If we have pending request, then start it */ - if (!ep->req) { + if (!ep->req) dwc2_gadget_start_next_request(ep); - } } break; @@ -1705,7 +1807,7 @@ static void dwc2_hsotg_stall_ep0(struct dwc2_hsotg *hsotg) * gadget driver). */ static void dwc2_hsotg_process_control(struct dwc2_hsotg *hsotg, - struct usb_ctrlrequest *ctrl) + struct usb_ctrlrequest *ctrl) { struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0]; int ret = 0; @@ -1781,7 +1883,7 @@ static void dwc2_hsotg_process_control(struct dwc2_hsotg *hsotg, * EP0 setup packets */ static void dwc2_hsotg_complete_setup(struct usb_ep *ep, - struct usb_request *req) + struct usb_request *req) { struct dwc2_hsotg_ep *hs_ep = our_ep(ep); struct dwc2_hsotg *hsotg = hs_ep->parent; @@ -1839,7 +1941,7 @@ static void dwc2_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg) } static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg, - struct dwc2_hsotg_ep *hs_ep) + struct dwc2_hsotg_ep *hs_ep) { u32 ctrl; u8 index = hs_ep->index; @@ -1885,11 +1987,10 @@ static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg, * Note, expects the ep to already be locked as appropriate. */ static void dwc2_hsotg_complete_request(struct dwc2_hsotg *hsotg, - struct dwc2_hsotg_ep *hs_ep, + struct dwc2_hsotg_ep *hs_ep, struct dwc2_hsotg_req *hs_req, int result) { - if (!hs_req) { dev_dbg(hsotg->dev, "%s: nothing to complete?\n", __func__); return; @@ -1935,9 +2036,8 @@ static void dwc2_hsotg_complete_request(struct dwc2_hsotg *hsotg, * so be careful when doing this. */ - if (!hs_ep->req && result >= 0) { + if (!hs_ep->req && result >= 0) dwc2_gadget_start_next_request(hs_ep); - } } /* @@ -2068,13 +2168,12 @@ static void dwc2_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size) int max_req; int read_ptr; - if (!hs_req) { u32 epctl = dwc2_readl(hsotg->regs + DOEPCTL(ep_idx)); int ptr; dev_dbg(hsotg->dev, - "%s: FIFO %d bytes on ep%d but no req (DXEPCTl=0x%08x)\n", + "%s: FIFO %d bytes on ep%d but no req (DXEPCTl=0x%08x)\n", __func__, size, ep_idx, epctl); /* dump the data from the FIFO, we've nothing we can do */ @@ -2134,7 +2233,7 @@ static void dwc2_hsotg_ep0_zlp(struct dwc2_hsotg *hsotg, bool dir_in) } static void dwc2_hsotg_change_ep_iso_parity(struct dwc2_hsotg *hsotg, - u32 epctl_reg) + u32 epctl_reg) { u32 ctrl; @@ -2191,7 +2290,7 @@ static void dwc2_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum) struct dwc2_hsotg_ep *hs_ep = hsotg->eps_out[epnum]; struct dwc2_hsotg_req *hs_req = hs_ep->req; struct usb_request *req = &hs_req->req; - unsigned size_left = DXEPTSIZ_XFERSIZE_GET(epsize); + unsigned int size_left = DXEPTSIZ_XFERSIZE_GET(epsize); int result = 0; if (!hs_req) { @@ -2210,7 +2309,7 @@ static void dwc2_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum) size_left = dwc2_gadget_get_xfersize_ddma(hs_ep); if (using_dma(hsotg)) { - unsigned size_done; + unsigned int size_done; /* * Calculate the size of the transfer by checking how much @@ -2295,7 +2394,7 @@ static void dwc2_hsotg_handle_rx(struct dwc2_hsotg *hsotg) size >>= GRXSTS_BYTECNT_SHIFT; dev_dbg(hsotg->dev, "%s: GRXSTSP=0x%08x (%d@%d)\n", - __func__, grxstsr, size, epnum); + __func__, grxstsr, size, epnum); switch ((status & GRXSTS_PKTSTS_MASK) >> GRXSTS_PKTSTS_SHIFT) { case GRXSTS_PKTSTS_GLOBALOUTNAK: @@ -2470,7 +2569,7 @@ static void dwc2_hsotg_txfifo_flush(struct dwc2_hsotg *hsotg, unsigned int idx) * make an attempt to write data into the FIFO. */ static int dwc2_hsotg_trytx(struct dwc2_hsotg *hsotg, - struct dwc2_hsotg_ep *hs_ep) + struct dwc2_hsotg_ep *hs_ep) { struct dwc2_hsotg_req *hs_req = hs_ep->req; @@ -2481,7 +2580,7 @@ static int dwc2_hsotg_trytx(struct dwc2_hsotg *hsotg, */ if (hs_ep->index != 0) dwc2_hsotg_ctrl_epint(hsotg, hs_ep->index, - hs_ep->dir_in, 0); + hs_ep->dir_in, 0); return 0; } @@ -2503,7 +2602,7 @@ static int dwc2_hsotg_trytx(struct dwc2_hsotg *hsotg, * call the relevant completion routines. */ static void dwc2_hsotg_complete_in(struct dwc2_hsotg *hsotg, - struct dwc2_hsotg_ep *hs_ep) + struct dwc2_hsotg_ep *hs_ep) { struct dwc2_hsotg_req *hs_req = hs_ep->req; u32 epsize = dwc2_readl(hsotg->regs + DIEPTSIZ(hs_ep->index)); @@ -2531,7 +2630,7 @@ static void dwc2_hsotg_complete_in(struct dwc2_hsotg *hsotg, ret = dwc2_hsotg_set_test_mode(hsotg, hsotg->test_mode); if (ret < 0) { dev_dbg(hsotg->dev, "Invalid Test #%d\n", - hsotg->test_mode); + hsotg->test_mode); dwc2_hsotg_stall_ep0(hsotg); return; } @@ -2751,19 +2850,19 @@ static void dwc2_gadget_handle_out_token_ep_disabled(struct dwc2_hsotg_ep *ep) } /** -* dwc2_gadget_handle_nak - handle NAK interrupt -* @hs_ep: The endpoint on which interrupt is asserted. -* -* This is starting point for ISOC-IN transfer, synchronization done with -* first IN token received from host while corresponding EP is disabled. -* -* Device does not know when first one token will arrive from host. On first -* token arrival HW generates 2 interrupts: 'in token received while FIFO empty' -* and 'NAK'. NAK interrupt for ISOC-IN means that token has arrived and ZLP was -* sent in response to that as there was no data in FIFO. SW is basing on this -* interrupt to obtain frame in which token has come and then based on the -* interval calculates next frame for transfer. -*/ + * dwc2_gadget_handle_nak - handle NAK interrupt + * @hs_ep: The endpoint on which interrupt is asserted. + * + * This is starting point for ISOC-IN transfer, synchronization done with + * first IN token received from host while corresponding EP is disabled. + * + * Device does not know when first one token will arrive from host. On first + * token arrival HW generates 2 interrupts: 'in token received while FIFO empty' + * and 'NAK'. NAK interrupt for ISOC-IN means that token has arrived and ZLP was + * sent in response to that as there was no data in FIFO. SW is basing on this + * interrupt to obtain frame in which token has come and then based on the + * interval calculates next frame for transfer. + */ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep) { struct dwc2_hsotg *hsotg = hs_ep->parent; @@ -2807,7 +2906,7 @@ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep) * Process and clear any interrupt pending for an individual endpoint */ static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx, - int dir_in) + int dir_in) { struct dwc2_hsotg_ep *hs_ep = index_to_ep(hsotg, idx, dir_in); u32 epint_reg = dir_in ? DIEPINT(idx) : DOEPINT(idx); @@ -2824,7 +2923,7 @@ static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx, if (!hs_ep) { dev_err(hsotg->dev, "%s:Interrupt for unconfigured ep%d(%s)\n", - __func__, idx, dir_in ? "in" : "out"); + __func__, idx, dir_in ? "in" : "out"); return; } @@ -3059,13 +3158,13 @@ static void kill_all_requests(struct dwc2_hsotg *hsotg, int result) { struct dwc2_hsotg_req *req, *treq; - unsigned size; + unsigned int size; ep->req = NULL; list_for_each_entry_safe(req, treq, &ep->queue, queue) dwc2_hsotg_complete_request(hsotg, ep, req, - result); + result); if (!hsotg->dedicated_fifos) return; @@ -3084,7 +3183,7 @@ static void kill_all_requests(struct dwc2_hsotg *hsotg, */ void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg) { - unsigned ep; + unsigned int ep; if (!hsotg->connected) return; @@ -3095,10 +3194,10 @@ void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg) for (ep = 0; ep < hsotg->num_of_eps; ep++) { if (hsotg->eps_in[ep]) kill_all_requests(hsotg, hsotg->eps_in[ep], - -ESHUTDOWN); + -ESHUTDOWN); if (hsotg->eps_out[ep]) kill_all_requests(hsotg, hsotg->eps_out[ep], - -ESHUTDOWN); + -ESHUTDOWN); } call_gadget(hsotg, disconnect); @@ -3147,7 +3246,7 @@ static void dwc2_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic) * Issue a soft reset to the core, and await the core finishing it. */ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, - bool is_usb_reset) + bool is_usb_reset) { u32 intmsk; u32 val; @@ -3158,7 +3257,7 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET); if (!is_usb_reset) - if (dwc2_core_reset(hsotg)) + if (dwc2_core_reset(hsotg, true)) return; /* @@ -3221,7 +3320,7 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, if (!using_desc_dma(hsotg)) intmsk |= GINTSTS_INCOMPL_SOIN | GINTSTS_INCOMPL_SOOUT; - if (hsotg->params.external_id_pin_ctl <= 0) + if (!hsotg->params.external_id_pin_ctl) intmsk |= GINTSTS_CONIDSTSCHNG; dwc2_writel(intmsk, hsotg->regs + GINTMSK); @@ -3462,7 +3561,6 @@ irq_retry: } if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) { - u32 usb_status = dwc2_readl(hsotg->regs + GOTGCTL); u32 connected = hsotg->connected; @@ -3601,7 +3699,7 @@ irq_retry: */ if (gintsts & IRQ_RETRY_MASK && --retry_count > 0) - goto irq_retry; + goto irq_retry; spin_unlock(&hsotg->lock); @@ -3705,7 +3803,7 @@ static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg, * This is called from the USB gadget code's usb_ep_enable(). */ static int dwc2_hsotg_ep_enable(struct usb_ep *ep, - const struct usb_endpoint_descriptor *desc) + const struct usb_endpoint_descriptor *desc) { struct dwc2_hsotg_ep *hs_ep = our_ep(ep); struct dwc2_hsotg *hsotg = hs_ep->parent; @@ -3827,12 +3925,13 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep, if (dir_in && hsotg->dedicated_fifos) { u32 fifo_index = 0; u32 fifo_size = UINT_MAX; - size = hs_ep->ep.maxpacket*hs_ep->mc; + + size = hs_ep->ep.maxpacket * hs_ep->mc; for (i = 1; i < hsotg->num_of_eps; ++i) { - if (hsotg->fifo_map & (1<<i)) + if (hsotg->fifo_map & (1 << i)) continue; val = dwc2_readl(hsotg->regs + DPTXFSIZN(i)); - val = (val >> FIFOSIZE_DEPTH_SHIFT)*4; + val = (val >> FIFOSIZE_DEPTH_SHIFT) * 4; if (val < size) continue; /* Search for smallest acceptable fifo */ @@ -4033,23 +4132,22 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now) epctl &= ~DXEPCTL_STALL; xfertype = epctl & DXEPCTL_EPTYPE_MASK; if (xfertype == DXEPCTL_EPTYPE_BULK || - xfertype == DXEPCTL_EPTYPE_INTERRUPT) - epctl |= DXEPCTL_SETD0PID; + xfertype == DXEPCTL_EPTYPE_INTERRUPT) + epctl |= DXEPCTL_SETD0PID; } dwc2_writel(epctl, hs->regs + epreg); } else { - epreg = DOEPCTL(index); epctl = dwc2_readl(hs->regs + epreg); - if (value) + if (value) { epctl |= DXEPCTL_STALL; - else { + } else { epctl &= ~DXEPCTL_STALL; xfertype = epctl & DXEPCTL_EPTYPE_MASK; if (xfertype == DXEPCTL_EPTYPE_BULK || - xfertype == DXEPCTL_EPTYPE_INTERRUPT) - epctl |= DXEPCTL_SETD0PID; + xfertype == DXEPCTL_EPTYPE_INTERRUPT) + epctl |= DXEPCTL_SETD0PID; } dwc2_writel(epctl, hs->regs + epreg); } @@ -4090,7 +4188,7 @@ static struct usb_ep_ops dwc2_hsotg_ep_ops = { }; /** - * dwc2_hsotg_init - initalize the usb core + * dwc2_hsotg_init - initialize the usb core * @hsotg: The driver state */ static void dwc2_hsotg_init(struct dwc2_hsotg *hsotg) @@ -4144,7 +4242,7 @@ static void dwc2_hsotg_init(struct dwc2_hsotg *hsotg) * to work. */ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget, - struct usb_gadget_driver *driver) + struct usb_gadget_driver *driver) { struct dwc2_hsotg *hsotg = to_hsotg(gadget); unsigned long flags; @@ -4267,7 +4365,7 @@ static int dwc2_hsotg_pullup(struct usb_gadget *gadget, int is_on) unsigned long flags = 0; dev_dbg(hsotg->dev, "%s: is_on: %d op_state: %d\n", __func__, is_on, - hsotg->op_state); + hsotg->op_state); /* Don't modify pullup state while in host mode */ if (hsotg->op_state != OTG_STATE_B_PERIPHERAL) { @@ -4329,7 +4427,7 @@ static int dwc2_hsotg_vbus_session(struct usb_gadget *gadget, int is_active) * * Report how much power the device may consume to the phy. */ -static int dwc2_hsotg_vbus_draw(struct usb_gadget *gadget, unsigned mA) +static int dwc2_hsotg_vbus_draw(struct usb_gadget *gadget, unsigned int mA) { struct dwc2_hsotg *hsotg = to_hsotg(gadget); @@ -4358,7 +4456,7 @@ static const struct usb_gadget_ops dwc2_hsotg_gadget_ops = { * direction information and other state that may be required. */ static void dwc2_hsotg_initep(struct dwc2_hsotg *hsotg, - struct dwc2_hsotg_ep *hs_ep, + struct dwc2_hsotg_ep *hs_ep, int epnum, bool dir_in) { @@ -4415,6 +4513,7 @@ static void dwc2_hsotg_initep(struct dwc2_hsotg *hsotg, if (using_dma(hsotg)) { u32 next = DXEPCTL_NEXTEP((epnum + 1) % 15); + if (dir_in) dwc2_writel(next, hsotg->regs + DIEPCTL(epnum)); else @@ -4441,8 +4540,9 @@ static int dwc2_hsotg_hw_cfg(struct dwc2_hsotg *hsotg) /* Add ep0 */ hsotg->num_of_eps++; - hsotg->eps_in[0] = devm_kzalloc(hsotg->dev, sizeof(struct dwc2_hsotg_ep), - GFP_KERNEL); + hsotg->eps_in[0] = devm_kzalloc(hsotg->dev, + sizeof(struct dwc2_hsotg_ep), + GFP_KERNEL); if (!hsotg->eps_in[0]) return -ENOMEM; /* Same dwc2_hsotg_ep is used in both directions for ep0 */ @@ -4521,7 +4621,6 @@ static void dwc2_hsotg_dump(struct dwc2_hsotg *hsotg) idx, dwc2_readl(regs + DOEPCTL(idx)), dwc2_readl(regs + DOEPTSIZ(idx)), dwc2_readl(regs + DOEPDMA(idx))); - } dev_info(dev, "DVBUSDIS=0x%08x, DVBUSPULSE=%08x\n", @@ -4576,7 +4675,7 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) } ret = devm_request_irq(hsotg->dev, irq, dwc2_hsotg_irq, IRQF_SHARED, - dev_name(hsotg->dev), hsotg); + dev_name(hsotg->dev), hsotg); if (ret < 0) { dev_err(dev, "cannot claim IRQ for gadget\n"); return ret; @@ -4607,10 +4706,10 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) for (epnum = 0; epnum < hsotg->num_of_eps; epnum++) { if (hsotg->eps_in[epnum]) dwc2_hsotg_initep(hsotg, hsotg->eps_in[epnum], - epnum, 1); + epnum, 1); if (hsotg->eps_out[epnum]) dwc2_hsotg_initep(hsotg, hsotg->eps_out[epnum], - epnum, 0); + epnum, 0); } ret = usb_add_gadget_udc(dev, &hsotg->gadget); diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 46d0ad5105e4..a73722e27d07 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -42,6 +42,7 @@ #include <linux/module.h> #include <linux/spinlock.h> #include <linux/interrupt.h> +#include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/delay.h> #include <linux/io.h> @@ -54,6 +55,8 @@ #include "core.h" #include "hcd.h" +static void dwc2_port_resume(struct dwc2_hsotg *hsotg); + /* * ========================================================================= * Host Core Layer Functions @@ -79,9 +82,9 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) /* Enable the interrupts in the GINTMSK */ intmsk = GINTSTS_MODEMIS | GINTSTS_OTGINT; - if (hsotg->params.host_dma <= 0) + if (!hsotg->params.host_dma) intmsk |= GINTSTS_RXFLVL; - if (hsotg->params.external_id_pin_ctl <= 0) + if (!hsotg->params.external_id_pin_ctl) intmsk |= GINTSTS_CONIDSTSCHNG; intmsk |= GINTSTS_WKUPINT | GINTSTS_USBSUSP | @@ -100,7 +103,7 @@ static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg) if ((hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED && - hsotg->params.ulpi_fs_ls > 0) || + hsotg->params.ulpi_fs_ls) || hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS) { /* Full speed PHY */ val = HCFG_FSLSPCLKSEL_48_MHZ; @@ -152,7 +155,7 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) if (dwc2_is_host_mode(hsotg)) dwc2_init_fs_ls_pclk_sel(hsotg); - if (hsotg->params.i2c_enable > 0) { + if (hsotg->params.i2c_enable) { dev_dbg(hsotg->dev, "FS PHY enabling I2C\n"); /* Program GUSBCFG.OtgUtmiFsSel to I2C */ @@ -195,7 +198,7 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) dev_dbg(hsotg->dev, "HS ULPI PHY selected\n"); usbcfg |= GUSBCFG_ULPI_UTMI_SEL; usbcfg &= ~(GUSBCFG_PHYIF16 | GUSBCFG_DDRSEL); - if (hsotg->params.phy_ulpi_ddr > 0) + if (hsotg->params.phy_ulpi_ddr) usbcfg |= GUSBCFG_DDRSEL; break; case DWC2_PHY_TYPE_PARAM_UTMI: @@ -246,7 +249,7 @@ static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED && - hsotg->params.ulpi_fs_ls > 0) { + hsotg->params.ulpi_fs_ls) { dev_dbg(hsotg->dev, "Setting ULPI FSLS\n"); usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); usbcfg |= GUSBCFG_ULPI_FS_LS; @@ -290,17 +293,17 @@ static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) hsotg->params.host_dma, hsotg->params.dma_desc_enable); - if (hsotg->params.host_dma > 0) { - if (hsotg->params.dma_desc_enable > 0) + if (hsotg->params.host_dma) { + if (hsotg->params.dma_desc_enable) dev_dbg(hsotg->dev, "Using Descriptor DMA mode\n"); else dev_dbg(hsotg->dev, "Using Buffer DMA mode\n"); } else { dev_dbg(hsotg->dev, "Using Slave mode\n"); - hsotg->params.dma_desc_enable = 0; + hsotg->params.dma_desc_enable = false; } - if (hsotg->params.host_dma > 0) + if (hsotg->params.host_dma) ahbcfg |= GAHBCFG_DMA_EN; dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG); @@ -491,9 +494,10 @@ static void dwc2_config_fifos(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "new hptxfsiz=%08x\n", dwc2_readl(hsotg->regs + HPTXFSIZ)); - if (hsotg->params.en_multiple_tx_fifo > 0 && - hsotg->hw_params.snpsid <= DWC2_CORE_REV_2_94a) { + if (hsotg->params.en_multiple_tx_fifo && + hsotg->hw_params.snpsid >= DWC2_CORE_REV_2_91a) { /* + * This feature was implemented in 2.91a version * Global DFIFOCFG calculation for Host mode - * include RxFIFO, NPTXFIFO and HPTXFIFO */ @@ -771,7 +775,7 @@ static void dwc2_hc_enable_dma_ints(struct dwc2_hsotg *hsotg, * For Descriptor DMA mode core halts the channel on AHB error. * Interrupt is not required. */ - if (hsotg->params.dma_desc_enable <= 0) { + if (!hsotg->params.dma_desc_enable) { if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "desc DMA disabled\n"); hcintmsk |= HCINTMSK_AHBERR; @@ -804,7 +808,7 @@ static void dwc2_hc_enable_ints(struct dwc2_hsotg *hsotg, { u32 intmsk; - if (hsotg->params.host_dma > 0) { + if (hsotg->params.host_dma) { if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "DMA enabled\n"); dwc2_hc_enable_dma_ints(hsotg, chan); @@ -1024,7 +1028,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, /* No need to set the bit in DDMA for disabling the channel */ /* TODO check it everywhere channel is disabled */ - if (hsotg->params.dma_desc_enable <= 0) { + if (!hsotg->params.dma_desc_enable) { if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "desc DMA disabled\n"); hcchar |= HCCHAR_CHENA; @@ -1034,7 +1038,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, } hcchar |= HCCHAR_CHDIS; - if (hsotg->params.host_dma <= 0) { + if (!hsotg->params.host_dma) { if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "DMA not enabled\n"); hcchar |= HCCHAR_CHENA; @@ -1380,7 +1384,7 @@ static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg, dev_vdbg(hsotg->dev, "%s()\n", __func__); if (chan->do_ping) { - if (hsotg->params.host_dma <= 0) { + if (!hsotg->params.host_dma) { if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "ping, no DMA\n"); dwc2_hc_do_ping(hsotg, chan); @@ -1508,7 +1512,7 @@ static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg, TSIZ_SC_MC_PID_SHIFT); } - if (hsotg->params.host_dma > 0) { + if (hsotg->params.host_dma) { dwc2_writel((u32)chan->xfer_dma, hsotg->regs + HCDMA(chan->hc_num)); if (dbg_hc(chan)) @@ -1551,7 +1555,7 @@ static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg, chan->xfer_started = 1; chan->requests++; - if (hsotg->params.host_dma <= 0 && + if (!hsotg->params.host_dma && !chan->ep_is_in && chan->xfer_len > 0) /* Load OUT packet into the appropriate Tx FIFO */ dwc2_hc_write_packet(hsotg, chan); @@ -1834,7 +1838,7 @@ static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg) u32 hcchar; int i; - if (hsotg->params.host_dma <= 0) { + if (!hsotg->params.host_dma) { /* Flush out any channel requests in slave mode */ for (i = 0; i < num_channels; i++) { channel = hsotg->hc_ptr_array[i]; @@ -1870,7 +1874,7 @@ static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg) channel->qh = NULL; } /* All channels have been freed, mark them available */ - if (hsotg->params.uframe_sched > 0) { + if (hsotg->params.uframe_sched) { hsotg->available_host_channels = hsotg->params.host_channels; } else { @@ -2107,7 +2111,7 @@ static int dwc2_hcd_urb_dequeue(struct dwc2_hsotg *hsotg, * Free the QTD and clean up the associated QH. Leave the QH in the * schedule if it has any remaining QTDs. */ - if (hsotg->params.dma_desc_enable <= 0) { + if (!hsotg->params.dma_desc_enable) { u8 in_process = urb_qtd->in_process; dwc2_hcd_qtd_unlink_and_free(hsotg, urb_qtd, qh); @@ -2150,7 +2154,7 @@ static int dwc2_hcd_endpoint_disable(struct dwc2_hsotg *hsotg, } spin_unlock_irqrestore(&hsotg->lock, flags); - usleep_range(20000, 40000); + msleep(20); spin_lock_irqsave(&hsotg->lock, flags); qh = ep->hcpriv; if (!qh) { @@ -2215,13 +2219,12 @@ static int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup) /* Set ULPI External VBUS bit if needed */ usbcfg &= ~GUSBCFG_ULPI_EXT_VBUS_DRV; - if (hsotg->params.phy_ulpi_ext_vbus == - DWC2_PHY_ULPI_EXTERNAL_VBUS) + if (hsotg->params.phy_ulpi_ext_vbus) usbcfg |= GUSBCFG_ULPI_EXT_VBUS_DRV; /* Set external TS Dline pulsing bit if needed */ usbcfg &= ~GUSBCFG_TERMSELDLPULSE; - if (hsotg->params.ts_dline > 0) + if (hsotg->params.ts_dline) usbcfg |= GUSBCFG_TERMSELDLPULSE; dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); @@ -2260,10 +2263,7 @@ static int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup) /* Program the GOTGCTL register */ otgctl = dwc2_readl(hsotg->regs + GOTGCTL); otgctl &= ~GOTGCTL_OTGVER; - if (hsotg->params.otg_ver > 0) - otgctl |= GOTGCTL_OTGVER; dwc2_writel(otgctl, hsotg->regs + GOTGCTL); - dev_dbg(hsotg->dev, "OTG VER PARAM: %d\n", hsotg->params.otg_ver); /* Clear the SRP success bit for FS-I2c */ hsotg->srp_success = 0; @@ -2319,13 +2319,13 @@ static void dwc2_core_host_init(struct dwc2_hsotg *hsotg) * runtime. This bit needs to be programmed during initial configuration * and its value must not be changed during runtime. */ - if (hsotg->params.reload_ctl > 0) { + if (hsotg->params.reload_ctl) { hfir = dwc2_readl(hsotg->regs + HFIR); hfir |= HFIR_RLDCTRL; dwc2_writel(hfir, hsotg->regs + HFIR); } - if (hsotg->params.dma_desc_enable > 0) { + if (hsotg->params.dma_desc_enable) { u32 op_mode = hsotg->hw_params.op_mode; if (hsotg->hw_params.snpsid < DWC2_CORE_REV_2_90a || @@ -2337,7 +2337,7 @@ static void dwc2_core_host_init(struct dwc2_hsotg *hsotg) "Hardware does not support descriptor DMA mode -\n"); dev_err(hsotg->dev, "falling back to buffer DMA mode.\n"); - hsotg->params.dma_desc_enable = 0; + hsotg->params.dma_desc_enable = false; } else { hcfg = dwc2_readl(hsotg->regs + HCFG); hcfg |= HCFG_DESCDMA; @@ -2363,7 +2363,7 @@ static void dwc2_core_host_init(struct dwc2_hsotg *hsotg) otgctl &= ~GOTGCTL_HSTSETHNPEN; dwc2_writel(otgctl, hsotg->regs + GOTGCTL); - if (hsotg->params.dma_desc_enable <= 0) { + if (!hsotg->params.dma_desc_enable) { int num_channels, i; u32 hcchar; @@ -2430,7 +2430,7 @@ static void dwc2_hcd_reinit(struct dwc2_hsotg *hsotg) hsotg->flags.d32 = 0; hsotg->non_periodic_qh_ptr = &hsotg->non_periodic_sched_active; - if (hsotg->params.uframe_sched > 0) { + if (hsotg->params.uframe_sched) { hsotg->available_host_channels = hsotg->params.host_channels; } else { @@ -2488,7 +2488,7 @@ static void dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg, chan->do_ping = 0; chan->ep_is_in = 0; chan->data_pid_start = DWC2_HC_PID_SETUP; - if (hsotg->params.host_dma > 0) + if (hsotg->params.host_dma) chan->xfer_dma = urb->setup_dma; else chan->xfer_buf = urb->setup_packet; @@ -2515,7 +2515,7 @@ static void dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg, chan->do_ping = 0; chan->data_pid_start = DWC2_HC_PID_DATA1; chan->xfer_len = 0; - if (hsotg->params.host_dma > 0) + if (hsotg->params.host_dma) chan->xfer_dma = hsotg->status_buf_dma; else chan->xfer_buf = hsotg->status_buf; @@ -2533,13 +2533,13 @@ static void dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg, case USB_ENDPOINT_XFER_ISOC: chan->ep_type = USB_ENDPOINT_XFER_ISOC; - if (hsotg->params.dma_desc_enable > 0) + if (hsotg->params.dma_desc_enable) break; frame_desc = &urb->iso_descs[qtd->isoc_frame_index]; frame_desc->status = 0; - if (hsotg->params.host_dma > 0) { + if (hsotg->params.host_dma) { chan->xfer_dma = urb->dma; chan->xfer_dma += frame_desc->offset + qtd->isoc_split_offset; @@ -2577,7 +2577,7 @@ static void dwc2_free_dma_aligned_buffer(struct urb *urb) return; temp = container_of(urb->transfer_buffer, - struct dma_aligned_buffer, data); + struct dma_aligned_buffer, data); if (usb_urb_dir_in(urb)) memcpy(temp->old_xfer_buffer, temp->data, @@ -2621,7 +2621,7 @@ static int dwc2_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags) } static int dwc2_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, - gfp_t mem_flags) + gfp_t mem_flags) { int ret; @@ -2718,10 +2718,10 @@ static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) chan->multi_count = 1; if (urb->actual_length > urb->length && - !dwc2_hcd_is_pipe_in(&urb->pipe_info)) + !dwc2_hcd_is_pipe_in(&urb->pipe_info)) urb->actual_length = urb->length; - if (hsotg->params.host_dma > 0) + if (hsotg->params.host_dma) chan->xfer_dma = urb->dma + urb->actual_length; else chan->xfer_buf = (u8 *)urb->buf + urb->actual_length; @@ -2746,7 +2746,7 @@ static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) */ chan->multi_count = dwc2_hb_mult(qh->maxp); - if (hsotg->params.dma_desc_enable > 0) { + if (hsotg->params.dma_desc_enable) { chan->desc_list_addr = qh->desc_list_dma; chan->desc_list_sz = qh->desc_list_sz; } @@ -2783,7 +2783,7 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions( while (qh_ptr != &hsotg->periodic_sched_ready) { if (list_empty(&hsotg->free_hc_list)) break; - if (hsotg->params.uframe_sched > 0) { + if (hsotg->params.uframe_sched) { if (hsotg->available_host_channels <= 1) break; hsotg->available_host_channels--; @@ -2810,14 +2810,14 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions( num_channels = hsotg->params.host_channels; qh_ptr = hsotg->non_periodic_sched_inactive.next; while (qh_ptr != &hsotg->non_periodic_sched_inactive) { - if (hsotg->params.uframe_sched <= 0 && + if (!hsotg->params.uframe_sched && hsotg->non_periodic_channels >= num_channels - hsotg->periodic_channels) break; if (list_empty(&hsotg->free_hc_list)) break; qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry); - if (hsotg->params.uframe_sched > 0) { + if (hsotg->params.uframe_sched) { if (hsotg->available_host_channels < 1) break; hsotg->available_host_channels--; @@ -2839,7 +2839,7 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions( else ret_val = DWC2_TRANSACTION_ALL; - if (hsotg->params.uframe_sched <= 0) + if (!hsotg->params.uframe_sched) hsotg->non_periodic_channels++; } @@ -2878,8 +2878,8 @@ static int dwc2_queue_transaction(struct dwc2_hsotg *hsotg, list_move_tail(&chan->split_order_list_entry, &hsotg->split_order); - if (hsotg->params.host_dma > 0) { - if (hsotg->params.dma_desc_enable > 0) { + if (hsotg->params.host_dma) { + if (hsotg->params.dma_desc_enable) { if (!chan->xfer_started || chan->ep_type == USB_ENDPOINT_XFER_ISOC) { dwc2_hcd_start_xfer_ddma(hsotg, chan->qh); @@ -2967,7 +2967,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT; if (qspcavail == 0) { - no_queue_space = 1; + no_queue_space = true; break; } @@ -2988,15 +2988,15 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) * The flag prevents any halts to get into the request queue in * the middle of multiple high-bandwidth packets getting queued. */ - if (hsotg->params.host_dma <= 0 && - qh->channel->multi_count > 1) + if (!hsotg->params.host_dma && + qh->channel->multi_count > 1) hsotg->queuing_high_bandwidth = 1; fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >> TXSTS_FSPCAVAIL_SHIFT; status = dwc2_queue_transaction(hsotg, qh->channel, fspcavail); if (status < 0) { - no_fifo_space = 1; + no_fifo_space = true; break; } @@ -3007,7 +3007,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) * controller automatically handles multiple packets for * high-bandwidth transfers. */ - if (hsotg->params.host_dma > 0 || status == 0 || + if (hsotg->params.host_dma || status == 0 || qh->channel->requests == qh->channel->multi_count) { qh_ptr = qh_ptr->next; /* @@ -3024,7 +3024,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) exit: if (no_queue_space || no_fifo_space || - (hsotg->params.host_dma <= 0 && + (!hsotg->params.host_dma && !list_empty(&hsotg->periodic_sched_assigned))) { /* * May need to queue more transactions as the request @@ -3045,7 +3045,7 @@ exit: * now. This function is called from interrupt * handlers to queue more transactions as transfer * states change. - */ + */ gintmsk = dwc2_readl(hsotg->regs + GINTMSK); if (gintmsk & GINTSTS_PTXFEMP) { gintmsk &= ~GINTSTS_PTXFEMP; @@ -3104,7 +3104,7 @@ static void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg) tx_status = dwc2_readl(hsotg->regs + GNPTXSTS); qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT; - if (hsotg->params.host_dma <= 0 && qspcavail == 0) { + if (!hsotg->params.host_dma && qspcavail == 0) { no_queue_space = 1; break; } @@ -3137,7 +3137,7 @@ next: hsotg->non_periodic_qh_ptr->next; } while (hsotg->non_periodic_qh_ptr != orig_qh_ptr); - if (hsotg->params.host_dma <= 0) { + if (!hsotg->params.host_dma) { tx_status = dwc2_readl(hsotg->regs + GNPTXSTS); qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT; @@ -3235,12 +3235,25 @@ static void dwc2_conn_id_status_change(struct work_struct *work) if (gotgctl & GOTGCTL_CONID_B) { /* Wait for switch to device mode */ dev_dbg(hsotg->dev, "connId B\n"); + if (hsotg->bus_suspended) { + dev_info(hsotg->dev, + "Do port resume before switching to device mode\n"); + dwc2_port_resume(hsotg); + } while (!dwc2_is_device_mode(hsotg)) { dev_info(hsotg->dev, "Waiting for Peripheral Mode, Mode=%s\n", dwc2_is_host_mode(hsotg) ? "Host" : "Peripheral"); - usleep_range(20000, 40000); + msleep(20); + /* + * Sometimes the initial GOTGCTRL read is wrong, so + * check it again and jump to host mode if that was + * the case. + */ + gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); + if (!(gotgctl & GOTGCTL_CONID_B)) + goto host; if (++count > 250) break; } @@ -3255,13 +3268,14 @@ static void dwc2_conn_id_status_change(struct work_struct *work) spin_unlock_irqrestore(&hsotg->lock, flags); dwc2_hsotg_core_connect(hsotg); } else { +host: /* A-Device connector (Host Mode) */ dev_dbg(hsotg->dev, "connId A\n"); while (!dwc2_is_host_mode(hsotg)) { dev_info(hsotg->dev, "Waiting for Host Mode, Mode=%s\n", dwc2_is_host_mode(hsotg) ? "Host" : "Peripheral"); - usleep_range(20000, 40000); + msleep(20); if (++count > 250) break; } @@ -3296,7 +3310,7 @@ static void dwc2_wakeup_detected(unsigned long data) dwc2_readl(hsotg->regs + HPRT0)); dwc2_hcd_rem_wakeup(hsotg); - hsotg->bus_suspended = 0; + hsotg->bus_suspended = false; /* Change to L0 state */ hsotg->lx_state = DWC2_L0; @@ -3332,7 +3346,7 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) hprt0 |= HPRT0_SUSP; dwc2_writel(hprt0, hsotg->regs + HPRT0); - hsotg->bus_suspended = 1; + hsotg->bus_suspended = true; /* * If hibernation is supported, Phy clock will be suspended @@ -3354,7 +3368,7 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) spin_unlock_irqrestore(&hsotg->lock, flags); - usleep_range(200000, 250000); + msleep(200); } else { spin_unlock_irqrestore(&hsotg->lock, flags); } @@ -3378,7 +3392,7 @@ static void dwc2_port_resume(struct dwc2_hsotg *hsotg) pcgctl &= ~PCGCTL_STOPPCLK; dwc2_writel(pcgctl, hsotg->regs + PCGCTL); spin_unlock_irqrestore(&hsotg->lock, flags); - usleep_range(20000, 40000); + msleep(20); spin_lock_irqsave(&hsotg->lock, flags); } @@ -3394,7 +3408,7 @@ static void dwc2_port_resume(struct dwc2_hsotg *hsotg) hprt0 = dwc2_read_hprt0(hsotg); hprt0 &= ~(HPRT0_RES | HPRT0_SUSP); dwc2_writel(hprt0, hsotg->regs + HPRT0); - hsotg->bus_suspended = 0; + hsotg->bus_suspended = false; spin_unlock_irqrestore(&hsotg->lock, flags); } @@ -3614,7 +3628,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, u32 hcfg; dev_info(hsotg->dev, "Enabling descriptor DMA mode\n"); - hsotg->params.dma_desc_enable = 1; + hsotg->params.dma_desc_enable = true; hcfg = dwc2_readl(hsotg->regs + HCFG); hcfg |= HCFG_DESCDMA; dwc2_writel(hcfg, hsotg->regs + HCFG); @@ -3691,7 +3705,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, } /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ - usleep_range(50000, 70000); + msleep(50); hprt0 &= ~HPRT0_RST; dwc2_writel(hprt0, hsotg->regs + HPRT0); hsotg->lx_state = DWC2_L0; /* Now back to On state */ @@ -4047,7 +4061,7 @@ static struct dwc2_hsotg *dwc2_hcd_to_hsotg(struct usb_hcd *hcd) { struct wrapper_priv_data *p; - p = (struct wrapper_priv_data *) &hcd->hcd_priv; + p = (struct wrapper_priv_data *)&hcd->hcd_priv; return p->hsotg; } @@ -4082,7 +4096,7 @@ struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg, void *context, *ttport = urb->dev->ttport; dwc_tt = urb->dev->tt->hcpriv; - if (dwc_tt == NULL) { + if (!dwc_tt) { size_t bitmap_size; /* @@ -4096,7 +4110,7 @@ struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg, void *context, dwc_tt = kzalloc(sizeof(*dwc_tt) + bitmap_size, mem_flags); - if (dwc_tt == NULL) + if (!dwc_tt) return NULL; dwc_tt->usb_tt = urb->dev->tt; @@ -4123,7 +4137,7 @@ struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg, void *context, void dwc2_host_put_tt_info(struct dwc2_hsotg *hsotg, struct dwc2_tt *dwc_tt) { /* Model kfree and make put of NULL a no-op */ - if (dwc_tt == NULL) + if (!dwc_tt) return; WARN_ON(dwc_tt->refcount < 1); @@ -4206,7 +4220,6 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, usb_pipein(urb->pipe) ? "IN" : "OUT", status, urb->actual_length); - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb); for (i = 0; i < urb->number_of_packets; ++i) { @@ -4587,7 +4600,7 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, dwc2_dump_urb_info(hcd, urb, "urb_enqueue"); } - if (ep == NULL) + if (!ep) return -EINVAL; if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS || @@ -4657,7 +4670,7 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, urb->iso_frame_desc[i].length); urb->hcpriv = dwc2_urb; - qh = (struct dwc2_qh *) ep->hcpriv; + qh = (struct dwc2_qh *)ep->hcpriv; /* Create QH for the endpoint if it doesn't exist */ if (!qh) { qh = dwc2_hcd_qh_create(hsotg, dwc2_urb, mem_flags); @@ -4712,7 +4725,7 @@ fail1: dwc2_hcd_qh_unlink(hsotg, qh); /* Free each QTD in the QH's QTD list */ list_for_each_entry_safe(qtd2, qtd2_tmp, &qh->qtd_list, - qtd_list_entry) + qtd_list_entry) dwc2_hcd_qtd_unlink_and_free(hsotg, qtd2, qh); dwc2_hcd_qh_free(hsotg, qh); } @@ -4860,6 +4873,61 @@ static void _dwc2_hcd_clear_tt_buffer_complete(struct usb_hcd *hcd, spin_unlock_irqrestore(&hsotg->lock, flags); } +/* + * HPRT0_SPD_HIGH_SPEED: high speed + * HPRT0_SPD_FULL_SPEED: full speed + */ +static void dwc2_change_bus_speed(struct usb_hcd *hcd, int speed) +{ + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); + + if (hsotg->params.speed == speed) + return; + + hsotg->params.speed = speed; + queue_work(hsotg->wq_otg, &hsotg->wf_otg); +} + +static void dwc2_free_dev(struct usb_hcd *hcd, struct usb_device *udev) +{ + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); + + if (!hsotg->params.change_speed_quirk) + return; + + /* + * On removal, set speed to default high-speed. + */ + if (udev->parent && udev->parent->speed > USB_SPEED_UNKNOWN && + udev->parent->speed < USB_SPEED_HIGH) { + dev_info(hsotg->dev, "Set speed to default high-speed\n"); + dwc2_change_bus_speed(hcd, HPRT0_SPD_HIGH_SPEED); + } +} + +static int dwc2_reset_device(struct usb_hcd *hcd, struct usb_device *udev) +{ + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); + + if (!hsotg->params.change_speed_quirk) + return 0; + + if (udev->speed == USB_SPEED_HIGH) { + dev_info(hsotg->dev, "Set speed to high-speed\n"); + dwc2_change_bus_speed(hcd, HPRT0_SPD_HIGH_SPEED); + } else if ((udev->speed == USB_SPEED_FULL || + udev->speed == USB_SPEED_LOW)) { + /* + * Change speed setting to full-speed if there's + * a full-speed or low-speed device plugged in. + */ + dev_info(hsotg->dev, "Set speed to full-speed\n"); + dwc2_change_bus_speed(hcd, HPRT0_SPD_FULL_SPEED); + } + + return 0; +} + static struct hc_driver dwc2_hc_driver = { .description = "dwc2_hsotg", .product_desc = "DWC OTG Controller", @@ -4911,7 +4979,7 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg) for (i = 0; i < MAX_EPS_CHANNELS; i++) { struct dwc2_host_chan *chan = hsotg->hc_ptr_array[i]; - if (chan != NULL) { + if (chan) { dev_dbg(hsotg->dev, "HCD Free channel #%i, chan=%p\n", i, chan); hsotg->hc_ptr_array[i] = NULL; @@ -4919,7 +4987,7 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg) } } - if (hsotg->params.host_dma > 0) { + if (hsotg->params.host_dma) { if (hsotg->status_buf) { dma_free_coherent(hsotg->dev, DWC2_HCD_STATUS_BUF_SIZE, hsotg->status_buf, @@ -4967,8 +5035,10 @@ static void dwc2_hcd_release(struct dwc2_hsotg *hsotg) * USB bus with the core and calls the hc_driver->start() function. It returns * a negative error on failure. */ -int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) +int dwc2_hcd_init(struct dwc2_hsotg *hsotg) { + struct platform_device *pdev = to_platform_device(hsotg->dev); + struct resource *res; struct usb_hcd *hcd; struct dwc2_host_chan *channel; u32 hcfg; @@ -4999,32 +5069,41 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) hsotg->last_frame_num = HFNUM_MAX_FRNUM; /* Check if the bus driver or platform code has setup a dma_mask */ - if (hsotg->params.host_dma > 0 && - hsotg->dev->dma_mask == NULL) { + if (hsotg->params.host_dma && + !hsotg->dev->dma_mask) { dev_warn(hsotg->dev, "dma_mask not set, disabling DMA\n"); - hsotg->params.host_dma = 0; - hsotg->params.dma_desc_enable = 0; + hsotg->params.host_dma = false; + hsotg->params.dma_desc_enable = false; } /* Set device flags indicating whether the HCD supports DMA */ - if (hsotg->params.host_dma > 0) { + if (hsotg->params.host_dma) { if (dma_set_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0) dev_warn(hsotg->dev, "can't set DMA mask\n"); if (dma_set_coherent_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0) dev_warn(hsotg->dev, "can't set coherent DMA mask\n"); } + if (hsotg->params.change_speed_quirk) { + dwc2_hc_driver.free_dev = dwc2_free_dev; + dwc2_hc_driver.reset_device = dwc2_reset_device; + } + hcd = usb_create_hcd(&dwc2_hc_driver, hsotg->dev, dev_name(hsotg->dev)); if (!hcd) goto error1; - if (hsotg->params.host_dma <= 0) + if (!hsotg->params.host_dma) hcd->self.uses_dma = 0; hcd->has_tt = 1; - ((struct wrapper_priv_data *) &hcd->hcd_priv)->hsotg = hsotg; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + + ((struct wrapper_priv_data *)&hcd->hcd_priv)->hsotg = hsotg; hsotg->priv = hcd; /* @@ -5072,7 +5151,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) for (i = 0; i < num_channels; i++) { channel = kzalloc(sizeof(*channel), GFP_KERNEL); - if (channel == NULL) + if (!channel) goto error3; channel->hc_num = i; INIT_LIST_HEAD(&channel->split_order_list_entry); @@ -5091,7 +5170,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) * done after usb_add_hcd since that function allocates the DMA buffer * pool. */ - if (hsotg->params.host_dma > 0) + if (hsotg->params.host_dma) hsotg->status_buf = dma_alloc_coherent(hsotg->dev, DWC2_HCD_STATUS_BUF_SIZE, &hsotg->status_buf_dma, GFP_KERNEL); @@ -5121,8 +5200,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) * Disable descriptor dma mode since it will not be * usable. */ - hsotg->params.dma_desc_enable = 0; - hsotg->params.dma_desc_fs_enable = 0; + hsotg->params.dma_desc_enable = false; + hsotg->params.dma_desc_fs_enable = false; } hsotg->desc_hsisoc_cache = kmem_cache_create("dwc2-hsisoc-desc", @@ -5138,8 +5217,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) * Disable descriptor dma mode since it will not be * usable. */ - hsotg->params.dma_desc_enable = 0; - hsotg->params.dma_desc_fs_enable = 0; + hsotg->params.dma_desc_enable = false; + hsotg->params.dma_desc_fs_enable = false; } } @@ -5164,7 +5243,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) * allocates the DMA buffer pool, registers the USB bus, requests the * IRQ line, and calls hcd_start method. */ - retval = usb_add_hcd(hcd, irq, IRQF_SHARED); + retval = usb_add_hcd(hcd, hsotg->irq, IRQF_SHARED); if (retval < 0) goto error4; diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h index 1ed5fa2beff4..11c3c145b793 100644 --- a/drivers/usb/dwc2/hcd.h +++ b/drivers/usb/dwc2/hcd.h @@ -521,29 +521,29 @@ static inline u8 dwc2_hcd_is_pipe_out(struct dwc2_hcd_pipe_info *pipe) return !dwc2_hcd_is_pipe_in(pipe); } -extern int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq); -extern void dwc2_hcd_remove(struct dwc2_hsotg *hsotg); +int dwc2_hcd_init(struct dwc2_hsotg *hsotg); +void dwc2_hcd_remove(struct dwc2_hsotg *hsotg); /* Transaction Execution Functions */ -extern enum dwc2_transaction_type dwc2_hcd_select_transactions( +enum dwc2_transaction_type dwc2_hcd_select_transactions( struct dwc2_hsotg *hsotg); -extern void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg, - enum dwc2_transaction_type tr_type); +void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg, + enum dwc2_transaction_type tr_type); /* Schedule Queue Functions */ /* Implemented in hcd_queue.c */ -extern struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, - struct dwc2_hcd_urb *urb, +struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, + struct dwc2_hcd_urb *urb, gfp_t mem_flags); -extern void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh); -extern int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh); -extern void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh); -extern void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, - int sched_csplit); +void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh); +int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh); +void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh); +void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, + int sched_csplit); -extern void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb); -extern int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, - struct dwc2_qh *qh); +void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb); +int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, + struct dwc2_qh *qh); /* Unlinks and frees a QTD */ static inline void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *hsotg, @@ -556,15 +556,15 @@ static inline void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *hsotg, } /* Descriptor DMA support functions */ -extern void dwc2_hcd_start_xfer_ddma(struct dwc2_hsotg *hsotg, - struct dwc2_qh *qh); -extern void dwc2_hcd_complete_xfer_ddma(struct dwc2_hsotg *hsotg, - struct dwc2_host_chan *chan, int chnum, +void dwc2_hcd_start_xfer_ddma(struct dwc2_hsotg *hsotg, + struct dwc2_qh *qh); +void dwc2_hcd_complete_xfer_ddma(struct dwc2_hsotg *hsotg, + struct dwc2_host_chan *chan, int chnum, enum dwc2_halt_status halt_status); -extern int dwc2_hcd_qh_init_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, - gfp_t mem_flags); -extern void dwc2_hcd_qh_free_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh); +int dwc2_hcd_qh_init_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, + gfp_t mem_flags); +void dwc2_hcd_qh_free_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh); /* Check if QH is non-periodic */ #define dwc2_qh_is_non_per(_qh_ptr_) \ @@ -732,8 +732,8 @@ static inline u16 dwc2_hcd_get_ep_bandwidth(struct dwc2_hsotg *hsotg, return qh->host_us; } -extern void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg, - struct dwc2_host_chan *chan, int chnum, +void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg, + struct dwc2_host_chan *chan, int chnum, struct dwc2_qtd *qtd); /* HCD Core API */ @@ -746,14 +746,14 @@ extern void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg, * Returns IRQ_HANDLED if interrupt is handled * Return IRQ_NONE if interrupt is not handled */ -extern irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg); +irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg); /** * dwc2_hcd_stop() - Halts the DWC_otg host mode operation * * @hsotg: The DWC2 HCD */ -extern void dwc2_hcd_stop(struct dwc2_hsotg *hsotg); +void dwc2_hcd_stop(struct dwc2_hsotg *hsotg); /** * dwc2_hcd_is_b_host() - Returns 1 if core currently is acting as B host, @@ -761,7 +761,7 @@ extern void dwc2_hcd_stop(struct dwc2_hsotg *hsotg); * * @hsotg: The DWC2 HCD */ -extern int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg); +int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg); /** * dwc2_hcd_dump_state() - Dumps hsotg state @@ -771,7 +771,7 @@ extern int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg); * NOTE: This function will be removed once the peripheral controller code * is integrated and the driver is stable */ -extern void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg); +void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg); /** * dwc2_hcd_dump_frrem() - Dumps the average frame remaining at SOF @@ -784,7 +784,7 @@ extern void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg); * NOTE: This function will be removed once the peripheral controller code * is integrated and the driver is stable */ -extern void dwc2_hcd_dump_frrem(struct dwc2_hsotg *hsotg); +void dwc2_hcd_dump_frrem(struct dwc2_hsotg *hsotg); /* URB interface */ @@ -793,15 +793,15 @@ extern void dwc2_hcd_dump_frrem(struct dwc2_hsotg *hsotg); #define URB_SEND_ZERO_PACKET 0x2 /* Host driver callbacks */ -extern struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg, - void *context, gfp_t mem_flags, - int *ttport); - -extern void dwc2_host_put_tt_info(struct dwc2_hsotg *hsotg, - struct dwc2_tt *dwc_tt); -extern int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context); -extern void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, - int status); +struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg, + void *context, gfp_t mem_flags, + int *ttport); + +void dwc2_host_put_tt_info(struct dwc2_hsotg *hsotg, + struct dwc2_tt *dwc_tt); +int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context); +void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, + int status); #ifdef DEBUG /* diff --git a/drivers/usb/dwc2/hcd_ddma.c b/drivers/usb/dwc2/hcd_ddma.c index cf0367768cb3..b8bdf545c3a7 100644 --- a/drivers/usb/dwc2/hcd_ddma.c +++ b/drivers/usb/dwc2/hcd_ddma.c @@ -89,8 +89,8 @@ static int dwc2_desc_list_alloc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, { struct kmem_cache *desc_cache; - if (qh->ep_type == USB_ENDPOINT_XFER_ISOC - && qh->dev_speed == USB_SPEED_HIGH) + if (qh->ep_type == USB_ENDPOINT_XFER_ISOC && + qh->dev_speed == USB_SPEED_HIGH) desc_cache = hsotg->desc_hsisoc_cache; else desc_cache = hsotg->desc_gen_cache; @@ -106,7 +106,7 @@ static int dwc2_desc_list_alloc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, qh->desc_list_sz, DMA_TO_DEVICE); - qh->n_bytes = kzalloc(sizeof(u32) * dwc2_max_desc_num(qh), flags); + qh->n_bytes = kcalloc(dwc2_max_desc_num(qh), sizeof(u32), flags); if (!qh->n_bytes) { dma_unmap_single(hsotg->dev, qh->desc_list_dma, qh->desc_list_sz, @@ -123,8 +123,8 @@ static void dwc2_desc_list_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { struct kmem_cache *desc_cache; - if (qh->ep_type == USB_ENDPOINT_XFER_ISOC - && qh->dev_speed == USB_SPEED_HIGH) + if (qh->ep_type == USB_ENDPOINT_XFER_ISOC && + qh->dev_speed == USB_SPEED_HIGH) desc_cache = hsotg->desc_hsisoc_cache; else desc_cache = hsotg->desc_gen_cache; @@ -175,7 +175,6 @@ static void dwc2_frame_list_free(struct dwc2_hsotg *hsotg) hsotg->frame_list = NULL; spin_unlock_irqrestore(&hsotg->lock, flags); - } static void dwc2_per_sched_enable(struct dwc2_hsotg *hsotg, u32 fr_list_en) @@ -297,7 +296,7 @@ static void dwc2_release_channel_ddma(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan = qh->channel; if (dwc2_qh_is_non_per(qh)) { - if (hsotg->params.uframe_sched > 0) + if (hsotg->params.uframe_sched) hsotg->available_host_channels++; else hsotg->non_periodic_channels--; @@ -404,7 +403,7 @@ void dwc2_hcd_qh_free_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) if ((qh->ep_type == USB_ENDPOINT_XFER_ISOC || qh->ep_type == USB_ENDPOINT_XFER_INT) && - (hsotg->params.uframe_sched > 0 || + (hsotg->params.uframe_sched || !hsotg->periodic_channels) && hsotg->frame_list) { dwc2_per_sched_disable(hsotg); dwc2_frame_list_free(hsotg); @@ -570,7 +569,7 @@ static void dwc2_fill_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, #endif dma_sync_single_for_device(hsotg->dev, - qh->desc_list_dma + + qh->desc_list_dma + (idx * sizeof(struct dwc2_dma_desc)), sizeof(struct dwc2_dma_desc), DMA_TO_DEVICE); @@ -776,7 +775,7 @@ static void dwc2_init_non_isoc_dma_desc(struct dwc2_hsotg *hsotg, n_desc - 1, &qh->desc_list[n_desc - 1]); dma_sync_single_for_device(hsotg->dev, - qh->desc_list_dma + + qh->desc_list_dma + ((n_desc - 1) * sizeof(struct dwc2_dma_desc)), sizeof(struct dwc2_dma_desc), @@ -816,7 +815,7 @@ static void dwc2_init_non_isoc_dma_desc(struct dwc2_hsotg *hsotg, dev_vdbg(hsotg->dev, "set A bit in desc 0 (%p)\n", &qh->desc_list[0]); dma_sync_single_for_device(hsotg->dev, - qh->desc_list_dma, + qh->desc_list_dma, sizeof(struct dwc2_dma_desc), DMA_TO_DEVICE); } @@ -1064,7 +1063,7 @@ stop_scan: } static int dwc2_update_non_isoc_urb_state_ddma(struct dwc2_hsotg *hsotg, - struct dwc2_host_chan *chan, + struct dwc2_host_chan *chan, struct dwc2_qtd *qtd, struct dwc2_dma_desc *dma_desc, enum dwc2_halt_status halt_status, diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index b8f4b6aaf1d0..28a8210710b1 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c @@ -60,7 +60,7 @@ static void dwc2_track_missed_sofs(struct dwc2_hsotg *hsotg) if (expected != curr_frame_number) dwc2_sch_vdbg(hsotg, "MISSED SOF %04x != %04x\n", - expected, curr_frame_number); + expected, curr_frame_number); #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS if (hsotg->frame_num_idx < FRAME_NUM_ARRAY_SIZE) { @@ -163,7 +163,7 @@ static void dwc2_sof_intr(struct dwc2_hsotg *hsotg) * (micro)frame */ list_move_tail(&qh->qh_list_entry, - &hsotg->periodic_sched_ready); + &hsotg->periodic_sched_ready); } } tr_type = dwc2_hcd_select_transactions(hsotg); @@ -297,8 +297,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, HCFG_FSLSPCLKSEL_SHIFT; if (prtspd == HPRT0_SPD_LOW_SPEED && - params->host_ls_low_power_phy_clk == - DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ) { + params->host_ls_low_power_phy_clk) { /* 6 MHZ */ dev_vdbg(hsotg->dev, "FS_PHY programming HCFG to 6 MHz\n"); @@ -398,7 +397,7 @@ static void dwc2_port_intr(struct dwc2_hsotg *hsotg) if (hsotg->params.dma_desc_fs_enable) { u32 hcfg; - hsotg->params.dma_desc_enable = 0; + hsotg->params.dma_desc_enable = false; hsotg->new_connection = false; hcfg = dwc2_readl(hsotg->regs + HCFG); hcfg &= ~HCFG_DESCDMA; @@ -442,7 +441,7 @@ static u32 dwc2_get_actual_xfer_length(struct dwc2_hsotg *hsotg, count = (hctsiz & TSIZ_XFERSIZE_MASK) >> TSIZ_XFERSIZE_SHIFT; length = chan->xfer_len - count; - if (short_read != NULL) + if (short_read) *short_read = (count != 0); } else if (chan->qh->do_split) { length = qtd->ssplit_out_xfer_count; @@ -604,7 +603,7 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state( /* Skip whole frame */ if (chan->qh->do_split && chan->ep_type == USB_ENDPOINT_XFER_ISOC && chan->ep_is_in && - hsotg->params.host_dma > 0) { + hsotg->params.host_dma) { qtd->complete_split = 0; qtd->isoc_split_offset = 0; } @@ -743,7 +742,7 @@ cleanup: dwc2_hc_cleanup(hsotg, chan); list_add_tail(&chan->hc_list_entry, &hsotg->free_hc_list); - if (hsotg->params.uframe_sched > 0) { + if (hsotg->params.uframe_sched) { hsotg->available_host_channels++; } else { switch (chan->ep_type) { @@ -789,7 +788,7 @@ static void dwc2_halt_channel(struct dwc2_hsotg *hsotg, if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "%s()\n", __func__); - if (hsotg->params.host_dma > 0) { + if (hsotg->params.host_dma) { if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "DMA enabled\n"); dwc2_release_channel(hsotg, chan, qtd, halt_status); @@ -823,7 +822,7 @@ static void dwc2_halt_channel(struct dwc2_hsotg *hsotg, * processed. */ list_move_tail(&chan->qh->qh_list_entry, - &hsotg->periodic_sched_assigned); + &hsotg->periodic_sched_assigned); /* * Make sure the Periodic Tx FIFO Empty interrupt is @@ -979,7 +978,7 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg, pipe_type = dwc2_hcd_get_pipe_type(&urb->pipe_info); - if (hsotg->params.dma_desc_enable > 0) { + if (hsotg->params.dma_desc_enable) { dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, halt_status); if (pipe_type == USB_ENDPOINT_XFER_ISOC) /* Do not disable the interrupt, just clear it */ @@ -990,7 +989,7 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg, /* Handle xfer complete on CSPLIT */ if (chan->qh->do_split) { if (chan->ep_type == USB_ENDPOINT_XFER_ISOC && chan->ep_is_in && - hsotg->params.host_dma > 0) { + hsotg->params.host_dma) { if (qtd->complete_split && dwc2_xfercomp_isoc_split_in(hsotg, chan, chnum, qtd)) @@ -1078,7 +1077,8 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg, dev_vdbg(hsotg->dev, " Isochronous transfer complete\n"); if (qtd->isoc_split_pos == DWC2_HCSPLT_XACTPOS_ALL) halt_status = dwc2_update_isoc_urb_state(hsotg, chan, - chnum, qtd, DWC2_HC_XFER_COMPLETE); + chnum, qtd, + DWC2_HC_XFER_COMPLETE); dwc2_complete_periodic_xfer(hsotg, chan, chnum, qtd, halt_status); break; @@ -1102,7 +1102,7 @@ static void dwc2_hc_stall_intr(struct dwc2_hsotg *hsotg, dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: STALL Received--\n", chnum); - if (hsotg->params.dma_desc_enable > 0) { + if (hsotg->params.dma_desc_enable) { dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, DWC2_HC_XFER_STALL); goto handle_stall_done; @@ -1212,7 +1212,7 @@ static void dwc2_hc_nak_intr(struct dwc2_hsotg *hsotg, switch (dwc2_hcd_get_pipe_type(&qtd->urb->pipe_info)) { case USB_ENDPOINT_XFER_CONTROL: case USB_ENDPOINT_XFER_BULK: - if (hsotg->params.host_dma > 0 && chan->ep_is_in) { + if (hsotg->params.host_dma && chan->ep_is_in) { /* * NAK interrupts are enabled on bulk/control IN * transfers in DMA mode for the sole purpose of @@ -1358,7 +1358,7 @@ static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg, */ if (chan->do_split && chan->complete_split) { if (chan->ep_is_in && chan->ep_type == USB_ENDPOINT_XFER_ISOC && - hsotg->params.host_dma > 0) { + hsotg->params.host_dma) { qtd->complete_split = 0; qtd->isoc_split_offset = 0; qtd->isoc_frame_index++; @@ -1379,7 +1379,7 @@ static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh = chan->qh; bool past_end; - if (hsotg->params.uframe_sched <= 0) { + if (!hsotg->params.uframe_sched) { int frnum = dwc2_hcd_get_frame_number(hsotg); /* Don't have num_hs_transfers; simple logic */ @@ -1389,22 +1389,27 @@ static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg, int end_frnum; /* - * Figure out the end frame based on schedule. - * - * We don't want to go on trying again and again - * forever. Let's stop when we've done all the - * transfers that were scheduled. - * - * We're going to be comparing start_active_frame - * and next_active_frame, both of which are 1 - * before the time the packet goes on the wire, - * so that cancels out. Basically if had 1 - * transfer and we saw 1 NYET then we're done. - * We're getting a NYET here so if next >= - * (start + num_transfers) we're done. The - * complexity is that for all but ISOC_OUT we - * skip one slot. - */ + * Figure out the end frame based on + * schedule. + * + * We don't want to go on trying again + * and again forever. Let's stop when + * we've done all the transfers that + * were scheduled. + * + * We're going to be comparing + * start_active_frame and + * next_active_frame, both of which + * are 1 before the time the packet + * goes on the wire, so that cancels + * out. Basically if had 1 transfer + * and we saw 1 NYET then we're done. + * We're getting a NYET here so if + * next >= (start + num_transfers) + * we're done. The complexity is that + * for all but ISOC_OUT we skip one + * slot. + */ end_frnum = dwc2_frame_num_inc( qh->start_active_frame, qh->num_hs_transfers); @@ -1472,7 +1477,7 @@ static void dwc2_hc_babble_intr(struct dwc2_hsotg *hsotg, dwc2_hc_handle_tt_clear(hsotg, chan, qtd); - if (hsotg->params.dma_desc_enable > 0) { + if (hsotg->params.dma_desc_enable) { dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, DWC2_HC_XFER_BABBLE_ERR); goto disable_int; @@ -1577,7 +1582,7 @@ static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg, dev_err(hsotg->dev, " Interval: %d\n", urb->interval); /* Core halts the channel for Descriptor DMA mode */ - if (hsotg->params.dma_desc_enable > 0) { + if (hsotg->params.dma_desc_enable) { dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, DWC2_HC_XFER_AHB_ERR); goto handle_ahberr_done; @@ -1609,7 +1614,7 @@ static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg, dwc2_hc_handle_tt_clear(hsotg, chan, qtd); - if (hsotg->params.dma_desc_enable > 0) { + if (hsotg->params.dma_desc_enable) { dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, DWC2_HC_XFER_XACT_ERR); goto handle_xacterr_done; @@ -1620,7 +1625,6 @@ static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg, case USB_ENDPOINT_XFER_BULK: qtd->error_count++; if (!chan->qh->ping_state) { - dwc2_update_urb_state_abn(hsotg, chan, chnum, qtd->urb, qtd, DWC2_HC_XFER_XACT_ERR); dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd); @@ -1645,7 +1649,7 @@ static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg, enum dwc2_halt_status halt_status; halt_status = dwc2_update_isoc_urb_state(hsotg, chan, - chnum, qtd, DWC2_HC_XFER_XACT_ERR); + chnum, qtd, DWC2_HC_XFER_XACT_ERR); dwc2_halt_channel(hsotg, chan, qtd, halt_status); } break; @@ -1803,8 +1807,8 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg, if (chan->halt_status == DWC2_HC_XFER_URB_DEQUEUE || (chan->halt_status == DWC2_HC_XFER_AHB_ERR && - hsotg->params.dma_desc_enable <= 0)) { - if (hsotg->params.dma_desc_enable > 0) + !hsotg->params.dma_desc_enable)) { + if (hsotg->params.dma_desc_enable) dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, chan->halt_status); else @@ -1835,7 +1839,7 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg, } else if (chan->hcint & HCINTMSK_STALL) { dwc2_hc_stall_intr(hsotg, chan, chnum, qtd); } else if ((chan->hcint & HCINTMSK_XACTERR) && - hsotg->params.dma_desc_enable <= 0) { + !hsotg->params.dma_desc_enable) { if (out_nak_enh) { if (chan->hcint & (HCINTMSK_NYET | HCINTMSK_NAK | HCINTMSK_ACK)) { @@ -1855,10 +1859,10 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg, */ dwc2_hc_xacterr_intr(hsotg, chan, chnum, qtd); } else if ((chan->hcint & HCINTMSK_XCS_XACT) && - hsotg->params.dma_desc_enable > 0) { + hsotg->params.dma_desc_enable) { dwc2_hc_xacterr_intr(hsotg, chan, chnum, qtd); } else if ((chan->hcint & HCINTMSK_AHBERR) && - hsotg->params.dma_desc_enable > 0) { + hsotg->params.dma_desc_enable) { dwc2_hc_ahberr_intr(hsotg, chan, chnum, qtd); } else if (chan->hcint & HCINTMSK_BBLERR) { dwc2_hc_babble_intr(hsotg, chan, chnum, qtd); @@ -1951,7 +1955,7 @@ static void dwc2_hc_chhltd_intr(struct dwc2_hsotg *hsotg, dev_vdbg(hsotg->dev, "--Host Channel %d Interrupt: Channel Halted--\n", chnum); - if (hsotg->params.host_dma > 0) { + if (hsotg->params.host_dma) { dwc2_hc_chhltd_intr_dma(hsotg, chan, chnum, qtd); } else { if (!dwc2_halt_status_ok(hsotg, chan, chnum, qtd)) @@ -1970,7 +1974,7 @@ static bool dwc2_check_qtd_still_ok(struct dwc2_qtd *qtd, struct dwc2_qh *qh) { struct dwc2_qtd *cur_head; - if (qh == NULL) + if (!qh) return false; cur_head = list_first_entry(&qh->qtd_list, struct dwc2_qtd, @@ -2028,7 +2032,7 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum) * interrupt unmasked */ WARN_ON(hcint != HCINTMSK_CHHLTD); - if (hsotg->params.dma_desc_enable > 0) + if (hsotg->params.dma_desc_enable) dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, chan->halt_status); else @@ -2056,7 +2060,7 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum) qtd = list_first_entry(&chan->qh->qtd_list, struct dwc2_qtd, qtd_list_entry); - if (hsotg->params.host_dma <= 0) { + if (!hsotg->params.host_dma) { if ((hcint & HCINTMSK_CHHLTD) && hcint != HCINTMSK_CHHLTD) hcint &= ~HCINTMSK_CHHLTD; } diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c index 5713f03a4e56..3ae8b1bbaa55 100644 --- a/drivers/usb/dwc2/hcd_queue.c +++ b/drivers/usb/dwc2/hcd_queue.c @@ -76,14 +76,13 @@ static int dwc2_periodic_channel_available(struct dwc2_hsotg *hsotg) int num_channels; num_channels = hsotg->params.host_channels; - if (hsotg->periodic_channels + hsotg->non_periodic_channels < - num_channels - && hsotg->periodic_channels < num_channels - 1) { + if ((hsotg->periodic_channels + hsotg->non_periodic_channels < + num_channels) && (hsotg->periodic_channels < num_channels - 1)) { status = 0; } else { dev_dbg(hsotg->dev, - "%s: Total channels: %d, Periodic: %d, " - "Non-periodic: %d\n", __func__, num_channels, + "%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n", + __func__, num_channels, hsotg->periodic_channels, hsotg->non_periodic_channels); status = -ENOSPC; } @@ -485,7 +484,6 @@ static void pmap_print(unsigned long *map, int bits_per_period, } } - struct dwc2_qh_print_data { struct dwc2_hsotg *hsotg; struct dwc2_qh *qh; @@ -558,7 +556,6 @@ static void dwc2_qh_schedule_print(struct dwc2_hsotg *hsotg, DWC2_HS_SCHEDULE_UFRAMES, "uFrame", "us", dwc2_qh_print, &print_data); } - return; } #else static inline void dwc2_qh_schedule_print(struct dwc2_hsotg *hsotg, @@ -587,7 +584,7 @@ static int dwc2_ls_pmap_schedule(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, unsigned long *map = dwc2_get_ls_map(hsotg, qh); int slice; - if (map == NULL) + if (!map) return -EINVAL; /* @@ -626,7 +623,7 @@ static void dwc2_ls_pmap_unschedule(struct dwc2_hsotg *hsotg, unsigned long *map = dwc2_get_ls_map(hsotg, qh); /* Schedule should have failed, so no worries about no error code */ - if (map == NULL) + if (!map) return; pmap_unschedule(map, DWC2_LS_PERIODIC_SLICES_PER_FRAME, @@ -1107,7 +1104,7 @@ static void dwc2_pick_first_frame(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) next_active_frame = earliest_frame; /* Get the "no microframe schduler" out of the way... */ - if (hsotg->params.uframe_sched <= 0) { + if (!hsotg->params.uframe_sched) { if (qh->do_split) /* Splits are active at microframe 0 minus 1 */ next_active_frame |= 0x7; @@ -1182,7 +1179,7 @@ exit: qh->start_active_frame = next_active_frame; dwc2_sch_vdbg(hsotg, "QH=%p First fn=%04x nxt=%04x\n", - qh, frame_number, qh->next_active_frame); + qh, frame_number, qh->next_active_frame); } /** @@ -1200,7 +1197,7 @@ static int dwc2_do_reserve(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { int status; - if (hsotg->params.uframe_sched > 0) { + if (hsotg->params.uframe_sched) { status = dwc2_uframe_schedule(hsotg, qh); } else { status = dwc2_periodic_channel_available(hsotg); @@ -1221,7 +1218,7 @@ static int dwc2_do_reserve(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) return status; } - if (hsotg->params.uframe_sched <= 0) + if (!hsotg->params.uframe_sched) /* Reserve periodic channel */ hsotg->periodic_channels++; @@ -1257,7 +1254,7 @@ static void dwc2_do_unreserve(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) /* Update claimed usecs per (micro)frame */ hsotg->periodic_usecs -= qh->host_us; - if (hsotg->params.uframe_sched > 0) { + if (hsotg->params.uframe_sched) { dwc2_uframe_unschedule(hsotg, qh); } else { /* Release periodic channel reservation */ @@ -1394,7 +1391,7 @@ static int dwc2_schedule_periodic(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) qh->unreserve_pending = 0; - if (hsotg->params.dma_desc_enable > 0) + if (hsotg->params.dma_desc_enable) /* Don't rely on SOF and start in ready schedule */ list_add_tail(&qh->qh_list_entry, &hsotg->periodic_sched_ready); else @@ -1501,7 +1498,6 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, device_ns += dwc_tt->usb_tt->think_time; qh->device_us = NS_TO_US(device_ns); - qh->device_interval = urb->interval; qh->host_interval = urb->interval * (do_split ? 8 : 1); @@ -1587,7 +1583,7 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, * Return: Pointer to the newly allocated QH, or NULL on error */ struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, - struct dwc2_hcd_urb *urb, + struct dwc2_hcd_urb *urb, gfp_t mem_flags) { struct dwc2_qh *qh; @@ -1602,7 +1598,7 @@ struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, dwc2_qh_init(hsotg, qh, urb, mem_flags); - if (hsotg->params.dma_desc_enable > 0 && + if (hsotg->params.dma_desc_enable && dwc2_hcd_qh_init_ddma(hsotg, qh, mem_flags) < 0) { dwc2_hcd_qh_free(hsotg, qh); return NULL; @@ -1714,7 +1710,7 @@ void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) dwc2_deschedule_periodic(hsotg, qh); hsotg->periodic_qh_count--; if (!hsotg->periodic_qh_count && - hsotg->params.dma_desc_enable <= 0) { + !hsotg->params.dma_desc_enable) { intr_mask = dwc2_readl(hsotg->regs + GINTMSK); intr_mask &= ~GINTSTS_SOF; dwc2_writel(intr_mask, hsotg->regs + GINTMSK); @@ -1741,7 +1737,7 @@ void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) * Return: number missed by (or 0 if we didn't miss). */ static int dwc2_next_for_periodic_split(struct dwc2_hsotg *hsotg, - struct dwc2_qh *qh, u16 frame_number) + struct dwc2_qh *qh, u16 frame_number) { u16 old_frame = qh->next_active_frame; u16 prev_frame_number = dwc2_frame_num_dec(frame_number, 1); @@ -1804,7 +1800,7 @@ static int dwc2_next_for_periodic_split(struct dwc2_hsotg *hsotg, * Return: number missed by (or 0 if we didn't miss). */ static int dwc2_next_periodic_start(struct dwc2_hsotg *hsotg, - struct dwc2_qh *qh, u16 frame_number) + struct dwc2_qh *qh, u16 frame_number) { int missed = 0; u16 interval = qh->host_interval; @@ -1926,7 +1922,7 @@ void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, missed = dwc2_next_periodic_start(hsotg, qh, frame_number); dwc2_sch_vdbg(hsotg, - "QH=%p next(%d) fn=%04x, sch=%04x=>%04x (%+d) miss=%d %s\n", + "QH=%p next(%d) fn=%04x, sch=%04x=>%04x (%+d) miss=%d %s\n", qh, sched_next_periodic_split, frame_number, old_frame, qh->next_active_frame, dwc2_frame_num_dec(qh->next_active_frame, old_frame), diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h index 5be056b39e5c..bde72489ae66 100644 --- a/drivers/usb/dwc2/hw.h +++ b/drivers/usb/dwc2/hw.h @@ -40,37 +40,37 @@ #define HSOTG_REG(x) (x) #define GOTGCTL HSOTG_REG(0x000) -#define GOTGCTL_CHIRPEN (1 << 27) +#define GOTGCTL_CHIRPEN BIT(27) #define GOTGCTL_MULT_VALID_BC_MASK (0x1f << 22) #define GOTGCTL_MULT_VALID_BC_SHIFT 22 -#define GOTGCTL_OTGVER (1 << 20) -#define GOTGCTL_BSESVLD (1 << 19) -#define GOTGCTL_ASESVLD (1 << 18) -#define GOTGCTL_DBNC_SHORT (1 << 17) -#define GOTGCTL_CONID_B (1 << 16) -#define GOTGCTL_DBNCE_FLTR_BYPASS (1 << 15) -#define GOTGCTL_DEVHNPEN (1 << 11) -#define GOTGCTL_HSTSETHNPEN (1 << 10) -#define GOTGCTL_HNPREQ (1 << 9) -#define GOTGCTL_HSTNEGSCS (1 << 8) -#define GOTGCTL_SESREQ (1 << 1) -#define GOTGCTL_SESREQSCS (1 << 0) +#define GOTGCTL_OTGVER BIT(20) +#define GOTGCTL_BSESVLD BIT(19) +#define GOTGCTL_ASESVLD BIT(18) +#define GOTGCTL_DBNC_SHORT BIT(17) +#define GOTGCTL_CONID_B BIT(16) +#define GOTGCTL_DBNCE_FLTR_BYPASS BIT(15) +#define GOTGCTL_DEVHNPEN BIT(11) +#define GOTGCTL_HSTSETHNPEN BIT(10) +#define GOTGCTL_HNPREQ BIT(9) +#define GOTGCTL_HSTNEGSCS BIT(8) +#define GOTGCTL_SESREQ BIT(1) +#define GOTGCTL_SESREQSCS BIT(0) #define GOTGINT HSOTG_REG(0x004) -#define GOTGINT_DBNCE_DONE (1 << 19) -#define GOTGINT_A_DEV_TOUT_CHG (1 << 18) -#define GOTGINT_HST_NEG_DET (1 << 17) -#define GOTGINT_HST_NEG_SUC_STS_CHNG (1 << 9) -#define GOTGINT_SES_REQ_SUC_STS_CHNG (1 << 8) -#define GOTGINT_SES_END_DET (1 << 2) +#define GOTGINT_DBNCE_DONE BIT(19) +#define GOTGINT_A_DEV_TOUT_CHG BIT(18) +#define GOTGINT_HST_NEG_DET BIT(17) +#define GOTGINT_HST_NEG_SUC_STS_CHNG BIT(9) +#define GOTGINT_SES_REQ_SUC_STS_CHNG BIT(8) +#define GOTGINT_SES_END_DET BIT(2) #define GAHBCFG HSOTG_REG(0x008) -#define GAHBCFG_AHB_SINGLE (1 << 23) -#define GAHBCFG_NOTI_ALL_DMA_WRIT (1 << 22) -#define GAHBCFG_REM_MEM_SUPP (1 << 21) -#define GAHBCFG_P_TXF_EMP_LVL (1 << 8) -#define GAHBCFG_NP_TXF_EMP_LVL (1 << 7) -#define GAHBCFG_DMA_EN (1 << 5) +#define GAHBCFG_AHB_SINGLE BIT(23) +#define GAHBCFG_NOTI_ALL_DMA_WRIT BIT(22) +#define GAHBCFG_REM_MEM_SUPP BIT(21) +#define GAHBCFG_P_TXF_EMP_LVL BIT(8) +#define GAHBCFG_NP_TXF_EMP_LVL BIT(7) +#define GAHBCFG_DMA_EN BIT(5) #define GAHBCFG_HBSTLEN_MASK (0xf << 1) #define GAHBCFG_HBSTLEN_SHIFT 1 #define GAHBCFG_HBSTLEN_SINGLE 0 @@ -78,38 +78,38 @@ #define GAHBCFG_HBSTLEN_INCR4 3 #define GAHBCFG_HBSTLEN_INCR8 5 #define GAHBCFG_HBSTLEN_INCR16 7 -#define GAHBCFG_GLBL_INTR_EN (1 << 0) +#define GAHBCFG_GLBL_INTR_EN BIT(0) #define GAHBCFG_CTRL_MASK (GAHBCFG_P_TXF_EMP_LVL | \ GAHBCFG_NP_TXF_EMP_LVL | \ GAHBCFG_DMA_EN | \ GAHBCFG_GLBL_INTR_EN) #define GUSBCFG HSOTG_REG(0x00C) -#define GUSBCFG_FORCEDEVMODE (1 << 30) -#define GUSBCFG_FORCEHOSTMODE (1 << 29) -#define GUSBCFG_TXENDDELAY (1 << 28) -#define GUSBCFG_ICTRAFFICPULLREMOVE (1 << 27) -#define GUSBCFG_ICUSBCAP (1 << 26) -#define GUSBCFG_ULPI_INT_PROT_DIS (1 << 25) -#define GUSBCFG_INDICATORPASSTHROUGH (1 << 24) -#define GUSBCFG_INDICATORCOMPLEMENT (1 << 23) -#define GUSBCFG_TERMSELDLPULSE (1 << 22) -#define GUSBCFG_ULPI_INT_VBUS_IND (1 << 21) -#define GUSBCFG_ULPI_EXT_VBUS_DRV (1 << 20) -#define GUSBCFG_ULPI_CLK_SUSP_M (1 << 19) -#define GUSBCFG_ULPI_AUTO_RES (1 << 18) -#define GUSBCFG_ULPI_FS_LS (1 << 17) -#define GUSBCFG_OTG_UTMI_FS_SEL (1 << 16) -#define GUSBCFG_PHY_LP_CLK_SEL (1 << 15) +#define GUSBCFG_FORCEDEVMODE BIT(30) +#define GUSBCFG_FORCEHOSTMODE BIT(29) +#define GUSBCFG_TXENDDELAY BIT(28) +#define GUSBCFG_ICTRAFFICPULLREMOVE BIT(27) +#define GUSBCFG_ICUSBCAP BIT(26) +#define GUSBCFG_ULPI_INT_PROT_DIS BIT(25) +#define GUSBCFG_INDICATORPASSTHROUGH BIT(24) +#define GUSBCFG_INDICATORCOMPLEMENT BIT(23) +#define GUSBCFG_TERMSELDLPULSE BIT(22) +#define GUSBCFG_ULPI_INT_VBUS_IND BIT(21) +#define GUSBCFG_ULPI_EXT_VBUS_DRV BIT(20) +#define GUSBCFG_ULPI_CLK_SUSP_M BIT(19) +#define GUSBCFG_ULPI_AUTO_RES BIT(18) +#define GUSBCFG_ULPI_FS_LS BIT(17) +#define GUSBCFG_OTG_UTMI_FS_SEL BIT(16) +#define GUSBCFG_PHY_LP_CLK_SEL BIT(15) #define GUSBCFG_USBTRDTIM_MASK (0xf << 10) #define GUSBCFG_USBTRDTIM_SHIFT 10 -#define GUSBCFG_HNPCAP (1 << 9) -#define GUSBCFG_SRPCAP (1 << 8) -#define GUSBCFG_DDRSEL (1 << 7) -#define GUSBCFG_PHYSEL (1 << 6) -#define GUSBCFG_FSINTF (1 << 5) -#define GUSBCFG_ULPI_UTMI_SEL (1 << 4) -#define GUSBCFG_PHYIF16 (1 << 3) +#define GUSBCFG_HNPCAP BIT(9) +#define GUSBCFG_SRPCAP BIT(8) +#define GUSBCFG_DDRSEL BIT(7) +#define GUSBCFG_PHYSEL BIT(6) +#define GUSBCFG_FSINTF BIT(5) +#define GUSBCFG_ULPI_UTMI_SEL BIT(4) +#define GUSBCFG_PHYIF16 BIT(3) #define GUSBCFG_PHYIF8 (0 << 3) #define GUSBCFG_TOUTCAL_MASK (0x7 << 0) #define GUSBCFG_TOUTCAL_SHIFT 0 @@ -117,54 +117,54 @@ #define GUSBCFG_TOUTCAL(_x) ((_x) << 0) #define GRSTCTL HSOTG_REG(0x010) -#define GRSTCTL_AHBIDLE (1 << 31) -#define GRSTCTL_DMAREQ (1 << 30) +#define GRSTCTL_AHBIDLE BIT(31) +#define GRSTCTL_DMAREQ BIT(30) #define GRSTCTL_TXFNUM_MASK (0x1f << 6) #define GRSTCTL_TXFNUM_SHIFT 6 #define GRSTCTL_TXFNUM_LIMIT 0x1f #define GRSTCTL_TXFNUM(_x) ((_x) << 6) -#define GRSTCTL_TXFFLSH (1 << 5) -#define GRSTCTL_RXFFLSH (1 << 4) -#define GRSTCTL_IN_TKNQ_FLSH (1 << 3) -#define GRSTCTL_FRMCNTRRST (1 << 2) -#define GRSTCTL_HSFTRST (1 << 1) -#define GRSTCTL_CSFTRST (1 << 0) +#define GRSTCTL_TXFFLSH BIT(5) +#define GRSTCTL_RXFFLSH BIT(4) +#define GRSTCTL_IN_TKNQ_FLSH BIT(3) +#define GRSTCTL_FRMCNTRRST BIT(2) +#define GRSTCTL_HSFTRST BIT(1) +#define GRSTCTL_CSFTRST BIT(0) #define GINTSTS HSOTG_REG(0x014) #define GINTMSK HSOTG_REG(0x018) -#define GINTSTS_WKUPINT (1 << 31) -#define GINTSTS_SESSREQINT (1 << 30) -#define GINTSTS_DISCONNINT (1 << 29) -#define GINTSTS_CONIDSTSCHNG (1 << 28) -#define GINTSTS_LPMTRANRCVD (1 << 27) -#define GINTSTS_PTXFEMP (1 << 26) -#define GINTSTS_HCHINT (1 << 25) -#define GINTSTS_PRTINT (1 << 24) -#define GINTSTS_RESETDET (1 << 23) -#define GINTSTS_FET_SUSP (1 << 22) -#define GINTSTS_INCOMPL_IP (1 << 21) -#define GINTSTS_INCOMPL_SOOUT (1 << 21) -#define GINTSTS_INCOMPL_SOIN (1 << 20) -#define GINTSTS_OEPINT (1 << 19) -#define GINTSTS_IEPINT (1 << 18) -#define GINTSTS_EPMIS (1 << 17) -#define GINTSTS_RESTOREDONE (1 << 16) -#define GINTSTS_EOPF (1 << 15) -#define GINTSTS_ISOUTDROP (1 << 14) -#define GINTSTS_ENUMDONE (1 << 13) -#define GINTSTS_USBRST (1 << 12) -#define GINTSTS_USBSUSP (1 << 11) -#define GINTSTS_ERLYSUSP (1 << 10) -#define GINTSTS_I2CINT (1 << 9) -#define GINTSTS_ULPI_CK_INT (1 << 8) -#define GINTSTS_GOUTNAKEFF (1 << 7) -#define GINTSTS_GINNAKEFF (1 << 6) -#define GINTSTS_NPTXFEMP (1 << 5) -#define GINTSTS_RXFLVL (1 << 4) -#define GINTSTS_SOF (1 << 3) -#define GINTSTS_OTGINT (1 << 2) -#define GINTSTS_MODEMIS (1 << 1) -#define GINTSTS_CURMODE_HOST (1 << 0) +#define GINTSTS_WKUPINT BIT(31) +#define GINTSTS_SESSREQINT BIT(30) +#define GINTSTS_DISCONNINT BIT(29) +#define GINTSTS_CONIDSTSCHNG BIT(28) +#define GINTSTS_LPMTRANRCVD BIT(27) +#define GINTSTS_PTXFEMP BIT(26) +#define GINTSTS_HCHINT BIT(25) +#define GINTSTS_PRTINT BIT(24) +#define GINTSTS_RESETDET BIT(23) +#define GINTSTS_FET_SUSP BIT(22) +#define GINTSTS_INCOMPL_IP BIT(21) +#define GINTSTS_INCOMPL_SOOUT BIT(21) +#define GINTSTS_INCOMPL_SOIN BIT(20) +#define GINTSTS_OEPINT BIT(19) +#define GINTSTS_IEPINT BIT(18) +#define GINTSTS_EPMIS BIT(17) +#define GINTSTS_RESTOREDONE BIT(16) +#define GINTSTS_EOPF BIT(15) +#define GINTSTS_ISOUTDROP BIT(14) +#define GINTSTS_ENUMDONE BIT(13) +#define GINTSTS_USBRST BIT(12) +#define GINTSTS_USBSUSP BIT(11) +#define GINTSTS_ERLYSUSP BIT(10) +#define GINTSTS_I2CINT BIT(9) +#define GINTSTS_ULPI_CK_INT BIT(8) +#define GINTSTS_GOUTNAKEFF BIT(7) +#define GINTSTS_GINNAKEFF BIT(6) +#define GINTSTS_NPTXFEMP BIT(5) +#define GINTSTS_RXFLVL BIT(4) +#define GINTSTS_SOF BIT(3) +#define GINTSTS_OTGINT BIT(2) +#define GINTSTS_MODEMIS BIT(1) +#define GINTSTS_CURMODE_HOST BIT(0) #define GRXSTSR HSOTG_REG(0x01C) #define GRXSTSP HSOTG_REG(0x020) @@ -208,14 +208,14 @@ #define GNPTXSTS_NP_TXF_SPC_AVAIL_GET(_v) (((_v) >> 0) & 0xffff) #define GI2CCTL HSOTG_REG(0x0030) -#define GI2CCTL_BSYDNE (1 << 31) -#define GI2CCTL_RW (1 << 30) -#define GI2CCTL_I2CDATSE0 (1 << 28) +#define GI2CCTL_BSYDNE BIT(31) +#define GI2CCTL_RW BIT(30) +#define GI2CCTL_I2CDATSE0 BIT(28) #define GI2CCTL_I2CDEVADDR_MASK (0x3 << 26) #define GI2CCTL_I2CDEVADDR_SHIFT 26 -#define GI2CCTL_I2CSUSPCTL (1 << 25) -#define GI2CCTL_ACK (1 << 24) -#define GI2CCTL_I2CEN (1 << 23) +#define GI2CCTL_I2CSUSPCTL BIT(25) +#define GI2CCTL_ACK BIT(24) +#define GI2CCTL_I2CEN BIT(23) #define GI2CCTL_ADDR_MASK (0x7f << 16) #define GI2CCTL_ADDR_SHIFT 16 #define GI2CCTL_REGADDR_MASK (0xff << 8) @@ -230,16 +230,16 @@ #define GHWCFG1 HSOTG_REG(0x0044) #define GHWCFG2 HSOTG_REG(0x0048) -#define GHWCFG2_OTG_ENABLE_IC_USB (1 << 31) +#define GHWCFG2_OTG_ENABLE_IC_USB BIT(31) #define GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK (0x1f << 26) #define GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT 26 #define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK (0x3 << 24) #define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT 24 #define GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK (0x3 << 22) #define GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT 22 -#define GHWCFG2_MULTI_PROC_INT (1 << 20) -#define GHWCFG2_DYNAMIC_FIFO (1 << 19) -#define GHWCFG2_PERIO_EP_SUPPORTED (1 << 18) +#define GHWCFG2_MULTI_PROC_INT BIT(20) +#define GHWCFG2_DYNAMIC_FIFO BIT(19) +#define GHWCFG2_PERIO_EP_SUPPORTED BIT(18) #define GHWCFG2_NUM_HOST_CHAN_MASK (0xf << 14) #define GHWCFG2_NUM_HOST_CHAN_SHIFT 14 #define GHWCFG2_NUM_DEV_EP_MASK (0xf << 10) @@ -256,7 +256,7 @@ #define GHWCFG2_HS_PHY_TYPE_UTMI 1 #define GHWCFG2_HS_PHY_TYPE_ULPI 2 #define GHWCFG2_HS_PHY_TYPE_UTMI_ULPI 3 -#define GHWCFG2_POINT2POINT (1 << 5) +#define GHWCFG2_POINT2POINT BIT(5) #define GHWCFG2_ARCHITECTURE_MASK (0x3 << 3) #define GHWCFG2_ARCHITECTURE_SHIFT 3 #define GHWCFG2_SLAVE_ONLY_ARCH 0 @@ -276,32 +276,32 @@ #define GHWCFG3 HSOTG_REG(0x004c) #define GHWCFG3_DFIFO_DEPTH_MASK (0xffff << 16) #define GHWCFG3_DFIFO_DEPTH_SHIFT 16 -#define GHWCFG3_OTG_LPM_EN (1 << 15) -#define GHWCFG3_BC_SUPPORT (1 << 14) -#define GHWCFG3_OTG_ENABLE_HSIC (1 << 13) -#define GHWCFG3_ADP_SUPP (1 << 12) -#define GHWCFG3_SYNCH_RESET_TYPE (1 << 11) -#define GHWCFG3_OPTIONAL_FEATURES (1 << 10) -#define GHWCFG3_VENDOR_CTRL_IF (1 << 9) -#define GHWCFG3_I2C (1 << 8) -#define GHWCFG3_OTG_FUNC (1 << 7) +#define GHWCFG3_OTG_LPM_EN BIT(15) +#define GHWCFG3_BC_SUPPORT BIT(14) +#define GHWCFG3_OTG_ENABLE_HSIC BIT(13) +#define GHWCFG3_ADP_SUPP BIT(12) +#define GHWCFG3_SYNCH_RESET_TYPE BIT(11) +#define GHWCFG3_OPTIONAL_FEATURES BIT(10) +#define GHWCFG3_VENDOR_CTRL_IF BIT(9) +#define GHWCFG3_I2C BIT(8) +#define GHWCFG3_OTG_FUNC BIT(7) #define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK (0x7 << 4) #define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT 4 #define GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK (0xf << 0) #define GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT 0 #define GHWCFG4 HSOTG_REG(0x0050) -#define GHWCFG4_DESC_DMA_DYN (1 << 31) -#define GHWCFG4_DESC_DMA (1 << 30) +#define GHWCFG4_DESC_DMA_DYN BIT(31) +#define GHWCFG4_DESC_DMA BIT(30) #define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26) #define GHWCFG4_NUM_IN_EPS_SHIFT 26 -#define GHWCFG4_DED_FIFO_EN (1 << 25) +#define GHWCFG4_DED_FIFO_EN BIT(25) #define GHWCFG4_DED_FIFO_SHIFT 25 -#define GHWCFG4_SESSION_END_FILT_EN (1 << 24) -#define GHWCFG4_B_VALID_FILT_EN (1 << 23) -#define GHWCFG4_A_VALID_FILT_EN (1 << 22) -#define GHWCFG4_VBUS_VALID_FILT_EN (1 << 21) -#define GHWCFG4_IDDIG_FILT_EN (1 << 20) +#define GHWCFG4_SESSION_END_FILT_EN BIT(24) +#define GHWCFG4_B_VALID_FILT_EN BIT(23) +#define GHWCFG4_A_VALID_FILT_EN BIT(22) +#define GHWCFG4_VBUS_VALID_FILT_EN BIT(21) +#define GHWCFG4_IDDIG_FILT_EN BIT(20) #define GHWCFG4_NUM_DEV_MODE_CTRL_EP_MASK (0xf << 16) #define GHWCFG4_NUM_DEV_MODE_CTRL_EP_SHIFT 16 #define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14) @@ -309,64 +309,64 @@ #define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0 #define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1 #define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2 -#define GHWCFG4_XHIBER (1 << 7) -#define GHWCFG4_HIBER (1 << 6) -#define GHWCFG4_MIN_AHB_FREQ (1 << 5) -#define GHWCFG4_POWER_OPTIMIZ (1 << 4) +#define GHWCFG4_XHIBER BIT(7) +#define GHWCFG4_HIBER BIT(6) +#define GHWCFG4_MIN_AHB_FREQ BIT(5) +#define GHWCFG4_POWER_OPTIMIZ BIT(4) #define GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK (0xf << 0) #define GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT 0 #define GLPMCFG HSOTG_REG(0x0054) -#define GLPMCFG_INV_SEL_HSIC (1 << 31) -#define GLPMCFG_HSIC_CONNECT (1 << 30) +#define GLPMCFG_INV_SEL_HSIC BIT(31) +#define GLPMCFG_HSIC_CONNECT BIT(30) #define GLPMCFG_RETRY_COUNT_STS_MASK (0x7 << 25) #define GLPMCFG_RETRY_COUNT_STS_SHIFT 25 -#define GLPMCFG_SEND_LPM (1 << 24) +#define GLPMCFG_SEND_LPM BIT(24) #define GLPMCFG_RETRY_COUNT_MASK (0x7 << 21) #define GLPMCFG_RETRY_COUNT_SHIFT 21 #define GLPMCFG_LPM_CHAN_INDEX_MASK (0xf << 17) #define GLPMCFG_LPM_CHAN_INDEX_SHIFT 17 -#define GLPMCFG_SLEEP_STATE_RESUMEOK (1 << 16) -#define GLPMCFG_PRT_SLEEP_STS (1 << 15) +#define GLPMCFG_SLEEP_STATE_RESUMEOK BIT(16) +#define GLPMCFG_PRT_SLEEP_STS BIT(15) #define GLPMCFG_LPM_RESP_MASK (0x3 << 13) #define GLPMCFG_LPM_RESP_SHIFT 13 #define GLPMCFG_HIRD_THRES_MASK (0x1f << 8) #define GLPMCFG_HIRD_THRES_SHIFT 8 #define GLPMCFG_HIRD_THRES_EN (0x10 << 8) -#define GLPMCFG_EN_UTMI_SLEEP (1 << 7) -#define GLPMCFG_REM_WKUP_EN (1 << 6) +#define GLPMCFG_EN_UTMI_SLEEP BIT(7) +#define GLPMCFG_REM_WKUP_EN BIT(6) #define GLPMCFG_HIRD_MASK (0xf << 2) #define GLPMCFG_HIRD_SHIFT 2 -#define GLPMCFG_APPL_RESP (1 << 1) -#define GLPMCFG_LPM_CAP_EN (1 << 0) +#define GLPMCFG_APPL_RESP BIT(1) +#define GLPMCFG_LPM_CAP_EN BIT(0) #define GPWRDN HSOTG_REG(0x0058) #define GPWRDN_MULT_VAL_ID_BC_MASK (0x1f << 24) #define GPWRDN_MULT_VAL_ID_BC_SHIFT 24 -#define GPWRDN_ADP_INT (1 << 23) -#define GPWRDN_BSESSVLD (1 << 22) -#define GPWRDN_IDSTS (1 << 21) +#define GPWRDN_ADP_INT BIT(23) +#define GPWRDN_BSESSVLD BIT(22) +#define GPWRDN_IDSTS BIT(21) #define GPWRDN_LINESTATE_MASK (0x3 << 19) #define GPWRDN_LINESTATE_SHIFT 19 -#define GPWRDN_STS_CHGINT_MSK (1 << 18) -#define GPWRDN_STS_CHGINT (1 << 17) -#define GPWRDN_SRP_DET_MSK (1 << 16) -#define GPWRDN_SRP_DET (1 << 15) -#define GPWRDN_CONNECT_DET_MSK (1 << 14) -#define GPWRDN_CONNECT_DET (1 << 13) -#define GPWRDN_DISCONN_DET_MSK (1 << 12) -#define GPWRDN_DISCONN_DET (1 << 11) -#define GPWRDN_RST_DET_MSK (1 << 10) -#define GPWRDN_RST_DET (1 << 9) -#define GPWRDN_LNSTSCHG_MSK (1 << 8) -#define GPWRDN_LNSTSCHG (1 << 7) -#define GPWRDN_DIS_VBUS (1 << 6) -#define GPWRDN_PWRDNSWTCH (1 << 5) -#define GPWRDN_PWRDNRSTN (1 << 4) -#define GPWRDN_PWRDNCLMP (1 << 3) -#define GPWRDN_RESTORE (1 << 2) -#define GPWRDN_PMUACTV (1 << 1) -#define GPWRDN_PMUINTSEL (1 << 0) +#define GPWRDN_STS_CHGINT_MSK BIT(18) +#define GPWRDN_STS_CHGINT BIT(17) +#define GPWRDN_SRP_DET_MSK BIT(16) +#define GPWRDN_SRP_DET BIT(15) +#define GPWRDN_CONNECT_DET_MSK BIT(14) +#define GPWRDN_CONNECT_DET BIT(13) +#define GPWRDN_DISCONN_DET_MSK BIT(12) +#define GPWRDN_DISCONN_DET BIT(11) +#define GPWRDN_RST_DET_MSK BIT(10) +#define GPWRDN_RST_DET BIT(9) +#define GPWRDN_LNSTSCHG_MSK BIT(8) +#define GPWRDN_LNSTSCHG BIT(7) +#define GPWRDN_DIS_VBUS BIT(6) +#define GPWRDN_PWRDNSWTCH BIT(5) +#define GPWRDN_PWRDNRSTN BIT(4) +#define GPWRDN_PWRDNCLMP BIT(3) +#define GPWRDN_RESTORE BIT(2) +#define GPWRDN_PMUACTV BIT(1) +#define GPWRDN_PMUINTSEL BIT(0) #define GDFIFOCFG HSOTG_REG(0x005c) #define GDFIFOCFG_EPINFOBASE_MASK (0xffff << 16) @@ -377,16 +377,16 @@ #define ADPCTL HSOTG_REG(0x0060) #define ADPCTL_AR_MASK (0x3 << 27) #define ADPCTL_AR_SHIFT 27 -#define ADPCTL_ADP_TMOUT_INT_MSK (1 << 26) -#define ADPCTL_ADP_SNS_INT_MSK (1 << 25) -#define ADPCTL_ADP_PRB_INT_MSK (1 << 24) -#define ADPCTL_ADP_TMOUT_INT (1 << 23) -#define ADPCTL_ADP_SNS_INT (1 << 22) -#define ADPCTL_ADP_PRB_INT (1 << 21) -#define ADPCTL_ADPENA (1 << 20) -#define ADPCTL_ADPRES (1 << 19) -#define ADPCTL_ENASNS (1 << 18) -#define ADPCTL_ENAPRB (1 << 17) +#define ADPCTL_ADP_TMOUT_INT_MSK BIT(26) +#define ADPCTL_ADP_SNS_INT_MSK BIT(25) +#define ADPCTL_ADP_PRB_INT_MSK BIT(24) +#define ADPCTL_ADP_TMOUT_INT BIT(23) +#define ADPCTL_ADP_SNS_INT BIT(22) +#define ADPCTL_ADP_PRB_INT BIT(21) +#define ADPCTL_ADPENA BIT(20) +#define ADPCTL_ADPRES BIT(19) +#define ADPCTL_ENASNS BIT(18) +#define ADPCTL_ENAPRB BIT(17) #define ADPCTL_RTIM_MASK (0x7ff << 6) #define ADPCTL_RTIM_SHIFT 6 #define ADPCTL_PRB_PER_MASK (0x3 << 4) @@ -412,7 +412,7 @@ /* Device mode registers */ #define DCFG HSOTG_REG(0x800) -#define DCFG_DESCDMA_EN (1 << 23) +#define DCFG_DESCDMA_EN BIT(23) #define DCFG_EPMISCNT_MASK (0x1f << 18) #define DCFG_EPMISCNT_SHIFT 18 #define DCFG_EPMISCNT_LIMIT 0x1f @@ -425,7 +425,7 @@ #define DCFG_DEVADDR_SHIFT 4 #define DCFG_DEVADDR_LIMIT 0x7f #define DCFG_DEVADDR(_x) ((_x) << 4) -#define DCFG_NZ_STS_OUT_HSHK (1 << 2) +#define DCFG_NZ_STS_OUT_HSHK BIT(2) #define DCFG_DEVSPD_MASK (0x3 << 0) #define DCFG_DEVSPD_SHIFT 0 #define DCFG_DEVSPD_HS 0 @@ -434,54 +434,54 @@ #define DCFG_DEVSPD_FS48 3 #define DCTL HSOTG_REG(0x804) -#define DCTL_PWRONPRGDONE (1 << 11) -#define DCTL_CGOUTNAK (1 << 10) -#define DCTL_SGOUTNAK (1 << 9) -#define DCTL_CGNPINNAK (1 << 8) -#define DCTL_SGNPINNAK (1 << 7) +#define DCTL_PWRONPRGDONE BIT(11) +#define DCTL_CGOUTNAK BIT(10) +#define DCTL_SGOUTNAK BIT(9) +#define DCTL_CGNPINNAK BIT(8) +#define DCTL_SGNPINNAK BIT(7) #define DCTL_TSTCTL_MASK (0x7 << 4) #define DCTL_TSTCTL_SHIFT 4 -#define DCTL_GOUTNAKSTS (1 << 3) -#define DCTL_GNPINNAKSTS (1 << 2) -#define DCTL_SFTDISCON (1 << 1) -#define DCTL_RMTWKUPSIG (1 << 0) +#define DCTL_GOUTNAKSTS BIT(3) +#define DCTL_GNPINNAKSTS BIT(2) +#define DCTL_SFTDISCON BIT(1) +#define DCTL_RMTWKUPSIG BIT(0) #define DSTS HSOTG_REG(0x808) #define DSTS_SOFFN_MASK (0x3fff << 8) #define DSTS_SOFFN_SHIFT 8 #define DSTS_SOFFN_LIMIT 0x3fff #define DSTS_SOFFN(_x) ((_x) << 8) -#define DSTS_ERRATICERR (1 << 3) +#define DSTS_ERRATICERR BIT(3) #define DSTS_ENUMSPD_MASK (0x3 << 1) #define DSTS_ENUMSPD_SHIFT 1 #define DSTS_ENUMSPD_HS 0 #define DSTS_ENUMSPD_FS 1 #define DSTS_ENUMSPD_LS 2 #define DSTS_ENUMSPD_FS48 3 -#define DSTS_SUSPSTS (1 << 0) +#define DSTS_SUSPSTS BIT(0) #define DIEPMSK HSOTG_REG(0x810) -#define DIEPMSK_NAKMSK (1 << 13) -#define DIEPMSK_BNAININTRMSK (1 << 9) -#define DIEPMSK_TXFIFOUNDRNMSK (1 << 8) -#define DIEPMSK_TXFIFOEMPTY (1 << 7) -#define DIEPMSK_INEPNAKEFFMSK (1 << 6) -#define DIEPMSK_INTKNEPMISMSK (1 << 5) -#define DIEPMSK_INTKNTXFEMPMSK (1 << 4) -#define DIEPMSK_TIMEOUTMSK (1 << 3) -#define DIEPMSK_AHBERRMSK (1 << 2) -#define DIEPMSK_EPDISBLDMSK (1 << 1) -#define DIEPMSK_XFERCOMPLMSK (1 << 0) +#define DIEPMSK_NAKMSK BIT(13) +#define DIEPMSK_BNAININTRMSK BIT(9) +#define DIEPMSK_TXFIFOUNDRNMSK BIT(8) +#define DIEPMSK_TXFIFOEMPTY BIT(7) +#define DIEPMSK_INEPNAKEFFMSK BIT(6) +#define DIEPMSK_INTKNEPMISMSK BIT(5) +#define DIEPMSK_INTKNTXFEMPMSK BIT(4) +#define DIEPMSK_TIMEOUTMSK BIT(3) +#define DIEPMSK_AHBERRMSK BIT(2) +#define DIEPMSK_EPDISBLDMSK BIT(1) +#define DIEPMSK_XFERCOMPLMSK BIT(0) #define DOEPMSK HSOTG_REG(0x814) -#define DOEPMSK_BNAMSK (1 << 9) -#define DOEPMSK_BACK2BACKSETUP (1 << 6) -#define DOEPMSK_STSPHSERCVDMSK (1 << 5) -#define DOEPMSK_OUTTKNEPDISMSK (1 << 4) -#define DOEPMSK_SETUPMSK (1 << 3) -#define DOEPMSK_AHBERRMSK (1 << 2) -#define DOEPMSK_EPDISBLDMSK (1 << 1) -#define DOEPMSK_XFERCOMPLMSK (1 << 0) +#define DOEPMSK_BNAMSK BIT(9) +#define DOEPMSK_BACK2BACKSETUP BIT(6) +#define DOEPMSK_STSPHSERCVDMSK BIT(5) +#define DOEPMSK_OUTTKNEPDISMSK BIT(4) +#define DOEPMSK_SETUPMSK BIT(3) +#define DOEPMSK_AHBERRMSK BIT(2) +#define DOEPMSK_EPDISBLDMSK BIT(1) +#define DOEPMSK_XFERCOMPLMSK BIT(0) #define DAINT HSOTG_REG(0x818) #define DAINTMSK HSOTG_REG(0x81C) @@ -516,30 +516,30 @@ #define D0EPCTL_MPS_16 2 #define D0EPCTL_MPS_8 3 -#define DXEPCTL_EPENA (1 << 31) -#define DXEPCTL_EPDIS (1 << 30) -#define DXEPCTL_SETD1PID (1 << 29) -#define DXEPCTL_SETODDFR (1 << 29) -#define DXEPCTL_SETD0PID (1 << 28) -#define DXEPCTL_SETEVENFR (1 << 28) -#define DXEPCTL_SNAK (1 << 27) -#define DXEPCTL_CNAK (1 << 26) +#define DXEPCTL_EPENA BIT(31) +#define DXEPCTL_EPDIS BIT(30) +#define DXEPCTL_SETD1PID BIT(29) +#define DXEPCTL_SETODDFR BIT(29) +#define DXEPCTL_SETD0PID BIT(28) +#define DXEPCTL_SETEVENFR BIT(28) +#define DXEPCTL_SNAK BIT(27) +#define DXEPCTL_CNAK BIT(26) #define DXEPCTL_TXFNUM_MASK (0xf << 22) #define DXEPCTL_TXFNUM_SHIFT 22 #define DXEPCTL_TXFNUM_LIMIT 0xf #define DXEPCTL_TXFNUM(_x) ((_x) << 22) -#define DXEPCTL_STALL (1 << 21) -#define DXEPCTL_SNP (1 << 20) +#define DXEPCTL_STALL BIT(21) +#define DXEPCTL_SNP BIT(20) #define DXEPCTL_EPTYPE_MASK (0x3 << 18) #define DXEPCTL_EPTYPE_CONTROL (0x0 << 18) #define DXEPCTL_EPTYPE_ISO (0x1 << 18) #define DXEPCTL_EPTYPE_BULK (0x2 << 18) #define DXEPCTL_EPTYPE_INTERRUPT (0x3 << 18) -#define DXEPCTL_NAKSTS (1 << 17) -#define DXEPCTL_DPID (1 << 16) -#define DXEPCTL_EOFRNUM (1 << 16) -#define DXEPCTL_USBACTEP (1 << 15) +#define DXEPCTL_NAKSTS BIT(17) +#define DXEPCTL_DPID BIT(16) +#define DXEPCTL_EOFRNUM BIT(16) +#define DXEPCTL_USBACTEP BIT(15) #define DXEPCTL_NEXTEP_MASK (0xf << 11) #define DXEPCTL_NEXTEP_SHIFT 11 #define DXEPCTL_NEXTEP_LIMIT 0xf @@ -551,26 +551,26 @@ #define DIEPINT(_a) HSOTG_REG(0x908 + ((_a) * 0x20)) #define DOEPINT(_a) HSOTG_REG(0xB08 + ((_a) * 0x20)) -#define DXEPINT_SETUP_RCVD (1 << 15) -#define DXEPINT_NYETINTRPT (1 << 14) -#define DXEPINT_NAKINTRPT (1 << 13) -#define DXEPINT_BBLEERRINTRPT (1 << 12) -#define DXEPINT_PKTDRPSTS (1 << 11) -#define DXEPINT_BNAINTR (1 << 9) -#define DXEPINT_TXFIFOUNDRN (1 << 8) -#define DXEPINT_OUTPKTERR (1 << 8) -#define DXEPINT_TXFEMP (1 << 7) -#define DXEPINT_INEPNAKEFF (1 << 6) -#define DXEPINT_BACK2BACKSETUP (1 << 6) -#define DXEPINT_INTKNEPMIS (1 << 5) -#define DXEPINT_STSPHSERCVD (1 << 5) -#define DXEPINT_INTKNTXFEMP (1 << 4) -#define DXEPINT_OUTTKNEPDIS (1 << 4) -#define DXEPINT_TIMEOUT (1 << 3) -#define DXEPINT_SETUP (1 << 3) -#define DXEPINT_AHBERR (1 << 2) -#define DXEPINT_EPDISBLD (1 << 1) -#define DXEPINT_XFERCOMPL (1 << 0) +#define DXEPINT_SETUP_RCVD BIT(15) +#define DXEPINT_NYETINTRPT BIT(14) +#define DXEPINT_NAKINTRPT BIT(13) +#define DXEPINT_BBLEERRINTRPT BIT(12) +#define DXEPINT_PKTDRPSTS BIT(11) +#define DXEPINT_BNAINTR BIT(9) +#define DXEPINT_TXFIFOUNDRN BIT(8) +#define DXEPINT_OUTPKTERR BIT(8) +#define DXEPINT_TXFEMP BIT(7) +#define DXEPINT_INEPNAKEFF BIT(6) +#define DXEPINT_BACK2BACKSETUP BIT(6) +#define DXEPINT_INTKNEPMIS BIT(5) +#define DXEPINT_STSPHSERCVD BIT(5) +#define DXEPINT_INTKNTXFEMP BIT(4) +#define DXEPINT_OUTTKNEPDIS BIT(4) +#define DXEPINT_TIMEOUT BIT(3) +#define DXEPINT_SETUP BIT(3) +#define DXEPINT_AHBERR BIT(2) +#define DXEPINT_EPDISBLD BIT(1) +#define DXEPINT_XFERCOMPL BIT(0) #define DIEPTSIZ0 HSOTG_REG(0x910) #define DIEPTSIZ0_PKTCNT_MASK (0x3 << 19) @@ -587,7 +587,7 @@ #define DOEPTSIZ0_SUPCNT_SHIFT 29 #define DOEPTSIZ0_SUPCNT_LIMIT 0x3 #define DOEPTSIZ0_SUPCNT(_x) ((_x) << 29) -#define DOEPTSIZ0_PKTCNT (1 << 19) +#define DOEPTSIZ0_PKTCNT BIT(19) #define DOEPTSIZ0_XFERSIZE_MASK (0x7f << 0) #define DOEPTSIZ0_XFERSIZE_SHIFT 0 @@ -614,55 +614,55 @@ #define DTXFSTS(_a) HSOTG_REG(0x918 + ((_a) * 0x20)) #define PCGCTL HSOTG_REG(0x0e00) -#define PCGCTL_IF_DEV_MODE (1 << 31) +#define PCGCTL_IF_DEV_MODE BIT(31) #define PCGCTL_P2HD_PRT_SPD_MASK (0x3 << 29) #define PCGCTL_P2HD_PRT_SPD_SHIFT 29 #define PCGCTL_P2HD_DEV_ENUM_SPD_MASK (0x3 << 27) #define PCGCTL_P2HD_DEV_ENUM_SPD_SHIFT 27 #define PCGCTL_MAC_DEV_ADDR_MASK (0x7f << 20) #define PCGCTL_MAC_DEV_ADDR_SHIFT 20 -#define PCGCTL_MAX_TERMSEL (1 << 19) +#define PCGCTL_MAX_TERMSEL BIT(19) #define PCGCTL_MAX_XCVRSELECT_MASK (0x3 << 17) #define PCGCTL_MAX_XCVRSELECT_SHIFT 17 -#define PCGCTL_PORT_POWER (1 << 16) +#define PCGCTL_PORT_POWER BIT(16) #define PCGCTL_PRT_CLK_SEL_MASK (0x3 << 14) #define PCGCTL_PRT_CLK_SEL_SHIFT 14 -#define PCGCTL_ESS_REG_RESTORED (1 << 13) -#define PCGCTL_EXTND_HIBER_SWITCH (1 << 12) -#define PCGCTL_EXTND_HIBER_PWRCLMP (1 << 11) -#define PCGCTL_ENBL_EXTND_HIBER (1 << 10) -#define PCGCTL_RESTOREMODE (1 << 9) -#define PCGCTL_RESETAFTSUSP (1 << 8) -#define PCGCTL_DEEP_SLEEP (1 << 7) -#define PCGCTL_PHY_IN_SLEEP (1 << 6) -#define PCGCTL_ENBL_SLEEP_GATING (1 << 5) -#define PCGCTL_RSTPDWNMODULE (1 << 3) -#define PCGCTL_PWRCLMP (1 << 2) -#define PCGCTL_GATEHCLK (1 << 1) -#define PCGCTL_STOPPCLK (1 << 0) +#define PCGCTL_ESS_REG_RESTORED BIT(13) +#define PCGCTL_EXTND_HIBER_SWITCH BIT(12) +#define PCGCTL_EXTND_HIBER_PWRCLMP BIT(11) +#define PCGCTL_ENBL_EXTND_HIBER BIT(10) +#define PCGCTL_RESTOREMODE BIT(9) +#define PCGCTL_RESETAFTSUSP BIT(8) +#define PCGCTL_DEEP_SLEEP BIT(7) +#define PCGCTL_PHY_IN_SLEEP BIT(6) +#define PCGCTL_ENBL_SLEEP_GATING BIT(5) +#define PCGCTL_RSTPDWNMODULE BIT(3) +#define PCGCTL_PWRCLMP BIT(2) +#define PCGCTL_GATEHCLK BIT(1) +#define PCGCTL_STOPPCLK BIT(0) #define EPFIFO(_a) HSOTG_REG(0x1000 + ((_a) * 0x1000)) /* Host Mode Registers */ #define HCFG HSOTG_REG(0x0400) -#define HCFG_MODECHTIMEN (1 << 31) -#define HCFG_PERSCHEDENA (1 << 26) +#define HCFG_MODECHTIMEN BIT(31) +#define HCFG_PERSCHEDENA BIT(26) #define HCFG_FRLISTEN_MASK (0x3 << 24) #define HCFG_FRLISTEN_SHIFT 24 #define HCFG_FRLISTEN_8 (0 << 24) #define FRLISTEN_8_SIZE 8 -#define HCFG_FRLISTEN_16 (1 << 24) +#define HCFG_FRLISTEN_16 BIT(24) #define FRLISTEN_16_SIZE 16 #define HCFG_FRLISTEN_32 (2 << 24) #define FRLISTEN_32_SIZE 32 #define HCFG_FRLISTEN_64 (3 << 24) #define FRLISTEN_64_SIZE 64 -#define HCFG_DESCDMA (1 << 23) +#define HCFG_DESCDMA BIT(23) #define HCFG_RESVALID_MASK (0xff << 8) #define HCFG_RESVALID_SHIFT 8 -#define HCFG_ENA32KHZ (1 << 7) -#define HCFG_FSLSSUPP (1 << 2) +#define HCFG_ENA32KHZ BIT(7) +#define HCFG_FSLSSUPP BIT(2) #define HCFG_FSLSPCLKSEL_MASK (0x3 << 0) #define HCFG_FSLSPCLKSEL_SHIFT 0 #define HCFG_FSLSPCLKSEL_30_60_MHZ 0 @@ -672,7 +672,7 @@ #define HFIR HSOTG_REG(0x0404) #define HFIR_FRINT_MASK (0xffff << 0) #define HFIR_FRINT_SHIFT 0 -#define HFIR_RLDCTRL (1 << 16) +#define HFIR_RLDCTRL BIT(16) #define HFNUM HSOTG_REG(0x0408) #define HFNUM_FRREM_MASK (0xffff << 16) @@ -682,12 +682,12 @@ #define HFNUM_MAX_FRNUM 0x3fff #define HPTXSTS HSOTG_REG(0x0410) -#define TXSTS_QTOP_ODD (1 << 31) +#define TXSTS_QTOP_ODD BIT(31) #define TXSTS_QTOP_CHNEP_MASK (0xf << 27) #define TXSTS_QTOP_CHNEP_SHIFT 27 #define TXSTS_QTOP_TOKEN_MASK (0x3 << 25) #define TXSTS_QTOP_TOKEN_SHIFT 25 -#define TXSTS_QTOP_TERMINATE (1 << 24) +#define TXSTS_QTOP_TERMINATE BIT(24) #define TXSTS_QSPCAVAIL_MASK (0xff << 16) #define TXSTS_QSPCAVAIL_SHIFT 16 #define TXSTS_FSPCAVAIL_MASK (0xffff << 0) @@ -705,39 +705,39 @@ #define HPRT0_SPD_LOW_SPEED 2 #define HPRT0_TSTCTL_MASK (0xf << 13) #define HPRT0_TSTCTL_SHIFT 13 -#define HPRT0_PWR (1 << 12) +#define HPRT0_PWR BIT(12) #define HPRT0_LNSTS_MASK (0x3 << 10) #define HPRT0_LNSTS_SHIFT 10 -#define HPRT0_RST (1 << 8) -#define HPRT0_SUSP (1 << 7) -#define HPRT0_RES (1 << 6) -#define HPRT0_OVRCURRCHG (1 << 5) -#define HPRT0_OVRCURRACT (1 << 4) -#define HPRT0_ENACHG (1 << 3) -#define HPRT0_ENA (1 << 2) -#define HPRT0_CONNDET (1 << 1) -#define HPRT0_CONNSTS (1 << 0) +#define HPRT0_RST BIT(8) +#define HPRT0_SUSP BIT(7) +#define HPRT0_RES BIT(6) +#define HPRT0_OVRCURRCHG BIT(5) +#define HPRT0_OVRCURRACT BIT(4) +#define HPRT0_ENACHG BIT(3) +#define HPRT0_ENA BIT(2) +#define HPRT0_CONNDET BIT(1) +#define HPRT0_CONNSTS BIT(0) #define HCCHAR(_ch) HSOTG_REG(0x0500 + 0x20 * (_ch)) -#define HCCHAR_CHENA (1 << 31) -#define HCCHAR_CHDIS (1 << 30) -#define HCCHAR_ODDFRM (1 << 29) +#define HCCHAR_CHENA BIT(31) +#define HCCHAR_CHDIS BIT(30) +#define HCCHAR_ODDFRM BIT(29) #define HCCHAR_DEVADDR_MASK (0x7f << 22) #define HCCHAR_DEVADDR_SHIFT 22 #define HCCHAR_MULTICNT_MASK (0x3 << 20) #define HCCHAR_MULTICNT_SHIFT 20 #define HCCHAR_EPTYPE_MASK (0x3 << 18) #define HCCHAR_EPTYPE_SHIFT 18 -#define HCCHAR_LSPDDEV (1 << 17) -#define HCCHAR_EPDIR (1 << 15) +#define HCCHAR_LSPDDEV BIT(17) +#define HCCHAR_EPDIR BIT(15) #define HCCHAR_EPNUM_MASK (0xf << 11) #define HCCHAR_EPNUM_SHIFT 11 #define HCCHAR_MPS_MASK (0x7ff << 0) #define HCCHAR_MPS_SHIFT 0 #define HCSPLT(_ch) HSOTG_REG(0x0504 + 0x20 * (_ch)) -#define HCSPLT_SPLTENA (1 << 31) -#define HCSPLT_COMPSPLT (1 << 16) +#define HCSPLT_SPLTENA BIT(31) +#define HCSPLT_COMPSPLT BIT(16) #define HCSPLT_XACTPOS_MASK (0x3 << 14) #define HCSPLT_XACTPOS_SHIFT 14 #define HCSPLT_XACTPOS_MID 0 @@ -752,23 +752,23 @@ #define HCINT(_ch) HSOTG_REG(0x0508 + 0x20 * (_ch)) #define HCINTMSK(_ch) HSOTG_REG(0x050c + 0x20 * (_ch)) #define HCINTMSK_RESERVED14_31 (0x3ffff << 14) -#define HCINTMSK_FRM_LIST_ROLL (1 << 13) -#define HCINTMSK_XCS_XACT (1 << 12) -#define HCINTMSK_BNA (1 << 11) -#define HCINTMSK_DATATGLERR (1 << 10) -#define HCINTMSK_FRMOVRUN (1 << 9) -#define HCINTMSK_BBLERR (1 << 8) -#define HCINTMSK_XACTERR (1 << 7) -#define HCINTMSK_NYET (1 << 6) -#define HCINTMSK_ACK (1 << 5) -#define HCINTMSK_NAK (1 << 4) -#define HCINTMSK_STALL (1 << 3) -#define HCINTMSK_AHBERR (1 << 2) -#define HCINTMSK_CHHLTD (1 << 1) -#define HCINTMSK_XFERCOMPL (1 << 0) +#define HCINTMSK_FRM_LIST_ROLL BIT(13) +#define HCINTMSK_XCS_XACT BIT(12) +#define HCINTMSK_BNA BIT(11) +#define HCINTMSK_DATATGLERR BIT(10) +#define HCINTMSK_FRMOVRUN BIT(9) +#define HCINTMSK_BBLERR BIT(8) +#define HCINTMSK_XACTERR BIT(7) +#define HCINTMSK_NYET BIT(6) +#define HCINTMSK_ACK BIT(5) +#define HCINTMSK_NAK BIT(4) +#define HCINTMSK_STALL BIT(3) +#define HCINTMSK_AHBERR BIT(2) +#define HCINTMSK_CHHLTD BIT(1) +#define HCINTMSK_XFERCOMPL BIT(0) #define HCTSIZ(_ch) HSOTG_REG(0x0510 + 0x20 * (_ch)) -#define TSIZ_DOPNG (1 << 31) +#define TSIZ_DOPNG BIT(31) #define TSIZ_SC_MC_PID_MASK (0x3 << 29) #define TSIZ_SC_MC_PID_SHIFT 29 #define TSIZ_SC_MC_PID_DATA0 0 @@ -808,14 +808,14 @@ struct dwc2_dma_desc { /* Host Mode DMA descriptor status quadlet */ -#define HOST_DMA_A (1 << 31) +#define HOST_DMA_A BIT(31) #define HOST_DMA_STS_MASK (0x3 << 28) #define HOST_DMA_STS_SHIFT 28 -#define HOST_DMA_STS_PKTERR (1 << 28) -#define HOST_DMA_EOL (1 << 26) -#define HOST_DMA_IOC (1 << 25) -#define HOST_DMA_SUP (1 << 24) -#define HOST_DMA_ALT_QTD (1 << 23) +#define HOST_DMA_STS_PKTERR BIT(28) +#define HOST_DMA_EOL BIT(26) +#define HOST_DMA_IOC BIT(25) +#define HOST_DMA_SUP BIT(24) +#define HOST_DMA_ALT_QTD BIT(23) #define HOST_DMA_QTD_OFFSET_MASK (0x3f << 17) #define HOST_DMA_QTD_OFFSET_SHIFT 17 #define HOST_DMA_ISOC_NBYTES_MASK (0xfff << 0) @@ -837,11 +837,11 @@ struct dwc2_dma_desc { #define DEV_DMA_STS_SUCC 0 #define DEV_DMA_STS_BUFF_FLUSH 1 #define DEV_DMA_STS_BUFF_ERR 3 -#define DEV_DMA_L (1 << 27) -#define DEV_DMA_SHORT (1 << 26) -#define DEV_DMA_IOC (1 << 25) -#define DEV_DMA_SR (1 << 24) -#define DEV_DMA_MTRF (1 << 23) +#define DEV_DMA_L BIT(27) +#define DEV_DMA_SHORT BIT(26) +#define DEV_DMA_IOC BIT(25) +#define DEV_DMA_SR BIT(24) +#define DEV_DMA_MTRF BIT(23) #define DEV_DMA_ISOC_PID_MASK (0x3 << 23) #define DEV_DMA_ISOC_PID_SHIFT 23 #define DEV_DMA_ISOC_PID_DATA0 0 diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index bcd1e19b4076..2990c347289f 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -38,1157 +38,499 @@ #include "core.h" -static const struct dwc2_core_params params_hi6220 = { - .otg_cap = 2, /* No HNP/SRP capable */ - .otg_ver = 0, /* 1.3 */ - .dma_desc_enable = 0, - .dma_desc_fs_enable = 0, - .speed = 0, /* High Speed */ - .enable_dynamic_fifo = 1, - .en_multiple_tx_fifo = 1, - .host_rx_fifo_size = 512, - .host_nperio_tx_fifo_size = 512, - .host_perio_tx_fifo_size = 512, - .max_transfer_size = 65535, - .max_packet_count = 511, - .host_channels = 16, - .phy_type = 1, /* UTMI */ - .phy_utmi_width = 8, - .phy_ulpi_ddr = 0, /* Single */ - .phy_ulpi_ext_vbus = 0, - .i2c_enable = 0, - .ulpi_fs_ls = 0, - .host_support_fs_ls_low_power = 0, - .host_ls_low_power_phy_clk = 0, /* 48 MHz */ - .ts_dline = 0, - .reload_ctl = 0, - .ahbcfg = GAHBCFG_HBSTLEN_INCR16 << - GAHBCFG_HBSTLEN_SHIFT, - .uframe_sched = 0, - .external_id_pin_ctl = -1, - .hibernation = -1, -}; - -static const struct dwc2_core_params params_bcm2835 = { - .otg_cap = 0, /* HNP/SRP capable */ - .otg_ver = 0, /* 1.3 */ - .dma_desc_enable = 0, - .dma_desc_fs_enable = 0, - .speed = 0, /* High Speed */ - .enable_dynamic_fifo = 1, - .en_multiple_tx_fifo = 1, - .host_rx_fifo_size = 774, /* 774 DWORDs */ - .host_nperio_tx_fifo_size = 256, /* 256 DWORDs */ - .host_perio_tx_fifo_size = 512, /* 512 DWORDs */ - .max_transfer_size = 65535, - .max_packet_count = 511, - .host_channels = 8, - .phy_type = 1, /* UTMI */ - .phy_utmi_width = 8, /* 8 bits */ - .phy_ulpi_ddr = 0, /* Single */ - .phy_ulpi_ext_vbus = 0, - .i2c_enable = 0, - .ulpi_fs_ls = 0, - .host_support_fs_ls_low_power = 0, - .host_ls_low_power_phy_clk = 0, /* 48 MHz */ - .ts_dline = 0, - .reload_ctl = 0, - .ahbcfg = 0x10, - .uframe_sched = 0, - .external_id_pin_ctl = -1, - .hibernation = -1, -}; - -static const struct dwc2_core_params params_rk3066 = { - .otg_cap = 2, /* non-HNP/non-SRP */ - .otg_ver = -1, - .dma_desc_enable = 0, - .dma_desc_fs_enable = 0, - .speed = -1, - .enable_dynamic_fifo = 1, - .en_multiple_tx_fifo = -1, - .host_rx_fifo_size = 525, /* 525 DWORDs */ - .host_nperio_tx_fifo_size = 128, /* 128 DWORDs */ - .host_perio_tx_fifo_size = 256, /* 256 DWORDs */ - .max_transfer_size = -1, - .max_packet_count = -1, - .host_channels = -1, - .phy_type = -1, - .phy_utmi_width = -1, - .phy_ulpi_ddr = -1, - .phy_ulpi_ext_vbus = -1, - .i2c_enable = -1, - .ulpi_fs_ls = -1, - .host_support_fs_ls_low_power = -1, - .host_ls_low_power_phy_clk = -1, - .ts_dline = -1, - .reload_ctl = -1, - .ahbcfg = GAHBCFG_HBSTLEN_INCR16 << - GAHBCFG_HBSTLEN_SHIFT, - .uframe_sched = -1, - .external_id_pin_ctl = -1, - .hibernation = -1, -}; - -static const struct dwc2_core_params params_ltq = { - .otg_cap = 2, /* non-HNP/non-SRP */ - .otg_ver = -1, - .dma_desc_enable = -1, - .dma_desc_fs_enable = -1, - .speed = -1, - .enable_dynamic_fifo = -1, - .en_multiple_tx_fifo = -1, - .host_rx_fifo_size = 288, /* 288 DWORDs */ - .host_nperio_tx_fifo_size = 128, /* 128 DWORDs */ - .host_perio_tx_fifo_size = 96, /* 96 DWORDs */ - .max_transfer_size = 65535, - .max_packet_count = 511, - .host_channels = -1, - .phy_type = -1, - .phy_utmi_width = -1, - .phy_ulpi_ddr = -1, - .phy_ulpi_ext_vbus = -1, - .i2c_enable = -1, - .ulpi_fs_ls = -1, - .host_support_fs_ls_low_power = -1, - .host_ls_low_power_phy_clk = -1, - .ts_dline = -1, - .reload_ctl = -1, - .ahbcfg = GAHBCFG_HBSTLEN_INCR16 << - GAHBCFG_HBSTLEN_SHIFT, - .uframe_sched = -1, - .external_id_pin_ctl = -1, - .hibernation = -1, -}; - -static const struct dwc2_core_params params_amlogic = { - .otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE, - .otg_ver = -1, - .dma_desc_enable = 0, - .dma_desc_fs_enable = 0, - .speed = DWC2_SPEED_PARAM_HIGH, - .enable_dynamic_fifo = 1, - .en_multiple_tx_fifo = -1, - .host_rx_fifo_size = 512, - .host_nperio_tx_fifo_size = 500, - .host_perio_tx_fifo_size = 500, - .max_transfer_size = -1, - .max_packet_count = -1, - .host_channels = 16, - .phy_type = DWC2_PHY_TYPE_PARAM_UTMI, - .phy_utmi_width = -1, - .phy_ulpi_ddr = -1, - .phy_ulpi_ext_vbus = -1, - .i2c_enable = -1, - .ulpi_fs_ls = -1, - .host_support_fs_ls_low_power = -1, - .host_ls_low_power_phy_clk = -1, - .ts_dline = -1, - .reload_ctl = 1, - .ahbcfg = GAHBCFG_HBSTLEN_INCR8 << - GAHBCFG_HBSTLEN_SHIFT, - .uframe_sched = 0, - .external_id_pin_ctl = -1, - .hibernation = -1, -}; - -static const struct dwc2_core_params params_default = { - .otg_cap = -1, - .otg_ver = -1, - - /* - * Disable descriptor dma mode by default as the HW can support - * it, but does not support it for SPLIT transactions. - * Disable it for FS devices as well. - */ - .dma_desc_enable = 0, - .dma_desc_fs_enable = 0, - - .speed = -1, - .enable_dynamic_fifo = -1, - .en_multiple_tx_fifo = -1, - .host_rx_fifo_size = -1, - .host_nperio_tx_fifo_size = -1, - .host_perio_tx_fifo_size = -1, - .max_transfer_size = -1, - .max_packet_count = -1, - .host_channels = -1, - .phy_type = -1, - .phy_utmi_width = -1, - .phy_ulpi_ddr = -1, - .phy_ulpi_ext_vbus = -1, - .i2c_enable = -1, - .ulpi_fs_ls = -1, - .host_support_fs_ls_low_power = -1, - .host_ls_low_power_phy_clk = -1, - .ts_dline = -1, - .reload_ctl = -1, - .ahbcfg = -1, - .uframe_sched = -1, - .external_id_pin_ctl = -1, - .hibernation = -1, -}; - -const struct of_device_id dwc2_of_match_table[] = { - { .compatible = "brcm,bcm2835-usb", .data = ¶ms_bcm2835 }, - { .compatible = "hisilicon,hi6220-usb", .data = ¶ms_hi6220 }, - { .compatible = "rockchip,rk3066-usb", .data = ¶ms_rk3066 }, - { .compatible = "lantiq,arx100-usb", .data = ¶ms_ltq }, - { .compatible = "lantiq,xrx200-usb", .data = ¶ms_ltq }, - { .compatible = "snps,dwc2", .data = NULL }, - { .compatible = "samsung,s3c6400-hsotg", .data = NULL}, - { .compatible = "amlogic,meson8b-usb", .data = ¶ms_amlogic }, - { .compatible = "amlogic,meson-gxbb-usb", .data = ¶ms_amlogic }, - { .compatible = "amcc,dwc-otg", .data = NULL }, - {}, -}; -MODULE_DEVICE_TABLE(of, dwc2_of_match_table); - -static void dwc2_get_device_property(struct dwc2_hsotg *hsotg, - char *property, u8 size, u64 *value) +static void dwc2_set_bcm_params(struct dwc2_hsotg *hsotg) { - u32 val32; - - switch (size) { - case 0: - *value = device_property_read_bool(hsotg->dev, property); - break; - case 1: - case 2: - case 4: - if (device_property_read_u32(hsotg->dev, property, &val32)) - return; - - *value = val32; - break; - case 8: - if (device_property_read_u64(hsotg->dev, property, value)) - return; + struct dwc2_core_params *p = &hsotg->params; - break; - default: - /* - * The size is checked by the only function that calls - * this so this should never happen. - */ - WARN_ON(1); - return; - } + p->host_rx_fifo_size = 774; + p->max_transfer_size = 65535; + p->max_packet_count = 511; + p->ahbcfg = 0x10; + p->uframe_sched = false; } -static void dwc2_set_core_param(void *param, u8 size, u64 value) +static void dwc2_set_his_params(struct dwc2_hsotg *hsotg) { - switch (size) { - case 0: - *((bool *)param) = !!value; - break; - case 1: - *((u8 *)param) = (u8)value; - break; - case 2: - *((u16 *)param) = (u16)value; - break; - case 4: - *((u32 *)param) = (u32)value; - break; - case 8: - *((u64 *)param) = (u64)value; - break; - default: - /* - * The size is checked by the only function that calls - * this so this should never happen. - */ - WARN_ON(1); - return; - } -} + struct dwc2_core_params *p = &hsotg->params; -/** - * dwc2_set_param() - Set a core parameter - * - * @hsotg: Programming view of the DWC_otg controller - * @param: Pointer to the parameter to set - * @lookup: True if the property should be looked up - * @property: The device property to read - * @legacy: The param value to set if @property is not available. This - * will typically be the legacy value set in the static - * params structure. - * @def: The default value - * @min: The minimum value - * @max: The maximum value - * @size: The size of the core parameter in bytes, or 0 for bool. - * - * This function looks up @property and sets the @param to that value. - * If the property doesn't exist it uses the passed-in @value. It will - * verify that the value falls between @min and @max. If it doesn't, - * it will output an error and set the parameter to either @def or, - * failing that, to @min. - * - * The @size is used to write to @param and to query the device - * properties so that this same function can be used with different - * types of parameters. - */ -static void dwc2_set_param(struct dwc2_hsotg *hsotg, void *param, - bool lookup, char *property, u64 legacy, - u64 def, u64 min, u64 max, u8 size) + p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; + p->speed = DWC2_SPEED_PARAM_HIGH; + p->host_rx_fifo_size = 512; + p->host_nperio_tx_fifo_size = 512; + p->host_perio_tx_fifo_size = 512; + p->max_transfer_size = 65535; + p->max_packet_count = 511; + p->host_channels = 16; + p->phy_type = DWC2_PHY_TYPE_PARAM_UTMI; + p->phy_utmi_width = 8; + p->i2c_enable = false; + p->reload_ctl = false; + p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << + GAHBCFG_HBSTLEN_SHIFT; + p->uframe_sched = false; + p->change_speed_quirk = true; +} + +static void dwc2_set_rk_params(struct dwc2_hsotg *hsotg) { - u64 sizemax; - u64 value; - - if (WARN_ON(!hsotg || !param || !property)) - return; - - if (WARN((size > 8) || ((size & (size - 1)) != 0), - "Invalid size %d for %s\n", size, property)) - return; - - dev_vdbg(hsotg->dev, "%s: Setting %s: legacy=%llu, def=%llu, min=%llu, max=%llu, size=%d\n", - __func__, property, legacy, def, min, max, size); - - sizemax = (1ULL << (size * 8)) - 1; - value = legacy; - - /* Override legacy settings. */ - if (lookup) - dwc2_get_device_property(hsotg, property, size, &value); - - /* - * While the value is not valid, try setting it to the default - * value, and failing that, set it to the minimum. - */ - while ((value < min) || (value > max)) { - /* Print an error unless the value is set to auto. */ - if (value != sizemax) - dev_err(hsotg->dev, "Invalid value %llu for param %s\n", - value, property); + struct dwc2_core_params *p = &hsotg->params; - /* - * If we are already the default, just set it to the - * minimum. - */ - if (value == def) { - dev_vdbg(hsotg->dev, "%s: setting value to min=%llu\n", - __func__, min); - value = min; - break; - } + p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; + p->host_rx_fifo_size = 525; + p->host_nperio_tx_fifo_size = 128; + p->host_perio_tx_fifo_size = 256; + p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << + GAHBCFG_HBSTLEN_SHIFT; +} - /* Try the default value */ - dev_vdbg(hsotg->dev, "%s: setting value to default=%llu\n", - __func__, def); - value = def; - } +static void dwc2_set_ltq_params(struct dwc2_hsotg *hsotg) +{ + struct dwc2_core_params *p = &hsotg->params; - dev_dbg(hsotg->dev, "Setting %s to %llu\n", property, value); - dwc2_set_core_param(param, size, value); + p->otg_cap = 2; + p->host_rx_fifo_size = 288; + p->host_nperio_tx_fifo_size = 128; + p->host_perio_tx_fifo_size = 96; + p->max_transfer_size = 65535; + p->max_packet_count = 511; + p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << + GAHBCFG_HBSTLEN_SHIFT; } -/** - * dwc2_set_param_u32() - Set a u32 parameter - * - * See dwc2_set_param(). - */ -static void dwc2_set_param_u32(struct dwc2_hsotg *hsotg, u32 *param, - bool lookup, char *property, u16 legacy, - u16 def, u16 min, u16 max) +static void dwc2_set_amlogic_params(struct dwc2_hsotg *hsotg) { - dwc2_set_param(hsotg, param, lookup, property, - legacy, def, min, max, 4); + struct dwc2_core_params *p = &hsotg->params; + + p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; + p->speed = DWC2_SPEED_PARAM_HIGH; + p->host_rx_fifo_size = 512; + p->host_nperio_tx_fifo_size = 500; + p->host_perio_tx_fifo_size = 500; + p->host_channels = 16; + p->phy_type = DWC2_PHY_TYPE_PARAM_UTMI; + p->ahbcfg = GAHBCFG_HBSTLEN_INCR8 << + GAHBCFG_HBSTLEN_SHIFT; + p->uframe_sched = false; } -/** - * dwc2_set_param_bool() - Set a bool parameter - * - * See dwc2_set_param(). - * - * Note: there is no 'legacy' argument here because there is no legacy - * source of bool params. - */ -static void dwc2_set_param_bool(struct dwc2_hsotg *hsotg, bool *param, - bool lookup, char *property, - bool def, bool min, bool max) +static void dwc2_set_amcc_params(struct dwc2_hsotg *hsotg) { - dwc2_set_param(hsotg, param, lookup, property, - def, def, min, max, 0); + struct dwc2_core_params *p = &hsotg->params; + + p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << GAHBCFG_HBSTLEN_SHIFT; } -#define DWC2_OUT_OF_BOUNDS(a, b, c) ((a) < (b) || (a) > (c)) +const struct of_device_id dwc2_of_match_table[] = { + { .compatible = "brcm,bcm2835-usb", .data = dwc2_set_bcm_params }, + { .compatible = "hisilicon,hi6220-usb", .data = dwc2_set_his_params }, + { .compatible = "rockchip,rk3066-usb", .data = dwc2_set_rk_params }, + { .compatible = "lantiq,arx100-usb", .data = dwc2_set_ltq_params }, + { .compatible = "lantiq,xrx200-usb", .data = dwc2_set_ltq_params }, + { .compatible = "snps,dwc2" }, + { .compatible = "samsung,s3c6400-hsotg" }, + { .compatible = "amlogic,meson8b-usb", + .data = dwc2_set_amlogic_params }, + { .compatible = "amlogic,meson-gxbb-usb", + .data = dwc2_set_amlogic_params }, + { .compatible = "amcc,dwc-otg", .data = dwc2_set_amcc_params }, + {}, +}; +MODULE_DEVICE_TABLE(of, dwc2_of_match_table); -/* Parameter access functions */ -static void dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val) +static void dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg) { - int valid = 1; + u8 val; - switch (val) { - case DWC2_CAP_PARAM_HNP_SRP_CAPABLE: - if (hsotg->hw_params.op_mode != GHWCFG2_OP_MODE_HNP_SRP_CAPABLE) - valid = 0; + switch (hsotg->hw_params.op_mode) { + case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE: + val = DWC2_CAP_PARAM_HNP_SRP_CAPABLE; break; - case DWC2_CAP_PARAM_SRP_ONLY_CAPABLE: - switch (hsotg->hw_params.op_mode) { - case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE: - case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE: - case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE: - case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST: - break; - default: - valid = 0; - break; - } - break; - case DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE: - /* always valid */ + case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE: + case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE: + case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST: + val = DWC2_CAP_PARAM_SRP_ONLY_CAPABLE; break; default: - valid = 0; + val = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; break; } - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for otg_cap parameter. Check HW configuration.\n", - val); - switch (hsotg->hw_params.op_mode) { - case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE: - val = DWC2_CAP_PARAM_HNP_SRP_CAPABLE; - break; - case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE: - case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE: - case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST: - val = DWC2_CAP_PARAM_SRP_ONLY_CAPABLE; - break; - default: - val = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; - break; - } - dev_dbg(hsotg->dev, "Setting otg_cap to %d\n", val); - } - hsotg->params.otg_cap = val; } -static void dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val) +static void dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg) { - int valid = 1; + int val; + u32 hs_phy_type = hsotg->hw_params.hs_phy_type; - if (val > 0 && (hsotg->params.host_dma <= 0 || - !hsotg->hw_params.dma_desc_enable)) - valid = 0; - if (val < 0) - valid = 0; - - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for dma_desc_enable parameter. Check HW configuration.\n", - val); - val = (hsotg->params.host_dma > 0 && - hsotg->hw_params.dma_desc_enable); - dev_dbg(hsotg->dev, "Setting dma_desc_enable to %d\n", val); + val = DWC2_PHY_TYPE_PARAM_FS; + if (hs_phy_type != GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED) { + if (hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI || + hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI) + val = DWC2_PHY_TYPE_PARAM_UTMI; + else + val = DWC2_PHY_TYPE_PARAM_ULPI; } - hsotg->params.dma_desc_enable = val; -} - -static void dwc2_set_param_dma_desc_fs_enable(struct dwc2_hsotg *hsotg, int val) -{ - int valid = 1; - - if (val > 0 && (hsotg->params.host_dma <= 0 || - !hsotg->hw_params.dma_desc_enable)) - valid = 0; - if (val < 0) - valid = 0; - - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for dma_desc_fs_enable parameter. Check HW configuration.\n", - val); - val = (hsotg->params.host_dma > 0 && - hsotg->hw_params.dma_desc_enable); - } + if (dwc2_is_fs_iot(hsotg)) + hsotg->params.phy_type = DWC2_PHY_TYPE_PARAM_FS; - hsotg->params.dma_desc_fs_enable = val; - dev_dbg(hsotg->dev, "Setting dma_desc_fs_enable to %d\n", val); + hsotg->params.phy_type = val; } -static void -dwc2_set_param_host_support_fs_ls_low_power(struct dwc2_hsotg *hsotg, - int val) +static void dwc2_set_param_speed(struct dwc2_hsotg *hsotg) { - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { - if (val >= 0) { - dev_err(hsotg->dev, - "Wrong value for host_support_fs_low_power\n"); - dev_err(hsotg->dev, - "host_support_fs_low_power must be 0 or 1\n"); - } - val = 0; - dev_dbg(hsotg->dev, - "Setting host_support_fs_low_power to %d\n", val); - } + int val; - hsotg->params.host_support_fs_ls_low_power = val; -} - -static void dwc2_set_param_enable_dynamic_fifo(struct dwc2_hsotg *hsotg, - int val) -{ - int valid = 1; + val = hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS ? + DWC2_SPEED_PARAM_FULL : DWC2_SPEED_PARAM_HIGH; - if (val > 0 && !hsotg->hw_params.enable_dynamic_fifo) - valid = 0; - if (val < 0) - valid = 0; + if (dwc2_is_fs_iot(hsotg)) + val = DWC2_SPEED_PARAM_FULL; - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for enable_dynamic_fifo parameter. Check HW configuration.\n", - val); - val = hsotg->hw_params.enable_dynamic_fifo; - dev_dbg(hsotg->dev, "Setting enable_dynamic_fifo to %d\n", val); - } + if (dwc2_is_hs_iot(hsotg)) + val = DWC2_SPEED_PARAM_HIGH; - hsotg->params.enable_dynamic_fifo = val; + hsotg->params.speed = val; } -static void dwc2_set_param_host_rx_fifo_size(struct dwc2_hsotg *hsotg, int val) +static void dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg) { - int valid = 1; + int val; - if (val < 16 || val > hsotg->hw_params.rx_fifo_size) - valid = 0; - - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for host_rx_fifo_size. Check HW configuration.\n", - val); - val = hsotg->hw_params.rx_fifo_size; - dev_dbg(hsotg->dev, "Setting host_rx_fifo_size to %d\n", val); - } + val = (hsotg->hw_params.utmi_phy_data_width == + GHWCFG4_UTMI_PHY_DATA_WIDTH_8) ? 8 : 16; - hsotg->params.host_rx_fifo_size = val; + hsotg->params.phy_utmi_width = val; } -static void dwc2_set_param_host_nperio_tx_fifo_size(struct dwc2_hsotg *hsotg, - int val) +static void dwc2_set_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg) { - int valid = 1; - - if (val < 16 || val > hsotg->hw_params.host_nperio_tx_fifo_size) - valid = 0; + struct dwc2_core_params *p = &hsotg->params; + int depth_average; + int fifo_count; + int i; - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n", - val); - val = hsotg->hw_params.host_nperio_tx_fifo_size; - dev_dbg(hsotg->dev, "Setting host_nperio_tx_fifo_size to %d\n", - val); - } + fifo_count = dwc2_hsotg_tx_fifo_count(hsotg); - hsotg->params.host_nperio_tx_fifo_size = val; + memset(p->g_tx_fifo_size, 0, sizeof(p->g_tx_fifo_size)); + depth_average = dwc2_hsotg_tx_fifo_average_depth(hsotg); + for (i = 1; i <= fifo_count; i++) + p->g_tx_fifo_size[i] = depth_average; } -static void dwc2_set_param_host_perio_tx_fifo_size(struct dwc2_hsotg *hsotg, - int val) +/** + * dwc2_set_default_params() - Set all core parameters to their + * auto-detected default values. + */ +static void dwc2_set_default_params(struct dwc2_hsotg *hsotg) { - int valid = 1; + struct dwc2_hw_params *hw = &hsotg->hw_params; + struct dwc2_core_params *p = &hsotg->params; + bool dma_capable = !(hw->arch == GHWCFG2_SLAVE_ONLY_ARCH); - if (val < 16 || val > hsotg->hw_params.host_perio_tx_fifo_size) - valid = 0; + dwc2_set_param_otg_cap(hsotg); + dwc2_set_param_phy_type(hsotg); + dwc2_set_param_speed(hsotg); + dwc2_set_param_phy_utmi_width(hsotg); + p->phy_ulpi_ddr = false; + p->phy_ulpi_ext_vbus = false; + + p->enable_dynamic_fifo = hw->enable_dynamic_fifo; + p->en_multiple_tx_fifo = hw->en_multiple_tx_fifo; + p->i2c_enable = hw->i2c_enable; + p->ulpi_fs_ls = false; + p->ts_dline = false; + p->reload_ctl = (hw->snpsid >= DWC2_CORE_REV_2_92a); + p->uframe_sched = true; + p->external_id_pin_ctl = false; + p->hibernation = false; + p->max_packet_count = hw->max_packet_count; + p->max_transfer_size = hw->max_transfer_size; + p->ahbcfg = GAHBCFG_HBSTLEN_INCR4 << GAHBCFG_HBSTLEN_SHIFT; - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n", - val); - val = hsotg->hw_params.host_perio_tx_fifo_size; - dev_dbg(hsotg->dev, "Setting host_perio_tx_fifo_size to %d\n", - val); + if ((hsotg->dr_mode == USB_DR_MODE_HOST) || + (hsotg->dr_mode == USB_DR_MODE_OTG)) { + p->host_dma = dma_capable; + p->dma_desc_enable = false; + p->dma_desc_fs_enable = false; + p->host_support_fs_ls_low_power = false; + p->host_ls_low_power_phy_clk = false; + p->host_channels = hw->host_channels; + p->host_rx_fifo_size = hw->rx_fifo_size; + p->host_nperio_tx_fifo_size = hw->host_nperio_tx_fifo_size; + p->host_perio_tx_fifo_size = hw->host_perio_tx_fifo_size; } - hsotg->params.host_perio_tx_fifo_size = val; -} - -static void dwc2_set_param_max_transfer_size(struct dwc2_hsotg *hsotg, int val) -{ - int valid = 1; - - if (val < 2047 || val > hsotg->hw_params.max_transfer_size) - valid = 0; + if ((hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) || + (hsotg->dr_mode == USB_DR_MODE_OTG)) { + p->g_dma = dma_capable; + p->g_dma_desc = hw->dma_desc_enable; - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for max_transfer_size. Check HW configuration.\n", - val); - val = hsotg->hw_params.max_transfer_size; - dev_dbg(hsotg->dev, "Setting max_transfer_size to %d\n", val); + /* + * The values for g_rx_fifo_size (2048) and + * g_np_tx_fifo_size (1024) come from the legacy s3c + * gadget driver. These defaults have been hard-coded + * for some time so many platforms depend on these + * values. Leave them as defaults for now and only + * auto-detect if the hardware does not support the + * default. + */ + p->g_rx_fifo_size = 2048; + p->g_np_tx_fifo_size = 1024; + dwc2_set_param_tx_fifo_sizes(hsotg); } - - hsotg->params.max_transfer_size = val; } -static void dwc2_set_param_max_packet_count(struct dwc2_hsotg *hsotg, int val) +/** + * dwc2_get_device_properties() - Read in device properties. + * + * Read in the device properties and adjust core parameters if needed. + */ +static void dwc2_get_device_properties(struct dwc2_hsotg *hsotg) { - int valid = 1; - - if (val < 15 || val > hsotg->hw_params.max_packet_count) - valid = 0; + struct dwc2_core_params *p = &hsotg->params; + int num; - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for max_packet_count. Check HW configuration.\n", - val); - val = hsotg->hw_params.max_packet_count; - dev_dbg(hsotg->dev, "Setting max_packet_count to %d\n", val); + if ((hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) || + (hsotg->dr_mode == USB_DR_MODE_OTG)) { + device_property_read_u32(hsotg->dev, "g-rx-fifo-size", + &p->g_rx_fifo_size); + + device_property_read_u32(hsotg->dev, "g-np-tx-fifo-size", + &p->g_np_tx_fifo_size); + + num = device_property_read_u32_array(hsotg->dev, + "g-tx-fifo-size", + NULL, 0); + + if (num > 0) { + num = min(num, 15); + memset(p->g_tx_fifo_size, 0, + sizeof(p->g_tx_fifo_size)); + device_property_read_u32_array(hsotg->dev, + "g-tx-fifo-size", + &p->g_tx_fifo_size[1], + num); + } } - - hsotg->params.max_packet_count = val; } -static void dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val) +static void dwc2_check_param_otg_cap(struct dwc2_hsotg *hsotg) { int valid = 1; - if (val < 1 || val > hsotg->hw_params.host_channels) + switch (hsotg->params.otg_cap) { + case DWC2_CAP_PARAM_HNP_SRP_CAPABLE: + if (hsotg->hw_params.op_mode != GHWCFG2_OP_MODE_HNP_SRP_CAPABLE) + valid = 0; + break; + case DWC2_CAP_PARAM_SRP_ONLY_CAPABLE: + switch (hsotg->hw_params.op_mode) { + case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE: + case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE: + case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE: + case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST: + break; + default: + valid = 0; + break; + } + break; + case DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE: + /* always valid */ + break; + default: valid = 0; - - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for host_channels. Check HW configuration.\n", - val); - val = hsotg->hw_params.host_channels; - dev_dbg(hsotg->dev, "Setting host_channels to %d\n", val); + break; } - hsotg->params.host_channels = val; + if (!valid) + dwc2_set_param_otg_cap(hsotg); } -static void dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val) +static void dwc2_check_param_phy_type(struct dwc2_hsotg *hsotg) { int valid = 0; - u32 hs_phy_type, fs_phy_type; - - if (DWC2_OUT_OF_BOUNDS(val, DWC2_PHY_TYPE_PARAM_FS, - DWC2_PHY_TYPE_PARAM_ULPI)) { - if (val >= 0) { - dev_err(hsotg->dev, "Wrong value for phy_type\n"); - dev_err(hsotg->dev, "phy_type must be 0, 1 or 2\n"); - } - - valid = 0; - } + u32 hs_phy_type; + u32 fs_phy_type; hs_phy_type = hsotg->hw_params.hs_phy_type; fs_phy_type = hsotg->hw_params.fs_phy_type; - if (val == DWC2_PHY_TYPE_PARAM_UTMI && - (hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI || - hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI)) - valid = 1; - else if (val == DWC2_PHY_TYPE_PARAM_ULPI && - (hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI || - hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI)) - valid = 1; - else if (val == DWC2_PHY_TYPE_PARAM_FS && - fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED) - valid = 1; - - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for phy_type. Check HW configuration.\n", - val); - val = DWC2_PHY_TYPE_PARAM_FS; - if (hs_phy_type != GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED) { - if (hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI || - hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI) - val = DWC2_PHY_TYPE_PARAM_UTMI; - else - val = DWC2_PHY_TYPE_PARAM_ULPI; - } - dev_dbg(hsotg->dev, "Setting phy_type to %d\n", val); - } - - hsotg->params.phy_type = val; -} - -static int dwc2_get_param_phy_type(struct dwc2_hsotg *hsotg) -{ - return hsotg->params.phy_type; -} - -static void dwc2_set_param_speed(struct dwc2_hsotg *hsotg, int val) -{ - int valid = 1; - - if (DWC2_OUT_OF_BOUNDS(val, 0, 2)) { - if (val >= 0) { - dev_err(hsotg->dev, "Wrong value for speed parameter\n"); - dev_err(hsotg->dev, "max_speed parameter must be 0, 1, or 2\n"); - } - valid = 0; - } - - if (dwc2_is_hs_iot(hsotg) && - val == DWC2_SPEED_PARAM_LOW) - valid = 0; - - if (val == DWC2_SPEED_PARAM_HIGH && - dwc2_get_param_phy_type(hsotg) == DWC2_PHY_TYPE_PARAM_FS) - valid = 0; - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for speed parameter. Check HW configuration.\n", - val); - val = dwc2_get_param_phy_type(hsotg) == DWC2_PHY_TYPE_PARAM_FS ? - DWC2_SPEED_PARAM_FULL : DWC2_SPEED_PARAM_HIGH; - dev_dbg(hsotg->dev, "Setting speed to %d\n", val); + switch (hsotg->params.phy_type) { + case DWC2_PHY_TYPE_PARAM_FS: + if (fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED) + valid = 1; + break; + case DWC2_PHY_TYPE_PARAM_UTMI: + if ((hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI) || + (hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI)) + valid = 1; + break; + case DWC2_PHY_TYPE_PARAM_ULPI: + if ((hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI) || + (hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI)) + valid = 1; + break; + default: + break; } - hsotg->params.speed = val; + if (!valid) + dwc2_set_param_phy_type(hsotg); } -static void dwc2_set_param_host_ls_low_power_phy_clk(struct dwc2_hsotg *hsotg, - int val) +static void dwc2_check_param_speed(struct dwc2_hsotg *hsotg) { int valid = 1; + int phy_type = hsotg->params.phy_type; + int speed = hsotg->params.speed; - if (DWC2_OUT_OF_BOUNDS(val, DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ, - DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)) { - if (val >= 0) { - dev_err(hsotg->dev, - "Wrong value for host_ls_low_power_phy_clk parameter\n"); - dev_err(hsotg->dev, - "host_ls_low_power_phy_clk must be 0 or 1\n"); - } - valid = 0; - } - - if (val == DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ && - dwc2_get_param_phy_type(hsotg) == DWC2_PHY_TYPE_PARAM_FS) + switch (speed) { + case DWC2_SPEED_PARAM_HIGH: + if ((hsotg->params.speed == DWC2_SPEED_PARAM_HIGH) && + (phy_type == DWC2_PHY_TYPE_PARAM_FS)) + valid = 0; + break; + case DWC2_SPEED_PARAM_FULL: + case DWC2_SPEED_PARAM_LOW: + break; + default: valid = 0; - - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n", - val); - val = dwc2_get_param_phy_type(hsotg) == DWC2_PHY_TYPE_PARAM_FS - ? DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ - : DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ; - dev_dbg(hsotg->dev, "Setting host_ls_low_power_phy_clk to %d\n", - val); - } - - hsotg->params.host_ls_low_power_phy_clk = val; -} - -static void dwc2_set_param_phy_ulpi_ddr(struct dwc2_hsotg *hsotg, int val) -{ - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { - if (val >= 0) { - dev_err(hsotg->dev, "Wrong value for phy_ulpi_ddr\n"); - dev_err(hsotg->dev, "phy_upli_ddr must be 0 or 1\n"); - } - val = 0; - dev_dbg(hsotg->dev, "Setting phy_upli_ddr to %d\n", val); - } - - hsotg->params.phy_ulpi_ddr = val; -} - -static void dwc2_set_param_phy_ulpi_ext_vbus(struct dwc2_hsotg *hsotg, int val) -{ - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { - if (val >= 0) { - dev_err(hsotg->dev, - "Wrong value for phy_ulpi_ext_vbus\n"); - dev_err(hsotg->dev, - "phy_ulpi_ext_vbus must be 0 or 1\n"); - } - val = 0; - dev_dbg(hsotg->dev, "Setting phy_ulpi_ext_vbus to %d\n", val); + break; } - hsotg->params.phy_ulpi_ext_vbus = val; + if (!valid) + dwc2_set_param_speed(hsotg); } -static void dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg, int val) +static void dwc2_check_param_phy_utmi_width(struct dwc2_hsotg *hsotg) { int valid = 0; + int param = hsotg->params.phy_utmi_width; + int width = hsotg->hw_params.utmi_phy_data_width; - switch (hsotg->hw_params.utmi_phy_data_width) { + switch (width) { case GHWCFG4_UTMI_PHY_DATA_WIDTH_8: - valid = (val == 8); + valid = (param == 8); break; case GHWCFG4_UTMI_PHY_DATA_WIDTH_16: - valid = (val == 16); + valid = (param == 16); break; case GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16: - valid = (val == 8 || val == 16); + valid = (param == 8 || param == 16); break; } - if (!valid) { - if (val >= 0) { - dev_err(hsotg->dev, - "%d invalid for phy_utmi_width. Check HW configuration.\n", - val); - } - val = (hsotg->hw_params.utmi_phy_data_width == - GHWCFG4_UTMI_PHY_DATA_WIDTH_8) ? 8 : 16; - dev_dbg(hsotg->dev, "Setting phy_utmi_width to %d\n", val); - } - - hsotg->params.phy_utmi_width = val; -} - -static void dwc2_set_param_ulpi_fs_ls(struct dwc2_hsotg *hsotg, int val) -{ - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { - if (val >= 0) { - dev_err(hsotg->dev, "Wrong value for ulpi_fs_ls\n"); - dev_err(hsotg->dev, "ulpi_fs_ls must be 0 or 1\n"); - } - val = 0; - dev_dbg(hsotg->dev, "Setting ulpi_fs_ls to %d\n", val); - } - - hsotg->params.ulpi_fs_ls = val; -} - -static void dwc2_set_param_ts_dline(struct dwc2_hsotg *hsotg, int val) -{ - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { - if (val >= 0) { - dev_err(hsotg->dev, "Wrong value for ts_dline\n"); - dev_err(hsotg->dev, "ts_dline must be 0 or 1\n"); - } - val = 0; - dev_dbg(hsotg->dev, "Setting ts_dline to %d\n", val); - } - - hsotg->params.ts_dline = val; -} - -static void dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val) -{ - int valid = 1; - - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { - if (val >= 0) { - dev_err(hsotg->dev, "Wrong value for i2c_enable\n"); - dev_err(hsotg->dev, "i2c_enable must be 0 or 1\n"); - } - - valid = 0; - } - - if (val == 1 && !(hsotg->hw_params.i2c_enable)) - valid = 0; - - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for i2c_enable. Check HW configuration.\n", - val); - val = hsotg->hw_params.i2c_enable; - dev_dbg(hsotg->dev, "Setting i2c_enable to %d\n", val); - } - - hsotg->params.i2c_enable = val; -} - -static void dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, - int val) -{ - int valid = 1; - - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { - if (val >= 0) { - dev_err(hsotg->dev, - "Wrong value for en_multiple_tx_fifo,\n"); - dev_err(hsotg->dev, - "en_multiple_tx_fifo must be 0 or 1\n"); - } - valid = 0; - } - - if (val == 1 && !hsotg->hw_params.en_multiple_tx_fifo) - valid = 0; - - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n", - val); - val = hsotg->hw_params.en_multiple_tx_fifo; - dev_dbg(hsotg->dev, "Setting en_multiple_tx_fifo to %d\n", val); - } - - hsotg->params.en_multiple_tx_fifo = val; + if (!valid) + dwc2_set_param_phy_utmi_width(hsotg); } -static void dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val) +static void dwc2_check_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg) { - int valid = 1; - - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { - if (val >= 0) { - dev_err(hsotg->dev, - "'%d' invalid for parameter reload_ctl\n", val); - dev_err(hsotg->dev, "reload_ctl must be 0 or 1\n"); - } - valid = 0; - } - - if (val == 1 && hsotg->hw_params.snpsid < DWC2_CORE_REV_2_92a) - valid = 0; - - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for parameter reload_ctl. Check HW configuration.\n", - val); - val = hsotg->hw_params.snpsid >= DWC2_CORE_REV_2_92a; - dev_dbg(hsotg->dev, "Setting reload_ctl to %d\n", val); - } + int fifo_count; + int fifo; + int min; + u32 total = 0; + u32 dptxfszn; - hsotg->params.reload_ctl = val; -} + fifo_count = dwc2_hsotg_tx_fifo_count(hsotg); + min = hsotg->hw_params.en_multiple_tx_fifo ? 16 : 4; -static void dwc2_set_param_ahbcfg(struct dwc2_hsotg *hsotg, int val) -{ - if (val != -1) - hsotg->params.ahbcfg = val; - else - hsotg->params.ahbcfg = GAHBCFG_HBSTLEN_INCR4 << - GAHBCFG_HBSTLEN_SHIFT; -} + for (fifo = 1; fifo <= fifo_count; fifo++) + total += hsotg->params.g_tx_fifo_size[fifo]; -static void dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val) -{ - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { - if (val >= 0) { - dev_err(hsotg->dev, - "'%d' invalid for parameter otg_ver\n", val); - dev_err(hsotg->dev, - "otg_ver must be 0 (for OTG 1.3 support) or 1 (for OTG 2.0 support)\n"); - } - val = 0; - dev_dbg(hsotg->dev, "Setting otg_ver to %d\n", val); + if (total > dwc2_hsotg_tx_fifo_total_depth(hsotg) || !total) { + dev_warn(hsotg->dev, "%s: Invalid parameter g-tx-fifo-size, setting to default average\n", + __func__); + dwc2_set_param_tx_fifo_sizes(hsotg); } - hsotg->params.otg_ver = val; -} + for (fifo = 1; fifo <= fifo_count; fifo++) { + dptxfszn = (dwc2_readl(hsotg->regs + DPTXFSIZN(fifo)) & + FIFOSIZE_DEPTH_MASK) >> FIFOSIZE_DEPTH_SHIFT; -static void dwc2_set_param_uframe_sched(struct dwc2_hsotg *hsotg, int val) -{ - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { - if (val >= 0) { - dev_err(hsotg->dev, - "'%d' invalid for parameter uframe_sched\n", - val); - dev_err(hsotg->dev, "uframe_sched must be 0 or 1\n"); + if (hsotg->params.g_tx_fifo_size[fifo] < min || + hsotg->params.g_tx_fifo_size[fifo] > dptxfszn) { + dev_warn(hsotg->dev, "%s: Invalid parameter g_tx_fifo_size[%d]=%d\n", + __func__, fifo, + hsotg->params.g_tx_fifo_size[fifo]); + hsotg->params.g_tx_fifo_size[fifo] = dptxfszn; } - val = 1; - dev_dbg(hsotg->dev, "Setting uframe_sched to %d\n", val); } - - hsotg->params.uframe_sched = val; } -static void dwc2_set_param_external_id_pin_ctl(struct dwc2_hsotg *hsotg, - int val) -{ - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { - if (val >= 0) { - dev_err(hsotg->dev, - "'%d' invalid for parameter external_id_pin_ctl\n", - val); - dev_err(hsotg->dev, "external_id_pin_ctl must be 0 or 1\n"); - } - val = 0; - dev_dbg(hsotg->dev, "Setting external_id_pin_ctl to %d\n", val); - } +#define CHECK_RANGE(_param, _min, _max, _def) do { \ + if ((hsotg->params._param) < (_min) || \ + (hsotg->params._param) > (_max)) { \ + dev_warn(hsotg->dev, "%s: Invalid parameter %s=%d\n", \ + __func__, #_param, hsotg->params._param); \ + hsotg->params._param = (_def); \ + } \ + } while (0) - hsotg->params.external_id_pin_ctl = val; -} +#define CHECK_BOOL(_param, _check) do { \ + if (hsotg->params._param && !(_check)) { \ + dev_warn(hsotg->dev, "%s: Invalid parameter %s=%d\n", \ + __func__, #_param, hsotg->params._param); \ + hsotg->params._param = false; \ + } \ + } while (0) -static void dwc2_set_param_hibernation(struct dwc2_hsotg *hsotg, - int val) -{ - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { - if (val >= 0) { - dev_err(hsotg->dev, - "'%d' invalid for parameter hibernation\n", - val); - dev_err(hsotg->dev, "hibernation must be 0 or 1\n"); - } - val = 0; - dev_dbg(hsotg->dev, "Setting hibernation to %d\n", val); - } - - hsotg->params.hibernation = val; -} - -static void dwc2_set_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg) -{ - int i; - int num; - char *property = "g-tx-fifo-size"; - struct dwc2_core_params *p = &hsotg->params; - - memset(p->g_tx_fifo_size, 0, sizeof(p->g_tx_fifo_size)); - - /* Read tx fifo sizes */ - num = device_property_read_u32_array(hsotg->dev, property, NULL, 0); - - if (num > 0) { - device_property_read_u32_array(hsotg->dev, property, - &p->g_tx_fifo_size[1], - num); - } else { - u32 p_tx_fifo[] = DWC2_G_P_LEGACY_TX_FIFO_SIZE; - - memcpy(&p->g_tx_fifo_size[1], - p_tx_fifo, - sizeof(p_tx_fifo)); - - num = ARRAY_SIZE(p_tx_fifo); - } - - for (i = 0; i < num; i++) { - if ((i + 1) >= ARRAY_SIZE(p->g_tx_fifo_size)) - break; - - dev_dbg(hsotg->dev, "Setting %s[%d] to %d\n", - property, i + 1, p->g_tx_fifo_size[i + 1]); - } -} - -static void dwc2_set_gadget_dma(struct dwc2_hsotg *hsotg) +static void dwc2_check_params(struct dwc2_hsotg *hsotg) { struct dwc2_hw_params *hw = &hsotg->hw_params; struct dwc2_core_params *p = &hsotg->params; bool dma_capable = !(hw->arch == GHWCFG2_SLAVE_ONLY_ARCH); - /* Buffer DMA */ - dwc2_set_param_bool(hsotg, &p->g_dma, - false, "gadget-dma", - dma_capable, false, - dma_capable); - - /* DMA Descriptor */ - dwc2_set_param_bool(hsotg, &p->g_dma_desc, false, - "gadget-dma-desc", - !!hw->dma_desc_enable, false, - !!hw->dma_desc_enable); -} + dwc2_check_param_otg_cap(hsotg); + dwc2_check_param_phy_type(hsotg); + dwc2_check_param_speed(hsotg); + dwc2_check_param_phy_utmi_width(hsotg); + CHECK_BOOL(enable_dynamic_fifo, hw->enable_dynamic_fifo); + CHECK_BOOL(en_multiple_tx_fifo, hw->en_multiple_tx_fifo); + CHECK_BOOL(i2c_enable, hw->i2c_enable); + CHECK_BOOL(reload_ctl, (hsotg->hw_params.snpsid > DWC2_CORE_REV_2_92a)); + CHECK_RANGE(max_packet_count, + 15, hw->max_packet_count, + hw->max_packet_count); + CHECK_RANGE(max_transfer_size, + 2047, hw->max_transfer_size, + hw->max_transfer_size); -/** - * dwc2_set_parameters() - Set all core parameters. - * - * @hsotg: Programming view of the DWC_otg controller - * @params: The parameters to set - */ -static void dwc2_set_parameters(struct dwc2_hsotg *hsotg, - const struct dwc2_core_params *params) -{ - struct dwc2_hw_params *hw = &hsotg->hw_params; - struct dwc2_core_params *p = &hsotg->params; - bool dma_capable = !(hw->arch == GHWCFG2_SLAVE_ONLY_ARCH); - - dwc2_set_param_otg_cap(hsotg, params->otg_cap); if ((hsotg->dr_mode == USB_DR_MODE_HOST) || (hsotg->dr_mode == USB_DR_MODE_OTG)) { - dev_dbg(hsotg->dev, "Setting HOST parameters\n"); - - dwc2_set_param_bool(hsotg, &p->host_dma, - false, "host-dma", - dma_capable, false, - dma_capable); - dwc2_set_param_host_rx_fifo_size(hsotg, - params->host_rx_fifo_size); - dwc2_set_param_host_nperio_tx_fifo_size(hsotg, - params->host_nperio_tx_fifo_size); - dwc2_set_param_host_perio_tx_fifo_size(hsotg, - params->host_perio_tx_fifo_size); + CHECK_BOOL(host_dma, dma_capable); + CHECK_BOOL(dma_desc_enable, p->host_dma); + CHECK_BOOL(dma_desc_fs_enable, p->dma_desc_enable); + CHECK_BOOL(host_ls_low_power_phy_clk, + p->phy_type == DWC2_PHY_TYPE_PARAM_FS); + CHECK_RANGE(host_channels, + 1, hw->host_channels, + hw->host_channels); + CHECK_RANGE(host_rx_fifo_size, + 16, hw->rx_fifo_size, + hw->rx_fifo_size); + CHECK_RANGE(host_nperio_tx_fifo_size, + 16, hw->host_nperio_tx_fifo_size, + hw->host_nperio_tx_fifo_size); + CHECK_RANGE(host_perio_tx_fifo_size, + 16, hw->host_perio_tx_fifo_size, + hw->host_perio_tx_fifo_size); } - dwc2_set_param_dma_desc_enable(hsotg, params->dma_desc_enable); - dwc2_set_param_dma_desc_fs_enable(hsotg, params->dma_desc_fs_enable); - - dwc2_set_param_host_support_fs_ls_low_power(hsotg, - params->host_support_fs_ls_low_power); - dwc2_set_param_enable_dynamic_fifo(hsotg, - params->enable_dynamic_fifo); - dwc2_set_param_max_transfer_size(hsotg, - params->max_transfer_size); - dwc2_set_param_max_packet_count(hsotg, - params->max_packet_count); - dwc2_set_param_host_channels(hsotg, params->host_channels); - dwc2_set_param_phy_type(hsotg, params->phy_type); - dwc2_set_param_speed(hsotg, params->speed); - dwc2_set_param_host_ls_low_power_phy_clk(hsotg, - params->host_ls_low_power_phy_clk); - dwc2_set_param_phy_ulpi_ddr(hsotg, params->phy_ulpi_ddr); - dwc2_set_param_phy_ulpi_ext_vbus(hsotg, - params->phy_ulpi_ext_vbus); - dwc2_set_param_phy_utmi_width(hsotg, params->phy_utmi_width); - dwc2_set_param_ulpi_fs_ls(hsotg, params->ulpi_fs_ls); - dwc2_set_param_ts_dline(hsotg, params->ts_dline); - dwc2_set_param_i2c_enable(hsotg, params->i2c_enable); - dwc2_set_param_en_multiple_tx_fifo(hsotg, - params->en_multiple_tx_fifo); - dwc2_set_param_reload_ctl(hsotg, params->reload_ctl); - dwc2_set_param_ahbcfg(hsotg, params->ahbcfg); - dwc2_set_param_otg_ver(hsotg, params->otg_ver); - dwc2_set_param_uframe_sched(hsotg, params->uframe_sched); - dwc2_set_param_external_id_pin_ctl(hsotg, params->external_id_pin_ctl); - dwc2_set_param_hibernation(hsotg, params->hibernation); - /* - * Set devicetree-only parameters. These parameters do not - * take any values from @params. - */ if ((hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) || (hsotg->dr_mode == USB_DR_MODE_OTG)) { - dev_dbg(hsotg->dev, "Setting peripheral device properties\n"); - - dwc2_set_gadget_dma(hsotg); - - /* - * The values for g_rx_fifo_size (2048) and - * g_np_tx_fifo_size (1024) come from the legacy s3c - * gadget driver. These defaults have been hard-coded - * for some time so many platforms depend on these - * values. Leave them as defaults for now and only - * auto-detect if the hardware does not support the - * default. - */ - dwc2_set_param_u32(hsotg, &p->g_rx_fifo_size, - true, "g-rx-fifo-size", 2048, - hw->rx_fifo_size, - 16, hw->rx_fifo_size); - - dwc2_set_param_u32(hsotg, &p->g_np_tx_fifo_size, - true, "g-np-tx-fifo-size", 1024, - hw->dev_nperio_tx_fifo_size, - 16, hw->dev_nperio_tx_fifo_size); - - dwc2_set_param_tx_fifo_sizes(hsotg); + CHECK_BOOL(g_dma, dma_capable); + CHECK_BOOL(g_dma_desc, (p->g_dma && hw->dma_desc_enable)); + CHECK_RANGE(g_rx_fifo_size, + 16, hw->rx_fifo_size, + hw->rx_fifo_size); + CHECK_RANGE(g_np_tx_fifo_size, + 16, hw->dev_nperio_tx_fifo_size, + hw->dev_nperio_tx_fifo_size); + dwc2_check_param_tx_fifo_sizes(hsotg); } } @@ -1211,8 +553,6 @@ static void dwc2_get_host_hwparams(struct dwc2_hsotg *hsotg) gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ); hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ); - dev_dbg(hsotg->dev, "gnptxfsiz=%08x\n", gnptxfsiz); - dev_dbg(hsotg->dev, "hptxfsiz=%08x\n", hptxfsiz); if (forced) dwc2_clear_force_mode(hsotg); @@ -1240,7 +580,6 @@ static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg) forced = dwc2_force_mode_if_needed(hsotg, false); gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ); - dev_dbg(hsotg->dev, "gnptxfsiz=%08x\n", gnptxfsiz); if (forced) dwc2_clear_force_mode(hsotg); @@ -1286,12 +625,6 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) hwcfg4 = dwc2_readl(hsotg->regs + GHWCFG4); grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ); - dev_dbg(hsotg->dev, "hwcfg1=%08x\n", hwcfg1); - dev_dbg(hsotg->dev, "hwcfg2=%08x\n", hwcfg2); - dev_dbg(hsotg->dev, "hwcfg3=%08x\n", hwcfg3); - dev_dbg(hsotg->dev, "hwcfg4=%08x\n", hwcfg4); - dev_dbg(hsotg->dev, "grxfsiz=%08x\n", grxfsiz); - /* * Host specific hardware parameters. Reading these parameters * requires the controller to be in host mode. The mode will @@ -1351,73 +684,24 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) hw->rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >> GRXFSIZ_DEPTH_SHIFT; - dev_dbg(hsotg->dev, "Detected values from hardware:\n"); - dev_dbg(hsotg->dev, " op_mode=%d\n", - hw->op_mode); - dev_dbg(hsotg->dev, " arch=%d\n", - hw->arch); - dev_dbg(hsotg->dev, " dma_desc_enable=%d\n", - hw->dma_desc_enable); - dev_dbg(hsotg->dev, " power_optimized=%d\n", - hw->power_optimized); - dev_dbg(hsotg->dev, " i2c_enable=%d\n", - hw->i2c_enable); - dev_dbg(hsotg->dev, " hs_phy_type=%d\n", - hw->hs_phy_type); - dev_dbg(hsotg->dev, " fs_phy_type=%d\n", - hw->fs_phy_type); - dev_dbg(hsotg->dev, " utmi_phy_data_width=%d\n", - hw->utmi_phy_data_width); - dev_dbg(hsotg->dev, " num_dev_ep=%d\n", - hw->num_dev_ep); - dev_dbg(hsotg->dev, " num_dev_perio_in_ep=%d\n", - hw->num_dev_perio_in_ep); - dev_dbg(hsotg->dev, " host_channels=%d\n", - hw->host_channels); - dev_dbg(hsotg->dev, " max_transfer_size=%d\n", - hw->max_transfer_size); - dev_dbg(hsotg->dev, " max_packet_count=%d\n", - hw->max_packet_count); - dev_dbg(hsotg->dev, " nperio_tx_q_depth=0x%0x\n", - hw->nperio_tx_q_depth); - dev_dbg(hsotg->dev, " host_perio_tx_q_depth=0x%0x\n", - hw->host_perio_tx_q_depth); - dev_dbg(hsotg->dev, " dev_token_q_depth=0x%0x\n", - hw->dev_token_q_depth); - dev_dbg(hsotg->dev, " enable_dynamic_fifo=%d\n", - hw->enable_dynamic_fifo); - dev_dbg(hsotg->dev, " en_multiple_tx_fifo=%d\n", - hw->en_multiple_tx_fifo); - dev_dbg(hsotg->dev, " total_fifo_size=%d\n", - hw->total_fifo_size); - dev_dbg(hsotg->dev, " rx_fifo_size=%d\n", - hw->rx_fifo_size); - dev_dbg(hsotg->dev, " host_nperio_tx_fifo_size=%d\n", - hw->host_nperio_tx_fifo_size); - dev_dbg(hsotg->dev, " host_perio_tx_fifo_size=%d\n", - hw->host_perio_tx_fifo_size); - dev_dbg(hsotg->dev, "\n"); - return 0; } int dwc2_init_params(struct dwc2_hsotg *hsotg) { const struct of_device_id *match; - struct dwc2_core_params params; + void (*set_params)(void *data); + + dwc2_set_default_params(hsotg); + dwc2_get_device_properties(hsotg); match = of_match_device(dwc2_of_match_table, hsotg->dev); - if (match && match->data) - params = *((struct dwc2_core_params *)match->data); - else - params = params_default; - - if (dwc2_is_fs_iot(hsotg)) { - params.speed = DWC2_SPEED_PARAM_FULL; - params.phy_type = DWC2_PHY_TYPE_PARAM_FS; + if (match && match->data) { + set_params = match->data; + set_params(hsotg); } - dwc2_set_parameters(hsotg, ¶ms); + dwc2_check_params(hsotg); return 0; } diff --git a/drivers/usb/dwc2/pci.c b/drivers/usb/dwc2/pci.c index a23329e3d7cd..fdeb8c7bf30a 100644 --- a/drivers/usb/dwc2/pci.c +++ b/drivers/usb/dwc2/pci.c @@ -87,7 +87,7 @@ static void dwc2_pci_remove(struct pci_dev *pci) } static int dwc2_pci_probe(struct pci_dev *pci, - const struct pci_device_id *id) + const struct pci_device_id *id) { struct resource res[2]; struct platform_device *dwc2; diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 4fc8c603afb8..9564bc76c56f 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -111,7 +111,7 @@ static int dwc2_get_dr_mode(struct dwc2_hsotg *hsotg) if (mode != hsotg->dr_mode) { dev_warn(hsotg->dev, - "Configuration mismatch. dr_mode forced to %s\n", + "Configuration mismatch. dr_mode forced to %s\n", mode == USB_DR_MODE_HOST ? "host" : "device"); hsotg->dr_mode = mode; @@ -136,11 +136,11 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) return ret; } - if (hsotg->uphy) + if (hsotg->uphy) { ret = usb_phy_init(hsotg->uphy); - else if (hsotg->plat && hsotg->plat->phy_init) + } else if (hsotg->plat && hsotg->plat->phy_init) { ret = hsotg->plat->phy_init(pdev, hsotg->plat->phy_type); - else { + } else { ret = phy_power_on(hsotg->phy); if (ret == 0) ret = phy_init(hsotg->phy); @@ -170,11 +170,11 @@ static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) struct platform_device *pdev = to_platform_device(hsotg->dev); int ret = 0; - if (hsotg->uphy) + if (hsotg->uphy) { usb_phy_shutdown(hsotg->uphy); - else if (hsotg->plat && hsotg->plat->phy_exit) + } else if (hsotg->plat && hsotg->plat->phy_exit) { ret = hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type); - else { + } else { ret = phy_exit(hsotg->phy); if (ret == 0) ret = phy_power_off(hsotg->phy); @@ -445,7 +445,7 @@ static int dwc2_driver_probe(struct platform_device *dev) } if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) { - retval = dwc2_hcd_init(hsotg, hsotg->irq); + retval = dwc2_hcd_init(hsotg); if (retval) { if (hsotg->gadget_enabled) dwc2_hsotg_remove(hsotg); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 14b760209680..2b9e4ca3c932 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -40,6 +40,7 @@ /* Global constants */ #define DWC3_PULL_UP_TIMEOUT 500 /* ms */ #define DWC3_ZLP_BUF_SIZE 1024 /* size of a superspeed bulk */ +#define DWC3_BOUNCE_SIZE 1024 /* size of a superspeed bulk */ #define DWC3_EP0_BOUNCE_SIZE 512 #define DWC3_ENDPOINTS_NUM 32 #define DWC3_XHCI_RESOURCES_NUM 2 @@ -724,6 +725,7 @@ struct dwc3_hwparams { * @epnum: endpoint number to which this request refers * @trb: pointer to struct dwc3_trb * @trb_dma: DMA address of @trb + * @unaligned: true for OUT endpoints with length not divisible by maxp * @direction: IN or OUT direction flag * @mapped: true when request has been dma-mapped * @queued: true when request has been queued to HW @@ -740,6 +742,7 @@ struct dwc3_request { struct dwc3_trb *trb; dma_addr_t trb_dma; + unsigned unaligned:1; unsigned direction:1; unsigned mapped:1; unsigned started:1; @@ -857,12 +860,14 @@ struct dwc3_scratchpad_array { struct dwc3 { struct usb_ctrlrequest *ctrl_req; struct dwc3_trb *ep0_trb; + void *bounce; void *ep0_bounce; void *zlp_buf; void *scratchbuf; u8 *setup_buf; dma_addr_t ctrl_req_addr; dma_addr_t ep0_trb_addr; + dma_addr_t bounce_addr; dma_addr_t ep0_bounce_addr; dma_addr_t scratch_addr; struct dwc3_request ep0_usb_req; diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index e956306d9b0f..1515d45ebcec 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -128,10 +128,8 @@ static int dwc3_exynos_probe(struct platform_device *pdev) clk_prepare_enable(exynos->clk); exynos->susp_clk = devm_clk_get(dev, "usbdrd30_susp_clk"); - if (IS_ERR(exynos->susp_clk)) { - dev_info(dev, "no suspend clk specified\n"); + if (IS_ERR(exynos->susp_clk)) exynos->susp_clk = NULL; - } clk_prepare_enable(exynos->susp_clk); if (of_device_is_compatible(node, "samsung,exynos7-dwusb3")) { @@ -290,7 +288,6 @@ static struct platform_driver dwc3_exynos_driver = { module_platform_driver(dwc3_exynos_driver); -MODULE_ALIAS("platform:exynos-dwc3"); MODULE_AUTHOR("Anton Tikhomirov <av.tikhomirov@samsung.com>"); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("DesignWare USB3 EXYNOS Glue Layer"); diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index eb1b9cb3f9d1..2092e46b1380 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -426,20 +426,20 @@ static int dwc3_omap_extcon_register(struct dwc3_omap *omap) } omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier; - ret = extcon_register_notifier(edev, EXTCON_USB, - &omap->vbus_nb); + ret = devm_extcon_register_notifier(omap->dev, edev, + EXTCON_USB, &omap->vbus_nb); if (ret < 0) dev_vdbg(omap->dev, "failed to register notifier for USB\n"); omap->id_nb.notifier_call = dwc3_omap_id_notifier; - ret = extcon_register_notifier(edev, EXTCON_USB_HOST, - &omap->id_nb); + ret = devm_extcon_register_notifier(omap->dev, edev, + EXTCON_USB_HOST, &omap->id_nb); if (ret < 0) dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n"); - if (extcon_get_cable_state_(edev, EXTCON_USB) == true) + if (extcon_get_state(edev, EXTCON_USB) == true) dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); - if (extcon_get_cable_state_(edev, EXTCON_USB_HOST) == true) + if (extcon_get_state(edev, EXTCON_USB_HOST) == true) dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); omap->edev = edev; @@ -528,17 +528,13 @@ static int dwc3_omap_probe(struct platform_device *pdev) ret = of_platform_populate(node, NULL, NULL, dev); if (ret) { dev_err(&pdev->dev, "failed to create dwc3 core\n"); - goto err2; + goto err1; } dwc3_omap_enable_irqs(omap); enable_irq(omap->irq); return 0; -err2: - extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb); - extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb); - err1: pm_runtime_put_sync(dev); pm_runtime_disable(dev); @@ -550,8 +546,6 @@ static int dwc3_omap_remove(struct platform_device *pdev) { struct dwc3_omap *omap = platform_get_drvdata(pdev); - extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb); - extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb); dwc3_omap_disable_irqs(omap); disable_irq(omap->irq); of_platform_depopulate(omap->dev); diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 9bb1f8526f3e..e689cede9b0e 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -1123,7 +1123,21 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc, dwc->ep0state = EP0_STATUS_PHASE; if (dwc->delayed_status) { + struct dwc3_ep *dep = dwc->eps[0]; + WARN_ON_ONCE(event->endpoint_number != 1); + /* + * We should handle the delay STATUS phase here if the + * request for handling delay STATUS has been queued + * into the list. + */ + if (!list_empty(&dep->pending_list)) { + dwc->delayed_status = false; + usb_gadget_set_state(&dwc->gadget, + USB_STATE_CONFIGURED); + dwc3_ep0_do_control_status(dwc, event); + } + return; } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 204c754cc647..4db97ecae885 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -833,29 +833,14 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep, static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep); -/** - * dwc3_prepare_one_trb - setup one TRB from one request - * @dep: endpoint for which this request is prepared - * @req: dwc3_request pointer - */ -static void dwc3_prepare_one_trb(struct dwc3_ep *dep, - struct dwc3_request *req, dma_addr_t dma, - unsigned length, unsigned chain, unsigned node) +static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, + dma_addr_t dma, unsigned length, unsigned chain, unsigned node, + unsigned stream_id, unsigned short_not_ok, unsigned no_interrupt) { - struct dwc3_trb *trb; struct dwc3 *dwc = dep->dwc; struct usb_gadget *gadget = &dwc->gadget; enum usb_device_speed speed = gadget->speed; - trb = &dep->trb_pool[dep->trb_enqueue]; - - if (!req->trb) { - dwc3_gadget_move_started_request(req); - req->trb = trb; - req->trb_dma = dwc3_trb_dma_offset(dep, trb); - dep->queued_requests++; - } - dwc3_ep_inc_enq(dep); trb->size = DWC3_TRB_SIZE_LENGTH(length); @@ -900,11 +885,11 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, if (usb_endpoint_dir_out(dep->endpoint.desc)) { trb->ctrl |= DWC3_TRB_CTRL_CSP; - if (req->request.short_not_ok) + if (short_not_ok) trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; } - if ((!req->request.no_interrupt && !chain) || + if ((!no_interrupt && !chain) || (dwc3_calc_trbs_left(dep) == 0)) trb->ctrl |= DWC3_TRB_CTRL_IOC; @@ -912,7 +897,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, trb->ctrl |= DWC3_TRB_CTRL_CHN; if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable) - trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id); + trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(stream_id); trb->ctrl |= DWC3_TRB_CTRL_HWO; @@ -920,6 +905,36 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, } /** + * dwc3_prepare_one_trb - setup one TRB from one request + * @dep: endpoint for which this request is prepared + * @req: dwc3_request pointer + * @chain: should this TRB be chained to the next? + * @node: only for isochronous endpoints. First TRB needs different type. + */ +static void dwc3_prepare_one_trb(struct dwc3_ep *dep, + struct dwc3_request *req, unsigned chain, unsigned node) +{ + struct dwc3_trb *trb; + unsigned length = req->request.length; + unsigned stream_id = req->request.stream_id; + unsigned short_not_ok = req->request.short_not_ok; + unsigned no_interrupt = req->request.no_interrupt; + dma_addr_t dma = req->request.dma; + + trb = &dep->trb_pool[dep->trb_enqueue]; + + if (!req->trb) { + dwc3_gadget_move_started_request(req); + req->trb = trb; + req->trb_dma = dwc3_trb_dma_offset(dep, trb); + dep->queued_requests++; + } + + __dwc3_prepare_one_trb(dep, trb, dma, length, chain, node, + stream_id, short_not_ok, no_interrupt); +} + +/** * dwc3_ep_prev_trb() - Returns the previous TRB in the ring * @dep: The endpoint with the TRB ring * @index: The index of the current TRB in the ring @@ -974,21 +989,36 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, { struct scatterlist *sg = req->sg; struct scatterlist *s; - unsigned int length; - dma_addr_t dma; int i; for_each_sg(sg, s, req->num_pending_sgs, i) { + unsigned int length = req->request.length; + unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); + unsigned int rem = length % maxp; unsigned chain = true; - length = sg_dma_len(s); - dma = sg_dma_address(s); - if (sg_is_last(s)) chain = false; - dwc3_prepare_one_trb(dep, req, dma, length, - chain, i); + if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) { + struct dwc3 *dwc = dep->dwc; + struct dwc3_trb *trb; + + req->unaligned = true; + + /* prepare normal TRB */ + dwc3_prepare_one_trb(dep, req, true, i); + + /* Now prepare one extra TRB to align transfer size */ + trb = &dep->trb_pool[dep->trb_enqueue]; + __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, + maxp - rem, false, 0, + req->request.stream_id, + req->request.short_not_ok, + req->request.no_interrupt); + } else { + dwc3_prepare_one_trb(dep, req, chain, i); + } if (!dwc3_calc_trbs_left(dep)) break; @@ -998,14 +1028,28 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, struct dwc3_request *req) { - unsigned int length; - dma_addr_t dma; + unsigned int length = req->request.length; + unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); + unsigned int rem = length % maxp; + + if (rem && usb_endpoint_dir_out(dep->endpoint.desc)) { + struct dwc3 *dwc = dep->dwc; + struct dwc3_trb *trb; - dma = req->request.dma; - length = req->request.length; + req->unaligned = true; - dwc3_prepare_one_trb(dep, req, dma, length, - false, 0); + /* prepare normal TRB */ + dwc3_prepare_one_trb(dep, req, true, 0); + + /* Now prepare one extra TRB to align transfer size */ + trb = &dep->trb_pool[dep->trb_enqueue]; + __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp - rem, + false, 0, req->request.stream_id, + req->request.short_not_ok, + req->request.no_interrupt); + } else { + dwc3_prepare_one_trb(dep, req, false, 0); + } } /* @@ -1335,6 +1379,9 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) unsigned transfer_in_flight; unsigned started; + if (dep->flags & DWC3_EP_STALL) + return 0; + if (dep->number > 1) trb = dwc3_ep_prev_trb(dep, dep->trb_enqueue); else @@ -1356,6 +1403,8 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) else dep->flags |= DWC3_EP_STALL; } else { + if (!(dep->flags & DWC3_EP_STALL)) + return 0; ret = dwc3_send_clear_stall_ep_cmd(dep); if (ret) @@ -1918,6 +1967,44 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, dep->endpoint.ops = &dwc3_gadget_ep0_ops; if (!epnum) dwc->gadget.ep0 = &dep->endpoint; + } else if (direction) { + int mdwidth; + int size; + int ret; + int num; + + mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0); + /* MDWIDTH is represented in bits, we need it in bytes */ + mdwidth /= 8; + + size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(i)); + size = DWC3_GTXFIFOSIZ_TXFDEF(size); + + /* FIFO Depth is in MDWDITH bytes. Multiply */ + size *= mdwidth; + + num = size / 1024; + if (num == 0) + num = 1; + + /* + * FIFO sizes account an extra MDWIDTH * (num + 1) bytes for + * internal overhead. We don't really know how these are used, + * but documentation say it exists. + */ + size -= mdwidth * (num + 1); + size /= num; + + usb_ep_set_maxpacket_limit(&dep->endpoint, size); + + dep->endpoint.max_streams = 15; + dep->endpoint.ops = &dwc3_gadget_ep_ops; + list_add_tail(&dep->endpoint.ep_list, + &dwc->gadget.ep_list); + + ret = dwc3_alloc_trb_pool(dep); + if (ret) + return ret; } else { int ret; @@ -2029,6 +2116,16 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, if (chain && (trb->ctrl & DWC3_TRB_CTRL_HWO)) trb->ctrl &= ~DWC3_TRB_CTRL_HWO; + /* + * If we're dealing with unaligned size OUT transfer, we will be left + * with one TRB pending in the ring. We need to manually clear HWO bit + * from that TRB. + */ + if (req->unaligned && (trb->ctrl & DWC3_TRB_CTRL_HWO)) { + trb->ctrl &= ~DWC3_TRB_CTRL_HWO; + return 1; + } + if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN) return 1; @@ -2118,6 +2215,13 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, event, status, chain); } + if (req->unaligned) { + trb = &dep->trb_pool[dep->trb_dequeue]; + ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb, + event, status, false); + req->unaligned = false; + } + req->request.actual = length - req->remaining; if ((req->request.actual < length) && req->num_pending_sgs) @@ -3019,6 +3123,13 @@ int dwc3_gadget_init(struct dwc3 *dwc) goto err4; } + dwc->bounce = dma_alloc_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, + &dwc->bounce_addr, GFP_KERNEL); + if (!dwc->bounce) { + ret = -ENOMEM; + goto err5; + } + init_completion(&dwc->ep0_in_setup); dwc->gadget.ops = &dwc3_gadget_ops; @@ -3050,27 +3161,24 @@ int dwc3_gadget_init(struct dwc3 *dwc) dwc->gadget.max_speed = dwc->maximum_speed; /* - * Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize - * on ep out. - */ - dwc->gadget.quirk_ep_out_aligned_size = true; - - /* * REVISIT: Here we should clear all pending IRQs to be * sure we're starting from a well known location. */ ret = dwc3_gadget_init_endpoints(dwc); if (ret) - goto err5; + goto err6; ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); if (ret) { dev_err(dwc->dev, "failed to register udc\n"); - goto err5; + goto err6; } return 0; +err6: + dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, + dwc->bounce_addr); err5: kfree(dwc->zlp_buf); @@ -3103,6 +3211,8 @@ void dwc3_gadget_exit(struct dwc3 *dwc) dwc3_gadget_free_endpoints(dwc); + dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, + dwc->bounce_addr); dma_free_coherent(dwc->sysdev, DWC3_EP0_BOUNCE_SIZE, dwc->ep0_bounce, dwc->ep0_bounce_addr); diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index 487f0ff6ae25..76f0b0df37c1 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -54,11 +54,12 @@ out: int dwc3_host_init(struct dwc3 *dwc) { - struct property_entry props[2]; + struct property_entry props[3]; struct platform_device *xhci; int ret, irq; struct resource *res; struct platform_device *dwc3_pdev = to_platform_device(dwc->dev); + int prop_idx = 0; irq = dwc3_host_get_irq(dwc); if (irq < 0) @@ -97,8 +98,22 @@ int dwc3_host_init(struct dwc3 *dwc) memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props)); - if (dwc->usb3_lpm_capable) { - props[0].name = "usb3-lpm-capable"; + if (dwc->usb3_lpm_capable) + props[prop_idx++].name = "usb3-lpm-capable"; + + /** + * WORKAROUND: dwc3 revisions <=3.00a have a limitation + * where Port Disable command doesn't work. + * + * The suggested workaround is that we avoid Port Disable + * completely. + * + * This following flag tells XHCI to do just that. + */ + if (dwc->revision <= DWC3_REVISION_300A) + props[prop_idx++].name = "quirk-broken-port-ped"; + + if (prop_idx) { ret = platform_device_add_properties(xhci, props); if (ret) { dev_err(dwc->dev, "failed to add properties to xHCI\n"); diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 5490fc51638e..c46666364c87 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1230,7 +1230,7 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code, desc = epfile->ep->descs[desc_idx]; spin_unlock_irq(&epfile->ffs->eps_lock); - ret = copy_to_user((void *)value, desc, sizeof(*desc)); + ret = copy_to_user((void *)value, desc, desc->bLength); if (ret) ret = -EFAULT; return ret; @@ -2101,7 +2101,7 @@ static int __ffs_data_do_entity(enum ffs_entity_type type, case FFS_ENDPOINT: d = (void *)desc; helper->eps_count++; - if (helper->eps_count >= 15) + if (helper->eps_count >= FFS_MAX_EPS_COUNT) return -EINVAL; /* Check if descriptors for any speed were already parsed */ if (!helper->ffs->eps_count && !helper->ffs->interfaces_count) diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index 5f8139b8e601..89b48bcc377a 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -50,12 +50,12 @@ struct f_hidg { /* recv report */ struct list_head completed_out_req; - spinlock_t spinlock; + spinlock_t read_spinlock; wait_queue_head_t read_queue; unsigned int qlen; /* send report */ - struct mutex lock; + spinlock_t write_spinlock; bool write_pending; wait_queue_head_t write_queue; struct usb_request *req; @@ -258,28 +258,35 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer, if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; - spin_lock_irqsave(&hidg->spinlock, flags); + spin_lock_irqsave(&hidg->read_spinlock, flags); #define READ_COND (!list_empty(&hidg->completed_out_req)) /* wait for at least one buffer to complete */ while (!READ_COND) { - spin_unlock_irqrestore(&hidg->spinlock, flags); + spin_unlock_irqrestore(&hidg->read_spinlock, flags); if (file->f_flags & O_NONBLOCK) return -EAGAIN; if (wait_event_interruptible(hidg->read_queue, READ_COND)) return -ERESTARTSYS; - spin_lock_irqsave(&hidg->spinlock, flags); + spin_lock_irqsave(&hidg->read_spinlock, flags); } /* pick the first one */ list = list_first_entry(&hidg->completed_out_req, struct f_hidg_req_list, list); + + /* + * Remove this from list to protect it from beign free() + * while host disables our function + */ + list_del(&list->list); + req = list->req; count = min_t(unsigned int, count, req->actual - list->pos); - spin_unlock_irqrestore(&hidg->spinlock, flags); + spin_unlock_irqrestore(&hidg->read_spinlock, flags); /* copy to user outside spinlock */ count -= copy_to_user(buffer, req->buf + list->pos, count); @@ -292,15 +299,20 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer, * call, taking into account its current read position. */ if (list->pos == req->actual) { - spin_lock_irqsave(&hidg->spinlock, flags); - list_del(&list->list); kfree(list); - spin_unlock_irqrestore(&hidg->spinlock, flags); req->length = hidg->report_length; ret = usb_ep_queue(hidg->out_ep, req, GFP_KERNEL); - if (ret < 0) + if (ret < 0) { + free_ep_req(hidg->out_ep, req); return ret; + } + } else { + spin_lock_irqsave(&hidg->read_spinlock, flags); + list_add(&list->list, &hidg->completed_out_req); + spin_unlock_irqrestore(&hidg->read_spinlock, flags); + + wake_up(&hidg->read_queue); } return count; @@ -309,13 +321,16 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer, static void f_hidg_req_complete(struct usb_ep *ep, struct usb_request *req) { struct f_hidg *hidg = (struct f_hidg *)ep->driver_data; + unsigned long flags; if (req->status != 0) { ERROR(hidg->func.config->cdev, "End Point Request ERROR: %d\n", req->status); } + spin_lock_irqsave(&hidg->write_spinlock, flags); hidg->write_pending = 0; + spin_unlock_irqrestore(&hidg->write_spinlock, flags); wake_up(&hidg->write_queue); } @@ -323,18 +338,20 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, size_t count, loff_t *offp) { struct f_hidg *hidg = file->private_data; + struct usb_request *req; + unsigned long flags; ssize_t status = -ENOMEM; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; - mutex_lock(&hidg->lock); + spin_lock_irqsave(&hidg->write_spinlock, flags); #define WRITE_COND (!hidg->write_pending) - +try_again: /* write queue */ while (!WRITE_COND) { - mutex_unlock(&hidg->lock); + spin_unlock_irqrestore(&hidg->write_spinlock, flags); if (file->f_flags & O_NONBLOCK) return -EAGAIN; @@ -342,37 +359,59 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, hidg->write_queue, WRITE_COND)) return -ERESTARTSYS; - mutex_lock(&hidg->lock); + spin_lock_irqsave(&hidg->write_spinlock, flags); } + hidg->write_pending = 1; + req = hidg->req; count = min_t(unsigned, count, hidg->report_length); + + spin_unlock_irqrestore(&hidg->write_spinlock, flags); status = copy_from_user(hidg->req->buf, buffer, count); if (status != 0) { ERROR(hidg->func.config->cdev, "copy_from_user error\n"); - mutex_unlock(&hidg->lock); - return -EINVAL; + status = -EINVAL; + goto release_write_pending; } - hidg->req->status = 0; - hidg->req->zero = 0; - hidg->req->length = count; - hidg->req->complete = f_hidg_req_complete; - hidg->req->context = hidg; - hidg->write_pending = 1; + spin_lock_irqsave(&hidg->write_spinlock, flags); + + /* we our function has been disabled by host */ + if (!hidg->req) { + free_ep_req(hidg->in_ep, hidg->req); + /* + * TODO + * Should we fail with error here? + */ + goto try_again; + } + + req->status = 0; + req->zero = 0; + req->length = count; + req->complete = f_hidg_req_complete; + req->context = hidg; status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC); if (status < 0) { ERROR(hidg->func.config->cdev, "usb_ep_queue error on int endpoint %zd\n", status); - hidg->write_pending = 0; - wake_up(&hidg->write_queue); + goto release_write_pending_unlocked; } else { status = count; } + spin_unlock_irqrestore(&hidg->write_spinlock, flags); - mutex_unlock(&hidg->lock); + return status; +release_write_pending: + spin_lock_irqsave(&hidg->write_spinlock, flags); +release_write_pending_unlocked: + hidg->write_pending = 0; + spin_unlock_irqrestore(&hidg->write_spinlock, flags); + + wake_up(&hidg->write_queue); return status; } @@ -425,20 +464,36 @@ static inline struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep, static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req) { struct f_hidg *hidg = (struct f_hidg *) req->context; + struct usb_composite_dev *cdev = hidg->func.config->cdev; struct f_hidg_req_list *req_list; unsigned long flags; - req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC); - if (!req_list) - return; + switch (req->status) { + case 0: + req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC); + if (!req_list) { + ERROR(cdev, "Unable to allocate mem for req_list\n"); + goto free_req; + } - req_list->req = req; + req_list->req = req; - spin_lock_irqsave(&hidg->spinlock, flags); - list_add_tail(&req_list->list, &hidg->completed_out_req); - spin_unlock_irqrestore(&hidg->spinlock, flags); + spin_lock_irqsave(&hidg->read_spinlock, flags); + list_add_tail(&req_list->list, &hidg->completed_out_req); + spin_unlock_irqrestore(&hidg->read_spinlock, flags); - wake_up(&hidg->read_queue); + wake_up(&hidg->read_queue); + break; + default: + ERROR(cdev, "Set report failed %d\n", req->status); + /* FALLTHROUGH */ + case -ECONNABORTED: /* hardware forced ep reset */ + case -ECONNRESET: /* request dequeued */ + case -ESHUTDOWN: /* disconnect from host */ +free_req: + free_ep_req(ep, req); + return; + } } static int hidg_setup(struct usb_function *f, @@ -544,20 +599,35 @@ static void hidg_disable(struct usb_function *f) { struct f_hidg *hidg = func_to_hidg(f); struct f_hidg_req_list *list, *next; + unsigned long flags; usb_ep_disable(hidg->in_ep); usb_ep_disable(hidg->out_ep); + spin_lock_irqsave(&hidg->read_spinlock, flags); list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) { + free_ep_req(hidg->out_ep, list->req); list_del(&list->list); kfree(list); } + spin_unlock_irqrestore(&hidg->read_spinlock, flags); + + spin_lock_irqsave(&hidg->write_spinlock, flags); + if (!hidg->write_pending) { + free_ep_req(hidg->in_ep, hidg->req); + hidg->write_pending = 1; + } + + hidg->req = NULL; + spin_unlock_irqrestore(&hidg->write_spinlock, flags); } static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct usb_composite_dev *cdev = f->config->cdev; struct f_hidg *hidg = func_to_hidg(f); + struct usb_request *req_in = NULL; + unsigned long flags; int i, status = 0; VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt); @@ -578,6 +648,12 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) goto fail; } hidg->in_ep->driver_data = hidg; + + req_in = hidg_alloc_ep_req(hidg->in_ep, hidg->report_length); + if (!req_in) { + status = -ENOMEM; + goto disable_ep_in; + } } @@ -589,12 +665,12 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) hidg->out_ep); if (status) { ERROR(cdev, "config_ep_by_speed FAILED!\n"); - goto fail; + goto free_req_in; } status = usb_ep_enable(hidg->out_ep); if (status < 0) { ERROR(cdev, "Enable OUT endpoint FAILED!\n"); - goto fail; + goto free_req_in; } hidg->out_ep->driver_data = hidg; @@ -610,17 +686,37 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) req->context = hidg; status = usb_ep_queue(hidg->out_ep, req, GFP_ATOMIC); - if (status) + if (status) { ERROR(cdev, "%s queue req --> %d\n", hidg->out_ep->name, status); + free_ep_req(hidg->out_ep, req); + } } else { - usb_ep_disable(hidg->out_ep); status = -ENOMEM; - goto fail; + goto disable_out_ep; } } } + if (hidg->in_ep != NULL) { + spin_lock_irqsave(&hidg->write_spinlock, flags); + hidg->req = req_in; + hidg->write_pending = 0; + spin_unlock_irqrestore(&hidg->write_spinlock, flags); + + wake_up(&hidg->write_queue); + } + return 0; +disable_out_ep: + usb_ep_disable(hidg->out_ep); +free_req_in: + if (req_in) + free_ep_req(hidg->in_ep, req_in); + +disable_ep_in: + if (hidg->in_ep) + usb_ep_disable(hidg->in_ep); + fail: return status; } @@ -669,12 +765,6 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) goto fail; hidg->out_ep = ep; - /* preallocate request and buffer */ - status = -ENOMEM; - hidg->req = alloc_ep_req(hidg->in_ep, hidg->report_length); - if (!hidg->req) - goto fail; - /* set descriptor dynamic values */ hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass; hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol; @@ -711,8 +801,10 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) if (status) goto fail; - mutex_init(&hidg->lock); - spin_lock_init(&hidg->spinlock); + spin_lock_init(&hidg->write_spinlock); + hidg->write_pending = 1; + hidg->req = NULL; + spin_lock_init(&hidg->read_spinlock); init_waitqueue_head(&hidg->write_queue); init_waitqueue_head(&hidg->read_queue); INIT_LIST_HEAD(&hidg->completed_out_req); @@ -976,10 +1068,6 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f) device_destroy(hidg_class, MKDEV(major, hidg->minor)); cdev_del(&hidg->cdev); - /* disable/free request and end point */ - usb_ep_disable(hidg->in_ep); - free_ep_req(hidg->in_ep, hidg->req); - usb_free_all_descriptors(f); } diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 8054da9276dd..8df244fc9d80 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -49,7 +49,6 @@ #include "u_printer.h" -#define PNP_STRING_LEN 1024 #define PRINTER_MINORS 4 #define GET_DEVICE_ID 0 #define GET_PORT_STATUS 1 @@ -907,8 +906,7 @@ static bool gprinter_req_match(struct usb_function *f, switch (ctrl->bRequest) { case GET_DEVICE_ID: w_index >>= 8; - if (w_length <= PNP_STRING_LEN && - (USB_DIR_IN & ctrl->bRequestType)) + if (USB_DIR_IN & ctrl->bRequestType) break; return false; case GET_PORT_STATUS: @@ -937,6 +935,7 @@ static int printer_func_setup(struct usb_function *f, struct printer_dev *dev = func_to_printer(f); struct usb_composite_dev *cdev = f->config->cdev; struct usb_request *req = cdev->req; + u8 *buf = req->buf; int value = -EOPNOTSUPP; u16 wIndex = le16_to_cpu(ctrl->wIndex); u16 wValue = le16_to_cpu(ctrl->wValue); @@ -953,10 +952,16 @@ static int printer_func_setup(struct usb_function *f, if ((wIndex>>8) != dev->interface) break; - value = (dev->pnp_string[0] << 8) | dev->pnp_string[1]; - memcpy(req->buf, dev->pnp_string, value); + if (!dev->pnp_string) { + value = 0; + break; + } + value = strlen(dev->pnp_string); + buf[0] = (value >> 8) & 0xFF; + buf[1] = value & 0xFF; + memcpy(buf + 2, dev->pnp_string, value); DBG(dev, "1284 PNP String: %x %s\n", value, - &dev->pnp_string[2]); + dev->pnp_string); break; case GET_PORT_STATUS: /* Get Port Status */ @@ -964,7 +969,7 @@ static int printer_func_setup(struct usb_function *f, if (wIndex != dev->interface) break; - *(u8 *)req->buf = dev->printer_status; + buf[0] = dev->printer_status; value = min_t(u16, wLength, 1); break; @@ -1157,10 +1162,21 @@ static ssize_t f_printer_opts_pnp_string_show(struct config_item *item, char *page) { struct f_printer_opts *opts = to_f_printer_opts(item); - int result; + int result = 0; mutex_lock(&opts->lock); - result = strlcpy(page, opts->pnp_string + 2, PNP_STRING_LEN - 2); + if (!opts->pnp_string) + goto unlock; + + result = strlcpy(page, opts->pnp_string, PAGE_SIZE); + if (result >= PAGE_SIZE) { + result = PAGE_SIZE; + } else if (page[result - 1] != '\n' && result + 1 < PAGE_SIZE) { + page[result++] = '\n'; + page[result] = '\0'; + } + +unlock: mutex_unlock(&opts->lock); return result; @@ -1170,13 +1186,24 @@ static ssize_t f_printer_opts_pnp_string_store(struct config_item *item, const char *page, size_t len) { struct f_printer_opts *opts = to_f_printer_opts(item); - int result, l; + char *new_pnp; + int result; mutex_lock(&opts->lock); - result = strlcpy(opts->pnp_string + 2, page, PNP_STRING_LEN - 2); - l = strlen(opts->pnp_string + 2) + 2; - opts->pnp_string[0] = (l >> 8) & 0xFF; - opts->pnp_string[1] = l & 0xFF; + + new_pnp = kstrndup(page, len, GFP_KERNEL); + if (!new_pnp) { + result = -ENOMEM; + goto unlock; + } + + if (opts->pnp_string_allocated) + kfree(opts->pnp_string); + + opts->pnp_string_allocated = true; + opts->pnp_string = new_pnp; + result = len; +unlock: mutex_unlock(&opts->lock); return result; @@ -1270,6 +1297,8 @@ static void gprinter_free_inst(struct usb_function_instance *f) mutex_unlock(&printer_ida_lock); + if (opts->pnp_string_allocated) + kfree(opts->pnp_string); kfree(opts); } diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 969cfe741380..f6a0d3a1311b 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -22,9 +22,6 @@ #include "u_uac2.h" -/* Keep everyone on toes */ -#define USB_XFERS 2 - /* * The driver implements a simple UAC_2 topology. * USB-OUT -> IT_1 -> OT_3 -> ALSA_Capture @@ -78,7 +75,7 @@ struct uac2_rtd_params { size_t period_size; unsigned max_psize; - struct uac2_req ureq[USB_XFERS]; + struct uac2_req *ureq; spinlock_t lock; }; @@ -269,6 +266,8 @@ static int uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream); + struct audio_dev *agdev = uac2_to_agdev(uac2); + struct f_uac2_opts *uac2_opts = agdev_to_uac2_opts(agdev); struct uac2_rtd_params *prm; unsigned long flags; int err = 0; @@ -300,7 +299,7 @@ uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd) /* Clear buffer after Play stops */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !prm->ss) - memset(prm->rbuf, 0, prm->max_psize * USB_XFERS); + memset(prm->rbuf, 0, prm->max_psize * uac2_opts->req_number); return err; } @@ -943,6 +942,8 @@ static inline void free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep) { struct snd_uac2_chip *uac2 = prm->uac2; + struct audio_dev *agdev = uac2_to_agdev(uac2); + struct f_uac2_opts *uac2_opts = agdev_to_uac2_opts(agdev); int i; if (!prm->ep_enabled) @@ -950,7 +951,7 @@ free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep) prm->ep_enabled = false; - for (i = 0; i < USB_XFERS; i++) { + for (i = 0; i < uac2_opts->req_number; i++) { if (prm->ureq[i].req) { usb_ep_dequeue(ep, prm->ureq[i].req); usb_ep_free_request(ep, prm->ureq[i].req); @@ -1095,31 +1096,47 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) prm = &agdev->uac2.c_prm; prm->max_psize = hs_epout_desc.wMaxPacketSize; - prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); + prm->ureq = kcalloc(uac2_opts->req_number, sizeof(struct uac2_req), + GFP_KERNEL); + if (!prm->ureq) { + ret = -ENOMEM; + goto err_free_descs; + } + prm->rbuf = kcalloc(uac2_opts->req_number, prm->max_psize, GFP_KERNEL); if (!prm->rbuf) { prm->max_psize = 0; + ret = -ENOMEM; goto err_free_descs; } prm = &agdev->uac2.p_prm; prm->max_psize = hs_epin_desc.wMaxPacketSize; - prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); + prm->ureq = kcalloc(uac2_opts->req_number, sizeof(struct uac2_req), + GFP_KERNEL); + if (!prm->ureq) { + ret = -ENOMEM; + goto err_free_descs; + } + prm->rbuf = kcalloc(uac2_opts->req_number, prm->max_psize, GFP_KERNEL); if (!prm->rbuf) { prm->max_psize = 0; - goto err; + ret = -ENOMEM; + goto err_no_memory; } ret = alsa_uac2_init(agdev); if (ret) - goto err; + goto err_no_memory; return 0; -err: +err_no_memory: + kfree(agdev->uac2.p_prm.ureq); + kfree(agdev->uac2.c_prm.ureq); kfree(agdev->uac2.p_prm.rbuf); kfree(agdev->uac2.c_prm.rbuf); err_free_descs: usb_free_all_descriptors(fn); - return -EINVAL; + return ret; } static int @@ -1127,6 +1144,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) { struct usb_composite_dev *cdev = fn->config->cdev; struct audio_dev *agdev = func_to_agdev(fn); + struct f_uac2_opts *opts = agdev_to_uac2_opts(agdev); struct snd_uac2_chip *uac2 = &agdev->uac2; struct usb_gadget *gadget = cdev->gadget; struct device *dev = &uac2->pdev.dev; @@ -1157,7 +1175,6 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) agdev->as_out_alt = alt; req_len = prm->max_psize; } else if (intf == agdev->as_in_intf) { - struct f_uac2_opts *opts = agdev_to_uac2_opts(agdev); unsigned int factor, rate; struct usb_endpoint_descriptor *ep_desc; @@ -1203,7 +1220,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) prm->ep_enabled = true; usb_ep_enable(ep); - for (i = 0; i < USB_XFERS; i++) { + for (i = 0; i < opts->req_number; i++) { if (!prm->ureq[i].req) { req = usb_ep_alloc_request(ep, GFP_ATOMIC); if (req == NULL) @@ -1487,6 +1504,7 @@ UAC2_ATTRIBUTE(p_ssize); UAC2_ATTRIBUTE(c_chmask); UAC2_ATTRIBUTE(c_srate); UAC2_ATTRIBUTE(c_ssize); +UAC2_ATTRIBUTE(req_number); static struct configfs_attribute *f_uac2_attrs[] = { &f_uac2_opts_attr_p_chmask, @@ -1495,6 +1513,7 @@ static struct configfs_attribute *f_uac2_attrs[] = { &f_uac2_opts_attr_c_chmask, &f_uac2_opts_attr_c_srate, &f_uac2_opts_attr_c_ssize, + &f_uac2_opts_attr_req_number, NULL, }; @@ -1532,6 +1551,7 @@ static struct usb_function_instance *afunc_alloc_inst(void) opts->c_chmask = UAC2_DEF_CCHMASK; opts->c_srate = UAC2_DEF_CSRATE; opts->c_ssize = UAC2_DEF_CSSIZE; + opts->req_number = UAC2_DEF_REQ_NUM; return &opts->func_inst; } @@ -1560,6 +1580,7 @@ static void afunc_unbind(struct usb_configuration *c, struct usb_function *f) prm = &agdev->uac2.c_prm; kfree(prm->rbuf); + kfree(prm->ureq); usb_free_all_descriptors(f); } diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index b4e5d6dfd549..c3cab77181d4 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c @@ -913,9 +913,16 @@ EXPORT_SYMBOL_GPL(gether_set_dev_addr); int gether_get_dev_addr(struct net_device *net, char *dev_addr, int len) { struct eth_dev *dev; + int ret; dev = netdev_priv(net); - return get_ether_addr_str(dev->dev_mac, dev_addr, len); + ret = get_ether_addr_str(dev->dev_mac, dev_addr, len); + if (ret + 1 < len) { + dev_addr[ret++] = '\n'; + dev_addr[ret] = '\0'; + } + + return ret; } EXPORT_SYMBOL_GPL(gether_get_dev_addr); @@ -935,9 +942,16 @@ EXPORT_SYMBOL_GPL(gether_set_host_addr); int gether_get_host_addr(struct net_device *net, char *host_addr, int len) { struct eth_dev *dev; + int ret; dev = netdev_priv(net); - return get_ether_addr_str(dev->host_mac, host_addr, len); + ret = get_ether_addr_str(dev->host_mac, host_addr, len); + if (ret + 1 < len) { + host_addr[ret++] = '\n'; + host_addr[ret] = '\0'; + } + + return ret; } EXPORT_SYMBOL_GPL(gether_get_host_addr); @@ -984,10 +998,12 @@ EXPORT_SYMBOL_GPL(gether_get_qmult); int gether_get_ifname(struct net_device *net, char *name, int len) { + int ret; + rtnl_lock(); - strlcpy(name, netdev_name(net), len); + ret = snprintf(name, len, "%s\n", netdev_name(net)); rtnl_unlock(); - return strlen(name); + return ret < len ? ret : len; } EXPORT_SYMBOL_GPL(gether_get_ifname); diff --git a/drivers/usb/gadget/function/u_ether_configfs.h b/drivers/usb/gadget/function/u_ether_configfs.h index 4f47289fcf7c..c71133de17e7 100644 --- a/drivers/usb/gadget/function/u_ether_configfs.h +++ b/drivers/usb/gadget/function/u_ether_configfs.h @@ -108,7 +108,7 @@ mutex_lock(&opts->lock); \ qmult = gether_get_qmult(opts->net); \ mutex_unlock(&opts->lock); \ - return sprintf(page, "%d", qmult); \ + return sprintf(page, "%d\n", qmult); \ } \ \ static ssize_t _f_##_opts_qmult_store(struct config_item *item, \ diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h index 60139854e0b1..4b6969451cdc 100644 --- a/drivers/usb/gadget/function/u_fs.h +++ b/drivers/usb/gadget/function/u_fs.h @@ -247,7 +247,8 @@ struct ffs_data { unsigned user_flags; - u8 eps_addrmap[15]; +#define FFS_MAX_EPS_COUNT 31 + u8 eps_addrmap[FFS_MAX_EPS_COUNT]; unsigned short strings_count; unsigned short interfaces_count; diff --git a/drivers/usb/gadget/function/u_printer.h b/drivers/usb/gadget/function/u_printer.h index 0e2c49d4274e..8d30b7577f87 100644 --- a/drivers/usb/gadget/function/u_printer.h +++ b/drivers/usb/gadget/function/u_printer.h @@ -18,12 +18,11 @@ #include <linux/usb/composite.h> -#define PNP_STRING_LEN 1024 - struct f_printer_opts { struct usb_function_instance func_inst; int minor; - char pnp_string[PNP_STRING_LEN]; + char *pnp_string; + bool pnp_string_allocated; unsigned q_len; /* diff --git a/drivers/usb/gadget/function/u_uac2.h b/drivers/usb/gadget/function/u_uac2.h index 78dd37279bd4..19eeb83538a5 100644 --- a/drivers/usb/gadget/function/u_uac2.h +++ b/drivers/usb/gadget/function/u_uac2.h @@ -24,6 +24,7 @@ #define UAC2_DEF_CCHMASK 0x3 #define UAC2_DEF_CSRATE 64000 #define UAC2_DEF_CSSIZE 2 +#define UAC2_DEF_REQ_NUM 2 struct f_uac2_opts { struct usb_function_instance func_inst; @@ -33,6 +34,7 @@ struct f_uac2_opts { int c_chmask; int c_srate; int c_ssize; + int req_number; bool bound; struct mutex lock; diff --git a/drivers/usb/gadget/legacy/audio.c b/drivers/usb/gadget/legacy/audio.c index 5d7b3c6a422b..8a39f42a4d56 100644 --- a/drivers/usb/gadget/legacy/audio.c +++ b/drivers/usb/gadget/legacy/audio.c @@ -229,6 +229,7 @@ static int audio_bind(struct usb_composite_dev *cdev) uac2_opts->c_chmask = c_chmask; uac2_opts->c_srate = c_srate; uac2_opts->c_ssize = c_ssize; + uac2_opts->req_number = UAC2_DEF_REQ_NUM; #else uac1_opts = container_of(fi_uac1, struct f_uac1_opts, func_inst); uac1_opts->fn_play = fn_play; diff --git a/drivers/usb/gadget/legacy/printer.c b/drivers/usb/gadget/legacy/printer.c index 6f969a86175c..4c9cfff34a03 100644 --- a/drivers/usb/gadget/legacy/printer.c +++ b/drivers/usb/gadget/legacy/printer.c @@ -88,8 +88,8 @@ static const struct usb_descriptor_header *otg_desc[2]; static char product_desc [40] = DRIVER_DESC; static char serial_num [40] = "1"; -static char pnp_string[PNP_STRING_LEN] = - "XXMFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;"; +static char *pnp_string = + "MFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;"; /* static strings, in UTF-8 */ static struct usb_string strings [] = { @@ -143,23 +143,29 @@ static int printer_do_config(struct usb_configuration *c) static int printer_bind(struct usb_composite_dev *cdev) { struct f_printer_opts *opts; - int ret, len; + int ret; fi_printer = usb_get_function_instance("printer"); if (IS_ERR(fi_printer)) return PTR_ERR(fi_printer); - if (iPNPstring) - strlcpy(&pnp_string[2], iPNPstring, PNP_STRING_LEN - 2); - - len = strlen(pnp_string); - pnp_string[0] = (len >> 8) & 0xFF; - pnp_string[1] = len & 0xFF; - opts = container_of(fi_printer, struct f_printer_opts, func_inst); opts->minor = 0; - memcpy(opts->pnp_string, pnp_string, PNP_STRING_LEN); opts->q_len = QLEN; + if (iPNPstring) { + opts->pnp_string = kstrdup(iPNPstring, GFP_KERNEL); + if (!opts->pnp_string) { + ret = -ENOMEM; + goto fail_put_func_inst; + } + opts->pnp_string_allocated = true; + /* + * we don't free this memory in case of error + * as printer cleanup func will do this for us + */ + } else { + opts->pnp_string = pnp_string; + } ret = usb_string_ids_tab(cdev, strings); if (ret < 0) diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index 658b8da60915..4b69f28a9af9 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig @@ -60,6 +60,20 @@ config USB_ATMEL_USBA USBA is the integrated high-speed USB Device controller on the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel. + The fifo_mode parameter is used to select endpoint allocation mode. + fifo_mode = 0 is used to let the driver autoconfigure the endpoints. + In this case 2 banks are allocated for isochronous endpoints and + only one bank is allocated for the rest of the endpoints. + + fifo_mode = 1 is a generic maximum fifo size (1024 bytes) configuration + allowing the usage of ep1 - ep6 + + fifo_mode = 2 is a generic performance maximum fifo size (1024 bytes) + configuration allowing the usage of ep1 - ep3 + + fifo_mode = 3 is a balanced performance configuration allowing the + the usage of ep1 - ep8 + config USB_BCM63XX_UDC tristate "Broadcom BCM63xx Peripheral Controller" depends on BCM63XX diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 12c7687216e6..11bbce28bc23 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -20,6 +20,7 @@ #include <linux/mfd/syscon.h> #include <linux/platform_device.h> #include <linux/regmap.h> +#include <linux/ctype.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> #include <linux/usb/atmel_usba_udc.h> @@ -318,6 +319,91 @@ static inline void usba_cleanup_debugfs(struct usba_udc *udc) } #endif +static ushort fifo_mode; + +/* "modprobe ... fifo_mode=1" etc */ +module_param(fifo_mode, ushort, 0x0); +MODULE_PARM_DESC(fifo_mode, "Endpoint configuration mode"); + +/* mode 0 - uses autoconfig */ + +/* mode 1 - fits in 8KB, generic max fifo configuration */ +static struct usba_fifo_cfg mode_1_cfg[] = { +{ .hw_ep_num = 0, .fifo_size = 64, .nr_banks = 1, }, +{ .hw_ep_num = 1, .fifo_size = 1024, .nr_banks = 2, }, +{ .hw_ep_num = 2, .fifo_size = 1024, .nr_banks = 1, }, +{ .hw_ep_num = 3, .fifo_size = 1024, .nr_banks = 1, }, +{ .hw_ep_num = 4, .fifo_size = 1024, .nr_banks = 1, }, +{ .hw_ep_num = 5, .fifo_size = 1024, .nr_banks = 1, }, +{ .hw_ep_num = 6, .fifo_size = 1024, .nr_banks = 1, }, +}; + +/* mode 2 - fits in 8KB, performance max fifo configuration */ +static struct usba_fifo_cfg mode_2_cfg[] = { +{ .hw_ep_num = 0, .fifo_size = 64, .nr_banks = 1, }, +{ .hw_ep_num = 1, .fifo_size = 1024, .nr_banks = 3, }, +{ .hw_ep_num = 2, .fifo_size = 1024, .nr_banks = 2, }, +{ .hw_ep_num = 3, .fifo_size = 1024, .nr_banks = 2, }, +}; + +/* mode 3 - fits in 8KB, mixed fifo configuration */ +static struct usba_fifo_cfg mode_3_cfg[] = { +{ .hw_ep_num = 0, .fifo_size = 64, .nr_banks = 1, }, +{ .hw_ep_num = 1, .fifo_size = 1024, .nr_banks = 2, }, +{ .hw_ep_num = 2, .fifo_size = 512, .nr_banks = 2, }, +{ .hw_ep_num = 3, .fifo_size = 512, .nr_banks = 2, }, +{ .hw_ep_num = 4, .fifo_size = 512, .nr_banks = 2, }, +{ .hw_ep_num = 5, .fifo_size = 512, .nr_banks = 2, }, +{ .hw_ep_num = 6, .fifo_size = 512, .nr_banks = 2, }, +}; + +/* mode 4 - fits in 8KB, custom fifo configuration */ +static struct usba_fifo_cfg mode_4_cfg[] = { +{ .hw_ep_num = 0, .fifo_size = 64, .nr_banks = 1, }, +{ .hw_ep_num = 1, .fifo_size = 512, .nr_banks = 2, }, +{ .hw_ep_num = 2, .fifo_size = 512, .nr_banks = 2, }, +{ .hw_ep_num = 3, .fifo_size = 8, .nr_banks = 2, }, +{ .hw_ep_num = 4, .fifo_size = 512, .nr_banks = 2, }, +{ .hw_ep_num = 5, .fifo_size = 512, .nr_banks = 2, }, +{ .hw_ep_num = 6, .fifo_size = 16, .nr_banks = 2, }, +{ .hw_ep_num = 7, .fifo_size = 8, .nr_banks = 2, }, +{ .hw_ep_num = 8, .fifo_size = 8, .nr_banks = 2, }, +}; +/* Add additional configurations here */ + +int usba_config_fifo_table(struct usba_udc *udc) +{ + int n; + + switch (fifo_mode) { + default: + fifo_mode = 0; + case 0: + udc->fifo_cfg = NULL; + n = 0; + break; + case 1: + udc->fifo_cfg = mode_1_cfg; + n = ARRAY_SIZE(mode_1_cfg); + break; + case 2: + udc->fifo_cfg = mode_2_cfg; + n = ARRAY_SIZE(mode_2_cfg); + break; + case 3: + udc->fifo_cfg = mode_3_cfg; + n = ARRAY_SIZE(mode_3_cfg); + break; + case 4: + udc->fifo_cfg = mode_4_cfg; + n = ARRAY_SIZE(mode_4_cfg); + break; + } + DBG(DBG_HW, "Setup fifo_mode %d\n", fifo_mode); + + return n; +} + static inline u32 usba_int_enb_get(struct usba_udc *udc) { return udc->int_enb_cache; @@ -543,24 +629,17 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) ep->is_isoc = 0; ep->is_in = 0; - if (maxpacket <= 8) - ept_cfg = USBA_BF(EPT_SIZE, USBA_EPT_SIZE_8); - else - /* LSB is bit 1, not 0 */ - ept_cfg = USBA_BF(EPT_SIZE, fls(maxpacket - 1) - 3); - - DBG(DBG_HW, "%s: EPT_SIZE = %lu (maxpacket = %lu)\n", + DBG(DBG_ERR, "%s: EPT_CFG = 0x%lx (maxpacket = %lu)\n", ep->ep.name, ept_cfg, maxpacket); if (usb_endpoint_dir_in(desc)) { ep->is_in = 1; - ept_cfg |= USBA_EPT_DIR_IN; + ep->ept_cfg |= USBA_EPT_DIR_IN; } switch (usb_endpoint_type(desc)) { case USB_ENDPOINT_XFER_CONTROL: - ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL); - ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE); + ep->ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL); break; case USB_ENDPOINT_XFER_ISOC: if (!ep->can_isoc) { @@ -578,24 +657,15 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) return -EINVAL; ep->is_isoc = 1; - ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_ISO); + ep->ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_ISO); + ep->ept_cfg |= USBA_BF(NB_TRANS, nr_trans); - /* - * Do triple-buffering on high-bandwidth iso endpoints. - */ - if (nr_trans > 1 && ep->nr_banks == 3) - ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_TRIPLE); - else - ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE); - ept_cfg |= USBA_BF(NB_TRANS, nr_trans); break; case USB_ENDPOINT_XFER_BULK: - ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK); - ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE); + ep->ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK); break; case USB_ENDPOINT_XFER_INT: - ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_INT); - ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE); + ep->ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_INT); break; } @@ -604,7 +674,7 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) ep->ep.desc = desc; ep->ep.maxpacket = maxpacket; - usba_ep_writel(ep, CFG, ept_cfg); + usba_ep_writel(ep, CFG, ep->ept_cfg); usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE); if (ep->can_dma) { @@ -1006,12 +1076,81 @@ static int atmel_usba_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver); static int atmel_usba_stop(struct usb_gadget *gadget); +static struct usb_ep *atmel_usba_match_ep( + struct usb_gadget *gadget, + struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *ep_comp +) +{ + struct usb_ep *_ep; + struct usba_ep *ep; + + /* Look at endpoints until an unclaimed one looks usable */ + list_for_each_entry(_ep, &gadget->ep_list, ep_list) { + if (usb_gadget_ep_match_desc(gadget, _ep, desc, ep_comp)) + goto found_ep; + } + /* Fail */ + return NULL; + +found_ep: + + if (fifo_mode == 0) { + /* Optimize hw fifo size based on ep type and other info */ + ep = to_usba_ep(_ep); + + switch (usb_endpoint_type(desc)) { + + case USB_ENDPOINT_XFER_CONTROL: + break; + + case USB_ENDPOINT_XFER_ISOC: + ep->fifo_size = 1024; + ep->nr_banks = 2; + break; + + case USB_ENDPOINT_XFER_BULK: + ep->fifo_size = 512; + ep->nr_banks = 1; + break; + + case USB_ENDPOINT_XFER_INT: + if (desc->wMaxPacketSize == 0) + ep->fifo_size = + roundup_pow_of_two(_ep->maxpacket_limit); + else + ep->fifo_size = + roundup_pow_of_two(le16_to_cpu(desc->wMaxPacketSize)); + ep->nr_banks = 1; + break; + } + + /* It might be a little bit late to set this */ + usb_ep_set_maxpacket_limit(&ep->ep, ep->fifo_size); + + /* Generate ept_cfg basd on FIFO size and number of banks */ + if (ep->fifo_size <= 8) + ep->ept_cfg = USBA_BF(EPT_SIZE, USBA_EPT_SIZE_8); + else + /* LSB is bit 1, not 0 */ + ep->ept_cfg = + USBA_BF(EPT_SIZE, fls(ep->fifo_size - 1) - 3); + + ep->ept_cfg |= USBA_BF(BK_NUMBER, ep->nr_banks); + + ep->udc->configured_ep++; + } + +return _ep; +} + static const struct usb_gadget_ops usba_udc_ops = { .get_frame = usba_udc_get_frame, .wakeup = usba_udc_wakeup, .set_selfpowered = usba_udc_set_selfpowered, .udc_start = atmel_usba_start, .udc_stop = atmel_usba_stop, + .match_ep = atmel_usba_match_ep, }; static struct usb_endpoint_descriptor usba_ep0_desc = { @@ -1678,7 +1817,8 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) } if (status & USBA_END_OF_RESET) { - struct usba_ep *ep0; + struct usba_ep *ep0, *ep; + int i, n; usba_writel(udc, INT_CLR, USBA_END_OF_RESET); generate_bias_pulse(udc); @@ -1717,6 +1857,16 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED)) dev_dbg(&udc->pdev->dev, "ODD: EP0 configuration is invalid!\n"); + + /* Preallocate other endpoints */ + n = fifo_mode ? udc->num_ep : udc->configured_ep; + for (i = 1; i < n; i++) { + ep = &udc->usba_ep[i]; + usba_ep_writel(ep, CFG, ep->ept_cfg); + if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) + dev_dbg(&udc->pdev->dev, + "ODD: EP%d configuration is invalid!\n", i); + } } spin_unlock(&udc->lock); @@ -1864,6 +2014,9 @@ static int atmel_usba_stop(struct usb_gadget *gadget) if (gpio_is_valid(udc->vbus_pin)) disable_irq(gpio_to_irq(udc->vbus_pin)); + if (fifo_mode == 0) + udc->configured_ep = 1; + usba_stop(udc); udc->driver = NULL; @@ -1931,9 +2084,13 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, &flags); udc->vbus_pin_inverted = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0; - pp = NULL; - while ((pp = of_get_next_child(np, pp))) - udc->num_ep++; + if (fifo_mode == 0) { + pp = NULL; + while ((pp = of_get_next_child(np, pp))) + udc->num_ep++; + udc->configured_ep = 1; + } else + udc->num_ep = usba_config_fifo_table(udc); eps = devm_kzalloc(&pdev->dev, sizeof(struct usba_ep) * udc->num_ep, GFP_KERNEL); @@ -1946,7 +2103,7 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, pp = NULL; i = 0; - while ((pp = of_get_next_child(np, pp))) { + while ((pp = of_get_next_child(np, pp)) && i < udc->num_ep) { ep = &eps[i]; ret = of_property_read_u32(pp, "reg", &val); @@ -1954,21 +2111,21 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, dev_err(&pdev->dev, "of_probe: reg error(%d)\n", ret); goto err; } - ep->index = val; + ep->index = fifo_mode ? udc->fifo_cfg[i].hw_ep_num : val; ret = of_property_read_u32(pp, "atmel,fifo-size", &val); if (ret) { dev_err(&pdev->dev, "of_probe: fifo-size error(%d)\n", ret); goto err; } - ep->fifo_size = val; + ep->fifo_size = fifo_mode ? udc->fifo_cfg[i].fifo_size : val; ret = of_property_read_u32(pp, "atmel,nb-banks", &val); if (ret) { dev_err(&pdev->dev, "of_probe: nb-banks error(%d)\n", ret); goto err; } - ep->nr_banks = val; + ep->nr_banks = fifo_mode ? udc->fifo_cfg[i].nr_banks : val; ep->can_dma = of_property_read_bool(pp, "atmel,can-dma"); ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc"); @@ -2000,6 +2157,21 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, ep->ep.caps.dir_in = true; ep->ep.caps.dir_out = true; + if (fifo_mode != 0) { + /* + * Generate ept_cfg based on FIFO size and + * banks number + */ + if (ep->fifo_size <= 8) + ep->ept_cfg = USBA_BF(EPT_SIZE, USBA_EPT_SIZE_8); + else + /* LSB is bit 1, not 0 */ + ep->ept_cfg = + USBA_BF(EPT_SIZE, fls(ep->fifo_size - 1) - 3); + + ep->ept_cfg |= USBA_BF(BK_NUMBER, ep->nr_banks); + } + if (i) list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.h b/drivers/usb/gadget/udc/atmel_usba_udc.h index b03b2ebfc53a..9551b704bfd3 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.h +++ b/drivers/usb/gadget/udc/atmel_usba_udc.h @@ -275,6 +275,12 @@ struct usba_dma_desc { u32 ctrl; }; +struct usba_fifo_cfg { + u8 hw_ep_num; + u16 fifo_size; + u8 nr_banks; +}; + struct usba_ep { int state; void __iomem *ep_regs; @@ -293,7 +299,7 @@ struct usba_ep { unsigned int can_isoc:1; unsigned int is_isoc:1; unsigned int is_in:1; - + unsigned long ept_cfg; #ifdef CONFIG_USB_GADGET_DEBUG_FS u32 last_dma_status; struct dentry *debugfs_dir; @@ -338,6 +344,8 @@ struct usba_udc { int vbus_pin; int vbus_pin_inverted; int num_ep; + int configured_ep; + struct usba_fifo_cfg *fifo_cfg; struct clk *pclk; struct clk *hclk; struct usba_ep *usba_ep; diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 0402177f93cd..d685d82dcf48 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -1080,6 +1080,24 @@ static void usb_udc_nop_release(struct device *dev) dev_vdbg(dev, "%s\n", __func__); } +/* should be called with udc_lock held */ +static int check_pending_gadget_drivers(struct usb_udc *udc) +{ + struct usb_gadget_driver *driver; + int ret = 0; + + list_for_each_entry(driver, &gadget_driver_pending_list, pending) + if (!driver->udc_name || strcmp(driver->udc_name, + dev_name(&udc->dev)) == 0) { + ret = udc_bind_to_driver(udc, driver); + if (ret != -EPROBE_DEFER) + list_del(&driver->pending); + break; + } + + return ret; +} + /** * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list * @parent: the parent device to this udc. Usually the controller driver's @@ -1093,7 +1111,6 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, void (*release)(struct device *dev)) { struct usb_udc *udc; - struct usb_gadget_driver *driver; int ret = -ENOMEM; udc = kzalloc(sizeof(*udc), GFP_KERNEL); @@ -1136,17 +1153,9 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, udc->vbus = true; /* pick up one of pending gadget drivers */ - list_for_each_entry(driver, &gadget_driver_pending_list, pending) { - if (!driver->udc_name || strcmp(driver->udc_name, - dev_name(&udc->dev)) == 0) { - ret = udc_bind_to_driver(udc, driver); - if (ret != -EPROBE_DEFER) - list_del(&driver->pending); - if (ret) - goto err5; - break; - } - } + ret = check_pending_gadget_drivers(udc); + if (ret) + goto err5; mutex_unlock(&udc_lock); @@ -1356,14 +1365,22 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) return -EINVAL; mutex_lock(&udc_lock); - list_for_each_entry(udc, &udc_list, list) + list_for_each_entry(udc, &udc_list, list) { if (udc->driver == driver) { usb_gadget_remove_driver(udc); usb_gadget_set_state(udc->gadget, - USB_STATE_NOTATTACHED); + USB_STATE_NOTATTACHED); + + /* Maybe there is someone waiting for this UDC? */ + check_pending_gadget_drivers(udc); + /* + * For now we ignore bind errors as probably it's + * not a valid reason to fail other's gadget unbind + */ ret = 0; break; } + } if (ret) { list_del(&driver->pending); diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c index f40b3916d274..78d0204e3e20 100644 --- a/drivers/usb/gadget/udc/fotg210-udc.c +++ b/drivers/usb/gadget/udc/fotg210-udc.c @@ -527,7 +527,7 @@ static void fotg210_ep_fifo_flush(struct usb_ep *_ep) { } -static struct usb_ep_ops fotg210_ep_ops = { +static const struct usb_ep_ops fotg210_ep_ops = { .enable = fotg210_ep_enable, .disable = fotg210_ep_disable, diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c index 4fff51b8a18e..303328ce59ee 100644 --- a/drivers/usb/gadget/udc/fsl_qe_udc.c +++ b/drivers/usb/gadget/udc/fsl_qe_udc.c @@ -1847,7 +1847,7 @@ out: return status; } -static struct usb_ep_ops qe_ep_ops = { +static const struct usb_ep_ops qe_ep_ops = { .enable = qe_ep_enable, .disable = qe_ep_disable, diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index 71094e479a96..2e41ef36b944 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c @@ -1118,7 +1118,7 @@ static void fsl_ep_fifo_flush(struct usb_ep *_ep) } while (fsl_readl(&dr_regs->endptstatus) & bits); } -static struct usb_ep_ops fsl_ep_ops = { +static const struct usb_ep_ops fsl_ep_ops = { .enable = fsl_ep_enable, .disable = fsl_ep_disable, @@ -1248,6 +1248,12 @@ static const struct usb_gadget_ops fsl_gadget_ops = { .udc_stop = fsl_udc_stop, }; +/* + * Empty complete function used by this driver to fill in the req->complete + * field when creating a request since the complete field is mandatory. + */ +static void fsl_noop_complete(struct usb_ep *ep, struct usb_request *req) { } + /* Set protocol stall on ep0, protocol stall will automatically be cleared on new transaction */ static void ep0stall(struct fsl_udc *udc) @@ -1282,7 +1288,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction) req->req.length = 0; req->req.status = -EINPROGRESS; req->req.actual = 0; - req->req.complete = NULL; + req->req.complete = fsl_noop_complete; req->dtd_count = 0; ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep)); @@ -1365,7 +1371,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, req->req.length = 2; req->req.status = -EINPROGRESS; req->req.actual = 0; - req->req.complete = NULL; + req->req.complete = fsl_noop_complete; req->dtd_count = 0; ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep)); diff --git a/drivers/usb/gadget/udc/fusb300_udc.c b/drivers/usb/gadget/udc/fusb300_udc.c index 42ff308578df..e0c1b0099265 100644 --- a/drivers/usb/gadget/udc/fusb300_udc.c +++ b/drivers/usb/gadget/udc/fusb300_udc.c @@ -518,7 +518,7 @@ static void fusb300_fifo_flush(struct usb_ep *_ep) { } -static struct usb_ep_ops fusb300_ep_ops = { +static const struct usb_ep_ops fusb300_ep_ops = { .enable = fusb300_enable, .disable = fusb300_disable, diff --git a/drivers/usb/gadget/udc/goku_udc.c b/drivers/usb/gadget/udc/goku_udc.c index 5107987bd353..8433c22900dc 100644 --- a/drivers/usb/gadget/udc/goku_udc.c +++ b/drivers/usb/gadget/udc/goku_udc.c @@ -968,7 +968,7 @@ static void goku_fifo_flush(struct usb_ep *_ep) command(regs, COMMAND_FIFO_CLEAR, ep->num); } -static struct usb_ep_ops goku_ep_ops = { +static const struct usb_ep_ops goku_ep_ops = { .enable = goku_ep_enable, .disable = goku_ep_disable, diff --git a/drivers/usb/gadget/udc/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c index b16f8af34050..1f9941145746 100644 --- a/drivers/usb/gadget/udc/gr_udc.c +++ b/drivers/usb/gadget/udc/gr_udc.c @@ -1841,7 +1841,7 @@ static void gr_fifo_flush(struct usb_ep *_ep) spin_unlock(&ep->dev->lock); } -static struct usb_ep_ops gr_ep_ops = { +static const struct usb_ep_ops gr_ep_ops = { .enable = gr_ep_enable, .disable = gr_ep_disable, diff --git a/drivers/usb/gadget/udc/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c index de3e03483659..46ce7bc15f2b 100644 --- a/drivers/usb/gadget/udc/m66592-udc.c +++ b/drivers/usb/gadget/udc/m66592-udc.c @@ -1436,7 +1436,7 @@ static void m66592_fifo_flush(struct usb_ep *_ep) spin_unlock_irqrestore(&ep->m66592->lock, flags); } -static struct usb_ep_ops m66592_ep_ops = { +static const struct usb_ep_ops m66592_ep_ops = { .enable = m66592_enable, .disable = m66592_disable, diff --git a/drivers/usb/gadget/udc/mv_u3d_core.c b/drivers/usb/gadget/udc/mv_u3d_core.c index 8d726bd767fd..d365449a295a 100644 --- a/drivers/usb/gadget/udc/mv_u3d_core.c +++ b/drivers/usb/gadget/udc/mv_u3d_core.c @@ -995,7 +995,7 @@ static int mv_u3d_ep_set_wedge(struct usb_ep *_ep) return mv_u3d_ep_set_halt_wedge(_ep, 1, 1); } -static struct usb_ep_ops mv_u3d_ep_ops = { +static const struct usb_ep_ops mv_u3d_ep_ops = { .enable = mv_u3d_ep_enable, .disable = mv_u3d_ep_disable, diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c index d82a91bddbd9..27ebb0d5449d 100644 --- a/drivers/usb/gadget/udc/mv_udc_core.c +++ b/drivers/usb/gadget/udc/mv_udc_core.c @@ -946,7 +946,7 @@ static int mv_ep_set_wedge(struct usb_ep *_ep) return mv_ep_set_halt_wedge(_ep, 1, 1); } -static struct usb_ep_ops mv_ep_ops = { +static const struct usb_ep_ops mv_ep_ops = { .enable = mv_ep_enable, .disable = mv_ep_disable, diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c index 078c91d546e0..7dc0102abdfe 100644 --- a/drivers/usb/gadget/udc/net2272.c +++ b/drivers/usb/gadget/udc/net2272.c @@ -181,7 +181,7 @@ static void net2272_dequeue_all(struct net2272_ep *); static int net2272_kick_dma(struct net2272_ep *, struct net2272_request *); static int net2272_fifo_status(struct usb_ep *); -static struct usb_ep_ops net2272_ep_ops; +static const struct usb_ep_ops net2272_ep_ops; /*---------------------------------------------------------------------------*/ @@ -1067,7 +1067,7 @@ net2272_fifo_flush(struct usb_ep *_ep) net2272_ep_write(ep, EP_STAT1, 1 << BUFFER_FLUSH); } -static struct usb_ep_ops net2272_ep_ops = { +static const struct usb_ep_ops net2272_ep_ops = { .enable = net2272_enable, .disable = net2272_disable, diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c index a8709f9e5648..f05ba6825bfe 100644 --- a/drivers/usb/gadget/udc/omap_udc.c +++ b/drivers/usb/gadget/udc/omap_udc.c @@ -1112,7 +1112,7 @@ done: return status; } -static struct usb_ep_ops omap_ep_ops = { +static const struct usb_ep_ops omap_ep_ops = { .enable = omap_ep_enable, .disable = omap_ep_disable, diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c index 7fa60f5b7ae4..e1335ad5bce9 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.c +++ b/drivers/usb/gadget/udc/pxa27x_udc.c @@ -1473,7 +1473,7 @@ static int pxa_ep_disable(struct usb_ep *_ep) return 0; } -static struct usb_ep_ops pxa_ep_ops = { +static const struct usb_ep_ops pxa_ep_ops = { .enable = pxa_ep_enable, .disable = pxa_ep_disable, diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c index f2c8862093a2..118ad70f1af0 100644 --- a/drivers/usb/gadget/udc/r8a66597-udc.c +++ b/drivers/usb/gadget/udc/r8a66597-udc.c @@ -1706,7 +1706,7 @@ static void r8a66597_fifo_flush(struct usb_ep *_ep) spin_unlock_irqrestore(&ep->r8a66597->lock, flags); } -static struct usb_ep_ops r8a66597_ep_ops = { +static const struct usb_ep_ops r8a66597_ep_ops = { .enable = r8a66597_enable, .disable = r8a66597_disable, diff --git a/drivers/usb/gadget/udc/s3c-hsudc.c b/drivers/usb/gadget/udc/s3c-hsudc.c index 82a9e2a3bedc..42587b738a1f 100644 --- a/drivers/usb/gadget/udc/s3c-hsudc.c +++ b/drivers/usb/gadget/udc/s3c-hsudc.c @@ -954,7 +954,7 @@ static int s3c_hsudc_dequeue(struct usb_ep *_ep, struct usb_request *_req) return 0; } -static struct usb_ep_ops s3c_hsudc_ep_ops = { +static const struct usb_ep_ops s3c_hsudc_ep_ops = { .enable = s3c_hsudc_ep_enable, .disable = s3c_hsudc_ep_disable, .alloc_request = s3c_hsudc_alloc_request, diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index a03caf4b1327..61bf2285d5b1 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -1023,38 +1023,6 @@ static void ab8500_usb_vbus_turn_on_event_work(struct work_struct *work) ab->enabled_charging_detection = true; } -static unsigned ab8500_eyediagram_workaroud(struct ab8500_usb *ab, unsigned mA) -{ - /* - * AB8500 V2 has eye diagram issues when drawing more than 100mA from - * VBUS. Set charging current to 100mA in case of standard host - */ - if (is_ab8500_2p0_or_earlier(ab->ab8500)) - if (mA > 100) - mA = 100; - - return mA; -} - -static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA) -{ - struct ab8500_usb *ab; - - if (!phy) - return -ENODEV; - - ab = phy_to_ab(phy); - - mA = ab8500_eyediagram_workaroud(ab, mA); - - ab->vbus_draw = mA; - - atomic_notifier_call_chain(&ab->phy.notifier, - UX500_MUSB_VBUS, &ab->vbus_draw); - - return 0; -} - static int ab8500_usb_set_suspend(struct usb_phy *x, int suspend) { /* TODO */ @@ -1392,7 +1360,6 @@ static int ab8500_usb_probe(struct platform_device *pdev) ab->phy.otg = otg; ab->phy.label = "ab8500"; ab->phy.set_suspend = ab8500_usb_set_suspend; - ab->phy.set_power = ab8500_usb_set_power; ab->phy.otg->state = OTG_STATE_UNDEFINED; otg->usb_phy = &ab->phy; diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c index 94eb2923afed..392ab422163c 100644 --- a/drivers/usb/phy/phy-fsl-usb.c +++ b/drivers/usb/phy/phy-fsl-usb.c @@ -642,17 +642,6 @@ static int fsl_otg_set_peripheral(struct usb_otg *otg, return 0; } -/* Set OTG port power, only for B-device */ -static int fsl_otg_set_power(struct usb_phy *phy, unsigned mA) -{ - if (!fsl_otg_dev) - return -ENODEV; - if (phy->otg->state == OTG_STATE_B_PERIPHERAL) - pr_info("FSL OTG: Draw %d mA\n", mA); - - return 0; -} - /* * Delayed pin detect interrupt processing. * @@ -821,7 +810,6 @@ static int fsl_otg_conf(struct platform_device *pdev) /* initialize the otg structure */ fsl_otg_tc->phy.label = DRIVER_DESC; fsl_otg_tc->phy.dev = &pdev->dev; - fsl_otg_tc->phy.set_power = fsl_otg_set_power; fsl_otg_tc->phy.otg->usb_phy = &fsl_otg_tc->phy; fsl_otg_tc->phy.otg->set_host = fsl_otg_set_host; diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 8a34759727bb..93d9aaad2994 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -842,23 +842,6 @@ static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA) motg->cur_power = mA; } -static int msm_otg_set_power(struct usb_phy *phy, unsigned mA) -{ - struct msm_otg *motg = container_of(phy, struct msm_otg, phy); - - /* - * Gadget driver uses set_power method to notify about the - * available current based on suspend/configured states. - * - * IDEV_CHG can be drawn irrespective of suspend/un-configured - * states when CDP/ACA is connected. - */ - if (motg->chg_type == USB_SDP_CHARGER) - msm_otg_notify_charger(motg, mA); - - return 0; -} - static void msm_otg_start_host(struct usb_phy *phy, int on) { struct msm_otg *motg = container_of(phy, struct msm_otg, phy); @@ -1742,14 +1725,14 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) if (!IS_ERR(ext_vbus)) { motg->vbus.extcon = ext_vbus; motg->vbus.nb.notifier_call = msm_otg_vbus_notifier; - ret = extcon_register_notifier(ext_vbus, EXTCON_USB, - &motg->vbus.nb); + ret = devm_extcon_register_notifier(&pdev->dev, ext_vbus, + EXTCON_USB, &motg->vbus.nb); if (ret < 0) { dev_err(&pdev->dev, "register VBUS notifier failed\n"); return ret; } - ret = extcon_get_cable_state_(ext_vbus, EXTCON_USB); + ret = extcon_get_state(ext_vbus, EXTCON_USB); if (ret) set_bit(B_SESS_VLD, &motg->inputs); else @@ -1759,16 +1742,14 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) if (!IS_ERR(ext_id)) { motg->id.extcon = ext_id; motg->id.nb.notifier_call = msm_otg_id_notifier; - ret = extcon_register_notifier(ext_id, EXTCON_USB_HOST, - &motg->id.nb); + ret = devm_extcon_register_notifier(&pdev->dev, ext_id, + EXTCON_USB_HOST, &motg->id.nb); if (ret < 0) { dev_err(&pdev->dev, "register ID notifier failed\n"); - extcon_unregister_notifier(motg->vbus.extcon, - EXTCON_USB, &motg->vbus.nb); return ret; } - ret = extcon_get_cable_state_(ext_id, EXTCON_USB_HOST); + ret = extcon_get_state(ext_id, EXTCON_USB_HOST); if (ret) clear_bit(ID, &motg->inputs); else @@ -1883,10 +1864,9 @@ static int msm_otg_probe(struct platform_device *pdev) */ if (motg->phy_number) { phy_select = devm_ioremap_nocache(&pdev->dev, USB2_PHY_SEL, 4); - if (!phy_select) { - ret = -ENOMEM; - goto unregister_extcon; - } + if (!phy_select) + return -ENOMEM; + /* Enable second PHY with the OTG port */ writel(0x1, phy_select); } @@ -1897,7 +1877,7 @@ static int msm_otg_probe(struct platform_device *pdev) if (motg->irq < 0) { dev_err(&pdev->dev, "platform_get_irq failed\n"); ret = motg->irq; - goto unregister_extcon; + return motg->irq; } regs[0].supply = "vddcx"; @@ -1906,7 +1886,7 @@ static int msm_otg_probe(struct platform_device *pdev) ret = devm_regulator_bulk_get(motg->phy.dev, ARRAY_SIZE(regs), regs); if (ret) - goto unregister_extcon; + return ret; motg->vddcx = regs[0].consumer; motg->v3p3 = regs[1].consumer; @@ -1950,7 +1930,6 @@ static int msm_otg_probe(struct platform_device *pdev) } phy->init = msm_phy_init; - phy->set_power = msm_otg_set_power; phy->notify_disconnect = msm_phy_notify_disconnect; phy->type = USB_PHY_TYPE_USB2; @@ -2003,11 +1982,6 @@ disable_clks: clk_disable_unprepare(motg->clk); if (!IS_ERR(motg->core_clk)) clk_disable_unprepare(motg->core_clk); -unregister_extcon: - extcon_unregister_notifier(motg->id.extcon, - EXTCON_USB_HOST, &motg->id.nb); - extcon_unregister_notifier(motg->vbus.extcon, - EXTCON_USB, &motg->vbus.nb); return ret; } @@ -2029,9 +2003,6 @@ static int msm_otg_remove(struct platform_device *pdev) */ gpiod_set_value_cansleep(motg->switch_gpio, 0); - extcon_unregister_notifier(motg->id.extcon, EXTCON_USB_HOST, &motg->id.nb); - extcon_unregister_notifier(motg->vbus.extcon, EXTCON_USB, &motg->vbus.nb); - msm_otg_debugfs_cleanup(); cancel_delayed_work_sync(&motg->chg_work); cancel_work_sync(&motg->sm_work); diff --git a/drivers/usb/phy/phy-omap-otg.c b/drivers/usb/phy/phy-omap-otg.c index 6523af4f8f93..800d1d90753d 100644 --- a/drivers/usb/phy/phy-omap-otg.c +++ b/drivers/usb/phy/phy-omap-otg.c @@ -118,19 +118,19 @@ static int omap_otg_probe(struct platform_device *pdev) otg_dev->id_nb.notifier_call = omap_otg_id_notifier; otg_dev->vbus_nb.notifier_call = omap_otg_vbus_notifier; - ret = extcon_register_notifier(extcon, EXTCON_USB_HOST, &otg_dev->id_nb); + ret = devm_extcon_register_notifier(&pdev->dev, extcon, + EXTCON_USB_HOST, &otg_dev->id_nb); if (ret) return ret; - ret = extcon_register_notifier(extcon, EXTCON_USB, &otg_dev->vbus_nb); + ret = devm_extcon_register_notifier(&pdev->dev, extcon, + EXTCON_USB, &otg_dev->vbus_nb); if (ret) { - extcon_unregister_notifier(extcon, EXTCON_USB_HOST, - &otg_dev->id_nb); return ret; } - otg_dev->id = extcon_get_cable_state_(extcon, EXTCON_USB_HOST); - otg_dev->vbus = extcon_get_cable_state_(extcon, EXTCON_USB); + otg_dev->id = extcon_get_state(extcon, EXTCON_USB_HOST); + otg_dev->vbus = extcon_get_state(extcon, EXTCON_USB); omap_otg_set_mode(otg_dev); rev = readl(otg_dev->base); @@ -145,20 +145,8 @@ static int omap_otg_probe(struct platform_device *pdev) return 0; } -static int omap_otg_remove(struct platform_device *pdev) -{ - struct otg_device *otg_dev = platform_get_drvdata(pdev); - struct extcon_dev *edev = otg_dev->extcon; - - extcon_unregister_notifier(edev, EXTCON_USB_HOST, &otg_dev->id_nb); - extcon_unregister_notifier(edev, EXTCON_USB, &otg_dev->vbus_nb); - - return 0; -} - static struct platform_driver omap_otg_driver = { .probe = omap_otg_probe, - .remove = omap_otg_remove, .driver = { .name = "omap_otg", }, diff --git a/drivers/usb/phy/phy-qcom-8x16-usb.c b/drivers/usb/phy/phy-qcom-8x16-usb.c index d8593adb3621..fdf686398772 100644 --- a/drivers/usb/phy/phy-qcom-8x16-usb.c +++ b/drivers/usb/phy/phy-qcom-8x16-usb.c @@ -187,7 +187,7 @@ static int phy_8x16_init(struct usb_phy *phy) val = ULPI_PWR_OTG_COMP_DISABLE; usb_phy_io_write(phy, val, ULPI_SET(ULPI_PWR_CLK_MNG_REG)); - state = extcon_get_cable_state_(qphy->vbus_edev, EXTCON_USB); + state = extcon_get_state(qphy->vbus_edev, EXTCON_USB); if (state) phy_8x16_vbus_on(qphy); else @@ -316,23 +316,20 @@ static int phy_8x16_probe(struct platform_device *pdev) goto off_clks; qphy->vbus_notify.notifier_call = phy_8x16_vbus_notify; - ret = extcon_register_notifier(qphy->vbus_edev, EXTCON_USB, - &qphy->vbus_notify); + ret = devm_extcon_register_notifier(&pdev->dev, qphy->vbus_edev, + EXTCON_USB, &qphy->vbus_notify); if (ret < 0) goto off_power; ret = usb_add_phy_dev(&qphy->phy); if (ret) - goto off_extcon; + goto off_power; qphy->reboot_notify.notifier_call = phy_8x16_reboot_notify; register_reboot_notifier(&qphy->reboot_notify); return 0; -off_extcon: - extcon_unregister_notifier(qphy->vbus_edev, EXTCON_USB, - &qphy->vbus_notify); off_power: regulator_bulk_disable(ARRAY_SIZE(qphy->regulator), qphy->regulator); off_clks: @@ -347,8 +344,6 @@ static int phy_8x16_remove(struct platform_device *pdev) struct phy_8x16 *qphy = platform_get_drvdata(pdev); unregister_reboot_notifier(&qphy->reboot_notify); - extcon_unregister_notifier(qphy->vbus_edev, EXTCON_USB, - &qphy->vbus_notify); /* * Ensure that D+/D- lines are routed to uB connector, so diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c index ab5d364f6e8c..a31c8682e998 100644 --- a/drivers/usb/phy/phy-tahvo.c +++ b/drivers/usb/phy/phy-tahvo.c @@ -121,7 +121,7 @@ static void check_vbus_state(struct tahvo_usb *tu) prev_state = tu->vbus_state; tu->vbus_state = reg & TAHVO_STAT_VBUS; if (prev_state != tu->vbus_state) { - extcon_set_cable_state_(tu->extcon, EXTCON_USB, tu->vbus_state); + extcon_set_state_sync(tu->extcon, EXTCON_USB, tu->vbus_state); sysfs_notify(&tu->pt_dev->dev.kobj, NULL, "vbus_state"); } } @@ -130,7 +130,7 @@ static void tahvo_usb_become_host(struct tahvo_usb *tu) { struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent); - extcon_set_cable_state_(tu->extcon, EXTCON_USB_HOST, true); + extcon_set_state_sync(tu->extcon, EXTCON_USB_HOST, true); /* Power up the transceiver in USB host mode */ retu_write(rdev, TAHVO_REG_USBR, USBR_REGOUT | USBR_NSUSPEND | @@ -149,7 +149,7 @@ static void tahvo_usb_become_peripheral(struct tahvo_usb *tu) { struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent); - extcon_set_cable_state_(tu->extcon, EXTCON_USB_HOST, false); + extcon_set_state_sync(tu->extcon, EXTCON_USB_HOST, false); /* Power up transceiver and set it in USB peripheral mode */ retu_write(rdev, TAHVO_REG_USBR, USBR_SLAVE_CONTROL | USBR_REGOUT | @@ -379,9 +379,9 @@ static int tahvo_usb_probe(struct platform_device *pdev) } /* Set the initial cable state. */ - extcon_set_cable_state_(tu->extcon, EXTCON_USB_HOST, + extcon_set_state_sync(tu->extcon, EXTCON_USB_HOST, tu->tahvo_mode == TAHVO_MODE_HOST); - extcon_set_cable_state_(tu->extcon, EXTCON_USB, tu->vbus_state); + extcon_set_state_sync(tu->extcon, EXTCON_USB, tu->vbus_state); /* Create OTG interface */ tahvo_usb_power_off(tu); diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index 012a37aa3e0d..623c51300393 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -389,7 +389,7 @@ static void usbhsc_hotplug(struct usbhs_priv *priv) if (enable && !mod) { if (priv->edev) { - cable = extcon_get_cable_state_(priv->edev, EXTCON_USB_HOST); + cable = extcon_get_state(priv->edev, EXTCON_USB_HOST); if ((cable > 0 && id != USBHS_HOST) || (!cable && id != USBHS_GADGET)) { dev_info(&pdev->dev, diff --git a/tools/usb/ffs-test.c b/tools/usb/ffs-test.c index 88d5e71be044..95dd14648ba5 100644 --- a/tools/usb/ffs-test.c +++ b/tools/usb/ffs-test.c @@ -22,7 +22,7 @@ /* $(CROSS_COMPILE)cc -Wall -Wextra -g -o ffs-test ffs-test.c -lpthread */ -#define _BSD_SOURCE /* for endian.h */ +#define _DEFAULT_SOURCE /* for endian.h */ #include <endian.h> #include <errno.h> @@ -110,16 +110,25 @@ static const struct { struct usb_functionfs_descs_head_v2 header; __le32 fs_count; __le32 hs_count; + __le32 ss_count; struct { struct usb_interface_descriptor intf; struct usb_endpoint_descriptor_no_audio sink; struct usb_endpoint_descriptor_no_audio source; } __attribute__((packed)) fs_descs, hs_descs; + struct { + struct usb_interface_descriptor intf; + struct usb_endpoint_descriptor_no_audio sink; + struct usb_ss_ep_comp_descriptor sink_comp; + struct usb_endpoint_descriptor_no_audio source; + struct usb_ss_ep_comp_descriptor source_comp; + } ss_descs; } __attribute__((packed)) descriptors = { .header = { .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2), .flags = cpu_to_le32(FUNCTIONFS_HAS_FS_DESC | - FUNCTIONFS_HAS_HS_DESC), + FUNCTIONFS_HAS_HS_DESC | + FUNCTIONFS_HAS_SS_DESC), .length = cpu_to_le32(sizeof descriptors), }, .fs_count = cpu_to_le32(3), @@ -171,6 +180,45 @@ static const struct { .bInterval = 1, /* NAK every 1 uframe */ }, }, + .ss_count = cpu_to_le32(5), + .ss_descs = { + .intf = { + .bLength = sizeof descriptors.fs_descs.intf, + .bDescriptorType = USB_DT_INTERFACE, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .iInterface = 1, + }, + .sink = { + .bLength = sizeof descriptors.hs_descs.sink, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 1 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), + }, + .sink_comp = { + .bLength = USB_DT_SS_EP_COMP_SIZE, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bMaxBurst = 0, + .bmAttributes = 0, + .wBytesPerInterval = 0, + }, + .source = { + .bLength = sizeof descriptors.hs_descs.source, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 2 | USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), + .bInterval = 1, /* NAK every 1 uframe */ + }, + .source_comp = { + .bLength = USB_DT_SS_EP_COMP_SIZE, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bMaxBurst = 0, + .bmAttributes = 0, + .wBytesPerInterval = 0, + }, + }, }; static size_t descs_to_legacy(void **legacy, const void *descriptors_v2) |