mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 13:20:52 +07:00
Merge 3.4-rc4 into usb-next.
This resolves the conflict in: drivers/usb/host/ehci-fsl.c And picks up loads of xhci bugfixes to make it easier for others to test with. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
commit
09091a4d5f
39
Documentation/devicetree/bindings/usb/spear-usb.txt
Normal file
39
Documentation/devicetree/bindings/usb/spear-usb.txt
Normal file
@ -0,0 +1,39 @@
|
||||
ST SPEAr SoC USB controllers:
|
||||
-----------------------------
|
||||
|
||||
EHCI:
|
||||
-----
|
||||
|
||||
Required properties:
|
||||
- compatible: "st,spear600-ehci"
|
||||
- interrupt-parent: Should be the phandle for the interrupt controller
|
||||
that services interrupts for this device
|
||||
- interrupts: Should contain the EHCI interrupt
|
||||
|
||||
Example:
|
||||
|
||||
ehci@e1800000 {
|
||||
compatible = "st,spear600-ehci", "usb-ehci";
|
||||
reg = <0xe1800000 0x1000>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <27>;
|
||||
};
|
||||
|
||||
|
||||
OHCI:
|
||||
-----
|
||||
|
||||
Required properties:
|
||||
- compatible: "st,spear600-ohci"
|
||||
- interrupt-parent: Should be the phandle for the interrupt controller
|
||||
that services interrupts for this device
|
||||
- interrupts: Should contain the OHCI interrupt
|
||||
|
||||
Example:
|
||||
|
||||
ohci@e1900000 {
|
||||
compatible = "st,spear600-ohci", "usb-ohci";
|
||||
reg = <0xe1800000 0x1000>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <26>;
|
||||
};
|
@ -297,6 +297,23 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
|
||||
return -EILSEQ;
|
||||
}
|
||||
|
||||
/* First Slave Address Descriptor should be port 0:
|
||||
* the main register space for the core
|
||||
*/
|
||||
tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, 0);
|
||||
if (tmp <= 0) {
|
||||
/* Try again to see if it is a bridge */
|
||||
tmp = bcma_erom_get_addr_desc(bus, eromptr,
|
||||
SCAN_ADDR_TYPE_BRIDGE, 0);
|
||||
if (tmp <= 0) {
|
||||
return -EILSEQ;
|
||||
} else {
|
||||
pr_info("Bridge found\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
}
|
||||
core->addr = tmp;
|
||||
|
||||
/* get & parse slave ports */
|
||||
for (i = 0; i < ports[1]; i++) {
|
||||
for (j = 0; ; j++) {
|
||||
@ -309,7 +326,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
|
||||
break;
|
||||
} else {
|
||||
if (i == 0 && j == 0)
|
||||
core->addr = tmp;
|
||||
core->addr1 = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -782,20 +782,20 @@ static int __init asus_oled_init(void)
|
||||
oled_class = class_create(THIS_MODULE, ASUS_OLED_UNDERSCORE_NAME);
|
||||
|
||||
if (IS_ERR(oled_class)) {
|
||||
err("Error creating " ASUS_OLED_UNDERSCORE_NAME " class");
|
||||
printk(KERN_ERR "Error creating " ASUS_OLED_UNDERSCORE_NAME " class\n");
|
||||
return PTR_ERR(oled_class);
|
||||
}
|
||||
|
||||
retval = class_create_file(oled_class, &class_attr_version.attr);
|
||||
if (retval) {
|
||||
err("Error creating class version file");
|
||||
printk(KERN_ERR "Error creating class version file\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
retval = usb_register(&oled_driver);
|
||||
|
||||
if (retval) {
|
||||
err("usb_register failed. Error number %d", retval);
|
||||
printk(KERN_ERR "usb_register failed. Error number %d\n", retval);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -547,7 +547,7 @@ static void dt9812_configure_gain(struct usb_dt9812 *dev,
|
||||
rmw->or_value = F020_MASK_ADC0CF_AMP0GN2;
|
||||
break;
|
||||
default:
|
||||
err("Illegal gain %d\n", gain);
|
||||
dev_err(&dev->interface->dev, "Illegal gain %d\n", gain);
|
||||
|
||||
}
|
||||
}
|
||||
@ -715,7 +715,7 @@ static int dt9812_probe(struct usb_interface *interface,
|
||||
iface_desc = interface->cur_altsetting;
|
||||
|
||||
if (iface_desc->desc.bNumEndpoints != 5) {
|
||||
err("Wrong number of endpints.");
|
||||
dev_err(&interface->dev, "Wrong number of endpoints.\n");
|
||||
retval = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
@ -781,22 +781,22 @@ static int dt9812_probe(struct usb_interface *interface,
|
||||
}
|
||||
|
||||
if (dt9812_read_info(dev, 1, &dev->vendor, sizeof(dev->vendor)) != 0) {
|
||||
err("Failed to read vendor.");
|
||||
dev_err(&interface->dev, "Failed to read vendor.\n");
|
||||
retval = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
if (dt9812_read_info(dev, 3, &dev->product, sizeof(dev->product)) != 0) {
|
||||
err("Failed to read product.");
|
||||
dev_err(&interface->dev, "Failed to read product.\n");
|
||||
retval = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
if (dt9812_read_info(dev, 5, &dev->device, sizeof(dev->device)) != 0) {
|
||||
err("Failed to read device.");
|
||||
dev_err(&interface->dev, "Failed to read device.\n");
|
||||
retval = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
if (dt9812_read_info(dev, 7, &dev->serial, sizeof(dev->serial)) != 0) {
|
||||
err("Failed to read serial.");
|
||||
dev_err(&interface->dev, "Failed to read serial.\n");
|
||||
retval = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
@ -1146,7 +1146,9 @@ static int __init usb_dt9812_init(void)
|
||||
result = comedi_driver_register(&dt9812_comedi_driver);
|
||||
if (result) {
|
||||
usb_deregister(&dt9812_usb_driver);
|
||||
err("comedi_driver_register failed. Error number %d", result);
|
||||
printk(KERN_ERR KBUILD_MODNAME
|
||||
": comedi_driver_register failed. Error number %d\n",
|
||||
result);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -295,7 +295,9 @@ static void vmk80xx_rx_callback(struct urb *urb)
|
||||
if (!usb_submit_urb(urb, GFP_KERNEL))
|
||||
goto exit;
|
||||
|
||||
err("comedi#: vmk80xx: %s - submit urb failed\n", __func__);
|
||||
dev_err(&urb->dev->dev,
|
||||
"comedi#: vmk80xx: %s - submit urb failed\n",
|
||||
__func__);
|
||||
|
||||
usb_unanchor_urb(urb);
|
||||
}
|
||||
|
@ -333,8 +333,8 @@ static int usb_alphatrack_open(struct inode *inode, struct file *file)
|
||||
interface = usb_find_interface(&usb_alphatrack_driver, subminor);
|
||||
|
||||
if (!interface) {
|
||||
err("%s - error, can't find device for minor %d\n",
|
||||
__func__, subminor);
|
||||
printk(KERN_ERR "%s - error, can't find device for minor %d\n",
|
||||
__func__, subminor);
|
||||
retval = -ENODEV;
|
||||
goto unlock_disconnect_exit;
|
||||
}
|
||||
@ -494,7 +494,8 @@ static ssize_t usb_alphatrack_read(struct file *file, char __user *buffer,
|
||||
/* verify that the device wasn't unplugged */
|
||||
if (dev->intf == NULL) {
|
||||
retval = -ENODEV;
|
||||
err("No device or device unplugged %d\n", retval);
|
||||
printk(KERN_ERR "%s: No device or device unplugged %d\n",
|
||||
__func__, retval);
|
||||
goto unlock_exit;
|
||||
}
|
||||
|
||||
@ -564,7 +565,8 @@ static ssize_t usb_alphatrack_write(struct file *file,
|
||||
/* verify that the device wasn't unplugged */
|
||||
if (dev->intf == NULL) {
|
||||
retval = -ENODEV;
|
||||
err("No device or device unplugged %d\n", retval);
|
||||
printk(KERN_ERR "%s: No device or device unplugged %d\n",
|
||||
__func__, retval);
|
||||
goto unlock_exit;
|
||||
}
|
||||
|
||||
@ -599,7 +601,7 @@ static ssize_t usb_alphatrack_write(struct file *file,
|
||||
}
|
||||
|
||||
if (dev->interrupt_out_endpoint == NULL) {
|
||||
err("Endpoint should not be be null!\n");
|
||||
dev_err(&dev->intf->dev, "Endpoint should not be be null!\n");
|
||||
goto unlock_exit;
|
||||
}
|
||||
|
||||
@ -619,7 +621,8 @@ static ssize_t usb_alphatrack_write(struct file *file,
|
||||
retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
|
||||
if (retval) {
|
||||
dev->interrupt_out_busy = 0;
|
||||
err("Couldn't submit interrupt_out_urb %d\n", retval);
|
||||
dev_err(&dev->intf->dev,
|
||||
"Couldn't submit interrupt_out_urb %d\n", retval);
|
||||
atomic_dec(&dev->writes_pending);
|
||||
goto unlock_exit;
|
||||
}
|
||||
|
@ -353,7 +353,7 @@ static int usb_tranzport_open(struct inode *inode, struct file *file)
|
||||
interface = usb_find_interface(&usb_tranzport_driver, subminor);
|
||||
|
||||
if (!interface) {
|
||||
err("%s - error, can't find device for minor %d\n",
|
||||
printk(KERN_ERR "%s - error, can't find device for minor %d\n",
|
||||
__func__, subminor);
|
||||
retval = -ENODEV;
|
||||
goto unlock_disconnect_exit;
|
||||
@ -517,9 +517,11 @@ static ssize_t usb_tranzport_read(struct file *file, char __user *buffer,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* verify that the device wasn't unplugged */ if (dev->intf == NULL) {
|
||||
/* verify that the device wasn't unplugged */
|
||||
if (dev->intf == NULL) {
|
||||
retval = -ENODEV;
|
||||
err("No device or device unplugged %d\n", retval);
|
||||
printk(KERN_ERR "%s: No device or device unplugged %d\n",
|
||||
__func__, retval);
|
||||
goto unlock_exit;
|
||||
}
|
||||
|
||||
@ -691,7 +693,8 @@ static ssize_t usb_tranzport_write(struct file *file,
|
||||
/* verify that the device wasn't unplugged */
|
||||
if (dev->intf == NULL) {
|
||||
retval = -ENODEV;
|
||||
err("No device or device unplugged %d\n", retval);
|
||||
printk(KERN_ERR "%s: No device or device unplugged %d\n",
|
||||
__func__, retval);
|
||||
goto unlock_exit;
|
||||
}
|
||||
|
||||
@ -726,7 +729,7 @@ static ssize_t usb_tranzport_write(struct file *file,
|
||||
}
|
||||
|
||||
if (dev->interrupt_out_endpoint == NULL) {
|
||||
err("Endpoint should not be be null!\n");
|
||||
dev_err(&dev->intf->dev, "Endpoint should not be be null!\n");
|
||||
goto unlock_exit;
|
||||
}
|
||||
|
||||
@ -746,7 +749,8 @@ static ssize_t usb_tranzport_write(struct file *file,
|
||||
retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
|
||||
if (retval) {
|
||||
dev->interrupt_out_busy = 0;
|
||||
err("Couldn't submit interrupt_out_urb %d\n", retval);
|
||||
dev_err(&dev->intf->dev,
|
||||
"Couldn't submit interrupt_out_urb %d\n", retval);
|
||||
goto unlock_exit;
|
||||
}
|
||||
retval = bytes_to_write;
|
||||
|
@ -1307,7 +1307,8 @@ static int __init line6_init(void)
|
||||
retval = usb_register(&line6_driver);
|
||||
|
||||
if (retval) {
|
||||
err("usb_register failed. Error number %d", retval);
|
||||
printk(KERN_ERR KBUILD_MODNAME
|
||||
": usb_register failed. Error number %d\n", retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -1315,7 +1316,7 @@ static int __init line6_init(void)
|
||||
GFP_KERNEL);
|
||||
|
||||
if (line6_request_version == NULL) {
|
||||
err("Out of memory");
|
||||
printk(KERN_ERR KBUILD_MODNAME ":Out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -168,7 +168,7 @@ static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2)
|
||||
cmd1, cmd2, NULL, 0, LINE6_TIMEOUT * HZ);
|
||||
|
||||
if (ret < 0) {
|
||||
err("send failed (error %d)\n", ret);
|
||||
dev_err(&usbdev->dev, "send failed (error %d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1357,10 +1357,8 @@ static int uea_stat_e1(struct uea_softc *sc)
|
||||
/* release the dsp firmware as it is not needed until
|
||||
* the next failure
|
||||
*/
|
||||
if (sc->dsp_firm) {
|
||||
release_firmware(sc->dsp_firm);
|
||||
sc->dsp_firm = NULL;
|
||||
}
|
||||
release_firmware(sc->dsp_firm);
|
||||
sc->dsp_firm = NULL;
|
||||
}
|
||||
|
||||
/* always update it as atm layer could not be init when we switch to
|
||||
@ -1496,10 +1494,8 @@ static int uea_stat_e4(struct uea_softc *sc)
|
||||
/* release the dsp firmware as it is not needed until
|
||||
* the next failure
|
||||
*/
|
||||
if (sc->dsp_firm) {
|
||||
release_firmware(sc->dsp_firm);
|
||||
sc->dsp_firm = NULL;
|
||||
}
|
||||
release_firmware(sc->dsp_firm);
|
||||
sc->dsp_firm = NULL;
|
||||
}
|
||||
|
||||
/* always update it as atm layer could not be init when we switch to
|
||||
@ -2240,8 +2236,7 @@ static void uea_stop(struct uea_softc *sc)
|
||||
/* flush the work item, when no one can schedule it */
|
||||
flush_work_sync(&sc->task);
|
||||
|
||||
if (sc->dsp_firm)
|
||||
release_firmware(sc->dsp_firm);
|
||||
release_firmware(sc->dsp_firm);
|
||||
uea_leaves(INS_TO_USBDEV(sc));
|
||||
}
|
||||
|
||||
|
@ -374,7 +374,7 @@ static int hidg_setup(struct usb_function *f,
|
||||
break;
|
||||
|
||||
default:
|
||||
VDBG(cdev, "Unknown decriptor request 0x%x\n",
|
||||
VDBG(cdev, "Unknown descriptor request 0x%x\n",
|
||||
value >> 8);
|
||||
goto stall;
|
||||
break;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2007,2011 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2004-2007,2011-2012 Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Author: Li Yang <leoli@freescale.com>
|
||||
@ -58,9 +58,8 @@ static const char driver_name[] = "fsl-usb2-udc";
|
||||
static const char driver_desc[] = DRIVER_DESC;
|
||||
|
||||
static struct usb_dr_device *dr_regs;
|
||||
#ifndef CONFIG_ARCH_MXC
|
||||
|
||||
static struct usb_sys_interface *usb_sys_regs;
|
||||
#endif
|
||||
|
||||
/* it is initialized in probe() */
|
||||
static struct fsl_udc *udc_controller = NULL;
|
||||
@ -244,10 +243,9 @@ static int dr_controller_setup(struct fsl_udc *udc)
|
||||
{
|
||||
unsigned int tmp, portctrl, ep_num;
|
||||
unsigned int max_no_of_ep;
|
||||
#ifndef CONFIG_ARCH_MXC
|
||||
unsigned int ctrl;
|
||||
#endif
|
||||
unsigned long timeout;
|
||||
|
||||
#define FSL_UDC_RESET_TIMEOUT 1000
|
||||
|
||||
/* Config PHY interface */
|
||||
@ -255,12 +253,32 @@ static int dr_controller_setup(struct fsl_udc *udc)
|
||||
portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH);
|
||||
switch (udc->phy_mode) {
|
||||
case FSL_USB2_PHY_ULPI:
|
||||
if (udc->pdata->have_sysif_regs) {
|
||||
if (udc->pdata->controller_ver) {
|
||||
/* controller version 1.6 or above */
|
||||
ctrl = __raw_readl(&usb_sys_regs->control);
|
||||
ctrl &= ~USB_CTRL_UTMI_PHY_EN;
|
||||
ctrl |= USB_CTRL_USB_EN;
|
||||
__raw_writel(ctrl, &usb_sys_regs->control);
|
||||
}
|
||||
}
|
||||
portctrl |= PORTSCX_PTS_ULPI;
|
||||
break;
|
||||
case FSL_USB2_PHY_UTMI_WIDE:
|
||||
portctrl |= PORTSCX_PTW_16BIT;
|
||||
/* fall through */
|
||||
case FSL_USB2_PHY_UTMI:
|
||||
if (udc->pdata->have_sysif_regs) {
|
||||
if (udc->pdata->controller_ver) {
|
||||
/* controller version 1.6 or above */
|
||||
ctrl = __raw_readl(&usb_sys_regs->control);
|
||||
ctrl |= (USB_CTRL_UTMI_PHY_EN |
|
||||
USB_CTRL_USB_EN);
|
||||
__raw_writel(ctrl, &usb_sys_regs->control);
|
||||
mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI
|
||||
PHY CLK to become stable - 10ms*/
|
||||
}
|
||||
}
|
||||
portctrl |= PORTSCX_PTS_UTMI;
|
||||
break;
|
||||
case FSL_USB2_PHY_SERIAL:
|
||||
|
@ -1,4 +1,12 @@
|
||||
/*
|
||||
* Copyright (C) 2004,2012 Freescale Semiconductor, Inc
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Freescale USB device/endpoint management registers
|
||||
*/
|
||||
#ifndef __FSL_USB2_UDC_H
|
||||
@ -348,6 +356,9 @@ struct usb_sys_interface {
|
||||
/* control Register Bit Masks */
|
||||
#define USB_CTRL_IOENB 0x00000004
|
||||
#define USB_CTRL_ULPI_INT0EN 0x00000001
|
||||
#define USB_CTRL_UTMI_PHY_EN 0x00000200
|
||||
#define USB_CTRL_USB_EN 0x00000004
|
||||
#define USB_CTRL_ULPI_PHY_CLK_SEL 0x00000400
|
||||
|
||||
/* Endpoint Queue Head data struct
|
||||
* Rem: all the variables of qh are LittleEndian Mode
|
||||
|
@ -110,13 +110,14 @@ config USB_EHCI_BIG_ENDIAN_MMIO
|
||||
depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || \
|
||||
ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
|
||||
PPC_MPC512x || CPU_CAVIUM_OCTEON || \
|
||||
PMC_MSP || SPARC_LEON)
|
||||
PMC_MSP || SPARC_LEON || MIPS_SEAD3)
|
||||
default y
|
||||
|
||||
config USB_EHCI_BIG_ENDIAN_DESC
|
||||
bool
|
||||
depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
|
||||
PPC_MPC512x || PMC_MSP || SPARC_LEON)
|
||||
PPC_MPC512x || PMC_MSP || SPARC_LEON || \
|
||||
MIPS_SEAD3)
|
||||
default y
|
||||
|
||||
config XPS_USB_HCD_XILINX
|
||||
@ -373,10 +374,15 @@ config USB_OHCI_HCD_PCI
|
||||
If unsure, say Y.
|
||||
|
||||
config USB_OHCI_HCD_SSB
|
||||
bool "OHCI support for Broadcom SSB OHCI core"
|
||||
bool "OHCI support for Broadcom SSB OHCI core (DEPRECATED)"
|
||||
depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) && EXPERIMENTAL
|
||||
select USB_HCD_SSB
|
||||
select USB_OHCI_HCD_PLATFORM
|
||||
default n
|
||||
---help---
|
||||
This option is deprecated now and the driver was removed, use
|
||||
USB_HCD_SSB and USB_OHCI_HCD_PLATFORM instead.
|
||||
|
||||
Support for the Sonics Silicon Backplane (SSB) attached
|
||||
Broadcom USB OHCI core.
|
||||
|
||||
@ -638,3 +644,27 @@ config USB_OCTEON_OHCI
|
||||
config USB_OCTEON2_COMMON
|
||||
bool
|
||||
default y if USB_OCTEON_EHCI || USB_OCTEON_OHCI
|
||||
|
||||
config USB_HCD_BCMA
|
||||
tristate "BCMA usb host driver"
|
||||
depends on BCMA && EXPERIMENTAL
|
||||
select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD
|
||||
select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD
|
||||
help
|
||||
Enbale support for the EHCI and OCHI host controller on an bcma bus.
|
||||
It converts the bcma driver into two platform device drivers
|
||||
for ehci and ohci.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config USB_HCD_SSB
|
||||
tristate "SSB usb host driver"
|
||||
depends on SSB && EXPERIMENTAL
|
||||
select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD
|
||||
select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD
|
||||
help
|
||||
Enbale support for the EHCI and OCHI host controller on an bcma bus.
|
||||
It converts the bcma driver into two platform device drivers
|
||||
for ehci and ohci.
|
||||
|
||||
If unsure, say N.
|
||||
|
@ -41,3 +41,5 @@ obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o
|
||||
obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o
|
||||
obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
|
||||
obj-$(CONFIG_MIPS_ALCHEMY) += alchemy-common.o
|
||||
obj-$(CONFIG_USB_HCD_BCMA) += bcma-hcd.o
|
||||
obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o
|
||||
|
334
drivers/usb/host/bcma-hcd.c
Normal file
334
drivers/usb/host/bcma-hcd.c
Normal file
@ -0,0 +1,334 @@
|
||||
/*
|
||||
* Broadcom specific Advanced Microcontroller Bus
|
||||
* Broadcom USB-core driver (BCMA bus glue)
|
||||
*
|
||||
* Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
|
||||
*
|
||||
* Based on ssb-ohci driver
|
||||
* Copyright 2007 Michael Buesch <m@bues.ch>
|
||||
*
|
||||
* Derived from the OHCI-PCI driver
|
||||
* Copyright 1999 Roman Weissgaerber
|
||||
* Copyright 2000-2002 David Brownell
|
||||
* Copyright 1999 Linus Torvalds
|
||||
* Copyright 1999 Gregory P. Smith
|
||||
*
|
||||
* Derived from the USBcore related parts of Broadcom-SB
|
||||
* Copyright 2005-2011 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
#include <linux/bcma/bcma.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb/ehci_pdriver.h>
|
||||
#include <linux/usb/ohci_pdriver.h>
|
||||
|
||||
MODULE_AUTHOR("Hauke Mehrtens");
|
||||
MODULE_DESCRIPTION("Common USB driver for BCMA Bus");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
struct bcma_hcd_device {
|
||||
struct platform_device *ehci_dev;
|
||||
struct platform_device *ohci_dev;
|
||||
};
|
||||
|
||||
/* Wait for bitmask in a register to get set or cleared.
|
||||
* timeout is in units of ten-microseconds.
|
||||
*/
|
||||
static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask,
|
||||
int timeout)
|
||||
{
|
||||
int i;
|
||||
u32 val;
|
||||
|
||||
for (i = 0; i < timeout; i++) {
|
||||
val = bcma_read32(dev, reg);
|
||||
if ((val & bitmask) == bitmask)
|
||||
return 0;
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static void __devinit bcma_hcd_4716wa(struct bcma_device *dev)
|
||||
{
|
||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
/* Work around for 4716 failures. */
|
||||
if (dev->bus->chipinfo.id == 0x4716) {
|
||||
u32 tmp;
|
||||
|
||||
tmp = bcma_cpu_clock(&dev->bus->drv_mips);
|
||||
if (tmp >= 480000000)
|
||||
tmp = 0x1846b; /* set CDR to 0x11(fast) */
|
||||
else if (tmp == 453000000)
|
||||
tmp = 0x1046b; /* set CDR to 0x10(slow) */
|
||||
else
|
||||
tmp = 0;
|
||||
|
||||
/* Change Shim mdio control reg to fix host not acking at
|
||||
* high frequencies
|
||||
*/
|
||||
if (tmp) {
|
||||
bcma_write32(dev, 0x524, 0x1); /* write sel to enable */
|
||||
udelay(500);
|
||||
|
||||
bcma_write32(dev, 0x524, tmp);
|
||||
udelay(500);
|
||||
bcma_write32(dev, 0x524, 0x4ab);
|
||||
udelay(500);
|
||||
bcma_read32(dev, 0x528);
|
||||
bcma_write32(dev, 0x528, 0x80000000);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BCMA_DRIVER_MIPS */
|
||||
}
|
||||
|
||||
/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
|
||||
static void __devinit bcma_hcd_init_chip(struct bcma_device *dev)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
/*
|
||||
* USB 2.0 special considerations:
|
||||
*
|
||||
* 1. Since the core supports both OHCI and EHCI functions, it must
|
||||
* only be reset once.
|
||||
*
|
||||
* 2. In addition to the standard SI reset sequence, the Host Control
|
||||
* Register must be programmed to bring the USB core and various
|
||||
* phy components out of reset.
|
||||
*/
|
||||
if (!bcma_core_is_enabled(dev)) {
|
||||
bcma_core_enable(dev, 0);
|
||||
mdelay(10);
|
||||
if (dev->id.rev >= 5) {
|
||||
/* Enable Misc PLL */
|
||||
tmp = bcma_read32(dev, 0x1e0);
|
||||
tmp |= 0x100;
|
||||
bcma_write32(dev, 0x1e0, tmp);
|
||||
if (bcma_wait_bits(dev, 0x1e0, 1 << 24, 100))
|
||||
printk(KERN_EMERG "Failed to enable misc PPL!\n");
|
||||
|
||||
/* Take out of resets */
|
||||
bcma_write32(dev, 0x200, 0x4ff);
|
||||
udelay(25);
|
||||
bcma_write32(dev, 0x200, 0x6ff);
|
||||
udelay(25);
|
||||
|
||||
/* Make sure digital and AFE are locked in USB PHY */
|
||||
bcma_write32(dev, 0x524, 0x6b);
|
||||
udelay(50);
|
||||
tmp = bcma_read32(dev, 0x524);
|
||||
udelay(50);
|
||||
bcma_write32(dev, 0x524, 0xab);
|
||||
udelay(50);
|
||||
tmp = bcma_read32(dev, 0x524);
|
||||
udelay(50);
|
||||
bcma_write32(dev, 0x524, 0x2b);
|
||||
udelay(50);
|
||||
tmp = bcma_read32(dev, 0x524);
|
||||
udelay(50);
|
||||
bcma_write32(dev, 0x524, 0x10ab);
|
||||
udelay(50);
|
||||
tmp = bcma_read32(dev, 0x524);
|
||||
|
||||
if (bcma_wait_bits(dev, 0x528, 0xc000, 10000)) {
|
||||
tmp = bcma_read32(dev, 0x528);
|
||||
printk(KERN_EMERG
|
||||
"USB20H mdio_rddata 0x%08x\n", tmp);
|
||||
}
|
||||
bcma_write32(dev, 0x528, 0x80000000);
|
||||
tmp = bcma_read32(dev, 0x314);
|
||||
udelay(265);
|
||||
bcma_write32(dev, 0x200, 0x7ff);
|
||||
udelay(10);
|
||||
|
||||
/* Take USB and HSIC out of non-driving modes */
|
||||
bcma_write32(dev, 0x510, 0);
|
||||
} else {
|
||||
bcma_write32(dev, 0x200, 0x7ff);
|
||||
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
bcma_hcd_4716wa(dev);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct usb_ehci_pdata ehci_pdata = {
|
||||
};
|
||||
|
||||
static const struct usb_ohci_pdata ohci_pdata = {
|
||||
};
|
||||
|
||||
static struct platform_device * __devinit
|
||||
bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr)
|
||||
{
|
||||
struct platform_device *hci_dev;
|
||||
struct resource hci_res[2];
|
||||
int ret = -ENOMEM;
|
||||
|
||||
memset(hci_res, 0, sizeof(hci_res));
|
||||
|
||||
hci_res[0].start = addr;
|
||||
hci_res[0].end = hci_res[0].start + 0x1000 - 1;
|
||||
hci_res[0].flags = IORESOURCE_MEM;
|
||||
|
||||
hci_res[1].start = dev->irq;
|
||||
hci_res[1].flags = IORESOURCE_IRQ;
|
||||
|
||||
hci_dev = platform_device_alloc(ohci ? "ohci-platform" :
|
||||
"ehci-platform" , 0);
|
||||
if (!hci_dev)
|
||||
return NULL;
|
||||
|
||||
hci_dev->dev.parent = &dev->dev;
|
||||
hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask;
|
||||
|
||||
ret = platform_device_add_resources(hci_dev, hci_res,
|
||||
ARRAY_SIZE(hci_res));
|
||||
if (ret)
|
||||
goto err_alloc;
|
||||
if (ohci)
|
||||
ret = platform_device_add_data(hci_dev, &ohci_pdata,
|
||||
sizeof(ohci_pdata));
|
||||
else
|
||||
ret = platform_device_add_data(hci_dev, &ehci_pdata,
|
||||
sizeof(ehci_pdata));
|
||||
if (ret)
|
||||
goto err_alloc;
|
||||
ret = platform_device_add(hci_dev);
|
||||
if (ret)
|
||||
goto err_alloc;
|
||||
|
||||
return hci_dev;
|
||||
|
||||
err_alloc:
|
||||
platform_device_put(hci_dev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static int __devinit bcma_hcd_probe(struct bcma_device *dev)
|
||||
{
|
||||
int err;
|
||||
u16 chipid_top;
|
||||
u32 ohci_addr;
|
||||
struct bcma_hcd_device *usb_dev;
|
||||
struct bcma_chipinfo *chipinfo;
|
||||
|
||||
chipinfo = &dev->bus->chipinfo;
|
||||
/* USBcores are only connected on embedded devices. */
|
||||
chipid_top = (chipinfo->id & 0xFF00);
|
||||
if (chipid_top != 0x4700 && chipid_top != 0x5300)
|
||||
return -ENODEV;
|
||||
|
||||
/* TODO: Probably need checks here; is the core connected? */
|
||||
|
||||
if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
|
||||
dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
usb_dev = kzalloc(sizeof(struct bcma_hcd_device), GFP_KERNEL);
|
||||
if (!usb_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
bcma_hcd_init_chip(dev);
|
||||
|
||||
/* In AI chips EHCI is addrspace 0, OHCI is 1 */
|
||||
ohci_addr = dev->addr1;
|
||||
if ((chipinfo->id == 0x5357 || chipinfo->id == 0x4749)
|
||||
&& chipinfo->rev == 0)
|
||||
ohci_addr = 0x18009000;
|
||||
|
||||
usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr);
|
||||
if (IS_ERR(usb_dev->ohci_dev)) {
|
||||
err = PTR_ERR(usb_dev->ohci_dev);
|
||||
goto err_free_usb_dev;
|
||||
}
|
||||
|
||||
usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr);
|
||||
if (IS_ERR(usb_dev->ehci_dev)) {
|
||||
err = PTR_ERR(usb_dev->ehci_dev);
|
||||
goto err_unregister_ohci_dev;
|
||||
}
|
||||
|
||||
bcma_set_drvdata(dev, usb_dev);
|
||||
return 0;
|
||||
|
||||
err_unregister_ohci_dev:
|
||||
platform_device_unregister(usb_dev->ohci_dev);
|
||||
err_free_usb_dev:
|
||||
kfree(usb_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __devexit bcma_hcd_remove(struct bcma_device *dev)
|
||||
{
|
||||
struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
|
||||
struct platform_device *ohci_dev = usb_dev->ohci_dev;
|
||||
struct platform_device *ehci_dev = usb_dev->ehci_dev;
|
||||
|
||||
if (ohci_dev)
|
||||
platform_device_unregister(ohci_dev);
|
||||
if (ehci_dev)
|
||||
platform_device_unregister(ehci_dev);
|
||||
|
||||
bcma_core_disable(dev, 0);
|
||||
}
|
||||
|
||||
static void bcma_hcd_shutdown(struct bcma_device *dev)
|
||||
{
|
||||
bcma_core_disable(dev, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int bcma_hcd_suspend(struct bcma_device *dev)
|
||||
{
|
||||
bcma_core_disable(dev, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcma_hcd_resume(struct bcma_device *dev)
|
||||
{
|
||||
bcma_core_enable(dev, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !CONFIG_PM */
|
||||
#define bcma_hcd_suspend NULL
|
||||
#define bcma_hcd_resume NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static const struct bcma_device_id bcma_hcd_table[] __devinitconst = {
|
||||
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),
|
||||
BCMA_CORETABLE_END
|
||||
};
|
||||
MODULE_DEVICE_TABLE(bcma, bcma_hcd_table);
|
||||
|
||||
static struct bcma_driver bcma_hcd_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = bcma_hcd_table,
|
||||
.probe = bcma_hcd_probe,
|
||||
.remove = __devexit_p(bcma_hcd_remove),
|
||||
.shutdown = bcma_hcd_shutdown,
|
||||
.suspend = bcma_hcd_suspend,
|
||||
.resume = bcma_hcd_resume,
|
||||
};
|
||||
|
||||
static int __init bcma_hcd_init(void)
|
||||
{
|
||||
return bcma_driver_register(&bcma_hcd_driver);
|
||||
}
|
||||
module_init(bcma_hcd_init);
|
||||
|
||||
static void __exit bcma_hcd_exit(void)
|
||||
{
|
||||
bcma_driver_unregister(&bcma_hcd_driver);
|
||||
}
|
||||
module_exit(bcma_hcd_exit);
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2005-2009 MontaVista Software, Inc.
|
||||
* Copyright 2008 Freescale Semiconductor, Inc.
|
||||
* Copyright 2008,2012 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@ -211,22 +211,32 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
|
||||
usb_put_hcd(hcd);
|
||||
}
|
||||
|
||||
static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
|
||||
static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
|
||||
enum fsl_usb2_phy_modes phy_mode,
|
||||
unsigned int port_offset)
|
||||
{
|
||||
u32 portsc;
|
||||
struct usb_hcd *hcd = ehci_to_hcd(ehci);
|
||||
u32 portsc, temp;
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
void __iomem *non_ehci = hcd->regs;
|
||||
struct fsl_usb2_platform_data *pdata;
|
||||
struct device *dev = hcd->self.controller;
|
||||
struct fsl_usb2_platform_data *pdata = dev->platform_data;
|
||||
|
||||
pdata = hcd->self.controller->platform_data;
|
||||
if (pdata->controller_ver < 0) {
|
||||
dev_warn(hcd->self.controller, "Could not get controller version\n");
|
||||
return;
|
||||
}
|
||||
|
||||
portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
|
||||
portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
|
||||
|
||||
switch (phy_mode) {
|
||||
case FSL_USB2_PHY_ULPI:
|
||||
if (pdata->controller_ver) {
|
||||
/* controller version 1.6 or above */
|
||||
temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
|
||||
out_be32(non_ehci + FSL_SOC_USB_CTRL, temp |
|
||||
USB_CTRL_USB_EN | ULPI_PHY_CLK_SEL);
|
||||
}
|
||||
portsc |= PORT_PTS_ULPI;
|
||||
break;
|
||||
case FSL_USB2_PHY_SERIAL:
|
||||
@ -236,6 +246,14 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
|
||||
portsc |= PORT_PTS_PTW;
|
||||
/* fall through */
|
||||
case FSL_USB2_PHY_UTMI:
|
||||
if (pdata->controller_ver) {
|
||||
/* controller version 1.6 or above */
|
||||
temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
|
||||
out_be32(non_ehci + FSL_SOC_USB_CTRL, temp |
|
||||
UTMI_PHY_EN | USB_CTRL_USB_EN);
|
||||
mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to
|
||||
become stable - 10ms*/
|
||||
}
|
||||
/* enable UTMI PHY */
|
||||
if (pdata->have_sysif_regs)
|
||||
setbits32(non_ehci + FSL_SOC_USB_CTRL,
|
||||
@ -276,7 +294,7 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
|
||||
|
||||
if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
|
||||
(pdata->operating_mode == FSL_USB2_DR_OTG))
|
||||
ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
|
||||
ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0);
|
||||
|
||||
if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
|
||||
unsigned int chip, rev, svr;
|
||||
@ -290,9 +308,9 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
|
||||
ehci->has_fsl_port_bug = 1;
|
||||
|
||||
if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
|
||||
ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
|
||||
ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0);
|
||||
if (pdata->port_enables & FSL_USB2_PORT1_ENABLED)
|
||||
ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1);
|
||||
ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1);
|
||||
}
|
||||
|
||||
if (pdata->have_sysif_regs) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2005-2010 Freescale Semiconductor, Inc.
|
||||
/* Copyright (C) 2005-2010,2012 Freescale Semiconductor, Inc.
|
||||
* Copyright (c) 2005 MontaVista Software
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@ -50,4 +50,15 @@
|
||||
#define CTRL_UTMI_PHY_EN (1<<9)
|
||||
#define CTRL_PHY_CLK_VALID (1 << 17)
|
||||
#define SNOOP_SIZE_2GB 0x1e
|
||||
|
||||
/* control Register Bit Masks */
|
||||
#define ULPI_INT_EN (1<<0)
|
||||
#define WU_INT_EN (1<<1)
|
||||
#define USB_CTRL_USB_EN (1<<2)
|
||||
#define LINE_STATE_FILTER__EN (1<<3)
|
||||
#define KEEP_OTG_ON (1<<4)
|
||||
#define OTG_PORT (1<<5)
|
||||
#define PLL_RESET (1<<8)
|
||||
#define UTMI_PHY_EN (1<<9)
|
||||
#define ULPI_PHY_CLK_SEL (1<<10)
|
||||
#endif /* _EHCI_FSL_H */
|
||||
|
@ -417,9 +417,6 @@ static void ehci_iaa_watchdog(unsigned long param)
|
||||
* CMD_IAAD when it sets STS_IAA.)
|
||||
*/
|
||||
cmd = ehci_readl(ehci, &ehci->regs->command);
|
||||
if (cmd & CMD_IAAD)
|
||||
ehci_writel(ehci, cmd & ~CMD_IAAD,
|
||||
&ehci->regs->command);
|
||||
|
||||
/* If IAA is set here it either legitimately triggered
|
||||
* before we cleared IAAD above (but _way_ late, so we'll
|
||||
@ -894,11 +891,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
|
||||
/* complete the unlinking of some qh [4.15.2.3] */
|
||||
if (status & STS_IAA) {
|
||||
/* guard against (alleged) silicon errata */
|
||||
if (cmd & CMD_IAAD) {
|
||||
ehci_writel(ehci, cmd & ~CMD_IAAD,
|
||||
&ehci->regs->command);
|
||||
if (cmd & CMD_IAAD)
|
||||
ehci_dbg(ehci, "IAA with IAAD still set?\n");
|
||||
}
|
||||
if (ehci->reclaim) {
|
||||
COUNT(ehci->stats.reclaim);
|
||||
end_unlink_async(ehci);
|
||||
@ -1378,6 +1372,11 @@ MODULE_LICENSE ("GPL");
|
||||
#define PLATFORM_DRIVER ehci_ls1x_driver
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MIPS_SEAD3
|
||||
#include "ehci-sead3.c"
|
||||
#define PLATFORM_DRIVER ehci_hcd_sead3_driver
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_EHCI_HCD_PLATFORM
|
||||
#include "ehci-platform.c"
|
||||
#define PLATFORM_DRIVER ehci_platform_driver
|
||||
|
@ -531,7 +531,8 @@ static int check_reset_complete (
|
||||
if (ehci->has_amcc_usb23)
|
||||
set_ohci_hcfs(ehci, 1);
|
||||
} else {
|
||||
ehci_dbg (ehci, "port %d high speed\n", index + 1);
|
||||
ehci_dbg(ehci, "port %d reset complete, port enabled\n",
|
||||
index + 1);
|
||||
/* ensure 440EPx ohci controller state is suspended */
|
||||
if (ehci->has_amcc_usb23)
|
||||
set_ohci_hcfs(ehci, 0);
|
||||
@ -699,6 +700,7 @@ static int ehci_hub_control (
|
||||
goto error;
|
||||
wIndex--;
|
||||
temp = ehci_readl(ehci, status_reg);
|
||||
temp &= ~PORT_RWC_BITS;
|
||||
|
||||
/*
|
||||
* Even if OWNER is set, so the port is owned by the
|
||||
@ -712,8 +714,7 @@ static int ehci_hub_control (
|
||||
ehci_writel(ehci, temp & ~PORT_PE, status_reg);
|
||||
break;
|
||||
case USB_PORT_FEAT_C_ENABLE:
|
||||
ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_PEC,
|
||||
status_reg);
|
||||
ehci_writel(ehci, temp | PORT_PEC, status_reg);
|
||||
break;
|
||||
case USB_PORT_FEAT_SUSPEND:
|
||||
if (temp & PORT_RESET)
|
||||
@ -742,7 +743,7 @@ static int ehci_hub_control (
|
||||
spin_lock_irqsave(&ehci->lock, flags);
|
||||
}
|
||||
/* resume signaling for 20 msec */
|
||||
temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
|
||||
temp &= ~PORT_WAKE_BITS;
|
||||
ehci_writel(ehci, temp | PORT_RESUME, status_reg);
|
||||
ehci->reset_done[wIndex] = jiffies
|
||||
+ msecs_to_jiffies(20);
|
||||
@ -752,9 +753,8 @@ static int ehci_hub_control (
|
||||
break;
|
||||
case USB_PORT_FEAT_POWER:
|
||||
if (HCS_PPC (ehci->hcs_params))
|
||||
ehci_writel(ehci,
|
||||
temp & ~(PORT_RWC_BITS | PORT_POWER),
|
||||
status_reg);
|
||||
ehci_writel(ehci, temp & ~PORT_POWER,
|
||||
status_reg);
|
||||
break;
|
||||
case USB_PORT_FEAT_C_CONNECTION:
|
||||
if (ehci->has_lpm) {
|
||||
@ -762,12 +762,10 @@ static int ehci_hub_control (
|
||||
temp &= ~PORT_LPM;
|
||||
temp &= ~PORT_DEV_ADDR;
|
||||
}
|
||||
ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC,
|
||||
status_reg);
|
||||
ehci_writel(ehci, temp | PORT_CSC, status_reg);
|
||||
break;
|
||||
case USB_PORT_FEAT_C_OVER_CURRENT:
|
||||
ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_OCC,
|
||||
status_reg);
|
||||
ehci_writel(ehci, temp | PORT_OCC, status_reg);
|
||||
break;
|
||||
case USB_PORT_FEAT_C_RESET:
|
||||
/* GetPortStatus clears reset */
|
||||
|
@ -94,12 +94,12 @@ static int __devinit ehci_platform_probe(struct platform_device *dev)
|
||||
|
||||
irq = platform_get_irq(dev, 0);
|
||||
if (irq < 0) {
|
||||
pr_err("no irq provieded");
|
||||
pr_err("no irq provided");
|
||||
return irq;
|
||||
}
|
||||
res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
|
||||
if (!res_mem) {
|
||||
pr_err("no memory recourse provieded");
|
||||
pr_err("no memory recourse provided");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
|
@ -232,6 +232,8 @@ static int s5p_ehci_suspend(struct device *dev)
|
||||
if (pdata && pdata->phy_exit)
|
||||
pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
|
||||
|
||||
clk_disable(s5p_ehci->clk);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -243,6 +245,8 @@ static int s5p_ehci_resume(struct device *dev)
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
|
||||
|
||||
clk_enable(s5p_ehci->clk);
|
||||
|
||||
if (pdata && pdata->phy_init)
|
||||
pdata->phy_init(pdev, S5P_USB_PHY_HOST);
|
||||
|
||||
|
266
drivers/usb/host/ehci-sead3.c
Normal file
266
drivers/usb/host/ehci-sead3.c
Normal file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
* MIPS CI13320A EHCI Host Controller driver
|
||||
* Based on "ehci-au1xxx.c" by K.Boge <karsten.boge@amd.com>
|
||||
*
|
||||
* Copyright (C) 2012 MIPS Technologies, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
static int ehci_sead3_setup(struct usb_hcd *hcd)
|
||||
{
|
||||
int ret;
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
|
||||
ehci->caps = hcd->regs + 0x100;
|
||||
|
||||
ret = ehci_setup(hcd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ehci->need_io_watchdog = 0;
|
||||
|
||||
#ifdef __BIG_ENDIAN
|
||||
ehci->big_endian_mmio = 1;
|
||||
ehci->big_endian_desc = 1;
|
||||
#endif
|
||||
|
||||
/* Set burst length to 16 words. */
|
||||
ehci_writel(ehci, 0x1010, &ehci->regs->reserved[1]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct hc_driver ehci_sead3_hc_driver = {
|
||||
.description = hcd_name,
|
||||
.product_desc = "SEAD-3 EHCI",
|
||||
.hcd_priv_size = sizeof(struct ehci_hcd),
|
||||
|
||||
/*
|
||||
* generic hardware linkage
|
||||
*/
|
||||
.irq = ehci_irq,
|
||||
.flags = HCD_MEMORY | HCD_USB2,
|
||||
|
||||
/*
|
||||
* basic lifecycle operations
|
||||
*
|
||||
*/
|
||||
.reset = ehci_sead3_setup,
|
||||
.start = ehci_run,
|
||||
.stop = ehci_stop,
|
||||
.shutdown = ehci_shutdown,
|
||||
|
||||
/*
|
||||
* managing i/o requests and associated device resources
|
||||
*/
|
||||
.urb_enqueue = ehci_urb_enqueue,
|
||||
.urb_dequeue = ehci_urb_dequeue,
|
||||
.endpoint_disable = ehci_endpoint_disable,
|
||||
.endpoint_reset = ehci_endpoint_reset,
|
||||
|
||||
/*
|
||||
* scheduling support
|
||||
*/
|
||||
.get_frame_number = ehci_get_frame,
|
||||
|
||||
/*
|
||||
* root hub support
|
||||
*/
|
||||
.hub_status_data = ehci_hub_status_data,
|
||||
.hub_control = ehci_hub_control,
|
||||
.bus_suspend = ehci_bus_suspend,
|
||||
.bus_resume = ehci_bus_resume,
|
||||
.relinquish_port = ehci_relinquish_port,
|
||||
.port_handed_over = ehci_port_handed_over,
|
||||
|
||||
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
|
||||
};
|
||||
|
||||
static int ehci_hcd_sead3_drv_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct usb_hcd *hcd;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
if (usb_disabled())
|
||||
return -ENODEV;
|
||||
|
||||
if (pdev->resource[1].flags != IORESOURCE_IRQ) {
|
||||
pr_debug("resource[1] is not IORESOURCE_IRQ");
|
||||
return -ENOMEM;
|
||||
}
|
||||
hcd = usb_create_hcd(&ehci_sead3_hc_driver, &pdev->dev, "SEAD-3");
|
||||
if (!hcd)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
hcd->rsrc_start = res->start;
|
||||
hcd->rsrc_len = resource_size(res);
|
||||
|
||||
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
|
||||
pr_debug("request_mem_region failed");
|
||||
ret = -EBUSY;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
|
||||
if (!hcd->regs) {
|
||||
pr_debug("ioremap failed");
|
||||
ret = -ENOMEM;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
/* Root hub has integrated TT. */
|
||||
hcd->has_tt = 1;
|
||||
|
||||
ret = usb_add_hcd(hcd, pdev->resource[1].start,
|
||||
IRQF_SHARED);
|
||||
if (ret == 0) {
|
||||
platform_set_drvdata(pdev, hcd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
iounmap(hcd->regs);
|
||||
err2:
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
err1:
|
||||
usb_put_hcd(hcd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ehci_hcd_sead3_drv_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
|
||||
usb_remove_hcd(hcd);
|
||||
iounmap(hcd->regs);
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
usb_put_hcd(hcd);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int ehci_hcd_sead3_drv_suspend(struct device *dev)
|
||||
{
|
||||
struct usb_hcd *hcd = dev_get_drvdata(dev);
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
unsigned long flags;
|
||||
int rc = 0;
|
||||
|
||||
if (time_before(jiffies, ehci->next_statechange))
|
||||
msleep(20);
|
||||
|
||||
/* Root hub was already suspended. Disable irq emission and
|
||||
* mark HW unaccessible. The PM and USB cores make sure that
|
||||
* the root hub is either suspended or stopped.
|
||||
*/
|
||||
ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
|
||||
spin_lock_irqsave(&ehci->lock, flags);
|
||||
ehci_writel(ehci, 0, &ehci->regs->intr_enable);
|
||||
(void)ehci_readl(ehci, &ehci->regs->intr_enable);
|
||||
|
||||
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
||||
spin_unlock_irqrestore(&ehci->lock, flags);
|
||||
|
||||
/* could save FLADJ in case of Vaux power loss
|
||||
* ... we'd only use it to handle clock skew
|
||||
*/
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ehci_hcd_sead3_drv_resume(struct device *dev)
|
||||
{
|
||||
struct usb_hcd *hcd = dev_get_drvdata(dev);
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
|
||||
/* maybe restore FLADJ. */
|
||||
|
||||
if (time_before(jiffies, ehci->next_statechange))
|
||||
msleep(100);
|
||||
|
||||
/* Mark hardware accessible again as we are out of D3 state by now */
|
||||
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
||||
|
||||
/* If CF is still set, we maintained PCI Vaux power.
|
||||
* Just undo the effect of ehci_pci_suspend().
|
||||
*/
|
||||
if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
|
||||
int mask = INTR_MASK;
|
||||
|
||||
ehci_prepare_ports_for_controller_resume(ehci);
|
||||
if (!hcd->self.root_hub->do_remote_wakeup)
|
||||
mask &= ~STS_PCD;
|
||||
ehci_writel(ehci, mask, &ehci->regs->intr_enable);
|
||||
ehci_readl(ehci, &ehci->regs->intr_enable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ehci_dbg(ehci, "lost power, restarting\n");
|
||||
usb_root_hub_lost_power(hcd->self.root_hub);
|
||||
|
||||
/* Else reset, to cope with power loss or flush-to-storage
|
||||
* style "resume" having let BIOS kick in during reboot.
|
||||
*/
|
||||
(void) ehci_halt(ehci);
|
||||
(void) ehci_reset(ehci);
|
||||
|
||||
/* emptying the schedule aborts any urbs */
|
||||
spin_lock_irq(&ehci->lock);
|
||||
if (ehci->reclaim)
|
||||
end_unlink_async(ehci);
|
||||
ehci_work(ehci);
|
||||
spin_unlock_irq(&ehci->lock);
|
||||
|
||||
ehci_writel(ehci, ehci->command, &ehci->regs->command);
|
||||
ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
|
||||
ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
|
||||
|
||||
/* here we "know" root ports should always stay powered */
|
||||
ehci_port_power(ehci, 1);
|
||||
|
||||
ehci->rh_state = EHCI_RH_SUSPENDED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops sead3_ehci_pmops = {
|
||||
.suspend = ehci_hcd_sead3_drv_suspend,
|
||||
.resume = ehci_hcd_sead3_drv_resume,
|
||||
};
|
||||
|
||||
#define SEAD3_EHCI_PMOPS (&sead3_ehci_pmops)
|
||||
|
||||
#else
|
||||
#define SEAD3_EHCI_PMOPS NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver ehci_hcd_sead3_driver = {
|
||||
.probe = ehci_hcd_sead3_drv_probe,
|
||||
.remove = ehci_hcd_sead3_drv_remove,
|
||||
.shutdown = usb_hcd_platform_shutdown,
|
||||
.driver = {
|
||||
.name = "sead3-ehci",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = SEAD3_EHCI_PMOPS,
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_ALIAS("platform:sead3-ehci");
|
@ -11,6 +11,7 @@
|
||||
*/
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/platform_data/ehci-sh.h>
|
||||
|
||||
struct ehci_sh_priv {
|
||||
struct clk *iclk, *fclk;
|
||||
@ -100,6 +101,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
|
||||
const struct hc_driver *driver = &ehci_sh_hc_driver;
|
||||
struct resource *res;
|
||||
struct ehci_sh_priv *priv;
|
||||
struct ehci_sh_platdata *pdata;
|
||||
struct usb_hcd *hcd;
|
||||
int irq, ret;
|
||||
|
||||
@ -124,6 +126,9 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
|
||||
goto fail_create_hcd;
|
||||
}
|
||||
|
||||
if (pdev->dev.platform_data != NULL)
|
||||
pdata = pdev->dev.platform_data;
|
||||
|
||||
/* initialize hcd */
|
||||
hcd = usb_create_hcd(&ehci_sh_hc_driver, &pdev->dev,
|
||||
dev_name(&pdev->dev));
|
||||
@ -168,6 +173,9 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
|
||||
clk_enable(priv->fclk);
|
||||
clk_enable(priv->iclk);
|
||||
|
||||
if (pdata && pdata->phy_init)
|
||||
pdata->phy_init();
|
||||
|
||||
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "Failed to add hcd");
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
@ -25,12 +26,12 @@ struct spear_ehci {
|
||||
|
||||
static void spear_start_ehci(struct spear_ehci *ehci)
|
||||
{
|
||||
clk_enable(ehci->clk);
|
||||
clk_prepare_enable(ehci->clk);
|
||||
}
|
||||
|
||||
static void spear_stop_ehci(struct spear_ehci *ehci)
|
||||
{
|
||||
clk_disable(ehci->clk);
|
||||
clk_disable_unprepare(ehci->clk);
|
||||
}
|
||||
|
||||
static int ehci_spear_setup(struct usb_hcd *hcd)
|
||||
@ -168,6 +169,8 @@ static int ehci_spear_drv_resume(struct device *dev)
|
||||
static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend,
|
||||
ehci_spear_drv_resume);
|
||||
|
||||
static u64 spear_ehci_dma_mask = DMA_BIT_MASK(32);
|
||||
|
||||
static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct usb_hcd *hcd ;
|
||||
@ -175,12 +178,9 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
|
||||
struct resource *res;
|
||||
struct clk *usbh_clk;
|
||||
const struct hc_driver *driver = &ehci_spear_hc_driver;
|
||||
int *pdata = pdev->dev.platform_data;
|
||||
int irq, retval;
|
||||
char clk_name[20] = "usbh_clk";
|
||||
|
||||
if (pdata == NULL)
|
||||
return -EFAULT;
|
||||
static int instance = -1;
|
||||
|
||||
if (usb_disabled())
|
||||
return -ENODEV;
|
||||
@ -191,8 +191,22 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
|
||||
goto fail_irq_get;
|
||||
}
|
||||
|
||||
if (*pdata >= 0)
|
||||
sprintf(clk_name, "usbh.%01d_clk", *pdata);
|
||||
/*
|
||||
* Right now device-tree probed devices don't get dma_mask set.
|
||||
* Since shared usb code relies on it, set it here for now.
|
||||
* Once we have dma capability bindings this can go away.
|
||||
*/
|
||||
if (!pdev->dev.dma_mask)
|
||||
pdev->dev.dma_mask = &spear_ehci_dma_mask;
|
||||
|
||||
/*
|
||||
* Increment the device instance, when probing via device-tree
|
||||
*/
|
||||
if (pdev->id < 0)
|
||||
instance++;
|
||||
else
|
||||
instance = pdev->id;
|
||||
sprintf(clk_name, "usbh.%01d_clk", instance);
|
||||
|
||||
usbh_clk = clk_get(NULL, clk_name);
|
||||
if (IS_ERR(usbh_clk)) {
|
||||
@ -277,6 +291,11 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id spear_ehci_id_table[] __devinitdata = {
|
||||
{ .compatible = "st,spear600-ehci", },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver spear_ehci_hcd_driver = {
|
||||
.probe = spear_ehci_hcd_drv_probe,
|
||||
.remove = spear_ehci_hcd_drv_remove,
|
||||
@ -285,6 +304,7 @@ static struct platform_driver spear_ehci_hcd_driver = {
|
||||
.name = "spear-ehci",
|
||||
.bus = &platform_bus_type,
|
||||
.pm = &ehci_spear_pm_ops,
|
||||
.of_match_table = of_match_ptr(spear_ehci_id_table),
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -148,18 +148,7 @@ static int tegra_ehci_hub_control(
|
||||
|
||||
spin_lock_irqsave(&ehci->lock, flags);
|
||||
|
||||
/*
|
||||
* In ehci_hub_control() for USB_PORT_FEAT_ENABLE clears the other bits
|
||||
* that are write on clear, by writing back the register read value, so
|
||||
* USB_PORT_FEAT_ENABLE is handled by masking the set on clear bits
|
||||
*/
|
||||
if (typeReq == ClearPortFeature && wValue == USB_PORT_FEAT_ENABLE) {
|
||||
temp = ehci_readl(ehci, status_reg) & ~PORT_RWC_BITS;
|
||||
ehci_writel(ehci, temp & ~PORT_PE, status_reg);
|
||||
goto done;
|
||||
}
|
||||
|
||||
else if (typeReq == GetPortStatus) {
|
||||
if (typeReq == GetPortStatus) {
|
||||
temp = ehci_readl(ehci, status_reg);
|
||||
if (tegra->port_resuming && !(temp & PORT_SUSPEND)) {
|
||||
/* Resume completed, re-enable disconnect detection */
|
||||
@ -464,26 +453,23 @@ static int tegra_ehci_bus_resume(struct usb_hcd *hcd)
|
||||
}
|
||||
#endif
|
||||
|
||||
struct temp_buffer {
|
||||
struct dma_aligned_buffer {
|
||||
void *kmalloc_ptr;
|
||||
void *old_xfer_buffer;
|
||||
u8 data[0];
|
||||
};
|
||||
|
||||
static void free_temp_buffer(struct urb *urb)
|
||||
static void free_dma_aligned_buffer(struct urb *urb)
|
||||
{
|
||||
enum dma_data_direction dir;
|
||||
struct temp_buffer *temp;
|
||||
struct dma_aligned_buffer *temp;
|
||||
|
||||
if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
|
||||
return;
|
||||
|
||||
dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
|
||||
temp = container_of(urb->transfer_buffer,
|
||||
struct dma_aligned_buffer, data);
|
||||
|
||||
temp = container_of(urb->transfer_buffer, struct temp_buffer,
|
||||
data);
|
||||
|
||||
if (dir == DMA_FROM_DEVICE)
|
||||
if (usb_urb_dir_in(urb))
|
||||
memcpy(temp->old_xfer_buffer, temp->data,
|
||||
urb->transfer_buffer_length);
|
||||
urb->transfer_buffer = temp->old_xfer_buffer;
|
||||
@ -492,10 +478,9 @@ static void free_temp_buffer(struct urb *urb)
|
||||
urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
|
||||
}
|
||||
|
||||
static int alloc_temp_buffer(struct urb *urb, gfp_t mem_flags)
|
||||
static int alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags)
|
||||
{
|
||||
enum dma_data_direction dir;
|
||||
struct temp_buffer *temp, *kmalloc_ptr;
|
||||
struct dma_aligned_buffer *temp, *kmalloc_ptr;
|
||||
size_t kmalloc_size;
|
||||
|
||||
if (urb->num_sgs || urb->sg ||
|
||||
@ -503,22 +488,19 @@ static int alloc_temp_buffer(struct urb *urb, gfp_t mem_flags)
|
||||
!((uintptr_t)urb->transfer_buffer & (TEGRA_USB_DMA_ALIGN - 1)))
|
||||
return 0;
|
||||
|
||||
dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
|
||||
|
||||
/* Allocate a buffer with enough padding for alignment */
|
||||
kmalloc_size = urb->transfer_buffer_length +
|
||||
sizeof(struct temp_buffer) + TEGRA_USB_DMA_ALIGN - 1;
|
||||
sizeof(struct dma_aligned_buffer) + TEGRA_USB_DMA_ALIGN - 1;
|
||||
|
||||
kmalloc_ptr = kmalloc(kmalloc_size, mem_flags);
|
||||
if (!kmalloc_ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Position our struct temp_buffer such that data is aligned */
|
||||
/* Position our struct dma_aligned_buffer such that data is aligned */
|
||||
temp = PTR_ALIGN(kmalloc_ptr + 1, TEGRA_USB_DMA_ALIGN) - 1;
|
||||
|
||||
temp->kmalloc_ptr = kmalloc_ptr;
|
||||
temp->old_xfer_buffer = urb->transfer_buffer;
|
||||
if (dir == DMA_TO_DEVICE)
|
||||
if (usb_urb_dir_out(urb))
|
||||
memcpy(temp->data, urb->transfer_buffer,
|
||||
urb->transfer_buffer_length);
|
||||
urb->transfer_buffer = temp->data;
|
||||
@ -533,13 +515,13 @@ static int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = alloc_temp_buffer(urb, mem_flags);
|
||||
ret = alloc_dma_aligned_buffer(urb, mem_flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
|
||||
if (ret)
|
||||
free_temp_buffer(urb);
|
||||
free_dma_aligned_buffer(urb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -547,38 +529,39 @@ static int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
|
||||
static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
|
||||
{
|
||||
usb_hcd_unmap_urb_for_dma(hcd, urb);
|
||||
free_temp_buffer(urb);
|
||||
free_dma_aligned_buffer(urb);
|
||||
}
|
||||
|
||||
static const struct hc_driver tegra_ehci_hc_driver = {
|
||||
.description = hcd_name,
|
||||
.product_desc = "Tegra EHCI Host Controller",
|
||||
.hcd_priv_size = sizeof(struct ehci_hcd),
|
||||
|
||||
.flags = HCD_USB2 | HCD_MEMORY,
|
||||
|
||||
.reset = tegra_ehci_setup,
|
||||
/* standard ehci functions */
|
||||
.irq = ehci_irq,
|
||||
|
||||
.start = ehci_run,
|
||||
.stop = ehci_stop,
|
||||
.shutdown = tegra_ehci_shutdown,
|
||||
.urb_enqueue = ehci_urb_enqueue,
|
||||
.urb_dequeue = ehci_urb_dequeue,
|
||||
.map_urb_for_dma = tegra_ehci_map_urb_for_dma,
|
||||
.unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma,
|
||||
.endpoint_disable = ehci_endpoint_disable,
|
||||
.endpoint_reset = ehci_endpoint_reset,
|
||||
.get_frame_number = ehci_get_frame,
|
||||
.hub_status_data = ehci_hub_status_data,
|
||||
.hub_control = tegra_ehci_hub_control,
|
||||
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
|
||||
.relinquish_port = ehci_relinquish_port,
|
||||
.port_handed_over = ehci_port_handed_over,
|
||||
|
||||
/* modified ehci functions for tegra */
|
||||
.reset = tegra_ehci_setup,
|
||||
.shutdown = tegra_ehci_shutdown,
|
||||
.map_urb_for_dma = tegra_ehci_map_urb_for_dma,
|
||||
.unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma,
|
||||
.hub_control = tegra_ehci_hub_control,
|
||||
#ifdef CONFIG_PM
|
||||
.bus_suspend = tegra_ehci_bus_suspend,
|
||||
.bus_resume = tegra_ehci_bus_resume,
|
||||
#endif
|
||||
.relinquish_port = ehci_relinquish_port,
|
||||
.port_handed_over = ehci_port_handed_over,
|
||||
};
|
||||
|
||||
static int setup_vbus_gpio(struct platform_device *pdev)
|
||||
|
@ -155,7 +155,7 @@ u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem,
|
||||
struct endpoint *ep;
|
||||
struct usb_td __iomem *td;
|
||||
unsigned long ep_offset;
|
||||
char *err_for = "enpoint PRAM";
|
||||
char *err_for = "endpoint PRAM";
|
||||
int ep_mem_size;
|
||||
u32 i;
|
||||
|
||||
|
@ -119,6 +119,39 @@ struct platform_device * __devinit fsl_usb2_device_register(
|
||||
|
||||
static const struct of_device_id fsl_usb2_mph_dr_of_match[];
|
||||
|
||||
static int usb_get_ver_info(struct device_node *np)
|
||||
{
|
||||
int ver = -1;
|
||||
|
||||
/*
|
||||
* returns 1 for usb controller version 1.6
|
||||
* returns 2 for usb controller version 2.2
|
||||
* returns 0 otherwise
|
||||
*/
|
||||
if (of_device_is_compatible(np, "fsl-usb2-dr")) {
|
||||
if (of_device_is_compatible(np, "fsl-usb2-dr-v1.6"))
|
||||
ver = FSL_USB_VER_1_6;
|
||||
else if (of_device_is_compatible(np, "fsl-usb2-dr-v2.2"))
|
||||
ver = FSL_USB_VER_2_2;
|
||||
else /* for previous controller versions */
|
||||
ver = FSL_USB_VER_OLD;
|
||||
|
||||
if (ver > -1)
|
||||
return ver;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(np, "fsl-usb2-mph")) {
|
||||
if (of_device_is_compatible(np, "fsl-usb2-mph-v1.6"))
|
||||
ver = FSL_USB_VER_1_6;
|
||||
else if (of_device_is_compatible(np, "fsl-usb2-mph-v2.2"))
|
||||
ver = FSL_USB_VER_2_2;
|
||||
else /* for previous controller versions */
|
||||
ver = FSL_USB_VER_OLD;
|
||||
}
|
||||
|
||||
return ver;
|
||||
}
|
||||
|
||||
static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
|
||||
{
|
||||
struct device_node *np = ofdev->dev.of_node;
|
||||
@ -166,6 +199,14 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
|
||||
|
||||
prop = of_get_property(np, "phy_type", NULL);
|
||||
pdata->phy_mode = determine_usb_phy(prop);
|
||||
pdata->controller_ver = usb_get_ver_info(np);
|
||||
|
||||
if (pdata->have_sysif_regs) {
|
||||
if (pdata->controller_ver < 0) {
|
||||
dev_warn(&ofdev->dev, "Could not get controller version\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev_data->drivers); i++) {
|
||||
if (!dev_data->drivers[i])
|
||||
|
@ -1562,11 +1562,14 @@ static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
|
||||
|
||||
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
|
||||
retval = -ESHUTDOWN;
|
||||
qtd_list_free(&new_qtds);
|
||||
goto out;
|
||||
}
|
||||
retval = usb_hcd_link_urb_to_ep(hcd, urb);
|
||||
if (retval)
|
||||
if (retval) {
|
||||
qtd_list_free(&new_qtds);
|
||||
goto out;
|
||||
}
|
||||
|
||||
qh = urb->ep->hcpriv;
|
||||
if (qh) {
|
||||
@ -1584,6 +1587,7 @@ static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
|
||||
if (!qh) {
|
||||
retval = -ENOMEM;
|
||||
usb_hcd_unlink_urb_from_ep(hcd, urb);
|
||||
qtd_list_free(&new_qtds);
|
||||
goto out;
|
||||
}
|
||||
list_add_tail(&qh->qh_list, ep_queue);
|
||||
@ -1683,6 +1687,7 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
|
||||
list_for_each_entry(qtd, &qh->qtd_list, qtd_list)
|
||||
if (qtd->urb == urb) {
|
||||
dequeue_urb_from_qtd(hcd, qh, qtd);
|
||||
list_move(&qtd->qtd_list, &qh->qtd_list);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2176,7 +2181,7 @@ static const struct hc_driver isp1760_hc_driver = {
|
||||
|
||||
int __init init_kmem_once(void)
|
||||
{
|
||||
urb_listitem_cachep = kmem_cache_create("isp1760 urb_listitem",
|
||||
urb_listitem_cachep = kmem_cache_create("isp1760_urb_listitem",
|
||||
sizeof(struct urb_listitem), 0, SLAB_TEMPORARY |
|
||||
SLAB_MEM_SPREAD, NULL);
|
||||
|
||||
|
@ -398,6 +398,9 @@ static int __devinit isp1760_plat_probe(struct platform_device *pdev)
|
||||
hcd = isp1760_register(mem_res->start, mem_size, irq_res->start,
|
||||
irqflags, -ENOENT,
|
||||
&pdev->dev, dev_name(&pdev->dev), devflags);
|
||||
|
||||
dev_set_drvdata(&pdev->dev, hcd);
|
||||
|
||||
if (IS_ERR(hcd)) {
|
||||
pr_warning("isp1760: Failed to register the HCD device\n");
|
||||
ret = -ENODEV;
|
||||
@ -417,11 +420,16 @@ static int __devexit isp1760_plat_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *mem_res;
|
||||
resource_size_t mem_size;
|
||||
struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
usb_remove_hcd(hcd);
|
||||
|
||||
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
mem_size = resource_size(mem_res);
|
||||
release_mem_region(mem_res->start, mem_size);
|
||||
|
||||
usb_put_hcd(hcd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1080,11 +1080,6 @@ MODULE_LICENSE ("GPL");
|
||||
#define PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_OHCI_HCD_SSB
|
||||
#include "ohci-ssb.c"
|
||||
#define SSB_OHCI_DRIVER ssb_ohci_driver
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MFD_SM501
|
||||
#include "ohci-sm501.c"
|
||||
#define SM501_OHCI_DRIVER ohci_hcd_sm501_driver
|
||||
@ -1128,8 +1123,7 @@ MODULE_LICENSE ("GPL");
|
||||
!defined(SA1111_DRIVER) && \
|
||||
!defined(PS3_SYSTEM_BUS_DRIVER) && \
|
||||
!defined(SM501_OHCI_DRIVER) && \
|
||||
!defined(TMIO_OHCI_DRIVER) && \
|
||||
!defined(SSB_OHCI_DRIVER)
|
||||
!defined(TMIO_OHCI_DRIVER)
|
||||
#error "missing bus glue for ohci-hcd"
|
||||
#endif
|
||||
|
||||
@ -1195,12 +1189,6 @@ static int __init ohci_hcd_mod_init(void)
|
||||
goto error_pci;
|
||||
#endif
|
||||
|
||||
#ifdef SSB_OHCI_DRIVER
|
||||
retval = ssb_driver_register(&SSB_OHCI_DRIVER);
|
||||
if (retval)
|
||||
goto error_ssb;
|
||||
#endif
|
||||
|
||||
#ifdef SM501_OHCI_DRIVER
|
||||
retval = platform_driver_register(&SM501_OHCI_DRIVER);
|
||||
if (retval < 0)
|
||||
@ -1224,10 +1212,6 @@ static int __init ohci_hcd_mod_init(void)
|
||||
platform_driver_unregister(&SM501_OHCI_DRIVER);
|
||||
error_sm501:
|
||||
#endif
|
||||
#ifdef SSB_OHCI_DRIVER
|
||||
ssb_driver_unregister(&SSB_OHCI_DRIVER);
|
||||
error_ssb:
|
||||
#endif
|
||||
#ifdef PCI_DRIVER
|
||||
pci_unregister_driver(&PCI_DRIVER);
|
||||
error_pci:
|
||||
@ -1275,9 +1259,6 @@ static void __exit ohci_hcd_mod_exit(void)
|
||||
#ifdef SM501_OHCI_DRIVER
|
||||
platform_driver_unregister(&SM501_OHCI_DRIVER);
|
||||
#endif
|
||||
#ifdef SSB_OHCI_DRIVER
|
||||
ssb_driver_unregister(&SSB_OHCI_DRIVER);
|
||||
#endif
|
||||
#ifdef PCI_DRIVER
|
||||
pci_unregister_driver(&PCI_DRIVER);
|
||||
#endif
|
||||
|
@ -93,13 +93,13 @@ static int __devinit ohci_platform_probe(struct platform_device *dev)
|
||||
|
||||
irq = platform_get_irq(dev, 0);
|
||||
if (irq < 0) {
|
||||
pr_err("no irq provieded");
|
||||
pr_err("no irq provided");
|
||||
return irq;
|
||||
}
|
||||
|
||||
res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
|
||||
if (!res_mem) {
|
||||
pr_err("no memory recourse provieded");
|
||||
pr_err("no memory recourse provided");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
|
@ -236,7 +236,7 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match);
|
||||
|
||||
#if !defined(CONFIG_USB_OHCI_HCD_PPC_OF_BE) && \
|
||||
!defined(CONFIG_USB_OHCI_HCD_PPC_OF_LE)
|
||||
#error "No endianess selected for ppc-of-ohci"
|
||||
#error "No endianness selected for ppc-of-ohci"
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/signal.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
struct spear_ohci {
|
||||
struct ohci_hcd ohci;
|
||||
@ -24,12 +25,12 @@ struct spear_ohci {
|
||||
|
||||
static void spear_start_ohci(struct spear_ohci *ohci)
|
||||
{
|
||||
clk_enable(ohci->clk);
|
||||
clk_prepare_enable(ohci->clk);
|
||||
}
|
||||
|
||||
static void spear_stop_ohci(struct spear_ohci *ohci)
|
||||
{
|
||||
clk_disable(ohci->clk);
|
||||
clk_disable_unprepare(ohci->clk);
|
||||
}
|
||||
|
||||
static int __devinit ohci_spear_start(struct usb_hcd *hcd)
|
||||
@ -90,6 +91,8 @@ static const struct hc_driver ohci_spear_hc_driver = {
|
||||
.start_port_reset = ohci_start_port_reset,
|
||||
};
|
||||
|
||||
static u64 spear_ohci_dma_mask = DMA_BIT_MASK(32);
|
||||
|
||||
static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct hc_driver *driver = &ohci_spear_hc_driver;
|
||||
@ -98,11 +101,8 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
|
||||
struct spear_ohci *ohci_p;
|
||||
struct resource *res;
|
||||
int retval, irq;
|
||||
int *pdata = pdev->dev.platform_data;
|
||||
char clk_name[20] = "usbh_clk";
|
||||
|
||||
if (pdata == NULL)
|
||||
return -EFAULT;
|
||||
static int instance = -1;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
@ -110,8 +110,22 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
|
||||
goto fail_irq_get;
|
||||
}
|
||||
|
||||
if (*pdata >= 0)
|
||||
sprintf(clk_name, "usbh.%01d_clk", *pdata);
|
||||
/*
|
||||
* Right now device-tree probed devices don't get dma_mask set.
|
||||
* Since shared usb code relies on it, set it here for now.
|
||||
* Once we have dma capability bindings this can go away.
|
||||
*/
|
||||
if (!pdev->dev.dma_mask)
|
||||
pdev->dev.dma_mask = &spear_ohci_dma_mask;
|
||||
|
||||
/*
|
||||
* Increment the device instance, when probing via device-tree
|
||||
*/
|
||||
if (pdev->id < 0)
|
||||
instance++;
|
||||
else
|
||||
instance = pdev->id;
|
||||
sprintf(clk_name, "usbh.%01d_clk", instance);
|
||||
|
||||
usbh_clk = clk_get(NULL, clk_name);
|
||||
if (IS_ERR(usbh_clk)) {
|
||||
@ -222,6 +236,11 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct of_device_id spear_ohci_id_table[] __devinitdata = {
|
||||
{ .compatible = "st,spear600-ohci", },
|
||||
{ },
|
||||
};
|
||||
|
||||
/* Driver definition to register with the platform bus */
|
||||
static struct platform_driver spear_ohci_hcd_driver = {
|
||||
.probe = spear_ohci_hcd_drv_probe,
|
||||
@ -233,6 +252,7 @@ static struct platform_driver spear_ohci_hcd_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "spear-ohci",
|
||||
.of_match_table = of_match_ptr(spear_ohci_id_table),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1,260 +0,0 @@
|
||||
/*
|
||||
* Sonics Silicon Backplane
|
||||
* Broadcom USB-core OHCI driver
|
||||
*
|
||||
* Copyright 2007 Michael Buesch <m@bues.ch>
|
||||
*
|
||||
* Derived from the OHCI-PCI driver
|
||||
* Copyright 1999 Roman Weissgaerber
|
||||
* Copyright 2000-2002 David Brownell
|
||||
* Copyright 1999 Linus Torvalds
|
||||
* Copyright 1999 Gregory P. Smith
|
||||
*
|
||||
* Derived from the USBcore related parts of Broadcom-SB
|
||||
* Copyright 2005 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
#include <linux/ssb/ssb.h>
|
||||
|
||||
|
||||
#define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
|
||||
|
||||
struct ssb_ohci_device {
|
||||
struct ohci_hcd ohci; /* _must_ be at the beginning. */
|
||||
|
||||
u32 enable_flags;
|
||||
};
|
||||
|
||||
static inline
|
||||
struct ssb_ohci_device *hcd_to_ssb_ohci(struct usb_hcd *hcd)
|
||||
{
|
||||
return (struct ssb_ohci_device *)(hcd->hcd_priv);
|
||||
}
|
||||
|
||||
|
||||
static int ssb_ohci_reset(struct usb_hcd *hcd)
|
||||
{
|
||||
struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
|
||||
struct ohci_hcd *ohci = &ohcidev->ohci;
|
||||
int err;
|
||||
|
||||
ohci_hcd_init(ohci);
|
||||
err = ohci_init(ohci);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ssb_ohci_start(struct usb_hcd *hcd)
|
||||
{
|
||||
struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
|
||||
struct ohci_hcd *ohci = &ohcidev->ohci;
|
||||
int err;
|
||||
|
||||
err = ohci_run(ohci);
|
||||
if (err < 0) {
|
||||
ohci_err(ohci, "can't start\n");
|
||||
ohci_stop(hcd);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct hc_driver ssb_ohci_hc_driver = {
|
||||
.description = "ssb-usb-ohci",
|
||||
.product_desc = "SSB OHCI Controller",
|
||||
.hcd_priv_size = sizeof(struct ssb_ohci_device),
|
||||
|
||||
.irq = ohci_irq,
|
||||
.flags = HCD_MEMORY | HCD_USB11,
|
||||
|
||||
.reset = ssb_ohci_reset,
|
||||
.start = ssb_ohci_start,
|
||||
.stop = ohci_stop,
|
||||
.shutdown = ohci_shutdown,
|
||||
|
||||
.urb_enqueue = ohci_urb_enqueue,
|
||||
.urb_dequeue = ohci_urb_dequeue,
|
||||
.endpoint_disable = ohci_endpoint_disable,
|
||||
|
||||
.get_frame_number = ohci_get_frame,
|
||||
|
||||
.hub_status_data = ohci_hub_status_data,
|
||||
.hub_control = ohci_hub_control,
|
||||
#ifdef CONFIG_PM
|
||||
.bus_suspend = ohci_bus_suspend,
|
||||
.bus_resume = ohci_bus_resume,
|
||||
#endif
|
||||
|
||||
.start_port_reset = ohci_start_port_reset,
|
||||
};
|
||||
|
||||
static void ssb_ohci_detach(struct ssb_device *dev)
|
||||
{
|
||||
struct usb_hcd *hcd = ssb_get_drvdata(dev);
|
||||
|
||||
if (hcd->driver->shutdown)
|
||||
hcd->driver->shutdown(hcd);
|
||||
usb_remove_hcd(hcd);
|
||||
iounmap(hcd->regs);
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
usb_put_hcd(hcd);
|
||||
ssb_device_disable(dev, 0);
|
||||
}
|
||||
|
||||
static int ssb_ohci_attach(struct ssb_device *dev)
|
||||
{
|
||||
struct ssb_ohci_device *ohcidev;
|
||||
struct usb_hcd *hcd;
|
||||
int err = -ENOMEM;
|
||||
u32 tmp, flags = 0;
|
||||
|
||||
if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
|
||||
dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
|
||||
/* Put the device into host-mode. */
|
||||
flags |= SSB_OHCI_TMSLOW_HOSTMODE;
|
||||
ssb_device_enable(dev, flags);
|
||||
} else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
|
||||
/*
|
||||
* USB 2.0 special considerations:
|
||||
*
|
||||
* In addition to the standard SSB reset sequence, the Host
|
||||
* Control Register must be programmed to bring the USB core
|
||||
* and various phy components out of reset.
|
||||
*/
|
||||
ssb_device_enable(dev, 0);
|
||||
ssb_write32(dev, 0x200, 0x7ff);
|
||||
|
||||
/* Change Flush control reg */
|
||||
tmp = ssb_read32(dev, 0x400);
|
||||
tmp &= ~8;
|
||||
ssb_write32(dev, 0x400, tmp);
|
||||
tmp = ssb_read32(dev, 0x400);
|
||||
|
||||
/* Change Shim control reg */
|
||||
tmp = ssb_read32(dev, 0x304);
|
||||
tmp &= ~0x100;
|
||||
ssb_write32(dev, 0x304, tmp);
|
||||
tmp = ssb_read32(dev, 0x304);
|
||||
|
||||
udelay(1);
|
||||
|
||||
/* Work around for 5354 failures */
|
||||
if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) {
|
||||
/* Change syn01 reg */
|
||||
tmp = 0x00fe00fe;
|
||||
ssb_write32(dev, 0x894, tmp);
|
||||
|
||||
/* Change syn03 reg */
|
||||
tmp = ssb_read32(dev, 0x89c);
|
||||
tmp |= 0x1;
|
||||
ssb_write32(dev, 0x89c, tmp);
|
||||
}
|
||||
} else
|
||||
ssb_device_enable(dev, 0);
|
||||
|
||||
hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
|
||||
dev_name(dev->dev));
|
||||
if (!hcd)
|
||||
goto err_dev_disable;
|
||||
ohcidev = hcd_to_ssb_ohci(hcd);
|
||||
ohcidev->enable_flags = flags;
|
||||
|
||||
tmp = ssb_read32(dev, SSB_ADMATCH0);
|
||||
hcd->rsrc_start = ssb_admatch_base(tmp);
|
||||
hcd->rsrc_len = ssb_admatch_size(tmp);
|
||||
hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
|
||||
if (!hcd->regs)
|
||||
goto err_put_hcd;
|
||||
err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED);
|
||||
if (err)
|
||||
goto err_iounmap;
|
||||
|
||||
ssb_set_drvdata(dev, hcd);
|
||||
|
||||
return err;
|
||||
|
||||
err_iounmap:
|
||||
iounmap(hcd->regs);
|
||||
err_put_hcd:
|
||||
usb_put_hcd(hcd);
|
||||
err_dev_disable:
|
||||
ssb_device_disable(dev, flags);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ssb_ohci_probe(struct ssb_device *dev,
|
||||
const struct ssb_device_id *id)
|
||||
{
|
||||
int err;
|
||||
u16 chipid_top;
|
||||
|
||||
/* USBcores are only connected on embedded devices. */
|
||||
chipid_top = (dev->bus->chip_id & 0xFF00);
|
||||
if (chipid_top != 0x4700 && chipid_top != 0x5300)
|
||||
return -ENODEV;
|
||||
|
||||
/* TODO: Probably need checks here; is the core connected? */
|
||||
|
||||
if (usb_disabled())
|
||||
return -ENODEV;
|
||||
|
||||
/* We currently always attach SSB_DEV_USB11_HOSTDEV
|
||||
* as HOST OHCI. If we want to attach it as Client device,
|
||||
* we must branch here and call into the (yet to
|
||||
* be written) Client mode driver. Same for remove(). */
|
||||
|
||||
err = ssb_ohci_attach(dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ssb_ohci_remove(struct ssb_device *dev)
|
||||
{
|
||||
ssb_ohci_detach(dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int ssb_ohci_suspend(struct ssb_device *dev, pm_message_t state)
|
||||
{
|
||||
ssb_device_disable(dev, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssb_ohci_resume(struct ssb_device *dev)
|
||||
{
|
||||
struct usb_hcd *hcd = ssb_get_drvdata(dev);
|
||||
struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
|
||||
|
||||
ssb_device_enable(dev, ohcidev->enable_flags);
|
||||
|
||||
ohci_finish_controller_resume(hcd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !CONFIG_PM */
|
||||
#define ssb_ohci_suspend NULL
|
||||
#define ssb_ohci_resume NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static const struct ssb_device_id ssb_ohci_table[] = {
|
||||
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
|
||||
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
|
||||
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
|
||||
SSB_DEVTABLE_END
|
||||
};
|
||||
MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);
|
||||
|
||||
static struct ssb_driver ssb_ohci_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = ssb_ohci_table,
|
||||
.probe = ssb_ohci_probe,
|
||||
.remove = ssb_ohci_remove,
|
||||
.suspend = ssb_ohci_suspend,
|
||||
.resume = ssb_ohci_resume,
|
||||
};
|
@ -2991,8 +2991,9 @@ static int oxu_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
||||
/* shouldn't happen often, but ...
|
||||
* FIXME kill those tds' urbs
|
||||
*/
|
||||
err("can't reschedule qh %p, err %d",
|
||||
qh, status);
|
||||
dev_err(hcd->self.controller,
|
||||
"can't reschedule qh %p, err %d\n", qh,
|
||||
status);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
279
drivers/usb/host/ssb-hcd.c
Normal file
279
drivers/usb/host/ssb-hcd.c
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Sonics Silicon Backplane
|
||||
* Broadcom USB-core driver (SSB bus glue)
|
||||
*
|
||||
* Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
|
||||
*
|
||||
* Based on ssb-ohci driver
|
||||
* Copyright 2007 Michael Buesch <m@bues.ch>
|
||||
*
|
||||
* Derived from the OHCI-PCI driver
|
||||
* Copyright 1999 Roman Weissgaerber
|
||||
* Copyright 2000-2002 David Brownell
|
||||
* Copyright 1999 Linus Torvalds
|
||||
* Copyright 1999 Gregory P. Smith
|
||||
*
|
||||
* Derived from the USBcore related parts of Broadcom-SB
|
||||
* Copyright 2005-2011 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
#include <linux/ssb/ssb.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb/ehci_pdriver.h>
|
||||
#include <linux/usb/ohci_pdriver.h>
|
||||
|
||||
MODULE_AUTHOR("Hauke Mehrtens");
|
||||
MODULE_DESCRIPTION("Common USB driver for SSB Bus");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#define SSB_HCD_TMSLOW_HOSTMODE (1 << 29)
|
||||
|
||||
struct ssb_hcd_device {
|
||||
struct platform_device *ehci_dev;
|
||||
struct platform_device *ohci_dev;
|
||||
|
||||
u32 enable_flags;
|
||||
};
|
||||
|
||||
static void __devinit ssb_hcd_5354wa(struct ssb_device *dev)
|
||||
{
|
||||
#ifdef CONFIG_SSB_DRIVER_MIPS
|
||||
/* Work around for 5354 failures */
|
||||
if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) {
|
||||
/* Change syn01 reg */
|
||||
ssb_write32(dev, 0x894, 0x00fe00fe);
|
||||
|
||||
/* Change syn03 reg */
|
||||
ssb_write32(dev, 0x89c, ssb_read32(dev, 0x89c) | 0x1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __devinit ssb_hcd_usb20wa(struct ssb_device *dev)
|
||||
{
|
||||
if (dev->id.coreid == SSB_DEV_USB20_HOST) {
|
||||
/*
|
||||
* USB 2.0 special considerations:
|
||||
*
|
||||
* In addition to the standard SSB reset sequence, the Host
|
||||
* Control Register must be programmed to bring the USB core
|
||||
* and various phy components out of reset.
|
||||
*/
|
||||
ssb_write32(dev, 0x200, 0x7ff);
|
||||
|
||||
/* Change Flush control reg */
|
||||
ssb_write32(dev, 0x400, ssb_read32(dev, 0x400) & ~8);
|
||||
ssb_read32(dev, 0x400);
|
||||
|
||||
/* Change Shim control reg */
|
||||
ssb_write32(dev, 0x304, ssb_read32(dev, 0x304) & ~0x100);
|
||||
ssb_read32(dev, 0x304);
|
||||
|
||||
udelay(1);
|
||||
|
||||
ssb_hcd_5354wa(dev);
|
||||
}
|
||||
}
|
||||
|
||||
/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
|
||||
static u32 __devinit ssb_hcd_init_chip(struct ssb_device *dev)
|
||||
{
|
||||
u32 flags = 0;
|
||||
|
||||
if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV)
|
||||
/* Put the device into host-mode. */
|
||||
flags |= SSB_HCD_TMSLOW_HOSTMODE;
|
||||
|
||||
ssb_device_enable(dev, flags);
|
||||
|
||||
ssb_hcd_usb20wa(dev);
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static const struct usb_ehci_pdata ehci_pdata = {
|
||||
};
|
||||
|
||||
static const struct usb_ohci_pdata ohci_pdata = {
|
||||
};
|
||||
|
||||
static struct platform_device * __devinit
|
||||
ssb_hcd_create_pdev(struct ssb_device *dev, bool ohci, u32 addr, u32 len)
|
||||
{
|
||||
struct platform_device *hci_dev;
|
||||
struct resource hci_res[2];
|
||||
int ret = -ENOMEM;
|
||||
|
||||
memset(hci_res, 0, sizeof(hci_res));
|
||||
|
||||
hci_res[0].start = addr;
|
||||
hci_res[0].end = hci_res[0].start + len - 1;
|
||||
hci_res[0].flags = IORESOURCE_MEM;
|
||||
|
||||
hci_res[1].start = dev->irq;
|
||||
hci_res[1].flags = IORESOURCE_IRQ;
|
||||
|
||||
hci_dev = platform_device_alloc(ohci ? "ohci-platform" :
|
||||
"ehci-platform" , 0);
|
||||
if (!hci_dev)
|
||||
return NULL;
|
||||
|
||||
hci_dev->dev.parent = dev->dev;
|
||||
hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask;
|
||||
|
||||
ret = platform_device_add_resources(hci_dev, hci_res,
|
||||
ARRAY_SIZE(hci_res));
|
||||
if (ret)
|
||||
goto err_alloc;
|
||||
if (ohci)
|
||||
ret = platform_device_add_data(hci_dev, &ohci_pdata,
|
||||
sizeof(ohci_pdata));
|
||||
else
|
||||
ret = platform_device_add_data(hci_dev, &ehci_pdata,
|
||||
sizeof(ehci_pdata));
|
||||
if (ret)
|
||||
goto err_alloc;
|
||||
ret = platform_device_add(hci_dev);
|
||||
if (ret)
|
||||
goto err_alloc;
|
||||
|
||||
return hci_dev;
|
||||
|
||||
err_alloc:
|
||||
platform_device_put(hci_dev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static int __devinit ssb_hcd_probe(struct ssb_device *dev,
|
||||
const struct ssb_device_id *id)
|
||||
{
|
||||
int err, tmp;
|
||||
int start, len;
|
||||
u16 chipid_top;
|
||||
u16 coreid = dev->id.coreid;
|
||||
struct ssb_hcd_device *usb_dev;
|
||||
|
||||
/* USBcores are only connected on embedded devices. */
|
||||
chipid_top = (dev->bus->chip_id & 0xFF00);
|
||||
if (chipid_top != 0x4700 && chipid_top != 0x5300)
|
||||
return -ENODEV;
|
||||
|
||||
/* TODO: Probably need checks here; is the core connected? */
|
||||
|
||||
if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
|
||||
dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
usb_dev = kzalloc(sizeof(struct ssb_hcd_device), GFP_KERNEL);
|
||||
if (!usb_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
/* We currently always attach SSB_DEV_USB11_HOSTDEV
|
||||
* as HOST OHCI. If we want to attach it as Client device,
|
||||
* we must branch here and call into the (yet to
|
||||
* be written) Client mode driver. Same for remove(). */
|
||||
usb_dev->enable_flags = ssb_hcd_init_chip(dev);
|
||||
|
||||
tmp = ssb_read32(dev, SSB_ADMATCH0);
|
||||
|
||||
start = ssb_admatch_base(tmp);
|
||||
len = (coreid == SSB_DEV_USB20_HOST) ? 0x800 : ssb_admatch_size(tmp);
|
||||
usb_dev->ohci_dev = ssb_hcd_create_pdev(dev, true, start, len);
|
||||
if (IS_ERR(usb_dev->ohci_dev)) {
|
||||
err = PTR_ERR(usb_dev->ohci_dev);
|
||||
goto err_free_usb_dev;
|
||||
}
|
||||
|
||||
if (coreid == SSB_DEV_USB20_HOST) {
|
||||
start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */
|
||||
usb_dev->ehci_dev = ssb_hcd_create_pdev(dev, false, start, len);
|
||||
if (IS_ERR(usb_dev->ehci_dev)) {
|
||||
err = PTR_ERR(usb_dev->ehci_dev);
|
||||
goto err_unregister_ohci_dev;
|
||||
}
|
||||
}
|
||||
|
||||
ssb_set_drvdata(dev, usb_dev);
|
||||
return 0;
|
||||
|
||||
err_unregister_ohci_dev:
|
||||
platform_device_unregister(usb_dev->ohci_dev);
|
||||
err_free_usb_dev:
|
||||
kfree(usb_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __devexit ssb_hcd_remove(struct ssb_device *dev)
|
||||
{
|
||||
struct ssb_hcd_device *usb_dev = ssb_get_drvdata(dev);
|
||||
struct platform_device *ohci_dev = usb_dev->ohci_dev;
|
||||
struct platform_device *ehci_dev = usb_dev->ehci_dev;
|
||||
|
||||
if (ohci_dev)
|
||||
platform_device_unregister(ohci_dev);
|
||||
if (ehci_dev)
|
||||
platform_device_unregister(ehci_dev);
|
||||
|
||||
ssb_device_disable(dev, 0);
|
||||
}
|
||||
|
||||
static void __devexit ssb_hcd_shutdown(struct ssb_device *dev)
|
||||
{
|
||||
ssb_device_disable(dev, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int ssb_hcd_suspend(struct ssb_device *dev, pm_message_t state)
|
||||
{
|
||||
ssb_device_disable(dev, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssb_hcd_resume(struct ssb_device *dev)
|
||||
{
|
||||
struct ssb_hcd_device *usb_dev = ssb_get_drvdata(dev);
|
||||
|
||||
ssb_device_enable(dev, usb_dev->enable_flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !CONFIG_PM */
|
||||
#define ssb_hcd_suspend NULL
|
||||
#define ssb_hcd_resume NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static const struct ssb_device_id ssb_hcd_table[] __devinitconst = {
|
||||
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
|
||||
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
|
||||
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
|
||||
SSB_DEVTABLE_END
|
||||
};
|
||||
MODULE_DEVICE_TABLE(ssb, ssb_hcd_table);
|
||||
|
||||
static struct ssb_driver ssb_hcd_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = ssb_hcd_table,
|
||||
.probe = ssb_hcd_probe,
|
||||
.remove = __devexit_p(ssb_hcd_remove),
|
||||
.shutdown = ssb_hcd_shutdown,
|
||||
.suspend = ssb_hcd_suspend,
|
||||
.resume = ssb_hcd_resume,
|
||||
};
|
||||
|
||||
static int __init ssb_hcd_init(void)
|
||||
{
|
||||
return ssb_driver_register(&ssb_hcd_driver);
|
||||
}
|
||||
module_init(ssb_hcd_init);
|
||||
|
||||
static void __exit ssb_hcd_exit(void)
|
||||
{
|
||||
ssb_driver_unregister(&ssb_hcd_driver);
|
||||
}
|
||||
module_exit(ssb_hcd_exit);
|
@ -78,18 +78,14 @@ static int emi26_load_firmware (struct usb_device *dev)
|
||||
const struct firmware *bitstream_fw = NULL;
|
||||
const struct firmware *firmware_fw = NULL;
|
||||
const struct ihex_binrec *rec;
|
||||
int err;
|
||||
int err = -ENOMEM;
|
||||
int i;
|
||||
__u32 addr; /* Address to write */
|
||||
__u8 *buf;
|
||||
|
||||
buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
dev_err(&dev->dev, "%s - error loading firmware: error = %d\n",
|
||||
__func__, -ENOMEM);
|
||||
err = -ENOMEM;
|
||||
if (!buf)
|
||||
goto wraperr;
|
||||
}
|
||||
|
||||
err = request_ihex_firmware(&loader_fw, "emi26/loader.fw", &dev->dev);
|
||||
if (err)
|
||||
@ -111,11 +107,8 @@ static int emi26_load_firmware (struct usb_device *dev)
|
||||
|
||||
/* Assert reset (stop the CPU in the EMI) */
|
||||
err = emi26_set_reset(dev,1);
|
||||
if (err < 0) {
|
||||
dev_err(&dev->dev,"%s - error loading firmware: error = %d\n",
|
||||
__func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
|
||||
rec = (const struct ihex_binrec *)loader_fw->data;
|
||||
/* 1. We need to put the loader for the FPGA into the EZ-USB */
|
||||
@ -123,19 +116,15 @@ static int emi26_load_firmware (struct usb_device *dev)
|
||||
err = emi26_writememory(dev, be32_to_cpu(rec->addr),
|
||||
rec->data, be16_to_cpu(rec->len),
|
||||
ANCHOR_LOAD_INTERNAL);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
rec = ihex_next_binrec(rec);
|
||||
}
|
||||
|
||||
/* De-assert reset (let the CPU run) */
|
||||
err = emi26_set_reset(dev,0);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
msleep(250); /* let device settle */
|
||||
|
||||
/* 2. We upload the FPGA firmware into the EMI
|
||||
@ -153,18 +142,14 @@ static int emi26_load_firmware (struct usb_device *dev)
|
||||
rec = ihex_next_binrec(rec);
|
||||
}
|
||||
err = emi26_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
} while (rec);
|
||||
|
||||
/* Assert reset (stop the CPU in the EMI) */
|
||||
err = emi26_set_reset(dev,1);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
|
||||
/* 3. We need to put the loader for the firmware into the EZ-USB (again...) */
|
||||
for (rec = (const struct ihex_binrec *)loader_fw->data;
|
||||
@ -172,19 +157,15 @@ static int emi26_load_firmware (struct usb_device *dev)
|
||||
err = emi26_writememory(dev, be32_to_cpu(rec->addr),
|
||||
rec->data, be16_to_cpu(rec->len),
|
||||
ANCHOR_LOAD_INTERNAL);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
}
|
||||
msleep(250); /* let device settle */
|
||||
|
||||
/* De-assert reset (let the CPU run) */
|
||||
err = emi26_set_reset(dev,0);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
|
||||
/* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */
|
||||
|
||||
@ -194,19 +175,15 @@ static int emi26_load_firmware (struct usb_device *dev)
|
||||
err = emi26_writememory(dev, be32_to_cpu(rec->addr),
|
||||
rec->data, be16_to_cpu(rec->len),
|
||||
ANCHOR_LOAD_EXTERNAL);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Assert reset (stop the CPU in the EMI) */
|
||||
err = emi26_set_reset(dev,1);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
|
||||
for (rec = (const struct ihex_binrec *)firmware_fw->data;
|
||||
rec; rec = ihex_next_binrec(rec)) {
|
||||
@ -214,19 +191,15 @@ static int emi26_load_firmware (struct usb_device *dev)
|
||||
err = emi26_writememory(dev, be32_to_cpu(rec->addr),
|
||||
rec->data, be16_to_cpu(rec->len),
|
||||
ANCHOR_LOAD_INTERNAL);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* De-assert reset (let the CPU run) */
|
||||
err = emi26_set_reset(dev,0);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
msleep(250); /* let device settle */
|
||||
|
||||
/* return 1 to fail the driver inialization
|
||||
@ -234,6 +207,10 @@ static int emi26_load_firmware (struct usb_device *dev)
|
||||
err = 1;
|
||||
|
||||
wraperr:
|
||||
if (err < 0)
|
||||
dev_err(&dev->dev,"%s - error loading firmware: error = %d\n",
|
||||
__func__, err);
|
||||
|
||||
release_firmware(loader_fw);
|
||||
release_firmware(bitstream_fw);
|
||||
release_firmware(firmware_fw);
|
||||
|
@ -56,7 +56,7 @@ static int emi62_writememory(struct usb_device *dev, int address,
|
||||
unsigned char *buffer = kmemdup(data, length, GFP_KERNEL);
|
||||
|
||||
if (!buffer) {
|
||||
err("emi62: kmalloc(%d) failed.", length);
|
||||
dev_err(&dev->dev, "kmalloc(%d) failed.\n", length);
|
||||
return -ENOMEM;
|
||||
}
|
||||
/* Note: usb_control_msg returns negative value on error or length of the
|
||||
@ -73,9 +73,8 @@ static int emi62_set_reset (struct usb_device *dev, unsigned char reset_bit)
|
||||
dev_info(&dev->dev, "%s - %d\n", __func__, reset_bit);
|
||||
|
||||
response = emi62_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0);
|
||||
if (response < 0) {
|
||||
err("emi62: set_reset (%d) failed", reset_bit);
|
||||
}
|
||||
if (response < 0)
|
||||
dev_err(&dev->dev, "set_reset (%d) failed\n", reset_bit);
|
||||
return response;
|
||||
}
|
||||
|
||||
@ -87,18 +86,15 @@ static int emi62_load_firmware (struct usb_device *dev)
|
||||
const struct firmware *bitstream_fw = NULL;
|
||||
const struct firmware *firmware_fw = NULL;
|
||||
const struct ihex_binrec *rec;
|
||||
int err;
|
||||
int err = -ENOMEM;
|
||||
int i;
|
||||
__u32 addr; /* Address to write */
|
||||
__u8 *buf;
|
||||
|
||||
dev_dbg(&dev->dev, "load_firmware\n");
|
||||
buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
err( "%s - error loading firmware: error = %d", __func__, -ENOMEM);
|
||||
err = -ENOMEM;
|
||||
if (!buf)
|
||||
goto wraperr;
|
||||
}
|
||||
|
||||
err = request_ihex_firmware(&loader_fw, "emi62/loader.fw", &dev->dev);
|
||||
if (err)
|
||||
@ -112,16 +108,13 @@ static int emi62_load_firmware (struct usb_device *dev)
|
||||
err = request_ihex_firmware(&firmware_fw, FIRMWARE_FW, &dev->dev);
|
||||
if (err) {
|
||||
nofw:
|
||||
err( "%s - request_firmware() failed", __func__);
|
||||
goto wraperr;
|
||||
}
|
||||
|
||||
/* Assert reset (stop the CPU in the EMI) */
|
||||
err = emi62_set_reset(dev,1);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
|
||||
rec = (const struct ihex_binrec *)loader_fw->data;
|
||||
|
||||
@ -130,19 +123,15 @@ static int emi62_load_firmware (struct usb_device *dev)
|
||||
err = emi62_writememory(dev, be32_to_cpu(rec->addr),
|
||||
rec->data, be16_to_cpu(rec->len),
|
||||
ANCHOR_LOAD_INTERNAL);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
rec = ihex_next_binrec(rec);
|
||||
}
|
||||
|
||||
/* De-assert reset (let the CPU run) */
|
||||
err = emi62_set_reset(dev,0);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
msleep(250); /* let device settle */
|
||||
|
||||
/* 2. We upload the FPGA firmware into the EMI
|
||||
@ -160,18 +149,14 @@ static int emi62_load_firmware (struct usb_device *dev)
|
||||
rec = ihex_next_binrec(rec);
|
||||
}
|
||||
err = emi62_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
} while (rec);
|
||||
|
||||
/* Assert reset (stop the CPU in the EMI) */
|
||||
err = emi62_set_reset(dev,1);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
|
||||
/* 3. We need to put the loader for the firmware into the EZ-USB (again...) */
|
||||
for (rec = (const struct ihex_binrec *)loader_fw->data;
|
||||
@ -179,18 +164,14 @@ static int emi62_load_firmware (struct usb_device *dev)
|
||||
err = emi62_writememory(dev, be32_to_cpu(rec->addr),
|
||||
rec->data, be16_to_cpu(rec->len),
|
||||
ANCHOR_LOAD_INTERNAL);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
}
|
||||
|
||||
/* De-assert reset (let the CPU run) */
|
||||
err = emi62_set_reset(dev,0);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
msleep(250); /* let device settle */
|
||||
|
||||
/* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */
|
||||
@ -201,19 +182,15 @@ static int emi62_load_firmware (struct usb_device *dev)
|
||||
err = emi62_writememory(dev, be32_to_cpu(rec->addr),
|
||||
rec->data, be16_to_cpu(rec->len),
|
||||
ANCHOR_LOAD_EXTERNAL);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Assert reset (stop the CPU in the EMI) */
|
||||
err = emi62_set_reset(dev,1);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
|
||||
for (rec = (const struct ihex_binrec *)firmware_fw->data;
|
||||
rec; rec = ihex_next_binrec(rec)) {
|
||||
@ -221,19 +198,15 @@ static int emi62_load_firmware (struct usb_device *dev)
|
||||
err = emi62_writememory(dev, be32_to_cpu(rec->addr),
|
||||
rec->data, be16_to_cpu(rec->len),
|
||||
ANCHOR_LOAD_EXTERNAL);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* De-assert reset (let the CPU run) */
|
||||
err = emi62_set_reset(dev,0);
|
||||
if (err < 0) {
|
||||
err("%s - error loading firmware: error = %d", __func__, err);
|
||||
if (err < 0)
|
||||
goto wraperr;
|
||||
}
|
||||
msleep(250); /* let device settle */
|
||||
|
||||
release_firmware(loader_fw);
|
||||
@ -247,6 +220,9 @@ static int emi62_load_firmware (struct usb_device *dev)
|
||||
return 1;
|
||||
|
||||
wraperr:
|
||||
if (err < 0)
|
||||
dev_err(&dev->dev,"%s - error loading firmware: error = %d\n",
|
||||
__func__, err);
|
||||
release_firmware(loader_fw);
|
||||
release_firmware(bitstream_fw);
|
||||
release_firmware(firmware_fw);
|
||||
|
@ -366,14 +366,14 @@ static int idmouse_probe(struct usb_interface *interface,
|
||||
kmalloc(IMGSIZE + dev->bulk_in_size, GFP_KERNEL);
|
||||
|
||||
if (!dev->bulk_in_buffer) {
|
||||
err("Unable to allocate input buffer.");
|
||||
dev_err(&interface->dev, "Unable to allocate input buffer.\n");
|
||||
idmouse_delete(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(dev->bulk_in_endpointAddr)) {
|
||||
err("Unable to find bulk-in endpoint.");
|
||||
dev_err(&interface->dev, "Unable to find bulk-in endpoint.\n");
|
||||
idmouse_delete(dev);
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -385,7 +385,7 @@ static int idmouse_probe(struct usb_interface *interface,
|
||||
result = usb_register_dev(interface, &idmouse_class);
|
||||
if (result) {
|
||||
/* something prevented us from registering this device */
|
||||
err("Unble to allocate minor number.");
|
||||
dev_err(&interface->dev, "Unble to allocate minor number.\n");
|
||||
usb_set_intfdata(interface, NULL);
|
||||
idmouse_delete(dev);
|
||||
return result;
|
||||
|
@ -610,8 +610,8 @@ static int iowarrior_open(struct inode *inode, struct file *file)
|
||||
interface = usb_find_interface(&iowarrior_driver, subminor);
|
||||
if (!interface) {
|
||||
mutex_unlock(&iowarrior_mutex);
|
||||
err("%s - error, can't find device for minor %d", __func__,
|
||||
subminor);
|
||||
printk(KERN_ERR "%s - error, can't find device for minor %d\n",
|
||||
__func__, subminor);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -334,8 +334,8 @@ static int ld_usb_open(struct inode *inode, struct file *file)
|
||||
interface = usb_find_interface(&ld_usb_driver, subminor);
|
||||
|
||||
if (!interface) {
|
||||
err("%s - error, can't find device for minor %d\n",
|
||||
__func__, subminor);
|
||||
printk(KERN_ERR "%s - error, can't find device for minor %d\n",
|
||||
__func__, subminor);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -485,7 +485,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
|
||||
/* verify that the device wasn't unplugged */
|
||||
if (dev->intf == NULL) {
|
||||
retval = -ENODEV;
|
||||
err("No device or device unplugged %d\n", retval);
|
||||
printk(KERN_ERR "ldusb: No device or device unplugged %d\n", retval);
|
||||
goto unlock_exit;
|
||||
}
|
||||
|
||||
@ -565,7 +565,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
|
||||
/* verify that the device wasn't unplugged */
|
||||
if (dev->intf == NULL) {
|
||||
retval = -ENODEV;
|
||||
err("No device or device unplugged %d\n", retval);
|
||||
printk(KERN_ERR "ldusb: No device or device unplugged %d\n", retval);
|
||||
goto unlock_exit;
|
||||
}
|
||||
|
||||
@ -603,7 +603,9 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
|
||||
bytes_to_write,
|
||||
USB_CTRL_SET_TIMEOUT * HZ);
|
||||
if (retval < 0)
|
||||
err("Couldn't submit HID_REQ_SET_REPORT %d\n", retval);
|
||||
dev_err(&dev->intf->dev,
|
||||
"Couldn't submit HID_REQ_SET_REPORT %d\n",
|
||||
retval);
|
||||
goto unlock_exit;
|
||||
}
|
||||
|
||||
@ -624,7 +626,8 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
|
||||
retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
|
||||
if (retval) {
|
||||
dev->interrupt_out_busy = 0;
|
||||
err("Couldn't submit interrupt_out_urb %d\n", retval);
|
||||
dev_err(&dev->intf->dev,
|
||||
"Couldn't submit interrupt_out_urb %d\n", retval);
|
||||
goto unlock_exit;
|
||||
}
|
||||
retval = bytes_to_write;
|
||||
|
@ -354,8 +354,8 @@ static int tower_open (struct inode *inode, struct file *file)
|
||||
interface = usb_find_interface (&tower_driver, subminor);
|
||||
|
||||
if (!interface) {
|
||||
err ("%s - error, can't find device for minor %d",
|
||||
__func__, subminor);
|
||||
printk(KERN_ERR "%s - error, can't find device for minor %d\n",
|
||||
__func__, subminor);
|
||||
retval = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
@ -397,7 +397,8 @@ static int tower_open (struct inode *inode, struct file *file)
|
||||
sizeof(reset_reply),
|
||||
1000);
|
||||
if (result < 0) {
|
||||
err("LEGO USB Tower reset control request failed");
|
||||
dev_err(&dev->udev->dev,
|
||||
"LEGO USB Tower reset control request failed\n");
|
||||
retval = result;
|
||||
goto unlock_exit;
|
||||
}
|
||||
@ -420,7 +421,8 @@ static int tower_open (struct inode *inode, struct file *file)
|
||||
|
||||
retval = usb_submit_urb (dev->interrupt_in_urb, GFP_KERNEL);
|
||||
if (retval) {
|
||||
err("Couldn't submit interrupt_in_urb %d", retval);
|
||||
dev_err(&dev->udev->dev,
|
||||
"Couldn't submit interrupt_in_urb %d\n", retval);
|
||||
dev->interrupt_in_running = 0;
|
||||
dev->open_count = 0;
|
||||
goto unlock_exit;
|
||||
@ -608,7 +610,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
|
||||
/* verify that the device wasn't unplugged */
|
||||
if (dev->udev == NULL) {
|
||||
retval = -ENODEV;
|
||||
err("No device or device unplugged %d", retval);
|
||||
printk(KERN_ERR "legousbtower: No device or device unplugged %d\n", retval);
|
||||
goto unlock_exit;
|
||||
}
|
||||
|
||||
@ -697,7 +699,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
|
||||
/* verify that the device wasn't unplugged */
|
||||
if (dev->udev == NULL) {
|
||||
retval = -ENODEV;
|
||||
err("No device or device unplugged %d", retval);
|
||||
printk(KERN_ERR "legousbtower: No device or device unplugged %d\n", retval);
|
||||
goto unlock_exit;
|
||||
}
|
||||
|
||||
@ -744,7 +746,8 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
|
||||
retval = usb_submit_urb (dev->interrupt_out_urb, GFP_KERNEL);
|
||||
if (retval) {
|
||||
dev->interrupt_out_busy = 0;
|
||||
err("Couldn't submit interrupt_out_urb %d", retval);
|
||||
dev_err(&dev->udev->dev,
|
||||
"Couldn't submit interrupt_out_urb %d\n", retval);
|
||||
goto unlock_exit;
|
||||
}
|
||||
retval = bytes_to_write;
|
||||
@ -803,9 +806,10 @@ static void tower_interrupt_in_callback (struct urb *urb)
|
||||
/* resubmit if we're still running */
|
||||
if (dev->interrupt_in_running && dev->udev) {
|
||||
retval = usb_submit_urb (dev->interrupt_in_urb, GFP_ATOMIC);
|
||||
if (retval) {
|
||||
err("%s: usb_submit_urb failed (%d)", __func__, retval);
|
||||
}
|
||||
if (retval)
|
||||
dev_err(&dev->udev->dev,
|
||||
"%s: usb_submit_urb failed (%d)\n",
|
||||
__func__, retval);
|
||||
}
|
||||
|
||||
exit:
|
||||
@ -852,6 +856,7 @@ static void tower_interrupt_out_callback (struct urb *urb)
|
||||
*/
|
||||
static int tower_probe (struct usb_interface *interface, const struct usb_device_id *id)
|
||||
{
|
||||
struct device *idev = &interface->dev;
|
||||
struct usb_device *udev = interface_to_usbdev(interface);
|
||||
struct lego_usb_tower *dev = NULL;
|
||||
struct usb_host_interface *iface_desc;
|
||||
@ -871,7 +876,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
|
||||
dev = kmalloc (sizeof(struct lego_usb_tower), GFP_KERNEL);
|
||||
|
||||
if (dev == NULL) {
|
||||
err ("Out of memory");
|
||||
dev_err(idev, "Out of memory\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@ -915,37 +920,37 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
|
||||
}
|
||||
}
|
||||
if(dev->interrupt_in_endpoint == NULL) {
|
||||
err("interrupt in endpoint not found");
|
||||
dev_err(idev, "interrupt in endpoint not found\n");
|
||||
goto error;
|
||||
}
|
||||
if (dev->interrupt_out_endpoint == NULL) {
|
||||
err("interrupt out endpoint not found");
|
||||
dev_err(idev, "interrupt out endpoint not found\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
dev->read_buffer = kmalloc (read_buffer_size, GFP_KERNEL);
|
||||
if (!dev->read_buffer) {
|
||||
err("Couldn't allocate read_buffer");
|
||||
dev_err(idev, "Couldn't allocate read_buffer\n");
|
||||
goto error;
|
||||
}
|
||||
dev->interrupt_in_buffer = kmalloc (usb_endpoint_maxp(dev->interrupt_in_endpoint), GFP_KERNEL);
|
||||
if (!dev->interrupt_in_buffer) {
|
||||
err("Couldn't allocate interrupt_in_buffer");
|
||||
dev_err(idev, "Couldn't allocate interrupt_in_buffer\n");
|
||||
goto error;
|
||||
}
|
||||
dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!dev->interrupt_in_urb) {
|
||||
err("Couldn't allocate interrupt_in_urb");
|
||||
dev_err(idev, "Couldn't allocate interrupt_in_urb\n");
|
||||
goto error;
|
||||
}
|
||||
dev->interrupt_out_buffer = kmalloc (write_buffer_size, GFP_KERNEL);
|
||||
if (!dev->interrupt_out_buffer) {
|
||||
err("Couldn't allocate interrupt_out_buffer");
|
||||
dev_err(idev, "Couldn't allocate interrupt_out_buffer\n");
|
||||
goto error;
|
||||
}
|
||||
dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!dev->interrupt_out_urb) {
|
||||
err("Couldn't allocate interrupt_out_urb");
|
||||
dev_err(idev, "Couldn't allocate interrupt_out_urb\n");
|
||||
goto error;
|
||||
}
|
||||
dev->interrupt_in_interval = interrupt_in_interval ? interrupt_in_interval : dev->interrupt_in_endpoint->bInterval;
|
||||
@ -958,7 +963,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
|
||||
|
||||
if (retval) {
|
||||
/* something prevented us from registering this driver */
|
||||
err ("Not able to get a minor for this device.");
|
||||
dev_err(idev, "Not able to get a minor for this device.\n");
|
||||
usb_set_intfdata (interface, NULL);
|
||||
goto error;
|
||||
}
|
||||
@ -980,7 +985,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
|
||||
sizeof(get_version_reply),
|
||||
1000);
|
||||
if (result < 0) {
|
||||
err("LEGO USB Tower get version control request failed");
|
||||
dev_err(idev, "LEGO USB Tower get version control request failed\n");
|
||||
retval = result;
|
||||
goto error;
|
||||
}
|
||||
|
@ -171,7 +171,9 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
if (result == -ETIMEDOUT)
|
||||
retries--;
|
||||
else if (result < 0) {
|
||||
err("Error executing ioctrl. code = %d", result);
|
||||
dev_err(&rio->rio_dev->dev,
|
||||
"Error executing ioctrl. code = %d\n",
|
||||
result);
|
||||
retries = 0;
|
||||
} else {
|
||||
dbg("Executed ioctl. Result = %d (data=%02x)",
|
||||
@ -238,7 +240,9 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
if (result == -ETIMEDOUT)
|
||||
retries--;
|
||||
else if (result < 0) {
|
||||
err("Error executing ioctrl. code = %d", result);
|
||||
dev_err(&rio->rio_dev->dev,
|
||||
"Error executing ioctrl. code = %d\n",
|
||||
result);
|
||||
retries = 0;
|
||||
} else {
|
||||
dbg("Executed ioctl. Result = %d", result);
|
||||
@ -332,7 +336,8 @@ write_rio(struct file *file, const char __user *buffer,
|
||||
break;
|
||||
};
|
||||
if (result) {
|
||||
err("Write Whoops - %x", result);
|
||||
dev_err(&rio->rio_dev->dev, "Write Whoops - %x\n",
|
||||
result);
|
||||
errn = -EIO;
|
||||
goto error;
|
||||
}
|
||||
@ -401,7 +406,8 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
|
||||
} else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */
|
||||
if (!maxretry--) {
|
||||
mutex_unlock(&(rio->lock));
|
||||
err("read_rio: maxretry timeout");
|
||||
dev_err(&rio->rio_dev->dev,
|
||||
"read_rio: maxretry timeout\n");
|
||||
return -ETIME;
|
||||
}
|
||||
prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE);
|
||||
@ -410,8 +416,9 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
|
||||
continue;
|
||||
} else if (result != -EREMOTEIO) {
|
||||
mutex_unlock(&(rio->lock));
|
||||
err("Read Whoops - result:%u partial:%u this_read:%u",
|
||||
result, partial, this_read);
|
||||
dev_err(&rio->rio_dev->dev,
|
||||
"Read Whoops - result:%u partial:%u this_read:%u\n",
|
||||
result, partial, this_read);
|
||||
return -EIO;
|
||||
} else {
|
||||
mutex_unlock(&(rio->lock));
|
||||
@ -459,21 +466,24 @@ static int probe_rio(struct usb_interface *intf,
|
||||
|
||||
retval = usb_register_dev(intf, &usb_rio_class);
|
||||
if (retval) {
|
||||
err("Not able to get a minor for this device.");
|
||||
dev_err(&dev->dev,
|
||||
"Not able to get a minor for this device.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rio->rio_dev = dev;
|
||||
|
||||
if (!(rio->obuf = kmalloc(OBUF_SIZE, GFP_KERNEL))) {
|
||||
err("probe_rio: Not enough memory for the output buffer");
|
||||
dev_err(&dev->dev,
|
||||
"probe_rio: Not enough memory for the output buffer\n");
|
||||
usb_deregister_dev(intf, &usb_rio_class);
|
||||
return -ENOMEM;
|
||||
}
|
||||
dbg("probe_rio: obuf address:%p", rio->obuf);
|
||||
|
||||
if (!(rio->ibuf = kmalloc(IBUF_SIZE, GFP_KERNEL))) {
|
||||
err("probe_rio: Not enough memory for the input buffer");
|
||||
dev_err(&dev->dev,
|
||||
"probe_rio: Not enough memory for the input buffer\n");
|
||||
usb_deregister_dev(intf, &usb_rio_class);
|
||||
kfree(rio->obuf);
|
||||
return -ENOMEM;
|
||||
|
@ -87,8 +87,8 @@ static int lcd_open(struct inode *inode, struct file *file)
|
||||
interface = usb_find_interface(&lcd_driver, subminor);
|
||||
if (!interface) {
|
||||
mutex_unlock(&lcd_mutex);
|
||||
err("USBLCD: %s - error, can't find device for minor %d",
|
||||
__func__, subminor);
|
||||
printk(KERN_ERR "USBLCD: %s - error, can't find device for minor %d\n",
|
||||
__func__, subminor);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -268,8 +268,9 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer,
|
||||
/* send the data out the bulk port */
|
||||
retval = usb_submit_urb(urb, GFP_KERNEL);
|
||||
if (retval) {
|
||||
err("USBLCD: %s - failed submitting write urb, error %d",
|
||||
__func__, retval);
|
||||
dev_err(&dev->udev->dev,
|
||||
"%s - failed submitting write urb, error %d\n",
|
||||
__func__, retval);
|
||||
goto error_unanchor;
|
||||
}
|
||||
|
||||
@ -322,7 +323,7 @@ static int lcd_probe(struct usb_interface *interface,
|
||||
/* allocate memory for our device state and initialize it */
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (dev == NULL) {
|
||||
err("Out of memory");
|
||||
dev_err(&interface->dev, "Out of memory\n");
|
||||
goto error;
|
||||
}
|
||||
kref_init(&dev->kref);
|
||||
@ -352,7 +353,8 @@ static int lcd_probe(struct usb_interface *interface,
|
||||
dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
|
||||
dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
|
||||
if (!dev->bulk_in_buffer) {
|
||||
err("Could not allocate bulk_in_buffer");
|
||||
dev_err(&interface->dev,
|
||||
"Could not allocate bulk_in_buffer\n");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@ -364,7 +366,8 @@ static int lcd_probe(struct usb_interface *interface,
|
||||
}
|
||||
}
|
||||
if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
|
||||
err("Could not find both bulk-in and bulk-out endpoints");
|
||||
dev_err(&interface->dev,
|
||||
"Could not find both bulk-in and bulk-out endpoints\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -375,7 +378,8 @@ static int lcd_probe(struct usb_interface *interface,
|
||||
retval = usb_register_dev(interface, &lcd_class);
|
||||
if (retval) {
|
||||
/* something prevented us from registering this driver */
|
||||
err("Not able to get a minor for this device.");
|
||||
dev_err(&interface->dev,
|
||||
"Not able to get a minor for this device.\n");
|
||||
usb_set_intfdata(interface, NULL);
|
||||
goto error;
|
||||
}
|
||||
|
@ -118,7 +118,8 @@ static void async_complete(struct urb *urb)
|
||||
priv = rq->priv;
|
||||
pp = priv->pp;
|
||||
if (status) {
|
||||
err("async_complete: urb error %d", status);
|
||||
dev_err(&urb->dev->dev, "async_complete: urb error %d\n",
|
||||
status);
|
||||
} else if (rq->dr.bRequest == 3) {
|
||||
memcpy(priv->reg, rq->reg, sizeof(priv->reg));
|
||||
#if 0
|
||||
@ -151,7 +152,7 @@ static struct uss720_async_request *submit_async_request(struct parport_uss720_p
|
||||
return NULL;
|
||||
rq = kmalloc(sizeof(struct uss720_async_request), mem_flags);
|
||||
if (!rq) {
|
||||
err("submit_async_request out of memory");
|
||||
dev_err(&usbdev->dev, "submit_async_request out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
kref_init(&rq->ref_count);
|
||||
@ -162,7 +163,7 @@ static struct uss720_async_request *submit_async_request(struct parport_uss720_p
|
||||
rq->urb = usb_alloc_urb(0, mem_flags);
|
||||
if (!rq->urb) {
|
||||
kref_put(&rq->ref_count, destroy_async);
|
||||
err("submit_async_request out of memory");
|
||||
dev_err(&usbdev->dev, "submit_async_request out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
rq->dr.bRequestType = requesttype;
|
||||
@ -182,7 +183,7 @@ static struct uss720_async_request *submit_async_request(struct parport_uss720_p
|
||||
if (!ret)
|
||||
return rq;
|
||||
destroy_async(&rq->ref_count);
|
||||
err("submit_async_request submit_urb failed with %d", ret);
|
||||
dev_err(&usbdev->dev, "submit_async_request submit_urb failed with %d\n", ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -217,7 +218,8 @@ static int get_1284_register(struct parport *pp, unsigned char reg, unsigned cha
|
||||
priv = pp->private_data;
|
||||
rq = submit_async_request(priv, 3, 0xc0, ((unsigned int)reg) << 8, 0, mem_flags);
|
||||
if (!rq) {
|
||||
err("get_1284_register(%u) failed", (unsigned int)reg);
|
||||
dev_err(&priv->usbdev->dev, "get_1284_register(%u) failed",
|
||||
(unsigned int)reg);
|
||||
return -EIO;
|
||||
}
|
||||
if (!val) {
|
||||
@ -248,7 +250,8 @@ static int set_1284_register(struct parport *pp, unsigned char reg, unsigned cha
|
||||
priv = pp->private_data;
|
||||
rq = submit_async_request(priv, 4, 0x40, (((unsigned int)reg) << 8) | val, 0, mem_flags);
|
||||
if (!rq) {
|
||||
err("set_1284_register(%u,%u) failed", (unsigned int)reg, (unsigned int)val);
|
||||
dev_err(&priv->usbdev->dev, "set_1284_register(%u,%u) failed",
|
||||
(unsigned int)reg, (unsigned int)val);
|
||||
return -EIO;
|
||||
}
|
||||
kref_put(&rq->ref_count, destroy_async);
|
||||
|
@ -83,7 +83,8 @@ static void yurex_control_callback(struct urb *urb)
|
||||
int status = urb->status;
|
||||
|
||||
if (status) {
|
||||
err("%s - control failed: %d\n", __func__, status);
|
||||
dev_err(&urb->dev->dev, "%s - control failed: %d\n",
|
||||
__func__, status);
|
||||
wake_up_interruptible(&dev->waitq);
|
||||
return;
|
||||
}
|
||||
@ -137,8 +138,9 @@ static void yurex_interrupt(struct urb *urb)
|
||||
case 0: /*success*/
|
||||
break;
|
||||
case -EOVERFLOW:
|
||||
err("%s - overflow with length %d, actual length is %d",
|
||||
__func__, YUREX_BUF_SIZE, dev->urb->actual_length);
|
||||
dev_err(&dev->interface->dev,
|
||||
"%s - overflow with length %d, actual length is %d\n",
|
||||
__func__, YUREX_BUF_SIZE, dev->urb->actual_length);
|
||||
case -ECONNRESET:
|
||||
case -ENOENT:
|
||||
case -ESHUTDOWN:
|
||||
@ -146,7 +148,8 @@ static void yurex_interrupt(struct urb *urb)
|
||||
/* The device is terminated, clean up */
|
||||
return;
|
||||
default:
|
||||
err("%s - unknown status received: %d", __func__, status);
|
||||
dev_err(&dev->interface->dev,
|
||||
"%s - unknown status received: %d\n", __func__, status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@ -179,7 +182,7 @@ static void yurex_interrupt(struct urb *urb)
|
||||
exit:
|
||||
retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
|
||||
if (retval) {
|
||||
err("%s - usb_submit_urb failed: %d",
|
||||
dev_err(&dev->interface->dev, "%s - usb_submit_urb failed: %d\n",
|
||||
__func__, retval);
|
||||
}
|
||||
}
|
||||
@ -196,7 +199,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
|
||||
/* allocate memory for our device state and initialize it */
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev) {
|
||||
err("Out of memory");
|
||||
dev_err(&interface->dev, "Out of memory\n");
|
||||
goto error;
|
||||
}
|
||||
kref_init(&dev->kref);
|
||||
@ -219,7 +222,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
|
||||
}
|
||||
if (!dev->int_in_endpointAddr) {
|
||||
retval = -ENODEV;
|
||||
err("Could not find endpoints");
|
||||
dev_err(&interface->dev, "Could not find endpoints\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -227,14 +230,14 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
|
||||
/* allocate control URB */
|
||||
dev->cntl_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!dev->cntl_urb) {
|
||||
err("Could not allocate control URB");
|
||||
dev_err(&interface->dev, "Could not allocate control URB\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* allocate buffer for control req */
|
||||
dev->cntl_req = kmalloc(YUREX_BUF_SIZE, GFP_KERNEL);
|
||||
if (!dev->cntl_req) {
|
||||
err("Could not allocate cntl_req");
|
||||
dev_err(&interface->dev, "Could not allocate cntl_req\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -243,7 +246,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
|
||||
GFP_KERNEL,
|
||||
&dev->cntl_urb->transfer_dma);
|
||||
if (!dev->cntl_buffer) {
|
||||
err("Could not allocate cntl_buffer");
|
||||
dev_err(&interface->dev, "Could not allocate cntl_buffer\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -265,7 +268,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
|
||||
/* allocate interrupt URB */
|
||||
dev->urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!dev->urb) {
|
||||
err("Could not allocate URB");
|
||||
dev_err(&interface->dev, "Could not allocate URB\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -273,7 +276,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
|
||||
dev->int_buffer = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE,
|
||||
GFP_KERNEL, &dev->urb->transfer_dma);
|
||||
if (!dev->int_buffer) {
|
||||
err("Could not allocate int_buffer");
|
||||
dev_err(&interface->dev, "Could not allocate int_buffer\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -285,7 +288,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
|
||||
dev->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||
if (usb_submit_urb(dev->urb, GFP_KERNEL)) {
|
||||
retval = -EIO;
|
||||
err("Could not submitting URB");
|
||||
dev_err(&interface->dev, "Could not submitting URB\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -295,7 +298,8 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
|
||||
/* we can register the device now, as it is ready */
|
||||
retval = usb_register_dev(interface, &yurex_class);
|
||||
if (retval) {
|
||||
err("Not able to get a minor for this device.");
|
||||
dev_err(&interface->dev,
|
||||
"Not able to get a minor for this device.\n");
|
||||
usb_set_intfdata(interface, NULL);
|
||||
goto error;
|
||||
}
|
||||
@ -368,8 +372,8 @@ static int yurex_open(struct inode *inode, struct file *file)
|
||||
|
||||
interface = usb_find_interface(&yurex_driver, subminor);
|
||||
if (!interface) {
|
||||
err("%s - error, can't find device for minor %d",
|
||||
__func__, subminor);
|
||||
printk(KERN_ERR "%s - error, can't find device for minor %d",
|
||||
__func__, subminor);
|
||||
retval = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
@ -514,7 +518,9 @@ static ssize_t yurex_write(struct file *file, const char *user_buffer, size_t co
|
||||
mutex_unlock(&dev->io_mutex);
|
||||
|
||||
if (retval < 0) {
|
||||
err("%s - failed to send bulk msg, error %d", __func__, retval);
|
||||
dev_err(&dev->interface->dev,
|
||||
"%s - failed to send bulk msg, error %d\n",
|
||||
__func__, retval);
|
||||
goto error;
|
||||
}
|
||||
if (set && timeout)
|
||||
|
@ -113,7 +113,8 @@ static int usb_console_setup(struct console *co, char *options)
|
||||
serial = usb_serial_get_by_index(co->index);
|
||||
if (serial == NULL) {
|
||||
/* no device is connected yet, sorry :( */
|
||||
err("No USB device connected to ttyUSB%i", co->index);
|
||||
printk(KERN_ERR "No USB device connected to ttyUSB%i\n",
|
||||
co->index);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -137,7 +138,7 @@ static int usb_console_setup(struct console *co, char *options)
|
||||
tty = kzalloc(sizeof(*tty), GFP_KERNEL);
|
||||
if (!tty) {
|
||||
retval = -ENOMEM;
|
||||
err("no more memory");
|
||||
dev_err(&port->dev, "no more memory\n");
|
||||
goto reset_open_count;
|
||||
}
|
||||
kref_init(&tty->kref);
|
||||
@ -146,7 +147,7 @@ static int usb_console_setup(struct console *co, char *options)
|
||||
tty->index = co->index;
|
||||
if (tty_init_termios(tty)) {
|
||||
retval = -ENOMEM;
|
||||
err("no more memory");
|
||||
dev_err(&port->dev, "no more memory\n");
|
||||
goto free_tty;
|
||||
}
|
||||
}
|
||||
@ -159,7 +160,7 @@ static int usb_console_setup(struct console *co, char *options)
|
||||
retval = usb_serial_generic_open(NULL, port);
|
||||
|
||||
if (retval) {
|
||||
err("could not open USB console port");
|
||||
dev_err(&port->dev, "could not open USB console port\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -547,6 +547,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
|
||||
{
|
||||
int baud_rate;
|
||||
struct tty_struct *tty = tty_port_tty_get(&port->port->port);
|
||||
struct usb_serial *serial = port->port->serial;
|
||||
wait_queue_t wait;
|
||||
unsigned long flags;
|
||||
|
||||
@ -561,7 +562,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (kfifo_len(&port->write_fifo) == 0
|
||||
|| timeout == 0 || signal_pending(current)
|
||||
|| !usb_get_intfdata(port->port->serial->interface))
|
||||
|| serial->disconnected)
|
||||
/* disconnect */
|
||||
break;
|
||||
spin_unlock_irqrestore(&port->ep_lock, flags);
|
||||
@ -578,7 +579,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
|
||||
/* wait for data to drain from the device */
|
||||
timeout += jiffies;
|
||||
while ((long)(jiffies - timeout) < 0 && !signal_pending(current)
|
||||
&& usb_get_intfdata(port->port->serial->interface)) {
|
||||
&& !serial->disconnected) {
|
||||
/* not disconnected */
|
||||
if (!tx_active(port))
|
||||
break;
|
||||
@ -586,7 +587,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
|
||||
}
|
||||
|
||||
/* disconnected */
|
||||
if (!usb_get_intfdata(port->port->serial->interface))
|
||||
if (serial->disconnected)
|
||||
return;
|
||||
|
||||
/* wait one more character time, based on baud rate */
|
||||
@ -2003,8 +2004,8 @@ static void edge_close(struct usb_serial_port *port)
|
||||
{
|
||||
struct edgeport_serial *edge_serial;
|
||||
struct edgeport_port *edge_port;
|
||||
struct usb_serial *serial = port->serial;
|
||||
int port_number;
|
||||
int status;
|
||||
|
||||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
@ -2028,12 +2029,18 @@ static void edge_close(struct usb_serial_port *port)
|
||||
* send a close port command to it */
|
||||
dbg("%s - send umpc_close_port", __func__);
|
||||
port_number = port->number - port->serial->minor;
|
||||
status = send_cmd(port->serial->dev,
|
||||
|
||||
mutex_lock(&serial->disc_mutex);
|
||||
if (!serial->disconnected) {
|
||||
send_cmd(serial->dev,
|
||||
UMPC_CLOSE_PORT,
|
||||
(__u8)(UMPM_UART1_PORT + port_number),
|
||||
0,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
mutex_unlock(&serial->disc_mutex);
|
||||
|
||||
mutex_lock(&edge_serial->es_lock);
|
||||
--edge_port->edge_serial->num_ports_open;
|
||||
if (edge_port->edge_serial->num_ports_open <= 0) {
|
||||
|
@ -33,7 +33,6 @@
|
||||
#define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>"
|
||||
#define DRIVER_DESC "USB PocketPC PDA driver"
|
||||
|
||||
static __u16 product, vendor;
|
||||
static bool debug;
|
||||
static int connect_retries = KP_RETRIES;
|
||||
static int initial_wait;
|
||||
@ -45,8 +44,6 @@ static int ipaq_calc_num_ports(struct usb_serial *serial);
|
||||
static int ipaq_startup(struct usb_serial *serial);
|
||||
|
||||
static struct usb_device_id ipaq_id_table [] = {
|
||||
/* The first entry is a placeholder for the insmod-specified device */
|
||||
{ USB_DEVICE(0x049F, 0x0003) },
|
||||
{ USB_DEVICE(0x0104, 0x00BE) }, /* Socket USB Sync */
|
||||
{ USB_DEVICE(0x03F0, 0x1016) }, /* HP USB Sync */
|
||||
{ USB_DEVICE(0x03F0, 0x1116) }, /* HP USB Sync 1611 */
|
||||
@ -623,30 +620,7 @@ static int ipaq_startup(struct usb_serial *serial)
|
||||
return usb_reset_configuration(serial->dev);
|
||||
}
|
||||
|
||||
static int __init ipaq_init(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (vendor) {
|
||||
ipaq_id_table[0].idVendor = vendor;
|
||||
ipaq_id_table[0].idProduct = product;
|
||||
}
|
||||
|
||||
retval = usb_serial_register_drivers(&ipaq_driver, serial_drivers);
|
||||
if (retval == 0)
|
||||
printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
|
||||
DRIVER_DESC "\n");
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void __exit ipaq_exit(void)
|
||||
{
|
||||
usb_serial_deregister_drivers(&ipaq_driver, serial_drivers);
|
||||
}
|
||||
|
||||
|
||||
module_init(ipaq_init);
|
||||
module_exit(ipaq_exit);
|
||||
module_usb_serial_driver(ipaq_driver, serial_drivers);
|
||||
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
@ -655,12 +629,6 @@ MODULE_LICENSE("GPL");
|
||||
module_param(debug, bool, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(debug, "Debug enabled or not");
|
||||
|
||||
module_param(vendor, ushort, 0);
|
||||
MODULE_PARM_DESC(vendor, "User specified USB idVendor");
|
||||
|
||||
module_param(product, ushort, 0);
|
||||
MODULE_PARM_DESC(product, "User specified USB idProduct");
|
||||
|
||||
module_param(connect_retries, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(connect_retries,
|
||||
"Maximum number of connect retries (one second each)");
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
@ -56,6 +55,47 @@ MODULE_DEVICE_TABLE(usb, id_table);
|
||||
/* Input parameter constants. */
|
||||
static bool debug;
|
||||
|
||||
/* UNI-Directional mode commands for device configure */
|
||||
#define UNI_CMD_OPEN 0x80
|
||||
#define UNI_CMD_CLOSE 0xFF
|
||||
|
||||
inline int metrousb_is_unidirectional_mode(struct usb_serial_port *port)
|
||||
{
|
||||
__u16 product_id = le16_to_cpu(
|
||||
port->serial->dev->descriptor.idProduct);
|
||||
|
||||
return product_id == FOCUS_PRODUCT_ID_UNI;
|
||||
}
|
||||
|
||||
static int metrousb_send_unidirectional_cmd(u8 cmd, struct usb_serial_port *port)
|
||||
{
|
||||
int ret;
|
||||
int actual_len;
|
||||
u8 *buffer_cmd = NULL;
|
||||
|
||||
if (!metrousb_is_unidirectional_mode(port))
|
||||
return 0;
|
||||
|
||||
buffer_cmd = kzalloc(sizeof(cmd), GFP_KERNEL);
|
||||
if (!buffer_cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
*buffer_cmd = cmd;
|
||||
|
||||
ret = usb_interrupt_msg(port->serial->dev,
|
||||
usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress),
|
||||
buffer_cmd, sizeof(cmd),
|
||||
&actual_len, USB_CTRL_SET_TIMEOUT);
|
||||
|
||||
kfree(buffer_cmd);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else if (actual_len != sizeof(cmd))
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void metrousb_read_int_callback(struct urb *urb)
|
||||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
@ -78,12 +118,12 @@ static void metrousb_read_int_callback(struct urb *urb)
|
||||
/* urb has been terminated. */
|
||||
dev_dbg(&port->dev,
|
||||
"%s - urb shutting down, error code=%d\n",
|
||||
__func__, result);
|
||||
__func__, urb->status);
|
||||
return;
|
||||
default:
|
||||
dev_dbg(&port->dev,
|
||||
"%s - non-zero urb received, error code=%d\n",
|
||||
__func__, result);
|
||||
__func__, urb->status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@ -91,7 +131,7 @@ static void metrousb_read_int_callback(struct urb *urb)
|
||||
/* Set the data read from the usb port into the serial port buffer. */
|
||||
tty = tty_port_tty_get(&port->port);
|
||||
if (!tty) {
|
||||
dev_dbg(&port->dev, "%s - bad tty pointer - exiting\n",
|
||||
dev_err(&port->dev, "%s - bad tty pointer - exiting\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
@ -121,7 +161,7 @@ static void metrousb_read_int_callback(struct urb *urb)
|
||||
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
|
||||
|
||||
if (result)
|
||||
dev_dbg(&port->dev,
|
||||
dev_err(&port->dev,
|
||||
"%s - failed submitting interrupt in urb, error code=%d\n",
|
||||
__func__, result);
|
||||
}
|
||||
@ -131,11 +171,19 @@ static void metrousb_read_int_callback(struct urb *urb)
|
||||
/* Try to resubmit the urb. */
|
||||
result = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (result)
|
||||
dev_dbg(&port->dev,
|
||||
dev_err(&port->dev,
|
||||
"%s - failed submitting interrupt in urb, error code=%d\n",
|
||||
__func__, result);
|
||||
}
|
||||
|
||||
static void metrousb_write_int_callback(struct urb *urb)
|
||||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
|
||||
dev_warn(&port->dev, "%s not implemented yet.\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
static void metrousb_cleanup(struct usb_serial_port *port)
|
||||
{
|
||||
dev_dbg(&port->dev, "%s\n", __func__);
|
||||
@ -146,6 +194,9 @@ static void metrousb_cleanup(struct usb_serial_port *port)
|
||||
usb_unlink_urb(port->interrupt_in_urb);
|
||||
usb_kill_urb(port->interrupt_in_urb);
|
||||
}
|
||||
|
||||
/* Send deactivate cmd to device */
|
||||
metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,7 +211,7 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||
|
||||
/* Make sure the urb is initialized. */
|
||||
if (!port->interrupt_in_urb) {
|
||||
dev_dbg(&port->dev, "%s - interrupt urb not initialized\n",
|
||||
dev_err(&port->dev, "%s - interrupt urb not initialized\n",
|
||||
__func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -191,12 +242,21 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
|
||||
|
||||
if (result) {
|
||||
dev_dbg(&port->dev,
|
||||
dev_err(&port->dev,
|
||||
"%s - failed submitting interrupt in urb, error code=%d\n",
|
||||
__func__, result);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Send activate cmd to device */
|
||||
result = metrousb_send_unidirectional_cmd(UNI_CMD_OPEN, port);
|
||||
if (result) {
|
||||
dev_err(&port->dev,
|
||||
"%s - failed to configure device for port number=%d, error code=%d\n",
|
||||
__func__, port->number, result);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
dev_dbg(&port->dev, "%s - port open\n", __func__);
|
||||
exit:
|
||||
return result;
|
||||
@ -221,7 +281,7 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr
|
||||
METROUSB_SET_REQUEST_TYPE, METROUSB_SET_MODEM_CTRL_REQUEST,
|
||||
control_state, 0, NULL, 0, WDR_TIMEOUT);
|
||||
if (retval < 0)
|
||||
dev_dbg(&serial->dev->dev,
|
||||
dev_err(&serial->dev->dev,
|
||||
"%s - set modem ctrl=0x%x failed, error code=%d\n",
|
||||
__func__, mcr, retval);
|
||||
|
||||
@ -354,7 +414,7 @@ static void metrousb_unthrottle(struct tty_struct *tty)
|
||||
port->interrupt_in_urb->dev = port->serial->dev;
|
||||
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
|
||||
if (result)
|
||||
dev_dbg(tty->dev,
|
||||
dev_err(tty->dev,
|
||||
"failed submitting interrupt in urb error code=%d\n",
|
||||
result);
|
||||
}
|
||||
@ -371,12 +431,13 @@ static struct usb_serial_driver metrousb_device = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "metro-usb",
|
||||
},
|
||||
.description = "Metrologic USB to serial converter.",
|
||||
.description = "Metrologic USB to Serial",
|
||||
.id_table = id_table,
|
||||
.num_ports = 1,
|
||||
.open = metrousb_open,
|
||||
.close = metrousb_cleanup,
|
||||
.read_int_callback = metrousb_read_int_callback,
|
||||
.write_int_callback = metrousb_write_int_callback,
|
||||
.attach = metrousb_startup,
|
||||
.release = metrousb_shutdown,
|
||||
.throttle = metrousb_throttle,
|
||||
|
@ -114,6 +114,7 @@
|
||||
#define USB_VENDOR_ID_MOSCHIP 0x9710
|
||||
#define MOSCHIP_DEVICE_ID_7840 0x7840
|
||||
#define MOSCHIP_DEVICE_ID_7820 0x7820
|
||||
#define MOSCHIP_DEVICE_ID_7810 0x7810
|
||||
/* The native component can have its vendor/device id's overridden
|
||||
* in vendor-specific implementations. Such devices can be handled
|
||||
* by making a change here, in moschip_port_id_table, and in
|
||||
@ -184,10 +185,16 @@
|
||||
#define NUM_URBS 16 /* URB Count */
|
||||
#define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */
|
||||
|
||||
/* LED on/off milliseconds*/
|
||||
#define LED_ON_MS 500
|
||||
#define LED_OFF_MS 500
|
||||
|
||||
static int device_type;
|
||||
|
||||
static const struct usb_device_id moschip_port_id_table[] = {
|
||||
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7810)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)},
|
||||
@ -209,6 +216,7 @@ static const struct usb_device_id moschip_port_id_table[] = {
|
||||
static const struct usb_device_id moschip_id_table_combined[] __devinitconst = {
|
||||
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7810)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)},
|
||||
@ -261,8 +269,13 @@ struct moschip_port {
|
||||
struct urb *write_urb_pool[NUM_URBS];
|
||||
char busy[NUM_URBS];
|
||||
bool read_urb_busy;
|
||||
};
|
||||
|
||||
/* For device(s) with LED indicator */
|
||||
bool has_led;
|
||||
bool led_flag;
|
||||
struct timer_list led_timer1; /* Timer for LED on */
|
||||
struct timer_list led_timer2; /* Timer for LED off */
|
||||
};
|
||||
|
||||
static bool debug;
|
||||
|
||||
@ -572,6 +585,69 @@ static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mos7840_set_led_callback(struct urb *urb)
|
||||
{
|
||||
switch (urb->status) {
|
||||
case 0:
|
||||
/* Success */
|
||||
break;
|
||||
case -ECONNRESET:
|
||||
case -ENOENT:
|
||||
case -ESHUTDOWN:
|
||||
/* This urb is terminated, clean up */
|
||||
dbg("%s - urb shutting down with status: %d", __func__,
|
||||
urb->status);
|
||||
break;
|
||||
default:
|
||||
dbg("%s - nonzero urb status received: %d", __func__,
|
||||
urb->status);
|
||||
}
|
||||
}
|
||||
|
||||
static void mos7840_set_led_async(struct moschip_port *mcs, __u16 wval,
|
||||
__u16 reg)
|
||||
{
|
||||
struct usb_device *dev = mcs->port->serial->dev;
|
||||
struct usb_ctrlrequest *dr = mcs->dr;
|
||||
|
||||
dr->bRequestType = MCS_WR_RTYPE;
|
||||
dr->bRequest = MCS_WRREQ;
|
||||
dr->wValue = cpu_to_le16(wval);
|
||||
dr->wIndex = cpu_to_le16(reg);
|
||||
dr->wLength = cpu_to_le16(0);
|
||||
|
||||
usb_fill_control_urb(mcs->control_urb, dev, usb_sndctrlpipe(dev, 0),
|
||||
(unsigned char *)dr, NULL, 0, mos7840_set_led_callback, NULL);
|
||||
|
||||
usb_submit_urb(mcs->control_urb, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
static void mos7840_set_led_sync(struct usb_serial_port *port, __u16 reg,
|
||||
__u16 val)
|
||||
{
|
||||
struct usb_device *dev = port->serial->dev;
|
||||
|
||||
usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, MCS_WR_RTYPE,
|
||||
val, reg, NULL, 0, MOS_WDR_TIMEOUT);
|
||||
}
|
||||
|
||||
static void mos7840_led_off(unsigned long arg)
|
||||
{
|
||||
struct moschip_port *mcs = (struct moschip_port *) arg;
|
||||
|
||||
/* Turn off LED */
|
||||
mos7840_set_led_async(mcs, 0x0300, MODEM_CONTROL_REGISTER);
|
||||
mod_timer(&mcs->led_timer2,
|
||||
jiffies + msecs_to_jiffies(LED_OFF_MS));
|
||||
}
|
||||
|
||||
static void mos7840_led_flag_off(unsigned long arg)
|
||||
{
|
||||
struct moschip_port *mcs = (struct moschip_port *) arg;
|
||||
|
||||
mcs->led_flag = false;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* mos7840_interrupt_callback
|
||||
* this is the callback function for when we have received data on the
|
||||
@ -792,6 +868,14 @@ static void mos7840_bulk_in_callback(struct urb *urb)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Turn on LED */
|
||||
if (mos7840_port->has_led && !mos7840_port->led_flag) {
|
||||
mos7840_port->led_flag = true;
|
||||
mos7840_set_led_async(mos7840_port, 0x0301,
|
||||
MODEM_CONTROL_REGISTER);
|
||||
mod_timer(&mos7840_port->led_timer1,
|
||||
jiffies + msecs_to_jiffies(LED_ON_MS));
|
||||
}
|
||||
|
||||
mos7840_port->read_urb_busy = true;
|
||||
retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
|
||||
@ -1554,6 +1638,14 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
|
||||
data1 = urb->transfer_buffer;
|
||||
dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress);
|
||||
|
||||
/* Turn on LED */
|
||||
if (mos7840_port->has_led && !mos7840_port->led_flag) {
|
||||
mos7840_port->led_flag = true;
|
||||
mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0301);
|
||||
mod_timer(&mos7840_port->led_timer1,
|
||||
jiffies + msecs_to_jiffies(LED_ON_MS));
|
||||
}
|
||||
|
||||
/* send it down the pipe */
|
||||
status = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
|
||||
@ -2327,28 +2419,74 @@ static int mos7840_ioctl(struct tty_struct *tty,
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
||||
static int mos7810_check(struct usb_serial *serial)
|
||||
{
|
||||
int i, pass_count = 0;
|
||||
__u16 data = 0, mcr_data = 0;
|
||||
__u16 test_pattern = 0x55AA;
|
||||
|
||||
/* Store MCR setting */
|
||||
usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
|
||||
MCS_RDREQ, MCS_RD_RTYPE, 0x0300, MODEM_CONTROL_REGISTER,
|
||||
&mcr_data, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
/* Send the 1-bit test pattern out to MCS7810 test pin */
|
||||
usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
|
||||
MCS_WRREQ, MCS_WR_RTYPE,
|
||||
(0x0300 | (((test_pattern >> i) & 0x0001) << 1)),
|
||||
MODEM_CONTROL_REGISTER, NULL, 0, MOS_WDR_TIMEOUT);
|
||||
|
||||
/* Read the test pattern back */
|
||||
usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
|
||||
MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &data,
|
||||
VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
|
||||
|
||||
/* If this is a MCS7810 device, both test patterns must match */
|
||||
if (((test_pattern >> i) ^ (~data >> 1)) & 0x0001)
|
||||
break;
|
||||
|
||||
pass_count++;
|
||||
}
|
||||
|
||||
/* Restore MCR setting */
|
||||
usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), MCS_WRREQ,
|
||||
MCS_WR_RTYPE, 0x0300 | mcr_data, MODEM_CONTROL_REGISTER, NULL,
|
||||
0, MOS_WDR_TIMEOUT);
|
||||
|
||||
if (pass_count == 16)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mos7840_calc_num_ports(struct usb_serial *serial)
|
||||
{
|
||||
__u16 Data = 0x00;
|
||||
int ret = 0;
|
||||
__u16 data = 0x00;
|
||||
int mos7840_num_ports;
|
||||
|
||||
ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
|
||||
MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &Data,
|
||||
usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
|
||||
MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &data,
|
||||
VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
|
||||
|
||||
if ((Data & 0x01) == 0) {
|
||||
mos7840_num_ports = 2;
|
||||
serial->num_bulk_in = 2;
|
||||
serial->num_bulk_out = 2;
|
||||
serial->num_ports = 2;
|
||||
if (serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7810 ||
|
||||
serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7820) {
|
||||
device_type = serial->dev->descriptor.idProduct;
|
||||
} else {
|
||||
mos7840_num_ports = 4;
|
||||
serial->num_bulk_in = 4;
|
||||
serial->num_bulk_out = 4;
|
||||
serial->num_ports = 4;
|
||||
/* For a MCS7840 device GPIO0 must be set to 1 */
|
||||
if ((data & 0x01) == 1)
|
||||
device_type = MOSCHIP_DEVICE_ID_7840;
|
||||
else if (mos7810_check(serial))
|
||||
device_type = MOSCHIP_DEVICE_ID_7810;
|
||||
else
|
||||
device_type = MOSCHIP_DEVICE_ID_7820;
|
||||
}
|
||||
|
||||
mos7840_num_ports = (device_type >> 4) & 0x000F;
|
||||
serial->num_bulk_in = mos7840_num_ports;
|
||||
serial->num_bulk_out = mos7840_num_ports;
|
||||
serial->num_ports = mos7840_num_ports;
|
||||
|
||||
return mos7840_num_ports;
|
||||
}
|
||||
|
||||
@ -2563,6 +2701,34 @@ static int mos7840_startup(struct usb_serial *serial)
|
||||
status = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
mos7840_port->has_led = false;
|
||||
|
||||
/* Initialize LED timers */
|
||||
if (device_type == MOSCHIP_DEVICE_ID_7810) {
|
||||
mos7840_port->has_led = true;
|
||||
|
||||
init_timer(&mos7840_port->led_timer1);
|
||||
mos7840_port->led_timer1.function = mos7840_led_off;
|
||||
mos7840_port->led_timer1.expires =
|
||||
jiffies + msecs_to_jiffies(LED_ON_MS);
|
||||
mos7840_port->led_timer1.data =
|
||||
(unsigned long)mos7840_port;
|
||||
|
||||
init_timer(&mos7840_port->led_timer2);
|
||||
mos7840_port->led_timer2.function =
|
||||
mos7840_led_flag_off;
|
||||
mos7840_port->led_timer2.expires =
|
||||
jiffies + msecs_to_jiffies(LED_OFF_MS);
|
||||
mos7840_port->led_timer2.data =
|
||||
(unsigned long)mos7840_port;
|
||||
|
||||
mos7840_port->led_flag = false;
|
||||
|
||||
/* Turn off LED */
|
||||
mos7840_set_led_sync(serial->port[i],
|
||||
MODEM_CONTROL_REGISTER, 0x0300);
|
||||
}
|
||||
}
|
||||
dbg ("mos7840_startup: all ports configured...........");
|
||||
|
||||
@ -2654,6 +2820,14 @@ static void mos7840_release(struct usb_serial *serial)
|
||||
mos7840_port = mos7840_get_port_private(serial->port[i]);
|
||||
dbg("mos7840_port %d = %p", i, mos7840_port);
|
||||
if (mos7840_port) {
|
||||
if (mos7840_port->has_led) {
|
||||
/* Turn off LED */
|
||||
mos7840_set_led_sync(mos7840_port->port,
|
||||
MODEM_CONTROL_REGISTER, 0x0300);
|
||||
|
||||
del_timer_sync(&mos7840_port->led_timer1);
|
||||
del_timer_sync(&mos7840_port->led_timer2);
|
||||
}
|
||||
kfree(mos7840_port->ctrl_buf);
|
||||
kfree(mos7840_port->dr);
|
||||
kfree(mos7840_port);
|
||||
|
@ -1413,7 +1413,7 @@ static void option_instat_callback(struct urb *urb)
|
||||
req_pkt->bRequestType, req_pkt->bRequest);
|
||||
}
|
||||
} else
|
||||
err("%s: error %d", __func__, status);
|
||||
dev_err(&port->dev, "%s: error %d\n", __func__, status);
|
||||
|
||||
/* Resubmit urb so we continue receiving IRQ data */
|
||||
if (status != -ESHUTDOWN && status != -ENOENT) {
|
||||
|
@ -394,7 +394,9 @@ static int ti_startup(struct usb_serial *serial)
|
||||
|
||||
/* if we have only 1 configuration, download firmware */
|
||||
if (dev->descriptor.bNumConfigurations == 1) {
|
||||
if ((status = ti_download_firmware(tdev)) != 0)
|
||||
status = ti_download_firmware(tdev);
|
||||
|
||||
if (status != 0)
|
||||
goto free_tdev;
|
||||
|
||||
/* 3410 must be reset, 5052 resets itself */
|
||||
@ -1683,7 +1685,9 @@ static int ti_download_firmware(struct ti_device *tdev)
|
||||
/* try ID specific firmware first, then try generic firmware */
|
||||
sprintf(buf, "ti_usb-v%04x-p%04x.fw", dev->descriptor.idVendor,
|
||||
dev->descriptor.idProduct);
|
||||
if ((status = request_firmware(&fw_p, buf, &dev->dev)) != 0) {
|
||||
status = request_firmware(&fw_p, buf, &dev->dev);
|
||||
|
||||
if (status != 0) {
|
||||
buf[0] = '\0';
|
||||
if (dev->descriptor.idVendor == MTS_VENDOR_ID) {
|
||||
switch (dev->descriptor.idProduct) {
|
||||
|
@ -725,8 +725,8 @@ int usb_wwan_resume(struct usb_serial *serial)
|
||||
err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
|
||||
dbg("Submitted interrupt URB for port %d (result %d)", i, err);
|
||||
if (err < 0) {
|
||||
err("%s: Error %d for interrupt URB of port%d",
|
||||
__func__, err, i);
|
||||
dev_err(&port->dev, "%s: Error %d for interrupt URB\n",
|
||||
__func__, err);
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
@ -747,8 +747,8 @@ int usb_wwan_resume(struct usb_serial *serial)
|
||||
urb = portdata->in_urbs[j];
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (err < 0) {
|
||||
err("%s: Error %d for bulk URB %d",
|
||||
__func__, err, i);
|
||||
dev_err(&port->dev, "%s: Error %d for bulk URB %d\n",
|
||||
__func__, err, i);
|
||||
spin_unlock_irq(&intfdata->susp_lock);
|
||||
goto err_out;
|
||||
}
|
||||
|
@ -53,8 +53,6 @@ static int palm_os_4_probe(struct usb_serial *serial,
|
||||
|
||||
/* Parameters that may be passed into the module. */
|
||||
static bool debug;
|
||||
static __u16 vendor;
|
||||
static __u16 product;
|
||||
|
||||
static struct usb_device_id id_table [] = {
|
||||
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID),
|
||||
@ -115,14 +113,12 @@ static struct usb_device_id id_table [] = {
|
||||
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
|
||||
{ USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID),
|
||||
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
|
||||
{ }, /* optional parameter entry */
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
static struct usb_device_id clie_id_5_table [] = {
|
||||
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID),
|
||||
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
|
||||
{ }, /* optional parameter entry */
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
@ -162,7 +158,6 @@ static struct usb_device_id id_table_combined [] = {
|
||||
{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) },
|
||||
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID) },
|
||||
{ USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID) },
|
||||
{ }, /* optional parameter entry */
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
@ -648,59 +643,7 @@ static int clie_5_attach(struct usb_serial *serial)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init visor_init(void)
|
||||
{
|
||||
int i, retval;
|
||||
/* Only if parameters were passed to us */
|
||||
if (vendor > 0 && product > 0) {
|
||||
struct usb_device_id usb_dev_temp[] = {
|
||||
{
|
||||
USB_DEVICE(vendor, product),
|
||||
.driver_info =
|
||||
(kernel_ulong_t) &palm_os_4_probe
|
||||
}
|
||||
};
|
||||
|
||||
/* Find the last entry in id_table */
|
||||
for (i = 0;; i++) {
|
||||
if (id_table[i].idVendor == 0) {
|
||||
id_table[i] = usb_dev_temp[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Find the last entry in id_table_combined */
|
||||
for (i = 0;; i++) {
|
||||
if (id_table_combined[i].idVendor == 0) {
|
||||
id_table_combined[i] = usb_dev_temp[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
printk(KERN_INFO KBUILD_MODNAME
|
||||
": Untested USB device specified at time of module insertion\n");
|
||||
printk(KERN_INFO KBUILD_MODNAME
|
||||
": Warning: This is not guaranteed to work\n");
|
||||
printk(KERN_INFO KBUILD_MODNAME
|
||||
": Using a newer kernel is preferred to this method\n");
|
||||
printk(KERN_INFO KBUILD_MODNAME
|
||||
": Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x\n",
|
||||
vendor, product);
|
||||
}
|
||||
|
||||
retval = usb_serial_register_drivers(&visor_driver, serial_drivers);
|
||||
if (retval == 0)
|
||||
printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static void __exit visor_exit (void)
|
||||
{
|
||||
usb_serial_deregister_drivers(&visor_driver, serial_drivers);
|
||||
}
|
||||
|
||||
|
||||
module_init(visor_init);
|
||||
module_exit(visor_exit);
|
||||
module_usb_serial_driver(visor_driver, serial_drivers);
|
||||
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
@ -708,9 +651,3 @@ MODULE_LICENSE("GPL");
|
||||
|
||||
module_param(debug, bool, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(debug, "Debug enabled or not");
|
||||
|
||||
module_param(vendor, ushort, 0);
|
||||
MODULE_PARM_DESC(vendor, "User specified vendor ID");
|
||||
module_param(product, ushort, 0);
|
||||
MODULE_PARM_DESC(product, "User specified product ID");
|
||||
|
||||
|
@ -45,7 +45,6 @@ static bool debug;
|
||||
/*
|
||||
* Version Information
|
||||
*/
|
||||
#define DRIVER_VERSION "v2.0"
|
||||
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Stuart MacDonald <stuartm@connecttech.com>"
|
||||
#define DRIVER_DESC "USB ConnectTech WhiteHEAT driver"
|
||||
|
||||
@ -96,10 +95,6 @@ static void whiteheat_release(struct usb_serial *serial);
|
||||
static int whiteheat_open(struct tty_struct *tty,
|
||||
struct usb_serial_port *port);
|
||||
static void whiteheat_close(struct usb_serial_port *port);
|
||||
static int whiteheat_write(struct tty_struct *tty,
|
||||
struct usb_serial_port *port,
|
||||
const unsigned char *buf, int count);
|
||||
static int whiteheat_write_room(struct tty_struct *tty);
|
||||
static int whiteheat_ioctl(struct tty_struct *tty,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
static void whiteheat_set_termios(struct tty_struct *tty,
|
||||
@ -108,11 +103,6 @@ static int whiteheat_tiocmget(struct tty_struct *tty);
|
||||
static int whiteheat_tiocmset(struct tty_struct *tty,
|
||||
unsigned int set, unsigned int clear);
|
||||
static void whiteheat_break_ctl(struct tty_struct *tty, int break_state);
|
||||
static int whiteheat_chars_in_buffer(struct tty_struct *tty);
|
||||
static void whiteheat_throttle(struct tty_struct *tty);
|
||||
static void whiteheat_unthrottle(struct tty_struct *tty);
|
||||
static void whiteheat_read_callback(struct urb *urb);
|
||||
static void whiteheat_write_callback(struct urb *urb);
|
||||
|
||||
static struct usb_serial_driver whiteheat_fake_device = {
|
||||
.driver = {
|
||||
@ -138,18 +128,13 @@ static struct usb_serial_driver whiteheat_device = {
|
||||
.release = whiteheat_release,
|
||||
.open = whiteheat_open,
|
||||
.close = whiteheat_close,
|
||||
.write = whiteheat_write,
|
||||
.write_room = whiteheat_write_room,
|
||||
.ioctl = whiteheat_ioctl,
|
||||
.set_termios = whiteheat_set_termios,
|
||||
.break_ctl = whiteheat_break_ctl,
|
||||
.tiocmget = whiteheat_tiocmget,
|
||||
.tiocmset = whiteheat_tiocmset,
|
||||
.chars_in_buffer = whiteheat_chars_in_buffer,
|
||||
.throttle = whiteheat_throttle,
|
||||
.unthrottle = whiteheat_unthrottle,
|
||||
.read_bulk_callback = whiteheat_read_callback,
|
||||
.write_bulk_callback = whiteheat_write_callback,
|
||||
.throttle = usb_serial_generic_throttle,
|
||||
.unthrottle = usb_serial_generic_unthrottle,
|
||||
};
|
||||
|
||||
static struct usb_serial_driver * const serial_drivers[] = {
|
||||
@ -166,29 +151,8 @@ struct whiteheat_command_private {
|
||||
__u8 result_buffer[64];
|
||||
};
|
||||
|
||||
|
||||
#define THROTTLED 0x01
|
||||
#define ACTUALLY_THROTTLED 0x02
|
||||
|
||||
static int urb_pool_size = 8;
|
||||
|
||||
struct whiteheat_urb_wrap {
|
||||
struct list_head list;
|
||||
struct urb *urb;
|
||||
};
|
||||
|
||||
struct whiteheat_private {
|
||||
spinlock_t lock;
|
||||
__u8 flags;
|
||||
__u8 mcr; /* FIXME: no locking on mcr */
|
||||
struct list_head rx_urbs_free;
|
||||
struct list_head rx_urbs_submitted;
|
||||
struct list_head rx_urb_q;
|
||||
struct work_struct rx_work;
|
||||
struct usb_serial_port *port;
|
||||
struct list_head tx_urbs_free;
|
||||
struct list_head tx_urbs_submitted;
|
||||
struct mutex deathwarrant;
|
||||
};
|
||||
|
||||
|
||||
@ -198,12 +162,6 @@ static void stop_command_port(struct usb_serial *serial);
|
||||
static void command_port_write_callback(struct urb *urb);
|
||||
static void command_port_read_callback(struct urb *urb);
|
||||
|
||||
static int start_port_read(struct usb_serial_port *port);
|
||||
static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb,
|
||||
struct list_head *head);
|
||||
static struct list_head *list_first(struct list_head *head);
|
||||
static void rx_data_softint(struct work_struct *work);
|
||||
|
||||
static int firm_send_command(struct usb_serial_port *port, __u8 command,
|
||||
__u8 *data, __u8 datasize);
|
||||
static int firm_open(struct usb_serial_port *port);
|
||||
@ -349,11 +307,6 @@ static int whiteheat_attach(struct usb_serial *serial)
|
||||
__u8 *command;
|
||||
__u8 *result;
|
||||
int i;
|
||||
int j;
|
||||
struct urb *urb;
|
||||
int buf_size;
|
||||
struct whiteheat_urb_wrap *wrap;
|
||||
struct list_head *tmp;
|
||||
|
||||
command_port = serial->port[COMMAND_PORT];
|
||||
|
||||
@ -408,8 +361,8 @@ static int whiteheat_attach(struct usb_serial *serial)
|
||||
|
||||
hw_info = (struct whiteheat_hw_info *)&result[1];
|
||||
|
||||
dev_info(&serial->dev->dev, "%s: Driver %s: Firmware v%d.%02d\n",
|
||||
serial->type->description, DRIVER_VERSION,
|
||||
dev_info(&serial->dev->dev, "%s: Firmware v%d.%02d\n",
|
||||
serial->type->description,
|
||||
hw_info->sw_major_rev, hw_info->sw_minor_rev);
|
||||
|
||||
for (i = 0; i < serial->num_ports; i++) {
|
||||
@ -423,72 +376,7 @@ static int whiteheat_attach(struct usb_serial *serial)
|
||||
goto no_private;
|
||||
}
|
||||
|
||||
spin_lock_init(&info->lock);
|
||||
mutex_init(&info->deathwarrant);
|
||||
info->flags = 0;
|
||||
info->mcr = 0;
|
||||
INIT_WORK(&info->rx_work, rx_data_softint);
|
||||
info->port = port;
|
||||
|
||||
INIT_LIST_HEAD(&info->rx_urbs_free);
|
||||
INIT_LIST_HEAD(&info->rx_urbs_submitted);
|
||||
INIT_LIST_HEAD(&info->rx_urb_q);
|
||||
INIT_LIST_HEAD(&info->tx_urbs_free);
|
||||
INIT_LIST_HEAD(&info->tx_urbs_submitted);
|
||||
|
||||
for (j = 0; j < urb_pool_size; j++) {
|
||||
urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!urb) {
|
||||
dev_err(&port->dev, "No free urbs available\n");
|
||||
goto no_rx_urb;
|
||||
}
|
||||
buf_size = port->read_urb->transfer_buffer_length;
|
||||
urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL);
|
||||
if (!urb->transfer_buffer) {
|
||||
dev_err(&port->dev,
|
||||
"Couldn't allocate urb buffer\n");
|
||||
goto no_rx_buf;
|
||||
}
|
||||
wrap = kmalloc(sizeof(*wrap), GFP_KERNEL);
|
||||
if (!wrap) {
|
||||
dev_err(&port->dev,
|
||||
"Couldn't allocate urb wrapper\n");
|
||||
goto no_rx_wrap;
|
||||
}
|
||||
usb_fill_bulk_urb(urb, serial->dev,
|
||||
usb_rcvbulkpipe(serial->dev,
|
||||
port->bulk_in_endpointAddress),
|
||||
urb->transfer_buffer, buf_size,
|
||||
whiteheat_read_callback, port);
|
||||
wrap->urb = urb;
|
||||
list_add(&wrap->list, &info->rx_urbs_free);
|
||||
|
||||
urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!urb) {
|
||||
dev_err(&port->dev, "No free urbs available\n");
|
||||
goto no_tx_urb;
|
||||
}
|
||||
buf_size = port->write_urb->transfer_buffer_length;
|
||||
urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL);
|
||||
if (!urb->transfer_buffer) {
|
||||
dev_err(&port->dev,
|
||||
"Couldn't allocate urb buffer\n");
|
||||
goto no_tx_buf;
|
||||
}
|
||||
wrap = kmalloc(sizeof(*wrap), GFP_KERNEL);
|
||||
if (!wrap) {
|
||||
dev_err(&port->dev,
|
||||
"Couldn't allocate urb wrapper\n");
|
||||
goto no_tx_wrap;
|
||||
}
|
||||
usb_fill_bulk_urb(urb, serial->dev,
|
||||
usb_sndbulkpipe(serial->dev,
|
||||
port->bulk_out_endpointAddress),
|
||||
urb->transfer_buffer, buf_size,
|
||||
whiteheat_write_callback, port);
|
||||
wrap->urb = urb;
|
||||
list_add(&wrap->list, &info->tx_urbs_free);
|
||||
}
|
||||
|
||||
usb_set_serial_port_data(port, info);
|
||||
}
|
||||
@ -531,29 +419,6 @@ static int whiteheat_attach(struct usb_serial *serial)
|
||||
for (i = serial->num_ports - 1; i >= 0; i--) {
|
||||
port = serial->port[i];
|
||||
info = usb_get_serial_port_data(port);
|
||||
for (j = urb_pool_size - 1; j >= 0; j--) {
|
||||
tmp = list_first(&info->tx_urbs_free);
|
||||
list_del(tmp);
|
||||
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
|
||||
urb = wrap->urb;
|
||||
kfree(wrap);
|
||||
no_tx_wrap:
|
||||
kfree(urb->transfer_buffer);
|
||||
no_tx_buf:
|
||||
usb_free_urb(urb);
|
||||
no_tx_urb:
|
||||
tmp = list_first(&info->rx_urbs_free);
|
||||
list_del(tmp);
|
||||
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
|
||||
urb = wrap->urb;
|
||||
kfree(wrap);
|
||||
no_rx_wrap:
|
||||
kfree(urb->transfer_buffer);
|
||||
no_rx_buf:
|
||||
usb_free_urb(urb);
|
||||
no_rx_urb:
|
||||
;
|
||||
}
|
||||
kfree(info);
|
||||
no_private:
|
||||
;
|
||||
@ -569,12 +434,7 @@ static int whiteheat_attach(struct usb_serial *serial)
|
||||
static void whiteheat_release(struct usb_serial *serial)
|
||||
{
|
||||
struct usb_serial_port *command_port;
|
||||
struct usb_serial_port *port;
|
||||
struct whiteheat_private *info;
|
||||
struct whiteheat_urb_wrap *wrap;
|
||||
struct urb *urb;
|
||||
struct list_head *tmp;
|
||||
struct list_head *tmp2;
|
||||
int i;
|
||||
|
||||
dbg("%s", __func__);
|
||||
@ -584,31 +444,14 @@ static void whiteheat_release(struct usb_serial *serial)
|
||||
kfree(usb_get_serial_port_data(command_port));
|
||||
|
||||
for (i = 0; i < serial->num_ports; i++) {
|
||||
port = serial->port[i];
|
||||
info = usb_get_serial_port_data(port);
|
||||
list_for_each_safe(tmp, tmp2, &info->rx_urbs_free) {
|
||||
list_del(tmp);
|
||||
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
|
||||
urb = wrap->urb;
|
||||
kfree(wrap);
|
||||
kfree(urb->transfer_buffer);
|
||||
usb_free_urb(urb);
|
||||
}
|
||||
list_for_each_safe(tmp, tmp2, &info->tx_urbs_free) {
|
||||
list_del(tmp);
|
||||
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
|
||||
urb = wrap->urb;
|
||||
kfree(wrap);
|
||||
kfree(urb->transfer_buffer);
|
||||
usb_free_urb(urb);
|
||||
}
|
||||
info = usb_get_serial_port_data(serial->port[i]);
|
||||
kfree(info);
|
||||
}
|
||||
}
|
||||
|
||||
static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||
{
|
||||
int retval = 0;
|
||||
int retval;
|
||||
|
||||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
@ -616,9 +459,6 @@ static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||
if (retval)
|
||||
goto exit;
|
||||
|
||||
if (tty)
|
||||
tty->low_latency = 1;
|
||||
|
||||
/* send an open port command */
|
||||
retval = firm_open(port);
|
||||
if (retval) {
|
||||
@ -640,17 +480,12 @@ static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||
usb_clear_halt(port->serial->dev, port->read_urb->pipe);
|
||||
usb_clear_halt(port->serial->dev, port->write_urb->pipe);
|
||||
|
||||
/* Start reading from the device */
|
||||
retval = start_port_read(port);
|
||||
retval = usb_serial_generic_open(tty, port);
|
||||
if (retval) {
|
||||
dev_err(&port->dev,
|
||||
"%s - failed submitting read urb, error %d\n",
|
||||
__func__, retval);
|
||||
firm_close(port);
|
||||
stop_command_port(port->serial);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
dbg("%s - exit, retval = %d", __func__, retval);
|
||||
return retval;
|
||||
@ -659,127 +494,16 @@ static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||
|
||||
static void whiteheat_close(struct usb_serial_port *port)
|
||||
{
|
||||
struct whiteheat_private *info = usb_get_serial_port_data(port);
|
||||
struct whiteheat_urb_wrap *wrap;
|
||||
struct urb *urb;
|
||||
struct list_head *tmp;
|
||||
struct list_head *tmp2;
|
||||
|
||||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
firm_report_tx_done(port);
|
||||
firm_close(port);
|
||||
|
||||
/* shutdown our bulk reads and writes */
|
||||
mutex_lock(&info->deathwarrant);
|
||||
spin_lock_irq(&info->lock);
|
||||
list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
|
||||
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
|
||||
urb = wrap->urb;
|
||||
list_del(tmp);
|
||||
spin_unlock_irq(&info->lock);
|
||||
usb_kill_urb(urb);
|
||||
spin_lock_irq(&info->lock);
|
||||
list_add(tmp, &info->rx_urbs_free);
|
||||
}
|
||||
list_for_each_safe(tmp, tmp2, &info->rx_urb_q)
|
||||
list_move(tmp, &info->rx_urbs_free);
|
||||
list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) {
|
||||
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
|
||||
urb = wrap->urb;
|
||||
list_del(tmp);
|
||||
spin_unlock_irq(&info->lock);
|
||||
usb_kill_urb(urb);
|
||||
spin_lock_irq(&info->lock);
|
||||
list_add(tmp, &info->tx_urbs_free);
|
||||
}
|
||||
spin_unlock_irq(&info->lock);
|
||||
mutex_unlock(&info->deathwarrant);
|
||||
usb_serial_generic_close(port);
|
||||
|
||||
stop_command_port(port->serial);
|
||||
}
|
||||
|
||||
|
||||
static int whiteheat_write(struct tty_struct *tty,
|
||||
struct usb_serial_port *port, const unsigned char *buf, int count)
|
||||
{
|
||||
struct whiteheat_private *info = usb_get_serial_port_data(port);
|
||||
struct whiteheat_urb_wrap *wrap;
|
||||
struct urb *urb;
|
||||
int result;
|
||||
int bytes;
|
||||
int sent = 0;
|
||||
unsigned long flags;
|
||||
struct list_head *tmp;
|
||||
|
||||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
if (count == 0) {
|
||||
dbg("%s - write request of 0 bytes", __func__);
|
||||
return (0);
|
||||
}
|
||||
|
||||
while (count) {
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
if (list_empty(&info->tx_urbs_free)) {
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
break;
|
||||
}
|
||||
tmp = list_first(&info->tx_urbs_free);
|
||||
list_del(tmp);
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
|
||||
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
|
||||
urb = wrap->urb;
|
||||
bytes = (count > port->bulk_out_size) ?
|
||||
port->bulk_out_size : count;
|
||||
memcpy(urb->transfer_buffer, buf + sent, bytes);
|
||||
|
||||
usb_serial_debug_data(debug, &port->dev,
|
||||
__func__, bytes, urb->transfer_buffer);
|
||||
|
||||
urb->transfer_buffer_length = bytes;
|
||||
result = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (result) {
|
||||
dev_err_console(port,
|
||||
"%s - failed submitting write urb, error %d\n",
|
||||
__func__, result);
|
||||
sent = result;
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
list_add(tmp, &info->tx_urbs_free);
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
break;
|
||||
} else {
|
||||
sent += bytes;
|
||||
count -= bytes;
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
list_add(tmp, &info->tx_urbs_submitted);
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
static int whiteheat_write_room(struct tty_struct *tty)
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
struct whiteheat_private *info = usb_get_serial_port_data(port);
|
||||
struct list_head *tmp;
|
||||
int room = 0;
|
||||
unsigned long flags;
|
||||
|
||||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
list_for_each(tmp, &info->tx_urbs_free)
|
||||
room++;
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
room *= port->bulk_out_size;
|
||||
|
||||
dbg("%s - returns %d", __func__, room);
|
||||
return (room);
|
||||
}
|
||||
|
||||
static int whiteheat_tiocmget(struct tty_struct *tty)
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
@ -837,7 +561,7 @@ static int whiteheat_ioctl(struct tty_struct *tty,
|
||||
serstruct.line = port->serial->minor;
|
||||
serstruct.port = port->number;
|
||||
serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
|
||||
serstruct.xmit_fifo_size = port->bulk_out_size;
|
||||
serstruct.xmit_fifo_size = kfifo_size(&port->write_fifo);
|
||||
serstruct.custom_divisor = 0;
|
||||
serstruct.baud_base = 460800;
|
||||
serstruct.close_delay = CLOSING_DELAY;
|
||||
@ -867,60 +591,6 @@ static void whiteheat_break_ctl(struct tty_struct *tty, int break_state)
|
||||
}
|
||||
|
||||
|
||||
static int whiteheat_chars_in_buffer(struct tty_struct *tty)
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
struct whiteheat_private *info = usb_get_serial_port_data(port);
|
||||
struct list_head *tmp;
|
||||
struct whiteheat_urb_wrap *wrap;
|
||||
int chars = 0;
|
||||
unsigned long flags;
|
||||
|
||||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
list_for_each(tmp, &info->tx_urbs_submitted) {
|
||||
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
|
||||
chars += wrap->urb->transfer_buffer_length;
|
||||
}
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
|
||||
dbg("%s - returns %d", __func__, chars);
|
||||
return chars;
|
||||
}
|
||||
|
||||
|
||||
static void whiteheat_throttle(struct tty_struct *tty)
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
struct whiteheat_private *info = usb_get_serial_port_data(port);
|
||||
|
||||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
spin_lock_irq(&info->lock);
|
||||
info->flags |= THROTTLED;
|
||||
spin_unlock_irq(&info->lock);
|
||||
}
|
||||
|
||||
|
||||
static void whiteheat_unthrottle(struct tty_struct *tty)
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
struct whiteheat_private *info = usb_get_serial_port_data(port);
|
||||
int actually_throttled;
|
||||
|
||||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
spin_lock_irq(&info->lock);
|
||||
actually_throttled = info->flags & ACTUALLY_THROTTLED;
|
||||
info->flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
|
||||
spin_unlock_irq(&info->lock);
|
||||
|
||||
if (actually_throttled)
|
||||
rx_data_softint(&info->rx_work);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Connect Tech's White Heat callback routines
|
||||
*****************************************************************************/
|
||||
@ -989,80 +659,6 @@ static void command_port_read_callback(struct urb *urb)
|
||||
}
|
||||
|
||||
|
||||
static void whiteheat_read_callback(struct urb *urb)
|
||||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
struct whiteheat_urb_wrap *wrap;
|
||||
unsigned char *data = urb->transfer_buffer;
|
||||
struct whiteheat_private *info = usb_get_serial_port_data(port);
|
||||
int status = urb->status;
|
||||
|
||||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
spin_lock(&info->lock);
|
||||
wrap = urb_to_wrap(urb, &info->rx_urbs_submitted);
|
||||
if (!wrap) {
|
||||
spin_unlock(&info->lock);
|
||||
dev_err(&port->dev, "%s - Not my urb!\n", __func__);
|
||||
return;
|
||||
}
|
||||
list_del(&wrap->list);
|
||||
spin_unlock(&info->lock);
|
||||
|
||||
if (status) {
|
||||
dbg("%s - nonzero read bulk status received: %d",
|
||||
__func__, status);
|
||||
spin_lock(&info->lock);
|
||||
list_add(&wrap->list, &info->rx_urbs_free);
|
||||
spin_unlock(&info->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
usb_serial_debug_data(debug, &port->dev,
|
||||
__func__, urb->actual_length, data);
|
||||
|
||||
spin_lock(&info->lock);
|
||||
list_add_tail(&wrap->list, &info->rx_urb_q);
|
||||
if (info->flags & THROTTLED) {
|
||||
info->flags |= ACTUALLY_THROTTLED;
|
||||
spin_unlock(&info->lock);
|
||||
return;
|
||||
}
|
||||
spin_unlock(&info->lock);
|
||||
|
||||
schedule_work(&info->rx_work);
|
||||
}
|
||||
|
||||
|
||||
static void whiteheat_write_callback(struct urb *urb)
|
||||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
struct whiteheat_private *info = usb_get_serial_port_data(port);
|
||||
struct whiteheat_urb_wrap *wrap;
|
||||
int status = urb->status;
|
||||
|
||||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
spin_lock(&info->lock);
|
||||
wrap = urb_to_wrap(urb, &info->tx_urbs_submitted);
|
||||
if (!wrap) {
|
||||
spin_unlock(&info->lock);
|
||||
dev_err(&port->dev, "%s - Not my urb!\n", __func__);
|
||||
return;
|
||||
}
|
||||
list_move(&wrap->list, &info->tx_urbs_free);
|
||||
spin_unlock(&info->lock);
|
||||
|
||||
if (status) {
|
||||
dbg("%s - nonzero write bulk status received: %d",
|
||||
__func__, status);
|
||||
return;
|
||||
}
|
||||
|
||||
usb_serial_port_softint(port);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Connect Tech's White Heat firmware interface
|
||||
*****************************************************************************/
|
||||
@ -1337,123 +933,6 @@ static void stop_command_port(struct usb_serial *serial)
|
||||
mutex_unlock(&command_info->mutex);
|
||||
}
|
||||
|
||||
|
||||
static int start_port_read(struct usb_serial_port *port)
|
||||
{
|
||||
struct whiteheat_private *info = usb_get_serial_port_data(port);
|
||||
struct whiteheat_urb_wrap *wrap;
|
||||
struct urb *urb;
|
||||
int retval = 0;
|
||||
unsigned long flags;
|
||||
struct list_head *tmp;
|
||||
struct list_head *tmp2;
|
||||
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
|
||||
list_for_each_safe(tmp, tmp2, &info->rx_urbs_free) {
|
||||
list_del(tmp);
|
||||
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
|
||||
urb = wrap->urb;
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
retval = usb_submit_urb(urb, GFP_KERNEL);
|
||||
if (retval) {
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
list_add(tmp, &info->rx_urbs_free);
|
||||
list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
|
||||
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
|
||||
urb = wrap->urb;
|
||||
list_del(tmp);
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
usb_kill_urb(urb);
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
list_add(tmp, &info->rx_urbs_free);
|
||||
}
|
||||
break;
|
||||
}
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
list_add(tmp, &info->rx_urbs_submitted);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct whiteheat_urb_wrap *wrap;
|
||||
struct list_head *tmp;
|
||||
|
||||
list_for_each(tmp, head) {
|
||||
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
|
||||
if (wrap->urb == urb)
|
||||
return wrap;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static struct list_head *list_first(struct list_head *head)
|
||||
{
|
||||
return head->next;
|
||||
}
|
||||
|
||||
|
||||
static void rx_data_softint(struct work_struct *work)
|
||||
{
|
||||
struct whiteheat_private *info =
|
||||
container_of(work, struct whiteheat_private, rx_work);
|
||||
struct usb_serial_port *port = info->port;
|
||||
struct tty_struct *tty = tty_port_tty_get(&port->port);
|
||||
struct whiteheat_urb_wrap *wrap;
|
||||
struct urb *urb;
|
||||
unsigned long flags;
|
||||
struct list_head *tmp;
|
||||
struct list_head *tmp2;
|
||||
int result;
|
||||
int sent = 0;
|
||||
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
if (info->flags & THROTTLED) {
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
goto out;
|
||||
}
|
||||
|
||||
list_for_each_safe(tmp, tmp2, &info->rx_urb_q) {
|
||||
list_del(tmp);
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
|
||||
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
|
||||
urb = wrap->urb;
|
||||
|
||||
if (tty && urb->actual_length)
|
||||
sent += tty_insert_flip_string(tty,
|
||||
urb->transfer_buffer, urb->actual_length);
|
||||
|
||||
result = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (result) {
|
||||
dev_err(&port->dev,
|
||||
"%s - failed resubmitting read urb, error %d\n",
|
||||
__func__, result);
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
list_add(tmp, &info->rx_urbs_free);
|
||||
continue;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&info->lock, flags);
|
||||
list_add(tmp, &info->rx_urbs_submitted);
|
||||
}
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
|
||||
if (sent)
|
||||
tty_flip_buffer_push(tty);
|
||||
out:
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
module_usb_serial_driver(whiteheat_driver, serial_drivers);
|
||||
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
@ -1463,8 +942,5 @@ MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE("whiteheat.fw");
|
||||
MODULE_FIRMWARE("whiteheat_loader.fw");
|
||||
|
||||
module_param(urb_pool_size, int, 0);
|
||||
MODULE_PARM_DESC(urb_pool_size, "Number of urbs to use for buffering");
|
||||
|
||||
module_param(debug, bool, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(debug, "Debug enabled or not");
|
||||
|
@ -1933,11 +1933,7 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag)
|
||||
kfree(buf);
|
||||
|
||||
nofw:
|
||||
if (sd_fw != NULL) {
|
||||
release_firmware(sd_fw);
|
||||
sd_fw = NULL;
|
||||
}
|
||||
|
||||
release_firmware(sd_fw);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -139,6 +139,7 @@ struct bcma_device {
|
||||
u8 core_unit;
|
||||
|
||||
u32 addr;
|
||||
u32 addr1;
|
||||
u32 wrap;
|
||||
|
||||
void __iomem *io_addr;
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* Maintainer: Kumar Gala <galak@kernel.crashing.org>
|
||||
*
|
||||
* Copyright 2004 Freescale Semiconductor, Inc
|
||||
* Copyright 2004,2012 Freescale Semiconductor, Inc
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@ -17,6 +17,12 @@
|
||||
#ifndef _FSL_DEVICE_H_
|
||||
#define _FSL_DEVICE_H_
|
||||
|
||||
#define FSL_UTMI_PHY_DLY 10 /*As per P1010RM, delay for UTMI
|
||||
PHY CLK to become stable - 10ms*/
|
||||
#define FSL_USB_VER_OLD 0
|
||||
#define FSL_USB_VER_1_6 1
|
||||
#define FSL_USB_VER_2_2 2
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
@ -63,6 +69,7 @@ struct platform_device;
|
||||
|
||||
struct fsl_usb2_platform_data {
|
||||
/* board specific information */
|
||||
int controller_ver;
|
||||
enum fsl_usb2_operating_modes operating_mode;
|
||||
enum fsl_usb2_phy_modes phy_mode;
|
||||
unsigned int port_enables;
|
||||
|
28
include/linux/platform_data/ehci-sh.h
Normal file
28
include/linux/platform_data/ehci-sh.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* EHCI SuperH driver platform data
|
||||
*
|
||||
* Copyright (C) 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
|
||||
* Copyright (C) 2012 Renesas Solutions Corp.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __USB_EHCI_SH_H
|
||||
#define __USB_EHCI_SH_H
|
||||
|
||||
struct ehci_sh_platdata {
|
||||
void (*phy_init)(void); /* Phy init function */
|
||||
};
|
||||
|
||||
#endif /* __USB_EHCI_SH_H */
|
@ -1627,6 +1627,7 @@ static inline int usb_translate_errors(int error_code)
|
||||
case 0:
|
||||
case -ENOMEM:
|
||||
case -ENODEV:
|
||||
case -EOPNOTSUPP:
|
||||
return error_code;
|
||||
default:
|
||||
return -EIO;
|
||||
|
Loading…
Reference in New Issue
Block a user