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. -----BEGIN PGP SIGNATURE----- iQJRBAABCAA7FiEElLzh7wn96CXwjh2IzL64meEamQYFAliKBd0dHGZlbGlwZS5i YWxiaUBsaW51eC5pbnRlbC5jb20ACgkQzL64meEamQb1Yw//XEI0VeUdsRM/JKK5 4BBoFCCUXT7jZMyzm7x9G7/4Tz3Xn9I9elAbZ7A3ctpLQXVO0KUAc5S3MRmq1ghj 8h18ZrOLqWG6gG+0eOtzSQLJ91+ULV+nyV6jS+RJyio7AMKy6XW0hRHQQs8ggcqg A/hZKVI/GdvnoSSLVNoWFxTiVC7Pu62IsWJV6BJuWubEze7u97xfBIt3qB9h2R8q ARfy29LYZulgrRYZ2DAtrKNFC8yKdIiKxWcmI47FHcNXtnQ6yAu7VqFcKWlH9Jvb NY/YAzv30leOXHrwHVXCM/Urh7SK6FJIIdgoDMpCWoy1CK2pHXkJCndt/NuM721h DYaopfNBJLtjvYDsvtnGXo3DC6+hBd3oYEz+gogGS/5gocr2ChnRK8Qc5T8eXYnC OBIVKeHcsx9wMxYwwxk2axWjflfbSRjPnpZHibgkvdrwGVY+Hcwf5GyixvTdqQJM dMrZcIPqtPJAg7OBPoH0LEViT14+lc8f5n6D0T/NezLxeeZvbcWQ5p17LpNal5oi S+4kmtNWR7nXKSdICvc00Ap+Iqu91eB4c1MfvP6HSLq7wpjs5QhWtDvM7++ygjL1 7m3ExmXUx+j29M64WM9KTNlXZFkQ8XB5PzmcXueQkz9fd2u8JJhBqGHdVWFHOv9y 4YGdaSpeqsui9bFoIdbjn0EO3+g= =gk8j -----END PGP SIGNATURE----- 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.
This commit is contained in:
commit
bc46e23c34
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
u8 speed;
|
||||
#define DWC2_SPEED_PARAM_HIGH 0
|
||||
#define DWC2_SPEED_PARAM_FULL 1
|
||||
#define DWC2_SPEED_PARAM_LOW 2
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
* 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,
|
||||
#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);
|
||||
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);
|
||||
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; }
|
||||
|
@ -1209,14 +1197,20 @@ 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; }
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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,
|
||||
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__);
|
||||
|
||||
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,7 +364,7 @@ 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,
|
||||
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",
|
||||
|
@ -377,7 +377,7 @@ 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,
|
||||
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",
|
||||
|
@ -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,7 +906,7 @@ 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,
|
||||
file = debugfs_create_regset32("regdump", 0444, hsotg->debug_root,
|
||||
hsotg->regset);
|
||||
if (!file) {
|
||||
ret = -ENOMEM;
|
||||
|
|
|
@ -191,6 +191,99 @@ static void dwc2_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg,
|
|||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -281,7 +377,7 @@ static struct usb_request *dwc2_hsotg_ep_alloc_request(struct usb_ep *ep,
|
|||
{
|
||||
struct dwc2_hsotg_req *req;
|
||||
|
||||
req = kzalloc(sizeof(struct dwc2_hsotg_req), flags);
|
||||
req = kzalloc(sizeof(*req), flags);
|
||||
if (!req)
|
||||
return NULL;
|
||||
|
||||
|
@ -316,6 +412,7 @@ static void dwc2_hsotg_unmap_dma(struct dwc2_hsotg *hsotg,
|
|||
struct dwc2_hsotg_req *hs_req)
|
||||
{
|
||||
struct usb_request *req = &hs_req->req;
|
||||
|
||||
usb_gadget_unmap_request(&hsotg->gadget, req, hs_ep->dir_in);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -1640,10 +1743,9 @@ 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;
|
||||
|
||||
|
@ -1889,7 +1991,6 @@ static void dwc2_hsotg_complete_request(struct dwc2_hsotg *hsotg,
|
|||
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,7 +2168,6 @@ 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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -3059,7 +3158,7 @@ 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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -4038,13 +4137,12 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now)
|
|||
}
|
||||
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 ||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,7 +4540,8 @@ 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),
|
||||
hsotg->eps_in[0] = devm_kzalloc(hsotg->dev,
|
||||
sizeof(struct dwc2_hsotg_ep),
|
||||
GFP_KERNEL);
|
||||
if (!hsotg->eps_in[0])
|
||||
return -ENOMEM;
|
||||
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
@ -2721,7 +2721,7 @@ static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
|
|||
!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,7 +2988,7 @@ 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 &&
|
||||
if (!hsotg->params.host_dma &&
|
||||
qh->channel->multi_count > 1)
|
||||
hsotg->queuing_high_bandwidth = 1;
|
||||
|
||||
|
@ -2996,7 +2996,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
|
|||
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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
|
|
@ -521,28 +521,28 @@ 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,
|
||||
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_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,
|
||||
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,
|
||||
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 */
|
||||
|
@ -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,
|
||||
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,
|
||||
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,
|
||||
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);
|
||||
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,7 +732,7 @@ 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,
|
||||
void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg,
|
||||
struct dwc2_host_chan *chan, int chnum,
|
||||
struct dwc2_qtd *qtd);
|
||||
|
||||
|
@ -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,14 +793,14 @@ 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,
|
||||
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,
|
||||
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 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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
@ -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,21 +1389,26 @@ static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg,
|
|||
int end_frnum;
|
||||
|
||||
/*
|
||||
* Figure out the end frame based on schedule.
|
||||
* 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 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.
|
||||
* 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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,13 +897,43 @@ 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;
|
||||
|
||||
trace_dwc3_prepare_trb(dep, trb);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -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;
|
||||
|
||||
dma = req->request.dma;
|
||||
length = req->request.length;
|
||||
if (rem && usb_endpoint_dir_out(dep->endpoint.desc)) {
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
struct dwc3_trb *trb;
|
||||
|
||||
dwc3_prepare_one_trb(dep, req, dma, length,
|
||||
false, 0);
|
||||
req->unaligned = true;
|
||||
|
||||
/* 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;
|
||||
|
@ -3049,12 +3160,6 @@ 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.
|
||||
|
@ -3062,15 +3167,18 @@ int dwc3_gadget_init(struct dwc3 *dwc)
|
|||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,16 +299,21 @@ 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;
|
||||
|
||||
switch (req->status) {
|
||||
case 0:
|
||||
req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC);
|
||||
if (!req_list)
|
||||
return;
|
||||
if (!req_list) {
|
||||
ERROR(cdev, "Unable to allocate mem for req_list\n");
|
||||
goto free_req;
|
||||
}
|
||||
|
||||
req_list->req = req;
|
||||
|
||||
spin_lock_irqsave(&hidg->spinlock, flags);
|
||||
spin_lock_irqsave(&hidg->read_spinlock, flags);
|
||||
list_add_tail(&req_list->list, &hidg->completed_out_req);
|
||||
spin_unlock_irqrestore(&hidg->spinlock, flags);
|
||||
spin_unlock_irqrestore(&hidg->read_spinlock, flags);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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, \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
ret = check_pending_gadget_drivers(udc);
|
||||
if (ret)
|
||||
goto err5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue