Commit c7c24e7a authored by Artur Petrosyan's avatar Artur Petrosyan Committed by Felipe Balbi

usb: dwc2: Change reading of current frame number flow.

The current frame_number is read from core for both
device and host modes. Reading of the current frame
number needs to be performed ASAP due to IRQ latency's.
This is why, it is moved to common interrupt handler.

Accordingly updated dwc2_gadget_target_frame_elapsed()
function which uses stored frame_number instead of
reading frame number.

In cases when target frame value is incremented
the frame_number is required to read again.
Signed-off-by: default avatarArtur Petrosyan <arturp@synopsys.com>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
parent 971b750d
...@@ -824,6 +824,9 @@ struct dwc2_hregs_backup { ...@@ -824,6 +824,9 @@ struct dwc2_hregs_backup {
* @gadget_enabled Peripheral mode sub-driver initialization indicator. * @gadget_enabled Peripheral mode sub-driver initialization indicator.
* @ll_hw_enabled Status of low-level hardware resources. * @ll_hw_enabled Status of low-level hardware resources.
* @hibernated: True if core is hibernated * @hibernated: True if core is hibernated
* @frame_number: Frame number read from the core. For both device
* and host modes. The value ranges are from 0
* to HFNUM_MAX_FRNUM.
* @phy: The otg phy transceiver structure for phy control. * @phy: The otg phy transceiver structure for phy control.
* @uphy: The otg phy transceiver structure for old USB phy * @uphy: The otg phy transceiver structure for old USB phy
* control. * control.
...@@ -897,8 +900,6 @@ struct dwc2_hregs_backup { ...@@ -897,8 +900,6 @@ struct dwc2_hregs_backup {
* @hs_periodic_bitmap: Bitmap used by the microframe scheduler any time the * @hs_periodic_bitmap: Bitmap used by the microframe scheduler any time the
* host is in high speed mode; low speed schedules are * host is in high speed mode; low speed schedules are
* stored elsewhere since we need one per TT. * stored elsewhere since we need one per TT.
* @frame_number: Frame number read from the core at SOF. The value ranges
* from 0 to HFNUM_MAX_FRNUM.
* @periodic_qh_count: Count of periodic QHs, if using several eps. Used for * @periodic_qh_count: Count of periodic QHs, if using several eps. Used for
* SOF enable/disable. * SOF enable/disable.
* @free_hc_list: Free host channels in the controller. This is a list of * @free_hc_list: Free host channels in the controller. This is a list of
...@@ -965,6 +966,7 @@ struct dwc2_hsotg { ...@@ -965,6 +966,7 @@ struct dwc2_hsotg {
unsigned int gadget_enabled:1; unsigned int gadget_enabled:1;
unsigned int ll_hw_enabled:1; unsigned int ll_hw_enabled:1;
unsigned int hibernated:1; unsigned int hibernated:1;
u16 frame_number;
struct phy *phy; struct phy *phy;
struct usb_phy *uphy; struct usb_phy *uphy;
...@@ -1038,7 +1040,6 @@ struct dwc2_hsotg { ...@@ -1038,7 +1040,6 @@ struct dwc2_hsotg {
u16 periodic_usecs; u16 periodic_usecs;
unsigned long hs_periodic_bitmap[ unsigned long hs_periodic_bitmap[
DIV_ROUND_UP(DWC2_HS_SCHEDULE_US, BITS_PER_LONG)]; DIV_ROUND_UP(DWC2_HS_SCHEDULE_US, BITS_PER_LONG)];
u16 frame_number;
u16 periodic_qh_count; u16 periodic_qh_count;
bool bus_suspended; bool bus_suspended;
bool new_connection; bool new_connection;
......
...@@ -778,6 +778,14 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev) ...@@ -778,6 +778,14 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
goto out; goto out;
} }
/* Reading current frame number value in device or host modes. */
if (dwc2_is_device_mode(hsotg))
hsotg->frame_number = (dwc2_readl(hsotg->regs + DSTS)
& DSTS_SOFFN_MASK) >> DSTS_SOFFN_SHIFT;
else
hsotg->frame_number = (dwc2_readl(hsotg->regs + HFNUM)
& HFNUM_FRNUM_MASK) >> HFNUM_FRNUM_SHIFT;
gintsts = dwc2_read_common_intr(hsotg); gintsts = dwc2_read_common_intr(hsotg);
if (gintsts & ~GINTSTS_PRTINT) if (gintsts & ~GINTSTS_PRTINT)
retval = IRQ_HANDLED; retval = IRQ_HANDLED;
......
...@@ -1225,7 +1225,7 @@ static bool dwc2_gadget_target_frame_elapsed(struct dwc2_hsotg_ep *hs_ep) ...@@ -1225,7 +1225,7 @@ static bool dwc2_gadget_target_frame_elapsed(struct dwc2_hsotg_ep *hs_ep)
{ {
struct dwc2_hsotg *hsotg = hs_ep->parent; struct dwc2_hsotg *hsotg = hs_ep->parent;
u32 target_frame = hs_ep->target_frame; u32 target_frame = hs_ep->target_frame;
u32 current_frame = dwc2_hsotg_read_frameno(hsotg); u32 current_frame = hsotg->frame_number;
bool frame_overrun = hs_ep->frame_overrun; bool frame_overrun = hs_ep->frame_overrun;
if (!frame_overrun && current_frame >= target_frame) if (!frame_overrun && current_frame >= target_frame)
...@@ -1359,8 +1359,15 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, ...@@ -1359,8 +1359,15 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
return 0; return 0;
} }
while (dwc2_gadget_target_frame_elapsed(hs_ep)) /* Update current frame number value. */
hs->frame_number = dwc2_hsotg_read_frameno(hs);
while (dwc2_gadget_target_frame_elapsed(hs_ep)) {
dwc2_gadget_incr_frame_num(hs_ep); dwc2_gadget_incr_frame_num(hs_ep);
/* Update current frame number value once more as it
* changes here.
*/
hs->frame_number = dwc2_hsotg_read_frameno(hs);
}
if (hs_ep->target_frame != TARGET_FRAME_INITIAL) if (hs_ep->target_frame != TARGET_FRAME_INITIAL)
dwc2_hsotg_start_req(hs, hs_ep, hs_req, false); dwc2_hsotg_start_req(hs, hs_ep, hs_req, false);
...@@ -2707,6 +2714,8 @@ static void dwc2_gadget_handle_ep_disabled(struct dwc2_hsotg_ep *hs_ep) ...@@ -2707,6 +2714,8 @@ static void dwc2_gadget_handle_ep_disabled(struct dwc2_hsotg_ep *hs_ep)
dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req,
-ENODATA); -ENODATA);
dwc2_gadget_incr_frame_num(hs_ep); dwc2_gadget_incr_frame_num(hs_ep);
/* Update current frame number value. */
hsotg->frame_number = dwc2_hsotg_read_frameno(hsotg);
} while (dwc2_gadget_target_frame_elapsed(hs_ep)); } while (dwc2_gadget_target_frame_elapsed(hs_ep));
dwc2_gadget_start_next_request(hs_ep); dwc2_gadget_start_next_request(hs_ep);
......
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