mirror of https://gitee.com/openkylin/linux.git
USB for v4.20
With 63 non-merge commits, this is not a large merge window for USB peripheral. The largest changes go to the UVC gadget driver which a few folks have been improving. Apart from UVC changes, we have a few more devices being added to Renesas USB3 and DWC3 controller drivers and a couple minor bug fixes on other drivers. -----BEGIN PGP SIGNATURE----- iQJRBAABCAA7FiEElLzh7wn96CXwjh2IzL64meEamQYFAlu3GlkdHGZlbGlwZS5i YWxiaUBsaW51eC5pbnRlbC5jb20ACgkQzL64meEamQYyUBAA27Q8biDTUT/bnmaU ZfyPtes3XGLsG9n0EbyApxnOd4G+uPvTMb2cyjNVbz/LOycWXdQluk/QU3wy1N6d Bqw7V4ve1oIgT6bITm48Mqep74qoZuBGV2UTAI7boevCjHQba7a8qrUveHUPGKED Um3KWqT3ChasWdWS7NhD57q2ez1upyyRdAbLuny1bH0Gwte2BCcU4A/imMxChT4d NIiume06HmTjkvay7FVkFQ+F1S7fejeAsfhA2dgG3KJrELInI7qhKTq+4nDH4x4U PSP9yaldBn0s0pwKjpocZei34llljAElrQBklF834o+nHO1Ya3a+QRLoAZXRoCLh Kcz+iLJHHI0C18d1zomi79kHumwhcsruCOfz2rAcSyFfexdJ1M9V5/7J2xFnqkEH LLhkfty8aRDDYzePjpY/talliiihJh9DGqCnTyHWc7BwCiMhqHKAt+fFNOvPwdnn NU8laFfUwPECtvIwxGxIDZyIlgw4JXyEp5TgyRzH4WX+DJziXahN+TL3XWYV34wO 8yoFxcALYoXzAPvc1jGue6B0M17SyAOwJFTFSXGK1Q/TG0cOe2B95z96WPk0k+kK seq4yaF9J0O1SGwsBJqqehitwLWjrJR9VxYo4VrcRx5BRJU/GyHdo/vRcpzMH1Tc +eFlL1QZ5p073Dxb2SWKmw7JDq4= =XZcP -----END PGP SIGNATURE----- Merge tag 'usb-for-v4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next Felipe writes: USB for v4.20 With 63 non-merge commits, this is not a large merge window for USB peripheral. The largest changes go to the UVC gadget driver which a few folks have been improving. Apart from UVC changes, we have a few more devices being added to Renesas USB3 and DWC3 controller drivers and a couple minor bug fixes on other drivers. * tag 'usb-for-v4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb: (63 commits) USB: net2280: Remove ->disconnect() callback from net2280_pullup() usb: dwc2: disable power_down on rockchip devices usb: gadget: udc: renesas_usb3: add support for r8a77990 dt-bindings: usb: renesas_usb3: add bindings for r8a77990 usb: gadget: udc: renesas_usb3: Add r8a774a1 support usb: gadget: udc: renesas_usb3: Fix b-device mode for "workaround" usb: dwc2: gadget: Add handler for WkupAlert interrupt usb: dwc2: gadget: enable WKUP_ALERT interrupt usb: dwc2: gadget: Program GREFCLK register usb: dwc2: gadget: Add parameters for GREFCLK register usb: dwc2: Add definitions for new registers usb: dwc2: Update target (u)frame calculation usb: dwc2: Add dwc2_gadget_dec_frame_num_by_one() function usb: dwc2: Add core parameter for service interval support usb: dwc2: Update registers definitions to support service interval usb: renesas_usbhs: add support for R-Car E3 dt-bindings: usb: renesas_usbhs: add bindings for r8a77990 usb: renesas_usbhs: rcar3: Use OTG mode for R-Car D3 Revert "usb: renesas_usbhs: set the mode by using extcon state for non-otg channel" usb: gadget: f_uac2: disable IN/OUT ep if unused ...
This commit is contained in:
commit
e7a2c3fa28
|
@ -12,6 +12,10 @@ Date: Dec 2014
|
|||
KernelVersion: 4.0
|
||||
Description: Control descriptors
|
||||
|
||||
All attributes read only:
|
||||
bInterfaceNumber - USB interface number for this
|
||||
streaming interface
|
||||
|
||||
What: /config/usb-gadget/gadget/functions/uvc.name/control/class
|
||||
Date: Dec 2014
|
||||
KernelVersion: 4.0
|
||||
|
@ -109,6 +113,10 @@ Date: Dec 2014
|
|||
KernelVersion: 4.0
|
||||
Description: Streaming descriptors
|
||||
|
||||
All attributes read only:
|
||||
bInterfaceNumber - USB interface number for this
|
||||
streaming interface
|
||||
|
||||
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/class
|
||||
Date: Dec 2014
|
||||
KernelVersion: 4.0
|
||||
|
@ -160,6 +168,10 @@ Description: Specific MJPEG format descriptors
|
|||
|
||||
All attributes read only,
|
||||
except bmaControls and bDefaultFrameIndex:
|
||||
bFormatIndex - unique id for this format descriptor;
|
||||
only defined after parent header is
|
||||
linked into the streaming class;
|
||||
read-only
|
||||
bmaControls - this format's data for bmaControls in
|
||||
the streaming header
|
||||
bmInterfaceFlags - specifies interlace information,
|
||||
|
@ -177,6 +189,10 @@ Date: Dec 2014
|
|||
KernelVersion: 4.0
|
||||
Description: Specific MJPEG frame descriptors
|
||||
|
||||
bFrameIndex - unique id for this framedescriptor;
|
||||
only defined after parent format is
|
||||
linked into the streaming header;
|
||||
read-only
|
||||
dwFrameInterval - indicates how frame interval can be
|
||||
programmed; a number of values
|
||||
separated by newline can be specified
|
||||
|
@ -204,6 +220,10 @@ Date: Dec 2014
|
|||
KernelVersion: 4.0
|
||||
Description: Specific uncompressed format descriptors
|
||||
|
||||
bFormatIndex - unique id for this format descriptor;
|
||||
only defined after parent header is
|
||||
linked into the streaming class;
|
||||
read-only
|
||||
bmaControls - this format's data for bmaControls in
|
||||
the streaming header
|
||||
bmInterfaceFlags - specifies interlace information,
|
||||
|
@ -224,6 +244,10 @@ Date: Dec 2014
|
|||
KernelVersion: 4.0
|
||||
Description: Specific uncompressed frame descriptors
|
||||
|
||||
bFrameIndex - unique id for this framedescriptor;
|
||||
only defined after parent format is
|
||||
linked into the streaming header;
|
||||
read-only
|
||||
dwFrameInterval - indicates how frame interval can be
|
||||
programmed; a number of values
|
||||
separated by newline can be specified
|
||||
|
|
|
@ -19,6 +19,7 @@ Exception for clocks:
|
|||
"cavium,octeon-7130-usb-uctl"
|
||||
"qcom,dwc3"
|
||||
"samsung,exynos5250-dwusb3"
|
||||
"samsung,exynos5433-dwusb3"
|
||||
"samsung,exynos7-dwusb3"
|
||||
"sprd,sc9860-dwc3"
|
||||
"st,stih407-dwc3"
|
||||
|
|
|
@ -83,6 +83,8 @@ Required properties:
|
|||
- compatible: should be one of the following -
|
||||
"samsung,exynos5250-dwusb3": for USB 3.0 DWC3 controller on
|
||||
Exynos5250/5420.
|
||||
"samsung,exynos5433-dwusb3": for USB 3.0 DWC3 controller on
|
||||
Exynos5433.
|
||||
"samsung,exynos7-dwusb3": for USB 3.0 DWC3 controller on Exynos7.
|
||||
- #address-cells, #size-cells : should be '1' if the device has sub-nodes
|
||||
with 'reg' property.
|
||||
|
|
|
@ -6,6 +6,7 @@ Required properties:
|
|||
- "renesas,r8a7795-usb3-peri"
|
||||
- "renesas,r8a7796-usb3-peri"
|
||||
- "renesas,r8a77965-usb3-peri"
|
||||
- "renesas,r8a77990-usb3-peri"
|
||||
- "renesas,rcar-gen3-usb3-peri" for a generic R-Car Gen3 or RZ/G2
|
||||
compatible device
|
||||
|
||||
|
|
|
@ -393,6 +393,20 @@ enum dwc2_ep0_state {
|
|||
* 0 - No
|
||||
* 1 - Yes
|
||||
* @hird_threshold: Value of BESL or HIRD Threshold.
|
||||
* @ref_clk_per: Indicates in terms of pico seconds the period
|
||||
* of ref_clk.
|
||||
* 62500 - 16MHz
|
||||
* 58823 - 17MHz
|
||||
* 52083 - 19.2MHz
|
||||
* 50000 - 20MHz
|
||||
* 41666 - 24MHz
|
||||
* 33333 - 30MHz (default)
|
||||
* 25000 - 40MHz
|
||||
* @sof_cnt_wkup_alert: Indicates in term of number of SOF's after which
|
||||
* the controller should generate an interrupt if the
|
||||
* device had been in L1 state until that period.
|
||||
* This is used by SW to initiate Remote WakeUp in the
|
||||
* controller so as to sync to the uF number from the host.
|
||||
* @activate_stm_fs_transceiver: Activate internal transceiver using GGPIO
|
||||
* register.
|
||||
* 0 - Deactivate the transceiver (default)
|
||||
|
@ -416,6 +430,9 @@ enum dwc2_ep0_state {
|
|||
* back to DWC2_SPEED_PARAM_HIGH while device is gone.
|
||||
* 0 - No (default)
|
||||
* 1 - Yes
|
||||
* @service_interval: Enable service interval based scheduling.
|
||||
* 0 - No
|
||||
* 1 - Yes
|
||||
*
|
||||
* The following parameters may be specified when starting the module. These
|
||||
* parameters define how the DWC_otg controller should be configured. A
|
||||
|
@ -461,6 +478,7 @@ struct dwc2_core_params {
|
|||
bool lpm_clock_gating;
|
||||
bool besl;
|
||||
bool hird_threshold_en;
|
||||
bool service_interval;
|
||||
u8 hird_threshold;
|
||||
bool activate_stm_fs_transceiver;
|
||||
bool ipg_isoc_en;
|
||||
|
@ -468,6 +486,10 @@ struct dwc2_core_params {
|
|||
u32 max_transfer_size;
|
||||
u32 ahbcfg;
|
||||
|
||||
/* GREFCLK parameters */
|
||||
u32 ref_clk_per;
|
||||
u16 sof_cnt_wkup_alert;
|
||||
|
||||
/* Host parameters */
|
||||
bool host_dma;
|
||||
bool dma_desc_enable;
|
||||
|
@ -605,6 +627,10 @@ struct dwc2_core_params {
|
|||
* FIFO sizing is enabled 16 to 32768
|
||||
* Actual maximum value is autodetected and also
|
||||
* the default.
|
||||
* @service_interval_mode: For enabling service interval based scheduling in the
|
||||
* controller.
|
||||
* 0 - Disable
|
||||
* 1 - Enable
|
||||
*/
|
||||
struct dwc2_hw_params {
|
||||
unsigned op_mode:3;
|
||||
|
@ -635,6 +661,7 @@ struct dwc2_hw_params {
|
|||
unsigned utmi_phy_data_width:2;
|
||||
unsigned lpm_mode:1;
|
||||
unsigned ipg_isoc_en:1;
|
||||
unsigned service_interval_mode:1;
|
||||
u32 snpsid;
|
||||
u32 dev_ep_dirs;
|
||||
u32 g_tx_fifo_size[MAX_EPS_CHANNELS];
|
||||
|
@ -1354,6 +1381,7 @@ 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);
|
||||
void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg);
|
||||
void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg);
|
||||
#else
|
||||
static inline int dwc2_hsotg_remove(struct dwc2_hsotg *dwc2)
|
||||
{ return 0; }
|
||||
|
@ -1388,6 +1416,7 @@ static inline int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
|
|||
static inline int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg)
|
||||
{ return 0; }
|
||||
static inline void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg) {}
|
||||
static inline void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg) {}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
|
||||
|
|
|
@ -701,6 +701,7 @@ static int params_show(struct seq_file *seq, void *v)
|
|||
print_param(seq, p, besl);
|
||||
print_param(seq, p, hird_threshold_en);
|
||||
print_param(seq, p, hird_threshold);
|
||||
print_param(seq, p, service_interval);
|
||||
print_param(seq, p, host_dma);
|
||||
print_param(seq, p, g_dma);
|
||||
print_param(seq, p, g_dma_desc);
|
||||
|
|
|
@ -122,6 +122,24 @@ static inline void dwc2_gadget_incr_frame_num(struct dwc2_hsotg_ep *hs_ep)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_gadget_dec_frame_num_by_one - Decrements the targeted frame number
|
||||
* by one.
|
||||
* @hs_ep: The endpoint.
|
||||
*
|
||||
* This function used in service interval based scheduling flow to calculate
|
||||
* descriptor frame number filed value. For service interval mode frame
|
||||
* number in descriptor should point to last (u)frame in the interval.
|
||||
*
|
||||
*/
|
||||
static inline void dwc2_gadget_dec_frame_num_by_one(struct dwc2_hsotg_ep *hs_ep)
|
||||
{
|
||||
if (hs_ep->target_frame)
|
||||
hs_ep->target_frame -= 1;
|
||||
else
|
||||
hs_ep->target_frame = DSTS_SOFFN_LIMIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_hsotg_en_gsint - enable one or more of the general interrupt
|
||||
* @hsotg: The device state
|
||||
|
@ -227,6 +245,27 @@ int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
|
|||
return tx_addr_max - addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_gadget_wkup_alert_handler - Handler for WKUP_ALERT interrupt
|
||||
*
|
||||
* @hsotg: Programming view of the DWC_otg controller
|
||||
*
|
||||
*/
|
||||
static void dwc2_gadget_wkup_alert_handler(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
u32 gintsts2;
|
||||
u32 gintmsk2;
|
||||
|
||||
gintsts2 = dwc2_readl(hsotg, GINTSTS2);
|
||||
gintmsk2 = dwc2_readl(hsotg, GINTMSK2);
|
||||
|
||||
if (gintsts2 & GINTSTS2_WKUP_ALERT_INT) {
|
||||
dev_dbg(hsotg->dev, "%s: Wkup_Alert_Int\n", __func__);
|
||||
dwc2_clear_bit(hsotg, GINTSTS2, GINTSTS2_WKUP_ALERT_INT);
|
||||
dwc2_set_bit(hsotg, DCFG, DCTL_RMTWKUPSIG);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_hsotg_tx_fifo_average_depth - returns average depth of device mode
|
||||
* TX FIFOs
|
||||
|
@ -2812,6 +2851,23 @@ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep)
|
|||
if (using_desc_dma(hsotg)) {
|
||||
hs_ep->target_frame = hsotg->frame_number;
|
||||
dwc2_gadget_incr_frame_num(hs_ep);
|
||||
|
||||
/* In service interval mode target_frame must
|
||||
* be set to last (u)frame of the service interval.
|
||||
*/
|
||||
if (hsotg->params.service_interval) {
|
||||
/* Set target_frame to the first (u)frame of
|
||||
* the service interval
|
||||
*/
|
||||
hs_ep->target_frame &= ~hs_ep->interval + 1;
|
||||
|
||||
/* Set target_frame to the last (u)frame of
|
||||
* the service interval
|
||||
*/
|
||||
dwc2_gadget_incr_frame_num(hs_ep);
|
||||
dwc2_gadget_dec_frame_num_by_one(hs_ep);
|
||||
}
|
||||
|
||||
dwc2_gadget_start_isoc_ddma(hs_ep);
|
||||
return;
|
||||
}
|
||||
|
@ -3109,6 +3165,8 @@ static void kill_all_requests(struct dwc2_hsotg *hsotg,
|
|||
dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index);
|
||||
}
|
||||
|
||||
static int dwc2_hsotg_ep_disable(struct usb_ep *ep);
|
||||
|
||||
/**
|
||||
* dwc2_hsotg_disconnect - disconnect service
|
||||
* @hsotg: The device state.
|
||||
|
@ -3127,13 +3185,12 @@ void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg)
|
|||
hsotg->connected = 0;
|
||||
hsotg->test_mode = 0;
|
||||
|
||||
/* all endpoints should be shutdown */
|
||||
for (ep = 0; ep < hsotg->num_of_eps; ep++) {
|
||||
if (hsotg->eps_in[ep])
|
||||
kill_all_requests(hsotg, hsotg->eps_in[ep],
|
||||
-ESHUTDOWN);
|
||||
dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
|
||||
if (hsotg->eps_out[ep])
|
||||
kill_all_requests(hsotg, hsotg->eps_out[ep],
|
||||
-ESHUTDOWN);
|
||||
dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
|
||||
}
|
||||
|
||||
call_gadget(hsotg, disconnect);
|
||||
|
@ -3191,13 +3248,23 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
|
|||
u32 val;
|
||||
u32 usbcfg;
|
||||
u32 dcfg = 0;
|
||||
int ep;
|
||||
|
||||
/* Kill any ep0 requests as controller will be reinitialized */
|
||||
kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
|
||||
|
||||
if (!is_usb_reset)
|
||||
if (!is_usb_reset) {
|
||||
if (dwc2_core_reset(hsotg, true))
|
||||
return;
|
||||
} else {
|
||||
/* all endpoints should be shutdown */
|
||||
for (ep = 1; ep < hsotg->num_of_eps; ep++) {
|
||||
if (hsotg->eps_in[ep])
|
||||
dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
|
||||
if (hsotg->eps_out[ep])
|
||||
dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* we must now enable ep0 ready for host detection and then
|
||||
|
@ -3312,6 +3379,10 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
|
|||
dwc2_set_bit(hsotg, DIEPMSK, DIEPMSK_BNAININTRMSK);
|
||||
}
|
||||
|
||||
/* Enable Service Interval mode if supported */
|
||||
if (using_desc_dma(hsotg) && hsotg->params.service_interval)
|
||||
dwc2_set_bit(hsotg, DCTL, DCTL_SERVICE_INTERVAL_SUPPORTED);
|
||||
|
||||
dwc2_writel(hsotg, 0, DAINTMSK);
|
||||
|
||||
dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
|
||||
|
@ -3368,6 +3439,10 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
|
|||
/* configure the core to support LPM */
|
||||
dwc2_gadget_init_lpm(hsotg);
|
||||
|
||||
/* program GREFCLK register if needed */
|
||||
if (using_desc_dma(hsotg) && hsotg->params.service_interval)
|
||||
dwc2_gadget_program_ref_clk(hsotg);
|
||||
|
||||
/* must be at-least 3ms to allow bus to see disconnect */
|
||||
mdelay(3);
|
||||
|
||||
|
@ -3676,6 +3751,10 @@ static irqreturn_t dwc2_hsotg_irq(int irq, void *pw)
|
|||
if (gintsts & IRQ_RETRY_MASK && --retry_count > 0)
|
||||
goto irq_retry;
|
||||
|
||||
/* Check WKUP_ALERT interrupt*/
|
||||
if (hsotg->params.service_interval)
|
||||
dwc2_gadget_wkup_alert_handler(hsotg);
|
||||
|
||||
spin_unlock(&hsotg->lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
@ -3993,6 +4072,7 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
|
|||
unsigned long flags;
|
||||
u32 epctrl_reg;
|
||||
u32 ctrl;
|
||||
int locked;
|
||||
|
||||
dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep);
|
||||
|
||||
|
@ -4008,6 +4088,8 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
|
|||
|
||||
epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
|
||||
|
||||
locked = spin_is_locked(&hsotg->lock);
|
||||
if (!locked)
|
||||
spin_lock_irqsave(&hsotg->lock, flags);
|
||||
|
||||
ctrl = dwc2_readl(hsotg, epctrl_reg);
|
||||
|
@ -4032,7 +4114,9 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
|
|||
hs_ep->fifo_index = 0;
|
||||
hs_ep->fifo_size = 0;
|
||||
|
||||
if (!locked)
|
||||
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4944,6 +5028,29 @@ void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg)
|
|||
val |= hsotg->params.besl ? GLPMCFG_ENBESL : 0;
|
||||
dwc2_writel(hsotg, val, GLPMCFG);
|
||||
dev_dbg(hsotg->dev, "GLPMCFG=0x%08x\n", dwc2_readl(hsotg, GLPMCFG));
|
||||
|
||||
/* Unmask WKUP_ALERT Interrupt */
|
||||
if (hsotg->params.service_interval)
|
||||
dwc2_set_bit(hsotg, GINTMSK2, GINTMSK2_WKUP_ALERT_INT_MSK);
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc2_gadget_program_ref_clk - Program GREFCLK register in device mode
|
||||
*
|
||||
* @hsotg: Programming view of DWC_otg controller
|
||||
*
|
||||
*/
|
||||
void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
val |= GREFCLK_REF_CLK_MODE;
|
||||
val |= hsotg->params.ref_clk_per << GREFCLK_REFCLKPER_SHIFT;
|
||||
val |= hsotg->params.sof_cnt_wkup_alert <<
|
||||
GREFCLK_SOF_CNT_WKUP_ALERT_SHIFT;
|
||||
|
||||
dwc2_writel(hsotg, val, GREFCLK);
|
||||
dev_dbg(hsotg->dev, "GREFCLK=0x%08x\n", dwc2_readl(hsotg, GREFCLK));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -358,16 +358,10 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg)
|
|||
|
||||
static int dwc2_vbus_supply_init(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
hsotg->vbus_supply = devm_regulator_get_optional(hsotg->dev, "vbus");
|
||||
if (IS_ERR(hsotg->vbus_supply)) {
|
||||
ret = PTR_ERR(hsotg->vbus_supply);
|
||||
hsotg->vbus_supply = NULL;
|
||||
return ret == -ENODEV ? 0 : ret;
|
||||
}
|
||||
|
||||
if (hsotg->vbus_supply)
|
||||
return regulator_enable(hsotg->vbus_supply);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dwc2_vbus_supply_exit(struct dwc2_hsotg *hsotg)
|
||||
|
@ -1328,14 +1322,11 @@ static void dwc2_hc_write_packet(struct dwc2_hsotg *hsotg,
|
|||
u32 remaining_count;
|
||||
u32 byte_count;
|
||||
u32 dword_count;
|
||||
u32 __iomem *data_fifo;
|
||||
u32 *data_buf = (u32 *)chan->xfer_buf;
|
||||
|
||||
if (dbg_hc(chan))
|
||||
dev_vdbg(hsotg->dev, "%s()\n", __func__);
|
||||
|
||||
data_fifo = (u32 __iomem *)(hsotg->regs + HCFIFO(chan->hc_num));
|
||||
|
||||
remaining_count = chan->xfer_len - chan->xfer_count;
|
||||
if (remaining_count > chan->max_packet)
|
||||
byte_count = chan->max_packet;
|
||||
|
@ -3564,6 +3555,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
|
|||
u32 port_status;
|
||||
u32 speed;
|
||||
u32 pcgctl;
|
||||
u32 pwr;
|
||||
|
||||
switch (typereq) {
|
||||
case ClearHubFeature:
|
||||
|
@ -3612,8 +3604,11 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
|
|||
dev_dbg(hsotg->dev,
|
||||
"ClearPortFeature USB_PORT_FEAT_POWER\n");
|
||||
hprt0 = dwc2_read_hprt0(hsotg);
|
||||
pwr = hprt0 & HPRT0_PWR;
|
||||
hprt0 &= ~HPRT0_PWR;
|
||||
dwc2_writel(hsotg, hprt0, HPRT0);
|
||||
if (pwr)
|
||||
dwc2_vbus_supply_exit(hsotg);
|
||||
break;
|
||||
|
||||
case USB_PORT_FEAT_INDICATOR:
|
||||
|
@ -3823,8 +3818,11 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
|
|||
dev_dbg(hsotg->dev,
|
||||
"SetPortFeature - USB_PORT_FEAT_POWER\n");
|
||||
hprt0 = dwc2_read_hprt0(hsotg);
|
||||
pwr = hprt0 & HPRT0_PWR;
|
||||
hprt0 |= HPRT0_PWR;
|
||||
dwc2_writel(hsotg, hprt0, HPRT0);
|
||||
if (!pwr)
|
||||
dwc2_vbus_supply_init(hsotg);
|
||||
break;
|
||||
|
||||
case USB_PORT_FEAT_RESET:
|
||||
|
@ -3841,6 +3839,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
|
|||
dwc2_writel(hsotg, 0, PCGCTL);
|
||||
|
||||
hprt0 = dwc2_read_hprt0(hsotg);
|
||||
pwr = hprt0 & HPRT0_PWR;
|
||||
/* Clear suspend bit if resetting from suspend state */
|
||||
hprt0 &= ~HPRT0_SUSP;
|
||||
|
||||
|
@ -3854,6 +3853,8 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
|
|||
dev_dbg(hsotg->dev,
|
||||
"In host mode, hprt0=%08x\n", hprt0);
|
||||
dwc2_writel(hsotg, hprt0, HPRT0);
|
||||
if (!pwr)
|
||||
dwc2_vbus_supply_init(hsotg);
|
||||
}
|
||||
|
||||
/* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
|
||||
|
@ -4393,6 +4394,8 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd)
|
|||
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
|
||||
struct usb_bus *bus = hcd_to_bus(hcd);
|
||||
unsigned long flags;
|
||||
u32 hprt0;
|
||||
int ret;
|
||||
|
||||
dev_dbg(hsotg->dev, "DWC OTG HCD START\n");
|
||||
|
||||
|
@ -4408,6 +4411,17 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd)
|
|||
|
||||
dwc2_hcd_reinit(hsotg);
|
||||
|
||||
hprt0 = dwc2_read_hprt0(hsotg);
|
||||
/* Has vbus power been turned on in dwc2_core_host_init ? */
|
||||
if (hprt0 & HPRT0_PWR) {
|
||||
/* Enable external vbus supply before resuming root hub */
|
||||
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||
ret = dwc2_vbus_supply_init(hsotg);
|
||||
if (ret)
|
||||
return ret;
|
||||
spin_lock_irqsave(&hsotg->lock, flags);
|
||||
}
|
||||
|
||||
/* Initialize and connect root hub if one is not already attached */
|
||||
if (bus->root_hub) {
|
||||
dev_dbg(hsotg->dev, "DWC OTG HCD Has Root Hub\n");
|
||||
|
@ -4417,7 +4431,7 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd)
|
|||
|
||||
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||
|
||||
return dwc2_vbus_supply_init(hsotg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4428,6 +4442,7 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
|
|||
{
|
||||
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
|
||||
unsigned long flags;
|
||||
u32 hprt0;
|
||||
|
||||
/* Turn off all host-specific interrupts */
|
||||
dwc2_disable_host_interrupts(hsotg);
|
||||
|
@ -4436,6 +4451,7 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
|
|||
synchronize_irq(hcd->irq);
|
||||
|
||||
spin_lock_irqsave(&hsotg->lock, flags);
|
||||
hprt0 = dwc2_read_hprt0(hsotg);
|
||||
/* Ensure hcd is disconnected */
|
||||
dwc2_hcd_disconnect(hsotg, true);
|
||||
dwc2_hcd_stop(hsotg);
|
||||
|
@ -4444,6 +4460,8 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
|
|||
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
||||
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||
|
||||
/* keep balanced supply init/exit by checking HPRT0_PWR */
|
||||
if (hprt0 & HPRT0_PWR)
|
||||
dwc2_vbus_supply_exit(hsotg);
|
||||
|
||||
usleep_range(1000, 3000);
|
||||
|
@ -4482,7 +4500,9 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
|
|||
hprt0 |= HPRT0_SUSP;
|
||||
hprt0 &= ~HPRT0_PWR;
|
||||
dwc2_writel(hsotg, hprt0, HPRT0);
|
||||
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||
dwc2_vbus_supply_exit(hsotg);
|
||||
spin_lock_irqsave(&hsotg->lock, flags);
|
||||
}
|
||||
|
||||
/* Enter partial_power_down */
|
||||
|
|
|
@ -312,6 +312,7 @@
|
|||
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT 14
|
||||
#define GHWCFG4_ACG_SUPPORTED BIT(12)
|
||||
#define GHWCFG4_IPG_ISOC_SUPPORTED BIT(11)
|
||||
#define GHWCFG4_SERVICE_INTERVAL_SUPPORTED BIT(10)
|
||||
#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
|
||||
|
@ -404,6 +405,19 @@
|
|||
#define ADPCTL_PRB_DSCHRG_MASK (0x3 << 0)
|
||||
#define ADPCTL_PRB_DSCHRG_SHIFT 0
|
||||
|
||||
#define GREFCLK HSOTG_REG(0x0064)
|
||||
#define GREFCLK_REFCLKPER_MASK (0x1ffff << 15)
|
||||
#define GREFCLK_REFCLKPER_SHIFT 15
|
||||
#define GREFCLK_REF_CLK_MODE BIT(14)
|
||||
#define GREFCLK_SOF_CNT_WKUP_ALERT_MASK (0x3ff)
|
||||
#define GREFCLK_SOF_CNT_WKUP_ALERT_SHIFT 0
|
||||
|
||||
#define GINTMSK2 HSOTG_REG(0x0068)
|
||||
#define GINTMSK2_WKUP_ALERT_INT_MSK BIT(0)
|
||||
|
||||
#define GINTSTS2 HSOTG_REG(0x006c)
|
||||
#define GINTSTS2_WKUP_ALERT_INT BIT(0)
|
||||
|
||||
#define HPTXFSIZ HSOTG_REG(0x100)
|
||||
/* Use FIFOSIZE_* constants to access this register */
|
||||
|
||||
|
@ -443,6 +457,7 @@
|
|||
#define DCFG_DEVSPD_FS48 3
|
||||
|
||||
#define DCTL HSOTG_REG(0x804)
|
||||
#define DCTL_SERVICE_INTERVAL_SUPPORTED BIT(19)
|
||||
#define DCTL_PWRONPRGDONE BIT(11)
|
||||
#define DCTL_CGOUTNAK BIT(10)
|
||||
#define DCTL_SGOUTNAK BIT(9)
|
||||
|
|
|
@ -81,6 +81,7 @@ static void dwc2_set_rk_params(struct dwc2_hsotg *hsotg)
|
|||
p->host_perio_tx_fifo_size = 256;
|
||||
p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 <<
|
||||
GAHBCFG_HBSTLEN_SHIFT;
|
||||
p->power_down = 0;
|
||||
}
|
||||
|
||||
static void dwc2_set_ltq_params(struct dwc2_hsotg *hsotg)
|
||||
|
@ -299,9 +300,12 @@ static void dwc2_set_default_params(struct dwc2_hsotg *hsotg)
|
|||
p->hird_threshold_en = true;
|
||||
p->hird_threshold = 4;
|
||||
p->ipg_isoc_en = false;
|
||||
p->service_interval = false;
|
||||
p->max_packet_count = hw->max_packet_count;
|
||||
p->max_transfer_size = hw->max_transfer_size;
|
||||
p->ahbcfg = GAHBCFG_HBSTLEN_INCR << GAHBCFG_HBSTLEN_SHIFT;
|
||||
p->ref_clk_per = 33333;
|
||||
p->sof_cnt_wkup_alert = 100;
|
||||
|
||||
if ((hsotg->dr_mode == USB_DR_MODE_HOST) ||
|
||||
(hsotg->dr_mode == USB_DR_MODE_OTG)) {
|
||||
|
@ -592,6 +596,7 @@ static void dwc2_check_params(struct dwc2_hsotg *hsotg)
|
|||
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_BOOL(service_interval, hw->service_interval_mode);
|
||||
CHECK_RANGE(max_packet_count,
|
||||
15, hw->max_packet_count,
|
||||
hw->max_packet_count);
|
||||
|
@ -780,6 +785,8 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
|
|||
GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT;
|
||||
hw->acg_enable = !!(hwcfg4 & GHWCFG4_ACG_SUPPORTED);
|
||||
hw->ipg_isoc_en = !!(hwcfg4 & GHWCFG4_IPG_ISOC_SUPPORTED);
|
||||
hw->service_interval_mode = !!(hwcfg4 &
|
||||
GHWCFG4_SERVICE_INTERVAL_SUPPORTED);
|
||||
|
||||
/* fifo sizes */
|
||||
hw->rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >>
|
||||
|
|
|
@ -432,6 +432,14 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
|||
if (retval)
|
||||
return retval;
|
||||
|
||||
hsotg->vbus_supply = devm_regulator_get_optional(hsotg->dev, "vbus");
|
||||
if (IS_ERR(hsotg->vbus_supply)) {
|
||||
retval = PTR_ERR(hsotg->vbus_supply);
|
||||
hsotg->vbus_supply = NULL;
|
||||
if (retval != -ENODEV)
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = dwc2_lowlevel_hw_enable(hsotg);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
|
|
@ -113,7 +113,7 @@ config USB_DWC3_ST
|
|||
|
||||
config USB_DWC3_QCOM
|
||||
tristate "Qualcomm Platform"
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
depends on EXTCON && (ARCH_QCOM || COMPILE_TEST)
|
||||
depends on OF
|
||||
default USB_DWC3
|
||||
help
|
||||
|
|
|
@ -756,7 +756,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc)
|
|||
|
||||
/* check if current dwc3 is on simulation board */
|
||||
if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) {
|
||||
dev_info(dwc->dev, "Running with FPGA optmizations\n");
|
||||
dev_info(dwc->dev, "Running with FPGA optimizations\n");
|
||||
dwc->is_fpga = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,80 +13,30 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/usb_phy_generic.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#define DWC3_EXYNOS_MAX_CLOCKS 4
|
||||
|
||||
struct dwc3_exynos_driverdata {
|
||||
const char *clk_names[DWC3_EXYNOS_MAX_CLOCKS];
|
||||
int num_clks;
|
||||
int suspend_clk_idx;
|
||||
};
|
||||
|
||||
struct dwc3_exynos {
|
||||
struct platform_device *usb2_phy;
|
||||
struct platform_device *usb3_phy;
|
||||
struct device *dev;
|
||||
|
||||
struct clk *clk;
|
||||
struct clk *susp_clk;
|
||||
struct clk *axius_clk;
|
||||
const char **clk_names;
|
||||
struct clk *clks[DWC3_EXYNOS_MAX_CLOCKS];
|
||||
int num_clks;
|
||||
int suspend_clk_idx;
|
||||
|
||||
struct regulator *vdd33;
|
||||
struct regulator *vdd10;
|
||||
};
|
||||
|
||||
static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
|
||||
{
|
||||
struct usb_phy_generic_platform_data pdata;
|
||||
struct platform_device *pdev;
|
||||
int ret;
|
||||
|
||||
memset(&pdata, 0x00, sizeof(pdata));
|
||||
|
||||
pdev = platform_device_alloc("usb_phy_generic", PLATFORM_DEVID_AUTO);
|
||||
if (!pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
exynos->usb2_phy = pdev;
|
||||
pdata.type = USB_PHY_TYPE_USB2;
|
||||
pdata.gpio_reset = -1;
|
||||
|
||||
ret = platform_device_add_data(exynos->usb2_phy, &pdata, sizeof(pdata));
|
||||
if (ret)
|
||||
goto err1;
|
||||
|
||||
pdev = platform_device_alloc("usb_phy_generic", PLATFORM_DEVID_AUTO);
|
||||
if (!pdev) {
|
||||
ret = -ENOMEM;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
exynos->usb3_phy = pdev;
|
||||
pdata.type = USB_PHY_TYPE_USB3;
|
||||
|
||||
ret = platform_device_add_data(exynos->usb3_phy, &pdata, sizeof(pdata));
|
||||
if (ret)
|
||||
goto err2;
|
||||
|
||||
ret = platform_device_add(exynos->usb2_phy);
|
||||
if (ret)
|
||||
goto err2;
|
||||
|
||||
ret = platform_device_add(exynos->usb3_phy);
|
||||
if (ret)
|
||||
goto err3;
|
||||
|
||||
return 0;
|
||||
|
||||
err3:
|
||||
platform_device_del(exynos->usb2_phy);
|
||||
|
||||
err2:
|
||||
platform_device_put(exynos->usb3_phy);
|
||||
|
||||
err1:
|
||||
platform_device_put(exynos->usb2_phy);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dwc3_exynos_remove_child(struct device *dev, void *unused)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
@ -101,47 +51,42 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
|
|||
struct dwc3_exynos *exynos;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *node = dev->of_node;
|
||||
|
||||
int ret;
|
||||
const struct dwc3_exynos_driverdata *driver_data;
|
||||
int i, ret;
|
||||
|
||||
exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
|
||||
if (!exynos)
|
||||
return -ENOMEM;
|
||||
|
||||
driver_data = of_device_get_match_data(dev);
|
||||
exynos->dev = dev;
|
||||
exynos->num_clks = driver_data->num_clks;
|
||||
exynos->clk_names = (const char **)driver_data->clk_names;
|
||||
exynos->suspend_clk_idx = driver_data->suspend_clk_idx;
|
||||
|
||||
platform_set_drvdata(pdev, exynos);
|
||||
|
||||
exynos->dev = dev;
|
||||
|
||||
exynos->clk = devm_clk_get(dev, "usbdrd30");
|
||||
if (IS_ERR(exynos->clk)) {
|
||||
dev_err(dev, "couldn't get clock\n");
|
||||
return -EINVAL;
|
||||
for (i = 0; i < exynos->num_clks; i++) {
|
||||
exynos->clks[i] = devm_clk_get(dev, exynos->clk_names[i]);
|
||||
if (IS_ERR(exynos->clks[i])) {
|
||||
dev_err(dev, "failed to get clock: %s\n",
|
||||
exynos->clk_names[i]);
|
||||
return PTR_ERR(exynos->clks[i]);
|
||||
}
|
||||
ret = clk_prepare_enable(exynos->clk);
|
||||
if (ret)
|
||||
}
|
||||
|
||||
for (i = 0; i < exynos->num_clks; i++) {
|
||||
ret = clk_prepare_enable(exynos->clks[i]);
|
||||
if (ret) {
|
||||
while (--i > 0)
|
||||
clk_disable_unprepare(exynos->clks[i]);
|
||||
return ret;
|
||||
|
||||
exynos->susp_clk = devm_clk_get(dev, "usbdrd30_susp_clk");
|
||||
if (IS_ERR(exynos->susp_clk))
|
||||
exynos->susp_clk = NULL;
|
||||
ret = clk_prepare_enable(exynos->susp_clk);
|
||||
if (ret)
|
||||
goto susp_clk_err;
|
||||
|
||||
if (of_device_is_compatible(node, "samsung,exynos7-dwusb3")) {
|
||||
exynos->axius_clk = devm_clk_get(dev, "usbdrd30_axius_clk");
|
||||
if (IS_ERR(exynos->axius_clk)) {
|
||||
dev_err(dev, "no AXI UpScaler clk specified\n");
|
||||
ret = -ENODEV;
|
||||
goto axius_clk_err;
|
||||
}
|
||||
ret = clk_prepare_enable(exynos->axius_clk);
|
||||
if (ret)
|
||||
goto axius_clk_err;
|
||||
} else {
|
||||
exynos->axius_clk = NULL;
|
||||
}
|
||||
|
||||
if (exynos->suspend_clk_idx >= 0)
|
||||
clk_prepare_enable(exynos->clks[exynos->suspend_clk_idx]);
|
||||
|
||||
exynos->vdd33 = devm_regulator_get(dev, "vdd33");
|
||||
if (IS_ERR(exynos->vdd33)) {
|
||||
ret = PTR_ERR(exynos->vdd33);
|
||||
|
@ -164,12 +109,6 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
|
|||
goto vdd10_err;
|
||||
}
|
||||
|
||||
ret = dwc3_exynos_register_phys(exynos);
|
||||
if (ret) {
|
||||
dev_err(dev, "couldn't register PHYs\n");
|
||||
goto phys_err;
|
||||
}
|
||||
|
||||
if (node) {
|
||||
ret = of_platform_populate(node, NULL, NULL, dev);
|
||||
if (ret) {
|
||||
|
@ -185,32 +124,31 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
populate_err:
|
||||
platform_device_unregister(exynos->usb2_phy);
|
||||
platform_device_unregister(exynos->usb3_phy);
|
||||
phys_err:
|
||||
regulator_disable(exynos->vdd10);
|
||||
vdd10_err:
|
||||
regulator_disable(exynos->vdd33);
|
||||
vdd33_err:
|
||||
clk_disable_unprepare(exynos->axius_clk);
|
||||
axius_clk_err:
|
||||
clk_disable_unprepare(exynos->susp_clk);
|
||||
susp_clk_err:
|
||||
clk_disable_unprepare(exynos->clk);
|
||||
for (i = exynos->num_clks - 1; i >= 0; i--)
|
||||
clk_disable_unprepare(exynos->clks[i]);
|
||||
|
||||
if (exynos->suspend_clk_idx >= 0)
|
||||
clk_disable_unprepare(exynos->clks[exynos->suspend_clk_idx]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dwc3_exynos_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct dwc3_exynos *exynos = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child);
|
||||
platform_device_unregister(exynos->usb2_phy);
|
||||
platform_device_unregister(exynos->usb3_phy);
|
||||
|
||||
clk_disable_unprepare(exynos->axius_clk);
|
||||
clk_disable_unprepare(exynos->susp_clk);
|
||||
clk_disable_unprepare(exynos->clk);
|
||||
for (i = exynos->num_clks - 1; i >= 0; i--)
|
||||
clk_disable_unprepare(exynos->clks[i]);
|
||||
|
||||
if (exynos->suspend_clk_idx >= 0)
|
||||
clk_disable_unprepare(exynos->clks[exynos->suspend_clk_idx]);
|
||||
|
||||
regulator_disable(exynos->vdd33);
|
||||
regulator_disable(exynos->vdd10);
|
||||
|
@ -218,10 +156,36 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct dwc3_exynos_driverdata exynos5250_drvdata = {
|
||||
.clk_names = { "usbdrd30" },
|
||||
.num_clks = 1,
|
||||
.suspend_clk_idx = -1,
|
||||
};
|
||||
|
||||
static const struct dwc3_exynos_driverdata exynos5433_drvdata = {
|
||||
.clk_names = { "aclk", "susp_clk", "pipe_pclk", "phyclk" },
|
||||
.num_clks = 4,
|
||||
.suspend_clk_idx = 1,
|
||||
};
|
||||
|
||||
static const struct dwc3_exynos_driverdata exynos7_drvdata = {
|
||||
.clk_names = { "usbdrd30", "usbdrd30_susp_clk", "usbdrd30_axius_clk" },
|
||||
.num_clks = 3,
|
||||
.suspend_clk_idx = 1,
|
||||
};
|
||||
|
||||
static const struct of_device_id exynos_dwc3_match[] = {
|
||||
{ .compatible = "samsung,exynos5250-dwusb3" },
|
||||
{ .compatible = "samsung,exynos7-dwusb3" },
|
||||
{},
|
||||
{
|
||||
.compatible = "samsung,exynos5250-dwusb3",
|
||||
.data = &exynos5250_drvdata,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5433-dwusb3",
|
||||
.data = &exynos5433_drvdata,
|
||||
}, {
|
||||
.compatible = "samsung,exynos7-dwusb3",
|
||||
.data = &exynos7_drvdata,
|
||||
}, {
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
|
||||
|
||||
|
@ -229,9 +193,10 @@ MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
|
|||
static int dwc3_exynos_suspend(struct device *dev)
|
||||
{
|
||||
struct dwc3_exynos *exynos = dev_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
clk_disable(exynos->axius_clk);
|
||||
clk_disable(exynos->clk);
|
||||
for (i = exynos->num_clks - 1; i >= 0; i--)
|
||||
clk_disable_unprepare(exynos->clks[i]);
|
||||
|
||||
regulator_disable(exynos->vdd33);
|
||||
regulator_disable(exynos->vdd10);
|
||||
|
@ -242,7 +207,7 @@ static int dwc3_exynos_suspend(struct device *dev)
|
|||
static int dwc3_exynos_resume(struct device *dev)
|
||||
{
|
||||
struct dwc3_exynos *exynos = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
int i, ret;
|
||||
|
||||
ret = regulator_enable(exynos->vdd33);
|
||||
if (ret) {
|
||||
|
@ -255,13 +220,14 @@ static int dwc3_exynos_resume(struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
clk_enable(exynos->clk);
|
||||
clk_enable(exynos->axius_clk);
|
||||
|
||||
/* runtime set active to reflect active state. */
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
for (i = 0; i < exynos->num_clks; i++) {
|
||||
ret = clk_prepare_enable(exynos->clks[i]);
|
||||
if (ret) {
|
||||
while (--i > 0)
|
||||
clk_disable_unprepare(exynos->clks[i]);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -270,27 +270,36 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
|
|||
const struct usb_endpoint_descriptor *desc = dep->endpoint.desc;
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
u32 timeout = 1000;
|
||||
u32 saved_config = 0;
|
||||
u32 reg;
|
||||
|
||||
int cmd_status = 0;
|
||||
int susphy = false;
|
||||
int ret = -EINVAL;
|
||||
|
||||
/*
|
||||
* Synopsys Databook 2.60a states, on section 6.3.2.5.[1-8], that if
|
||||
* we're issuing an endpoint command, we must check if
|
||||
* GUSB2PHYCFG.SUSPHY bit is set. If it is, then we need to clear it.
|
||||
* When operating in USB 2.0 speeds (HS/FS), if GUSB2PHYCFG.ENBLSLPM or
|
||||
* GUSB2PHYCFG.SUSPHY is set, it must be cleared before issuing an
|
||||
* endpoint command.
|
||||
*
|
||||
* We will also set SUSPHY bit to what it was before returning as stated
|
||||
* by the same section on Synopsys databook.
|
||||
* Save and clear both GUSB2PHYCFG.ENBLSLPM and GUSB2PHYCFG.SUSPHY
|
||||
* settings. Restore them after the command is completed.
|
||||
*
|
||||
* DWC_usb3 3.30a and DWC_usb31 1.90a programming guide section 3.2.2
|
||||
*/
|
||||
if (dwc->gadget.speed <= USB_SPEED_HIGH) {
|
||||
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
|
||||
if (unlikely(reg & DWC3_GUSB2PHYCFG_SUSPHY)) {
|
||||
susphy = true;
|
||||
saved_config |= DWC3_GUSB2PHYCFG_SUSPHY;
|
||||
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
|
||||
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
|
||||
}
|
||||
|
||||
if (reg & DWC3_GUSB2PHYCFG_ENBLSLPM) {
|
||||
saved_config |= DWC3_GUSB2PHYCFG_ENBLSLPM;
|
||||
reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
|
||||
}
|
||||
|
||||
if (saved_config)
|
||||
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
|
||||
}
|
||||
|
||||
if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) {
|
||||
|
@ -389,9 +398,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
|
|||
}
|
||||
}
|
||||
|
||||
if (unlikely(susphy)) {
|
||||
if (saved_config) {
|
||||
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
|
||||
reg |= DWC3_GUSB2PHYCFG_SUSPHY;
|
||||
reg |= saved_config;
|
||||
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,12 +22,8 @@
|
|||
* controlled by two clock sources :
|
||||
* CLK_5 := c_srate, and CLK_6 := p_srate
|
||||
*/
|
||||
#define USB_OUT_IT_ID 1
|
||||
#define IO_IN_IT_ID 2
|
||||
#define IO_OUT_OT_ID 3
|
||||
#define USB_IN_OT_ID 4
|
||||
#define USB_OUT_CLK_ID 5
|
||||
#define USB_IN_CLK_ID 6
|
||||
#define USB_OUT_CLK_ID (out_clk_src_desc.bClockID)
|
||||
#define USB_IN_CLK_ID (in_clk_src_desc.bClockID)
|
||||
|
||||
#define CONTROL_ABSENT 0
|
||||
#define CONTROL_RDONLY 1
|
||||
|
@ -43,6 +39,9 @@
|
|||
#define UNFLW_CTRL 8
|
||||
#define OVFLW_CTRL 10
|
||||
|
||||
#define EPIN_EN(_opts) ((_opts)->p_chmask != 0)
|
||||
#define EPOUT_EN(_opts) ((_opts)->c_chmask != 0)
|
||||
|
||||
struct f_uac2 {
|
||||
struct g_audio g_audio;
|
||||
u8 ac_intf, as_in_intf, as_out_intf;
|
||||
|
@ -135,7 +134,7 @@ static struct uac_clock_source_descriptor in_clk_src_desc = {
|
|||
.bDescriptorType = USB_DT_CS_INTERFACE,
|
||||
|
||||
.bDescriptorSubtype = UAC2_CLOCK_SOURCE,
|
||||
.bClockID = USB_IN_CLK_ID,
|
||||
/* .bClockID = DYNAMIC */
|
||||
.bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED,
|
||||
.bmControls = (CONTROL_RDONLY << CLK_FREQ_CTRL),
|
||||
.bAssocTerminal = 0,
|
||||
|
@ -147,7 +146,7 @@ static struct uac_clock_source_descriptor out_clk_src_desc = {
|
|||
.bDescriptorType = USB_DT_CS_INTERFACE,
|
||||
|
||||
.bDescriptorSubtype = UAC2_CLOCK_SOURCE,
|
||||
.bClockID = USB_OUT_CLK_ID,
|
||||
/* .bClockID = DYNAMIC */
|
||||
.bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED,
|
||||
.bmControls = (CONTROL_RDONLY << CLK_FREQ_CTRL),
|
||||
.bAssocTerminal = 0,
|
||||
|
@ -159,10 +158,10 @@ static struct uac2_input_terminal_descriptor usb_out_it_desc = {
|
|||
.bDescriptorType = USB_DT_CS_INTERFACE,
|
||||
|
||||
.bDescriptorSubtype = UAC_INPUT_TERMINAL,
|
||||
.bTerminalID = USB_OUT_IT_ID,
|
||||
/* .bTerminalID = DYNAMIC */
|
||||
.wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING),
|
||||
.bAssocTerminal = 0,
|
||||
.bCSourceID = USB_OUT_CLK_ID,
|
||||
/* .bCSourceID = DYNAMIC */
|
||||
.iChannelNames = 0,
|
||||
.bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL),
|
||||
};
|
||||
|
@ -173,10 +172,10 @@ static struct uac2_input_terminal_descriptor io_in_it_desc = {
|
|||
.bDescriptorType = USB_DT_CS_INTERFACE,
|
||||
|
||||
.bDescriptorSubtype = UAC_INPUT_TERMINAL,
|
||||
.bTerminalID = IO_IN_IT_ID,
|
||||
/* .bTerminalID = DYNAMIC */
|
||||
.wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_UNDEFINED),
|
||||
.bAssocTerminal = 0,
|
||||
.bCSourceID = USB_IN_CLK_ID,
|
||||
/* .bCSourceID = DYNAMIC */
|
||||
.iChannelNames = 0,
|
||||
.bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL),
|
||||
};
|
||||
|
@ -187,11 +186,11 @@ static struct uac2_output_terminal_descriptor usb_in_ot_desc = {
|
|||
.bDescriptorType = USB_DT_CS_INTERFACE,
|
||||
|
||||
.bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
|
||||
.bTerminalID = USB_IN_OT_ID,
|
||||
/* .bTerminalID = DYNAMIC */
|
||||
.wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING),
|
||||
.bAssocTerminal = 0,
|
||||
.bSourceID = IO_IN_IT_ID,
|
||||
.bCSourceID = USB_IN_CLK_ID,
|
||||
/* .bSourceID = DYNAMIC */
|
||||
/* .bCSourceID = DYNAMIC */
|
||||
.bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL),
|
||||
};
|
||||
|
||||
|
@ -201,11 +200,11 @@ static struct uac2_output_terminal_descriptor io_out_ot_desc = {
|
|||
.bDescriptorType = USB_DT_CS_INTERFACE,
|
||||
|
||||
.bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
|
||||
.bTerminalID = IO_OUT_OT_ID,
|
||||
/* .bTerminalID = DYNAMIC */
|
||||
.wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_UNDEFINED),
|
||||
.bAssocTerminal = 0,
|
||||
.bSourceID = USB_OUT_IT_ID,
|
||||
.bCSourceID = USB_OUT_CLK_ID,
|
||||
/* .bSourceID = DYNAMIC */
|
||||
/* .bCSourceID = DYNAMIC */
|
||||
.bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL),
|
||||
};
|
||||
|
||||
|
@ -253,7 +252,7 @@ static struct uac2_as_header_descriptor as_out_hdr_desc = {
|
|||
.bDescriptorType = USB_DT_CS_INTERFACE,
|
||||
|
||||
.bDescriptorSubtype = UAC_AS_GENERAL,
|
||||
.bTerminalLink = USB_OUT_IT_ID,
|
||||
/* .bTerminalLink = DYNAMIC */
|
||||
.bmControls = 0,
|
||||
.bFormatType = UAC_FORMAT_TYPE_I,
|
||||
.bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM),
|
||||
|
@ -330,7 +329,7 @@ static struct uac2_as_header_descriptor as_in_hdr_desc = {
|
|||
.bDescriptorType = USB_DT_CS_INTERFACE,
|
||||
|
||||
.bDescriptorSubtype = UAC_AS_GENERAL,
|
||||
.bTerminalLink = USB_IN_OT_ID,
|
||||
/* .bTerminalLink = DYNAMIC */
|
||||
.bmControls = 0,
|
||||
.bFormatType = UAC_FORMAT_TYPE_I,
|
||||
.bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM),
|
||||
|
@ -471,6 +470,125 @@ static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
|
|||
le16_to_cpu(ep_desc->wMaxPacketSize)));
|
||||
}
|
||||
|
||||
/* Use macro to overcome line length limitation */
|
||||
#define USBDHDR(p) (struct usb_descriptor_header *)(p)
|
||||
|
||||
static void setup_descriptor(struct f_uac2_opts *opts)
|
||||
{
|
||||
/* patch descriptors */
|
||||
int i = 1; /* ID's start with 1 */
|
||||
|
||||
if (EPOUT_EN(opts))
|
||||
usb_out_it_desc.bTerminalID = i++;
|
||||
if (EPIN_EN(opts))
|
||||
io_in_it_desc.bTerminalID = i++;
|
||||
if (EPOUT_EN(opts))
|
||||
io_out_ot_desc.bTerminalID = i++;
|
||||
if (EPIN_EN(opts))
|
||||
usb_in_ot_desc.bTerminalID = i++;
|
||||
if (EPOUT_EN(opts))
|
||||
out_clk_src_desc.bClockID = i++;
|
||||
if (EPIN_EN(opts))
|
||||
in_clk_src_desc.bClockID = i++;
|
||||
|
||||
usb_out_it_desc.bCSourceID = out_clk_src_desc.bClockID;
|
||||
usb_in_ot_desc.bSourceID = io_in_it_desc.bTerminalID;
|
||||
usb_in_ot_desc.bCSourceID = in_clk_src_desc.bClockID;
|
||||
io_in_it_desc.bCSourceID = in_clk_src_desc.bClockID;
|
||||
io_out_ot_desc.bCSourceID = out_clk_src_desc.bClockID;
|
||||
io_out_ot_desc.bSourceID = usb_out_it_desc.bTerminalID;
|
||||
as_out_hdr_desc.bTerminalLink = usb_out_it_desc.bTerminalID;
|
||||
as_in_hdr_desc.bTerminalLink = usb_in_ot_desc.bTerminalID;
|
||||
|
||||
iad_desc.bInterfaceCount = 1;
|
||||
ac_hdr_desc.wTotalLength = 0;
|
||||
|
||||
if (EPIN_EN(opts)) {
|
||||
u16 len = le16_to_cpu(ac_hdr_desc.wTotalLength);
|
||||
|
||||
len += sizeof(in_clk_src_desc);
|
||||
len += sizeof(usb_in_ot_desc);
|
||||
len += sizeof(io_in_it_desc);
|
||||
ac_hdr_desc.wTotalLength = cpu_to_le16(len);
|
||||
iad_desc.bInterfaceCount++;
|
||||
}
|
||||
if (EPOUT_EN(opts)) {
|
||||
u16 len = le16_to_cpu(ac_hdr_desc.wTotalLength);
|
||||
|
||||
len += sizeof(out_clk_src_desc);
|
||||
len += sizeof(usb_out_it_desc);
|
||||
len += sizeof(io_out_ot_desc);
|
||||
ac_hdr_desc.wTotalLength = cpu_to_le16(len);
|
||||
iad_desc.bInterfaceCount++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
fs_audio_desc[i++] = USBDHDR(&iad_desc);
|
||||
fs_audio_desc[i++] = USBDHDR(&std_ac_if_desc);
|
||||
fs_audio_desc[i++] = USBDHDR(&ac_hdr_desc);
|
||||
if (EPIN_EN(opts))
|
||||
fs_audio_desc[i++] = USBDHDR(&in_clk_src_desc);
|
||||
if (EPOUT_EN(opts)) {
|
||||
fs_audio_desc[i++] = USBDHDR(&out_clk_src_desc);
|
||||
fs_audio_desc[i++] = USBDHDR(&usb_out_it_desc);
|
||||
}
|
||||
if (EPIN_EN(opts)) {
|
||||
fs_audio_desc[i++] = USBDHDR(&io_in_it_desc);
|
||||
fs_audio_desc[i++] = USBDHDR(&usb_in_ot_desc);
|
||||
}
|
||||
if (EPOUT_EN(opts)) {
|
||||
fs_audio_desc[i++] = USBDHDR(&io_out_ot_desc);
|
||||
fs_audio_desc[i++] = USBDHDR(&std_as_out_if0_desc);
|
||||
fs_audio_desc[i++] = USBDHDR(&std_as_out_if1_desc);
|
||||
fs_audio_desc[i++] = USBDHDR(&as_out_hdr_desc);
|
||||
fs_audio_desc[i++] = USBDHDR(&as_out_fmt1_desc);
|
||||
fs_audio_desc[i++] = USBDHDR(&fs_epout_desc);
|
||||
fs_audio_desc[i++] = USBDHDR(&as_iso_out_desc);
|
||||
}
|
||||
if (EPIN_EN(opts)) {
|
||||
fs_audio_desc[i++] = USBDHDR(&std_as_in_if0_desc);
|
||||
fs_audio_desc[i++] = USBDHDR(&std_as_in_if1_desc);
|
||||
fs_audio_desc[i++] = USBDHDR(&as_in_hdr_desc);
|
||||
fs_audio_desc[i++] = USBDHDR(&as_in_fmt1_desc);
|
||||
fs_audio_desc[i++] = USBDHDR(&fs_epin_desc);
|
||||
fs_audio_desc[i++] = USBDHDR(&as_iso_in_desc);
|
||||
}
|
||||
fs_audio_desc[i] = NULL;
|
||||
|
||||
i = 0;
|
||||
hs_audio_desc[i++] = USBDHDR(&iad_desc);
|
||||
hs_audio_desc[i++] = USBDHDR(&std_ac_if_desc);
|
||||
hs_audio_desc[i++] = USBDHDR(&ac_hdr_desc);
|
||||
if (EPIN_EN(opts))
|
||||
hs_audio_desc[i++] = USBDHDR(&in_clk_src_desc);
|
||||
if (EPOUT_EN(opts)) {
|
||||
hs_audio_desc[i++] = USBDHDR(&out_clk_src_desc);
|
||||
hs_audio_desc[i++] = USBDHDR(&usb_out_it_desc);
|
||||
}
|
||||
if (EPIN_EN(opts)) {
|
||||
hs_audio_desc[i++] = USBDHDR(&io_in_it_desc);
|
||||
hs_audio_desc[i++] = USBDHDR(&usb_in_ot_desc);
|
||||
}
|
||||
if (EPOUT_EN(opts)) {
|
||||
hs_audio_desc[i++] = USBDHDR(&io_out_ot_desc);
|
||||
hs_audio_desc[i++] = USBDHDR(&std_as_out_if0_desc);
|
||||
hs_audio_desc[i++] = USBDHDR(&std_as_out_if1_desc);
|
||||
hs_audio_desc[i++] = USBDHDR(&as_out_hdr_desc);
|
||||
hs_audio_desc[i++] = USBDHDR(&as_out_fmt1_desc);
|
||||
hs_audio_desc[i++] = USBDHDR(&hs_epout_desc);
|
||||
hs_audio_desc[i++] = USBDHDR(&as_iso_out_desc);
|
||||
}
|
||||
if (EPIN_EN(opts)) {
|
||||
hs_audio_desc[i++] = USBDHDR(&std_as_in_if0_desc);
|
||||
hs_audio_desc[i++] = USBDHDR(&std_as_in_if1_desc);
|
||||
hs_audio_desc[i++] = USBDHDR(&as_in_hdr_desc);
|
||||
hs_audio_desc[i++] = USBDHDR(&as_in_fmt1_desc);
|
||||
hs_audio_desc[i++] = USBDHDR(&hs_epin_desc);
|
||||
hs_audio_desc[i++] = USBDHDR(&as_iso_in_desc);
|
||||
}
|
||||
hs_audio_desc[i] = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
|
||||
{
|
||||
|
@ -530,6 +648,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
|
|||
uac2->ac_intf = ret;
|
||||
uac2->ac_alt = 0;
|
||||
|
||||
if (EPOUT_EN(uac2_opts)) {
|
||||
ret = usb_interface_id(cfg, fn);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
|
||||
|
@ -539,7 +658,9 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
|
|||
std_as_out_if1_desc.bInterfaceNumber = ret;
|
||||
uac2->as_out_intf = ret;
|
||||
uac2->as_out_alt = 0;
|
||||
}
|
||||
|
||||
if (EPIN_EN(uac2_opts)) {
|
||||
ret = usb_interface_id(cfg, fn);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
|
||||
|
@ -549,6 +670,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
|
|||
std_as_in_if1_desc.bInterfaceNumber = ret;
|
||||
uac2->as_in_intf = ret;
|
||||
uac2->as_in_alt = 0;
|
||||
}
|
||||
|
||||
/* Calculate wMaxPacketSize according to audio bandwidth */
|
||||
set_ep_max_packet_size(uac2_opts, &fs_epin_desc, 1000, true);
|
||||
|
@ -556,17 +678,21 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
|
|||
set_ep_max_packet_size(uac2_opts, &hs_epin_desc, 8000, true);
|
||||
set_ep_max_packet_size(uac2_opts, &hs_epout_desc, 8000, false);
|
||||
|
||||
if (EPOUT_EN(uac2_opts)) {
|
||||
agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
|
||||
if (!agdev->out_ep) {
|
||||
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
if (EPIN_EN(uac2_opts)) {
|
||||
agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc);
|
||||
if (!agdev->in_ep) {
|
||||
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
agdev->in_ep_maxpsize = max_t(u16,
|
||||
le16_to_cpu(fs_epin_desc.wMaxPacketSize),
|
||||
|
@ -578,6 +704,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
|
|||
hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
|
||||
hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
|
||||
|
||||
setup_descriptor(uac2_opts);
|
||||
|
||||
ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL,
|
||||
NULL);
|
||||
if (ret)
|
||||
|
|
|
@ -197,12 +197,6 @@ static const struct usb_descriptor_header * const uvc_ss_streaming[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
void uvc_set_trace_param(unsigned int trace)
|
||||
{
|
||||
uvc_gadget_trace_param = trace;
|
||||
}
|
||||
EXPORT_SYMBOL(uvc_set_trace_param);
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* Control requests
|
||||
*/
|
||||
|
@ -232,13 +226,8 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
|
|||
struct v4l2_event v4l2_event;
|
||||
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
|
||||
|
||||
/* printk(KERN_INFO "setup request %02x %02x value %04x index %04x %04x\n",
|
||||
* ctrl->bRequestType, ctrl->bRequest, le16_to_cpu(ctrl->wValue),
|
||||
* le16_to_cpu(ctrl->wIndex), le16_to_cpu(ctrl->wLength));
|
||||
*/
|
||||
|
||||
if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) {
|
||||
INFO(f->config->cdev, "invalid request type\n");
|
||||
uvcg_info(f, "invalid request type\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -272,7 +261,7 @@ uvc_function_get_alt(struct usb_function *f, unsigned interface)
|
|||
{
|
||||
struct uvc_device *uvc = to_uvc(f);
|
||||
|
||||
INFO(f->config->cdev, "uvc_function_get_alt(%u)\n", interface);
|
||||
uvcg_info(f, "%s(%u)\n", __func__, interface);
|
||||
|
||||
if (interface == uvc->control_intf)
|
||||
return 0;
|
||||
|
@ -291,13 +280,13 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
|
|||
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
|
||||
int ret;
|
||||
|
||||
INFO(cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt);
|
||||
uvcg_info(f, "%s(%u, %u)\n", __func__, interface, alt);
|
||||
|
||||
if (interface == uvc->control_intf) {
|
||||
if (alt)
|
||||
return -EINVAL;
|
||||
|
||||
INFO(cdev, "reset UVC Control\n");
|
||||
uvcg_info(f, "reset UVC Control\n");
|
||||
usb_ep_disable(uvc->control_ep);
|
||||
|
||||
if (!uvc->control_ep->desc)
|
||||
|
@ -348,7 +337,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
|
|||
if (!uvc->video.ep)
|
||||
return -EINVAL;
|
||||
|
||||
INFO(cdev, "reset UVC\n");
|
||||
uvcg_info(f, "reset UVC\n");
|
||||
usb_ep_disable(uvc->video.ep);
|
||||
|
||||
ret = config_ep_by_speed(f->config->cdev->gadget,
|
||||
|
@ -373,7 +362,7 @@ uvc_function_disable(struct usb_function *f)
|
|||
struct uvc_device *uvc = to_uvc(f);
|
||||
struct v4l2_event v4l2_event;
|
||||
|
||||
INFO(f->config->cdev, "uvc_function_disable\n");
|
||||
uvcg_info(f, "%s()\n", __func__);
|
||||
|
||||
memset(&v4l2_event, 0, sizeof(v4l2_event));
|
||||
v4l2_event.type = UVC_EVENT_DISCONNECT;
|
||||
|
@ -392,21 +381,19 @@ uvc_function_disable(struct usb_function *f)
|
|||
void
|
||||
uvc_function_connect(struct uvc_device *uvc)
|
||||
{
|
||||
struct usb_composite_dev *cdev = uvc->func.config->cdev;
|
||||
int ret;
|
||||
|
||||
if ((ret = usb_function_activate(&uvc->func)) < 0)
|
||||
INFO(cdev, "UVC connect failed with %d\n", ret);
|
||||
uvcg_info(&uvc->func, "UVC connect failed with %d\n", ret);
|
||||
}
|
||||
|
||||
void
|
||||
uvc_function_disconnect(struct uvc_device *uvc)
|
||||
{
|
||||
struct usb_composite_dev *cdev = uvc->func.config->cdev;
|
||||
int ret;
|
||||
|
||||
if ((ret = usb_function_deactivate(&uvc->func)) < 0)
|
||||
INFO(cdev, "UVC disconnect failed with %d\n", ret);
|
||||
uvcg_info(&uvc->func, "UVC disconnect failed with %d\n", ret);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
|
@ -605,7 +592,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
struct f_uvc_opts *opts;
|
||||
int ret = -EINVAL;
|
||||
|
||||
INFO(cdev, "uvc_function_bind\n");
|
||||
uvcg_info(f, "%s()\n", __func__);
|
||||
|
||||
opts = fi_to_f_uvc_opts(f->fi);
|
||||
/* Sanity check the streaming endpoint module parameters.
|
||||
|
@ -618,7 +605,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
if (opts->streaming_maxburst &&
|
||||
(opts->streaming_maxpacket % 1024) != 0) {
|
||||
opts->streaming_maxpacket = roundup(opts->streaming_maxpacket, 1024);
|
||||
INFO(cdev, "overriding streaming_maxpacket to %d\n",
|
||||
uvcg_info(f, "overriding streaming_maxpacket to %d\n",
|
||||
opts->streaming_maxpacket);
|
||||
}
|
||||
|
||||
|
@ -658,7 +645,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
/* Allocate endpoints. */
|
||||
ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep);
|
||||
if (!ep) {
|
||||
INFO(cdev, "Unable to allocate control EP\n");
|
||||
uvcg_info(f, "Unable to allocate control EP\n");
|
||||
goto error;
|
||||
}
|
||||
uvc->control_ep = ep;
|
||||
|
@ -672,7 +659,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep);
|
||||
|
||||
if (!ep) {
|
||||
INFO(cdev, "Unable to allocate streaming EP\n");
|
||||
uvcg_info(f, "Unable to allocate streaming EP\n");
|
||||
goto error;
|
||||
}
|
||||
uvc->video.ep = ep;
|
||||
|
@ -699,12 +686,14 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
uvc_iad.bFirstInterface = ret;
|
||||
uvc_control_intf.bInterfaceNumber = ret;
|
||||
uvc->control_intf = ret;
|
||||
opts->control_interface = ret;
|
||||
|
||||
if ((ret = usb_interface_id(c, f)) < 0)
|
||||
goto error;
|
||||
uvc_streaming_intf_alt0.bInterfaceNumber = ret;
|
||||
uvc_streaming_intf_alt1.bInterfaceNumber = ret;
|
||||
uvc->streaming_intf = ret;
|
||||
opts->streaming_interface = ret;
|
||||
|
||||
/* Copy descriptors */
|
||||
f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
|
||||
|
@ -743,19 +732,19 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
uvc->control_req->context = uvc;
|
||||
|
||||
if (v4l2_device_register(&cdev->gadget->dev, &uvc->v4l2_dev)) {
|
||||
printk(KERN_INFO "v4l2_device_register failed\n");
|
||||
uvcg_err(f, "failed to register V4L2 device\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Initialise video. */
|
||||
ret = uvcg_video_init(&uvc->video);
|
||||
ret = uvcg_video_init(&uvc->video, uvc);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
/* Register a V4L2 device. */
|
||||
ret = uvc_register_video(uvc);
|
||||
if (ret < 0) {
|
||||
printk(KERN_INFO "Unable to register video device\n");
|
||||
uvcg_err(f, "failed to register video device\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -792,6 +781,7 @@ static struct usb_function_instance *uvc_alloc_inst(void)
|
|||
struct uvc_output_terminal_descriptor *od;
|
||||
struct uvc_color_matching_descriptor *md;
|
||||
struct uvc_descriptor_header **ctl_cls;
|
||||
int ret;
|
||||
|
||||
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
|
||||
if (!opts)
|
||||
|
@ -868,7 +858,12 @@ static struct usb_function_instance *uvc_alloc_inst(void)
|
|||
opts->streaming_interval = 1;
|
||||
opts->streaming_maxpacket = 1024;
|
||||
|
||||
uvcg_attach_configfs(opts);
|
||||
ret = uvcg_attach_configfs(opts);
|
||||
if (ret < 0) {
|
||||
kfree(opts);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return &opts->func_inst;
|
||||
}
|
||||
|
||||
|
@ -886,7 +881,7 @@ static void uvc_unbind(struct usb_configuration *c, struct usb_function *f)
|
|||
struct usb_composite_dev *cdev = c->cdev;
|
||||
struct uvc_device *uvc = to_uvc(f);
|
||||
|
||||
INFO(cdev, "%s\n", __func__);
|
||||
uvcg_info(f, "%s\n", __func__);
|
||||
|
||||
device_remove_file(&uvc->vdev.dev, &dev_attr_function_name);
|
||||
video_unregister_device(&uvc->vdev);
|
||||
|
|
|
@ -25,6 +25,9 @@ struct f_uvc_opts {
|
|||
unsigned int streaming_maxpacket;
|
||||
unsigned int streaming_maxburst;
|
||||
|
||||
unsigned int control_interface;
|
||||
unsigned int streaming_interface;
|
||||
|
||||
/*
|
||||
* Control descriptors array pointers for full-/high-speed and
|
||||
* super-speed. They point by default to the uvc_fs_control_cls and
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
struct usb_ep;
|
||||
struct usb_request;
|
||||
struct uvc_descriptor_header;
|
||||
struct uvc_device;
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Debugging, printing and logging
|
||||
|
@ -51,14 +52,12 @@ extern unsigned int uvc_gadget_trace_param;
|
|||
printk(KERN_DEBUG "uvcvideo: " msg); \
|
||||
} while (0)
|
||||
|
||||
#define uvc_warn_once(dev, warn, msg...) \
|
||||
do { \
|
||||
if (!test_and_set_bit(warn, &dev->warnings)) \
|
||||
printk(KERN_INFO "uvcvideo: " msg); \
|
||||
} while (0)
|
||||
|
||||
#define uvc_printk(level, msg...) \
|
||||
printk(level "uvcvideo: " msg)
|
||||
#define uvcg_dbg(f, fmt, args...) \
|
||||
dev_dbg(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
|
||||
#define uvcg_info(f, fmt, args...) \
|
||||
dev_info(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
|
||||
#define uvcg_err(f, fmt, args...) \
|
||||
dev_err(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Driver specific constants
|
||||
|
@ -73,6 +72,7 @@ extern unsigned int uvc_gadget_trace_param;
|
|||
*/
|
||||
|
||||
struct uvc_video {
|
||||
struct uvc_device *uvc;
|
||||
struct usb_ep *ep;
|
||||
|
||||
/* Frame parameters */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -115,7 +115,7 @@ uvc_v4l2_set_format(struct file *file, void *fh, struct v4l2_format *fmt)
|
|||
}
|
||||
|
||||
if (i == ARRAY_SIZE(uvc_formats)) {
|
||||
printk(KERN_INFO "Unsupported format 0x%08x.\n",
|
||||
uvcg_info(&uvc->func, "Unsupported format 0x%08x.\n",
|
||||
fmt->fmt.pix.pixelformat);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -125,6 +125,23 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
|
|||
* Request handling
|
||||
*/
|
||||
|
||||
static int uvcg_video_ep_queue(struct uvc_video *video, struct usb_request *req)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = usb_ep_queue(video->ep, req, GFP_ATOMIC);
|
||||
if (ret < 0) {
|
||||
uvcg_err(&video->uvc->func, "Failed to queue request (%d).\n",
|
||||
ret);
|
||||
|
||||
/* Isochronous endpoints can't be halted. */
|
||||
if (usb_endpoint_xfer_bulk(video->ep->desc))
|
||||
usb_ep_set_halt(video->ep);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* I somehow feel that synchronisation won't be easy to achieve here. We have
|
||||
* three events that control USB requests submission:
|
||||
|
@ -169,12 +186,13 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
|
|||
break;
|
||||
|
||||
case -ESHUTDOWN: /* disconnect from host. */
|
||||
printk(KERN_DEBUG "VS request cancelled.\n");
|
||||
uvcg_dbg(&video->uvc->func, "VS request cancelled.\n");
|
||||
uvcg_queue_cancel(queue, 1);
|
||||
goto requeue;
|
||||
|
||||
default:
|
||||
printk(KERN_INFO "VS request completed with status %d.\n",
|
||||
uvcg_info(&video->uvc->func,
|
||||
"VS request completed with status %d.\n",
|
||||
req->status);
|
||||
uvcg_queue_cancel(queue, 0);
|
||||
goto requeue;
|
||||
|
@ -189,14 +207,13 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
|
|||
|
||||
video->encode(req, video, buf);
|
||||
|
||||
if ((ret = usb_ep_queue(ep, req, GFP_ATOMIC)) < 0) {
|
||||
printk(KERN_INFO "Failed to queue request (%d).\n", ret);
|
||||
usb_ep_set_halt(ep);
|
||||
ret = uvcg_video_ep_queue(video, req);
|
||||
spin_unlock_irqrestore(&video->queue.irqlock, flags);
|
||||
|
||||
if (ret < 0) {
|
||||
uvcg_queue_cancel(queue, 0);
|
||||
goto requeue;
|
||||
}
|
||||
spin_unlock_irqrestore(&video->queue.irqlock, flags);
|
||||
|
||||
return;
|
||||
|
||||
|
@ -316,15 +333,13 @@ int uvcg_video_pump(struct uvc_video *video)
|
|||
video->encode(req, video, buf);
|
||||
|
||||
/* Queue the USB request */
|
||||
ret = usb_ep_queue(video->ep, req, GFP_ATOMIC);
|
||||
if (ret < 0) {
|
||||
printk(KERN_INFO "Failed to queue request (%d)\n", ret);
|
||||
usb_ep_set_halt(video->ep);
|
||||
ret = uvcg_video_ep_queue(video, req);
|
||||
spin_unlock_irqrestore(&queue->irqlock, flags);
|
||||
|
||||
if (ret < 0) {
|
||||
uvcg_queue_cancel(queue, 0);
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&queue->irqlock, flags);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&video->req_lock, flags);
|
||||
|
@ -342,8 +357,8 @@ int uvcg_video_enable(struct uvc_video *video, int enable)
|
|||
int ret;
|
||||
|
||||
if (video->ep == NULL) {
|
||||
printk(KERN_INFO "Video enable failed, device is "
|
||||
"uninitialized.\n");
|
||||
uvcg_info(&video->uvc->func,
|
||||
"Video enable failed, device is uninitialized.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -375,11 +390,12 @@ int uvcg_video_enable(struct uvc_video *video, int enable)
|
|||
/*
|
||||
* Initialize the UVC video stream.
|
||||
*/
|
||||
int uvcg_video_init(struct uvc_video *video)
|
||||
int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc)
|
||||
{
|
||||
INIT_LIST_HEAD(&video->req_free);
|
||||
spin_lock_init(&video->req_lock);
|
||||
|
||||
video->uvc = uvc;
|
||||
video->fcc = V4L2_PIX_FMT_YUYV;
|
||||
video->bpp = 16;
|
||||
video->width = 320;
|
||||
|
|
|
@ -18,6 +18,6 @@ int uvcg_video_pump(struct uvc_video *video);
|
|||
|
||||
int uvcg_video_enable(struct uvc_video *video, int enable);
|
||||
|
||||
int uvcg_video_init(struct uvc_video *video);
|
||||
int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc);
|
||||
|
||||
#endif /* __UVC_VIDEO_H__ */
|
||||
|
|
|
@ -2004,7 +2004,6 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
|
|||
struct usba_udc *udc)
|
||||
{
|
||||
u32 val;
|
||||
const char *name;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct of_device_id *match;
|
||||
struct device_node *pp;
|
||||
|
@ -2017,6 +2016,8 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
|
|||
|
||||
udc->errata = match->data;
|
||||
udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9g45-pmc");
|
||||
if (IS_ERR(udc->pmc))
|
||||
udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9rl-pmc");
|
||||
if (IS_ERR(udc->pmc))
|
||||
udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9x5-pmc");
|
||||
if (udc->errata && IS_ERR(udc->pmc))
|
||||
|
@ -2094,11 +2095,6 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
|
|||
ep->can_dma = of_property_read_bool(pp, "atmel,can-dma");
|
||||
ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc");
|
||||
|
||||
ret = of_property_read_string(pp, "name", &name);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "of_probe: name error(%d)\n", ret);
|
||||
goto err;
|
||||
}
|
||||
sprintf(ep->name, "ep%d", ep->index);
|
||||
ep->ep.name = ep->name;
|
||||
|
||||
|
|
|
@ -690,6 +690,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_connect);
|
|||
* as a disconnect (when a VBUS session is active). Not all systems
|
||||
* support software pullup controls.
|
||||
*
|
||||
* Following a successful disconnect, invoke the ->disconnect() callback
|
||||
* for the current gadget driver so that UDC drivers don't need to.
|
||||
*
|
||||
* Returns zero on success, else negative errno.
|
||||
*/
|
||||
int usb_gadget_disconnect(struct usb_gadget *gadget)
|
||||
|
@ -711,8 +714,10 @@ int usb_gadget_disconnect(struct usb_gadget *gadget)
|
|||
}
|
||||
|
||||
ret = gadget->ops->pullup(gadget, 0);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
gadget->connected = 0;
|
||||
gadget->udc->driver->disconnect(gadget);
|
||||
}
|
||||
|
||||
out:
|
||||
trace_usb_gadget_disconnect(gadget, ret);
|
||||
|
@ -1281,7 +1286,6 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
|
|||
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
|
||||
|
||||
usb_gadget_disconnect(udc->gadget);
|
||||
udc->driver->disconnect(udc->gadget);
|
||||
udc->driver->unbind(udc->gadget);
|
||||
usb_gadget_udc_stop(udc);
|
||||
|
||||
|
@ -1471,7 +1475,6 @@ static ssize_t soft_connect_store(struct device *dev,
|
|||
usb_gadget_connect(udc->gadget);
|
||||
} else if (sysfs_streq(buf, "disconnect")) {
|
||||
usb_gadget_disconnect(udc->gadget);
|
||||
udc->driver->disconnect(udc->gadget);
|
||||
usb_gadget_udc_stop(udc);
|
||||
} else {
|
||||
dev_err(dev, "unsupported command '%s'\n", buf);
|
||||
|
|
|
@ -741,7 +741,7 @@ static void fotg210_get_status(struct fotg210_udc *fotg210,
|
|||
fotg210->ep0_req->length = 2;
|
||||
|
||||
spin_unlock(&fotg210->lock);
|
||||
fotg210_ep_queue(fotg210->gadget.ep0, fotg210->ep0_req, GFP_KERNEL);
|
||||
fotg210_ep_queue(fotg210->gadget.ep0, fotg210->ep0_req, GFP_ATOMIC);
|
||||
spin_lock(&fotg210->lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -2234,8 +2234,10 @@ static void fsl_udc_release(struct device *dev)
|
|||
Internal structure setup functions
|
||||
*******************************************************************/
|
||||
/*------------------------------------------------------------------
|
||||
* init resource for globle controller
|
||||
* Return the udc handle on success or NULL on failure
|
||||
* init resource for global controller called by fsl_udc_probe()
|
||||
* On success the udc handle is initialized, on failure it is
|
||||
* unchanged (reset).
|
||||
* Return 0 on success and -1 on allocation failure
|
||||
------------------------------------------------------------------*/
|
||||
static int struct_udc_setup(struct fsl_udc *udc,
|
||||
struct platform_device *pdev)
|
||||
|
@ -2247,8 +2249,10 @@ static int struct_udc_setup(struct fsl_udc *udc,
|
|||
udc->phy_mode = pdata->phy_mode;
|
||||
|
||||
udc->eps = kcalloc(udc->max_ep, sizeof(struct fsl_ep), GFP_KERNEL);
|
||||
if (!udc->eps)
|
||||
return -1;
|
||||
if (!udc->eps) {
|
||||
ERR("kmalloc udc endpoint status failed\n");
|
||||
goto eps_alloc_failed;
|
||||
}
|
||||
|
||||
/* initialized QHs, take care of alignment */
|
||||
size = udc->max_ep * sizeof(struct ep_queue_head);
|
||||
|
@ -2262,8 +2266,7 @@ static int struct_udc_setup(struct fsl_udc *udc,
|
|||
&udc->ep_qh_dma, GFP_KERNEL);
|
||||
if (!udc->ep_qh) {
|
||||
ERR("malloc QHs for udc failed\n");
|
||||
kfree(udc->eps);
|
||||
return -1;
|
||||
goto ep_queue_alloc_failed;
|
||||
}
|
||||
|
||||
udc->ep_qh_size = size;
|
||||
|
@ -2272,8 +2275,17 @@ static int struct_udc_setup(struct fsl_udc *udc,
|
|||
/* FIXME: fsl_alloc_request() ignores ep argument */
|
||||
udc->status_req = container_of(fsl_alloc_request(NULL, GFP_KERNEL),
|
||||
struct fsl_req, req);
|
||||
if (!udc->status_req) {
|
||||
ERR("kzalloc for udc status request failed\n");
|
||||
goto udc_status_alloc_failed;
|
||||
}
|
||||
|
||||
/* allocate a small amount of memory to get valid address */
|
||||
udc->status_req->req.buf = kmalloc(8, GFP_KERNEL);
|
||||
if (!udc->status_req->req.buf) {
|
||||
ERR("kzalloc for udc request buffer failed\n");
|
||||
goto udc_req_buf_alloc_failed;
|
||||
}
|
||||
|
||||
udc->resume_state = USB_STATE_NOTATTACHED;
|
||||
udc->usb_state = USB_STATE_POWERED;
|
||||
|
@ -2281,6 +2293,18 @@ static int struct_udc_setup(struct fsl_udc *udc,
|
|||
udc->remote_wakeup = 0; /* default to 0 on reset */
|
||||
|
||||
return 0;
|
||||
|
||||
udc_req_buf_alloc_failed:
|
||||
kfree(udc->status_req);
|
||||
udc_status_alloc_failed:
|
||||
kfree(udc->ep_qh);
|
||||
udc->ep_qh_size = 0;
|
||||
ep_queue_alloc_failed:
|
||||
kfree(udc->eps);
|
||||
eps_alloc_failed:
|
||||
udc->phy_mode = 0;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
|
|
|
@ -185,7 +185,7 @@ static int process_ep_req(struct mv_udc *udc, int index,
|
|||
else
|
||||
bit_pos = 1 << (16 + curr_req->ep->ep_num);
|
||||
|
||||
while ((curr_dqh->curr_dtd_ptr == curr_dtd->td_dma)) {
|
||||
while (curr_dqh->curr_dtd_ptr == curr_dtd->td_dma) {
|
||||
if (curr_dtd->dtd_next == EP_QUEUE_HEAD_NEXT_TERMINATE) {
|
||||
while (readl(&udc->op_regs->epstatus) & bit_pos)
|
||||
udelay(1);
|
||||
|
|
|
@ -1550,9 +1550,6 @@ static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
|
|||
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
if (!is_on && dev->driver)
|
||||
dev->driver->disconnect(&dev->gadget);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -2437,6 +2437,9 @@ static ssize_t renesas_usb3_b_device_write(struct file *file,
|
|||
else
|
||||
usb3->forced_b_device = false;
|
||||
|
||||
if (usb3->workaround_for_vbus)
|
||||
usb3_disconnect(usb3);
|
||||
|
||||
/* Let this driver call usb3_connect() anyway */
|
||||
usb3_check_id(usb3);
|
||||
|
||||
|
@ -2600,6 +2603,13 @@ static const struct renesas_usb3_priv renesas_usb3_priv_gen3 = {
|
|||
.ramsize_per_pipe = SZ_4K,
|
||||
};
|
||||
|
||||
static const struct renesas_usb3_priv renesas_usb3_priv_r8a77990 = {
|
||||
.ramsize_per_ramif = SZ_16K,
|
||||
.num_ramif = 4,
|
||||
.ramsize_per_pipe = SZ_4K,
|
||||
.workaround_for_vbus = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id usb3_of_match[] = {
|
||||
{
|
||||
.compatible = "renesas,r8a7795-usb3-peri",
|
||||
|
@ -2618,6 +2628,10 @@ static const struct soc_device_attribute renesas_usb3_quirks_match[] = {
|
|||
.soc_id = "r8a7795", .revision = "ES1.*",
|
||||
.data = &renesas_usb3_priv_r8a7795_es1,
|
||||
},
|
||||
{
|
||||
.soc_id = "r8a77990",
|
||||
.data = &renesas_usb3_priv_r8a77990,
|
||||
},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
|
|
|
@ -195,9 +195,9 @@ struct uvc_header_descriptor {
|
|||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
__u16 bcdUVC;
|
||||
__u16 wTotalLength;
|
||||
__u32 dwClockFrequency;
|
||||
__le16 bcdUVC;
|
||||
__le16 wTotalLength;
|
||||
__le32 dwClockFrequency;
|
||||
__u8 bInCollection;
|
||||
__u8 baInterfaceNr[];
|
||||
} __attribute__((__packed__));
|
||||
|
@ -212,9 +212,9 @@ struct UVC_HEADER_DESCRIPTOR(n) { \
|
|||
__u8 bLength; \
|
||||
__u8 bDescriptorType; \
|
||||
__u8 bDescriptorSubType; \
|
||||
__u16 bcdUVC; \
|
||||
__u16 wTotalLength; \
|
||||
__u32 dwClockFrequency; \
|
||||
__le16 bcdUVC; \
|
||||
__le16 wTotalLength; \
|
||||
__le32 dwClockFrequency; \
|
||||
__u8 bInCollection; \
|
||||
__u8 baInterfaceNr[n]; \
|
||||
} __attribute__ ((packed))
|
||||
|
@ -225,7 +225,7 @@ struct uvc_input_terminal_descriptor {
|
|||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
__u8 bTerminalID;
|
||||
__u16 wTerminalType;
|
||||
__le16 wTerminalType;
|
||||
__u8 bAssocTerminal;
|
||||
__u8 iTerminal;
|
||||
} __attribute__((__packed__));
|
||||
|
@ -238,7 +238,7 @@ struct uvc_output_terminal_descriptor {
|
|||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
__u8 bTerminalID;
|
||||
__u16 wTerminalType;
|
||||
__le16 wTerminalType;
|
||||
__u8 bAssocTerminal;
|
||||
__u8 bSourceID;
|
||||
__u8 iTerminal;
|
||||
|
@ -252,12 +252,12 @@ struct uvc_camera_terminal_descriptor {
|
|||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
__u8 bTerminalID;
|
||||
__u16 wTerminalType;
|
||||
__le16 wTerminalType;
|
||||
__u8 bAssocTerminal;
|
||||
__u8 iTerminal;
|
||||
__u16 wObjectiveFocalLengthMin;
|
||||
__u16 wObjectiveFocalLengthMax;
|
||||
__u16 wOcularFocalLength;
|
||||
__le16 wObjectiveFocalLengthMin;
|
||||
__le16 wObjectiveFocalLengthMax;
|
||||
__le16 wOcularFocalLength;
|
||||
__u8 bControlSize;
|
||||
__u8 bmControls[3];
|
||||
} __attribute__((__packed__));
|
||||
|
@ -298,7 +298,7 @@ struct uvc_processing_unit_descriptor {
|
|||
__u8 bDescriptorSubType;
|
||||
__u8 bUnitID;
|
||||
__u8 bSourceID;
|
||||
__u16 wMaxMultiplier;
|
||||
__le16 wMaxMultiplier;
|
||||
__u8 bControlSize;
|
||||
__u8 bmControls[2];
|
||||
__u8 iProcessing;
|
||||
|
@ -346,7 +346,7 @@ struct uvc_control_endpoint_descriptor {
|
|||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
__u16 wMaxTransferSize;
|
||||
__le16 wMaxTransferSize;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define UVC_DT_CONTROL_ENDPOINT_SIZE 5
|
||||
|
@ -357,7 +357,7 @@ struct uvc_input_header_descriptor {
|
|||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
__u8 bNumFormats;
|
||||
__u16 wTotalLength;
|
||||
__le16 wTotalLength;
|
||||
__u8 bEndpointAddress;
|
||||
__u8 bmInfo;
|
||||
__u8 bTerminalLink;
|
||||
|
@ -379,7 +379,7 @@ struct UVC_INPUT_HEADER_DESCRIPTOR(n, p) { \
|
|||
__u8 bDescriptorType; \
|
||||
__u8 bDescriptorSubType; \
|
||||
__u8 bNumFormats; \
|
||||
__u16 wTotalLength; \
|
||||
__le16 wTotalLength; \
|
||||
__u8 bEndpointAddress; \
|
||||
__u8 bmInfo; \
|
||||
__u8 bTerminalLink; \
|
||||
|
@ -396,7 +396,7 @@ struct uvc_output_header_descriptor {
|
|||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
__u8 bNumFormats;
|
||||
__u16 wTotalLength;
|
||||
__le16 wTotalLength;
|
||||
__u8 bEndpointAddress;
|
||||
__u8 bTerminalLink;
|
||||
__u8 bControlSize;
|
||||
|
@ -414,7 +414,7 @@ struct UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) { \
|
|||
__u8 bDescriptorType; \
|
||||
__u8 bDescriptorSubType; \
|
||||
__u8 bNumFormats; \
|
||||
__u16 wTotalLength; \
|
||||
__le16 wTotalLength; \
|
||||
__u8 bEndpointAddress; \
|
||||
__u8 bTerminalLink; \
|
||||
__u8 bControlSize; \
|
||||
|
@ -478,14 +478,14 @@ struct uvc_frame_uncompressed {
|
|||
__u8 bDescriptorSubType;
|
||||
__u8 bFrameIndex;
|
||||
__u8 bmCapabilities;
|
||||
__u16 wWidth;
|
||||
__u16 wHeight;
|
||||
__u32 dwMinBitRate;
|
||||
__u32 dwMaxBitRate;
|
||||
__u32 dwMaxVideoFrameBufferSize;
|
||||
__u32 dwDefaultFrameInterval;
|
||||
__le16 wWidth;
|
||||
__le16 wHeight;
|
||||
__le32 dwMinBitRate;
|
||||
__le32 dwMaxBitRate;
|
||||
__le32 dwMaxVideoFrameBufferSize;
|
||||
__le32 dwDefaultFrameInterval;
|
||||
__u8 bFrameIntervalType;
|
||||
__u32 dwFrameInterval[];
|
||||
__le32 dwFrameInterval[];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define UVC_DT_FRAME_UNCOMPRESSED_SIZE(n) (26+4*(n))
|
||||
|
@ -500,14 +500,14 @@ struct UVC_FRAME_UNCOMPRESSED(n) { \
|
|||
__u8 bDescriptorSubType; \
|
||||
__u8 bFrameIndex; \
|
||||
__u8 bmCapabilities; \
|
||||
__u16 wWidth; \
|
||||
__u16 wHeight; \
|
||||
__u32 dwMinBitRate; \
|
||||
__u32 dwMaxBitRate; \
|
||||
__u32 dwMaxVideoFrameBufferSize; \
|
||||
__u32 dwDefaultFrameInterval; \
|
||||
__le16 wWidth; \
|
||||
__le16 wHeight; \
|
||||
__le32 dwMinBitRate; \
|
||||
__le32 dwMaxBitRate; \
|
||||
__le32 dwMaxVideoFrameBufferSize; \
|
||||
__le32 dwDefaultFrameInterval; \
|
||||
__u8 bFrameIntervalType; \
|
||||
__u32 dwFrameInterval[n]; \
|
||||
__le32 dwFrameInterval[n]; \
|
||||
} __attribute__ ((packed))
|
||||
|
||||
/* MJPEG Payload - 3.1.1. MJPEG Video Format Descriptor */
|
||||
|
@ -534,14 +534,14 @@ struct uvc_frame_mjpeg {
|
|||
__u8 bDescriptorSubType;
|
||||
__u8 bFrameIndex;
|
||||
__u8 bmCapabilities;
|
||||
__u16 wWidth;
|
||||
__u16 wHeight;
|
||||
__u32 dwMinBitRate;
|
||||
__u32 dwMaxBitRate;
|
||||
__u32 dwMaxVideoFrameBufferSize;
|
||||
__u32 dwDefaultFrameInterval;
|
||||
__le16 wWidth;
|
||||
__le16 wHeight;
|
||||
__le32 dwMinBitRate;
|
||||
__le32 dwMaxBitRate;
|
||||
__le32 dwMaxVideoFrameBufferSize;
|
||||
__le32 dwDefaultFrameInterval;
|
||||
__u8 bFrameIntervalType;
|
||||
__u32 dwFrameInterval[];
|
||||
__le32 dwFrameInterval[];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define UVC_DT_FRAME_MJPEG_SIZE(n) (26+4*(n))
|
||||
|
@ -556,14 +556,14 @@ struct UVC_FRAME_MJPEG(n) { \
|
|||
__u8 bDescriptorSubType; \
|
||||
__u8 bFrameIndex; \
|
||||
__u8 bmCapabilities; \
|
||||
__u16 wWidth; \
|
||||
__u16 wHeight; \
|
||||
__u32 dwMinBitRate; \
|
||||
__u32 dwMaxBitRate; \
|
||||
__u32 dwMaxVideoFrameBufferSize; \
|
||||
__u32 dwDefaultFrameInterval; \
|
||||
__le16 wWidth; \
|
||||
__le16 wHeight; \
|
||||
__le32 dwMinBitRate; \
|
||||
__le32 dwMaxBitRate; \
|
||||
__le32 dwMaxVideoFrameBufferSize; \
|
||||
__le32 dwDefaultFrameInterval; \
|
||||
__u8 bFrameIntervalType; \
|
||||
__u32 dwFrameInterval[n]; \
|
||||
__le32 dwFrameInterval[n]; \
|
||||
} __attribute__ ((packed))
|
||||
|
||||
#endif /* __LINUX_USB_VIDEO_H */
|
||||
|
|
Loading…
Reference in New Issue