forked from Minki/linux
Merge branch 'for-next/gadget' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
* 'for-next/gadget' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb: (50 commits) usb: renesas_usbhs: show error reason on usbhsh_urb_enqueu() usb: renesas_usbhs: add force packet remove method usb: renesas_usbhs: care usb_hcd_giveback_urb() status usb: renesas_usbhs: add usbhsh_is_running() usb: renesas_usbhs: disable attch irq after device attached usb: renesas_usbhs: care pipe sequence usb: renesas_usbhs: add usbhs_pipe_attach() method usb: renesas_usbhs: add usbhsh_endpoint_detach_all() for error case usb: renesas_usbhs: modify device attach method usb: renesas_usbhs: pop packet when urb dequeued usb: renesas_usbhs: add lost error value when enqueue usb: gadget: mv_udc: replace some debug info usb: gadget: mv_udc: refine suspend/resume function usb: gadget: mv_udc: refine the clock relative code usb: gadget: mv_udc: disable ISR when stopped usb: gadget: mv_udc: add otg relative code usb: gadget: Use kcalloc instead of kzalloc to allocate array usb: renesas_usbhs: remove the_controller_link usb: renesas_usbhs: add test-mode support usb: renesas_usbhs: call usbhsg_queue_pop() when pipe disable. ...
This commit is contained in:
commit
121a8cdd79
@ -535,6 +535,20 @@ Why: In 3.0, we can now autodetect internal 3G device and already have
|
|||||||
information log when acer-wmi initial.
|
information log when acer-wmi initial.
|
||||||
Who: Lee, Chun-Yi <jlee@novell.com>
|
Who: Lee, Chun-Yi <jlee@novell.com>
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
What: /sys/devices/platform/_UDC_/udc/_UDC_/is_dualspeed file and
|
||||||
|
is_dualspeed line in /sys/devices/platform/ci13xxx_*/udc/device file.
|
||||||
|
When: 3.8
|
||||||
|
Why: The is_dualspeed file is superseded by maximum_speed in the same
|
||||||
|
directory and is_dualspeed line in device file is superseded by
|
||||||
|
max_speed line in the same file.
|
||||||
|
|
||||||
|
The maximum_speed/max_speed specifies maximum speed supported by UDC.
|
||||||
|
To check if dualspeeed is supported, check if the value is >= 3.
|
||||||
|
Various possible speeds are defined in <linux/usb/ch9.h>.
|
||||||
|
Who: Michal Nazarewicz <mina86@mina86.com>
|
||||||
|
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
What: The XFS nodelaylog mount option
|
What: The XFS nodelaylog mount option
|
||||||
|
@ -2087,7 +2087,7 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
|
|||||||
dev_set_name(&dwc->gadget.dev, "gadget");
|
dev_set_name(&dwc->gadget.dev, "gadget");
|
||||||
|
|
||||||
dwc->gadget.ops = &dwc3_gadget_ops;
|
dwc->gadget.ops = &dwc3_gadget_ops;
|
||||||
dwc->gadget.is_dualspeed = true;
|
dwc->gadget.max_speed = USB_SPEED_SUPER;
|
||||||
dwc->gadget.speed = USB_SPEED_UNKNOWN;
|
dwc->gadget.speed = USB_SPEED_UNKNOWN;
|
||||||
dwc->gadget.dev.parent = dwc->dev;
|
dwc->gadget.dev.parent = dwc->dev;
|
||||||
|
|
||||||
|
@ -235,7 +235,6 @@ config USB_R8A66597
|
|||||||
|
|
||||||
config USB_RENESAS_USBHS_UDC
|
config USB_RENESAS_USBHS_UDC
|
||||||
tristate 'Renesas USBHS controller'
|
tristate 'Renesas USBHS controller'
|
||||||
depends on SUPERH || ARCH_SHMOBILE
|
|
||||||
depends on USB_RENESAS_USBHS
|
depends on USB_RENESAS_USBHS
|
||||||
select USB_GADGET_DUALSPEED
|
select USB_GADGET_DUALSPEED
|
||||||
help
|
help
|
||||||
|
@ -1959,7 +1959,7 @@ static int amd5536_start(struct usb_gadget_driver *driver,
|
|||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
if (!driver || !bind || !driver->setup
|
if (!driver || !bind || !driver->setup
|
||||||
|| driver->speed < USB_SPEED_HIGH)
|
|| driver->max_speed < USB_SPEED_HIGH)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@ -3349,7 +3349,7 @@ static int udc_probe(struct udc *dev)
|
|||||||
dev_set_name(&dev->gadget.dev, "gadget");
|
dev_set_name(&dev->gadget.dev, "gadget");
|
||||||
dev->gadget.dev.release = gadget_release;
|
dev->gadget.dev.release = gadget_release;
|
||||||
dev->gadget.name = name;
|
dev->gadget.name = name;
|
||||||
dev->gadget.is_dualspeed = 1;
|
dev->gadget.max_speed = USB_SPEED_HIGH;
|
||||||
|
|
||||||
/* init registers, interrupts, ... */
|
/* init registers, interrupts, ... */
|
||||||
startup_registers(dev);
|
startup_registers(dev);
|
||||||
|
@ -1633,7 +1633,7 @@ static int at91_start(struct usb_gadget_driver *driver,
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (!driver
|
if (!driver
|
||||||
|| driver->speed < USB_SPEED_FULL
|
|| driver->max_speed < USB_SPEED_FULL
|
||||||
|| !bind
|
|| !bind
|
||||||
|| !driver->setup) {
|
|| !driver->setup) {
|
||||||
DBG("bad parameter.\n");
|
DBG("bad parameter.\n");
|
||||||
|
@ -1038,7 +1038,7 @@ static struct usba_udc the_udc = {
|
|||||||
.gadget = {
|
.gadget = {
|
||||||
.ops = &usba_udc_ops,
|
.ops = &usba_udc_ops,
|
||||||
.ep_list = LIST_HEAD_INIT(the_udc.gadget.ep_list),
|
.ep_list = LIST_HEAD_INIT(the_udc.gadget.ep_list),
|
||||||
.is_dualspeed = 1,
|
.max_speed = USB_SPEED_HIGH,
|
||||||
.name = "atmel_usba_udc",
|
.name = "atmel_usba_udc",
|
||||||
.dev = {
|
.dev = {
|
||||||
.init_name = "gadget",
|
.init_name = "gadget",
|
||||||
|
@ -182,6 +182,16 @@ static inline int hw_ep_bit(int num, int dir)
|
|||||||
return num + (dir ? 16 : 0);
|
return num + (dir ? 16 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ep_to_bit(int n)
|
||||||
|
{
|
||||||
|
int fill = 16 - hw_ep_max / 2;
|
||||||
|
|
||||||
|
if (n >= hw_ep_max / 2)
|
||||||
|
n += fill;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hw_aread: reads from register bitfield
|
* hw_aread: reads from register bitfield
|
||||||
* @addr: address relative to bus map
|
* @addr: address relative to bus map
|
||||||
@ -440,12 +450,13 @@ static int hw_ep_get_halt(int num, int dir)
|
|||||||
/**
|
/**
|
||||||
* hw_test_and_clear_setup_status: test & clear setup status (execute without
|
* hw_test_and_clear_setup_status: test & clear setup status (execute without
|
||||||
* interruption)
|
* interruption)
|
||||||
* @n: bit number (endpoint)
|
* @n: endpoint number
|
||||||
*
|
*
|
||||||
* This function returns setup status
|
* This function returns setup status
|
||||||
*/
|
*/
|
||||||
static int hw_test_and_clear_setup_status(int n)
|
static int hw_test_and_clear_setup_status(int n)
|
||||||
{
|
{
|
||||||
|
n = ep_to_bit(n);
|
||||||
return hw_ctest_and_clear(CAP_ENDPTSETUPSTAT, BIT(n));
|
return hw_ctest_and_clear(CAP_ENDPTSETUPSTAT, BIT(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -641,12 +652,13 @@ static int hw_register_write(u16 addr, u32 data)
|
|||||||
/**
|
/**
|
||||||
* hw_test_and_clear_complete: test & clear complete status (execute without
|
* hw_test_and_clear_complete: test & clear complete status (execute without
|
||||||
* interruption)
|
* interruption)
|
||||||
* @n: bit number (endpoint)
|
* @n: endpoint number
|
||||||
*
|
*
|
||||||
* This function returns complete status
|
* This function returns complete status
|
||||||
*/
|
*/
|
||||||
static int hw_test_and_clear_complete(int n)
|
static int hw_test_and_clear_complete(int n)
|
||||||
{
|
{
|
||||||
|
n = ep_to_bit(n);
|
||||||
return hw_ctest_and_clear(CAP_ENDPTCOMPLETE, BIT(n));
|
return hw_ctest_and_clear(CAP_ENDPTCOMPLETE, BIT(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -754,8 +766,11 @@ static ssize_t show_device(struct device *dev, struct device_attribute *attr,
|
|||||||
|
|
||||||
n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n",
|
n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n",
|
||||||
gadget->speed);
|
gadget->speed);
|
||||||
|
n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed = %d\n",
|
||||||
|
gadget->max_speed);
|
||||||
|
/* TODO: Scheduled for removal in 3.8. */
|
||||||
n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n",
|
n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n",
|
||||||
gadget->is_dualspeed);
|
gadget_is_dualspeed(gadget));
|
||||||
n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n",
|
n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n",
|
||||||
gadget->is_otg);
|
gadget->is_otg);
|
||||||
n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n",
|
n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n",
|
||||||
@ -798,7 +813,7 @@ static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
|
|||||||
n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n",
|
n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n",
|
||||||
(driver->function ? driver->function : ""));
|
(driver->function ? driver->function : ""));
|
||||||
n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
|
n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
|
||||||
driver->speed);
|
driver->max_speed);
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
@ -2563,9 +2578,7 @@ static int ci13xxx_start(struct usb_gadget_driver *driver,
|
|||||||
if (driver == NULL ||
|
if (driver == NULL ||
|
||||||
bind == NULL ||
|
bind == NULL ||
|
||||||
driver->setup == NULL ||
|
driver->setup == NULL ||
|
||||||
driver->disconnect == NULL ||
|
driver->disconnect == NULL)
|
||||||
driver->suspend == NULL ||
|
|
||||||
driver->resume == NULL)
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
else if (udc == NULL)
|
else if (udc == NULL)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@ -2693,8 +2706,6 @@ static int ci13xxx_stop(struct usb_gadget_driver *driver)
|
|||||||
driver->unbind == NULL ||
|
driver->unbind == NULL ||
|
||||||
driver->setup == NULL ||
|
driver->setup == NULL ||
|
||||||
driver->disconnect == NULL ||
|
driver->disconnect == NULL ||
|
||||||
driver->suspend == NULL ||
|
|
||||||
driver->resume == NULL ||
|
|
||||||
driver != udc->driver)
|
driver != udc->driver)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -2793,7 +2804,7 @@ static irqreturn_t udc_irq(void)
|
|||||||
isr_statistics.pci++;
|
isr_statistics.pci++;
|
||||||
udc->gadget.speed = hw_port_is_high_speed() ?
|
udc->gadget.speed = hw_port_is_high_speed() ?
|
||||||
USB_SPEED_HIGH : USB_SPEED_FULL;
|
USB_SPEED_HIGH : USB_SPEED_FULL;
|
||||||
if (udc->suspended) {
|
if (udc->suspended && udc->driver->resume) {
|
||||||
spin_unlock(udc->lock);
|
spin_unlock(udc->lock);
|
||||||
udc->driver->resume(&udc->gadget);
|
udc->driver->resume(&udc->gadget);
|
||||||
spin_lock(udc->lock);
|
spin_lock(udc->lock);
|
||||||
@ -2807,7 +2818,8 @@ static irqreturn_t udc_irq(void)
|
|||||||
isr_tr_complete_handler(udc);
|
isr_tr_complete_handler(udc);
|
||||||
}
|
}
|
||||||
if (USBi_SLI & intr) {
|
if (USBi_SLI & intr) {
|
||||||
if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
|
if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
|
||||||
|
udc->driver->suspend) {
|
||||||
udc->suspended = 1;
|
udc->suspended = 1;
|
||||||
spin_unlock(udc->lock);
|
spin_unlock(udc->lock);
|
||||||
udc->driver->suspend(&udc->gadget);
|
udc->driver->suspend(&udc->gadget);
|
||||||
@ -2871,7 +2883,7 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
|
|||||||
|
|
||||||
udc->gadget.ops = &usb_gadget_ops;
|
udc->gadget.ops = &usb_gadget_ops;
|
||||||
udc->gadget.speed = USB_SPEED_UNKNOWN;
|
udc->gadget.speed = USB_SPEED_UNKNOWN;
|
||||||
udc->gadget.is_dualspeed = 1;
|
udc->gadget.max_speed = USB_SPEED_HIGH;
|
||||||
udc->gadget.is_otg = 0;
|
udc->gadget.is_otg = 0;
|
||||||
udc->gadget.name = driver->name;
|
udc->gadget.name = driver->name;
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ struct ci13xxx {
|
|||||||
struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX]; /* extended endpts */
|
struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX]; /* extended endpts */
|
||||||
u32 ep0_dir; /* ep0 direction */
|
u32 ep0_dir; /* ep0 direction */
|
||||||
#define ep0out ci13xxx_ep[0]
|
#define ep0out ci13xxx_ep[0]
|
||||||
#define ep0in ci13xxx_ep[16]
|
#define ep0in ci13xxx_ep[hw_ep_max / 2]
|
||||||
u8 remote_wakeup; /* Is remote wakeup feature
|
u8 remote_wakeup; /* Is remote wakeup feature
|
||||||
enabled by the host? */
|
enabled by the host? */
|
||||||
u8 suspended; /* suspended by the host */
|
u8 suspended; /* suspended by the host */
|
||||||
|
@ -1535,9 +1535,9 @@ composite_resume(struct usb_gadget *gadget)
|
|||||||
|
|
||||||
static struct usb_gadget_driver composite_driver = {
|
static struct usb_gadget_driver composite_driver = {
|
||||||
#ifdef CONFIG_USB_GADGET_SUPERSPEED
|
#ifdef CONFIG_USB_GADGET_SUPERSPEED
|
||||||
.speed = USB_SPEED_SUPER,
|
.max_speed = USB_SPEED_SUPER,
|
||||||
#else
|
#else
|
||||||
.speed = USB_SPEED_HIGH,
|
.max_speed = USB_SPEED_HIGH,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
.unbind = composite_unbind,
|
.unbind = composite_unbind,
|
||||||
@ -1584,8 +1584,8 @@ int usb_composite_probe(struct usb_composite_driver *driver,
|
|||||||
driver->iProduct = driver->name;
|
driver->iProduct = driver->name;
|
||||||
composite_driver.function = (char *) driver->name;
|
composite_driver.function = (char *) driver->name;
|
||||||
composite_driver.driver.name = driver->name;
|
composite_driver.driver.name = driver->name;
|
||||||
composite_driver.speed = min((u8)composite_driver.speed,
|
composite_driver.max_speed =
|
||||||
(u8)driver->max_speed);
|
min_t(u8, composite_driver.max_speed, driver->max_speed);
|
||||||
composite = driver;
|
composite = driver;
|
||||||
composite_gadget_bind = bind;
|
composite_gadget_bind = bind;
|
||||||
|
|
||||||
|
@ -404,7 +404,7 @@ fail:
|
|||||||
|
|
||||||
static struct usb_gadget_driver dbgp_driver = {
|
static struct usb_gadget_driver dbgp_driver = {
|
||||||
.function = "dbgp",
|
.function = "dbgp",
|
||||||
.speed = USB_SPEED_HIGH,
|
.max_speed = USB_SPEED_HIGH,
|
||||||
.unbind = dbgp_unbind,
|
.unbind = dbgp_unbind,
|
||||||
.setup = dbgp_setup,
|
.setup = dbgp_setup,
|
||||||
.disconnect = dbgp_disconnect,
|
.disconnect = dbgp_disconnect,
|
||||||
|
@ -823,19 +823,18 @@ static int dummy_pullup (struct usb_gadget *_gadget, int value)
|
|||||||
|
|
||||||
if (value && dum->driver) {
|
if (value && dum->driver) {
|
||||||
if (mod_data.is_super_speed)
|
if (mod_data.is_super_speed)
|
||||||
dum->gadget.speed = dum->driver->speed;
|
dum->gadget.speed = dum->driver->max_speed;
|
||||||
else if (mod_data.is_high_speed)
|
else if (mod_data.is_high_speed)
|
||||||
dum->gadget.speed = min_t(u8, USB_SPEED_HIGH,
|
dum->gadget.speed = min_t(u8, USB_SPEED_HIGH,
|
||||||
dum->driver->speed);
|
dum->driver->max_speed);
|
||||||
else
|
else
|
||||||
dum->gadget.speed = USB_SPEED_FULL;
|
dum->gadget.speed = USB_SPEED_FULL;
|
||||||
dummy_udc_udpate_ep0(dum);
|
dummy_udc_udpate_ep0(dum);
|
||||||
|
|
||||||
if (dum->gadget.speed < dum->driver->speed)
|
if (dum->gadget.speed < dum->driver->max_speed)
|
||||||
dev_dbg(udc_dev(dum), "This device can perform faster"
|
dev_dbg(udc_dev(dum), "This device can perform faster"
|
||||||
" if you connect it to a %s port...\n",
|
" if you connect it to a %s port...\n",
|
||||||
(dum->driver->speed == USB_SPEED_SUPER ?
|
usb_speed_string(dum->driver->max_speed));
|
||||||
"SuperSpeed" : "HighSpeed"));
|
|
||||||
}
|
}
|
||||||
dum_hcd = gadget_to_dummy_hcd(_gadget);
|
dum_hcd = gadget_to_dummy_hcd(_gadget);
|
||||||
|
|
||||||
@ -898,7 +897,7 @@ static int dummy_udc_start(struct usb_gadget *g,
|
|||||||
struct dummy_hcd *dum_hcd = gadget_to_dummy_hcd(g);
|
struct dummy_hcd *dum_hcd = gadget_to_dummy_hcd(g);
|
||||||
struct dummy *dum = dum_hcd->dum;
|
struct dummy *dum = dum_hcd->dum;
|
||||||
|
|
||||||
if (driver->speed == USB_SPEED_UNKNOWN)
|
if (driver->max_speed == USB_SPEED_UNKNOWN)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -977,7 +976,7 @@ static int dummy_udc_probe (struct platform_device *pdev)
|
|||||||
|
|
||||||
dum->gadget.name = gadget_name;
|
dum->gadget.name = gadget_name;
|
||||||
dum->gadget.ops = &dummy_ops;
|
dum->gadget.ops = &dummy_ops;
|
||||||
dum->gadget.is_dualspeed = 1;
|
dum->gadget.max_speed = USB_SPEED_SUPER;
|
||||||
|
|
||||||
dev_set_name(&dum->gadget.dev, "gadget");
|
dev_set_name(&dum->gadget.dev, "gadget");
|
||||||
dum->gadget.dev.parent = &pdev->dev;
|
dum->gadget.dev.parent = &pdev->dev;
|
||||||
|
@ -152,7 +152,7 @@ ep_matches (
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case USB_ENDPOINT_XFER_INT:
|
case USB_ENDPOINT_XFER_INT:
|
||||||
/* INT: limit 64 bytes full speed, 1024 high/super speed */
|
/* INT: limit 64 bytes full speed, 1024 high/super speed */
|
||||||
if (!gadget->is_dualspeed && max > 64)
|
if (!gadget_is_dualspeed(gadget) && max > 64)
|
||||||
return 0;
|
return 0;
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
@ -160,12 +160,12 @@ ep_matches (
|
|||||||
/* ISO: limit 1023 bytes full speed, 1024 high/super speed */
|
/* ISO: limit 1023 bytes full speed, 1024 high/super speed */
|
||||||
if (ep->maxpacket < max)
|
if (ep->maxpacket < max)
|
||||||
return 0;
|
return 0;
|
||||||
if (!gadget->is_dualspeed && max > 1023)
|
if (!gadget_is_dualspeed(gadget) && max > 1023)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* BOTH: "high bandwidth" works only at high speed */
|
/* BOTH: "high bandwidth" works only at high speed */
|
||||||
if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) {
|
if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) {
|
||||||
if (!gadget->is_dualspeed)
|
if (!gadget_is_dualspeed(gadget))
|
||||||
return 0;
|
return 0;
|
||||||
/* configure your hardware with enough buffering!! */
|
/* configure your hardware with enough buffering!! */
|
||||||
}
|
}
|
||||||
|
@ -1408,7 +1408,7 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
|
|||||||
ENTER();
|
ENTER();
|
||||||
|
|
||||||
count = ffs->eps_count;
|
count = ffs->eps_count;
|
||||||
epfiles = kzalloc(count * sizeof *epfiles, GFP_KERNEL);
|
epfiles = kcalloc(count, sizeof(*epfiles), GFP_KERNEL);
|
||||||
if (!epfiles)
|
if (!epfiles)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -1873,17 +1873,14 @@ static int check_command(struct fsg_common *common, int cmnd_size,
|
|||||||
common->lun, lun);
|
common->lun, lun);
|
||||||
|
|
||||||
/* Check the LUN */
|
/* Check the LUN */
|
||||||
if (common->lun < common->nluns) {
|
curlun = common->curlun;
|
||||||
curlun = &common->luns[common->lun];
|
if (curlun) {
|
||||||
common->curlun = curlun;
|
|
||||||
if (common->cmnd[0] != REQUEST_SENSE) {
|
if (common->cmnd[0] != REQUEST_SENSE) {
|
||||||
curlun->sense_data = SS_NO_SENSE;
|
curlun->sense_data = SS_NO_SENSE;
|
||||||
curlun->sense_data_info = 0;
|
curlun->sense_data_info = 0;
|
||||||
curlun->info_valid = 0;
|
curlun->info_valid = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
common->curlun = NULL;
|
|
||||||
curlun = NULL;
|
|
||||||
common->bad_lun_okay = 0;
|
common->bad_lun_okay = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1929,6 +1926,17 @@ static int check_command(struct fsg_common *common, int cmnd_size,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* wrapper of check_command for data size in blocks handling */
|
||||||
|
static int check_command_size_in_blocks(struct fsg_common *common,
|
||||||
|
int cmnd_size, enum data_direction data_dir,
|
||||||
|
unsigned int mask, int needs_medium, const char *name)
|
||||||
|
{
|
||||||
|
if (common->curlun)
|
||||||
|
common->data_size_from_cmnd <<= common->curlun->blkbits;
|
||||||
|
return check_command(common, cmnd_size, data_dir,
|
||||||
|
mask, needs_medium, name);
|
||||||
|
}
|
||||||
|
|
||||||
static int do_scsi_command(struct fsg_common *common)
|
static int do_scsi_command(struct fsg_common *common)
|
||||||
{
|
{
|
||||||
struct fsg_buffhd *bh;
|
struct fsg_buffhd *bh;
|
||||||
@ -2011,9 +2019,9 @@ static int do_scsi_command(struct fsg_common *common)
|
|||||||
|
|
||||||
case READ_6:
|
case READ_6:
|
||||||
i = common->cmnd[4];
|
i = common->cmnd[4];
|
||||||
common->data_size_from_cmnd = (i == 0 ? 256 : i) <<
|
common->data_size_from_cmnd = (i == 0) ? 256 : i;
|
||||||
common->curlun->blkbits;
|
reply = check_command_size_in_blocks(common, 6,
|
||||||
reply = check_command(common, 6, DATA_DIR_TO_HOST,
|
DATA_DIR_TO_HOST,
|
||||||
(7<<1) | (1<<4), 1,
|
(7<<1) | (1<<4), 1,
|
||||||
"READ(6)");
|
"READ(6)");
|
||||||
if (reply == 0)
|
if (reply == 0)
|
||||||
@ -2022,9 +2030,9 @@ static int do_scsi_command(struct fsg_common *common)
|
|||||||
|
|
||||||
case READ_10:
|
case READ_10:
|
||||||
common->data_size_from_cmnd =
|
common->data_size_from_cmnd =
|
||||||
get_unaligned_be16(&common->cmnd[7]) <<
|
get_unaligned_be16(&common->cmnd[7]);
|
||||||
common->curlun->blkbits;
|
reply = check_command_size_in_blocks(common, 10,
|
||||||
reply = check_command(common, 10, DATA_DIR_TO_HOST,
|
DATA_DIR_TO_HOST,
|
||||||
(1<<1) | (0xf<<2) | (3<<7), 1,
|
(1<<1) | (0xf<<2) | (3<<7), 1,
|
||||||
"READ(10)");
|
"READ(10)");
|
||||||
if (reply == 0)
|
if (reply == 0)
|
||||||
@ -2033,9 +2041,9 @@ static int do_scsi_command(struct fsg_common *common)
|
|||||||
|
|
||||||
case READ_12:
|
case READ_12:
|
||||||
common->data_size_from_cmnd =
|
common->data_size_from_cmnd =
|
||||||
get_unaligned_be32(&common->cmnd[6]) <<
|
get_unaligned_be32(&common->cmnd[6]);
|
||||||
common->curlun->blkbits;
|
reply = check_command_size_in_blocks(common, 12,
|
||||||
reply = check_command(common, 12, DATA_DIR_TO_HOST,
|
DATA_DIR_TO_HOST,
|
||||||
(1<<1) | (0xf<<2) | (0xf<<6), 1,
|
(1<<1) | (0xf<<2) | (0xf<<6), 1,
|
||||||
"READ(12)");
|
"READ(12)");
|
||||||
if (reply == 0)
|
if (reply == 0)
|
||||||
@ -2134,9 +2142,9 @@ static int do_scsi_command(struct fsg_common *common)
|
|||||||
|
|
||||||
case WRITE_6:
|
case WRITE_6:
|
||||||
i = common->cmnd[4];
|
i = common->cmnd[4];
|
||||||
common->data_size_from_cmnd = (i == 0 ? 256 : i) <<
|
common->data_size_from_cmnd = (i == 0) ? 256 : i;
|
||||||
common->curlun->blkbits;
|
reply = check_command_size_in_blocks(common, 6,
|
||||||
reply = check_command(common, 6, DATA_DIR_FROM_HOST,
|
DATA_DIR_FROM_HOST,
|
||||||
(7<<1) | (1<<4), 1,
|
(7<<1) | (1<<4), 1,
|
||||||
"WRITE(6)");
|
"WRITE(6)");
|
||||||
if (reply == 0)
|
if (reply == 0)
|
||||||
@ -2145,9 +2153,9 @@ static int do_scsi_command(struct fsg_common *common)
|
|||||||
|
|
||||||
case WRITE_10:
|
case WRITE_10:
|
||||||
common->data_size_from_cmnd =
|
common->data_size_from_cmnd =
|
||||||
get_unaligned_be16(&common->cmnd[7]) <<
|
get_unaligned_be16(&common->cmnd[7]);
|
||||||
common->curlun->blkbits;
|
reply = check_command_size_in_blocks(common, 10,
|
||||||
reply = check_command(common, 10, DATA_DIR_FROM_HOST,
|
DATA_DIR_FROM_HOST,
|
||||||
(1<<1) | (0xf<<2) | (3<<7), 1,
|
(1<<1) | (0xf<<2) | (3<<7), 1,
|
||||||
"WRITE(10)");
|
"WRITE(10)");
|
||||||
if (reply == 0)
|
if (reply == 0)
|
||||||
@ -2156,9 +2164,9 @@ static int do_scsi_command(struct fsg_common *common)
|
|||||||
|
|
||||||
case WRITE_12:
|
case WRITE_12:
|
||||||
common->data_size_from_cmnd =
|
common->data_size_from_cmnd =
|
||||||
get_unaligned_be32(&common->cmnd[6]) <<
|
get_unaligned_be32(&common->cmnd[6]);
|
||||||
common->curlun->blkbits;
|
reply = check_command_size_in_blocks(common, 12,
|
||||||
reply = check_command(common, 12, DATA_DIR_FROM_HOST,
|
DATA_DIR_FROM_HOST,
|
||||||
(1<<1) | (0xf<<2) | (0xf<<6), 1,
|
(1<<1) | (0xf<<2) | (0xf<<6), 1,
|
||||||
"WRITE(12)");
|
"WRITE(12)");
|
||||||
if (reply == 0)
|
if (reply == 0)
|
||||||
@ -2273,6 +2281,10 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
|
|||||||
if (common->data_size == 0)
|
if (common->data_size == 0)
|
||||||
common->data_dir = DATA_DIR_NONE;
|
common->data_dir = DATA_DIR_NONE;
|
||||||
common->lun = cbw->Lun;
|
common->lun = cbw->Lun;
|
||||||
|
if (common->lun >= 0 && common->lun < common->nluns)
|
||||||
|
common->curlun = &common->luns[common->lun];
|
||||||
|
else
|
||||||
|
common->curlun = NULL;
|
||||||
common->tag = cbw->Tag;
|
common->tag = cbw->Tag;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2763,7 +2775,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
|
|||||||
* Create the LUNs, open their backing files, and register the
|
* Create the LUNs, open their backing files, and register the
|
||||||
* LUN devices in sysfs.
|
* LUN devices in sysfs.
|
||||||
*/
|
*/
|
||||||
curlun = kzalloc(nluns * sizeof *curlun, GFP_KERNEL);
|
curlun = kcalloc(nluns, sizeof(*curlun), GFP_KERNEL);
|
||||||
if (unlikely(!curlun)) {
|
if (unlikely(!curlun)) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto error_release;
|
goto error_release;
|
||||||
|
@ -2297,19 +2297,17 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
|
|||||||
DBG(fsg, "using LUN %d from CBW, "
|
DBG(fsg, "using LUN %d from CBW, "
|
||||||
"not LUN %d from CDB\n",
|
"not LUN %d from CDB\n",
|
||||||
fsg->lun, lun);
|
fsg->lun, lun);
|
||||||
} else
|
}
|
||||||
fsg->lun = lun; // Use LUN from the command
|
|
||||||
|
|
||||||
/* Check the LUN */
|
/* Check the LUN */
|
||||||
if (fsg->lun < fsg->nluns) {
|
curlun = fsg->curlun;
|
||||||
fsg->curlun = curlun = &fsg->luns[fsg->lun];
|
if (curlun) {
|
||||||
if (fsg->cmnd[0] != REQUEST_SENSE) {
|
if (fsg->cmnd[0] != REQUEST_SENSE) {
|
||||||
curlun->sense_data = SS_NO_SENSE;
|
curlun->sense_data = SS_NO_SENSE;
|
||||||
curlun->sense_data_info = 0;
|
curlun->sense_data_info = 0;
|
||||||
curlun->info_valid = 0;
|
curlun->info_valid = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fsg->curlun = curlun = NULL;
|
|
||||||
fsg->bad_lun_okay = 0;
|
fsg->bad_lun_okay = 0;
|
||||||
|
|
||||||
/* INQUIRY and REQUEST SENSE commands are explicitly allowed
|
/* INQUIRY and REQUEST SENSE commands are explicitly allowed
|
||||||
@ -2351,6 +2349,16 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* wrapper of check_command for data size in blocks handling */
|
||||||
|
static int check_command_size_in_blocks(struct fsg_dev *fsg, int cmnd_size,
|
||||||
|
enum data_direction data_dir, unsigned int mask,
|
||||||
|
int needs_medium, const char *name)
|
||||||
|
{
|
||||||
|
if (fsg->curlun)
|
||||||
|
fsg->data_size_from_cmnd <<= fsg->curlun->blkbits;
|
||||||
|
return check_command(fsg, cmnd_size, data_dir,
|
||||||
|
mask, needs_medium, name);
|
||||||
|
}
|
||||||
|
|
||||||
static int do_scsi_command(struct fsg_dev *fsg)
|
static int do_scsi_command(struct fsg_dev *fsg)
|
||||||
{
|
{
|
||||||
@ -2425,26 +2433,27 @@ static int do_scsi_command(struct fsg_dev *fsg)
|
|||||||
|
|
||||||
case READ_6:
|
case READ_6:
|
||||||
i = fsg->cmnd[4];
|
i = fsg->cmnd[4];
|
||||||
fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << fsg->curlun->blkbits;
|
fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
|
||||||
if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
|
if ((reply = check_command_size_in_blocks(fsg, 6,
|
||||||
|
DATA_DIR_TO_HOST,
|
||||||
(7<<1) | (1<<4), 1,
|
(7<<1) | (1<<4), 1,
|
||||||
"READ(6)")) == 0)
|
"READ(6)")) == 0)
|
||||||
reply = do_read(fsg);
|
reply = do_read(fsg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case READ_10:
|
case READ_10:
|
||||||
fsg->data_size_from_cmnd =
|
fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
|
||||||
get_unaligned_be16(&fsg->cmnd[7]) << fsg->curlun->blkbits;
|
if ((reply = check_command_size_in_blocks(fsg, 10,
|
||||||
if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
|
DATA_DIR_TO_HOST,
|
||||||
(1<<1) | (0xf<<2) | (3<<7), 1,
|
(1<<1) | (0xf<<2) | (3<<7), 1,
|
||||||
"READ(10)")) == 0)
|
"READ(10)")) == 0)
|
||||||
reply = do_read(fsg);
|
reply = do_read(fsg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case READ_12:
|
case READ_12:
|
||||||
fsg->data_size_from_cmnd =
|
fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
|
||||||
get_unaligned_be32(&fsg->cmnd[6]) << fsg->curlun->blkbits;
|
if ((reply = check_command_size_in_blocks(fsg, 12,
|
||||||
if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST,
|
DATA_DIR_TO_HOST,
|
||||||
(1<<1) | (0xf<<2) | (0xf<<6), 1,
|
(1<<1) | (0xf<<2) | (0xf<<6), 1,
|
||||||
"READ(12)")) == 0)
|
"READ(12)")) == 0)
|
||||||
reply = do_read(fsg);
|
reply = do_read(fsg);
|
||||||
@ -2529,26 +2538,27 @@ static int do_scsi_command(struct fsg_dev *fsg)
|
|||||||
|
|
||||||
case WRITE_6:
|
case WRITE_6:
|
||||||
i = fsg->cmnd[4];
|
i = fsg->cmnd[4];
|
||||||
fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << fsg->curlun->blkbits;
|
fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
|
||||||
if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
|
if ((reply = check_command_size_in_blocks(fsg, 6,
|
||||||
|
DATA_DIR_FROM_HOST,
|
||||||
(7<<1) | (1<<4), 1,
|
(7<<1) | (1<<4), 1,
|
||||||
"WRITE(6)")) == 0)
|
"WRITE(6)")) == 0)
|
||||||
reply = do_write(fsg);
|
reply = do_write(fsg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WRITE_10:
|
case WRITE_10:
|
||||||
fsg->data_size_from_cmnd =
|
fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
|
||||||
get_unaligned_be16(&fsg->cmnd[7]) << fsg->curlun->blkbits;
|
if ((reply = check_command_size_in_blocks(fsg, 10,
|
||||||
if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
|
DATA_DIR_FROM_HOST,
|
||||||
(1<<1) | (0xf<<2) | (3<<7), 1,
|
(1<<1) | (0xf<<2) | (3<<7), 1,
|
||||||
"WRITE(10)")) == 0)
|
"WRITE(10)")) == 0)
|
||||||
reply = do_write(fsg);
|
reply = do_write(fsg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WRITE_12:
|
case WRITE_12:
|
||||||
fsg->data_size_from_cmnd =
|
fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
|
||||||
get_unaligned_be32(&fsg->cmnd[6]) << fsg->curlun->blkbits;
|
if ((reply = check_command_size_in_blocks(fsg, 12,
|
||||||
if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST,
|
DATA_DIR_FROM_HOST,
|
||||||
(1<<1) | (0xf<<2) | (0xf<<6), 1,
|
(1<<1) | (0xf<<2) | (0xf<<6), 1,
|
||||||
"WRITE(12)")) == 0)
|
"WRITE(12)")) == 0)
|
||||||
reply = do_write(fsg);
|
reply = do_write(fsg);
|
||||||
@ -2715,7 +2725,17 @@ static int get_next_command(struct fsg_dev *fsg)
|
|||||||
memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size);
|
memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size);
|
||||||
fsg->cbbuf_cmnd_size = 0;
|
fsg->cbbuf_cmnd_size = 0;
|
||||||
spin_unlock_irq(&fsg->lock);
|
spin_unlock_irq(&fsg->lock);
|
||||||
|
|
||||||
|
/* Use LUN from the command */
|
||||||
|
fsg->lun = fsg->cmnd[1] >> 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update current lun */
|
||||||
|
if (fsg->lun >= 0 && fsg->lun < fsg->nluns)
|
||||||
|
fsg->curlun = &fsg->luns[fsg->lun];
|
||||||
|
else
|
||||||
|
fsg->curlun = NULL;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3584,7 +3604,7 @@ static void fsg_resume(struct usb_gadget *gadget)
|
|||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static struct usb_gadget_driver fsg_driver = {
|
static struct usb_gadget_driver fsg_driver = {
|
||||||
.speed = USB_SPEED_SUPER,
|
.max_speed = USB_SPEED_SUPER,
|
||||||
.function = (char *) fsg_string_product,
|
.function = (char *) fsg_string_product,
|
||||||
.unbind = fsg_unbind,
|
.unbind = fsg_unbind,
|
||||||
.disconnect = fsg_disconnect,
|
.disconnect = fsg_disconnect,
|
||||||
|
@ -2336,7 +2336,7 @@ static int fsl_qe_start(struct usb_gadget_driver *driver,
|
|||||||
if (!udc_controller)
|
if (!udc_controller)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (!driver || driver->speed < USB_SPEED_FULL
|
if (!driver || driver->max_speed < USB_SPEED_FULL
|
||||||
|| !bind || !driver->disconnect || !driver->setup)
|
|| !bind || !driver->disconnect || !driver->setup)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -2350,7 +2350,7 @@ static int fsl_qe_start(struct usb_gadget_driver *driver,
|
|||||||
/* hook up the driver */
|
/* hook up the driver */
|
||||||
udc_controller->driver = driver;
|
udc_controller->driver = driver;
|
||||||
udc_controller->gadget.dev.driver = &driver->driver;
|
udc_controller->gadget.dev.driver = &driver->driver;
|
||||||
udc_controller->gadget.speed = (enum usb_device_speed)(driver->speed);
|
udc_controller->gadget.speed = driver->max_speed;
|
||||||
spin_unlock_irqrestore(&udc_controller->lock, flags);
|
spin_unlock_irqrestore(&udc_controller->lock, flags);
|
||||||
|
|
||||||
retval = bind(&udc_controller->gadget);
|
retval = bind(&udc_controller->gadget);
|
||||||
|
@ -1934,7 +1934,7 @@ static int fsl_start(struct usb_gadget_driver *driver,
|
|||||||
if (!udc_controller)
|
if (!udc_controller)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (!driver || driver->speed < USB_SPEED_FULL
|
if (!driver || driver->max_speed < USB_SPEED_FULL
|
||||||
|| !bind || !driver->disconnect || !driver->setup)
|
|| !bind || !driver->disconnect || !driver->setup)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -2525,7 +2525,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
/* Setup gadget structure */
|
/* Setup gadget structure */
|
||||||
udc_controller->gadget.ops = &fsl_gadget_ops;
|
udc_controller->gadget.ops = &fsl_gadget_ops;
|
||||||
udc_controller->gadget.is_dualspeed = 1;
|
udc_controller->gadget.max_speed = USB_SPEED_HIGH;
|
||||||
udc_controller->gadget.ep0 = &udc_controller->eps[0].ep;
|
udc_controller->gadget.ep0 = &udc_controller->eps[0].ep;
|
||||||
INIT_LIST_HEAD(&udc_controller->gadget.ep_list);
|
INIT_LIST_HEAD(&udc_controller->gadget.ep_list);
|
||||||
udc_controller->gadget.speed = USB_SPEED_UNKNOWN;
|
udc_controller->gadget.speed = USB_SPEED_UNKNOWN;
|
||||||
|
@ -1317,7 +1317,7 @@ static int fusb300_udc_start(struct usb_gadget_driver *driver,
|
|||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (!driver
|
if (!driver
|
||||||
|| driver->speed < USB_SPEED_FULL
|
|| driver->max_speed < USB_SPEED_FULL
|
||||||
|| !bind
|
|| !bind
|
||||||
|| !driver->setup)
|
|| !driver->setup)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -1463,7 +1463,7 @@ static int __init fusb300_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
dev_set_name(&fusb300->gadget.dev, "gadget");
|
dev_set_name(&fusb300->gadget.dev, "gadget");
|
||||||
|
|
||||||
fusb300->gadget.is_dualspeed = 1;
|
fusb300->gadget.max_speed = USB_SPEED_HIGH;
|
||||||
fusb300->gadget.dev.parent = &pdev->dev;
|
fusb300->gadget.dev.parent = &pdev->dev;
|
||||||
fusb300->gadget.dev.dma_mask = pdev->dev.dma_mask;
|
fusb300->gadget.dev.dma_mask = pdev->dev.dma_mask;
|
||||||
fusb300->gadget.dev.release = pdev->dev.release;
|
fusb300->gadget.dev.release = pdev->dev.release;
|
||||||
|
@ -1357,7 +1357,7 @@ static int goku_start(struct usb_gadget_driver *driver,
|
|||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (!driver
|
if (!driver
|
||||||
|| driver->speed < USB_SPEED_FULL
|
|| driver->max_speed < USB_SPEED_FULL
|
||||||
|| !bind
|
|| !bind
|
||||||
|| !driver->disconnect
|
|| !driver->disconnect
|
||||||
|| !driver->setup)
|
|| !driver->setup)
|
||||||
@ -1796,6 +1796,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||||||
spin_lock_init(&dev->lock);
|
spin_lock_init(&dev->lock);
|
||||||
dev->pdev = pdev;
|
dev->pdev = pdev;
|
||||||
dev->gadget.ops = &goku_ops;
|
dev->gadget.ops = &goku_ops;
|
||||||
|
dev->gadget.max_speed = USB_SPEED_FULL;
|
||||||
|
|
||||||
/* the "gadget" abstracts/virtualizes the controller */
|
/* the "gadget" abstracts/virtualizes the controller */
|
||||||
dev_set_name(&dev->gadget.dev, "gadget");
|
dev_set_name(&dev->gadget.dev, "gadget");
|
||||||
|
@ -1336,7 +1336,7 @@ static int imx_udc_start(struct usb_gadget_driver *driver,
|
|||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (!driver
|
if (!driver
|
||||||
|| driver->speed < USB_SPEED_FULL
|
|| driver->max_speed < USB_SPEED_FULL
|
||||||
|| !bind
|
|| !bind
|
||||||
|| !driver->disconnect
|
|| !driver->disconnect
|
||||||
|| !driver->setup)
|
|| !driver->setup)
|
||||||
|
@ -1766,9 +1766,9 @@ gadgetfs_suspend (struct usb_gadget *gadget)
|
|||||||
|
|
||||||
static struct usb_gadget_driver gadgetfs_driver = {
|
static struct usb_gadget_driver gadgetfs_driver = {
|
||||||
#ifdef CONFIG_USB_GADGET_DUALSPEED
|
#ifdef CONFIG_USB_GADGET_DUALSPEED
|
||||||
.speed = USB_SPEED_HIGH,
|
.max_speed = USB_SPEED_HIGH,
|
||||||
#else
|
#else
|
||||||
.speed = USB_SPEED_FULL,
|
.max_speed = USB_SPEED_FULL,
|
||||||
#endif
|
#endif
|
||||||
.function = (char *) driver_desc,
|
.function = (char *) driver_desc,
|
||||||
.unbind = gadgetfs_unbind,
|
.unbind = gadgetfs_unbind,
|
||||||
@ -1792,7 +1792,7 @@ static int gadgetfs_probe (struct usb_gadget *gadget)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct usb_gadget_driver probe_driver = {
|
static struct usb_gadget_driver probe_driver = {
|
||||||
.speed = USB_SPEED_HIGH,
|
.max_speed = USB_SPEED_HIGH,
|
||||||
.unbind = gadgetfs_nop,
|
.unbind = gadgetfs_nop,
|
||||||
.setup = (void *)gadgetfs_nop,
|
.setup = (void *)gadgetfs_nop,
|
||||||
.disconnect = gadgetfs_nop,
|
.disconnect = gadgetfs_nop,
|
||||||
|
@ -3267,7 +3267,7 @@ static int langwell_udc_probe(struct pci_dev *pdev,
|
|||||||
dev->gadget.ep0 = &dev->ep[0].ep; /* gadget ep0 */
|
dev->gadget.ep0 = &dev->ep[0].ep; /* gadget ep0 */
|
||||||
INIT_LIST_HEAD(&dev->gadget.ep_list); /* ep_list */
|
INIT_LIST_HEAD(&dev->gadget.ep_list); /* ep_list */
|
||||||
dev->gadget.speed = USB_SPEED_UNKNOWN; /* speed */
|
dev->gadget.speed = USB_SPEED_UNKNOWN; /* speed */
|
||||||
dev->gadget.is_dualspeed = 1; /* support dual speed */
|
dev->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */
|
||||||
#ifdef OTG_TRANSCEIVER
|
#ifdef OTG_TRANSCEIVER
|
||||||
dev->gadget.is_otg = 1; /* support otg mode */
|
dev->gadget.is_otg = 1; /* support otg mode */
|
||||||
#endif
|
#endif
|
||||||
|
@ -1472,7 +1472,7 @@ static int m66592_start(struct usb_gadget_driver *driver,
|
|||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (!driver
|
if (!driver
|
||||||
|| driver->speed < USB_SPEED_HIGH
|
|| driver->max_speed < USB_SPEED_HIGH
|
||||||
|| !bind
|
|| !bind
|
||||||
|| !driver->setup)
|
|| !driver->setup)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -1653,7 +1653,7 @@ static int __init m66592_probe(struct platform_device *pdev)
|
|||||||
m66592->gadget.ops = &m66592_gadget_ops;
|
m66592->gadget.ops = &m66592_gadget_ops;
|
||||||
device_initialize(&m66592->gadget.dev);
|
device_initialize(&m66592->gadget.dev);
|
||||||
dev_set_name(&m66592->gadget.dev, "gadget");
|
dev_set_name(&m66592->gadget.dev, "gadget");
|
||||||
m66592->gadget.is_dualspeed = 1;
|
m66592->gadget.max_speed = USB_SPEED_HIGH;
|
||||||
m66592->gadget.dev.parent = &pdev->dev;
|
m66592->gadget.dev.parent = &pdev->dev;
|
||||||
m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
|
m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
|
||||||
m66592->gadget.dev.release = pdev->dev.release;
|
m66592->gadget.dev.release = pdev->dev.release;
|
||||||
|
@ -211,11 +211,14 @@ struct mv_udc {
|
|||||||
softconnected:1,
|
softconnected:1,
|
||||||
force_fs:1,
|
force_fs:1,
|
||||||
clock_gating:1,
|
clock_gating:1,
|
||||||
active:1;
|
active:1,
|
||||||
|
stopped:1; /* stop bit is setted */
|
||||||
|
|
||||||
struct work_struct vbus_work;
|
struct work_struct vbus_work;
|
||||||
struct workqueue_struct *qwork;
|
struct workqueue_struct *qwork;
|
||||||
|
|
||||||
|
struct otg_transceiver *transceiver;
|
||||||
|
|
||||||
struct mv_usb_platform_data *pdata;
|
struct mv_usb_platform_data *pdata;
|
||||||
|
|
||||||
/* some SOC has mutiple clock sources for USB*/
|
/* some SOC has mutiple clock sources for USB*/
|
||||||
|
@ -1056,6 +1056,8 @@ static void udc_stop(struct mv_udc *udc)
|
|||||||
USBINTR_PORT_CHANGE_DETECT_EN | USBINTR_RESET_EN);
|
USBINTR_PORT_CHANGE_DETECT_EN | USBINTR_RESET_EN);
|
||||||
writel(tmp, &udc->op_regs->usbintr);
|
writel(tmp, &udc->op_regs->usbintr);
|
||||||
|
|
||||||
|
udc->stopped = 1;
|
||||||
|
|
||||||
/* Reset the Run the bit in the command register to stop VUSB */
|
/* Reset the Run the bit in the command register to stop VUSB */
|
||||||
tmp = readl(&udc->op_regs->usbcmd);
|
tmp = readl(&udc->op_regs->usbcmd);
|
||||||
tmp &= ~USBCMD_RUN_STOP;
|
tmp &= ~USBCMD_RUN_STOP;
|
||||||
@ -1072,6 +1074,8 @@ static void udc_start(struct mv_udc *udc)
|
|||||||
/* Enable interrupts */
|
/* Enable interrupts */
|
||||||
writel(usbintr, &udc->op_regs->usbintr);
|
writel(usbintr, &udc->op_regs->usbintr);
|
||||||
|
|
||||||
|
udc->stopped = 0;
|
||||||
|
|
||||||
/* Set the Run bit in the command register */
|
/* Set the Run bit in the command register */
|
||||||
writel(USBCMD_RUN_STOP, &udc->op_regs->usbcmd);
|
writel(USBCMD_RUN_STOP, &udc->op_regs->usbcmd);
|
||||||
}
|
}
|
||||||
@ -1134,11 +1138,11 @@ static int udc_reset(struct mv_udc *udc)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mv_udc_enable(struct mv_udc *udc)
|
static int mv_udc_enable_internal(struct mv_udc *udc)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (udc->clock_gating == 0 || udc->active)
|
if (udc->active)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dev_dbg(&udc->dev->dev, "enable udc\n");
|
dev_dbg(&udc->dev->dev, "enable udc\n");
|
||||||
@ -1157,9 +1161,17 @@ static int mv_udc_enable(struct mv_udc *udc)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mv_udc_disable(struct mv_udc *udc)
|
static int mv_udc_enable(struct mv_udc *udc)
|
||||||
{
|
{
|
||||||
if (udc->clock_gating && udc->active) {
|
if (udc->clock_gating)
|
||||||
|
return mv_udc_enable_internal(udc);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mv_udc_disable_internal(struct mv_udc *udc)
|
||||||
|
{
|
||||||
|
if (udc->active) {
|
||||||
dev_dbg(&udc->dev->dev, "disable udc\n");
|
dev_dbg(&udc->dev->dev, "disable udc\n");
|
||||||
if (udc->pdata->phy_deinit)
|
if (udc->pdata->phy_deinit)
|
||||||
udc->pdata->phy_deinit(udc->phy_regs);
|
udc->pdata->phy_deinit(udc->phy_regs);
|
||||||
@ -1168,6 +1180,12 @@ static void mv_udc_disable(struct mv_udc *udc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mv_udc_disable(struct mv_udc *udc)
|
||||||
|
{
|
||||||
|
if (udc->clock_gating)
|
||||||
|
mv_udc_disable_internal(udc);
|
||||||
|
}
|
||||||
|
|
||||||
static int mv_udc_get_frame(struct usb_gadget *gadget)
|
static int mv_udc_get_frame(struct usb_gadget *gadget)
|
||||||
{
|
{
|
||||||
struct mv_udc *udc;
|
struct mv_udc *udc;
|
||||||
@ -1212,10 +1230,11 @@ static int mv_udc_vbus_session(struct usb_gadget *gadget, int is_active)
|
|||||||
udc = container_of(gadget, struct mv_udc, gadget);
|
udc = container_of(gadget, struct mv_udc, gadget);
|
||||||
spin_lock_irqsave(&udc->lock, flags);
|
spin_lock_irqsave(&udc->lock, flags);
|
||||||
|
|
||||||
|
udc->vbus_active = (is_active != 0);
|
||||||
|
|
||||||
dev_dbg(&udc->dev->dev, "%s: softconnect %d, vbus_active %d\n",
|
dev_dbg(&udc->dev->dev, "%s: softconnect %d, vbus_active %d\n",
|
||||||
__func__, udc->softconnect, udc->vbus_active);
|
__func__, udc->softconnect, udc->vbus_active);
|
||||||
|
|
||||||
udc->vbus_active = (is_active != 0);
|
|
||||||
if (udc->driver && udc->softconnect && udc->vbus_active) {
|
if (udc->driver && udc->softconnect && udc->vbus_active) {
|
||||||
retval = mv_udc_enable(udc);
|
retval = mv_udc_enable(udc);
|
||||||
if (retval == 0) {
|
if (retval == 0) {
|
||||||
@ -1244,10 +1263,11 @@ static int mv_udc_pullup(struct usb_gadget *gadget, int is_on)
|
|||||||
udc = container_of(gadget, struct mv_udc, gadget);
|
udc = container_of(gadget, struct mv_udc, gadget);
|
||||||
spin_lock_irqsave(&udc->lock, flags);
|
spin_lock_irqsave(&udc->lock, flags);
|
||||||
|
|
||||||
|
udc->softconnect = (is_on != 0);
|
||||||
|
|
||||||
dev_dbg(&udc->dev->dev, "%s: softconnect %d, vbus_active %d\n",
|
dev_dbg(&udc->dev->dev, "%s: softconnect %d, vbus_active %d\n",
|
||||||
__func__, udc->softconnect, udc->vbus_active);
|
__func__, udc->softconnect, udc->vbus_active);
|
||||||
|
|
||||||
udc->softconnect = (is_on != 0);
|
|
||||||
if (udc->driver && udc->softconnect && udc->vbus_active) {
|
if (udc->driver && udc->softconnect && udc->vbus_active) {
|
||||||
retval = mv_udc_enable(udc);
|
retval = mv_udc_enable(udc);
|
||||||
if (retval == 0) {
|
if (retval == 0) {
|
||||||
@ -1407,6 +1427,20 @@ static int mv_udc_start(struct usb_gadget_driver *driver,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (udc->transceiver) {
|
||||||
|
retval = otg_set_peripheral(udc->transceiver, &udc->gadget);
|
||||||
|
if (retval) {
|
||||||
|
dev_err(&udc->dev->dev,
|
||||||
|
"unable to register peripheral to otg\n");
|
||||||
|
if (driver->unbind) {
|
||||||
|
driver->unbind(&udc->gadget);
|
||||||
|
udc->gadget.dev.driver = NULL;
|
||||||
|
udc->driver = NULL;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* pullup is always on */
|
/* pullup is always on */
|
||||||
mv_udc_pullup(&udc->gadget, 1);
|
mv_udc_pullup(&udc->gadget, 1);
|
||||||
|
|
||||||
@ -2026,6 +2060,10 @@ static irqreturn_t mv_udc_irq(int irq, void *dev)
|
|||||||
struct mv_udc *udc = (struct mv_udc *)dev;
|
struct mv_udc *udc = (struct mv_udc *)dev;
|
||||||
u32 status, intr;
|
u32 status, intr;
|
||||||
|
|
||||||
|
/* Disable ISR when stopped bit is set */
|
||||||
|
if (udc->stopped)
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
spin_lock(&udc->lock);
|
spin_lock(&udc->lock);
|
||||||
|
|
||||||
status = readl(&udc->op_regs->usbsts);
|
status = readl(&udc->op_regs->usbsts);
|
||||||
@ -2109,7 +2147,12 @@ static int __devexit mv_udc_remove(struct platform_device *dev)
|
|||||||
destroy_workqueue(udc->qwork);
|
destroy_workqueue(udc->qwork);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (udc->pdata && udc->pdata->vbus && udc->clock_gating)
|
/*
|
||||||
|
* If we have transceiver inited,
|
||||||
|
* then vbus irq will not be requested in udc driver.
|
||||||
|
*/
|
||||||
|
if (udc->pdata && udc->pdata->vbus
|
||||||
|
&& udc->clock_gating && udc->transceiver == NULL)
|
||||||
free_irq(udc->pdata->vbus->irq, &dev->dev);
|
free_irq(udc->pdata->vbus->irq, &dev->dev);
|
||||||
|
|
||||||
/* free memory allocated in probe */
|
/* free memory allocated in probe */
|
||||||
@ -2182,6 +2225,11 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
|
|||||||
|
|
||||||
udc->dev = dev;
|
udc->dev = dev;
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_OTG_UTILS
|
||||||
|
if (pdata->mode == MV_USB_MODE_OTG)
|
||||||
|
udc->transceiver = otg_get_transceiver();
|
||||||
|
#endif
|
||||||
|
|
||||||
udc->clknum = pdata->clknum;
|
udc->clknum = pdata->clknum;
|
||||||
for (clk_i = 0; clk_i < udc->clknum; clk_i++) {
|
for (clk_i = 0; clk_i < udc->clknum; clk_i++) {
|
||||||
udc->clk[clk_i] = clk_get(&dev->dev, pdata->clkname[clk_i]);
|
udc->clk[clk_i] = clk_get(&dev->dev, pdata->clkname[clk_i]);
|
||||||
@ -2221,14 +2269,9 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* we will acces controller register, so enable the clk */
|
/* we will acces controller register, so enable the clk */
|
||||||
udc_clock_enable(udc);
|
retval = mv_udc_enable_internal(udc);
|
||||||
if (pdata->phy_init) {
|
if (retval)
|
||||||
retval = pdata->phy_init(udc->phy_regs);
|
goto err_iounmap_phyreg;
|
||||||
if (retval) {
|
|
||||||
dev_err(&dev->dev, "phy init error %d\n", retval);
|
|
||||||
goto err_iounmap_phyreg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
udc->op_regs = (struct mv_op_regs __iomem *)((u32)udc->cap_regs
|
udc->op_regs = (struct mv_op_regs __iomem *)((u32)udc->cap_regs
|
||||||
+ (readl(&udc->cap_regs->caplength_hciversion)
|
+ (readl(&udc->cap_regs->caplength_hciversion)
|
||||||
@ -2312,7 +2355,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
|
|||||||
udc->gadget.ep0 = &udc->eps[0].ep; /* gadget ep0 */
|
udc->gadget.ep0 = &udc->eps[0].ep; /* gadget ep0 */
|
||||||
INIT_LIST_HEAD(&udc->gadget.ep_list); /* ep_list */
|
INIT_LIST_HEAD(&udc->gadget.ep_list); /* ep_list */
|
||||||
udc->gadget.speed = USB_SPEED_UNKNOWN; /* speed */
|
udc->gadget.speed = USB_SPEED_UNKNOWN; /* speed */
|
||||||
udc->gadget.is_dualspeed = 1; /* support dual speed */
|
udc->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */
|
||||||
|
|
||||||
/* the "gadget" abstracts/virtualizes the controller */
|
/* the "gadget" abstracts/virtualizes the controller */
|
||||||
dev_set_name(&udc->gadget.dev, "gadget");
|
dev_set_name(&udc->gadget.dev, "gadget");
|
||||||
@ -2328,7 +2371,9 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
|
|||||||
eps_init(udc);
|
eps_init(udc);
|
||||||
|
|
||||||
/* VBUS detect: we can disable/enable clock on demand.*/
|
/* VBUS detect: we can disable/enable clock on demand.*/
|
||||||
if (pdata->vbus) {
|
if (udc->transceiver)
|
||||||
|
udc->clock_gating = 1;
|
||||||
|
else if (pdata->vbus) {
|
||||||
udc->clock_gating = 1;
|
udc->clock_gating = 1;
|
||||||
retval = request_threaded_irq(pdata->vbus->irq, NULL,
|
retval = request_threaded_irq(pdata->vbus->irq, NULL,
|
||||||
mv_udc_vbus_irq, IRQF_ONESHOT, "vbus", udc);
|
mv_udc_vbus_irq, IRQF_ONESHOT, "vbus", udc);
|
||||||
@ -2354,11 +2399,9 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
|
|||||||
* If not, it means that VBUS detection is not supported, we
|
* If not, it means that VBUS detection is not supported, we
|
||||||
* have to enable vbus active all the time to let controller work.
|
* have to enable vbus active all the time to let controller work.
|
||||||
*/
|
*/
|
||||||
if (udc->clock_gating) {
|
if (udc->clock_gating)
|
||||||
if (udc->pdata->phy_deinit)
|
mv_udc_disable_internal(udc);
|
||||||
udc->pdata->phy_deinit(udc->phy_regs);
|
else
|
||||||
udc_clock_disable(udc);
|
|
||||||
} else
|
|
||||||
udc->vbus_active = 1;
|
udc->vbus_active = 1;
|
||||||
|
|
||||||
retval = usb_add_gadget_udc(&dev->dev, &udc->gadget);
|
retval = usb_add_gadget_udc(&dev->dev, &udc->gadget);
|
||||||
@ -2371,7 +2414,8 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_unregister:
|
err_unregister:
|
||||||
if (udc->pdata && udc->pdata->vbus && udc->clock_gating)
|
if (udc->pdata && udc->pdata->vbus
|
||||||
|
&& udc->clock_gating && udc->transceiver == NULL)
|
||||||
free_irq(pdata->vbus->irq, &dev->dev);
|
free_irq(pdata->vbus->irq, &dev->dev);
|
||||||
device_unregister(&udc->gadget.dev);
|
device_unregister(&udc->gadget.dev);
|
||||||
err_free_irq:
|
err_free_irq:
|
||||||
@ -2387,9 +2431,7 @@ err_free_dma:
|
|||||||
dma_free_coherent(&dev->dev, udc->ep_dqh_size,
|
dma_free_coherent(&dev->dev, udc->ep_dqh_size,
|
||||||
udc->ep_dqh, udc->ep_dqh_dma);
|
udc->ep_dqh, udc->ep_dqh_dma);
|
||||||
err_disable_clock:
|
err_disable_clock:
|
||||||
if (udc->pdata->phy_deinit)
|
mv_udc_disable_internal(udc);
|
||||||
udc->pdata->phy_deinit(udc->phy_regs);
|
|
||||||
udc_clock_disable(udc);
|
|
||||||
err_iounmap_phyreg:
|
err_iounmap_phyreg:
|
||||||
iounmap((void *)udc->phy_regs);
|
iounmap((void *)udc->phy_regs);
|
||||||
err_iounmap_capreg:
|
err_iounmap_capreg:
|
||||||
@ -2407,7 +2449,30 @@ static int mv_udc_suspend(struct device *_dev)
|
|||||||
{
|
{
|
||||||
struct mv_udc *udc = the_controller;
|
struct mv_udc *udc = the_controller;
|
||||||
|
|
||||||
udc_stop(udc);
|
/* if OTG is enabled, the following will be done in OTG driver*/
|
||||||
|
if (udc->transceiver)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (udc->pdata->vbus && udc->pdata->vbus->poll)
|
||||||
|
if (udc->pdata->vbus->poll() == VBUS_HIGH) {
|
||||||
|
dev_info(&udc->dev->dev, "USB cable is connected!\n");
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* only cable is unplugged, udc can suspend.
|
||||||
|
* So do not care about clock_gating == 1.
|
||||||
|
*/
|
||||||
|
if (!udc->clock_gating) {
|
||||||
|
udc_stop(udc);
|
||||||
|
|
||||||
|
spin_lock_irq(&udc->lock);
|
||||||
|
/* stop all usb activities */
|
||||||
|
stop_activity(udc, udc->driver);
|
||||||
|
spin_unlock_irq(&udc->lock);
|
||||||
|
|
||||||
|
mv_udc_disable_internal(udc);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2417,20 +2482,22 @@ static int mv_udc_resume(struct device *_dev)
|
|||||||
struct mv_udc *udc = the_controller;
|
struct mv_udc *udc = the_controller;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (udc->pdata->phy_init) {
|
/* if OTG is enabled, the following will be done in OTG driver*/
|
||||||
retval = udc->pdata->phy_init(udc->phy_regs);
|
if (udc->transceiver)
|
||||||
if (retval) {
|
return 0;
|
||||||
dev_err(&udc->dev->dev,
|
|
||||||
"init phy error %d when resume back\n",
|
if (!udc->clock_gating) {
|
||||||
retval);
|
retval = mv_udc_enable_internal(udc);
|
||||||
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
if (udc->driver && udc->softconnect) {
|
||||||
|
udc_reset(udc);
|
||||||
|
ep0_reset(udc);
|
||||||
|
udc_start(udc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
udc_reset(udc);
|
|
||||||
ep0_reset(udc);
|
|
||||||
udc_start(udc);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1459,7 +1459,7 @@ static int net2272_start(struct usb_gadget *_gadget,
|
|||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
if (!driver || !driver->unbind || !driver->setup ||
|
if (!driver || !driver->unbind || !driver->setup ||
|
||||||
driver->speed != USB_SPEED_HIGH)
|
driver->max_speed != USB_SPEED_HIGH)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
dev = container_of(_gadget, struct net2272, gadget);
|
dev = container_of(_gadget, struct net2272, gadget);
|
||||||
@ -2235,7 +2235,7 @@ net2272_probe_init(struct device *dev, unsigned int irq)
|
|||||||
ret->irq = irq;
|
ret->irq = irq;
|
||||||
ret->dev = dev;
|
ret->dev = dev;
|
||||||
ret->gadget.ops = &net2272_ops;
|
ret->gadget.ops = &net2272_ops;
|
||||||
ret->gadget.is_dualspeed = 1;
|
ret->gadget.max_speed = USB_SPEED_HIGH;
|
||||||
|
|
||||||
/* the "gadget" abstracts/virtualizes the controller */
|
/* the "gadget" abstracts/virtualizes the controller */
|
||||||
dev_set_name(&ret->gadget.dev, "gadget");
|
dev_set_name(&ret->gadget.dev, "gadget");
|
||||||
|
@ -1881,7 +1881,7 @@ static int net2280_start(struct usb_gadget *_gadget,
|
|||||||
* (dev->usb->xcvrdiag & FORCE_FULL_SPEED_MODE)
|
* (dev->usb->xcvrdiag & FORCE_FULL_SPEED_MODE)
|
||||||
* "must not be used in normal operation"
|
* "must not be used in normal operation"
|
||||||
*/
|
*/
|
||||||
if (!driver || driver->speed < USB_SPEED_HIGH
|
if (!driver || driver->max_speed < USB_SPEED_HIGH
|
||||||
|| !driver->setup)
|
|| !driver->setup)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -2698,7 +2698,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
|
|||||||
spin_lock_init (&dev->lock);
|
spin_lock_init (&dev->lock);
|
||||||
dev->pdev = pdev;
|
dev->pdev = pdev;
|
||||||
dev->gadget.ops = &net2280_ops;
|
dev->gadget.ops = &net2280_ops;
|
||||||
dev->gadget.is_dualspeed = 1;
|
dev->gadget.max_speed = USB_SPEED_HIGH;
|
||||||
|
|
||||||
/* the "gadget" abstracts/virtualizes the controller */
|
/* the "gadget" abstracts/virtualizes the controller */
|
||||||
dev_set_name(&dev->gadget.dev, "gadget");
|
dev_set_name(&dev->gadget.dev, "gadget");
|
||||||
|
@ -2110,7 +2110,7 @@ static int omap_udc_start(struct usb_gadget_driver *driver,
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
if (!driver
|
if (!driver
|
||||||
// FIXME if otg, check: driver->is_otg
|
// FIXME if otg, check: driver->is_otg
|
||||||
|| driver->speed < USB_SPEED_FULL
|
|| driver->max_speed < USB_SPEED_FULL
|
||||||
|| !bind || !driver->setup)
|
|| !bind || !driver->setup)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -2676,6 +2676,7 @@ omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv)
|
|||||||
INIT_LIST_HEAD(&udc->gadget.ep_list);
|
INIT_LIST_HEAD(&udc->gadget.ep_list);
|
||||||
INIT_LIST_HEAD(&udc->iso);
|
INIT_LIST_HEAD(&udc->iso);
|
||||||
udc->gadget.speed = USB_SPEED_UNKNOWN;
|
udc->gadget.speed = USB_SPEED_UNKNOWN;
|
||||||
|
udc->gadget.max_speed = USB_SPEED_FULL;
|
||||||
udc->gadget.name = driver_name;
|
udc->gadget.name = driver_name;
|
||||||
|
|
||||||
device_initialize(&udc->gadget.dev);
|
device_initialize(&udc->gadget.dev);
|
||||||
|
@ -2693,7 +2693,7 @@ static int pch_udc_start(struct usb_gadget_driver *driver,
|
|||||||
struct pch_udc_dev *dev = pch_udc;
|
struct pch_udc_dev *dev = pch_udc;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (!driver || (driver->speed == USB_SPEED_UNKNOWN) || !bind ||
|
if (!driver || (driver->max_speed == USB_SPEED_UNKNOWN) || !bind ||
|
||||||
!driver->setup || !driver->unbind || !driver->disconnect) {
|
!driver->setup || !driver->unbind || !driver->disconnect) {
|
||||||
dev_err(&dev->pdev->dev,
|
dev_err(&dev->pdev->dev,
|
||||||
"%s: invalid driver parameter\n", __func__);
|
"%s: invalid driver parameter\n", __func__);
|
||||||
@ -2941,7 +2941,7 @@ static int pch_udc_probe(struct pci_dev *pdev,
|
|||||||
dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
|
dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
|
||||||
dev->gadget.dev.release = gadget_release;
|
dev->gadget.dev.release = gadget_release;
|
||||||
dev->gadget.name = KBUILD_MODNAME;
|
dev->gadget.name = KBUILD_MODNAME;
|
||||||
dev->gadget.is_dualspeed = 1;
|
dev->gadget.max_speed = USB_SPEED_HIGH;
|
||||||
|
|
||||||
retval = device_register(&dev->gadget.dev);
|
retval = device_register(&dev->gadget.dev);
|
||||||
if (retval)
|
if (retval)
|
||||||
|
@ -1141,7 +1141,7 @@ printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|||||||
break;
|
break;
|
||||||
#ifdef CONFIG_USB_GADGET_DUALSPEED
|
#ifdef CONFIG_USB_GADGET_DUALSPEED
|
||||||
case USB_DT_DEVICE_QUALIFIER:
|
case USB_DT_DEVICE_QUALIFIER:
|
||||||
if (!gadget->is_dualspeed)
|
if (!gadget_is_dualspeed(gadget))
|
||||||
break;
|
break;
|
||||||
/*
|
/*
|
||||||
* assumes ep0 uses the same value for both
|
* assumes ep0 uses the same value for both
|
||||||
@ -1155,7 +1155,7 @@ printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_DT_OTHER_SPEED_CONFIG:
|
case USB_DT_OTHER_SPEED_CONFIG:
|
||||||
if (!gadget->is_dualspeed)
|
if (!gadget_is_dualspeed(gadget))
|
||||||
break;
|
break;
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
#endif /* CONFIG_USB_GADGET_DUALSPEED */
|
#endif /* CONFIG_USB_GADGET_DUALSPEED */
|
||||||
@ -1535,7 +1535,7 @@ fail:
|
|||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static struct usb_gadget_driver printer_driver = {
|
static struct usb_gadget_driver printer_driver = {
|
||||||
.speed = DEVSPEED,
|
.max_speed = DEVSPEED,
|
||||||
|
|
||||||
.function = (char *) driver_desc,
|
.function = (char *) driver_desc,
|
||||||
.unbind = printer_unbind,
|
.unbind = printer_unbind,
|
||||||
|
@ -1264,7 +1264,7 @@ static int pxa25x_start(struct usb_gadget_driver *driver,
|
|||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (!driver
|
if (!driver
|
||||||
|| driver->speed < USB_SPEED_FULL
|
|| driver->max_speed < USB_SPEED_FULL
|
||||||
|| !bind
|
|| !bind
|
||||||
|| !driver->disconnect
|
|| !driver->disconnect
|
||||||
|| !driver->setup)
|
|| !driver->setup)
|
||||||
|
@ -1807,7 +1807,7 @@ static int pxa27x_udc_start(struct usb_gadget_driver *driver,
|
|||||||
struct pxa_udc *udc = the_controller;
|
struct pxa_udc *udc = the_controller;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (!driver || driver->speed < USB_SPEED_FULL || !bind
|
if (!driver || driver->max_speed < USB_SPEED_FULL || !bind
|
||||||
|| !driver->disconnect || !driver->setup)
|
|| !driver->disconnect || !driver->setup)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!udc)
|
if (!udc)
|
||||||
|
@ -1746,7 +1746,7 @@ static int r8a66597_start(struct usb_gadget *gadget,
|
|||||||
struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
|
struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
|
||||||
|
|
||||||
if (!driver
|
if (!driver
|
||||||
|| driver->speed < USB_SPEED_HIGH
|
|| driver->max_speed < USB_SPEED_HIGH
|
||||||
|| !driver->setup)
|
|| !driver->setup)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!r8a66597)
|
if (!r8a66597)
|
||||||
@ -1911,7 +1911,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
r8a66597->gadget.ops = &r8a66597_gadget_ops;
|
r8a66597->gadget.ops = &r8a66597_gadget_ops;
|
||||||
dev_set_name(&r8a66597->gadget.dev, "gadget");
|
dev_set_name(&r8a66597->gadget.dev, "gadget");
|
||||||
r8a66597->gadget.is_dualspeed = 1;
|
r8a66597->gadget.max_speed = USB_SPEED_HIGH;
|
||||||
r8a66597->gadget.dev.parent = &pdev->dev;
|
r8a66597->gadget.dev.parent = &pdev->dev;
|
||||||
r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask;
|
r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask;
|
||||||
r8a66597->gadget.dev.release = pdev->dev.release;
|
r8a66597->gadget.dev.release = pdev->dev.release;
|
||||||
|
@ -2586,7 +2586,7 @@ static int s3c_hsotg_start(struct usb_gadget_driver *driver,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (driver->speed < USB_SPEED_FULL)
|
if (driver->max_speed < USB_SPEED_FULL)
|
||||||
dev_err(hsotg->dev, "%s: bad speed\n", __func__);
|
dev_err(hsotg->dev, "%s: bad speed\n", __func__);
|
||||||
|
|
||||||
if (!bind || !driver->setup) {
|
if (!bind || !driver->setup) {
|
||||||
@ -3362,7 +3362,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
dev_set_name(&hsotg->gadget.dev, "gadget");
|
dev_set_name(&hsotg->gadget.dev, "gadget");
|
||||||
|
|
||||||
hsotg->gadget.is_dualspeed = 1;
|
hsotg->gadget.max_speed = USB_SPEED_HIGH;
|
||||||
hsotg->gadget.ops = &s3c_hsotg_gadget_ops;
|
hsotg->gadget.ops = &s3c_hsotg_gadget_ops;
|
||||||
hsotg->gadget.name = dev_name(dev);
|
hsotg->gadget.name = dev_name(dev);
|
||||||
|
|
||||||
|
@ -1142,7 +1142,7 @@ static int s3c_hsudc_start(struct usb_gadget_driver *driver,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!driver
|
if (!driver
|
||||||
|| driver->speed < USB_SPEED_FULL
|
|| driver->max_speed < USB_SPEED_FULL
|
||||||
|| !bind
|
|| !bind
|
||||||
|| !driver->unbind || !driver->disconnect || !driver->setup)
|
|| !driver->unbind || !driver->disconnect || !driver->setup)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -1310,7 +1310,7 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
|
|||||||
device_initialize(&hsudc->gadget.dev);
|
device_initialize(&hsudc->gadget.dev);
|
||||||
dev_set_name(&hsudc->gadget.dev, "gadget");
|
dev_set_name(&hsudc->gadget.dev, "gadget");
|
||||||
|
|
||||||
hsudc->gadget.is_dualspeed = 1;
|
hsudc->gadget.max_speed = USB_SPEED_HIGH;
|
||||||
hsudc->gadget.ops = &s3c_hsudc_gadget_ops;
|
hsudc->gadget.ops = &s3c_hsudc_gadget_ops;
|
||||||
hsudc->gadget.name = dev_name(dev);
|
hsudc->gadget.name = dev_name(dev);
|
||||||
hsudc->gadget.dev.parent = dev;
|
hsudc->gadget.dev.parent = dev;
|
||||||
|
@ -1683,9 +1683,9 @@ static int s3c2410_udc_start(struct usb_gadget_driver *driver,
|
|||||||
if (udc->driver)
|
if (udc->driver)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
if (!bind || !driver->setup || driver->speed < USB_SPEED_FULL) {
|
if (!bind || !driver->setup || driver->max_speed < USB_SPEED_FULL) {
|
||||||
printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n",
|
printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n",
|
||||||
bind, driver->setup, driver->speed);
|
bind, driver->setup, driver->max_speed);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
#if defined(MODULE)
|
#if defined(MODULE)
|
||||||
|
@ -371,14 +371,28 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
|
|||||||
}
|
}
|
||||||
static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store);
|
static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store);
|
||||||
|
|
||||||
static ssize_t usb_udc_speed_show(struct device *dev,
|
#define USB_UDC_SPEED_ATTR(name, param) \
|
||||||
|
ssize_t usb_udc_##param##_show(struct device *dev, \
|
||||||
|
struct device_attribute *attr, char *buf) \
|
||||||
|
{ \
|
||||||
|
struct usb_udc *udc = container_of(dev, struct usb_udc, dev); \
|
||||||
|
return snprintf(buf, PAGE_SIZE, "%s\n", \
|
||||||
|
usb_speed_string(udc->gadget->param)); \
|
||||||
|
} \
|
||||||
|
static DEVICE_ATTR(name, S_IRUSR, usb_udc_##param##_show, NULL)
|
||||||
|
|
||||||
|
static USB_UDC_SPEED_ATTR(current_speed, speed);
|
||||||
|
static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
|
||||||
|
|
||||||
|
/* TODO: Scheduled for removal in 3.8. */
|
||||||
|
static ssize_t usb_udc_is_dualspeed_show(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
|
struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
|
||||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||||
usb_speed_string(udc->gadget->speed));
|
gadget_is_dualspeed(udc->gadget));
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR(speed, S_IRUGO, usb_udc_speed_show, NULL);
|
static DEVICE_ATTR(is_dualspeed, S_IRUSR, usb_udc_is_dualspeed_show, NULL);
|
||||||
|
|
||||||
#define USB_UDC_ATTR(name) \
|
#define USB_UDC_ATTR(name) \
|
||||||
ssize_t usb_udc_##name##_show(struct device *dev, \
|
ssize_t usb_udc_##name##_show(struct device *dev, \
|
||||||
@ -391,7 +405,6 @@ ssize_t usb_udc_##name##_show(struct device *dev, \
|
|||||||
} \
|
} \
|
||||||
static DEVICE_ATTR(name, S_IRUGO, usb_udc_##name##_show, NULL)
|
static DEVICE_ATTR(name, S_IRUGO, usb_udc_##name##_show, NULL)
|
||||||
|
|
||||||
static USB_UDC_ATTR(is_dualspeed);
|
|
||||||
static USB_UDC_ATTR(is_otg);
|
static USB_UDC_ATTR(is_otg);
|
||||||
static USB_UDC_ATTR(is_a_peripheral);
|
static USB_UDC_ATTR(is_a_peripheral);
|
||||||
static USB_UDC_ATTR(b_hnp_enable);
|
static USB_UDC_ATTR(b_hnp_enable);
|
||||||
@ -401,7 +414,8 @@ static USB_UDC_ATTR(a_alt_hnp_support);
|
|||||||
static struct attribute *usb_udc_attrs[] = {
|
static struct attribute *usb_udc_attrs[] = {
|
||||||
&dev_attr_srp.attr,
|
&dev_attr_srp.attr,
|
||||||
&dev_attr_soft_connect.attr,
|
&dev_attr_soft_connect.attr,
|
||||||
&dev_attr_speed.attr,
|
&dev_attr_current_speed.attr,
|
||||||
|
&dev_attr_maximum_speed.attr,
|
||||||
|
|
||||||
&dev_attr_is_dualspeed.attr,
|
&dev_attr_is_dualspeed.attr,
|
||||||
&dev_attr_is_otg.attr,
|
&dev_attr_is_otg.attr,
|
||||||
|
@ -1842,7 +1842,7 @@ int __init musb_gadget_setup(struct musb *musb)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
musb->g.ops = &musb_gadget_operations;
|
musb->g.ops = &musb_gadget_operations;
|
||||||
musb->g.is_dualspeed = 1;
|
musb->g.max_speed = USB_SPEED_HIGH;
|
||||||
musb->g.speed = USB_SPEED_UNKNOWN;
|
musb->g.speed = USB_SPEED_UNKNOWN;
|
||||||
|
|
||||||
/* this "gadget" abstracts/virtualizes the controller */
|
/* this "gadget" abstracts/virtualizes the controller */
|
||||||
@ -1901,7 +1901,7 @@ static int musb_gadget_start(struct usb_gadget *g,
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int retval = -EINVAL;
|
int retval = -EINVAL;
|
||||||
|
|
||||||
if (driver->speed < USB_SPEED_HIGH)
|
if (driver->max_speed < USB_SPEED_HIGH)
|
||||||
goto err0;
|
goto err0;
|
||||||
|
|
||||||
pm_runtime_get_sync(musb->controller);
|
pm_runtime_get_sync(musb->controller);
|
||||||
|
@ -95,25 +95,15 @@ struct usbhs_priv *usbhs_pdev_to_priv(struct platform_device *pdev)
|
|||||||
/*
|
/*
|
||||||
* syscfg functions
|
* syscfg functions
|
||||||
*/
|
*/
|
||||||
void usbhs_sys_clock_ctrl(struct usbhs_priv *priv, int enable)
|
static void usbhs_sys_clock_ctrl(struct usbhs_priv *priv, int enable)
|
||||||
{
|
{
|
||||||
usbhs_bset(priv, SYSCFG, SCKE, enable ? SCKE : 0);
|
usbhs_bset(priv, SYSCFG, SCKE, enable ? SCKE : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbhs_sys_hispeed_ctrl(struct usbhs_priv *priv, int enable)
|
|
||||||
{
|
|
||||||
usbhs_bset(priv, SYSCFG, HSE, enable ? HSE : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void usbhs_sys_usb_ctrl(struct usbhs_priv *priv, int enable)
|
|
||||||
{
|
|
||||||
usbhs_bset(priv, SYSCFG, USBE, enable ? USBE : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable)
|
void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable)
|
||||||
{
|
{
|
||||||
u16 mask = DCFM | DRPD | DPRPU;
|
u16 mask = DCFM | DRPD | DPRPU | HSE | USBE;
|
||||||
u16 val = DCFM | DRPD;
|
u16 val = DCFM | DRPD | HSE | USBE;
|
||||||
int has_otg = usbhs_get_dparam(priv, has_otg);
|
int has_otg = usbhs_get_dparam(priv, has_otg);
|
||||||
|
|
||||||
if (has_otg)
|
if (has_otg)
|
||||||
@ -130,8 +120,8 @@ void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable)
|
|||||||
|
|
||||||
void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable)
|
void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable)
|
||||||
{
|
{
|
||||||
u16 mask = DCFM | DRPD | DPRPU;
|
u16 mask = DCFM | DRPD | DPRPU | HSE | USBE;
|
||||||
u16 val = DPRPU;
|
u16 val = DPRPU | HSE | USBE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if enable
|
* if enable
|
||||||
@ -142,6 +132,11 @@ void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable)
|
|||||||
usbhs_bset(priv, SYSCFG, mask, enable ? val : 0);
|
usbhs_bset(priv, SYSCFG, mask, enable ? val : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void usbhs_sys_set_test_mode(struct usbhs_priv *priv, u16 mode)
|
||||||
|
{
|
||||||
|
usbhs_write(priv, TESTMODE, mode);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* frame functions
|
* frame functions
|
||||||
*/
|
*/
|
||||||
@ -229,7 +224,7 @@ static void usbhsc_bus_init(struct usbhs_priv *priv)
|
|||||||
/*
|
/*
|
||||||
* device configuration
|
* device configuration
|
||||||
*/
|
*/
|
||||||
int usbhs_set_device_speed(struct usbhs_priv *priv, int devnum,
|
int usbhs_set_device_config(struct usbhs_priv *priv, int devnum,
|
||||||
u16 upphub, u16 hubport, u16 speed)
|
u16 upphub, u16 hubport, u16 speed)
|
||||||
{
|
{
|
||||||
struct device *dev = usbhs_priv_to_dev(priv);
|
struct device *dev = usbhs_priv_to_dev(priv);
|
||||||
@ -301,18 +296,25 @@ static u32 usbhsc_default_pipe_type[] = {
|
|||||||
*/
|
*/
|
||||||
static void usbhsc_power_ctrl(struct usbhs_priv *priv, int enable)
|
static void usbhsc_power_ctrl(struct usbhs_priv *priv, int enable)
|
||||||
{
|
{
|
||||||
|
struct platform_device *pdev = usbhs_priv_to_pdev(priv);
|
||||||
struct device *dev = usbhs_priv_to_dev(priv);
|
struct device *dev = usbhs_priv_to_dev(priv);
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
/* enable PM */
|
/* enable PM */
|
||||||
pm_runtime_get_sync(dev);
|
pm_runtime_get_sync(dev);
|
||||||
|
|
||||||
|
/* enable platform power */
|
||||||
|
usbhs_platform_call(priv, power_ctrl, pdev, priv->base, enable);
|
||||||
|
|
||||||
/* USB on */
|
/* USB on */
|
||||||
usbhs_sys_clock_ctrl(priv, enable);
|
usbhs_sys_clock_ctrl(priv, enable);
|
||||||
} else {
|
} else {
|
||||||
/* USB off */
|
/* USB off */
|
||||||
usbhs_sys_clock_ctrl(priv, enable);
|
usbhs_sys_clock_ctrl(priv, enable);
|
||||||
|
|
||||||
|
/* disable platform power */
|
||||||
|
usbhs_platform_call(priv, power_ctrl, pdev, priv->base, enable);
|
||||||
|
|
||||||
/* disable PM */
|
/* disable PM */
|
||||||
pm_runtime_put_sync(dev);
|
pm_runtime_put_sync(dev);
|
||||||
}
|
}
|
||||||
@ -388,7 +390,7 @@ static void usbhsc_notify_hotplug(struct work_struct *work)
|
|||||||
usbhsc_hotplug(priv);
|
usbhsc_hotplug(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev)
|
static int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
|
struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
|
||||||
int delay = usbhs_get_dparam(priv, detection_delay);
|
int delay = usbhs_get_dparam(priv, detection_delay);
|
||||||
@ -398,7 +400,8 @@ int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev)
|
|||||||
* To make sure safety context,
|
* To make sure safety context,
|
||||||
* use workqueue for usbhs_notify_hotplug
|
* use workqueue for usbhs_notify_hotplug
|
||||||
*/
|
*/
|
||||||
schedule_delayed_work(&priv->notify_hotplug_work, delay);
|
schedule_delayed_work(&priv->notify_hotplug_work,
|
||||||
|
msecs_to_jiffies(delay));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ struct usbhs_priv;
|
|||||||
#define SYSCFG 0x0000
|
#define SYSCFG 0x0000
|
||||||
#define BUSWAIT 0x0002
|
#define BUSWAIT 0x0002
|
||||||
#define DVSTCTR 0x0008
|
#define DVSTCTR 0x0008
|
||||||
|
#define TESTMODE 0x000C
|
||||||
#define CFIFO 0x0014
|
#define CFIFO 0x0014
|
||||||
#define CFIFOSEL 0x0020
|
#define CFIFOSEL 0x0020
|
||||||
#define CFIFOCTR 0x0022
|
#define CFIFOCTR 0x0022
|
||||||
@ -275,19 +276,15 @@ u16 usbhs_read(struct usbhs_priv *priv, u32 reg);
|
|||||||
void usbhs_write(struct usbhs_priv *priv, u32 reg, u16 data);
|
void usbhs_write(struct usbhs_priv *priv, u32 reg, u16 data);
|
||||||
void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data);
|
void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data);
|
||||||
|
|
||||||
int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev);
|
|
||||||
|
|
||||||
#define usbhs_lock(p, f) spin_lock_irqsave(usbhs_priv_to_lock(p), f)
|
#define usbhs_lock(p, f) spin_lock_irqsave(usbhs_priv_to_lock(p), f)
|
||||||
#define usbhs_unlock(p, f) spin_unlock_irqrestore(usbhs_priv_to_lock(p), f)
|
#define usbhs_unlock(p, f) spin_unlock_irqrestore(usbhs_priv_to_lock(p), f)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sysconfig
|
* sysconfig
|
||||||
*/
|
*/
|
||||||
void usbhs_sys_clock_ctrl(struct usbhs_priv *priv, int enable);
|
|
||||||
void usbhs_sys_hispeed_ctrl(struct usbhs_priv *priv, int enable);
|
|
||||||
void usbhs_sys_usb_ctrl(struct usbhs_priv *priv, int enable);
|
|
||||||
void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable);
|
void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable);
|
||||||
void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable);
|
void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable);
|
||||||
|
void usbhs_sys_set_test_mode(struct usbhs_priv *priv, u16 mode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* usb request
|
* usb request
|
||||||
@ -311,7 +308,7 @@ int usbhs_frame_get_num(struct usbhs_priv *priv);
|
|||||||
/*
|
/*
|
||||||
* device config
|
* device config
|
||||||
*/
|
*/
|
||||||
int usbhs_set_device_speed(struct usbhs_priv *priv, int devnum, u16 upphub,
|
int usbhs_set_device_config(struct usbhs_priv *priv, int devnum, u16 upphub,
|
||||||
u16 hubport, u16 speed);
|
u16 hubport, u16 speed);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -56,7 +56,7 @@ static struct usbhs_pkt_handle usbhsf_null_handler = {
|
|||||||
void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
|
void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
|
||||||
void (*done)(struct usbhs_priv *priv,
|
void (*done)(struct usbhs_priv *priv,
|
||||||
struct usbhs_pkt *pkt),
|
struct usbhs_pkt *pkt),
|
||||||
void *buf, int len, int zero)
|
void *buf, int len, int zero, int sequence)
|
||||||
{
|
{
|
||||||
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
|
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
|
||||||
struct device *dev = usbhs_priv_to_dev(priv);
|
struct device *dev = usbhs_priv_to_dev(priv);
|
||||||
@ -90,6 +90,7 @@ void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
|
|||||||
pkt->zero = zero;
|
pkt->zero = zero;
|
||||||
pkt->actual = 0;
|
pkt->actual = 0;
|
||||||
pkt->done = done;
|
pkt->done = done;
|
||||||
|
pkt->sequence = sequence;
|
||||||
|
|
||||||
usbhs_unlock(priv, flags);
|
usbhs_unlock(priv, flags);
|
||||||
/******************** spin unlock ******************/
|
/******************** spin unlock ******************/
|
||||||
@ -481,6 +482,9 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done)
|
|||||||
int i, ret, len;
|
int i, ret, len;
|
||||||
int is_short;
|
int is_short;
|
||||||
|
|
||||||
|
usbhs_pipe_data_sequence(pipe, pkt->sequence);
|
||||||
|
pkt->sequence = -1; /* -1 sequence will be ignored */
|
||||||
|
|
||||||
ret = usbhsf_fifo_select(pipe, fifo, 1);
|
ret = usbhsf_fifo_select(pipe, fifo, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return 0;
|
return 0;
|
||||||
@ -584,6 +588,8 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
|
|||||||
/*
|
/*
|
||||||
* pipe enable to prepare packet receive
|
* pipe enable to prepare packet receive
|
||||||
*/
|
*/
|
||||||
|
usbhs_pipe_data_sequence(pipe, pkt->sequence);
|
||||||
|
pkt->sequence = -1; /* -1 sequence will be ignored */
|
||||||
|
|
||||||
usbhs_pipe_enable(pipe);
|
usbhs_pipe_enable(pipe);
|
||||||
usbhsf_rx_irq_ctrl(pipe, 1);
|
usbhsf_rx_irq_ctrl(pipe, 1);
|
||||||
@ -641,6 +647,7 @@ static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done)
|
|||||||
* "Operation" - "FIFO Buffer Memory" - "FIFO Port Function"
|
* "Operation" - "FIFO Buffer Memory" - "FIFO Port Function"
|
||||||
*/
|
*/
|
||||||
if (0 == rcv_len) {
|
if (0 == rcv_len) {
|
||||||
|
pkt->zero = 1;
|
||||||
usbhsf_fifo_clear(pipe, fifo);
|
usbhsf_fifo_clear(pipe, fifo);
|
||||||
goto usbhs_fifo_read_end;
|
goto usbhs_fifo_read_end;
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@ struct usbhs_pkt {
|
|||||||
int trans;
|
int trans;
|
||||||
int actual;
|
int actual;
|
||||||
int zero;
|
int zero;
|
||||||
|
int sequence;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct usbhs_pkt_handle {
|
struct usbhs_pkt_handle {
|
||||||
@ -95,7 +96,7 @@ void usbhs_pkt_init(struct usbhs_pkt *pkt);
|
|||||||
void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
|
void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
|
||||||
void (*done)(struct usbhs_priv *priv,
|
void (*done)(struct usbhs_priv *priv,
|
||||||
struct usbhs_pkt *pkt),
|
struct usbhs_pkt *pkt),
|
||||||
void *buf, int len, int zero);
|
void *buf, int len, int zero, int sequence);
|
||||||
struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt);
|
struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt);
|
||||||
void usbhs_pkt_start(struct usbhs_pipe *pipe);
|
void usbhs_pkt_start(struct usbhs_pipe *pipe);
|
||||||
|
|
||||||
|
@ -50,7 +50,9 @@ static int usbhsm_autonomy_irq_vbus(struct usbhs_priv *priv,
|
|||||||
{
|
{
|
||||||
struct platform_device *pdev = usbhs_priv_to_pdev(priv);
|
struct platform_device *pdev = usbhs_priv_to_pdev(priv);
|
||||||
|
|
||||||
return usbhsc_drvcllbck_notify_hotplug(pdev);
|
renesas_usbhs_call_notify_hotplug(pdev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbhs_mod_autonomy_mode(struct usbhs_priv *priv)
|
void usbhs_mod_autonomy_mode(struct usbhs_priv *priv)
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
#include <linux/delay.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
@ -44,7 +45,6 @@ struct usbhsg_uep {
|
|||||||
struct usbhsg_gpriv {
|
struct usbhsg_gpriv {
|
||||||
struct usb_gadget gadget;
|
struct usb_gadget gadget;
|
||||||
struct usbhs_mod mod;
|
struct usbhs_mod mod;
|
||||||
struct list_head link;
|
|
||||||
|
|
||||||
struct usbhsg_uep *uep;
|
struct usbhsg_uep *uep;
|
||||||
int uep_size;
|
int uep_size;
|
||||||
@ -114,16 +114,6 @@ struct usbhsg_recip_handle {
|
|||||||
#define usbhsg_status_clr(gp, b) (gp->status &= ~b)
|
#define usbhsg_status_clr(gp, b) (gp->status &= ~b)
|
||||||
#define usbhsg_status_has(gp, b) (gp->status & b)
|
#define usbhsg_status_has(gp, b) (gp->status & b)
|
||||||
|
|
||||||
/* controller */
|
|
||||||
LIST_HEAD(the_controller_link);
|
|
||||||
|
|
||||||
#define usbhsg_for_each_controller(gpriv)\
|
|
||||||
list_for_each_entry(gpriv, &the_controller_link, link)
|
|
||||||
#define usbhsg_controller_register(gpriv)\
|
|
||||||
list_add_tail(&(gpriv)->link, &the_controller_link)
|
|
||||||
#define usbhsg_controller_unregister(gpriv)\
|
|
||||||
list_del_init(&(gpriv)->link)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* queue push/pop
|
* queue push/pop
|
||||||
*/
|
*/
|
||||||
@ -164,7 +154,7 @@ static void usbhsg_queue_push(struct usbhsg_uep *uep,
|
|||||||
req->actual = 0;
|
req->actual = 0;
|
||||||
req->status = -EINPROGRESS;
|
req->status = -EINPROGRESS;
|
||||||
usbhs_pkt_push(pipe, pkt, usbhsg_queue_done,
|
usbhs_pkt_push(pipe, pkt, usbhsg_queue_done,
|
||||||
req->buf, req->length, req->zero);
|
req->buf, req->length, req->zero, -1);
|
||||||
usbhs_pkt_start(pipe);
|
usbhs_pkt_start(pipe);
|
||||||
|
|
||||||
dev_dbg(dev, "pipe %d : queue push (%d)\n",
|
dev_dbg(dev, "pipe %d : queue push (%d)\n",
|
||||||
@ -271,6 +261,8 @@ static int usbhsg_recip_handler_std_clear_endpoint(struct usbhs_priv *priv,
|
|||||||
|
|
||||||
usbhsg_recip_handler_std_control_done(priv, uep, ctrl);
|
usbhsg_recip_handler_std_control_done(priv, uep, ctrl);
|
||||||
|
|
||||||
|
usbhs_pkt_start(pipe);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,6 +273,145 @@ struct usbhsg_recip_handle req_clear_feature = {
|
|||||||
.endpoint = usbhsg_recip_handler_std_clear_endpoint,
|
.endpoint = usbhsg_recip_handler_std_clear_endpoint,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB_TYPE_STANDARD / set feature functions
|
||||||
|
*/
|
||||||
|
static int usbhsg_recip_handler_std_set_device(struct usbhs_priv *priv,
|
||||||
|
struct usbhsg_uep *uep,
|
||||||
|
struct usb_ctrlrequest *ctrl)
|
||||||
|
{
|
||||||
|
switch (le16_to_cpu(ctrl->wValue)) {
|
||||||
|
case USB_DEVICE_TEST_MODE:
|
||||||
|
usbhsg_recip_handler_std_control_done(priv, uep, ctrl);
|
||||||
|
udelay(100);
|
||||||
|
usbhs_sys_set_test_mode(priv, le16_to_cpu(ctrl->wIndex >> 8));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usbhsg_recip_handler_std_control_done(priv, uep, ctrl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbhsg_recip_handler_std_set_endpoint(struct usbhs_priv *priv,
|
||||||
|
struct usbhsg_uep *uep,
|
||||||
|
struct usb_ctrlrequest *ctrl)
|
||||||
|
{
|
||||||
|
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
|
||||||
|
|
||||||
|
usbhs_pipe_stall(pipe);
|
||||||
|
|
||||||
|
usbhsg_recip_handler_std_control_done(priv, uep, ctrl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct usbhsg_recip_handle req_set_feature = {
|
||||||
|
.name = "set feature",
|
||||||
|
.device = usbhsg_recip_handler_std_set_device,
|
||||||
|
.interface = usbhsg_recip_handler_std_control_done,
|
||||||
|
.endpoint = usbhsg_recip_handler_std_set_endpoint,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB_TYPE_STANDARD / get status functions
|
||||||
|
*/
|
||||||
|
static void __usbhsg_recip_send_complete(struct usb_ep *ep,
|
||||||
|
struct usb_request *req)
|
||||||
|
{
|
||||||
|
struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
|
||||||
|
|
||||||
|
/* free allocated recip-buffer/usb_request */
|
||||||
|
kfree(ureq->pkt.buf);
|
||||||
|
usb_ep_free_request(ep, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __usbhsg_recip_send_status(struct usbhsg_gpriv *gpriv,
|
||||||
|
unsigned short status)
|
||||||
|
{
|
||||||
|
struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv);
|
||||||
|
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(dcp);
|
||||||
|
struct device *dev = usbhsg_gpriv_to_dev(gpriv);
|
||||||
|
struct usb_request *req;
|
||||||
|
unsigned short *buf;
|
||||||
|
|
||||||
|
/* alloc new usb_request for recip */
|
||||||
|
req = usb_ep_alloc_request(&dcp->ep, GFP_ATOMIC);
|
||||||
|
if (!req) {
|
||||||
|
dev_err(dev, "recip request allocation fail\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* alloc recip data buffer */
|
||||||
|
buf = kmalloc(sizeof(*buf), GFP_ATOMIC);
|
||||||
|
if (!buf) {
|
||||||
|
usb_ep_free_request(&dcp->ep, req);
|
||||||
|
dev_err(dev, "recip data allocation fail\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* recip data is status */
|
||||||
|
*buf = cpu_to_le16(status);
|
||||||
|
|
||||||
|
/* allocated usb_request/buffer will be freed */
|
||||||
|
req->complete = __usbhsg_recip_send_complete;
|
||||||
|
req->buf = buf;
|
||||||
|
req->length = sizeof(*buf);
|
||||||
|
req->zero = 0;
|
||||||
|
|
||||||
|
/* push packet */
|
||||||
|
pipe->handler = &usbhs_fifo_pio_push_handler;
|
||||||
|
usbhsg_queue_push(dcp, usbhsg_req_to_ureq(req));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbhsg_recip_handler_std_get_device(struct usbhs_priv *priv,
|
||||||
|
struct usbhsg_uep *uep,
|
||||||
|
struct usb_ctrlrequest *ctrl)
|
||||||
|
{
|
||||||
|
struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
|
||||||
|
unsigned short status = 1 << USB_DEVICE_SELF_POWERED;
|
||||||
|
|
||||||
|
__usbhsg_recip_send_status(gpriv, status);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbhsg_recip_handler_std_get_interface(struct usbhs_priv *priv,
|
||||||
|
struct usbhsg_uep *uep,
|
||||||
|
struct usb_ctrlrequest *ctrl)
|
||||||
|
{
|
||||||
|
struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
|
||||||
|
unsigned short status = 0;
|
||||||
|
|
||||||
|
__usbhsg_recip_send_status(gpriv, status);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbhsg_recip_handler_std_get_endpoint(struct usbhs_priv *priv,
|
||||||
|
struct usbhsg_uep *uep,
|
||||||
|
struct usb_ctrlrequest *ctrl)
|
||||||
|
{
|
||||||
|
struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
|
||||||
|
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
|
||||||
|
unsigned short status = 0;
|
||||||
|
|
||||||
|
if (usbhs_pipe_is_stall(pipe))
|
||||||
|
status = 1 << USB_ENDPOINT_HALT;
|
||||||
|
|
||||||
|
__usbhsg_recip_send_status(gpriv, status);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct usbhsg_recip_handle req_get_status = {
|
||||||
|
.name = "get status",
|
||||||
|
.device = usbhsg_recip_handler_std_get_device,
|
||||||
|
.interface = usbhsg_recip_handler_std_get_interface,
|
||||||
|
.endpoint = usbhsg_recip_handler_std_get_endpoint,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* USB_TYPE handler
|
* USB_TYPE handler
|
||||||
*/
|
*/
|
||||||
@ -303,8 +434,7 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv,
|
|||||||
pipe = usbhsg_uep_to_pipe(uep);
|
pipe = usbhsg_uep_to_pipe(uep);
|
||||||
if (!pipe) {
|
if (!pipe) {
|
||||||
dev_err(dev, "wrong recip request\n");
|
dev_err(dev, "wrong recip request\n");
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
goto usbhsg_recip_run_handle_end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (recip) {
|
switch (recip) {
|
||||||
@ -327,20 +457,10 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (func) {
|
if (func) {
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
dev_dbg(dev, "%s (pipe %d :%s)\n", handler->name, nth, msg);
|
dev_dbg(dev, "%s (pipe %d :%s)\n", handler->name, nth, msg);
|
||||||
|
|
||||||
/******************** spin lock ********************/
|
|
||||||
usbhs_lock(priv, flags);
|
|
||||||
ret = func(priv, uep, ctrl);
|
ret = func(priv, uep, ctrl);
|
||||||
usbhs_unlock(priv, flags);
|
|
||||||
/******************** spin unlock ******************/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
usbhsg_recip_run_handle_end:
|
|
||||||
usbhs_pkt_start(pipe);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,6 +532,12 @@ static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv,
|
|||||||
case USB_REQ_CLEAR_FEATURE:
|
case USB_REQ_CLEAR_FEATURE:
|
||||||
recip_handler = &req_clear_feature;
|
recip_handler = &req_clear_feature;
|
||||||
break;
|
break;
|
||||||
|
case USB_REQ_SET_FEATURE:
|
||||||
|
recip_handler = &req_set_feature;
|
||||||
|
break;
|
||||||
|
case USB_REQ_GET_STATUS:
|
||||||
|
recip_handler = &req_get_status;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,14 +565,16 @@ static int usbhsg_pipe_disable(struct usbhsg_uep *uep)
|
|||||||
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
|
struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
|
||||||
struct usbhs_pkt *pkt;
|
struct usbhs_pkt *pkt;
|
||||||
|
|
||||||
usbhs_pipe_disable(pipe);
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
pkt = usbhs_pkt_pop(pipe, NULL);
|
pkt = usbhs_pkt_pop(pipe, NULL);
|
||||||
if (!pkt)
|
if (!pkt)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
usbhsg_queue_pop(uep, usbhsg_pkt_to_ureq(pkt), -ECONNRESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usbhs_pipe_disable(pipe);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -681,9 +809,7 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status)
|
|||||||
* - function
|
* - function
|
||||||
* - usb module
|
* - usb module
|
||||||
*/
|
*/
|
||||||
usbhs_sys_hispeed_ctrl(priv, 1);
|
|
||||||
usbhs_sys_function_ctrl(priv, 1);
|
usbhs_sys_function_ctrl(priv, 1);
|
||||||
usbhs_sys_usb_ctrl(priv, 1);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* enable irq callback
|
* enable irq callback
|
||||||
@ -731,9 +857,8 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status)
|
|||||||
gpriv->gadget.speed = USB_SPEED_UNKNOWN;
|
gpriv->gadget.speed = USB_SPEED_UNKNOWN;
|
||||||
|
|
||||||
/* disable sys */
|
/* disable sys */
|
||||||
usbhs_sys_hispeed_ctrl(priv, 0);
|
usbhs_sys_set_test_mode(priv, 0);
|
||||||
usbhs_sys_function_ctrl(priv, 0);
|
usbhs_sys_function_ctrl(priv, 0);
|
||||||
usbhs_sys_usb_ctrl(priv, 0);
|
|
||||||
|
|
||||||
usbhsg_pipe_disable(dcp);
|
usbhsg_pipe_disable(dcp);
|
||||||
|
|
||||||
@ -755,7 +880,7 @@ static int usbhsg_gadget_start(struct usb_gadget *gadget,
|
|||||||
|
|
||||||
if (!driver ||
|
if (!driver ||
|
||||||
!driver->setup ||
|
!driver->setup ||
|
||||||
driver->speed < USB_SPEED_FULL)
|
driver->max_speed < USB_SPEED_FULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* first hook up the driver ... */
|
/* first hook up the driver ... */
|
||||||
@ -866,7 +991,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
|
|||||||
gpriv->gadget.dev.parent = dev;
|
gpriv->gadget.dev.parent = dev;
|
||||||
gpriv->gadget.name = "renesas_usbhs_udc";
|
gpriv->gadget.name = "renesas_usbhs_udc";
|
||||||
gpriv->gadget.ops = &usbhsg_gadget_ops;
|
gpriv->gadget.ops = &usbhsg_gadget_ops;
|
||||||
gpriv->gadget.is_dualspeed = 1;
|
gpriv->gadget.max_speed = USB_SPEED_HIGH;
|
||||||
ret = device_register(&gpriv->gadget.dev);
|
ret = device_register(&gpriv->gadget.dev);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_add_udc;
|
goto err_add_udc;
|
||||||
@ -896,8 +1021,6 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usbhsg_controller_register(gpriv);
|
|
||||||
|
|
||||||
ret = usb_add_gadget_udc(dev, &gpriv->gadget);
|
ret = usb_add_gadget_udc(dev, &gpriv->gadget);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_register;
|
goto err_register;
|
||||||
@ -926,8 +1049,6 @@ void usbhs_mod_gadget_remove(struct usbhs_priv *priv)
|
|||||||
|
|
||||||
device_unregister(&gpriv->gadget.dev);
|
device_unregister(&gpriv->gadget.dev);
|
||||||
|
|
||||||
usbhsg_controller_unregister(gpriv);
|
|
||||||
|
|
||||||
kfree(gpriv->uep);
|
kfree(gpriv->uep);
|
||||||
kfree(gpriv);
|
kfree(gpriv);
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -257,6 +257,13 @@ void usbhs_pipe_stall(struct usbhs_pipe *pipe)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int usbhs_pipe_is_stall(struct usbhs_pipe *pipe)
|
||||||
|
{
|
||||||
|
u16 pid = usbhsp_pipectrl_get(pipe) & PID_MASK;
|
||||||
|
|
||||||
|
return (int)(pid == PID_STALL10 || pid == PID_STALL11);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pipe setup
|
* pipe setup
|
||||||
*/
|
*/
|
||||||
@ -471,10 +478,27 @@ int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe)
|
|||||||
return usbhsp_flags_has(pipe, IS_DIR_HOST);
|
return usbhsp_flags_has(pipe, IS_DIR_HOST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int data)
|
void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int sequence)
|
||||||
{
|
{
|
||||||
u16 mask = (SQCLR | SQSET);
|
u16 mask = (SQCLR | SQSET);
|
||||||
u16 val = (data) ? SQSET : SQCLR;
|
u16 val;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sequence
|
||||||
|
* 0 : data0
|
||||||
|
* 1 : data1
|
||||||
|
* -1 : no change
|
||||||
|
*/
|
||||||
|
switch (sequence) {
|
||||||
|
case 0:
|
||||||
|
val = SQCLR;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
val = SQSET;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
usbhsp_pipectrl_set(pipe, mask, val);
|
usbhsp_pipectrl_set(pipe, mask, val);
|
||||||
}
|
}
|
||||||
|
@ -87,6 +87,7 @@ int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe);
|
|||||||
void usbhs_pipe_enable(struct usbhs_pipe *pipe);
|
void usbhs_pipe_enable(struct usbhs_pipe *pipe);
|
||||||
void usbhs_pipe_disable(struct usbhs_pipe *pipe);
|
void usbhs_pipe_disable(struct usbhs_pipe *pipe);
|
||||||
void usbhs_pipe_stall(struct usbhs_pipe *pipe);
|
void usbhs_pipe_stall(struct usbhs_pipe *pipe);
|
||||||
|
int usbhs_pipe_is_stall(struct usbhs_pipe *pipe);
|
||||||
void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo);
|
void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo);
|
||||||
void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 devsel,
|
void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 devsel,
|
||||||
u16 epnum, u16 maxp);
|
u16 epnum, u16 maxp);
|
||||||
|
@ -477,8 +477,8 @@ struct usb_gadget_ops {
|
|||||||
* driver setup() requests
|
* driver setup() requests
|
||||||
* @ep_list: List of other endpoints supported by the device.
|
* @ep_list: List of other endpoints supported by the device.
|
||||||
* @speed: Speed of current connection to USB host.
|
* @speed: Speed of current connection to USB host.
|
||||||
* @is_dualspeed: True if the controller supports both high and full speed
|
* @max_speed: Maximal speed the UDC can handle. UDC must support this
|
||||||
* operation. If it does, the gadget driver must also support both.
|
* and all slower speeds.
|
||||||
* @is_otg: True if the USB device port uses a Mini-AB jack, so that the
|
* @is_otg: True if the USB device port uses a Mini-AB jack, so that the
|
||||||
* gadget driver must provide a USB OTG descriptor.
|
* gadget driver must provide a USB OTG descriptor.
|
||||||
* @is_a_peripheral: False unless is_otg, the "A" end of a USB cable
|
* @is_a_peripheral: False unless is_otg, the "A" end of a USB cable
|
||||||
@ -518,7 +518,7 @@ struct usb_gadget {
|
|||||||
struct usb_ep *ep0;
|
struct usb_ep *ep0;
|
||||||
struct list_head ep_list; /* of usb_ep */
|
struct list_head ep_list; /* of usb_ep */
|
||||||
enum usb_device_speed speed;
|
enum usb_device_speed speed;
|
||||||
unsigned is_dualspeed:1;
|
enum usb_device_speed max_speed;
|
||||||
unsigned is_otg:1;
|
unsigned is_otg:1;
|
||||||
unsigned is_a_peripheral:1;
|
unsigned is_a_peripheral:1;
|
||||||
unsigned b_hnp_enable:1;
|
unsigned b_hnp_enable:1;
|
||||||
@ -549,7 +549,7 @@ static inline struct usb_gadget *dev_to_usb_gadget(struct device *dev)
|
|||||||
static inline int gadget_is_dualspeed(struct usb_gadget *g)
|
static inline int gadget_is_dualspeed(struct usb_gadget *g)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_USB_GADGET_DUALSPEED
|
#ifdef CONFIG_USB_GADGET_DUALSPEED
|
||||||
/* runtime test would check "g->is_dualspeed" ... that might be
|
/* runtime test would check "g->max_speed" ... that might be
|
||||||
* useful to work around hardware bugs, but is mostly pointless
|
* useful to work around hardware bugs, but is mostly pointless
|
||||||
*/
|
*/
|
||||||
return 1;
|
return 1;
|
||||||
@ -567,7 +567,7 @@ static inline int gadget_is_superspeed(struct usb_gadget *g)
|
|||||||
{
|
{
|
||||||
#ifdef CONFIG_USB_GADGET_SUPERSPEED
|
#ifdef CONFIG_USB_GADGET_SUPERSPEED
|
||||||
/*
|
/*
|
||||||
* runtime test would check "g->is_superspeed" ... that might be
|
* runtime test would check "g->max_speed" ... that might be
|
||||||
* useful to work around hardware bugs, but is mostly pointless
|
* useful to work around hardware bugs, but is mostly pointless
|
||||||
*/
|
*/
|
||||||
return 1;
|
return 1;
|
||||||
@ -760,7 +760,7 @@ static inline int usb_gadget_disconnect(struct usb_gadget *gadget)
|
|||||||
/**
|
/**
|
||||||
* struct usb_gadget_driver - driver for usb 'slave' devices
|
* struct usb_gadget_driver - driver for usb 'slave' devices
|
||||||
* @function: String describing the gadget's function
|
* @function: String describing the gadget's function
|
||||||
* @speed: Highest speed the driver handles.
|
* @max_speed: Highest speed the driver handles.
|
||||||
* @setup: Invoked for ep0 control requests that aren't handled by
|
* @setup: Invoked for ep0 control requests that aren't handled by
|
||||||
* the hardware level driver. Most calls must be handled by
|
* the hardware level driver. Most calls must be handled by
|
||||||
* the gadget driver, including descriptor and configuration
|
* the gadget driver, including descriptor and configuration
|
||||||
@ -824,7 +824,7 @@ static inline int usb_gadget_disconnect(struct usb_gadget *gadget)
|
|||||||
*/
|
*/
|
||||||
struct usb_gadget_driver {
|
struct usb_gadget_driver {
|
||||||
char *function;
|
char *function;
|
||||||
enum usb_device_speed speed;
|
enum usb_device_speed max_speed;
|
||||||
void (*unbind)(struct usb_gadget *);
|
void (*unbind)(struct usb_gadget *);
|
||||||
int (*setup)(struct usb_gadget *,
|
int (*setup)(struct usb_gadget *,
|
||||||
const struct usb_ctrlrequest *);
|
const struct usb_ctrlrequest *);
|
||||||
|
@ -64,6 +64,14 @@ struct renesas_usbhs_platform_callback {
|
|||||||
*/
|
*/
|
||||||
void (*hardware_exit)(struct platform_device *pdev);
|
void (*hardware_exit)(struct platform_device *pdev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* option:
|
||||||
|
*
|
||||||
|
* for board specific clock control
|
||||||
|
*/
|
||||||
|
void (*power_ctrl)(struct platform_device *pdev,
|
||||||
|
void __iomem *base, int enable);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* option:
|
* option:
|
||||||
*
|
*
|
||||||
@ -118,7 +126,7 @@ struct renesas_usbhs_driver_param {
|
|||||||
*
|
*
|
||||||
* delay time from notify_hotplug callback
|
* delay time from notify_hotplug callback
|
||||||
*/
|
*/
|
||||||
int detection_delay;
|
int detection_delay; /* msec */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* option:
|
* option:
|
||||||
|
Loading…
Reference in New Issue
Block a user