USB patches for 3.14-rc1
Here's the big USB pull request for 3.14-rc1 Lots of little things all over the place, and the usual USB gadget updates, and XHCI fixes (some for an issue reported by a lot of people.) USB PHY updates as well as chipidea updates and fixes. All of these have been in the linux-next tree with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iEYEABECAAYFAlLdjwIACgkQMUfUDdst+ylBIQCgkRoR8lJc0L5lZ3fugIJL4IzZ j6AAn0nBLP6VI0cvUEi3TcrPTzv4MEuL =Yb+I -----END PGP SIGNATURE----- Merge tag 'usb-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB updates from Greg KH: "Here's the big USB pull request for 3.14-rc1 Lots of little things all over the place, and the usual USB gadget updates, and XHCI fixes (some for an issue reported by a lot of people). USB PHY updates as well as chipidea updates and fixes. All of these have been in the linux-next tree with no reported issues" * tag 'usb-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (318 commits) usb: chipidea: udc: using MultO at TD as real mult value for ISO-TX usb: chipidea: need to mask INT_STATUS when write otgsc usb: chipidea: put hw_phymode_configure before ci_usb_phy_init usb: chipidea: Fix Internal error: : 808 [#1] ARM related to STS flag usb: chipidea: imx: set CI_HDRC_IMX28_WRITE_FIX for imx28 usb: chipidea: add freescale imx28 special write register method usb: ehci: add freescale imx28 special write register method usb: core: check for valid id_table when using the RefId feature usb: cdc-wdm: resp_count can be 0 even if WDM_READ is set usb: core: bail out if user gives an unknown RefId when using new_id usb: core: allow a reference device for new_id usb: core: add sanity checks when using bInterfaceClass with new_id USB: image: correct spelling mistake in comment USB: c67x00: correct spelling mistakes in comments usb: delete non-required instances of include <linux/init.h> usb:hub set hub->change_bits when over-current happens Revert "usb: chipidea: imx: set CI_HDRC_IMX28_WRITE_FIX for imx28" xhci: Set scatter-gather limit to avoid failed block writes. xhci: Avoid infinite loop when sg urb requires too many trbs usb: gadget: remove unused variable in gr_queue_int() ...
This commit is contained in:
commit
ec513b16c4
9
Documentation/ABI/testing/configfs-usb-gadget-ffs
Normal file
9
Documentation/ABI/testing/configfs-usb-gadget-ffs
Normal file
@ -0,0 +1,9 @@
|
||||
What: /config/usb-gadget/gadget/functions/ffs.name
|
||||
Date: Nov 2013
|
||||
KenelVersion: 3.13
|
||||
Description: The purpose of this directory is to create and remove it.
|
||||
|
||||
A corresponding USB function instance is created/removed.
|
||||
There are no attributes here.
|
||||
|
||||
All parameters are set through FunctionFS.
|
8
Documentation/ABI/testing/configfs-usb-gadget-loopback
Normal file
8
Documentation/ABI/testing/configfs-usb-gadget-loopback
Normal file
@ -0,0 +1,8 @@
|
||||
What: /config/usb-gadget/gadget/functions/Loopback.name
|
||||
Date: Nov 2013
|
||||
KenelVersion: 3.13
|
||||
Description:
|
||||
The attributes:
|
||||
|
||||
qlen - depth of loopback queue
|
||||
bulk_buflen - buffer length
|
12
Documentation/ABI/testing/configfs-usb-gadget-sourcesink
Normal file
12
Documentation/ABI/testing/configfs-usb-gadget-sourcesink
Normal file
@ -0,0 +1,12 @@
|
||||
What: /config/usb-gadget/gadget/functions/SourceSink.name
|
||||
Date: Nov 2013
|
||||
KenelVersion: 3.13
|
||||
Description:
|
||||
The attributes:
|
||||
|
||||
pattern - 0 (all zeros), 1 (mod63), 2 (none)
|
||||
isoc_interval - 1..16
|
||||
isoc_maxpacket - 0 - 1023 (fs), 0 - 1024 (hs/ss)
|
||||
isoc_mult - 0..2 (hs/ss only)
|
||||
isoc_maxburst - 0..15 (ss only)
|
||||
qlen - buffer length
|
@ -50,13 +50,19 @@ Description:
|
||||
This may allow the driver to support more hardware than
|
||||
was included in the driver's static device ID support
|
||||
table at compile time. The format for the device ID is:
|
||||
idVendor idProduct bInterfaceClass.
|
||||
idVendor idProduct bInterfaceClass RefIdVendor RefIdProduct
|
||||
The vendor ID and device ID fields are required, the
|
||||
interface class is optional.
|
||||
rest is optional. The Ref* tuple can be used to tell the
|
||||
driver to use the same driver_data for the new device as
|
||||
it is used for the reference device.
|
||||
Upon successfully adding an ID, the driver will probe
|
||||
for the device and attempt to bind to it. For example:
|
||||
# echo "8086 10f5" > /sys/bus/usb/drivers/foo/new_id
|
||||
|
||||
Here add a new device (0458:7045) using driver_data from
|
||||
an already supported device (0458:704c):
|
||||
# echo "0458 7045 0 0458 704c" > /sys/bus/usb/drivers/foo/new_id
|
||||
|
||||
Reading from this file will list all dynamically added
|
||||
device IDs in the same format, with one entry per
|
||||
line. For example:
|
||||
|
16
Documentation/ABI/testing/sysfs-platform-tahvo-usb
Normal file
16
Documentation/ABI/testing/sysfs-platform-tahvo-usb
Normal file
@ -0,0 +1,16 @@
|
||||
What: /sys/bus/platform/devices/tahvo-usb/otg_mode
|
||||
Date: December 2013
|
||||
Contact: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
Description:
|
||||
Set or read the current OTG mode. Valid values are "host" and
|
||||
"peripheral".
|
||||
|
||||
Reading: returns the current mode.
|
||||
|
||||
What: /sys/bus/platform/devices/tahvo-usb/vbus
|
||||
Date: December 2013
|
||||
Contact: Aaro Koskinen <aaro.koskinen@iki.fi>
|
||||
Description:
|
||||
Read the current VBUS state.
|
||||
|
||||
Reading: returns "on" or "off".
|
15
Documentation/devicetree/bindings/phy/bcm-phy.txt
Normal file
15
Documentation/devicetree/bindings/phy/bcm-phy.txt
Normal file
@ -0,0 +1,15 @@
|
||||
BROADCOM KONA USB2 PHY
|
||||
|
||||
Required properties:
|
||||
- compatible: brcm,kona-usb2-phy
|
||||
- reg: offset and length of the PHY registers
|
||||
- #phy-cells: must be 0
|
||||
Refer to phy/phy-bindings.txt for the generic PHY binding properties
|
||||
|
||||
Example:
|
||||
|
||||
usbphy: usb-phy@3f130000 {
|
||||
compatible = "brcm,kona-usb2-phy";
|
||||
reg = <0x3f130000 0x28>;
|
||||
#phy-cells = <0>;
|
||||
};
|
@ -7,6 +7,14 @@ Required properties:
|
||||
- snps,dwc2: A generic DWC2 USB controller with default parameters.
|
||||
- reg : Should contain 1 register range (address and length)
|
||||
- interrupts : Should contain 1 interrupt
|
||||
- clocks: clock provider specifier
|
||||
- clock-names: shall be "otg"
|
||||
Refer to clk/clock-bindings.txt for generic clock consumer properties
|
||||
|
||||
Optional properties:
|
||||
- phys: phy provider specifier
|
||||
- phy-names: shall be "device"
|
||||
Refer to phy/phy-bindings.txt for generic phy consumer properties
|
||||
|
||||
Example:
|
||||
|
||||
@ -14,4 +22,8 @@ Example:
|
||||
compatible = "ralink,rt3050-usb, snps,dwc2";
|
||||
reg = <0x101c0000 40000>;
|
||||
interrupts = <18>;
|
||||
clocks = <&usb_otg_ahb_clk>;
|
||||
clock-names = "otg";
|
||||
phys = <&usbphy>;
|
||||
phy-names = "usb2-phy";
|
||||
};
|
||||
|
28
Documentation/devicetree/bindings/usb/gr-udc.txt
Normal file
28
Documentation/devicetree/bindings/usb/gr-udc.txt
Normal file
@ -0,0 +1,28 @@
|
||||
USB Peripheral Controller driver for Aeroflex Gaisler GRUSBDC.
|
||||
|
||||
The GRUSBDC USB Device Controller core is available in the GRLIB VHDL
|
||||
IP core library.
|
||||
|
||||
Note: In the ordinary environment for the core, a Leon SPARC system,
|
||||
these properties are built from information in the AMBA plug&play.
|
||||
|
||||
Required properties:
|
||||
|
||||
- name : Should be "GAISLER_USBDC" or "01_021"
|
||||
|
||||
- reg : Address and length of the register set for the device
|
||||
|
||||
- interrupts : Interrupt numbers for this device
|
||||
|
||||
Optional properties:
|
||||
|
||||
- epobufsizes : An array of buffer sizes for OUT endpoints. If the property is
|
||||
not present, or for endpoints outside of the array, 1024 is assumed by
|
||||
the driver.
|
||||
|
||||
- epibufsizes : An array of buffer sizes for IN endpoints. If the property is
|
||||
not present, or for endpoints outside of the array, 1024 is assumed by
|
||||
the driver.
|
||||
|
||||
For further information look in the documentation for the GLIB IP core library:
|
||||
http://www.gaisler.com/products/grlib/grip.pdf
|
@ -87,6 +87,8 @@ Required properties:
|
||||
e.g. USB3 PHY and SATA PHY on OMAP5.
|
||||
"ti,control-phy-dra7usb2" - if it has power down register like USB2 PHY on
|
||||
DRA7 platform.
|
||||
"ti,control-phy-am437usb2" - if it has power down register like USB2 PHY on
|
||||
AM437 platform.
|
||||
- reg : Address and length of the register set for the device. It contains
|
||||
the address of "otghs_control" for control-phy-otghs or "power" register
|
||||
for other types.
|
||||
|
@ -8,43 +8,7 @@
|
||||
#define is_usb0_device(config) 0
|
||||
#endif
|
||||
|
||||
struct omap_usb_config {
|
||||
/* Configure drivers according to the connectors on your board:
|
||||
* - "A" connector (rectagular)
|
||||
* ... for host/OHCI use, set "register_host".
|
||||
* - "B" connector (squarish) or "Mini-B"
|
||||
* ... for device/gadget use, set "register_dev".
|
||||
* - "Mini-AB" connector (very similar to Mini-B)
|
||||
* ... for OTG use as device OR host, initialize "otg"
|
||||
*/
|
||||
unsigned register_host:1;
|
||||
unsigned register_dev:1;
|
||||
u8 otg; /* port number, 1-based: usb1 == 2 */
|
||||
|
||||
u8 hmc_mode;
|
||||
|
||||
/* implicitly true if otg: host supports remote wakeup? */
|
||||
u8 rwc;
|
||||
|
||||
/* signaling pins used to talk to transceiver on usbN:
|
||||
* 0 == usbN unused
|
||||
* 2 == usb0-only, using internal transceiver
|
||||
* 3 == 3 wire bidirectional
|
||||
* 4 == 4 wire bidirectional
|
||||
* 6 == 6 wire unidirectional (or TLL)
|
||||
*/
|
||||
u8 pins[3];
|
||||
|
||||
struct platform_device *udc_device;
|
||||
struct platform_device *ohci_device;
|
||||
struct platform_device *otg_device;
|
||||
|
||||
u32 (*usb0_init)(unsigned nwires, unsigned is_device);
|
||||
u32 (*usb1_init)(unsigned nwires);
|
||||
u32 (*usb2_init)(unsigned nwires, unsigned alt_pingroup);
|
||||
|
||||
int (*ocpi_enable)(void);
|
||||
};
|
||||
#include <linux/platform_data/usb-omap1.h>
|
||||
|
||||
void omap_otg_init(struct omap_usb_config *config);
|
||||
|
||||
|
@ -57,4 +57,10 @@ config PHY_EXYNOS_DP_VIDEO
|
||||
help
|
||||
Support for Display Port PHY found on Samsung EXYNOS SoCs.
|
||||
|
||||
config BCM_KONA_USB2_PHY
|
||||
tristate "Broadcom Kona USB2 PHY Driver"
|
||||
depends on GENERIC_PHY
|
||||
help
|
||||
Enable this to support the Broadcom Kona USB 2.0 PHY.
|
||||
|
||||
endmenu
|
||||
|
@ -3,6 +3,7 @@
|
||||
#
|
||||
|
||||
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
|
||||
obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o
|
||||
obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
|
||||
obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
|
||||
obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
|
||||
|
158
drivers/phy/phy-bcm-kona-usb2.c
Normal file
158
drivers/phy/phy-bcm-kona-usb2.c
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* phy-bcm-kona-usb2.c - Broadcom Kona USB2 Phy Driver
|
||||
*
|
||||
* Copyright (C) 2013 Linaro Limited
|
||||
* Matt Porter <mporter@linaro.org>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define OTGCTL (0)
|
||||
#define OTGCTL_OTGSTAT2 BIT(31)
|
||||
#define OTGCTL_OTGSTAT1 BIT(30)
|
||||
#define OTGCTL_PRST_N_SW BIT(11)
|
||||
#define OTGCTL_HRESET_N BIT(10)
|
||||
#define OTGCTL_UTMI_LINE_STATE1 BIT(9)
|
||||
#define OTGCTL_UTMI_LINE_STATE0 BIT(8)
|
||||
|
||||
#define P1CTL (8)
|
||||
#define P1CTL_SOFT_RESET BIT(1)
|
||||
#define P1CTL_NON_DRIVING BIT(0)
|
||||
|
||||
struct bcm_kona_usb {
|
||||
void __iomem *regs;
|
||||
};
|
||||
|
||||
static void bcm_kona_usb_phy_power(struct bcm_kona_usb *phy, int on)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(phy->regs + OTGCTL);
|
||||
if (on) {
|
||||
/* Configure and power PHY */
|
||||
val &= ~(OTGCTL_OTGSTAT2 | OTGCTL_OTGSTAT1 |
|
||||
OTGCTL_UTMI_LINE_STATE1 | OTGCTL_UTMI_LINE_STATE0);
|
||||
val |= OTGCTL_PRST_N_SW | OTGCTL_HRESET_N;
|
||||
} else {
|
||||
val &= ~(OTGCTL_PRST_N_SW | OTGCTL_HRESET_N);
|
||||
}
|
||||
writel(val, phy->regs + OTGCTL);
|
||||
}
|
||||
|
||||
static int bcm_kona_usb_phy_init(struct phy *gphy)
|
||||
{
|
||||
struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
|
||||
u32 val;
|
||||
|
||||
/* Soft reset PHY */
|
||||
val = readl(phy->regs + P1CTL);
|
||||
val &= ~P1CTL_NON_DRIVING;
|
||||
val |= P1CTL_SOFT_RESET;
|
||||
writel(val, phy->regs + P1CTL);
|
||||
writel(val & ~P1CTL_SOFT_RESET, phy->regs + P1CTL);
|
||||
/* Reset needs to be asserted for 2ms */
|
||||
mdelay(2);
|
||||
writel(val | P1CTL_SOFT_RESET, phy->regs + P1CTL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm_kona_usb_phy_power_on(struct phy *gphy)
|
||||
{
|
||||
struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
|
||||
|
||||
bcm_kona_usb_phy_power(phy, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm_kona_usb_phy_power_off(struct phy *gphy)
|
||||
{
|
||||
struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
|
||||
|
||||
bcm_kona_usb_phy_power(phy, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct phy_ops ops = {
|
||||
.init = bcm_kona_usb_phy_init,
|
||||
.power_on = bcm_kona_usb_phy_power_on,
|
||||
.power_off = bcm_kona_usb_phy_power_off,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int bcm_kona_usb2_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct bcm_kona_usb *phy;
|
||||
struct resource *res;
|
||||
struct phy *gphy;
|
||||
struct phy_provider *phy_provider;
|
||||
|
||||
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
|
||||
if (!phy)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
phy->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(phy->regs))
|
||||
return PTR_ERR(phy->regs);
|
||||
|
||||
platform_set_drvdata(pdev, phy);
|
||||
|
||||
gphy = devm_phy_create(dev, &ops, NULL);
|
||||
if (IS_ERR(gphy))
|
||||
return PTR_ERR(gphy);
|
||||
|
||||
/* The Kona PHY supports an 8-bit wide UTMI interface */
|
||||
phy_set_bus_width(gphy, 8);
|
||||
|
||||
phy_set_drvdata(gphy, phy);
|
||||
|
||||
phy_provider = devm_of_phy_provider_register(dev,
|
||||
of_phy_simple_xlate);
|
||||
if (IS_ERR(phy_provider))
|
||||
return PTR_ERR(phy_provider);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id bcm_kona_usb2_dt_ids[] = {
|
||||
{ .compatible = "brcm,kona-usb2-phy" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, bcm_kona_usb2_dt_ids);
|
||||
|
||||
static struct platform_driver bcm_kona_usb2_driver = {
|
||||
.probe = bcm_kona_usb2_probe,
|
||||
.driver = {
|
||||
.name = "bcm-kona-usb2",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = bcm_kona_usb2_dt_ids,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(bcm_kona_usb2_driver);
|
||||
|
||||
MODULE_ALIAS("platform:bcm-kona-usb2");
|
||||
MODULE_AUTHOR("Matt Porter <mporter@linaro.org>");
|
||||
MODULE_DESCRIPTION("BCM Kona USB 2.0 PHY driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -3498,6 +3498,7 @@ static int octeon_usb_driver_probe(struct device *dev)
|
||||
kfree(hcd);
|
||||
return -1;
|
||||
}
|
||||
device_wakeup_enable(hcd->self.controller);
|
||||
|
||||
dev_dbg(dev, "Registered HCD for port %d on irq %d\n", usb_num, irq);
|
||||
|
||||
|
@ -2270,6 +2270,8 @@ static int oz_plat_probe(struct platform_device *dev)
|
||||
usb_put_hcd(hcd);
|
||||
return -1;
|
||||
}
|
||||
device_wakeup_enable(hcd->self.controller);
|
||||
|
||||
spin_lock_bh(&g_hcdlock);
|
||||
g_ozhcd = ozhcd;
|
||||
spin_unlock_bh(&g_hcdlock);
|
||||
|
@ -94,8 +94,6 @@ source "drivers/usb/wusbcore/Kconfig"
|
||||
|
||||
source "drivers/usb/host/Kconfig"
|
||||
|
||||
source "drivers/usb/musb/Kconfig"
|
||||
|
||||
source "drivers/usb/renesas_usbhs/Kconfig"
|
||||
|
||||
source "drivers/usb/class/Kconfig"
|
||||
@ -106,6 +104,8 @@ source "drivers/usb/image/Kconfig"
|
||||
|
||||
endif
|
||||
|
||||
source "drivers/usb/musb/Kconfig"
|
||||
|
||||
source "drivers/usb/dwc3/Kconfig"
|
||||
|
||||
source "drivers/usb/dwc2/Kconfig"
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include <linux/timer.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/mutex.h>
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
@ -57,7 +57,6 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/firmware.h>
|
||||
|
@ -170,9 +170,9 @@ struct usbatm_control {
|
||||
static void usbatm_atm_dev_close(struct atm_dev *atm_dev);
|
||||
static int usbatm_atm_open(struct atm_vcc *vcc);
|
||||
static void usbatm_atm_close(struct atm_vcc *vcc);
|
||||
static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user * arg);
|
||||
static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user *arg);
|
||||
static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb);
|
||||
static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page);
|
||||
static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t *pos, char *page);
|
||||
|
||||
static struct atmdev_ops usbatm_atm_devops = {
|
||||
.dev_close = usbatm_atm_dev_close,
|
||||
@ -739,7 +739,7 @@ static void usbatm_atm_dev_close(struct atm_dev *atm_dev)
|
||||
usbatm_put_instance(instance); /* taken in usbatm_atm_init */
|
||||
}
|
||||
|
||||
static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page)
|
||||
static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t *pos, char *page)
|
||||
{
|
||||
struct usbatm_data *instance = atm_dev->dev_data;
|
||||
int left = *pos;
|
||||
@ -895,7 +895,7 @@ static void usbatm_atm_close(struct atm_vcc *vcc)
|
||||
}
|
||||
|
||||
static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd,
|
||||
void __user * arg)
|
||||
void __user *arg)
|
||||
{
|
||||
struct usbatm_data *instance = atm_dev->dev_data;
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
# Makefile for Cypress C67X00 USB Controller
|
||||
#
|
||||
|
||||
ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
|
||||
|
||||
obj-$(CONFIG_USB_C67X00_HCD) += c67x00.o
|
||||
|
||||
c67x00-y := c67x00-drv.o c67x00-ll-hpi.o c67x00-hcd.o c67x00-sched.o
|
||||
|
@ -384,6 +384,8 @@ int c67x00_hcd_probe(struct c67x00_sie *sie)
|
||||
goto err2;
|
||||
}
|
||||
|
||||
device_wakeup_enable(hcd->self.controller);
|
||||
|
||||
spin_lock_irqsave(&sie->lock, flags);
|
||||
sie->private_data = c67x00;
|
||||
sie->irq = c67x00_hcd_irq;
|
||||
|
@ -45,7 +45,7 @@
|
||||
/*
|
||||
* The current implementation switches between _STD (default) and _ISO (when
|
||||
* isochronous transfers are scheduled), in order to optimize the throughput
|
||||
* in normal cicrumstances, but also provide good isochronous behaviour.
|
||||
* in normal circumstances, but also provide good isochronous behaviour.
|
||||
*
|
||||
* Bandwidth is described in bit time so with a 12MHz USB clock and 1ms
|
||||
* frames; there are 12000 bit times per frame.
|
||||
|
@ -22,6 +22,7 @@
|
||||
*/
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/usb/c67x00.h>
|
||||
@ -62,8 +63,8 @@ struct c67x00_lcp_int_data {
|
||||
* HPI implementation
|
||||
*
|
||||
* The c67x00 chip also support control via SPI or HSS serial
|
||||
* interfaces. However, this driver assumes that register access can
|
||||
* be performed from IRQ context. While this is a safe assuption with
|
||||
* interfaces. However, this driver assumes that register access can
|
||||
* be performed from IRQ context. While this is a safe assumption with
|
||||
* the HPI interface, it is not true for the serial interfaces.
|
||||
*/
|
||||
|
||||
@ -73,13 +74,22 @@ struct c67x00_lcp_int_data {
|
||||
#define HPI_ADDR 2
|
||||
#define HPI_STATUS 3
|
||||
|
||||
/*
|
||||
* According to CY7C67300 specification (tables 140 and 141) HPI read and
|
||||
* write cycle duration Tcyc must be at least 6T long, where T is 1/48MHz,
|
||||
* which is 125ns.
|
||||
*/
|
||||
#define HPI_T_CYC_NS 125
|
||||
|
||||
static inline u16 hpi_read_reg(struct c67x00_device *dev, int reg)
|
||||
{
|
||||
ndelay(HPI_T_CYC_NS);
|
||||
return __raw_readw(dev->hpi.base + reg * dev->hpi.regstep);
|
||||
}
|
||||
|
||||
static inline void hpi_write_reg(struct c67x00_device *dev, int reg, u16 value)
|
||||
{
|
||||
ndelay(HPI_T_CYC_NS);
|
||||
__raw_writew(value, dev->hpi.base + reg * dev->hpi.regstep);
|
||||
}
|
||||
|
||||
|
@ -144,8 +144,6 @@ struct c67x00_urb_priv {
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
/**
|
||||
* dbg_td - Dump the contents of the TD
|
||||
*/
|
||||
@ -166,16 +164,8 @@ static void dbg_td(struct c67x00_hcd *c67x00, struct c67x00_td *td, char *msg)
|
||||
dev_dbg(dev, "retry_cnt: 0x%02x\n", td->retry_cnt);
|
||||
dev_dbg(dev, "residue: 0x%02x\n", td->residue);
|
||||
dev_dbg(dev, "next_td_addr: 0x%04x\n", td_next_td_addr(td));
|
||||
dev_dbg(dev, "data:");
|
||||
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
td->data, td_length(td), 1);
|
||||
dev_dbg(dev, "data: %*ph\n", td_length(td), td->data);
|
||||
}
|
||||
#else /* DEBUG */
|
||||
|
||||
static inline void
|
||||
dbg_td(struct c67x00_hcd *c67x00, struct c67x00_td *td, char *msg) { }
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Helper functions */
|
||||
@ -372,6 +362,13 @@ int c67x00_urb_enqueue(struct usb_hcd *hcd,
|
||||
struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
|
||||
int port = get_root_port(urb->dev)-1;
|
||||
|
||||
/* Allocate and initialize urb private data */
|
||||
urbp = kzalloc(sizeof(*urbp), mem_flags);
|
||||
if (!urbp) {
|
||||
ret = -ENOMEM;
|
||||
goto err_urbp;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&c67x00->lock, flags);
|
||||
|
||||
/* Make sure host controller is running */
|
||||
@ -384,13 +381,6 @@ int c67x00_urb_enqueue(struct usb_hcd *hcd,
|
||||
if (ret)
|
||||
goto err_not_linked;
|
||||
|
||||
/* Allocate and initialize urb private data */
|
||||
urbp = kzalloc(sizeof(*urbp), mem_flags);
|
||||
if (!urbp) {
|
||||
ret = -ENOMEM;
|
||||
goto err_urbp;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&urbp->hep_node);
|
||||
urbp->urb = urb;
|
||||
urbp->port = port;
|
||||
@ -453,11 +443,11 @@ int c67x00_urb_enqueue(struct usb_hcd *hcd,
|
||||
return 0;
|
||||
|
||||
err_epdata:
|
||||
kfree(urbp);
|
||||
err_urbp:
|
||||
usb_hcd_unlink_urb_from_ep(hcd, urb);
|
||||
err_not_linked:
|
||||
spin_unlock_irqrestore(&c67x00->lock, flags);
|
||||
kfree(urbp);
|
||||
err_urbp:
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -780,7 +770,8 @@ static int c67x00_add_iso_urb(struct c67x00_hcd *c67x00, struct urb *urb)
|
||||
ret = c67x00_create_td(c67x00, urb, td_buf, len, pid, 0,
|
||||
urbp->cnt);
|
||||
if (ret) {
|
||||
printk(KERN_DEBUG "create failed: %d\n", ret);
|
||||
dev_dbg(c67x00_hcd_dev(c67x00), "create failed: %d\n",
|
||||
ret);
|
||||
urb->iso_frame_desc[urbp->cnt].actual_length = 0;
|
||||
urb->iso_frame_desc[urbp->cnt].status = ret;
|
||||
if (urbp->cnt + 1 == urb->number_of_packets)
|
||||
|
@ -17,5 +17,5 @@ ifneq ($(CONFIG_PCI),)
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_OF),)
|
||||
obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_imx.o usbmisc_imx.o
|
||||
obj-$(CONFIG_USB_CHIPIDEA) += usbmisc_imx.o ci_hdrc_imx.o
|
||||
endif
|
||||
|
@ -25,6 +25,35 @@
|
||||
#define CI_HDRC_PAGE_SIZE 4096ul /* page size for TD's */
|
||||
#define ENDPT_MAX 32
|
||||
|
||||
/******************************************************************************
|
||||
* REGISTERS
|
||||
*****************************************************************************/
|
||||
/* register indices */
|
||||
enum ci_hw_regs {
|
||||
CAP_CAPLENGTH,
|
||||
CAP_HCCPARAMS,
|
||||
CAP_DCCPARAMS,
|
||||
CAP_TESTMODE,
|
||||
CAP_LAST = CAP_TESTMODE,
|
||||
OP_USBCMD,
|
||||
OP_USBSTS,
|
||||
OP_USBINTR,
|
||||
OP_DEVICEADDR,
|
||||
OP_ENDPTLISTADDR,
|
||||
OP_PORTSC,
|
||||
OP_DEVLC,
|
||||
OP_OTGSC,
|
||||
OP_USBMODE,
|
||||
OP_ENDPTSETUPSTAT,
|
||||
OP_ENDPTPRIME,
|
||||
OP_ENDPTFLUSH,
|
||||
OP_ENDPTSTAT,
|
||||
OP_ENDPTCOMPLETE,
|
||||
OP_ENDPTCTRL,
|
||||
/* endptctrl1..15 follow */
|
||||
OP_LAST = OP_ENDPTCTRL + ENDPT_MAX / 2,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* STRUCTURES
|
||||
*****************************************************************************/
|
||||
@ -98,7 +127,7 @@ struct hw_bank {
|
||||
void __iomem *cap;
|
||||
void __iomem *op;
|
||||
size_t size;
|
||||
void __iomem **regmap;
|
||||
void __iomem *regmap[OP_LAST + 1];
|
||||
};
|
||||
|
||||
/**
|
||||
@ -135,6 +164,7 @@ struct hw_bank {
|
||||
* @id_event: indicates there is an id event, and handled at ci_otg_work
|
||||
* @b_sess_valid_event: indicates there is a vbus event, and handled
|
||||
* at ci_otg_work
|
||||
* @imx28_write_fix: Freescale imx28 needs swp instruction for writing
|
||||
*/
|
||||
struct ci_hdrc {
|
||||
struct device *dev;
|
||||
@ -173,6 +203,7 @@ struct ci_hdrc {
|
||||
struct dentry *debugfs;
|
||||
bool id_event;
|
||||
bool b_sess_valid_event;
|
||||
bool imx28_write_fix;
|
||||
};
|
||||
|
||||
static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci)
|
||||
@ -209,38 +240,6 @@ static inline void ci_role_stop(struct ci_hdrc *ci)
|
||||
ci->roles[role]->stop(ci);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* REGISTERS
|
||||
*****************************************************************************/
|
||||
/* register size */
|
||||
#define REG_BITS (32)
|
||||
|
||||
/* register indices */
|
||||
enum ci_hw_regs {
|
||||
CAP_CAPLENGTH,
|
||||
CAP_HCCPARAMS,
|
||||
CAP_DCCPARAMS,
|
||||
CAP_TESTMODE,
|
||||
CAP_LAST = CAP_TESTMODE,
|
||||
OP_USBCMD,
|
||||
OP_USBSTS,
|
||||
OP_USBINTR,
|
||||
OP_DEVICEADDR,
|
||||
OP_ENDPTLISTADDR,
|
||||
OP_PORTSC,
|
||||
OP_DEVLC,
|
||||
OP_OTGSC,
|
||||
OP_USBMODE,
|
||||
OP_ENDPTSETUPSTAT,
|
||||
OP_ENDPTPRIME,
|
||||
OP_ENDPTFLUSH,
|
||||
OP_ENDPTSTAT,
|
||||
OP_ENDPTCOMPLETE,
|
||||
OP_ENDPTCTRL,
|
||||
/* endptctrl1..15 follow */
|
||||
OP_LAST = OP_ENDPTCTRL + ENDPT_MAX / 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* hw_read: reads from a hw register
|
||||
* @reg: register index
|
||||
@ -253,6 +252,26 @@ static inline u32 hw_read(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask)
|
||||
return ioread32(ci->hw_bank.regmap[reg]) & mask;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SOC_IMX28
|
||||
static inline void imx28_ci_writel(u32 val, volatile void __iomem *addr)
|
||||
{
|
||||
__asm__ ("swp %0, %0, [%1]" : : "r"(val), "r"(addr));
|
||||
}
|
||||
#else
|
||||
static inline void imx28_ci_writel(u32 val, volatile void __iomem *addr)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void __hw_write(struct ci_hdrc *ci, u32 val,
|
||||
void __iomem *addr)
|
||||
{
|
||||
if (ci->imx28_write_fix)
|
||||
imx28_ci_writel(val, addr);
|
||||
else
|
||||
iowrite32(val, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* hw_write: writes to a hw register
|
||||
* @reg: register index
|
||||
@ -266,7 +285,7 @@ static inline void hw_write(struct ci_hdrc *ci, enum ci_hw_regs reg,
|
||||
data = (ioread32(ci->hw_bank.regmap[reg]) & ~mask)
|
||||
| (data & mask);
|
||||
|
||||
iowrite32(data, ci->hw_bank.regmap[reg]);
|
||||
__hw_write(ci, data, ci->hw_bank.regmap[reg]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -281,7 +300,7 @@ static inline u32 hw_test_and_clear(struct ci_hdrc *ci, enum ci_hw_regs reg,
|
||||
{
|
||||
u32 val = ioread32(ci->hw_bank.regmap[reg]) & mask;
|
||||
|
||||
iowrite32(val, ci->hw_bank.regmap[reg]);
|
||||
__hw_write(ci, val, ci->hw_bank.regmap[reg]);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,26 @@
|
||||
#include "ci.h"
|
||||
#include "ci_hdrc_imx.h"
|
||||
|
||||
#define CI_HDRC_IMX_IMX28_WRITE_FIX BIT(0)
|
||||
|
||||
struct ci_hdrc_imx_platform_flag {
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
static const struct ci_hdrc_imx_platform_flag imx27_usb_data = {
|
||||
};
|
||||
|
||||
static const struct ci_hdrc_imx_platform_flag imx28_usb_data = {
|
||||
.flags = CI_HDRC_IMX_IMX28_WRITE_FIX,
|
||||
};
|
||||
|
||||
static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx28-usb", .data = &imx28_usb_data},
|
||||
{ .compatible = "fsl,imx27-usb", .data = &imx27_usb_data},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
|
||||
|
||||
struct ci_hdrc_imx_data {
|
||||
struct usb_phy *phy;
|
||||
struct platform_device *ci_pdev;
|
||||
@ -82,6 +102,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
||||
CI_HDRC_DISABLE_STREAMING,
|
||||
};
|
||||
int ret;
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev);
|
||||
const struct ci_hdrc_imx_platform_flag *imx_platform_flag = of_id->data;
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
@ -115,6 +138,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
||||
|
||||
pdata.phy = data->phy;
|
||||
|
||||
if (imx_platform_flag->flags & CI_HDRC_IMX_IMX28_WRITE_FIX)
|
||||
pdata.flags |= CI_HDRC_IMX28_WRITE_FIX;
|
||||
|
||||
ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
@ -173,12 +199,6 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx27-usb", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
|
||||
|
||||
static struct platform_driver ci_hdrc_imx_driver = {
|
||||
.probe = ci_hdrc_imx_probe,
|
||||
.remove = ci_hdrc_imx_remove,
|
||||
|
@ -9,6 +9,9 @@
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
#ifndef __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H
|
||||
#define __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H
|
||||
|
||||
struct imx_usbmisc_data {
|
||||
int index;
|
||||
|
||||
@ -18,3 +21,5 @@ struct imx_usbmisc_data {
|
||||
|
||||
int imx_usbmisc_init(struct imx_usbmisc_data *);
|
||||
int imx_usbmisc_init_post(struct imx_usbmisc_data *);
|
||||
|
||||
#endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */
|
||||
|
@ -112,7 +112,7 @@ static void ci_hdrc_pci_remove(struct pci_dev *pdev)
|
||||
*
|
||||
* Check "pci.h" for details
|
||||
*/
|
||||
static DEFINE_PCI_DEVICE_TABLE(ci_hdrc_pci_id_table) = {
|
||||
static const struct pci_device_id ci_hdrc_pci_id_table[] = {
|
||||
{
|
||||
PCI_DEVICE(0x153F, 0x1004),
|
||||
.driver_data = (kernel_ulong_t)&pci_platdata,
|
||||
|
@ -75,61 +75,54 @@
|
||||
#include "otg.h"
|
||||
|
||||
/* Controller register map */
|
||||
static uintptr_t ci_regs_nolpm[] = {
|
||||
[CAP_CAPLENGTH] = 0x000UL,
|
||||
[CAP_HCCPARAMS] = 0x008UL,
|
||||
[CAP_DCCPARAMS] = 0x024UL,
|
||||
[CAP_TESTMODE] = 0x038UL,
|
||||
[OP_USBCMD] = 0x000UL,
|
||||
[OP_USBSTS] = 0x004UL,
|
||||
[OP_USBINTR] = 0x008UL,
|
||||
[OP_DEVICEADDR] = 0x014UL,
|
||||
[OP_ENDPTLISTADDR] = 0x018UL,
|
||||
[OP_PORTSC] = 0x044UL,
|
||||
[OP_DEVLC] = 0x084UL,
|
||||
[OP_OTGSC] = 0x064UL,
|
||||
[OP_USBMODE] = 0x068UL,
|
||||
[OP_ENDPTSETUPSTAT] = 0x06CUL,
|
||||
[OP_ENDPTPRIME] = 0x070UL,
|
||||
[OP_ENDPTFLUSH] = 0x074UL,
|
||||
[OP_ENDPTSTAT] = 0x078UL,
|
||||
[OP_ENDPTCOMPLETE] = 0x07CUL,
|
||||
[OP_ENDPTCTRL] = 0x080UL,
|
||||
static const u8 ci_regs_nolpm[] = {
|
||||
[CAP_CAPLENGTH] = 0x00U,
|
||||
[CAP_HCCPARAMS] = 0x08U,
|
||||
[CAP_DCCPARAMS] = 0x24U,
|
||||
[CAP_TESTMODE] = 0x38U,
|
||||
[OP_USBCMD] = 0x00U,
|
||||
[OP_USBSTS] = 0x04U,
|
||||
[OP_USBINTR] = 0x08U,
|
||||
[OP_DEVICEADDR] = 0x14U,
|
||||
[OP_ENDPTLISTADDR] = 0x18U,
|
||||
[OP_PORTSC] = 0x44U,
|
||||
[OP_DEVLC] = 0x84U,
|
||||
[OP_OTGSC] = 0x64U,
|
||||
[OP_USBMODE] = 0x68U,
|
||||
[OP_ENDPTSETUPSTAT] = 0x6CU,
|
||||
[OP_ENDPTPRIME] = 0x70U,
|
||||
[OP_ENDPTFLUSH] = 0x74U,
|
||||
[OP_ENDPTSTAT] = 0x78U,
|
||||
[OP_ENDPTCOMPLETE] = 0x7CU,
|
||||
[OP_ENDPTCTRL] = 0x80U,
|
||||
};
|
||||
|
||||
static uintptr_t ci_regs_lpm[] = {
|
||||
[CAP_CAPLENGTH] = 0x000UL,
|
||||
[CAP_HCCPARAMS] = 0x008UL,
|
||||
[CAP_DCCPARAMS] = 0x024UL,
|
||||
[CAP_TESTMODE] = 0x0FCUL,
|
||||
[OP_USBCMD] = 0x000UL,
|
||||
[OP_USBSTS] = 0x004UL,
|
||||
[OP_USBINTR] = 0x008UL,
|
||||
[OP_DEVICEADDR] = 0x014UL,
|
||||
[OP_ENDPTLISTADDR] = 0x018UL,
|
||||
[OP_PORTSC] = 0x044UL,
|
||||
[OP_DEVLC] = 0x084UL,
|
||||
[OP_OTGSC] = 0x0C4UL,
|
||||
[OP_USBMODE] = 0x0C8UL,
|
||||
[OP_ENDPTSETUPSTAT] = 0x0D8UL,
|
||||
[OP_ENDPTPRIME] = 0x0DCUL,
|
||||
[OP_ENDPTFLUSH] = 0x0E0UL,
|
||||
[OP_ENDPTSTAT] = 0x0E4UL,
|
||||
[OP_ENDPTCOMPLETE] = 0x0E8UL,
|
||||
[OP_ENDPTCTRL] = 0x0ECUL,
|
||||
static const u8 ci_regs_lpm[] = {
|
||||
[CAP_CAPLENGTH] = 0x00U,
|
||||
[CAP_HCCPARAMS] = 0x08U,
|
||||
[CAP_DCCPARAMS] = 0x24U,
|
||||
[CAP_TESTMODE] = 0xFCU,
|
||||
[OP_USBCMD] = 0x00U,
|
||||
[OP_USBSTS] = 0x04U,
|
||||
[OP_USBINTR] = 0x08U,
|
||||
[OP_DEVICEADDR] = 0x14U,
|
||||
[OP_ENDPTLISTADDR] = 0x18U,
|
||||
[OP_PORTSC] = 0x44U,
|
||||
[OP_DEVLC] = 0x84U,
|
||||
[OP_OTGSC] = 0xC4U,
|
||||
[OP_USBMODE] = 0xC8U,
|
||||
[OP_ENDPTSETUPSTAT] = 0xD8U,
|
||||
[OP_ENDPTPRIME] = 0xDCU,
|
||||
[OP_ENDPTFLUSH] = 0xE0U,
|
||||
[OP_ENDPTSTAT] = 0xE4U,
|
||||
[OP_ENDPTCOMPLETE] = 0xE8U,
|
||||
[OP_ENDPTCTRL] = 0xECU,
|
||||
};
|
||||
|
||||
static int hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm)
|
||||
{
|
||||
int i;
|
||||
|
||||
kfree(ci->hw_bank.regmap);
|
||||
|
||||
ci->hw_bank.regmap = kzalloc((OP_LAST + 1) * sizeof(void *),
|
||||
GFP_KERNEL);
|
||||
if (!ci->hw_bank.regmap)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < OP_ENDPTCTRL; i++)
|
||||
ci->hw_bank.regmap[i] =
|
||||
(i <= CAP_LAST ? ci->hw_bank.cap : ci->hw_bank.op) +
|
||||
@ -208,7 +201,8 @@ static int hw_device_init(struct ci_hdrc *ci, void __iomem *base)
|
||||
reg = hw_read(ci, CAP_HCCPARAMS, HCCPARAMS_LEN) >>
|
||||
__ffs(HCCPARAMS_LEN);
|
||||
ci->hw_bank.lpm = reg;
|
||||
hw_alloc_regmap(ci, !!reg);
|
||||
if (reg)
|
||||
hw_alloc_regmap(ci, !!reg);
|
||||
ci->hw_bank.size = ci->hw_bank.op - ci->hw_bank.abs;
|
||||
ci->hw_bank.size += OP_LAST;
|
||||
ci->hw_bank.size /= sizeof(u32);
|
||||
@ -242,7 +236,7 @@ static int hw_device_init(struct ci_hdrc *ci, void __iomem *base)
|
||||
|
||||
static void hw_phymode_configure(struct ci_hdrc *ci)
|
||||
{
|
||||
u32 portsc, lpm, sts;
|
||||
u32 portsc, lpm, sts = 0;
|
||||
|
||||
switch (ci->platdata->phy_mode) {
|
||||
case USBPHY_INTERFACE_MODE_UTMI:
|
||||
@ -272,10 +266,12 @@ static void hw_phymode_configure(struct ci_hdrc *ci)
|
||||
|
||||
if (ci->hw_bank.lpm) {
|
||||
hw_write(ci, OP_DEVLC, DEVLC_PTS(7) | DEVLC_PTW, lpm);
|
||||
hw_write(ci, OP_DEVLC, DEVLC_STS, sts);
|
||||
if (sts)
|
||||
hw_write(ci, OP_DEVLC, DEVLC_STS, DEVLC_STS);
|
||||
} else {
|
||||
hw_write(ci, OP_PORTSC, PORTSC_PTS(7) | PORTSC_PTW, portsc);
|
||||
hw_write(ci, OP_PORTSC, PORTSC_STS, sts);
|
||||
if (sts)
|
||||
hw_write(ci, OP_PORTSC, PORTSC_STS, PORTSC_STS);
|
||||
}
|
||||
}
|
||||
|
||||
@ -554,6 +550,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
||||
|
||||
ci->dev = dev;
|
||||
ci->platdata = dev->platform_data;
|
||||
ci->imx28_write_fix = !!(ci->platdata->flags &
|
||||
CI_HDRC_IMX28_WRITE_FIX);
|
||||
|
||||
ret = hw_device_init(ci, base);
|
||||
if (ret < 0) {
|
||||
@ -561,6 +559,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
hw_phymode_configure(ci);
|
||||
|
||||
ret = ci_usb_phy_init(ci);
|
||||
if (ret) {
|
||||
dev_err(dev, "unable to init phy: %d\n", ret);
|
||||
@ -578,8 +578,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
||||
|
||||
ci_get_otg_capable(ci);
|
||||
|
||||
hw_phymode_configure(ci);
|
||||
|
||||
dr_mode = ci->platdata->dr_mode;
|
||||
/* initialize role(s) before the interrupt is requested */
|
||||
if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) {
|
||||
@ -680,7 +678,6 @@ static int ci_hdrc_remove(struct platform_device *pdev)
|
||||
ci_role_destroy(ci);
|
||||
ci_hdrc_enter_lpm(ci, true);
|
||||
ci_usb_phy_destroy(ci);
|
||||
kfree(ci->hw_bank.regmap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ static int host_start(struct ci_hdrc *ci)
|
||||
ehci->caps = ci->hw_bank.cap;
|
||||
ehci->has_hostpc = ci->hw_bank.lpm;
|
||||
ehci->has_tdi_phy_lpm = ci->hw_bank.lpm;
|
||||
ehci->imx28_write_fix = ci->imx28_write_fix;
|
||||
|
||||
if (ci->platdata->reg_vbus) {
|
||||
ret = regulator_enable(ci->platdata->reg_vbus);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2013-2014 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* Author: Peter Chen
|
||||
*
|
||||
@ -19,12 +19,12 @@ static inline void ci_clear_otg_interrupt(struct ci_hdrc *ci, u32 bits)
|
||||
|
||||
static inline void ci_enable_otg_interrupt(struct ci_hdrc *ci, u32 bits)
|
||||
{
|
||||
hw_write(ci, OP_OTGSC, bits, bits);
|
||||
hw_write(ci, OP_OTGSC, bits | OTGSC_INT_STATUS_BITS, bits);
|
||||
}
|
||||
|
||||
static inline void ci_disable_otg_interrupt(struct ci_hdrc *ci, u32 bits)
|
||||
{
|
||||
hw_write(ci, OP_OTGSC, bits, 0);
|
||||
hw_write(ci, OP_OTGSC, bits | OTGSC_INT_STATUS_BITS, 0);
|
||||
}
|
||||
|
||||
int ci_hdrc_otg_init(struct ci_hdrc *ci);
|
||||
|
@ -393,6 +393,14 @@ static int add_td_to_list(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq,
|
||||
node->ptr->token = cpu_to_le32(length << __ffs(TD_TOTAL_BYTES));
|
||||
node->ptr->token &= cpu_to_le32(TD_TOTAL_BYTES);
|
||||
node->ptr->token |= cpu_to_le32(TD_STATUS_ACTIVE);
|
||||
if (hwep->type == USB_ENDPOINT_XFER_ISOC && hwep->dir == TX) {
|
||||
u32 mul = hwreq->req.length / hwep->ep.maxpacket;
|
||||
|
||||
if (hwreq->req.length == 0
|
||||
|| hwreq->req.length % hwep->ep.maxpacket)
|
||||
mul++;
|
||||
node->ptr->token |= mul << __ffs(TD_MULTO);
|
||||
}
|
||||
|
||||
temp = (u32) (hwreq->req.dma + hwreq->req.actual);
|
||||
if (length) {
|
||||
@ -515,10 +523,11 @@ static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
|
||||
hwep->qh.ptr->td.token &=
|
||||
cpu_to_le32(~(TD_STATUS_HALTED|TD_STATUS_ACTIVE));
|
||||
|
||||
if (hwep->type == USB_ENDPOINT_XFER_ISOC) {
|
||||
if (hwep->type == USB_ENDPOINT_XFER_ISOC && hwep->dir == RX) {
|
||||
u32 mul = hwreq->req.length / hwep->ep.maxpacket;
|
||||
|
||||
if (hwreq->req.length % hwep->ep.maxpacket)
|
||||
if (hwreq->req.length == 0
|
||||
|| hwreq->req.length % hwep->ep.maxpacket)
|
||||
mul++;
|
||||
hwep->qh.ptr->cap |= mul << __ffs(QH_MULT);
|
||||
}
|
||||
@ -1173,6 +1182,12 @@ static int ep_enable(struct usb_ep *ep,
|
||||
if (hwep->num)
|
||||
cap |= QH_ZLT;
|
||||
cap |= (hwep->ep.maxpacket << __ffs(QH_MAX_PKT)) & QH_MAX_PKT;
|
||||
/*
|
||||
* For ISO-TX, we set mult at QH as the largest value, and use
|
||||
* MultO at TD as real mult value.
|
||||
*/
|
||||
if (hwep->type == USB_ENDPOINT_XFER_ISOC && hwep->dir == TX)
|
||||
cap |= 3 << __ffs(QH_MULT);
|
||||
|
||||
hwep->qh.ptr->cap = cpu_to_le32(cap);
|
||||
|
||||
@ -1566,7 +1581,7 @@ static int init_eps(struct ci_hdrc *ci)
|
||||
* eps, maxP is set by epautoconfig() called
|
||||
* by gadget layer
|
||||
*/
|
||||
hwep->ep.maxpacket = (unsigned short)~0;
|
||||
usb_ep_set_maxpacket_limit(&hwep->ep, (unsigned short)~0);
|
||||
|
||||
INIT_LIST_HEAD(&hwep->qh.queue);
|
||||
hwep->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL,
|
||||
@ -1586,7 +1601,7 @@ static int init_eps(struct ci_hdrc *ci)
|
||||
else
|
||||
ci->ep0in = hwep;
|
||||
|
||||
hwep->ep.maxpacket = CTRL_PAYLOAD_MAX;
|
||||
usb_ep_set_maxpacket_limit(&hwep->ep, CTRL_PAYLOAD_MAX);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,10 @@
|
||||
#define MX25_USB_PHY_CTRL_OFFSET 0x08
|
||||
#define MX25_BM_EXTERNAL_VBUS_DIVIDER BIT(23)
|
||||
|
||||
#define MX27_H1_PM_BIT BIT(8)
|
||||
#define MX27_H2_PM_BIT BIT(16)
|
||||
#define MX27_OTG_PM_BIT BIT(24)
|
||||
|
||||
#define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08
|
||||
#define MX53_USB_UH2_CTRL_OFFSET 0x14
|
||||
#define MX53_USB_UH3_CTRL_OFFSET 0x18
|
||||
@ -68,6 +72,36 @@ static int usbmisc_imx25_post(struct imx_usbmisc_data *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbmisc_imx27_init(struct imx_usbmisc_data *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
switch (data->index) {
|
||||
case 0:
|
||||
val = MX27_OTG_PM_BIT;
|
||||
break;
|
||||
case 1:
|
||||
val = MX27_H1_PM_BIT;
|
||||
break;
|
||||
case 2:
|
||||
val = MX27_H2_PM_BIT;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
spin_lock_irqsave(&usbmisc->lock, flags);
|
||||
if (data->disable_oc)
|
||||
val = readl(usbmisc->base) | val;
|
||||
else
|
||||
val = readl(usbmisc->base) & ~val;
|
||||
writel(val, usbmisc->base);
|
||||
spin_unlock_irqrestore(&usbmisc->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
|
||||
{
|
||||
void __iomem *reg = NULL;
|
||||
@ -128,6 +162,10 @@ static const struct usbmisc_ops imx25_usbmisc_ops = {
|
||||
.post = usbmisc_imx25_post,
|
||||
};
|
||||
|
||||
static const struct usbmisc_ops imx27_usbmisc_ops = {
|
||||
.init = usbmisc_imx27_init,
|
||||
};
|
||||
|
||||
static const struct usbmisc_ops imx53_usbmisc_ops = {
|
||||
.init = usbmisc_imx53_init,
|
||||
};
|
||||
@ -161,6 +199,14 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = {
|
||||
.compatible = "fsl,imx25-usbmisc",
|
||||
.data = &imx25_usbmisc_ops,
|
||||
},
|
||||
{
|
||||
.compatible = "fsl,imx27-usbmisc",
|
||||
.data = &imx27_usbmisc_ops,
|
||||
},
|
||||
{
|
||||
.compatible = "fsl,imx51-usbmisc",
|
||||
.data = &imx53_usbmisc_ops,
|
||||
},
|
||||
{
|
||||
.compatible = "fsl,imx53-usbmisc",
|
||||
.data = &imx53_usbmisc_ops,
|
||||
|
@ -262,6 +262,7 @@ static void acm_ctrl_irq(struct urb *urb)
|
||||
struct usb_cdc_notification *dr = urb->transfer_buffer;
|
||||
unsigned char *data;
|
||||
int newctrl;
|
||||
int difference;
|
||||
int retval;
|
||||
int status = urb->status;
|
||||
|
||||
@ -302,20 +303,31 @@ static void acm_ctrl_irq(struct urb *urb)
|
||||
tty_port_tty_hangup(&acm->port, false);
|
||||
}
|
||||
|
||||
difference = acm->ctrlin ^ newctrl;
|
||||
spin_lock(&acm->read_lock);
|
||||
acm->ctrlin = newctrl;
|
||||
acm->oldcount = acm->iocount;
|
||||
|
||||
dev_dbg(&acm->control->dev,
|
||||
"%s - input control lines: dcd%c dsr%c break%c "
|
||||
"ring%c framing%c parity%c overrun%c\n",
|
||||
__func__,
|
||||
acm->ctrlin & ACM_CTRL_DCD ? '+' : '-',
|
||||
acm->ctrlin & ACM_CTRL_DSR ? '+' : '-',
|
||||
acm->ctrlin & ACM_CTRL_BRK ? '+' : '-',
|
||||
acm->ctrlin & ACM_CTRL_RI ? '+' : '-',
|
||||
acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-',
|
||||
acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-',
|
||||
acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-');
|
||||
break;
|
||||
if (difference & ACM_CTRL_DSR)
|
||||
acm->iocount.dsr++;
|
||||
if (difference & ACM_CTRL_BRK)
|
||||
acm->iocount.brk++;
|
||||
if (difference & ACM_CTRL_RI)
|
||||
acm->iocount.rng++;
|
||||
if (difference & ACM_CTRL_DCD)
|
||||
acm->iocount.dcd++;
|
||||
if (difference & ACM_CTRL_FRAMING)
|
||||
acm->iocount.frame++;
|
||||
if (difference & ACM_CTRL_PARITY)
|
||||
acm->iocount.parity++;
|
||||
if (difference & ACM_CTRL_OVERRUN)
|
||||
acm->iocount.overrun++;
|
||||
spin_unlock(&acm->read_lock);
|
||||
|
||||
if (difference)
|
||||
wake_up_all(&acm->wioctl);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_dbg(&acm->control->dev,
|
||||
@ -796,6 +808,72 @@ static int set_serial_info(struct acm *acm,
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int wait_serial_change(struct acm *acm, unsigned long arg)
|
||||
{
|
||||
int rv = 0;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
struct async_icount old, new;
|
||||
|
||||
if (arg & (TIOCM_DSR | TIOCM_RI | TIOCM_CD ))
|
||||
return -EINVAL;
|
||||
do {
|
||||
spin_lock_irq(&acm->read_lock);
|
||||
old = acm->oldcount;
|
||||
new = acm->iocount;
|
||||
acm->oldcount = new;
|
||||
spin_unlock_irq(&acm->read_lock);
|
||||
|
||||
if ((arg & TIOCM_DSR) &&
|
||||
old.dsr != new.dsr)
|
||||
break;
|
||||
if ((arg & TIOCM_CD) &&
|
||||
old.dcd != new.dcd)
|
||||
break;
|
||||
if ((arg & TIOCM_RI) &&
|
||||
old.rng != new.rng)
|
||||
break;
|
||||
|
||||
add_wait_queue(&acm->wioctl, &wait);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule();
|
||||
remove_wait_queue(&acm->wioctl, &wait);
|
||||
if (acm->disconnected) {
|
||||
if (arg & TIOCM_CD)
|
||||
break;
|
||||
else
|
||||
rv = -ENODEV;
|
||||
} else {
|
||||
if (signal_pending(current))
|
||||
rv = -ERESTARTSYS;
|
||||
}
|
||||
} while (!rv);
|
||||
|
||||
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int get_serial_usage(struct acm *acm,
|
||||
struct serial_icounter_struct __user *count)
|
||||
{
|
||||
struct serial_icounter_struct icount;
|
||||
int rv = 0;
|
||||
|
||||
memset(&icount, 0, sizeof(icount));
|
||||
icount.dsr = acm->iocount.dsr;
|
||||
icount.rng = acm->iocount.rng;
|
||||
icount.dcd = acm->iocount.dcd;
|
||||
icount.frame = acm->iocount.frame;
|
||||
icount.overrun = acm->iocount.overrun;
|
||||
icount.parity = acm->iocount.parity;
|
||||
icount.brk = acm->iocount.brk;
|
||||
|
||||
if (copy_to_user(count, &icount, sizeof(icount)) > 0)
|
||||
rv = -EFAULT;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int acm_tty_ioctl(struct tty_struct *tty,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
@ -809,6 +887,18 @@ static int acm_tty_ioctl(struct tty_struct *tty,
|
||||
case TIOCSSERIAL:
|
||||
rv = set_serial_info(acm, (struct serial_struct __user *) arg);
|
||||
break;
|
||||
case TIOCMIWAIT:
|
||||
rv = usb_autopm_get_interface(acm->control);
|
||||
if (rv < 0) {
|
||||
rv = -EIO;
|
||||
break;
|
||||
}
|
||||
rv = wait_serial_change(acm, arg);
|
||||
usb_autopm_put_interface(acm->control);
|
||||
break;
|
||||
case TIOCGICOUNT:
|
||||
rv = get_serial_usage(acm, (struct serial_icounter_struct __user *) arg);
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -1167,6 +1257,7 @@ static int acm_probe(struct usb_interface *intf,
|
||||
acm->readsize = readsize;
|
||||
acm->rx_buflimit = num_rx_buf;
|
||||
INIT_WORK(&acm->work, acm_softint);
|
||||
init_waitqueue_head(&acm->wioctl);
|
||||
spin_lock_init(&acm->write_lock);
|
||||
spin_lock_init(&acm->read_lock);
|
||||
mutex_init(&acm->mutex);
|
||||
@ -1383,6 +1474,7 @@ static void acm_disconnect(struct usb_interface *intf)
|
||||
device_remove_file(&acm->control->dev,
|
||||
&dev_attr_iCountryCodeRelDate);
|
||||
}
|
||||
wake_up_all(&acm->wioctl);
|
||||
device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities);
|
||||
usb_set_intfdata(acm->control, NULL);
|
||||
usb_set_intfdata(acm->data, NULL);
|
||||
|
@ -106,6 +106,9 @@ struct acm {
|
||||
struct work_struct work; /* work queue entry for line discipline waking up */
|
||||
unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
|
||||
unsigned int ctrlout; /* output control lines (DTR, RTS) */
|
||||
struct async_icount iocount; /* counters for control line changes */
|
||||
struct async_icount oldcount; /* for comparison of counter */
|
||||
wait_queue_head_t wioctl; /* for ioctl */
|
||||
unsigned int writesize; /* max packet size for the output bulk endpoint */
|
||||
unsigned int readsize,ctrlsize; /* buffer sizes for freeing */
|
||||
unsigned int minor; /* acm minor number */
|
||||
|
@ -432,6 +432,38 @@ static ssize_t wdm_write
|
||||
return rv < 0 ? rv : count;
|
||||
}
|
||||
|
||||
/*
|
||||
* clear WDM_READ flag and possibly submit the read urb if resp_count
|
||||
* is non-zero.
|
||||
*
|
||||
* Called with desc->iuspin locked
|
||||
*/
|
||||
static int clear_wdm_read_flag(struct wdm_device *desc)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
clear_bit(WDM_READ, &desc->flags);
|
||||
|
||||
/* submit read urb only if the device is waiting for it */
|
||||
if (!desc->resp_count || !--desc->resp_count)
|
||||
goto out;
|
||||
|
||||
set_bit(WDM_RESPONDING, &desc->flags);
|
||||
spin_unlock_irq(&desc->iuspin);
|
||||
rv = usb_submit_urb(desc->response, GFP_KERNEL);
|
||||
spin_lock_irq(&desc->iuspin);
|
||||
if (rv) {
|
||||
dev_err(&desc->intf->dev,
|
||||
"usb_submit_urb failed with result %d\n", rv);
|
||||
|
||||
/* make sure the next notification trigger a submit */
|
||||
clear_bit(WDM_RESPONDING, &desc->flags);
|
||||
desc->resp_count = 0;
|
||||
}
|
||||
out:
|
||||
return rv;
|
||||
}
|
||||
|
||||
static ssize_t wdm_read
|
||||
(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
|
||||
{
|
||||
@ -503,8 +535,10 @@ static ssize_t wdm_read
|
||||
|
||||
if (!desc->reslength) { /* zero length read */
|
||||
dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__);
|
||||
clear_bit(WDM_READ, &desc->flags);
|
||||
rv = clear_wdm_read_flag(desc);
|
||||
spin_unlock_irq(&desc->iuspin);
|
||||
if (rv < 0)
|
||||
goto err;
|
||||
goto retry;
|
||||
}
|
||||
cntr = desc->length;
|
||||
@ -526,37 +560,9 @@ static ssize_t wdm_read
|
||||
|
||||
desc->length -= cntr;
|
||||
/* in case we had outstanding data */
|
||||
if (!desc->length) {
|
||||
clear_bit(WDM_READ, &desc->flags);
|
||||
|
||||
if (--desc->resp_count) {
|
||||
set_bit(WDM_RESPONDING, &desc->flags);
|
||||
spin_unlock_irq(&desc->iuspin);
|
||||
|
||||
rv = usb_submit_urb(desc->response, GFP_KERNEL);
|
||||
if (rv) {
|
||||
dev_err(&desc->intf->dev,
|
||||
"%s: usb_submit_urb failed with result %d\n",
|
||||
__func__, rv);
|
||||
spin_lock_irq(&desc->iuspin);
|
||||
clear_bit(WDM_RESPONDING, &desc->flags);
|
||||
spin_unlock_irq(&desc->iuspin);
|
||||
|
||||
if (rv == -ENOMEM) {
|
||||
rv = schedule_work(&desc->rxwork);
|
||||
if (rv)
|
||||
dev_err(&desc->intf->dev, "Cannot schedule work\n");
|
||||
} else {
|
||||
spin_lock_irq(&desc->iuspin);
|
||||
desc->resp_count = 0;
|
||||
spin_unlock_irq(&desc->iuspin);
|
||||
}
|
||||
}
|
||||
} else
|
||||
spin_unlock_irq(&desc->iuspin);
|
||||
} else
|
||||
spin_unlock_irq(&desc->iuspin);
|
||||
|
||||
if (!desc->length)
|
||||
clear_wdm_read_flag(desc);
|
||||
spin_unlock_irq(&desc->iuspin);
|
||||
rv = cntr;
|
||||
|
||||
err:
|
||||
|
@ -52,7 +52,6 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/lp.h>
|
||||
#include <linux/mutex.h>
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
|
@ -2,8 +2,6 @@
|
||||
# Makefile for USB Core files and filesystem
|
||||
#
|
||||
|
||||
ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
|
||||
|
||||
usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
|
||||
usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
|
||||
usbcore-y += devio.o notify.o generic.o quirks.o devices.o
|
||||
|
@ -2,7 +2,7 @@
|
||||
* DMA memory management for framework level HCD code (hc_driver)
|
||||
*
|
||||
* This implementation plugs in through generic "usb_bus" level methods,
|
||||
* and should work with all USB controllers, regardles of bus type.
|
||||
* and should work with all USB controllers, regardless of bus type.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include <linux/usb/hcd.h>
|
||||
#include <linux/usb/quirks.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include <asm/byteorder.h>
|
||||
@ -651,10 +650,6 @@ void usb_destroy_configuration(struct usb_device *dev)
|
||||
*
|
||||
* hub-only!! ... and only in reset path, or usb_new_device()
|
||||
* (used by real hubs and virtual root hubs)
|
||||
*
|
||||
* NOTE: if this is a WUSB device and is not authorized, we skip the
|
||||
* whole thing. A non-authorized USB device has no
|
||||
* configurations.
|
||||
*/
|
||||
int usb_get_configuration(struct usb_device *dev)
|
||||
{
|
||||
@ -666,8 +661,6 @@ int usb_get_configuration(struct usb_device *dev)
|
||||
struct usb_config_descriptor *desc;
|
||||
|
||||
cfgno = 0;
|
||||
if (dev->authorized == 0) /* Not really an error */
|
||||
goto out_not_authorized;
|
||||
result = -ENOMEM;
|
||||
if (ncfg > USB_MAXCONFIG) {
|
||||
dev_warn(ddev, "too many configurations: %d, "
|
||||
@ -751,7 +744,6 @@ int usb_get_configuration(struct usb_device *dev)
|
||||
|
||||
err:
|
||||
kfree(desc);
|
||||
out_not_authorized:
|
||||
dev->descriptor.bNumConfigurations = cfgno;
|
||||
err2:
|
||||
if (result == -ENOMEM)
|
||||
|
@ -118,7 +118,7 @@ module_param(usbfs_memory_mb, uint, 0644);
|
||||
MODULE_PARM_DESC(usbfs_memory_mb,
|
||||
"maximum MB allowed for usbfs buffers (0 = no limit)");
|
||||
|
||||
/* Hard limit, necessary to avoid aithmetic overflow */
|
||||
/* Hard limit, necessary to avoid arithmetic overflow */
|
||||
#define USBFS_XFER_MAX (UINT_MAX / 2 - 1000000)
|
||||
|
||||
static atomic_t usbfs_memory_usage; /* Total memory currently allocated */
|
||||
|
@ -37,6 +37,7 @@
|
||||
* and cause the driver to probe for all devices again.
|
||||
*/
|
||||
ssize_t usb_store_new_id(struct usb_dynids *dynids,
|
||||
const struct usb_device_id *id_table,
|
||||
struct device_driver *driver,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
@ -44,11 +45,12 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
|
||||
u32 idVendor = 0;
|
||||
u32 idProduct = 0;
|
||||
unsigned int bInterfaceClass = 0;
|
||||
u32 refVendor, refProduct;
|
||||
int fields = 0;
|
||||
int retval = 0;
|
||||
|
||||
fields = sscanf(buf, "%x %x %x", &idVendor, &idProduct,
|
||||
&bInterfaceClass);
|
||||
fields = sscanf(buf, "%x %x %x %x %x", &idVendor, &idProduct,
|
||||
&bInterfaceClass, &refVendor, &refProduct);
|
||||
if (fields < 2)
|
||||
return -EINVAL;
|
||||
|
||||
@ -60,11 +62,30 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
|
||||
dynid->id.idVendor = idVendor;
|
||||
dynid->id.idProduct = idProduct;
|
||||
dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
|
||||
if (fields == 3) {
|
||||
if (fields > 2 && bInterfaceClass) {
|
||||
if (bInterfaceClass > 255)
|
||||
return -EINVAL;
|
||||
|
||||
dynid->id.bInterfaceClass = (u8)bInterfaceClass;
|
||||
dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS;
|
||||
}
|
||||
|
||||
if (fields > 4) {
|
||||
const struct usb_device_id *id = id_table;
|
||||
|
||||
if (!id)
|
||||
return -ENODEV;
|
||||
|
||||
for (; id->match_flags; id++)
|
||||
if (id->idVendor == refVendor && id->idProduct == refProduct)
|
||||
break;
|
||||
|
||||
if (id->match_flags)
|
||||
dynid->id.driver_info = id->driver_info;
|
||||
else
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
spin_lock(&dynids->lock);
|
||||
list_add_tail(&dynid->node, &dynids->list);
|
||||
spin_unlock(&dynids->lock);
|
||||
@ -106,7 +127,7 @@ static ssize_t new_id_store(struct device_driver *driver,
|
||||
{
|
||||
struct usb_driver *usb_drv = to_usb_driver(driver);
|
||||
|
||||
return usb_store_new_id(&usb_drv->dynids, driver, buf, count);
|
||||
return usb_store_new_id(&usb_drv->dynids, usb_drv->id_table, driver, buf, count);
|
||||
}
|
||||
static DRIVER_ATTR_RW(new_id);
|
||||
|
||||
@ -839,7 +860,7 @@ int usb_register_device_driver(struct usb_device_driver *new_udriver,
|
||||
return -ENODEV;
|
||||
|
||||
new_udriver->drvwrap.for_devices = 1;
|
||||
new_udriver->drvwrap.driver.name = (char *) new_udriver->name;
|
||||
new_udriver->drvwrap.driver.name = new_udriver->name;
|
||||
new_udriver->drvwrap.driver.bus = &usb_bus_type;
|
||||
new_udriver->drvwrap.driver.probe = usb_probe_device;
|
||||
new_udriver->drvwrap.driver.remove = usb_unbind_device;
|
||||
@ -900,7 +921,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
|
||||
return -ENODEV;
|
||||
|
||||
new_driver->drvwrap.for_devices = 0;
|
||||
new_driver->drvwrap.driver.name = (char *) new_driver->name;
|
||||
new_driver->drvwrap.driver.name = new_driver->name;
|
||||
new_driver->drvwrap.driver.bus = &usb_bus_type;
|
||||
new_driver->drvwrap.driver.probe = usb_probe_interface;
|
||||
new_driver->drvwrap.driver.remove = usb_unbind_interface;
|
||||
|
@ -282,6 +282,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
|
||||
if (retval != 0)
|
||||
goto unmap_registers;
|
||||
device_wakeup_enable(hcd->self.controller);
|
||||
|
||||
if (pci_dev_run_wake(dev))
|
||||
pm_runtime_put_noidle(&dev->dev);
|
||||
|
@ -44,6 +44,7 @@
|
||||
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/hcd.h>
|
||||
#include <linux/usb/phy.h>
|
||||
|
||||
#include "usb.h"
|
||||
|
||||
@ -1297,7 +1298,7 @@ EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep);
|
||||
* DMA framework is dma_declare_coherent_memory()
|
||||
*
|
||||
* - So we use that, even though the primary requirement
|
||||
* is that the memory be "local" (hence addressible
|
||||
* is that the memory be "local" (hence addressable
|
||||
* by that device), not "coherent".
|
||||
*
|
||||
*/
|
||||
@ -2588,6 +2589,24 @@ int usb_add_hcd(struct usb_hcd *hcd,
|
||||
int retval;
|
||||
struct usb_device *rhdev;
|
||||
|
||||
if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->phy) {
|
||||
struct usb_phy *phy = usb_get_phy_dev(hcd->self.controller, 0);
|
||||
|
||||
if (IS_ERR(phy)) {
|
||||
retval = PTR_ERR(phy);
|
||||
if (retval == -EPROBE_DEFER)
|
||||
return retval;
|
||||
} else {
|
||||
retval = usb_phy_init(phy);
|
||||
if (retval) {
|
||||
usb_put_phy(phy);
|
||||
return retval;
|
||||
}
|
||||
hcd->phy = phy;
|
||||
hcd->remove_phy = 1;
|
||||
}
|
||||
}
|
||||
|
||||
dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
|
||||
|
||||
/* Keep old behaviour if authorized_default is not in [0, 1]. */
|
||||
@ -2603,7 +2622,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
|
||||
*/
|
||||
if ((retval = hcd_buffer_create(hcd)) != 0) {
|
||||
dev_dbg(hcd->self.controller, "pool alloc failed\n");
|
||||
return retval;
|
||||
goto err_remove_phy;
|
||||
}
|
||||
|
||||
if ((retval = usb_register_bus(&hcd->self)) < 0)
|
||||
@ -2693,12 +2712,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
|
||||
if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
|
||||
usb_hcd_poll_rh_status(hcd);
|
||||
|
||||
/*
|
||||
* Host controllers don't generate their own wakeup requests;
|
||||
* they only forward requests from the root hub. Therefore
|
||||
* controllers should always be enabled for remote wakeup.
|
||||
*/
|
||||
device_wakeup_enable(hcd->self.controller);
|
||||
return retval;
|
||||
|
||||
error_create_attr_group:
|
||||
@ -2734,6 +2747,12 @@ int usb_add_hcd(struct usb_hcd *hcd,
|
||||
usb_deregister_bus(&hcd->self);
|
||||
err_register_bus:
|
||||
hcd_buffer_destroy(hcd);
|
||||
err_remove_phy:
|
||||
if (hcd->remove_phy && hcd->phy) {
|
||||
usb_phy_shutdown(hcd->phy);
|
||||
usb_put_phy(hcd->phy);
|
||||
hcd->phy = NULL;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_add_hcd);
|
||||
@ -2806,6 +2825,11 @@ void usb_remove_hcd(struct usb_hcd *hcd)
|
||||
usb_put_dev(hcd->self.root_hub);
|
||||
usb_deregister_bus(&hcd->self);
|
||||
hcd_buffer_destroy(hcd);
|
||||
if (hcd->remove_phy && hcd->phy) {
|
||||
usb_phy_shutdown(hcd->phy);
|
||||
usb_put_phy(hcd->phy);
|
||||
hcd->phy = NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_remove_hcd);
|
||||
|
||||
|
@ -33,13 +33,6 @@
|
||||
|
||||
#include "hub.h"
|
||||
|
||||
/* if we are in debug mode, always announce new devices */
|
||||
#ifdef DEBUG
|
||||
#ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES
|
||||
#define CONFIG_USB_ANNOUNCE_NEW_DEVICES
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define USB_VENDOR_GENESYS_LOGIC 0x05e3
|
||||
#define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01
|
||||
|
||||
@ -1154,7 +1147,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
|
||||
/* Tell khubd to disconnect the device or
|
||||
* check for a new connection
|
||||
*/
|
||||
if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
|
||||
if (udev || (portstatus & USB_PORT_STAT_CONNECTION) ||
|
||||
(portstatus & USB_PORT_STAT_OVERCURRENT))
|
||||
set_bit(port1, hub->change_bits);
|
||||
|
||||
} else if (portstatus & USB_PORT_STAT_ENABLE) {
|
||||
@ -1607,7 +1601,7 @@ static void hub_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_hub *hub = usb_get_intfdata(intf);
|
||||
struct usb_device *hdev = interface_to_usbdev(intf);
|
||||
int i;
|
||||
int port1;
|
||||
|
||||
/* Take the hub off the event list and don't let it be added again */
|
||||
spin_lock_irq(&hub_event_lock);
|
||||
@ -1622,11 +1616,15 @@ static void hub_disconnect(struct usb_interface *intf)
|
||||
hub->error = 0;
|
||||
hub_quiesce(hub, HUB_DISCONNECT);
|
||||
|
||||
usb_set_intfdata (intf, NULL);
|
||||
/* Avoid races with recursively_mark_NOTATTACHED() */
|
||||
spin_lock_irq(&device_state_lock);
|
||||
port1 = hdev->maxchild;
|
||||
hdev->maxchild = 0;
|
||||
usb_set_intfdata(intf, NULL);
|
||||
spin_unlock_irq(&device_state_lock);
|
||||
|
||||
for (i = 0; i < hdev->maxchild; i++)
|
||||
usb_hub_remove_port_device(hub, i + 1);
|
||||
hub->hdev->maxchild = 0;
|
||||
for (; port1 > 0; --port1)
|
||||
usb_hub_remove_port_device(hub, port1);
|
||||
|
||||
if (hub->hdev->speed == USB_SPEED_HIGH)
|
||||
highspeed_hubs--;
|
||||
@ -2235,17 +2233,13 @@ static int usb_enumerate_device(struct usb_device *udev)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
if (udev->wusb == 1 && udev->authorized == 0) {
|
||||
udev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
|
||||
udev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
|
||||
udev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
|
||||
} else {
|
||||
/* read the standard strings and cache them if present */
|
||||
udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
|
||||
udev->manufacturer = usb_cache_string(udev,
|
||||
udev->descriptor.iManufacturer);
|
||||
udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
|
||||
}
|
||||
|
||||
/* read the standard strings and cache them if present */
|
||||
udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
|
||||
udev->manufacturer = usb_cache_string(udev,
|
||||
udev->descriptor.iManufacturer);
|
||||
udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
|
||||
|
||||
err = usb_enumerate_device_otg(udev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@ -2427,16 +2421,6 @@ int usb_deauthorize_device(struct usb_device *usb_dev)
|
||||
usb_dev->authorized = 0;
|
||||
usb_set_configuration(usb_dev, -1);
|
||||
|
||||
kfree(usb_dev->product);
|
||||
usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
|
||||
kfree(usb_dev->manufacturer);
|
||||
usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
|
||||
kfree(usb_dev->serial);
|
||||
usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
|
||||
|
||||
usb_destroy_configuration(usb_dev);
|
||||
usb_dev->descriptor.bNumConfigurations = 0;
|
||||
|
||||
out_unauthorized:
|
||||
usb_unlock_device(usb_dev);
|
||||
return 0;
|
||||
@ -2464,17 +2448,7 @@ int usb_authorize_device(struct usb_device *usb_dev)
|
||||
goto error_device_descriptor;
|
||||
}
|
||||
|
||||
kfree(usb_dev->product);
|
||||
usb_dev->product = NULL;
|
||||
kfree(usb_dev->manufacturer);
|
||||
usb_dev->manufacturer = NULL;
|
||||
kfree(usb_dev->serial);
|
||||
usb_dev->serial = NULL;
|
||||
|
||||
usb_dev->authorized = 1;
|
||||
result = usb_enumerate_device(usb_dev);
|
||||
if (result < 0)
|
||||
goto error_enumerate;
|
||||
/* Choose and set the configuration. This registers the interfaces
|
||||
* with the driver core and lets interface drivers bind to them.
|
||||
*/
|
||||
@ -2490,7 +2464,6 @@ int usb_authorize_device(struct usb_device *usb_dev)
|
||||
}
|
||||
dev_info(&usb_dev->dev, "authorized to connect\n");
|
||||
|
||||
error_enumerate:
|
||||
error_device_descriptor:
|
||||
usb_autosuspend_device(usb_dev);
|
||||
error_autoresume:
|
||||
@ -2523,10 +2496,25 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
|
||||
#define HUB_LONG_RESET_TIME 200
|
||||
#define HUB_RESET_TIMEOUT 800
|
||||
|
||||
/*
|
||||
* "New scheme" enumeration causes an extra state transition to be
|
||||
* exposed to an xhci host and causes USB3 devices to receive control
|
||||
* commands in the default state. This has been seen to cause
|
||||
* enumeration failures, so disable this enumeration scheme for USB3
|
||||
* devices.
|
||||
*/
|
||||
static bool use_new_scheme(struct usb_device *udev, int retry)
|
||||
{
|
||||
if (udev->speed == USB_SPEED_SUPER)
|
||||
return false;
|
||||
|
||||
return USE_NEW_SCHEME(retry);
|
||||
}
|
||||
|
||||
static int hub_port_reset(struct usb_hub *hub, int port1,
|
||||
struct usb_device *udev, unsigned int delay, bool warm);
|
||||
|
||||
/* Is a USB 3.0 port in the Inactive or Complinance Mode state?
|
||||
/* Is a USB 3.0 port in the Inactive or Compliance Mode state?
|
||||
* Port worm reset is required to recover
|
||||
*/
|
||||
static bool hub_port_warm_reset_required(struct usb_hub *hub, u16 portstatus)
|
||||
@ -3334,7 +3322,8 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
|
||||
|
||||
udev = hub->ports[port1 - 1]->child;
|
||||
if (udev && udev->can_submit) {
|
||||
dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
|
||||
dev_warn(&intf->dev, "port %d not suspended yet\n",
|
||||
port1);
|
||||
if (PMSG_IS_AUTO(msg))
|
||||
return -EBUSY;
|
||||
}
|
||||
@ -3981,6 +3970,20 @@ static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev)
|
||||
}
|
||||
}
|
||||
|
||||
static int hub_enable_device(struct usb_device *udev)
|
||||
{
|
||||
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
||||
|
||||
if (!hcd->driver->enable_device)
|
||||
return 0;
|
||||
if (udev->state == USB_STATE_ADDRESS)
|
||||
return 0;
|
||||
if (udev->state != USB_STATE_DEFAULT)
|
||||
return -EINVAL;
|
||||
|
||||
return hcd->driver->enable_device(hcd, udev);
|
||||
}
|
||||
|
||||
/* Reset device, (re)assign address, get device descriptor.
|
||||
* Device connection must be stable, no more debouncing needed.
|
||||
* Returns device in USB_STATE_ADDRESS, except on error.
|
||||
@ -4093,7 +4096,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
|
||||
* this area, and this is how Linux has done it for ages.
|
||||
* Change it cautiously.
|
||||
*
|
||||
* NOTE: If USE_NEW_SCHEME() is true we will start by issuing
|
||||
* NOTE: If use_new_scheme() is true we will start by issuing
|
||||
* a 64-byte GET_DESCRIPTOR request. This is what Windows does,
|
||||
* so it may help with some non-standards-compliant devices.
|
||||
* Otherwise we start with SET_ADDRESS and then try to read the
|
||||
@ -4101,10 +4104,17 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
|
||||
* value.
|
||||
*/
|
||||
for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) {
|
||||
if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3)) {
|
||||
bool did_new_scheme = false;
|
||||
|
||||
if (use_new_scheme(udev, retry_counter)) {
|
||||
struct usb_device_descriptor *buf;
|
||||
int r = 0;
|
||||
|
||||
did_new_scheme = true;
|
||||
retval = hub_enable_device(udev);
|
||||
if (retval < 0)
|
||||
goto fail;
|
||||
|
||||
#define GET_DESCRIPTOR_BUFSIZE 64
|
||||
buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
|
||||
if (!buf) {
|
||||
@ -4193,7 +4203,11 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
|
||||
* - read ep0 maxpacket even for high and low speed,
|
||||
*/
|
||||
msleep(10);
|
||||
if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3))
|
||||
/* use_new_scheme() checks the speed which may have
|
||||
* changed since the initial look so we cache the result
|
||||
* in did_new_scheme
|
||||
*/
|
||||
if (did_new_scheme)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4900,7 +4914,7 @@ static void hub_events(void)
|
||||
|
||||
static int hub_thread(void *__unused)
|
||||
{
|
||||
/* khubd needs to be freezable to avoid intefering with USB-PERSIST
|
||||
/* khubd needs to be freezable to avoid interfering with USB-PERSIST
|
||||
* port handover. Otherwise it might see that a full-speed device
|
||||
* was gone before the EHCI controller had handed its port over to
|
||||
* the companion full-speed controller.
|
||||
|
@ -78,7 +78,7 @@ struct usb_hub {
|
||||
|
||||
/**
|
||||
* struct usb port - kernel's representation of a usb port
|
||||
* @child: usb device attatched to the port
|
||||
* @child: usb device attached to the port
|
||||
* @dev: generic device interface
|
||||
* @port_owner: port's owner
|
||||
* @connect_type: port's connect type
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include <linux/usb.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/ctype.h>
|
||||
@ -218,7 +217,7 @@ EXPORT_SYMBOL_GPL(usb_interrupt_msg);
|
||||
*
|
||||
* Return:
|
||||
* If successful, 0. Otherwise a negative error number. The number of actual
|
||||
* bytes transferred will be stored in the @actual_length paramater.
|
||||
* bytes transferred will be stored in the @actual_length parameter.
|
||||
*
|
||||
*/
|
||||
int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
|
||||
@ -518,7 +517,7 @@ void usb_sg_wait(struct usb_sg_request *io)
|
||||
io->urbs[i]->dev = io->dev;
|
||||
retval = usb_submit_urb(io->urbs[i], GFP_ATOMIC);
|
||||
|
||||
/* after we submit, let completions or cancelations fire;
|
||||
/* after we submit, let completions or cancellations fire;
|
||||
* we handshake using io->status.
|
||||
*/
|
||||
spin_unlock_irq(&io->lock);
|
||||
|
@ -98,9 +98,6 @@ static const struct usb_device_id usb_quirk_list[] = {
|
||||
/* Alcor Micro Corp. Hub */
|
||||
{ USB_DEVICE(0x058f, 0x9254), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||
|
||||
/* MicroTouch Systems touchscreen */
|
||||
{ USB_DEVICE(0x0596, 0x051e), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||
|
||||
/* appletouch */
|
||||
{ USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||
|
||||
|
@ -837,7 +837,7 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
|
||||
device_remove_bin_file(dev, &dev_bin_attr_descriptors);
|
||||
}
|
||||
|
||||
/* Interface Accociation Descriptor fields */
|
||||
/* Interface Association Descriptor fields */
|
||||
#define usb_intf_assoc_attr(field, format_string) \
|
||||
static ssize_t \
|
||||
iad_##field##_show(struct device *dev, struct device_attribute *attr, \
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/wait.h>
|
||||
@ -53,7 +52,7 @@ EXPORT_SYMBOL_GPL(usb_init_urb);
|
||||
* valid options for this.
|
||||
*
|
||||
* Creates an urb for the USB driver to use, initializes a few internal
|
||||
* structures, incrementes the usage counter, and returns a pointer to it.
|
||||
* structures, increments the usage counter, and returns a pointer to it.
|
||||
*
|
||||
* If the driver want to use this urb for interrupt, control, or bulk
|
||||
* endpoints, pass '0' as the number of iso packets.
|
||||
@ -281,7 +280,7 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
|
||||
*
|
||||
* Device drivers must explicitly request that repetition, by ensuring that
|
||||
* some URB is always on the endpoint's queue (except possibly for short
|
||||
* periods during completion callacks). When there is no longer an urb
|
||||
* periods during completion callbacks). When there is no longer an urb
|
||||
* queued, the endpoint's bandwidth reservation is canceled. This means
|
||||
* drivers can use their completion handlers to ensure they keep bandwidth
|
||||
* they need, by reinitializing and resubmitting the just-completed urb
|
||||
@ -325,10 +324,14 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
|
||||
*/
|
||||
int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
||||
{
|
||||
static int pipetypes[4] = {
|
||||
PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
|
||||
};
|
||||
int xfertype, max;
|
||||
struct usb_device *dev;
|
||||
struct usb_host_endpoint *ep;
|
||||
int is_out;
|
||||
unsigned int allowed;
|
||||
|
||||
if (!urb || !urb->complete)
|
||||
return -EINVAL;
|
||||
@ -436,15 +439,10 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
||||
if (urb->transfer_buffer_length > INT_MAX)
|
||||
return -EMSGSIZE;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* stuff that drivers shouldn't do, but which shouldn't
|
||||
/*
|
||||
* stuff that drivers shouldn't do, but which shouldn't
|
||||
* cause problems in HCDs if they get it wrong.
|
||||
*/
|
||||
{
|
||||
unsigned int allowed;
|
||||
static int pipetypes[4] = {
|
||||
PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
|
||||
};
|
||||
|
||||
/* Check that the pipe's type matches the endpoint's type */
|
||||
if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
|
||||
@ -476,8 +474,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
||||
if (allowed != urb->transfer_flags)
|
||||
dev_WARN(&dev->dev, "BOGUS urb flags, %x --> %x\n",
|
||||
urb->transfer_flags, allowed);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Force periodic transfer intervals to be legal values that are
|
||||
* a power of two (so HCDs don't need to).
|
||||
@ -492,9 +489,9 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
||||
/* too small? */
|
||||
switch (dev->speed) {
|
||||
case USB_SPEED_WIRELESS:
|
||||
if (urb->interval < 6)
|
||||
if ((urb->interval < 6)
|
||||
&& (xfertype == USB_ENDPOINT_XFER_INT))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
if (urb->interval <= 0)
|
||||
return -EINVAL;
|
||||
|
@ -92,7 +92,7 @@ static int usb_acpi_check_port_connect_type(struct usb_device *hdev,
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* Accoding to ACPI Spec 9.13. PLD indicates whether usb port is
|
||||
* According to ACPI Spec 9.13. PLD indicates whether usb port is
|
||||
* user visible and _UPC indicates whether it is connectable. If
|
||||
* the port was visible and connectable, it could be freely connected
|
||||
* and disconnected with USB devices. If no visible and connectable,
|
||||
|
@ -2935,6 +2935,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
|
||||
if (retval < 0)
|
||||
goto error3;
|
||||
|
||||
device_wakeup_enable(hcd->self.controller);
|
||||
|
||||
dwc2_hcd_dump_state(hsotg);
|
||||
|
||||
dwc2_enable_global_interrupts(hsotg);
|
||||
|
@ -70,6 +70,13 @@ config USB_DWC3_PCI
|
||||
One such PCIe-based platform is Synopsys' PCIe HAPS model of
|
||||
this IP.
|
||||
|
||||
config USB_DWC3_KEYSTONE
|
||||
tristate "Texas Instruments Keystone2 Platforms"
|
||||
default USB_DWC3
|
||||
help
|
||||
Support of USB2/3 functionality in TI Keystone2 platforms.
|
||||
Say 'Y' or 'M' here if you have one such device
|
||||
|
||||
comment "Debugging features"
|
||||
|
||||
config USB_DWC3_DEBUG
|
||||
|
@ -32,3 +32,4 @@ endif
|
||||
obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o
|
||||
obj-$(CONFIG_USB_DWC3_EXYNOS) += dwc3-exynos.o
|
||||
obj-$(CONFIG_USB_DWC3_PCI) += dwc3-pci.o
|
||||
obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o
|
||||
|
@ -50,6 +50,7 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
|
||||
|
||||
exynos->usb2_phy = pdev;
|
||||
pdata.type = USB_PHY_TYPE_USB2;
|
||||
pdata.gpio_reset = -1;
|
||||
|
||||
ret = platform_device_add_data(exynos->usb2_phy, &pdata, sizeof(pdata));
|
||||
if (ret)
|
||||
|
202
drivers/usb/dwc3/dwc3-keystone.c
Normal file
202
drivers/usb/dwc3/dwc3-keystone.c
Normal file
@ -0,0 +1,202 @@
|
||||
/**
|
||||
* dwc3-keystone.c - Keystone Specific Glue layer
|
||||
*
|
||||
* Copyright (C) 2010-2013 Texas Instruments Incorporated - http://www.ti.com
|
||||
*
|
||||
* Author: WingMan Kwok <w-kwok2@ti.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 of
|
||||
* the License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
/* USBSS register offsets */
|
||||
#define USBSS_REVISION 0x0000
|
||||
#define USBSS_SYSCONFIG 0x0010
|
||||
#define USBSS_IRQ_EOI 0x0018
|
||||
#define USBSS_IRQSTATUS_RAW_0 0x0020
|
||||
#define USBSS_IRQSTATUS_0 0x0024
|
||||
#define USBSS_IRQENABLE_SET_0 0x0028
|
||||
#define USBSS_IRQENABLE_CLR_0 0x002c
|
||||
|
||||
/* IRQ register bits */
|
||||
#define USBSS_IRQ_EOI_LINE(n) BIT(n)
|
||||
#define USBSS_IRQ_EVENT_ST BIT(0)
|
||||
#define USBSS_IRQ_COREIRQ_EN BIT(0)
|
||||
#define USBSS_IRQ_COREIRQ_CLR BIT(0)
|
||||
|
||||
static u64 kdwc3_dma_mask;
|
||||
|
||||
struct dwc3_keystone {
|
||||
struct device *dev;
|
||||
struct clk *clk;
|
||||
void __iomem *usbss;
|
||||
};
|
||||
|
||||
static inline u32 kdwc3_readl(void __iomem *base, u32 offset)
|
||||
{
|
||||
return readl(base + offset);
|
||||
}
|
||||
|
||||
static inline void kdwc3_writel(void __iomem *base, u32 offset, u32 value)
|
||||
{
|
||||
writel(value, base + offset);
|
||||
}
|
||||
|
||||
static void kdwc3_enable_irqs(struct dwc3_keystone *kdwc)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = kdwc3_readl(kdwc->usbss, USBSS_IRQENABLE_SET_0);
|
||||
val |= USBSS_IRQ_COREIRQ_EN;
|
||||
kdwc3_writel(kdwc->usbss, USBSS_IRQENABLE_SET_0, val);
|
||||
}
|
||||
|
||||
static void kdwc3_disable_irqs(struct dwc3_keystone *kdwc)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = kdwc3_readl(kdwc->usbss, USBSS_IRQENABLE_SET_0);
|
||||
val &= ~USBSS_IRQ_COREIRQ_EN;
|
||||
kdwc3_writel(kdwc->usbss, USBSS_IRQENABLE_SET_0, val);
|
||||
}
|
||||
|
||||
static irqreturn_t dwc3_keystone_interrupt(int irq, void *_kdwc)
|
||||
{
|
||||
struct dwc3_keystone *kdwc = _kdwc;
|
||||
|
||||
kdwc3_writel(kdwc->usbss, USBSS_IRQENABLE_CLR_0, USBSS_IRQ_COREIRQ_CLR);
|
||||
kdwc3_writel(kdwc->usbss, USBSS_IRQSTATUS_0, USBSS_IRQ_EVENT_ST);
|
||||
kdwc3_writel(kdwc->usbss, USBSS_IRQENABLE_SET_0, USBSS_IRQ_COREIRQ_EN);
|
||||
kdwc3_writel(kdwc->usbss, USBSS_IRQ_EOI, USBSS_IRQ_EOI_LINE(0));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int kdwc3_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct dwc3_keystone *kdwc;
|
||||
struct resource *res;
|
||||
int error, irq;
|
||||
|
||||
kdwc = devm_kzalloc(dev, sizeof(*kdwc), GFP_KERNEL);
|
||||
if (!kdwc)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, kdwc);
|
||||
|
||||
kdwc->dev = dev;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(dev, "missing usbss resource\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
kdwc->usbss = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(kdwc->usbss))
|
||||
return PTR_ERR(kdwc->usbss);
|
||||
|
||||
kdwc3_dma_mask = dma_get_mask(dev);
|
||||
dev->dma_mask = &kdwc3_dma_mask;
|
||||
|
||||
kdwc->clk = devm_clk_get(kdwc->dev, "usb");
|
||||
|
||||
error = clk_prepare_enable(kdwc->clk);
|
||||
if (error < 0) {
|
||||
dev_dbg(kdwc->dev, "unable to enable usb clock, err %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
dev_err(&pdev->dev, "missing irq\n");
|
||||
goto err_irq;
|
||||
}
|
||||
|
||||
error = devm_request_irq(dev, irq, dwc3_keystone_interrupt, IRQF_SHARED,
|
||||
dev_name(dev), kdwc);
|
||||
if (error) {
|
||||
dev_err(dev, "failed to request IRQ #%d --> %d\n",
|
||||
irq, error);
|
||||
goto err_irq;
|
||||
}
|
||||
|
||||
kdwc3_enable_irqs(kdwc);
|
||||
|
||||
error = of_platform_populate(node, NULL, NULL, dev);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to create dwc3 core\n");
|
||||
goto err_core;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_core:
|
||||
kdwc3_disable_irqs(kdwc);
|
||||
err_irq:
|
||||
clk_disable_unprepare(kdwc->clk);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int kdwc3_remove_core(struct device *dev, void *c)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
||||
platform_device_unregister(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kdwc3_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct dwc3_keystone *kdwc = platform_get_drvdata(pdev);
|
||||
|
||||
kdwc3_disable_irqs(kdwc);
|
||||
device_for_each_child(&pdev->dev, NULL, kdwc3_remove_core);
|
||||
clk_disable_unprepare(kdwc->clk);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id kdwc3_of_match[] = {
|
||||
{ .compatible = "ti,keystone-dwc3", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, kdwc3_of_match);
|
||||
|
||||
static struct platform_driver kdwc3_driver = {
|
||||
.probe = kdwc3_probe,
|
||||
.remove = kdwc3_remove,
|
||||
.driver = {
|
||||
.name = "keystone-dwc3",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = kdwc3_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(kdwc3_driver);
|
||||
|
||||
MODULE_ALIAS("platform:keystone-dwc3");
|
||||
MODULE_AUTHOR("WingMan Kwok <w-kwok2@ti.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("DesignWare USB3 KEYSTONE Glue Layer");
|
@ -20,7 +20,6 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/dwc3-omap.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
@ -120,9 +119,6 @@
|
||||
#define USBOTGSS_UTMI_OTG_STATUS_VBUSVALID (1 << 1)
|
||||
|
||||
struct dwc3_omap {
|
||||
/* device lock */
|
||||
spinlock_t lock;
|
||||
|
||||
struct device *dev;
|
||||
|
||||
int irq;
|
||||
@ -280,8 +276,6 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
|
||||
struct dwc3_omap *omap = _omap;
|
||||
u32 reg;
|
||||
|
||||
spin_lock(&omap->lock);
|
||||
|
||||
reg = dwc3_omap_read_irqmisc_status(omap);
|
||||
|
||||
if (reg & USBOTGSS_IRQMISC_DMADISABLECLR) {
|
||||
@ -322,8 +316,6 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
|
||||
|
||||
dwc3_omap_write_irq0_status(omap, reg);
|
||||
|
||||
spin_unlock(&omap->lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@ -449,8 +441,6 @@ static int dwc3_omap_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_init(&omap->lock);
|
||||
|
||||
omap->dev = dev;
|
||||
omap->irq = irq;
|
||||
omap->base = base;
|
||||
@ -535,7 +525,7 @@ static int dwc3_omap_probe(struct platform_device *pdev)
|
||||
edev = of_extcon_get_extcon_dev(dev, 0);
|
||||
if (IS_ERR(edev)) {
|
||||
dev_vdbg(dev, "couldn't get extcon device\n");
|
||||
ret = PTR_ERR(edev);
|
||||
ret = -EPROBE_DEFER;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,7 @@ static int dwc3_pci_register_phys(struct dwc3_pci *glue)
|
||||
|
||||
glue->usb2_phy = pdev;
|
||||
pdata.type = USB_PHY_TYPE_USB2;
|
||||
pdata.gpio_reset = -1;
|
||||
|
||||
ret = platform_device_add_data(glue->usb2_phy, &pdata, sizeof(pdata));
|
||||
if (ret)
|
||||
@ -182,7 +183,7 @@ static void dwc3_pci_remove(struct pci_dev *pci)
|
||||
pci_disable_device(pci);
|
||||
}
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
|
||||
static const struct pci_device_id dwc3_pci_id_table[] = {
|
||||
{
|
||||
PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
|
||||
PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),
|
||||
|
@ -1650,7 +1650,7 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
|
||||
dev_vdbg(dwc->dev, "initializing %s\n", dep->name);
|
||||
|
||||
if (epnum == 0 || epnum == 1) {
|
||||
dep->endpoint.maxpacket = 512;
|
||||
usb_ep_set_maxpacket_limit(&dep->endpoint, 512);
|
||||
dep->endpoint.maxburst = 1;
|
||||
dep->endpoint.ops = &dwc3_gadget_ep0_ops;
|
||||
if (!epnum)
|
||||
@ -1658,7 +1658,7 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
|
||||
} else {
|
||||
int ret;
|
||||
|
||||
dep->endpoint.maxpacket = 1024;
|
||||
usb_ep_set_maxpacket_limit(&dep->endpoint, 1024);
|
||||
dep->endpoint.max_streams = 15;
|
||||
dep->endpoint.ops = &dwc3_gadget_ep_ops;
|
||||
list_add_tail(&dep->endpoint.ep_list,
|
||||
@ -2596,6 +2596,12 @@ int dwc3_gadget_init(struct dwc3 *dwc)
|
||||
dwc->gadget.sg_supported = true;
|
||||
dwc->gadget.name = "dwc3-gadget";
|
||||
|
||||
/*
|
||||
* Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize
|
||||
* on ep out.
|
||||
*/
|
||||
dwc->gadget.quirk_ep_out_aligned_size = true;
|
||||
|
||||
/*
|
||||
* REVISIT: Here we should clear all pending IRQs to be
|
||||
* sure we're starting from a well known location.
|
||||
|
@ -216,6 +216,13 @@ config USB_FOTG210_UDC
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "fotg210_udc".
|
||||
|
||||
config USB_GR_UDC
|
||||
tristate "Aeroflex Gaisler GRUSBDC USB Peripheral Controller Driver"
|
||||
depends on HAS_DMA
|
||||
help
|
||||
Select this to support Aeroflex Gaisler GRUSBDC cores from the GRLIB
|
||||
VHDL IP core library.
|
||||
|
||||
config USB_OMAP
|
||||
tristate "OMAP USB Device Controller"
|
||||
depends on ARCH_OMAP1
|
||||
@ -294,11 +301,11 @@ config USB_PXA27X
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_S3C_HSOTG
|
||||
tristate "S3C HS/OtG USB Device controller"
|
||||
depends on S3C_DEV_USB_HSOTG
|
||||
depends on ARM
|
||||
tristate "Designware/S3C HS/OtG USB Device controller"
|
||||
help
|
||||
The Samsung S3C64XX USB2.0 high-speed gadget controller
|
||||
integrated into the S3C64XX series SoC.
|
||||
The Designware USB2.0 high-speed gadget controller
|
||||
integrated into many SoCs.
|
||||
|
||||
config USB_S3C2410
|
||||
tristate "S3C2410 USB Device Controller"
|
||||
@ -512,9 +519,6 @@ config USB_U_SERIAL
|
||||
config USB_U_ETHER
|
||||
tristate
|
||||
|
||||
config USB_U_RNDIS
|
||||
tristate
|
||||
|
||||
config USB_F_SERIAL
|
||||
tristate
|
||||
|
||||
@ -542,6 +546,9 @@ config USB_F_RNDIS
|
||||
config USB_F_MASS_STORAGE
|
||||
tristate
|
||||
|
||||
config USB_F_FS
|
||||
tristate
|
||||
|
||||
choice
|
||||
tristate "USB Gadget Drivers"
|
||||
default USB_ETH
|
||||
@ -642,7 +649,6 @@ config USB_CONFIGFS_RNDIS
|
||||
depends on USB_CONFIGFS
|
||||
depends on NET
|
||||
select USB_U_ETHER
|
||||
select USB_U_RNDIS
|
||||
select USB_F_RNDIS
|
||||
help
|
||||
Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
|
||||
@ -690,6 +696,31 @@ config USB_CONFIGFS_MASS_STORAGE
|
||||
device (in much the same way as the "loop" device driver),
|
||||
specified as a module parameter or sysfs option.
|
||||
|
||||
config USB_CONFIGFS_F_LB_SS
|
||||
boolean "Loopback and sourcesink function (for testing)"
|
||||
depends on USB_CONFIGFS
|
||||
select USB_F_SS_LB
|
||||
help
|
||||
Loopback function loops back a configurable number of transfers.
|
||||
Sourcesink function either sinks and sources bulk data.
|
||||
It also implements control requests, for "chapter 9" conformance.
|
||||
Make this be the first driver you try using on top of any new
|
||||
USB peripheral controller driver. Then you can use host-side
|
||||
test software, like the "usbtest" driver, to put your hardware
|
||||
and its driver through a basic set of functional tests.
|
||||
|
||||
config USB_CONFIGFS_F_FS
|
||||
boolean "Function filesystem (FunctionFS)"
|
||||
depends on USB_CONFIGFS
|
||||
select USB_F_FS
|
||||
help
|
||||
The Function Filesystem (FunctionFS) lets one create USB
|
||||
composite functions in user space in the same way GadgetFS
|
||||
lets one create USB gadgets in user space. This allows creation
|
||||
of composite gadgets such that some of the functions are
|
||||
implemented in kernel space (for instance Ethernet, serial or
|
||||
mass storage) and other are implemented in user space.
|
||||
|
||||
config USB_ZERO
|
||||
tristate "Gadget Zero (DEVELOPMENT)"
|
||||
select USB_LIBCOMPOSITE
|
||||
@ -760,7 +791,6 @@ config USB_ETH
|
||||
depends on NET
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_U_ETHER
|
||||
select USB_U_RNDIS
|
||||
select USB_F_ECM
|
||||
select USB_F_SUBSET
|
||||
select CRC32
|
||||
@ -864,6 +894,7 @@ config USB_GADGETFS
|
||||
config USB_FUNCTIONFS
|
||||
tristate "Function Filesystem"
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_F_FS
|
||||
select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
|
||||
help
|
||||
The Function Filesystem (FunctionFS) lets one create USB
|
||||
@ -883,6 +914,8 @@ config USB_FUNCTIONFS_ETH
|
||||
bool "Include configuration with CDC ECM (Ethernet)"
|
||||
depends on USB_FUNCTIONFS && NET
|
||||
select USB_U_ETHER
|
||||
select USB_F_ECM
|
||||
select USB_F_SUBSET
|
||||
help
|
||||
Include a configuration with CDC ECM function (Ethernet) and the
|
||||
Function Filesystem.
|
||||
@ -891,7 +924,7 @@ config USB_FUNCTIONFS_RNDIS
|
||||
bool "Include configuration with RNDIS (Ethernet)"
|
||||
depends on USB_FUNCTIONFS && NET
|
||||
select USB_U_ETHER
|
||||
select USB_U_RNDIS
|
||||
select USB_F_RNDIS
|
||||
help
|
||||
Include a configuration with RNDIS function (Ethernet) and the Filesystem.
|
||||
|
||||
@ -1065,7 +1098,6 @@ config USB_G_MULTI
|
||||
config USB_G_MULTI_RNDIS
|
||||
bool "RNDIS + CDC Serial + Storage configuration"
|
||||
depends on USB_G_MULTI
|
||||
select USB_U_RNDIS
|
||||
select USB_F_RNDIS
|
||||
default y
|
||||
help
|
||||
|
@ -7,7 +7,7 @@ ccflags-$(CONFIG_USB_GADGET_VERBOSE) += -DVERBOSE_DEBUG
|
||||
obj-$(CONFIG_USB_GADGET) += udc-core.o
|
||||
obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
|
||||
libcomposite-y := usbstring.o config.o epautoconf.o
|
||||
libcomposite-y += composite.o functions.o configfs.o
|
||||
libcomposite-y += composite.o functions.o configfs.o u_f.o
|
||||
obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
|
||||
obj-$(CONFIG_USB_NET2272) += net2272.o
|
||||
obj-$(CONFIG_USB_NET2280) += net2280.o
|
||||
@ -35,6 +35,7 @@ mv_udc-y := mv_udc_core.o
|
||||
obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o
|
||||
obj-$(CONFIG_USB_FOTG210_UDC) += fotg210-udc.o
|
||||
obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o
|
||||
obj-$(CONFIG_USB_GR_UDC) += gr_udc.o
|
||||
|
||||
# USB Functions
|
||||
usb_f_acm-y := f_acm.o
|
||||
@ -47,8 +48,6 @@ obj-$(CONFIG_USB_F_SERIAL) += usb_f_serial.o
|
||||
usb_f_obex-y := f_obex.o
|
||||
obj-$(CONFIG_USB_F_OBEX) += usb_f_obex.o
|
||||
obj-$(CONFIG_USB_U_ETHER) += u_ether.o
|
||||
u_rndis-y := rndis.o
|
||||
obj-$(CONFIG_USB_U_RNDIS) += u_rndis.o
|
||||
usb_f_ncm-y := f_ncm.o
|
||||
obj-$(CONFIG_USB_F_NCM) += usb_f_ncm.o
|
||||
usb_f_ecm-y := f_ecm.o
|
||||
@ -59,10 +58,12 @@ usb_f_eem-y := f_eem.o
|
||||
obj-$(CONFIG_USB_F_EEM) += usb_f_eem.o
|
||||
usb_f_ecm_subset-y := f_subset.o
|
||||
obj-$(CONFIG_USB_F_SUBSET) += usb_f_ecm_subset.o
|
||||
usb_f_rndis-y := f_rndis.o
|
||||
usb_f_rndis-y := f_rndis.o rndis.o
|
||||
obj-$(CONFIG_USB_F_RNDIS) += usb_f_rndis.o
|
||||
usb_f_mass_storage-y := f_mass_storage.o storage_common.o
|
||||
obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
|
||||
usb_f_fs-y := f_fs.o
|
||||
obj-$(CONFIG_USB_F_FS) += usb_f_fs.o
|
||||
|
||||
#
|
||||
# USB gadget drivers
|
||||
|
@ -107,7 +107,7 @@ static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
|
||||
*/
|
||||
#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
|
||||
|
||||
#endif /* CONFIG_USB_DEBUG */
|
||||
#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
|
||||
|
||||
FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
|
||||
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/interrupt.h>
|
||||
@ -446,7 +445,7 @@ static void ep_init(struct udc_regs __iomem *regs, struct udc_ep *ep)
|
||||
ep->ep.ops = &udc_ep_ops;
|
||||
INIT_LIST_HEAD(&ep->queue);
|
||||
|
||||
ep->ep.maxpacket = (u16) ~0;
|
||||
usb_ep_set_maxpacket_limit(&ep->ep,(u16) ~0);
|
||||
/* set NAK */
|
||||
tmp = readl(&ep->regs->ctl);
|
||||
tmp |= AMD_BIT(UDC_EPCTL_SNAK);
|
||||
@ -1564,12 +1563,15 @@ static void udc_setup_endpoints(struct udc *dev)
|
||||
}
|
||||
/* EP0 max packet */
|
||||
if (dev->gadget.speed == USB_SPEED_FULL) {
|
||||
dev->ep[UDC_EP0IN_IX].ep.maxpacket = UDC_FS_EP0IN_MAX_PKT_SIZE;
|
||||
dev->ep[UDC_EP0OUT_IX].ep.maxpacket =
|
||||
UDC_FS_EP0OUT_MAX_PKT_SIZE;
|
||||
usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0IN_IX].ep,
|
||||
UDC_FS_EP0IN_MAX_PKT_SIZE);
|
||||
usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0OUT_IX].ep,
|
||||
UDC_FS_EP0OUT_MAX_PKT_SIZE);
|
||||
} else if (dev->gadget.speed == USB_SPEED_HIGH) {
|
||||
dev->ep[UDC_EP0IN_IX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE;
|
||||
dev->ep[UDC_EP0OUT_IX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE;
|
||||
usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0IN_IX].ep,
|
||||
UDC_EP0IN_MAX_PKT_SIZE);
|
||||
usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0OUT_IX].ep,
|
||||
UDC_EP0OUT_MAX_PKT_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3338,7 +3340,7 @@ static int udc_remote_wakeup(struct udc *dev)
|
||||
}
|
||||
|
||||
/* PCI device parameters */
|
||||
static DEFINE_PCI_DEVICE_TABLE(pci_id) = {
|
||||
static const struct pci_device_id pci_id[] = {
|
||||
{
|
||||
PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096),
|
||||
.class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/proc_fs.h>
|
||||
@ -834,7 +833,7 @@ static void udc_reinit(struct at91_udc *udc)
|
||||
ep->ep.desc = NULL;
|
||||
ep->stopped = 0;
|
||||
ep->fifo_bank = 0;
|
||||
ep->ep.maxpacket = ep->maxpacket;
|
||||
usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket);
|
||||
ep->creg = (void __iomem *) udc->udp_baseaddr + AT91_UDP_CSR(i);
|
||||
/* initialize one queue per endpoint */
|
||||
INIT_LIST_HEAD(&ep->queue);
|
||||
@ -1759,15 +1758,15 @@ static int at91udc_probe(struct platform_device *pdev)
|
||||
|
||||
/* newer chips have more FIFO memory than rm9200 */
|
||||
if (cpu_is_at91sam9260() || cpu_is_at91sam9g20()) {
|
||||
udc->ep[0].maxpacket = 64;
|
||||
udc->ep[3].maxpacket = 64;
|
||||
udc->ep[4].maxpacket = 512;
|
||||
udc->ep[5].maxpacket = 512;
|
||||
usb_ep_set_maxpacket_limit(&udc->ep[0].ep, 64);
|
||||
usb_ep_set_maxpacket_limit(&udc->ep[3].ep, 64);
|
||||
usb_ep_set_maxpacket_limit(&udc->ep[4].ep, 512);
|
||||
usb_ep_set_maxpacket_limit(&udc->ep[5].ep, 512);
|
||||
} else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
|
||||
udc->ep[3].maxpacket = 64;
|
||||
usb_ep_set_maxpacket_limit(&udc->ep[3].ep, 64);
|
||||
} else if (cpu_is_at91sam9263()) {
|
||||
udc->ep[0].maxpacket = 64;
|
||||
udc->ep[3].maxpacket = 64;
|
||||
usb_ep_set_maxpacket_limit(&udc->ep[0].ep, 64);
|
||||
usb_ep_set_maxpacket_limit(&udc->ep[3].ep, 64);
|
||||
}
|
||||
|
||||
udc->udp_baseaddr = ioremap(res->start, resource_size(res));
|
||||
|
@ -1012,7 +1012,7 @@ static void nop_release(struct device *dev)
|
||||
|
||||
}
|
||||
|
||||
struct usb_gadget usba_gadget_template = {
|
||||
static struct usb_gadget usba_gadget_template = {
|
||||
.ops = &usba_udc_ops,
|
||||
.max_speed = USB_SPEED_HIGH,
|
||||
.name = "atmel_usba_udc",
|
||||
@ -1904,7 +1904,7 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
|
||||
ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
|
||||
ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
|
||||
ep->ep.ops = &usba_ep_ops;
|
||||
ep->ep.maxpacket = ep->fifo_size;
|
||||
usb_ep_set_maxpacket_limit(&ep->ep, ep->fifo_size);
|
||||
ep->udc = udc;
|
||||
INIT_LIST_HEAD(&ep->queue);
|
||||
|
||||
@ -1957,7 +1957,8 @@ static struct usba_ep * usba_udc_pdata(struct platform_device *pdev,
|
||||
ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
|
||||
ep->ep.ops = &usba_ep_ops;
|
||||
ep->ep.name = pdata->ep[i].name;
|
||||
ep->fifo_size = ep->ep.maxpacket = pdata->ep[i].fifo_size;
|
||||
ep->fifo_size = pdata->ep[i].fifo_size;
|
||||
usb_ep_set_maxpacket_limit(&ep->ep, ep->fifo_size);
|
||||
ep->udc = udc;
|
||||
INIT_LIST_HEAD(&ep->queue);
|
||||
ep->nr_banks = pdata->ep[i].nr_banks;
|
||||
@ -1995,14 +1996,12 @@ static int __init usba_udc_probe(struct platform_device *pdev)
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
pclk = clk_get(&pdev->dev, "pclk");
|
||||
pclk = devm_clk_get(&pdev->dev, "pclk");
|
||||
if (IS_ERR(pclk))
|
||||
return PTR_ERR(pclk);
|
||||
hclk = clk_get(&pdev->dev, "hclk");
|
||||
if (IS_ERR(hclk)) {
|
||||
ret = PTR_ERR(hclk);
|
||||
goto err_get_hclk;
|
||||
}
|
||||
hclk = devm_clk_get(&pdev->dev, "hclk");
|
||||
if (IS_ERR(hclk))
|
||||
return PTR_ERR(hclk);
|
||||
|
||||
spin_lock_init(&udc->lock);
|
||||
udc->pdev = pdev;
|
||||
@ -2011,17 +2010,17 @@ static int __init usba_udc_probe(struct platform_device *pdev)
|
||||
udc->vbus_pin = -ENODEV;
|
||||
|
||||
ret = -ENOMEM;
|
||||
udc->regs = ioremap(regs->start, resource_size(regs));
|
||||
udc->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
|
||||
if (!udc->regs) {
|
||||
dev_err(&pdev->dev, "Unable to map I/O memory, aborting.\n");
|
||||
goto err_map_regs;
|
||||
return ret;
|
||||
}
|
||||
dev_info(&pdev->dev, "MMIO registers at 0x%08lx mapped at %p\n",
|
||||
(unsigned long)regs->start, udc->regs);
|
||||
udc->fifo = ioremap(fifo->start, resource_size(fifo));
|
||||
udc->fifo = devm_ioremap(&pdev->dev, fifo->start, resource_size(fifo));
|
||||
if (!udc->fifo) {
|
||||
dev_err(&pdev->dev, "Unable to map FIFO, aborting.\n");
|
||||
goto err_map_fifo;
|
||||
return ret;
|
||||
}
|
||||
dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",
|
||||
(unsigned long)fifo->start, udc->fifo);
|
||||
@ -2032,7 +2031,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
|
||||
ret = clk_prepare_enable(pclk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Unable to enable pclk, aborting.\n");
|
||||
goto err_clk_enable;
|
||||
return ret;
|
||||
}
|
||||
toggle_bias(0);
|
||||
usba_writel(udc, CTRL, USBA_DISABLE_MASK);
|
||||
@ -2043,22 +2042,22 @@ static int __init usba_udc_probe(struct platform_device *pdev)
|
||||
else
|
||||
udc->usba_ep = usba_udc_pdata(pdev, udc);
|
||||
|
||||
if (IS_ERR(udc->usba_ep)) {
|
||||
ret = PTR_ERR(udc->usba_ep);
|
||||
goto err_alloc_ep;
|
||||
}
|
||||
if (IS_ERR(udc->usba_ep))
|
||||
return PTR_ERR(udc->usba_ep);
|
||||
|
||||
ret = request_irq(irq, usba_udc_irq, 0, "atmel_usba_udc", udc);
|
||||
ret = devm_request_irq(&pdev->dev, irq, usba_udc_irq, 0,
|
||||
"atmel_usba_udc", udc);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Cannot request irq %d (error %d)\n",
|
||||
irq, ret);
|
||||
goto err_request_irq;
|
||||
return ret;
|
||||
}
|
||||
udc->irq = irq;
|
||||
|
||||
if (gpio_is_valid(udc->vbus_pin)) {
|
||||
if (!devm_gpio_request(&pdev->dev, udc->vbus_pin, "atmel_usba_udc")) {
|
||||
ret = request_irq(gpio_to_irq(udc->vbus_pin),
|
||||
ret = devm_request_irq(&pdev->dev,
|
||||
gpio_to_irq(udc->vbus_pin),
|
||||
usba_vbus_irq, 0,
|
||||
"atmel_usba_udc", udc);
|
||||
if (ret) {
|
||||
@ -2077,31 +2076,13 @@ static int __init usba_udc_probe(struct platform_device *pdev)
|
||||
|
||||
ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
|
||||
if (ret)
|
||||
goto err_add_udc;
|
||||
return ret;
|
||||
|
||||
usba_init_debugfs(udc);
|
||||
for (i = 1; i < udc->num_ep; i++)
|
||||
usba_ep_init_debugfs(udc, &udc->usba_ep[i]);
|
||||
|
||||
return 0;
|
||||
|
||||
err_add_udc:
|
||||
if (gpio_is_valid(udc->vbus_pin))
|
||||
free_irq(gpio_to_irq(udc->vbus_pin), udc);
|
||||
|
||||
free_irq(irq, udc);
|
||||
err_request_irq:
|
||||
err_alloc_ep:
|
||||
err_clk_enable:
|
||||
iounmap(udc->fifo);
|
||||
err_map_fifo:
|
||||
iounmap(udc->regs);
|
||||
err_map_regs:
|
||||
clk_put(hclk);
|
||||
err_get_hclk:
|
||||
clk_put(pclk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __exit usba_udc_remove(struct platform_device *pdev)
|
||||
@ -2117,16 +2098,6 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
|
||||
usba_ep_cleanup_debugfs(&udc->usba_ep[i]);
|
||||
usba_cleanup_debugfs(udc);
|
||||
|
||||
if (gpio_is_valid(udc->vbus_pin)) {
|
||||
free_irq(gpio_to_irq(udc->vbus_pin), udc);
|
||||
}
|
||||
|
||||
free_irq(udc->irq, udc);
|
||||
iounmap(udc->fifo);
|
||||
iounmap(udc->regs);
|
||||
clk_put(udc->hclk);
|
||||
clk_put(udc->pclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/kconfig.h>
|
||||
@ -549,7 +548,7 @@ static void bcm63xx_ep_setup(struct bcm63xx_udc *udc)
|
||||
|
||||
if (idx < 0)
|
||||
continue;
|
||||
udc->bep[idx].ep.maxpacket = max_pkt;
|
||||
usb_ep_set_maxpacket_limit(&udc->bep[idx].ep, max_pkt);
|
||||
|
||||
val = (idx << USBD_CSR_EP_LOG_SHIFT) |
|
||||
(cfg->dir << USBD_CSR_EP_DIR_SHIFT) |
|
||||
@ -943,7 +942,7 @@ static int bcm63xx_init_udc_hw(struct bcm63xx_udc *udc)
|
||||
bep->ep.ops = &bcm63xx_udc_ep_ops;
|
||||
list_add_tail(&bep->ep.ep_list, &udc->gadget.ep_list);
|
||||
bep->halted = 0;
|
||||
bep->ep.maxpacket = BCM63XX_MAX_CTRL_PKT;
|
||||
usb_ep_set_maxpacket_limit(&bep->ep, BCM63XX_MAX_CTRL_PKT);
|
||||
bep->udc = udc;
|
||||
bep->ep.desc = NULL;
|
||||
INIT_LIST_HEAD(&bep->queue);
|
||||
|
@ -1452,8 +1452,22 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
||||
struct usb_configuration *c;
|
||||
|
||||
c = cdev->config;
|
||||
if (c && c->setup)
|
||||
if (!c)
|
||||
goto done;
|
||||
|
||||
/* try current config's setup */
|
||||
if (c->setup) {
|
||||
value = c->setup(c, ctrl);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* try the only function in the current config */
|
||||
if (!list_is_singular(&c->functions))
|
||||
goto done;
|
||||
f = list_first_entry(&c->functions, struct usb_function,
|
||||
list);
|
||||
if (f->setup)
|
||||
value = f->setup(f, ctrl);
|
||||
}
|
||||
|
||||
goto done;
|
||||
@ -1714,7 +1728,7 @@ composite_resume(struct usb_gadget *gadget)
|
||||
{
|
||||
struct usb_composite_dev *cdev = get_gadget_data(gadget);
|
||||
struct usb_function *f;
|
||||
u8 maxpower;
|
||||
u16 maxpower;
|
||||
|
||||
/* REVISIT: should we have config level
|
||||
* suspend/resume callbacks?
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/usb/composite.h>
|
||||
#include <linux/usb/gadget_configfs.h>
|
||||
#include "configfs.h"
|
||||
|
||||
int check_user_usb_string(const char *name,
|
||||
struct usb_gadget_strings *stringtab_dev)
|
||||
@ -564,6 +565,13 @@ static struct config_group *function_make(
|
||||
usb_put_function_instance(fi);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
if (fi->set_inst_name) {
|
||||
ret = fi->set_inst_name(fi, instance_name);
|
||||
if (ret) {
|
||||
usb_put_function_instance(fi);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
}
|
||||
|
||||
gi = container_of(group, struct gadget_info, functions_group);
|
||||
|
||||
|
@ -951,7 +951,7 @@ static void init_dummy_udc_hw(struct dummy *dum)
|
||||
list_add_tail(&ep->ep.ep_list, &dum->gadget.ep_list);
|
||||
ep->halted = ep->wedged = ep->already_seen =
|
||||
ep->setup_stage = 0;
|
||||
ep->ep.maxpacket = ~0;
|
||||
usb_ep_set_maxpacket_limit(&ep->ep, ~0);
|
||||
ep->ep.max_streams = 16;
|
||||
ep->last_io = jiffies;
|
||||
ep->gadget = &dum->gadget;
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
@ -58,7 +57,7 @@ ep_matches (
|
||||
return 0;
|
||||
|
||||
/* only support ep0 for portable CONTROL traffic */
|
||||
type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
|
||||
type = usb_endpoint_type(desc);
|
||||
if (USB_ENDPOINT_XFER_CONTROL == type)
|
||||
return 0;
|
||||
|
||||
@ -129,7 +128,7 @@ ep_matches (
|
||||
* and wants to know the maximum possible, provide the info.
|
||||
*/
|
||||
if (desc->wMaxPacketSize == 0)
|
||||
desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket);
|
||||
desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit);
|
||||
|
||||
/* endpoint maxpacket size is an input parameter, except for bulk
|
||||
* where it's an output parameter representing the full speed limit.
|
||||
@ -145,7 +144,7 @@ ep_matches (
|
||||
|
||||
case USB_ENDPOINT_XFER_ISOC:
|
||||
/* ISO: limit 1023 bytes full speed, 1024 high/super speed */
|
||||
if (ep->maxpacket < max)
|
||||
if (ep->maxpacket_limit < max)
|
||||
return 0;
|
||||
if (!gadget_is_dualspeed(gadget) && max > 1023)
|
||||
return 0;
|
||||
@ -178,7 +177,7 @@ ep_matches (
|
||||
|
||||
/* report (variable) full speed bulk maxpacket */
|
||||
if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) {
|
||||
int size = ep->maxpacket;
|
||||
int size = ep->maxpacket_limit;
|
||||
|
||||
/* min() doesn't work on bitfields with gcc-3.5 */
|
||||
if (size > 64)
|
||||
|
@ -691,7 +691,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
int status;
|
||||
struct usb_ep *ep;
|
||||
|
||||
#ifndef USBF_ECM_INCLUDED
|
||||
struct f_ecm_opts *ecm_opts;
|
||||
|
||||
if (!can_support_ecm(cdev->gadget))
|
||||
@ -715,7 +714,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
return status;
|
||||
ecm_opts->bound = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
us = usb_gstrings_attach(cdev, ecm_strings,
|
||||
ARRAY_SIZE(ecm_string_defs));
|
||||
if (IS_ERR(us))
|
||||
@ -834,74 +833,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef USBF_ECM_INCLUDED
|
||||
|
||||
static void
|
||||
ecm_old_unbind(struct usb_configuration *c, struct usb_function *f)
|
||||
{
|
||||
struct f_ecm *ecm = func_to_ecm(f);
|
||||
|
||||
DBG(c->cdev, "ecm unbind\n");
|
||||
|
||||
usb_free_all_descriptors(f);
|
||||
|
||||
kfree(ecm->notify_req->buf);
|
||||
usb_ep_free_request(ecm->notify, ecm->notify_req);
|
||||
kfree(ecm);
|
||||
}
|
||||
|
||||
/**
|
||||
* ecm_bind_config - add CDC Ethernet network link to a configuration
|
||||
* @c: the configuration to support the network link
|
||||
* @ethaddr: a buffer in which the ethernet address of the host side
|
||||
* side of the link was recorded
|
||||
* @dev: eth_dev structure
|
||||
* Context: single threaded during gadget setup
|
||||
*
|
||||
* Returns zero on success, else negative errno.
|
||||
*
|
||||
* Caller must have called @gether_setup(). Caller is also responsible
|
||||
* for calling @gether_cleanup() before module unload.
|
||||
*/
|
||||
int
|
||||
ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
|
||||
struct eth_dev *dev)
|
||||
{
|
||||
struct f_ecm *ecm;
|
||||
int status;
|
||||
|
||||
if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
|
||||
return -EINVAL;
|
||||
|
||||
/* allocate and initialize one new instance */
|
||||
ecm = kzalloc(sizeof *ecm, GFP_KERNEL);
|
||||
if (!ecm)
|
||||
return -ENOMEM;
|
||||
|
||||
/* export host's Ethernet address in CDC format */
|
||||
snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr);
|
||||
ecm_string_defs[1].s = ecm->ethaddr;
|
||||
|
||||
ecm->port.ioport = dev;
|
||||
ecm->port.cdc_filter = DEFAULT_FILTER;
|
||||
|
||||
ecm->port.func.name = "cdc_ethernet";
|
||||
/* descriptors are per-instance copies */
|
||||
ecm->port.func.bind = ecm_bind;
|
||||
ecm->port.func.unbind = ecm_old_unbind;
|
||||
ecm->port.func.set_alt = ecm_set_alt;
|
||||
ecm->port.func.get_alt = ecm_get_alt;
|
||||
ecm->port.func.setup = ecm_setup;
|
||||
ecm->port.func.disable = ecm_disable;
|
||||
|
||||
status = usb_add_function(c, &ecm->port.func);
|
||||
if (status)
|
||||
kfree(ecm);
|
||||
return status;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline struct f_ecm_opts *to_f_ecm_opts(struct config_item *item)
|
||||
{
|
||||
return container_of(to_config_group(item), struct f_ecm_opts,
|
||||
@ -1040,5 +971,3 @@ static struct usb_function *ecm_alloc(struct usb_function_instance *fi)
|
||||
DECLARE_USB_FUNCTION_INIT(ecm, ecm_alloc_inst, ecm_alloc);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("David Brownell");
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -20,6 +20,8 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/usb/g_hid.h>
|
||||
|
||||
#include "u_f.h"
|
||||
|
||||
static int major, minors;
|
||||
static struct class *hidg_class;
|
||||
|
||||
@ -334,20 +336,10 @@ static int f_hidg_open(struct inode *inode, struct file *fd)
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/* usb_function */
|
||||
|
||||
static struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep, unsigned length)
|
||||
static inline struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep,
|
||||
unsigned length)
|
||||
{
|
||||
struct usb_request *req;
|
||||
|
||||
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
|
||||
if (req) {
|
||||
req->length = length;
|
||||
req->buf = kmalloc(length, GFP_ATOMIC);
|
||||
if (!req->buf) {
|
||||
usb_ep_free_request(ep, req);
|
||||
req = NULL;
|
||||
}
|
||||
}
|
||||
return req;
|
||||
return alloc_ep_req(ep, length, length);
|
||||
}
|
||||
|
||||
static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req)
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <linux/usb/composite.h>
|
||||
|
||||
#include "g_zero.h"
|
||||
#include "u_f.h"
|
||||
|
||||
/*
|
||||
* LOOPBACK FUNCTION ... a testing vehicle for USB peripherals,
|
||||
@ -119,7 +120,7 @@ static struct usb_endpoint_descriptor ss_loop_source_desc = {
|
||||
.wMaxPacketSize = cpu_to_le16(1024),
|
||||
};
|
||||
|
||||
struct usb_ss_ep_comp_descriptor ss_loop_source_comp_desc = {
|
||||
static struct usb_ss_ep_comp_descriptor ss_loop_source_comp_desc = {
|
||||
.bLength = USB_DT_SS_EP_COMP_SIZE,
|
||||
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
||||
.bMaxBurst = 0,
|
||||
@ -135,7 +136,7 @@ static struct usb_endpoint_descriptor ss_loop_sink_desc = {
|
||||
.wMaxPacketSize = cpu_to_le16(1024),
|
||||
};
|
||||
|
||||
struct usb_ss_ep_comp_descriptor ss_loop_sink_comp_desc = {
|
||||
static struct usb_ss_ep_comp_descriptor ss_loop_sink_comp_desc = {
|
||||
.bLength = USB_DT_SS_EP_COMP_SIZE,
|
||||
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
||||
.bMaxBurst = 0,
|
||||
@ -230,6 +231,14 @@ static int loopback_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
|
||||
static void lb_free_func(struct usb_function *f)
|
||||
{
|
||||
struct f_lb_opts *opts;
|
||||
|
||||
opts = container_of(f->fi, struct f_lb_opts, func_inst);
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
opts->refcnt--;
|
||||
mutex_unlock(&opts->lock);
|
||||
|
||||
usb_free_all_descriptors(f);
|
||||
kfree(func_to_loop(f));
|
||||
}
|
||||
@ -293,6 +302,11 @@ static void disable_loopback(struct f_loopback *loop)
|
||||
VDBG(cdev, "%s disabled\n", loop->function.name);
|
||||
}
|
||||
|
||||
static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len)
|
||||
{
|
||||
return alloc_ep_req(ep, len, buflen);
|
||||
}
|
||||
|
||||
static int
|
||||
enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
|
||||
{
|
||||
@ -332,7 +346,7 @@ enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
|
||||
* than 'buflen' bytes each.
|
||||
*/
|
||||
for (i = 0; i < qlen && result == 0; i++) {
|
||||
req = alloc_ep_req(ep, 0);
|
||||
req = lb_alloc_ep_req(ep, 0);
|
||||
if (req) {
|
||||
req->complete = loopback_complete;
|
||||
result = usb_ep_queue(ep, req, GFP_ATOMIC);
|
||||
@ -380,6 +394,11 @@ static struct usb_function *loopback_alloc(struct usb_function_instance *fi)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
lb_opts = container_of(fi, struct f_lb_opts, func_inst);
|
||||
|
||||
mutex_lock(&lb_opts->lock);
|
||||
lb_opts->refcnt++;
|
||||
mutex_unlock(&lb_opts->lock);
|
||||
|
||||
buflen = lb_opts->bulk_buflen;
|
||||
qlen = lb_opts->qlen;
|
||||
if (!qlen)
|
||||
@ -396,6 +415,118 @@ static struct usb_function *loopback_alloc(struct usb_function_instance *fi)
|
||||
return &loop->function;
|
||||
}
|
||||
|
||||
static inline struct f_lb_opts *to_f_lb_opts(struct config_item *item)
|
||||
{
|
||||
return container_of(to_config_group(item), struct f_lb_opts,
|
||||
func_inst.group);
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR_STRUCT(f_lb_opts);
|
||||
CONFIGFS_ATTR_OPS(f_lb_opts);
|
||||
|
||||
static void lb_attr_release(struct config_item *item)
|
||||
{
|
||||
struct f_lb_opts *lb_opts = to_f_lb_opts(item);
|
||||
|
||||
usb_put_function_instance(&lb_opts->func_inst);
|
||||
}
|
||||
|
||||
static struct configfs_item_operations lb_item_ops = {
|
||||
.release = lb_attr_release,
|
||||
.show_attribute = f_lb_opts_attr_show,
|
||||
.store_attribute = f_lb_opts_attr_store,
|
||||
};
|
||||
|
||||
static ssize_t f_lb_opts_qlen_show(struct f_lb_opts *opts, char *page)
|
||||
{
|
||||
int result;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
result = sprintf(page, "%d", opts->qlen);
|
||||
mutex_unlock(&opts->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t f_lb_opts_qlen_store(struct f_lb_opts *opts,
|
||||
const char *page, size_t len)
|
||||
{
|
||||
int ret;
|
||||
u32 num;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
if (opts->refcnt) {
|
||||
ret = -EBUSY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = kstrtou32(page, 0, &num);
|
||||
if (ret)
|
||||
goto end;
|
||||
|
||||
opts->qlen = num;
|
||||
ret = len;
|
||||
end:
|
||||
mutex_unlock(&opts->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct f_lb_opts_attribute f_lb_opts_qlen =
|
||||
__CONFIGFS_ATTR(qlen, S_IRUGO | S_IWUSR,
|
||||
f_lb_opts_qlen_show,
|
||||
f_lb_opts_qlen_store);
|
||||
|
||||
static ssize_t f_lb_opts_bulk_buflen_show(struct f_lb_opts *opts, char *page)
|
||||
{
|
||||
int result;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
result = sprintf(page, "%d", opts->bulk_buflen);
|
||||
mutex_unlock(&opts->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t f_lb_opts_bulk_buflen_store(struct f_lb_opts *opts,
|
||||
const char *page, size_t len)
|
||||
{
|
||||
int ret;
|
||||
u32 num;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
if (opts->refcnt) {
|
||||
ret = -EBUSY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = kstrtou32(page, 0, &num);
|
||||
if (ret)
|
||||
goto end;
|
||||
|
||||
opts->bulk_buflen = num;
|
||||
ret = len;
|
||||
end:
|
||||
mutex_unlock(&opts->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct f_lb_opts_attribute f_lb_opts_bulk_buflen =
|
||||
__CONFIGFS_ATTR(buflen, S_IRUGO | S_IWUSR,
|
||||
f_lb_opts_bulk_buflen_show,
|
||||
f_lb_opts_bulk_buflen_store);
|
||||
|
||||
static struct configfs_attribute *lb_attrs[] = {
|
||||
&f_lb_opts_qlen.attr,
|
||||
&f_lb_opts_bulk_buflen.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct config_item_type lb_func_type = {
|
||||
.ct_item_ops = &lb_item_ops,
|
||||
.ct_attrs = lb_attrs,
|
||||
.ct_owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static void lb_free_instance(struct usb_function_instance *fi)
|
||||
{
|
||||
struct f_lb_opts *lb_opts;
|
||||
@ -411,7 +542,14 @@ static struct usb_function_instance *loopback_alloc_instance(void)
|
||||
lb_opts = kzalloc(sizeof(*lb_opts), GFP_KERNEL);
|
||||
if (!lb_opts)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
mutex_init(&lb_opts->lock);
|
||||
lb_opts->func_inst.free_func_inst = lb_free_instance;
|
||||
lb_opts->bulk_buflen = GZERO_BULK_BUFLEN;
|
||||
lb_opts->qlen = GZERO_QLEN;
|
||||
|
||||
config_group_init_type_name(&lb_opts->func_inst.group, "",
|
||||
&lb_func_type);
|
||||
|
||||
return &lb_opts->func_inst;
|
||||
}
|
||||
DECLARE_USB_FUNCTION(Loopback, loopback_alloc_instance, loopback_alloc);
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include <linux/usb/audio.h>
|
||||
#include <linux/usb/midi.h>
|
||||
|
||||
#include "u_f.h"
|
||||
|
||||
MODULE_AUTHOR("Ben Williamson");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@ -191,20 +193,10 @@ static struct usb_gadget_strings *midi_strings[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
|
||||
static inline struct usb_request *midi_alloc_ep_req(struct usb_ep *ep,
|
||||
unsigned length)
|
||||
{
|
||||
struct usb_request *req;
|
||||
|
||||
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
|
||||
if (req) {
|
||||
req->length = length;
|
||||
req->buf = kmalloc(length, GFP_ATOMIC);
|
||||
if (!req->buf) {
|
||||
usb_ep_free_request(ep, req);
|
||||
req = NULL;
|
||||
}
|
||||
}
|
||||
return req;
|
||||
return alloc_ep_req(ep, length, length);
|
||||
}
|
||||
|
||||
static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
|
||||
@ -365,7 +357,7 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
|
||||
/* allocate a bunch of read buffers and queue them all at once. */
|
||||
for (i = 0; i < midi->qlen && err == 0; i++) {
|
||||
struct usb_request *req =
|
||||
alloc_ep_req(midi->out_ep, midi->buflen);
|
||||
midi_alloc_ep_req(midi->out_ep, midi->buflen);
|
||||
if (req == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -546,7 +538,7 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req)
|
||||
return;
|
||||
|
||||
if (!req)
|
||||
req = alloc_ep_req(ep, midi->buflen);
|
||||
req = midi_alloc_ep_req(ep, midi->buflen);
|
||||
|
||||
if (!req) {
|
||||
ERROR(midi, "gmidi_transmit: alloc_ep_request failed\n");
|
||||
|
@ -1386,7 +1386,7 @@ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f)
|
||||
usb_ep_free_request(ncm->notify, ncm->notify_req);
|
||||
}
|
||||
|
||||
struct usb_function *ncm_alloc(struct usb_function_instance *fi)
|
||||
static struct usb_function *ncm_alloc(struct usb_function_instance *fi)
|
||||
{
|
||||
struct f_ncm *ncm;
|
||||
struct f_ncm_opts *opts;
|
||||
|
@ -499,7 +499,7 @@ static void obex_unbind(struct usb_configuration *c, struct usb_function *f)
|
||||
usb_free_all_descriptors(f);
|
||||
}
|
||||
|
||||
struct usb_function *obex_alloc(struct usb_function_instance *fi)
|
||||
static struct usb_function *obex_alloc(struct usb_function_instance *fi)
|
||||
{
|
||||
struct f_obex *obex;
|
||||
struct f_serial_opts *opts;
|
||||
|
@ -689,7 +689,7 @@ static void pn_unbind(struct usb_configuration *c, struct usb_function *f)
|
||||
usb_free_all_descriptors(f);
|
||||
}
|
||||
|
||||
struct usb_function *phonet_alloc(struct usb_function_instance *fi)
|
||||
static struct usb_function *phonet_alloc(struct usb_function_instance *fi)
|
||||
{
|
||||
struct f_phonet *fp;
|
||||
struct f_phonet_opts *opts;
|
||||
|
@ -675,7 +675,6 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
int status;
|
||||
struct usb_ep *ep;
|
||||
|
||||
#ifndef USB_FRNDIS_INCLUDED
|
||||
struct f_rndis_opts *rndis_opts;
|
||||
|
||||
if (!can_support_rndis(c))
|
||||
@ -697,7 +696,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
return status;
|
||||
rndis_opts->bound = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
us = usb_gstrings_attach(cdev, rndis_strings,
|
||||
ARRAY_SIZE(rndis_string_defs));
|
||||
if (IS_ERR(us))
|
||||
@ -782,13 +781,6 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
rndis->port.open = rndis_open;
|
||||
rndis->port.close = rndis_close;
|
||||
|
||||
#ifdef USB_FRNDIS_INCLUDED
|
||||
status = rndis_register(rndis_response_available, rndis);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
rndis->config = status;
|
||||
#endif
|
||||
|
||||
rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0);
|
||||
rndis_set_host_mac(rndis->config, rndis->ethaddr);
|
||||
|
||||
@ -830,66 +822,6 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef USB_FRNDIS_INCLUDED
|
||||
|
||||
static void
|
||||
rndis_old_unbind(struct usb_configuration *c, struct usb_function *f)
|
||||
{
|
||||
struct f_rndis *rndis = func_to_rndis(f);
|
||||
|
||||
rndis_deregister(rndis->config);
|
||||
|
||||
usb_free_all_descriptors(f);
|
||||
|
||||
kfree(rndis->notify_req->buf);
|
||||
usb_ep_free_request(rndis->notify, rndis->notify_req);
|
||||
|
||||
kfree(rndis);
|
||||
}
|
||||
|
||||
int
|
||||
rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
|
||||
u32 vendorID, const char *manufacturer, struct eth_dev *dev)
|
||||
{
|
||||
struct f_rndis *rndis;
|
||||
int status;
|
||||
|
||||
/* allocate and initialize one new instance */
|
||||
status = -ENOMEM;
|
||||
rndis = kzalloc(sizeof *rndis, GFP_KERNEL);
|
||||
if (!rndis)
|
||||
goto fail;
|
||||
|
||||
memcpy(rndis->ethaddr, ethaddr, ETH_ALEN);
|
||||
rndis->vendorID = vendorID;
|
||||
rndis->manufacturer = manufacturer;
|
||||
|
||||
rndis->port.ioport = dev;
|
||||
/* RNDIS activates when the host changes this filter */
|
||||
rndis->port.cdc_filter = 0;
|
||||
|
||||
/* RNDIS has special (and complex) framing */
|
||||
rndis->port.header_len = sizeof(struct rndis_packet_msg_type);
|
||||
rndis->port.wrap = rndis_add_header;
|
||||
rndis->port.unwrap = rndis_rm_hdr;
|
||||
|
||||
rndis->port.func.name = "rndis";
|
||||
/* descriptors are per-instance copies */
|
||||
rndis->port.func.bind = rndis_bind;
|
||||
rndis->port.func.unbind = rndis_old_unbind;
|
||||
rndis->port.func.set_alt = rndis_set_alt;
|
||||
rndis->port.func.setup = rndis_setup;
|
||||
rndis->port.func.disable = rndis_disable;
|
||||
|
||||
status = usb_add_function(c, &rndis->port.func);
|
||||
if (status)
|
||||
kfree(rndis);
|
||||
fail:
|
||||
return status;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net)
|
||||
{
|
||||
struct f_rndis_opts *opts;
|
||||
@ -1047,8 +979,26 @@ static struct usb_function *rndis_alloc(struct usb_function_instance *fi)
|
||||
return &rndis->port.func;
|
||||
}
|
||||
|
||||
DECLARE_USB_FUNCTION_INIT(rndis, rndis_alloc_inst, rndis_alloc);
|
||||
DECLARE_USB_FUNCTION(rndis, rndis_alloc_inst, rndis_alloc);
|
||||
|
||||
static int __init rndis_mod_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rndis_init();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return usb_function_register(&rndisusb_func);
|
||||
}
|
||||
module_init(rndis_mod_init);
|
||||
|
||||
static void __exit rndis_mod_exit(void)
|
||||
{
|
||||
usb_function_unregister(&rndisusb_func);
|
||||
rndis_exit();
|
||||
}
|
||||
module_exit(rndis_mod_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("David Brownell");
|
||||
|
||||
#endif
|
||||
|
@ -354,7 +354,7 @@ static void gser_unbind(struct usb_configuration *c, struct usb_function *f)
|
||||
usb_free_all_descriptors(f);
|
||||
}
|
||||
|
||||
struct usb_function *gser_alloc(struct usb_function_instance *fi)
|
||||
static struct usb_function *gser_alloc(struct usb_function_instance *fi)
|
||||
{
|
||||
struct f_gser *gser;
|
||||
struct f_serial_opts *opts;
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "g_zero.h"
|
||||
#include "gadget_chips.h"
|
||||
#include "u_f.h"
|
||||
|
||||
/*
|
||||
* SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral
|
||||
@ -201,7 +202,7 @@ static struct usb_endpoint_descriptor ss_source_desc = {
|
||||
.wMaxPacketSize = cpu_to_le16(1024),
|
||||
};
|
||||
|
||||
struct usb_ss_ep_comp_descriptor ss_source_comp_desc = {
|
||||
static struct usb_ss_ep_comp_descriptor ss_source_comp_desc = {
|
||||
.bLength = USB_DT_SS_EP_COMP_SIZE,
|
||||
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
||||
|
||||
@ -218,7 +219,7 @@ static struct usb_endpoint_descriptor ss_sink_desc = {
|
||||
.wMaxPacketSize = cpu_to_le16(1024),
|
||||
};
|
||||
|
||||
struct usb_ss_ep_comp_descriptor ss_sink_comp_desc = {
|
||||
static struct usb_ss_ep_comp_descriptor ss_sink_comp_desc = {
|
||||
.bLength = USB_DT_SS_EP_COMP_SIZE,
|
||||
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
||||
|
||||
@ -236,7 +237,7 @@ static struct usb_endpoint_descriptor ss_iso_source_desc = {
|
||||
.bInterval = 4,
|
||||
};
|
||||
|
||||
struct usb_ss_ep_comp_descriptor ss_iso_source_comp_desc = {
|
||||
static struct usb_ss_ep_comp_descriptor ss_iso_source_comp_desc = {
|
||||
.bLength = USB_DT_SS_EP_COMP_SIZE,
|
||||
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
||||
|
||||
@ -254,7 +255,7 @@ static struct usb_endpoint_descriptor ss_iso_sink_desc = {
|
||||
.bInterval = 4,
|
||||
};
|
||||
|
||||
struct usb_ss_ep_comp_descriptor ss_iso_sink_comp_desc = {
|
||||
static struct usb_ss_ep_comp_descriptor ss_iso_sink_comp_desc = {
|
||||
.bLength = USB_DT_SS_EP_COMP_SIZE,
|
||||
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
||||
|
||||
@ -301,23 +302,9 @@ static struct usb_gadget_strings *sourcesink_strings[] = {
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
struct usb_request *alloc_ep_req(struct usb_ep *ep, int len)
|
||||
static inline struct usb_request *ss_alloc_ep_req(struct usb_ep *ep, int len)
|
||||
{
|
||||
struct usb_request *req;
|
||||
|
||||
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
|
||||
if (req) {
|
||||
if (len)
|
||||
req->length = len;
|
||||
else
|
||||
req->length = buflen;
|
||||
req->buf = kmalloc(req->length, GFP_ATOMIC);
|
||||
if (!req->buf) {
|
||||
usb_ep_free_request(ep, req);
|
||||
req = NULL;
|
||||
}
|
||||
}
|
||||
return req;
|
||||
return alloc_ep_req(ep, len, buflen);
|
||||
}
|
||||
|
||||
void free_ep_req(struct usb_ep *ep, struct usb_request *req)
|
||||
@ -490,6 +477,14 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
static void
|
||||
sourcesink_free_func(struct usb_function *f)
|
||||
{
|
||||
struct f_ss_opts *opts;
|
||||
|
||||
opts = container_of(f->fi, struct f_ss_opts, func_inst);
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
opts->refcnt--;
|
||||
mutex_unlock(&opts->lock);
|
||||
|
||||
usb_free_all_descriptors(f);
|
||||
kfree(func_to_ss(f));
|
||||
}
|
||||
@ -628,10 +623,10 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
|
||||
break;
|
||||
}
|
||||
ep = is_in ? ss->iso_in_ep : ss->iso_out_ep;
|
||||
req = alloc_ep_req(ep, size);
|
||||
req = ss_alloc_ep_req(ep, size);
|
||||
} else {
|
||||
ep = is_in ? ss->in_ep : ss->out_ep;
|
||||
req = alloc_ep_req(ep, 0);
|
||||
req = ss_alloc_ep_req(ep, 0);
|
||||
}
|
||||
|
||||
if (!req)
|
||||
@ -878,6 +873,11 @@ static struct usb_function *source_sink_alloc_func(
|
||||
return NULL;
|
||||
|
||||
ss_opts = container_of(fi, struct f_ss_opts, func_inst);
|
||||
|
||||
mutex_lock(&ss_opts->lock);
|
||||
ss_opts->refcnt++;
|
||||
mutex_unlock(&ss_opts->lock);
|
||||
|
||||
pattern = ss_opts->pattern;
|
||||
isoc_interval = ss_opts->isoc_interval;
|
||||
isoc_maxpacket = ss_opts->isoc_maxpacket;
|
||||
@ -898,6 +898,303 @@ static struct usb_function *source_sink_alloc_func(
|
||||
return &ss->function;
|
||||
}
|
||||
|
||||
static inline struct f_ss_opts *to_f_ss_opts(struct config_item *item)
|
||||
{
|
||||
return container_of(to_config_group(item), struct f_ss_opts,
|
||||
func_inst.group);
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR_STRUCT(f_ss_opts);
|
||||
CONFIGFS_ATTR_OPS(f_ss_opts);
|
||||
|
||||
static void ss_attr_release(struct config_item *item)
|
||||
{
|
||||
struct f_ss_opts *ss_opts = to_f_ss_opts(item);
|
||||
|
||||
usb_put_function_instance(&ss_opts->func_inst);
|
||||
}
|
||||
|
||||
static struct configfs_item_operations ss_item_ops = {
|
||||
.release = ss_attr_release,
|
||||
.show_attribute = f_ss_opts_attr_show,
|
||||
.store_attribute = f_ss_opts_attr_store,
|
||||
};
|
||||
|
||||
static ssize_t f_ss_opts_pattern_show(struct f_ss_opts *opts, char *page)
|
||||
{
|
||||
int result;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
result = sprintf(page, "%d", opts->pattern);
|
||||
mutex_unlock(&opts->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t f_ss_opts_pattern_store(struct f_ss_opts *opts,
|
||||
const char *page, size_t len)
|
||||
{
|
||||
int ret;
|
||||
u8 num;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
if (opts->refcnt) {
|
||||
ret = -EBUSY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = kstrtou8(page, 0, &num);
|
||||
if (ret)
|
||||
goto end;
|
||||
|
||||
if (num != 0 && num != 1 && num != 2) {
|
||||
ret = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
opts->pattern = num;
|
||||
ret = len;
|
||||
end:
|
||||
mutex_unlock(&opts->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct f_ss_opts_attribute f_ss_opts_pattern =
|
||||
__CONFIGFS_ATTR(pattern, S_IRUGO | S_IWUSR,
|
||||
f_ss_opts_pattern_show,
|
||||
f_ss_opts_pattern_store);
|
||||
|
||||
static ssize_t f_ss_opts_isoc_interval_show(struct f_ss_opts *opts, char *page)
|
||||
{
|
||||
int result;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
result = sprintf(page, "%d", opts->isoc_interval);
|
||||
mutex_unlock(&opts->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t f_ss_opts_isoc_interval_store(struct f_ss_opts *opts,
|
||||
const char *page, size_t len)
|
||||
{
|
||||
int ret;
|
||||
u8 num;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
if (opts->refcnt) {
|
||||
ret = -EBUSY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = kstrtou8(page, 0, &num);
|
||||
if (ret)
|
||||
goto end;
|
||||
|
||||
if (num > 16) {
|
||||
ret = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
opts->isoc_interval = num;
|
||||
ret = len;
|
||||
end:
|
||||
mutex_unlock(&opts->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct f_ss_opts_attribute f_ss_opts_isoc_interval =
|
||||
__CONFIGFS_ATTR(isoc_interval, S_IRUGO | S_IWUSR,
|
||||
f_ss_opts_isoc_interval_show,
|
||||
f_ss_opts_isoc_interval_store);
|
||||
|
||||
static ssize_t f_ss_opts_isoc_maxpacket_show(struct f_ss_opts *opts, char *page)
|
||||
{
|
||||
int result;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
result = sprintf(page, "%d", opts->isoc_maxpacket);
|
||||
mutex_unlock(&opts->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t f_ss_opts_isoc_maxpacket_store(struct f_ss_opts *opts,
|
||||
const char *page, size_t len)
|
||||
{
|
||||
int ret;
|
||||
u16 num;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
if (opts->refcnt) {
|
||||
ret = -EBUSY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = kstrtou16(page, 0, &num);
|
||||
if (ret)
|
||||
goto end;
|
||||
|
||||
if (num > 1024) {
|
||||
ret = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
opts->isoc_maxpacket = num;
|
||||
ret = len;
|
||||
end:
|
||||
mutex_unlock(&opts->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct f_ss_opts_attribute f_ss_opts_isoc_maxpacket =
|
||||
__CONFIGFS_ATTR(isoc_maxpacket, S_IRUGO | S_IWUSR,
|
||||
f_ss_opts_isoc_maxpacket_show,
|
||||
f_ss_opts_isoc_maxpacket_store);
|
||||
|
||||
static ssize_t f_ss_opts_isoc_mult_show(struct f_ss_opts *opts, char *page)
|
||||
{
|
||||
int result;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
result = sprintf(page, "%d", opts->isoc_mult);
|
||||
mutex_unlock(&opts->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t f_ss_opts_isoc_mult_store(struct f_ss_opts *opts,
|
||||
const char *page, size_t len)
|
||||
{
|
||||
int ret;
|
||||
u8 num;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
if (opts->refcnt) {
|
||||
ret = -EBUSY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = kstrtou8(page, 0, &num);
|
||||
if (ret)
|
||||
goto end;
|
||||
|
||||
if (num > 2) {
|
||||
ret = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
opts->isoc_mult = num;
|
||||
ret = len;
|
||||
end:
|
||||
mutex_unlock(&opts->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct f_ss_opts_attribute f_ss_opts_isoc_mult =
|
||||
__CONFIGFS_ATTR(isoc_mult, S_IRUGO | S_IWUSR,
|
||||
f_ss_opts_isoc_mult_show,
|
||||
f_ss_opts_isoc_mult_store);
|
||||
|
||||
static ssize_t f_ss_opts_isoc_maxburst_show(struct f_ss_opts *opts, char *page)
|
||||
{
|
||||
int result;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
result = sprintf(page, "%d", opts->isoc_maxburst);
|
||||
mutex_unlock(&opts->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t f_ss_opts_isoc_maxburst_store(struct f_ss_opts *opts,
|
||||
const char *page, size_t len)
|
||||
{
|
||||
int ret;
|
||||
u8 num;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
if (opts->refcnt) {
|
||||
ret = -EBUSY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = kstrtou8(page, 0, &num);
|
||||
if (ret)
|
||||
goto end;
|
||||
|
||||
if (num > 15) {
|
||||
ret = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
opts->isoc_maxburst = num;
|
||||
ret = len;
|
||||
end:
|
||||
mutex_unlock(&opts->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct f_ss_opts_attribute f_ss_opts_isoc_maxburst =
|
||||
__CONFIGFS_ATTR(isoc_maxburst, S_IRUGO | S_IWUSR,
|
||||
f_ss_opts_isoc_maxburst_show,
|
||||
f_ss_opts_isoc_maxburst_store);
|
||||
|
||||
static ssize_t f_ss_opts_bulk_buflen_show(struct f_ss_opts *opts, char *page)
|
||||
{
|
||||
int result;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
result = sprintf(page, "%d", opts->bulk_buflen);
|
||||
mutex_unlock(&opts->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t f_ss_opts_bulk_buflen_store(struct f_ss_opts *opts,
|
||||
const char *page, size_t len)
|
||||
{
|
||||
int ret;
|
||||
u32 num;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
if (opts->refcnt) {
|
||||
ret = -EBUSY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = kstrtou32(page, 0, &num);
|
||||
if (ret)
|
||||
goto end;
|
||||
|
||||
opts->bulk_buflen = num;
|
||||
ret = len;
|
||||
end:
|
||||
mutex_unlock(&opts->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct f_ss_opts_attribute f_ss_opts_bulk_buflen =
|
||||
__CONFIGFS_ATTR(buflen, S_IRUGO | S_IWUSR,
|
||||
f_ss_opts_bulk_buflen_show,
|
||||
f_ss_opts_bulk_buflen_store);
|
||||
|
||||
static struct configfs_attribute *ss_attrs[] = {
|
||||
&f_ss_opts_pattern.attr,
|
||||
&f_ss_opts_isoc_interval.attr,
|
||||
&f_ss_opts_isoc_maxpacket.attr,
|
||||
&f_ss_opts_isoc_mult.attr,
|
||||
&f_ss_opts_isoc_maxburst.attr,
|
||||
&f_ss_opts_bulk_buflen.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct config_item_type ss_func_type = {
|
||||
.ct_item_ops = &ss_item_ops,
|
||||
.ct_attrs = ss_attrs,
|
||||
.ct_owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static void source_sink_free_instance(struct usb_function_instance *fi)
|
||||
{
|
||||
struct f_ss_opts *ss_opts;
|
||||
@ -913,7 +1210,15 @@ static struct usb_function_instance *source_sink_alloc_inst(void)
|
||||
ss_opts = kzalloc(sizeof(*ss_opts), GFP_KERNEL);
|
||||
if (!ss_opts)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
mutex_init(&ss_opts->lock);
|
||||
ss_opts->func_inst.free_func_inst = source_sink_free_instance;
|
||||
ss_opts->isoc_interval = GZERO_ISOC_INTERVAL;
|
||||
ss_opts->isoc_maxpacket = GZERO_ISOC_MAXPACKET;
|
||||
ss_opts->bulk_buflen = GZERO_BULK_BUFLEN;
|
||||
|
||||
config_group_init_type_name(&ss_opts->func_inst.group, "",
|
||||
&ss_func_type);
|
||||
|
||||
return &ss_opts->func_inst;
|
||||
}
|
||||
DECLARE_USB_FUNCTION(SourceSink, source_sink_alloc_inst,
|
||||
|
@ -301,7 +301,6 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
int status;
|
||||
struct usb_ep *ep;
|
||||
|
||||
#ifndef USB_FSUBSET_INCLUDED
|
||||
struct f_gether_opts *gether_opts;
|
||||
|
||||
gether_opts = container_of(f->fi, struct f_gether_opts, func_inst);
|
||||
@ -322,7 +321,7 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
return status;
|
||||
gether_opts->bound = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
us = usb_gstrings_attach(cdev, geth_strings,
|
||||
ARRAY_SIZE(geth_string_defs));
|
||||
if (IS_ERR(us))
|
||||
@ -393,61 +392,6 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef USB_FSUBSET_INCLUDED
|
||||
|
||||
static void
|
||||
geth_old_unbind(struct usb_configuration *c, struct usb_function *f)
|
||||
{
|
||||
geth_string_defs[0].id = 0;
|
||||
usb_free_all_descriptors(f);
|
||||
kfree(func_to_geth(f));
|
||||
}
|
||||
|
||||
/**
|
||||
* geth_bind_config - add CDC Subset network link to a configuration
|
||||
* @c: the configuration to support the network link
|
||||
* @ethaddr: a buffer in which the ethernet address of the host side
|
||||
* side of the link was recorded
|
||||
* @dev: eth_dev structure
|
||||
* Context: single threaded during gadget setup
|
||||
*
|
||||
* Returns zero on success, else negative errno.
|
||||
*
|
||||
* Caller must have called @gether_setup(). Caller is also responsible
|
||||
* for calling @gether_cleanup() before module unload.
|
||||
*/
|
||||
int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
|
||||
struct eth_dev *dev)
|
||||
{
|
||||
struct f_gether *geth;
|
||||
int status;
|
||||
|
||||
/* allocate and initialize one new instance */
|
||||
geth = kzalloc(sizeof *geth, GFP_KERNEL);
|
||||
if (!geth)
|
||||
return -ENOMEM;
|
||||
|
||||
/* export host's Ethernet address in CDC format */
|
||||
snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr);
|
||||
geth_string_defs[1].s = geth->ethaddr;
|
||||
|
||||
geth->port.ioport = dev;
|
||||
geth->port.cdc_filter = DEFAULT_FILTER;
|
||||
|
||||
geth->port.func.name = "cdc_subset";
|
||||
geth->port.func.bind = geth_bind;
|
||||
geth->port.func.unbind = geth_old_unbind;
|
||||
geth->port.func.set_alt = geth_set_alt;
|
||||
geth->port.func.disable = geth_disable;
|
||||
|
||||
status = usb_add_function(c, &geth->port.func);
|
||||
if (status)
|
||||
kfree(geth);
|
||||
return status;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline struct f_gether_opts *to_f_gether_opts(struct config_item *item)
|
||||
{
|
||||
return container_of(to_config_group(item), struct f_gether_opts,
|
||||
@ -573,5 +517,3 @@ static struct usb_function *geth_alloc(struct usb_function_instance *fi)
|
||||
DECLARE_USB_FUNCTION_INIT(geth, geth_alloc_inst, geth_alloc);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("David Brownell");
|
||||
|
||||
#endif
|
||||
|
@ -1157,8 +1157,9 @@ static int fotg210_udc_probe(struct platform_device *pdev)
|
||||
INIT_LIST_HEAD(&ep->queue);
|
||||
ep->ep.name = fotg210_ep_name[i];
|
||||
ep->ep.ops = &fotg210_ep_ops;
|
||||
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
|
||||
}
|
||||
fotg210->ep[0]->ep.maxpacket = 0x40;
|
||||
usb_ep_set_maxpacket_limit(&fotg210->ep[0]->ep, 0x40);
|
||||
fotg210->gadget.ep0 = &fotg210->ep[0]->ep;
|
||||
INIT_LIST_HEAD(&fotg210->gadget.ep0->ep_list);
|
||||
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
@ -2429,7 +2428,7 @@ static int qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
|
||||
|
||||
ep->ep.ops = &qe_ep_ops;
|
||||
ep->stopped = 1;
|
||||
ep->ep.maxpacket = (unsigned short) ~0;
|
||||
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
|
||||
ep->ep.desc = NULL;
|
||||
ep->dir = 0xff;
|
||||
ep->epnum = (u8)pipe_num;
|
||||
@ -2717,7 +2716,7 @@ MODULE_DEVICE_TABLE(of, qe_udc_match);
|
||||
|
||||
static struct platform_driver udc_driver = {
|
||||
.driver = {
|
||||
.name = (char *)driver_name,
|
||||
.name = driver_name,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = qe_udc_match,
|
||||
},
|
||||
|
@ -2311,7 +2311,7 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,
|
||||
/* for ep0: maxP defined in desc
|
||||
* for other eps, maxP is set by epautoconfig() called by gadget layer
|
||||
*/
|
||||
ep->ep.maxpacket = (unsigned short) ~0;
|
||||
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
|
||||
|
||||
/* the queue lists any req for this ep */
|
||||
INIT_LIST_HEAD(&ep->queue);
|
||||
@ -2469,7 +2469,8 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
|
||||
* for other eps, gadget layer called ep_enable with defined desc
|
||||
*/
|
||||
udc_controller->eps[0].ep.desc = &fsl_ep0_desc;
|
||||
udc_controller->eps[0].ep.maxpacket = USB_MAX_CTRL_PAYLOAD;
|
||||
usb_ep_set_maxpacket_limit(&udc_controller->eps[0].ep,
|
||||
USB_MAX_CTRL_PAYLOAD);
|
||||
|
||||
/* setup the udc->eps[] for non-control endpoints and link
|
||||
* to gadget.ep_list */
|
||||
@ -2666,7 +2667,7 @@ static struct platform_driver udc_driver = {
|
||||
.suspend = fsl_udc_suspend,
|
||||
.resume = fsl_udc_resume,
|
||||
.driver = {
|
||||
.name = (char *)driver_name,
|
||||
.name = driver_name,
|
||||
.owner = THIS_MODULE,
|
||||
/* udc suspend/resume called from OTG driver */
|
||||
.suspend = fsl_udc_otg_suspend,
|
||||
|
@ -1452,9 +1452,9 @@ static int __init fusb300_probe(struct platform_device *pdev)
|
||||
INIT_LIST_HEAD(&ep->queue);
|
||||
ep->ep.name = fusb300_ep_name[i];
|
||||
ep->ep.ops = &fusb300_ep_ops;
|
||||
ep->ep.maxpacket = HS_BULK_MAX_PACKET_SIZE;
|
||||
usb_ep_set_maxpacket_limit(&ep->ep, HS_BULK_MAX_PACKET_SIZE);
|
||||
}
|
||||
fusb300->ep[0]->ep.maxpacket = HS_CTL_MAX_PACKET_SIZE;
|
||||
usb_ep_set_maxpacket_limit(&fusb300->ep[0]->ep, HS_CTL_MAX_PACKET_SIZE);
|
||||
fusb300->ep[0]->epnum = 0;
|
||||
fusb300->gadget.ep0 = &fusb300->ep[0]->ep;
|
||||
INIT_LIST_HEAD(&fusb300->gadget.ep0->ep_list);
|
||||
|
@ -13,14 +13,10 @@
|
||||
#define pr_fmt(fmt) "g_ffs: " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
/*
|
||||
* kbuild is not very cooperative with respect to linking separately
|
||||
* compiled library objects into one module. So for now we won't use
|
||||
* separate compilation ... ensuring init/exit sections work to shrink
|
||||
* the runtime footprint, and giving us at least some parts of what
|
||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
|
||||
#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
# if defined USB_ETH_RNDIS
|
||||
# undef USB_ETH_RNDIS
|
||||
# endif
|
||||
@ -28,31 +24,31 @@
|
||||
# define USB_ETH_RNDIS y
|
||||
# endif
|
||||
|
||||
#define USBF_ECM_INCLUDED
|
||||
# include "f_ecm.c"
|
||||
#define USB_FSUBSET_INCLUDED
|
||||
# include "f_subset.c"
|
||||
# include "u_ecm.h"
|
||||
# include "u_gether.h"
|
||||
# ifdef USB_ETH_RNDIS
|
||||
# define USB_FRNDIS_INCLUDED
|
||||
# include "f_rndis.c"
|
||||
# include "u_rndis.h"
|
||||
# include "rndis.h"
|
||||
# endif
|
||||
# include "u_ether.h"
|
||||
|
||||
static u8 gfs_host_mac[ETH_ALEN];
|
||||
static struct eth_dev *the_dev;
|
||||
USB_ETHERNET_MODULE_PARAMETERS();
|
||||
|
||||
# ifdef CONFIG_USB_FUNCTIONFS_ETH
|
||||
static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
|
||||
struct eth_dev *dev);
|
||||
static int eth_bind_config(struct usb_configuration *c);
|
||||
static struct usb_function_instance *fi_ecm;
|
||||
static struct usb_function *f_ecm;
|
||||
static struct usb_function_instance *fi_geth;
|
||||
static struct usb_function *f_geth;
|
||||
# endif
|
||||
# ifdef CONFIG_USB_FUNCTIONFS_RNDIS
|
||||
static int bind_rndis_config(struct usb_configuration *c);
|
||||
static struct usb_function_instance *fi_rndis;
|
||||
static struct usb_function *f_rndis;
|
||||
# endif
|
||||
#else
|
||||
# define the_dev NULL
|
||||
# define gether_cleanup(dev) do { } while (0)
|
||||
# define gfs_host_mac NULL
|
||||
struct eth_dev;
|
||||
#endif
|
||||
|
||||
#include "f_fs.c"
|
||||
#include "u_fs.h"
|
||||
|
||||
#define DRIVER_NAME "g_ffs"
|
||||
#define DRIVER_DESC "USB Function Filesystem"
|
||||
@ -67,19 +63,8 @@ MODULE_LICENSE("GPL");
|
||||
|
||||
#define GFS_MAX_DEVS 10
|
||||
|
||||
struct gfs_ffs_obj {
|
||||
const char *name;
|
||||
bool mounted;
|
||||
bool desc_ready;
|
||||
struct ffs_data *ffs_data;
|
||||
};
|
||||
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
|
||||
#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
|
||||
USB_ETHERNET_MODULE_PARAMETERS();
|
||||
#endif
|
||||
|
||||
static struct usb_device_descriptor gfs_dev_desc = {
|
||||
.bLength = sizeof gfs_dev_desc,
|
||||
.bDescriptorType = USB_DT_DEVICE,
|
||||
@ -146,12 +131,12 @@ static struct usb_gadget_strings *gfs_dev_strings[] = {
|
||||
|
||||
struct gfs_configuration {
|
||||
struct usb_configuration c;
|
||||
int (*eth)(struct usb_configuration *c, u8 *ethaddr,
|
||||
struct eth_dev *dev);
|
||||
int (*eth)(struct usb_configuration *c);
|
||||
int num;
|
||||
} gfs_configurations[] = {
|
||||
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
|
||||
{
|
||||
.eth = rndis_bind_config,
|
||||
.eth = bind_rndis_config,
|
||||
},
|
||||
#endif
|
||||
|
||||
@ -167,10 +152,15 @@ struct gfs_configuration {
|
||||
#endif
|
||||
};
|
||||
|
||||
static void *functionfs_acquire_dev(struct ffs_dev *dev);
|
||||
static void functionfs_release_dev(struct ffs_dev *dev);
|
||||
static int functionfs_ready_callback(struct ffs_data *ffs);
|
||||
static void functionfs_closed_callback(struct ffs_data *ffs);
|
||||
static int gfs_bind(struct usb_composite_dev *cdev);
|
||||
static int gfs_unbind(struct usb_composite_dev *cdev);
|
||||
static int gfs_do_config(struct usb_configuration *c);
|
||||
|
||||
|
||||
static __refdata struct usb_composite_driver gfs_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.dev = &gfs_dev_desc,
|
||||
@ -180,205 +170,243 @@ static __refdata struct usb_composite_driver gfs_driver = {
|
||||
.unbind = gfs_unbind,
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(gfs_lock);
|
||||
static unsigned int missing_funcs;
|
||||
static bool gfs_ether_setup;
|
||||
static bool gfs_registered;
|
||||
static bool gfs_single_func;
|
||||
static struct gfs_ffs_obj *ffs_tab;
|
||||
static struct usb_function_instance **fi_ffs;
|
||||
static struct usb_function **f_ffs[] = {
|
||||
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
|
||||
NULL,
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_FUNCTIONFS_ETH
|
||||
NULL,
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
|
||||
NULL,
|
||||
#endif
|
||||
};
|
||||
|
||||
#define N_CONF ARRAY_SIZE(f_ffs)
|
||||
|
||||
static int __init gfs_init(void)
|
||||
{
|
||||
struct f_fs_opts *opts;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
ENTER();
|
||||
|
||||
if (!func_num) {
|
||||
if (func_num < 2) {
|
||||
gfs_single_func = true;
|
||||
func_num = 1;
|
||||
}
|
||||
|
||||
ffs_tab = kcalloc(func_num, sizeof *ffs_tab, GFP_KERNEL);
|
||||
if (!ffs_tab)
|
||||
return -ENOMEM;
|
||||
/*
|
||||
* Allocate in one chunk for easier maintenance
|
||||
*/
|
||||
f_ffs[0] = kcalloc(func_num * N_CONF, sizeof(*f_ffs), GFP_KERNEL);
|
||||
if (!f_ffs[0]) {
|
||||
ret = -ENOMEM;
|
||||
goto no_func;
|
||||
}
|
||||
for (i = 1; i < N_CONF; ++i)
|
||||
f_ffs[i] = f_ffs[0] + i * func_num;
|
||||
|
||||
if (!gfs_single_func)
|
||||
for (i = 0; i < func_num; i++)
|
||||
ffs_tab[i].name = func_names[i];
|
||||
fi_ffs = kcalloc(func_num, sizeof(*fi_ffs), GFP_KERNEL);
|
||||
if (!fi_ffs) {
|
||||
ret = -ENOMEM;
|
||||
goto no_func;
|
||||
}
|
||||
|
||||
for (i = 0; i < func_num; i++) {
|
||||
fi_ffs[i] = usb_get_function_instance("ffs");
|
||||
if (IS_ERR(fi_ffs[i])) {
|
||||
ret = PTR_ERR(fi_ffs[i]);
|
||||
--i;
|
||||
goto no_dev;
|
||||
}
|
||||
opts = to_f_fs_opts(fi_ffs[i]);
|
||||
if (gfs_single_func)
|
||||
ret = ffs_single_dev(opts->dev);
|
||||
else
|
||||
ret = ffs_name_dev(opts->dev, func_names[i]);
|
||||
if (ret)
|
||||
goto no_dev;
|
||||
opts->dev->ffs_ready_callback = functionfs_ready_callback;
|
||||
opts->dev->ffs_closed_callback = functionfs_closed_callback;
|
||||
opts->dev->ffs_acquire_dev_callback = functionfs_acquire_dev;
|
||||
opts->dev->ffs_release_dev_callback = functionfs_release_dev;
|
||||
opts->no_configfs = true;
|
||||
}
|
||||
|
||||
missing_funcs = func_num;
|
||||
|
||||
return functionfs_init();
|
||||
return 0;
|
||||
no_dev:
|
||||
while (i >= 0)
|
||||
usb_put_function_instance(fi_ffs[i--]);
|
||||
kfree(fi_ffs);
|
||||
no_func:
|
||||
kfree(f_ffs[0]);
|
||||
return ret;
|
||||
}
|
||||
module_init(gfs_init);
|
||||
|
||||
static void __exit gfs_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
ENTER();
|
||||
mutex_lock(&gfs_lock);
|
||||
|
||||
if (gfs_registered)
|
||||
usb_composite_unregister(&gfs_driver);
|
||||
gfs_registered = false;
|
||||
|
||||
functionfs_cleanup();
|
||||
kfree(f_ffs[0]);
|
||||
|
||||
mutex_unlock(&gfs_lock);
|
||||
kfree(ffs_tab);
|
||||
for (i = 0; i < func_num; i++)
|
||||
usb_put_function_instance(fi_ffs[i]);
|
||||
|
||||
kfree(fi_ffs);
|
||||
}
|
||||
module_exit(gfs_exit);
|
||||
|
||||
static struct gfs_ffs_obj *gfs_find_dev(const char *dev_name)
|
||||
static void *functionfs_acquire_dev(struct ffs_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
ENTER();
|
||||
|
||||
if (gfs_single_func)
|
||||
return &ffs_tab[0];
|
||||
|
||||
for (i = 0; i < func_num; i++)
|
||||
if (strcmp(ffs_tab[i].name, dev_name) == 0)
|
||||
return &ffs_tab[i];
|
||||
|
||||
return NULL;
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void functionfs_release_dev(struct ffs_dev *dev)
|
||||
{
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
/*
|
||||
* The caller of this function takes ffs_lock
|
||||
*/
|
||||
static int functionfs_ready_callback(struct ffs_data *ffs)
|
||||
{
|
||||
struct gfs_ffs_obj *ffs_obj;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
ENTER();
|
||||
mutex_lock(&gfs_lock);
|
||||
if (--missing_funcs)
|
||||
return 0;
|
||||
|
||||
ffs_obj = ffs->private_data;
|
||||
if (!ffs_obj) {
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
if (gfs_registered)
|
||||
return -EBUSY;
|
||||
|
||||
if (WARN_ON(ffs_obj->desc_ready)) {
|
||||
ret = -EBUSY;
|
||||
goto done;
|
||||
}
|
||||
ffs_obj->desc_ready = true;
|
||||
ffs_obj->ffs_data = ffs;
|
||||
|
||||
if (--missing_funcs) {
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (gfs_registered) {
|
||||
ret = -EBUSY;
|
||||
goto done;
|
||||
}
|
||||
gfs_registered = true;
|
||||
|
||||
ret = usb_composite_probe(&gfs_driver);
|
||||
if (unlikely(ret < 0))
|
||||
gfs_registered = false;
|
||||
|
||||
done:
|
||||
mutex_unlock(&gfs_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* The caller of this function takes ffs_lock
|
||||
*/
|
||||
static void functionfs_closed_callback(struct ffs_data *ffs)
|
||||
{
|
||||
struct gfs_ffs_obj *ffs_obj;
|
||||
|
||||
ENTER();
|
||||
mutex_lock(&gfs_lock);
|
||||
|
||||
ffs_obj = ffs->private_data;
|
||||
if (!ffs_obj)
|
||||
goto done;
|
||||
|
||||
ffs_obj->desc_ready = false;
|
||||
missing_funcs++;
|
||||
|
||||
if (gfs_registered)
|
||||
usb_composite_unregister(&gfs_driver);
|
||||
gfs_registered = false;
|
||||
|
||||
done:
|
||||
mutex_unlock(&gfs_lock);
|
||||
}
|
||||
|
||||
static void *functionfs_acquire_dev_callback(const char *dev_name)
|
||||
{
|
||||
struct gfs_ffs_obj *ffs_dev;
|
||||
|
||||
ENTER();
|
||||
mutex_lock(&gfs_lock);
|
||||
|
||||
ffs_dev = gfs_find_dev(dev_name);
|
||||
if (!ffs_dev) {
|
||||
ffs_dev = ERR_PTR(-ENODEV);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ffs_dev->mounted) {
|
||||
ffs_dev = ERR_PTR(-EBUSY);
|
||||
goto done;
|
||||
}
|
||||
ffs_dev->mounted = true;
|
||||
|
||||
done:
|
||||
mutex_unlock(&gfs_lock);
|
||||
return ffs_dev;
|
||||
}
|
||||
|
||||
static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
|
||||
{
|
||||
struct gfs_ffs_obj *ffs_dev;
|
||||
|
||||
ENTER();
|
||||
mutex_lock(&gfs_lock);
|
||||
|
||||
ffs_dev = ffs_data->private_data;
|
||||
if (ffs_dev)
|
||||
ffs_dev->mounted = false;
|
||||
|
||||
mutex_unlock(&gfs_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* It is assumed that gfs_bind is called from a context where gfs_lock is held
|
||||
* It is assumed that gfs_bind is called from a context where ffs_lock is held
|
||||
*/
|
||||
static int gfs_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
|
||||
struct net_device *net;
|
||||
#endif
|
||||
int ret, i;
|
||||
|
||||
ENTER();
|
||||
|
||||
if (missing_funcs)
|
||||
return -ENODEV;
|
||||
#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
|
||||
the_dev = gether_setup(cdev->gadget, dev_addr, host_addr, gfs_host_mac,
|
||||
qmult);
|
||||
#endif
|
||||
if (IS_ERR(the_dev)) {
|
||||
ret = PTR_ERR(the_dev);
|
||||
goto error_quick;
|
||||
#if defined CONFIG_USB_FUNCTIONFS_ETH
|
||||
if (can_support_ecm(cdev->gadget)) {
|
||||
struct f_ecm_opts *ecm_opts;
|
||||
|
||||
fi_ecm = usb_get_function_instance("ecm");
|
||||
if (IS_ERR(fi_ecm))
|
||||
return PTR_ERR(fi_ecm);
|
||||
ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst);
|
||||
net = ecm_opts->net;
|
||||
} else {
|
||||
struct f_gether_opts *geth_opts;
|
||||
|
||||
fi_geth = usb_get_function_instance("geth");
|
||||
if (IS_ERR(fi_geth))
|
||||
return PTR_ERR(fi_geth);
|
||||
geth_opts = container_of(fi_geth, struct f_gether_opts,
|
||||
func_inst);
|
||||
net = geth_opts->net;
|
||||
}
|
||||
gfs_ether_setup = true;
|
||||
#endif
|
||||
|
||||
ret = usb_string_ids_tab(cdev, gfs_strings);
|
||||
if (unlikely(ret < 0))
|
||||
goto error;
|
||||
gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
|
||||
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
|
||||
{
|
||||
struct f_rndis_opts *rndis_opts;
|
||||
|
||||
for (i = func_num; i--; ) {
|
||||
ret = functionfs_bind(ffs_tab[i].ffs_data, cdev);
|
||||
if (unlikely(ret < 0)) {
|
||||
while (++i < func_num)
|
||||
functionfs_unbind(ffs_tab[i].ffs_data);
|
||||
fi_rndis = usb_get_function_instance("rndis");
|
||||
if (IS_ERR(fi_rndis)) {
|
||||
ret = PTR_ERR(fi_rndis);
|
||||
goto error;
|
||||
}
|
||||
rndis_opts = container_of(fi_rndis, struct f_rndis_opts,
|
||||
func_inst);
|
||||
#ifndef CONFIG_USB_FUNCTIONFS_ETH
|
||||
net = rndis_opts->net;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
|
||||
gether_set_qmult(net, qmult);
|
||||
if (!gether_set_host_addr(net, host_addr))
|
||||
pr_info("using host ethernet address: %s", host_addr);
|
||||
if (!gether_set_dev_addr(net, dev_addr))
|
||||
pr_info("using self ethernet address: %s", dev_addr);
|
||||
#endif
|
||||
|
||||
#if defined CONFIG_USB_FUNCTIONFS_RNDIS && defined CONFIG_USB_FUNCTIONFS_ETH
|
||||
gether_set_gadget(net, cdev->gadget);
|
||||
ret = gether_register_netdev(net);
|
||||
if (ret)
|
||||
goto error_rndis;
|
||||
|
||||
if (can_support_ecm(cdev->gadget)) {
|
||||
struct f_ecm_opts *ecm_opts;
|
||||
|
||||
ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst);
|
||||
ecm_opts->bound = true;
|
||||
} else {
|
||||
struct f_gether_opts *geth_opts;
|
||||
|
||||
geth_opts = container_of(fi_geth, struct f_gether_opts,
|
||||
func_inst);
|
||||
geth_opts->bound = true;
|
||||
}
|
||||
|
||||
rndis_borrow_net(fi_rndis, net);
|
||||
#endif
|
||||
|
||||
/* TODO: gstrings_attach? */
|
||||
ret = usb_string_ids_tab(cdev, gfs_strings);
|
||||
if (unlikely(ret < 0))
|
||||
goto error_rndis;
|
||||
gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
|
||||
struct gfs_configuration *c = gfs_configurations + i;
|
||||
@ -389,6 +417,8 @@ static int gfs_bind(struct usb_composite_dev *cdev)
|
||||
c->c.bConfigurationValue = 1 + i;
|
||||
c->c.bmAttributes = USB_CONFIG_ATT_SELFPOWER;
|
||||
|
||||
c->num = i;
|
||||
|
||||
ret = usb_add_config(cdev, &c->c, gfs_do_config);
|
||||
if (unlikely(ret < 0))
|
||||
goto error_unbind;
|
||||
@ -396,18 +426,24 @@ static int gfs_bind(struct usb_composite_dev *cdev)
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
return 0;
|
||||
|
||||
/* TODO */
|
||||
error_unbind:
|
||||
for (i = 0; i < func_num; i++)
|
||||
functionfs_unbind(ffs_tab[i].ffs_data);
|
||||
error_rndis:
|
||||
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
|
||||
usb_put_function_instance(fi_rndis);
|
||||
error:
|
||||
gether_cleanup(the_dev);
|
||||
error_quick:
|
||||
gfs_ether_setup = false;
|
||||
#endif
|
||||
#if defined CONFIG_USB_FUNCTIONFS_ETH
|
||||
if (can_support_ecm(cdev->gadget))
|
||||
usb_put_function_instance(fi_ecm);
|
||||
else
|
||||
usb_put_function_instance(fi_geth);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* It is assumed that gfs_unbind is called from a context where gfs_lock is held
|
||||
* It is assumed that gfs_unbind is called from a context where ffs_lock is held
|
||||
*/
|
||||
static int gfs_unbind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
@ -415,28 +451,30 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
|
||||
|
||||
ENTER();
|
||||
|
||||
/*
|
||||
* We may have been called in an error recovery from
|
||||
* composite_bind() after gfs_unbind() failure so we need to
|
||||
* check if gfs_ffs_data is not NULL since gfs_bind() handles
|
||||
* all error recovery itself. I'd rather we werent called
|
||||
* from composite on orror recovery, but what you're gonna
|
||||
* do...?
|
||||
*/
|
||||
if (gfs_ether_setup)
|
||||
gether_cleanup(the_dev);
|
||||
gfs_ether_setup = false;
|
||||
|
||||
for (i = func_num; i--; )
|
||||
if (ffs_tab[i].ffs_data)
|
||||
functionfs_unbind(ffs_tab[i].ffs_data);
|
||||
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
|
||||
usb_put_function(f_rndis);
|
||||
usb_put_function_instance(fi_rndis);
|
||||
#endif
|
||||
|
||||
#if defined CONFIG_USB_FUNCTIONFS_ETH
|
||||
if (can_support_ecm(cdev->gadget)) {
|
||||
usb_put_function(f_ecm);
|
||||
usb_put_function_instance(fi_ecm);
|
||||
} else {
|
||||
usb_put_function(f_geth);
|
||||
usb_put_function_instance(fi_geth);
|
||||
}
|
||||
#endif
|
||||
for (i = 0; i < N_CONF * func_num; ++i)
|
||||
usb_put_function(*(f_ffs[0] + i));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* It is assumed that gfs_do_config is called from a context where
|
||||
* gfs_lock is held
|
||||
* ffs_lock is held
|
||||
*/
|
||||
static int gfs_do_config(struct usb_configuration *c)
|
||||
{
|
||||
@ -454,15 +492,22 @@ static int gfs_do_config(struct usb_configuration *c)
|
||||
}
|
||||
|
||||
if (gc->eth) {
|
||||
ret = gc->eth(c, gfs_host_mac, the_dev);
|
||||
ret = gc->eth(c);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < func_num; i++) {
|
||||
ret = functionfs_bind_config(c->cdev, c, ffs_tab[i].ffs_data);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
f_ffs[gc->num][i] = usb_get_function(fi_ffs[i]);
|
||||
if (IS_ERR(f_ffs[gc->num][i])) {
|
||||
ret = PTR_ERR(f_ffs[gc->num][i]);
|
||||
goto error;
|
||||
}
|
||||
ret = usb_add_function(c, f_ffs[gc->num][i]);
|
||||
if (ret < 0) {
|
||||
usb_put_function(f_ffs[gc->num][i]);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -479,16 +524,59 @@ static int gfs_do_config(struct usb_configuration *c)
|
||||
c->interface[c->next_interface_id] = NULL;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
while (--i >= 0) {
|
||||
if (!IS_ERR(f_ffs[gc->num][i]))
|
||||
usb_remove_function(c, f_ffs[gc->num][i]);
|
||||
usb_put_function(f_ffs[gc->num][i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_FUNCTIONFS_ETH
|
||||
|
||||
static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
|
||||
struct eth_dev *dev)
|
||||
static int eth_bind_config(struct usb_configuration *c)
|
||||
{
|
||||
return can_support_ecm(c->cdev->gadget)
|
||||
? ecm_bind_config(c, ethaddr, dev)
|
||||
: geth_bind_config(c, ethaddr, dev);
|
||||
int status = 0;
|
||||
|
||||
if (can_support_ecm(c->cdev->gadget)) {
|
||||
f_ecm = usb_get_function(fi_ecm);
|
||||
if (IS_ERR(f_ecm))
|
||||
return PTR_ERR(f_ecm);
|
||||
|
||||
status = usb_add_function(c, f_ecm);
|
||||
if (status < 0)
|
||||
usb_put_function(f_ecm);
|
||||
|
||||
} else {
|
||||
f_geth = usb_get_function(fi_geth);
|
||||
if (IS_ERR(f_geth))
|
||||
return PTR_ERR(f_geth);
|
||||
|
||||
status = usb_add_function(c, f_geth);
|
||||
if (status < 0)
|
||||
usb_put_function(f_geth);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
|
||||
|
||||
static int bind_rndis_config(struct usb_configuration *c)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
f_rndis = usb_get_function(fi_rndis);
|
||||
if (IS_ERR(f_rndis))
|
||||
return PTR_ERR(f_rndis);
|
||||
|
||||
status = usb_add_function(c, f_rndis);
|
||||
if (status < 0)
|
||||
usb_put_function(f_rndis);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -6,6 +6,11 @@
|
||||
#ifndef __G_ZERO_H
|
||||
#define __G_ZERO_H
|
||||
|
||||
#define GZERO_BULK_BUFLEN 4096
|
||||
#define GZERO_QLEN 32
|
||||
#define GZERO_ISOC_INTERVAL 4
|
||||
#define GZERO_ISOC_MAXPACKET 1024
|
||||
|
||||
struct usb_zero_options {
|
||||
unsigned pattern;
|
||||
unsigned isoc_interval;
|
||||
@ -24,19 +29,36 @@ struct f_ss_opts {
|
||||
unsigned isoc_mult;
|
||||
unsigned isoc_maxburst;
|
||||
unsigned bulk_buflen;
|
||||
|
||||
/*
|
||||
* Read/write access to configfs attributes is handled by configfs.
|
||||
*
|
||||
* This is to protect the data from concurrent access by read/write
|
||||
* and create symlink/remove symlink.
|
||||
*/
|
||||
struct mutex lock;
|
||||
int refcnt;
|
||||
};
|
||||
|
||||
struct f_lb_opts {
|
||||
struct usb_function_instance func_inst;
|
||||
unsigned bulk_buflen;
|
||||
unsigned qlen;
|
||||
|
||||
/*
|
||||
* Read/write access to configfs attributes is handled by configfs.
|
||||
*
|
||||
* This is to protect the data from concurrent access by read/write
|
||||
* and create symlink/remove symlink.
|
||||
*/
|
||||
struct mutex lock;
|
||||
int refcnt;
|
||||
};
|
||||
|
||||
void lb_modexit(void);
|
||||
int lb_modinit(void);
|
||||
|
||||
/* common utilities */
|
||||
struct usb_request *alloc_ep_req(struct usb_ep *ep, int len);
|
||||
void free_ep_req(struct usb_ep *ep, struct usb_request *req);
|
||||
void disable_endpoints(struct usb_composite_dev *cdev,
|
||||
struct usb_ep *in, struct usb_ep *out,
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/interrupt.h>
|
||||
@ -231,7 +230,7 @@ static void ep_reset(struct goku_udc_regs __iomem *regs, struct goku_ep *ep)
|
||||
}
|
||||
}
|
||||
|
||||
ep->ep.maxpacket = MAX_FIFO_SIZE;
|
||||
usb_ep_set_maxpacket_limit(&ep->ep, MAX_FIFO_SIZE);
|
||||
ep->ep.desc = NULL;
|
||||
ep->stopped = 1;
|
||||
ep->irqs = 0;
|
||||
@ -1251,7 +1250,7 @@ static void udc_reinit (struct goku_udc *dev)
|
||||
}
|
||||
|
||||
dev->ep[0].reg_mode = NULL;
|
||||
dev->ep[0].ep.maxpacket = MAX_EP0_SIZE;
|
||||
usb_ep_set_maxpacket_limit(&dev->ep[0].ep, MAX_EP0_SIZE);
|
||||
list_del_init (&dev->ep[0].ep.ep_list);
|
||||
}
|
||||
|
||||
@ -1350,16 +1349,12 @@ static int goku_udc_start(struct usb_gadget *g,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
|
||||
static void stop_activity(struct goku_udc *dev)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
DBG (dev, "%s\n", __func__);
|
||||
|
||||
if (dev->gadget.speed == USB_SPEED_UNKNOWN)
|
||||
driver = NULL;
|
||||
|
||||
/* disconnect gadget driver after quiesceing hw and the driver */
|
||||
udc_reset (dev);
|
||||
for (i = 0; i < 4; i++)
|
||||
@ -1377,7 +1372,7 @@ static int goku_udc_stop(struct usb_gadget *g,
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
dev->driver = NULL;
|
||||
stop_activity(dev, driver);
|
||||
stop_activity(dev);
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
return 0;
|
||||
@ -1521,7 +1516,7 @@ static irqreturn_t goku_irq(int irq, void *_dev)
|
||||
if (unlikely(stat & INT_DEVWIDE)) {
|
||||
if (stat & INT_SYSERROR) {
|
||||
ERROR(dev, "system error\n");
|
||||
stop_activity(dev, dev->driver);
|
||||
stop_activity(dev);
|
||||
stat = 0;
|
||||
handled = 1;
|
||||
// FIXME have a neater way to prevent re-enumeration
|
||||
@ -1536,7 +1531,7 @@ static irqreturn_t goku_irq(int irq, void *_dev)
|
||||
} else {
|
||||
DBG(dev, "disconnect\n");
|
||||
if (dev->gadget.speed == USB_SPEED_FULL)
|
||||
stop_activity(dev, dev->driver);
|
||||
stop_activity(dev);
|
||||
dev->ep0state = EP0_DISCONNECT;
|
||||
dev->int_enable = INT_DEVWIDE;
|
||||
writel(dev->int_enable, &dev->regs->int_enable);
|
||||
|
2238
drivers/usb/gadget/gr_udc.c
Normal file
2238
drivers/usb/gadget/gr_udc.c
Normal file
File diff suppressed because it is too large
Load Diff
220
drivers/usb/gadget/gr_udc.h
Normal file
220
drivers/usb/gadget/gr_udc.h
Normal file
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* USB Peripheral Controller driver for Aeroflex Gaisler GRUSBDC.
|
||||
*
|
||||
* 2013 (c) Aeroflex Gaisler AB
|
||||
*
|
||||
* This driver supports GRUSBDC USB Device Controller cores available in the
|
||||
* GRLIB VHDL IP core library.
|
||||
*
|
||||
* Full documentation of the GRUSBDC core can be found here:
|
||||
* http://www.gaisler.com/products/grlib/grip.pdf
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contributors:
|
||||
* - Andreas Larsson <andreas@gaisler.com>
|
||||
* - Marko Isomaki
|
||||
*/
|
||||
|
||||
/* Control registers on the AMBA bus */
|
||||
|
||||
#define GR_MAXEP 16 /* Max # endpoints for *each* direction */
|
||||
|
||||
struct gr_epregs {
|
||||
u32 epctrl;
|
||||
union {
|
||||
struct { /* Slave mode*/
|
||||
u32 slvctrl;
|
||||
u32 slvdata;
|
||||
};
|
||||
struct { /* DMA mode*/
|
||||
u32 dmactrl;
|
||||
u32 dmaaddr;
|
||||
};
|
||||
};
|
||||
u32 epstat;
|
||||
};
|
||||
|
||||
struct gr_regs {
|
||||
struct gr_epregs epo[GR_MAXEP]; /* 0x000 - 0x0fc */
|
||||
struct gr_epregs epi[GR_MAXEP]; /* 0x100 - 0x1fc */
|
||||
u32 control; /* 0x200 */
|
||||
u32 status; /* 0x204 */
|
||||
};
|
||||
|
||||
#define GR_EPCTRL_BUFSZ_SCALER 8
|
||||
#define GR_EPCTRL_BUFSZ_MASK 0xffe00000
|
||||
#define GR_EPCTRL_BUFSZ_POS 21
|
||||
#define GR_EPCTRL_PI BIT(20)
|
||||
#define GR_EPCTRL_CB BIT(19)
|
||||
#define GR_EPCTRL_CS BIT(18)
|
||||
#define GR_EPCTRL_MAXPL_MASK 0x0003ff80
|
||||
#define GR_EPCTRL_MAXPL_POS 7
|
||||
#define GR_EPCTRL_NT_MASK 0x00000060
|
||||
#define GR_EPCTRL_NT_POS 5
|
||||
#define GR_EPCTRL_TT_MASK 0x00000018
|
||||
#define GR_EPCTRL_TT_POS 3
|
||||
#define GR_EPCTRL_EH BIT(2)
|
||||
#define GR_EPCTRL_ED BIT(1)
|
||||
#define GR_EPCTRL_EV BIT(0)
|
||||
|
||||
#define GR_DMACTRL_AE BIT(10)
|
||||
#define GR_DMACTRL_AD BIT(3)
|
||||
#define GR_DMACTRL_AI BIT(2)
|
||||
#define GR_DMACTRL_IE BIT(1)
|
||||
#define GR_DMACTRL_DA BIT(0)
|
||||
|
||||
#define GR_EPSTAT_PT BIT(29)
|
||||
#define GR_EPSTAT_PR BIT(29)
|
||||
#define GR_EPSTAT_B1CNT_MASK 0x1fff0000
|
||||
#define GR_EPSTAT_B1CNT_POS 16
|
||||
#define GR_EPSTAT_B0CNT_MASK 0x0000fff8
|
||||
#define GR_EPSTAT_B0CNT_POS 3
|
||||
#define GR_EPSTAT_B1 BIT(2)
|
||||
#define GR_EPSTAT_B0 BIT(1)
|
||||
#define GR_EPSTAT_BS BIT(0)
|
||||
|
||||
#define GR_CONTROL_SI BIT(31)
|
||||
#define GR_CONTROL_UI BIT(30)
|
||||
#define GR_CONTROL_VI BIT(29)
|
||||
#define GR_CONTROL_SP BIT(28)
|
||||
#define GR_CONTROL_FI BIT(27)
|
||||
#define GR_CONTROL_EP BIT(14)
|
||||
#define GR_CONTROL_DH BIT(13)
|
||||
#define GR_CONTROL_RW BIT(12)
|
||||
#define GR_CONTROL_TS_MASK 0x00000e00
|
||||
#define GR_CONTROL_TS_POS 9
|
||||
#define GR_CONTROL_TM BIT(8)
|
||||
#define GR_CONTROL_UA_MASK 0x000000fe
|
||||
#define GR_CONTROL_UA_POS 1
|
||||
#define GR_CONTROL_SU BIT(0)
|
||||
|
||||
#define GR_STATUS_NEPI_MASK 0xf0000000
|
||||
#define GR_STATUS_NEPI_POS 28
|
||||
#define GR_STATUS_NEPO_MASK 0x0f000000
|
||||
#define GR_STATUS_NEPO_POS 24
|
||||
#define GR_STATUS_DM BIT(23)
|
||||
#define GR_STATUS_SU BIT(17)
|
||||
#define GR_STATUS_UR BIT(16)
|
||||
#define GR_STATUS_VB BIT(15)
|
||||
#define GR_STATUS_SP BIT(14)
|
||||
#define GR_STATUS_AF_MASK 0x00003800
|
||||
#define GR_STATUS_AF_POS 11
|
||||
#define GR_STATUS_FN_MASK 0x000007ff
|
||||
#define GR_STATUS_FN_POS 0
|
||||
|
||||
|
||||
#define MAX_CTRL_PL_SIZE 64 /* As per USB standard for full and high speed */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* Driver data structures and utilities */
|
||||
|
||||
struct gr_dma_desc {
|
||||
u32 ctrl;
|
||||
u32 data;
|
||||
u32 next;
|
||||
|
||||
/* These must be last because hw uses the previous three */
|
||||
u32 paddr;
|
||||
struct gr_dma_desc *next_desc;
|
||||
};
|
||||
|
||||
#define GR_DESC_OUT_CTRL_SE BIT(17)
|
||||
#define GR_DESC_OUT_CTRL_IE BIT(15)
|
||||
#define GR_DESC_OUT_CTRL_NX BIT(14)
|
||||
#define GR_DESC_OUT_CTRL_EN BIT(13)
|
||||
#define GR_DESC_OUT_CTRL_LEN_MASK 0x00001fff
|
||||
|
||||
#define GR_DESC_IN_CTRL_MO BIT(18)
|
||||
#define GR_DESC_IN_CTRL_PI BIT(17)
|
||||
#define GR_DESC_IN_CTRL_ML BIT(16)
|
||||
#define GR_DESC_IN_CTRL_IE BIT(15)
|
||||
#define GR_DESC_IN_CTRL_NX BIT(14)
|
||||
#define GR_DESC_IN_CTRL_EN BIT(13)
|
||||
#define GR_DESC_IN_CTRL_LEN_MASK 0x00001fff
|
||||
|
||||
#define GR_DESC_DMAADDR_MASK 0xfffffffc
|
||||
|
||||
struct gr_ep {
|
||||
struct usb_ep ep;
|
||||
struct gr_udc *dev;
|
||||
u16 bytes_per_buffer;
|
||||
unsigned int dma_start;
|
||||
struct gr_epregs __iomem *regs;
|
||||
|
||||
unsigned num:8;
|
||||
unsigned is_in:1;
|
||||
unsigned stopped:1;
|
||||
unsigned wedged:1;
|
||||
unsigned callback:1;
|
||||
|
||||
/* analogous to a host-side qh */
|
||||
struct list_head queue;
|
||||
|
||||
struct list_head ep_list;
|
||||
};
|
||||
|
||||
struct gr_request {
|
||||
struct usb_request req;
|
||||
struct list_head queue;
|
||||
|
||||
/* Chain of dma descriptors */
|
||||
struct gr_dma_desc *first_desc; /* First in the chain */
|
||||
struct gr_dma_desc *curr_desc; /* Current descriptor */
|
||||
struct gr_dma_desc *last_desc; /* Last in the chain */
|
||||
|
||||
u8 setup; /* Setup packet */
|
||||
};
|
||||
|
||||
enum gr_ep0state {
|
||||
GR_EP0_DISCONNECT = 0, /* No host */
|
||||
GR_EP0_SETUP, /* Between STATUS ack and SETUP report */
|
||||
GR_EP0_IDATA, /* IN data stage */
|
||||
GR_EP0_ODATA, /* OUT data stage */
|
||||
GR_EP0_ISTATUS, /* Status stage after IN data stage */
|
||||
GR_EP0_OSTATUS, /* Status stage after OUT data stage */
|
||||
GR_EP0_STALL, /* Data or status stages */
|
||||
GR_EP0_SUSPEND, /* USB suspend */
|
||||
};
|
||||
|
||||
struct gr_udc {
|
||||
struct usb_gadget gadget;
|
||||
struct gr_ep epi[GR_MAXEP];
|
||||
struct gr_ep epo[GR_MAXEP];
|
||||
struct usb_gadget_driver *driver;
|
||||
struct dma_pool *desc_pool;
|
||||
struct device *dev;
|
||||
|
||||
enum gr_ep0state ep0state;
|
||||
struct gr_request *ep0reqo;
|
||||
struct gr_request *ep0reqi;
|
||||
|
||||
struct gr_regs __iomem *regs;
|
||||
int irq;
|
||||
int irqi;
|
||||
int irqo;
|
||||
|
||||
unsigned added:1;
|
||||
unsigned irq_enabled:1;
|
||||
unsigned remote_wakeup:1;
|
||||
|
||||
u8 test_mode;
|
||||
|
||||
enum usb_device_state suspended_from;
|
||||
|
||||
unsigned int nepi;
|
||||
unsigned int nepo;
|
||||
|
||||
struct list_head ep_list;
|
||||
|
||||
spinlock_t lock; /* General lock, a.k.a. "dev->lock" in comments */
|
||||
|
||||
struct dentry *dfs_root;
|
||||
struct dentry *dfs_state;
|
||||
};
|
||||
|
||||
#define to_gr_udc(gadget) (container_of((gadget), struct gr_udc, gadget))
|
@ -1449,7 +1449,7 @@ static void udc_reinit(struct lpc32xx_udc *udc)
|
||||
|
||||
if (i != 0)
|
||||
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
|
||||
ep->ep.maxpacket = ep->maxpacket;
|
||||
usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket);
|
||||
INIT_LIST_HEAD(&ep->queue);
|
||||
ep->req_pending = 0;
|
||||
}
|
||||
|
@ -1647,9 +1647,9 @@ static int __init m66592_probe(struct platform_device *pdev)
|
||||
INIT_LIST_HEAD(&ep->queue);
|
||||
ep->ep.name = m66592_ep_name[i];
|
||||
ep->ep.ops = &m66592_ep_ops;
|
||||
ep->ep.maxpacket = 512;
|
||||
usb_ep_set_maxpacket_limit(&ep->ep, 512);
|
||||
}
|
||||
m66592->ep[0].ep.maxpacket = 64;
|
||||
usb_ep_set_maxpacket_limit(&m66592->ep[0].ep, 64);
|
||||
m66592->ep[0].pipenum = 0;
|
||||
m66592->ep[0].fifoaddr = M66592_CFIFO;
|
||||
m66592->ep[0].fifosel = M66592_CFIFOSEL;
|
||||
|
@ -134,7 +134,7 @@ static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
|
||||
*/
|
||||
#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
|
||||
|
||||
#endif /* CONFIG_USB_DEBUG */
|
||||
#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
|
||||
|
||||
FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/notifier.h>
|
||||
@ -1336,7 +1335,7 @@ static int mv_u3d_eps_init(struct mv_u3d *u3d)
|
||||
ep->ep.name = ep->name;
|
||||
ep->ep.ops = &mv_u3d_ep_ops;
|
||||
ep->wedge = 0;
|
||||
ep->ep.maxpacket = MV_U3D_EP0_MAX_PKT_SIZE;
|
||||
usb_ep_set_maxpacket_limit(&ep->ep, MV_U3D_EP0_MAX_PKT_SIZE);
|
||||
ep->ep_num = 0;
|
||||
ep->ep.desc = &mv_u3d_ep0_desc;
|
||||
INIT_LIST_HEAD(&ep->queue);
|
||||
@ -1361,7 +1360,7 @@ static int mv_u3d_eps_init(struct mv_u3d *u3d)
|
||||
ep->ep.name = ep->name;
|
||||
|
||||
ep->ep.ops = &mv_u3d_ep_ops;
|
||||
ep->ep.maxpacket = (unsigned short) ~0;
|
||||
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
|
||||
ep->ep_num = i / 2;
|
||||
|
||||
INIT_LIST_HEAD(&ep->queue);
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/interrupt.h>
|
||||
@ -1261,7 +1260,7 @@ static int eps_init(struct mv_udc *udc)
|
||||
ep->ep.ops = &mv_ep_ops;
|
||||
ep->wedge = 0;
|
||||
ep->stopped = 0;
|
||||
ep->ep.maxpacket = EP0_MAX_PKT_SIZE;
|
||||
usb_ep_set_maxpacket_limit(&ep->ep, EP0_MAX_PKT_SIZE);
|
||||
ep->ep_num = 0;
|
||||
ep->ep.desc = &mv_ep0_desc;
|
||||
INIT_LIST_HEAD(&ep->queue);
|
||||
@ -1284,7 +1283,7 @@ static int eps_init(struct mv_udc *udc)
|
||||
|
||||
ep->ep.ops = &mv_ep_ops;
|
||||
ep->stopped = 0;
|
||||
ep->ep.maxpacket = (unsigned short) ~0;
|
||||
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
|
||||
ep->ep_num = i / 2;
|
||||
|
||||
INIT_LIST_HEAD(&ep->queue);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user