12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790 |
- From 1d35e363dd6e8bb1733bca0dfc186e3f70e692fe Mon Sep 17 00:00:00 2001
- From: Yangbo Lu <[email protected]>
- Date: Thu, 5 Jul 2018 17:38:52 +0800
- Subject: [PATCH 29/32] usb: support layerscape
- This is an integrated patch for layerscape usb support.
- Signed-off-by: yinbo.zhu <[email protected]>
- Signed-off-by: Ramneek Mehresh <[email protected]>
- Signed-off-by: Nikhil Badola <[email protected]>
- Signed-off-by: Changming Huang <[email protected]>
- Signed-off-by: Catalin Marinas <[email protected]>
- Signed-off-by: Rajesh Bhagat <[email protected]>
- Signed-off-by: Suresh Gupta <[email protected]>
- Signed-off-by: Zhao Chenhui <[email protected]>
- Signed-off-by: Yangbo Lu <[email protected]>
- ---
- drivers/net/usb/cdc_ether.c | 8 +
- drivers/net/usb/r8152.c | 6 +
- drivers/usb/common/common.c | 50 +++++
- drivers/usb/core/hub.c | 8 +
- drivers/usb/dwc3/core.c | 243 +++++++++++++++++++++-
- drivers/usb/dwc3/core.h | 51 ++++-
- drivers/usb/dwc3/ep0.c | 4 +-
- drivers/usb/dwc3/gadget.c | 7 +
- drivers/usb/dwc3/host.c | 24 ++-
- drivers/usb/gadget/udc/fsl_udc_core.c | 46 +++--
- drivers/usb/gadget/udc/fsl_usb2_udc.h | 16 +-
- drivers/usb/host/Kconfig | 4 +-
- drivers/usb/host/ehci-fsl.c | 279 ++++++++++++++++++++++++--
- drivers/usb/host/ehci-fsl.h | 3 +
- drivers/usb/host/ehci-hub.c | 4 +
- drivers/usb/host/ehci.h | 9 +
- drivers/usb/host/fsl-mph-dr-of.c | 16 +-
- drivers/usb/host/xhci-hub.c | 22 ++
- drivers/usb/host/xhci-plat.c | 16 +-
- drivers/usb/host/xhci-ring.c | 29 ++-
- drivers/usb/host/xhci.c | 38 +++-
- drivers/usb/host/xhci.h | 6 +-
- drivers/usb/phy/phy-fsl-usb.c | 59 ++++--
- drivers/usb/phy/phy-fsl-usb.h | 8 +
- include/linux/usb.h | 1 +
- include/linux/usb/of.h | 2 +
- 26 files changed, 867 insertions(+), 92 deletions(-)
- --- a/drivers/net/usb/cdc_ether.c
- +++ b/drivers/net/usb/cdc_ether.c
- @@ -533,6 +533,7 @@ static const struct driver_info wwan_inf
- #define LINKSYS_VENDOR_ID 0x13b1
- #define NVIDIA_VENDOR_ID 0x0955
- #define HP_VENDOR_ID 0x03f0
- +#define TPLINK_VENDOR_ID 0x2357
-
- static const struct usb_device_id products[] = {
- /* BLACKLIST !!
- @@ -742,6 +743,13 @@ static const struct usb_device_id produc
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
- .driver_info = 0,
- },
- +
- + /* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
- +{
- + USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM,
- + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
- + .driver_info = 0,
- +},
-
- /* WHITELIST!!!
- *
- --- a/drivers/net/usb/r8152.c
- +++ b/drivers/net/usb/r8152.c
- @@ -521,6 +521,7 @@ enum rtl8152_flags {
- #define VENDOR_ID_LENOVO 0x17ef
- #define VENDOR_ID_LINKSYS 0x13b1
- #define VENDOR_ID_NVIDIA 0x0955
- +#define VENDOR_ID_TPLINK 0x2357
-
- #define MCU_TYPE_PLA 0x0100
- #define MCU_TYPE_USB 0x0000
- @@ -1817,6 +1818,10 @@ static int rx_bottom(struct r8152 *tp, i
- unsigned int pkt_len;
- struct sk_buff *skb;
-
- + /* limite the skb numbers for rx_queue */
- + if (unlikely(skb_queue_len(&tp->rx_queue) >= 1000))
- + break;
- +
- pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
- if (pkt_len < ETH_ZLEN)
- break;
- @@ -4510,6 +4515,7 @@ static struct usb_device_id rtl8152_tabl
- {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f)},
- {REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041)},
- {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff)},
- + {REALTEK_USB_DEVICE(VENDOR_ID_TPLINK, 0x0601)},
- {}
- };
-
- --- a/drivers/usb/common/common.c
- +++ b/drivers/usb/common/common.c
- @@ -105,6 +105,56 @@ static const char *const usb_dr_modes[]
- [USB_DR_MODE_OTG] = "otg",
- };
-
- +/**
- + * of_usb_get_dr_mode - Get dual role mode for given device_node
- + * @np: Pointer to the given device_node
- + *
- + * The function gets phy interface string from property 'dr_mode',
- + * and returns the correspondig enum usb_dr_mode
- + */
- +enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np)
- +{
- + const char *dr_mode;
- + int err, i;
- +
- + err = of_property_read_string(np, "dr_mode", &dr_mode);
- + if (err < 0)
- + return USB_DR_MODE_UNKNOWN;
- +
- + for (i = 0; i < ARRAY_SIZE(usb_dr_modes); i++)
- + if (!strcmp(dr_mode, usb_dr_modes[i]))
- + return i;
- +
- + return USB_DR_MODE_UNKNOWN;
- +}
- +EXPORT_SYMBOL_GPL(of_usb_get_dr_mode);
- +
- +/**
- + * of_usb_get_maximum_speed - Get maximum requested speed for a given USB
- + * controller.
- + * @np: Pointer to the given device_node
- + *
- + * The function gets the maximum speed string from property "maximum-speed",
- + * and returns the corresponding enum usb_device_speed.
- + */
- +enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np)
- +{
- + const char *maximum_speed;
- + int err;
- + int i;
- +
- + err = of_property_read_string(np, "maximum-speed", &maximum_speed);
- + if (err < 0)
- + return USB_SPEED_UNKNOWN;
- +
- + for (i = 0; i < ARRAY_SIZE(speed_names); i++)
- + if (strcmp(maximum_speed, speed_names[i]) == 0)
- + return i;
- +
- + return USB_SPEED_UNKNOWN;
- +}
- +EXPORT_SYMBOL_GPL(of_usb_get_maximum_speed);
- +
- static enum usb_dr_mode usb_get_dr_mode_from_string(const char *str)
- {
- int ret;
- --- a/drivers/usb/core/hub.c
- +++ b/drivers/usb/core/hub.c
- @@ -4431,6 +4431,14 @@ hub_port_init(struct usb_hub *hub, struc
- else
- speed = usb_speed_string(udev->speed);
-
- +#if !defined(CONFIG_FSL_USB2_OTG) && !defined(CONFIG_FSL_USB2_OTG_MODULE)
- +if (udev->speed != USB_SPEED_SUPER)
- + dev_info(&udev->dev,
- + "%s %s USB device number %d using %s\n",
- + (udev->config) ? "reset" : "new", speed,
- + devnum, udev->bus->controller->driver->name);
- +#endif
- +
- if (udev->speed < USB_SPEED_SUPER)
- dev_info(&udev->dev,
- "%s %s USB device number %d using %s\n",
- --- a/drivers/usb/dwc3/core.c
- +++ b/drivers/usb/dwc3/core.c
- @@ -58,6 +58,7 @@ static int dwc3_get_dr_mode(struct dwc3
- enum usb_dr_mode mode;
- struct device *dev = dwc->dev;
- unsigned int hw_mode;
- + struct device_node *node = dev->of_node;
-
- if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
- dwc->dr_mode = USB_DR_MODE_OTG;
- @@ -83,6 +84,24 @@ static int dwc3_get_dr_mode(struct dwc3
- mode = USB_DR_MODE_HOST;
- break;
- default:
- + /* Adjust Frame Length */
- + if (dwc->configure_gfladj)
- + dwc3_writel(dwc->regs, DWC3_GFLADJ, GFLADJ_30MHZ_REG_SEL |
- + GFLADJ_30MHZ(GFLADJ_30MHZ_DEFAULT));
- +
- + /* Change burst beat and outstanding pipelined transfers requests */
- + dwc3_writel(dwc->regs, DWC3_GSBUSCFG0,
- + (dwc3_readl(dwc->regs, DWC3_GSBUSCFG0) & ~0xff) | 0xf);
- + dwc3_writel(dwc->regs, DWC3_GSBUSCFG1,
- + dwc3_readl(dwc->regs, DWC3_GSBUSCFG1) | 0xf00);
- +
- + /* Enable Snooping */
- + if (node && of_dma_is_coherent(node)) {
- + dwc3_writel(dwc->regs, DWC3_GSBUSCFG0,
- + dwc3_readl(dwc->regs, DWC3_GSBUSCFG0) | 0x22220000);
- + dev_dbg(dev, "enabled snooping for usb\n");
- + }
- +
- if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
- mode = USB_DR_MODE_HOST;
- else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
- @@ -227,8 +246,9 @@ static void dwc3_frame_length_adjustment
-
- reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
- dft = reg & DWC3_GFLADJ_30MHZ_MASK;
- - if (!dev_WARN_ONCE(dwc->dev, dft == dwc->fladj,
- - "request value same as default, ignoring\n")) {
- + if (dft == dwc->fladj) {
- + dev_warn(dwc->dev, "request value same as default, ignoring\n");
- + } else {
- reg &= ~DWC3_GFLADJ_30MHZ_MASK;
- reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj;
- dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
- @@ -599,6 +619,99 @@ static int dwc3_phy_setup(struct dwc3 *d
- 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);
- @@ -741,6 +854,8 @@ static int dwc3_core_init(struct dwc3 *d
- if (ret)
- goto err1;
-
- + dwc3_set_soc_bus_cfg(dwc);
- +
- /* Adjust Frame Length */
- dwc3_frame_length_adjustment(dwc);
-
- @@ -939,11 +1054,117 @@ static void dwc3_core_exit_mode(struct d
- }
- }
-
- +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->quirk_reverse_in_out = device_property_read_bool(dev,
- + "snps,quirk_reverse_in_out");
- + dwc->quirk_stop_transfer_in_block = device_property_read_bool(dev,
- + "snps,quirk_stop_transfer_in_block");
- + dwc->quirk_stop_ep_in_u1 = device_property_read_bool(dev,
- + "snps,quirk_stop_ep_in_u1");
- +
- + 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");
- + dwc->disable_devinit_u1u2_quirk = device_property_read_bool(dev,
- + "snps,disable_devinit_u1u2");
- + 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)
- {
- struct device *dev = &pdev->dev;
- + struct device_node *node = dev->of_node;
- struct resource *res;
- struct dwc3 *dwc;
- u8 lpm_nyet_threshold;
- @@ -975,6 +1196,11 @@ static int dwc3_probe(struct platform_de
- dwc->xhci_resources[0].flags = res->flags;
- dwc->xhci_resources[0].name = res->name;
-
- + if (node) {
- + dwc->configure_gfladj =
- + of_property_read_bool(node, "configure-gfladj");
- + }
- +
- res->start += DWC3_GLOBALS_REGS_START;
-
- /*
- @@ -1017,6 +1243,12 @@ static int dwc3_probe(struct platform_de
- 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 = of_usb_get_dr_mode(node);
- +
- dwc->disable_scramble_quirk = device_property_read_bool(dev,
- "snps,disable_scramble_quirk");
- dwc->u2exit_lfps_quirk = device_property_read_bool(dev,
- @@ -1061,6 +1293,8 @@ static int dwc3_probe(struct platform_de
- dwc->hird_threshold = hird_threshold
- | (dwc->is_utmi_l1_suspend << 4);
-
- + dwc3_get_properties(dwc);
- +
- platform_set_drvdata(pdev, dwc);
- dwc3_cache_hwparams(dwc);
-
- @@ -1084,6 +1318,11 @@ static int dwc3_probe(struct platform_de
- if (ret < 0)
- goto err1;
-
- + /* Adjust Frame Length */
- + if (dwc->configure_gfladj)
- + dwc3_writel(dwc->regs, DWC3_GFLADJ, GFLADJ_30MHZ_REG_SEL |
- + GFLADJ_30MHZ(GFLADJ_30MHZ_DEFAULT));
- +
- pm_runtime_forbid(dev);
-
- ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
- --- a/drivers/usb/dwc3/core.h
- +++ b/drivers/usb/dwc3/core.h
- @@ -26,6 +26,7 @@
- #include <linux/dma-mapping.h>
- #include <linux/mm.h>
- #include <linux/debugfs.h>
- +#include <linux/of_address.h>
-
- #include <linux/usb/ch9.h>
- #include <linux/usb/gadget.h>
- @@ -154,6 +155,32 @@
-
- /* Bit fields */
-
- +/* Global SoC Bus Configuration Register 0 */
- +#define AXI3_CACHE_TYPE_AW 0x8 /* write allocate */
- +#define AXI3_CACHE_TYPE_AR 0x4 /* read allocate */
- +#define AXI3_CACHE_TYPE_SNP 0x2 /* cacheable */
- +#define AXI3_CACHE_TYPE_BUF 0x1 /* bufferable */
- +#define DWC3_GSBUSCFG0_DATARD_SHIFT 28
- +#define DWC3_GSBUSCFG0_DESCRD_SHIFT 24
- +#define DWC3_GSBUSCFG0_DATAWR_SHIFT 20
- +#define DWC3_GSBUSCFG0_DESCWR_SHIFT 16
- +#define DWC3_GSBUSCFG0_SNP_MASK 0xffff0000
- +#define DWC3_GSBUSCFG0_DATABIGEND (1 << 11)
- +#define DWC3_GSBUSCFG0_DESCBIGEND (1 << 10)
- +#define DWC3_GSBUSCFG0_INCR256BRSTENA (1 << 7) /* INCR256 burst */
- +#define DWC3_GSBUSCFG0_INCR128BRSTENA (1 << 6) /* INCR128 burst */
- +#define DWC3_GSBUSCFG0_INCR64BRSTENA (1 << 5) /* INCR64 burst */
- +#define DWC3_GSBUSCFG0_INCR32BRSTENA (1 << 4) /* INCR32 burst */
- +#define DWC3_GSBUSCFG0_INCR16BRSTENA (1 << 3) /* INCR16 burst */
- +#define DWC3_GSBUSCFG0_INCR8BRSTENA (1 << 2) /* INCR8 burst */
- +#define DWC3_GSBUSCFG0_INCR4BRSTENA (1 << 1) /* INCR4 burst */
- +#define DWC3_GSBUSCFG0_INCRBRSTENA (1 << 0) /* undefined length enable */
- +#define DWC3_GSBUSCFG0_INCRBRST_MASK 0xff
- +
- +/* Global SoC Bus Configuration Register 1 */
- +#define DWC3_GSBUSCFG1_1KPAGEENA (1 << 12) /* 1K page boundary enable */
- +#define DWC3_GSBUSCFG1_PTRANSLIMIT_MASK 0xf00
- +
- /* Global Debug Queue/FIFO Space Available Register */
- #define DWC3_GDBGFIFOSPACE_NUM(n) ((n) & 0x1f)
- #define DWC3_GDBGFIFOSPACE_TYPE(n) (((n) << 5) & 0x1e0)
- @@ -182,7 +209,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
- @@ -294,6 +320,10 @@
- /* Global Frame Length Adjustment Register */
- #define DWC3_GFLADJ_30MHZ_SDBND_SEL (1 << 7)
- #define DWC3_GFLADJ_30MHZ_MASK 0x3f
- +#define GFLADJ_30MHZ_REG_SEL (1 << 7)
- +#define GFLADJ_30MHZ(n) ((n) & 0x3f)
- +#define GFLADJ_30MHZ_DEFAULT 0x20
- +
-
- /* Global User Control Register 2 */
- #define DWC3_GUCTL2_RST_ACTBITLATER (1 << 14)
- @@ -758,6 +788,7 @@ struct dwc3_scratchpad_array {
- * @regs: base address for our registers
- * @regs_size: address space size
- * @fladj: frame length adjustment
- + * @incrx_type: INCR burst type adjustment
- * @irq_gadget: peripheral controller's IRQ number
- * @nr_scratch: number of scratch buffers
- * @u1u2: only used on revisions <1.83a for workaround
- @@ -834,6 +865,7 @@ struct dwc3_scratchpad_array {
- * 1 - -3.5dB de-emphasis
- * 2 - No de-emphasis
- * 3 - Reserved
- + * @disable_devinit_u1u2_quirk: disable device-initiated U1/U2 request.
- */
- struct dwc3 {
- struct usb_ctrlrequest *ctrl_req;
- @@ -852,6 +884,7 @@ struct dwc3 {
- spinlock_t lock;
-
- struct device *dev;
- + struct device *sysdev;
-
- struct platform_device *xhci;
- struct resource xhci_resources[DWC3_XHCI_RESOURCES_NUM];
- @@ -877,6 +910,12 @@ struct dwc3 {
- enum usb_phy_interface hsphy_mode;
-
- u32 fladj;
- + /*
- + * For INCR burst type.
- + * First field: for undefined length INCR burst type enable.
- + * Second field: for INCRx burst type enable
- + */
- + u32 incrx_type[2];
- u32 irq_gadget;
- u32 nr_scratch;
- u32 u1u2;
- @@ -953,9 +992,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;
- @@ -976,9 +1018,16 @@ 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;
- + unsigned disable_devinit_u1u2_quirk:1;
- + unsigned quirk_reverse_in_out:1;
- + unsigned quirk_stop_transfer_in_block:1;
- + unsigned quirk_stop_ep_in_u1:1;
- +
- + u16 imod_interval;
- };
-
- /* -------------------------------------------------------------------------- */
- --- a/drivers/usb/dwc3/ep0.c
- +++ b/drivers/usb/dwc3/ep0.c
- @@ -360,9 +360,9 @@ static int dwc3_ep0_handle_status(struct
- if ((dwc->speed == DWC3_DSTS_SUPERSPEED) ||
- (dwc->speed == DWC3_DSTS_SUPERSPEED_PLUS)) {
- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
- - if (reg & DWC3_DCTL_INITU1ENA)
- + if ((reg & DWC3_DCTL_INITU1ENA) && !dwc->disable_devinit_u1u2_quirk)
- usb_status |= 1 << USB_DEV_STAT_U1_ENABLED;
- - if (reg & DWC3_DCTL_INITU2ENA)
- + if ((reg & DWC3_DCTL_INITU2ENA) && !dwc->disable_devinit_u1u2_quirk)
- usb_status |= 1 << USB_DEV_STAT_U2_ENABLED;
- }
-
- --- a/drivers/usb/dwc3/gadget.c
- +++ b/drivers/usb/dwc3/gadget.c
- @@ -2932,6 +2932,7 @@ static irqreturn_t dwc3_interrupt(int ir
- int dwc3_gadget_init(struct dwc3 *dwc)
- {
- int ret, irq;
- + u32 reg;
- struct platform_device *dwc3_pdev = to_platform_device(dwc->dev);
-
- irq = platform_get_irq_byname(dwc3_pdev, "peripheral");
- @@ -3046,6 +3047,12 @@ int dwc3_gadget_init(struct dwc3 *dwc)
- goto err5;
- }
-
- + if (dwc->disable_devinit_u1u2_quirk) {
- + reg = dwc3_readl(dwc->regs, DWC3_DCTL);
- + reg &= ~(DWC3_DCTL_INITU1ENA | DWC3_DCTL_INITU2ENA);
- + dwc3_writel(dwc->regs, DWC3_DCTL, reg);
- + }
- +
- return 0;
-
- err5:
- --- a/drivers/usb/dwc3/host.c
- +++ b/drivers/usb/dwc3/host.c
- @@ -17,6 +17,8 @@
-
- #include <linux/platform_device.h>
-
- +#include <linux/of_device.h>
- +
- #include "core.h"
-
- int dwc3_host_init(struct dwc3 *dwc)
- @@ -73,12 +75,21 @@ int dwc3_host_init(struct dwc3 *dwc)
- return -ENOMEM;
- }
-
- - dma_set_coherent_mask(&xhci->dev, dwc->dev->coherent_dma_mask);
- + if (IS_ENABLED(CONFIG_OF) && dwc->dev->of_node)
- + of_dma_configure(&xhci->dev, dwc->dev->of_node);
- + else
- + dma_set_coherent_mask(&xhci->dev, dwc->dev->coherent_dma_mask);
-
- - xhci->dev.parent = dwc->dev;
- + xhci->dev.parent = dwc->dev;
- xhci->dev.dma_mask = dwc->dev->dma_mask;
- xhci->dev.dma_parms = dwc->dev->dma_parms;
-
- + /* set DMA operations */
- + if (dwc->dev->of_node && of_dma_is_coherent(dwc->dev->of_node)) {
- + xhci->dev.archdata.dma_ops = dwc->dev->archdata.dma_ops;
- + dev_dbg(dwc->dev, "set dma_ops for usb\n");
- + }
- +
- dwc->xhci = xhci;
-
- ret = platform_device_add_resources(xhci, dwc->xhci_resources,
- @@ -90,6 +101,15 @@ int dwc3_host_init(struct dwc3 *dwc)
-
- memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props));
-
- + if (dwc->quirk_reverse_in_out)
- + props[prop_idx++].name = "quirk-reverse-in-out";
- +
- + if (dwc->quirk_stop_transfer_in_block)
- + props[prop_idx++].name = "quirk-stop-transfer-in-block";
- +
- + if (dwc->quirk_stop_ep_in_u1)
- + props[prop_idx++].name = "quirk-stop-ep-in-u1";
- +
- if (dwc->usb3_lpm_capable)
- props[prop_idx++].name = "usb3-lpm-capable";
-
- --- a/drivers/usb/gadget/udc/fsl_udc_core.c
- +++ b/drivers/usb/gadget/udc/fsl_udc_core.c
- @@ -198,7 +198,11 @@ __acquires(ep->udc->lock)
-
- spin_unlock(&ep->udc->lock);
-
- - usb_gadget_giveback_request(&ep->ep, &req->req);
- + /* this complete() should a func implemented by gadget layer,
- + * eg fsg->bulk_in_complete()
- + */
- + if (req->req.complete)
- + usb_gadget_giveback_request(&ep->ep, &req->req);
-
- spin_lock(&ep->udc->lock);
- ep->stopped = stopped;
- @@ -245,10 +249,10 @@ static int dr_controller_setup(struct fs
- if (udc->pdata->have_sysif_regs) {
- if (udc->pdata->controller_ver) {
- /* controller version 1.6 or above */
- - ctrl = __raw_readl(&usb_sys_regs->control);
- + ctrl = ioread32be(&usb_sys_regs->control);
- ctrl &= ~USB_CTRL_UTMI_PHY_EN;
- ctrl |= USB_CTRL_USB_EN;
- - __raw_writel(ctrl, &usb_sys_regs->control);
- + iowrite32be(ctrl, &usb_sys_regs->control);
- }
- }
- portctrl |= PORTSCX_PTS_ULPI;
- @@ -257,13 +261,14 @@ static int dr_controller_setup(struct fs
- portctrl |= PORTSCX_PTW_16BIT;
- /* fall through */
- case FSL_USB2_PHY_UTMI:
- + case FSL_USB2_PHY_UTMI_DUAL:
- if (udc->pdata->have_sysif_regs) {
- if (udc->pdata->controller_ver) {
- /* controller version 1.6 or above */
- - ctrl = __raw_readl(&usb_sys_regs->control);
- + ctrl = ioread32be(&usb_sys_regs->control);
- ctrl |= (USB_CTRL_UTMI_PHY_EN |
- USB_CTRL_USB_EN);
- - __raw_writel(ctrl, &usb_sys_regs->control);
- + iowrite32be(ctrl, &usb_sys_regs->control);
- mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI
- PHY CLK to become stable - 10ms*/
- }
- @@ -329,22 +334,22 @@ static int dr_controller_setup(struct fs
- /* Config control enable i/o output, cpu endian register */
- #ifndef CONFIG_ARCH_MXC
- if (udc->pdata->have_sysif_regs) {
- - ctrl = __raw_readl(&usb_sys_regs->control);
- + ctrl = ioread32be(&usb_sys_regs->control);
- ctrl |= USB_CTRL_IOENB;
- - __raw_writel(ctrl, &usb_sys_regs->control);
- + iowrite32be(ctrl, &usb_sys_regs->control);
- }
- #endif
-
- -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- +#if !defined(CONFIG_NOT_COHERENT_CACHE)
- /* Turn on cache snooping hardware, since some PowerPC platforms
- * wholly rely on hardware to deal with cache coherent. */
-
- if (udc->pdata->have_sysif_regs) {
- /* Setup Snooping for all the 4GB space */
- tmp = SNOOP_SIZE_2GB; /* starts from 0x0, size 2G */
- - __raw_writel(tmp, &usb_sys_regs->snoop1);
- + iowrite32be(tmp, &usb_sys_regs->snoop1);
- tmp |= 0x80000000; /* starts from 0x8000000, size 2G */
- - __raw_writel(tmp, &usb_sys_regs->snoop2);
- + iowrite32be(tmp, &usb_sys_regs->snoop2);
- }
- #endif
-
- @@ -1057,7 +1062,7 @@ static int fsl_ep_fifo_status(struct usb
- struct ep_queue_head *qh;
-
- ep = container_of(_ep, struct fsl_ep, ep);
- - if (!_ep || (!ep->ep.desc && ep_index(ep) != 0))
- + if (!_ep || !ep->ep.desc || (ep_index(ep) == 0))
- return -ENODEV;
-
- udc = (struct fsl_udc *)ep->udc;
- @@ -1599,14 +1604,13 @@ static int process_ep_req(struct fsl_udc
- struct fsl_req *curr_req)
- {
- struct ep_td_struct *curr_td;
- - int td_complete, actual, remaining_length, j, tmp;
- + int actual, remaining_length, j, tmp;
- int status = 0;
- int errors = 0;
- struct ep_queue_head *curr_qh = &udc->ep_qh[pipe];
- int direction = pipe % 2;
-
- curr_td = curr_req->head;
- - td_complete = 0;
- actual = curr_req->req.length;
-
- for (j = 0; j < curr_req->dtd_count; j++) {
- @@ -1651,11 +1655,9 @@ static int process_ep_req(struct fsl_udc
- status = -EPROTO;
- break;
- } else {
- - td_complete++;
- break;
- }
- } else {
- - td_complete++;
- VDBG("dTD transmitted successful");
- }
-
- @@ -1698,7 +1700,7 @@ static void dtd_complete_irq(struct fsl_
- curr_ep = get_ep_by_pipe(udc, i);
-
- /* If the ep is configured */
- - if (!curr_ep->ep.name) {
- + if (strncmp(curr_ep->name, "ep", 2)) {
- WARNING("Invalid EP?");
- continue;
- }
- @@ -2420,10 +2422,12 @@ static int fsl_udc_probe(struct platform
- usb_sys_regs = (void *)dr_regs + USB_DR_SYS_OFFSET;
- #endif
-
- +#ifdef CONFIG_ARCH_MXC
- /* Initialize USB clocks */
- ret = fsl_udc_clk_init(pdev);
- if (ret < 0)
- goto err_iounmap_noclk;
- +#endif
-
- /* Read Device Controller Capability Parameters register */
- dccparams = fsl_readl(&dr_regs->dccparams);
- @@ -2463,9 +2467,11 @@ static int fsl_udc_probe(struct platform
- dr_controller_setup(udc_controller);
- }
-
- +#ifdef CONFIG_ARCH_MXC
- ret = fsl_udc_clk_finalize(pdev);
- if (ret)
- goto err_free_irq;
- +#endif
-
- /* Setup gadget structure */
- udc_controller->gadget.ops = &fsl_gadget_ops;
- @@ -2478,6 +2484,7 @@ static int fsl_udc_probe(struct platform
- /* Setup gadget.dev and register with kernel */
- dev_set_name(&udc_controller->gadget.dev, "gadget");
- udc_controller->gadget.dev.of_node = pdev->dev.of_node;
- + set_dma_ops(&udc_controller->gadget.dev, pdev->dev.archdata.dma_ops);
-
- if (!IS_ERR_OR_NULL(udc_controller->transceiver))
- udc_controller->gadget.is_otg = 1;
- @@ -2529,7 +2536,9 @@ err_free_irq:
- err_iounmap:
- if (pdata->exit)
- pdata->exit(pdev);
- +#ifdef CONFIG_ARCH_MXC
- fsl_udc_clk_release();
- +#endif
- err_iounmap_noclk:
- iounmap(dr_regs);
- err_release_mem_region:
- @@ -2557,8 +2566,9 @@ static int fsl_udc_remove(struct platfor
- udc_controller->done = &done;
- usb_del_gadget_udc(&udc_controller->gadget);
-
- +#ifdef CONFIG_ARCH_MXC
- fsl_udc_clk_release();
- -
- +#endif
- /* DR has been stopped in usb_gadget_unregister_driver() */
- remove_proc_file();
-
- @@ -2570,7 +2580,7 @@ static int fsl_udc_remove(struct platfor
- dma_pool_destroy(udc_controller->td_pool);
- free_irq(udc_controller->irq, udc_controller);
- iounmap(dr_regs);
- - if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
- + if (res && (pdata->operating_mode == FSL_USB2_DR_DEVICE))
- release_mem_region(res->start, resource_size(res));
-
- /* free udc --wait for the release() finished */
- --- a/drivers/usb/gadget/udc/fsl_usb2_udc.h
- +++ b/drivers/usb/gadget/udc/fsl_usb2_udc.h
- @@ -20,6 +20,10 @@
- #define USB_MAX_CTRL_PAYLOAD 64
- #define USB_DR_SYS_OFFSET 0x400
-
- +#ifdef CONFIG_SOC_LS1021A
- +#undef CONFIG_ARCH_MXC
- +#endif
- +
- /* USB DR device mode registers (Little Endian) */
- struct usb_dr_device {
- /* Capability register */
- @@ -597,18 +601,6 @@ struct platform_device;
- int fsl_udc_clk_init(struct platform_device *pdev);
- int fsl_udc_clk_finalize(struct platform_device *pdev);
- void fsl_udc_clk_release(void);
- -#else
- -static inline int fsl_udc_clk_init(struct platform_device *pdev)
- -{
- - return 0;
- -}
- -static inline int fsl_udc_clk_finalize(struct platform_device *pdev)
- -{
- - return 0;
- -}
- -static inline void fsl_udc_clk_release(void)
- -{
- -}
- #endif
-
- #endif
- --- a/drivers/usb/host/Kconfig
- +++ b/drivers/usb/host/Kconfig
- @@ -164,8 +164,8 @@ config XPS_USB_HCD_XILINX
- devices only.
-
- config USB_EHCI_FSL
- - tristate "Support for Freescale PPC on-chip EHCI USB controller"
- - depends on FSL_SOC
- + tristate "Support for Freescale QorIQ(ARM/PPC) on-chip EHCI USB controller"
- + depends on USB_EHCI_HCD
- select USB_EHCI_ROOT_HUB_TT
- ---help---
- Variation of ARC USB block used in some Freescale chips.
- --- a/drivers/usb/host/ehci-fsl.c
- +++ b/drivers/usb/host/ehci-fsl.c
- @@ -36,15 +36,127 @@
- #include <linux/platform_device.h>
- #include <linux/fsl_devices.h>
- #include <linux/of_platform.h>
- +#include <linux/io.h>
- +
- +#ifdef CONFIG_PPC
- +#include <asm/fsl_pm.h>
- +#include <linux/suspend.h>
- +#endif
-
- #include "ehci.h"
- #include "ehci-fsl.h"
-
- +#define FSL_USB_PHY_ADDR 0xffe214000
- +
- +struct ccsr_usb_port_ctrl {
- + u32 ctrl;
- + u32 drvvbuscfg;
- + u32 pwrfltcfg;
- + u32 sts;
- + u8 res_14[0xc];
- + u32 bistcfg;
- + u32 biststs;
- + u32 abistcfg;
- + u32 abiststs;
- + u8 res_30[0x10];
- + u32 xcvrprg;
- + u32 anaprg;
- + u32 anadrv;
- + u32 anasts;
- +};
- +
- +struct ccsr_usb_phy {
- + u32 id;
- + struct ccsr_usb_port_ctrl port1;
- + u8 res_50[0xc];
- + u32 tvr;
- + u32 pllprg[4];
- + u8 res_70[0x4];
- + u32 anaccfg;
- + u32 dbg;
- + u8 res_7c[0x4];
- + struct ccsr_usb_port_ctrl port2;
- + u8 res_dc[0x334];
- +};
- +
- #define DRIVER_DESC "Freescale EHCI Host controller driver"
- #define DRV_NAME "ehci-fsl"
-
- static struct hc_driver __read_mostly fsl_ehci_hc_driver;
-
- +struct ehci_fsl {
- + struct ehci_hcd ehci;
- +
- +#ifdef CONFIG_PM
- +struct ehci_regs saved_regs;
- +struct ccsr_usb_phy saved_phy_regs;
- +/* Saved USB PHY settings, need to restore after deep sleep. */
- +u32 usb_ctrl;
- +#endif
- + /*
- + * store current hcd state for otg;
- + * have_hcd is true when host drv al already part of otg framework,
- + * otherwise false;
- + * hcd_add is true when otg framework wants to add host
- + * drv as part of otg;flase when it wants to remove it
- + */
- +unsigned have_hcd:1;
- +unsigned hcd_add:1;
- +};
- +
- +static struct ehci_fsl *hcd_to_ehci_fsl(struct usb_hcd *hcd)
- +{
- +struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- +
- +return container_of(ehci, struct ehci_fsl, ehci);
- +}
- +
- +#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
- +static void do_change_hcd(struct work_struct *work)
- +{
- +struct ehci_hcd *ehci = container_of(work, struct ehci_hcd,
- + change_hcd_work);
- +struct usb_hcd *hcd = ehci_to_hcd(ehci);
- +struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
- +void __iomem *non_ehci = hcd->regs;
- +int retval;
- +
- + if (ehci_fsl->hcd_add && !ehci_fsl->have_hcd) {
- + writel(USBMODE_CM_HOST, non_ehci + FSL_SOC_USB_USBMODE);
- + /* host, gadget and otg share same int line */
- + retval = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
- + if (retval == 0)
- + ehci_fsl->have_hcd = 1;
- + } else if (!ehci_fsl->hcd_add && ehci_fsl->have_hcd) {
- + usb_remove_hcd(hcd);
- + ehci_fsl->have_hcd = 0;
- + }
- +}
- +#endif
- +
- +#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
- +static void do_change_hcd(struct work_struct *work)
- +{
- + struct ehci_hcd *ehci = container_of(work, struct ehci_hcd,
- + change_hcd_work);
- + struct usb_hcd *hcd = ehci_to_hcd(ehci);
- + struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
- + void __iomem *non_ehci = hcd->regs;
- + int retval;
- +
- + if (ehci_fsl->hcd_add && !ehci_fsl->have_hcd) {
- + writel(USBMODE_CM_HOST, non_ehci + FSL_SOC_USB_USBMODE);
- + /* host, gadget and otg share same int line */
- + retval = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
- + if (retval == 0)
- + ehci_fsl->have_hcd = 1;
- + } else if (!ehci_fsl->hcd_add && ehci_fsl->have_hcd) {
- + usb_remove_hcd(hcd);
- + ehci_fsl->have_hcd = 0;
- + }
- +}
- +#endif
- +
- /* configure so an HC device and id are always provided */
- /* always called with process context; sleeping is OK */
-
- @@ -131,6 +243,12 @@ static int fsl_ehci_drv_probe(struct pla
- clrsetbits_be32(hcd->regs + FSL_SOC_USB_CTRL,
- CONTROL_REGISTER_W1C_MASK, 0x4);
-
- + /* Set USB_EN bit to select ULPI phy for USB controller version 2.5 */
- + if (pdata->controller_ver == FSL_USB_VER_2_5 &&
- + pdata->phy_mode == FSL_USB2_PHY_ULPI)
- + iowrite32be(USB_CTRL_USB_EN, hcd->regs + FSL_SOC_USB_CTRL);
- +
- +
- /*
- * Enable UTMI phy and program PTS field in UTMI mode before asserting
- * controller reset for USB Controller version 2.5
- @@ -143,16 +261,20 @@ static int fsl_ehci_drv_probe(struct pla
-
- /* Don't need to set host mode here. It will be done by tdi_reset() */
-
- - retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
- + retval = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_NO_SUSPEND);
- if (retval != 0)
- goto err2;
- device_wakeup_enable(hcd->self.controller);
-
- -#ifdef CONFIG_USB_OTG
- +#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
- if (pdata->operating_mode == FSL_USB2_DR_OTG) {
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- + struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
-
- hcd->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
- +
- + INIT_WORK(&ehci->change_hcd_work, do_change_hcd);
- +
- dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, phy=0x%p\n",
- hcd, ehci, hcd->usb_phy);
-
- @@ -168,6 +290,11 @@ static int fsl_ehci_drv_probe(struct pla
- retval = -ENODEV;
- goto err2;
- }
- +
- + ehci_fsl->have_hcd = 1;
- + } else {
- + dev_err(&pdev->dev, "wrong operating mode\n");
- + return -ENODEV;
- }
- #endif
- return retval;
- @@ -181,6 +308,17 @@ static int fsl_ehci_drv_probe(struct pla
- return retval;
- }
-
- +static bool usb_phy_clk_valid(struct usb_hcd *hcd)
- +{
- + void __iomem *non_ehci = hcd->regs;
- + bool ret = true;
- +
- + if (!(ioread32be(non_ehci + FSL_SOC_USB_CTRL) & PHY_CLK_VALID))
- + ret = false;
- +
- + return ret;
- +}
- +
- static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
- enum fsl_usb2_phy_modes phy_mode,
- unsigned int port_offset)
- @@ -219,6 +357,21 @@ static int ehci_fsl_setup_phy(struct usb
- /* fall through */
- case FSL_USB2_PHY_UTMI:
- case FSL_USB2_PHY_UTMI_DUAL:
- + if (pdata->has_fsl_erratum_a006918) {
- + pr_warn("fsl-ehci: USB PHY clock invalid\n");
- + return -EINVAL;
- + }
- +
- + /* PHY_CLK_VALID bit is de-featured from all controller
- + * versions below 2.4 and is to be checked only for
- + * internal UTMI phy
- + */
- + if (pdata->controller_ver > FSL_USB_VER_2_4 &&
- + pdata->have_sysif_regs && !usb_phy_clk_valid(hcd)) {
- + pr_err("fsl-ehci: USB PHY clock invalid\n");
- + return -EINVAL;
- + }
- +
- if (pdata->have_sysif_regs && pdata->controller_ver) {
- /* controller version 1.6 or above */
- clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
- @@ -286,20 +439,18 @@ static int ehci_fsl_usb_setup(struct ehc
- if (pdata->has_fsl_erratum_a005275 == 1)
- ehci->has_fsl_hs_errata = 1;
-
- + if (pdata->has_fsl_erratum_a005697 == 1)
- + ehci->has_fsl_susp_errata = 1;
- +
- if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
- (pdata->operating_mode == FSL_USB2_DR_OTG))
- if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
- return -EINVAL;
-
- if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
- - unsigned int chip, rev, svr;
- -
- - svr = mfspr(SPRN_SVR);
- - chip = svr >> 16;
- - rev = (svr >> 4) & 0xf;
-
- /* Deal with USB Erratum #14 on MPC834x Rev 1.0 & 1.1 chips */
- - if ((rev == 1) && (chip >= 0x8050) && (chip <= 0x8055))
- + if (pdata->has_fsl_erratum_14 == 1)
- ehci->has_fsl_port_bug = 1;
-
- if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
- @@ -379,16 +530,57 @@ static int ehci_fsl_setup(struct usb_hcd
- return retval;
- }
-
- -struct ehci_fsl {
- - struct ehci_hcd ehci;
-
- #ifdef CONFIG_PM
- - /* Saved USB PHY settings, need to restore after deep sleep. */
- - u32 usb_ctrl;
- -#endif
- -};
- +void __iomem *phy_reg;
-
- -#ifdef CONFIG_PM
- +#ifdef CONFIG_PPC
- +/* save usb registers */
- +static int ehci_fsl_save_context(struct usb_hcd *hcd)
- +{
- + struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
- + struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- + void __iomem *non_ehci = hcd->regs;
- + struct device *dev = hcd->self.controller;
- + struct fsl_usb2_platform_data *pdata = dev_get_platdata(dev);
- +
- + if (pdata->phy_mode == FSL_USB2_PHY_UTMI_DUAL) {
- + phy_reg = ioremap(FSL_USB_PHY_ADDR,
- + sizeof(struct ccsr_usb_phy));
- + _memcpy_fromio((void *)&ehci_fsl->saved_phy_regs, phy_reg,
- + sizeof(struct ccsr_usb_phy));
- + }
- +
- + _memcpy_fromio((void *)&ehci_fsl->saved_regs, ehci->regs,
- + sizeof(struct ehci_regs));
- + ehci_fsl->usb_ctrl = ioread32be(non_ehci + FSL_SOC_USB_CTRL);
- +
- + return 0;
- +}
- +
- +/*Restore usb registers */
- +static int ehci_fsl_restore_context(struct usb_hcd *hcd)
- +{
- + struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
- + struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- + void __iomem *non_ehci = hcd->regs;
- + struct device *dev = hcd->self.controller;
- + struct fsl_usb2_platform_data *pdata = dev_get_platdata(dev);
- +
- + if (pdata->phy_mode == FSL_USB2_PHY_UTMI_DUAL) {
- + if (phy_reg)
- + _memcpy_toio(phy_reg,
- + (void *)&ehci_fsl->saved_phy_regs,
- + sizeof(struct ccsr_usb_phy));
- + }
- +
- + _memcpy_toio(ehci->regs, (void *)&ehci_fsl->saved_regs,
- + sizeof(struct ehci_regs));
- + iowrite32be(ehci_fsl->usb_ctrl, non_ehci + FSL_SOC_USB_CTRL);
- +
- + return 0;
- +}
- +#endif
-
- #ifdef CONFIG_PPC_MPC512x
- static int ehci_fsl_mpc512x_drv_suspend(struct device *dev)
- @@ -535,26 +727,45 @@ static inline int ehci_fsl_mpc512x_drv_r
- }
- #endif /* CONFIG_PPC_MPC512x */
-
- -static struct ehci_fsl *hcd_to_ehci_fsl(struct usb_hcd *hcd)
- -{
- - struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- -
- - return container_of(ehci, struct ehci_fsl, ehci);
- -}
- -
- static int ehci_fsl_drv_suspend(struct device *dev)
- {
- struct usb_hcd *hcd = dev_get_drvdata(dev);
- struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
- void __iomem *non_ehci = hcd->regs;
- +#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
- + struct usb_bus host = hcd->self;
- +#endif
- +
- +#ifdef CONFIG_PPC
- +suspend_state_t pm_state;
- +/* FIXME:Need to port fsl_pm.h before enable below code. */
- +/*pm_state = pm_suspend_state();*/
- +pm_state = PM_SUSPEND_MEM;
- +
- +if (pm_state == PM_SUSPEND_MEM)
- + ehci_fsl_save_context(hcd);
- +#endif
-
- if (of_device_is_compatible(dev->parent->of_node,
- "fsl,mpc5121-usb2-dr")) {
- return ehci_fsl_mpc512x_drv_suspend(dev);
- }
-
- +#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
- + if (host.is_otg) {
- + struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- +
- + /* remove hcd */
- + ehci_fsl->hcd_add = 0;
- + schedule_work(&ehci->change_hcd_work);
- + host.is_otg = 0;
- + return 0;
- + }
- +#endif
- +
- ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd),
- device_may_wakeup(dev));
- +
- if (!fsl_deep_sleep())
- return 0;
-
- @@ -568,12 +779,36 @@ static int ehci_fsl_drv_resume(struct de
- struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- void __iomem *non_ehci = hcd->regs;
- +#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
- + struct usb_bus host = hcd->self;
- +#endif
- +
- +#ifdef CONFIG_PPC
- +suspend_state_t pm_state;
- +/* FIXME:Need to port fsl_pm.h before enable below code.*/
- +/* pm_state = pm_suspend_state(); */
- +pm_state = PM_SUSPEND_MEM;
- +
- +if (pm_state == PM_SUSPEND_MEM)
- + ehci_fsl_restore_context(hcd);
- +#endif
-
- if (of_device_is_compatible(dev->parent->of_node,
- "fsl,mpc5121-usb2-dr")) {
- return ehci_fsl_mpc512x_drv_resume(dev);
- }
-
- +#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
- + if (host.is_otg) {
- + /* add hcd */
- + ehci_fsl->hcd_add = 1;
- + schedule_work(&ehci->change_hcd_work);
- + usb_hcd_resume_root_hub(hcd);
- + host.is_otg = 0;
- + return 0;
- + }
- +#endif
- +
- ehci_prepare_ports_for_controller_resume(ehci);
- if (!fsl_deep_sleep())
- return 0;
- --- a/drivers/usb/host/ehci-fsl.h
- +++ b/drivers/usb/host/ehci-fsl.h
- @@ -63,4 +63,7 @@
- #define UTMI_PHY_EN (1<<9)
- #define ULPI_PHY_CLK_SEL (1<<10)
- #define PHY_CLK_VALID (1<<17)
- +
- +/* Retry count for checking UTMI PHY CLK validity */
- +#define UTMI_PHY_CLK_VALID_CHK_RETRY 5
- #endif /* _EHCI_FSL_H */
- --- a/drivers/usb/host/ehci-hub.c
- +++ b/drivers/usb/host/ehci-hub.c
- @@ -278,6 +278,8 @@ static int ehci_bus_suspend (struct usb_
- else if ((t1 & PORT_PE) && !(t1 & PORT_SUSPEND)) {
- t2 |= PORT_SUSPEND;
- set_bit(port, &ehci->bus_suspended);
- + if (ehci_has_fsl_susp_errata(ehci))
- + usleep_range(10000, 20000);
- }
-
- /* enable remote wakeup on all ports, if told to do so */
- @@ -305,6 +307,8 @@ static int ehci_bus_suspend (struct usb_
- USB_PORT_STAT_HIGH_SPEED)
- fs_idle_delay = true;
- ehci_writel(ehci, t2, reg);
- + if (ehci_has_fsl_susp_errata(ehci))
- + usleep_range(10000, 20000);
- changed = 1;
- }
- }
- --- a/drivers/usb/host/ehci.h
- +++ b/drivers/usb/host/ehci.h
- @@ -180,6 +180,9 @@ struct ehci_hcd { /* one per controlle
- unsigned periodic_count; /* periodic activity count */
- unsigned uframe_periodic_max; /* max periodic time per uframe */
-
- +#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
- + struct work_struct change_hcd_work;
- +#endif
-
- /* list of itds & sitds completed while now_frame was still active */
- struct list_head cached_itd_list;
- @@ -219,6 +222,7 @@ struct ehci_hcd { /* one per controlle
- unsigned no_selective_suspend:1;
- unsigned has_fsl_port_bug:1; /* FreeScale */
- unsigned has_fsl_hs_errata:1; /* Freescale HS quirk */
- + unsigned has_fsl_susp_errata:1; /*Freescale SUSP quirk*/
- unsigned big_endian_mmio:1;
- unsigned big_endian_desc:1;
- unsigned big_endian_capbase:1;
- @@ -704,10 +708,15 @@ ehci_port_speed(struct ehci_hcd *ehci, u
- #if defined(CONFIG_PPC_85xx)
- /* Some Freescale processors have an erratum (USB A-005275) in which
- * incoming packets get corrupted in HS mode
- + * Some Freescale processors have an erratum (USB A-005697) in which
- + * we need to wait for 10ms for bus to fo into suspend mode after
- + * setting SUSP bit
- */
- #define ehci_has_fsl_hs_errata(e) ((e)->has_fsl_hs_errata)
- +#define ehci_has_fsl_susp_errata(e) ((e)->has_fsl_susp_errata)
- #else
- #define ehci_has_fsl_hs_errata(e) (0)
- +#define ehci_has_fsl_susp_errata(e) (0)
- #endif
-
- /*
- --- a/drivers/usb/host/fsl-mph-dr-of.c
- +++ b/drivers/usb/host/fsl-mph-dr-of.c
- @@ -98,8 +98,8 @@ static struct platform_device *fsl_usb2_
-
- pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask;
-
- - if (!pdev->dev.dma_mask)
- - pdev->dev.dma_mask = &ofdev->dev.coherent_dma_mask;
- + if (!pdev->dev.dma_mask && ofdev->dev.of_node)
- + of_dma_configure(&pdev->dev, ofdev->dev.of_node);
- else
- dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
-
- @@ -226,6 +226,18 @@ static int fsl_usb2_mph_dr_of_probe(stru
- of_property_read_bool(np, "fsl,usb-erratum-a007792");
- pdata->has_fsl_erratum_a005275 =
- of_property_read_bool(np, "fsl,usb-erratum-a005275");
- + pdata->has_fsl_erratum_a005697 =
- + of_property_read_bool(np, "fsl,usb_erratum-a005697");
- + if (of_get_property(np, "fsl,erratum_a006918", NULL))
- + pdata->has_fsl_erratum_a006918 = 1;
- + else
- + pdata->has_fsl_erratum_a006918 = 0;
- +
- + if (of_get_property(np, "fsl,usb_erratum_14", NULL))
- + pdata->has_fsl_erratum_14 = 1;
- + else
- + pdata->has_fsl_erratum_14 = 0;
- +
-
- /*
- * Determine whether phy_clk_valid needs to be checked
- --- a/drivers/usb/host/xhci-hub.c
- +++ b/drivers/usb/host/xhci-hub.c
- @@ -562,12 +562,34 @@ void xhci_set_link_state(struct xhci_hcd
- int port_id, u32 link_state)
- {
- u32 temp;
- + u32 portpmsc_u2_backup = 0;
- +
- + /* Backup U2 timeout info before initiating U3 entry erratum A-010131 */
- + if (xhci->shared_hcd->speed >= HCD_USB3 &&
- + link_state == USB_SS_PORT_LS_U3 &&
- + (xhci->quirks & XHCI_DIS_U1U2_WHEN_U3)) {
- + portpmsc_u2_backup = readl(port_array[port_id] + PORTPMSC);
- + portpmsc_u2_backup &= PORT_U2_TIMEOUT_MASK;
- + temp = readl(port_array[port_id] + PORTPMSC);
- + temp |= PORT_U2_TIMEOUT_MASK;
- + writel(temp, port_array[port_id] + PORTPMSC);
- + }
-
- temp = readl(port_array[port_id]);
- temp = xhci_port_state_to_neutral(temp);
- temp &= ~PORT_PLS_MASK;
- temp |= PORT_LINK_STROBE | link_state;
- writel(temp, port_array[port_id]);
- +
- + /* Restore U2 timeout info after U3 entry complete */
- + if (xhci->shared_hcd->speed >= HCD_USB3 &&
- + link_state == USB_SS_PORT_LS_U3 &&
- + (xhci->quirks & XHCI_DIS_U1U2_WHEN_U3)) {
- + temp = readl(port_array[port_id] + PORTPMSC);
- + temp &= ~PORT_U2_TIMEOUT_MASK;
- + temp |= portpmsc_u2_backup;
- + writel(temp, port_array[port_id] + PORTPMSC);
- + }
- }
-
- static void xhci_set_remote_wake_mask(struct xhci_hcd *xhci,
- --- a/drivers/usb/host/xhci-plat.c
- +++ b/drivers/usb/host/xhci-plat.c
- @@ -220,8 +220,22 @@ static int xhci_plat_probe(struct platfo
- goto disable_clk;
- }
-
- - if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable"))
- + if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable")) {
- xhci->quirks |= XHCI_LPM_SUPPORT;
- + if (device_property_read_bool(&pdev->dev,
- + "snps,dis-u1u2-when-u3-quirk"))
- + xhci->quirks |= XHCI_DIS_U1U2_WHEN_U3;
- + }
- +
- + if (device_property_read_bool(&pdev->dev, "quirk-reverse-in-out"))
- + xhci->quirks |= XHCI_REVERSE_IN_OUT;
- +
- + if (device_property_read_bool(&pdev->dev,
- + "quirk-stop-transfer-in-block"))
- + xhci->quirks |= XHCI_STOP_TRANSFER_IN_BLOCK;
- +
- + if (device_property_read_bool(&pdev->dev, "quirk-stop-ep-in-u1"))
- + xhci->quirks |= XHCI_STOP_EP_IN_U1;
-
- if (device_property_read_bool(&pdev->dev, "quirk-broken-port-ped"))
- xhci->quirks |= XHCI_BROKEN_PORT_PED;
- --- a/drivers/usb/host/xhci-ring.c
- +++ b/drivers/usb/host/xhci-ring.c
- @@ -1852,14 +1852,17 @@ static int finish_td(struct xhci_hcd *xh
- union xhci_trb *event_trb, struct xhci_transfer_event *event,
- struct xhci_virt_ep *ep, int *status, bool skip)
- {
- + struct xhci_dequeue_state deq_state;
- struct xhci_virt_device *xdev;
- struct xhci_ring *ep_ring;
- + unsigned int stream_id;
- unsigned int slot_id;
- int ep_index;
- struct urb *urb = NULL;
- struct xhci_ep_ctx *ep_ctx;
- int ret = 0;
- struct urb_priv *urb_priv;
- + u32 remaining;
- u32 trb_comp_code;
-
- slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
- @@ -1885,13 +1888,29 @@ static int finish_td(struct xhci_hcd *xh
- if (trb_comp_code == COMP_STALL ||
- xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
- trb_comp_code)) {
- - /* Issue a reset endpoint command to clear the host side
- - * halt, followed by a set dequeue command to move the
- - * dequeue pointer past the TD.
- - * The class driver clears the device side halt later.
- + /*
- + * A-007463: After transaction error, controller switches
- + * control transfer data stage from IN to OUT direction.
- */
- - xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index,
- + remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
- + if (remaining && xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
- + trb_comp_code) &&
- + (xhci->quirks & XHCI_REVERSE_IN_OUT)) {
- + memset(&deq_state, 0, sizeof(deq_state));
- + xhci_find_new_dequeue_state(xhci, slot_id,
- + ep_index, td->urb->stream_id, td, &deq_state);
- + xhci_queue_new_dequeue_state(xhci, slot_id, ep_index,
- + stream_id, &deq_state);
- + xhci_ring_cmd_db(xhci);
- + } else {
- + /* Issue a reset endpoint command to clear the host side
- + * halt, followed by a set dequeue command to move the
- + * dequeue pointer past the TD.
- + * The class driver clears the device side halt later.
- + */
- + xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index,
- ep_ring->stream_id, td, event_trb);
- + }
- } else {
- /* Update ring dequeue pointer */
- while (ep_ring->dequeue != td->last_trb)
- --- a/drivers/usb/host/xhci.c
- +++ b/drivers/usb/host/xhci.c
- @@ -1609,14 +1609,38 @@ int xhci_urb_dequeue(struct usb_hcd *hcd
- ret = -ENOMEM;
- goto done;
- }
- - ep->ep_state |= EP_HALT_PENDING;
- - ep->stop_cmds_pending++;
- - ep->stop_cmd_timer.expires = jiffies +
- + /*
- + *A-009611: Issuing an End Transfer command on an IN endpoint.
- + *when a transfer is in progress on USB blocks the transmission
- + *Workaround: Software must wait for all existing TRBs to
- + *complete before issuing End transfer command.
- + */
- + if ((ep_ring->enqueue == ep_ring->dequeue &&
- + (xhci->quirks & XHCI_STOP_TRANSFER_IN_BLOCK)) ||
- + !(xhci->quirks & XHCI_STOP_TRANSFER_IN_BLOCK)) {
- + ep->ep_state |= EP_HALT_PENDING;
- + ep->stop_cmds_pending++;
- + ep->stop_cmd_timer.expires = jiffies +
- XHCI_STOP_EP_CMD_TIMEOUT * HZ;
- - add_timer(&ep->stop_cmd_timer);
- - xhci_queue_stop_endpoint(xhci, command, urb->dev->slot_id,
- - ep_index, 0);
- - xhci_ring_cmd_db(xhci);
- + add_timer(&ep->stop_cmd_timer);
- + xhci_queue_stop_endpoint(xhci, command,
- + urb->dev->slot_id,
- + ep_index, 0);
- + xhci_ring_cmd_db(xhci);
- + }
- +
- + /*
- + *A-009668: Stop Endpoint Command does not complete.
- + *Workaround: Instead of issuing a Stop Endpoint Command,
- + *issue a Disable Slot Command with the corresponding slot ID.
- + *Alternately, you can issue an Address Device Command with
- + *BSR=1
- + */
- + if ((urb->dev->speed <= USB_SPEED_HIGH) &&
- + (xhci->quirks & XHCI_STOP_EP_IN_U1)) {
- + xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT,
- + urb->dev->slot_id);
- + }
- }
- done:
- spin_unlock_irqrestore(&xhci->lock, flags);
- --- a/drivers/usb/host/xhci.h
- +++ b/drivers/usb/host/xhci.h
- @@ -1625,7 +1625,7 @@ struct xhci_hcd {
- #define XHCI_STATE_REMOVING (1 << 2)
- /* Statistics */
- int error_bitmask;
- - unsigned int quirks;
- + u64 quirks;
- #define XHCI_LINK_TRB_QUIRK (1 << 0)
- #define XHCI_RESET_EP_QUIRK (1 << 1)
- #define XHCI_NEC_HOST (1 << 2)
- @@ -1661,6 +1661,10 @@ struct xhci_hcd {
- #define XHCI_SSIC_PORT_UNUSED (1 << 22)
- #define XHCI_NO_64BIT_SUPPORT (1 << 23)
- #define XHCI_MISSING_CAS (1 << 24)
- +#define XHCI_REVERSE_IN_OUT (1 << 29)
- +#define XHCI_STOP_TRANSFER_IN_BLOCK (1 << 30)
- +#define XHCI_STOP_EP_IN_U1 (1 << 31)
- +#define XHCI_DIS_U1U2_WHEN_U3 (1 << 32)
- /* For controller with a broken Port Disable implementation */
- #define XHCI_BROKEN_PORT_PED (1 << 25)
- #define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26)
- --- a/drivers/usb/phy/phy-fsl-usb.c
- +++ b/drivers/usb/phy/phy-fsl-usb.c
- @@ -1,5 +1,5 @@
- /*
- - * Copyright (C) 2007,2008 Freescale semiconductor, Inc.
- + * Copyright 2007,2008 Freescale Semiconductor, Inc.
- *
- * Author: Li Yang <[email protected]>
- * Jerry Huang <[email protected]>
- @@ -463,6 +463,7 @@ void otg_reset_controller(void)
- int fsl_otg_start_host(struct otg_fsm *fsm, int on)
- {
- struct usb_otg *otg = fsm->otg;
- + struct usb_bus *host = otg->host;
- struct device *dev;
- struct fsl_otg *otg_dev =
- container_of(otg->usb_phy, struct fsl_otg, phy);
- @@ -486,6 +487,7 @@ int fsl_otg_start_host(struct otg_fsm *f
- otg_reset_controller();
- VDBG("host on......\n");
- if (dev->driver->pm && dev->driver->pm->resume) {
- + host->is_otg = 1;
- retval = dev->driver->pm->resume(dev);
- if (fsm->id) {
- /* default-b */
- @@ -510,8 +512,11 @@ int fsl_otg_start_host(struct otg_fsm *f
- else {
- VDBG("host off......\n");
- if (dev && dev->driver) {
- - if (dev->driver->pm && dev->driver->pm->suspend)
- + if (dev->driver->pm &&
- + dev->driver->pm->suspend) {
- + host->is_otg = 1;
- retval = dev->driver->pm->suspend(dev);
- + }
- if (fsm->id)
- /* default-b */
- fsl_otg_drv_vbus(fsm, 0);
- @@ -539,8 +544,17 @@ int fsl_otg_start_gadget(struct otg_fsm
- dev = otg->gadget->dev.parent;
-
- if (on) {
- - if (dev->driver->resume)
- + /* Delay gadget resume to synchronize between host and gadget
- + * drivers. Upon role-reversal host drv is shutdown by kernel
- + * worker thread. By the time host drv shuts down, controller
- + * gets programmed for gadget role. Shutting host drv after
- + * this results in controller getting reset, and it stops
- + * responding to otg events
- + */
- + if (dev->driver->resume) {
- + msleep(1000);
- dev->driver->resume(dev);
- + }
- } else {
- if (dev->driver->suspend)
- dev->driver->suspend(dev, otg_suspend_state);
- @@ -672,6 +686,10 @@ static void fsl_otg_event(struct work_st
- fsl_otg_start_host(fsm, 0);
- otg_drv_vbus(fsm, 0);
- fsl_otg_start_gadget(fsm, 1);
- + } else {
- + fsl_otg_start_gadget(fsm, 0);
- + otg_drv_vbus(fsm, 1);
- + fsl_otg_start_host(fsm, 1);
- }
- }
-
- @@ -724,6 +742,7 @@ irqreturn_t fsl_otg_isr(int irq, void *d
- {
- struct otg_fsm *fsm = &((struct fsl_otg *)dev_id)->fsm;
- struct usb_otg *otg = ((struct fsl_otg *)dev_id)->phy.otg;
- + struct fsl_otg *otg_dev = dev_id;
- u32 otg_int_src, otg_sc;
-
- otg_sc = fsl_readl(&usb_dr_regs->otgsc);
- @@ -753,18 +772,8 @@ irqreturn_t fsl_otg_isr(int irq, void *d
- otg->gadget->is_a_peripheral = !fsm->id;
- VDBG("ID int (ID is %d)\n", fsm->id);
-
- - if (fsm->id) { /* switch to gadget */
- - schedule_delayed_work(
- - &((struct fsl_otg *)dev_id)->otg_event,
- - 100);
- - } else { /* switch to host */
- - cancel_delayed_work(&
- - ((struct fsl_otg *)dev_id)->
- - otg_event);
- - fsl_otg_start_gadget(fsm, 0);
- - otg_drv_vbus(fsm, 1);
- - fsl_otg_start_host(fsm, 1);
- - }
- + schedule_delayed_work(&otg_dev->otg_event, 100);
- +
- return IRQ_HANDLED;
- }
- }
- @@ -925,12 +934,32 @@ int usb_otg_start(struct platform_device
- temp &= ~(PORTSC_PHY_TYPE_SEL | PORTSC_PTW);
- switch (pdata->phy_mode) {
- case FSL_USB2_PHY_ULPI:
- + if (pdata->controller_ver) {
- + /* controller version 1.6 or above */
- + setbits32(&p_otg->dr_mem_map->control,
- + USB_CTRL_ULPI_PHY_CLK_SEL);
- + /*
- + * Due to controller issue of PHY_CLK_VALID in ULPI
- + * mode, we set USB_CTRL_USB_EN before checking
- + * PHY_CLK_VALID, otherwise PHY_CLK_VALID doesn't work.
- + */
- + clrsetbits_be32(&p_otg->dr_mem_map->control,
- + USB_CTRL_UTMI_PHY_EN, USB_CTRL_IOENB);
- + }
- temp |= PORTSC_PTS_ULPI;
- break;
- case FSL_USB2_PHY_UTMI_WIDE:
- temp |= PORTSC_PTW_16BIT;
- /* fall through */
- case FSL_USB2_PHY_UTMI:
- + if (pdata->controller_ver) {
- + /* controller version 1.6 or above */
- + setbits32(&p_otg->dr_mem_map->control,
- + USB_CTRL_UTMI_PHY_EN);
- + /* Delay for UTMI PHY CLK to become stable - 10ms */
- + mdelay(FSL_UTMI_PHY_DLY);
- + }
- + setbits32(&p_otg->dr_mem_map->control, USB_CTRL_UTMI_PHY_EN);
- temp |= PORTSC_PTS_UTMI;
- /* fall through */
- default:
- --- a/drivers/usb/phy/phy-fsl-usb.h
- +++ b/drivers/usb/phy/phy-fsl-usb.h
- @@ -199,6 +199,14 @@
- /* control Register Bit Masks */
- #define USB_CTRL_IOENB (0x1<<2)
- #define USB_CTRL_ULPI_INT0EN (0x1<<0)
- +#define USB_CTRL_WU_INT_EN (0x1<<1)
- +#define USB_CTRL_LINE_STATE_FILTER__EN (0x1<<3)
- +#define USB_CTRL_KEEP_OTG_ON (0x1<<4)
- +#define USB_CTRL_OTG_PORT (0x1<<5)
- +#define USB_CTRL_PLL_RESET (0x1<<8)
- +#define USB_CTRL_UTMI_PHY_EN (0x1<<9)
- +#define USB_CTRL_ULPI_PHY_CLK_SEL (0x1<<10)
- +#define USB_CTRL_PHY_CLK_VALID (0x1<<17)
-
- /* BCSR5 */
- #define BCSR5_INT_USB (0x02)
- --- a/include/linux/usb.h
- +++ b/include/linux/usb.h
- @@ -362,6 +362,7 @@ struct usb_bus {
- * for control transfers?
- */
- u8 otg_port; /* 0, or number of OTG/HNP port */
- + unsigned is_otg:1; /* true when host is also otg */
- unsigned is_b_host:1; /* true during some HNP roleswitches */
- unsigned b_hnp_enable:1; /* OTG: did A-Host enable HNP? */
- unsigned no_stop_on_short:1; /*
- --- a/include/linux/usb/of.h
- +++ b/include/linux/usb/of.h
- @@ -11,6 +11,8 @@
- #include <linux/usb/otg.h>
- #include <linux/usb/phy.h>
-
- +enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np);
- +
- #if IS_ENABLED(CONFIG_OF)
- enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *np, int arg0);
- bool of_usb_host_tpl_support(struct device_node *np);
|