usb: xhci: add quirks flag to support MediaTek xHCI 0.96

There some vendor quirks for MTK xHCI 0.96 host controller:
1. It defines some extra SW scheduling parameters for HW
   to minimize the scheduling effort for synchronous and
   interrupt endpoints. The parameters are put into reserved
   DWs of slot context and endpoint context.
2. Its TDS in  Normal TRB defines a number of packets that
   remains to be transferred for a TD after processing all
   Max packets in all previous TRBs.

Tested-by: Frank Wunderlich <frank-w@public-files.de>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index 8ff7185..f3f181d 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -258,6 +258,7 @@
 	if (ret)
 		goto ssusb_init_err;
 
+	mtk->ctrl.quirks = XHCI_MTK_HOST;
 	hcor = (struct xhci_hcor *)((uintptr_t)mtk->hcd +
 			HC_LENGTH(xhci_readl(&mtk->hcd->cr_capbase)));
 
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 603e0e5..3f915ae 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -332,7 +332,8 @@
 {
 	u32 total_packet_count;
 
-	if (ctrl->hci_version < 0x100)
+	/* MTK xHCI 0.96 contains some features from 1.0 */
+	if (ctrl->hci_version < 0x100 && !(ctrl->quirks & XHCI_MTK_HOST))
 		return ((td_total_len - transferred) >> 10);
 
 	/* One TRB with a zero-length data packet. */
@@ -340,6 +341,10 @@
 	    trb_buff_len == td_total_len)
 		return 0;
 
+	/* for MTK xHCI 0.96, TD size include this TRB, but not in 1.x */
+	if ((ctrl->quirks & XHCI_MTK_HOST) && (ctrl->hci_version < 0x100))
+		trb_buff_len = 0;
+
 	total_packet_count = DIV_ROUND_UP(td_total_len, maxp);
 
 	/* Queueing functions don't count the current TRB into transferred */
@@ -823,7 +828,7 @@
 		field |= 0x1;
 
 	/* xHCI 1.0 6.4.1.2.1: Transfer Type field */
-	if (ctrl->hci_version >= 0x100) {
+	if (ctrl->hci_version >= 0x100 || ctrl->quirks & XHCI_MTK_HOST) {
 		if (length > 0) {
 			if (req->requesttype & USB_DIR_IN)
 				field |= (TRB_DATA_IN << TRB_TX_TYPE_SHIFT);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 4be1411..51edeb2 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -650,7 +650,7 @@
 		 * are put into reserved DWs in Slot and Endpoint Contexts
 		 * for synchronous endpoints.
 		 */
-		if (IS_ENABLED(CONFIG_USB_XHCI_MTK)) {
+		if (ctrl->quirks & XHCI_MTK_HOST) {
 			ep_ctx[ep_index]->reserved[0] =
 				cpu_to_le32(EP_BPKTS(1) | EP_BBM(1));
 		}
diff --git a/include/usb/xhci.h b/include/usb/xhci.h
index 15926eb..3de46cd 100644
--- a/include/usb/xhci.h
+++ b/include/usb/xhci.h
@@ -1230,6 +1230,8 @@
 	struct xhci_virt_device *devs[MAX_HC_SLOTS];
 	int rootdev;
 	u16 hci_version;
+	u32 quirks;
+#define XHCI_MTK_HOST		BIT(0)
 };
 
 unsigned long trb_addr(struct xhci_segment *seg, union xhci_trb *trb);