diff options
author | Changming Huang <jerry.huang@nxp.com> | 2017-01-19 06:56:26 (GMT) |
---|---|---|
committer | Xie Xiaobo <xiaobo.xie@nxp.com> | 2017-09-25 07:25:26 (GMT) |
commit | 4e01addf7075dfd7d87468d1b99bfa73f4e6c6f2 (patch) | |
tree | dd18d6aa3995853d3d529daa55429ddc761b2e55 | |
parent | c4e77700de7289a77b61fb2365e3267e35c6dda9 (diff) | |
download | linux-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.c | 192 | ||||
-rw-r--r-- | drivers/usb/dwc3/core.h | 8 |
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; }; /* -------------------------------------------------------------------------- */ |