Merge tag 'usb-for-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

Felipe writes:

usb: patches for v4.10 merge window

One big merge this time with a total of 166 non-merge commits.

Most of the work, by far, is on dwc2 this time (68.2%) with dwc3 a far
second (22.5%). The remaining 9.3% are scattered on gadget drivers.

The most important changes for dwc2 are the peripheral side DMA support
implemented by Synopsys folks and support for the new IOT dwc2
compatible core from Synopsys.

In dwc3 land we have support for high-bandwidth, high-speed isochronous
endpoints and some non-critical fixes for large scatter lists.

Apart from these, we have our usual set of cleanups, non-critical fixes,
etc.
This commit is contained in:
Greg Kroah-Hartman
2016-11-18 16:02:15 +01:00
85 changed files with 4087 additions and 2767 deletions

View File

@@ -12,6 +12,7 @@ Required properties:
- "lantiq,xrx200-usb": The DWC2 USB controller instance in Lantiq XRX SoCs; - "lantiq,xrx200-usb": The DWC2 USB controller instance in Lantiq XRX SoCs;
- "amlogic,meson8b-usb": The DWC2 USB controller instance in Amlogic Meson8b SoCs; - "amlogic,meson8b-usb": The DWC2 USB controller instance in Amlogic Meson8b SoCs;
- "amlogic,meson-gxbb-usb": The DWC2 USB controller instance in Amlogic S905 SoCs; - "amlogic,meson-gxbb-usb": The DWC2 USB controller instance in Amlogic S905 SoCs;
- "amcc,dwc-otg": The DWC2 USB controller instance in AMCC Canyonlands 460EX SoCs;
- snps,dwc2: A generic DWC2 USB controller with default parameters. - snps,dwc2: A generic DWC2 USB controller with default parameters.
- reg : Should contain 1 register range (address and length) - reg : Should contain 1 register range (address and length)
- interrupts : Should contain 1 interrupt - interrupts : Should contain 1 interrupt
@@ -25,11 +26,13 @@ Optional properties:
Refer to phy/phy-bindings.txt for generic phy consumer properties Refer to phy/phy-bindings.txt for generic phy consumer properties
- dr_mode: shall be one of "host", "peripheral" and "otg" - dr_mode: shall be one of "host", "peripheral" and "otg"
Refer to usb/generic.txt Refer to usb/generic.txt
- g-use-dma: enable dma usage in gadget driver.
- g-rx-fifo-size: size of rx fifo size in gadget mode. - g-rx-fifo-size: size of rx fifo size in gadget mode.
- g-np-tx-fifo-size: size of non-periodic tx fifo size in gadget mode. - g-np-tx-fifo-size: size of non-periodic tx fifo size in gadget mode.
- g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode. - g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode.
Deprecated properties:
- g-use-dma: gadget DMA mode is automatically detected
Example: Example:
usb@101c0000 { usb@101c0000 {

View File

@@ -204,7 +204,6 @@
g-np-tx-fifo-size = <16>; g-np-tx-fifo-size = <16>;
g-rx-fifo-size = <275>; g-rx-fifo-size = <275>;
g-tx-fifo-size = <256 128 128 64 64 32>; g-tx-fifo-size = <256 128 128 64 64 32>;
g-use-dma;
status = "disabled"; status = "disabled";
}; };

View File

@@ -596,7 +596,6 @@
g-np-tx-fifo-size = <16>; g-np-tx-fifo-size = <16>;
g-rx-fifo-size = <275>; g-rx-fifo-size = <275>;
g-tx-fifo-size = <256 128 128 64 64 32>; g-tx-fifo-size = <256 128 128 64 64 32>;
g-use-dma;
phys = <&usbphy0>; phys = <&usbphy0>;
phy-names = "usb2-phy"; phy-names = "usb2-phy";
status = "disabled"; status = "disabled";

View File

@@ -181,7 +181,6 @@
g-np-tx-fifo-size = <16>; g-np-tx-fifo-size = <16>;
g-rx-fifo-size = <275>; g-rx-fifo-size = <275>;
g-tx-fifo-size = <256 128 128 64 64 32>; g-tx-fifo-size = <256 128 128 64 64 32>;
g-use-dma;
phys = <&usbphy0>; phys = <&usbphy0>;
phy-names = "usb2-phy"; phy-names = "usb2-phy";
status = "disabled"; status = "disabled";

View File

@@ -747,7 +747,6 @@
clocks = <&sys_ctrl HI6220_USBOTG_HCLK>; clocks = <&sys_ctrl HI6220_USBOTG_HCLK>;
clock-names = "otg"; clock-names = "otg";
dr_mode = "otg"; dr_mode = "otg";
g-use-dma;
g-rx-fifo-size = <512>; g-rx-fifo-size = <512>;
g-np-tx-fifo-size = <128>; g-np-tx-fifo-size = <128>;
g-tx-fifo-size = <128 128 128 128 128 128>; g-tx-fifo-size = <128 128 128 128 128 128>;

View File

@@ -537,7 +537,6 @@
g-np-tx-fifo-size = <16>; g-np-tx-fifo-size = <16>;
g-rx-fifo-size = <275>; g-rx-fifo-size = <275>;
g-tx-fifo-size = <256 128 128 64 64 32>; g-tx-fifo-size = <256 128 128 64 64 32>;
g-use-dma;
status = "disabled"; status = "disabled";
}; };

View File

@@ -71,6 +71,7 @@ static int usbtv_probe(struct usb_interface *intf,
int size; int size;
struct device *dev = &intf->dev; struct device *dev = &intf->dev;
struct usbtv *usbtv; struct usbtv *usbtv;
struct usb_host_endpoint *ep;
/* Checks that the device is what we think it is. */ /* Checks that the device is what we think it is. */
if (intf->num_altsetting != 2) if (intf->num_altsetting != 2)
@@ -78,10 +79,12 @@ static int usbtv_probe(struct usb_interface *intf,
if (intf->altsetting[1].desc.bNumEndpoints != 4) if (intf->altsetting[1].desc.bNumEndpoints != 4)
return -ENODEV; return -ENODEV;
ep = &intf->altsetting[1].endpoint[0];
/* Packet size is split into 11 bits of base size and count of /* Packet size is split into 11 bits of base size and count of
* extra multiplies of it.*/ * extra multiplies of it.*/
size = usb_endpoint_maxp(&intf->altsetting[1].endpoint[0].desc); size = usb_endpoint_maxp(&ep->desc);
size = (size & 0x07ff) * (((size & 0x1800) >> 11) + 1); size = (size & 0x07ff) * usb_endpoint_maxp_mult(&ep->desc);
/* Device structure */ /* Device structure */
usbtv = kzalloc(sizeof(struct usbtv), GFP_KERNEL); usbtv = kzalloc(sizeof(struct usbtv), GFP_KERNEL);

View File

@@ -1467,6 +1467,7 @@ static unsigned int uvc_endpoint_max_bpi(struct usb_device *dev,
struct usb_host_endpoint *ep) struct usb_host_endpoint *ep)
{ {
u16 psize; u16 psize;
u16 mult;
switch (dev->speed) { switch (dev->speed) {
case USB_SPEED_SUPER: case USB_SPEED_SUPER:
@@ -1474,7 +1475,8 @@ static unsigned int uvc_endpoint_max_bpi(struct usb_device *dev,
return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval); return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
case USB_SPEED_HIGH: case USB_SPEED_HIGH:
psize = usb_endpoint_maxp(&ep->desc); psize = usb_endpoint_maxp(&ep->desc);
return (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); mult = usb_endpoint_maxp_mult(&ep->desc);
return (psize & 0x07ff) * mult;
case USB_SPEED_WIRELESS: case USB_SPEED_WIRELESS:
psize = usb_endpoint_maxp(&ep->desc); psize = usb_endpoint_maxp(&ep->desc);
return psize; return psize;
@@ -1551,7 +1553,7 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream,
u16 psize; u16 psize;
u32 size; u32 size;
psize = usb_endpoint_maxp(&ep->desc) & 0x7ff; psize = usb_endpoint_maxp(&ep->desc);
size = stream->ctrl.dwMaxPayloadTransferSize; size = stream->ctrl.dwMaxPayloadTransferSize;
stream->bulk.max_payload_size = size; stream->bulk.max_payload_size = size;

View File

@@ -821,7 +821,7 @@ static int _ep_queue(struct usb_ep *ep, struct usb_request *req,
} }
if (usb_endpoint_xfer_isoc(hwep->ep.desc) && if (usb_endpoint_xfer_isoc(hwep->ep.desc) &&
hwreq->req.length > (1 + hwep->ep.mult) * hwep->ep.maxpacket) { hwreq->req.length > hwep->ep.mult * hwep->ep.maxpacket) {
dev_err(hwep->ci->dev, "request length too big for isochronous\n"); dev_err(hwep->ci->dev, "request length too big for isochronous\n");
return -EMSGSIZE; return -EMSGSIZE;
} }
@@ -1253,8 +1253,8 @@ static int ep_enable(struct usb_ep *ep,
hwep->num = usb_endpoint_num(desc); hwep->num = usb_endpoint_num(desc);
hwep->type = usb_endpoint_type(desc); hwep->type = usb_endpoint_type(desc);
hwep->ep.maxpacket = usb_endpoint_maxp(desc) & 0x07ff; hwep->ep.maxpacket = usb_endpoint_maxp(desc);
hwep->ep.mult = QH_ISO_MULT(usb_endpoint_maxp(desc)); hwep->ep.mult = usb_endpoint_maxp_mult(desc);
if (hwep->type == USB_ENDPOINT_XFER_CONTROL) if (hwep->type == USB_ENDPOINT_XFER_CONTROL)
cap |= QH_IOS; cap |= QH_IOS;

View File

@@ -182,14 +182,8 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
dir = usb_endpoint_dir_in(desc) ? 'I' : 'O'; dir = usb_endpoint_dir_in(desc) ? 'I' : 'O';
if (speed == USB_SPEED_HIGH) { if (speed == USB_SPEED_HIGH)
switch (usb_endpoint_maxp(desc) & (0x03 << 11)) { bandwidth = usb_endpoint_maxp_mult(desc);
case 1 << 11:
bandwidth = 2; break;
case 2 << 11:
bandwidth = 3; break;
}
}
/* this isn't checking for illegal values */ /* this isn't checking for illegal values */
switch (usb_endpoint_type(desc)) { switch (usb_endpoint_type(desc)) {
@@ -233,7 +227,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
start += sprintf(start, format_endpt, desc->bEndpointAddress, dir, start += sprintf(start, format_endpt, desc->bEndpointAddress, dir,
desc->bmAttributes, type, desc->bmAttributes, type,
(usb_endpoint_maxp(desc) & 0x07ff) * usb_endpoint_maxp(desc) *
bandwidth, bandwidth,
interval, unit); interval, unit);
return start; return start;

View File

@@ -52,8 +52,7 @@ static ssize_t wMaxPacketSize_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct ep_device *ep = to_ep_device(dev); struct ep_device *ep = to_ep_device(dev);
return sprintf(buf, "%04x\n", return sprintf(buf, "%04x\n", usb_endpoint_maxp(ep->desc));
usb_endpoint_maxp(ep->desc) & 0x07ff);
} }
static DEVICE_ATTR_RO(wMaxPacketSize); static DEVICE_ATTR_RO(wMaxPacketSize);

View File

@@ -412,11 +412,8 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
} }
/* "high bandwidth" mode, 1-3 packets/uframe? */ /* "high bandwidth" mode, 1-3 packets/uframe? */
if (dev->speed == USB_SPEED_HIGH) { if (dev->speed == USB_SPEED_HIGH)
int mult = 1 + ((max >> 11) & 0x03); max *= usb_endpoint_maxp_mult(&ep->desc);
max &= 0x07ff;
max *= mult;
}
if (urb->number_of_packets <= 0) if (urb->number_of_packets <= 0)
return -EINVAL; return -EINVAL;

View File

@@ -3,6 +3,7 @@ ccflags-$(CONFIG_USB_DWC2_VERBOSE) += -DVERBOSE_DEBUG
obj-$(CONFIG_USB_DWC2) += dwc2.o obj-$(CONFIG_USB_DWC2) += dwc2.o
dwc2-y := core.o core_intr.o platform.o dwc2-y := core.o core_intr.o platform.o
dwc2-y += params.o
ifneq ($(filter y,$(CONFIG_USB_DWC2_HOST) $(CONFIG_USB_DWC2_DUAL_ROLE)),) ifneq ($(filter y,$(CONFIG_USB_DWC2_HOST) $(CONFIG_USB_DWC2_DUAL_ROLE)),)
dwc2-y += hcd.o hcd_intr.o dwc2-y += hcd.o hcd_intr.o

View File

@@ -135,7 +135,7 @@ int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore)
u32 pcgcctl; u32 pcgcctl;
int ret = 0; int ret = 0;
if (!hsotg->core_params->hibernation) if (!hsotg->params.hibernation)
return -ENOTSUPP; return -ENOTSUPP;
pcgcctl = dwc2_readl(hsotg->regs + PCGCTL); pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
@@ -188,7 +188,7 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg)
u32 pcgcctl; u32 pcgcctl;
int ret = 0; int ret = 0;
if (!hsotg->core_params->hibernation) if (!hsotg->params.hibernation)
return -ENOTSUPP; return -ENOTSUPP;
/* Backup all registers */ /* Backup all registers */
@@ -445,7 +445,7 @@ static bool dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host)
* the force mode. We only need to call this once during probe if * the force mode. We only need to call this once during probe if
* dr_mode == OTG. * dr_mode == OTG.
*/ */
static void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg) void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg)
{ {
u32 gusbcfg; u32 gusbcfg;
@@ -541,7 +541,7 @@ void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg)
addr = hsotg->regs + HAINTMSK; addr = hsotg->regs + HAINTMSK;
dev_dbg(hsotg->dev, "HAINTMSK @0x%08lX : 0x%08X\n", dev_dbg(hsotg->dev, "HAINTMSK @0x%08lX : 0x%08X\n",
(unsigned long)addr, dwc2_readl(addr)); (unsigned long)addr, dwc2_readl(addr));
if (hsotg->core_params->dma_desc_enable > 0) { if (hsotg->params.dma_desc_enable > 0) {
addr = hsotg->regs + HFLBADDR; addr = hsotg->regs + HFLBADDR;
dev_dbg(hsotg->dev, "HFLBADDR @0x%08lX : 0x%08X\n", dev_dbg(hsotg->dev, "HFLBADDR @0x%08lX : 0x%08X\n",
(unsigned long)addr, dwc2_readl(addr)); (unsigned long)addr, dwc2_readl(addr));
@@ -551,7 +551,7 @@ void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev, "HPRT0 @0x%08lX : 0x%08X\n", dev_dbg(hsotg->dev, "HPRT0 @0x%08lX : 0x%08X\n",
(unsigned long)addr, dwc2_readl(addr)); (unsigned long)addr, dwc2_readl(addr));
for (i = 0; i < hsotg->core_params->host_channels; i++) { for (i = 0; i < hsotg->params.host_channels; i++) {
dev_dbg(hsotg->dev, "Host Channel %d Specific Registers\n", i); dev_dbg(hsotg->dev, "Host Channel %d Specific Registers\n", i);
addr = hsotg->regs + HCCHAR(i); addr = hsotg->regs + HCCHAR(i);
dev_dbg(hsotg->dev, "HCCHAR @0x%08lX : 0x%08X\n", dev_dbg(hsotg->dev, "HCCHAR @0x%08lX : 0x%08X\n",
@@ -571,7 +571,7 @@ void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg)
addr = hsotg->regs + HCDMA(i); addr = hsotg->regs + HCDMA(i);
dev_dbg(hsotg->dev, "HCDMA @0x%08lX : 0x%08X\n", dev_dbg(hsotg->dev, "HCDMA @0x%08lX : 0x%08X\n",
(unsigned long)addr, dwc2_readl(addr)); (unsigned long)addr, dwc2_readl(addr));
if (hsotg->core_params->dma_desc_enable > 0) { if (hsotg->params.dma_desc_enable > 0) {
addr = hsotg->regs + HCDMAB(i); addr = hsotg->regs + HCDMAB(i);
dev_dbg(hsotg->dev, "HCDMAB @0x%08lX : 0x%08X\n", dev_dbg(hsotg->dev, "HCDMAB @0x%08lX : 0x%08X\n",
(unsigned long)addr, dwc2_readl(addr)); (unsigned long)addr, dwc2_readl(addr));
@@ -735,704 +735,13 @@ void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg)
udelay(1); udelay(1);
} }
#define DWC2_OUT_OF_BOUNDS(a, b, c) ((a) < (b) || (a) > (c))
/* Parameter access functions */
void dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val)
{
int valid = 1;
switch (val) {
case DWC2_CAP_PARAM_HNP_SRP_CAPABLE:
if (hsotg->hw_params.op_mode != GHWCFG2_OP_MODE_HNP_SRP_CAPABLE)
valid = 0;
break;
case DWC2_CAP_PARAM_SRP_ONLY_CAPABLE:
switch (hsotg->hw_params.op_mode) {
case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE:
case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE:
case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE:
case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST:
break;
default:
valid = 0;
break;
}
break;
case DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE:
/* always valid */
break;
default:
valid = 0;
break;
}
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for otg_cap parameter. Check HW configuration.\n",
val);
switch (hsotg->hw_params.op_mode) {
case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE:
val = DWC2_CAP_PARAM_HNP_SRP_CAPABLE;
break;
case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE:
case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE:
case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST:
val = DWC2_CAP_PARAM_SRP_ONLY_CAPABLE;
break;
default:
val = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE;
break;
}
dev_dbg(hsotg->dev, "Setting otg_cap to %d\n", val);
}
hsotg->core_params->otg_cap = val;
}
void dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val)
{
int valid = 1;
if (val > 0 && hsotg->hw_params.arch == GHWCFG2_SLAVE_ONLY_ARCH)
valid = 0;
if (val < 0)
valid = 0;
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for dma_enable parameter. Check HW configuration.\n",
val);
val = hsotg->hw_params.arch != GHWCFG2_SLAVE_ONLY_ARCH;
dev_dbg(hsotg->dev, "Setting dma_enable to %d\n", val);
}
hsotg->core_params->dma_enable = val;
}
void dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val)
{
int valid = 1;
if (val > 0 && (hsotg->core_params->dma_enable <= 0 ||
!hsotg->hw_params.dma_desc_enable))
valid = 0;
if (val < 0)
valid = 0;
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for dma_desc_enable parameter. Check HW configuration.\n",
val);
val = (hsotg->core_params->dma_enable > 0 &&
hsotg->hw_params.dma_desc_enable);
dev_dbg(hsotg->dev, "Setting dma_desc_enable to %d\n", val);
}
hsotg->core_params->dma_desc_enable = val;
}
void dwc2_set_param_dma_desc_fs_enable(struct dwc2_hsotg *hsotg, int val)
{
int valid = 1;
if (val > 0 && (hsotg->core_params->dma_enable <= 0 ||
!hsotg->hw_params.dma_desc_enable))
valid = 0;
if (val < 0)
valid = 0;
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for dma_desc_fs_enable parameter. Check HW configuration.\n",
val);
val = (hsotg->core_params->dma_enable > 0 &&
hsotg->hw_params.dma_desc_enable);
}
hsotg->core_params->dma_desc_fs_enable = val;
dev_dbg(hsotg->dev, "Setting dma_desc_fs_enable to %d\n", val);
}
void dwc2_set_param_host_support_fs_ls_low_power(struct dwc2_hsotg *hsotg,
int val)
{
if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) {
if (val >= 0) {
dev_err(hsotg->dev,
"Wrong value for host_support_fs_low_power\n");
dev_err(hsotg->dev,
"host_support_fs_low_power must be 0 or 1\n");
}
val = 0;
dev_dbg(hsotg->dev,
"Setting host_support_fs_low_power to %d\n", val);
}
hsotg->core_params->host_support_fs_ls_low_power = val;
}
void dwc2_set_param_enable_dynamic_fifo(struct dwc2_hsotg *hsotg, int val)
{
int valid = 1;
if (val > 0 && !hsotg->hw_params.enable_dynamic_fifo)
valid = 0;
if (val < 0)
valid = 0;
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for enable_dynamic_fifo parameter. Check HW configuration.\n",
val);
val = hsotg->hw_params.enable_dynamic_fifo;
dev_dbg(hsotg->dev, "Setting enable_dynamic_fifo to %d\n", val);
}
hsotg->core_params->enable_dynamic_fifo = val;
}
void dwc2_set_param_host_rx_fifo_size(struct dwc2_hsotg *hsotg, int val)
{
int valid = 1;
if (val < 16 || val > hsotg->hw_params.host_rx_fifo_size)
valid = 0;
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for host_rx_fifo_size. Check HW configuration.\n",
val);
val = hsotg->hw_params.host_rx_fifo_size;
dev_dbg(hsotg->dev, "Setting host_rx_fifo_size to %d\n", val);
}
hsotg->core_params->host_rx_fifo_size = val;
}
void dwc2_set_param_host_nperio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val)
{
int valid = 1;
if (val < 16 || val > hsotg->hw_params.host_nperio_tx_fifo_size)
valid = 0;
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n",
val);
val = hsotg->hw_params.host_nperio_tx_fifo_size;
dev_dbg(hsotg->dev, "Setting host_nperio_tx_fifo_size to %d\n",
val);
}
hsotg->core_params->host_nperio_tx_fifo_size = val;
}
void dwc2_set_param_host_perio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val)
{
int valid = 1;
if (val < 16 || val > hsotg->hw_params.host_perio_tx_fifo_size)
valid = 0;
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n",
val);
val = hsotg->hw_params.host_perio_tx_fifo_size;
dev_dbg(hsotg->dev, "Setting host_perio_tx_fifo_size to %d\n",
val);
}
hsotg->core_params->host_perio_tx_fifo_size = val;
}
void dwc2_set_param_max_transfer_size(struct dwc2_hsotg *hsotg, int val)
{
int valid = 1;
if (val < 2047 || val > hsotg->hw_params.max_transfer_size)
valid = 0;
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for max_transfer_size. Check HW configuration.\n",
val);
val = hsotg->hw_params.max_transfer_size;
dev_dbg(hsotg->dev, "Setting max_transfer_size to %d\n", val);
}
hsotg->core_params->max_transfer_size = val;
}
void dwc2_set_param_max_packet_count(struct dwc2_hsotg *hsotg, int val)
{
int valid = 1;
if (val < 15 || val > hsotg->hw_params.max_packet_count)
valid = 0;
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for max_packet_count. Check HW configuration.\n",
val);
val = hsotg->hw_params.max_packet_count;
dev_dbg(hsotg->dev, "Setting max_packet_count to %d\n", val);
}
hsotg->core_params->max_packet_count = val;
}
void dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val)
{
int valid = 1;
if (val < 1 || val > hsotg->hw_params.host_channels)
valid = 0;
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for host_channels. Check HW configuration.\n",
val);
val = hsotg->hw_params.host_channels;
dev_dbg(hsotg->dev, "Setting host_channels to %d\n", val);
}
hsotg->core_params->host_channels = val;
}
void dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val)
{
int valid = 0;
u32 hs_phy_type, fs_phy_type;
if (DWC2_OUT_OF_BOUNDS(val, DWC2_PHY_TYPE_PARAM_FS,
DWC2_PHY_TYPE_PARAM_ULPI)) {
if (val >= 0) {
dev_err(hsotg->dev, "Wrong value for phy_type\n");
dev_err(hsotg->dev, "phy_type must be 0, 1 or 2\n");
}
valid = 0;
}
hs_phy_type = hsotg->hw_params.hs_phy_type;
fs_phy_type = hsotg->hw_params.fs_phy_type;
if (val == DWC2_PHY_TYPE_PARAM_UTMI &&
(hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI ||
hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI))
valid = 1;
else if (val == DWC2_PHY_TYPE_PARAM_ULPI &&
(hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI ||
hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI))
valid = 1;
else if (val == DWC2_PHY_TYPE_PARAM_FS &&
fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED)
valid = 1;
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for phy_type. Check HW configuration.\n",
val);
val = DWC2_PHY_TYPE_PARAM_FS;
if (hs_phy_type != GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED) {
if (hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI ||
hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI)
val = DWC2_PHY_TYPE_PARAM_UTMI;
else
val = DWC2_PHY_TYPE_PARAM_ULPI;
}
dev_dbg(hsotg->dev, "Setting phy_type to %d\n", val);
}
hsotg->core_params->phy_type = val;
}
static int dwc2_get_param_phy_type(struct dwc2_hsotg *hsotg)
{
return hsotg->core_params->phy_type;
}
void dwc2_set_param_speed(struct dwc2_hsotg *hsotg, int val)
{
int valid = 1;
if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) {
if (val >= 0) {
dev_err(hsotg->dev, "Wrong value for speed parameter\n");
dev_err(hsotg->dev, "max_speed parameter must be 0 or 1\n");
}
valid = 0;
}
if (val == DWC2_SPEED_PARAM_HIGH &&
dwc2_get_param_phy_type(hsotg) == DWC2_PHY_TYPE_PARAM_FS)
valid = 0;
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for speed parameter. Check HW configuration.\n",
val);
val = dwc2_get_param_phy_type(hsotg) == DWC2_PHY_TYPE_PARAM_FS ?
DWC2_SPEED_PARAM_FULL : DWC2_SPEED_PARAM_HIGH;
dev_dbg(hsotg->dev, "Setting speed to %d\n", val);
}
hsotg->core_params->speed = val;
}
void dwc2_set_param_host_ls_low_power_phy_clk(struct dwc2_hsotg *hsotg, int val)
{
int valid = 1;
if (DWC2_OUT_OF_BOUNDS(val, DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ,
DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)) {
if (val >= 0) {
dev_err(hsotg->dev,
"Wrong value for host_ls_low_power_phy_clk parameter\n");
dev_err(hsotg->dev,
"host_ls_low_power_phy_clk must be 0 or 1\n");
}
valid = 0;
}
if (val == DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ &&
dwc2_get_param_phy_type(hsotg) == DWC2_PHY_TYPE_PARAM_FS)
valid = 0;
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n",
val);
val = dwc2_get_param_phy_type(hsotg) == DWC2_PHY_TYPE_PARAM_FS
? DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ
: DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ;
dev_dbg(hsotg->dev, "Setting host_ls_low_power_phy_clk to %d\n",
val);
}
hsotg->core_params->host_ls_low_power_phy_clk = val;
}
void dwc2_set_param_phy_ulpi_ddr(struct dwc2_hsotg *hsotg, int val)
{
if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) {
if (val >= 0) {
dev_err(hsotg->dev, "Wrong value for phy_ulpi_ddr\n");
dev_err(hsotg->dev, "phy_upli_ddr must be 0 or 1\n");
}
val = 0;
dev_dbg(hsotg->dev, "Setting phy_upli_ddr to %d\n", val);
}
hsotg->core_params->phy_ulpi_ddr = val;
}
void dwc2_set_param_phy_ulpi_ext_vbus(struct dwc2_hsotg *hsotg, int val)
{
if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) {
if (val >= 0) {
dev_err(hsotg->dev,
"Wrong value for phy_ulpi_ext_vbus\n");
dev_err(hsotg->dev,
"phy_ulpi_ext_vbus must be 0 or 1\n");
}
val = 0;
dev_dbg(hsotg->dev, "Setting phy_ulpi_ext_vbus to %d\n", val);
}
hsotg->core_params->phy_ulpi_ext_vbus = val;
}
void dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg, int val)
{
int valid = 0;
switch (hsotg->hw_params.utmi_phy_data_width) {
case GHWCFG4_UTMI_PHY_DATA_WIDTH_8:
valid = (val == 8);
break;
case GHWCFG4_UTMI_PHY_DATA_WIDTH_16:
valid = (val == 16);
break;
case GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16:
valid = (val == 8 || val == 16);
break;
}
if (!valid) {
if (val >= 0) {
dev_err(hsotg->dev,
"%d invalid for phy_utmi_width. Check HW configuration.\n",
val);
}
val = (hsotg->hw_params.utmi_phy_data_width ==
GHWCFG4_UTMI_PHY_DATA_WIDTH_8) ? 8 : 16;
dev_dbg(hsotg->dev, "Setting phy_utmi_width to %d\n", val);
}
hsotg->core_params->phy_utmi_width = val;
}
void dwc2_set_param_ulpi_fs_ls(struct dwc2_hsotg *hsotg, int val)
{
if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) {
if (val >= 0) {
dev_err(hsotg->dev, "Wrong value for ulpi_fs_ls\n");
dev_err(hsotg->dev, "ulpi_fs_ls must be 0 or 1\n");
}
val = 0;
dev_dbg(hsotg->dev, "Setting ulpi_fs_ls to %d\n", val);
}
hsotg->core_params->ulpi_fs_ls = val;
}
void dwc2_set_param_ts_dline(struct dwc2_hsotg *hsotg, int val)
{
if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) {
if (val >= 0) {
dev_err(hsotg->dev, "Wrong value for ts_dline\n");
dev_err(hsotg->dev, "ts_dline must be 0 or 1\n");
}
val = 0;
dev_dbg(hsotg->dev, "Setting ts_dline to %d\n", val);
}
hsotg->core_params->ts_dline = val;
}
void dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val)
{
int valid = 1;
if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) {
if (val >= 0) {
dev_err(hsotg->dev, "Wrong value for i2c_enable\n");
dev_err(hsotg->dev, "i2c_enable must be 0 or 1\n");
}
valid = 0;
}
if (val == 1 && !(hsotg->hw_params.i2c_enable))
valid = 0;
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for i2c_enable. Check HW configuration.\n",
val);
val = hsotg->hw_params.i2c_enable;
dev_dbg(hsotg->dev, "Setting i2c_enable to %d\n", val);
}
hsotg->core_params->i2c_enable = val;
}
void dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, int val)
{
int valid = 1;
if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) {
if (val >= 0) {
dev_err(hsotg->dev,
"Wrong value for en_multiple_tx_fifo,\n");
dev_err(hsotg->dev,
"en_multiple_tx_fifo must be 0 or 1\n");
}
valid = 0;
}
if (val == 1 && !hsotg->hw_params.en_multiple_tx_fifo)
valid = 0;
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n",
val);
val = hsotg->hw_params.en_multiple_tx_fifo;
dev_dbg(hsotg->dev, "Setting en_multiple_tx_fifo to %d\n", val);
}
hsotg->core_params->en_multiple_tx_fifo = val;
}
void dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val)
{
int valid = 1;
if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) {
if (val >= 0) {
dev_err(hsotg->dev,
"'%d' invalid for parameter reload_ctl\n", val);
dev_err(hsotg->dev, "reload_ctl must be 0 or 1\n");
}
valid = 0;
}
if (val == 1 && hsotg->hw_params.snpsid < DWC2_CORE_REV_2_92a)
valid = 0;
if (!valid) {
if (val >= 0)
dev_err(hsotg->dev,
"%d invalid for parameter reload_ctl. Check HW configuration.\n",
val);
val = hsotg->hw_params.snpsid >= DWC2_CORE_REV_2_92a;
dev_dbg(hsotg->dev, "Setting reload_ctl to %d\n", val);
}
hsotg->core_params->reload_ctl = val;
}
void dwc2_set_param_ahbcfg(struct dwc2_hsotg *hsotg, int val)
{
if (val != -1)
hsotg->core_params->ahbcfg = val;
else
hsotg->core_params->ahbcfg = GAHBCFG_HBSTLEN_INCR4 <<
GAHBCFG_HBSTLEN_SHIFT;
}
void dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val)
{
if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) {
if (val >= 0) {
dev_err(hsotg->dev,
"'%d' invalid for parameter otg_ver\n", val);
dev_err(hsotg->dev,
"otg_ver must be 0 (for OTG 1.3 support) or 1 (for OTG 2.0 support)\n");
}
val = 0;
dev_dbg(hsotg->dev, "Setting otg_ver to %d\n", val);
}
hsotg->core_params->otg_ver = val;
}
static void dwc2_set_param_uframe_sched(struct dwc2_hsotg *hsotg, int val)
{
if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) {
if (val >= 0) {
dev_err(hsotg->dev,
"'%d' invalid for parameter uframe_sched\n",
val);
dev_err(hsotg->dev, "uframe_sched must be 0 or 1\n");
}
val = 1;
dev_dbg(hsotg->dev, "Setting uframe_sched to %d\n", val);
}
hsotg->core_params->uframe_sched = val;
}
static void dwc2_set_param_external_id_pin_ctl(struct dwc2_hsotg *hsotg,
int val)
{
if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) {
if (val >= 0) {
dev_err(hsotg->dev,
"'%d' invalid for parameter external_id_pin_ctl\n",
val);
dev_err(hsotg->dev, "external_id_pin_ctl must be 0 or 1\n");
}
val = 0;
dev_dbg(hsotg->dev, "Setting external_id_pin_ctl to %d\n", val);
}
hsotg->core_params->external_id_pin_ctl = val;
}
static void dwc2_set_param_hibernation(struct dwc2_hsotg *hsotg,
int val)
{
if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) {
if (val >= 0) {
dev_err(hsotg->dev,
"'%d' invalid for parameter hibernation\n",
val);
dev_err(hsotg->dev, "hibernation must be 0 or 1\n");
}
val = 0;
dev_dbg(hsotg->dev, "Setting hibernation to %d\n", val);
}
hsotg->core_params->hibernation = val;
}
/*
* This function is called during module intialization to pass module parameters
* for the DWC_otg core.
*/
void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
const struct dwc2_core_params *params)
{
dev_dbg(hsotg->dev, "%s()\n", __func__);
dwc2_set_param_otg_cap(hsotg, params->otg_cap);
dwc2_set_param_dma_enable(hsotg, params->dma_enable);
dwc2_set_param_dma_desc_enable(hsotg, params->dma_desc_enable);
dwc2_set_param_dma_desc_fs_enable(hsotg, params->dma_desc_fs_enable);
dwc2_set_param_host_support_fs_ls_low_power(hsotg,
params->host_support_fs_ls_low_power);
dwc2_set_param_enable_dynamic_fifo(hsotg,
params->enable_dynamic_fifo);
dwc2_set_param_host_rx_fifo_size(hsotg,
params->host_rx_fifo_size);
dwc2_set_param_host_nperio_tx_fifo_size(hsotg,
params->host_nperio_tx_fifo_size);
dwc2_set_param_host_perio_tx_fifo_size(hsotg,
params->host_perio_tx_fifo_size);
dwc2_set_param_max_transfer_size(hsotg,
params->max_transfer_size);
dwc2_set_param_max_packet_count(hsotg,
params->max_packet_count);
dwc2_set_param_host_channels(hsotg, params->host_channels);
dwc2_set_param_phy_type(hsotg, params->phy_type);
dwc2_set_param_speed(hsotg, params->speed);
dwc2_set_param_host_ls_low_power_phy_clk(hsotg,
params->host_ls_low_power_phy_clk);
dwc2_set_param_phy_ulpi_ddr(hsotg, params->phy_ulpi_ddr);
dwc2_set_param_phy_ulpi_ext_vbus(hsotg,
params->phy_ulpi_ext_vbus);
dwc2_set_param_phy_utmi_width(hsotg, params->phy_utmi_width);
dwc2_set_param_ulpi_fs_ls(hsotg, params->ulpi_fs_ls);
dwc2_set_param_ts_dline(hsotg, params->ts_dline);
dwc2_set_param_i2c_enable(hsotg, params->i2c_enable);
dwc2_set_param_en_multiple_tx_fifo(hsotg,
params->en_multiple_tx_fifo);
dwc2_set_param_reload_ctl(hsotg, params->reload_ctl);
dwc2_set_param_ahbcfg(hsotg, params->ahbcfg);
dwc2_set_param_otg_ver(hsotg, params->otg_ver);
dwc2_set_param_uframe_sched(hsotg, params->uframe_sched);
dwc2_set_param_external_id_pin_ctl(hsotg, params->external_id_pin_ctl);
dwc2_set_param_hibernation(hsotg, params->hibernation);
}
/* /*
* Forces either host or device mode if the controller is not * Forces either host or device mode if the controller is not
* currently in that mode. * currently in that mode.
* *
* Returns true if the mode was forced. * Returns true if the mode was forced.
*/ */
static bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host) bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host)
{ {
if (host && dwc2_is_host_mode(hsotg)) if (host && dwc2_is_host_mode(hsotg))
return false; return false;
@@ -1442,232 +751,9 @@ static bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host)
return dwc2_force_mode(hsotg, host); return dwc2_force_mode(hsotg, host);
} }
/*
* Gets host hardware parameters. Forces host mode if not currently in
* host mode. Should be called immediately after a core soft reset in
* order to get the reset values.
*/
static void dwc2_get_host_hwparams(struct dwc2_hsotg *hsotg)
{
struct dwc2_hw_params *hw = &hsotg->hw_params;
u32 gnptxfsiz;
u32 hptxfsiz;
bool forced;
if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
return;
forced = dwc2_force_mode_if_needed(hsotg, true);
gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ);
dev_dbg(hsotg->dev, "gnptxfsiz=%08x\n", gnptxfsiz);
dev_dbg(hsotg->dev, "hptxfsiz=%08x\n", hptxfsiz);
if (forced)
dwc2_clear_force_mode(hsotg);
hw->host_nperio_tx_fifo_size = (gnptxfsiz & FIFOSIZE_DEPTH_MASK) >>
FIFOSIZE_DEPTH_SHIFT;
hw->host_perio_tx_fifo_size = (hptxfsiz & FIFOSIZE_DEPTH_MASK) >>
FIFOSIZE_DEPTH_SHIFT;
}
/*
* Gets device hardware parameters. Forces device mode if not
* currently in device mode. Should be called immediately after a core
* soft reset in order to get the reset values.
*/
static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg)
{
struct dwc2_hw_params *hw = &hsotg->hw_params;
bool forced;
u32 gnptxfsiz;
if (hsotg->dr_mode == USB_DR_MODE_HOST)
return;
forced = dwc2_force_mode_if_needed(hsotg, false);
gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
dev_dbg(hsotg->dev, "gnptxfsiz=%08x\n", gnptxfsiz);
if (forced)
dwc2_clear_force_mode(hsotg);
hw->dev_nperio_tx_fifo_size = (gnptxfsiz & FIFOSIZE_DEPTH_MASK) >>
FIFOSIZE_DEPTH_SHIFT;
}
/**
* During device initialization, read various hardware configuration
* registers and interpret the contents.
*/
int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
{
struct dwc2_hw_params *hw = &hsotg->hw_params;
unsigned width;
u32 hwcfg1, hwcfg2, hwcfg3, hwcfg4;
u32 grxfsiz;
/*
* Attempt to ensure this device is really a DWC_otg Controller.
* Read and verify the GSNPSID register contents. The value should be
* 0x45f42xxx or 0x45f43xxx, which corresponds to either "OT2" or "OT3",
* as in "OTG version 2.xx" or "OTG version 3.xx".
*/
hw->snpsid = dwc2_readl(hsotg->regs + GSNPSID);
if ((hw->snpsid & 0xfffff000) != 0x4f542000 &&
(hw->snpsid & 0xfffff000) != 0x4f543000) {
dev_err(hsotg->dev, "Bad value for GSNPSID: 0x%08x\n",
hw->snpsid);
return -ENODEV;
}
dev_dbg(hsotg->dev, "Core Release: %1x.%1x%1x%1x (snpsid=%x)\n",
hw->snpsid >> 12 & 0xf, hw->snpsid >> 8 & 0xf,
hw->snpsid >> 4 & 0xf, hw->snpsid & 0xf, hw->snpsid);
hwcfg1 = dwc2_readl(hsotg->regs + GHWCFG1);
hwcfg2 = dwc2_readl(hsotg->regs + GHWCFG2);
hwcfg3 = dwc2_readl(hsotg->regs + GHWCFG3);
hwcfg4 = dwc2_readl(hsotg->regs + GHWCFG4);
grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ);
dev_dbg(hsotg->dev, "hwcfg1=%08x\n", hwcfg1);
dev_dbg(hsotg->dev, "hwcfg2=%08x\n", hwcfg2);
dev_dbg(hsotg->dev, "hwcfg3=%08x\n", hwcfg3);
dev_dbg(hsotg->dev, "hwcfg4=%08x\n", hwcfg4);
dev_dbg(hsotg->dev, "grxfsiz=%08x\n", grxfsiz);
/*
* Host specific hardware parameters. Reading these parameters
* requires the controller to be in host mode. The mode will
* be forced, if necessary, to read these values.
*/
dwc2_get_host_hwparams(hsotg);
dwc2_get_dev_hwparams(hsotg);
/* hwcfg1 */
hw->dev_ep_dirs = hwcfg1;
/* hwcfg2 */
hw->op_mode = (hwcfg2 & GHWCFG2_OP_MODE_MASK) >>
GHWCFG2_OP_MODE_SHIFT;
hw->arch = (hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) >>
GHWCFG2_ARCHITECTURE_SHIFT;
hw->enable_dynamic_fifo = !!(hwcfg2 & GHWCFG2_DYNAMIC_FIFO);
hw->host_channels = 1 + ((hwcfg2 & GHWCFG2_NUM_HOST_CHAN_MASK) >>
GHWCFG2_NUM_HOST_CHAN_SHIFT);
hw->hs_phy_type = (hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK) >>
GHWCFG2_HS_PHY_TYPE_SHIFT;
hw->fs_phy_type = (hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) >>
GHWCFG2_FS_PHY_TYPE_SHIFT;
hw->num_dev_ep = (hwcfg2 & GHWCFG2_NUM_DEV_EP_MASK) >>
GHWCFG2_NUM_DEV_EP_SHIFT;
hw->nperio_tx_q_depth =
(hwcfg2 & GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK) >>
GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT << 1;
hw->host_perio_tx_q_depth =
(hwcfg2 & GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK) >>
GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT << 1;
hw->dev_token_q_depth =
(hwcfg2 & GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK) >>
GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT;
/* hwcfg3 */
width = (hwcfg3 & GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK) >>
GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT;
hw->max_transfer_size = (1 << (width + 11)) - 1;
width = (hwcfg3 & GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK) >>
GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT;
hw->max_packet_count = (1 << (width + 4)) - 1;
hw->i2c_enable = !!(hwcfg3 & GHWCFG3_I2C);
hw->total_fifo_size = (hwcfg3 & GHWCFG3_DFIFO_DEPTH_MASK) >>
GHWCFG3_DFIFO_DEPTH_SHIFT;
/* hwcfg4 */
hw->en_multiple_tx_fifo = !!(hwcfg4 & GHWCFG4_DED_FIFO_EN);
hw->num_dev_perio_in_ep = (hwcfg4 & GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK) >>
GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT;
hw->dma_desc_enable = !!(hwcfg4 & GHWCFG4_DESC_DMA);
hw->power_optimized = !!(hwcfg4 & GHWCFG4_POWER_OPTIMIZ);
hw->utmi_phy_data_width = (hwcfg4 & GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK) >>
GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT;
/* fifo sizes */
hw->host_rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >>
GRXFSIZ_DEPTH_SHIFT;
dev_dbg(hsotg->dev, "Detected values from hardware:\n");
dev_dbg(hsotg->dev, " op_mode=%d\n",
hw->op_mode);
dev_dbg(hsotg->dev, " arch=%d\n",
hw->arch);
dev_dbg(hsotg->dev, " dma_desc_enable=%d\n",
hw->dma_desc_enable);
dev_dbg(hsotg->dev, " power_optimized=%d\n",
hw->power_optimized);
dev_dbg(hsotg->dev, " i2c_enable=%d\n",
hw->i2c_enable);
dev_dbg(hsotg->dev, " hs_phy_type=%d\n",
hw->hs_phy_type);
dev_dbg(hsotg->dev, " fs_phy_type=%d\n",
hw->fs_phy_type);
dev_dbg(hsotg->dev, " utmi_phy_data_width=%d\n",
hw->utmi_phy_data_width);
dev_dbg(hsotg->dev, " num_dev_ep=%d\n",
hw->num_dev_ep);
dev_dbg(hsotg->dev, " num_dev_perio_in_ep=%d\n",
hw->num_dev_perio_in_ep);
dev_dbg(hsotg->dev, " host_channels=%d\n",
hw->host_channels);
dev_dbg(hsotg->dev, " max_transfer_size=%d\n",
hw->max_transfer_size);
dev_dbg(hsotg->dev, " max_packet_count=%d\n",
hw->max_packet_count);
dev_dbg(hsotg->dev, " nperio_tx_q_depth=0x%0x\n",
hw->nperio_tx_q_depth);
dev_dbg(hsotg->dev, " host_perio_tx_q_depth=0x%0x\n",
hw->host_perio_tx_q_depth);
dev_dbg(hsotg->dev, " dev_token_q_depth=0x%0x\n",
hw->dev_token_q_depth);
dev_dbg(hsotg->dev, " enable_dynamic_fifo=%d\n",
hw->enable_dynamic_fifo);
dev_dbg(hsotg->dev, " en_multiple_tx_fifo=%d\n",
hw->en_multiple_tx_fifo);
dev_dbg(hsotg->dev, " total_fifo_size=%d\n",
hw->total_fifo_size);
dev_dbg(hsotg->dev, " host_rx_fifo_size=%d\n",
hw->host_rx_fifo_size);
dev_dbg(hsotg->dev, " host_nperio_tx_fifo_size=%d\n",
hw->host_nperio_tx_fifo_size);
dev_dbg(hsotg->dev, " host_perio_tx_fifo_size=%d\n",
hw->host_perio_tx_fifo_size);
dev_dbg(hsotg->dev, "\n");
return 0;
}
/*
* Sets all parameters to the given value.
*
* Assumes that the dwc2_core_params struct contains only integers.
*/
void dwc2_set_all_params(struct dwc2_core_params *params, int value)
{
int *p = (int *)params;
size_t size = sizeof(*params) / sizeof(*p);
int i;
for (i = 0; i < size; i++)
p[i] = value;
}
u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg) u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg)
{ {
return hsotg->core_params->otg_ver == 1 ? 0x0200 : 0x0103; return hsotg->params.otg_ver == 1 ? 0x0200 : 0x0103;
} }
bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg) bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg)

View File

@@ -172,6 +172,11 @@ struct dwc2_hsotg_req;
* @periodic: Set if this is a periodic ep, such as Interrupt * @periodic: Set if this is a periodic ep, such as Interrupt
* @isochronous: Set if this is a isochronous ep * @isochronous: Set if this is a isochronous ep
* @send_zlp: Set if we need to send a zero-length packet. * @send_zlp: Set if we need to send a zero-length packet.
* @desc_list_dma: The DMA address of descriptor chain currently in use.
* @desc_list: Pointer to descriptor DMA chain head currently in use.
* @desc_count: Count of entries within the DMA descriptor chain of EP.
* @isoc_chain_num: Number of ISOC chain currently in use - either 0 or 1.
* @next_desc: index of next free descriptor in the ISOC chain under SW control.
* @total_data: The total number of data bytes done. * @total_data: The total number of data bytes done.
* @fifo_size: The size of the FIFO (for periodic IN endpoints) * @fifo_size: The size of the FIFO (for periodic IN endpoints)
* @fifo_load: The amount of data loaded into the FIFO (periodic IN) * @fifo_load: The amount of data loaded into the FIFO (periodic IN)
@@ -219,6 +224,13 @@ struct dwc2_hsotg_ep {
#define TARGET_FRAME_INITIAL 0xFFFFFFFF #define TARGET_FRAME_INITIAL 0xFFFFFFFF
bool frame_overrun; bool frame_overrun;
dma_addr_t desc_list_dma;
struct dwc2_dma_desc *desc_list;
u8 desc_count;
unsigned char isoc_chain_num;
unsigned int next_desc;
char name[10]; char name[10];
}; };
@@ -286,7 +298,7 @@ enum dwc2_ep0_state {
* @otg_ver: OTG version supported * @otg_ver: OTG version supported
* 0 - 1.3 (default) * 0 - 1.3 (default)
* 1 - 2.0 * 1 - 2.0
* @dma_enable: Specifies whether to use slave or DMA mode for accessing * @host_dma: Specifies whether to use slave or DMA mode for accessing
* the data FIFOs. The driver will automatically detect the * the data FIFOs. The driver will automatically detect the
* value for this parameter if none is specified. * value for this parameter if none is specified.
* 0 - Slave (always available) * 0 - Slave (always available)
@@ -314,7 +326,8 @@ enum dwc2_ep0_state {
* @enable_dynamic_fifo: 0 - Use coreConsultant-specified FIFO size parameters * @enable_dynamic_fifo: 0 - Use coreConsultant-specified FIFO size parameters
* 1 - Allow dynamic FIFO sizing (default, if available) * 1 - Allow dynamic FIFO sizing (default, if available)
* @en_multiple_tx_fifo: Specifies whether dedicated per-endpoint transmit FIFOs * @en_multiple_tx_fifo: Specifies whether dedicated per-endpoint transmit FIFOs
* are enabled * are enabled for non-periodic IN endpoints in device
* mode.
* @host_rx_fifo_size: Number of 4-byte words in the Rx FIFO in host mode when * @host_rx_fifo_size: Number of 4-byte words in the Rx FIFO in host mode when
* dynamic FIFO sizing is enabled * dynamic FIFO sizing is enabled
* 16 to 32768 * 16 to 32768
@@ -417,6 +430,20 @@ enum dwc2_ep0_state {
* needed. * needed.
* 0 - No (default) * 0 - No (default)
* 1 - Yes * 1 - Yes
* @g_dma: Enables gadget dma usage (default: autodetect).
* @g_dma_desc: Enables gadget descriptor DMA (default: autodetect).
* @g_rx_fifo_size: The periodic rx fifo size for the device, in
* DWORDS from 16-32768 (default: 2048 if
* possible, otherwise autodetect).
* @g_np_tx_fifo_size: The non-periodic tx fifo size for the device in
* DWORDS from 16-32768 (default: 1024 if
* possible, otherwise autodetect).
* @g_tx_fifo_size: An array of TX fifo sizes in dedicated fifo
* mode. Each value corresponds to one EP
* starting from EP1 (max 15 values). Sizes are
* in DWORDS with possible values from from
* 16-32768 (default: 256, 256, 256, 256, 768,
* 768, 768, 768, 0, 0, 0, 0, 0, 0, 0).
* *
* The following parameters may be specified when starting the module. These * The following parameters may be specified when starting the module. These
* parameters define how the DWC_otg controller should be configured. A * parameters define how the DWC_otg controller should be configured. A
@@ -430,11 +457,18 @@ struct dwc2_core_params {
* dwc2_set_all_params! * dwc2_set_all_params!
*/ */
int otg_cap; int otg_cap;
#define DWC2_CAP_PARAM_HNP_SRP_CAPABLE 0
#define DWC2_CAP_PARAM_SRP_ONLY_CAPABLE 1
#define DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE 2
int otg_ver; int otg_ver;
int dma_enable;
int dma_desc_enable; int dma_desc_enable;
int dma_desc_fs_enable; int dma_desc_fs_enable;
int speed; int speed;
#define DWC2_SPEED_PARAM_HIGH 0
#define DWC2_SPEED_PARAM_FULL 1
#define DWC2_SPEED_PARAM_LOW 2
int enable_dynamic_fifo; int enable_dynamic_fifo;
int en_multiple_tx_fifo; int en_multiple_tx_fifo;
int host_rx_fifo_size; int host_rx_fifo_size;
@@ -444,19 +478,44 @@ struct dwc2_core_params {
int max_packet_count; int max_packet_count;
int host_channels; int host_channels;
int phy_type; int phy_type;
#define DWC2_PHY_TYPE_PARAM_FS 0
#define DWC2_PHY_TYPE_PARAM_UTMI 1
#define DWC2_PHY_TYPE_PARAM_ULPI 2
int phy_utmi_width; int phy_utmi_width;
int phy_ulpi_ddr; int phy_ulpi_ddr;
int phy_ulpi_ext_vbus; int phy_ulpi_ext_vbus;
#define DWC2_PHY_ULPI_INTERNAL_VBUS 0
#define DWC2_PHY_ULPI_EXTERNAL_VBUS 1
int i2c_enable; int i2c_enable;
int ulpi_fs_ls; int ulpi_fs_ls;
int host_support_fs_ls_low_power; int host_support_fs_ls_low_power;
int host_ls_low_power_phy_clk; int host_ls_low_power_phy_clk;
#define DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0
#define DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1
int ts_dline; int ts_dline;
int reload_ctl; int reload_ctl;
int ahbcfg; int ahbcfg;
int uframe_sched; int uframe_sched;
int external_id_pin_ctl; int external_id_pin_ctl;
int hibernation; int hibernation;
/*
* The following parameters are *only* set via device
* properties and cannot be set directly in this structure.
*/
/* Host parameters */
bool host_dma;
/* Gadget parameters */
bool g_dma;
bool g_dma_desc;
u16 g_rx_fifo_size;
u16 g_np_tx_fifo_size;
u32 g_tx_fifo_size[MAX_EPS_CHANNELS];
}; };
/** /**
@@ -516,10 +575,9 @@ struct dwc2_hw_params {
unsigned op_mode:3; unsigned op_mode:3;
unsigned arch:2; unsigned arch:2;
unsigned dma_desc_enable:1; unsigned dma_desc_enable:1;
unsigned dma_desc_fs_enable:1;
unsigned enable_dynamic_fifo:1; unsigned enable_dynamic_fifo:1;
unsigned en_multiple_tx_fifo:1; unsigned en_multiple_tx_fifo:1;
unsigned host_rx_fifo_size:16; unsigned rx_fifo_size:16;
unsigned host_nperio_tx_fifo_size:16; unsigned host_nperio_tx_fifo_size:16;
unsigned dev_nperio_tx_fifo_size:16; unsigned dev_nperio_tx_fifo_size:16;
unsigned host_perio_tx_fifo_size:16; unsigned host_perio_tx_fifo_size:16;
@@ -839,11 +897,13 @@ struct dwc2_hregs_backup {
* @ctrl_req: Request for EP0 control packets. * @ctrl_req: Request for EP0 control packets.
* @ep0_state: EP0 control transfers state * @ep0_state: EP0 control transfers state
* @test_mode: USB test mode requested by the host * @test_mode: USB test mode requested by the host
* @setup_desc_dma: EP0 setup stage desc chain DMA address
* @setup_desc: EP0 setup stage desc chain pointer
* @ctrl_in_desc_dma: EP0 IN data phase desc chain DMA address
* @ctrl_in_desc: EP0 IN data phase desc chain pointer
* @ctrl_out_desc_dma: EP0 OUT data phase desc chain DMA address
* @ctrl_out_desc: EP0 OUT data phase desc chain pointer
* @eps: The endpoints being supplied to the gadget framework * @eps: The endpoints being supplied to the gadget framework
* @g_using_dma: Indicate if dma usage is enabled
* @g_rx_fifo_sz: Contains rx fifo size value
* @g_np_g_tx_fifo_sz: Contains Non-Periodic tx fifo size value
* @g_tx_fifo_sz: Contains tx fifo size value per endpoints
*/ */
struct dwc2_hsotg { struct dwc2_hsotg {
struct device *dev; struct device *dev;
@@ -851,7 +911,7 @@ struct dwc2_hsotg {
/** Params detected from hardware */ /** Params detected from hardware */
struct dwc2_hw_params hw_params; struct dwc2_hw_params hw_params;
/** Params to actually use */ /** Params to actually use */
struct dwc2_core_params *core_params; struct dwc2_core_params params;
enum usb_otg_state op_state; enum usb_otg_state op_state;
enum usb_dr_mode dr_mode; enum usb_dr_mode dr_mode;
unsigned int hcd_enabled:1; unsigned int hcd_enabled:1;
@@ -891,6 +951,8 @@ struct dwc2_hsotg {
#define DWC2_CORE_REV_2_94a 0x4f54294a #define DWC2_CORE_REV_2_94a 0x4f54294a
#define DWC2_CORE_REV_3_00a 0x4f54300a #define DWC2_CORE_REV_3_00a 0x4f54300a
#define DWC2_CORE_REV_3_10a 0x4f54310a #define DWC2_CORE_REV_3_10a 0x4f54310a
#define DWC2_FS_IOT_REV_1_00a 0x5531100a
#define DWC2_HS_IOT_REV_1_00a 0x5532100a
#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) #if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
union dwc2_hcd_internal_flags { union dwc2_hcd_internal_flags {
@@ -986,15 +1048,18 @@ struct dwc2_hsotg {
enum dwc2_ep0_state ep0_state; enum dwc2_ep0_state ep0_state;
u8 test_mode; u8 test_mode;
dma_addr_t setup_desc_dma[2];
struct dwc2_dma_desc *setup_desc[2];
dma_addr_t ctrl_in_desc_dma;
struct dwc2_dma_desc *ctrl_in_desc;
dma_addr_t ctrl_out_desc_dma;
struct dwc2_dma_desc *ctrl_out_desc;
struct usb_gadget gadget; struct usb_gadget gadget;
unsigned int enabled:1; unsigned int enabled:1;
unsigned int connected:1; unsigned int connected:1;
struct dwc2_hsotg_ep *eps_in[MAX_EPS_CHANNELS]; struct dwc2_hsotg_ep *eps_in[MAX_EPS_CHANNELS];
struct dwc2_hsotg_ep *eps_out[MAX_EPS_CHANNELS]; struct dwc2_hsotg_ep *eps_out[MAX_EPS_CHANNELS];
u32 g_using_dma;
u32 g_rx_fifo_sz;
u32 g_np_g_tx_fifo_sz;
u32 g_tx_fifo_sz[MAX_EPS_CHANNELS];
#endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */ #endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
}; };
@@ -1016,6 +1081,22 @@ enum dwc2_halt_status {
DWC2_HC_XFER_URB_DEQUEUE, DWC2_HC_XFER_URB_DEQUEUE,
}; };
/* Core version information */
static inline bool dwc2_is_iot(struct dwc2_hsotg *hsotg)
{
return (hsotg->hw_params.snpsid & 0xfff00000) == 0x55300000;
}
static inline bool dwc2_is_fs_iot(struct dwc2_hsotg *hsotg)
{
return (hsotg->hw_params.snpsid & 0xffff0000) == 0x55310000;
}
static inline bool dwc2_is_hs_iot(struct dwc2_hsotg *hsotg)
{
return (hsotg->hw_params.snpsid & 0xffff0000) == 0x55320000;
}
/* /*
* The following functions support initialization of the core driver component * The following functions support initialization of the core driver component
* and the DWC_otg controller * and the DWC_otg controller
@@ -1025,6 +1106,8 @@ extern int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg);
extern int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg); extern int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg);
extern int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore); extern int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore);
bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host);
void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg);
void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg); void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg);
extern bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg); extern bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg);
@@ -1044,217 +1127,16 @@ extern void dwc2_disable_global_interrupts(struct dwc2_hsotg *hcd);
/* This function should be called on every hardware interrupt. */ /* This function should be called on every hardware interrupt. */
extern irqreturn_t dwc2_handle_common_intr(int irq, void *dev); extern irqreturn_t dwc2_handle_common_intr(int irq, void *dev);
/* OTG Core Parameters */ /* The device ID match table */
extern const struct of_device_id dwc2_of_match_table[];
/*
* Specifies the OTG capabilities. The driver will automatically
* detect the value for this parameter if none is specified.
* 0 - HNP and SRP capable (default)
* 1 - SRP Only capable
* 2 - No HNP/SRP capable
*/
extern void dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val);
#define DWC2_CAP_PARAM_HNP_SRP_CAPABLE 0
#define DWC2_CAP_PARAM_SRP_ONLY_CAPABLE 1
#define DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE 2
/*
* Specifies whether to use slave or DMA mode for accessing the data
* FIFOs. The driver will automatically detect the value for this
* parameter if none is specified.
* 0 - Slave
* 1 - DMA (default, if available)
*/
extern void dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val);
/*
* When DMA mode is enabled specifies whether to use
* address DMA or DMA Descritor mode for accessing the data
* FIFOs in device mode. The driver will automatically detect
* the value for this parameter if none is specified.
* 0 - address DMA
* 1 - DMA Descriptor(default, if available)
*/
extern void dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val);
/*
* When DMA mode is enabled specifies whether to use
* address DMA or DMA Descritor mode with full speed devices
* for accessing the data FIFOs in host mode.
* 0 - address DMA
* 1 - FS DMA Descriptor(default, if available)
*/
extern void dwc2_set_param_dma_desc_fs_enable(struct dwc2_hsotg *hsotg,
int val);
/*
* Specifies the maximum speed of operation in host and device mode.
* The actual speed depends on the speed of the attached device and
* the value of phy_type. The actual speed depends on the speed of the
* attached device.
* 0 - High Speed (default)
* 1 - Full Speed
*/
extern void dwc2_set_param_speed(struct dwc2_hsotg *hsotg, int val);
#define DWC2_SPEED_PARAM_HIGH 0
#define DWC2_SPEED_PARAM_FULL 1
/*
* Specifies whether low power mode is supported when attached
* to a Full Speed or Low Speed device in host mode.
*
* 0 - Don't support low power mode (default)
* 1 - Support low power mode
*/
extern void dwc2_set_param_host_support_fs_ls_low_power(
struct dwc2_hsotg *hsotg, int val);
/*
* Specifies the PHY clock rate in low power mode when connected to a
* Low Speed device in host mode. This parameter is applicable only if
* HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
* then defaults to 6 MHZ otherwise 48 MHZ.
*
* 0 - 48 MHz
* 1 - 6 MHz
*/
extern void dwc2_set_param_host_ls_low_power_phy_clk(struct dwc2_hsotg *hsotg,
int val);
#define DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0
#define DWC2_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1
/*
* 0 - Use cC FIFO size parameters
* 1 - Allow dynamic FIFO sizing (default)
*/
extern void dwc2_set_param_enable_dynamic_fifo(struct dwc2_hsotg *hsotg,
int val);
/*
* Number of 4-byte words in the Rx FIFO in host mode when dynamic
* FIFO sizing is enabled.
* 16 to 32768 (default 1024)
*/
extern void dwc2_set_param_host_rx_fifo_size(struct dwc2_hsotg *hsotg, int val);
/*
* Number of 4-byte words in the non-periodic Tx FIFO in host mode
* when Dynamic FIFO sizing is enabled in the core.
* 16 to 32768 (default 256)
*/
extern void dwc2_set_param_host_nperio_tx_fifo_size(struct dwc2_hsotg *hsotg,
int val);
/*
* Number of 4-byte words in the host periodic Tx FIFO when dynamic
* FIFO sizing is enabled.
* 16 to 32768 (default 256)
*/
extern void dwc2_set_param_host_perio_tx_fifo_size(struct dwc2_hsotg *hsotg,
int val);
/*
* The maximum transfer size supported in bytes.
* 2047 to 65,535 (default 65,535)
*/
extern void dwc2_set_param_max_transfer_size(struct dwc2_hsotg *hsotg, int val);
/*
* The maximum number of packets in a transfer.
* 15 to 511 (default 511)
*/
extern void dwc2_set_param_max_packet_count(struct dwc2_hsotg *hsotg, int val);
/*
* The number of host channel registers to use.
* 1 to 16 (default 11)
* Note: The FPGA configuration supports a maximum of 11 host channels.
*/
extern void dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val);
/*
* Specifies the type of PHY interface to use. By default, the driver
* will automatically detect the phy_type.
*
* 0 - Full Speed PHY
* 1 - UTMI+ (default)
* 2 - ULPI
*/
extern void dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val);
#define DWC2_PHY_TYPE_PARAM_FS 0
#define DWC2_PHY_TYPE_PARAM_UTMI 1
#define DWC2_PHY_TYPE_PARAM_ULPI 2
/*
* Specifies the UTMI+ Data Width. This parameter is
* applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
* PHY_TYPE, this parameter indicates the data width between
* the MAC and the ULPI Wrapper.) Also, this parameter is
* applicable only if the OTG_HSPHY_WIDTH cC parameter was set
* to "8 and 16 bits", meaning that the core has been
* configured to work at either data path width.
*
* 8 or 16 bits (default 16)
*/
extern void dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg, int val);
/*
* Specifies whether the ULPI operates at double or single
* data rate. This parameter is only applicable if PHY_TYPE is
* ULPI.
*
* 0 - single data rate ULPI interface with 8 bit wide data
* bus (default)
* 1 - double data rate ULPI interface with 4 bit wide data
* bus
*/
extern void dwc2_set_param_phy_ulpi_ddr(struct dwc2_hsotg *hsotg, int val);
/*
* Specifies whether to use the internal or external supply to
* drive the vbus with a ULPI phy.
*/
extern void dwc2_set_param_phy_ulpi_ext_vbus(struct dwc2_hsotg *hsotg, int val);
#define DWC2_PHY_ULPI_INTERNAL_VBUS 0
#define DWC2_PHY_ULPI_EXTERNAL_VBUS 1
/*
* Specifies whether to use the I2Cinterface for full speed PHY. This
* parameter is only applicable if PHY_TYPE is FS.
* 0 - No (default)
* 1 - Yes
*/
extern void dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val);
extern void dwc2_set_param_ulpi_fs_ls(struct dwc2_hsotg *hsotg, int val);
extern void dwc2_set_param_ts_dline(struct dwc2_hsotg *hsotg, int val);
/*
* Specifies whether dedicated transmit FIFOs are
* enabled for non periodic IN endpoints in device mode
* 0 - No
* 1 - Yes
*/
extern void dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg,
int val);
extern void dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val);
extern void dwc2_set_param_ahbcfg(struct dwc2_hsotg *hsotg, int val);
extern void dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val);
extern void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
const struct dwc2_core_params *params);
extern void dwc2_set_all_params(struct dwc2_core_params *params, int value);
extern int dwc2_get_hwparams(struct dwc2_hsotg *hsotg);
extern int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg); extern int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg);
extern int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg); extern int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg);
/* Parameters */
int dwc2_get_hwparams(struct dwc2_hsotg *hsotg);
int dwc2_init_params(struct dwc2_hsotg *hsotg);
/* /*
* The following functions check the controller's OTG operation mode * The following functions check the controller's OTG operation mode
* capability (GHWCFG2.OTG_MODE). * capability (GHWCFG2.OTG_MODE).

View File

@@ -159,9 +159,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
" ++OTG Interrupt: Session Request Success Status Change++\n"); " ++OTG Interrupt: Session Request Success Status Change++\n");
gotgctl = dwc2_readl(hsotg->regs + GOTGCTL); gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
if (gotgctl & GOTGCTL_SESREQSCS) { if (gotgctl & GOTGCTL_SESREQSCS) {
if (hsotg->core_params->phy_type == if (hsotg->params.phy_type ==
DWC2_PHY_TYPE_PARAM_FS DWC2_PHY_TYPE_PARAM_FS
&& hsotg->core_params->i2c_enable > 0) { && hsotg->params.i2c_enable > 0) {
hsotg->srp_success = 1; hsotg->srp_success = 1;
} else { } else {
/* Clear Session Request */ /* Clear Session Request */
@@ -370,7 +370,7 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
/* Change to L0 state */ /* Change to L0 state */
hsotg->lx_state = DWC2_L0; hsotg->lx_state = DWC2_L0;
} else { } else {
if (hsotg->core_params->hibernation) if (hsotg->params.hibernation)
return; return;
if (hsotg->lx_state != DWC2_L1) { if (hsotg->lx_state != DWC2_L1) {

View File

@@ -213,7 +213,7 @@ static int fifo_show(struct seq_file *seq, void *v)
val = dwc2_readl(regs + GNPTXFSIZ); val = dwc2_readl(regs + GNPTXFSIZ);
seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n", seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n",
val >> FIFOSIZE_DEPTH_SHIFT, val >> FIFOSIZE_DEPTH_SHIFT,
val & FIFOSIZE_DEPTH_MASK); val & FIFOSIZE_STARTADDR_MASK);
seq_puts(seq, "\nPeriodic TXFIFOs:\n"); seq_puts(seq, "\nPeriodic TXFIFOs:\n");

File diff suppressed because it is too large Load Diff

View File

@@ -79,9 +79,9 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg)
/* Enable the interrupts in the GINTMSK */ /* Enable the interrupts in the GINTMSK */
intmsk = GINTSTS_MODEMIS | GINTSTS_OTGINT; intmsk = GINTSTS_MODEMIS | GINTSTS_OTGINT;
if (hsotg->core_params->dma_enable <= 0) if (hsotg->params.host_dma <= 0)
intmsk |= GINTSTS_RXFLVL; intmsk |= GINTSTS_RXFLVL;
if (hsotg->core_params->external_id_pin_ctl <= 0) if (hsotg->params.external_id_pin_ctl <= 0)
intmsk |= GINTSTS_CONIDSTSCHNG; intmsk |= GINTSTS_CONIDSTSCHNG;
intmsk |= GINTSTS_WKUPINT | GINTSTS_USBSUSP | intmsk |= GINTSTS_WKUPINT | GINTSTS_USBSUSP |
@@ -100,8 +100,8 @@ static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg)
if ((hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && if ((hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED && hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
hsotg->core_params->ulpi_fs_ls > 0) || hsotg->params.ulpi_fs_ls > 0) ||
hsotg->core_params->phy_type == DWC2_PHY_TYPE_PARAM_FS) { hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
/* Full speed PHY */ /* Full speed PHY */
val = HCFG_FSLSPCLKSEL_48_MHZ; val = HCFG_FSLSPCLKSEL_48_MHZ;
} else { } else {
@@ -152,7 +152,7 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
if (dwc2_is_host_mode(hsotg)) if (dwc2_is_host_mode(hsotg))
dwc2_init_fs_ls_pclk_sel(hsotg); dwc2_init_fs_ls_pclk_sel(hsotg);
if (hsotg->core_params->i2c_enable > 0) { if (hsotg->params.i2c_enable > 0) {
dev_dbg(hsotg->dev, "FS PHY enabling I2C\n"); dev_dbg(hsotg->dev, "FS PHY enabling I2C\n");
/* Program GUSBCFG.OtgUtmiFsSel to I2C */ /* Program GUSBCFG.OtgUtmiFsSel to I2C */
@@ -189,20 +189,20 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
* so only program the first time. Do a soft reset immediately after * so only program the first time. Do a soft reset immediately after
* setting phyif. * setting phyif.
*/ */
switch (hsotg->core_params->phy_type) { switch (hsotg->params.phy_type) {
case DWC2_PHY_TYPE_PARAM_ULPI: case DWC2_PHY_TYPE_PARAM_ULPI:
/* ULPI interface */ /* ULPI interface */
dev_dbg(hsotg->dev, "HS ULPI PHY selected\n"); dev_dbg(hsotg->dev, "HS ULPI PHY selected\n");
usbcfg |= GUSBCFG_ULPI_UTMI_SEL; usbcfg |= GUSBCFG_ULPI_UTMI_SEL;
usbcfg &= ~(GUSBCFG_PHYIF16 | GUSBCFG_DDRSEL); usbcfg &= ~(GUSBCFG_PHYIF16 | GUSBCFG_DDRSEL);
if (hsotg->core_params->phy_ulpi_ddr > 0) if (hsotg->params.phy_ulpi_ddr > 0)
usbcfg |= GUSBCFG_DDRSEL; usbcfg |= GUSBCFG_DDRSEL;
break; break;
case DWC2_PHY_TYPE_PARAM_UTMI: case DWC2_PHY_TYPE_PARAM_UTMI:
/* UTMI+ interface */ /* UTMI+ interface */
dev_dbg(hsotg->dev, "HS UTMI+ PHY selected\n"); dev_dbg(hsotg->dev, "HS UTMI+ PHY selected\n");
usbcfg &= ~(GUSBCFG_ULPI_UTMI_SEL | GUSBCFG_PHYIF16); usbcfg &= ~(GUSBCFG_ULPI_UTMI_SEL | GUSBCFG_PHYIF16);
if (hsotg->core_params->phy_utmi_width == 16) if (hsotg->params.phy_utmi_width == 16)
usbcfg |= GUSBCFG_PHYIF16; usbcfg |= GUSBCFG_PHYIF16;
break; break;
default: default:
@@ -230,9 +230,10 @@ static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
u32 usbcfg; u32 usbcfg;
int retval = 0; int retval = 0;
if (hsotg->core_params->speed == DWC2_SPEED_PARAM_FULL && if ((hsotg->params.speed == DWC2_SPEED_PARAM_FULL ||
hsotg->core_params->phy_type == DWC2_PHY_TYPE_PARAM_FS) { hsotg->params.speed == DWC2_SPEED_PARAM_LOW) &&
/* If FS mode with FS PHY */ hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
/* If FS/LS mode with FS/LS PHY */
retval = dwc2_fs_phy_init(hsotg, select_phy); retval = dwc2_fs_phy_init(hsotg, select_phy);
if (retval) if (retval)
return retval; return retval;
@@ -245,7 +246,7 @@ static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED && hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
hsotg->core_params->ulpi_fs_ls > 0) { hsotg->params.ulpi_fs_ls > 0) {
dev_dbg(hsotg->dev, "Setting ULPI FSLS\n"); dev_dbg(hsotg->dev, "Setting ULPI FSLS\n");
usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
usbcfg |= GUSBCFG_ULPI_FS_LS; usbcfg |= GUSBCFG_ULPI_FS_LS;
@@ -272,9 +273,9 @@ static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg)
case GHWCFG2_INT_DMA_ARCH: case GHWCFG2_INT_DMA_ARCH:
dev_dbg(hsotg->dev, "Internal DMA Mode\n"); dev_dbg(hsotg->dev, "Internal DMA Mode\n");
if (hsotg->core_params->ahbcfg != -1) { if (hsotg->params.ahbcfg != -1) {
ahbcfg &= GAHBCFG_CTRL_MASK; ahbcfg &= GAHBCFG_CTRL_MASK;
ahbcfg |= hsotg->core_params->ahbcfg & ahbcfg |= hsotg->params.ahbcfg &
~GAHBCFG_CTRL_MASK; ~GAHBCFG_CTRL_MASK;
} }
break; break;
@@ -285,21 +286,21 @@ static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg)
break; break;
} }
dev_dbg(hsotg->dev, "dma_enable:%d dma_desc_enable:%d\n", dev_dbg(hsotg->dev, "host_dma:%d dma_desc_enable:%d\n",
hsotg->core_params->dma_enable, hsotg->params.host_dma,
hsotg->core_params->dma_desc_enable); hsotg->params.dma_desc_enable);
if (hsotg->core_params->dma_enable > 0) { if (hsotg->params.host_dma > 0) {
if (hsotg->core_params->dma_desc_enable > 0) if (hsotg->params.dma_desc_enable > 0)
dev_dbg(hsotg->dev, "Using Descriptor DMA mode\n"); dev_dbg(hsotg->dev, "Using Descriptor DMA mode\n");
else else
dev_dbg(hsotg->dev, "Using Buffer DMA mode\n"); dev_dbg(hsotg->dev, "Using Buffer DMA mode\n");
} else { } else {
dev_dbg(hsotg->dev, "Using Slave mode\n"); dev_dbg(hsotg->dev, "Using Slave mode\n");
hsotg->core_params->dma_desc_enable = 0; hsotg->params.dma_desc_enable = 0;
} }
if (hsotg->core_params->dma_enable > 0) if (hsotg->params.host_dma > 0)
ahbcfg |= GAHBCFG_DMA_EN; ahbcfg |= GAHBCFG_DMA_EN;
dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG); dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG);
@@ -316,10 +317,10 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg)
switch (hsotg->hw_params.op_mode) { switch (hsotg->hw_params.op_mode) {
case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE: case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE:
if (hsotg->core_params->otg_cap == if (hsotg->params.otg_cap ==
DWC2_CAP_PARAM_HNP_SRP_CAPABLE) DWC2_CAP_PARAM_HNP_SRP_CAPABLE)
usbcfg |= GUSBCFG_HNPCAP; usbcfg |= GUSBCFG_HNPCAP;
if (hsotg->core_params->otg_cap != if (hsotg->params.otg_cap !=
DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE) DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE)
usbcfg |= GUSBCFG_SRPCAP; usbcfg |= GUSBCFG_SRPCAP;
break; break;
@@ -327,7 +328,7 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg)
case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE: case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE:
case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE: case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE:
case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST: case GHWCFG2_OP_MODE_SRP_CAPABLE_HOST:
if (hsotg->core_params->otg_cap != if (hsotg->params.otg_cap !=
DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE) DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE)
usbcfg |= GUSBCFG_SRPCAP; usbcfg |= GUSBCFG_SRPCAP;
break; break;
@@ -390,7 +391,7 @@ static void dwc2_disable_host_interrupts(struct dwc2_hsotg *hsotg)
*/ */
static void dwc2_calculate_dynamic_fifo(struct dwc2_hsotg *hsotg) static void dwc2_calculate_dynamic_fifo(struct dwc2_hsotg *hsotg)
{ {
struct dwc2_core_params *params = hsotg->core_params; struct dwc2_core_params *params = &hsotg->params;
struct dwc2_hw_params *hw = &hsotg->hw_params; struct dwc2_hw_params *hw = &hsotg->hw_params;
u32 rxfsiz, nptxfsiz, ptxfsiz, total_fifo_size; u32 rxfsiz, nptxfsiz, ptxfsiz, total_fifo_size;
@@ -449,7 +450,7 @@ static void dwc2_calculate_dynamic_fifo(struct dwc2_hsotg *hsotg)
static void dwc2_config_fifos(struct dwc2_hsotg *hsotg) static void dwc2_config_fifos(struct dwc2_hsotg *hsotg)
{ {
struct dwc2_core_params *params = hsotg->core_params; struct dwc2_core_params *params = &hsotg->params;
u32 nptxfsiz, hptxfsiz, dfifocfg, grxfsiz; u32 nptxfsiz, hptxfsiz, dfifocfg, grxfsiz;
if (!params->enable_dynamic_fifo) if (!params->enable_dynamic_fifo)
@@ -490,7 +491,7 @@ static void dwc2_config_fifos(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev, "new hptxfsiz=%08x\n", dev_dbg(hsotg->dev, "new hptxfsiz=%08x\n",
dwc2_readl(hsotg->regs + HPTXFSIZ)); dwc2_readl(hsotg->regs + HPTXFSIZ));
if (hsotg->core_params->en_multiple_tx_fifo > 0 && if (hsotg->params.en_multiple_tx_fifo > 0 &&
hsotg->hw_params.snpsid <= DWC2_CORE_REV_2_94a) { hsotg->hw_params.snpsid <= DWC2_CORE_REV_2_94a) {
/* /*
* Global DFIFOCFG calculation for Host mode - * Global DFIFOCFG calculation for Host mode -
@@ -598,7 +599,7 @@ static void dwc2_dump_channel_info(struct dwc2_hsotg *hsotg,
struct dwc2_host_chan *chan) struct dwc2_host_chan *chan)
{ {
#ifdef VERBOSE_DEBUG #ifdef VERBOSE_DEBUG
int num_channels = hsotg->core_params->host_channels; int num_channels = hsotg->params.host_channels;
struct dwc2_qh *qh; struct dwc2_qh *qh;
u32 hcchar; u32 hcchar;
u32 hcsplt; u32 hcsplt;
@@ -648,6 +649,35 @@ static void dwc2_dump_channel_info(struct dwc2_hsotg *hsotg,
#endif /* VERBOSE_DEBUG */ #endif /* VERBOSE_DEBUG */
} }
static int _dwc2_hcd_start(struct usb_hcd *hcd);
static void dwc2_host_start(struct dwc2_hsotg *hsotg)
{
struct usb_hcd *hcd = dwc2_hsotg_to_hcd(hsotg);
hcd->self.is_b_host = dwc2_hcd_is_b_host(hsotg);
_dwc2_hcd_start(hcd);
}
static void dwc2_host_disconnect(struct dwc2_hsotg *hsotg)
{
struct usb_hcd *hcd = dwc2_hsotg_to_hcd(hsotg);
hcd->self.is_b_host = 0;
}
static void dwc2_host_hub_info(struct dwc2_hsotg *hsotg, void *context,
int *hub_addr, int *hub_port)
{
struct urb *urb = context;
if (urb->dev->tt)
*hub_addr = urb->dev->tt->hub->devnum;
else
*hub_addr = 0;
*hub_port = urb->dev->ttport;
}
/* /*
* ========================================================================= * =========================================================================
* Low Level Host Channel Access Functions * Low Level Host Channel Access Functions
@@ -741,7 +771,7 @@ static void dwc2_hc_enable_dma_ints(struct dwc2_hsotg *hsotg,
* For Descriptor DMA mode core halts the channel on AHB error. * For Descriptor DMA mode core halts the channel on AHB error.
* Interrupt is not required. * Interrupt is not required.
*/ */
if (hsotg->core_params->dma_desc_enable <= 0) { if (hsotg->params.dma_desc_enable <= 0) {
if (dbg_hc(chan)) if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "desc DMA disabled\n"); dev_vdbg(hsotg->dev, "desc DMA disabled\n");
hcintmsk |= HCINTMSK_AHBERR; hcintmsk |= HCINTMSK_AHBERR;
@@ -774,7 +804,7 @@ static void dwc2_hc_enable_ints(struct dwc2_hsotg *hsotg,
{ {
u32 intmsk; u32 intmsk;
if (hsotg->core_params->dma_enable > 0) { if (hsotg->params.host_dma > 0) {
if (dbg_hc(chan)) if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "DMA enabled\n"); dev_vdbg(hsotg->dev, "DMA enabled\n");
dwc2_hc_enable_dma_ints(hsotg, chan); dwc2_hc_enable_dma_ints(hsotg, chan);
@@ -994,7 +1024,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
/* No need to set the bit in DDMA for disabling the channel */ /* No need to set the bit in DDMA for disabling the channel */
/* TODO check it everywhere channel is disabled */ /* TODO check it everywhere channel is disabled */
if (hsotg->core_params->dma_desc_enable <= 0) { if (hsotg->params.dma_desc_enable <= 0) {
if (dbg_hc(chan)) if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "desc DMA disabled\n"); dev_vdbg(hsotg->dev, "desc DMA disabled\n");
hcchar |= HCCHAR_CHENA; hcchar |= HCCHAR_CHENA;
@@ -1004,7 +1034,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
} }
hcchar |= HCCHAR_CHDIS; hcchar |= HCCHAR_CHDIS;
if (hsotg->core_params->dma_enable <= 0) { if (hsotg->params.host_dma <= 0) {
if (dbg_hc(chan)) if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "DMA not enabled\n"); dev_vdbg(hsotg->dev, "DMA not enabled\n");
hcchar |= HCCHAR_CHENA; hcchar |= HCCHAR_CHENA;
@@ -1143,7 +1173,7 @@ static void dwc2_hc_set_even_odd_frame(struct dwc2_hsotg *hsotg,
fifo_space = (dwc2_readl(hsotg->regs + HPTXSTS) & fifo_space = (dwc2_readl(hsotg->regs + HPTXSTS) &
TXSTS_FSPCAVAIL_MASK) >> TXSTS_FSPCAVAIL_SHIFT; TXSTS_FSPCAVAIL_MASK) >> TXSTS_FSPCAVAIL_SHIFT;
bytes_in_fifo = sizeof(u32) * bytes_in_fifo = sizeof(u32) *
(hsotg->core_params->host_perio_tx_fifo_size - (hsotg->params.host_perio_tx_fifo_size -
fifo_space); fifo_space);
/* /*
@@ -1339,8 +1369,8 @@ static void dwc2_hc_do_ping(struct dwc2_hsotg *hsotg,
static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg, static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
struct dwc2_host_chan *chan) struct dwc2_host_chan *chan)
{ {
u32 max_hc_xfer_size = hsotg->core_params->max_transfer_size; u32 max_hc_xfer_size = hsotg->params.max_transfer_size;
u16 max_hc_pkt_count = hsotg->core_params->max_packet_count; u16 max_hc_pkt_count = hsotg->params.max_packet_count;
u32 hcchar; u32 hcchar;
u32 hctsiz = 0; u32 hctsiz = 0;
u16 num_packets; u16 num_packets;
@@ -1350,7 +1380,7 @@ static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
dev_vdbg(hsotg->dev, "%s()\n", __func__); dev_vdbg(hsotg->dev, "%s()\n", __func__);
if (chan->do_ping) { if (chan->do_ping) {
if (hsotg->core_params->dma_enable <= 0) { if (hsotg->params.host_dma <= 0) {
if (dbg_hc(chan)) if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "ping, no DMA\n"); dev_vdbg(hsotg->dev, "ping, no DMA\n");
dwc2_hc_do_ping(hsotg, chan); dwc2_hc_do_ping(hsotg, chan);
@@ -1478,7 +1508,7 @@ static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
TSIZ_SC_MC_PID_SHIFT); TSIZ_SC_MC_PID_SHIFT);
} }
if (hsotg->core_params->dma_enable > 0) { if (hsotg->params.host_dma > 0) {
dwc2_writel((u32)chan->xfer_dma, dwc2_writel((u32)chan->xfer_dma,
hsotg->regs + HCDMA(chan->hc_num)); hsotg->regs + HCDMA(chan->hc_num));
if (dbg_hc(chan)) if (dbg_hc(chan))
@@ -1521,7 +1551,7 @@ static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
chan->xfer_started = 1; chan->xfer_started = 1;
chan->requests++; chan->requests++;
if (hsotg->core_params->dma_enable <= 0 && if (hsotg->params.host_dma <= 0 &&
!chan->ep_is_in && chan->xfer_len > 0) !chan->ep_is_in && chan->xfer_len > 0)
/* Load OUT packet into the appropriate Tx FIFO */ /* Load OUT packet into the appropriate Tx FIFO */
dwc2_hc_write_packet(hsotg, chan); dwc2_hc_write_packet(hsotg, chan);
@@ -1799,12 +1829,12 @@ void dwc2_hcd_start(struct dwc2_hsotg *hsotg)
/* Must be called with interrupt disabled and spinlock held */ /* Must be called with interrupt disabled and spinlock held */
static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg) static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg)
{ {
int num_channels = hsotg->core_params->host_channels; int num_channels = hsotg->params.host_channels;
struct dwc2_host_chan *channel; struct dwc2_host_chan *channel;
u32 hcchar; u32 hcchar;
int i; int i;
if (hsotg->core_params->dma_enable <= 0) { if (hsotg->params.host_dma <= 0) {
/* Flush out any channel requests in slave mode */ /* Flush out any channel requests in slave mode */
for (i = 0; i < num_channels; i++) { for (i = 0; i < num_channels; i++) {
channel = hsotg->hc_ptr_array[i]; channel = hsotg->hc_ptr_array[i];
@@ -1840,9 +1870,9 @@ static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg)
channel->qh = NULL; channel->qh = NULL;
} }
/* All channels have been freed, mark them available */ /* All channels have been freed, mark them available */
if (hsotg->core_params->uframe_sched > 0) { if (hsotg->params.uframe_sched > 0) {
hsotg->available_host_channels = hsotg->available_host_channels =
hsotg->core_params->host_channels; hsotg->params.host_channels;
} else { } else {
hsotg->non_periodic_channels = 0; hsotg->non_periodic_channels = 0;
hsotg->periodic_channels = 0; hsotg->periodic_channels = 0;
@@ -2077,7 +2107,7 @@ static int dwc2_hcd_urb_dequeue(struct dwc2_hsotg *hsotg,
* Free the QTD and clean up the associated QH. Leave the QH in the * Free the QTD and clean up the associated QH. Leave the QH in the
* schedule if it has any remaining QTDs. * schedule if it has any remaining QTDs.
*/ */
if (hsotg->core_params->dma_desc_enable <= 0) { if (hsotg->params.dma_desc_enable <= 0) {
u8 in_process = urb_qtd->in_process; u8 in_process = urb_qtd->in_process;
dwc2_hcd_qtd_unlink_and_free(hsotg, urb_qtd, qh); dwc2_hcd_qtd_unlink_and_free(hsotg, urb_qtd, qh);
@@ -2185,13 +2215,13 @@ static int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup)
/* Set ULPI External VBUS bit if needed */ /* Set ULPI External VBUS bit if needed */
usbcfg &= ~GUSBCFG_ULPI_EXT_VBUS_DRV; usbcfg &= ~GUSBCFG_ULPI_EXT_VBUS_DRV;
if (hsotg->core_params->phy_ulpi_ext_vbus == if (hsotg->params.phy_ulpi_ext_vbus ==
DWC2_PHY_ULPI_EXTERNAL_VBUS) DWC2_PHY_ULPI_EXTERNAL_VBUS)
usbcfg |= GUSBCFG_ULPI_EXT_VBUS_DRV; usbcfg |= GUSBCFG_ULPI_EXT_VBUS_DRV;
/* Set external TS Dline pulsing bit if needed */ /* Set external TS Dline pulsing bit if needed */
usbcfg &= ~GUSBCFG_TERMSELDLPULSE; usbcfg &= ~GUSBCFG_TERMSELDLPULSE;
if (hsotg->core_params->ts_dline > 0) if (hsotg->params.ts_dline > 0)
usbcfg |= GUSBCFG_TERMSELDLPULSE; usbcfg |= GUSBCFG_TERMSELDLPULSE;
dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
@@ -2230,10 +2260,10 @@ static int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup)
/* Program the GOTGCTL register */ /* Program the GOTGCTL register */
otgctl = dwc2_readl(hsotg->regs + GOTGCTL); otgctl = dwc2_readl(hsotg->regs + GOTGCTL);
otgctl &= ~GOTGCTL_OTGVER; otgctl &= ~GOTGCTL_OTGVER;
if (hsotg->core_params->otg_ver > 0) if (hsotg->params.otg_ver > 0)
otgctl |= GOTGCTL_OTGVER; otgctl |= GOTGCTL_OTGVER;
dwc2_writel(otgctl, hsotg->regs + GOTGCTL); dwc2_writel(otgctl, hsotg->regs + GOTGCTL);
dev_dbg(hsotg->dev, "OTG VER PARAM: %d\n", hsotg->core_params->otg_ver); dev_dbg(hsotg->dev, "OTG VER PARAM: %d\n", hsotg->params.otg_ver);
/* Clear the SRP success bit for FS-I2c */ /* Clear the SRP success bit for FS-I2c */
hsotg->srp_success = 0; hsotg->srp_success = 0;
@@ -2277,7 +2307,8 @@ static void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
/* Initialize Host Configuration Register */ /* Initialize Host Configuration Register */
dwc2_init_fs_ls_pclk_sel(hsotg); dwc2_init_fs_ls_pclk_sel(hsotg);
if (hsotg->core_params->speed == DWC2_SPEED_PARAM_FULL) { if (hsotg->params.speed == DWC2_SPEED_PARAM_FULL ||
hsotg->params.speed == DWC2_SPEED_PARAM_LOW) {
hcfg = dwc2_readl(hsotg->regs + HCFG); hcfg = dwc2_readl(hsotg->regs + HCFG);
hcfg |= HCFG_FSLSSUPP; hcfg |= HCFG_FSLSSUPP;
dwc2_writel(hcfg, hsotg->regs + HCFG); dwc2_writel(hcfg, hsotg->regs + HCFG);
@@ -2288,13 +2319,13 @@ static void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
* runtime. This bit needs to be programmed during initial configuration * runtime. This bit needs to be programmed during initial configuration
* and its value must not be changed during runtime. * and its value must not be changed during runtime.
*/ */
if (hsotg->core_params->reload_ctl > 0) { if (hsotg->params.reload_ctl > 0) {
hfir = dwc2_readl(hsotg->regs + HFIR); hfir = dwc2_readl(hsotg->regs + HFIR);
hfir |= HFIR_RLDCTRL; hfir |= HFIR_RLDCTRL;
dwc2_writel(hfir, hsotg->regs + HFIR); dwc2_writel(hfir, hsotg->regs + HFIR);
} }
if (hsotg->core_params->dma_desc_enable > 0) { if (hsotg->params.dma_desc_enable > 0) {
u32 op_mode = hsotg->hw_params.op_mode; u32 op_mode = hsotg->hw_params.op_mode;
if (hsotg->hw_params.snpsid < DWC2_CORE_REV_2_90a || if (hsotg->hw_params.snpsid < DWC2_CORE_REV_2_90a ||
@@ -2306,7 +2337,7 @@ static void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
"Hardware does not support descriptor DMA mode -\n"); "Hardware does not support descriptor DMA mode -\n");
dev_err(hsotg->dev, dev_err(hsotg->dev,
"falling back to buffer DMA mode.\n"); "falling back to buffer DMA mode.\n");
hsotg->core_params->dma_desc_enable = 0; hsotg->params.dma_desc_enable = 0;
} else { } else {
hcfg = dwc2_readl(hsotg->regs + HCFG); hcfg = dwc2_readl(hsotg->regs + HCFG);
hcfg |= HCFG_DESCDMA; hcfg |= HCFG_DESCDMA;
@@ -2332,12 +2363,12 @@ static void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
otgctl &= ~GOTGCTL_HSTSETHNPEN; otgctl &= ~GOTGCTL_HSTSETHNPEN;
dwc2_writel(otgctl, hsotg->regs + GOTGCTL); dwc2_writel(otgctl, hsotg->regs + GOTGCTL);
if (hsotg->core_params->dma_desc_enable <= 0) { if (hsotg->params.dma_desc_enable <= 0) {
int num_channels, i; int num_channels, i;
u32 hcchar; u32 hcchar;
/* Flush out any leftover queued requests */ /* Flush out any leftover queued requests */
num_channels = hsotg->core_params->host_channels; num_channels = hsotg->params.host_channels;
for (i = 0; i < num_channels; i++) { for (i = 0; i < num_channels; i++) {
hcchar = dwc2_readl(hsotg->regs + HCCHAR(i)); hcchar = dwc2_readl(hsotg->regs + HCCHAR(i));
hcchar &= ~HCCHAR_CHENA; hcchar &= ~HCCHAR_CHENA;
@@ -2399,9 +2430,9 @@ static void dwc2_hcd_reinit(struct dwc2_hsotg *hsotg)
hsotg->flags.d32 = 0; hsotg->flags.d32 = 0;
hsotg->non_periodic_qh_ptr = &hsotg->non_periodic_sched_active; hsotg->non_periodic_qh_ptr = &hsotg->non_periodic_sched_active;
if (hsotg->core_params->uframe_sched > 0) { if (hsotg->params.uframe_sched > 0) {
hsotg->available_host_channels = hsotg->available_host_channels =
hsotg->core_params->host_channels; hsotg->params.host_channels;
} else { } else {
hsotg->non_periodic_channels = 0; hsotg->non_periodic_channels = 0;
hsotg->periodic_channels = 0; hsotg->periodic_channels = 0;
@@ -2415,7 +2446,7 @@ static void dwc2_hcd_reinit(struct dwc2_hsotg *hsotg)
hc_list_entry) hc_list_entry)
list_del_init(&chan->hc_list_entry); list_del_init(&chan->hc_list_entry);
num_channels = hsotg->core_params->host_channels; num_channels = hsotg->params.host_channels;
for (i = 0; i < num_channels; i++) { for (i = 0; i < num_channels; i++) {
chan = hsotg->hc_ptr_array[i]; chan = hsotg->hc_ptr_array[i];
list_add_tail(&chan->hc_list_entry, &hsotg->free_hc_list); list_add_tail(&chan->hc_list_entry, &hsotg->free_hc_list);
@@ -2457,7 +2488,7 @@ static void dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg,
chan->do_ping = 0; chan->do_ping = 0;
chan->ep_is_in = 0; chan->ep_is_in = 0;
chan->data_pid_start = DWC2_HC_PID_SETUP; chan->data_pid_start = DWC2_HC_PID_SETUP;
if (hsotg->core_params->dma_enable > 0) if (hsotg->params.host_dma > 0)
chan->xfer_dma = urb->setup_dma; chan->xfer_dma = urb->setup_dma;
else else
chan->xfer_buf = urb->setup_packet; chan->xfer_buf = urb->setup_packet;
@@ -2484,7 +2515,7 @@ static void dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg,
chan->do_ping = 0; chan->do_ping = 0;
chan->data_pid_start = DWC2_HC_PID_DATA1; chan->data_pid_start = DWC2_HC_PID_DATA1;
chan->xfer_len = 0; chan->xfer_len = 0;
if (hsotg->core_params->dma_enable > 0) if (hsotg->params.host_dma > 0)
chan->xfer_dma = hsotg->status_buf_dma; chan->xfer_dma = hsotg->status_buf_dma;
else else
chan->xfer_buf = hsotg->status_buf; chan->xfer_buf = hsotg->status_buf;
@@ -2502,13 +2533,13 @@ static void dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg,
case USB_ENDPOINT_XFER_ISOC: case USB_ENDPOINT_XFER_ISOC:
chan->ep_type = USB_ENDPOINT_XFER_ISOC; chan->ep_type = USB_ENDPOINT_XFER_ISOC;
if (hsotg->core_params->dma_desc_enable > 0) if (hsotg->params.dma_desc_enable > 0)
break; break;
frame_desc = &urb->iso_descs[qtd->isoc_frame_index]; frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
frame_desc->status = 0; frame_desc->status = 0;
if (hsotg->core_params->dma_enable > 0) { if (hsotg->params.host_dma > 0) {
chan->xfer_dma = urb->dma; chan->xfer_dma = urb->dma;
chan->xfer_dma += frame_desc->offset + chan->xfer_dma += frame_desc->offset +
qtd->isoc_split_offset; qtd->isoc_split_offset;
@@ -2690,7 +2721,7 @@ static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
!dwc2_hcd_is_pipe_in(&urb->pipe_info)) !dwc2_hcd_is_pipe_in(&urb->pipe_info))
urb->actual_length = urb->length; urb->actual_length = urb->length;
if (hsotg->core_params->dma_enable > 0) if (hsotg->params.host_dma > 0)
chan->xfer_dma = urb->dma + urb->actual_length; chan->xfer_dma = urb->dma + urb->actual_length;
else else
chan->xfer_buf = (u8 *)urb->buf + urb->actual_length; chan->xfer_buf = (u8 *)urb->buf + urb->actual_length;
@@ -2715,7 +2746,7 @@ static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
*/ */
chan->multi_count = dwc2_hb_mult(qh->maxp); chan->multi_count = dwc2_hb_mult(qh->maxp);
if (hsotg->core_params->dma_desc_enable > 0) { if (hsotg->params.dma_desc_enable > 0) {
chan->desc_list_addr = qh->desc_list_dma; chan->desc_list_addr = qh->desc_list_dma;
chan->desc_list_sz = qh->desc_list_sz; chan->desc_list_sz = qh->desc_list_sz;
} }
@@ -2752,7 +2783,7 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
while (qh_ptr != &hsotg->periodic_sched_ready) { while (qh_ptr != &hsotg->periodic_sched_ready) {
if (list_empty(&hsotg->free_hc_list)) if (list_empty(&hsotg->free_hc_list))
break; break;
if (hsotg->core_params->uframe_sched > 0) { if (hsotg->params.uframe_sched > 0) {
if (hsotg->available_host_channels <= 1) if (hsotg->available_host_channels <= 1)
break; break;
hsotg->available_host_channels--; hsotg->available_host_channels--;
@@ -2776,17 +2807,17 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
* schedule. Some free host channels may not be used if they are * schedule. Some free host channels may not be used if they are
* reserved for periodic transfers. * reserved for periodic transfers.
*/ */
num_channels = hsotg->core_params->host_channels; num_channels = hsotg->params.host_channels;
qh_ptr = hsotg->non_periodic_sched_inactive.next; qh_ptr = hsotg->non_periodic_sched_inactive.next;
while (qh_ptr != &hsotg->non_periodic_sched_inactive) { while (qh_ptr != &hsotg->non_periodic_sched_inactive) {
if (hsotg->core_params->uframe_sched <= 0 && if (hsotg->params.uframe_sched <= 0 &&
hsotg->non_periodic_channels >= num_channels - hsotg->non_periodic_channels >= num_channels -
hsotg->periodic_channels) hsotg->periodic_channels)
break; break;
if (list_empty(&hsotg->free_hc_list)) if (list_empty(&hsotg->free_hc_list))
break; break;
qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry); qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry);
if (hsotg->core_params->uframe_sched > 0) { if (hsotg->params.uframe_sched > 0) {
if (hsotg->available_host_channels < 1) if (hsotg->available_host_channels < 1)
break; break;
hsotg->available_host_channels--; hsotg->available_host_channels--;
@@ -2808,7 +2839,7 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
else else
ret_val = DWC2_TRANSACTION_ALL; ret_val = DWC2_TRANSACTION_ALL;
if (hsotg->core_params->uframe_sched <= 0) if (hsotg->params.uframe_sched <= 0)
hsotg->non_periodic_channels++; hsotg->non_periodic_channels++;
} }
@@ -2847,8 +2878,8 @@ static int dwc2_queue_transaction(struct dwc2_hsotg *hsotg,
list_move_tail(&chan->split_order_list_entry, list_move_tail(&chan->split_order_list_entry,
&hsotg->split_order); &hsotg->split_order);
if (hsotg->core_params->dma_enable > 0) { if (hsotg->params.host_dma > 0) {
if (hsotg->core_params->dma_desc_enable > 0) { if (hsotg->params.dma_desc_enable > 0) {
if (!chan->xfer_started || if (!chan->xfer_started ||
chan->ep_type == USB_ENDPOINT_XFER_ISOC) { chan->ep_type == USB_ENDPOINT_XFER_ISOC) {
dwc2_hcd_start_xfer_ddma(hsotg, chan->qh); dwc2_hcd_start_xfer_ddma(hsotg, chan->qh);
@@ -2957,7 +2988,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
* The flag prevents any halts to get into the request queue in * The flag prevents any halts to get into the request queue in
* the middle of multiple high-bandwidth packets getting queued. * the middle of multiple high-bandwidth packets getting queued.
*/ */
if (hsotg->core_params->dma_enable <= 0 && if (hsotg->params.host_dma <= 0 &&
qh->channel->multi_count > 1) qh->channel->multi_count > 1)
hsotg->queuing_high_bandwidth = 1; hsotg->queuing_high_bandwidth = 1;
@@ -2976,7 +3007,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
* controller automatically handles multiple packets for * controller automatically handles multiple packets for
* high-bandwidth transfers. * high-bandwidth transfers.
*/ */
if (hsotg->core_params->dma_enable > 0 || status == 0 || if (hsotg->params.host_dma > 0 || status == 0 ||
qh->channel->requests == qh->channel->multi_count) { qh->channel->requests == qh->channel->multi_count) {
qh_ptr = qh_ptr->next; qh_ptr = qh_ptr->next;
/* /*
@@ -2993,7 +3024,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
exit: exit:
if (no_queue_space || no_fifo_space || if (no_queue_space || no_fifo_space ||
(hsotg->core_params->dma_enable <= 0 && (hsotg->params.host_dma <= 0 &&
!list_empty(&hsotg->periodic_sched_assigned))) { !list_empty(&hsotg->periodic_sched_assigned))) {
/* /*
* May need to queue more transactions as the request * May need to queue more transactions as the request
@@ -3073,7 +3104,7 @@ static void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg)
tx_status = dwc2_readl(hsotg->regs + GNPTXSTS); tx_status = dwc2_readl(hsotg->regs + GNPTXSTS);
qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
TXSTS_QSPCAVAIL_SHIFT; TXSTS_QSPCAVAIL_SHIFT;
if (hsotg->core_params->dma_enable <= 0 && qspcavail == 0) { if (hsotg->params.host_dma <= 0 && qspcavail == 0) {
no_queue_space = 1; no_queue_space = 1;
break; break;
} }
@@ -3106,7 +3137,7 @@ next:
hsotg->non_periodic_qh_ptr->next; hsotg->non_periodic_qh_ptr->next;
} while (hsotg->non_periodic_qh_ptr != orig_qh_ptr); } while (hsotg->non_periodic_qh_ptr != orig_qh_ptr);
if (hsotg->core_params->dma_enable <= 0) { if (hsotg->params.host_dma <= 0) {
tx_status = dwc2_readl(hsotg->regs + GNPTXSTS); tx_status = dwc2_readl(hsotg->regs + GNPTXSTS);
qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
TXSTS_QSPCAVAIL_SHIFT; TXSTS_QSPCAVAIL_SHIFT;
@@ -3307,7 +3338,7 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)
* If hibernation is supported, Phy clock will be suspended * If hibernation is supported, Phy clock will be suspended
* after registers are backuped. * after registers are backuped.
*/ */
if (!hsotg->core_params->hibernation) { if (!hsotg->params.hibernation) {
/* Suspend the Phy Clock */ /* Suspend the Phy Clock */
pcgctl = dwc2_readl(hsotg->regs + PCGCTL); pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
pcgctl |= PCGCTL_STOPPCLK; pcgctl |= PCGCTL_STOPPCLK;
@@ -3342,7 +3373,7 @@ static void dwc2_port_resume(struct dwc2_hsotg *hsotg)
* If hibernation is supported, Phy clock is already resumed * If hibernation is supported, Phy clock is already resumed
* after registers restore. * after registers restore.
*/ */
if (!hsotg->core_params->hibernation) { if (!hsotg->params.hibernation) {
pcgctl = dwc2_readl(hsotg->regs + PCGCTL); pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
pcgctl &= ~PCGCTL_STOPPCLK; pcgctl &= ~PCGCTL_STOPPCLK;
dwc2_writel(pcgctl, hsotg->regs + PCGCTL); dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
@@ -3569,7 +3600,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
port_status |= USB_PORT_STAT_TEST; port_status |= USB_PORT_STAT_TEST;
/* USB_PORT_FEAT_INDICATOR unsupported always 0 */ /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
if (hsotg->core_params->dma_desc_fs_enable) { if (hsotg->params.dma_desc_fs_enable) {
/* /*
* Enable descriptor DMA only if a full speed * Enable descriptor DMA only if a full speed
* device is connected. * device is connected.
@@ -3583,7 +3614,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
u32 hcfg; u32 hcfg;
dev_info(hsotg->dev, "Enabling descriptor DMA mode\n"); dev_info(hsotg->dev, "Enabling descriptor DMA mode\n");
hsotg->core_params->dma_desc_enable = 1; hsotg->params.dma_desc_enable = 1;
hcfg = dwc2_readl(hsotg->regs + HCFG); hcfg = dwc2_readl(hsotg->regs + HCFG);
hcfg |= HCFG_DESCDMA; hcfg |= HCFG_DESCDMA;
dwc2_writel(hcfg, hsotg->regs + HCFG); dwc2_writel(hcfg, hsotg->regs + HCFG);
@@ -3824,7 +3855,7 @@ void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg)
u32 p_tx_status; u32 p_tx_status;
int i; int i;
num_channels = hsotg->core_params->host_channels; num_channels = hsotg->params.host_channels;
dev_dbg(hsotg->dev, "\n"); dev_dbg(hsotg->dev, "\n");
dev_dbg(hsotg->dev, dev_dbg(hsotg->dev,
"************************************************************\n"); "************************************************************\n");
@@ -4020,35 +4051,6 @@ static struct dwc2_hsotg *dwc2_hcd_to_hsotg(struct usb_hcd *hcd)
return p->hsotg; return p->hsotg;
} }
static int _dwc2_hcd_start(struct usb_hcd *hcd);
void dwc2_host_start(struct dwc2_hsotg *hsotg)
{
struct usb_hcd *hcd = dwc2_hsotg_to_hcd(hsotg);
hcd->self.is_b_host = dwc2_hcd_is_b_host(hsotg);
_dwc2_hcd_start(hcd);
}
void dwc2_host_disconnect(struct dwc2_hsotg *hsotg)
{
struct usb_hcd *hcd = dwc2_hsotg_to_hcd(hsotg);
hcd->self.is_b_host = 0;
}
void dwc2_host_hub_info(struct dwc2_hsotg *hsotg, void *context, int *hub_addr,
int *hub_port)
{
struct urb *urb = context;
if (urb->dev->tt)
*hub_addr = urb->dev->tt->hub->devnum;
else
*hub_addr = 0;
*hub_port = urb->dev->ttport;
}
/** /**
* dwc2_host_get_tt_info() - Get the dwc2_tt associated with context * dwc2_host_get_tt_info() - Get the dwc2_tt associated with context
* *
@@ -4365,7 +4367,7 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
if (!HCD_HW_ACCESSIBLE(hcd)) if (!HCD_HW_ACCESSIBLE(hcd))
goto unlock; goto unlock;
if (!hsotg->core_params->hibernation) if (!hsotg->params.hibernation)
goto skip_power_saving; goto skip_power_saving;
/* /*
@@ -4417,7 +4419,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
if (hsotg->lx_state != DWC2_L2) if (hsotg->lx_state != DWC2_L2)
goto unlock; goto unlock;
if (!hsotg->core_params->hibernation) { if (!hsotg->params.hibernation) {
hsotg->lx_state = DWC2_L0; hsotg->lx_state = DWC2_L0;
goto unlock; goto unlock;
} }
@@ -4510,9 +4512,6 @@ static void dwc2_dump_urb_info(struct usb_hcd *hcd, struct urb *urb,
case PIPE_ISOCHRONOUS: case PIPE_ISOCHRONOUS:
pipetype = "ISOCHRONOUS"; pipetype = "ISOCHRONOUS";
break; break;
default:
pipetype = "UNKNOWN";
break;
} }
dev_vdbg(hsotg->dev, " Endpoint type: %s %s (%s)\n", pipetype, dev_vdbg(hsotg->dev, " Endpoint type: %s %s (%s)\n", pipetype,
@@ -4609,8 +4608,6 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
case PIPE_INTERRUPT: case PIPE_INTERRUPT:
ep_type = USB_ENDPOINT_XFER_INT; ep_type = USB_ENDPOINT_XFER_INT;
break; break;
default:
dev_warn(hsotg->dev, "Wrong ep type\n");
} }
dwc2_urb = dwc2_hcd_urb_alloc(hsotg, urb->number_of_packets, dwc2_urb = dwc2_hcd_urb_alloc(hsotg, urb->number_of_packets,
@@ -4919,7 +4916,7 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg)
} }
} }
if (hsotg->core_params->dma_enable > 0) { if (hsotg->params.host_dma > 0) {
if (hsotg->status_buf) { if (hsotg->status_buf) {
dma_free_coherent(hsotg->dev, DWC2_HCD_STATUS_BUF_SIZE, dma_free_coherent(hsotg->dev, DWC2_HCD_STATUS_BUF_SIZE,
hsotg->status_buf, hsotg->status_buf,
@@ -4999,16 +4996,16 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
hsotg->last_frame_num = HFNUM_MAX_FRNUM; hsotg->last_frame_num = HFNUM_MAX_FRNUM;
/* Check if the bus driver or platform code has setup a dma_mask */ /* Check if the bus driver or platform code has setup a dma_mask */
if (hsotg->core_params->dma_enable > 0 && if (hsotg->params.host_dma > 0 &&
hsotg->dev->dma_mask == NULL) { hsotg->dev->dma_mask == NULL) {
dev_warn(hsotg->dev, dev_warn(hsotg->dev,
"dma_mask not set, disabling DMA\n"); "dma_mask not set, disabling DMA\n");
hsotg->core_params->dma_enable = 0; hsotg->params.host_dma = 0;
hsotg->core_params->dma_desc_enable = 0; hsotg->params.dma_desc_enable = 0;
} }
/* Set device flags indicating whether the HCD supports DMA */ /* Set device flags indicating whether the HCD supports DMA */
if (hsotg->core_params->dma_enable > 0) { if (hsotg->params.host_dma > 0) {
if (dma_set_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0) if (dma_set_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0)
dev_warn(hsotg->dev, "can't set DMA mask\n"); dev_warn(hsotg->dev, "can't set DMA mask\n");
if (dma_set_coherent_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0) if (dma_set_coherent_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0)
@@ -5019,7 +5016,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
if (!hcd) if (!hcd)
goto error1; goto error1;
if (hsotg->core_params->dma_enable <= 0) if (hsotg->params.host_dma <= 0)
hcd->self.uses_dma = 0; hcd->self.uses_dma = 0;
hcd->has_tt = 1; hcd->has_tt = 1;
@@ -5067,7 +5064,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
* in the controller. Initialize the channel descriptor array. * in the controller. Initialize the channel descriptor array.
*/ */
INIT_LIST_HEAD(&hsotg->free_hc_list); INIT_LIST_HEAD(&hsotg->free_hc_list);
num_channels = hsotg->core_params->host_channels; num_channels = hsotg->params.host_channels;
memset(&hsotg->hc_ptr_array[0], 0, sizeof(hsotg->hc_ptr_array)); memset(&hsotg->hc_ptr_array[0], 0, sizeof(hsotg->hc_ptr_array));
for (i = 0; i < num_channels; i++) { for (i = 0; i < num_channels; i++) {
@@ -5091,7 +5088,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
* done after usb_add_hcd since that function allocates the DMA buffer * done after usb_add_hcd since that function allocates the DMA buffer
* pool. * pool.
*/ */
if (hsotg->core_params->dma_enable > 0) if (hsotg->params.host_dma > 0)
hsotg->status_buf = dma_alloc_coherent(hsotg->dev, hsotg->status_buf = dma_alloc_coherent(hsotg->dev,
DWC2_HCD_STATUS_BUF_SIZE, DWC2_HCD_STATUS_BUF_SIZE,
&hsotg->status_buf_dma, GFP_KERNEL); &hsotg->status_buf_dma, GFP_KERNEL);
@@ -5107,10 +5104,10 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
* DMA mode. * DMA mode.
* Alignment must be set to 512 bytes. * Alignment must be set to 512 bytes.
*/ */
if (hsotg->core_params->dma_desc_enable || if (hsotg->params.dma_desc_enable ||
hsotg->core_params->dma_desc_fs_enable) { hsotg->params.dma_desc_fs_enable) {
hsotg->desc_gen_cache = kmem_cache_create("dwc2-gen-desc", hsotg->desc_gen_cache = kmem_cache_create("dwc2-gen-desc",
sizeof(struct dwc2_hcd_dma_desc) * sizeof(struct dwc2_dma_desc) *
MAX_DMA_DESC_NUM_GENERIC, 512, SLAB_CACHE_DMA, MAX_DMA_DESC_NUM_GENERIC, 512, SLAB_CACHE_DMA,
NULL); NULL);
if (!hsotg->desc_gen_cache) { if (!hsotg->desc_gen_cache) {
@@ -5121,12 +5118,12 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
* Disable descriptor dma mode since it will not be * Disable descriptor dma mode since it will not be
* usable. * usable.
*/ */
hsotg->core_params->dma_desc_enable = 0; hsotg->params.dma_desc_enable = 0;
hsotg->core_params->dma_desc_fs_enable = 0; hsotg->params.dma_desc_fs_enable = 0;
} }
hsotg->desc_hsisoc_cache = kmem_cache_create("dwc2-hsisoc-desc", hsotg->desc_hsisoc_cache = kmem_cache_create("dwc2-hsisoc-desc",
sizeof(struct dwc2_hcd_dma_desc) * sizeof(struct dwc2_dma_desc) *
MAX_DMA_DESC_NUM_HS_ISOC, 512, 0, NULL); MAX_DMA_DESC_NUM_HS_ISOC, 512, 0, NULL);
if (!hsotg->desc_hsisoc_cache) { if (!hsotg->desc_hsisoc_cache) {
dev_err(hsotg->dev, dev_err(hsotg->dev,
@@ -5138,8 +5135,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
* Disable descriptor dma mode since it will not be * Disable descriptor dma mode since it will not be
* usable. * usable.
*/ */
hsotg->core_params->dma_desc_enable = 0; hsotg->params.dma_desc_enable = 0;
hsotg->core_params->dma_desc_fs_enable = 0; hsotg->params.dma_desc_fs_enable = 0;
} }
} }
@@ -5184,7 +5181,6 @@ error3:
error2: error2:
usb_put_hcd(hcd); usb_put_hcd(hcd);
error1: error1:
kfree(hsotg->core_params);
#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
kfree(hsotg->last_frame_num_array); kfree(hsotg->last_frame_num_array);
@@ -5250,7 +5246,7 @@ int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg)
hr = &hsotg->hr_backup; hr = &hsotg->hr_backup;
hr->hcfg = dwc2_readl(hsotg->regs + HCFG); hr->hcfg = dwc2_readl(hsotg->regs + HCFG);
hr->haintmsk = dwc2_readl(hsotg->regs + HAINTMSK); hr->haintmsk = dwc2_readl(hsotg->regs + HAINTMSK);
for (i = 0; i < hsotg->core_params->host_channels; ++i) for (i = 0; i < hsotg->params.host_channels; ++i)
hr->hcintmsk[i] = dwc2_readl(hsotg->regs + HCINTMSK(i)); hr->hcintmsk[i] = dwc2_readl(hsotg->regs + HCINTMSK(i));
hr->hprt0 = dwc2_read_hprt0(hsotg); hr->hprt0 = dwc2_read_hprt0(hsotg);
@@ -5286,7 +5282,7 @@ int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg)
dwc2_writel(hr->hcfg, hsotg->regs + HCFG); dwc2_writel(hr->hcfg, hsotg->regs + HCFG);
dwc2_writel(hr->haintmsk, hsotg->regs + HAINTMSK); dwc2_writel(hr->haintmsk, hsotg->regs + HAINTMSK);
for (i = 0; i < hsotg->core_params->host_channels; ++i) for (i = 0; i < hsotg->params.host_channels; ++i)
dwc2_writel(hr->hcintmsk[i], hsotg->regs + HCINTMSK(i)); dwc2_writel(hr->hcintmsk[i], hsotg->regs + HCINTMSK(i));
dwc2_writel(hr->hprt0, hsotg->regs + HPRT0); dwc2_writel(hr->hprt0, hsotg->regs + HPRT0);

View File

@@ -348,7 +348,7 @@ struct dwc2_qh {
struct list_head qtd_list; struct list_head qtd_list;
struct dwc2_host_chan *channel; struct dwc2_host_chan *channel;
struct list_head qh_list_entry; struct list_head qh_list_entry;
struct dwc2_hcd_dma_desc *desc_list; struct dwc2_dma_desc *desc_list;
dma_addr_t desc_list_dma; dma_addr_t desc_list_dma;
u32 desc_list_sz; u32 desc_list_sz;
u32 *n_bytes; u32 *n_bytes;
@@ -793,11 +793,6 @@ extern void dwc2_hcd_dump_frrem(struct dwc2_hsotg *hsotg);
#define URB_SEND_ZERO_PACKET 0x2 #define URB_SEND_ZERO_PACKET 0x2
/* Host driver callbacks */ /* Host driver callbacks */
extern void dwc2_host_start(struct dwc2_hsotg *hsotg);
extern void dwc2_host_disconnect(struct dwc2_hsotg *hsotg);
extern void dwc2_host_hub_info(struct dwc2_hsotg *hsotg, void *context,
int *hub_addr, int *hub_port);
extern struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg, extern struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg,
void *context, gfp_t mem_flags, void *context, gfp_t mem_flags,
int *ttport); int *ttport);

View File

@@ -95,7 +95,7 @@ static int dwc2_desc_list_alloc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
else else
desc_cache = hsotg->desc_gen_cache; desc_cache = hsotg->desc_gen_cache;
qh->desc_list_sz = sizeof(struct dwc2_hcd_dma_desc) * qh->desc_list_sz = sizeof(struct dwc2_dma_desc) *
dwc2_max_desc_num(qh); dwc2_max_desc_num(qh);
qh->desc_list = kmem_cache_zalloc(desc_cache, flags | GFP_DMA); qh->desc_list = kmem_cache_zalloc(desc_cache, flags | GFP_DMA);
@@ -297,7 +297,7 @@ static void dwc2_release_channel_ddma(struct dwc2_hsotg *hsotg,
struct dwc2_host_chan *chan = qh->channel; struct dwc2_host_chan *chan = qh->channel;
if (dwc2_qh_is_non_per(qh)) { if (dwc2_qh_is_non_per(qh)) {
if (hsotg->core_params->uframe_sched > 0) if (hsotg->params.uframe_sched > 0)
hsotg->available_host_channels++; hsotg->available_host_channels++;
else else
hsotg->non_periodic_channels--; hsotg->non_periodic_channels--;
@@ -322,7 +322,7 @@ static void dwc2_release_channel_ddma(struct dwc2_hsotg *hsotg,
qh->ntd = 0; qh->ntd = 0;
if (qh->desc_list) if (qh->desc_list)
memset(qh->desc_list, 0, sizeof(struct dwc2_hcd_dma_desc) * memset(qh->desc_list, 0, sizeof(struct dwc2_dma_desc) *
dwc2_max_desc_num(qh)); dwc2_max_desc_num(qh));
} }
@@ -404,7 +404,7 @@ void dwc2_hcd_qh_free_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
if ((qh->ep_type == USB_ENDPOINT_XFER_ISOC || if ((qh->ep_type == USB_ENDPOINT_XFER_ISOC ||
qh->ep_type == USB_ENDPOINT_XFER_INT) && qh->ep_type == USB_ENDPOINT_XFER_INT) &&
(hsotg->core_params->uframe_sched > 0 || (hsotg->params.uframe_sched > 0 ||
!hsotg->periodic_channels) && hsotg->frame_list) { !hsotg->periodic_channels) && hsotg->frame_list) {
dwc2_per_sched_disable(hsotg); dwc2_per_sched_disable(hsotg);
dwc2_frame_list_free(hsotg); dwc2_frame_list_free(hsotg);
@@ -542,7 +542,7 @@ static void dwc2_fill_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
struct dwc2_qh *qh, u32 max_xfer_size, struct dwc2_qh *qh, u32 max_xfer_size,
u16 idx) u16 idx)
{ {
struct dwc2_hcd_dma_desc *dma_desc = &qh->desc_list[idx]; struct dwc2_dma_desc *dma_desc = &qh->desc_list[idx];
struct dwc2_hcd_iso_packet_desc *frame_desc; struct dwc2_hcd_iso_packet_desc *frame_desc;
memset(dma_desc, 0, sizeof(*dma_desc)); memset(dma_desc, 0, sizeof(*dma_desc));
@@ -571,8 +571,8 @@ static void dwc2_fill_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
dma_sync_single_for_device(hsotg->dev, dma_sync_single_for_device(hsotg->dev,
qh->desc_list_dma + qh->desc_list_dma +
(idx * sizeof(struct dwc2_hcd_dma_desc)), (idx * sizeof(struct dwc2_dma_desc)),
sizeof(struct dwc2_hcd_dma_desc), sizeof(struct dwc2_dma_desc),
DMA_TO_DEVICE); DMA_TO_DEVICE);
} }
@@ -645,8 +645,8 @@ static void dwc2_init_isoc_dma_desc(struct dwc2_hsotg *hsotg,
qh->desc_list[idx].status |= HOST_DMA_IOC; qh->desc_list[idx].status |= HOST_DMA_IOC;
dma_sync_single_for_device(hsotg->dev, dma_sync_single_for_device(hsotg->dev,
qh->desc_list_dma + (idx * qh->desc_list_dma + (idx *
sizeof(struct dwc2_hcd_dma_desc)), sizeof(struct dwc2_dma_desc)),
sizeof(struct dwc2_hcd_dma_desc), sizeof(struct dwc2_dma_desc),
DMA_TO_DEVICE); DMA_TO_DEVICE);
} }
#else #else
@@ -679,8 +679,8 @@ static void dwc2_init_isoc_dma_desc(struct dwc2_hsotg *hsotg,
qh->desc_list[idx].status |= HOST_DMA_IOC; qh->desc_list[idx].status |= HOST_DMA_IOC;
dma_sync_single_for_device(hsotg->dev, dma_sync_single_for_device(hsotg->dev,
qh->desc_list_dma + qh->desc_list_dma +
(idx * sizeof(struct dwc2_hcd_dma_desc)), (idx * sizeof(struct dwc2_dma_desc)),
sizeof(struct dwc2_hcd_dma_desc), sizeof(struct dwc2_dma_desc),
DMA_TO_DEVICE); DMA_TO_DEVICE);
#endif #endif
} }
@@ -690,11 +690,11 @@ static void dwc2_fill_host_dma_desc(struct dwc2_hsotg *hsotg,
struct dwc2_qtd *qtd, struct dwc2_qh *qh, struct dwc2_qtd *qtd, struct dwc2_qh *qh,
int n_desc) int n_desc)
{ {
struct dwc2_hcd_dma_desc *dma_desc = &qh->desc_list[n_desc]; struct dwc2_dma_desc *dma_desc = &qh->desc_list[n_desc];
int len = chan->xfer_len; int len = chan->xfer_len;
if (len > MAX_DMA_DESC_SIZE - (chan->max_packet - 1)) if (len > HOST_DMA_NBYTES_LIMIT - (chan->max_packet - 1))
len = MAX_DMA_DESC_SIZE - (chan->max_packet - 1); len = HOST_DMA_NBYTES_LIMIT - (chan->max_packet - 1);
if (chan->ep_is_in) { if (chan->ep_is_in) {
int num_packets; int num_packets;
@@ -721,8 +721,8 @@ static void dwc2_fill_host_dma_desc(struct dwc2_hsotg *hsotg,
dma_sync_single_for_device(hsotg->dev, dma_sync_single_for_device(hsotg->dev,
qh->desc_list_dma + qh->desc_list_dma +
(n_desc * sizeof(struct dwc2_hcd_dma_desc)), (n_desc * sizeof(struct dwc2_dma_desc)),
sizeof(struct dwc2_hcd_dma_desc), sizeof(struct dwc2_dma_desc),
DMA_TO_DEVICE); DMA_TO_DEVICE);
/* /*
@@ -778,8 +778,8 @@ static void dwc2_init_non_isoc_dma_desc(struct dwc2_hsotg *hsotg,
dma_sync_single_for_device(hsotg->dev, dma_sync_single_for_device(hsotg->dev,
qh->desc_list_dma + qh->desc_list_dma +
((n_desc - 1) * ((n_desc - 1) *
sizeof(struct dwc2_hcd_dma_desc)), sizeof(struct dwc2_dma_desc)),
sizeof(struct dwc2_hcd_dma_desc), sizeof(struct dwc2_dma_desc),
DMA_TO_DEVICE); DMA_TO_DEVICE);
} }
dwc2_fill_host_dma_desc(hsotg, chan, qtd, qh, n_desc); dwc2_fill_host_dma_desc(hsotg, chan, qtd, qh, n_desc);
@@ -808,8 +808,8 @@ static void dwc2_init_non_isoc_dma_desc(struct dwc2_hsotg *hsotg,
n_desc - 1, &qh->desc_list[n_desc - 1]); n_desc - 1, &qh->desc_list[n_desc - 1]);
dma_sync_single_for_device(hsotg->dev, dma_sync_single_for_device(hsotg->dev,
qh->desc_list_dma + (n_desc - 1) * qh->desc_list_dma + (n_desc - 1) *
sizeof(struct dwc2_hcd_dma_desc), sizeof(struct dwc2_dma_desc),
sizeof(struct dwc2_hcd_dma_desc), sizeof(struct dwc2_dma_desc),
DMA_TO_DEVICE); DMA_TO_DEVICE);
if (n_desc > 1) { if (n_desc > 1) {
qh->desc_list[0].status |= HOST_DMA_A; qh->desc_list[0].status |= HOST_DMA_A;
@@ -817,7 +817,7 @@ static void dwc2_init_non_isoc_dma_desc(struct dwc2_hsotg *hsotg,
&qh->desc_list[0]); &qh->desc_list[0]);
dma_sync_single_for_device(hsotg->dev, dma_sync_single_for_device(hsotg->dev,
qh->desc_list_dma, qh->desc_list_dma,
sizeof(struct dwc2_hcd_dma_desc), sizeof(struct dwc2_dma_desc),
DMA_TO_DEVICE); DMA_TO_DEVICE);
} }
chan->ntd = n_desc; chan->ntd = n_desc;
@@ -893,7 +893,7 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
struct dwc2_qtd *qtd, struct dwc2_qtd *qtd,
struct dwc2_qh *qh, u16 idx) struct dwc2_qh *qh, u16 idx)
{ {
struct dwc2_hcd_dma_desc *dma_desc; struct dwc2_dma_desc *dma_desc;
struct dwc2_hcd_iso_packet_desc *frame_desc; struct dwc2_hcd_iso_packet_desc *frame_desc;
u16 remain = 0; u16 remain = 0;
int rc = 0; int rc = 0;
@@ -902,8 +902,8 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
return -EINVAL; return -EINVAL;
dma_sync_single_for_cpu(hsotg->dev, qh->desc_list_dma + (idx * dma_sync_single_for_cpu(hsotg->dev, qh->desc_list_dma + (idx *
sizeof(struct dwc2_hcd_dma_desc)), sizeof(struct dwc2_dma_desc)),
sizeof(struct dwc2_hcd_dma_desc), sizeof(struct dwc2_dma_desc),
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
dma_desc = &qh->desc_list[idx]; dma_desc = &qh->desc_list[idx];
@@ -1066,7 +1066,7 @@ stop_scan:
static int dwc2_update_non_isoc_urb_state_ddma(struct dwc2_hsotg *hsotg, static int dwc2_update_non_isoc_urb_state_ddma(struct dwc2_hsotg *hsotg,
struct dwc2_host_chan *chan, struct dwc2_host_chan *chan,
struct dwc2_qtd *qtd, struct dwc2_qtd *qtd,
struct dwc2_hcd_dma_desc *dma_desc, struct dwc2_dma_desc *dma_desc,
enum dwc2_halt_status halt_status, enum dwc2_halt_status halt_status,
u32 n_bytes, int *xfer_done) u32 n_bytes, int *xfer_done)
{ {
@@ -1154,7 +1154,7 @@ static int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg,
{ {
struct dwc2_qh *qh = chan->qh; struct dwc2_qh *qh = chan->qh;
struct dwc2_hcd_urb *urb = qtd->urb; struct dwc2_hcd_urb *urb = qtd->urb;
struct dwc2_hcd_dma_desc *dma_desc; struct dwc2_dma_desc *dma_desc;
u32 n_bytes; u32 n_bytes;
int failed; int failed;
@@ -1165,8 +1165,8 @@ static int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg,
dma_sync_single_for_cpu(hsotg->dev, dma_sync_single_for_cpu(hsotg->dev,
qh->desc_list_dma + (desc_num * qh->desc_list_dma + (desc_num *
sizeof(struct dwc2_hcd_dma_desc)), sizeof(struct dwc2_dma_desc)),
sizeof(struct dwc2_hcd_dma_desc), sizeof(struct dwc2_dma_desc),
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
dma_desc = &qh->desc_list[desc_num]; dma_desc = &qh->desc_list[desc_num];

View File

@@ -256,7 +256,7 @@ static void dwc2_perio_tx_fifo_empty_intr(struct dwc2_hsotg *hsotg)
static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0,
u32 *hprt0_modify) u32 *hprt0_modify)
{ {
struct dwc2_core_params *params = hsotg->core_params; struct dwc2_core_params *params = &hsotg->params;
int do_reset = 0; int do_reset = 0;
u32 usbcfg; u32 usbcfg;
u32 prtspd; u32 prtspd;
@@ -395,10 +395,10 @@ static void dwc2_port_intr(struct dwc2_hsotg *hsotg)
dwc2_hprt0_enable(hsotg, hprt0, &hprt0_modify); dwc2_hprt0_enable(hsotg, hprt0, &hprt0_modify);
} else { } else {
hsotg->flags.b.port_enable_change = 1; hsotg->flags.b.port_enable_change = 1;
if (hsotg->core_params->dma_desc_fs_enable) { if (hsotg->params.dma_desc_fs_enable) {
u32 hcfg; u32 hcfg;
hsotg->core_params->dma_desc_enable = 0; hsotg->params.dma_desc_enable = 0;
hsotg->new_connection = false; hsotg->new_connection = false;
hcfg = dwc2_readl(hsotg->regs + HCFG); hcfg = dwc2_readl(hsotg->regs + HCFG);
hcfg &= ~HCFG_DESCDMA; hcfg &= ~HCFG_DESCDMA;
@@ -604,7 +604,7 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state(
/* Skip whole frame */ /* Skip whole frame */
if (chan->qh->do_split && if (chan->qh->do_split &&
chan->ep_type == USB_ENDPOINT_XFER_ISOC && chan->ep_is_in && chan->ep_type == USB_ENDPOINT_XFER_ISOC && chan->ep_is_in &&
hsotg->core_params->dma_enable > 0) { hsotg->params.host_dma > 0) {
qtd->complete_split = 0; qtd->complete_split = 0;
qtd->isoc_split_offset = 0; qtd->isoc_split_offset = 0;
} }
@@ -743,7 +743,7 @@ cleanup:
dwc2_hc_cleanup(hsotg, chan); dwc2_hc_cleanup(hsotg, chan);
list_add_tail(&chan->hc_list_entry, &hsotg->free_hc_list); list_add_tail(&chan->hc_list_entry, &hsotg->free_hc_list);
if (hsotg->core_params->uframe_sched > 0) { if (hsotg->params.uframe_sched > 0) {
hsotg->available_host_channels++; hsotg->available_host_channels++;
} else { } else {
switch (chan->ep_type) { switch (chan->ep_type) {
@@ -789,7 +789,7 @@ static void dwc2_halt_channel(struct dwc2_hsotg *hsotg,
if (dbg_hc(chan)) if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "%s()\n", __func__); dev_vdbg(hsotg->dev, "%s()\n", __func__);
if (hsotg->core_params->dma_enable > 0) { if (hsotg->params.host_dma > 0) {
if (dbg_hc(chan)) if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "DMA enabled\n"); dev_vdbg(hsotg->dev, "DMA enabled\n");
dwc2_release_channel(hsotg, chan, qtd, halt_status); dwc2_release_channel(hsotg, chan, qtd, halt_status);
@@ -915,6 +915,8 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg,
{ {
struct dwc2_hcd_iso_packet_desc *frame_desc; struct dwc2_hcd_iso_packet_desc *frame_desc;
u32 len; u32 len;
u32 hctsiz;
u32 pid;
if (!qtd->urb) if (!qtd->urb)
return 0; return 0;
@@ -932,7 +934,10 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg,
qtd->isoc_split_offset += len; qtd->isoc_split_offset += len;
if (frame_desc->actual_length >= frame_desc->length) { hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
pid = (hctsiz & TSIZ_SC_MC_PID_MASK) >> TSIZ_SC_MC_PID_SHIFT;
if (frame_desc->actual_length >= frame_desc->length || pid == 0) {
frame_desc->status = 0; frame_desc->status = 0;
qtd->isoc_frame_index++; qtd->isoc_frame_index++;
qtd->complete_split = 0; qtd->complete_split = 0;
@@ -974,7 +979,7 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg,
pipe_type = dwc2_hcd_get_pipe_type(&urb->pipe_info); pipe_type = dwc2_hcd_get_pipe_type(&urb->pipe_info);
if (hsotg->core_params->dma_desc_enable > 0) { if (hsotg->params.dma_desc_enable > 0) {
dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, halt_status); dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, halt_status);
if (pipe_type == USB_ENDPOINT_XFER_ISOC) if (pipe_type == USB_ENDPOINT_XFER_ISOC)
/* Do not disable the interrupt, just clear it */ /* Do not disable the interrupt, just clear it */
@@ -985,7 +990,7 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg,
/* Handle xfer complete on CSPLIT */ /* Handle xfer complete on CSPLIT */
if (chan->qh->do_split) { if (chan->qh->do_split) {
if (chan->ep_type == USB_ENDPOINT_XFER_ISOC && chan->ep_is_in && if (chan->ep_type == USB_ENDPOINT_XFER_ISOC && chan->ep_is_in &&
hsotg->core_params->dma_enable > 0) { hsotg->params.host_dma > 0) {
if (qtd->complete_split && if (qtd->complete_split &&
dwc2_xfercomp_isoc_split_in(hsotg, chan, chnum, dwc2_xfercomp_isoc_split_in(hsotg, chan, chnum,
qtd)) qtd))
@@ -1097,7 +1102,7 @@ static void dwc2_hc_stall_intr(struct dwc2_hsotg *hsotg,
dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: STALL Received--\n", dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: STALL Received--\n",
chnum); chnum);
if (hsotg->core_params->dma_desc_enable > 0) { if (hsotg->params.dma_desc_enable > 0) {
dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
DWC2_HC_XFER_STALL); DWC2_HC_XFER_STALL);
goto handle_stall_done; goto handle_stall_done;
@@ -1207,7 +1212,7 @@ static void dwc2_hc_nak_intr(struct dwc2_hsotg *hsotg,
switch (dwc2_hcd_get_pipe_type(&qtd->urb->pipe_info)) { switch (dwc2_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
case USB_ENDPOINT_XFER_CONTROL: case USB_ENDPOINT_XFER_CONTROL:
case USB_ENDPOINT_XFER_BULK: case USB_ENDPOINT_XFER_BULK:
if (hsotg->core_params->dma_enable > 0 && chan->ep_is_in) { if (hsotg->params.host_dma > 0 && chan->ep_is_in) {
/* /*
* NAK interrupts are enabled on bulk/control IN * NAK interrupts are enabled on bulk/control IN
* transfers in DMA mode for the sole purpose of * transfers in DMA mode for the sole purpose of
@@ -1353,7 +1358,7 @@ static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg,
*/ */
if (chan->do_split && chan->complete_split) { if (chan->do_split && chan->complete_split) {
if (chan->ep_is_in && chan->ep_type == USB_ENDPOINT_XFER_ISOC && if (chan->ep_is_in && chan->ep_type == USB_ENDPOINT_XFER_ISOC &&
hsotg->core_params->dma_enable > 0) { hsotg->params.host_dma > 0) {
qtd->complete_split = 0; qtd->complete_split = 0;
qtd->isoc_split_offset = 0; qtd->isoc_split_offset = 0;
qtd->isoc_frame_index++; qtd->isoc_frame_index++;
@@ -1374,7 +1379,7 @@ static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg,
struct dwc2_qh *qh = chan->qh; struct dwc2_qh *qh = chan->qh;
bool past_end; bool past_end;
if (hsotg->core_params->uframe_sched <= 0) { if (hsotg->params.uframe_sched <= 0) {
int frnum = dwc2_hcd_get_frame_number(hsotg); int frnum = dwc2_hcd_get_frame_number(hsotg);
/* Don't have num_hs_transfers; simple logic */ /* Don't have num_hs_transfers; simple logic */
@@ -1467,7 +1472,7 @@ static void dwc2_hc_babble_intr(struct dwc2_hsotg *hsotg,
dwc2_hc_handle_tt_clear(hsotg, chan, qtd); dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
if (hsotg->core_params->dma_desc_enable > 0) { if (hsotg->params.dma_desc_enable > 0) {
dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
DWC2_HC_XFER_BABBLE_ERR); DWC2_HC_XFER_BABBLE_ERR);
goto disable_int; goto disable_int;
@@ -1572,7 +1577,7 @@ static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg,
dev_err(hsotg->dev, " Interval: %d\n", urb->interval); dev_err(hsotg->dev, " Interval: %d\n", urb->interval);
/* Core halts the channel for Descriptor DMA mode */ /* Core halts the channel for Descriptor DMA mode */
if (hsotg->core_params->dma_desc_enable > 0) { if (hsotg->params.dma_desc_enable > 0) {
dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
DWC2_HC_XFER_AHB_ERR); DWC2_HC_XFER_AHB_ERR);
goto handle_ahberr_done; goto handle_ahberr_done;
@@ -1604,7 +1609,7 @@ static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg,
dwc2_hc_handle_tt_clear(hsotg, chan, qtd); dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
if (hsotg->core_params->dma_desc_enable > 0) { if (hsotg->params.dma_desc_enable > 0) {
dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
DWC2_HC_XFER_XACT_ERR); DWC2_HC_XFER_XACT_ERR);
goto handle_xacterr_done; goto handle_xacterr_done;
@@ -1798,8 +1803,8 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg,
if (chan->halt_status == DWC2_HC_XFER_URB_DEQUEUE || if (chan->halt_status == DWC2_HC_XFER_URB_DEQUEUE ||
(chan->halt_status == DWC2_HC_XFER_AHB_ERR && (chan->halt_status == DWC2_HC_XFER_AHB_ERR &&
hsotg->core_params->dma_desc_enable <= 0)) { hsotg->params.dma_desc_enable <= 0)) {
if (hsotg->core_params->dma_desc_enable > 0) if (hsotg->params.dma_desc_enable > 0)
dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
chan->halt_status); chan->halt_status);
else else
@@ -1830,7 +1835,7 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg,
} else if (chan->hcint & HCINTMSK_STALL) { } else if (chan->hcint & HCINTMSK_STALL) {
dwc2_hc_stall_intr(hsotg, chan, chnum, qtd); dwc2_hc_stall_intr(hsotg, chan, chnum, qtd);
} else if ((chan->hcint & HCINTMSK_XACTERR) && } else if ((chan->hcint & HCINTMSK_XACTERR) &&
hsotg->core_params->dma_desc_enable <= 0) { hsotg->params.dma_desc_enable <= 0) {
if (out_nak_enh) { if (out_nak_enh) {
if (chan->hcint & if (chan->hcint &
(HCINTMSK_NYET | HCINTMSK_NAK | HCINTMSK_ACK)) { (HCINTMSK_NYET | HCINTMSK_NAK | HCINTMSK_ACK)) {
@@ -1850,10 +1855,10 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg,
*/ */
dwc2_hc_xacterr_intr(hsotg, chan, chnum, qtd); dwc2_hc_xacterr_intr(hsotg, chan, chnum, qtd);
} else if ((chan->hcint & HCINTMSK_XCS_XACT) && } else if ((chan->hcint & HCINTMSK_XCS_XACT) &&
hsotg->core_params->dma_desc_enable > 0) { hsotg->params.dma_desc_enable > 0) {
dwc2_hc_xacterr_intr(hsotg, chan, chnum, qtd); dwc2_hc_xacterr_intr(hsotg, chan, chnum, qtd);
} else if ((chan->hcint & HCINTMSK_AHBERR) && } else if ((chan->hcint & HCINTMSK_AHBERR) &&
hsotg->core_params->dma_desc_enable > 0) { hsotg->params.dma_desc_enable > 0) {
dwc2_hc_ahberr_intr(hsotg, chan, chnum, qtd); dwc2_hc_ahberr_intr(hsotg, chan, chnum, qtd);
} else if (chan->hcint & HCINTMSK_BBLERR) { } else if (chan->hcint & HCINTMSK_BBLERR) {
dwc2_hc_babble_intr(hsotg, chan, chnum, qtd); dwc2_hc_babble_intr(hsotg, chan, chnum, qtd);
@@ -1946,7 +1951,7 @@ static void dwc2_hc_chhltd_intr(struct dwc2_hsotg *hsotg,
dev_vdbg(hsotg->dev, "--Host Channel %d Interrupt: Channel Halted--\n", dev_vdbg(hsotg->dev, "--Host Channel %d Interrupt: Channel Halted--\n",
chnum); chnum);
if (hsotg->core_params->dma_enable > 0) { if (hsotg->params.host_dma > 0) {
dwc2_hc_chhltd_intr_dma(hsotg, chan, chnum, qtd); dwc2_hc_chhltd_intr_dma(hsotg, chan, chnum, qtd);
} else { } else {
if (!dwc2_halt_status_ok(hsotg, chan, chnum, qtd)) if (!dwc2_halt_status_ok(hsotg, chan, chnum, qtd))
@@ -2023,7 +2028,7 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
* interrupt unmasked * interrupt unmasked
*/ */
WARN_ON(hcint != HCINTMSK_CHHLTD); WARN_ON(hcint != HCINTMSK_CHHLTD);
if (hsotg->core_params->dma_desc_enable > 0) if (hsotg->params.dma_desc_enable > 0)
dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum,
chan->halt_status); chan->halt_status);
else else
@@ -2051,7 +2056,7 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
qtd = list_first_entry(&chan->qh->qtd_list, struct dwc2_qtd, qtd = list_first_entry(&chan->qh->qtd_list, struct dwc2_qtd,
qtd_list_entry); qtd_list_entry);
if (hsotg->core_params->dma_enable <= 0) { if (hsotg->params.host_dma <= 0) {
if ((hcint & HCINTMSK_CHHLTD) && hcint != HCINTMSK_CHHLTD) if ((hcint & HCINTMSK_CHHLTD) && hcint != HCINTMSK_CHHLTD)
hcint &= ~HCINTMSK_CHHLTD; hcint &= ~HCINTMSK_CHHLTD;
} }
@@ -2156,7 +2161,7 @@ static void dwc2_hc_intr(struct dwc2_hsotg *hsotg)
} }
} }
for (i = 0; i < hsotg->core_params->host_channels; i++) { for (i = 0; i < hsotg->params.host_channels; i++) {
if (haint & (1 << i)) if (haint & (1 << i))
dwc2_hc_n_intr(hsotg, i); dwc2_hc_n_intr(hsotg, i);
} }

View File

@@ -75,7 +75,7 @@ static int dwc2_periodic_channel_available(struct dwc2_hsotg *hsotg)
int status; int status;
int num_channels; int num_channels;
num_channels = hsotg->core_params->host_channels; num_channels = hsotg->params.host_channels;
if (hsotg->periodic_channels + hsotg->non_periodic_channels < if (hsotg->periodic_channels + hsotg->non_periodic_channels <
num_channels num_channels
&& hsotg->periodic_channels < num_channels - 1) { && hsotg->periodic_channels < num_channels - 1) {
@@ -355,6 +355,37 @@ static void pmap_unschedule(unsigned long *map, int bits_per_period,
} }
} }
/**
* dwc2_get_ls_map() - Get the map used for the given qh
*
* @hsotg: The HCD state structure for the DWC OTG controller.
* @qh: QH for the periodic transfer.
*
* We'll always get the periodic map out of our TT. Note that even if we're
* running the host straight in low speed / full speed mode it appears as if
* a TT is allocated for us, so we'll use it. If that ever changes we can
* add logic here to get a map out of "hsotg" if !qh->do_split.
*
* Returns: the map or NULL if a map couldn't be found.
*/
static unsigned long *dwc2_get_ls_map(struct dwc2_hsotg *hsotg,
struct dwc2_qh *qh)
{
unsigned long *map;
/* Don't expect to be missing a TT and be doing low speed scheduling */
if (WARN_ON(!qh->dwc_tt))
return NULL;
/* Get the map and adjust if this is a multi_tt hub */
map = qh->dwc_tt->periodic_bitmaps;
if (qh->dwc_tt->usb_tt->multi)
map += DWC2_ELEMENTS_PER_LS_BITMAP * qh->ttport;
return map;
}
#ifdef DWC2_PRINT_SCHEDULE
/* /*
* cat_printf() - A printf() + strcat() helper * cat_printf() - A printf() + strcat() helper
* *
@@ -454,35 +485,6 @@ static void pmap_print(unsigned long *map, int bits_per_period,
} }
} }
/**
* dwc2_get_ls_map() - Get the map used for the given qh
*
* @hsotg: The HCD state structure for the DWC OTG controller.
* @qh: QH for the periodic transfer.
*
* We'll always get the periodic map out of our TT. Note that even if we're
* running the host straight in low speed / full speed mode it appears as if
* a TT is allocated for us, so we'll use it. If that ever changes we can
* add logic here to get a map out of "hsotg" if !qh->do_split.
*
* Returns: the map or NULL if a map couldn't be found.
*/
static unsigned long *dwc2_get_ls_map(struct dwc2_hsotg *hsotg,
struct dwc2_qh *qh)
{
unsigned long *map;
/* Don't expect to be missing a TT and be doing low speed scheduling */
if (WARN_ON(!qh->dwc_tt))
return NULL;
/* Get the map and adjust if this is a multi_tt hub */
map = qh->dwc_tt->periodic_bitmaps;
if (qh->dwc_tt->usb_tt->multi)
map += DWC2_ELEMENTS_PER_LS_BITMAP * qh->ttport;
return map;
}
struct dwc2_qh_print_data { struct dwc2_qh_print_data {
struct dwc2_hsotg *hsotg; struct dwc2_hsotg *hsotg;
@@ -519,9 +521,6 @@ static void dwc2_qh_schedule_print(struct dwc2_hsotg *hsotg,
* If we don't have tracing turned on, don't run unless the special * If we don't have tracing turned on, don't run unless the special
* define is turned on. * define is turned on.
*/ */
#ifndef DWC2_PRINT_SCHEDULE
return;
#endif
if (qh->schedule_low_speed) { if (qh->schedule_low_speed) {
unsigned long *map = dwc2_get_ls_map(hsotg, qh); unsigned long *map = dwc2_get_ls_map(hsotg, qh);
@@ -559,8 +558,12 @@ static void dwc2_qh_schedule_print(struct dwc2_hsotg *hsotg,
DWC2_HS_SCHEDULE_UFRAMES, "uFrame", "us", DWC2_HS_SCHEDULE_UFRAMES, "uFrame", "us",
dwc2_qh_print, &print_data); dwc2_qh_print, &print_data);
} }
return;
} }
#else
static inline void dwc2_qh_schedule_print(struct dwc2_hsotg *hsotg,
struct dwc2_qh *qh) {};
#endif
/** /**
* dwc2_ls_pmap_schedule() - Schedule a low speed QH * dwc2_ls_pmap_schedule() - Schedule a low speed QH
@@ -1104,7 +1107,7 @@ static void dwc2_pick_first_frame(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
next_active_frame = earliest_frame; next_active_frame = earliest_frame;
/* Get the "no microframe schduler" out of the way... */ /* Get the "no microframe schduler" out of the way... */
if (hsotg->core_params->uframe_sched <= 0) { if (hsotg->params.uframe_sched <= 0) {
if (qh->do_split) if (qh->do_split)
/* Splits are active at microframe 0 minus 1 */ /* Splits are active at microframe 0 minus 1 */
next_active_frame |= 0x7; next_active_frame |= 0x7;
@@ -1197,7 +1200,7 @@ static int dwc2_do_reserve(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{ {
int status; int status;
if (hsotg->core_params->uframe_sched > 0) { if (hsotg->params.uframe_sched > 0) {
status = dwc2_uframe_schedule(hsotg, qh); status = dwc2_uframe_schedule(hsotg, qh);
} else { } else {
status = dwc2_periodic_channel_available(hsotg); status = dwc2_periodic_channel_available(hsotg);
@@ -1218,7 +1221,7 @@ static int dwc2_do_reserve(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
return status; return status;
} }
if (hsotg->core_params->uframe_sched <= 0) if (hsotg->params.uframe_sched <= 0)
/* Reserve periodic channel */ /* Reserve periodic channel */
hsotg->periodic_channels++; hsotg->periodic_channels++;
@@ -1254,7 +1257,7 @@ static void dwc2_do_unreserve(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
/* Update claimed usecs per (micro)frame */ /* Update claimed usecs per (micro)frame */
hsotg->periodic_usecs -= qh->host_us; hsotg->periodic_usecs -= qh->host_us;
if (hsotg->core_params->uframe_sched > 0) { if (hsotg->params.uframe_sched > 0) {
dwc2_uframe_unschedule(hsotg, qh); dwc2_uframe_unschedule(hsotg, qh);
} else { } else {
/* Release periodic channel reservation */ /* Release periodic channel reservation */
@@ -1328,7 +1331,7 @@ static int dwc2_check_max_xfer_size(struct dwc2_hsotg *hsotg,
int status = 0; int status = 0;
max_xfer_size = dwc2_max_packet(qh->maxp) * dwc2_hb_mult(qh->maxp); max_xfer_size = dwc2_max_packet(qh->maxp) * dwc2_hb_mult(qh->maxp);
max_channel_xfer_size = hsotg->core_params->max_transfer_size; max_channel_xfer_size = hsotg->params.max_transfer_size;
if (max_xfer_size > max_channel_xfer_size) { if (max_xfer_size > max_channel_xfer_size) {
dev_err(hsotg->dev, dev_err(hsotg->dev,
@@ -1391,7 +1394,7 @@ static int dwc2_schedule_periodic(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
qh->unreserve_pending = 0; qh->unreserve_pending = 0;
if (hsotg->core_params->dma_desc_enable > 0) if (hsotg->params.dma_desc_enable > 0)
/* Don't rely on SOF and start in ready schedule */ /* Don't rely on SOF and start in ready schedule */
list_add_tail(&qh->qh_list_entry, &hsotg->periodic_sched_ready); list_add_tail(&qh->qh_list_entry, &hsotg->periodic_sched_ready);
else else
@@ -1599,7 +1602,7 @@ struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
dwc2_qh_init(hsotg, qh, urb, mem_flags); dwc2_qh_init(hsotg, qh, urb, mem_flags);
if (hsotg->core_params->dma_desc_enable > 0 && if (hsotg->params.dma_desc_enable > 0 &&
dwc2_hcd_qh_init_ddma(hsotg, qh, mem_flags) < 0) { dwc2_hcd_qh_init_ddma(hsotg, qh, mem_flags) < 0) {
dwc2_hcd_qh_free(hsotg, qh); dwc2_hcd_qh_free(hsotg, qh);
return NULL; return NULL;
@@ -1711,7 +1714,7 @@ void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
dwc2_deschedule_periodic(hsotg, qh); dwc2_deschedule_periodic(hsotg, qh);
hsotg->periodic_qh_count--; hsotg->periodic_qh_count--;
if (!hsotg->periodic_qh_count && if (!hsotg->periodic_qh_count &&
hsotg->core_params->dma_desc_enable <= 0) { hsotg->params.dma_desc_enable <= 0) {
intr_mask = dwc2_readl(hsotg->regs + GINTMSK); intr_mask = dwc2_readl(hsotg->regs + GINTMSK);
intr_mask &= ~GINTSTS_SOF; intr_mask &= ~GINTSTS_SOF;
dwc2_writel(intr_mask, hsotg->regs + GINTMSK); dwc2_writel(intr_mask, hsotg->regs + GINTMSK);

View File

@@ -412,6 +412,7 @@
/* Device mode registers */ /* Device mode registers */
#define DCFG HSOTG_REG(0x800) #define DCFG HSOTG_REG(0x800)
#define DCFG_DESCDMA_EN (1 << 23)
#define DCFG_EPMISCNT_MASK (0x1f << 18) #define DCFG_EPMISCNT_MASK (0x1f << 18)
#define DCFG_EPMISCNT_SHIFT 18 #define DCFG_EPMISCNT_SHIFT 18
#define DCFG_EPMISCNT_LIMIT 0x1f #define DCFG_EPMISCNT_LIMIT 0x1f
@@ -473,6 +474,7 @@
#define DIEPMSK_XFERCOMPLMSK (1 << 0) #define DIEPMSK_XFERCOMPLMSK (1 << 0)
#define DOEPMSK HSOTG_REG(0x814) #define DOEPMSK HSOTG_REG(0x814)
#define DOEPMSK_BNAMSK (1 << 9)
#define DOEPMSK_BACK2BACKSETUP (1 << 6) #define DOEPMSK_BACK2BACKSETUP (1 << 6)
#define DOEPMSK_STSPHSERCVDMSK (1 << 5) #define DOEPMSK_STSPHSERCVDMSK (1 << 5)
#define DOEPMSK_OUTTKNEPDISMSK (1 << 4) #define DOEPMSK_OUTTKNEPDISMSK (1 << 4)
@@ -790,7 +792,8 @@
#define HCFIFO(_ch) HSOTG_REG(0x1000 + 0x1000 * (_ch)) #define HCFIFO(_ch) HSOTG_REG(0x1000 + 0x1000 * (_ch))
/** /**
* struct dwc2_hcd_dma_desc - Host-mode DMA descriptor structure * struct dwc2_dma_desc - DMA descriptor structure,
* used for both host and gadget modes
* *
* @status: DMA descriptor status quadlet * @status: DMA descriptor status quadlet
* @buf: DMA descriptor data buffer pointer * @buf: DMA descriptor data buffer pointer
@@ -798,10 +801,12 @@
* DMA Descriptor structure contains two quadlets: * DMA Descriptor structure contains two quadlets:
* Status quadlet and Data buffer pointer. * Status quadlet and Data buffer pointer.
*/ */
struct dwc2_hcd_dma_desc { struct dwc2_dma_desc {
u32 status; u32 status;
u32 buf; u32 buf;
}; } __packed;
/* Host Mode DMA descriptor status quadlet */
#define HOST_DMA_A (1 << 31) #define HOST_DMA_A (1 << 31)
#define HOST_DMA_STS_MASK (0x3 << 28) #define HOST_DMA_STS_MASK (0x3 << 28)
@@ -817,8 +822,43 @@ struct dwc2_hcd_dma_desc {
#define HOST_DMA_ISOC_NBYTES_SHIFT 0 #define HOST_DMA_ISOC_NBYTES_SHIFT 0
#define HOST_DMA_NBYTES_MASK (0x1ffff << 0) #define HOST_DMA_NBYTES_MASK (0x1ffff << 0)
#define HOST_DMA_NBYTES_SHIFT 0 #define HOST_DMA_NBYTES_SHIFT 0
#define HOST_DMA_NBYTES_LIMIT 131071
/* Device Mode DMA descriptor status quadlet */
#define DEV_DMA_BUFF_STS_MASK (0x3 << 30)
#define DEV_DMA_BUFF_STS_SHIFT 30
#define DEV_DMA_BUFF_STS_HREADY 0
#define DEV_DMA_BUFF_STS_DMABUSY 1
#define DEV_DMA_BUFF_STS_DMADONE 2
#define DEV_DMA_BUFF_STS_HBUSY 3
#define DEV_DMA_STS_MASK (0x3 << 28)
#define DEV_DMA_STS_SHIFT 28
#define DEV_DMA_STS_SUCC 0
#define DEV_DMA_STS_BUFF_FLUSH 1
#define DEV_DMA_STS_BUFF_ERR 3
#define DEV_DMA_L (1 << 27)
#define DEV_DMA_SHORT (1 << 26)
#define DEV_DMA_IOC (1 << 25)
#define DEV_DMA_SR (1 << 24)
#define DEV_DMA_MTRF (1 << 23)
#define DEV_DMA_ISOC_PID_MASK (0x3 << 23)
#define DEV_DMA_ISOC_PID_SHIFT 23
#define DEV_DMA_ISOC_PID_DATA0 0
#define DEV_DMA_ISOC_PID_DATA2 1
#define DEV_DMA_ISOC_PID_DATA1 2
#define DEV_DMA_ISOC_PID_MDATA 3
#define DEV_DMA_ISOC_FRNUM_MASK (0x7ff << 12)
#define DEV_DMA_ISOC_FRNUM_SHIFT 12
#define DEV_DMA_ISOC_TX_NBYTES_MASK (0xfff << 0)
#define DEV_DMA_ISOC_TX_NBYTES_LIMIT 0xfff
#define DEV_DMA_ISOC_RX_NBYTES_MASK (0x7ff << 0)
#define DEV_DMA_ISOC_RX_NBYTES_LIMIT 0x7ff
#define DEV_DMA_ISOC_NBYTES_SHIFT 0
#define DEV_DMA_NBYTES_MASK (0xffff << 0)
#define DEV_DMA_NBYTES_SHIFT 0
#define DEV_DMA_NBYTES_LIMIT 0xffff
#define MAX_DMA_DESC_SIZE 131071
#define MAX_DMA_DESC_NUM_GENERIC 64 #define MAX_DMA_DESC_NUM_GENERIC 64
#define MAX_DMA_DESC_NUM_HS_ISOC 256 #define MAX_DMA_DESC_NUM_HS_ISOC 256

1435
drivers/usb/dwc2/params.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -62,6 +62,20 @@ struct dwc2_pci_glue {
struct platform_device *phy; struct platform_device *phy;
}; };
static int dwc2_pci_quirks(struct pci_dev *pdev, struct platform_device *dwc2)
{
if (pdev->vendor == PCI_VENDOR_ID_SYNOPSYS &&
pdev->device == PCI_PRODUCT_ID_HAPS_HSOTG) {
struct property_entry properties[] = {
{ },
};
return platform_device_add_properties(dwc2, properties);
}
return 0;
}
static void dwc2_pci_remove(struct pci_dev *pci) static void dwc2_pci_remove(struct pci_dev *pci)
{ {
struct dwc2_pci_glue *glue = pci_get_drvdata(pci); struct dwc2_pci_glue *glue = pci_get_drvdata(pci);
@@ -122,6 +136,10 @@ static int dwc2_pci_probe(struct pci_dev *pci,
return PTR_ERR(phy); return PTR_ERR(phy);
} }
ret = dwc2_pci_quirks(pci, dwc2);
if (ret)
goto err;
ret = platform_device_add(dwc2); ret = platform_device_add(dwc2);
if (ret) { if (ret) {
dev_err(dev, "failed to register dwc2 device\n"); dev_err(dev, "failed to register dwc2 device\n");

View File

@@ -55,165 +55,6 @@
static const char dwc2_driver_name[] = "dwc2"; static const char dwc2_driver_name[] = "dwc2";
static const struct dwc2_core_params params_hi6220 = {
.otg_cap = 2, /* No HNP/SRP capable */
.otg_ver = 0, /* 1.3 */
.dma_enable = 1,
.dma_desc_enable = 0,
.dma_desc_fs_enable = 0,
.speed = 0, /* High Speed */
.enable_dynamic_fifo = 1,
.en_multiple_tx_fifo = 1,
.host_rx_fifo_size = 512,
.host_nperio_tx_fifo_size = 512,
.host_perio_tx_fifo_size = 512,
.max_transfer_size = 65535,
.max_packet_count = 511,
.host_channels = 16,
.phy_type = 1, /* UTMI */
.phy_utmi_width = 8,
.phy_ulpi_ddr = 0, /* Single */
.phy_ulpi_ext_vbus = 0,
.i2c_enable = 0,
.ulpi_fs_ls = 0,
.host_support_fs_ls_low_power = 0,
.host_ls_low_power_phy_clk = 0, /* 48 MHz */
.ts_dline = 0,
.reload_ctl = 0,
.ahbcfg = GAHBCFG_HBSTLEN_INCR16 <<
GAHBCFG_HBSTLEN_SHIFT,
.uframe_sched = 0,
.external_id_pin_ctl = -1,
.hibernation = -1,
};
static const struct dwc2_core_params params_bcm2835 = {
.otg_cap = 0, /* HNP/SRP capable */
.otg_ver = 0, /* 1.3 */
.dma_enable = 1,
.dma_desc_enable = 0,
.dma_desc_fs_enable = 0,
.speed = 0, /* High Speed */
.enable_dynamic_fifo = 1,
.en_multiple_tx_fifo = 1,
.host_rx_fifo_size = 774, /* 774 DWORDs */
.host_nperio_tx_fifo_size = 256, /* 256 DWORDs */
.host_perio_tx_fifo_size = 512, /* 512 DWORDs */
.max_transfer_size = 65535,
.max_packet_count = 511,
.host_channels = 8,
.phy_type = 1, /* UTMI */
.phy_utmi_width = 8, /* 8 bits */
.phy_ulpi_ddr = 0, /* Single */
.phy_ulpi_ext_vbus = 0,
.i2c_enable = 0,
.ulpi_fs_ls = 0,
.host_support_fs_ls_low_power = 0,
.host_ls_low_power_phy_clk = 0, /* 48 MHz */
.ts_dline = 0,
.reload_ctl = 0,
.ahbcfg = 0x10,
.uframe_sched = 0,
.external_id_pin_ctl = -1,
.hibernation = -1,
};
static const struct dwc2_core_params params_rk3066 = {
.otg_cap = 2, /* non-HNP/non-SRP */
.otg_ver = -1,
.dma_enable = -1,
.dma_desc_enable = 0,
.dma_desc_fs_enable = 0,
.speed = -1,
.enable_dynamic_fifo = 1,
.en_multiple_tx_fifo = -1,
.host_rx_fifo_size = 525, /* 525 DWORDs */
.host_nperio_tx_fifo_size = 128, /* 128 DWORDs */
.host_perio_tx_fifo_size = 256, /* 256 DWORDs */
.max_transfer_size = -1,
.max_packet_count = -1,
.host_channels = -1,
.phy_type = -1,
.phy_utmi_width = -1,
.phy_ulpi_ddr = -1,
.phy_ulpi_ext_vbus = -1,
.i2c_enable = -1,
.ulpi_fs_ls = -1,
.host_support_fs_ls_low_power = -1,
.host_ls_low_power_phy_clk = -1,
.ts_dline = -1,
.reload_ctl = -1,
.ahbcfg = GAHBCFG_HBSTLEN_INCR16 <<
GAHBCFG_HBSTLEN_SHIFT,
.uframe_sched = -1,
.external_id_pin_ctl = -1,
.hibernation = -1,
};
static const struct dwc2_core_params params_ltq = {
.otg_cap = 2, /* non-HNP/non-SRP */
.otg_ver = -1,
.dma_enable = -1,
.dma_desc_enable = -1,
.dma_desc_fs_enable = -1,
.speed = -1,
.enable_dynamic_fifo = -1,
.en_multiple_tx_fifo = -1,
.host_rx_fifo_size = 288, /* 288 DWORDs */
.host_nperio_tx_fifo_size = 128, /* 128 DWORDs */
.host_perio_tx_fifo_size = 96, /* 96 DWORDs */
.max_transfer_size = 65535,
.max_packet_count = 511,
.host_channels = -1,
.phy_type = -1,
.phy_utmi_width = -1,
.phy_ulpi_ddr = -1,
.phy_ulpi_ext_vbus = -1,
.i2c_enable = -1,
.ulpi_fs_ls = -1,
.host_support_fs_ls_low_power = -1,
.host_ls_low_power_phy_clk = -1,
.ts_dline = -1,
.reload_ctl = -1,
.ahbcfg = GAHBCFG_HBSTLEN_INCR16 <<
GAHBCFG_HBSTLEN_SHIFT,
.uframe_sched = -1,
.external_id_pin_ctl = -1,
.hibernation = -1,
};
static const struct dwc2_core_params params_amlogic = {
.otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE,
.otg_ver = -1,
.dma_enable = 1,
.dma_desc_enable = 0,
.dma_desc_fs_enable = 0,
.speed = DWC2_SPEED_PARAM_HIGH,
.enable_dynamic_fifo = 1,
.en_multiple_tx_fifo = -1,
.host_rx_fifo_size = 512,
.host_nperio_tx_fifo_size = 500,
.host_perio_tx_fifo_size = 500,
.max_transfer_size = -1,
.max_packet_count = -1,
.host_channels = 16,
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
.phy_utmi_width = -1,
.phy_ulpi_ddr = -1,
.phy_ulpi_ext_vbus = -1,
.i2c_enable = -1,
.ulpi_fs_ls = -1,
.host_support_fs_ls_low_power = -1,
.host_ls_low_power_phy_clk = -1,
.ts_dline = -1,
.reload_ctl = 1,
.ahbcfg = GAHBCFG_HBSTLEN_INCR8 <<
GAHBCFG_HBSTLEN_SHIFT,
.uframe_sched = 0,
.external_id_pin_ctl = -1,
.hibernation = -1,
};
/* /*
* Check the dr_mode against the module configuration and hardware * Check the dr_mode against the module configuration and hardware
* capabilities. * capabilities.
@@ -510,20 +351,6 @@ static void dwc2_driver_shutdown(struct platform_device *dev)
disable_irq(hsotg->irq); disable_irq(hsotg->irq);
} }
static const struct of_device_id dwc2_of_match_table[] = {
{ .compatible = "brcm,bcm2835-usb", .data = &params_bcm2835 },
{ .compatible = "hisilicon,hi6220-usb", .data = &params_hi6220 },
{ .compatible = "rockchip,rk3066-usb", .data = &params_rk3066 },
{ .compatible = "lantiq,arx100-usb", .data = &params_ltq },
{ .compatible = "lantiq,xrx200-usb", .data = &params_ltq },
{ .compatible = "snps,dwc2", .data = NULL },
{ .compatible = "samsung,s3c6400-hsotg", .data = NULL},
{ .compatible = "amlogic,meson8b-usb", .data = &params_amlogic },
{ .compatible = "amlogic,meson-gxbb-usb", .data = &params_amlogic },
{},
};
MODULE_DEVICE_TABLE(of, dwc2_of_match_table);
/** /**
* dwc2_driver_probe() - Called when the DWC_otg core is bound to the DWC_otg * dwc2_driver_probe() - Called when the DWC_otg core is bound to the DWC_otg
* driver * driver
@@ -538,30 +365,10 @@ MODULE_DEVICE_TABLE(of, dwc2_of_match_table);
*/ */
static int dwc2_driver_probe(struct platform_device *dev) static int dwc2_driver_probe(struct platform_device *dev)
{ {
const struct of_device_id *match;
const struct dwc2_core_params *params;
struct dwc2_core_params defparams;
struct dwc2_hsotg *hsotg; struct dwc2_hsotg *hsotg;
struct resource *res; struct resource *res;
int retval; int retval;
match = of_match_device(dwc2_of_match_table, &dev->dev);
if (match && match->data) {
params = match->data;
} else {
/* Default all params to autodetect */
dwc2_set_all_params(&defparams, -1);
params = &defparams;
/*
* Disable descriptor dma mode by default as the HW can support
* it, but does not support it for SPLIT transactions.
* Disable it for FS devices as well.
*/
defparams.dma_desc_enable = 0;
defparams.dma_desc_fs_enable = 0;
}
hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL); hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL);
if (!hsotg) if (!hsotg)
return -ENOMEM; return -ENOMEM;
@@ -591,13 +398,6 @@ static int dwc2_driver_probe(struct platform_device *dev)
spin_lock_init(&hsotg->lock); spin_lock_init(&hsotg->lock);
hsotg->core_params = devm_kzalloc(&dev->dev,
sizeof(*hsotg->core_params), GFP_KERNEL);
if (!hsotg->core_params)
return -ENOMEM;
dwc2_set_all_params(hsotg->core_params, -1);
hsotg->irq = platform_get_irq(dev, 0); hsotg->irq = platform_get_irq(dev, 0);
if (hsotg->irq < 0) { if (hsotg->irq < 0) {
dev_err(&dev->dev, "missing IRQ resource\n"); dev_err(&dev->dev, "missing IRQ resource\n");
@@ -631,11 +431,12 @@ static int dwc2_driver_probe(struct platform_device *dev)
if (retval) if (retval)
goto error; goto error;
/* Validate parameter values */
dwc2_set_parameters(hsotg, params);
dwc2_force_dr_mode(hsotg); dwc2_force_dr_mode(hsotg);
retval = dwc2_init_params(hsotg);
if (retval)
goto error;
if (hsotg->dr_mode != USB_DR_MODE_HOST) { if (hsotg->dr_mode != USB_DR_MODE_HOST) {
retval = dwc2_gadget_init(hsotg, hsotg->irq); retval = dwc2_gadget_init(hsotg, hsotg->irq);
if (retval) if (retval)

View File

@@ -62,7 +62,7 @@ config USB_DWC3_OMAP
config USB_DWC3_EXYNOS config USB_DWC3_EXYNOS
tristate "Samsung Exynos Platform" tristate "Samsung Exynos Platform"
depends on ARCH_EXYNOS && OF || COMPILE_TEST depends on (ARCH_EXYNOS || COMPILE_TEST) && OF
default USB_DWC3 default USB_DWC3
help help
Recent Exynos5 SoCs ship with one DesignWare Core USB3 IP inside, Recent Exynos5 SoCs ship with one DesignWare Core USB3 IP inside,
@@ -70,7 +70,7 @@ config USB_DWC3_EXYNOS
config USB_DWC3_PCI config USB_DWC3_PCI
tristate "PCIe-based Platforms" tristate "PCIe-based Platforms"
depends on PCI depends on PCI && ACPI
default USB_DWC3 default USB_DWC3
help help
If you're using the DesignWare Core IP with a PCIe, please say If you're using the DesignWare Core IP with a PCIe, please say
@@ -98,7 +98,7 @@ config USB_DWC3_OF_SIMPLE
config USB_DWC3_ST config USB_DWC3_ST
tristate "STMicroelectronics Platforms" tristate "STMicroelectronics Platforms"
depends on ARCH_STI && OF depends on (ARCH_STI || COMPILE_TEST) && OF
default USB_DWC3 default USB_DWC3
help help
STMicroelectronics SoCs with one DesignWare Core USB3 IP STMicroelectronics SoCs with one DesignWare Core USB3 IP

View File

@@ -3,7 +3,11 @@ CFLAGS_trace.o := -I$(src)
obj-$(CONFIG_USB_DWC3) += dwc3.o obj-$(CONFIG_USB_DWC3) += dwc3.o
dwc3-y := core.o debug.o trace.o dwc3-y := core.o
ifneq ($(CONFIG_FTRACE),)
dwc3-y += trace.o
endif
ifneq ($(filter y,$(CONFIG_USB_DWC3_HOST) $(CONFIG_USB_DWC3_DUAL_ROLE)),) ifneq ($(filter y,$(CONFIG_USB_DWC3_HOST) $(CONFIG_USB_DWC3_DUAL_ROLE)),)
dwc3-y += host.o dwc3-y += host.o

View File

@@ -169,33 +169,6 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
return -ETIMEDOUT; return -ETIMEDOUT;
} }
/**
* dwc3_soft_reset - Issue soft reset
* @dwc: Pointer to our controller context structure
*/
static int dwc3_soft_reset(struct dwc3 *dwc)
{
unsigned long timeout;
u32 reg;
timeout = jiffies + msecs_to_jiffies(500);
dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
do {
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
if (!(reg & DWC3_DCTL_CSFTRST))
break;
if (time_after(jiffies, timeout)) {
dev_err(dwc->dev, "Reset Timed Out\n");
return -ETIMEDOUT;
}
cpu_relax();
} while (true);
return 0;
}
/* /*
* dwc3_frame_length_adjustment - Adjusts frame length if required * dwc3_frame_length_adjustment - Adjusts frame length if required
* @dwc3: Pointer to our controller context structure * @dwc3: Pointer to our controller context structure
@@ -229,7 +202,7 @@ static void dwc3_frame_length_adjustment(struct dwc3 *dwc)
static void dwc3_free_one_event_buffer(struct dwc3 *dwc, static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
struct dwc3_event_buffer *evt) struct dwc3_event_buffer *evt)
{ {
dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); dma_free_coherent(dwc->sysdev, evt->length, evt->buf, evt->dma);
} }
/** /**
@@ -251,7 +224,11 @@ static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
evt->dwc = dwc; evt->dwc = dwc;
evt->length = length; evt->length = length;
evt->buf = dma_alloc_coherent(dwc->dev, length, evt->cache = devm_kzalloc(dwc->dev, length, GFP_KERNEL);
if (!evt->cache)
return ERR_PTR(-ENOMEM);
evt->buf = dma_alloc_coherent(dwc->sysdev, length,
&evt->dma, GFP_KERNEL); &evt->dma, GFP_KERNEL);
if (!evt->buf) if (!evt->buf)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
@@ -305,13 +282,7 @@ static int dwc3_event_buffers_setup(struct dwc3 *dwc)
struct dwc3_event_buffer *evt; struct dwc3_event_buffer *evt;
evt = dwc->ev_buf; evt = dwc->ev_buf;
dwc3_trace(trace_dwc3_core,
"Event buf %p dma %08llx length %d\n",
evt->buf, (unsigned long long) evt->dma,
evt->length);
evt->lpos = 0; evt->lpos = 0;
dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0),
lower_32_bits(evt->dma)); lower_32_bits(evt->dma));
dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0),
@@ -370,11 +341,11 @@ static int dwc3_setup_scratch_buffers(struct dwc3 *dwc)
if (!WARN_ON(dwc->scratchbuf)) if (!WARN_ON(dwc->scratchbuf))
return 0; return 0;
scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf, scratch_addr = dma_map_single(dwc->sysdev, dwc->scratchbuf,
dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
DMA_BIDIRECTIONAL); DMA_BIDIRECTIONAL);
if (dma_mapping_error(dwc->dev, scratch_addr)) { if (dma_mapping_error(dwc->sysdev, scratch_addr)) {
dev_err(dwc->dev, "failed to map scratch buffer\n"); dev_err(dwc->sysdev, "failed to map scratch buffer\n");
ret = -EFAULT; ret = -EFAULT;
goto err0; goto err0;
} }
@@ -398,7 +369,7 @@ static int dwc3_setup_scratch_buffers(struct dwc3 *dwc)
return 0; return 0;
err1: err1:
dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * dma_unmap_single(dwc->sysdev, dwc->scratch_addr, dwc->nr_scratch *
DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
err0: err0:
@@ -417,7 +388,7 @@ static void dwc3_free_scratch_buffers(struct dwc3 *dwc)
if (!WARN_ON(dwc->scratchbuf)) if (!WARN_ON(dwc->scratchbuf))
return; return;
dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * dma_unmap_single(dwc->sysdev, dwc->scratch_addr, dwc->nr_scratch *
DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
kfree(dwc->scratchbuf); kfree(dwc->scratchbuf);
} }
@@ -428,9 +399,6 @@ static void dwc3_core_num_eps(struct dwc3 *dwc)
dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
dwc3_trace(trace_dwc3_core, "found %d IN and %d OUT endpoints",
dwc->num_in_eps, dwc->num_out_eps);
} }
static void dwc3_cache_hwparams(struct dwc3 *dwc) static void dwc3_cache_hwparams(struct dwc3 *dwc)
@@ -524,13 +492,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI:
/* Making sure the interface and PHY are operational */
ret = dwc3_soft_reset(dwc);
if (ret)
return ret;
udelay(1);
ret = dwc3_ulpi_init(dwc); ret = dwc3_ulpi_init(dwc);
if (ret) if (ret)
return ret; return ret;
@@ -594,19 +555,12 @@ static void dwc3_core_exit(struct dwc3 *dwc)
phy_power_off(dwc->usb3_generic_phy); phy_power_off(dwc->usb3_generic_phy);
} }
/** static bool dwc3_core_is_valid(struct dwc3 *dwc)
* dwc3_core_init - Low-level initialization of DWC3 Core
* @dwc: Pointer to our controller context structure
*
* Returns 0 on success otherwise negative errno.
*/
static int dwc3_core_init(struct dwc3 *dwc)
{ {
u32 hwparams4 = dwc->hwparams.hwparams4;
u32 reg; u32 reg;
int ret;
reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
/* This should read as U3 followed by revision number */ /* This should read as U3 followed by revision number */
if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) { if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) {
/* Detected DWC_usb3 IP */ /* Detected DWC_usb3 IP */
@@ -616,36 +570,16 @@ static int dwc3_core_init(struct dwc3 *dwc)
dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER);
dwc->revision |= DWC3_REVISION_IS_DWC31; dwc->revision |= DWC3_REVISION_IS_DWC31;
} else { } else {
dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); return false;
ret = -ENODEV;
goto err0;
} }
/* return true;
* Write Linux Version Code to our GUID register so it's easy to figure }
* out which kernel version a bug was found.
*/
dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE);
/* Handle USB2.0-only core configuration */ static void dwc3_core_setup_global_control(struct dwc3 *dwc)
if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == {
DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { u32 hwparams4 = dwc->hwparams.hwparams4;
if (dwc->maximum_speed == USB_SPEED_SUPER) u32 reg;
dwc->maximum_speed = USB_SPEED_HIGH;
}
/* issue device SoftReset too */
ret = dwc3_soft_reset(dwc);
if (ret)
goto err0;
ret = dwc3_core_soft_reset(dwc);
if (ret)
goto err0;
ret = dwc3_phy_setup(dwc);
if (ret)
goto err0;
reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg = dwc3_readl(dwc->regs, DWC3_GCTL);
reg &= ~DWC3_GCTL_SCALEDOWN_MASK; reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
@@ -683,13 +617,13 @@ static int dwc3_core_init(struct dwc3 *dwc)
reg |= DWC3_GCTL_GBLHIBERNATIONEN; reg |= DWC3_GCTL_GBLHIBERNATIONEN;
break; break;
default: default:
dwc3_trace(trace_dwc3_core, "No power optimization available\n"); /* nothing */
break;
} }
/* check if current dwc3 is on simulation board */ /* check if current dwc3 is on simulation board */
if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) {
dwc3_trace(trace_dwc3_core, dev_info(dwc->dev, "Running with FPGA optmizations\n");
"running on FPGA platform\n");
dwc->is_fpga = true; dwc->is_fpga = true;
} }
@@ -714,7 +648,47 @@ static int dwc3_core_init(struct dwc3 *dwc)
reg |= DWC3_GCTL_U2RSTECN; reg |= DWC3_GCTL_U2RSTECN;
dwc3_writel(dwc->regs, DWC3_GCTL, reg); dwc3_writel(dwc->regs, DWC3_GCTL, reg);
}
/**
* dwc3_core_init - Low-level initialization of DWC3 Core
* @dwc: Pointer to our controller context structure
*
* Returns 0 on success otherwise negative errno.
*/
static int dwc3_core_init(struct dwc3 *dwc)
{
u32 reg;
int ret;
if (!dwc3_core_is_valid(dwc)) {
dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
ret = -ENODEV;
goto err0;
}
/*
* Write Linux Version Code to our GUID register so it's easy to figure
* out which kernel version a bug was found.
*/
dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE);
/* Handle USB2.0-only core configuration */
if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
DWC3_GHWPARAMS3_SSPHY_IFC_DIS) {
if (dwc->maximum_speed == USB_SPEED_SUPER)
dwc->maximum_speed = USB_SPEED_HIGH;
}
ret = dwc3_core_soft_reset(dwc);
if (ret)
goto err0;
ret = dwc3_phy_setup(dwc);
if (ret)
goto err0;
dwc3_core_setup_global_control(dwc);
dwc3_core_num_eps(dwc); dwc3_core_num_eps(dwc);
ret = dwc3_setup_scratch_buffers(dwc); ret = dwc3_setup_scratch_buffers(dwc);
@@ -766,6 +740,16 @@ static int dwc3_core_init(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); dwc3_writel(dwc->regs, DWC3_GUCTL2, reg);
} }
/*
* Enable hardware control of sending remote wakeup in HS when
* the device is in the L1 state.
*/
if (dwc->revision >= DWC3_REVISION_290A) {
reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW;
dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
}
return 0; return 0;
err4: err4:
@@ -919,57 +903,13 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)
} }
} }
#define DWC3_ALIGN_MASK (16 - 1) static void dwc3_get_properties(struct dwc3 *dwc)
static int dwc3_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = dwc->dev;
struct resource *res;
struct dwc3 *dwc;
u8 lpm_nyet_threshold; u8 lpm_nyet_threshold;
u8 tx_de_emphasis; u8 tx_de_emphasis;
u8 hird_threshold; u8 hird_threshold;
int ret;
void __iomem *regs;
void *mem;
mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
if (!mem)
return -ENOMEM;
dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
dwc->mem = mem;
dwc->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "missing memory resource\n");
return -ENODEV;
}
dwc->xhci_resources[0].start = res->start;
dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
DWC3_XHCI_REGS_END;
dwc->xhci_resources[0].flags = res->flags;
dwc->xhci_resources[0].name = res->name;
res->start += DWC3_GLOBALS_REGS_START;
/*
* Request memory region but exclude xHCI regs,
* since it will be requested by the xhci-plat driver.
*/
regs = devm_ioremap_resource(dev, res);
if (IS_ERR(regs)) {
ret = PTR_ERR(regs);
goto err0;
}
dwc->regs = regs;
dwc->regs_size = resource_size(res);
/* default to highest possible threshold */ /* default to highest possible threshold */
lpm_nyet_threshold = 0xff; lpm_nyet_threshold = 0xff;
@@ -986,6 +926,13 @@ static int dwc3_probe(struct platform_device *pdev)
dwc->dr_mode = usb_get_dr_mode(dev); dwc->dr_mode = usb_get_dr_mode(dev);
dwc->hsphy_mode = of_usb_get_phy_mode(dev->of_node); 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, dwc->has_lpm_erratum = device_property_read_bool(dev,
"snps,has-lpm-erratum"); "snps,has-lpm-erratum");
device_property_read_u8(dev, "snps,lpm-nyet-threshold", device_property_read_u8(dev, "snps,lpm-nyet-threshold",
@@ -1041,6 +988,112 @@ static int dwc3_probe(struct platform_device *pdev)
dwc->hird_threshold = hird_threshold dwc->hird_threshold = hird_threshold
| (dwc->is_utmi_l1_suspend << 4); | (dwc->is_utmi_l1_suspend << 4);
dwc->imod_interval = 0;
}
/* check whether the core supports IMOD */
bool dwc3_has_imod(struct dwc3 *dwc)
{
return ((dwc3_is_usb3(dwc) &&
dwc->revision >= DWC3_REVISION_300A) ||
(dwc3_is_usb31(dwc) &&
dwc->revision >= DWC3_USB31_REVISION_120A));
}
static void dwc3_check_params(struct dwc3 *dwc)
{
struct device *dev = dwc->dev;
/* Check for proper value of imod_interval */
if (dwc->imod_interval && !dwc3_has_imod(dwc)) {
dev_warn(dwc->dev, "Interrupt moderation not supported\n");
dwc->imod_interval = 0;
}
/*
* Workaround for STAR 9000961433 which affects only version
* 3.00a of the DWC_usb3 core. This prevents the controller
* interrupt from being masked while handling events. IMOD
* allows us to work around this issue. Enable it for the
* affected version.
*/
if (!dwc->imod_interval &&
(dwc->revision == DWC3_REVISION_300A))
dwc->imod_interval = 1;
/* Check the maximum_speed parameter */
switch (dwc->maximum_speed) {
case USB_SPEED_LOW:
case USB_SPEED_FULL:
case USB_SPEED_HIGH:
case USB_SPEED_SUPER:
case USB_SPEED_SUPER_PLUS:
break;
default:
dev_err(dev, "invalid maximum_speed parameter %d\n",
dwc->maximum_speed);
/* fall through */
case USB_SPEED_UNKNOWN:
/* default to superspeed */
dwc->maximum_speed = USB_SPEED_SUPER;
/*
* default to superspeed plus if we are capable.
*/
if (dwc3_is_usb31(dwc) &&
(DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
DWC3_GHWPARAMS3_SSPHY_IFC_GEN2))
dwc->maximum_speed = USB_SPEED_SUPER_PLUS;
break;
}
}
static int dwc3_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
struct dwc3 *dwc;
int ret;
void __iomem *regs;
dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL);
if (!dwc)
return -ENOMEM;
dwc->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "missing memory resource\n");
return -ENODEV;
}
dwc->xhci_resources[0].start = res->start;
dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
DWC3_XHCI_REGS_END;
dwc->xhci_resources[0].flags = res->flags;
dwc->xhci_resources[0].name = res->name;
res->start += DWC3_GLOBALS_REGS_START;
/*
* Request memory region but exclude xHCI regs,
* since it will be requested by the xhci-plat driver.
*/
regs = devm_ioremap_resource(dev, res);
if (IS_ERR(regs)) {
ret = PTR_ERR(regs);
goto err0;
}
dwc->regs = regs;
dwc->regs_size = resource_size(res);
dwc3_get_properties(dwc);
platform_set_drvdata(pdev, dwc); platform_set_drvdata(pdev, dwc);
dwc3_cache_hwparams(dwc); dwc3_cache_hwparams(dwc);
@@ -1050,12 +1103,6 @@ static int dwc3_probe(struct platform_device *pdev)
spin_lock_init(&dwc->lock); spin_lock_init(&dwc->lock);
if (!dev->dma_mask) {
dev->dma_mask = dev->parent->dma_mask;
dev->dma_parms = dev->parent->dma_parms;
dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
}
pm_runtime_set_active(dev); pm_runtime_set_active(dev);
pm_runtime_use_autosuspend(dev); pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY); pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY);
@@ -1087,32 +1134,7 @@ static int dwc3_probe(struct platform_device *pdev)
goto err4; goto err4;
} }
/* Check the maximum_speed parameter */ dwc3_check_params(dwc);
switch (dwc->maximum_speed) {
case USB_SPEED_LOW:
case USB_SPEED_FULL:
case USB_SPEED_HIGH:
case USB_SPEED_SUPER:
case USB_SPEED_SUPER_PLUS:
break;
default:
dev_err(dev, "invalid maximum_speed parameter %d\n",
dwc->maximum_speed);
/* fall through */
case USB_SPEED_UNKNOWN:
/* default to superspeed */
dwc->maximum_speed = USB_SPEED_SUPER;
/*
* default to superspeed plus if we are capable.
*/
if (dwc3_is_usb31(dwc) &&
(DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
DWC3_GHWPARAMS3_SSPHY_IFC_GEN2))
dwc->maximum_speed = USB_SPEED_SUPER_PLUS;
break;
}
ret = dwc3_core_init_mode(dwc); ret = dwc3_core_init_mode(dwc);
if (ret) if (ret)

View File

@@ -26,6 +26,7 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/wait.h>
#include <linux/usb/ch9.h> #include <linux/usb/ch9.h>
#include <linux/usb/gadget.h> #include <linux/usb/gadget.h>
@@ -37,6 +38,7 @@
#define DWC3_MSG_MAX 500 #define DWC3_MSG_MAX 500
/* Global constants */ /* Global constants */
#define DWC3_PULL_UP_TIMEOUT 500 /* ms */
#define DWC3_ZLP_BUF_SIZE 1024 /* size of a superspeed bulk */ #define DWC3_ZLP_BUF_SIZE 1024 /* size of a superspeed bulk */
#define DWC3_EP0_BOUNCE_SIZE 512 #define DWC3_EP0_BOUNCE_SIZE 512
#define DWC3_ENDPOINTS_NUM 32 #define DWC3_ENDPOINTS_NUM 32
@@ -65,6 +67,7 @@
#define DWC3_DEVICE_EVENT_OVERFLOW 11 #define DWC3_DEVICE_EVENT_OVERFLOW 11
#define DWC3_GEVNTCOUNT_MASK 0xfffc #define DWC3_GEVNTCOUNT_MASK 0xfffc
#define DWC3_GEVNTCOUNT_EHB (1 << 31)
#define DWC3_GSNPSID_MASK 0xffff0000 #define DWC3_GSNPSID_MASK 0xffff0000
#define DWC3_GSNPSREV_MASK 0xffff #define DWC3_GSNPSREV_MASK 0xffff
@@ -147,6 +150,8 @@
#define DWC3_DEPCMDPAR0 0x08 #define DWC3_DEPCMDPAR0 0x08
#define DWC3_DEPCMD 0x0c #define DWC3_DEPCMD 0x0c
#define DWC3_DEV_IMOD(n) (0xca00 + (n * 0x4))
/* OTG Registers */ /* OTG Registers */
#define DWC3_OCFG 0xcc00 #define DWC3_OCFG 0xcc00
#define DWC3_OCTL 0xcc04 #define DWC3_OCTL 0xcc04
@@ -198,6 +203,9 @@
#define DWC3_GCTL_GBLHIBERNATIONEN (1 << 1) #define DWC3_GCTL_GBLHIBERNATIONEN (1 << 1)
#define DWC3_GCTL_DSBLCLKGTNG (1 << 0) #define DWC3_GCTL_DSBLCLKGTNG (1 << 0)
/* Global User Control 1 Register */
#define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW (1 << 24)
/* Global USB2 PHY Configuration Register */ /* Global USB2 PHY Configuration Register */
#define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31) #define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31)
#define DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS (1 << 30) #define DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS (1 << 30)
@@ -450,6 +458,8 @@
#define DWC3_DEPCMD_SETTRANSFRESOURCE (0x02 << 0) #define DWC3_DEPCMD_SETTRANSFRESOURCE (0x02 << 0)
#define DWC3_DEPCMD_SETEPCONFIG (0x01 << 0) #define DWC3_DEPCMD_SETEPCONFIG (0x01 << 0)
#define DWC3_DEPCMD_CMD(x) ((x) & 0xf)
/* The EP number goes 0..31 so ep0 is always out and ep1 is always in */ /* The EP number goes 0..31 so ep0 is always out and ep1 is always in */
#define DWC3_DALEPENA_EP(n) (1 << n) #define DWC3_DALEPENA_EP(n) (1 << n)
@@ -458,6 +468,11 @@
#define DWC3_DEPCMD_TYPE_BULK 2 #define DWC3_DEPCMD_TYPE_BULK 2
#define DWC3_DEPCMD_TYPE_INTR 3 #define DWC3_DEPCMD_TYPE_INTR 3
#define DWC3_DEV_IMOD_COUNT_SHIFT 16
#define DWC3_DEV_IMOD_COUNT_MASK (0xffff << 16)
#define DWC3_DEV_IMOD_INTERVAL_SHIFT 0
#define DWC3_DEV_IMOD_INTERVAL_MASK (0xffff << 0)
/* Structures */ /* Structures */
struct dwc3_trb; struct dwc3_trb;
@@ -465,6 +480,7 @@ struct dwc3_trb;
/** /**
* struct dwc3_event_buffer - Software event buffer representation * struct dwc3_event_buffer - Software event buffer representation
* @buf: _THE_ buffer * @buf: _THE_ buffer
* @cache: The buffer cache used in the threaded interrupt
* @length: size of this buffer * @length: size of this buffer
* @lpos: event offset * @lpos: event offset
* @count: cache of last read event count register * @count: cache of last read event count register
@@ -474,6 +490,7 @@ struct dwc3_trb;
*/ */
struct dwc3_event_buffer { struct dwc3_event_buffer {
void *buf; void *buf;
void *cache;
unsigned length; unsigned length;
unsigned int lpos; unsigned int lpos;
unsigned int count; unsigned int count;
@@ -499,6 +516,7 @@ struct dwc3_event_buffer {
* @endpoint: usb endpoint * @endpoint: usb endpoint
* @pending_list: list of pending requests for this endpoint * @pending_list: list of pending requests for this endpoint
* @started_list: list of started requests on this endpoint * @started_list: list of started requests on this endpoint
* @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete
* @lock: spinlock for endpoint request queue traversal * @lock: spinlock for endpoint request queue traversal
* @regs: pointer to first endpoint register * @regs: pointer to first endpoint register
* @trb_pool: array of transaction buffers * @trb_pool: array of transaction buffers
@@ -524,12 +542,13 @@ struct dwc3_ep {
struct list_head pending_list; struct list_head pending_list;
struct list_head started_list; struct list_head started_list;
wait_queue_head_t wait_end_transfer;
spinlock_t lock; spinlock_t lock;
void __iomem *regs; void __iomem *regs;
struct dwc3_trb *trb_pool; struct dwc3_trb *trb_pool;
dma_addr_t trb_pool_dma; dma_addr_t trb_pool_dma;
const struct usb_ss_ep_comp_descriptor *comp_desc;
struct dwc3 *dwc; struct dwc3 *dwc;
u32 saved_state; u32 saved_state;
@@ -540,6 +559,8 @@ struct dwc3_ep {
#define DWC3_EP_BUSY (1 << 4) #define DWC3_EP_BUSY (1 << 4)
#define DWC3_EP_PENDING_REQUEST (1 << 5) #define DWC3_EP_PENDING_REQUEST (1 << 5)
#define DWC3_EP_MISSED_ISOC (1 << 6) #define DWC3_EP_MISSED_ISOC (1 << 6)
#define DWC3_EP_END_TRANSFER_PENDING (1 << 7)
#define DWC3_EP_TRANSFER_STARTED (1 << 8)
/* This last one is specific to EP0 */ /* This last one is specific to EP0 */
#define DWC3_EP0_DIR_IN (1 << 31) #define DWC3_EP0_DIR_IN (1 << 31)
@@ -703,7 +724,7 @@ struct dwc3_hwparams {
* @dep: struct dwc3_ep owning this request * @dep: struct dwc3_ep owning this request
* @sg: pointer to first incomplete sg * @sg: pointer to first incomplete sg
* @num_pending_sgs: counter to pending sgs * @num_pending_sgs: counter to pending sgs
* @first_trb_index: index to first trb used by this request * @remaining: amount of data remaining
* @epnum: endpoint number to which this request refers * @epnum: endpoint number to which this request refers
* @trb: pointer to struct dwc3_trb * @trb: pointer to struct dwc3_trb
* @trb_dma: DMA address of @trb * @trb_dma: DMA address of @trb
@@ -718,7 +739,7 @@ struct dwc3_request {
struct scatterlist *sg; struct scatterlist *sg;
unsigned num_pending_sgs; unsigned num_pending_sgs;
u8 first_trb_index; unsigned remaining;
u8 epnum; u8 epnum;
struct dwc3_trb *trb; struct dwc3_trb *trb;
dma_addr_t trb_dma; dma_addr_t trb_dma;
@@ -748,6 +769,7 @@ struct dwc3_scratchpad_array {
* @ep0_usb_req: dummy req used while handling STD USB requests * @ep0_usb_req: dummy req used while handling STD USB requests
* @ep0_bounce_addr: dma address of ep0_bounce * @ep0_bounce_addr: dma address of ep0_bounce
* @scratch_addr: dma address of scratchbuf * @scratch_addr: dma address of scratchbuf
* @ep0_in_setup: one control transfer is completed and enter setup phase
* @lock: for synchronizing * @lock: for synchronizing
* @dev: pointer to our struct device * @dev: pointer to our struct device
* @xhci: pointer to our xHCI child * @xhci: pointer to our xHCI child
@@ -784,7 +806,6 @@ struct dwc3_scratchpad_array {
* @ep0state: state of endpoint zero * @ep0state: state of endpoint zero
* @link_state: link state * @link_state: link state
* @speed: device speed (super, high, full, low) * @speed: device speed (super, high, full, low)
* @mem: points to start of memory which is used for this struct.
* @hwparams: copy of hwparams registers * @hwparams: copy of hwparams registers
* @root: debugfs root folder pointer * @root: debugfs root folder pointer
* @regset: debugfs pointer to regdump file * @regset: debugfs pointer to regdump file
@@ -798,6 +819,7 @@ struct dwc3_scratchpad_array {
* @ep0_bounced: true when we used bounce buffer * @ep0_bounced: true when we used bounce buffer
* @ep0_expect_in: true when we expect a DATA IN transfer * @ep0_expect_in: true when we expect a DATA IN transfer
* @has_hibernation: true when dwc3 was configured with Hibernation * @has_hibernation: true when dwc3 was configured with Hibernation
* @sysdev_is_parent: true when dwc3 device has a parent driver
* @has_lpm_erratum: true when core was configured with LPM Erratum. Note that * @has_lpm_erratum: true when core was configured with LPM Erratum. Note that
* there's now way for software to detect this in runtime. * there's now way for software to detect this in runtime.
* @is_utmi_l1_suspend: the core asserts output signal * @is_utmi_l1_suspend: the core asserts output signal
@@ -833,6 +855,8 @@ struct dwc3_scratchpad_array {
* 1 - -3.5dB de-emphasis * 1 - -3.5dB de-emphasis
* 2 - No de-emphasis * 2 - No de-emphasis
* 3 - Reserved * 3 - Reserved
* @imod_interval: set the interrupt moderation interval in 250ns
* increments or 0 to disable.
*/ */
struct dwc3 { struct dwc3 {
struct usb_ctrlrequest *ctrl_req; struct usb_ctrlrequest *ctrl_req;
@@ -846,11 +870,13 @@ struct dwc3 {
dma_addr_t ep0_bounce_addr; dma_addr_t ep0_bounce_addr;
dma_addr_t scratch_addr; dma_addr_t scratch_addr;
struct dwc3_request ep0_usb_req; struct dwc3_request ep0_usb_req;
struct completion ep0_in_setup;
/* device lock */ /* device lock */
spinlock_t lock; spinlock_t lock;
struct device *dev; struct device *dev;
struct device *sysdev;
struct platform_device *xhci; struct platform_device *xhci;
struct resource xhci_resources[DWC3_XHCI_RESOURCES_NUM]; struct resource xhci_resources[DWC3_XHCI_RESOURCES_NUM];
@@ -909,6 +935,7 @@ struct dwc3 {
#define DWC3_REVISION_260A 0x5533260a #define DWC3_REVISION_260A 0x5533260a
#define DWC3_REVISION_270A 0x5533270a #define DWC3_REVISION_270A 0x5533270a
#define DWC3_REVISION_280A 0x5533280a #define DWC3_REVISION_280A 0x5533280a
#define DWC3_REVISION_290A 0x5533290a
#define DWC3_REVISION_300A 0x5533300a #define DWC3_REVISION_300A 0x5533300a
#define DWC3_REVISION_310A 0x5533310a #define DWC3_REVISION_310A 0x5533310a
@@ -918,6 +945,7 @@ struct dwc3 {
*/ */
#define DWC3_REVISION_IS_DWC31 0x80000000 #define DWC3_REVISION_IS_DWC31 0x80000000
#define DWC3_USB31_REVISION_110A (0x3131302a | DWC3_REVISION_IS_DWC31) #define DWC3_USB31_REVISION_110A (0x3131302a | DWC3_REVISION_IS_DWC31)
#define DWC3_USB31_REVISION_120A (0x3132302a | DWC3_REVISION_IS_DWC31)
enum dwc3_ep0_next ep0_next_event; enum dwc3_ep0_next ep0_next_event;
enum dwc3_ep0_state ep0state; enum dwc3_ep0_state ep0state;
@@ -934,8 +962,6 @@ struct dwc3 {
u8 num_out_eps; u8 num_out_eps;
u8 num_in_eps; u8 num_in_eps;
void *mem;
struct dwc3_hwparams hwparams; struct dwc3_hwparams hwparams;
struct dentry *root; struct dentry *root;
struct debugfs_regset32 *regset; struct debugfs_regset32 *regset;
@@ -952,6 +978,7 @@ struct dwc3 {
unsigned ep0_bounced:1; unsigned ep0_bounced:1;
unsigned ep0_expect_in:1; unsigned ep0_expect_in:1;
unsigned has_hibernation:1; unsigned has_hibernation:1;
unsigned sysdev_is_parent:1;
unsigned has_lpm_erratum:1; unsigned has_lpm_erratum:1;
unsigned is_utmi_l1_suspend:1; unsigned is_utmi_l1_suspend:1;
unsigned is_fpga:1; unsigned is_fpga:1;
@@ -978,6 +1005,8 @@ struct dwc3 {
unsigned tx_de_emphasis_quirk:1; unsigned tx_de_emphasis_quirk:1;
unsigned tx_de_emphasis:2; unsigned tx_de_emphasis:2;
u16 imod_interval;
}; };
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
@@ -1039,12 +1068,16 @@ struct dwc3_event_depevt {
/* Control-only Status */ /* Control-only Status */
#define DEPEVT_STATUS_CONTROL_DATA 1 #define DEPEVT_STATUS_CONTROL_DATA 1
#define DEPEVT_STATUS_CONTROL_STATUS 2 #define DEPEVT_STATUS_CONTROL_STATUS 2
#define DEPEVT_STATUS_CONTROL_PHASE(n) ((n) & 3)
/* In response to Start Transfer */ /* In response to Start Transfer */
#define DEPEVT_TRANSFER_NO_RESOURCE 1 #define DEPEVT_TRANSFER_NO_RESOURCE 1
#define DEPEVT_TRANSFER_BUS_EXPIRY 2 #define DEPEVT_TRANSFER_BUS_EXPIRY 2
u32 parameters:16; u32 parameters:16;
/* For Command Complete Events */
#define DEPEVT_PARAMETER_CMD(n) (((n) & (0xf << 8)) >> 8)
} __packed; } __packed;
/** /**
@@ -1133,12 +1166,20 @@ struct dwc3_gadget_ep_cmd_params {
void dwc3_set_mode(struct dwc3 *dwc, u32 mode); void dwc3_set_mode(struct dwc3 *dwc, u32 mode);
u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type); u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type);
/* check whether we are on the DWC_usb3 core */
static inline bool dwc3_is_usb3(struct dwc3 *dwc)
{
return !(dwc->revision & DWC3_REVISION_IS_DWC31);
}
/* check whether we are on the DWC_usb31 core */ /* check whether we are on the DWC_usb31 core */
static inline bool dwc3_is_usb31(struct dwc3 *dwc) static inline bool dwc3_is_usb31(struct dwc3 *dwc)
{ {
return !!(dwc->revision & DWC3_REVISION_IS_DWC31); return !!(dwc->revision & DWC3_REVISION_IS_DWC31);
} }
bool dwc3_has_imod(struct dwc3 *dwc);
#if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
int dwc3_host_init(struct dwc3 *dwc); int dwc3_host_init(struct dwc3 *dwc);
void dwc3_host_exit(struct dwc3 *dwc); void dwc3_host_exit(struct dwc3 *dwc);

View File

@@ -1,32 +0,0 @@
/**
* debug.c - DesignWare USB3 DRD Controller Debug/Trace Support
*
* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
*
* Author: Felipe Balbi <balbi@ti.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "debug.h"
void dwc3_trace(void (*trace)(struct va_format *), const char *fmt, ...)
{
struct va_format vaf;
va_list args;
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
trace(&vaf);
va_end(args);
}

View File

@@ -124,6 +124,22 @@ dwc3_gadget_link_string(enum dwc3_link_state link_state)
} }
} }
static inline const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
{
switch (state) {
case EP0_UNCONNECTED:
return "Unconnected";
case EP0_SETUP_PHASE:
return "Setup Phase";
case EP0_DATA_PHASE:
return "Data Phase";
case EP0_STATUS_PHASE:
return "Status Phase";
default:
return "UNKNOWN";
}
}
/** /**
* dwc3_gadget_event_string - returns event name * dwc3_gadget_event_string - returns event name
* @event: the event code * @event: the event code
@@ -184,10 +200,11 @@ dwc3_gadget_event_string(const struct dwc3_event_devt *event)
* @event: then event code * @event: then event code
*/ */
static inline const char * static inline const char *
dwc3_ep_event_string(const struct dwc3_event_depevt *event) dwc3_ep_event_string(const struct dwc3_event_depevt *event, u32 ep0state)
{ {
u8 epnum = event->endpoint_number; u8 epnum = event->endpoint_number;
static char str[256]; static char str[256];
size_t len;
int status; int status;
int ret; int ret;
@@ -199,6 +216,10 @@ dwc3_ep_event_string(const struct dwc3_event_depevt *event)
switch (event->endpoint_event) { switch (event->endpoint_event) {
case DWC3_DEPEVT_XFERCOMPLETE: case DWC3_DEPEVT_XFERCOMPLETE:
strcat(str, "Transfer Complete"); strcat(str, "Transfer Complete");
len = strlen(str);
if (epnum <= 1)
sprintf(str + len, " [%s]", dwc3_ep0_state_string(ep0state));
break; break;
case DWC3_DEPEVT_XFERINPROGRESS: case DWC3_DEPEVT_XFERINPROGRESS:
strcat(str, "Transfer In-Progress"); strcat(str, "Transfer In-Progress");
@@ -207,6 +228,19 @@ dwc3_ep_event_string(const struct dwc3_event_depevt *event)
strcat(str, "Transfer Not Ready"); strcat(str, "Transfer Not Ready");
status = event->status & DEPEVT_STATUS_TRANSFER_ACTIVE; status = event->status & DEPEVT_STATUS_TRANSFER_ACTIVE;
strcat(str, status ? " (Active)" : " (Not Active)"); strcat(str, status ? " (Active)" : " (Not Active)");
/* Control Endpoints */
if (epnum <= 1) {
int phase = DEPEVT_STATUS_CONTROL_PHASE(event->status);
switch (phase) {
case DEPEVT_STATUS_CONTROL_DATA:
strcat(str, " [Data Phase]");
break;
case DEPEVT_STATUS_CONTROL_STATUS:
strcat(str, " [Status Phase]");
}
}
break; break;
case DWC3_DEPEVT_RXTXFIFOEVT: case DWC3_DEPEVT_RXTXFIFOEVT:
strcat(str, "FIFO"); strcat(str, "FIFO");
@@ -270,14 +304,14 @@ static inline const char *dwc3_gadget_event_type_string(u8 event)
} }
} }
static inline const char *dwc3_decode_event(u32 event) static inline const char *dwc3_decode_event(u32 event, u32 ep0state)
{ {
const union dwc3_event evt = (union dwc3_event) event; const union dwc3_event evt = (union dwc3_event) event;
if (evt.type.is_devspec) if (evt.type.is_devspec)
return dwc3_gadget_event_string(&evt.devt); return dwc3_gadget_event_string(&evt.devt);
else else
return dwc3_ep_event_string(&evt.depevt); return dwc3_ep_event_string(&evt.depevt, ep0state);
} }
static inline const char *dwc3_ep_cmd_status_string(int status) static inline const char *dwc3_ep_cmd_status_string(int status)
@@ -310,7 +344,6 @@ static inline const char *dwc3_gadget_generic_cmd_status_string(int status)
} }
} }
void dwc3_trace(void (*trace)(struct va_format *), const char *fmt, ...);
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
extern void dwc3_debugfs_init(struct dwc3 *); extern void dwc3_debugfs_init(struct dwc3 *);

View File

@@ -20,7 +20,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/usb/otg.h> #include <linux/usb/otg.h>
#include <linux/usb/usb_phy_generic.h> #include <linux/usb/usb_phy_generic.h>
@@ -117,15 +116,6 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
if (!exynos) if (!exynos)
return -ENOMEM; return -ENOMEM;
/*
* Right now device-tree probed devices don't get dma_mask set.
* Since shared usb code relies on it, set it here for now.
* Once we move to full device tree support this will vanish off.
*/
ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret)
return ret;
platform_set_drvdata(pdev, exynos); platform_set_drvdata(pdev, exynos);
exynos->dev = dev; exynos->dev = dev;

View File

@@ -39,6 +39,27 @@
#define PCI_DEVICE_ID_INTEL_APL 0x5aaa #define PCI_DEVICE_ID_INTEL_APL 0x5aaa
#define PCI_DEVICE_ID_INTEL_KBP 0xa2b0 #define PCI_DEVICE_ID_INTEL_KBP 0xa2b0
#define PCI_INTEL_BXT_DSM_UUID "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"
#define PCI_INTEL_BXT_FUNC_PMU_PWR 4
#define PCI_INTEL_BXT_STATE_D0 0
#define PCI_INTEL_BXT_STATE_D3 3
/**
* struct dwc3_pci - Driver private structure
* @dwc3: child dwc3 platform_device
* @pci: our link to PCI bus
* @uuid: _DSM UUID
* @has_dsm_for_pm: true for devices which need to run _DSM on runtime PM
*/
struct dwc3_pci {
struct platform_device *dwc3;
struct pci_dev *pci;
u8 uuid[16];
unsigned int has_dsm_for_pm:1;
};
static const struct acpi_gpio_params reset_gpios = { 0, 0, false }; static const struct acpi_gpio_params reset_gpios = { 0, 0, false };
static const struct acpi_gpio_params cs_gpios = { 1, 0, false }; static const struct acpi_gpio_params cs_gpios = { 1, 0, false };
@@ -48,8 +69,21 @@ static const struct acpi_gpio_mapping acpi_dwc3_byt_gpios[] = {
{ }, { },
}; };
static int dwc3_pci_quirks(struct pci_dev *pdev, struct platform_device *dwc3) static int dwc3_pci_quirks(struct dwc3_pci *dwc)
{ {
struct platform_device *dwc3 = dwc->dwc3;
struct pci_dev *pdev = dwc->pci;
int ret;
struct property_entry sysdev_property[] = {
PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
{ },
};
ret = platform_device_add_properties(dwc3, sysdev_property);
if (ret)
return ret;
if (pdev->vendor == PCI_VENDOR_ID_AMD && if (pdev->vendor == PCI_VENDOR_ID_AMD &&
pdev->device == PCI_DEVICE_ID_AMD_NL_USB) { pdev->device == PCI_DEVICE_ID_AMD_NL_USB) {
struct property_entry properties[] = { struct property_entry properties[] = {
@@ -89,6 +123,12 @@ static int dwc3_pci_quirks(struct pci_dev *pdev, struct platform_device *dwc3)
if (ret < 0) if (ret < 0)
return ret; return ret;
if (pdev->device == PCI_DEVICE_ID_INTEL_BXT ||
pdev->device == PCI_DEVICE_ID_INTEL_BXT_M) {
acpi_str_to_uuid(PCI_INTEL_BXT_DSM_UUID, dwc->uuid);
dwc->has_dsm_for_pm = true;
}
if (pdev->device == PCI_DEVICE_ID_INTEL_BYT) { if (pdev->device == PCI_DEVICE_ID_INTEL_BYT) {
struct gpio_desc *gpio; struct gpio_desc *gpio;
@@ -139,8 +179,8 @@ static int dwc3_pci_quirks(struct pci_dev *pdev, struct platform_device *dwc3)
static int dwc3_pci_probe(struct pci_dev *pci, static int dwc3_pci_probe(struct pci_dev *pci,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
struct dwc3_pci *dwc;
struct resource res[2]; struct resource res[2];
struct platform_device *dwc3;
int ret; int ret;
struct device *dev = &pci->dev; struct device *dev = &pci->dev;
@@ -152,11 +192,13 @@ static int dwc3_pci_probe(struct pci_dev *pci,
pci_set_master(pci); pci_set_master(pci);
dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO); dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL);
if (!dwc3) { if (!dwc)
dev_err(dev, "couldn't allocate dwc3 device\n"); return -ENOMEM;
dwc->dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
if (!dwc->dwc3)
return -ENOMEM; return -ENOMEM;
}
memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
@@ -169,20 +211,21 @@ static int dwc3_pci_probe(struct pci_dev *pci,
res[1].name = "dwc_usb3"; res[1].name = "dwc_usb3";
res[1].flags = IORESOURCE_IRQ; res[1].flags = IORESOURCE_IRQ;
ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res)); ret = platform_device_add_resources(dwc->dwc3, res, ARRAY_SIZE(res));
if (ret) { if (ret) {
dev_err(dev, "couldn't add resources to dwc3 device\n"); dev_err(dev, "couldn't add resources to dwc3 device\n");
return ret; return ret;
} }
dwc3->dev.parent = dev; dwc->pci = pci;
ACPI_COMPANION_SET(&dwc3->dev, ACPI_COMPANION(dev)); dwc->dwc3->dev.parent = dev;
ACPI_COMPANION_SET(&dwc->dwc3->dev, ACPI_COMPANION(dev));
ret = dwc3_pci_quirks(pci, dwc3); ret = dwc3_pci_quirks(dwc);
if (ret) if (ret)
goto err; goto err;
ret = platform_device_add(dwc3); ret = platform_device_add(dwc->dwc3);
if (ret) { if (ret) {
dev_err(dev, "failed to register dwc3 device\n"); dev_err(dev, "failed to register dwc3 device\n");
goto err; goto err;
@@ -190,21 +233,23 @@ static int dwc3_pci_probe(struct pci_dev *pci,
device_init_wakeup(dev, true); device_init_wakeup(dev, true);
device_set_run_wake(dev, true); device_set_run_wake(dev, true);
pci_set_drvdata(pci, dwc3); pci_set_drvdata(pci, dwc);
pm_runtime_put(dev); pm_runtime_put(dev);
return 0; return 0;
err: err:
platform_device_put(dwc3); platform_device_put(dwc->dwc3);
return ret; return ret;
} }
static void dwc3_pci_remove(struct pci_dev *pci) static void dwc3_pci_remove(struct pci_dev *pci)
{ {
struct dwc3_pci *dwc = pci_get_drvdata(pci);
device_init_wakeup(&pci->dev, false); device_init_wakeup(&pci->dev, false);
pm_runtime_get(&pci->dev); pm_runtime_get(&pci->dev);
acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pci->dev)); acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pci->dev));
platform_device_unregister(pci_get_drvdata(pci)); platform_device_unregister(dwc->dwc3);
} }
static const struct pci_device_id dwc3_pci_id_table[] = { static const struct pci_device_id dwc3_pci_id_table[] = {
@@ -234,40 +279,75 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
}; };
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table); MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
#if defined(CONFIG_PM) || defined(CONFIG_PM_SLEEP)
static int dwc3_pci_dsm(struct dwc3_pci *dwc, int param)
{
union acpi_object *obj;
union acpi_object tmp;
union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp);
if (!dwc->has_dsm_for_pm)
return 0;
tmp.type = ACPI_TYPE_INTEGER;
tmp.integer.value = param;
obj = acpi_evaluate_dsm(ACPI_HANDLE(&dwc->pci->dev), dwc->uuid,
1, PCI_INTEL_BXT_FUNC_PMU_PWR, &argv4);
if (!obj) {
dev_err(&dwc->pci->dev, "failed to evaluate _DSM\n");
return -EIO;
}
ACPI_FREE(obj);
return 0;
}
#endif /* CONFIG_PM || CONFIG_PM_SLEEP */
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int dwc3_pci_runtime_suspend(struct device *dev) static int dwc3_pci_runtime_suspend(struct device *dev)
{ {
struct dwc3_pci *dwc = dev_get_drvdata(dev);
if (device_run_wake(dev)) if (device_run_wake(dev))
return 0; return dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D3);
return -EBUSY; return -EBUSY;
} }
static int dwc3_pci_runtime_resume(struct device *dev) static int dwc3_pci_runtime_resume(struct device *dev)
{ {
struct platform_device *dwc3 = dev_get_drvdata(dev); struct dwc3_pci *dwc = dev_get_drvdata(dev);
struct platform_device *dwc3 = dwc->dwc3;
int ret;
ret = dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D0);
if (ret)
return ret;
return pm_runtime_get(&dwc3->dev); return pm_runtime_get(&dwc3->dev);
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int dwc3_pci_pm_dummy(struct device *dev) static int dwc3_pci_suspend(struct device *dev)
{ {
/* struct dwc3_pci *dwc = dev_get_drvdata(dev);
* There's nothing to do here. No, seriously. Everything is either taken
* care either by PCI subsystem or dwc3/core.c, so we have nothing return dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D3);
* missing here. }
*
* So you'd think we didn't need this at all, but PCI subsystem will static int dwc3_pci_resume(struct device *dev)
* bail out if we don't have a valid callback :-s {
*/ struct dwc3_pci *dwc = dev_get_drvdata(dev);
return 0;
return dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D0);
} }
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
static struct dev_pm_ops dwc3_pci_dev_pm_ops = { static struct dev_pm_ops dwc3_pci_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_pm_dummy, dwc3_pci_pm_dummy) SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume)
SET_RUNTIME_PM_OPS(dwc3_pci_runtime_suspend, dwc3_pci_runtime_resume, SET_RUNTIME_PM_OPS(dwc3_pci_runtime_suspend, dwc3_pci_runtime_resume,
NULL) NULL)
}; };

View File

@@ -219,7 +219,6 @@ static int st_dwc3_probe(struct platform_device *pdev)
if (IS_ERR(regmap)) if (IS_ERR(regmap))
return PTR_ERR(regmap); return PTR_ERR(regmap);
dma_set_coherent_mask(dev, dev->coherent_dma_mask);
dwc3_data->dev = dev; dwc3_data->dev = dev;
dwc3_data->regmap = regmap; dwc3_data->regmap = regmap;

View File

@@ -39,22 +39,6 @@ static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep);
static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
struct dwc3_ep *dep, struct dwc3_request *req); struct dwc3_ep *dep, struct dwc3_request *req);
static const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
{
switch (state) {
case EP0_UNCONNECTED:
return "Unconnected";
case EP0_SETUP_PHASE:
return "Setup Phase";
case EP0_DATA_PHASE:
return "Data Phase";
case EP0_STATUS_PHASE:
return "Status Phase";
default:
return "UNKNOWN";
}
}
static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
u32 len, u32 type, bool chain) u32 len, u32 type, bool chain)
{ {
@@ -65,10 +49,8 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
int ret; int ret;
dep = dwc->eps[epnum]; dep = dwc->eps[epnum];
if (dep->flags & DWC3_EP_BUSY) { if (dep->flags & DWC3_EP_BUSY)
dwc3_trace(trace_dwc3_ep0, "%s still busy", dep->name);
return 0; return 0;
}
trb = &dwc->ep0_trb[dep->trb_enqueue]; trb = &dwc->ep0_trb[dep->trb_enqueue];
@@ -99,11 +81,8 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
trace_dwc3_prepare_trb(dep, trb); trace_dwc3_prepare_trb(dep, trb);
ret = dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_STARTTRANSFER, &params); ret = dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_STARTTRANSFER, &params);
if (ret < 0) { if (ret < 0)
dwc3_trace(trace_dwc3_ep0, "%s STARTTRANSFER failed",
dep->name);
return ret; return ret;
}
dep->flags |= DWC3_EP_BUSY; dep->flags |= DWC3_EP_BUSY;
dep->resource_index = dwc3_gadget_ep_get_transfer_index(dep); dep->resource_index = dwc3_gadget_ep_get_transfer_index(dep);
@@ -163,9 +142,6 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
if (dwc->ep0state == EP0_STATUS_PHASE) if (dwc->ep0state == EP0_STATUS_PHASE)
__dwc3_ep0_do_control_status(dwc, dwc->eps[direction]); __dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
else
dwc3_trace(trace_dwc3_ep0,
"too early for delayed status");
return 0; return 0;
} }
@@ -229,9 +205,8 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
spin_lock_irqsave(&dwc->lock, flags); spin_lock_irqsave(&dwc->lock, flags);
if (!dep->endpoint.desc) { if (!dep->endpoint.desc) {
dwc3_trace(trace_dwc3_ep0, dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
"trying to queue request %p to disabled %s", dep->name);
request, dep->name);
ret = -ESHUTDOWN; ret = -ESHUTDOWN;
goto out; goto out;
} }
@@ -242,11 +217,6 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
goto out; goto out;
} }
dwc3_trace(trace_dwc3_ep0,
"queueing request %p to %s length %d state '%s'",
request, dep->name, request->length,
dwc3_ep0_state_string(dwc->ep0state));
ret = __dwc3_gadget_ep0_queue(dep, req); ret = __dwc3_gadget_ep0_queue(dep, req);
out: out:
@@ -308,6 +278,8 @@ void dwc3_ep0_out_start(struct dwc3 *dwc)
{ {
int ret; int ret;
complete(&dwc->ep0_in_setup);
ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8, ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8,
DWC3_TRBCTL_CONTROL_SETUP, false); DWC3_TRBCTL_CONTROL_SETUP, false);
WARN_ON(ret < 0); WARN_ON(ret < 0);
@@ -395,33 +367,11 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req); return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
} }
static int dwc3_ep0_handle_feature(struct dwc3 *dwc, static int dwc3_ep0_handle_u1(struct dwc3 *dwc, enum usb_device_state state,
struct usb_ctrlrequest *ctrl, int set) int set)
{ {
struct dwc3_ep *dep;
u32 recip;
u32 wValue;
u32 wIndex;
u32 reg; u32 reg;
int ret;
enum usb_device_state state;
wValue = le16_to_cpu(ctrl->wValue);
wIndex = le16_to_cpu(ctrl->wIndex);
recip = ctrl->bRequestType & USB_RECIP_MASK;
state = dwc->gadget.state;
switch (recip) {
case USB_RECIP_DEVICE:
switch (wValue) {
case USB_DEVICE_REMOTE_WAKEUP:
break;
/*
* 9.4.1 says only only for SS, in AddressState only for
* default control pipe
*/
case USB_DEVICE_U1_ENABLE:
if (state != USB_STATE_CONFIGURED) if (state != USB_STATE_CONFIGURED)
return -EINVAL; return -EINVAL;
if ((dwc->speed != DWC3_DSTS_SUPERSPEED) && if ((dwc->speed != DWC3_DSTS_SUPERSPEED) &&
@@ -434,9 +384,16 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
else else
reg &= ~DWC3_DCTL_INITU1ENA; reg &= ~DWC3_DCTL_INITU1ENA;
dwc3_writel(dwc->regs, DWC3_DCTL, reg); dwc3_writel(dwc->regs, DWC3_DCTL, reg);
break;
case USB_DEVICE_U2_ENABLE: return 0;
}
static int dwc3_ep0_handle_u2(struct dwc3 *dwc, enum usb_device_state state,
int set)
{
u32 reg;
if (state != USB_STATE_CONFIGURED) if (state != USB_STATE_CONFIGURED)
return -EINVAL; return -EINVAL;
if ((dwc->speed != DWC3_DSTS_SUPERSPEED) && if ((dwc->speed != DWC3_DSTS_SUPERSPEED) &&
@@ -449,12 +406,13 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
else else
reg &= ~DWC3_DCTL_INITU2ENA; reg &= ~DWC3_DCTL_INITU2ENA;
dwc3_writel(dwc->regs, DWC3_DCTL, reg); dwc3_writel(dwc->regs, DWC3_DCTL, reg);
break;
case USB_DEVICE_LTM_ENABLE: return 0;
return -EINVAL; }
case USB_DEVICE_TEST_MODE: static int dwc3_ep0_handle_test(struct dwc3 *dwc, enum usb_device_state state,
u32 wIndex, int set)
{
if ((wIndex & 0xff) != 0) if ((wIndex & 0xff) != 0)
return -EINVAL; return -EINVAL;
if (!set) if (!set)
@@ -472,35 +430,99 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
default: default:
return -EINVAL; return -EINVAL;
} }
return 0;
}
static int dwc3_ep0_handle_device(struct dwc3 *dwc,
struct usb_ctrlrequest *ctrl, int set)
{
enum usb_device_state state;
u32 wValue;
u32 wIndex;
int ret = 0;
wValue = le16_to_cpu(ctrl->wValue);
wIndex = le16_to_cpu(ctrl->wIndex);
state = dwc->gadget.state;
switch (wValue) {
case USB_DEVICE_REMOTE_WAKEUP:
break;
/*
* 9.4.1 says only only for SS, in AddressState only for
* default control pipe
*/
case USB_DEVICE_U1_ENABLE:
ret = dwc3_ep0_handle_u1(dwc, state, set);
break;
case USB_DEVICE_U2_ENABLE:
ret = dwc3_ep0_handle_u2(dwc, state, set);
break;
case USB_DEVICE_LTM_ENABLE:
ret = -EINVAL;
break;
case USB_DEVICE_TEST_MODE:
ret = dwc3_ep0_handle_test(dwc, state, wIndex, set);
break; break;
default: default:
return -EINVAL; ret = -EINVAL;
} }
break;
case USB_RECIP_INTERFACE: return ret;
}
static int dwc3_ep0_handle_intf(struct dwc3 *dwc,
struct usb_ctrlrequest *ctrl, int set)
{
enum usb_device_state state;
u32 wValue;
u32 wIndex;
int ret = 0;
wValue = le16_to_cpu(ctrl->wValue);
wIndex = le16_to_cpu(ctrl->wIndex);
state = dwc->gadget.state;
switch (wValue) { switch (wValue) {
case USB_INTRF_FUNC_SUSPEND: case USB_INTRF_FUNC_SUSPEND:
if (wIndex & USB_INTRF_FUNC_SUSPEND_LP) /*
/* XXX enable Low power suspend */ * REVISIT: Ideally we would enable some low power mode here,
; * however it's unclear what we should be doing here.
if (wIndex & USB_INTRF_FUNC_SUSPEND_RW) *
/* XXX enable remote wakeup */ * For now, we're not doing anything, just making sure we return
; * 0 so USB Command Verifier tests pass without any errors.
*/
break; break;
default: default:
return -EINVAL; ret = -EINVAL;
} }
break;
case USB_RECIP_ENDPOINT: return ret;
}
static int dwc3_ep0_handle_endpoint(struct dwc3 *dwc,
struct usb_ctrlrequest *ctrl, int set)
{
struct dwc3_ep *dep;
enum usb_device_state state;
u32 wValue;
u32 wIndex;
int ret;
wValue = le16_to_cpu(ctrl->wValue);
wIndex = le16_to_cpu(ctrl->wIndex);
state = dwc->gadget.state;
switch (wValue) { switch (wValue) {
case USB_ENDPOINT_HALT: case USB_ENDPOINT_HALT:
dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex); dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex);
if (!dep) if (!dep)
return -EINVAL; return -EINVAL;
if (set == 0 && (dep->flags & DWC3_EP_WEDGE)) if (set == 0 && (dep->flags & DWC3_EP_WEDGE))
break; break;
ret = __dwc3_gadget_ep_set_halt(dep, set, true); ret = __dwc3_gadget_ep_set_halt(dep, set, true);
if (ret) if (ret)
return -EINVAL; return -EINVAL;
@@ -508,15 +530,37 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
default: default:
return -EINVAL; return -EINVAL;
} }
break;
default:
return -EINVAL;
}
return 0; return 0;
} }
static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
struct usb_ctrlrequest *ctrl, int set)
{
u32 recip;
int ret;
enum usb_device_state state;
recip = ctrl->bRequestType & USB_RECIP_MASK;
state = dwc->gadget.state;
switch (recip) {
case USB_RECIP_DEVICE:
ret = dwc3_ep0_handle_device(dwc, ctrl, set);
break;
case USB_RECIP_INTERFACE:
ret = dwc3_ep0_handle_intf(dwc, ctrl, set);
break;
case USB_RECIP_ENDPOINT:
ret = dwc3_ep0_handle_endpoint(dwc, ctrl, set);
break;
default:
ret = -EINVAL;
}
return ret;
}
static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{ {
enum usb_device_state state = dwc->gadget.state; enum usb_device_state state = dwc->gadget.state;
@@ -525,13 +569,12 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
addr = le16_to_cpu(ctrl->wValue); addr = le16_to_cpu(ctrl->wValue);
if (addr > 127) { if (addr > 127) {
dwc3_trace(trace_dwc3_ep0, "invalid device address %d", addr); dev_err(dwc->dev, "invalid device address %d\n", addr);
return -EINVAL; return -EINVAL;
} }
if (state == USB_STATE_CONFIGURED) { if (state == USB_STATE_CONFIGURED) {
dwc3_trace(trace_dwc3_ep0, dev_err(dwc->dev, "can't SetAddress() from Configured State\n");
"trying to set address when configured");
return -EINVAL; return -EINVAL;
} }
@@ -716,35 +759,27 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
switch (ctrl->bRequest) { switch (ctrl->bRequest) {
case USB_REQ_GET_STATUS: case USB_REQ_GET_STATUS:
dwc3_trace(trace_dwc3_ep0, "USB_REQ_GET_STATUS");
ret = dwc3_ep0_handle_status(dwc, ctrl); ret = dwc3_ep0_handle_status(dwc, ctrl);
break; break;
case USB_REQ_CLEAR_FEATURE: case USB_REQ_CLEAR_FEATURE:
dwc3_trace(trace_dwc3_ep0, "USB_REQ_CLEAR_FEATURE");
ret = dwc3_ep0_handle_feature(dwc, ctrl, 0); ret = dwc3_ep0_handle_feature(dwc, ctrl, 0);
break; break;
case USB_REQ_SET_FEATURE: case USB_REQ_SET_FEATURE:
dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_FEATURE");
ret = dwc3_ep0_handle_feature(dwc, ctrl, 1); ret = dwc3_ep0_handle_feature(dwc, ctrl, 1);
break; break;
case USB_REQ_SET_ADDRESS: case USB_REQ_SET_ADDRESS:
dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ADDRESS");
ret = dwc3_ep0_set_address(dwc, ctrl); ret = dwc3_ep0_set_address(dwc, ctrl);
break; break;
case USB_REQ_SET_CONFIGURATION: case USB_REQ_SET_CONFIGURATION:
dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_CONFIGURATION");
ret = dwc3_ep0_set_config(dwc, ctrl); ret = dwc3_ep0_set_config(dwc, ctrl);
break; break;
case USB_REQ_SET_SEL: case USB_REQ_SET_SEL:
dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_SEL");
ret = dwc3_ep0_set_sel(dwc, ctrl); ret = dwc3_ep0_set_sel(dwc, ctrl);
break; break;
case USB_REQ_SET_ISOCH_DELAY: case USB_REQ_SET_ISOCH_DELAY:
dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY");
ret = dwc3_ep0_set_isoch_delay(dwc, ctrl); ret = dwc3_ep0_set_isoch_delay(dwc, ctrl);
break; break;
default: default:
dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver");
ret = dwc3_ep0_delegate_req(dwc, ctrl); ret = dwc3_ep0_delegate_req(dwc, ctrl);
break; break;
} }
@@ -820,9 +855,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
status = DWC3_TRB_SIZE_TRBSTS(trb->size); status = DWC3_TRB_SIZE_TRBSTS(trb->size);
if (status == DWC3_TRBSTS_SETUP_PENDING) { if (status == DWC3_TRBSTS_SETUP_PENDING) {
dwc->setup_packet_pending = true; dwc->setup_packet_pending = true;
dwc3_trace(trace_dwc3_ep0, "Setup Pending received");
if (r) if (r)
dwc3_gadget_giveback(ep0, r, -ECONNRESET); dwc3_gadget_giveback(ep0, r, -ECONNRESET);
@@ -912,7 +944,7 @@ static void dwc3_ep0_complete_status(struct dwc3 *dwc,
ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr); ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr);
if (ret < 0) { if (ret < 0) {
dwc3_trace(trace_dwc3_ep0, "Invalid Test #%d", dev_err(dwc->dev, "invalid test #%d\n",
dwc->test_mode_nr); dwc->test_mode_nr);
dwc3_ep0_stall_and_restart(dwc); dwc3_ep0_stall_and_restart(dwc);
return; return;
@@ -920,10 +952,8 @@ static void dwc3_ep0_complete_status(struct dwc3 *dwc,
} }
status = DWC3_TRB_SIZE_TRBSTS(trb->size); status = DWC3_TRB_SIZE_TRBSTS(trb->size);
if (status == DWC3_TRBSTS_SETUP_PENDING) { if (status == DWC3_TRBSTS_SETUP_PENDING)
dwc->setup_packet_pending = true; dwc->setup_packet_pending = true;
dwc3_trace(trace_dwc3_ep0, "Setup Pending received");
}
dwc->ep0state = EP0_SETUP_PHASE; dwc->ep0state = EP0_SETUP_PHASE;
dwc3_ep0_out_start(dwc); dwc3_ep0_out_start(dwc);
@@ -940,17 +970,14 @@ static void dwc3_ep0_xfer_complete(struct dwc3 *dwc,
switch (dwc->ep0state) { switch (dwc->ep0state) {
case EP0_SETUP_PHASE: case EP0_SETUP_PHASE:
dwc3_trace(trace_dwc3_ep0, "Setup Phase");
dwc3_ep0_inspect_setup(dwc, event); dwc3_ep0_inspect_setup(dwc, event);
break; break;
case EP0_DATA_PHASE: case EP0_DATA_PHASE:
dwc3_trace(trace_dwc3_ep0, "Data Phase");
dwc3_ep0_complete_data(dwc, event); dwc3_ep0_complete_data(dwc, event);
break; break;
case EP0_STATUS_PHASE: case EP0_STATUS_PHASE:
dwc3_trace(trace_dwc3_ep0, "Status Phase");
dwc3_ep0_complete_status(dwc, event); dwc3_ep0_complete_status(dwc, event);
break; break;
default: default:
@@ -974,12 +1001,10 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
u32 transfer_size = 0; u32 transfer_size = 0;
u32 maxpacket; u32 maxpacket;
ret = usb_gadget_map_request(&dwc->gadget, &req->request, ret = usb_gadget_map_request_by_dev(dwc->sysdev,
dep->number); &req->request, dep->number);
if (ret) { if (ret)
dwc3_trace(trace_dwc3_ep0, "failed to map request");
return; return;
}
maxpacket = dep->endpoint.maxpacket; maxpacket = dep->endpoint.maxpacket;
@@ -1002,12 +1027,10 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
dwc->ep0_bounce_addr, transfer_size, dwc->ep0_bounce_addr, transfer_size,
DWC3_TRBCTL_CONTROL_DATA, false); DWC3_TRBCTL_CONTROL_DATA, false);
} else { } else {
ret = usb_gadget_map_request(&dwc->gadget, &req->request, ret = usb_gadget_map_request_by_dev(dwc->sysdev,
dep->number); &req->request, dep->number);
if (ret) { if (ret)
dwc3_trace(trace_dwc3_ep0, "failed to map request");
return; return;
}
ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma, ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma,
req->request.length, DWC3_TRBCTL_CONTROL_DATA, req->request.length, DWC3_TRBCTL_CONTROL_DATA,
@@ -1065,8 +1088,6 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
{ {
switch (event->status) { switch (event->status) {
case DEPEVT_STATUS_CONTROL_DATA: case DEPEVT_STATUS_CONTROL_DATA:
dwc3_trace(trace_dwc3_ep0, "Control Data");
/* /*
* We already have a DATA transfer in the controller's cache, * We already have a DATA transfer in the controller's cache,
* if we receive a XferNotReady(DATA) we will ignore it, unless * if we receive a XferNotReady(DATA) we will ignore it, unless
@@ -1079,8 +1100,7 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
if (dwc->ep0_expect_in != event->endpoint_number) { if (dwc->ep0_expect_in != event->endpoint_number) {
struct dwc3_ep *dep = dwc->eps[dwc->ep0_expect_in]; struct dwc3_ep *dep = dwc->eps[dwc->ep0_expect_in];
dwc3_trace(trace_dwc3_ep0, dev_err(dwc->dev, "unexpected direction for Data Phase\n");
"Wrong direction for Data phase");
dwc3_ep0_end_control_data(dwc, dep); dwc3_ep0_end_control_data(dwc, dep);
dwc3_ep0_stall_and_restart(dwc); dwc3_ep0_stall_and_restart(dwc);
return; return;
@@ -1092,13 +1112,10 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS) if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS)
return; return;
dwc3_trace(trace_dwc3_ep0, "Control Status");
dwc->ep0state = EP0_STATUS_PHASE; dwc->ep0state = EP0_STATUS_PHASE;
if (dwc->delayed_status) { if (dwc->delayed_status) {
WARN_ON_ONCE(event->endpoint_number != 1); WARN_ON_ONCE(event->endpoint_number != 1);
dwc3_trace(trace_dwc3_ep0, "Delayed Status");
return; return;
} }
@@ -1109,10 +1126,6 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
void dwc3_ep0_interrupt(struct dwc3 *dwc, void dwc3_ep0_interrupt(struct dwc3 *dwc,
const struct dwc3_event_depevt *event) const struct dwc3_event_depevt *event)
{ {
dwc3_trace(trace_dwc3_ep0, "%s: state '%s'",
dwc3_ep_event_string(event),
dwc3_ep0_state_string(dwc->ep0state));
switch (event->endpoint_event) { switch (event->endpoint_event) {
case DWC3_DEPEVT_XFERCOMPLETE: case DWC3_DEPEVT_XFERCOMPLETE:
dwc3_ep0_xfer_complete(dwc, event); dwc3_ep0_xfer_complete(dwc, event);

File diff suppressed because it is too large Load Diff

View File

@@ -62,10 +62,7 @@ struct dwc3;
static inline struct dwc3_request *next_request(struct list_head *list) static inline struct dwc3_request *next_request(struct list_head *list)
{ {
if (list_empty(list)) return list_first_entry_or_null(list, struct dwc3_request, list);
return NULL;
return list_first_entry(list, struct dwc3_request, list);
} }
static inline void dwc3_gadget_move_started_request(struct dwc3_request *req) static inline void dwc3_gadget_move_started_request(struct dwc3_request *req)

View File

@@ -19,6 +19,39 @@
#include "core.h" #include "core.h"
static int dwc3_host_get_irq(struct dwc3 *dwc)
{
struct platform_device *dwc3_pdev = to_platform_device(dwc->dev);
int irq;
irq = platform_get_irq_byname(dwc3_pdev, "host");
if (irq > 0)
goto out;
if (irq == -EPROBE_DEFER)
goto out;
irq = platform_get_irq_byname(dwc3_pdev, "dwc_usb3");
if (irq > 0)
goto out;
if (irq == -EPROBE_DEFER)
goto out;
irq = platform_get_irq(dwc3_pdev, 0);
if (irq > 0)
goto out;
if (irq != -EPROBE_DEFER)
dev_err(dwc->dev, "missing host IRQ\n");
if (!irq)
irq = -EINVAL;
out:
return irq;
}
int dwc3_host_init(struct dwc3 *dwc) int dwc3_host_init(struct dwc3 *dwc)
{ {
struct property_entry props[2]; struct property_entry props[2];
@@ -27,39 +60,18 @@ int dwc3_host_init(struct dwc3 *dwc)
struct resource *res; struct resource *res;
struct platform_device *dwc3_pdev = to_platform_device(dwc->dev); struct platform_device *dwc3_pdev = to_platform_device(dwc->dev);
irq = platform_get_irq_byname(dwc3_pdev, "host"); irq = dwc3_host_get_irq(dwc);
if (irq == -EPROBE_DEFER) if (irq < 0)
return irq; return irq;
if (irq <= 0) { res = platform_get_resource_byname(dwc3_pdev, IORESOURCE_IRQ, "host");
irq = platform_get_irq_byname(dwc3_pdev, "dwc_usb3"); if (!res)
if (irq == -EPROBE_DEFER)
return irq;
if (irq <= 0) {
irq = platform_get_irq(dwc3_pdev, 0);
if (irq <= 0) {
if (irq != -EPROBE_DEFER) {
dev_err(dwc->dev,
"missing host IRQ\n");
}
if (!irq)
irq = -EINVAL;
return irq;
} else {
res = platform_get_resource(dwc3_pdev,
IORESOURCE_IRQ, 0);
}
} else {
res = platform_get_resource_byname(dwc3_pdev,
IORESOURCE_IRQ,
"dwc_usb3");
}
} else {
res = platform_get_resource_byname(dwc3_pdev, IORESOURCE_IRQ, res = platform_get_resource_byname(dwc3_pdev, IORESOURCE_IRQ,
"host"); "dwc_usb3");
} if (!res)
res = platform_get_resource(dwc3_pdev, IORESOURCE_IRQ, 0);
if (!res)
return -ENOMEM;
dwc->xhci_resources[1].start = irq; dwc->xhci_resources[1].start = irq;
dwc->xhci_resources[1].end = irq; dwc->xhci_resources[1].end = irq;
@@ -72,11 +84,7 @@ int dwc3_host_init(struct dwc3 *dwc)
return -ENOMEM; return -ENOMEM;
} }
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;
dwc->xhci = xhci; dwc->xhci = xhci;
@@ -99,9 +107,9 @@ int dwc3_host_init(struct dwc3 *dwc)
} }
phy_create_lookup(dwc->usb2_generic_phy, "usb2-phy", phy_create_lookup(dwc->usb2_generic_phy, "usb2-phy",
dev_name(&xhci->dev)); dev_name(dwc->dev));
phy_create_lookup(dwc->usb3_generic_phy, "usb3-phy", phy_create_lookup(dwc->usb3_generic_phy, "usb3-phy",
dev_name(&xhci->dev)); dev_name(dwc->dev));
ret = platform_device_add(xhci); ret = platform_device_add(xhci);
if (ret) { if (ret) {
@@ -112,9 +120,9 @@ int dwc3_host_init(struct dwc3 *dwc)
return 0; return 0;
err2: err2:
phy_remove_lookup(dwc->usb2_generic_phy, "usb2-phy", phy_remove_lookup(dwc->usb2_generic_phy, "usb2-phy",
dev_name(&xhci->dev)); dev_name(dwc->dev));
phy_remove_lookup(dwc->usb3_generic_phy, "usb3-phy", phy_remove_lookup(dwc->usb3_generic_phy, "usb3-phy",
dev_name(&xhci->dev)); dev_name(dwc->dev));
err1: err1:
platform_device_put(xhci); platform_device_put(xhci);
return ret; return ret;
@@ -123,8 +131,8 @@ err1:
void dwc3_host_exit(struct dwc3 *dwc) void dwc3_host_exit(struct dwc3 *dwc)
{ {
phy_remove_lookup(dwc->usb2_generic_phy, "usb2-phy", phy_remove_lookup(dwc->usb2_generic_phy, "usb2-phy",
dev_name(&dwc->xhci->dev)); dev_name(dwc->dev));
phy_remove_lookup(dwc->usb3_generic_phy, "usb3-phy", phy_remove_lookup(dwc->usb3_generic_phy, "usb3-phy",
dev_name(&dwc->xhci->dev)); dev_name(dwc->dev));
platform_device_unregister(dwc->xhci); platform_device_unregister(dwc->xhci);
} }

View File

@@ -40,8 +40,7 @@ static inline u32 dwc3_readl(void __iomem *base, u32 offset)
* documentation, so we revert it back to the proper addresses, the * documentation, so we revert it back to the proper addresses, the
* same way they are described on SNPS documentation * same way they are described on SNPS documentation
*/ */
dwc3_trace(trace_dwc3_readl, "addr %p value %08x", trace_dwc3_readl(base - DWC3_GLOBALS_REGS_START, offset, value);
base - DWC3_GLOBALS_REGS_START + offset, value);
return value; return value;
} }
@@ -60,8 +59,7 @@ static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value)
* documentation, so we revert it back to the proper addresses, the * documentation, so we revert it back to the proper addresses, the
* same way they are described on SNPS documentation * same way they are described on SNPS documentation
*/ */
dwc3_trace(trace_dwc3_writel, "addr %p value %08x", trace_dwc3_writel(base - DWC3_GLOBALS_REGS_START, offset, value);
base - DWC3_GLOBALS_REGS_START + offset, value);
} }
#endif /* __DRIVERS_USB_DWC3_IO_H */ #endif /* __DRIVERS_USB_DWC3_IO_H */

View File

@@ -37,16 +37,6 @@ DECLARE_EVENT_CLASS(dwc3_log_msg,
TP_printk("%s", __get_str(msg)) TP_printk("%s", __get_str(msg))
); );
DEFINE_EVENT(dwc3_log_msg, dwc3_readl,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf)
);
DEFINE_EVENT(dwc3_log_msg, dwc3_writel,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf)
);
DEFINE_EVENT(dwc3_log_msg, dwc3_gadget, DEFINE_EVENT(dwc3_log_msg, dwc3_gadget,
TP_PROTO(struct va_format *vaf), TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf) TP_ARGS(vaf)
@@ -62,22 +52,51 @@ DEFINE_EVENT(dwc3_log_msg, dwc3_ep0,
TP_ARGS(vaf) TP_ARGS(vaf)
); );
DECLARE_EVENT_CLASS(dwc3_log_io,
TP_PROTO(void *base, u32 offset, u32 value),
TP_ARGS(base, offset, value),
TP_STRUCT__entry(
__field(void *, base)
__field(u32, offset)
__field(u32, value)
),
TP_fast_assign(
__entry->base = base;
__entry->offset = offset;
__entry->value = value;
),
TP_printk("addr %p value %08x", __entry->base + __entry->offset,
__entry->value)
);
DEFINE_EVENT(dwc3_log_io, dwc3_readl,
TP_PROTO(void *base, u32 offset, u32 value),
TP_ARGS(base, offset, value)
);
DEFINE_EVENT(dwc3_log_io, dwc3_writel,
TP_PROTO(void *base, u32 offset, u32 value),
TP_ARGS(base, offset, value)
);
DECLARE_EVENT_CLASS(dwc3_log_event, DECLARE_EVENT_CLASS(dwc3_log_event,
TP_PROTO(u32 event), TP_PROTO(u32 event, struct dwc3 *dwc),
TP_ARGS(event), TP_ARGS(event, dwc),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(u32, event) __field(u32, event)
__field(u32, ep0state)
), ),
TP_fast_assign( TP_fast_assign(
__entry->event = event; __entry->event = event;
__entry->ep0state = dwc->ep0state;
), ),
TP_printk("event (%08x): %s", __entry->event, TP_printk("event (%08x): %s", __entry->event,
dwc3_decode_event(__entry->event)) dwc3_decode_event(__entry->event, __entry->ep0state))
); );
DEFINE_EVENT(dwc3_log_event, dwc3_event, DEFINE_EVENT(dwc3_log_event, dwc3_event,
TP_PROTO(u32 event), TP_PROTO(u32 event, struct dwc3 *dwc),
TP_ARGS(event) TP_ARGS(event, dwc)
); );
DECLARE_EVENT_CLASS(dwc3_log_ctrl, DECLARE_EVENT_CLASS(dwc3_log_ctrl,
@@ -237,6 +256,7 @@ DECLARE_EVENT_CLASS(dwc3_log_trb,
__field(u32, bph) __field(u32, bph)
__field(u32, size) __field(u32, size)
__field(u32, ctrl) __field(u32, ctrl)
__field(u32, type)
), ),
TP_fast_assign( TP_fast_assign(
snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name); snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
@@ -247,11 +267,31 @@ DECLARE_EVENT_CLASS(dwc3_log_trb,
__entry->bph = trb->bph; __entry->bph = trb->bph;
__entry->size = trb->size; __entry->size = trb->size;
__entry->ctrl = trb->ctrl; __entry->ctrl = trb->ctrl;
__entry->type = usb_endpoint_type(dep->endpoint.desc);
), ),
TP_printk("%s: %d/%d trb %p buf %08x%08x size %d ctrl %08x (%c%c%c%c:%c%c:%s)", TP_printk("%s: %d/%d trb %p buf %08x%08x size %s%d ctrl %08x (%c%c%c%c:%c%c:%s)",
__get_str(name), __entry->queued, __entry->allocated, __get_str(name), __entry->queued, __entry->allocated,
__entry->trb, __entry->bph, __entry->bpl, __entry->trb, __entry->bph, __entry->bpl,
__entry->size, __entry->ctrl, ({char *s;
int pcm = ((__entry->size >> 24) & 3) + 1;
switch (__entry->type) {
case USB_ENDPOINT_XFER_INT:
case USB_ENDPOINT_XFER_ISOC:
switch (pcm) {
case 1:
s = "1x ";
break;
case 2:
s = "2x ";
break;
case 3:
s = "3x ";
break;
}
default:
s = "";
} s; }),
DWC3_TRB_SIZE_LENGTH(__entry->size), __entry->ctrl,
__entry->ctrl & DWC3_TRB_CTRL_HWO ? 'H' : 'h', __entry->ctrl & DWC3_TRB_CTRL_HWO ? 'H' : 'h',
__entry->ctrl & DWC3_TRB_CTRL_LST ? 'L' : 'l', __entry->ctrl & DWC3_TRB_CTRL_LST ? 'L' : 'l',
__entry->ctrl & DWC3_TRB_CTRL_CHN ? 'C' : 'c', __entry->ctrl & DWC3_TRB_CTRL_CHN ? 'C' : 'c',
@@ -301,6 +341,57 @@ DEFINE_EVENT(dwc3_log_trb, dwc3_complete_trb,
TP_ARGS(dep, trb) TP_ARGS(dep, trb)
); );
DECLARE_EVENT_CLASS(dwc3_log_ep,
TP_PROTO(struct dwc3_ep *dep),
TP_ARGS(dep),
TP_STRUCT__entry(
__dynamic_array(char, name, DWC3_MSG_MAX)
__field(unsigned, maxpacket)
__field(unsigned, maxpacket_limit)
__field(unsigned, max_streams)
__field(unsigned, maxburst)
__field(unsigned, flags)
__field(unsigned, direction)
__field(u8, trb_enqueue)
__field(u8, trb_dequeue)
),
TP_fast_assign(
snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
__entry->maxpacket = dep->endpoint.maxpacket;
__entry->maxpacket_limit = dep->endpoint.maxpacket_limit;
__entry->max_streams = dep->endpoint.max_streams;
__entry->maxburst = dep->endpoint.maxburst;
__entry->flags = dep->flags;
__entry->direction = dep->direction;
__entry->trb_enqueue = dep->trb_enqueue;
__entry->trb_dequeue = dep->trb_dequeue;
),
TP_printk("%s: mps %d/%d streams %d burst %d ring %d/%d flags %c:%c%c%c%c%c:%c:%c",
__get_str(name), __entry->maxpacket,
__entry->maxpacket_limit, __entry->max_streams,
__entry->maxburst, __entry->trb_enqueue,
__entry->trb_dequeue,
__entry->flags & DWC3_EP_ENABLED ? 'E' : 'e',
__entry->flags & DWC3_EP_STALL ? 'S' : 's',
__entry->flags & DWC3_EP_WEDGE ? 'W' : 'w',
__entry->flags & DWC3_EP_BUSY ? 'B' : 'b',
__entry->flags & DWC3_EP_PENDING_REQUEST ? 'P' : 'p',
__entry->flags & DWC3_EP_MISSED_ISOC ? 'M' : 'm',
__entry->flags & DWC3_EP_END_TRANSFER_PENDING ? 'E' : 'e',
__entry->direction ? '<' : '>'
)
);
DEFINE_EVENT(dwc3_log_ep, dwc3_gadget_ep_enable,
TP_PROTO(struct dwc3_ep *dep),
TP_ARGS(dep)
);
DEFINE_EVENT(dwc3_log_ep, dwc3_gadget_ep_disable,
TP_PROTO(struct dwc3_ep *dep),
TP_ARGS(dep)
);
#endif /* __DWC3_TRACE_H */ #endif /* __DWC3_TRACE_H */
/* this part has to be here */ /* this part has to be here */

View File

@@ -201,7 +201,12 @@ ep_found:
_ep->desc = chosen_desc; _ep->desc = chosen_desc;
_ep->comp_desc = NULL; _ep->comp_desc = NULL;
_ep->maxburst = 0; _ep->maxburst = 0;
_ep->mult = 0; _ep->mult = 1;
if (g->speed == USB_SPEED_HIGH && (usb_endpoint_xfer_isoc(_ep->desc) ||
usb_endpoint_xfer_int(_ep->desc)))
_ep->mult = usb_endpoint_maxp_mult(_ep->desc);
if (!want_comp_desc) if (!want_comp_desc)
return 0; return 0;
@@ -218,7 +223,7 @@ ep_found:
switch (usb_endpoint_type(_ep->desc)) { switch (usb_endpoint_type(_ep->desc)) {
case USB_ENDPOINT_XFER_ISOC: case USB_ENDPOINT_XFER_ISOC:
/* mult: bits 1:0 of bmAttributes */ /* mult: bits 1:0 of bmAttributes */
_ep->mult = comp_desc->bmAttributes & 0x3; _ep->mult = (comp_desc->bmAttributes & 0x3) + 1;
case USB_ENDPOINT_XFER_BULK: case USB_ENDPOINT_XFER_BULK:
case USB_ENDPOINT_XFER_INT: case USB_ENDPOINT_XFER_INT:
_ep->maxburst = comp_desc->bMaxBurst + 1; _ep->maxburst = comp_desc->bMaxBurst + 1;
@@ -2382,18 +2387,8 @@ EXPORT_SYMBOL_GPL(usb_composite_setup_continue);
static char *composite_default_mfr(struct usb_gadget *gadget) static char *composite_default_mfr(struct usb_gadget *gadget)
{ {
char *mfr; return kasprintf(GFP_KERNEL, "%s %s with %s", init_utsname()->sysname,
int len;
len = snprintf(NULL, 0, "%s %s with %s", init_utsname()->sysname,
init_utsname()->release, gadget->name); init_utsname()->release, gadget->name);
len++;
mfr = kmalloc(len, GFP_KERNEL);
if (!mfr)
return NULL;
snprintf(mfr, len, "%s %s with %s", init_utsname()->sysname,
init_utsname()->release, gadget->name);
return mfr;
} }
void usb_composite_overwrite_options(struct usb_composite_dev *cdev, void usb_composite_overwrite_options(struct usb_composite_dev *cdev,

View File

@@ -266,7 +266,7 @@ static void ffs_ep0_complete(struct usb_ep *ep, struct usb_request *req)
{ {
struct ffs_data *ffs = req->context; struct ffs_data *ffs = req->context;
complete_all(&ffs->ep0req_completion); complete(&ffs->ep0req_completion);
} }
static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len) static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)

View File

@@ -98,6 +98,60 @@ static struct hid_descriptor hidg_desc = {
/*.desc[0].wDescriptorLenght = DYNAMIC */ /*.desc[0].wDescriptorLenght = DYNAMIC */
}; };
/* Super-Speed Support */
static struct usb_endpoint_descriptor hidg_ss_in_ep_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
/*.wMaxPacketSize = DYNAMIC */
.bInterval = 4, /* FIXME: Add this field in the
* HID gadget configuration?
* (struct hidg_func_descriptor)
*/
};
static struct usb_ss_ep_comp_descriptor hidg_ss_in_comp_desc = {
.bLength = sizeof(hidg_ss_in_comp_desc),
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/* .bMaxBurst = 0, */
/* .bmAttributes = 0, */
/* .wBytesPerInterval = DYNAMIC */
};
static struct usb_endpoint_descriptor hidg_ss_out_ep_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_INT,
/*.wMaxPacketSize = DYNAMIC */
.bInterval = 4, /* FIXME: Add this field in the
* HID gadget configuration?
* (struct hidg_func_descriptor)
*/
};
static struct usb_ss_ep_comp_descriptor hidg_ss_out_comp_desc = {
.bLength = sizeof(hidg_ss_out_comp_desc),
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/* .bMaxBurst = 0, */
/* .bmAttributes = 0, */
/* .wBytesPerInterval = DYNAMIC */
};
static struct usb_descriptor_header *hidg_ss_descriptors[] = {
(struct usb_descriptor_header *)&hidg_interface_desc,
(struct usb_descriptor_header *)&hidg_desc,
(struct usb_descriptor_header *)&hidg_ss_in_ep_desc,
(struct usb_descriptor_header *)&hidg_ss_in_comp_desc,
(struct usb_descriptor_header *)&hidg_ss_out_ep_desc,
(struct usb_descriptor_header *)&hidg_ss_out_comp_desc,
NULL,
};
/* High-Speed Support */ /* High-Speed Support */
static struct usb_endpoint_descriptor hidg_hs_in_ep_desc = { static struct usb_endpoint_descriptor hidg_hs_in_ep_desc = {
@@ -624,8 +678,14 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
/* set descriptor dynamic values */ /* set descriptor dynamic values */
hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass; hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass;
hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol; hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol;
hidg_ss_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
hidg_ss_in_comp_desc.wBytesPerInterval =
cpu_to_le16(hidg->report_length);
hidg_hs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_hs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
hidg_fs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_fs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
hidg_ss_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
hidg_ss_out_comp_desc.wBytesPerInterval =
cpu_to_le16(hidg->report_length);
hidg_hs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_hs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
hidg_fs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_fs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
/* /*
@@ -641,8 +701,13 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
hidg_hs_out_ep_desc.bEndpointAddress = hidg_hs_out_ep_desc.bEndpointAddress =
hidg_fs_out_ep_desc.bEndpointAddress; hidg_fs_out_ep_desc.bEndpointAddress;
hidg_ss_in_ep_desc.bEndpointAddress =
hidg_fs_in_ep_desc.bEndpointAddress;
hidg_ss_out_ep_desc.bEndpointAddress =
hidg_fs_out_ep_desc.bEndpointAddress;
status = usb_assign_descriptors(f, hidg_fs_descriptors, status = usb_assign_descriptors(f, hidg_fs_descriptors,
hidg_hs_descriptors, NULL, NULL); hidg_hs_descriptors, hidg_ss_descriptors, NULL);
if (status) if (status)
goto fail; goto fail;

View File

@@ -998,7 +998,7 @@ static struct sk_buff *package_for_tx(struct f_ncm *ncm)
/* Merge the skbs */ /* Merge the skbs */
swap(skb2, ncm->skb_tx_data); swap(skb2, ncm->skb_tx_data);
if (ncm->skb_tx_data) { if (ncm->skb_tx_data) {
dev_kfree_skb_any(ncm->skb_tx_data); dev_consume_skb_any(ncm->skb_tx_data);
ncm->skb_tx_data = NULL; ncm->skb_tx_data = NULL;
} }
@@ -1009,7 +1009,7 @@ static struct sk_buff *package_for_tx(struct f_ncm *ncm)
/* Copy NTB across. */ /* Copy NTB across. */
ntb_iter = (void *) skb_put(skb2, ncm->skb_tx_ndp->len); ntb_iter = (void *) skb_put(skb2, ncm->skb_tx_ndp->len);
memcpy(ntb_iter, ncm->skb_tx_ndp->data, ncm->skb_tx_ndp->len); memcpy(ntb_iter, ncm->skb_tx_ndp->data, ncm->skb_tx_ndp->len);
dev_kfree_skb_any(ncm->skb_tx_ndp); dev_consume_skb_any(ncm->skb_tx_ndp);
ncm->skb_tx_ndp = NULL; ncm->skb_tx_ndp = NULL;
/* Insert zero'd datagram. */ /* Insert zero'd datagram. */
@@ -1078,6 +1078,7 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port,
if (!ncm->skb_tx_data) if (!ncm->skb_tx_data)
goto err; goto err;
ncm->skb_tx_data->dev = ncm->netdev;
ntb_data = (void *) skb_put(ncm->skb_tx_data, ncb_len); ntb_data = (void *) skb_put(ncm->skb_tx_data, ncb_len);
memset(ntb_data, 0, ncb_len); memset(ntb_data, 0, ncb_len);
/* dwSignature */ /* dwSignature */
@@ -1096,6 +1097,8 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port,
GFP_ATOMIC); GFP_ATOMIC);
if (!ncm->skb_tx_ndp) if (!ncm->skb_tx_ndp)
goto err; goto err;
ncm->skb_tx_ndp->dev = ncm->netdev;
ntb_ndp = (void *) skb_put(ncm->skb_tx_ndp, ntb_ndp = (void *) skb_put(ncm->skb_tx_ndp,
opts->ndp_size); opts->ndp_size);
memset(ntb_ndp, 0, ncb_len); memset(ntb_ndp, 0, ncb_len);
@@ -1133,7 +1136,7 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port,
memset(ntb_data, 0, dgram_pad); memset(ntb_data, 0, dgram_pad);
ntb_data = (void *) skb_put(ncm->skb_tx_data, skb->len); ntb_data = (void *) skb_put(ncm->skb_tx_data, skb->len);
memcpy(ntb_data, skb->data, skb->len); memcpy(ntb_data, skb->data, skb->len);
dev_kfree_skb_any(skb); dev_consume_skb_any(skb);
skb = NULL; skb = NULL;
} else if (ncm->skb_tx_data && ncm->timer_force_tx) { } else if (ncm->skb_tx_data && ncm->timer_force_tx) {
@@ -1329,7 +1332,7 @@ static int ncm_unwrap_ntb(struct gether *port,
} while (ndp_len > 2 * (opts->dgram_item_len * 2)); } while (ndp_len > 2 * (opts->dgram_item_len * 2));
} while (ndp_index); } while (ndp_index);
dev_kfree_skb_any(skb); dev_consume_skb_any(skb);
VDBG(port->func.config->cdev, VDBG(port->func.config->cdev,
"Parsed NTB with %d frames\n", dgram_counter); "Parsed NTB with %d frames\n", dgram_counter);

View File

@@ -1067,13 +1067,13 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc); agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
if (!agdev->out_ep) { if (!agdev->out_ep) {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
goto err; return ret;
} }
agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc); agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc);
if (!agdev->in_ep) { if (!agdev->in_ep) {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
goto err; return ret;
} }
uac2->p_prm.uac2 = uac2; uac2->p_prm.uac2 = uac2;
@@ -1091,7 +1091,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL, ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL,
NULL); NULL);
if (ret) if (ret)
goto err; return ret;
prm = &agdev->uac2.c_prm; prm = &agdev->uac2.c_prm;
prm->max_psize = hs_epout_desc.wMaxPacketSize; prm->max_psize = hs_epout_desc.wMaxPacketSize;
@@ -1106,19 +1106,19 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
if (!prm->rbuf) { if (!prm->rbuf) {
prm->max_psize = 0; prm->max_psize = 0;
goto err_free_descs; goto err;
} }
ret = alsa_uac2_init(agdev); ret = alsa_uac2_init(agdev);
if (ret) if (ret)
goto err_free_descs; goto err;
return 0; return 0;
err_free_descs:
usb_free_all_descriptors(fn);
err: err:
kfree(agdev->uac2.p_prm.rbuf); kfree(agdev->uac2.p_prm.rbuf);
kfree(agdev->uac2.c_prm.rbuf); kfree(agdev->uac2.c_prm.rbuf);
err_free_descs:
usb_free_all_descriptors(fn);
return -EINVAL; return -EINVAL;
} }

View File

@@ -80,8 +80,7 @@ static const struct file_operations rndis_proc_fops;
#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ #endif /* CONFIG_USB_GADGET_DEBUG_FILES */
/* supported OIDs */ /* supported OIDs */
static const u32 oid_supported_list[] = static const u32 oid_supported_list[] = {
{
/* the general stuff */ /* the general stuff */
RNDIS_OID_GEN_SUPPORTED_LIST, RNDIS_OID_GEN_SUPPORTED_LIST,
RNDIS_OID_GEN_HARDWARE_STATUS, RNDIS_OID_GEN_HARDWARE_STATUS,

View File

@@ -22,8 +22,7 @@
#define RNDIS_MAXIMUM_FRAME_SIZE 1518 #define RNDIS_MAXIMUM_FRAME_SIZE 1518
#define RNDIS_MAX_TOTAL_SIZE 1558 #define RNDIS_MAX_TOTAL_SIZE 1558
typedef struct rndis_init_msg_type typedef struct rndis_init_msg_type {
{
__le32 MessageType; __le32 MessageType;
__le32 MessageLength; __le32 MessageLength;
__le32 RequestID; __le32 RequestID;
@@ -32,8 +31,7 @@ typedef struct rndis_init_msg_type
__le32 MaxTransferSize; __le32 MaxTransferSize;
} rndis_init_msg_type; } rndis_init_msg_type;
typedef struct rndis_init_cmplt_type typedef struct rndis_init_cmplt_type {
{
__le32 MessageType; __le32 MessageType;
__le32 MessageLength; __le32 MessageLength;
__le32 RequestID; __le32 RequestID;
@@ -49,15 +47,13 @@ typedef struct rndis_init_cmplt_type
__le32 AFListSize; __le32 AFListSize;
} rndis_init_cmplt_type; } rndis_init_cmplt_type;
typedef struct rndis_halt_msg_type typedef struct rndis_halt_msg_type {
{
__le32 MessageType; __le32 MessageType;
__le32 MessageLength; __le32 MessageLength;
__le32 RequestID; __le32 RequestID;
} rndis_halt_msg_type; } rndis_halt_msg_type;
typedef struct rndis_query_msg_type typedef struct rndis_query_msg_type {
{
__le32 MessageType; __le32 MessageType;
__le32 MessageLength; __le32 MessageLength;
__le32 RequestID; __le32 RequestID;
@@ -67,8 +63,7 @@ typedef struct rndis_query_msg_type
__le32 DeviceVcHandle; __le32 DeviceVcHandle;
} rndis_query_msg_type; } rndis_query_msg_type;
typedef struct rndis_query_cmplt_type typedef struct rndis_query_cmplt_type {
{
__le32 MessageType; __le32 MessageType;
__le32 MessageLength; __le32 MessageLength;
__le32 RequestID; __le32 RequestID;
@@ -77,8 +72,7 @@ typedef struct rndis_query_cmplt_type
__le32 InformationBufferOffset; __le32 InformationBufferOffset;
} rndis_query_cmplt_type; } rndis_query_cmplt_type;
typedef struct rndis_set_msg_type typedef struct rndis_set_msg_type {
{
__le32 MessageType; __le32 MessageType;
__le32 MessageLength; __le32 MessageLength;
__le32 RequestID; __le32 RequestID;
@@ -88,31 +82,27 @@ typedef struct rndis_set_msg_type
__le32 DeviceVcHandle; __le32 DeviceVcHandle;
} rndis_set_msg_type; } rndis_set_msg_type;
typedef struct rndis_set_cmplt_type typedef struct rndis_set_cmplt_type {
{
__le32 MessageType; __le32 MessageType;
__le32 MessageLength; __le32 MessageLength;
__le32 RequestID; __le32 RequestID;
__le32 Status; __le32 Status;
} rndis_set_cmplt_type; } rndis_set_cmplt_type;
typedef struct rndis_reset_msg_type typedef struct rndis_reset_msg_type {
{
__le32 MessageType; __le32 MessageType;
__le32 MessageLength; __le32 MessageLength;
__le32 Reserved; __le32 Reserved;
} rndis_reset_msg_type; } rndis_reset_msg_type;
typedef struct rndis_reset_cmplt_type typedef struct rndis_reset_cmplt_type {
{
__le32 MessageType; __le32 MessageType;
__le32 MessageLength; __le32 MessageLength;
__le32 Status; __le32 Status;
__le32 AddressingReset; __le32 AddressingReset;
} rndis_reset_cmplt_type; } rndis_reset_cmplt_type;
typedef struct rndis_indicate_status_msg_type typedef struct rndis_indicate_status_msg_type {
{
__le32 MessageType; __le32 MessageType;
__le32 MessageLength; __le32 MessageLength;
__le32 Status; __le32 Status;
@@ -120,23 +110,20 @@ typedef struct rndis_indicate_status_msg_type
__le32 StatusBufferOffset; __le32 StatusBufferOffset;
} rndis_indicate_status_msg_type; } rndis_indicate_status_msg_type;
typedef struct rndis_keepalive_msg_type typedef struct rndis_keepalive_msg_type {
{
__le32 MessageType; __le32 MessageType;
__le32 MessageLength; __le32 MessageLength;
__le32 RequestID; __le32 RequestID;
} rndis_keepalive_msg_type; } rndis_keepalive_msg_type;
typedef struct rndis_keepalive_cmplt_type typedef struct rndis_keepalive_cmplt_type {
{
__le32 MessageType; __le32 MessageType;
__le32 MessageLength; __le32 MessageLength;
__le32 RequestID; __le32 RequestID;
__le32 Status; __le32 Status;
} rndis_keepalive_cmplt_type; } rndis_keepalive_cmplt_type;
struct rndis_packet_msg_type struct rndis_packet_msg_type {
{
__le32 MessageType; __le32 MessageType;
__le32 MessageLength; __le32 MessageLength;
__le32 DataOffset; __le32 DataOffset;
@@ -150,8 +137,7 @@ struct rndis_packet_msg_type
__le32 Reserved; __le32 Reserved;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct rndis_config_parameter struct rndis_config_parameter {
{
__le32 ParameterNameOffset; __le32 ParameterNameOffset;
__le32 ParameterNameLength; __le32 ParameterNameLength;
__le32 ParameterType; __le32 ParameterType;
@@ -160,23 +146,20 @@ struct rndis_config_parameter
}; };
/* implementation specific */ /* implementation specific */
enum rndis_state enum rndis_state {
{
RNDIS_UNINITIALIZED, RNDIS_UNINITIALIZED,
RNDIS_INITIALIZED, RNDIS_INITIALIZED,
RNDIS_DATA_INITIALIZED, RNDIS_DATA_INITIALIZED,
}; };
typedef struct rndis_resp_t typedef struct rndis_resp_t {
{
struct list_head list; struct list_head list;
u8 *buf; u8 *buf;
u32 length; u32 length;
int send; int send;
} rndis_resp_t; } rndis_resp_t;
typedef struct rndis_params typedef struct rndis_params {
{
int confignr; int confignr;
u8 used; u8 used;
u16 saved_filter; u16 saved_filter;

View File

@@ -224,7 +224,7 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
if (dev->port_usb->is_fixed) if (dev->port_usb->is_fixed)
size = max_t(size_t, size, dev->port_usb->fixed_out_len); size = max_t(size_t, size, dev->port_usb->fixed_out_len);
skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags); skb = __netdev_alloc_skb(dev->net, size + NET_IP_ALIGN, gfp_flags);
if (skb == NULL) { if (skb == NULL) {
DBG(dev, "no rx skb\n"); DBG(dev, "no rx skb\n");
goto enomem; goto enomem;
@@ -455,16 +455,17 @@ static void tx_complete(struct usb_ep *ep, struct usb_request *req)
/* FALLTHROUGH */ /* FALLTHROUGH */
case -ECONNRESET: /* unlink */ case -ECONNRESET: /* unlink */
case -ESHUTDOWN: /* disconnect etc */ case -ESHUTDOWN: /* disconnect etc */
dev_kfree_skb_any(skb);
break; break;
case 0: case 0:
dev->net->stats.tx_bytes += skb->len; dev->net->stats.tx_bytes += skb->len;
dev_consume_skb_any(skb);
} }
dev->net->stats.tx_packets++; dev->net->stats.tx_packets++;
spin_lock(&dev->req_lock); spin_lock(&dev->req_lock);
list_add(&req->list, &dev->tx_reqs); list_add(&req->list, &dev->tx_reqs);
spin_unlock(&dev->req_lock); spin_unlock(&dev->req_lock);
dev_kfree_skb_any(skb);
atomic_dec(&dev->tx_qlen); atomic_dec(&dev->tx_qlen);
if (netif_carrier_ok(dev->net)) if (netif_carrier_ok(dev->net))

View File

@@ -1256,6 +1256,7 @@ static void gserial_console_exit(void)
struct gscons_info *info = &gscons_info; struct gscons_info *info = &gscons_info;
unregister_console(&gserial_cons); unregister_console(&gserial_cons);
if (info->console_thread != NULL)
kthread_stop(info->console_thread); kthread_stop(info->console_thread);
gs_buf_free(&info->con_buf); gs_buf_free(&info->con_buf);
} }

View File

@@ -26,14 +26,12 @@
#define UVC_EVENT_DATA (V4L2_EVENT_PRIVATE_START + 5) #define UVC_EVENT_DATA (V4L2_EVENT_PRIVATE_START + 5)
#define UVC_EVENT_LAST (V4L2_EVENT_PRIVATE_START + 5) #define UVC_EVENT_LAST (V4L2_EVENT_PRIVATE_START + 5)
struct uvc_request_data struct uvc_request_data {
{
__s32 length; __s32 length;
__u8 data[60]; __u8 data[60];
}; };
struct uvc_event struct uvc_event {
{
union { union {
enum usb_device_speed speed; enum usb_device_speed speed;
struct usb_ctrlrequest req; struct usb_ctrlrequest req;
@@ -104,8 +102,7 @@ extern unsigned int uvc_gadget_trace_param;
* Structures * Structures
*/ */
struct uvc_video struct uvc_video {
{
struct usb_ep *ep; struct usb_ep *ep;
/* Frame parameters */ /* Frame parameters */
@@ -134,15 +131,13 @@ struct uvc_video
unsigned int fid; unsigned int fid;
}; };
enum uvc_state enum uvc_state {
{
UVC_STATE_DISCONNECTED, UVC_STATE_DISCONNECTED,
UVC_STATE_CONNECTED, UVC_STATE_CONNECTED,
UVC_STATE_STREAMING, UVC_STATE_STREAMING,
}; };
struct uvc_device struct uvc_device {
{
struct video_device vdev; struct video_device vdev;
struct v4l2_device v4l2_dev; struct v4l2_device v4l2_dev;
enum uvc_state state; enum uvc_state state;
@@ -175,8 +170,7 @@ static inline struct uvc_device *to_uvc(struct usb_function *f)
return container_of(f, struct uvc_device, func); return container_of(f, struct uvc_device, func);
} }
struct uvc_file_handle struct uvc_file_handle {
{
struct v4l2_fh vfh; struct v4l2_fh vfh;
struct uvc_video *device; struct uvc_video *device;
}; };

View File

@@ -53,8 +53,7 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
* V4L2 ioctls * V4L2 ioctls
*/ */
struct uvc_format struct uvc_format {
{
u8 bpp; u8 bpp;
u32 fcc; u32 fcc;
}; };

View File

@@ -243,7 +243,7 @@ uvc_video_alloc_requests(struct uvc_video *video)
req_size = video->ep->maxpacket req_size = video->ep->maxpacket
* max_t(unsigned int, video->ep->maxburst, 1) * max_t(unsigned int, video->ep->maxburst, 1)
* (video->ep->mult + 1); * (video->ep->mult);
for (i = 0; i < UVC_NUM_REQUESTS; ++i) { for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL); video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL);

View File

@@ -529,7 +529,7 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
DBG(DBG_GADGET, "%s: ep_enable: desc=%p\n", ep->ep.name, desc); DBG(DBG_GADGET, "%s: ep_enable: desc=%p\n", ep->ep.name, desc);
maxpacket = usb_endpoint_maxp(desc) & 0x7ff; maxpacket = usb_endpoint_maxp(desc);
if (((desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) != ep->index) if (((desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) != ep->index)
|| ep->index == 0 || ep->index == 0
@@ -573,7 +573,7 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
* Bits 11:12 specify number of _additional_ * Bits 11:12 specify number of _additional_
* transactions per microframe. * transactions per microframe.
*/ */
nr_trans = ((usb_endpoint_maxp(desc) >> 11) & 3) + 1; nr_trans = usb_endpoint_maxp_mult(desc);
if (nr_trans > 3) if (nr_trans > 3)
return -EINVAL; return -EINVAL;

View File

@@ -182,7 +182,7 @@ int bdc_config_ep(struct bdc *bdc, struct bdc_ep *ep)
usb_endpoint_xfer_int(desc)) { usb_endpoint_xfer_int(desc)) {
param2 |= si; param2 |= si;
mbs = (usb_endpoint_maxp(desc) & 0x1800) >> 11; mbs = usb_endpoint_maxp_mult(desc);
param2 |= mbs << MB_SHIFT; param2 |= mbs << MB_SHIFT;
} }
break; break;

View File

@@ -446,7 +446,7 @@ static int setup_bd_list_xfr(struct bdc *bdc, struct bdc_req *req, int num_bds)
bd_xfr->start_bdi = bd_list->eqp_bdi; bd_xfr->start_bdi = bd_list->eqp_bdi;
bd = bdi_to_bd(ep, bd_list->eqp_bdi); bd = bdi_to_bd(ep, bd_list->eqp_bdi);
req_len = req->usb_req.length; req_len = req->usb_req.length;
maxp = usb_endpoint_maxp(ep->desc) & 0x7ff; maxp = usb_endpoint_maxp(ep->desc);
tfs = roundup(req->usb_req.length, maxp); tfs = roundup(req->usb_req.length, maxp);
tfs = tfs/maxp; tfs = tfs/maxp;
dev_vdbg(bdc->dev, "%s ep:%s num_bds:%d tfs:%d r_len:%d bd:%p\n", dev_vdbg(bdc->dev, "%s ep:%s num_bds:%d tfs:%d r_len:%d bd:%p\n",

View File

@@ -503,7 +503,7 @@ static int dummy_enable(struct usb_ep *_ep,
* maximum packet size. * maximum packet size.
* For SS devices the wMaxPacketSize is limited by 1024. * For SS devices the wMaxPacketSize is limited by 1024.
*/ */
max = usb_endpoint_maxp(desc) & 0x7ff; max = usb_endpoint_maxp(desc);
/* drivers must not request bad settings, since lower levels /* drivers must not request bad settings, since lower levels
* (hardware or its drivers) may not check. some endpoints * (hardware or its drivers) may not check. some endpoints
@@ -1483,8 +1483,7 @@ static int periodic_bytes(struct dummy *dum, struct dummy_ep *ep)
int tmp; int tmp;
/* high bandwidth mode */ /* high bandwidth mode */
tmp = usb_endpoint_maxp(ep->desc); tmp = usb_endpoint_maxp_mult(ep->desc);
tmp = (tmp >> 11) & 0x03;
tmp *= 8 /* applies to entire frame */; tmp *= 8 /* applies to entire frame */;
limit += limit * tmp; limit += limit * tmp;
} }

View File

@@ -585,8 +585,7 @@ static int fsl_ep_enable(struct usb_ep *_ep,
break; break;
case USB_ENDPOINT_XFER_ISOC: case USB_ENDPOINT_XFER_ISOC:
/* Calculate transactions needed for high bandwidth iso */ /* Calculate transactions needed for high bandwidth iso */
mult = (unsigned char)(1 + ((max >> 11) & 0x03)); mult = usb_endpoint_maxp_mult(desc);
max = max & 0x7ff; /* bit 0~10 */
/* 3 transactions at most */ /* 3 transactions at most */
if (mult > 3) if (mult > 3)
goto en_done; goto en_done;

View File

@@ -218,7 +218,7 @@ static int config_ep(struct fusb300_ep *ep,
(info.type == USB_ENDPOINT_XFER_ISOC)) { (info.type == USB_ENDPOINT_XFER_ISOC)) {
info.interval = desc->bInterval; info.interval = desc->bInterval;
if (info.type == USB_ENDPOINT_XFER_ISOC) if (info.type == USB_ENDPOINT_XFER_ISOC)
info.bw_num = ((desc->wMaxPacketSize & 0x1800) >> 11); info.bw_num = usb_endpoint_maxp_mult(desc);
} }
ep_fifo_setting(fusb300, info); ep_fifo_setting(fusb300, info);

View File

@@ -1539,7 +1539,7 @@ static int gr_ep_enable(struct usb_ep *_ep,
* additional transactions. * additional transactions.
*/ */
max = 0x7ff & usb_endpoint_maxp(desc); max = 0x7ff & usb_endpoint_maxp(desc);
nt = 0x3 & (usb_endpoint_maxp(desc) >> 11); nt = usb_endpoint_maxp_mult(desc) - 1;
buffer_size = GR_BUFFER_SIZE(epctrl); buffer_size = GR_BUFFER_SIZE(epctrl);
if (nt && (mode == 0 || mode == 2)) { if (nt && (mode == 0 || mode == 2)) {
dev_err(dev->dev, dev_err(dev->dev,

View File

@@ -462,6 +462,12 @@ static int mv_u3d_req_to_trb(struct mv_u3d_req *req)
req->trb_head->trb_hw, req->trb_head->trb_hw,
trb_num * sizeof(*trb_hw), trb_num * sizeof(*trb_hw),
DMA_BIDIRECTIONAL); DMA_BIDIRECTIONAL);
if (dma_mapping_error(u3d->gadget.dev.parent,
req->trb_head->trb_dma)) {
kfree(req->trb_head->trb_hw);
kfree(req->trb_head);
return -EFAULT;
}
req->chain = 1; req->chain = 1;
} }
@@ -487,30 +493,32 @@ mv_u3d_start_queue(struct mv_u3d_ep *ep)
ret = usb_gadget_map_request(&u3d->gadget, &req->req, ret = usb_gadget_map_request(&u3d->gadget, &req->req,
mv_u3d_ep_dir(ep)); mv_u3d_ep_dir(ep));
if (ret) if (ret)
return ret; goto break_processing;
req->req.status = -EINPROGRESS; req->req.status = -EINPROGRESS;
req->req.actual = 0; req->req.actual = 0;
req->trb_count = 0; req->trb_count = 0;
/* build trbs and push them to device queue */ /* build trbs */
if (!mv_u3d_req_to_trb(req)) { ret = mv_u3d_req_to_trb(req);
ret = mv_u3d_queue_trb(ep, req);
if (ret) { if (ret) {
ep->processing = 0;
return ret;
}
} else {
ep->processing = 0;
dev_err(u3d->dev, "%s, mv_u3d_req_to_trb fail\n", __func__); dev_err(u3d->dev, "%s, mv_u3d_req_to_trb fail\n", __func__);
return -ENOMEM; goto break_processing;
} }
/* and push them to device queue */
ret = mv_u3d_queue_trb(ep, req);
if (ret)
goto break_processing;
/* irq handler advances the queue */ /* irq handler advances the queue */
if (req)
list_add_tail(&req->queue, &ep->queue); list_add_tail(&req->queue, &ep->queue);
return 0; return 0;
break_processing:
ep->processing = 0;
return ret;
} }
static int mv_u3d_ep_enable(struct usb_ep *_ep, static int mv_u3d_ep_enable(struct usb_ep *_ep,

View File

@@ -494,8 +494,7 @@ static int mv_ep_enable(struct usb_ep *_ep,
break; break;
case USB_ENDPOINT_XFER_ISOC: case USB_ENDPOINT_XFER_ISOC:
/* Calculate transactions needed for high bandwidth iso */ /* Calculate transactions needed for high bandwidth iso */
mult = (unsigned char)(1 + ((max >> 11) & 0x03)); mult = usb_endpoint_maxp_mult(desc);
max = max & 0x7ff; /* bit 0~10 */
/* 3 transactions at most */ /* 3 transactions at most */
if (mult > 3) if (mult > 3)
goto en_done; goto en_done;

View File

@@ -202,10 +202,10 @@ net2272_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
return -ESHUTDOWN; return -ESHUTDOWN;
max = usb_endpoint_maxp(desc) & 0x1fff; max = usb_endpoint_maxp(desc);
spin_lock_irqsave(&dev->lock, flags); spin_lock_irqsave(&dev->lock, flags);
_ep->maxpacket = max & 0x7fff; _ep->maxpacket = max;
ep->desc = desc; ep->desc = desc;
/* net2272_ep_reset() has already been called */ /* net2272_ep_reset() has already been called */

View File

@@ -224,14 +224,14 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
} }
/* sanity check ep-e/ep-f since their fifos are small */ /* sanity check ep-e/ep-f since their fifos are small */
max = usb_endpoint_maxp(desc) & 0x1fff; max = usb_endpoint_maxp(desc);
if (ep->num > 4 && max > 64 && (dev->quirks & PLX_LEGACY)) { if (ep->num > 4 && max > 64 && (dev->quirks & PLX_LEGACY)) {
ret = -ERANGE; ret = -ERANGE;
goto print_err; goto print_err;
} }
spin_lock_irqsave(&dev->lock, flags); spin_lock_irqsave(&dev->lock, flags);
_ep->maxpacket = max & 0x7ff; _ep->maxpacket = max;
ep->desc = desc; ep->desc = desc;
/* ep_reset() has already been called */ /* ep_reset() has already been called */
@@ -1839,7 +1839,7 @@ static ssize_t queues_show(struct device *_dev, struct device_attribute *attr,
ep->ep.name, t & USB_ENDPOINT_NUMBER_MASK, ep->ep.name, t & USB_ENDPOINT_NUMBER_MASK,
(t & USB_DIR_IN) ? "in" : "out", (t & USB_DIR_IN) ? "in" : "out",
type_string(d->bmAttributes), type_string(d->bmAttributes),
usb_endpoint_maxp(d) & 0x1fff, usb_endpoint_maxp(d),
ep->dma ? "dma" : "pio", ep->fifo_size ep->dma ? "dma" : "pio", ep->fifo_size
); );
} else /* ep0 should only have one transfer queued */ } else /* ep0 should only have one transfer queued */

View File

@@ -1047,10 +1047,10 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep,
if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
return -ESHUTDOWN; return -ESHUTDOWN;
max = usb_endpoint_maxp(desc) & 0x1fff; max = usb_endpoint_maxp(desc);
local_irq_save(flags); local_irq_save(flags);
_ep->maxpacket = max & 0x7ff; _ep->maxpacket = max;
ep->ep.desc = desc; ep->ep.desc = desc;
ep->halted = 0; ep->halted = 0;
ep->bEndpointAddress = desc->bEndpointAddress; ep->bEndpointAddress = desc->bEndpointAddress;

View File

@@ -550,11 +550,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
// high bandwidth multiplier, as encoded in highspeed endpoint descriptors
#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
// ... and packet size, for any kind of endpoint descriptor
#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
/* /*
* reverse of qh_urb_transaction: free a list of TDs. * reverse of qh_urb_transaction: free a list of TDs.
* used for cleanup after errors, before HC sees an URB's TDs. * used for cleanup after errors, before HC sees an URB's TDs.
@@ -651,7 +646,7 @@ qh_urb_transaction (
token |= (1 /* "in" */ << 8); token |= (1 /* "in" */ << 8);
/* else it's already initted to "out" pid (0 << 8) */ /* else it's already initted to "out" pid (0 << 8) */
maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input)); maxpacket = usb_maxpacket(urb->dev, urb->pipe, !is_input);
/* /*
* buffer gets wrapped in one or more qtds; * buffer gets wrapped in one or more qtds;
@@ -770,9 +765,11 @@ qh_make (
gfp_t flags gfp_t flags
) { ) {
struct ehci_qh *qh = ehci_qh_alloc (ehci, flags); struct ehci_qh *qh = ehci_qh_alloc (ehci, flags);
struct usb_host_endpoint *ep;
u32 info1 = 0, info2 = 0; u32 info1 = 0, info2 = 0;
int is_input, type; int is_input, type;
int maxp = 0; int maxp = 0;
int mult;
struct usb_tt *tt = urb->dev->tt; struct usb_tt *tt = urb->dev->tt;
struct ehci_qh_hw *hw; struct ehci_qh_hw *hw;
@@ -787,13 +784,15 @@ qh_make (
is_input = usb_pipein (urb->pipe); is_input = usb_pipein (urb->pipe);
type = usb_pipetype (urb->pipe); type = usb_pipetype (urb->pipe);
maxp = usb_maxpacket (urb->dev, urb->pipe, !is_input); ep = usb_pipe_endpoint (urb->dev, urb->pipe);
maxp = usb_endpoint_maxp (&ep->desc);
mult = usb_endpoint_maxp_mult (&ep->desc);
/* 1024 byte maxpacket is a hardware ceiling. High bandwidth /* 1024 byte maxpacket is a hardware ceiling. High bandwidth
* acts like up to 3KB, but is built from smaller packets. * acts like up to 3KB, but is built from smaller packets.
*/ */
if (max_packet(maxp) > 1024) { if (maxp > 1024) {
ehci_dbg(ehci, "bogus qh maxpacket %d\n", max_packet(maxp)); ehci_dbg(ehci, "bogus qh maxpacket %d\n", maxp);
goto done; goto done;
} }
@@ -809,8 +808,7 @@ qh_make (
unsigned tmp; unsigned tmp;
qh->ps.usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH, qh->ps.usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH,
is_input, 0, is_input, 0, mult * maxp));
hb_mult(maxp) * max_packet(maxp)));
qh->ps.phase = NO_FRAME; qh->ps.phase = NO_FRAME;
if (urb->dev->speed == USB_SPEED_HIGH) { if (urb->dev->speed == USB_SPEED_HIGH) {
@@ -854,7 +852,7 @@ qh_make (
think_time = tt ? tt->think_time : 0; think_time = tt ? tt->think_time : 0;
qh->ps.tt_usecs = NS_TO_US(think_time + qh->ps.tt_usecs = NS_TO_US(think_time +
usb_calc_bus_time (urb->dev->speed, usb_calc_bus_time (urb->dev->speed,
is_input, 0, max_packet (maxp))); is_input, 0, maxp));
if (urb->interval > ehci->periodic_size) if (urb->interval > ehci->periodic_size)
urb->interval = ehci->periodic_size; urb->interval = ehci->periodic_size;
qh->ps.period = urb->interval; qh->ps.period = urb->interval;
@@ -925,11 +923,11 @@ qh_make (
* to help them do so. So now people expect to use * to help them do so. So now people expect to use
* such nonconformant devices with Linux too; sigh. * such nonconformant devices with Linux too; sigh.
*/ */
info1 |= max_packet(maxp) << 16; info1 |= maxp << 16;
info2 |= (EHCI_TUNE_MULT_HS << 30); info2 |= (EHCI_TUNE_MULT_HS << 30);
} else { /* PIPE_INTERRUPT */ } else { /* PIPE_INTERRUPT */
info1 |= max_packet (maxp) << 16; info1 |= maxp << 16;
info2 |= hb_mult (maxp) << 30; info2 |= mult << 30;
} }
break; break;
default: default:
@@ -1221,7 +1219,7 @@ static int submit_single_step_set_feature(
token |= (1 /* "in" */ << 8); /*This is IN stage*/ token |= (1 /* "in" */ << 8); /*This is IN stage*/
maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, 0)); maxpacket = usb_maxpacket(urb->dev, urb->pipe, 0);
qtd_fill(ehci, qtd, buf, len, token, maxpacket); qtd_fill(ehci, qtd, buf, len, token, maxpacket);

View File

@@ -1064,11 +1064,10 @@ iso_stream_init(
/* knows about ITD vs SITD */ /* knows about ITD vs SITD */
if (dev->speed == USB_SPEED_HIGH) { if (dev->speed == USB_SPEED_HIGH) {
unsigned multi = hb_mult(maxp); unsigned multi = usb_endpoint_maxp_mult(&urb->ep->desc);
stream->highspeed = 1; stream->highspeed = 1;
maxp = max_packet(maxp);
buf1 |= maxp; buf1 |= maxp;
maxp *= multi; maxp *= multi;

View File

@@ -1369,7 +1369,7 @@ static u32 xhci_get_endpoint_max_burst(struct usb_device *udev,
if (udev->speed == USB_SPEED_HIGH && if (udev->speed == USB_SPEED_HIGH &&
(usb_endpoint_xfer_isoc(&ep->desc) || (usb_endpoint_xfer_isoc(&ep->desc) ||
usb_endpoint_xfer_int(&ep->desc))) usb_endpoint_xfer_int(&ep->desc)))
return (usb_endpoint_maxp(&ep->desc) & 0x1800) >> 11; return usb_endpoint_maxp_mult(&ep->desc) - 1;
return 0; return 0;
} }
@@ -1414,10 +1414,10 @@ static u32 xhci_get_max_esit_payload(struct usb_device *udev,
else if (udev->speed >= USB_SPEED_SUPER) else if (udev->speed >= USB_SPEED_SUPER)
return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval); return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); max_packet = usb_endpoint_maxp(&ep->desc);
max_burst = (usb_endpoint_maxp(&ep->desc) & 0x1800) >> 11; max_burst = usb_endpoint_maxp_mult(&ep->desc);
/* A 0 in max burst means 1 transfer per ESIT */ /* A 0 in max burst means 1 transfer per ESIT */
return max_packet * (max_burst + 1); return max_packet * max_burst;
} }
/* Set up an endpoint with one ring segment. Do not allocate stream rings. /* Set up an endpoint with one ring segment. Do not allocate stream rings.
@@ -1460,7 +1460,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
max_esit_payload = xhci_get_max_esit_payload(udev, ep); max_esit_payload = xhci_get_max_esit_payload(udev, ep);
interval = xhci_get_endpoint_interval(udev, ep); interval = xhci_get_endpoint_interval(udev, ep);
mult = xhci_get_endpoint_mult(udev, ep); mult = xhci_get_endpoint_mult(udev, ep);
max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); max_packet = usb_endpoint_maxp(&ep->desc);
max_burst = xhci_get_endpoint_max_burst(udev, ep); max_burst = xhci_get_endpoint_max_burst(udev, ep);
avg_trb_len = max_esit_payload; avg_trb_len = max_esit_payload;

View File

@@ -337,7 +337,7 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
xhci_dbg(xhci, "%s() type:%d, speed:%d, mpkt:%d, dir:%d, ep:%p\n", xhci_dbg(xhci, "%s() type:%d, speed:%d, mpkt:%d, dir:%d, ep:%p\n",
__func__, usb_endpoint_type(&ep->desc), udev->speed, __func__, usb_endpoint_type(&ep->desc), udev->speed,
GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)), usb_endpoint_maxp(&ep->desc),
usb_endpoint_dir_in(&ep->desc), ep); usb_endpoint_dir_in(&ep->desc), ep);
if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT)) { if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT)) {
@@ -403,7 +403,7 @@ void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
xhci_dbg(xhci, "%s() type:%d, speed:%d, mpks:%d, dir:%d, ep:%p\n", xhci_dbg(xhci, "%s() type:%d, speed:%d, mpks:%d, dir:%d, ep:%p\n",
__func__, usb_endpoint_type(&ep->desc), udev->speed, __func__, usb_endpoint_type(&ep->desc), udev->speed,
GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)), usb_endpoint_maxp(&ep->desc),
usb_endpoint_dir_in(&ep->desc), ep); usb_endpoint_dir_in(&ep->desc), ep);
if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT)) if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT))

View File

@@ -2991,7 +2991,7 @@ static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred,
if (xhci->quirks & XHCI_MTK_HOST) if (xhci->quirks & XHCI_MTK_HOST)
trb_buff_len = 0; trb_buff_len = 0;
maxp = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); maxp = usb_endpoint_maxp(&urb->ep->desc);
total_packet_count = DIV_ROUND_UP(td_total_len, maxp); total_packet_count = DIV_ROUND_UP(td_total_len, maxp);
/* Queueing functions don't count the current TRB into transferred */ /* Queueing functions don't count the current TRB into transferred */
@@ -3007,7 +3007,7 @@ static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len,
unsigned int max_pkt; unsigned int max_pkt;
u32 new_buff_len; u32 new_buff_len;
max_pkt = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); max_pkt = usb_endpoint_maxp(&urb->ep->desc);
unalign = (enqd_len + *trb_buff_len) % max_pkt; unalign = (enqd_len + *trb_buff_len) % max_pkt;
/* we got lucky, last normal TRB data on segment is packet aligned */ /* we got lucky, last normal TRB data on segment is packet aligned */
@@ -3521,7 +3521,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
addr = start_addr + urb->iso_frame_desc[i].offset; addr = start_addr + urb->iso_frame_desc[i].offset;
td_len = urb->iso_frame_desc[i].length; td_len = urb->iso_frame_desc[i].length;
td_remain_len = td_len; td_remain_len = td_len;
max_pkt = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); max_pkt = usb_endpoint_maxp(&urb->ep->desc);
total_pkt_count = DIV_ROUND_UP(td_len, max_pkt); total_pkt_count = DIV_ROUND_UP(td_len, max_pkt);
/* A zero-length transfer still involves at least one packet. */ /* A zero-length transfer still involves at least one packet. */

View File

@@ -3213,7 +3213,7 @@ int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
for (i = 0; i < num_eps; i++) { for (i = 0; i < num_eps; i++) {
ep_index = xhci_get_endpoint_index(&eps[i]->desc); ep_index = xhci_get_endpoint_index(&eps[i]->desc);
max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&eps[i]->desc)); max_packet = usb_endpoint_maxp(&eps[i]->desc);
vdev->eps[ep_index].stream_info = xhci_alloc_stream_info(xhci, vdev->eps[ep_index].stream_info = xhci_alloc_stream_info(xhci,
num_stream_ctxs, num_stream_ctxs,
num_streams, num_streams,

View File

@@ -749,11 +749,6 @@ struct xhci_ep_ctx {
#define MAX_PACKET_MASK (0xffff << 16) #define MAX_PACKET_MASK (0xffff << 16)
#define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff) #define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff)
/* Get max packet size from ep desc. Bit 10..0 specify the max packet size.
* USB2.0 spec 9.6.6.
*/
#define GET_MAX_PACKET(p) ((p) & 0x7ff)
/* tx_info bitmasks */ /* tx_info bitmasks */
#define EP_AVG_TRB_LENGTH(p) ((p) & 0xffff) #define EP_AVG_TRB_LENGTH(p) ((p) & 0xffff)
#define EP_MAX_ESIT_PAYLOAD_LO(p) (((p) & 0xffff) << 16) #define EP_MAX_ESIT_PAYLOAD_LO(p) (((p) & 0xffff) << 16)

View File

@@ -1915,7 +1915,7 @@ static struct urb *iso_alloc_urb(
if (bytes < 0 || !desc) if (bytes < 0 || !desc)
return NULL; return NULL;
maxp = 0x7ff & usb_endpoint_maxp(desc); maxp = 0x7ff & usb_endpoint_maxp(desc);
maxp *= 1 + (0x3 & (usb_endpoint_maxp(desc) >> 11)); maxp *= usb_endpoint_maxp_mult(desc);
packets = DIV_ROUND_UP(bytes, maxp); packets = DIV_ROUND_UP(bytes, maxp);
urb = usb_alloc_urb(packets, GFP_KERNEL); urb = usb_alloc_urb(packets, GFP_KERNEL);
@@ -2001,8 +2001,8 @@ test_queue(struct usbtest_dev *dev, struct usbtest_param_32 *param,
"iso period %d %sframes, wMaxPacket %d, transactions: %d\n", "iso period %d %sframes, wMaxPacket %d, transactions: %d\n",
1 << (desc->bInterval - 1), 1 << (desc->bInterval - 1),
(udev->speed == USB_SPEED_HIGH) ? "micro" : "", (udev->speed == USB_SPEED_HIGH) ? "micro" : "",
usb_endpoint_maxp(desc) & 0x7ff, usb_endpoint_maxp(desc),
1 + (0x3 & (usb_endpoint_maxp(desc) >> 11))); usb_endpoint_maxp_mult(desc));
dev_info(&dev->intf->dev, dev_info(&dev->intf->dev,
"total %lu msec (%lu packets)\n", "total %lu msec (%lu packets)\n",

View File

@@ -974,8 +974,8 @@ static int musb_gadget_enable(struct usb_ep *ep,
goto fail; goto fail;
/* REVISIT this rules out high bandwidth periodic transfers */ /* REVISIT this rules out high bandwidth periodic transfers */
tmp = usb_endpoint_maxp(desc); tmp = usb_endpoint_maxp_mult(desc) - 1;
if (tmp & ~0x07ff) { if (tmp) {
int ok; int ok;
if (usb_endpoint_dir_in(desc)) if (usb_endpoint_dir_in(desc))
@@ -987,12 +987,12 @@ static int musb_gadget_enable(struct usb_ep *ep,
musb_dbg(musb, "no support for high bandwidth ISO"); musb_dbg(musb, "no support for high bandwidth ISO");
goto fail; goto fail;
} }
musb_ep->hb_mult = (tmp >> 11) & 3; musb_ep->hb_mult = tmp;
} else { } else {
musb_ep->hb_mult = 0; musb_ep->hb_mult = 0;
} }
musb_ep->packet_sz = tmp & 0x7ff; musb_ep->packet_sz = usb_endpoint_maxp(desc);
tmp = musb_ep->packet_sz * (musb_ep->hb_mult + 1); tmp = musb_ep->packet_sz * (musb_ep->hb_mult + 1);
/* enable the interrupts for the endpoint, set the endpoint /* enable the interrupts for the endpoint, set the endpoint

View File

@@ -2237,7 +2237,7 @@ static int musb_urb_enqueue(
* Some musb cores don't support high bandwidth ISO transfers; and * Some musb cores don't support high bandwidth ISO transfers; and
* we don't (yet!) support high bandwidth interrupt transfers. * we don't (yet!) support high bandwidth interrupt transfers.
*/ */
qh->hb_mult = 1 + ((qh->maxpacket >> 11) & 0x03); qh->hb_mult = usb_endpoint_maxp_mult(epd);
if (qh->hb_mult > 1) { if (qh->hb_mult > 1) {
int ok = (qh->type == USB_ENDPOINT_XFER_ISOC); int ok = (qh->type == USB_ENDPOINT_XFER_ISOC);

View File

@@ -84,6 +84,7 @@ config SAMSUNG_USBPHY
config TWL6030_USB config TWL6030_USB
tristate "TWL6030 USB Transceiver Driver" tristate "TWL6030 USB Transceiver Driver"
depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS
depends on OF
help help
Enable this to support the USB OTG transceiver on TWL6030 Enable this to support the USB OTG transceiver on TWL6030
family chips. This TWL6030 transceiver has the VBUS and ID GND family chips. This TWL6030 transceiver has the VBUS and ID GND

View File

@@ -134,10 +134,12 @@ struct phy_control *am335x_get_phy_control(struct device *dev)
return NULL; return NULL;
dev = bus_find_device(&platform_bus_type, NULL, node, match); dev = bus_find_device(&platform_bus_type, NULL, node, match);
of_node_put(node);
if (!dev) if (!dev)
return NULL; return NULL;
ctrl_usb = dev_get_drvdata(dev); ctrl_usb = dev_get_drvdata(dev);
put_device(dev);
if (!ctrl_usb) if (!ctrl_usb)
return NULL; return NULL;
return &ctrl_usb->phy_ctrl; return &ctrl_usb->phy_ctrl;

View File

@@ -59,6 +59,15 @@ EXPORT_SYMBOL_GPL(usb_phy_generic_unregister);
static int nop_set_suspend(struct usb_phy *x, int suspend) static int nop_set_suspend(struct usb_phy *x, int suspend)
{ {
struct usb_phy_generic *nop = dev_get_drvdata(x->dev);
if (!IS_ERR(nop->clk)) {
if (suspend)
clk_disable_unprepare(nop->clk);
else
clk_prepare_enable(nop->clk);
}
return 0; return 0;
} }

View File

@@ -94,7 +94,7 @@ struct isp1301 {
#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3) #if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3)
#if defined(CONFIG_TPS65010) || (defined(CONFIG_TPS65010_MODULE) && defined(MODULE)) #if IS_REACHABLE(CONFIG_TPS65010)
#include <linux/i2c/tps65010.h> #include <linux/i2c/tps65010.h>

View File

@@ -108,7 +108,6 @@ struct twl6030_usb {
enum musb_vbus_id_status linkstat; enum musb_vbus_id_status linkstat;
u8 asleep; u8 asleep;
bool vbus_enable; bool vbus_enable;
const char *regulator;
}; };
#define comparator_to_twl(x) container_of((x), struct twl6030_usb, comparator) #define comparator_to_twl(x) container_of((x), struct twl6030_usb, comparator)
@@ -166,7 +165,7 @@ static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
/* Program MISC2 register and set bit VUSB_IN_VBAT */ /* Program MISC2 register and set bit VUSB_IN_VBAT */
twl6030_writeb(twl, TWL6030_MODULE_ID0, 0x10, TWL6030_MISC2); twl6030_writeb(twl, TWL6030_MODULE_ID0, 0x10, TWL6030_MISC2);
twl->usb3v3 = regulator_get(twl->dev, twl->regulator); twl->usb3v3 = regulator_get(twl->dev, "usb");
if (IS_ERR(twl->usb3v3)) if (IS_ERR(twl->usb3v3))
return -ENODEV; return -ENODEV;
@@ -341,7 +340,11 @@ static int twl6030_usb_probe(struct platform_device *pdev)
int status, err; int status, err;
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct twl4030_usb_data *pdata = dev_get_platdata(dev);
if (!np) {
dev_err(dev, "no DT info\n");
return -EINVAL;
}
twl = devm_kzalloc(dev, sizeof(*twl), GFP_KERNEL); twl = devm_kzalloc(dev, sizeof(*twl), GFP_KERNEL);
if (!twl) if (!twl)
@@ -361,18 +364,6 @@ static int twl6030_usb_probe(struct platform_device *pdev)
return -EPROBE_DEFER; return -EPROBE_DEFER;
} }
if (np) {
twl->regulator = "usb";
} else if (pdata) {
if (pdata->features & TWL6032_SUBCLASS)
twl->regulator = "ldousb";
else
twl->regulator = "vusb";
} else {
dev_err(&pdev->dev, "twl6030 initialized without pdata\n");
return -EINVAL;
}
/* init spinlock for workqueue */ /* init spinlock for workqueue */
spin_lock_init(&twl->lock); spin_lock_init(&twl->lock);
@@ -436,13 +427,11 @@ static int twl6030_usb_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_OF
static const struct of_device_id twl6030_usb_id_table[] = { static const struct of_device_id twl6030_usb_id_table[] = {
{ .compatible = "ti,twl6030-usb" }, { .compatible = "ti,twl6030-usb" },
{} {}
}; };
MODULE_DEVICE_TABLE(of, twl6030_usb_id_table); MODULE_DEVICE_TABLE(of, twl6030_usb_id_table);
#endif
static struct platform_driver twl6030_usb_driver = { static struct platform_driver twl6030_usb_driver = {
.probe = twl6030_usb_probe, .probe = twl6030_usb_probe,

View File

@@ -100,10 +100,7 @@ static void __usbhsf_pkt_del(struct usbhs_pkt *pkt)
static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe) static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe)
{ {
if (list_empty(&pipe->list)) return list_first_entry_or_null(&pipe->list, struct usbhs_pkt, node);
return NULL;
return list_first_entry(&pipe->list, struct usbhs_pkt, node);
} }
static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, static void usbhsf_fifo_clear(struct usbhs_pipe *pipe,

View File

@@ -259,7 +259,7 @@ static int vep_enable(struct usb_ep *_ep,
spin_lock_irqsave(&udc->lock, flags); spin_lock_irqsave(&udc->lock, flags);
maxp = usb_endpoint_maxp(desc) & 0x7ff; maxp = usb_endpoint_maxp(desc);
_ep->maxpacket = maxp; _ep->maxpacket = maxp;
ep->desc = desc; ep->desc = desc;
ep->type = usb_endpoint_type(desc); ep->type = usb_endpoint_type(desc);

View File

@@ -429,7 +429,9 @@ static inline struct usb_gadget *dev_to_usb_gadget(struct device *dev)
*/ */
static inline size_t usb_ep_align(struct usb_ep *ep, size_t len) static inline size_t usb_ep_align(struct usb_ep *ep, size_t len)
{ {
return round_up(len, (size_t)le16_to_cpu(ep->desc->wMaxPacketSize)); int max_packet_size = (size_t)usb_endpoint_maxp(ep->desc) & 0x7ff;
return round_up(len, max_packet_size);
} }
/** /**

View File

@@ -423,6 +423,12 @@ struct usb_endpoint_descriptor {
#define USB_ENDPOINT_XFER_INT 3 #define USB_ENDPOINT_XFER_INT 3
#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 #define USB_ENDPOINT_MAX_ADJUSTABLE 0x80
#define USB_ENDPOINT_MAXP_MASK 0x07ff
#define USB_EP_MAXP_MULT_SHIFT 11
#define USB_EP_MAXP_MULT_MASK (3 << USB_EP_MAXP_MULT_SHIFT)
#define USB_EP_MAXP_MULT(m) \
(((m) & USB_EP_MAXP_MULT_MASK) >> USB_EP_MAXP_MULT_SHIFT)
/* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */ /* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */
#define USB_ENDPOINT_INTRTYPE 0x30 #define USB_ENDPOINT_INTRTYPE 0x30
#define USB_ENDPOINT_INTR_PERIODIC (0 << 4) #define USB_ENDPOINT_INTR_PERIODIC (0 << 4)
@@ -623,11 +629,25 @@ static inline int usb_endpoint_is_isoc_out(
* usb_endpoint_maxp - get endpoint's max packet size * usb_endpoint_maxp - get endpoint's max packet size
* @epd: endpoint to be checked * @epd: endpoint to be checked
* *
* Returns @epd's max packet * Returns @epd's max packet bits [10:0]
*/ */
static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd) static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd)
{ {
return __le16_to_cpu(epd->wMaxPacketSize); return __le16_to_cpu(epd->wMaxPacketSize) & USB_ENDPOINT_MAXP_MASK;
}
/**
* usb_endpoint_maxp_mult - get endpoint's transactional opportunities
* @epd: endpoint to be checked
*
* Return @epd's wMaxPacketSize[12:11] + 1
*/
static inline int
usb_endpoint_maxp_mult(const struct usb_endpoint_descriptor *epd)
{
int maxp = __le16_to_cpu(epd->wMaxPacketSize);
return USB_EP_MAXP_MULT(maxp) + 1;
} }
static inline int usb_endpoint_interrupt_type( static inline int usb_endpoint_interrupt_type(