Commit 6d23ee9c authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'usb-for-v4.17' of...

Merge tag 'usb-for-v4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-testing

Felipe writes:

usb: changes for v4.17 merge window

Quite a lot happened in this cycle, with a total of 95 non-merge
commits. The most interesting parts are listed below:

Synopsys has been adding better support for USB 3.1 to dwc3. The same
series also sets g_mass_storage's max speed to SSP.

Roger Quadros (TI) added support for dual-role using the OTG block
available in some dwc3 implementations, this makes sure that AM437x
can swap roles in runtime.

We have a new SoC supported in dwc3 now - Amlogic Meson GX - thanks to
the work of Martin Blumenstingl.

We also have a ton of changes in dwc2 (51% of all changes, in
fact). The most interesting part there is the support for
Hibernation (a Synopsys PM feature).

Apart from these, we have our regular set of non-critical fixes all
over the place.
parents 6555ad13 aaeab02d
Amlogic Meson GX DWC3 USB SoC controller
Required properties:
- compatible: depending on the SoC this should contain one of:
* amlogic,meson-axg-dwc3
* amlogic,meson-gxl-dwc3
- clocks: a handle for the "USB general" clock
- clock-names: must be "usb_general"
- resets: a handle for the shared "USB OTG" reset line
- reset-names: must be "usb_otg"
Required child node:
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/meson-gxl-usb2-phy.txt
- Documentation/devicetree/bindings/phy/meson-gxl-usb3-phy.txt
Example device nodes:
usb0: usb@ff500000 {
compatible = "amlogic,meson-axg-dwc3";
#address-cells = <2>;
#size-cells = <2>;
ranges;
clocks = <&clkc CLKID_USB>;
clock-names = "usb_general";
resets = <&reset RESET_USB_OTG>;
reset-names = "usb_otg";
dwc3: dwc3@ff500000 {
compatible = "snps,dwc3";
reg = <0x0 0xff500000 0x0 0x100000>;
interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
dr_mode = "host";
maximum-speed = "high-speed";
snps,dis_u2_susphy_quirk;
phys = <&usb3_phy>, <&usb2_phy0>;
phy-names = "usb2-phy", "usb3-phy";
};
};
...@@ -57,6 +57,22 @@ Optional properties: ...@@ -57,6 +57,22 @@ Optional properties:
- snps,quirk-frame-length-adjustment: Value for GFLADJ_30MHZ field of GFLADJ - snps,quirk-frame-length-adjustment: Value for GFLADJ_30MHZ field of GFLADJ
register for post-silicon frame length adjustment when the register for post-silicon frame length adjustment when the
fladj_30mhz_sdbnd signal is invalid or incorrect. fladj_30mhz_sdbnd signal is invalid or incorrect.
- snps,rx-thr-num-pkt-prd: periodic ESS RX packet threshold count - host mode
only. Set this and rx-max-burst-prd to a valid,
non-zero value 1-16 (DWC_usb31 programming guide
section 1.2.4) to enable periodic ESS RX threshold.
- snps,rx-max-burst-prd: max periodic ESS RX burst size - host mode only. Set
this and rx-thr-num-pkt-prd to a valid, non-zero value
1-16 (DWC_usb31 programming guide section 1.2.4) to
enable periodic ESS RX threshold.
- snps,tx-thr-num-pkt-prd: periodic ESS TX packet threshold count - host mode
only. Set this and tx-max-burst-prd to a valid,
non-zero value 1-16 (DWC_usb31 programming guide
section 1.2.3) to enable periodic ESS TX threshold.
- snps,tx-max-burst-prd: max periodic ESS TX burst size - host mode only. Set
this and tx-thr-num-pkt-prd to a valid, non-zero value
1-16 (DWC_usb31 programming guide section 1.2.3) to
enable periodic ESS TX threshold.
- <DEPRECATED> tx-fifo-resize: determines if the FIFO *has* to be reallocated. - <DEPRECATED> tx-fifo-resize: determines if the FIFO *has* to be reallocated.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -718,7 +718,12 @@ static int params_show(struct seq_file *seq, void *v) ...@@ -718,7 +718,12 @@ static int params_show(struct seq_file *seq, void *v)
print_param_hex(seq, p, ahbcfg); print_param_hex(seq, p, ahbcfg);
print_param(seq, p, uframe_sched); print_param(seq, p, uframe_sched);
print_param(seq, p, external_id_pin_ctl); print_param(seq, p, external_id_pin_ctl);
print_param(seq, p, hibernation); print_param(seq, p, power_down);
print_param(seq, p, lpm);
print_param(seq, p, lpm_clock_gating);
print_param(seq, p, besl);
print_param(seq, p, hird_threshold_en);
print_param(seq, p, hird_threshold);
print_param(seq, p, host_dma); print_param(seq, p, host_dma);
print_param(seq, p, g_dma); print_param(seq, p, g_dma);
print_param(seq, p, g_dma_desc); print_param(seq, p, g_dma_desc);
......
This diff is collapsed.
This diff is collapsed.
...@@ -783,19 +783,6 @@ int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg); ...@@ -783,19 +783,6 @@ int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg);
*/ */
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
*
* @hsotg: The DWC2 HCD
*
* This can be used to determine average interrupt latency. Frame remaining is
* also shown for start transfer and two additional sample points.
*
* NOTE: This function will be removed once the peripheral controller code
* is integrated and the driver is stable
*/
void dwc2_hcd_dump_frrem(struct dwc2_hsotg *hsotg);
/* URB interface */ /* URB interface */
/* Transfer flags */ /* Transfer flags */
...@@ -813,47 +800,4 @@ int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context); ...@@ -813,47 +800,4 @@ int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context);
void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
int status); int status);
#ifdef DEBUG
/*
* Macro to sample the remaining PHY clocks left in the current frame. This
* may be used during debugging to determine the average time it takes to
* execute sections of code. There are two possible sample points, "a" and
* "b", so the _letter_ argument must be one of these values.
*
* To dump the average sample times, read the "hcd_frrem" sysfs attribute. For
* example, "cat /sys/devices/lm0/hcd_frrem".
*/
#define dwc2_sample_frrem(_hcd_, _qh_, _letter_) \
do { \
struct hfnum_data _hfnum_; \
struct dwc2_qtd *_qtd_; \
\
_qtd_ = list_entry((_qh_)->qtd_list.next, struct dwc2_qtd, \
qtd_list_entry); \
if (usb_pipeint(_qtd_->urb->pipe) && \
(_qh_)->start_active_frame != 0 && !_qtd_->complete_split) { \
_hfnum_.d32 = dwc2_readl((_hcd_)->regs + HFNUM); \
switch (_hfnum_.b.frnum & 0x7) { \
case 7: \
(_hcd_)->hfnum_7_samples_##_letter_++; \
(_hcd_)->hfnum_7_frrem_accum_##_letter_ += \
_hfnum_.b.frrem; \
break; \
case 0: \
(_hcd_)->hfnum_0_samples_##_letter_++; \
(_hcd_)->hfnum_0_frrem_accum_##_letter_ += \
_hfnum_.b.frrem; \
break; \
default: \
(_hcd_)->hfnum_other_samples_##_letter_++; \
(_hcd_)->hfnum_other_frrem_accum_##_letter_ += \
_hfnum_.b.frrem; \
break; \
} \
} \
} while (0)
#else
#define dwc2_sample_frrem(_hcd_, _qh_, _letter_) do {} while (0)
#endif
#endif /* __DWC2_HCD_H__ */ #endif /* __DWC2_HCD_H__ */
...@@ -231,6 +231,7 @@ ...@@ -231,6 +231,7 @@
#define GUID HSOTG_REG(0x003c) #define GUID HSOTG_REG(0x003c)
#define GSNPSID HSOTG_REG(0x0040) #define GSNPSID HSOTG_REG(0x0040)
#define GHWCFG1 HSOTG_REG(0x0044) #define GHWCFG1 HSOTG_REG(0x0044)
#define GSNPSID_ID_MASK GENMASK(31, 16)
#define GHWCFG2 HSOTG_REG(0x0048) #define GHWCFG2 HSOTG_REG(0x0048)
#define GHWCFG2_OTG_ENABLE_IC_USB BIT(31) #define GHWCFG2_OTG_ENABLE_IC_USB BIT(31)
...@@ -309,6 +310,7 @@ ...@@ -309,6 +310,7 @@
#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_SHIFT 16 #define GHWCFG4_NUM_DEV_MODE_CTRL_EP_SHIFT 16
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14) #define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14)
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT 14 #define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT 14
#define GHWCFG4_ACG_SUPPORTED BIT(12)
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0 #define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1 #define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2 #define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2
...@@ -320,28 +322,30 @@ ...@@ -320,28 +322,30 @@
#define GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT 0 #define GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT 0
#define GLPMCFG HSOTG_REG(0x0054) #define GLPMCFG HSOTG_REG(0x0054)
#define GLPMCFG_INV_SEL_HSIC BIT(31) #define GLPMCFG_INVSELHSIC BIT(31)
#define GLPMCFG_HSIC_CONNECT BIT(30) #define GLPMCFG_HSICCON BIT(30)
#define GLPMCFG_RETRY_COUNT_STS_MASK (0x7 << 25) #define GLPMCFG_RSTRSLPSTS BIT(29)
#define GLPMCFG_RETRY_COUNT_STS_SHIFT 25 #define GLPMCFG_ENBESL BIT(28)
#define GLPMCFG_SEND_LPM BIT(24) #define GLPMCFG_LPM_RETRYCNT_STS_MASK (0x7 << 25)
#define GLPMCFG_RETRY_COUNT_MASK (0x7 << 21) #define GLPMCFG_LPM_RETRYCNT_STS_SHIFT 25
#define GLPMCFG_RETRY_COUNT_SHIFT 21 #define GLPMCFG_SNDLPM BIT(24)
#define GLPMCFG_LPM_CHAN_INDEX_MASK (0xf << 17) #define GLPMCFG_RETRY_CNT_MASK (0x7 << 21)
#define GLPMCFG_LPM_CHAN_INDEX_SHIFT 17 #define GLPMCFG_RETRY_CNT_SHIFT 21
#define GLPMCFG_SLEEP_STATE_RESUMEOK BIT(16) #define GLPMCFG_LPM_CHNL_INDX_MASK (0xf << 17)
#define GLPMCFG_PRT_SLEEP_STS BIT(15) #define GLPMCFG_LPM_CHNL_INDX_SHIFT 17
#define GLPMCFG_LPM_RESP_MASK (0x3 << 13) #define GLPMCFG_L1RESUMEOK BIT(16)
#define GLPMCFG_LPM_RESP_SHIFT 13 #define GLPMCFG_SLPSTS BIT(15)
#define GLPMCFG_COREL1RES_MASK (0x3 << 13)
#define GLPMCFG_COREL1RES_SHIFT 13
#define GLPMCFG_HIRD_THRES_MASK (0x1f << 8) #define GLPMCFG_HIRD_THRES_MASK (0x1f << 8)
#define GLPMCFG_HIRD_THRES_SHIFT 8 #define GLPMCFG_HIRD_THRES_SHIFT 8
#define GLPMCFG_HIRD_THRES_EN (0x10 << 8) #define GLPMCFG_HIRD_THRES_EN (0x10 << 8)
#define GLPMCFG_EN_UTMI_SLEEP BIT(7) #define GLPMCFG_ENBLSLPM BIT(7)
#define GLPMCFG_REM_WKUP_EN BIT(6) #define GLPMCFG_BREMOTEWAKE BIT(6)
#define GLPMCFG_HIRD_MASK (0xf << 2) #define GLPMCFG_HIRD_MASK (0xf << 2)
#define GLPMCFG_HIRD_SHIFT 2 #define GLPMCFG_HIRD_SHIFT 2
#define GLPMCFG_APPL_RESP BIT(1) #define GLPMCFG_APPL1RES BIT(1)
#define GLPMCFG_LPM_CAP_EN BIT(0) #define GLPMCFG_LPMCAP BIT(0)
#define GPWRDN HSOTG_REG(0x0058) #define GPWRDN HSOTG_REG(0x0058)
#define GPWRDN_MULT_VAL_ID_BC_MASK (0x1f << 24) #define GPWRDN_MULT_VAL_ID_BC_MASK (0x1f << 24)
...@@ -644,6 +648,10 @@ ...@@ -644,6 +648,10 @@
#define PCGCTL_GATEHCLK BIT(1) #define PCGCTL_GATEHCLK BIT(1)
#define PCGCTL_STOPPCLK BIT(0) #define PCGCTL_STOPPCLK BIT(0)
#define PCGCCTL1 HSOTG_REG(0xe04)
#define PCGCCTL1_TIMER (0x3 << 1)
#define PCGCCTL1_GATEEN BIT(0)
#define EPFIFO(_a) HSOTG_REG(0x1000 + ((_a) * 0x1000)) #define EPFIFO(_a) HSOTG_REG(0x1000 + ((_a) * 0x1000))
/* Host Mode Registers */ /* Host Mode Registers */
......
...@@ -252,6 +252,20 @@ static void dwc2_set_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg) ...@@ -252,6 +252,20 @@ static void dwc2_set_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg)
p->g_tx_fifo_size[i] = depth_average; p->g_tx_fifo_size[i] = depth_average;
} }
static void dwc2_set_param_power_down(struct dwc2_hsotg *hsotg)
{
int val;
if (hsotg->hw_params.hibernation)
val = 2;
else if (hsotg->hw_params.power_optimized)
val = 1;
else
val = 0;
hsotg->params.power_down = val;
}
/** /**
* dwc2_set_default_params() - Set all core parameters to their * dwc2_set_default_params() - Set all core parameters to their
* auto-detected default values. * auto-detected default values.
...@@ -266,21 +280,27 @@ static void dwc2_set_default_params(struct dwc2_hsotg *hsotg) ...@@ -266,21 +280,27 @@ static void dwc2_set_default_params(struct dwc2_hsotg *hsotg)
dwc2_set_param_phy_type(hsotg); dwc2_set_param_phy_type(hsotg);
dwc2_set_param_speed(hsotg); dwc2_set_param_speed(hsotg);
dwc2_set_param_phy_utmi_width(hsotg); dwc2_set_param_phy_utmi_width(hsotg);
dwc2_set_param_power_down(hsotg);
p->phy_ulpi_ddr = false; p->phy_ulpi_ddr = false;
p->phy_ulpi_ext_vbus = false; p->phy_ulpi_ext_vbus = false;
p->enable_dynamic_fifo = hw->enable_dynamic_fifo; p->enable_dynamic_fifo = hw->enable_dynamic_fifo;
p->en_multiple_tx_fifo = hw->en_multiple_tx_fifo; p->en_multiple_tx_fifo = hw->en_multiple_tx_fifo;
p->i2c_enable = hw->i2c_enable; p->i2c_enable = hw->i2c_enable;
p->acg_enable = hw->acg_enable;
p->ulpi_fs_ls = false; p->ulpi_fs_ls = false;
p->ts_dline = false; p->ts_dline = false;
p->reload_ctl = (hw->snpsid >= DWC2_CORE_REV_2_92a); p->reload_ctl = (hw->snpsid >= DWC2_CORE_REV_2_92a);
p->uframe_sched = true; p->uframe_sched = true;
p->external_id_pin_ctl = false; p->external_id_pin_ctl = false;
p->hibernation = false; p->lpm = true;
p->lpm_clock_gating = true;
p->besl = true;
p->hird_threshold_en = true;
p->hird_threshold = 4;
p->max_packet_count = hw->max_packet_count; p->max_packet_count = hw->max_packet_count;
p->max_transfer_size = hw->max_transfer_size; p->max_transfer_size = hw->max_transfer_size;
p->ahbcfg = GAHBCFG_HBSTLEN_INCR4 << GAHBCFG_HBSTLEN_SHIFT; p->ahbcfg = GAHBCFG_HBSTLEN_INCR << GAHBCFG_HBSTLEN_SHIFT;
if ((hsotg->dr_mode == USB_DR_MODE_HOST) || if ((hsotg->dr_mode == USB_DR_MODE_HOST) ||
(hsotg->dr_mode == USB_DR_MODE_OTG)) { (hsotg->dr_mode == USB_DR_MODE_OTG)) {
...@@ -463,6 +483,38 @@ static void dwc2_check_param_phy_utmi_width(struct dwc2_hsotg *hsotg) ...@@ -463,6 +483,38 @@ static void dwc2_check_param_phy_utmi_width(struct dwc2_hsotg *hsotg)
dwc2_set_param_phy_utmi_width(hsotg); dwc2_set_param_phy_utmi_width(hsotg);
} }
static void dwc2_check_param_power_down(struct dwc2_hsotg *hsotg)
{
int param = hsotg->params.power_down;
switch (param) {
case DWC2_POWER_DOWN_PARAM_NONE:
break;
case DWC2_POWER_DOWN_PARAM_PARTIAL:
if (hsotg->hw_params.power_optimized)
break;
dev_dbg(hsotg->dev,
"Partial power down isn't supported by HW\n");
param = DWC2_POWER_DOWN_PARAM_NONE;
break;
case DWC2_POWER_DOWN_PARAM_HIBERNATION:
if (hsotg->hw_params.hibernation)
break;
dev_dbg(hsotg->dev,
"Hibernation isn't supported by HW\n");
param = DWC2_POWER_DOWN_PARAM_NONE;
break;
default:
dev_err(hsotg->dev,
"%s: Invalid parameter power_down=%d\n",
__func__, param);
param = DWC2_POWER_DOWN_PARAM_NONE;
break;
}
hsotg->params.power_down = param;
}
static void dwc2_check_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg) static void dwc2_check_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg)
{ {
int fifo_count; int fifo_count;
...@@ -523,10 +575,19 @@ static void dwc2_check_params(struct dwc2_hsotg *hsotg) ...@@ -523,10 +575,19 @@ static void dwc2_check_params(struct dwc2_hsotg *hsotg)
dwc2_check_param_phy_type(hsotg); dwc2_check_param_phy_type(hsotg);
dwc2_check_param_speed(hsotg); dwc2_check_param_speed(hsotg);
dwc2_check_param_phy_utmi_width(hsotg); dwc2_check_param_phy_utmi_width(hsotg);
dwc2_check_param_power_down(hsotg);
CHECK_BOOL(enable_dynamic_fifo, hw->enable_dynamic_fifo); CHECK_BOOL(enable_dynamic_fifo, hw->enable_dynamic_fifo);
CHECK_BOOL(en_multiple_tx_fifo, hw->en_multiple_tx_fifo); CHECK_BOOL(en_multiple_tx_fifo, hw->en_multiple_tx_fifo);
CHECK_BOOL(i2c_enable, hw->i2c_enable); CHECK_BOOL(i2c_enable, hw->i2c_enable);
CHECK_BOOL(acg_enable, hw->acg_enable);
CHECK_BOOL(reload_ctl, (hsotg->hw_params.snpsid > DWC2_CORE_REV_2_92a)); CHECK_BOOL(reload_ctl, (hsotg->hw_params.snpsid > DWC2_CORE_REV_2_92a));
CHECK_BOOL(lpm, (hsotg->hw_params.snpsid >= DWC2_CORE_REV_2_80a));
CHECK_BOOL(lpm, hw->lpm_mode);
CHECK_BOOL(lpm_clock_gating, hsotg->params.lpm);
CHECK_BOOL(besl, hsotg->params.lpm);
CHECK_BOOL(besl, (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a));
CHECK_BOOL(hird_threshold_en, hsotg->params.lpm);
CHECK_RANGE(hird_threshold, 0, hsotg->params.besl ? 12 : 7, 0);
CHECK_RANGE(max_packet_count, CHECK_RANGE(max_packet_count,
15, hw->max_packet_count, 15, hw->max_packet_count,
hw->max_packet_count); hw->max_packet_count);
...@@ -579,19 +640,15 @@ static void dwc2_get_host_hwparams(struct dwc2_hsotg *hsotg) ...@@ -579,19 +640,15 @@ static void dwc2_get_host_hwparams(struct dwc2_hsotg *hsotg)
struct dwc2_hw_params *hw = &hsotg->hw_params; struct dwc2_hw_params *hw = &hsotg->hw_params;
u32 gnptxfsiz; u32 gnptxfsiz;
u32 hptxfsiz; u32 hptxfsiz;
bool forced;
if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
return; return;
forced = dwc2_force_mode_if_needed(hsotg, true); dwc2_force_mode(hsotg, true);
gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ); gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ); hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ);
if (forced)
dwc2_clear_force_mode(hsotg);
hw->host_nperio_tx_fifo_size = (gnptxfsiz & FIFOSIZE_DEPTH_MASK) >> hw->host_nperio_tx_fifo_size = (gnptxfsiz & FIFOSIZE_DEPTH_MASK) >>
FIFOSIZE_DEPTH_SHIFT; FIFOSIZE_DEPTH_SHIFT;
hw->host_perio_tx_fifo_size = (hptxfsiz & FIFOSIZE_DEPTH_MASK) >> hw->host_perio_tx_fifo_size = (hptxfsiz & FIFOSIZE_DEPTH_MASK) >>
...@@ -606,14 +663,13 @@ static void dwc2_get_host_hwparams(struct dwc2_hsotg *hsotg) ...@@ -606,14 +663,13 @@ static void dwc2_get_host_hwparams(struct dwc2_hsotg *hsotg)
static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg) static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg)
{ {
struct dwc2_hw_params *hw = &hsotg->hw_params; struct dwc2_hw_params *hw = &hsotg->hw_params;
bool forced;
u32 gnptxfsiz; u32 gnptxfsiz;
int fifo, fifo_count; int fifo, fifo_count;
if (hsotg->dr_mode == USB_DR_MODE_HOST) if (hsotg->dr_mode == USB_DR_MODE_HOST)
return; return;
forced = dwc2_force_mode_if_needed(hsotg, false); dwc2_force_mode(hsotg, false);
gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ); gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
...@@ -625,9 +681,6 @@ static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg) ...@@ -625,9 +681,6 @@ static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg)
FIFOSIZE_DEPTH_MASK) >> FIFOSIZE_DEPTH_SHIFT; FIFOSIZE_DEPTH_MASK) >> FIFOSIZE_DEPTH_SHIFT;
} }
if (forced)
dwc2_clear_force_mode(hsotg);
hw->dev_nperio_tx_fifo_size = (gnptxfsiz & FIFOSIZE_DEPTH_MASK) >> hw->dev_nperio_tx_fifo_size = (gnptxfsiz & FIFOSIZE_DEPTH_MASK) >>
FIFOSIZE_DEPTH_SHIFT; FIFOSIZE_DEPTH_SHIFT;
} }
...@@ -646,14 +699,13 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) ...@@ -646,14 +699,13 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
/* /*
* Attempt to ensure this device is really a DWC_otg Controller. * Attempt to ensure this device is really a DWC_otg Controller.
* Read and verify the GSNPSID register contents. The value should be * Read and verify the GSNPSID register contents. The value should be
* 0x45f42xxx or 0x45f43xxx, which corresponds to either "OT2" or "OT3", * 0x45f4xxxx, 0x5531xxxx or 0x5532xxxx
* as in "OTG version 2.xx" or "OTG version 3.xx".
*/ */
hw->snpsid = dwc2_readl(hsotg->regs + GSNPSID); hw->snpsid = dwc2_readl(hsotg->regs + GSNPSID);
if ((hw->snpsid & 0xfffff000) != 0x4f542000 && if ((hw->snpsid & GSNPSID_ID_MASK) != DWC2_OTG_ID &&
(hw->snpsid & 0xfffff000) != 0x4f543000 && (hw->snpsid & GSNPSID_ID_MASK) != DWC2_FS_IOT_ID &&
(hw->snpsid & 0xffff0000) != 0x55310000 && (hw->snpsid & GSNPSID_ID_MASK) != DWC2_HS_IOT_ID) {
(hw->snpsid & 0xffff0000) != 0x55320000) {
dev_err(hsotg->dev, "Bad value for GSNPSID: 0x%08x\n", dev_err(hsotg->dev, "Bad value for GSNPSID: 0x%08x\n",
hw->snpsid); hw->snpsid);
return -ENODEV; return -ENODEV;
...@@ -706,6 +758,7 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) ...@@ -706,6 +758,7 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
hw->i2c_enable = !!(hwcfg3 & GHWCFG3_I2C); hw->i2c_enable = !!(hwcfg3 & GHWCFG3_I2C);
hw->total_fifo_size = (hwcfg3 & GHWCFG3_DFIFO_DEPTH_MASK) >> hw->total_fifo_size = (hwcfg3 & GHWCFG3_DFIFO_DEPTH_MASK) >>
GHWCFG3_DFIFO_DEPTH_SHIFT; GHWCFG3_DFIFO_DEPTH_SHIFT;
hw->lpm_mode = !!(hwcfg3 & GHWCFG3_OTG_LPM_EN);
/* hwcfg4 */ /* hwcfg4 */
hw->en_multiple_tx_fifo = !!(hwcfg4 & GHWCFG4_DED_FIFO_EN); hw->en_multiple_tx_fifo = !!(hwcfg4 & GHWCFG4_DED_FIFO_EN);
...@@ -715,8 +768,10 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) ...@@ -715,8 +768,10 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
GHWCFG4_NUM_IN_EPS_SHIFT; GHWCFG4_NUM_IN_EPS_SHIFT;
hw->dma_desc_enable = !!(hwcfg4 & GHWCFG4_DESC_DMA); hw->dma_desc_enable = !!(hwcfg4 & GHWCFG4_DESC_DMA);
hw->power_optimized = !!(hwcfg4 & GHWCFG4_POWER_OPTIMIZ); hw->power_optimized = !!(hwcfg4 & GHWCFG4_POWER_OPTIMIZ);
hw->hibernation = !!(hwcfg4 & GHWCFG4_HIBER);
hw->utmi_phy_data_width = (hwcfg4 & GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK) >> hw->utmi_phy_data_width = (hwcfg4 & GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK) >>
GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT; GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT;
hw->acg_enable = !!(hwcfg4 & GHWCFG4_ACG_SUPPORTED);
/* fifo sizes */ /* fifo sizes */
hw->rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >> hw->rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >>
......
...@@ -83,7 +83,6 @@ static void dwc2_pci_remove(struct pci_dev *pci) ...@@ -83,7 +83,6 @@ static void dwc2_pci_remove(struct pci_dev *pci)
platform_device_unregister(glue->dwc2); platform_device_unregister(glue->dwc2);
usb_phy_generic_unregister(glue->phy); usb_phy_generic_unregister(glue->phy);
kfree(glue);
pci_set_drvdata(pci, NULL); pci_set_drvdata(pci, NULL);
} }
...@@ -105,10 +104,17 @@ static int dwc2_pci_probe(struct pci_dev *pci, ...@@ -105,10 +104,17 @@ static int dwc2_pci_probe(struct pci_dev *pci,
pci_set_master(pci); pci_set_master(pci);
phy = usb_phy_generic_register();
if (IS_ERR(phy)) {
dev_err(dev, "error registering generic PHY (%ld)\n",
PTR_ERR(phy));
return PTR_ERR(phy);
}
dwc2 = platform_device_alloc("dwc2", PLATFORM_DEVID_AUTO); dwc2 = platform_device_alloc("dwc2", PLATFORM_DEVID_AUTO);
if (!dwc2) { if (!dwc2) {
dev_err(dev, "couldn't allocate dwc2 device\n"); dev_err(dev, "couldn't allocate dwc2 device\n");
return -ENOMEM; goto err;
} }
memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
...@@ -125,32 +131,25 @@ static int dwc2_pci_probe(struct pci_dev *pci, ...@@ -125,32 +131,25 @@ static int dwc2_pci_probe(struct pci_dev *pci,
ret = platform_device_add_resources(dwc2, res, ARRAY_SIZE(res)); ret = platform_device_add_resources(dwc2, res, ARRAY_SIZE(res));
if (ret) { if (ret) {
dev_err(dev, "couldn't add resources to dwc2 device\n"); dev_err(dev, "couldn't add resources to dwc2 device\n");
return ret; goto err;
} }
dwc2->dev.parent = dev; dwc2->dev.parent = dev;
phy = usb_phy_generic_register();
if (IS_ERR(phy)) {
dev_err(dev, "error registering generic PHY (%ld)\n",
PTR_ERR(phy));
return PTR_ERR(phy);
}
ret = dwc2_pci_quirks(pci, dwc2); ret = dwc2_pci_quirks(pci, dwc2);
if (ret) if (ret)
goto err; goto err;
glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
if (!glue)
goto err;
ret = platform_device_add(dwc2); ret = platform_device_add(dwc2);
if (ret) { if (ret) {
dev_err(dev, "failed to register dwc2 device\n"); dev_err(dev, "failed to register dwc2 device\n");
goto err; goto err;
} }
glue = kzalloc(sizeof(*glue), GFP_KERNEL);
if (!glue)
return -ENOMEM;
glue->phy = phy; glue->phy = phy;
glue->dwc2 = dwc2; glue->dwc2 = dwc2;
pci_set_drvdata(pci, glue); pci_set_drvdata(pci, glue);
......
...@@ -382,8 +382,10 @@ static int dwc2_driver_probe(struct platform_device *dev) ...@@ -382,8 +382,10 @@ static int dwc2_driver_probe(struct platform_device *dev)
if (!dev->dev.dma_mask) if (!dev->dev.dma_mask)
dev->dev.dma_mask = &dev->dev.coherent_dma_mask; dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
retval = dma_set_coherent_mask(&dev->dev, DMA_BIT_MASK(32)); retval = dma_set_coherent_mask(&dev->dev, DMA_BIT_MASK(32));
if (retval) if (retval) {
dev_err(&dev->dev, "can't set coherent DMA mask: %d\n", retval);
return retval; return retval;
}
res = platform_get_resource(dev, IORESOURCE_MEM, 0); res = platform_get_resource(dev, IORESOURCE_MEM, 0);
hsotg->regs = devm_ioremap_resource(&dev->dev, res); hsotg->regs = devm_ioremap_resource(&dev->dev, res);
...@@ -425,13 +427,20 @@ static int dwc2_driver_probe(struct platform_device *dev) ...@@ -425,13 +427,20 @@ static int dwc2_driver_probe(struct platform_device *dev)
* Reset before dwc2_get_hwparams() then it could get power-on real * Reset before dwc2_get_hwparams() then it could get power-on real
* reset value form registers. * reset value form registers.
*/ */
dwc2_core_reset_and_force_dr_mode(hsotg); retval = dwc2_core_reset(hsotg, false);
if (retval)
goto error;
/* Detect config values from hardware */ /* Detect config values from hardware */
retval = dwc2_get_hwparams(hsotg); retval = dwc2_get_hwparams(hsotg);
if (retval) if (retval)
goto error; goto error;
/*
* For OTG cores, set the force mode bits to reflect the value
* of dr_mode. Force mode bits should not be touched at any
* other time after this.
*/
dwc2_force_dr_mode(hsotg); dwc2_force_dr_mode(hsotg);
retval = dwc2_init_params(hsotg); retval = dwc2_init_params(hsotg);
...@@ -439,7 +448,7 @@ static int dwc2_driver_probe(struct platform_device *dev) ...@@ -439,7 +448,7 @@ static int dwc2_driver_probe(struct platform_device *dev)
goto error; goto error;
if (hsotg->dr_mode != USB_DR_MODE_HOST) { if (hsotg->dr_mode != USB_DR_MODE_HOST) {
retval = dwc2_gadget_init(hsotg, hsotg->irq); retval = dwc2_gadget_init(hsotg);
if (retval) if (retval)
goto error; goto error;
hsotg->gadget_enabled = 1; hsotg->gadget_enabled = 1;
...@@ -456,6 +465,7 @@ static int dwc2_driver_probe(struct platform_device *dev) ...@@ -456,6 +465,7 @@ static int dwc2_driver_probe(struct platform_device *dev)
} }
platform_set_drvdata(dev, hsotg); platform_set_drvdata(dev, hsotg);
hsotg->hibernated = 0;
dwc2_debugfs_init(hsotg); dwc2_debugfs_init(hsotg);
......
...@@ -6,7 +6,7 @@ obj-$(CONFIG_USB_DWC3) += dwc3.o ...@@ -6,7 +6,7 @@ obj-$(CONFIG_USB_DWC3) += dwc3.o
dwc3-y := core.o dwc3-y := core.o
ifneq ($(CONFIG_FTRACE),) ifneq ($(CONFIG_TRACING),)
dwc3-y += trace.o dwc3-y += trace.o
endif endif
......
...@@ -89,10 +89,7 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc) ...@@ -89,10 +89,7 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc)
return 0; return 0;
} }
static void dwc3_event_buffers_cleanup(struct dwc3 *dwc); void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
static int dwc3_event_buffers_setup(struct dwc3 *dwc);
static void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
{ {
u32 reg; u32 reg;
...@@ -110,13 +107,19 @@ static void __dwc3_set_mode(struct work_struct *work) ...@@ -110,13 +107,19 @@ static void __dwc3_set_mode(struct work_struct *work)
unsigned long flags; unsigned long flags;
int ret; int ret;
if (dwc->dr_mode != USB_DR_MODE_OTG)
return;
if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_OTG)
dwc3_otg_update(dwc, 0);
if (!dwc->desired_dr_role) if (!dwc->desired_dr_role)
return; return;
if (dwc->desired_dr_role == dwc->current_dr_role) if (dwc->desired_dr_role == dwc->current_dr_role)
return; return;
if (dwc->dr_mode != USB_DR_MODE_OTG) if (dwc->desired_dr_role == DWC3_GCTL_PRTCAP_OTG && dwc->edev)
return; return;
switch (dwc->current_dr_role) { switch (dwc->current_dr_role) {
...@@ -127,6 +130,13 @@ static void __dwc3_set_mode(struct work_struct *work) ...@@ -127,6 +130,13 @@ static void __dwc3_set_mode(struct work_struct *work)
dwc3_gadget_exit(dwc); dwc3_gadget_exit(dwc);
dwc3_event_buffers_cleanup(dwc); dwc3_event_buffers_cleanup(dwc);
break; break;
case DWC3_GCTL_PRTCAP_OTG:
dwc3_otg_exit(dwc);
spin_lock_irqsave(&dwc->lock, flags);
dwc->desired_otg_role = DWC3_OTG_ROLE_IDLE;
spin_unlock_irqrestore(&dwc->lock, flags);
dwc3_otg_update(dwc, 1);
break;
default: default:
break; break;
} }
...@@ -162,9 +172,14 @@ static void __dwc3_set_mode(struct work_struct *work) ...@@ -162,9 +172,14 @@ static void __dwc3_set_mode(struct work_struct *work)
if (ret) if (ret)
dev_err(dwc->dev, "failed to initialize peripheral\n"); dev_err(dwc->dev, "failed to initialize peripheral\n");
break; break;
case DWC3_GCTL_PRTCAP_OTG:
dwc3_otg_init(dwc);
dwc3_otg_update(dwc, 0);
break;
default: default:
break; break;
} }
} }
void dwc3_set_mode(struct dwc3 *dwc, u32 mode) void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
...@@ -229,7 +244,7 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) ...@@ -229,7 +244,7 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
do { do {
reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg = dwc3_readl(dwc->regs, DWC3_DCTL);
if (!(reg & DWC3_DCTL_CSFTRST)) if (!(reg & DWC3_DCTL_CSFTRST))
return 0; goto done;
udelay(1); udelay(1);
} while (--retries); } while (--retries);
...@@ -238,6 +253,17 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) ...@@ -238,6 +253,17 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
phy_exit(dwc->usb2_generic_phy); phy_exit(dwc->usb2_generic_phy);
return -ETIMEDOUT; return -ETIMEDOUT;
done:
/*
* For DWC_usb31 controller, once DWC3_DCTL_CSFTRST bit is cleared,
* we must wait at least 50ms before accessing the PHY domain
* (synchronization delay). DWC_usb31 programming guide section 1.3.2.
*/
if (dwc3_is_usb31(dwc))
msleep(50);
return 0;
} }
/* /*
...@@ -348,7 +374,7 @@ static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) ...@@ -348,7 +374,7 @@ static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
* *
* Returns 0 on success otherwise negative errno. * Returns 0 on success otherwise negative errno.
*/ */
static int dwc3_event_buffers_setup(struct dwc3 *dwc) int dwc3_event_buffers_setup(struct dwc3 *dwc)
{ {
struct dwc3_event_buffer *evt; struct dwc3_event_buffer *evt;
...@@ -365,7 +391,7 @@ static int dwc3_event_buffers_setup(struct dwc3 *dwc) ...@@ -365,7 +391,7 @@ static int dwc3_event_buffers_setup(struct dwc3 *dwc)
return 0; return 0;
} }
static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
{ {
struct dwc3_event_buffer *evt; struct dwc3_event_buffer *evt;
...@@ -846,6 +872,43 @@ static int dwc3_core_init(struct dwc3 *dwc) ...@@ -846,6 +872,43 @@ static int dwc3_core_init(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
} }
/*
* Must config both number of packets and max burst settings to enable
* RX and/or TX threshold.
*/
if (dwc3_is_usb31(dwc) && dwc->dr_mode == USB_DR_MODE_HOST) {
u8 rx_thr_num = dwc->rx_thr_num_pkt_prd;
u8 rx_maxburst = dwc->rx_max_burst_prd;
u8 tx_thr_num = dwc->tx_thr_num_pkt_prd;
u8 tx_maxburst = dwc->tx_max_burst_prd;
if (rx_thr_num && rx_maxburst) {
reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
reg |= DWC31_RXTHRNUMPKTSEL_PRD;
reg &= ~DWC31_RXTHRNUMPKT_PRD(~0);
reg |= DWC31_RXTHRNUMPKT_PRD(rx_thr_num);
reg &= ~DWC31_MAXRXBURSTSIZE_PRD(~0);
reg |= DWC31_MAXRXBURSTSIZE_PRD(rx_maxburst);
dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
}
if (tx_thr_num && tx_maxburst) {
reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
reg |= DWC31_TXTHRNUMPKTSEL_PRD;
reg &= ~DWC31_TXTHRNUMPKT_PRD(~0);
reg |= DWC31_TXTHRNUMPKT_PRD(tx_thr_num);
reg &= ~DWC31_MAXTXBURSTSIZE_PRD(~0);
reg |= DWC31_MAXTXBURSTSIZE_PRD(tx_maxburst);
dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
}
}
return 0; return 0;
err4: err4:
...@@ -1016,6 +1079,10 @@ static void dwc3_get_properties(struct dwc3 *dwc) ...@@ -1016,6 +1079,10 @@ static void dwc3_get_properties(struct dwc3 *dwc)
u8 lpm_nyet_threshold; u8 lpm_nyet_threshold;
u8 tx_de_emphasis; u8 tx_de_emphasis;
u8 hird_threshold; u8 hird_threshold;
u8 rx_thr_num_pkt_prd;
u8 rx_max_burst_prd;
u8 tx_thr_num_pkt_prd;
u8 tx_max_burst_prd;
/* default to highest possible threshold */ /* default to highest possible threshold */
lpm_nyet_threshold = 0xff; lpm_nyet_threshold = 0xff;
...@@ -1050,6 +1117,14 @@ static void dwc3_get_properties(struct dwc3 *dwc) ...@@ -1050,6 +1117,14 @@ static void dwc3_get_properties(struct dwc3 *dwc)
&hird_threshold); &hird_threshold);
dwc->usb3_lpm_capable = device_property_read_bool(dev, dwc->usb3_lpm_capable = device_property_read_bool(dev,
"snps,usb3_lpm_capable"); "snps,usb3_lpm_capable");
device_property_read_u8(dev, "snps,rx-thr-num-pkt-prd",
&rx_thr_num_pkt_prd);
device_property_read_u8(dev, "snps,rx-max-burst-prd",
&rx_max_burst_prd);
device_property_read_u8(dev, "snps,tx-thr-num-pkt-prd",
&tx_thr_num_pkt_prd);
device_property_read_u8(dev, "snps,tx-max-burst-prd",
&tx_max_burst_prd);
dwc->disable_scramble_quirk = device_property_read_bool(dev, dwc->disable_scramble_quirk = device_property_read_bool(dev,
"snps,disable_scramble_quirk"); "snps,disable_scramble_quirk");
...@@ -1100,6 +1175,12 @@ static void dwc3_get_properties(struct dwc3 *dwc) ...@@ -1100,6 +1175,12 @@ static void dwc3_get_properties(struct dwc3 *dwc)
dwc->hird_threshold = hird_threshold dwc->hird_threshold = hird_threshold
| (dwc->is_utmi_l1_suspend << 4); | (dwc->is_utmi_l1_suspend << 4);
dwc->rx_thr_num_pkt_prd = rx_thr_num_pkt_prd;
dwc->rx_max_burst_prd = rx_max_burst_prd;
dwc->tx_thr_num_pkt_prd = tx_thr_num_pkt_prd;
dwc->tx_max_burst_prd = tx_max_burst_prd;
dwc->imod_interval = 0; dwc->imod_interval = 0;
} }
...@@ -1326,6 +1407,20 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) ...@@ -1326,6 +1407,20 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
if (!PMSG_IS_AUTO(msg)) if (!PMSG_IS_AUTO(msg))
dwc3_core_exit(dwc); dwc3_core_exit(dwc);
break; break;
case DWC3_GCTL_PRTCAP_OTG:
/* do nothing during runtime_suspend */
if (PMSG_IS_AUTO(msg))
break;
if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) {
spin_lock_irqsave(&dwc->lock, flags);
dwc3_gadget_suspend(dwc);
spin_unlock_irqrestore(&dwc->lock, flags);
}
dwc3_otg_exit(dwc);
dwc3_core_exit(dwc);
break;
default: default:
/* do nothing */ /* do nothing */
break; break;
...@@ -1345,6 +1440,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) ...@@ -1345,6 +1440,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
if (ret) if (ret)
return ret; return ret;
dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);
spin_lock_irqsave(&dwc->lock, flags); spin_lock_irqsave(&dwc->lock, flags);
dwc3_gadget_resume(dwc); dwc3_gadget_resume(dwc);
spin_unlock_irqrestore(&dwc->lock, flags); spin_unlock_irqrestore(&dwc->lock, flags);
...@@ -1355,7 +1451,29 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) ...@@ -1355,7 +1451,29 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
ret = dwc3_core_init(dwc); ret = dwc3_core_init(dwc);
if (ret) if (ret)
return ret; return ret;
dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST);
}
break;
case DWC3_GCTL_PRTCAP_OTG:
/* nothing to do on runtime_resume */
if (PMSG_IS_AUTO(msg))
break;
ret = dwc3_core_init(dwc);
if (ret)
return ret;
dwc3_set_prtcap(dwc, dwc->current_dr_role);
dwc3_otg_init(dwc);
if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST) {
dwc3_otg_host_init(dwc);
} else if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) {
spin_lock_irqsave(&dwc->lock, flags);
dwc3_gadget_resume(dwc);
spin_unlock_irqrestore(&dwc->lock, flags);
} }
break; break;
default: default:
/* do nothing */ /* do nothing */
......
...@@ -58,6 +58,11 @@ ...@@ -58,6 +58,11 @@
#define DWC3_DEVICE_EVENT_CMD_CMPL 10 #define DWC3_DEVICE_EVENT_CMD_CMPL 10
#define DWC3_DEVICE_EVENT_OVERFLOW 11 #define DWC3_DEVICE_EVENT_OVERFLOW 11
/* Controller's role while using the OTG block */
#define DWC3_OTG_ROLE_IDLE 0
#define DWC3_OTG_ROLE_HOST 1
#define DWC3_OTG_ROLE_DEVICE 2
#define DWC3_GEVNTCOUNT_MASK 0xfffc #define DWC3_GEVNTCOUNT_MASK 0xfffc
#define DWC3_GEVNTCOUNT_EHB BIT(31) #define DWC3_GEVNTCOUNT_EHB BIT(31)
#define DWC3_GSNPSID_MASK 0xffff0000 #define DWC3_GSNPSID_MASK 0xffff0000
...@@ -100,6 +105,11 @@ ...@@ -100,6 +105,11 @@
#define DWC3_GHWPARAMS7 0xc15c #define DWC3_GHWPARAMS7 0xc15c
#define DWC3_GDBGFIFOSPACE 0xc160 #define DWC3_GDBGFIFOSPACE 0xc160
#define DWC3_GDBGLTSSM 0xc164 #define DWC3_GDBGLTSSM 0xc164
#define DWC3_GDBGBMU 0xc16c
#define DWC3_GDBGLSPMUX 0xc170
#define DWC3_GDBGLSP 0xc174
#define DWC3_GDBGEPINFO0 0xc178
#define DWC3_GDBGEPINFO1 0xc17c
#define DWC3_GPRTBIMAP_HS0 0xc180 #define DWC3_GPRTBIMAP_HS0 0xc180
#define DWC3_GPRTBIMAP_HS1 0xc184 #define DWC3_GPRTBIMAP_HS1 0xc184
#define DWC3_GPRTBIMAP_FS0 0xc188 #define DWC3_GPRTBIMAP_FS0 0xc188
...@@ -173,6 +183,26 @@ ...@@ -173,6 +183,26 @@
#define DWC3_GRXTHRCFG_RXPKTCNT(n) (((n) & 0xf) << 24) #define DWC3_GRXTHRCFG_RXPKTCNT(n) (((n) & 0xf) << 24)
#define DWC3_GRXTHRCFG_PKTCNTSEL BIT(29) #define DWC3_GRXTHRCFG_PKTCNTSEL BIT(29)
/* Global RX Threshold Configuration Register for DWC_usb31 only */
#define DWC31_GRXTHRCFG_MAXRXBURSTSIZE(n) (((n) & 0x1f) << 16)
#define DWC31_GRXTHRCFG_RXPKTCNT(n) (((n) & 0x1f) << 21)
#define DWC31_GRXTHRCFG_PKTCNTSEL BIT(26)
#define DWC31_RXTHRNUMPKTSEL_HS_PRD BIT(15)
#define DWC31_RXTHRNUMPKT_HS_PRD(n) (((n) & 0x3) << 13)
#define DWC31_RXTHRNUMPKTSEL_PRD BIT(10)
#define DWC31_RXTHRNUMPKT_PRD(n) (((n) & 0x1f) << 5)
#define DWC31_MAXRXBURSTSIZE_PRD(n) ((n) & 0x1f)
/* Global TX Threshold Configuration Register for DWC_usb31 only */
#define DWC31_GTXTHRCFG_MAXTXBURSTSIZE(n) (((n) & 0x1f) << 16)
#define DWC31_GTXTHRCFG_TXPKTCNT(n) (((n) & 0x1f) << 21)
#define DWC31_GTXTHRCFG_PKTCNTSEL BIT(26)
#define DWC31_TXTHRNUMPKTSEL_HS_PRD BIT(15)
#define DWC31_TXTHRNUMPKT_HS_PRD(n) (((n) & 0x3) << 13)
#define DWC31_TXTHRNUMPKTSEL_PRD BIT(10)
#define DWC31_TXTHRNUMPKT_PRD(n) (((n) & 0x1f) << 5)
#define DWC31_MAXTXBURSTSIZE_PRD(n) ((n) & 0x1f)
/* Global Configuration Register */ /* Global Configuration Register */
#define DWC3_GCTL_PWRDNSCALE(n) ((n) << 19) #define DWC3_GCTL_PWRDNSCALE(n) ((n) << 19)
#define DWC3_GCTL_U2RSTECN BIT(16) #define DWC3_GCTL_U2RSTECN BIT(16)
...@@ -201,6 +231,15 @@ ...@@ -201,6 +231,15 @@
#define DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS BIT(28) #define DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS BIT(28)
#define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24) #define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24)
/* Global Status Register */
#define DWC3_GSTS_OTG_IP BIT(10)
#define DWC3_GSTS_BC_IP BIT(9)
#define DWC3_GSTS_ADP_IP BIT(8)
#define DWC3_GSTS_HOST_IP BIT(7)
#define DWC3_GSTS_DEVICE_IP BIT(6)
#define DWC3_GSTS_CSR_TIMEOUT BIT(5)
#define DWC3_GSTS_BUS_ERR_ADDR_VLD BIT(4)
/* Global USB2 PHY Configuration Register */ /* Global USB2 PHY Configuration Register */
#define DWC3_GUSB2PHYCFG_PHYSOFTRST BIT(31) #define DWC3_GUSB2PHYCFG_PHYSOFTRST BIT(31)
#define DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS BIT(30) #define DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS BIT(30)
...@@ -241,6 +280,8 @@ ...@@ -241,6 +280,8 @@
#define DWC3_GUSB3PIPECTL_TX_DEEPH(n) ((n) << 1) #define DWC3_GUSB3PIPECTL_TX_DEEPH(n) ((n) << 1)
/* Global TX Fifo Size Register */ /* Global TX Fifo Size Register */
#define DWC31_GTXFIFOSIZ_TXFRAMNUM BIT(15) /* DWC_usb31 only */
#define DWC31_GTXFIFOSIZ_TXFDEF(n) ((n) & 0x7fff) /* DWC_usb31 only */
#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff) #define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff)
#define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000) #define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000)
...@@ -286,6 +327,11 @@ ...@@ -286,6 +327,11 @@
#define DWC3_MAX_HIBER_SCRATCHBUFS 15 #define DWC3_MAX_HIBER_SCRATCHBUFS 15
/* Global HWPARAMS6 Register */ /* Global HWPARAMS6 Register */
#define DWC3_GHWPARAMS6_BCSUPPORT BIT(14)
#define DWC3_GHWPARAMS6_OTG3SUPPORT BIT(13)
#define DWC3_GHWPARAMS6_ADPSUPPORT BIT(12)
#define DWC3_GHWPARAMS6_HNPSUPPORT BIT(11)
#define DWC3_GHWPARAMS6_SRPSUPPORT BIT(10)
#define DWC3_GHWPARAMS6_EN_FPGA BIT(7) #define DWC3_GHWPARAMS6_EN_FPGA BIT(7)
/* Global HWPARAMS7 Register */ /* Global HWPARAMS7 Register */
...@@ -467,6 +513,74 @@ ...@@ -467,6 +513,74 @@
#define DWC3_DEV_IMOD_INTERVAL_SHIFT 0 #define DWC3_DEV_IMOD_INTERVAL_SHIFT 0
#define DWC3_DEV_IMOD_INTERVAL_MASK (0xffff << 0) #define DWC3_DEV_IMOD_INTERVAL_MASK (0xffff << 0)
/* OTG Configuration Register */
#define DWC3_OCFG_DISPWRCUTTOFF BIT(5)
#define DWC3_OCFG_HIBDISMASK BIT(4)
#define DWC3_OCFG_SFTRSTMASK BIT(3)
#define DWC3_OCFG_OTGVERSION BIT(2)
#define DWC3_OCFG_HNPCAP BIT(1)
#define DWC3_OCFG_SRPCAP BIT(0)
/* OTG CTL Register */
#define DWC3_OCTL_OTG3GOERR BIT(7)
#define DWC3_OCTL_PERIMODE BIT(6)
#define DWC3_OCTL_PRTPWRCTL BIT(5)
#define DWC3_OCTL_HNPREQ BIT(4)
#define DWC3_OCTL_SESREQ BIT(3)
#define DWC3_OCTL_TERMSELIDPULSE BIT(2)
#define DWC3_OCTL_DEVSETHNPEN BIT(1)
#define DWC3_OCTL_HSTSETHNPEN BIT(0)
/* OTG Event Register */
#define DWC3_OEVT_DEVICEMODE BIT(31)
#define DWC3_OEVT_XHCIRUNSTPSET BIT(27)
#define DWC3_OEVT_DEVRUNSTPSET BIT(26)
#define DWC3_OEVT_HIBENTRY BIT(25)
#define DWC3_OEVT_CONIDSTSCHNG BIT(24)
#define DWC3_OEVT_HRRCONFNOTIF BIT(23)
#define DWC3_OEVT_HRRINITNOTIF BIT(22)
#define DWC3_OEVT_ADEVIDLE BIT(21)
#define DWC3_OEVT_ADEVBHOSTEND BIT(20)
#define DWC3_OEVT_ADEVHOST BIT(19)
#define DWC3_OEVT_ADEVHNPCHNG BIT(18)
#define DWC3_OEVT_ADEVSRPDET BIT(17)
#define DWC3_OEVT_ADEVSESSENDDET BIT(16)
#define DWC3_OEVT_BDEVBHOSTEND BIT(11)
#define DWC3_OEVT_BDEVHNPCHNG BIT(10)
#define DWC3_OEVT_BDEVSESSVLDDET BIT(9)
#define DWC3_OEVT_BDEVVBUSCHNG BIT(8)
#define DWC3_OEVT_BSESSVLD BIT(3)
#define DWC3_OEVT_HSTNEGSTS BIT(2)
#define DWC3_OEVT_SESREQSTS BIT(1)
#define DWC3_OEVT_ERROR BIT(0)
/* OTG Event Enable Register */
#define DWC3_OEVTEN_XHCIRUNSTPSETEN BIT(27)
#define DWC3_OEVTEN_DEVRUNSTPSETEN BIT(26)
#define DWC3_OEVTEN_HIBENTRYEN BIT(25)
#define DWC3_OEVTEN_CONIDSTSCHNGEN BIT(24)
#define DWC3_OEVTEN_HRRCONFNOTIFEN BIT(23)
#define DWC3_OEVTEN_HRRINITNOTIFEN BIT(22)
#define DWC3_OEVTEN_ADEVIDLEEN BIT(21)
#define DWC3_OEVTEN_ADEVBHOSTENDEN BIT(20)
#define DWC3_OEVTEN_ADEVHOSTEN BIT(19)
#define DWC3_OEVTEN_ADEVHNPCHNGEN BIT(18)
#define DWC3_OEVTEN_ADEVSRPDETEN BIT(17)
#define DWC3_OEVTEN_ADEVSESSENDDETEN BIT(16)
#define DWC3_OEVTEN_BDEVBHOSTENDEN BIT(11)
#define DWC3_OEVTEN_BDEVHNPCHNGEN BIT(10)
#define DWC3_OEVTEN_BDEVSESSVLDDETEN BIT(9)
#define DWC3_OEVTEN_BDEVVBUSCHNGEN BIT(8)
/* OTG Status Register */
#define DWC3_OSTS_DEVRUNSTP BIT(13)
#define DWC3_OSTS_XHCIRUNSTP BIT(12)
#define DWC3_OSTS_PERIPHERALSTATE BIT(4)
#define DWC3_OSTS_XHCIPRTPOWER BIT(3)
#define DWC3_OSTS_BSESVLD BIT(2)
#define DWC3_OSTS_VBUSVLD BIT(1)
#define DWC3_OSTS_CONIDSTS BIT(0)
/* Structures */ /* Structures */
struct dwc3_trb; struct dwc3_trb;
...@@ -781,6 +895,10 @@ struct dwc3_scratchpad_array { ...@@ -781,6 +895,10 @@ struct dwc3_scratchpad_array {
* @regs_size: address space size * @regs_size: address space size
* @fladj: frame length adjustment * @fladj: frame length adjustment
* @irq_gadget: peripheral controller's IRQ number * @irq_gadget: peripheral controller's IRQ number
* @otg_irq: IRQ number for OTG IRQs
* @current_otg_role: current role of operation while using the OTG block
* @desired_otg_role: desired role of operation while using the OTG block
* @otg_restart_host: flag that OTG controller needs to restart host
* @nr_scratch: number of scratch buffers * @nr_scratch: number of scratch buffers
* @u1u2: only used on revisions <1.83a for workaround * @u1u2: only used on revisions <1.83a for workaround
* @maximum_speed: maximum speed requested (mainly for testing purposes) * @maximum_speed: maximum speed requested (mainly for testing purposes)
...@@ -816,6 +934,10 @@ struct dwc3_scratchpad_array { ...@@ -816,6 +934,10 @@ struct dwc3_scratchpad_array {
* @test_mode_nr: test feature selector * @test_mode_nr: test feature selector
* @lpm_nyet_threshold: LPM NYET response threshold * @lpm_nyet_threshold: LPM NYET response threshold
* @hird_threshold: HIRD threshold * @hird_threshold: HIRD threshold
* @rx_thr_num_pkt_prd: periodic ESS receive packet count
* @rx_max_burst_prd: max periodic ESS receive burst size
* @tx_thr_num_pkt_prd: periodic ESS transmit packet count
* @tx_max_burst_prd: max periodic ESS transmit burst size
* @hsphy_interface: "utmi" or "ulpi" * @hsphy_interface: "utmi" or "ulpi"
* @connected: true when we're connected to a host, false otherwise * @connected: true when we're connected to a host, false otherwise
* @delayed_status: true when gadget driver asks for delayed status * @delayed_status: true when gadget driver asks for delayed status
...@@ -914,6 +1036,10 @@ struct dwc3 { ...@@ -914,6 +1036,10 @@ struct dwc3 {
u32 fladj; u32 fladj;
u32 irq_gadget; u32 irq_gadget;
u32 otg_irq;
u32 current_otg_role;
u32 desired_otg_role;
bool otg_restart_host;
u32 nr_scratch; u32 nr_scratch;
u32 u1u2; u32 u1u2;
u32 maximum_speed; u32 maximum_speed;
...@@ -979,6 +1105,10 @@ struct dwc3 { ...@@ -979,6 +1105,10 @@ struct dwc3 {
u8 test_mode_nr; u8 test_mode_nr;
u8 lpm_nyet_threshold; u8 lpm_nyet_threshold;
u8 hird_threshold; u8 hird_threshold;
u8 rx_thr_num_pkt_prd;
u8 rx_max_burst_prd;
u8 tx_thr_num_pkt_prd;
u8 tx_max_burst_prd;
const char *hsphy_interface; const char *hsphy_interface;
...@@ -1175,6 +1305,7 @@ struct dwc3_gadget_ep_cmd_params { ...@@ -1175,6 +1305,7 @@ struct dwc3_gadget_ep_cmd_params {
#define DWC3_HAS_OTG BIT(3) #define DWC3_HAS_OTG BIT(3)
/* prototypes */ /* prototypes */
void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode);
void dwc3_set_mode(struct dwc3 *dwc, u32 mode); void dwc3_set_mode(struct dwc3 *dwc, u32 mode);
u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type); u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type);
...@@ -1192,6 +1323,9 @@ static inline bool dwc3_is_usb31(struct dwc3 *dwc) ...@@ -1192,6 +1323,9 @@ static inline bool dwc3_is_usb31(struct dwc3 *dwc)
bool dwc3_has_imod(struct dwc3 *dwc); bool dwc3_has_imod(struct dwc3 *dwc);
int dwc3_event_buffers_setup(struct dwc3 *dwc);
void dwc3_event_buffers_cleanup(struct dwc3 *dwc);
#if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
int dwc3_host_init(struct dwc3 *dwc); int dwc3_host_init(struct dwc3 *dwc);
void dwc3_host_exit(struct dwc3 *dwc); void dwc3_host_exit(struct dwc3 *dwc);
...@@ -1235,11 +1369,23 @@ static inline int dwc3_send_gadget_generic_command(struct dwc3 *dwc, ...@@ -1235,11 +1369,23 @@ static inline int dwc3_send_gadget_generic_command(struct dwc3 *dwc,
#if IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) #if IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
int dwc3_drd_init(struct dwc3 *dwc); int dwc3_drd_init(struct dwc3 *dwc);
void dwc3_drd_exit(struct dwc3 *dwc); void dwc3_drd_exit(struct dwc3 *dwc);
void dwc3_otg_init(struct dwc3 *dwc);
void dwc3_otg_exit(struct dwc3 *dwc);
void dwc3_otg_update(struct dwc3 *dwc, bool ignore_idstatus);
void dwc3_otg_host_init(struct dwc3 *dwc);
#else #else
static inline int dwc3_drd_init(struct dwc3 *dwc) static inline int dwc3_drd_init(struct dwc3 *dwc)
{ return 0; } { return 0; }
static inline void dwc3_drd_exit(struct dwc3 *dwc) static inline void dwc3_drd_exit(struct dwc3 *dwc)
{ } { }
static inline void dwc3_otg_init(struct dwc3 *dwc)
{ }
static inline void dwc3_otg_exit(struct dwc3 *dwc)
{ }
static inline void dwc3_otg_update(struct dwc3 *dwc, bool ignore_idstatus)
{ }
static inline void dwc3_otg_host_init(struct dwc3 *dwc)
{ }
#endif #endif
/* power management interface */ /* power management interface */
......
...@@ -81,6 +81,11 @@ static const struct debugfs_reg32 dwc3_regs[] = { ...@@ -81,6 +81,11 @@ static const struct debugfs_reg32 dwc3_regs[] = {
dump_register(GHWPARAMS7), dump_register(GHWPARAMS7),
dump_register(GDBGFIFOSPACE), dump_register(GDBGFIFOSPACE),
dump_register(GDBGLTSSM), dump_register(GDBGLTSSM),
dump_register(GDBGBMU),
dump_register(GDBGLSPMUX),
dump_register(GDBGLSP),
dump_register(GDBGEPINFO0),
dump_register(GDBGEPINFO1),
dump_register(GPRTBIMAP_HS0), dump_register(GPRTBIMAP_HS0),
dump_register(GPRTBIMAP_HS1), dump_register(GPRTBIMAP_HS1),
dump_register(GPRTBIMAP_FS0), dump_register(GPRTBIMAP_FS0),
...@@ -487,8 +492,8 @@ static const struct file_operations dwc3_link_state_fops = { ...@@ -487,8 +492,8 @@ static const struct file_operations dwc3_link_state_fops = {
}; };
struct dwc3_ep_file_map { struct dwc3_ep_file_map {
char name[25]; const char name[25];
int (*show)(struct seq_file *s, void *unused); const struct file_operations *const fops;
}; };
static int dwc3_tx_fifo_queue_show(struct seq_file *s, void *unused) static int dwc3_tx_fifo_queue_show(struct seq_file *s, void *unused)
...@@ -596,7 +601,7 @@ static int dwc3_event_queue_show(struct seq_file *s, void *unused) ...@@ -596,7 +601,7 @@ static int dwc3_event_queue_show(struct seq_file *s, void *unused)
return 0; return 0;
} }
static int dwc3_ep_transfer_type_show(struct seq_file *s, void *unused) static int dwc3_transfer_type_show(struct seq_file *s, void *unused)
{ {
struct dwc3_ep *dep = s->private; struct dwc3_ep *dep = s->private;
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
...@@ -632,7 +637,7 @@ static int dwc3_ep_transfer_type_show(struct seq_file *s, void *unused) ...@@ -632,7 +637,7 @@ static int dwc3_ep_transfer_type_show(struct seq_file *s, void *unused)
return 0; return 0;
} }
static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused) static int dwc3_trb_ring_show(struct seq_file *s, void *unused)
{ {
struct dwc3_ep *dep = s->private; struct dwc3_ep *dep = s->private;
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
...@@ -670,58 +675,39 @@ static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused) ...@@ -670,58 +675,39 @@ static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused)
return 0; return 0;
} }
static struct dwc3_ep_file_map map[] = { DEFINE_SHOW_ATTRIBUTE(dwc3_tx_fifo_queue);
{ "tx_fifo_queue", dwc3_tx_fifo_queue_show, }, DEFINE_SHOW_ATTRIBUTE(dwc3_rx_fifo_queue);
{ "rx_fifo_queue", dwc3_rx_fifo_queue_show, }, DEFINE_SHOW_ATTRIBUTE(dwc3_tx_request_queue);
{ "tx_request_queue", dwc3_tx_request_queue_show, }, DEFINE_SHOW_ATTRIBUTE(dwc3_rx_request_queue);
{ "rx_request_queue", dwc3_rx_request_queue_show, }, DEFINE_SHOW_ATTRIBUTE(dwc3_rx_info_queue);
{ "rx_info_queue", dwc3_rx_info_queue_show, }, DEFINE_SHOW_ATTRIBUTE(dwc3_descriptor_fetch_queue);
{ "descriptor_fetch_queue", dwc3_descriptor_fetch_queue_show, }, DEFINE_SHOW_ATTRIBUTE(dwc3_event_queue);
{ "event_queue", dwc3_event_queue_show, }, DEFINE_SHOW_ATTRIBUTE(dwc3_transfer_type);
{ "transfer_type", dwc3_ep_transfer_type_show, }, DEFINE_SHOW_ATTRIBUTE(dwc3_trb_ring);
{ "trb_ring", dwc3_ep_trb_ring_show, },
static const struct dwc3_ep_file_map dwc3_ep_file_map[] = {
{ "tx_fifo_queue", &dwc3_tx_fifo_queue_fops, },
{ "rx_fifo_queue", &dwc3_rx_fifo_queue_fops, },
{ "tx_request_queue", &dwc3_tx_request_queue_fops, },
{ "rx_request_queue", &dwc3_rx_request_queue_fops, },
{ "rx_info_queue", &dwc3_rx_info_queue_fops, },
{ "descriptor_fetch_queue", &dwc3_descriptor_fetch_queue_fops, },
{ "event_queue", &dwc3_event_queue_fops, },
{ "transfer_type", &dwc3_transfer_type_fops, },
{ "trb_ring", &dwc3_trb_ring_fops, },
}; };
static int dwc3_endpoint_open(struct inode *inode, struct file *file)
{
const char *file_name = file_dentry(file)->d_iname;
struct dwc3_ep_file_map *f_map;
int i;
for (i = 0; i < ARRAY_SIZE(map); i++) {
f_map = &map[i];
if (strcmp(f_map->name, file_name) == 0)
break;
}
return single_open(file, f_map->show, inode->i_private);
}
static const struct file_operations dwc3_endpoint_fops = {
.open = dwc3_endpoint_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static void dwc3_debugfs_create_endpoint_file(struct dwc3_ep *dep,
struct dentry *parent, int type)
{
struct dentry *file;
struct dwc3_ep_file_map *ep_file = &map[type];
file = debugfs_create_file(ep_file->name, S_IRUGO, parent, dep,
&dwc3_endpoint_fops);
}
static void dwc3_debugfs_create_endpoint_files(struct dwc3_ep *dep, static void dwc3_debugfs_create_endpoint_files(struct dwc3_ep *dep,
struct dentry *parent) struct dentry *parent)
{ {
int i; int i;
for (i = 0; i < ARRAY_SIZE(map); i++) for (i = 0; i < ARRAY_SIZE(dwc3_ep_file_map); i++) {
dwc3_debugfs_create_endpoint_file(dep, parent, i); const struct file_operations *fops = dwc3_ep_file_map[i].fops;
const char *name = dwc3_ep_file_map[i].name;
debugfs_create_file(name, S_IRUGO, parent, dep, fops);
}
} }
static void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep, static void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep,
......
This diff is collapsed.
...@@ -27,6 +27,7 @@ struct dwc3_of_simple { ...@@ -27,6 +27,7 @@ struct dwc3_of_simple {
struct clk **clks; struct clk **clks;
int num_clocks; int num_clocks;
struct reset_control *resets; struct reset_control *resets;
bool pulse_resets;
}; };
static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count) static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count)
...@@ -83,6 +84,7 @@ static int dwc3_of_simple_probe(struct platform_device *pdev) ...@@ -83,6 +84,7 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
int ret; int ret;
int i; int i;
bool shared_resets = false;
simple = devm_kzalloc(dev, sizeof(*simple), GFP_KERNEL); simple = devm_kzalloc(dev, sizeof(*simple), GFP_KERNEL);
if (!simple) if (!simple)
...@@ -91,16 +93,28 @@ static int dwc3_of_simple_probe(struct platform_device *pdev) ...@@ -91,16 +93,28 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, simple); platform_set_drvdata(pdev, simple);
simple->dev = dev; simple->dev = dev;
simple->resets = of_reset_control_array_get_optional_exclusive(np); if (of_device_is_compatible(np, "amlogic,meson-axg-dwc3") ||
of_device_is_compatible(np, "amlogic,meson-gxl-dwc3")) {
shared_resets = true;
simple->pulse_resets = true;
}
simple->resets = of_reset_control_array_get(np, shared_resets, true);
if (IS_ERR(simple->resets)) { if (IS_ERR(simple->resets)) {
ret = PTR_ERR(simple->resets); ret = PTR_ERR(simple->resets);
dev_err(dev, "failed to get device resets, err=%d\n", ret); dev_err(dev, "failed to get device resets, err=%d\n", ret);
return ret; return ret;
} }
ret = reset_control_deassert(simple->resets); if (simple->pulse_resets) {
if (ret) ret = reset_control_reset(simple->resets);
goto err_resetc_put; if (ret)
goto err_resetc_put;
} else {
ret = reset_control_deassert(simple->resets);
if (ret)
goto err_resetc_put;
}
ret = dwc3_of_simple_clk_init(simple, of_count_phandle_with_args(np, ret = dwc3_of_simple_clk_init(simple, of_count_phandle_with_args(np,
"clocks", "#clock-cells")); "clocks", "#clock-cells"));
...@@ -124,7 +138,8 @@ static int dwc3_of_simple_probe(struct platform_device *pdev) ...@@ -124,7 +138,8 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
return 0; return 0;
err_resetc_assert: err_resetc_assert:
reset_control_assert(simple->resets); if (!simple->pulse_resets)
reset_control_assert(simple->resets);
err_resetc_put: err_resetc_put:
reset_control_put(simple->resets); reset_control_put(simple->resets);
...@@ -145,7 +160,9 @@ static int dwc3_of_simple_remove(struct platform_device *pdev) ...@@ -145,7 +160,9 @@ static int dwc3_of_simple_remove(struct platform_device *pdev)
} }
simple->num_clocks = 0; simple->num_clocks = 0;
reset_control_assert(simple->resets); if (!simple->pulse_resets)
reset_control_assert(simple->resets);
reset_control_put(simple->resets); reset_control_put(simple->resets);
pm_runtime_put_sync(dev); pm_runtime_put_sync(dev);
...@@ -196,6 +213,8 @@ static const struct of_device_id of_dwc3_simple_match[] = { ...@@ -196,6 +213,8 @@ static const struct of_device_id of_dwc3_simple_match[] = {
{ .compatible = "xlnx,zynqmp-dwc3" }, { .compatible = "xlnx,zynqmp-dwc3" },
{ .compatible = "cavium,octeon-7130-usb-uctl" }, { .compatible = "cavium,octeon-7130-usb-uctl" },
{ .compatible = "sprd,sc9860-dwc3" }, { .compatible = "sprd,sc9860-dwc3" },
{ .compatible = "amlogic,meson-axg-dwc3" },
{ .compatible = "amlogic,meson-gxl-dwc3" },
{ /* Sentinel */ } { /* Sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, of_dwc3_simple_match); MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
......
...@@ -222,7 +222,7 @@ static int dwc3_pci_probe(struct pci_dev *pci, ...@@ -222,7 +222,7 @@ static int dwc3_pci_probe(struct pci_dev *pci,
ret = platform_device_add_resources(dwc->dwc3, res, ARRAY_SIZE(res)); ret = platform_device_add_resources(dwc->dwc3, res, ARRAY_SIZE(res));
if (ret) { if (ret) {
dev_err(dev, "couldn't add resources to dwc3 device\n"); dev_err(dev, "couldn't add resources to dwc3 device\n");
return ret; goto err;
} }
dwc->pci = pci; dwc->pci = pci;
......
...@@ -814,7 +814,7 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, ...@@ -814,7 +814,7 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc,
static void dwc3_ep0_complete_data(struct dwc3 *dwc, static void dwc3_ep0_complete_data(struct dwc3 *dwc,
const struct dwc3_event_depevt *event) const struct dwc3_event_depevt *event)
{ {
struct dwc3_request *r = NULL; struct dwc3_request *r;
struct usb_request *ur; struct usb_request *ur;
struct dwc3_trb *trb; struct dwc3_trb *trb;
struct dwc3_ep *ep0; struct dwc3_ep *ep0;
......
...@@ -1858,7 +1858,11 @@ static int __dwc3_gadget_start(struct dwc3 *dwc) ...@@ -1858,7 +1858,11 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
* bursts of data without going through any sort of endpoint throttling. * bursts of data without going through any sort of endpoint throttling.
*/ */
reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG); reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
reg &= ~DWC3_GRXTHRCFG_PKTCNTSEL; if (dwc3_is_usb31(dwc))
reg &= ~DWC31_GRXTHRCFG_PKTCNTSEL;
else
reg &= ~DWC3_GRXTHRCFG_PKTCNTSEL;
dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg); dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
dwc3_gadget_setup_nump(dwc); dwc3_gadget_setup_nump(dwc);
...@@ -1950,6 +1954,7 @@ static int dwc3_gadget_stop(struct usb_gadget *g) ...@@ -1950,6 +1954,7 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
struct dwc3 *dwc = gadget_to_dwc(g); struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long flags; unsigned long flags;
int epnum; int epnum;
u32 tmo_eps = 0;
spin_lock_irqsave(&dwc->lock, flags); spin_lock_irqsave(&dwc->lock, flags);
...@@ -1960,6 +1965,7 @@ static int dwc3_gadget_stop(struct usb_gadget *g) ...@@ -1960,6 +1965,7 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) { for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
struct dwc3_ep *dep = dwc->eps[epnum]; struct dwc3_ep *dep = dwc->eps[epnum];
int ret;
if (!dep) if (!dep)
continue; continue;
...@@ -1967,9 +1973,24 @@ static int dwc3_gadget_stop(struct usb_gadget *g) ...@@ -1967,9 +1973,24 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
continue; continue;
wait_event_lock_irq(dep->wait_end_transfer, ret = wait_event_interruptible_lock_irq_timeout(dep->wait_end_transfer,
!(dep->flags & DWC3_EP_END_TRANSFER_PENDING), !(dep->flags & DWC3_EP_END_TRANSFER_PENDING),
dwc->lock); dwc->lock, msecs_to_jiffies(5));
if (ret <= 0) {
/* Timed out or interrupted! There's nothing much
* we can do so we just log here and print which
* endpoints timed out at the end.
*/
tmo_eps |= 1 << epnum;
dep->flags &= DWC3_EP_END_TRANSFER_PENDING;
}
}
if (tmo_eps) {
dev_err(dwc->dev,
"end transfer timed out on endpoints 0x%x [bitmap]\n",
tmo_eps);
} }
out: out:
...@@ -2023,7 +2044,10 @@ static void dwc3_gadget_set_speed(struct usb_gadget *g, ...@@ -2023,7 +2044,10 @@ static void dwc3_gadget_set_speed(struct usb_gadget *g,
reg |= DWC3_DCFG_SUPERSPEED; reg |= DWC3_DCFG_SUPERSPEED;
break; break;
case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER_PLUS:
reg |= DWC3_DCFG_SUPERSPEED_PLUS; if (dwc3_is_usb31(dwc))
reg |= DWC3_DCFG_SUPERSPEED_PLUS;
else
reg |= DWC3_DCFG_SUPERSPEED;
break; break;
default: default:
dev_err(dwc->dev, "invalid speed (%d)\n", speed); dev_err(dwc->dev, "invalid speed (%d)\n", speed);
...@@ -2101,7 +2125,10 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 total) ...@@ -2101,7 +2125,10 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 total)
mdwidth /= 8; mdwidth /= 8;
size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(num)); size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(num));
size = DWC3_GTXFIFOSIZ_TXFDEF(size); if (dwc3_is_usb31(dwc))
size = DWC31_GTXFIFOSIZ_TXFDEF(size);
else
size = DWC3_GTXFIFOSIZ_TXFDEF(size);
/* FIFO Depth is in MDWDITH bytes. Multiply */ /* FIFO Depth is in MDWDITH bytes. Multiply */
size *= mdwidth; size *= mdwidth;
......
...@@ -1422,11 +1422,12 @@ static int count_ext_compat(struct usb_configuration *c) ...@@ -1422,11 +1422,12 @@ static int count_ext_compat(struct usb_configuration *c)
return res; return res;
} }
static void fill_ext_compat(struct usb_configuration *c, u8 *buf) static int fill_ext_compat(struct usb_configuration *c, u8 *buf)
{ {
int i, count; int i, count;
count = 16; count = 16;
buf += 16;
for (i = 0; i < c->next_interface_id; ++i) { for (i = 0; i < c->next_interface_id; ++i) {
struct usb_function *f; struct usb_function *f;
int j; int j;
...@@ -1449,10 +1450,12 @@ static void fill_ext_compat(struct usb_configuration *c, u8 *buf) ...@@ -1449,10 +1450,12 @@ static void fill_ext_compat(struct usb_configuration *c, u8 *buf)
buf += 23; buf += 23;
} }
count += 24; count += 24;
if (count >= 4096) if (count + 24 >= USB_COMP_EP0_OS_DESC_BUFSIZ)
return; return count;
} }
} }
return count;
} }
static int count_ext_prop(struct usb_configuration *c, int interface) static int count_ext_prop(struct usb_configuration *c, int interface)
...@@ -1497,25 +1500,21 @@ static int fill_ext_prop(struct usb_configuration *c, int interface, u8 *buf) ...@@ -1497,25 +1500,21 @@ static int fill_ext_prop(struct usb_configuration *c, int interface, u8 *buf)
struct usb_os_desc *d; struct usb_os_desc *d;
struct usb_os_desc_ext_prop *ext_prop; struct usb_os_desc_ext_prop *ext_prop;
int j, count, n, ret; int j, count, n, ret;
u8 *start = buf;
f = c->interface[interface]; f = c->interface[interface];
count = 10; /* header length */
buf += 10;
for (j = 0; j < f->os_desc_n; ++j) { for (j = 0; j < f->os_desc_n; ++j) {
if (interface != f->os_desc_table[j].if_id) if (interface != f->os_desc_table[j].if_id)
continue; continue;
d = f->os_desc_table[j].os_desc; d = f->os_desc_table[j].os_desc;
if (d) if (d)
list_for_each_entry(ext_prop, &d->ext_prop, entry) { list_for_each_entry(ext_prop, &d->ext_prop, entry) {
/* 4kB minus header length */ n = ext_prop->data_len +
n = buf - start;
if (n >= 4086)
return 0;
count = ext_prop->data_len +
ext_prop->name_len + 14; ext_prop->name_len + 14;
if (count > 4086 - n) if (count + n >= USB_COMP_EP0_OS_DESC_BUFSIZ)
return -EINVAL; return count;
usb_ext_prop_put_size(buf, count); usb_ext_prop_put_size(buf, n);
usb_ext_prop_put_type(buf, ext_prop->type); usb_ext_prop_put_type(buf, ext_prop->type);
ret = usb_ext_prop_put_name(buf, ext_prop->name, ret = usb_ext_prop_put_name(buf, ext_prop->name,
ext_prop->name_len); ext_prop->name_len);
...@@ -1541,11 +1540,12 @@ static int fill_ext_prop(struct usb_configuration *c, int interface, u8 *buf) ...@@ -1541,11 +1540,12 @@ static int fill_ext_prop(struct usb_configuration *c, int interface, u8 *buf)
default: default:
return -EINVAL; return -EINVAL;
} }
buf += count; buf += n;
count += n;
} }
} }
return 0; return count;
} }
/* /*
...@@ -1827,6 +1827,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1827,6 +1827,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
req->complete = composite_setup_complete; req->complete = composite_setup_complete;
buf = req->buf; buf = req->buf;
os_desc_cfg = cdev->os_desc_config; os_desc_cfg = cdev->os_desc_config;
w_length = min_t(u16, w_length, USB_COMP_EP0_OS_DESC_BUFSIZ);
memset(buf, 0, w_length); memset(buf, 0, w_length);
buf[5] = 0x01; buf[5] = 0x01;
switch (ctrl->bRequestType & USB_RECIP_MASK) { switch (ctrl->bRequestType & USB_RECIP_MASK) {
...@@ -1834,24 +1835,16 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1834,24 +1835,16 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (w_index != 0x4 || (w_value >> 8)) if (w_index != 0x4 || (w_value >> 8))
break; break;
buf[6] = w_index; buf[6] = w_index;
if (w_length == 0x10) { /* Number of ext compat interfaces */
/* Number of ext compat interfaces */ count = count_ext_compat(os_desc_cfg);
count = count_ext_compat(os_desc_cfg); buf[8] = count;
buf[8] = count; count *= 24; /* 24 B/ext compat desc */
count *= 24; /* 24 B/ext compat desc */ count += 16; /* header */
count += 16; /* header */ put_unaligned_le32(count, buf);
put_unaligned_le32(count, buf); value = w_length;
value = w_length; if (w_length > 0x10) {
} else { value = fill_ext_compat(os_desc_cfg, buf);
/* "extended compatibility ID"s */ value = min_t(u16, w_length, value);
count = count_ext_compat(os_desc_cfg);
buf[8] = count;
count *= 24; /* 24 B/ext compat desc */
count += 16; /* header */
put_unaligned_le32(count, buf);
buf += 16;
fill_ext_compat(os_desc_cfg, buf);
value = w_length;
} }
break; break;
case USB_RECIP_INTERFACE: case USB_RECIP_INTERFACE:
...@@ -1859,47 +1852,23 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1859,47 +1852,23 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
break; break;
interface = w_value & 0xFF; interface = w_value & 0xFF;
buf[6] = w_index; buf[6] = w_index;
if (w_length == 0x0A) { count = count_ext_prop(os_desc_cfg,
count = count_ext_prop(os_desc_cfg, interface);
interface); put_unaligned_le16(count, buf + 8);
put_unaligned_le16(count, buf + 8); count = len_ext_prop(os_desc_cfg,
count = len_ext_prop(os_desc_cfg, interface);
interface); put_unaligned_le32(count, buf);
put_unaligned_le32(count, buf); value = w_length;
if (w_length > 0x0A) {
value = w_length;
} else {
count = count_ext_prop(os_desc_cfg,
interface);
put_unaligned_le16(count, buf + 8);
count = len_ext_prop(os_desc_cfg,
interface);
put_unaligned_le32(count, buf);
buf += 10;
value = fill_ext_prop(os_desc_cfg, value = fill_ext_prop(os_desc_cfg,
interface, buf); interface, buf);
if (value < 0) if (value >= 0)
return value; value = min_t(u16, w_length, value);
value = w_length;
} }
break; break;
} }
if (value >= 0) { goto check_value;
req->length = value;
req->context = cdev;
req->zero = value < w_length;
value = composite_ep0_queue(cdev, req,
GFP_ATOMIC);
if (value < 0) {
DBG(cdev, "ep_queue --> %d\n", value);
req->status = 0;
composite_setup_complete(gadget->ep0,
req);
}
}
return value;
} }
VDBG(cdev, VDBG(cdev,
...@@ -1973,6 +1942,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1973,6 +1942,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
goto done; goto done;
} }
check_value:
/* respond with data transfer before status phase? */ /* respond with data transfer before status phase? */
if (value >= 0 && value != USB_GADGET_DELAYED_STATUS) { if (value >= 0 && value != USB_GADGET_DELAYED_STATUS) {
req->length = value; req->length = value;
...@@ -2156,8 +2126,8 @@ int composite_os_desc_req_prepare(struct usb_composite_dev *cdev, ...@@ -2156,8 +2126,8 @@ int composite_os_desc_req_prepare(struct usb_composite_dev *cdev,
goto end; goto end;
} }
/* OS feature descriptor length <= 4kB */ cdev->os_desc_req->buf = kmalloc(USB_COMP_EP0_OS_DESC_BUFSIZ,
cdev->os_desc_req->buf = kmalloc(4096, GFP_KERNEL); GFP_KERNEL);
if (!cdev->os_desc_req->buf) { if (!cdev->os_desc_req->buf) {
ret = -ENOMEM; ret = -ENOMEM;
usb_ep_free_request(ep0, cdev->os_desc_req); usb_ep_free_request(ep0, cdev->os_desc_req);
...@@ -2172,6 +2142,7 @@ int composite_os_desc_req_prepare(struct usb_composite_dev *cdev, ...@@ -2172,6 +2142,7 @@ int composite_os_desc_req_prepare(struct usb_composite_dev *cdev,
void composite_dev_cleanup(struct usb_composite_dev *cdev) void composite_dev_cleanup(struct usb_composite_dev *cdev)
{ {
struct usb_gadget_string_container *uc, *tmp; struct usb_gadget_string_container *uc, *tmp;
struct usb_ep *ep, *tmp_ep;
list_for_each_entry_safe(uc, tmp, &cdev->gstrings, list) { list_for_each_entry_safe(uc, tmp, &cdev->gstrings, list) {
list_del(&uc->list); list_del(&uc->list);
...@@ -2193,6 +2164,21 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev) ...@@ -2193,6 +2164,21 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
} }
cdev->next_string_id = 0; cdev->next_string_id = 0;
device_remove_file(&cdev->gadget->dev, &dev_attr_suspended); device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);
/*
* Some UDC backends have a dynamic EP allocation scheme.
*
* In that case, the dispose() callback is used to notify the
* backend that the EPs are no longer in use.
*
* Note: The UDC backend can remove the EP from the ep_list as
* a result, so we need to use the _safe list iterator.
*/
list_for_each_entry_safe(ep, tmp_ep,
&cdev->gadget->ep_list, ep_list) {
if (ep->ops->dispose)
ep->ops->dispose(ep);
}
} }
static int composite_bind(struct usb_gadget *gadget, static int composite_bind(struct usb_gadget *gadget,
......
...@@ -758,9 +758,13 @@ static void ffs_user_copy_worker(struct work_struct *work) ...@@ -758,9 +758,13 @@ static void ffs_user_copy_worker(struct work_struct *work)
bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD; bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;
if (io_data->read && ret > 0) { if (io_data->read && ret > 0) {
mm_segment_t oldfs = get_fs();
set_fs(USER_DS);
use_mm(io_data->mm); use_mm(io_data->mm);
ret = ffs_copy_to_iter(io_data->buf, ret, &io_data->data); ret = ffs_copy_to_iter(io_data->buf, ret, &io_data->data);
unuse_mm(io_data->mm); unuse_mm(io_data->mm);
set_fs(oldfs);
} }
io_data->kiocb->ki_complete(io_data->kiocb, ret, ret); io_data->kiocb->ki_complete(io_data->kiocb, ret, ret);
...@@ -3238,7 +3242,7 @@ static int ffs_func_setup(struct usb_function *f, ...@@ -3238,7 +3242,7 @@ static int ffs_func_setup(struct usb_function *f,
__ffs_event_add(ffs, FUNCTIONFS_SETUP); __ffs_event_add(ffs, FUNCTIONFS_SETUP);
spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags); spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
return 0; return USB_GADGET_DELAYED_STATUS;
} }
static bool ffs_func_req_match(struct usb_function *f, static bool ffs_func_req_match(struct usb_function *f,
......
...@@ -1094,7 +1094,7 @@ static int usbg_submit_command(struct f_uas *fu, ...@@ -1094,7 +1094,7 @@ static int usbg_submit_command(struct f_uas *fu,
struct command_iu *cmd_iu = cmdbuf; struct command_iu *cmd_iu = cmdbuf;
struct usbg_cmd *cmd; struct usbg_cmd *cmd;
struct usbg_tpg *tpg = fu->tpg; struct usbg_tpg *tpg = fu->tpg;
struct tcm_usbg_nexus *tv_nexus = tpg->tpg_nexus; struct tcm_usbg_nexus *tv_nexus;
u32 cmd_len; u32 cmd_len;
u16 scsi_tag; u16 scsi_tag;
......
...@@ -225,7 +225,7 @@ static int msg_unbind(struct usb_composite_dev *cdev) ...@@ -225,7 +225,7 @@ static int msg_unbind(struct usb_composite_dev *cdev)
static struct usb_composite_driver msg_driver = { static struct usb_composite_driver msg_driver = {
.name = "g_mass_storage", .name = "g_mass_storage",
.dev = &msg_device_desc, .dev = &msg_device_desc,
.max_speed = USB_SPEED_SUPER, .max_speed = USB_SPEED_SUPER_PLUS,
.needs_serial = 1, .needs_serial = 1,
.strings = dev_strings, .strings = dev_strings,
.bind = msg_bind, .bind = msg_bind,
......
...@@ -23,7 +23,8 @@ ...@@ -23,7 +23,8 @@
#include <linux/usb/atmel_usba_udc.h> #include <linux/usb/atmel_usba_udc.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h> #include <linux/irq.h>
#include <linux/gpio/consumer.h>
#include "atmel_usba_udc.h" #include "atmel_usba_udc.h"
#define USBA_VBUS_IRQFLAGS (IRQF_ONESHOT \ #define USBA_VBUS_IRQFLAGS (IRQF_ONESHOT \
...@@ -415,8 +416,8 @@ static inline void usba_int_enb_set(struct usba_udc *udc, u32 val) ...@@ -415,8 +416,8 @@ static inline void usba_int_enb_set(struct usba_udc *udc, u32 val)
static int vbus_is_present(struct usba_udc *udc) static int vbus_is_present(struct usba_udc *udc)
{ {
if (gpio_is_valid(udc->vbus_pin)) if (udc->vbus_pin)
return gpio_get_value(udc->vbus_pin) ^ udc->vbus_pin_inverted; return gpiod_get_value(udc->vbus_pin) ^ udc->vbus_pin_inverted;
/* No Vbus detection: Assume always present */ /* No Vbus detection: Assume always present */
return 1; return 1;
...@@ -1975,8 +1976,8 @@ static int atmel_usba_start(struct usb_gadget *gadget, ...@@ -1975,8 +1976,8 @@ static int atmel_usba_start(struct usb_gadget *gadget,
mutex_lock(&udc->vbus_mutex); mutex_lock(&udc->vbus_mutex);
if (gpio_is_valid(udc->vbus_pin)) if (udc->vbus_pin)
enable_irq(gpio_to_irq(udc->vbus_pin)); enable_irq(gpiod_to_irq(udc->vbus_pin));
/* If Vbus is present, enable the controller and wait for reset */ /* If Vbus is present, enable the controller and wait for reset */
udc->vbus_prev = vbus_is_present(udc); udc->vbus_prev = vbus_is_present(udc);
...@@ -1990,8 +1991,8 @@ static int atmel_usba_start(struct usb_gadget *gadget, ...@@ -1990,8 +1991,8 @@ static int atmel_usba_start(struct usb_gadget *gadget,
return 0; return 0;
err: err:
if (gpio_is_valid(udc->vbus_pin)) if (udc->vbus_pin)
disable_irq(gpio_to_irq(udc->vbus_pin)); disable_irq(gpiod_to_irq(udc->vbus_pin));
mutex_unlock(&udc->vbus_mutex); mutex_unlock(&udc->vbus_mutex);
...@@ -2006,8 +2007,8 @@ static int atmel_usba_stop(struct usb_gadget *gadget) ...@@ -2006,8 +2007,8 @@ static int atmel_usba_stop(struct usb_gadget *gadget)
{ {
struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget); struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget);
if (gpio_is_valid(udc->vbus_pin)) if (udc->vbus_pin)
disable_irq(gpio_to_irq(udc->vbus_pin)); disable_irq(gpiod_to_irq(udc->vbus_pin));
if (fifo_mode == 0) if (fifo_mode == 0)
udc->configured_ep = 1; udc->configured_ep = 1;
...@@ -2019,7 +2020,6 @@ static int atmel_usba_stop(struct usb_gadget *gadget) ...@@ -2019,7 +2020,6 @@ static int atmel_usba_stop(struct usb_gadget *gadget)
return 0; return 0;
} }
#ifdef CONFIG_OF
static void at91sam9rl_toggle_bias(struct usba_udc *udc, int is_on) static void at91sam9rl_toggle_bias(struct usba_udc *udc, int is_on)
{ {
regmap_update_bits(udc->pmc, AT91_CKGR_UCKR, AT91_PMC_BIASEN, regmap_update_bits(udc->pmc, AT91_CKGR_UCKR, AT91_PMC_BIASEN,
...@@ -2055,7 +2055,6 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, ...@@ -2055,7 +2055,6 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
{ {
u32 val; u32 val;
const char *name; const char *name;
enum of_gpio_flags flags;
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
const struct of_device_id *match; const struct of_device_id *match;
struct device_node *pp; struct device_node *pp;
...@@ -2075,9 +2074,9 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, ...@@ -2075,9 +2074,9 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
udc->num_ep = 0; udc->num_ep = 0;
udc->vbus_pin = of_get_named_gpio_flags(np, "atmel,vbus-gpio", 0, udc->vbus_pin = devm_gpiod_get_optional(&pdev->dev, "atmel,vbus",
&flags); GPIOD_IN);
udc->vbus_pin_inverted = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0; udc->vbus_pin_inverted = gpiod_is_active_low(udc->vbus_pin);
if (fifo_mode == 0) { if (fifo_mode == 0) {
pp = NULL; pp = NULL;
...@@ -2204,75 +2203,10 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, ...@@ -2204,75 +2203,10 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
err: err:
return ERR_PTR(ret); return ERR_PTR(ret);
} }
#else
static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
struct usba_udc *udc)
{
return ERR_PTR(-ENOSYS);
}
#endif
static struct usba_ep * usba_udc_pdata(struct platform_device *pdev,
struct usba_udc *udc)
{
struct usba_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct usba_ep *eps;
int i;
if (!pdata)
return ERR_PTR(-ENXIO);
eps = devm_kzalloc(&pdev->dev, sizeof(struct usba_ep) * pdata->num_ep,
GFP_KERNEL);
if (!eps)
return ERR_PTR(-ENOMEM);
udc->gadget.ep0 = &eps[0].ep;
udc->vbus_pin = pdata->vbus_pin;
udc->vbus_pin_inverted = pdata->vbus_pin_inverted;
udc->num_ep = pdata->num_ep;
INIT_LIST_HEAD(&eps[0].ep.ep_list);
for (i = 0; i < pdata->num_ep; i++) {
struct usba_ep *ep = &eps[i];
ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
ep->ep.ops = &usba_ep_ops;
ep->ep.name = pdata->ep[i].name;
ep->fifo_size = pdata->ep[i].fifo_size;
usb_ep_set_maxpacket_limit(&ep->ep, ep->fifo_size);
ep->udc = udc;
INIT_LIST_HEAD(&ep->queue);
ep->nr_banks = pdata->ep[i].nr_banks;
ep->index = pdata->ep[i].index;
ep->can_dma = pdata->ep[i].can_dma;
ep->can_isoc = pdata->ep[i].can_isoc;
if (i == 0) {
ep->ep.caps.type_control = true;
} else {
ep->ep.caps.type_iso = ep->can_isoc;
ep->ep.caps.type_bulk = true;
ep->ep.caps.type_int = true;
}
ep->ep.caps.dir_in = true;
ep->ep.caps.dir_out = true;
if (i)
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
}
return eps;
}
static int usba_udc_probe(struct platform_device *pdev) static int usba_udc_probe(struct platform_device *pdev)
{ {
struct resource *regs, *fifo; struct resource *res;
struct clk *pclk, *hclk; struct clk *pclk, *hclk;
struct usba_udc *udc; struct usba_udc *udc;
int irq, ret, i; int irq, ret, i;
...@@ -2284,10 +2218,18 @@ static int usba_udc_probe(struct platform_device *pdev) ...@@ -2284,10 +2218,18 @@ static int usba_udc_probe(struct platform_device *pdev)
udc->gadget = usba_gadget_template; udc->gadget = usba_gadget_template;
INIT_LIST_HEAD(&udc->gadget.ep_list); INIT_LIST_HEAD(&udc->gadget.ep_list);
regs = platform_get_resource(pdev, IORESOURCE_MEM, CTRL_IOMEM_ID); res = platform_get_resource(pdev, IORESOURCE_MEM, CTRL_IOMEM_ID);
fifo = platform_get_resource(pdev, IORESOURCE_MEM, FIFO_IOMEM_ID); udc->regs = devm_ioremap_resource(&pdev->dev, res);
if (!regs || !fifo) if (IS_ERR(udc->regs))
return -ENXIO; return PTR_ERR(udc->regs);
dev_info(&pdev->dev, "MMIO registers at %pR mapped at %p\n",
res, udc->regs);
res = platform_get_resource(pdev, IORESOURCE_MEM, FIFO_IOMEM_ID);
udc->fifo = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(udc->fifo))
return PTR_ERR(udc->fifo);
dev_info(&pdev->dev, "FIFO at %pR mapped at %p\n", res, udc->fifo);
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) if (irq < 0)
...@@ -2305,23 +2247,6 @@ static int usba_udc_probe(struct platform_device *pdev) ...@@ -2305,23 +2247,6 @@ static int usba_udc_probe(struct platform_device *pdev)
udc->pdev = pdev; udc->pdev = pdev;
udc->pclk = pclk; udc->pclk = pclk;
udc->hclk = hclk; udc->hclk = hclk;
udc->vbus_pin = -ENODEV;
ret = -ENOMEM;
udc->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
if (!udc->regs) {
dev_err(&pdev->dev, "Unable to map I/O memory, aborting.\n");
return ret;
}
dev_info(&pdev->dev, "MMIO registers at 0x%08lx mapped at %p\n",
(unsigned long)regs->start, udc->regs);
udc->fifo = devm_ioremap(&pdev->dev, fifo->start, resource_size(fifo));
if (!udc->fifo) {
dev_err(&pdev->dev, "Unable to map FIFO, aborting.\n");
return ret;
}
dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",
(unsigned long)fifo->start, udc->fifo);
platform_set_drvdata(pdev, udc); platform_set_drvdata(pdev, udc);
...@@ -2335,10 +2260,7 @@ static int usba_udc_probe(struct platform_device *pdev) ...@@ -2335,10 +2260,7 @@ static int usba_udc_probe(struct platform_device *pdev)
usba_writel(udc, CTRL, USBA_DISABLE_MASK); usba_writel(udc, CTRL, USBA_DISABLE_MASK);
clk_disable_unprepare(pclk); clk_disable_unprepare(pclk);
if (pdev->dev.of_node) udc->usba_ep = atmel_udc_of_init(pdev, udc);
udc->usba_ep = atmel_udc_of_init(pdev, udc);
else
udc->usba_ep = usba_udc_pdata(pdev, udc);
toggle_bias(udc, 0); toggle_bias(udc, 0);
...@@ -2354,24 +2276,18 @@ static int usba_udc_probe(struct platform_device *pdev) ...@@ -2354,24 +2276,18 @@ static int usba_udc_probe(struct platform_device *pdev)
} }
udc->irq = irq; udc->irq = irq;
if (gpio_is_valid(udc->vbus_pin)) { if (udc->vbus_pin) {
if (!devm_gpio_request(&pdev->dev, udc->vbus_pin, "atmel_usba_udc")) { irq_set_status_flags(gpiod_to_irq(udc->vbus_pin), IRQ_NOAUTOEN);
irq_set_status_flags(gpio_to_irq(udc->vbus_pin), ret = devm_request_threaded_irq(&pdev->dev,
IRQ_NOAUTOEN); gpiod_to_irq(udc->vbus_pin), NULL,
ret = devm_request_threaded_irq(&pdev->dev,
gpio_to_irq(udc->vbus_pin), NULL,
usba_vbus_irq_thread, USBA_VBUS_IRQFLAGS, usba_vbus_irq_thread, USBA_VBUS_IRQFLAGS,
"atmel_usba_udc", udc); "atmel_usba_udc", udc);
if (ret) { if (ret) {
udc->vbus_pin = -ENODEV; udc->vbus_pin = NULL;
dev_warn(&udc->pdev->dev, dev_warn(&udc->pdev->dev,
"failed to request vbus irq; " "failed to request vbus irq; "
"assuming always on\n"); "assuming always on\n");
} }
} else {
/* gpio_request fail so use -EINVAL for gpio_is_valid */
udc->vbus_pin = -EINVAL;
}
} }
ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget); ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
...@@ -2423,9 +2339,9 @@ static int usba_udc_suspend(struct device *dev) ...@@ -2423,9 +2339,9 @@ static int usba_udc_suspend(struct device *dev)
* Device may wake up. We stay clocked if we failed * Device may wake up. We stay clocked if we failed
* to request vbus irq, assuming always on. * to request vbus irq, assuming always on.
*/ */
if (gpio_is_valid(udc->vbus_pin)) { if (udc->vbus_pin) {
usba_stop(udc); usba_stop(udc);
enable_irq_wake(gpio_to_irq(udc->vbus_pin)); enable_irq_wake(gpiod_to_irq(udc->vbus_pin));
} }
out: out:
...@@ -2441,8 +2357,8 @@ static int usba_udc_resume(struct device *dev) ...@@ -2441,8 +2357,8 @@ static int usba_udc_resume(struct device *dev)
if (!udc->driver) if (!udc->driver)
return 0; return 0;
if (device_may_wakeup(dev) && gpio_is_valid(udc->vbus_pin)) if (device_may_wakeup(dev) && udc->vbus_pin)
disable_irq_wake(gpio_to_irq(udc->vbus_pin)); disable_irq_wake(gpiod_to_irq(udc->vbus_pin));
/* If Vbus is present, enable the controller and wait for reset */ /* If Vbus is present, enable the controller and wait for reset */
mutex_lock(&udc->vbus_mutex); mutex_lock(&udc->vbus_mutex);
...@@ -2462,7 +2378,7 @@ static struct platform_driver udc_driver = { ...@@ -2462,7 +2378,7 @@ static struct platform_driver udc_driver = {
.driver = { .driver = {
.name = "atmel_usba_udc", .name = "atmel_usba_udc",
.pm = &usba_udc_pm_ops, .pm = &usba_udc_pm_ops,
.of_match_table = of_match_ptr(atmel_udc_dt_ids), .of_match_table = atmel_udc_dt_ids,
}, },
}; };
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#ifndef __LINUX_USB_GADGET_USBA_UDC_H__ #ifndef __LINUX_USB_GADGET_USBA_UDC_H__
#define __LINUX_USB_GADGET_USBA_UDC_H__ #define __LINUX_USB_GADGET_USBA_UDC_H__
#include <linux/gpio/consumer.h>
/* USB register offsets */ /* USB register offsets */
#define USBA_CTRL 0x0000 #define USBA_CTRL 0x0000
#define USBA_FNUM 0x0004 #define USBA_FNUM 0x0004
...@@ -323,7 +325,7 @@ struct usba_udc { ...@@ -323,7 +325,7 @@ struct usba_udc {
struct platform_device *pdev; struct platform_device *pdev;
const struct usba_udc_errata *errata; const struct usba_udc_errata *errata;
int irq; int irq;
int vbus_pin; struct gpio_desc *vbus_pin;
int vbus_pin_inverted; int vbus_pin_inverted;
int num_ep; int num_ep;
int configured_ep; int configured_ep;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment