Commit 976f8bef authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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

Felipe writes:

usb: patches for v3.11 merge window

All function drivers are now converted to our new configfs-based
binding. Eventually this will help us getting rid of in-kernel
gadget drivers and only keep function drivers in the kernel.

MUSB was taught that it needs to be built for host-only and
device-only modes too. We had this support long ago but it
involved a ridiculous amount of ifdefs. Now we have a much
cleaner approach.

Samsung Exynos4 platform now implements HSIC support.

We're introducing support for AB8540 and AB9540 PHYs.

MUSB module reinsertion now works as expected, before we were
getting -EBUSY being returned by the resource checks done on
driver core.

DWC3 now has minimum support for TI's AM437x series of SoCs.

OMAP5 USB3 PHY learned one extra DPLL configuration values because
that PHY is reused in TI's DRA7xx devices.

We're introducing support for Faraday fotg210 UDCs.

Last, but not least, the usual set of non-critical fixes and cleanups
ranging from usage of platform_{get,set}_drvdata to lock improvements.
Signed-of-by: default avatarFelipe Balbi <balbi@ti.com>
parents 1143832e b1fd6cb5
What: /config/usb-gadget/gadget/functions/eem.name
Date: May 2013
KenelVersion: 3.11
Description:
The attributes:
ifname - network device interface name associated with
this function instance
qmult - queue length multiplier for high and
super speed
host_addr - MAC address of host's end of this
Ethernet over USB link
dev_addr - MAC address of device's end of this
Ethernet over USB link
What: /config/usb-gadget/gadget/functions/phonet.name
Date: May 2013
KenelVersion: 3.11
Description:
This item contains just one readonly attribute: ifname.
It contains the network interface name assigned during
network device registration.
What: /config/usb-gadget/gadget/functions/rndis.name
Date: May 2013
KenelVersion: 3.11
Description:
The attributes:
ifname - network device interface name associated with
this function instance
qmult - queue length multiplier for high and
super speed
host_addr - MAC address of host's end of this
Ethernet over USB link
dev_addr - MAC address of device's end of this
Ethernet over USB link
What: /config/usb-gadget/gadget/functions/geth.name
Date: May 2013
KenelVersion: 3.11
Description:
The attributes:
ifname - network device interface name associated with
this function instance
qmult - queue length multiplier for high and
super speed
host_addr - MAC address of host's end of this
Ethernet over USB link
dev_addr - MAC address of device's end of this
Ethernet over USB link
......@@ -6,27 +6,10 @@ Practice : Universal Serial Bus" with the following modifications
and additions :
Required properties :
- compatible : Should be "nvidia,tegra20-ehci" for USB controllers
used in host mode.
- phy_type : Should be one of "ulpi" or "utmi".
- nvidia,vbus-gpio : If present, specifies a gpio that needs to be
activated for the bus to be powered.
- nvidia,phy : phandle of the PHY instance, the controller is connected to.
Required properties for phy_type == ulpi:
- nvidia,phy-reset-gpio : The GPIO used to reset the PHY.
- compatible : Should be "nvidia,tegra20-ehci".
- nvidia,phy : phandle of the PHY that the controller is connected to.
- clocks : Contains a single entry which defines the USB controller's clock.
Optional properties:
- dr_mode : dual role mode. Indicates the working mode for
nvidia,tegra20-ehci compatible controllers. Can be "host", "peripheral",
or "otg". Default to "host" if not defined for backward compatibility.
host means this is a host controller
peripheral means it is device controller
otg means it can operate as either ("on the go")
- nvidia,has-legacy-mode : boolean indicates whether this controller can
operate in legacy mode (as APX 2500 / 2600). In legacy mode some
registers are accessed through the APB_MISC base address instead of
the USB controller. Since this is a legacy issue it probably does not
warrant a compatible string of its own.
- nvidia,needs-double-reset : boolean is to be set for some of the Tegra2
USB ports, which need reset twice due to hardware issues.
- nvidia,needs-double-reset : boolean is to be set for some of the Tegra20
USB ports, which need reset twice due to hardware issues.
......@@ -4,14 +4,49 @@ The device node for Tegra SOC USB PHY:
Required properties :
- compatible : Should be "nvidia,tegra20-usb-phy".
- reg : Address and length of the register set for the USB PHY interface.
- phy_type : Should be one of "ulpi" or "utmi".
- reg : Defines the following set of registers, in the order listed:
- The PHY's own register set.
Always present.
- The register set of the PHY containing the UTMI pad control registers.
Present if-and-only-if phy_type == utmi.
- phy_type : Should be one of "utmi", "ulpi" or "hsic".
- clocks : Defines the clocks listed in the clock-names property.
- clock-names : The following clock names must be present:
- reg: The clock needed to access the PHY's own registers. This is the
associated EHCI controller's clock. Always present.
- pll_u: PLL_U. Always present.
- timer: The timeout clock (clk_m). Present if phy_type == utmi.
- utmi-pads: The clock needed to access the UTMI pad control registers.
Present if phy_type == utmi.
- ulpi-link: The clock Tegra provides to the ULPI PHY (cdev2).
Present if phy_type == ulpi, and ULPI link mode is in use.
Required properties for phy_type == ulpi:
- nvidia,phy-reset-gpio : The GPIO used to reset the PHY.
Required PHY timing params for utmi phy:
- nvidia,hssync-start-delay : Number of 480 Mhz clock cycles to wait before
start of sync launches RxActive
- nvidia,elastic-limit : Variable FIFO Depth of elastic input store
- nvidia,idle-wait-delay : Number of 480 Mhz clock cycles of idle to wait
before declare IDLE.
- nvidia,term-range-adj : Range adjusment on terminations
- nvidia,xcvr-setup : HS driver output control
- nvidia,xcvr-lsfslew : LS falling slew rate control.
- nvidia,xcvr-lsrslew : LS rising slew rate control.
Optional properties:
- nvidia,has-legacy-mode : boolean indicates whether this controller can
operate in legacy mode (as APX 2500 / 2600). In legacy mode some
registers are accessed through the APB_MISC base address instead of
the USB controller.
\ No newline at end of file
the USB controller.
- nvidia,is-wired : boolean. Indicates whether we can do certain kind of power
optimizations for the devices that are always connected. e.g. modem.
- dr_mode : dual role mode. Indicates the working mode for the PHY. Can be
"host", "peripheral", or "otg". Defaults to "host" if not defined.
host means this is a host controller
peripheral means it is device controller
otg means it can operate as either ("on the go")
Required properties for dr_mode == otg:
- vbus-supply: regulator for VBUS
......@@ -449,7 +449,11 @@ ac97: ac97 {
usb@c5004000 {
status = "okay";
nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */
};
usb-phy@c5004000 {
nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */
};
sdhci@c8000600 {
......
......@@ -428,17 +428,26 @@ usb@c5000000 {
status = "okay";
};
usb-phy@c5000000 {
status = "okay";
};
usb@c5004000 {
status = "okay";
nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */
};
usb-phy@c5004000 {
status = "okay";
nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */
};
usb@c5008000 {
status = "okay";
};
usb-phy@c5004400 {
nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
usb-phy@c5008000 {
status = "okay";
};
sdhci@c8000200 {
......
......@@ -38,13 +38,20 @@ uartd {
usb@c5000000 {
status = "okay";
dr_mode = "otg";
};
usb-phy@c5000000 {
status = "okay";
};
usb@c5008000 {
status = "okay";
};
usb-phy@c5008000 {
status = "okay";
};
serial@70006000 {
status = "okay";
};
......
......@@ -427,17 +427,26 @@ usb@c5000000 {
status = "okay";
};
usb-phy@c5000000 {
status = "okay";
};
usb@c5004000 {
status = "okay";
nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */
nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */
};
usb-phy@c5004000 {
status = "okay";
nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */
};
usb@c5008000 {
status = "okay";
};
usb-phy@c5004400 {
nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */
usb-phy@c5008000 {
status = "okay";
};
sdhci@c8000000 {
......
......@@ -569,17 +569,28 @@ usb@c5000000 {
dr_mode = "otg";
};
usb-phy@c5000000 {
status = "okay";
vbus-supply = <&vbus_reg>;
dr_mode = "otg";
};
usb@c5004000 {
status = "okay";
nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */
};
usb-phy@c5004000 {
status = "okay";
nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */
};
usb@c5008000 {
status = "okay";
};
usb-phy@c5004400 {
nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
usb-phy@c5008000 {
status = "okay";
};
sdhci@c8000000 {
......@@ -807,6 +818,15 @@ regulator@2 {
gpio = <&pmic 1 0>;
enable-active-high;
};
vbus_reg: regulator@3 {
compatible = "regulator-fixed";
reg = <3>;
regulator-name = "vdd_vbus_wup1";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio 24 0>; /* PD0 */
};
};
sound {
......
......@@ -470,6 +470,10 @@ usb@c5008000 {
status = "okay";
};
usb-phy@c5008000 {
status = "okay";
};
sdhci@c8000600 {
cd-gpios = <&gpio 58 1>; /* gpio PH2 */
wp-gpios = <&gpio 59 0>; /* gpio PH3 */
......
......@@ -314,17 +314,27 @@ usb@c5000000 {
nvidia,vbus-gpio = <&gpio 170 0>; /* gpio PV2 */
};
usb-phy@c5000000 {
status = "okay";
vbus-supply = <&vbus_reg>;
};
usb@c5004000 {
status = "okay";
nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */
nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */
};
usb-phy@c5004000 {
status = "okay";
nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */
};
usb@c5008000 {
status = "okay";
};
usb-phy@c5004400 {
nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */
usb-phy@c5008000 {
status = "okay";
};
sdhci@c8000000 {
......@@ -390,6 +400,15 @@ hdmi_pll_reg: regulator@1 {
regulator-max-microvolt = <1800000>;
regulator-always-on;
};
vbus_reg: regulator@2 {
compatible = "regulator-fixed";
reg = <2>;
regulator-name = "usb1_vbus";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio 170 0>; /* PV2 */
};
};
sound {
......
......@@ -505,17 +505,26 @@ usb@c5000000 {
status = "okay";
};
usb-phy@c5000000 {
status = "okay";
};
usb@c5004000 {
status = "okay";
nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */
};
usb-phy@c5004000 {
status = "okay";
nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */
};
usb@c5008000 {
status = "okay";
};
usb-phy@c5004400 {
nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
usb-phy@c5008000 {
status = "okay";
};
sdhci@c8000000 {
......
......@@ -511,11 +511,21 @@ usb@c5000000 {
nvidia,vbus-gpio = <&tca6416 0 0>; /* GPIO_PMU0 */
};
usb-phy@c5000000 {
status = "okay";
vbus-supply = <&vbus1_reg>;
};
usb@c5008000 {
status = "okay";
nvidia,vbus-gpio = <&tca6416 1 0>; /* GPIO_PMU1 */
};
usb-phy@c5008000 {
status = "okay";
vbus-supply = <&vbus3_reg>;
};
sdhci@c8000400 {
status = "okay";
cd-gpios = <&gpio 69 1>; /* gpio PI5 */
......@@ -568,6 +578,24 @@ usb0_vbus_reg: regulator {
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
vbus1_reg: regulator@2 {
compatible = "regulator-fixed";
reg = <2>;
regulator-name = "vbus1";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&tca6416 0 0>; /* GPIO_PMU0 */
};
vbus3_reg: regulator@3 {
compatible = "regulator-fixed";
reg = <3>;
regulator-name = "vbus3";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&tca6416 1 0>; /* GPIO_PMU1 */
};
};
sound {
......
......@@ -455,13 +455,24 @@ usb@c5000000 {
status = "disabled";
};
phy1: usb-phy@c5000400 {
phy1: usb-phy@c5000000 {
compatible = "nvidia,tegra20-usb-phy";
reg = <0xc5000400 0x3c00>;
reg = <0xc5000000 0x4000 0xc5000000 0x4000>;
phy_type = "utmi";
clocks = <&tegra_car 22>,
<&tegra_car 127>,
<&tegra_car 106>,
<&tegra_car 22>;
clock-names = "reg", "pll_u", "timer", "utmi-pads";
nvidia,has-legacy-mode;
clocks = <&tegra_car 22>, <&tegra_car 127>;
clock-names = "phy", "pll_u";
hssync_start_delay = <9>;
idle_wait_delay = <17>;
elastic_limit = <16>;
term_range_adj = <6>;
xcvr_setup = <9>;
xcvr_lsfslew = <1>;
xcvr_lsrslew = <1>;
status = "disabled";
};
usb@c5004000 {
......@@ -474,12 +485,15 @@ usb@c5004000 {
status = "disabled";
};
phy2: usb-phy@c5004400 {
phy2: usb-phy@c5004000 {
compatible = "nvidia,tegra20-usb-phy";
reg = <0xc5004400 0x3c00>;
reg = <0xc5004000 0x4000>;
phy_type = "ulpi";
clocks = <&tegra_car 93>, <&tegra_car 127>;
clock-names = "phy", "pll_u";
clocks = <&tegra_car 58>,
<&tegra_car 127>,
<&tegra_car 93>;
clock-names = "reg", "pll_u", "ulpi-link";
status = "disabled";
};
usb@c5008000 {
......@@ -492,12 +506,23 @@ usb@c5008000 {
status = "disabled";
};
phy3: usb-phy@c5008400 {
phy3: usb-phy@c5008000 {
compatible = "nvidia,tegra20-usb-phy";
reg = <0xc5008400 0x3c00>;
reg = <0xc5008000 0x4000 0xc5000000 0x4000>;
phy_type = "utmi";
clocks = <&tegra_car 22>, <&tegra_car 127>;
clock-names = "phy", "pll_u";
clocks = <&tegra_car 59>,
<&tegra_car 127>,
<&tegra_car 106>,
<&tegra_car 22>;
clock-names = "reg", "pll_u", "timer", "utmi-pads";
hssync_start_delay = <9>;
idle_wait_delay = <17>;
elastic_limit = <16>;
term_range_adj = <6>;
xcvr_setup = <9>;
xcvr_lsfslew = <2>;
xcvr_lsrslew = <2>;
status = "disabled";
};
sdhci@c8000000 {
......
This diff is collapsed.
......@@ -133,7 +133,6 @@ static int dwc3_pci_probe(struct pci_dev *pci,
return -ENODEV;
}
pci_set_power_state(pci, PCI_D0);
pci_set_master(pci);
ret = dwc3_pci_register_phys(glue);
......
......@@ -192,6 +192,16 @@ config USB_FUSB300
help
Faraday usb device controller FUSB300 driver
config USB_FOTG210_UDC
tristate "Faraday FOTG210 USB Peripheral Controller"
help
Faraday USB2.0 OTG controller which can be configured as
high speed or full speed USB device. This driver supppors
Bulk Transfer so far.
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "fotg210_udc".
config USB_OMAP
tristate "OMAP USB Device Controller"
depends on ARCH_OMAP1
......@@ -334,14 +344,6 @@ config USB_MV_U3D
# Controllers available in both integrated and discrete versions
#
# musb builds in ../musb along with host support
config USB_GADGET_MUSB_HDRC
tristate "Inventra HDRC USB Peripheral (TI, ADI, ...)"
depends on USB_MUSB_HDRC
help
This OTG-capable silicon IP is used in dual designs including
the TI DaVinci, OMAP 243x, OMAP 343x, TUSB 6010, and ADI Blackfin
config USB_M66592
tristate "Renesas M66592 USB Peripheral Controller"
help
......@@ -507,12 +509,36 @@ config USB_F_SS_LB
config USB_U_SERIAL
tristate
config USB_U_ETHER
tristate
config USB_U_RNDIS
tristate
config USB_F_SERIAL
tristate
config USB_F_OBEX
tristate
config USB_F_NCM
tristate
config USB_F_ECM
tristate
config USB_F_PHONET
tristate
config USB_F_EEM
tristate
config USB_F_SUBSET
tristate
config USB_F_RNDIS
tristate
choice
tristate "USB Gadget Drivers"
default USB_ETH
......@@ -534,6 +560,57 @@ choice
# this first set of drivers all depend on bulk-capable hardware.
config USB_CONFIGFS_ECM_SUBSET
boolean "Ethernet Control Model (CDC ECM) subset"
depends on USB_CONFIGFS
depends on NET
select USB_U_ETHER
select USB_F_SUBSET
help
On hardware that can't implement the full protocol,
a simple CDC subset is used, placing fewer demands on USB.
config USB_CONFIGFS_RNDIS
bool "RNDIS"
depends on USB_CONFIGFS
depends on NET
select USB_U_ETHER
select USB_F_RNDIS
help
Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
and Microsoft provides redistributable binary RNDIS drivers for
older versions of Windows.
To make MS-Windows work with this, use Documentation/usb/linux.inf
as the "driver info file". For versions of MS-Windows older than
XP, you'll need to download drivers from Microsoft's website; a URL
is given in comments found in that info file.
config USB_CONFIGFS_EEM
bool "Ethernet Emulation Model (EEM)"
depends on USB_CONFIGFS
depends on NET
select USB_U_ETHER
select USB_F_EEM
help
CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM
and therefore can be supported by more hardware. Technically ECM and
EEM are designed for different applications. The ECM model extends
the network interface to the target (e.g. a USB cable modem), and the
EEM model is for mobile devices to communicate with hosts using
ethernet over USB. For Linux gadgets, however, the interface with
the host is the same (a usbX device), so the differences are minimal.
config USB_CONFIGFS_PHONET
boolean "Phonet protocol"
depends on USB_CONFIGFS
depends on NET
depends on PHONET
select USB_U_ETHER
select USB_F_PHONET
help
The Phonet protocol implementation for USB device.
config USB_ZERO
tristate "Gadget Zero (DEVELOPMENT)"
select USB_LIBCOMPOSITE
......@@ -603,6 +680,10 @@ config USB_ETH
tristate "Ethernet Gadget (with CDC Ethernet support)"
depends on NET
select USB_LIBCOMPOSITE
select USB_U_ETHER
select USB_U_RNDIS
select USB_F_ECM
select USB_F_SUBSET
select CRC32
help
This driver implements Ethernet style communication, in one of
......@@ -639,6 +720,7 @@ config USB_ETH_RNDIS
bool "RNDIS support"
depends on USB_ETH
select USB_LIBCOMPOSITE
select USB_F_RNDIS
default y
help
Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
......@@ -658,6 +740,7 @@ config USB_ETH_EEM
bool "Ethernet Emulation Model (EEM) support"
depends on USB_ETH
select USB_LIBCOMPOSITE
select USB_F_EEM
default n
help
CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM
......@@ -675,6 +758,8 @@ config USB_G_NCM
tristate "Network Control Model (NCM) support"
depends on NET
select USB_LIBCOMPOSITE
select USB_U_ETHER
select USB_F_NCM
select CRC32
help
This driver implements USB CDC NCM subclass standard. NCM is
......@@ -718,6 +803,7 @@ config USB_FUNCTIONFS
config USB_FUNCTIONFS_ETH
bool "Include configuration with CDC ECM (Ethernet)"
depends on USB_FUNCTIONFS && NET
select USB_U_ETHER
help
Include a configuration with CDC ECM function (Ethernet) and the
Function Filesystem.
......@@ -725,6 +811,8 @@ config USB_FUNCTIONFS_ETH
config USB_FUNCTIONFS_RNDIS
bool "Include configuration with RNDIS (Ethernet)"
depends on USB_FUNCTIONFS && NET
select USB_U_ETHER
select USB_U_RNDIS
help
Include a configuration with RNDIS function (Ethernet) and the Filesystem.
......@@ -825,7 +913,9 @@ config USB_CDC_COMPOSITE
depends on NET
select USB_LIBCOMPOSITE
select USB_U_SERIAL
select USB_U_ETHER
select USB_F_ACM
select USB_F_ECM
help
This driver provides two functions in one configuration:
a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
......@@ -842,7 +932,11 @@ config USB_G_NOKIA
depends on PHONET
select USB_LIBCOMPOSITE
select USB_U_SERIAL
select USB_U_ETHER
select USB_F_ACM
select USB_F_OBEX
select USB_F_PHONET
select USB_F_ECM
help
The Nokia composite gadget provides support for acm, obex
and phonet in only one composite gadget driver.
......@@ -869,6 +963,8 @@ config USB_G_MULTI
select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
select USB_LIBCOMPOSITE
select USB_U_SERIAL
select USB_U_ETHER
select USB_U_RNDIS
select USB_F_ACM
help
The Multifunction Composite Gadget provides Ethernet (RNDIS
......
......@@ -33,6 +33,7 @@ obj-$(CONFIG_USB_EG20T) += pch_udc.o
obj-$(CONFIG_USB_MV_UDC) += mv_udc.o
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
# USB Functions
......@@ -45,6 +46,21 @@ usb_f_serial-y := f_serial.o
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
obj-$(CONFIG_USB_F_ECM) += usb_f_ecm.o
usb_f_phonet-y := f_phonet.o
obj-$(CONFIG_USB_F_PHONET) += usb_f_phonet.o
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
obj-$(CONFIG_USB_F_RNDIS) += usb_f_rndis.o
#
# USB gadget drivers
......
......@@ -15,6 +15,7 @@
#include "u_ether.h"
#include "u_serial.h"
#include "u_ecm.h"
#define DRIVER_DESC "CDC Composite Gadget"
......@@ -32,18 +33,9 @@
#define CDC_VENDOR_NUM 0x0525 /* NetChip */
#define CDC_PRODUCT_NUM 0xa4aa /* CDC Composite: ECM + ACM */
/*-------------------------------------------------------------------------*/
USB_GADGET_COMPOSITE_OPTIONS();
/*
* 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.
*/
#include "f_ecm.c"
#include "u_ether.c"
USB_ETHERNET_MODULE_PARAMETERS();
/*-------------------------------------------------------------------------*/
......@@ -102,12 +94,13 @@ static struct usb_gadget_strings *dev_strings[] = {
NULL,
};
static u8 hostaddr[ETH_ALEN];
static struct eth_dev *the_dev;
/*-------------------------------------------------------------------------*/
static struct usb_function *f_acm;
static struct usb_function_instance *fi_serial;
static struct usb_function *f_ecm;
static struct usb_function_instance *fi_ecm;
/*
* We _always_ have both CDC ECM and CDC ACM functions.
*/
......@@ -120,13 +113,27 @@ static int __init cdc_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
status = ecm_bind_config(c, hostaddr, the_dev);
if (status < 0)
return status;
fi_ecm = usb_get_function_instance("ecm");
if (IS_ERR(fi_ecm)) {
status = PTR_ERR(fi_ecm);
goto err_func_ecm;
}
f_ecm = usb_get_function(fi_ecm);
if (IS_ERR(f_ecm)) {
status = PTR_ERR(f_ecm);
goto err_get_ecm;
}
status = usb_add_function(c, f_ecm);
if (status)
goto err_add_ecm;
fi_serial = usb_get_function_instance("acm");
if (IS_ERR(fi_serial))
return PTR_ERR(fi_serial);
if (IS_ERR(fi_serial)) {
status = PTR_ERR(fi_serial);
goto err_get_acm;
}
f_acm = usb_get_function(fi_serial);
if (IS_ERR(f_acm)) {
......@@ -136,12 +143,21 @@ static int __init cdc_do_config(struct usb_configuration *c)
status = usb_add_function(c, f_acm);
if (status)
goto err_conf;
goto err_add_acm;
return 0;
err_conf:
err_add_acm:
usb_put_function(f_acm);
err_func_acm:
usb_put_function_instance(fi_serial);
err_get_acm:
usb_remove_function(c, f_ecm);
err_add_ecm:
usb_put_function(f_ecm);
err_get_ecm:
usb_put_function_instance(fi_ecm);
err_func_ecm:
return status;
}
......@@ -157,6 +173,7 @@ static struct usb_configuration cdc_config_driver = {
static int __init cdc_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
struct f_ecm_opts *ecm_opts;
int status;
if (!can_support_ecm(cdev->gadget)) {
......@@ -165,10 +182,23 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
return -EINVAL;
}
/* set up network link layer */
the_dev = gether_setup(cdev->gadget, hostaddr);
if (IS_ERR(the_dev))
return PTR_ERR(the_dev);
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);
gether_set_qmult(ecm_opts->net, qmult);
if (!gether_set_host_addr(ecm_opts->net, host_addr))
pr_info("using host ethernet address: %s", host_addr);
if (!gether_set_dev_addr(ecm_opts->net, dev_addr))
pr_info("using self ethernet address: %s", dev_addr);
fi_serial = usb_get_function_instance("acm");
if (IS_ERR(fi_serial)) {
status = PTR_ERR(fi_serial);
goto fail;
}
/* Allocate string descriptor numbers ... note that string
* contents can be overridden by the composite_dev glue.
......@@ -192,7 +222,9 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
return 0;
fail1:
gether_cleanup(the_dev);
usb_put_function_instance(fi_serial);
fail:
usb_put_function_instance(fi_ecm);
return status;
}
......@@ -200,7 +232,10 @@ static int __exit cdc_unbind(struct usb_composite_dev *cdev)
{
usb_put_function(f_acm);
usb_put_function_instance(fi_serial);
gether_cleanup(the_dev);
if (!IS_ERR_OR_NULL(f_ecm))
usb_put_function(f_ecm);
if (!IS_ERR_OR_NULL(fi_ecm))
usb_put_function_instance(fi_ecm);
return 0;
}
......
......@@ -14,6 +14,7 @@
/* #define VERBOSE_DEBUG */
#include <linux/kernel.h>
#include <linux/netdevice.h>
#if defined USB_ETH_RNDIS
# undef USB_ETH_RNDIS
......@@ -91,27 +92,23 @@ static inline bool has_rndis(void)
#endif
}
/*-------------------------------------------------------------------------*/
#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.
*/
#include "f_ecm.c"
#include "f_subset.c"
#include "u_ecm.h"
#include "u_gether.h"
#ifdef USB_ETH_RNDIS
#include "f_rndis.c"
#include "rndis.c"
#include "u_rndis.h"
#include "rndis.h"
#else
#define rndis_borrow_net(...) do {} while (0)
#endif
#include "f_eem.c"
#include "u_ether.c"
#include "u_eem.h"
/*-------------------------------------------------------------------------*/
USB_GADGET_COMPOSITE_OPTIONS();
USB_ETHERNET_MODULE_PARAMETERS();
/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
* Instead: allocate your own, using normal USB-IF procedures.
*/
......@@ -206,8 +203,18 @@ static struct usb_gadget_strings *dev_strings[] = {
NULL,
};
static u8 hostaddr[ETH_ALEN];
static struct eth_dev *the_dev;
static struct usb_function_instance *fi_ecm;
static struct usb_function *f_ecm;
static struct usb_function_instance *fi_eem;
static struct usb_function *f_eem;
static struct usb_function_instance *fi_geth;
static struct usb_function *f_geth;
static struct usb_function_instance *fi_rndis;
static struct usb_function *f_rndis;
/*-------------------------------------------------------------------------*/
/*
......@@ -217,6 +224,8 @@ static struct eth_dev *the_dev;
*/
static int __init rndis_do_config(struct usb_configuration *c)
{
int status;
/* FIXME alloc iConfiguration string, set it in c->strings */
if (gadget_is_otg(c->cdev->gadget)) {
......@@ -224,7 +233,15 @@ static int __init rndis_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
return rndis_bind_config(c, hostaddr, the_dev);
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;
}
static struct usb_configuration rndis_config_driver = {
......@@ -249,6 +266,8 @@ MODULE_PARM_DESC(use_eem, "use CDC EEM mode");
*/
static int __init eth_do_config(struct usb_configuration *c)
{
int status = 0;
/* FIXME alloc iConfiguration string, set it in c->strings */
if (gadget_is_otg(c->cdev->gadget)) {
......@@ -256,12 +275,38 @@ static int __init eth_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
if (use_eem)
return eem_bind_config(c, the_dev);
else if (can_support_ecm(c->cdev->gadget))
return ecm_bind_config(c, hostaddr, the_dev);
else
return geth_bind_config(c, hostaddr, the_dev);
if (use_eem) {
f_eem = usb_get_function(fi_eem);
if (IS_ERR(f_eem))
return PTR_ERR(f_eem);
status = usb_add_function(c, f_eem);
if (status < 0)
usb_put_function(f_eem);
return status;
} else 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);
return status;
} 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;
}
}
static struct usb_configuration eth_config_driver = {
......@@ -276,24 +321,50 @@ static struct usb_configuration eth_config_driver = {
static int __init eth_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
struct f_eem_opts *eem_opts = NULL;
struct f_ecm_opts *ecm_opts = NULL;
struct f_gether_opts *geth_opts = NULL;
struct net_device *net;
int status;
/* set up network link layer */
the_dev = gether_setup(cdev->gadget, hostaddr);
if (IS_ERR(the_dev))
return PTR_ERR(the_dev);
/* set up main config label and device descriptor */
if (use_eem) {
/* EEM */
fi_eem = usb_get_function_instance("eem");
if (IS_ERR(fi_eem))
return PTR_ERR(fi_eem);
eem_opts = container_of(fi_eem, struct f_eem_opts, func_inst);
net = eem_opts->net;
eth_config_driver.label = "CDC Ethernet (EEM)";
device_desc.idVendor = cpu_to_le16(EEM_VENDOR_NUM);
device_desc.idProduct = cpu_to_le16(EEM_PRODUCT_NUM);
} else if (can_support_ecm(cdev->gadget)) {
} else if (can_support_ecm(gadget)) {
/* ECM */
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;
eth_config_driver.label = "CDC Ethernet (ECM)";
} else {
/* CDC Subset */
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;
eth_config_driver.label = "CDC Subset/SAFE";
device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM);
......@@ -302,8 +373,34 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
}
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);
if (has_rndis()) {
/* RNDIS plus ECM-or-Subset */
gether_set_gadget(net, cdev->gadget);
status = gether_register_netdev(net);
if (status)
goto fail;
if (use_eem)
eem_opts->bound = true;
else if (can_support_ecm(gadget))
ecm_opts->bound = true;
else
geth_opts->bound = true;
fi_rndis = usb_get_function_instance("rndis");
if (IS_ERR(fi_rndis)) {
status = PTR_ERR(fi_rndis);
goto fail;
}
rndis_borrow_net(fi_rndis, net);
device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM);
device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM);
device_desc.bNumConfigurations = 2;
......@@ -315,7 +412,7 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
status = usb_string_ids_tab(cdev, strings_dev);
if (status < 0)
goto fail;
goto fail1;
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
......@@ -324,12 +421,12 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
status = usb_add_config(cdev, &rndis_config_driver,
rndis_do_config);
if (status < 0)
goto fail;
goto fail1;
}
status = usb_add_config(cdev, &eth_config_driver, eth_do_config);
if (status < 0)
goto fail;
goto fail1;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
......@@ -337,14 +434,29 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
return 0;
fail1:
if (has_rndis())
usb_put_function_instance(fi_rndis);
fail:
gether_cleanup(the_dev);
if (use_eem)
usb_put_function_instance(fi_eem);
else if (can_support_ecm(gadget))
usb_put_function_instance(fi_ecm);
else
usb_put_function_instance(fi_geth);
return status;
}
static int __exit eth_unbind(struct usb_composite_dev *cdev)
{
gether_cleanup(the_dev);
if (has_rndis())
usb_put_function_instance(fi_rndis);
if (use_eem)
usb_put_function_instance(fi_eem);
else if (can_support_ecm(cdev->gadget))
usb_put_function_instance(fi_ecm);
else
usb_put_function_instance(fi_geth);
return 0;
}
......
......@@ -14,10 +14,13 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/etherdevice.h>
#include "u_ether.h"
#include "u_ether_configfs.h"
#include "u_ecm.h"
/*
......@@ -684,9 +687,44 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct f_ecm *ecm = func_to_ecm(f);
struct usb_string *us;
int status;
struct usb_ep *ep;
#ifndef USBF_ECM_INCLUDED
struct f_ecm_opts *ecm_opts;
if (!can_support_ecm(cdev->gadget))
return -EINVAL;
ecm_opts = container_of(f->fi, struct f_ecm_opts, func_inst);
/*
* in drivers/usb/gadget/configfs.c:configfs_composite_bind()
* configurations are bound in sequence with list_for_each_entry,
* in each configuration its functions are bound in sequence
* with list_for_each_entry, so we assume no race condition
* with regard to ecm_opts->bound access
*/
if (!ecm_opts->bound) {
mutex_lock(&ecm_opts->lock);
gether_set_gadget(ecm_opts->net, cdev->gadget);
status = gether_register_netdev(ecm_opts->net);
mutex_unlock(&ecm_opts->lock);
if (status)
return status;
ecm_opts->bound = true;
}
#endif
us = usb_gstrings_attach(cdev, ecm_strings,
ARRAY_SIZE(ecm_string_defs));
if (IS_ERR(us))
return PTR_ERR(us);
ecm_control_intf.iInterface = us[0].id;
ecm_data_intf.iInterface = us[2].id;
ecm_desc.iMACAddress = us[1].id;
ecm_iad_descriptor.iFunction = us[3].id;
/* allocate instance-specific interface IDs */
status = usb_interface_id(c, f);
if (status < 0)
......@@ -796,14 +834,15 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
return status;
}
#ifdef USBF_ECM_INCLUDED
static void
ecm_unbind(struct usb_configuration *c, struct usb_function *f)
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");
ecm_string_defs[0].id = 0;
usb_free_all_descriptors(f);
kfree(ecm->notify_req->buf);
......@@ -834,17 +873,6 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
return -EINVAL;
if (ecm_string_defs[0].id == 0) {
status = usb_string_ids_tab(c->cdev, ecm_string_defs);
if (status)
return status;
ecm_control_intf.iInterface = ecm_string_defs[0].id;
ecm_data_intf.iInterface = ecm_string_defs[2].id;
ecm_desc.iMACAddress = ecm_string_defs[1].id;
ecm_iad_descriptor.iFunction = ecm_string_defs[3].id;
}
/* allocate and initialize one new instance */
ecm = kzalloc(sizeof *ecm, GFP_KERNEL);
if (!ecm)
......@@ -858,10 +886,9 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
ecm->port.cdc_filter = DEFAULT_FILTER;
ecm->port.func.name = "cdc_ethernet";
ecm->port.func.strings = ecm_strings;
/* descriptors are per-instance copies */
ecm->port.func.bind = ecm_bind;
ecm->port.func.unbind = ecm_unbind;
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;
......@@ -872,3 +899,142 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
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,
func_inst.group);
}
/* f_ecm_item_ops */
USB_ETHERNET_CONFIGFS_ITEM(ecm);
/* f_ecm_opts_dev_addr */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(ecm);
/* f_ecm_opts_host_addr */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(ecm);
/* f_ecm_opts_qmult */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(ecm);
/* f_ecm_opts_ifname */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(ecm);
static struct configfs_attribute *ecm_attrs[] = {
&f_ecm_opts_dev_addr.attr,
&f_ecm_opts_host_addr.attr,
&f_ecm_opts_qmult.attr,
&f_ecm_opts_ifname.attr,
NULL,
};
static struct config_item_type ecm_func_type = {
.ct_item_ops = &ecm_item_ops,
.ct_attrs = ecm_attrs,
.ct_owner = THIS_MODULE,
};
static void ecm_free_inst(struct usb_function_instance *f)
{
struct f_ecm_opts *opts;
opts = container_of(f, struct f_ecm_opts, func_inst);
if (opts->bound)
gether_cleanup(netdev_priv(opts->net));
else
free_netdev(opts->net);
kfree(opts);
}
static struct usb_function_instance *ecm_alloc_inst(void)
{
struct f_ecm_opts *opts;
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
return ERR_PTR(-ENOMEM);
mutex_init(&opts->lock);
opts->func_inst.free_func_inst = ecm_free_inst;
opts->net = gether_setup_default();
if (IS_ERR(opts->net))
return ERR_PTR(PTR_ERR(opts->net));
config_group_init_type_name(&opts->func_inst.group, "", &ecm_func_type);
return &opts->func_inst;
}
static void ecm_free(struct usb_function *f)
{
struct f_ecm *ecm;
struct f_ecm_opts *opts;
ecm = func_to_ecm(f);
opts = container_of(f->fi, struct f_ecm_opts, func_inst);
kfree(ecm);
mutex_lock(&opts->lock);
opts->refcnt--;
mutex_unlock(&opts->lock);
}
static void ecm_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);
}
struct usb_function *ecm_alloc(struct usb_function_instance *fi)
{
struct f_ecm *ecm;
struct f_ecm_opts *opts;
int status;
/* allocate and initialize one new instance */
ecm = kzalloc(sizeof(*ecm), GFP_KERNEL);
if (!ecm)
return ERR_PTR(-ENOMEM);
opts = container_of(fi, struct f_ecm_opts, func_inst);
mutex_lock(&opts->lock);
opts->refcnt++;
/* export host's Ethernet address in CDC format */
status = gether_get_host_addr_cdc(opts->net, ecm->ethaddr,
sizeof(ecm->ethaddr));
if (status < 12) {
kfree(ecm);
return ERR_PTR(-EINVAL);
}
ecm_string_defs[1].s = ecm->ethaddr;
ecm->port.ioport = netdev_priv(opts->net);
mutex_unlock(&opts->lock);
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_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;
ecm->port.func.free_func = ecm_free;
return &ecm->port.func;
}
DECLARE_USB_FUNCTION_INIT(ecm, ecm_alloc_inst, ecm_alloc);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Brownell");
#endif
......@@ -12,12 +12,15 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/etherdevice.h>
#include <linux/crc32.h>
#include <linux/slab.h>
#include "u_ether.h"
#include "u_ether_configfs.h"
#include "u_eem.h"
#define EEM_HLEN 2
......@@ -40,7 +43,7 @@ static inline struct f_eem *func_to_eem(struct usb_function *f)
/* interface descriptor: */
static struct usb_interface_descriptor eem_intf __initdata = {
static struct usb_interface_descriptor eem_intf = {
.bLength = sizeof eem_intf,
.bDescriptorType = USB_DT_INTERFACE,
......@@ -54,7 +57,7 @@ static struct usb_interface_descriptor eem_intf __initdata = {
/* full speed support: */
static struct usb_endpoint_descriptor eem_fs_in_desc __initdata = {
static struct usb_endpoint_descriptor eem_fs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
......@@ -62,7 +65,7 @@ static struct usb_endpoint_descriptor eem_fs_in_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_endpoint_descriptor eem_fs_out_desc __initdata = {
static struct usb_endpoint_descriptor eem_fs_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
......@@ -70,7 +73,7 @@ static struct usb_endpoint_descriptor eem_fs_out_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_descriptor_header *eem_fs_function[] __initdata = {
static struct usb_descriptor_header *eem_fs_function[] = {
/* CDC EEM control descriptors */
(struct usb_descriptor_header *) &eem_intf,
(struct usb_descriptor_header *) &eem_fs_in_desc,
......@@ -80,7 +83,7 @@ static struct usb_descriptor_header *eem_fs_function[] __initdata = {
/* high speed support: */
static struct usb_endpoint_descriptor eem_hs_in_desc __initdata = {
static struct usb_endpoint_descriptor eem_hs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
......@@ -89,7 +92,7 @@ static struct usb_endpoint_descriptor eem_hs_in_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor eem_hs_out_desc __initdata = {
static struct usb_endpoint_descriptor eem_hs_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
......@@ -98,7 +101,7 @@ static struct usb_endpoint_descriptor eem_hs_out_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *eem_hs_function[] __initdata = {
static struct usb_descriptor_header *eem_hs_function[] = {
/* CDC EEM control descriptors */
(struct usb_descriptor_header *) &eem_intf,
(struct usb_descriptor_header *) &eem_hs_in_desc,
......@@ -108,7 +111,7 @@ static struct usb_descriptor_header *eem_hs_function[] __initdata = {
/* super speed support: */
static struct usb_endpoint_descriptor eem_ss_in_desc __initdata = {
static struct usb_endpoint_descriptor eem_ss_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
......@@ -117,7 +120,7 @@ static struct usb_endpoint_descriptor eem_ss_in_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(1024),
};
static struct usb_endpoint_descriptor eem_ss_out_desc __initdata = {
static struct usb_endpoint_descriptor eem_ss_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
......@@ -126,7 +129,7 @@ static struct usb_endpoint_descriptor eem_ss_out_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(1024),
};
static struct usb_ss_ep_comp_descriptor eem_ss_bulk_comp_desc __initdata = {
static struct usb_ss_ep_comp_descriptor eem_ss_bulk_comp_desc = {
.bLength = sizeof eem_ss_bulk_comp_desc,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
......@@ -135,7 +138,7 @@ static struct usb_ss_ep_comp_descriptor eem_ss_bulk_comp_desc __initdata = {
/* .bmAttributes = 0, */
};
static struct usb_descriptor_header *eem_ss_function[] __initdata = {
static struct usb_descriptor_header *eem_ss_function[] = {
/* CDC EEM control descriptors */
(struct usb_descriptor_header *) &eem_intf,
(struct usb_descriptor_header *) &eem_ss_in_desc,
......@@ -242,14 +245,40 @@ static void eem_disable(struct usb_function *f)
/* EEM function driver setup/binding */
static int __init
eem_bind(struct usb_configuration *c, struct usb_function *f)
static int eem_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct f_eem *eem = func_to_eem(f);
struct usb_string *us;
int status;
struct usb_ep *ep;
struct f_eem_opts *eem_opts;
eem_opts = container_of(f->fi, struct f_eem_opts, func_inst);
/*
* in drivers/usb/gadget/configfs.c:configfs_composite_bind()
* configurations are bound in sequence with list_for_each_entry,
* in each configuration its functions are bound in sequence
* with list_for_each_entry, so we assume no race condition
* with regard to eem_opts->bound access
*/
if (!eem_opts->bound) {
mutex_lock(&eem_opts->lock);
gether_set_gadget(eem_opts->net, cdev->gadget);
status = gether_register_netdev(eem_opts->net);
mutex_unlock(&eem_opts->lock);
if (status)
return status;
eem_opts->bound = true;
}
us = usb_gstrings_attach(cdev, eem_strings,
ARRAY_SIZE(eem_string_defs));
if (IS_ERR(us))
return PTR_ERR(us);
eem_intf.iInterface = us[0].id;
/* allocate instance-specific interface IDs */
status = usb_interface_id(c, f);
if (status < 0)
......@@ -307,17 +336,6 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
return status;
}
static void
eem_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_eem *eem = func_to_eem(f);
DBG(c->cdev, "eem unbind\n");
usb_free_all_descriptors(f);
kfree(eem);
}
static void eem_cmd_complete(struct usb_ep *ep, struct usb_request *req)
{
struct sk_buff *skb = (struct sk_buff *)req->context;
......@@ -518,55 +536,124 @@ static int eem_unwrap(struct gether *port,
return status;
}
/**
* eem_bind_config - add CDC Ethernet (EEM) network link to a configuration
* @c: the configuration to support the network link
* 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 __init eem_bind_config(struct usb_configuration *c, struct eth_dev *dev)
static inline struct f_eem_opts *to_f_eem_opts(struct config_item *item)
{
struct f_eem *eem;
int status;
return container_of(to_config_group(item), struct f_eem_opts,
func_inst.group);
}
/* maybe allocate device-global string IDs */
if (eem_string_defs[0].id == 0) {
/* f_eem_item_ops */
USB_ETHERNET_CONFIGFS_ITEM(eem);
/* control interface label */
status = usb_string_id(c->cdev);
if (status < 0)
return status;
eem_string_defs[0].id = status;
eem_intf.iInterface = status;
}
/* f_eem_opts_dev_addr */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(eem);
/* f_eem_opts_host_addr */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(eem);
/* f_eem_opts_qmult */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(eem);
/* f_eem_opts_ifname */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(eem);
static struct configfs_attribute *eem_attrs[] = {
&f_eem_opts_dev_addr.attr,
&f_eem_opts_host_addr.attr,
&f_eem_opts_qmult.attr,
&f_eem_opts_ifname.attr,
NULL,
};
static struct config_item_type eem_func_type = {
.ct_item_ops = &eem_item_ops,
.ct_attrs = eem_attrs,
.ct_owner = THIS_MODULE,
};
static void eem_free_inst(struct usb_function_instance *f)
{
struct f_eem_opts *opts;
opts = container_of(f, struct f_eem_opts, func_inst);
if (opts->bound)
gether_cleanup(netdev_priv(opts->net));
else
free_netdev(opts->net);
kfree(opts);
}
static struct usb_function_instance *eem_alloc_inst(void)
{
struct f_eem_opts *opts;
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
return ERR_PTR(-ENOMEM);
mutex_init(&opts->lock);
opts->func_inst.free_func_inst = eem_free_inst;
opts->net = gether_setup_default();
if (IS_ERR(opts->net))
return ERR_CAST(opts->net);
config_group_init_type_name(&opts->func_inst.group, "", &eem_func_type);
return &opts->func_inst;
}
static void eem_free(struct usb_function *f)
{
struct f_eem *eem;
struct f_eem_opts *opts;
eem = func_to_eem(f);
opts = container_of(f->fi, struct f_eem_opts, func_inst);
kfree(eem);
mutex_lock(&opts->lock);
opts->refcnt--;
mutex_unlock(&opts->lock);
}
static void eem_unbind(struct usb_configuration *c, struct usb_function *f)
{
DBG(c->cdev, "eem unbind\n");
usb_free_all_descriptors(f);
}
struct usb_function *eem_alloc(struct usb_function_instance *fi)
{
struct f_eem *eem;
struct f_eem_opts *opts;
/* allocate and initialize one new instance */
eem = kzalloc(sizeof *eem, GFP_KERNEL);
eem = kzalloc(sizeof(*eem), GFP_KERNEL);
if (!eem)
return -ENOMEM;
return ERR_PTR(-ENOMEM);
eem->port.ioport = dev;
opts = container_of(fi, struct f_eem_opts, func_inst);
mutex_lock(&opts->lock);
opts->refcnt++;
eem->port.ioport = netdev_priv(opts->net);
mutex_unlock(&opts->lock);
eem->port.cdc_filter = DEFAULT_FILTER;
eem->port.func.name = "cdc_eem";
eem->port.func.strings = eem_strings;
/* descriptors are per-instance copies */
eem->port.func.bind = eem_bind;
eem->port.func.unbind = eem_unbind;
eem->port.func.set_alt = eem_set_alt;
eem->port.func.setup = eem_setup;
eem->port.func.disable = eem_disable;
eem->port.func.free_func = eem_free;
eem->port.wrap = eem_wrap;
eem->port.unwrap = eem_unwrap;
eem->port.header_len = EEM_HLEN;
status = usb_add_function(c, &eem->port.func);
if (status)
kfree(eem);
return status;
return &eem->port.func;
}
DECLARE_USB_FUNCTION_INIT(eem, eem_alloc_inst, eem_alloc);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Brownell");
......@@ -413,6 +413,7 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
/* Caller must hold fsg->lock */
static void wakeup_thread(struct fsg_common *common)
{
smp_wmb(); /* ensure the write of bh->state is complete */
/* Tell the main thread that something has happened */
common->thread_wakeup_needed = 1;
if (common->thread_task)
......@@ -632,6 +633,7 @@ static int sleep_thread(struct fsg_common *common)
}
__set_current_state(TASK_RUNNING);
common->thread_wakeup_needed = 0;
smp_rmb(); /* ensure the latest bh->state is visible */
return rc;
}
......@@ -2745,8 +2747,8 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
"%-8s%-16s%04x", cfg->vendor_name ?: "Linux",
/* Assume product name dependent on the first LUN */
cfg->product_name ?: (common->luns->cdrom
? "File-Stor Gadget"
: "File-CD Gadget"),
? "File-CD Gadget"
: "File-Stor Gadget"),
i);
/*
......
This diff is collapsed.
......@@ -309,23 +309,20 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct f_obex *obex = func_to_obex(f);
struct usb_string *us;
int status;
struct usb_ep *ep;
if (!can_support_obex(c))
return -EINVAL;
if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
status = usb_string_ids_tab(c->cdev, obex_string_defs);
if (status < 0)
return status;
obex_control_intf.iInterface =
obex_string_defs[OBEX_CTRL_IDX].id;
status = obex_string_defs[OBEX_DATA_IDX].id;
obex_data_nop_intf.iInterface = status;
obex_data_intf.iInterface = status;
}
us = usb_gstrings_attach(cdev, obex_strings,
ARRAY_SIZE(obex_string_defs));
if (IS_ERR(us))
return PTR_ERR(us);
obex_control_intf.iInterface = us[OBEX_CTRL_IDX].id;
obex_data_nop_intf.iInterface = us[OBEX_DATA_IDX].id;
obex_data_intf.iInterface = us[OBEX_DATA_IDX].id;
/* allocate instance-specific interface IDs, and patch descriptors */
......@@ -406,57 +403,6 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f)
return status;
}
#ifdef USBF_OBEX_INCLUDED
static void
obex_old_unbind(struct usb_configuration *c, struct usb_function *f)
{
obex_string_defs[OBEX_CTRL_IDX].id = 0;
usb_free_all_descriptors(f);
kfree(func_to_obex(f));
}
/**
* obex_bind_config - add a CDC OBEX function to a configuration
* @c: the configuration to support the CDC OBEX instance
* @port_num: /dev/ttyGS* port this interface will use
* Context: single threaded during gadget setup
*
* Returns zero on success, else negative errno.
*/
int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
{
struct f_obex *obex;
int status;
/* allocate and initialize one new instance */
obex = kzalloc(sizeof *obex, GFP_KERNEL);
if (!obex)
return -ENOMEM;
obex->port_num = port_num;
obex->port.connect = obex_connect;
obex->port.disconnect = obex_disconnect;
obex->port.func.name = "obex";
obex->port.func.strings = obex_strings;
/* descriptors are per-instance copies */
obex->port.func.bind = obex_bind;
obex->port.func.unbind = obex_old_unbind;
obex->port.func.set_alt = obex_set_alt;
obex->port.func.get_alt = obex_get_alt;
obex->port.func.disable = obex_disable;
status = usb_add_function(c, &obex->port.func);
if (status)
kfree(obex);
return status;
}
#else
static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
{
return container_of(to_config_group(item), struct f_serial_opts,
......@@ -550,7 +496,6 @@ static void obex_free(struct usb_function *f)
static void obex_unbind(struct usb_configuration *c, struct usb_function *f)
{
obex_string_defs[OBEX_CTRL_IDX].id = 0;
usb_free_all_descriptors(f);
}
......@@ -572,7 +517,6 @@ struct usb_function *obex_alloc(struct usb_function_instance *fi)
obex->port.disconnect = obex_disconnect;
obex->port.func.name = "obex";
obex->port.func.strings = obex_strings;
/* descriptors are per-instance copies */
obex->port.func.bind = obex_bind;
obex->port.func.unbind = obex_unbind;
......@@ -585,8 +529,5 @@ struct usb_function *obex_alloc(struct usb_function_instance *fi)
}
DECLARE_USB_FUNCTION_INIT(obex, obex_alloc_inst, obex_alloc);
#endif
MODULE_AUTHOR("Felipe Balbi");
MODULE_LICENSE("GPL");
......@@ -13,6 +13,7 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/netdevice.h>
......@@ -25,6 +26,7 @@
#include <linux/usb/composite.h>
#include "u_phonet.h"
#include "u_ether.h"
#define PN_MEDIA_USB 0x1B
#define MAXPACKET 512
......@@ -478,8 +480,7 @@ static void pn_disconnect(struct usb_function *f)
/*-------------------------------------------------------------------------*/
static __init
int pn_bind(struct usb_configuration *c, struct usb_function *f)
static int pn_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct usb_gadget *gadget = cdev->gadget;
......@@ -487,6 +488,27 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_ep *ep;
int status, i;
#ifndef USBF_PHONET_INCLUDED
struct f_phonet_opts *phonet_opts;
phonet_opts = container_of(f->fi, struct f_phonet_opts, func_inst);
/*
* in drivers/usb/gadget/configfs.c:configfs_composite_bind()
* configurations are bound in sequence with list_for_each_entry,
* in each configuration its functions are bound in sequence
* with list_for_each_entry, so we assume no race condition
* with regard to phonet_opts->bound access
*/
if (!phonet_opts->bound) {
gphonet_set_gadget(phonet_opts->net, gadget);
status = gphonet_register_netdev(phonet_opts->net);
if (status)
return status;
phonet_opts->bound = true;
}
#endif
/* Reserve interface IDs */
status = usb_interface_id(c, f);
if (status < 0)
......@@ -560,8 +582,98 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)
return status;
}
static void
pn_unbind(struct usb_configuration *c, struct usb_function *f)
static inline struct f_phonet_opts *to_f_phonet_opts(struct config_item *item)
{
return container_of(to_config_group(item), struct f_phonet_opts,
func_inst.group);
}
CONFIGFS_ATTR_STRUCT(f_phonet_opts);
static ssize_t f_phonet_attr_show(struct config_item *item,
struct configfs_attribute *attr,
char *page)
{
struct f_phonet_opts *opts = to_f_phonet_opts(item);
struct f_phonet_opts_attribute *f_phonet_opts_attr =
container_of(attr, struct f_phonet_opts_attribute, attr);
ssize_t ret = 0;
if (f_phonet_opts_attr->show)
ret = f_phonet_opts_attr->show(opts, page);
return ret;
}
static void phonet_attr_release(struct config_item *item)
{
struct f_phonet_opts *opts = to_f_phonet_opts(item);
usb_put_function_instance(&opts->func_inst);
}
static struct configfs_item_operations phonet_item_ops = {
.release = phonet_attr_release,
.show_attribute = f_phonet_attr_show,
};
static ssize_t f_phonet_ifname_show(struct f_phonet_opts *opts, char *page)
{
return gether_get_ifname(opts->net, page, PAGE_SIZE);
}
static struct f_phonet_opts_attribute f_phonet_ifname =
__CONFIGFS_ATTR_RO(ifname, f_phonet_ifname_show);
static struct configfs_attribute *phonet_attrs[] = {
&f_phonet_ifname.attr,
NULL,
};
static struct config_item_type phonet_func_type = {
.ct_item_ops = &phonet_item_ops,
.ct_attrs = phonet_attrs,
.ct_owner = THIS_MODULE,
};
static void phonet_free_inst(struct usb_function_instance *f)
{
struct f_phonet_opts *opts;
opts = container_of(f, struct f_phonet_opts, func_inst);
if (opts->bound)
gphonet_cleanup(opts->net);
else
free_netdev(opts->net);
kfree(opts);
}
static struct usb_function_instance *phonet_alloc_inst(void)
{
struct f_phonet_opts *opts;
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
return ERR_PTR(-ENOMEM);
opts->func_inst.free_func_inst = phonet_free_inst;
opts->net = gphonet_setup_default();
if (IS_ERR(opts->net))
return ERR_PTR(PTR_ERR(opts->net));
config_group_init_type_name(&opts->func_inst.group, "",
&phonet_func_type);
return &opts->func_inst;
}
static void phonet_free(struct usb_function *f)
{
struct f_phonet *phonet;
phonet = func_to_pn(f);
kfree(phonet);
}
static void pn_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_phonet *fp = func_to_pn(f);
int i;
......@@ -574,61 +686,72 @@ pn_unbind(struct usb_configuration *c, struct usb_function *f)
usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
usb_free_all_descriptors(f);
kfree(fp);
}
/*-------------------------------------------------------------------------*/
static struct net_device *dev;
int __init phonet_bind_config(struct usb_configuration *c)
struct usb_function *phonet_alloc(struct usb_function_instance *fi)
{
struct f_phonet *fp;
int err, size;
struct f_phonet_opts *opts;
int size;
size = sizeof(*fp) + (phonet_rxq_size * sizeof(struct usb_request *));
fp = kzalloc(size, GFP_KERNEL);
if (!fp)
return -ENOMEM;
return ERR_PTR(-ENOMEM);
opts = container_of(fi, struct f_phonet_opts, func_inst);
fp->dev = dev;
fp->dev = opts->net;
fp->function.name = "phonet";
fp->function.bind = pn_bind;
fp->function.unbind = pn_unbind;
fp->function.set_alt = pn_set_alt;
fp->function.get_alt = pn_get_alt;
fp->function.disable = pn_disconnect;
fp->function.free_func = phonet_free;
spin_lock_init(&fp->rx.lock);
err = usb_add_function(c, &fp->function);
if (err)
kfree(fp);
return err;
return &fp->function;
}
int __init gphonet_setup(struct usb_gadget *gadget)
struct net_device *gphonet_setup_default(void)
{
struct net_device *dev;
struct phonet_port *port;
int err;
/* Create net device */
BUG_ON(dev);
dev = alloc_netdev(sizeof(*port), "upnlink%d", pn_net_setup);
if (!dev)
return -ENOMEM;
return ERR_PTR(-ENOMEM);
port = netdev_priv(dev);
spin_lock_init(&port->lock);
netif_carrier_off(dev);
SET_NETDEV_DEV(dev, &gadget->dev);
err = register_netdev(dev);
if (err)
free_netdev(dev);
return err;
return dev;
}
void gphonet_set_gadget(struct net_device *net, struct usb_gadget *g)
{
SET_NETDEV_DEV(net, &g->dev);
}
int gphonet_register_netdev(struct net_device *net)
{
int status;
status = register_netdev(net);
if (status)
free_netdev(net);
return status;
}
void gphonet_cleanup(void)
void gphonet_cleanup(struct net_device *dev)
{
unregister_netdev(dev);
}
DECLARE_USB_FUNCTION_INIT(phonet, phonet_alloc_inst, phonet_alloc);
MODULE_AUTHOR("Rémi Denis-Courmont");
MODULE_LICENSE("GPL");
......@@ -17,15 +17,17 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/etherdevice.h>
#include <linux/atomic.h>
#include "u_ether.h"
#include "u_ether_configfs.h"
#include "u_rndis.h"
#include "rndis.h"
/*
* This function is an RNDIS Ethernet port -- a Microsoft protocol that's
* been promoted instead of the standard CDC Ethernet. The published RNDIS
......@@ -655,6 +657,13 @@ static void rndis_close(struct gether *geth)
/*-------------------------------------------------------------------------*/
/* Some controllers can't support RNDIS ... */
static inline bool can_support_rndis(struct usb_configuration *c)
{
/* everything else is *presumably* fine */
return true;
}
/* ethernet function driver setup/binding */
static int
......@@ -662,9 +671,41 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct f_rndis *rndis = func_to_rndis(f);
struct usb_string *us;
int status;
struct usb_ep *ep;
#ifndef USB_FRNDIS_INCLUDED
struct f_rndis_opts *rndis_opts;
if (!can_support_rndis(c))
return -EINVAL;
rndis_opts = container_of(f->fi, struct f_rndis_opts, func_inst);
/*
* in drivers/usb/gadget/configfs.c:configfs_composite_bind()
* configurations are bound in sequence with list_for_each_entry,
* in each configuration its functions are bound in sequence
* with list_for_each_entry, so we assume no race condition
* with regard to rndis_opts->bound access
*/
if (!rndis_opts->bound) {
gether_set_gadget(rndis_opts->net, cdev->gadget);
status = gether_register_netdev(rndis_opts->net);
if (status)
return status;
rndis_opts->bound = true;
}
#endif
us = usb_gstrings_attach(cdev, rndis_strings,
ARRAY_SIZE(rndis_string_defs));
if (IS_ERR(us))
return PTR_ERR(us);
rndis_control_intf.iInterface = us[0].id;
rndis_data_intf.iInterface = us[1].id;
rndis_iad_descriptor.iFunction = us[2].id;
/* allocate instance-specific interface IDs */
status = usb_interface_id(c, f);
if (status < 0)
......@@ -741,10 +782,12 @@ 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);
......@@ -787,15 +830,15 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
return status;
}
#ifdef USB_FRNDIS_INCLUDED
static void
rndis_unbind(struct usb_configuration *c, struct usb_function *f)
rndis_old_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_rndis *rndis = func_to_rndis(f);
rndis_deregister(rndis->config);
rndis_exit();
rndis_string_defs[0].id = 0;
usb_free_all_descriptors(f);
kfree(rndis->notify_req->buf);
......@@ -804,13 +847,6 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f)
kfree(rndis);
}
/* Some controllers can't support RNDIS ... */
static inline bool can_support_rndis(struct usb_configuration *c)
{
/* everything else is *presumably* fine */
return true;
}
int
rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
u32 vendorID, const char *manufacturer, struct eth_dev *dev)
......@@ -818,24 +854,6 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct f_rndis *rndis;
int status;
if (!can_support_rndis(c) || !ethaddr)
return -EINVAL;
if (rndis_string_defs[0].id == 0) {
/* ... and setup RNDIS itself */
status = rndis_init();
if (status < 0)
return status;
status = usb_string_ids_tab(c->cdev, rndis_string_defs);
if (status)
return status;
rndis_control_intf.iInterface = rndis_string_defs[0].id;
rndis_data_intf.iInterface = rndis_string_defs[1].id;
rndis_iad_descriptor.iFunction = rndis_string_defs[2].id;
}
/* allocate and initialize one new instance */
status = -ENOMEM;
rndis = kzalloc(sizeof *rndis, GFP_KERNEL);
......@@ -856,19 +874,178 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
rndis->port.unwrap = rndis_rm_hdr;
rndis->port.func.name = "rndis";
rndis->port.func.strings = rndis_strings;
/* descriptors are per-instance copies */
rndis->port.func.bind = rndis_bind;
rndis->port.func.unbind = rndis_unbind;
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) {
if (status)
kfree(rndis);
fail:
rndis_exit();
}
return status;
}
#else
void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net)
{
struct f_rndis_opts *opts;
opts = container_of(f, struct f_rndis_opts, func_inst);
if (opts->bound)
gether_cleanup(netdev_priv(opts->net));
else
free_netdev(opts->net);
opts->borrowed_net = opts->bound = true;
opts->net = net;
}
EXPORT_SYMBOL(rndis_borrow_net);
static inline struct f_rndis_opts *to_f_rndis_opts(struct config_item *item)
{
return container_of(to_config_group(item), struct f_rndis_opts,
func_inst.group);
}
/* f_rndis_item_ops */
USB_ETHERNET_CONFIGFS_ITEM(rndis);
/* f_rndis_opts_dev_addr */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(rndis);
/* f_rndis_opts_host_addr */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(rndis);
/* f_rndis_opts_qmult */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(rndis);
/* f_rndis_opts_ifname */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(rndis);
static struct configfs_attribute *rndis_attrs[] = {
&f_rndis_opts_dev_addr.attr,
&f_rndis_opts_host_addr.attr,
&f_rndis_opts_qmult.attr,
&f_rndis_opts_ifname.attr,
NULL,
};
static struct config_item_type rndis_func_type = {
.ct_item_ops = &rndis_item_ops,
.ct_attrs = rndis_attrs,
.ct_owner = THIS_MODULE,
};
static void rndis_free_inst(struct usb_function_instance *f)
{
struct f_rndis_opts *opts;
opts = container_of(f, struct f_rndis_opts, func_inst);
if (!opts->borrowed_net) {
if (opts->bound)
gether_cleanup(netdev_priv(opts->net));
else
free_netdev(opts->net);
}
kfree(opts);
}
static struct usb_function_instance *rndis_alloc_inst(void)
{
struct f_rndis_opts *opts;
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
return ERR_PTR(-ENOMEM);
mutex_init(&opts->lock);
opts->func_inst.free_func_inst = rndis_free_inst;
opts->net = gether_setup_default();
if (IS_ERR(opts->net))
return ERR_CAST(opts->net);
config_group_init_type_name(&opts->func_inst.group, "",
&rndis_func_type);
return &opts->func_inst;
}
static void rndis_free(struct usb_function *f)
{
struct f_rndis *rndis;
struct f_rndis_opts *opts;
rndis = func_to_rndis(f);
rndis_deregister(rndis->config);
opts = container_of(f->fi, struct f_rndis_opts, func_inst);
kfree(rndis);
mutex_lock(&opts->lock);
opts->refcnt--;
mutex_unlock(&opts->lock);
}
static void rndis_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_rndis *rndis = func_to_rndis(f);
usb_free_all_descriptors(f);
kfree(rndis->notify_req->buf);
usb_ep_free_request(rndis->notify, rndis->notify_req);
}
static struct usb_function *rndis_alloc(struct usb_function_instance *fi)
{
struct f_rndis *rndis;
struct f_rndis_opts *opts;
int status;
/* allocate and initialize one new instance */
rndis = kzalloc(sizeof(*rndis), GFP_KERNEL);
if (!rndis)
return ERR_PTR(-ENOMEM);
opts = container_of(fi, struct f_rndis_opts, func_inst);
mutex_lock(&opts->lock);
opts->refcnt++;
gether_get_host_addr_u8(opts->net, rndis->ethaddr);
rndis->vendorID = opts->vendor_id;
rndis->manufacturer = opts->manufacturer;
rndis->port.ioport = netdev_priv(opts->net);
mutex_unlock(&opts->lock);
/* 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_unbind;
rndis->port.func.set_alt = rndis_set_alt;
rndis->port.func.setup = rndis_setup;
rndis->port.func.disable = rndis_disable;
rndis->port.func.free_func = rndis_free;
status = rndis_register(rndis_response_available, rndis);
if (status < 0) {
kfree(rndis);
return ERR_PTR(status);
}
rndis->config = status;
return &rndis->port.func;
}
DECLARE_USB_FUNCTION_INIT(rndis, rndis_alloc_inst, rndis_alloc);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Brownell");
#endif
......@@ -12,11 +12,13 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/etherdevice.h>
#include "u_ether.h"
#include "u_ether_configfs.h"
#include "u_gether.h"
/*
* This function packages a simple "CDC Subset" Ethernet port with no real
......@@ -295,9 +297,40 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct f_gether *geth = func_to_geth(f);
struct usb_string *us;
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);
/*
* in drivers/usb/gadget/configfs.c:configfs_composite_bind()
* configurations are bound in sequence with list_for_each_entry,
* in each configuration its functions are bound in sequence
* with list_for_each_entry, so we assume no race condition
* with regard to gether_opts->bound access
*/
if (!gether_opts->bound) {
mutex_lock(&gether_opts->lock);
gether_set_gadget(gether_opts->net, cdev->gadget);
status = gether_register_netdev(gether_opts->net);
mutex_unlock(&gether_opts->lock);
if (status)
return status;
gether_opts->bound = true;
}
#endif
us = usb_gstrings_attach(cdev, geth_strings,
ARRAY_SIZE(geth_string_defs));
if (IS_ERR(us))
return PTR_ERR(us);
subset_data_intf.iInterface = us[0].id;
ether_desc.iMACAddress = us[1].id;
/* allocate instance-specific interface IDs */
status = usb_interface_id(c, f);
if (status < 0)
......@@ -360,8 +393,10 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
return status;
}
#ifdef USB_FSUBSET_INCLUDED
static void
geth_unbind(struct usb_configuration *c, struct usb_function *f)
geth_old_unbind(struct usb_configuration *c, struct usb_function *f)
{
geth_string_defs[0].id = 0;
usb_free_all_descriptors(f);
......@@ -387,18 +422,6 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct f_gether *geth;
int status;
if (!ethaddr)
return -EINVAL;
/* maybe allocate device-global string IDs */
if (geth_string_defs[0].id == 0) {
status = usb_string_ids_tab(c->cdev, geth_string_defs);
if (status < 0)
return status;
subset_data_intf.iInterface = geth_string_defs[0].id;
ether_desc.iMACAddress = geth_string_defs[1].id;
}
/* allocate and initialize one new instance */
geth = kzalloc(sizeof *geth, GFP_KERNEL);
if (!geth)
......@@ -412,9 +435,8 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
geth->port.cdc_filter = DEFAULT_FILTER;
geth->port.func.name = "cdc_subset";
geth->port.func.strings = geth_strings;
geth->port.func.bind = geth_bind;
geth->port.func.unbind = geth_unbind;
geth->port.func.unbind = geth_old_unbind;
geth->port.func.set_alt = geth_set_alt;
geth->port.func.disable = geth_disable;
......@@ -423,3 +445,129 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
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,
func_inst.group);
}
/* f_gether_item_ops */
USB_ETHERNET_CONFIGFS_ITEM(gether);
/* f_gether_opts_dev_addr */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(gether);
/* f_gether_opts_host_addr */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(gether);
/* f_gether_opts_qmult */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(gether);
/* f_gether_opts_ifname */
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(gether);
static struct configfs_attribute *gether_attrs[] = {
&f_gether_opts_dev_addr.attr,
&f_gether_opts_host_addr.attr,
&f_gether_opts_qmult.attr,
&f_gether_opts_ifname.attr,
NULL,
};
static struct config_item_type gether_func_type = {
.ct_item_ops = &gether_item_ops,
.ct_attrs = gether_attrs,
.ct_owner = THIS_MODULE,
};
static void geth_free_inst(struct usb_function_instance *f)
{
struct f_gether_opts *opts;
opts = container_of(f, struct f_gether_opts, func_inst);
if (opts->bound)
gether_cleanup(netdev_priv(opts->net));
else
free_netdev(opts->net);
kfree(opts);
}
static struct usb_function_instance *geth_alloc_inst(void)
{
struct f_gether_opts *opts;
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
return ERR_PTR(-ENOMEM);
mutex_init(&opts->lock);
opts->func_inst.free_func_inst = geth_free_inst;
opts->net = gether_setup_default();
if (IS_ERR(opts->net))
return ERR_CAST(opts->net);
config_group_init_type_name(&opts->func_inst.group, "",
&gether_func_type);
return &opts->func_inst;
}
static void geth_free(struct usb_function *f)
{
struct f_gether *eth;
eth = func_to_geth(f);
kfree(eth);
}
static void geth_unbind(struct usb_configuration *c, struct usb_function *f)
{
geth_string_defs[0].id = 0;
usb_free_all_descriptors(f);
}
static struct usb_function *geth_alloc(struct usb_function_instance *fi)
{
struct f_gether *geth;
struct f_gether_opts *opts;
int status;
/* allocate and initialize one new instance */
geth = kzalloc(sizeof(*geth), GFP_KERNEL);
if (!geth)
return ERR_PTR(-ENOMEM);
opts = container_of(fi, struct f_gether_opts, func_inst);
mutex_lock(&opts->lock);
opts->refcnt++;
/* export host's Ethernet address in CDC format */
status = gether_get_host_addr_cdc(opts->net, geth->ethaddr,
sizeof(geth->ethaddr));
if (status < 12) {
kfree(geth);
return ERR_PTR(-EINVAL);
}
geth_string_defs[1].s = geth->ethaddr;
geth->port.ioport = netdev_priv(opts->net);
mutex_unlock(&opts->lock);
geth->port.cdc_filter = DEFAULT_FILTER;
geth->port.func.name = "cdc_subset";
geth->port.func.bind = geth_bind;
geth->port.func.unbind = geth_unbind;
geth->port.func.set_alt = geth_set_alt;
geth->port.func.disable = geth_disable;
geth->port.func.free_func = geth_free;
return &geth->port.func;
}
DECLARE_USB_FUNCTION_INIT(geth, geth_alloc_inst, geth_alloc);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Brownell");
#endif
......@@ -90,6 +90,7 @@ struct uac2_req {
};
struct uac2_rtd_params {
struct snd_uac2_chip *uac2; /* parent chip */
bool ep_enabled; /* if the ep is enabled */
/* Size of the ring buffer */
size_t dma_bytes;
......@@ -168,18 +169,6 @@ struct snd_uac2_chip *pdev_to_uac2(struct platform_device *p)
return container_of(p, struct snd_uac2_chip, pdev);
}
static inline
struct snd_uac2_chip *prm_to_uac2(struct uac2_rtd_params *r)
{
struct snd_uac2_chip *uac2 = container_of(r,
struct snd_uac2_chip, c_prm);
if (&uac2->c_prm != r)
uac2 = container_of(r, struct snd_uac2_chip, p_prm);
return uac2;
}
static inline
uint num_channels(uint chanmask)
{
......@@ -204,7 +193,7 @@ agdev_iso_complete(struct usb_ep *ep, struct usb_request *req)
struct uac2_req *ur = req->context;
struct snd_pcm_substream *substream;
struct uac2_rtd_params *prm = ur->pp;
struct snd_uac2_chip *uac2 = prm_to_uac2(prm);
struct snd_uac2_chip *uac2 = prm->uac2;
/* i/f shutting down */
if (!prm->ep_enabled)
......@@ -894,7 +883,7 @@ struct cntrl_range_lay3 {
static inline void
free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep)
{
struct snd_uac2_chip *uac2 = prm_to_uac2(prm);
struct snd_uac2_chip *uac2 = prm->uac2;
int i;
prm->ep_enabled = false;
......@@ -970,6 +959,9 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
}
agdev->in_ep->driver_data = agdev;
uac2->p_prm.uac2 = uac2;
uac2->c_prm.uac2 = uac2;
hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
hs_epout_desc.wMaxPacketSize = fs_epout_desc.wMaxPacketSize;
hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
......
......@@ -156,8 +156,6 @@ static struct usb_endpoint_descriptor uvc_fs_streaming_ep __initdata = {
/* The wMaxPacketSize and bInterval values will be initialized from
* module parameters.
*/
.wMaxPacketSize = 0,
.bInterval = 0,
};
static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = {
......@@ -169,8 +167,6 @@ static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = {
/* The wMaxPacketSize and bInterval values will be initialized from
* module parameters.
*/
.wMaxPacketSize = 0,
.bInterval = 0,
};
static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = {
......@@ -183,17 +179,14 @@ static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = {
/* The wMaxPacketSize and bInterval values will be initialized from
* module parameters.
*/
.wMaxPacketSize = 0,
.bInterval = 0,
};
static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp __initdata = {
.bLength = sizeof(uvc_ss_streaming_comp),
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/* The following 3 values can be tweaked if necessary. */
.bMaxBurst = 0,
.bmAttributes = 0,
.wBytesPerInterval = cpu_to_le16(1024),
/* The bMaxBurst, bmAttributes and wBytesPerInterval values will be
* initialized from module parameters.
*/
};
static const struct usb_descriptor_header * const uvc_fs_streaming[] = {
......
This diff is collapsed.
/*
* Faraday FOTG210 USB OTG controller
*
* Copyright (C) 2013 Faraday Technology Corporation
* Author: Yuan-Hsin Chen <yhchen@faraday-tech.com>
*
* 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.
*/
#include <linux/kernel.h>
#define FOTG210_MAX_NUM_EP 5 /* ep0...ep4 */
#define FOTG210_MAX_FIFO_NUM 4 /* fifo0...fifo4 */
/* Global Mask of HC/OTG/DEV interrupt Register(0xC4) */
#define FOTG210_GMIR 0xC4
#define GMIR_INT_POLARITY 0x8 /*Active High*/
#define GMIR_MHC_INT 0x4
#define GMIR_MOTG_INT 0x2
#define GMIR_MDEV_INT 0x1
/* Device Main Control Register(0x100) */
#define FOTG210_DMCR 0x100
#define DMCR_HS_EN (1 << 6)
#define DMCR_CHIP_EN (1 << 5)
#define DMCR_SFRST (1 << 4)
#define DMCR_GOSUSP (1 << 3)
#define DMCR_GLINT_EN (1 << 2)
#define DMCR_HALF_SPEED (1 << 1)
#define DMCR_CAP_RMWAKUP (1 << 0)
/* Device Address Register(0x104) */
#define FOTG210_DAR 0x104
#define DAR_AFT_CONF (1 << 7)
/* Device Test Register(0x108) */
#define FOTG210_DTR 0x108
#define DTR_TST_CLRFF (1 << 0)
/* PHY Test Mode Selector register(0x114) */
#define FOTG210_PHYTMSR 0x114
#define PHYTMSR_TST_PKT (1 << 4)
#define PHYTMSR_TST_SE0NAK (1 << 3)
#define PHYTMSR_TST_KSTA (1 << 2)
#define PHYTMSR_TST_JSTA (1 << 1)
#define PHYTMSR_UNPLUG (1 << 0)
/* Cx configuration and FIFO Empty Status register(0x120) */
#define FOTG210_DCFESR 0x120
#define DCFESR_FIFO_EMPTY(fifo) (1 << 8 << (fifo))
#define DCFESR_CX_EMP (1 << 5)
#define DCFESR_CX_CLR (1 << 3)
#define DCFESR_CX_STL (1 << 2)
#define DCFESR_TST_PKDONE (1 << 1)
#define DCFESR_CX_DONE (1 << 0)
/* Device IDLE Counter Register(0x124) */
#define FOTG210_DICR 0x124
/* Device Mask of Interrupt Group Register (0x130) */
#define FOTG210_DMIGR 0x130
#define DMIGR_MINT_G0 (1 << 0)
/* Device Mask of Interrupt Source Group 0(0x134) */
#define FOTG210_DMISGR0 0x134
#define DMISGR0_MCX_COMEND (1 << 3)
#define DMISGR0_MCX_OUT_INT (1 << 2)
#define DMISGR0_MCX_IN_INT (1 << 1)
#define DMISGR0_MCX_SETUP_INT (1 << 0)
/* Device Mask of Interrupt Source Group 1 Register(0x138)*/
#define FOTG210_DMISGR1 0x138
#define DMISGR1_MF3_IN_INT (1 << 19)
#define DMISGR1_MF2_IN_INT (1 << 18)
#define DMISGR1_MF1_IN_INT (1 << 17)
#define DMISGR1_MF0_IN_INT (1 << 16)
#define DMISGR1_MF_IN_INT(fifo) (1 << (16 + (fifo)))
#define DMISGR1_MF3_SPK_INT (1 << 7)
#define DMISGR1_MF3_OUT_INT (1 << 6)
#define DMISGR1_MF2_SPK_INT (1 << 5)
#define DMISGR1_MF2_OUT_INT (1 << 4)
#define DMISGR1_MF1_SPK_INT (1 << 3)
#define DMISGR1_MF1_OUT_INT (1 << 2)
#define DMISGR1_MF0_SPK_INT (1 << 1)
#define DMISGR1_MF0_OUT_INT (1 << 0)
#define DMISGR1_MF_OUTSPK_INT(fifo) (0x3 << (fifo) * 2)
/* Device Mask of Interrupt Source Group 2 Register (0x13C) */
#define FOTG210_DMISGR2 0x13C
#define DMISGR2_MDMA_ERROR (1 << 8)
#define DMISGR2_MDMA_CMPLT (1 << 7)
/* Device Interrupt group Register (0x140) */
#define FOTG210_DIGR 0x140
#define DIGR_INT_G2 (1 << 2)
#define DIGR_INT_G1 (1 << 1)
#define DIGR_INT_G0 (1 << 0)
/* Device Interrupt Source Group 0 Register (0x144) */
#define FOTG210_DISGR0 0x144
#define DISGR0_CX_COMABT_INT (1 << 5)
#define DISGR0_CX_COMFAIL_INT (1 << 4)
#define DISGR0_CX_COMEND_INT (1 << 3)
#define DISGR0_CX_OUT_INT (1 << 2)
#define DISGR0_CX_IN_INT (1 << 1)
#define DISGR0_CX_SETUP_INT (1 << 0)
/* Device Interrupt Source Group 1 Register (0x148) */
#define FOTG210_DISGR1 0x148
#define DISGR1_OUT_INT(fifo) (1 << ((fifo) * 2))
#define DISGR1_SPK_INT(fifo) (1 << 1 << ((fifo) * 2))
#define DISGR1_IN_INT(fifo) (1 << 16 << (fifo))
/* Device Interrupt Source Group 2 Register (0x14C) */
#define FOTG210_DISGR2 0x14C
#define DISGR2_DMA_ERROR (1 << 8)
#define DISGR2_DMA_CMPLT (1 << 7)
#define DISGR2_RX0BYTE_INT (1 << 6)
#define DISGR2_TX0BYTE_INT (1 << 5)
#define DISGR2_ISO_SEQ_ABORT_INT (1 << 4)
#define DISGR2_ISO_SEQ_ERR_INT (1 << 3)
#define DISGR2_RESM_INT (1 << 2)
#define DISGR2_SUSP_INT (1 << 1)
#define DISGR2_USBRST_INT (1 << 0)
/* Device Receive Zero-Length Data Packet Register (0x150)*/
#define FOTG210_RX0BYTE 0x150
#define RX0BYTE_EP8 (1 << 7)
#define RX0BYTE_EP7 (1 << 6)
#define RX0BYTE_EP6 (1 << 5)
#define RX0BYTE_EP5 (1 << 4)
#define RX0BYTE_EP4 (1 << 3)
#define RX0BYTE_EP3 (1 << 2)
#define RX0BYTE_EP2 (1 << 1)
#define RX0BYTE_EP1 (1 << 0)
/* Device Transfer Zero-Length Data Packet Register (0x154)*/
#define FOTG210_TX0BYTE 0x154
#define TX0BYTE_EP8 (1 << 7)
#define TX0BYTE_EP7 (1 << 6)
#define TX0BYTE_EP6 (1 << 5)
#define TX0BYTE_EP5 (1 << 4)
#define TX0BYTE_EP4 (1 << 3)
#define TX0BYTE_EP3 (1 << 2)
#define TX0BYTE_EP2 (1 << 1)
#define TX0BYTE_EP1 (1 << 0)
/* Device IN Endpoint x MaxPacketSize Register(0x160+4*(x-1)) */
#define FOTG210_INEPMPSR(ep) (0x160 + 4 * ((ep) - 1))
#define INOUTEPMPSR_MPS(mps) ((mps) & 0x2FF)
#define INOUTEPMPSR_STL_EP (1 << 11)
#define INOUTEPMPSR_RESET_TSEQ (1 << 12)
/* Device OUT Endpoint x MaxPacketSize Register(0x180+4*(x-1)) */
#define FOTG210_OUTEPMPSR(ep) (0x180 + 4 * ((ep) - 1))
/* Device Endpoint 1~4 Map Register (0x1A0) */
#define FOTG210_EPMAP 0x1A0
#define EPMAP_FIFONO(ep, dir) \
((((ep) - 1) << ((ep) - 1) * 8) << ((dir) ? 0 : 4))
#define EPMAP_FIFONOMSK(ep, dir) \
((3 << ((ep) - 1) * 8) << ((dir) ? 0 : 4))
/* Device FIFO Map Register (0x1A8) */
#define FOTG210_FIFOMAP 0x1A8
#define FIFOMAP_DIROUT(fifo) (0x0 << 4 << (fifo) * 8)
#define FIFOMAP_DIRIN(fifo) (0x1 << 4 << (fifo) * 8)
#define FIFOMAP_BIDIR(fifo) (0x2 << 4 << (fifo) * 8)
#define FIFOMAP_NA(fifo) (0x3 << 4 << (fifo) * 8)
#define FIFOMAP_EPNO(ep) ((ep) << ((ep) - 1) * 8)
#define FIFOMAP_EPNOMSK(ep) (0xF << ((ep) - 1) * 8)
/* Device FIFO Confuguration Register (0x1AC) */
#define FOTG210_FIFOCF 0x1AC
#define FIFOCF_TYPE(type, fifo) ((type) << (fifo) * 8)
#define FIFOCF_BLK_SIN(fifo) (0x0 << (fifo) * 8 << 2)
#define FIFOCF_BLK_DUB(fifo) (0x1 << (fifo) * 8 << 2)
#define FIFOCF_BLK_TRI(fifo) (0x2 << (fifo) * 8 << 2)
#define FIFOCF_BLKSZ_512(fifo) (0x0 << (fifo) * 8 << 4)
#define FIFOCF_BLKSZ_1024(fifo) (0x1 << (fifo) * 8 << 4)
#define FIFOCF_FIFO_EN(fifo) (0x1 << (fifo) * 8 << 5)
/* Device FIFO n Instruction and Byte Count Register (0x1B0+4*n) */
#define FOTG210_FIBCR(fifo) (0x1B0 + (fifo) * 4)
#define FIBCR_BCFX 0x7FF
#define FIBCR_FFRST (1 << 12)
/* Device DMA Target FIFO Number Register (0x1C0) */
#define FOTG210_DMATFNR 0x1C0
#define DMATFNR_ACC_CXF (1 << 4)
#define DMATFNR_ACC_F3 (1 << 3)
#define DMATFNR_ACC_F2 (1 << 2)
#define DMATFNR_ACC_F1 (1 << 1)
#define DMATFNR_ACC_F0 (1 << 0)
#define DMATFNR_ACC_FN(fifo) (1 << (fifo))
#define DMATFNR_DISDMA 0
/* Device DMA Controller Parameter setting 1 Register (0x1C8) */
#define FOTG210_DMACPSR1 0x1C8
#define DMACPSR1_DMA_LEN(len) (((len) & 0xFFFF) << 8)
#define DMACPSR1_DMA_ABORT (1 << 3)
#define DMACPSR1_DMA_TYPE(dir_in) (((dir_in) ? 1 : 0) << 1)
#define DMACPSR1_DMA_START (1 << 0)
/* Device DMA Controller Parameter setting 2 Register (0x1CC) */
#define FOTG210_DMACPSR2 0x1CC
/* Device DMA Controller Parameter setting 3 Register (0x1CC) */
#define FOTG210_CXPORT 0x1D0
struct fotg210_request {
struct usb_request req;
struct list_head queue;
};
struct fotg210_ep {
struct usb_ep ep;
struct fotg210_udc *fotg210;
struct list_head queue;
unsigned stall:1;
unsigned wedged:1;
unsigned use_dma:1;
unsigned char epnum;
unsigned char type;
unsigned char dir_in;
unsigned int maxp;
const struct usb_endpoint_descriptor *desc;
};
struct fotg210_udc {
spinlock_t lock; /* protect the struct */
void __iomem *reg;
unsigned long irq_trigger;
struct usb_gadget gadget;
struct usb_gadget_driver *driver;
struct fotg210_ep *ep[FOTG210_MAX_NUM_EP];
struct usb_request *ep0_req; /* for internal request */
__le16 ep0_data;
u8 ep0_dir; /* 0/0x80 out/in */
u8 reenum; /* if re-enumeration */
};
#define gadget_to_fotg210(g) container_of((g), struct fotg210_udc, gadget)
......@@ -2589,7 +2589,7 @@ static int qe_udc_probe(struct platform_device *ofdev)
if (ret)
goto err6;
dev_set_drvdata(&ofdev->dev, udc);
platform_set_drvdata(ofdev, udc);
dev_info(udc->dev,
"%s USB controller initialized as device\n",
(udc->soc_type == PORT_QE) ? "QE" : "CPM");
......@@ -2640,7 +2640,7 @@ static int qe_udc_resume(struct platform_device *dev)
static int qe_udc_remove(struct platform_device *ofdev)
{
struct qe_udc *udc = dev_get_drvdata(&ofdev->dev);
struct qe_udc *udc = platform_get_drvdata(ofdev);
struct qe_ep *ep;
unsigned int size;
DECLARE_COMPLETION(done);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -2050,7 +2050,7 @@ static SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);
static void mv_u3d_shutdown(struct platform_device *dev)
{
struct mv_u3d *u3d = dev_get_drvdata(&dev->dev);
struct mv_u3d *u3d = platform_get_drvdata(dev);
u32 tmp;
tmp = ioread32(&u3d->op_regs->usbcmd);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment