summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChangming Huang <jerry.huang@nxp.com>2017-01-19 06:56:26 (GMT)
committerXie Xiaobo <xiaobo.xie@nxp.com>2017-09-25 07:25:26 (GMT)
commit4e01addf7075dfd7d87468d1b99bfa73f4e6c6f2 (patch)
treedd18d6aa3995853d3d529daa55429ddc761b2e55
parentc4e77700de7289a77b61fb2365e3267e35c6dda9 (diff)
downloadlinux-4e01addf7075dfd7d87468d1b99bfa73f4e6c6f2.tar.xz
USB3/DWC3: Enable the USB snooping
Add support for USB3 snooping by asserting bits in register DWC3_GSBUSCFG0 for data and descriptor. Signed-off-by: Changming Huang <jerry.huang@nxp.com> Signed-off-by: Rajesh Bhagat <rajesh.bhagat@nxp.com> Signed-off-by: yinbo.zhu <yinbo.zhu@nxp.com>
-rw-r--r--drivers/usb/dwc3/core.c192
-rw-r--r--drivers/usb/dwc3/core.h8
2 files changed, 199 insertions, 1 deletions
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 0672672..ab12822 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -586,6 +586,99 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
return 0;
}
+/* set global soc bus configuration registers */
+static void dwc3_set_soc_bus_cfg(struct dwc3 *dwc)
+{
+ struct device *dev = dwc->dev;
+ u32 *vals;
+ u32 cfg;
+ int ntype;
+ int ret;
+ int i;
+
+ cfg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0);
+
+ /*
+ * Handle property "snps,incr-burst-type-adjustment".
+ * Get the number of value from this property:
+ * result <= 0, means this property is not supported.
+ * result = 1, means INCRx burst mode supported.
+ * result > 1, means undefined length burst mode supported.
+ */
+ ntype = device_property_read_u32_array(dev,
+ "snps,incr-burst-type-adjustment", NULL, 0);
+ if (ntype > 0) {
+ vals = kcalloc(ntype, sizeof(u32), GFP_KERNEL);
+ if (!vals) {
+ dev_err(dev, "Error to get memory\n");
+ return;
+ }
+ /* Get INCR burst type, and parse it */
+ ret = device_property_read_u32_array(dev,
+ "snps,incr-burst-type-adjustment", vals, ntype);
+ if (ret) {
+ dev_err(dev, "Error to get property\n");
+ return;
+ }
+ *(dwc->incrx_type + 1) = vals[0];
+ if (ntype > 1) {
+ *dwc->incrx_type = 1;
+ for (i = 1; i < ntype; i++) {
+ if (vals[i] > *(dwc->incrx_type + 1))
+ *(dwc->incrx_type + 1) = vals[i];
+ }
+ } else
+ *dwc->incrx_type = 0;
+
+ /* Enable Undefined Length INCR Burst and Enable INCRx Burst */
+ cfg &= ~DWC3_GSBUSCFG0_INCRBRST_MASK;
+ if (*dwc->incrx_type)
+ cfg |= DWC3_GSBUSCFG0_INCRBRSTENA;
+ switch (*(dwc->incrx_type + 1)) {
+ case 256:
+ cfg |= DWC3_GSBUSCFG0_INCR256BRSTENA;
+ break;
+ case 128:
+ cfg |= DWC3_GSBUSCFG0_INCR128BRSTENA;
+ break;
+ case 64:
+ cfg |= DWC3_GSBUSCFG0_INCR64BRSTENA;
+ break;
+ case 32:
+ cfg |= DWC3_GSBUSCFG0_INCR32BRSTENA;
+ break;
+ case 16:
+ cfg |= DWC3_GSBUSCFG0_INCR16BRSTENA;
+ break;
+ case 8:
+ cfg |= DWC3_GSBUSCFG0_INCR8BRSTENA;
+ break;
+ case 4:
+ cfg |= DWC3_GSBUSCFG0_INCR4BRSTENA;
+ break;
+ case 1:
+ break;
+ default:
+ dev_err(dev, "Invalid property\n");
+ break;
+ }
+ }
+
+ /* Handle usb snooping */
+ if (dwc->dma_snooping_quirk) {
+ cfg &= ~DWC3_GSBUSCFG0_SNP_MASK;
+ cfg |= (AXI3_CACHE_TYPE_SNP << DWC3_GSBUSCFG0_DATARD_SHIFT) |
+ (AXI3_CACHE_TYPE_SNP << DWC3_GSBUSCFG0_DESCRD_SHIFT) |
+ (AXI3_CACHE_TYPE_SNP << DWC3_GSBUSCFG0_DATAWR_SHIFT) |
+ (AXI3_CACHE_TYPE_SNP << DWC3_GSBUSCFG0_DESCWR_SHIFT);
+ }
+
+ dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, cfg);
+
+}
+
+
+
static void dwc3_core_exit(struct dwc3 *dwc)
{
dwc3_event_buffers_cleanup(dwc);
@@ -928,6 +1021,103 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)
}
}
+static void dwc3_get_properties(struct dwc3 *dwc)
+{
+ struct device *dev = dwc->dev;
+ struct device_node *node = dev->of_node;
+ u8 lpm_nyet_threshold;
+ u8 tx_de_emphasis;
+ u8 hird_threshold;
+
+ /* default to highest possible threshold */
+ lpm_nyet_threshold = 0xff;
+
+ /* default to -3.5dB de-emphasis */
+ tx_de_emphasis = 1;
+
+ /*
+ * default to assert utmi_sleep_n and use maximum allowed HIRD
+ * threshold value of 0b1100
+ */
+ hird_threshold = 12;
+
+ dwc->maximum_speed = usb_get_maximum_speed(dev);
+ dwc->dr_mode = usb_get_dr_mode(dev);
+ dwc->hsphy_mode = of_usb_get_phy_mode(dev->of_node);
+
+ dwc->sysdev_is_parent = device_property_read_bool(dev,
+ "linux,sysdev_is_parent");
+ if (dwc->sysdev_is_parent)
+ dwc->sysdev = dwc->dev->parent;
+ else
+ dwc->sysdev = dwc->dev;
+
+ dwc->has_lpm_erratum = device_property_read_bool(dev,
+ "snps,has-lpm-erratum");
+ device_property_read_u8(dev, "snps,lpm-nyet-threshold",
+ &lpm_nyet_threshold);
+ dwc->is_utmi_l1_suspend = device_property_read_bool(dev,
+ "snps,is-utmi-l1-suspend");
+ device_property_read_u8(dev, "snps,hird-threshold",
+ &hird_threshold);
+ dwc->usb3_lpm_capable = device_property_read_bool(dev,
+ "snps,usb3_lpm_capable");
+
+ dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
+
+ dwc->configure_gfladj =
+ of_property_read_bool(node, "configure-gfladj");
+ dwc->dr_mode = usb_get_dr_mode(dev);
+
+ dwc->disable_scramble_quirk = device_property_read_bool(dev,
+ "snps,disable_scramble_quirk");
+ dwc->u2exit_lfps_quirk = device_property_read_bool(dev,
+ "snps,u2exit_lfps_quirk");
+ dwc->u2ss_inp3_quirk = device_property_read_bool(dev,
+ "snps,u2ss_inp3_quirk");
+ dwc->req_p1p2p3_quirk = device_property_read_bool(dev,
+ "snps,req_p1p2p3_quirk");
+ dwc->del_p1p2p3_quirk = device_property_read_bool(dev,
+ "snps,del_p1p2p3_quirk");
+ dwc->del_phy_power_chg_quirk = device_property_read_bool(dev,
+ "snps,del_phy_power_chg_quirk");
+ dwc->lfps_filter_quirk = device_property_read_bool(dev,
+ "snps,lfps_filter_quirk");
+ dwc->rx_detect_poll_quirk = device_property_read_bool(dev,
+ "snps,rx_detect_poll_quirk");
+ dwc->dis_u3_susphy_quirk = device_property_read_bool(dev,
+ "snps,dis_u3_susphy_quirk");
+ dwc->dis_u2_susphy_quirk = device_property_read_bool(dev,
+ "snps,dis_u2_susphy_quirk");
+ dwc->dis_enblslpm_quirk = device_property_read_bool(dev,
+ "snps,dis_enblslpm_quirk");
+ dwc->dis_rxdet_inp3_quirk = device_property_read_bool(dev,
+ "snps,dis_rxdet_inp3_quirk");
+ dwc->dis_u2_freeclk_exists_quirk = device_property_read_bool(dev,
+ "snps,dis-u2-freeclk-exists-quirk");
+ dwc->dis_del_phy_power_chg_quirk = device_property_read_bool(dev,
+ "snps,dis-del-phy-power-chg-quirk");
+ dwc->dma_snooping_quirk = device_property_read_bool(dev,
+ "snps,dma-snooping");
+
+ dwc->tx_de_emphasis_quirk = device_property_read_bool(dev,
+ "snps,tx_de_emphasis_quirk");
+ device_property_read_u8(dev, "snps,tx_de_emphasis",
+ &tx_de_emphasis);
+ device_property_read_string(dev, "snps,hsphy_interface",
+ &dwc->hsphy_interface);
+ device_property_read_u32(dev, "snps,quirk-frame-length-adjustment",
+ &dwc->fladj);
+
+ dwc->lpm_nyet_threshold = lpm_nyet_threshold;
+ dwc->tx_de_emphasis = tx_de_emphasis;
+
+ dwc->hird_threshold = hird_threshold
+ | (dwc->is_utmi_l1_suspend << 4);
+
+ dwc->imod_interval = 0;
+}
+
#define DWC3_ALIGN_MASK (16 - 1)
static int dwc3_probe(struct platform_device *pdev)
@@ -1050,6 +1240,8 @@ static int dwc3_probe(struct platform_device *pdev)
dwc->hird_threshold = hird_threshold
| (dwc->is_utmi_l1_suspend << 4);
+ dwc3_get_properties(dwc);
+
platform_set_drvdata(pdev, dwc);
dwc3_cache_hwparams(dwc);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 910f068..b835b69 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -206,7 +206,6 @@
#define DWC3_GCTL_CLK_PIPE (1)
#define DWC3_GCTL_CLK_PIPEHALF (2)
#define DWC3_GCTL_CLK_MASK (3)
-
#define DWC3_GCTL_PRTCAP(n) (((n) & (3 << 12)) >> 12)
#define DWC3_GCTL_PRTCAPDIR(n) ((n) << 12)
#define DWC3_GCTL_PRTCAP_HOST 1
@@ -874,6 +873,7 @@ struct dwc3 {
spinlock_t lock;
struct device *dev;
+ struct device *sysdev;
struct platform_device *xhci;
struct resource xhci_resources[DWC3_XHCI_RESOURCES_NUM];
@@ -981,9 +981,12 @@ struct dwc3 {
unsigned ep0_bounced:1;
unsigned ep0_expect_in:1;
unsigned has_hibernation:1;
+ unsigned sysdev_is_parent:1;
unsigned has_lpm_erratum:1;
unsigned is_utmi_l1_suspend:1;
unsigned is_fpga:1;
+ unsigned needs_fifo_resize:1;
+ unsigned configure_gfladj:1;
unsigned pending_events:1;
unsigned pullups_connected:1;
unsigned setup_packet_pending:1;
@@ -1004,9 +1007,12 @@ struct dwc3 {
unsigned dis_rxdet_inp3_quirk:1;
unsigned dis_u2_freeclk_exists_quirk:1;
unsigned dis_del_phy_power_chg_quirk:1;
+ unsigned dma_snooping_quirk:1;
unsigned tx_de_emphasis_quirk:1;
unsigned tx_de_emphasis:2;
+
+ u16 imod_interval;
};
/* -------------------------------------------------------------------------- */