Commit a8427018 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'usb-3.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB updates from Greg KH:
 "Here's the big USB 3.11-rc1 merge request.

  Lots of gadget and finally, chipidea driver updates (they were much
  needed), along with a new host controller driver, lots of little
  serial driver fixes, the removal of the 255 usb-serial device
  limitation, and a variety of other minor things.

  All of these have been in the linux-next releases for a while"

* tag 'usb-3.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (254 commits)
  usb: musb: omap2430: make it compile again
  usb: chipidea: ci_hdrc_imx: access phy via private data
  xhci: Add missing unlocks on error paths
  USB: option,qcserial: move Novatel Gobi1K IDs to qcserial
  ehci-atmel.c: prepare clk before calling enable
  USB: ohci-at91: prepare clk before calling enable
  USB: HWA: fix device probe failure
  wusbcore: add entries in Documentation/ABI for new wusbhc sysfs attributes
  wusbcore: add sysfs attribute for retry count
  wusbcore: add sysfs attribute for DNTS count and interval
  usb: chipidea: drop "13xxx" infix
  usb: phy: tegra: remove duplicated include from phy-tegra-usb.c
  usb: host: xhci-plat: release mem region while removing module
  usbmisc_imx: allow autoloading on according to dt ids
  usb: fix build error without CONFIG_USB_PHY
  usb: check usb_hub_to_struct_hub() return value
  xhci: check for failed dma pool allocation
  usb: gadget: f_subset: fix missing unlock on error in geth_alloc()
  usb: gadget: f_ncm: fix missing unlock on error in ncm_alloc()
  usb: gadget: f_ecm: fix missing unlock on error in ecm_alloc()
  ...
parents bcd7351e 3a0ddc71
What: /config/usb-gadget
Date: Jun 2013
KenelVersion: 3.11
Description:
This group contains sub-groups corresponding to created
USB gadgets.
What: /config/usb-gadget/gadget
Date: Jun 2013
KenelVersion: 3.11
Description:
The attributes of a gadget:
UDC - bind a gadget to UDC/unbind a gadget;
write UDC's name found in /sys/class/udc/*
to bind a gadget, empty string "" to unbind.
bDeviceClass - USB device class code
bDeviceSubClass - USB device subclass code
bDeviceProtocol - USB device protocol code
bMaxPacketSize0 - maximum endpoint 0 packet size
bcdDevice - bcd device release number
bcdUSB - bcd USB specification version number
idProduct - product ID
idVendor - vendor ID
What: /config/usb-gadget/gadget/configs
Date: Jun 2013
KenelVersion: 3.11
Description:
This group contains a USB gadget's configurations
What: /config/usb-gadget/gadget/configs/config
Date: Jun 2013
KernelVersion: 3.11
Description:
The attributes of a configuration:
bmAttributes - configuration characteristics
MaxPower - maximum power consumption from the bus
What: /config/usb-gadget/gadget/configs/config/strings
Date: Jun 2013
KernelVersion: 3.11
Description:
This group contains subdirectories for language-specific
strings for this configuration.
What: /config/usb-gadget/gadget/configs/config/strings/language
Date: Jun 2013
KernelVersion: 3.11
Description:
The attributes:
configuration - configuration description
What: /config/usb-gadget/gadget/functions
Date: Jun 2013
KenelVersion: 3.11
Description:
This group contains functions available to this USB gadget.
What: /config/usb-gadget/gadget/strings
Date: Jun 2013
KenelVersion: 3.11
Description:
This group contains subdirectories for language-specific
strings for this gadget.
What: /config/usb-gadget/gadget/strings/language
Date: Jun 2013
KenelVersion: 3.11
Description:
The attributes:
serialnumber - gadget's serial number (string)
product - gadget's product description
manufacturer - gadget's manufacturer description
What: /config/usb-gadget/gadget/functions/acm.name
Date: Jun 2013
KenelVersion: 3.11
Description:
This item contains just one readonly attribute: port_num.
It contains the port number of the /dev/ttyGS<n> device
associated with acm function's instance "name".
What: /config/usb-gadget/gadget/functions/ecm.name
Date: Jun 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/eem.name
Date: Jun 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/ncm.name
Date: Jun 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/obex.name
Date: Jun 2013
KenelVersion: 3.11
Description:
This item contains just one readonly attribute: port_num.
It contains the port number of the /dev/ttyGS<n> device
associated with obex function's instance "name".
What: /config/usb-gadget/gadget/functions/phonet.name
Date: Jun 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: Jun 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/gser.name
Date: Jun 2013
KenelVersion: 3.11
Description:
This item contains just one readonly attribute: port_num.
It contains the port number of the /dev/ttyGS<n> device
associated with gser function's instance "name".
What: /config/usb-gadget/gadget/functions/geth.name
Date: Jun 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
......@@ -236,3 +236,30 @@ Description:
This attribute is to expose these information to user space.
The file will read "hotplug", "wired" and "not used" if the
information is available, and "unknown" otherwise.
What: /sys/bus/usb/devices/.../power/usb2_lpm_l1_timeout
Date: May 2013
Contact: Mathias Nyman <mathias.nyman@linux.intel.com>
Description:
USB 2.0 devices may support hardware link power management (LPM)
L1 sleep state. The usb2_lpm_l1_timeout attribute allows
tuning the timeout for L1 inactivity timer (LPM timer), e.g.
needed inactivity time before host requests the device to go to L1 sleep.
Useful for power management tuning.
Supported values are 0 - 65535 microseconds.
What: /sys/bus/usb/devices/.../power/usb2_lpm_besl
Date: May 2013
Contact: Mathias Nyman <mathias.nyman@linux.intel.com>
Description:
USB 2.0 devices that support hardware link power management (LPM)
L1 sleep state now use a best effort service latency value (BESL) to
indicate the best effort to resumption of service to the device after the
initiation of the resume event.
If the device does not have a preferred besl value then the host can select
one instead. This usb2_lpm_besl attribute allows to tune the host selected besl
value in order to tune power saving and service latency.
Supported values are 0 - 15.
More information on how besl values map to microseconds can be found in
USB 2.0 ECN Errata for Link Power Management, section 4.10)
......@@ -36,3 +36,22 @@ Description:
Refer to [ECMA-368] section 10.3.1.1 for the value to
use.
What: /sys/class/uwb_rc/uwbN/wusbhc/wusb_dnts
Date: June 2013
KernelVersion: 3.11
Contact: Thomas Pugliese <thomas.pugliese@gmail.com>
Description:
The device notification time slot (DNTS) count and inverval in
milliseconds that the WUSB host should use. This controls how
often the devices will have the opportunity to send
notifications to the host.
What: /sys/class/uwb_rc/uwbN/wusbhc/wusb_retry_count
Date: June 2013
KernelVersion: 3.11
Contact: Thomas Pugliese <thomas.pugliese@gmail.com>
Description:
The number of retries that the WUSB host should attempt
before reporting an error for a bus transaction. The range of
valid values is [0..15], where 0 indicates infinite retries.
......@@ -5,6 +5,12 @@ Required properties:
- reg: Should contain registers location and length
- interrupts: Should contain controller interrupt
Recommended properies:
- phy_type: the type of the phy connected to the core. Should be one
of "utmi", "utmi_wide", "ulpi", "serial" or "hsic". Without this
property the PORTSC register won't be touched
- dr_mode: One of "host", "peripheral" or "otg". Defaults to "otg"
Optional properties:
- fsl,usbphy: phandler of usb phy that connects to the only one port
- fsl,usbmisc: phandler of non-core register device, with one argument
......
......@@ -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
......@@ -4,6 +4,10 @@ Required properties:
- compatible: Should be "smsc,usb3503".
- reg: Specifies the i2c slave address, it should be 0x08.
- connect-gpios: Should specify GPIO for connect.
- disabled-ports: Should specify the ports unused.
'1' or '2' or '3' are availe for this property to describe the port
number. 1~3 property values are possible to be desribed.
Do not describe this property if all ports have to be enabled.
- intn-gpios: Should specify GPIO for interrupt.
- reset-gpios: Should specify GPIO for reset.
- initial-mode: Should specify initial mode.
......@@ -14,6 +18,7 @@ Examples:
compatible = "smsc,usb3503";
reg = <0x08>;
connect-gpios = <&gpx3 0 1>;
disabled-ports = <2 3>;
intn-gpios = <&gpx3 4 1>;
reset-gpios = <&gpx3 5 1>;
initial-mode = <1>;
......
This diff is collapsed.
......@@ -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 {
......
......@@ -873,7 +873,7 @@ static int qt_open(struct tty_struct *tty,
result = qt_get_device(serial, &port0->DeviceData);
/* Port specific setups */
result = qt_open_channel(serial, port->number, &ChannelData);
result = qt_open_channel(serial, port->port_number, &ChannelData);
if (result < 0) {
dev_dbg(&port->dev, "qt_open_channel failed\n");
return result;
......@@ -888,7 +888,7 @@ static int qt_open(struct tty_struct *tty,
(SERIAL_MSR_CTS | SERIAL_MSR_DSR | SERIAL_MSR_RI | SERIAL_MSR_CD);
/* Set Baud rate to default and turn off (default)flow control here */
result = qt_setuart(serial, port->number, DEFAULT_DIVISOR, DEFAULT_LCR);
result = qt_setuart(serial, port->port_number, DEFAULT_DIVISOR, DEFAULT_LCR);
if (result < 0) {
dev_dbg(&port->dev, "qt_setuart failed\n");
return result;
......@@ -906,8 +906,7 @@ static int qt_open(struct tty_struct *tty,
qt_submit_urb_from_open(serial, port);
}
dev_dbg(&port->dev, "port number is %d\n", port->number);
dev_dbg(&port->dev, "serial number is %d\n", port->serial->minor);
dev_dbg(&port->dev, "minor number is %d\n", port->minor);
dev_dbg(&port->dev,
"Bulkin endpoint is %d\n", port->bulk_in_endpointAddress);
dev_dbg(&port->dev,
......@@ -1003,7 +1002,7 @@ static void qt_close(struct usb_serial_port *port)
status = 0;
tty = tty_port_tty_get(&port->port);
index = tty->index - serial->minor;
index = port->port_number;
qt_port = qt_get_port_private(port);
port0 = qt_get_port_private(serial->port[0]);
......@@ -1022,14 +1021,11 @@ static void qt_close(struct usb_serial_port *port)
/* Close uart channel */
status = qt_close_channel(serial, index);
if (status < 0)
dev_dbg(&port->dev,
"%s - port %d qt_close_channel failed.\n",
__func__, port->number);
dev_dbg(&port->dev, "%s - qt_close_channel failed.\n", __func__);
port0->open_ports--;
dev_dbg(&port->dev, "qt_num_open_ports in close%d:in port%d\n",
port0->open_ports, port->number);
dev_dbg(&port->dev, "qt_num_open_ports in close%d\n", port0->open_ports);
if (port0->open_ports == 0) {
if (serial->port[0]->interrupt_in_urb) {
......@@ -1133,12 +1129,11 @@ static int qt_ioctl(struct tty_struct *tty,
{
struct usb_serial_port *port = tty->driver_data;
struct quatech_port *qt_port = qt_get_port_private(port);
struct usb_serial *serial = get_usb_serial(port, __func__);
unsigned int index;
dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd);
index = tty->index - serial->minor;
index = port->port_number;
if (cmd == TIOCMIWAIT) {
while (qt_port != NULL) {
......@@ -1169,8 +1164,7 @@ static int qt_ioctl(struct tty_struct *tty,
return 0;
}
dev_dbg(&port->dev, "%s -No ioctl for that one. port = %d\n",
__func__, port->number);
dev_dbg(&port->dev, "%s -No ioctl for that one.\n", __func__);
return -ENOIOCTLCMD;
}
......@@ -1185,7 +1179,7 @@ static void qt_set_termios(struct tty_struct *tty,
int baud, divisor, remainder;
int status;
index = tty->index - port->serial->minor;
index = port->port_number;
switch (cflag & CSIZE) {
case CS5:
......@@ -1245,8 +1239,7 @@ static void qt_set_termios(struct tty_struct *tty,
/* Now determine flow control */
if (cflag & CRTSCTS) {
dev_dbg(&port->dev, "%s - Enabling HW flow control port %d\n",
__func__, port->number);
dev_dbg(&port->dev, "%s - Enabling HW flow control\n", __func__);
/* Enable RTS/CTS flow control */
status = BoxSetHW_FlowCtrl(port->serial, index, 1);
......@@ -1258,8 +1251,7 @@ static void qt_set_termios(struct tty_struct *tty,
} else {
/* Disable RTS/CTS flow control */
dev_dbg(&port->dev,
"%s - disabling HW flow control port %d\n",
__func__, port->number);
"%s - disabling HW flow control\n", __func__);
status = BoxSetHW_FlowCtrl(port->serial, index, 0);
if (status < 0) {
......@@ -1303,7 +1295,7 @@ static void qt_break(struct tty_struct *tty, int break_state)
u16 index, onoff;
unsigned int result;
index = tty->index - serial->minor;
index = port->port_number;
qt_port = qt_get_port_private(port);
......@@ -1332,7 +1324,7 @@ static inline int qt_real_tiocmget(struct tty_struct *tty,
int status;
unsigned int index;
index = tty->index - serial->minor;
index = port->port_number;
status =
BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr);
if (status >= 0) {
......@@ -1371,7 +1363,7 @@ static inline int qt_real_tiocmset(struct tty_struct *tty,
int status;
unsigned int index;
index = tty->index - serial->minor;
index = port->port_number;
status =
BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr);
if (status < 0)
......
......@@ -2,59 +2,15 @@
# USB device configuration
#
# many non-PCI SOC chips embed OHCI
# These are unused now, remove them once they are no longer selected
config USB_ARCH_HAS_OHCI
boolean
# ARM:
default y if SA1111
default y if ARCH_OMAP
default y if ARCH_S3C24XX
default y if PXA27x
default y if PXA3xx
default y if ARCH_EP93XX
default y if ARCH_AT91
default y if MFD_TC6393XB
default y if ARCH_W90X900
default y if ARCH_DAVINCI_DA8XX
default y if ARCH_CNS3XXX
default y if PLAT_SPEAR
default y if ARCH_EXYNOS
# PPC:
default y if STB03xxx
default y if PPC_MPC52xx
# MIPS:
default y if MIPS_ALCHEMY
default y if MACH_JZ4740
# more:
default PCI
# some non-PCI hcds implement EHCI
bool
config USB_ARCH_HAS_EHCI
boolean
default y if FSL_SOC
default y if PPC_MPC512x
default y if ARCH_IXP4XX
default y if ARCH_W90X900
default y if ARCH_AT91
default y if ARCH_MXC
default y if ARCH_MXS
default y if ARCH_OMAP3
default y if ARCH_CNS3XXX
default y if ARCH_VT8500
default y if PLAT_SPEAR
default y if PLAT_S5P
default y if ARCH_MSM
default y if MICROBLAZE
default y if SPARC_LEON
default y if ARCH_MMP
default y if MACH_LOONGSON1
default y if PLAT_ORION
default PCI
# some non-PCI HCDs implement xHCI
bool
config USB_ARCH_HAS_XHCI
boolean
default PCI
bool
menuconfig USB_SUPPORT
bool "USB support"
......@@ -71,19 +27,8 @@ config USB_COMMON
default y
depends on USB || USB_GADGET
# Host-side USB depends on having a host controller
# NOTE: dummy_hcd is always an option, but it's ignored here ...
# NOTE: SL-811 option should be board-specific ...
config USB_ARCH_HAS_HCD
boolean
default y if USB_ARCH_HAS_OHCI
default y if USB_ARCH_HAS_EHCI
default y if USB_ARCH_HAS_XHCI
default y if PCMCIA && !M32R # sl811_cs
default y if ARM # SL-811
default y if BLACKFIN # SL-811
default y if SUPERH # r8a66597-hcd
default PCI
def_bool y
# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
config USB
......
......@@ -25,6 +25,7 @@ obj-$(CONFIG_USB_HWA_HCD) += host/
obj-$(CONFIG_USB_ISP1760_HCD) += host/
obj-$(CONFIG_USB_IMX21_HCD) += host/
obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/
obj-$(CONFIG_USB_FUSBH200_HCD) += host/
obj-$(CONFIG_USB_C67X00_HCD) += c67x00/
......
......@@ -12,15 +12,15 @@ if USB_CHIPIDEA
config USB_CHIPIDEA_UDC
bool "ChipIdea device controller"
depends on USB_GADGET=y || USB_GADGET=USB_CHIPIDEA
depends on USB_GADGET=y || USB_CHIPIDEA=m
help
Say Y here to enable device controller functionality of the
ChipIdea driver.
config USB_CHIPIDEA_HOST
bool "ChipIdea host controller"
depends on USB=y || USB=USB_CHIPIDEA
depends on USB_EHCI_HCD=y
depends on USB=y
depends on USB_EHCI_HCD=y || USB_CHIPIDEA=m
select USB_EHCI_ROOT_HUB_TT
help
Say Y here to enable host controller functionality of the
......
......@@ -9,13 +9,13 @@ ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o
# Glue/Bridge layers go here
obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_msm.o
obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_msm.o
# PCI doesn't provide stubs, need to check
ifneq ($(CONFIG_PCI),)
obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_pci.o
obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_pci.o
endif
ifneq ($(CONFIG_OF_DEVICE),)
obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_imx.o usbmisc_imx.o
obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_imx.o usbmisc_imx.o
endif
......@@ -48,10 +48,24 @@
#define PORTSC_SUSP BIT(7)
#define PORTSC_HSP BIT(9)
#define PORTSC_PTC (0x0FUL << 16)
/* PTS and PTW for non lpm version only */
#define PORTSC_PTS(d) \
((((d) & 0x3) << 30) | (((d) & 0x4) ? BIT(25) : 0))
#define PORTSC_PTW BIT(28)
#define PORTSC_STS BIT(29)
/* DEVLC */
#define DEVLC_PSPD (0x03UL << 25)
#define DEVLC_PSPD_HS (0x02UL << 25)
#define DEVLC_PSPD_HS (0x02UL << 25)
#define DEVLC_PTW BIT(27)
#define DEVLC_STS BIT(28)
#define DEVLC_PTS(d) (((d) & 0x7) << 29)
/* Encoding for DEVLC_PTS and PORTSC_PTS */
#define PTS_UTMI 0
#define PTS_ULPI 2
#define PTS_SERIAL 3
#define PTS_HSIC 4
/* OTGSC */
#define OTGSC_IDPU BIT(5)
......
......@@ -22,14 +22,14 @@
* DEFINE
*****************************************************************************/
#define TD_PAGE_COUNT 5
#define CI13XXX_PAGE_SIZE 4096ul /* page size for TD's */
#define CI_HDRC_PAGE_SIZE 4096ul /* page size for TD's */
#define ENDPT_MAX 32
/******************************************************************************
* STRUCTURES
*****************************************************************************/
/**
* struct ci13xxx_ep - endpoint representation
* struct ci_hw_ep - endpoint representation
* @ep: endpoint structure for gadget drivers
* @dir: endpoint direction (TX/RX)
* @num: endpoint number
......@@ -41,7 +41,7 @@
* @lock: pointer to controller's spinlock
* @td_pool: pointer to controller's TD pool
*/
struct ci13xxx_ep {
struct ci_hw_ep {
struct usb_ep ep;
u8 dir;
u8 num;
......@@ -49,15 +49,16 @@ struct ci13xxx_ep {
char name[16];
struct {
struct list_head queue;
struct ci13xxx_qh *ptr;
struct ci_hw_qh *ptr;
dma_addr_t dma;
} qh;
int wedge;
/* global resources */
struct ci13xxx *ci;
struct ci_hdrc *ci;
spinlock_t *lock;
struct dma_pool *td_pool;
struct td_node *pending_td;
};
enum ci_role {
......@@ -74,9 +75,9 @@ enum ci_role {
* name: role name string (host/gadget)
*/
struct ci_role_driver {
int (*start)(struct ci13xxx *);
void (*stop)(struct ci13xxx *);
irqreturn_t (*irq)(struct ci13xxx *);
int (*start)(struct ci_hdrc *);
void (*stop)(struct ci_hdrc *);
irqreturn_t (*irq)(struct ci_hdrc *);
const char *name;
};
......@@ -101,7 +102,7 @@ struct hw_bank {
};
/**
* struct ci13xxx - chipidea device representation
* struct ci_hdrc - chipidea device representation
* @dev: pointer to parent device
* @lock: access synchronization
* @hw_bank: hardware register mapping
......@@ -116,7 +117,7 @@ struct hw_bank {
* @gadget: device side representation for peripheral controller
* @driver: gadget driver
* @hw_ep_max: total number of endpoints supported by hardware
* @ci13xxx_ep: array of endpoints
* @ci_hw_ep: array of endpoints
* @ep0_dir: ep0 direction
* @ep0out: pointer to ep0 OUT endpoint
* @ep0in: pointer to ep0 IN endpoint
......@@ -132,7 +133,7 @@ struct hw_bank {
* @hcd: pointer to usb_hcd for ehci host driver
* @debugfs: root dentry for this controller in debugfs
*/
struct ci13xxx {
struct ci_hdrc {
struct device *dev;
spinlock_t lock;
struct hw_bank hw_bank;
......@@ -149,9 +150,9 @@ struct ci13xxx {
struct usb_gadget gadget;
struct usb_gadget_driver *driver;
unsigned hw_ep_max;
struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX];
struct ci_hw_ep ci_hw_ep[ENDPT_MAX];
u32 ep0_dir;
struct ci13xxx_ep *ep0out, *ep0in;
struct ci_hw_ep *ep0out, *ep0in;
struct usb_request *status;
bool setaddr;
......@@ -160,7 +161,7 @@ struct ci13xxx {
u8 suspended;
u8 test_mode;
struct ci13xxx_platform_data *platdata;
struct ci_hdrc_platform_data *platdata;
int vbus_active;
/* FIXME: some day, we'll not use global phy */
bool global_phy;
......@@ -169,13 +170,13 @@ struct ci13xxx {
struct dentry *debugfs;
};
static inline struct ci_role_driver *ci_role(struct ci13xxx *ci)
static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci)
{
BUG_ON(ci->role >= CI_ROLE_END || !ci->roles[ci->role]);
return ci->roles[ci->role];
}
static inline int ci_role_start(struct ci13xxx *ci, enum ci_role role)
static inline int ci_role_start(struct ci_hdrc *ci, enum ci_role role)
{
int ret;
......@@ -191,7 +192,7 @@ static inline int ci_role_start(struct ci13xxx *ci, enum ci_role role)
return ret;
}
static inline void ci_role_stop(struct ci13xxx *ci)
static inline void ci_role_stop(struct ci_hdrc *ci)
{
enum ci_role role = ci->role;
......@@ -210,7 +211,7 @@ static inline void ci_role_stop(struct ci13xxx *ci)
#define REG_BITS (32)
/* register indices */
enum ci13xxx_regs {
enum ci_hw_regs {
CAP_CAPLENGTH,
CAP_HCCPARAMS,
CAP_DCCPARAMS,
......@@ -242,7 +243,7 @@ enum ci13xxx_regs {
*
* This function returns register contents
*/
static inline u32 hw_read(struct ci13xxx *ci, enum ci13xxx_regs reg, u32 mask)
static inline u32 hw_read(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask)
{
return ioread32(ci->hw_bank.regmap[reg]) & mask;
}
......@@ -253,7 +254,7 @@ static inline u32 hw_read(struct ci13xxx *ci, enum ci13xxx_regs reg, u32 mask)
* @mask: bitfield mask
* @data: new value
*/
static inline void hw_write(struct ci13xxx *ci, enum ci13xxx_regs reg,
static inline void hw_write(struct ci_hdrc *ci, enum ci_hw_regs reg,
u32 mask, u32 data)
{
if (~mask)
......@@ -270,7 +271,7 @@ static inline void hw_write(struct ci13xxx *ci, enum ci13xxx_regs reg,
*
* This function returns register contents
*/
static inline u32 hw_test_and_clear(struct ci13xxx *ci, enum ci13xxx_regs reg,
static inline u32 hw_test_and_clear(struct ci_hdrc *ci, enum ci_hw_regs reg,
u32 mask)
{
u32 val = ioread32(ci->hw_bank.regmap[reg]) & mask;
......@@ -287,7 +288,7 @@ static inline u32 hw_test_and_clear(struct ci13xxx *ci, enum ci13xxx_regs reg,
*
* This function returns register contents
*/
static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg,
static inline u32 hw_test_and_write(struct ci_hdrc *ci, enum ci_hw_regs reg,
u32 mask, u32 data)
{
u32 val = hw_read(ci, reg, ~0);
......@@ -296,10 +297,10 @@ static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg,
return (val & mask) >> __ffs(mask);
}
int hw_device_reset(struct ci13xxx *ci, u32 mode);
int hw_device_reset(struct ci_hdrc *ci, u32 mode);
int hw_port_test_set(struct ci13xxx *ci, u8 mode);
int hw_port_test_set(struct ci_hdrc *ci, u8 mode);
u8 hw_port_test_get(struct ci13xxx *ci);
u8 hw_port_test_get(struct ci_hdrc *ci);
#endif /* __DRIVERS_USB_CHIPIDEA_CI_H */
......@@ -20,16 +20,14 @@
#include <linux/usb/chipidea.h>
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/pinctrl/consumer.h>
#include "ci.h"
#include "ci13xxx_imx.h"
#include "ci_hdrc_imx.h"
#define pdev_to_phy(pdev) \
((struct usb_phy *)platform_get_drvdata(pdev))
struct ci13xxx_imx_data {
struct device_node *phy_np;
struct ci_hdrc_imx_data {
struct usb_phy *phy;
struct platform_device *ci_pdev;
struct clk *clk;
......@@ -88,22 +86,17 @@ EXPORT_SYMBOL_GPL(usbmisc_get_init_data);
/* End of common functions shared by usbmisc drivers*/
static struct ci13xxx_platform_data ci13xxx_imx_platdata = {
.name = "ci13xxx_imx",
.flags = CI13XXX_REQUIRE_TRANSCEIVER |
CI13XXX_PULLUP_ON_VBUS |
CI13XXX_DISABLE_STREAMING,
.capoffset = DEF_CAPOFFSET,
};
static int ci13xxx_imx_probe(struct platform_device *pdev)
static int ci_hdrc_imx_probe(struct platform_device *pdev)
{
struct ci13xxx_imx_data *data;
struct platform_device *plat_ci, *phy_pdev;
struct device_node *phy_np;
struct ci_hdrc_imx_data *data;
struct ci_hdrc_platform_data pdata = {
.name = "ci_hdrc_imx",
.capoffset = DEF_CAPOFFSET,
.flags = CI_HDRC_REQUIRE_TRANSCEIVER |
CI_HDRC_PULLUP_ON_VBUS |
CI_HDRC_DISABLE_STREAMING,
};
struct resource *res;
struct regulator *reg_vbus;
struct pinctrl *pinctrl;
int ret;
if (of_find_property(pdev->dev.of_node, "fsl,usbmisc", NULL)
......@@ -112,7 +105,7 @@ static int ci13xxx_imx_probe(struct platform_device *pdev)
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data) {
dev_err(&pdev->dev, "Failed to allocate CI13xxx-IMX data!\n");
dev_err(&pdev->dev, "Failed to allocate ci_hdrc-imx data!\n");
return -ENOMEM;
}
......@@ -122,11 +115,6 @@ static int ci13xxx_imx_probe(struct platform_device *pdev)
return -ENOENT;
}
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
if (IS_ERR(pinctrl))
dev_warn(&pdev->dev, "pinctrl get/select failed, err=%ld\n",
PTR_ERR(pinctrl));
data->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(data->clk)) {
dev_err(&pdev->dev,
......@@ -141,37 +129,33 @@ static int ci13xxx_imx_probe(struct platform_device *pdev)
return ret;
}
phy_np = of_parse_phandle(pdev->dev.of_node, "fsl,usbphy", 0);
if (phy_np) {
data->phy_np = phy_np;
phy_pdev = of_find_device_by_node(phy_np);
if (phy_pdev) {
struct usb_phy *phy;
phy = pdev_to_phy(phy_pdev);
if (phy &&
try_module_get(phy_pdev->dev.driver->owner)) {
usb_phy_init(phy);
data->phy = phy;
}
data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0);
if (!IS_ERR(data->phy)) {
ret = usb_phy_init(data->phy);
if (ret) {
dev_err(&pdev->dev, "unable to init phy: %d\n", ret);
goto err_clk;
}
} else if (PTR_ERR(data->phy) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto err_clk;
}
/* we only support host now, so enable vbus here */
reg_vbus = devm_regulator_get(&pdev->dev, "vbus");
if (!IS_ERR(reg_vbus)) {
ret = regulator_enable(reg_vbus);
data->reg_vbus = devm_regulator_get(&pdev->dev, "vbus");
if (!IS_ERR(data->reg_vbus)) {
ret = regulator_enable(data->reg_vbus);
if (ret) {
dev_err(&pdev->dev,
"Failed to enable vbus regulator, err=%d\n",
ret);
goto put_np;
goto err_clk;
}
data->reg_vbus = reg_vbus;
} else {
reg_vbus = NULL;
data->reg_vbus = NULL;
}
ci13xxx_imx_platdata.phy = data->phy;
pdata.phy = data->phy;
if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
......@@ -187,11 +171,11 @@ static int ci13xxx_imx_probe(struct platform_device *pdev)
}
}
plat_ci = ci13xxx_add_device(&pdev->dev,
data->ci_pdev = ci_hdrc_add_device(&pdev->dev,
pdev->resource, pdev->num_resources,
&ci13xxx_imx_platdata);
if (IS_ERR(plat_ci)) {
ret = PTR_ERR(plat_ci);
&pdata);
if (IS_ERR(data->ci_pdev)) {
ret = PTR_ERR(data->ci_pdev);
dev_err(&pdev->dev,
"Can't register ci_hdrc platform device, err=%d\n",
ret);
......@@ -203,11 +187,10 @@ static int ci13xxx_imx_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev,
"usbmisc post failed, ret=%d\n", ret);
goto put_np;
goto disable_device;
}
}
data->ci_pdev = plat_ci;
platform_set_drvdata(pdev, data);
pm_runtime_no_callbacks(&pdev->dev);
......@@ -215,22 +198,22 @@ static int ci13xxx_imx_probe(struct platform_device *pdev)
return 0;
disable_device:
ci_hdrc_remove_device(data->ci_pdev);
err:
if (reg_vbus)
regulator_disable(reg_vbus);
put_np:
if (phy_np)
of_node_put(phy_np);
if (data->reg_vbus)
regulator_disable(data->reg_vbus);
err_clk:
clk_disable_unprepare(data->clk);
return ret;
}
static int ci13xxx_imx_remove(struct platform_device *pdev)
static int ci_hdrc_imx_remove(struct platform_device *pdev)
{
struct ci13xxx_imx_data *data = platform_get_drvdata(pdev);
struct ci_hdrc_imx_data *data = platform_get_drvdata(pdev);
pm_runtime_disable(&pdev->dev);
ci13xxx_remove_device(data->ci_pdev);
ci_hdrc_remove_device(data->ci_pdev);
if (data->reg_vbus)
regulator_disable(data->reg_vbus);
......@@ -240,35 +223,31 @@ static int ci13xxx_imx_remove(struct platform_device *pdev)
module_put(data->phy->dev->driver->owner);
}
of_node_put(data->phy_np);
clk_disable_unprepare(data->clk);
platform_set_drvdata(pdev, NULL);
return 0;
}
static const struct of_device_id ci13xxx_imx_dt_ids[] = {
static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
{ .compatible = "fsl,imx27-usb", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ci13xxx_imx_dt_ids);
MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
static struct platform_driver ci13xxx_imx_driver = {
.probe = ci13xxx_imx_probe,
.remove = ci13xxx_imx_remove,
static struct platform_driver ci_hdrc_imx_driver = {
.probe = ci_hdrc_imx_probe,
.remove = ci_hdrc_imx_remove,
.driver = {
.name = "imx_usb",
.owner = THIS_MODULE,
.of_match_table = ci13xxx_imx_dt_ids,
.of_match_table = ci_hdrc_imx_dt_ids,
},
};
module_platform_driver(ci13xxx_imx_driver);
module_platform_driver(ci_hdrc_imx_driver);
MODULE_ALIAS("platform:imx-usb");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("CI13xxx i.MX USB binding");
MODULE_DESCRIPTION("CI HDRC i.MX USB binding");
MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
......@@ -17,19 +17,19 @@
#define MSM_USB_BASE (ci->hw_bank.abs)
static void ci13xxx_msm_notify_event(struct ci13xxx *ci, unsigned event)
static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
{
struct device *dev = ci->gadget.dev.parent;
int val;
switch (event) {
case CI13XXX_CONTROLLER_RESET_EVENT:
dev_dbg(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n");
case CI_HDRC_CONTROLLER_RESET_EVENT:
dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
writel(0, USB_AHBBURST);
writel(0, USB_AHBMODE);
break;
case CI13XXX_CONTROLLER_STOPPED_EVENT:
dev_dbg(dev, "CI13XXX_CONTROLLER_STOPPED_EVENT received\n");
case CI_HDRC_CONTROLLER_STOPPED_EVENT:
dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n");
/*
* Put the transceiver in non-driving mode. Otherwise host
* may not detect soft-disconnection.
......@@ -40,32 +40,32 @@ static void ci13xxx_msm_notify_event(struct ci13xxx *ci, unsigned event)
usb_phy_io_write(ci->transceiver, val, ULPI_FUNC_CTRL);
break;
default:
dev_dbg(dev, "unknown ci13xxx event\n");
dev_dbg(dev, "unknown ci_hdrc event\n");
break;
}
}
static struct ci13xxx_platform_data ci13xxx_msm_platdata = {
.name = "ci13xxx_msm",
.flags = CI13XXX_REGS_SHARED |
CI13XXX_REQUIRE_TRANSCEIVER |
CI13XXX_PULLUP_ON_VBUS |
CI13XXX_DISABLE_STREAMING,
static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
.name = "ci_hdrc_msm",
.flags = CI_HDRC_REGS_SHARED |
CI_HDRC_REQUIRE_TRANSCEIVER |
CI_HDRC_PULLUP_ON_VBUS |
CI_HDRC_DISABLE_STREAMING,
.notify_event = ci13xxx_msm_notify_event,
.notify_event = ci_hdrc_msm_notify_event,
};
static int ci13xxx_msm_probe(struct platform_device *pdev)
static int ci_hdrc_msm_probe(struct platform_device *pdev)
{
struct platform_device *plat_ci;
dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n");
dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n");
plat_ci = ci13xxx_add_device(&pdev->dev,
plat_ci = ci_hdrc_add_device(&pdev->dev,
pdev->resource, pdev->num_resources,
&ci13xxx_msm_platdata);
&ci_hdrc_msm_platdata);
if (IS_ERR(plat_ci)) {
dev_err(&pdev->dev, "ci13xxx_add_device failed!\n");
dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
return PTR_ERR(plat_ci);
}
......@@ -77,23 +77,24 @@ static int ci13xxx_msm_probe(struct platform_device *pdev)
return 0;
}
static int ci13xxx_msm_remove(struct platform_device *pdev)
static int ci_hdrc_msm_remove(struct platform_device *pdev)
{
struct platform_device *plat_ci = platform_get_drvdata(pdev);
pm_runtime_disable(&pdev->dev);
ci13xxx_remove_device(plat_ci);
ci_hdrc_remove_device(plat_ci);
return 0;
}
static struct platform_driver ci13xxx_msm_driver = {
.probe = ci13xxx_msm_probe,
.remove = ci13xxx_msm_remove,
static struct platform_driver ci_hdrc_msm_driver = {
.probe = ci_hdrc_msm_probe,
.remove = ci_hdrc_msm_remove,
.driver = { .name = "msm_hsusb", },
};
module_platform_driver(ci13xxx_msm_driver);
module_platform_driver(ci_hdrc_msm_driver);
MODULE_ALIAS("platform:msm_hsusb");
MODULE_ALIAS("platform:ci13xxx_msm");
MODULE_LICENSE("GPL v2");
/*
* ci13xxx_pci.c - MIPS USB IP core family device controller
* ci_hdrc_pci.c - MIPS USB IP core family device controller
*
* Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
*
......@@ -18,29 +18,29 @@
#include <linux/usb/chipidea.h>
/* driver name */
#define UDC_DRIVER_NAME "ci13xxx_pci"
#define UDC_DRIVER_NAME "ci_hdrc_pci"
/******************************************************************************
* PCI block
*****************************************************************************/
static struct ci13xxx_platform_data pci_platdata = {
static struct ci_hdrc_platform_data pci_platdata = {
.name = UDC_DRIVER_NAME,
.capoffset = DEF_CAPOFFSET,
};
static struct ci13xxx_platform_data langwell_pci_platdata = {
static struct ci_hdrc_platform_data langwell_pci_platdata = {
.name = UDC_DRIVER_NAME,
.capoffset = 0,
};
static struct ci13xxx_platform_data penwell_pci_platdata = {
static struct ci_hdrc_platform_data penwell_pci_platdata = {
.name = UDC_DRIVER_NAME,
.capoffset = 0,
.power_budget = 200,
};
/**
* ci13xxx_pci_probe: PCI probe
* ci_hdrc_pci_probe: PCI probe
* @pdev: USB device controller being probed
* @id: PCI hotplug ID connecting controller to UDC framework
*
......@@ -48,10 +48,10 @@ static struct ci13xxx_platform_data penwell_pci_platdata = {
* Allocates basic PCI resources for this USB device controller, and then
* invokes the udc_probe() method to start the UDC associated with it
*/
static int ci13xxx_pci_probe(struct pci_dev *pdev,
static int ci_hdrc_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct ci13xxx_platform_data *platdata = (void *)id->driver_data;
struct ci_hdrc_platform_data *platdata = (void *)id->driver_data;
struct platform_device *plat_ci;
struct resource res[3];
int retval = 0, nres = 2;
......@@ -61,17 +61,15 @@ static int ci13xxx_pci_probe(struct pci_dev *pdev,
return -ENODEV;
}
retval = pci_enable_device(pdev);
retval = pcim_enable_device(pdev);
if (retval)
goto done;
return retval;
if (!pdev->irq) {
dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!");
retval = -ENODEV;
goto disable_device;
return -ENODEV;
}
pci_set_power_state(pdev, PCI_D0);
pci_set_master(pdev);
pci_try_set_mwi(pdev);
......@@ -82,38 +80,30 @@ static int ci13xxx_pci_probe(struct pci_dev *pdev,
res[1].start = pdev->irq;
res[1].flags = IORESOURCE_IRQ;
plat_ci = ci13xxx_add_device(&pdev->dev, res, nres, platdata);
plat_ci = ci_hdrc_add_device(&pdev->dev, res, nres, platdata);
if (IS_ERR(plat_ci)) {
dev_err(&pdev->dev, "ci13xxx_add_device failed!\n");
retval = PTR_ERR(plat_ci);
goto disable_device;
dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
return PTR_ERR(plat_ci);
}
pci_set_drvdata(pdev, plat_ci);
return 0;
disable_device:
pci_disable_device(pdev);
done:
return retval;
}
/**
* ci13xxx_pci_remove: PCI remove
* ci_hdrc_pci_remove: PCI remove
* @pdev: USB Device Controller being removed
*
* Reverses the effect of ci13xxx_pci_probe(),
* Reverses the effect of ci_hdrc_pci_probe(),
* first invoking the udc_remove() and then releases
* all PCI resources allocated for this USB device controller
*/
static void ci13xxx_pci_remove(struct pci_dev *pdev)
static void ci_hdrc_pci_remove(struct pci_dev *pdev)
{
struct platform_device *plat_ci = pci_get_drvdata(pdev);
ci13xxx_remove_device(plat_ci);
pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
ci_hdrc_remove_device(plat_ci);
}
/**
......@@ -122,7 +112,7 @@ static void ci13xxx_pci_remove(struct pci_dev *pdev)
*
* Check "pci.h" for details
*/
static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = {
static DEFINE_PCI_DEVICE_TABLE(ci_hdrc_pci_id_table) = {
{
PCI_DEVICE(0x153F, 0x1004),
.driver_data = (kernel_ulong_t)&pci_platdata,
......@@ -141,18 +131,19 @@ static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = {
},
{ 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table);
MODULE_DEVICE_TABLE(pci, ci_hdrc_pci_id_table);
static struct pci_driver ci13xxx_pci_driver = {
static struct pci_driver ci_hdrc_pci_driver = {
.name = UDC_DRIVER_NAME,
.id_table = ci13xxx_pci_id_table,
.probe = ci13xxx_pci_probe,
.remove = ci13xxx_pci_remove,
.id_table = ci_hdrc_pci_id_table,
.probe = ci_hdrc_pci_probe,
.remove = ci_hdrc_pci_remove,
};
module_pci_driver(ci13xxx_pci_driver);
module_pci_driver(ci_hdrc_pci_driver);
MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>");
MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller");
MODULE_LICENSE("GPL");
MODULE_VERSION("June 2008");
MODULE_ALIAS("platform:ci13xxx_pci");
......@@ -43,8 +43,7 @@
*
* TODO List
* - OTG
* - Isochronous & Interrupt Traffic
* - Handle requests which spawns into several TDs
* - Interrupt Traffic
* - GET_STATUS(device) - always reports 0
* - Gadget API (majority of optional features)
* - Suspend & Remote Wakeup
......@@ -64,6 +63,8 @@
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
#include <linux/usb/chipidea.h>
#include <linux/usb/of.h>
#include <linux/phy.h>
#include "ci.h"
#include "udc.h"
......@@ -116,7 +117,7 @@ static uintptr_t ci_regs_lpm[] = {
[OP_ENDPTCTRL] = 0x0ECUL,
};
static int hw_alloc_regmap(struct ci13xxx *ci, bool is_lpm)
static int hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm)
{
int i;
......@@ -148,7 +149,7 @@ static int hw_alloc_regmap(struct ci13xxx *ci, bool is_lpm)
*
* This function returns an error code
*/
int hw_port_test_set(struct ci13xxx *ci, u8 mode)
int hw_port_test_set(struct ci_hdrc *ci, u8 mode)
{
const u8 TEST_MODE_MAX = 7;
......@@ -164,12 +165,12 @@ int hw_port_test_set(struct ci13xxx *ci, u8 mode)
*
* This function returns port test mode value
*/
u8 hw_port_test_get(struct ci13xxx *ci)
u8 hw_port_test_get(struct ci_hdrc *ci)
{
return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> __ffs(PORTSC_PTC);
}
static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
static int hw_device_init(struct ci_hdrc *ci, void __iomem *base)
{
u32 reg;
......@@ -208,13 +209,52 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
return 0;
}
static void hw_phymode_configure(struct ci_hdrc *ci)
{
u32 portsc, lpm, sts;
switch (ci->platdata->phy_mode) {
case USBPHY_INTERFACE_MODE_UTMI:
portsc = PORTSC_PTS(PTS_UTMI);
lpm = DEVLC_PTS(PTS_UTMI);
break;
case USBPHY_INTERFACE_MODE_UTMIW:
portsc = PORTSC_PTS(PTS_UTMI) | PORTSC_PTW;
lpm = DEVLC_PTS(PTS_UTMI) | DEVLC_PTW;
break;
case USBPHY_INTERFACE_MODE_ULPI:
portsc = PORTSC_PTS(PTS_ULPI);
lpm = DEVLC_PTS(PTS_ULPI);
break;
case USBPHY_INTERFACE_MODE_SERIAL:
portsc = PORTSC_PTS(PTS_SERIAL);
lpm = DEVLC_PTS(PTS_SERIAL);
sts = 1;
break;
case USBPHY_INTERFACE_MODE_HSIC:
portsc = PORTSC_PTS(PTS_HSIC);
lpm = DEVLC_PTS(PTS_HSIC);
break;
default:
return;
}
if (ci->hw_bank.lpm) {
hw_write(ci, OP_DEVLC, DEVLC_PTS(7) | DEVLC_PTW, lpm);
hw_write(ci, OP_DEVLC, DEVLC_STS, sts);
} else {
hw_write(ci, OP_PORTSC, PORTSC_PTS(7) | PORTSC_PTW, portsc);
hw_write(ci, OP_PORTSC, PORTSC_STS, sts);
}
}
/**
* hw_device_reset: resets chip (execute without interruption)
* @ci: the controller
*
* This function returns an error code
*/
int hw_device_reset(struct ci13xxx *ci, u32 mode)
int hw_device_reset(struct ci_hdrc *ci, u32 mode)
{
/* should flush & stop before reset */
hw_write(ci, OP_ENDPTFLUSH, ~0, ~0);
......@@ -224,12 +264,13 @@ int hw_device_reset(struct ci13xxx *ci, u32 mode)
while (hw_read(ci, OP_USBCMD, USBCMD_RST))
udelay(10); /* not RTOS friendly */
hw_phymode_configure(ci);
if (ci->platdata->notify_event)
ci->platdata->notify_event(ci,
CI13XXX_CONTROLLER_RESET_EVENT);
CI_HDRC_CONTROLLER_RESET_EVENT);
if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING)
if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING)
hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
/* USBMODE should be configured step by step */
......@@ -251,7 +292,7 @@ int hw_device_reset(struct ci13xxx *ci, u32 mode)
* ci_otg_role - pick role based on ID pin state
* @ci: the controller
*/
static enum ci_role ci_otg_role(struct ci13xxx *ci)
static enum ci_role ci_otg_role(struct ci_hdrc *ci)
{
u32 sts = hw_read(ci, OP_OTGSC, ~0);
enum ci_role role = sts & OTGSC_ID
......@@ -267,7 +308,7 @@ static enum ci_role ci_otg_role(struct ci13xxx *ci)
*/
static void ci_role_work(struct work_struct *work)
{
struct ci13xxx *ci = container_of(work, struct ci13xxx, work);
struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work);
enum ci_role role = ci_otg_role(ci);
if (role != ci->role) {
......@@ -283,7 +324,7 @@ static void ci_role_work(struct work_struct *work)
static irqreturn_t ci_irq(int irq, void *data)
{
struct ci13xxx *ci = data;
struct ci_hdrc *ci = data;
irqreturn_t ret = IRQ_NONE;
u32 otgsc = 0;
......@@ -305,9 +346,9 @@ static irqreturn_t ci_irq(int irq, void *data)
static DEFINE_IDA(ci_ida);
struct platform_device *ci13xxx_add_device(struct device *dev,
struct platform_device *ci_hdrc_add_device(struct device *dev,
struct resource *res, int nres,
struct ci13xxx_platform_data *platdata)
struct ci_hdrc_platform_data *platdata)
{
struct platform_device *pdev;
int id, ret;
......@@ -347,29 +388,33 @@ struct platform_device *ci13xxx_add_device(struct device *dev,
ida_simple_remove(&ci_ida, id);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(ci13xxx_add_device);
EXPORT_SYMBOL_GPL(ci_hdrc_add_device);
void ci13xxx_remove_device(struct platform_device *pdev)
void ci_hdrc_remove_device(struct platform_device *pdev)
{
int id = pdev->id;
platform_device_unregister(pdev);
ida_simple_remove(&ci_ida, id);
}
EXPORT_SYMBOL_GPL(ci13xxx_remove_device);
EXPORT_SYMBOL_GPL(ci_hdrc_remove_device);
static int ci_hdrc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct ci13xxx *ci;
struct ci_hdrc *ci;
struct resource *res;
void __iomem *base;
int ret;
enum usb_dr_mode dr_mode;
if (!dev->platform_data) {
dev_err(dev, "platform data missing\n");
return -ENODEV;
}
if (!dev->of_node && dev->parent)
dev->of_node = dev->parent->of_node;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
......@@ -409,14 +454,28 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -ENODEV;
}
if (!ci->platdata->phy_mode)
ci->platdata->phy_mode = of_usb_get_phy_mode(dev->of_node);
if (!ci->platdata->dr_mode)
ci->platdata->dr_mode = of_usb_get_dr_mode(dev->of_node);
if (ci->platdata->dr_mode == USB_DR_MODE_UNKNOWN)
ci->platdata->dr_mode = USB_DR_MODE_OTG;
dr_mode = ci->platdata->dr_mode;
/* initialize role(s) before the interrupt is requested */
ret = ci_hdrc_host_init(ci);
if (ret)
dev_info(dev, "doesn't support host\n");
if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) {
ret = ci_hdrc_host_init(ci);
if (ret)
dev_info(dev, "doesn't support host\n");
}
ret = ci_hdrc_gadget_init(ci);
if (ret)
dev_info(dev, "doesn't support gadget\n");
if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_PERIPHERAL) {
ret = ci_hdrc_gadget_init(ci);
if (ret)
dev_info(dev, "doesn't support gadget\n");
}
if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) {
dev_err(dev, "no supported roles\n");
......@@ -467,7 +526,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
static int ci_hdrc_remove(struct platform_device *pdev)
{
struct ci13xxx *ci = platform_get_drvdata(pdev);
struct ci_hdrc *ci = platform_get_drvdata(pdev);
dbg_remove_files(ci);
flush_workqueue(ci->wq);
......
......@@ -18,7 +18,7 @@
*/
static int ci_device_show(struct seq_file *s, void *data)
{
struct ci13xxx *ci = s->private;
struct ci_hdrc *ci = s->private;
struct usb_gadget *gadget = &ci->gadget;
seq_printf(s, "speed = %d\n", gadget->speed);
......@@ -58,7 +58,7 @@ static const struct file_operations ci_device_fops = {
*/
static int ci_port_test_show(struct seq_file *s, void *data)
{
struct ci13xxx *ci = s->private;
struct ci_hdrc *ci = s->private;
unsigned long flags;
unsigned mode;
......@@ -78,7 +78,7 @@ static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
struct seq_file *s = file->private_data;
struct ci13xxx *ci = s->private;
struct ci_hdrc *ci = s->private;
unsigned long flags;
unsigned mode;
char buf[32];
......@@ -115,7 +115,7 @@ static const struct file_operations ci_port_test_fops = {
*/
static int ci_qheads_show(struct seq_file *s, void *data)
{
struct ci13xxx *ci = s->private;
struct ci_hdrc *ci = s->private;
unsigned long flags;
unsigned i, j;
......@@ -126,15 +126,15 @@ static int ci_qheads_show(struct seq_file *s, void *data)
spin_lock_irqsave(&ci->lock, flags);
for (i = 0; i < ci->hw_ep_max/2; i++) {
struct ci13xxx_ep *mEpRx = &ci->ci13xxx_ep[i];
struct ci13xxx_ep *mEpTx =
&ci->ci13xxx_ep[i + ci->hw_ep_max/2];
struct ci_hw_ep *hweprx = &ci->ci_hw_ep[i];
struct ci_hw_ep *hweptx =
&ci->ci_hw_ep[i + ci->hw_ep_max/2];
seq_printf(s, "EP=%02i: RX=%08X TX=%08X\n",
i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++)
i, (u32)hweprx->qh.dma, (u32)hweptx->qh.dma);
for (j = 0; j < (sizeof(struct ci_hw_qh)/sizeof(u32)); j++)
seq_printf(s, " %04X: %08X %08X\n", j,
*((u32 *)mEpRx->qh.ptr + j),
*((u32 *)mEpTx->qh.ptr + j));
*((u32 *)hweprx->qh.ptr + j),
*((u32 *)hweptx->qh.ptr + j));
}
spin_unlock_irqrestore(&ci->lock, flags);
......@@ -158,11 +158,12 @@ static const struct file_operations ci_qheads_fops = {
*/
static int ci_requests_show(struct seq_file *s, void *data)
{
struct ci13xxx *ci = s->private;
struct ci_hdrc *ci = s->private;
unsigned long flags;
struct list_head *ptr = NULL;
struct ci13xxx_req *req = NULL;
unsigned i, j, qsize = sizeof(struct ci13xxx_td)/sizeof(u32);
struct ci_hw_req *req = NULL;
struct td_node *node, *tmpnode;
unsigned i, j, qsize = sizeof(struct ci_hw_td)/sizeof(u32);
if (ci->role != CI_ROLE_GADGET) {
seq_printf(s, "not in gadget mode\n");
......@@ -171,16 +172,20 @@ static int ci_requests_show(struct seq_file *s, void *data)
spin_lock_irqsave(&ci->lock, flags);
for (i = 0; i < ci->hw_ep_max; i++)
list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue) {
req = list_entry(ptr, struct ci13xxx_req, queue);
seq_printf(s, "EP=%02i: TD=%08X %s\n",
i % (ci->hw_ep_max / 2), (u32)req->dma,
((i < ci->hw_ep_max/2) ? "RX" : "TX"));
for (j = 0; j < qsize; j++)
seq_printf(s, " %04X: %08X\n", j,
*((u32 *)req->ptr + j));
list_for_each(ptr, &ci->ci_hw_ep[i].qh.queue) {
req = list_entry(ptr, struct ci_hw_req, queue);
list_for_each_entry_safe(node, tmpnode, &req->tds, td) {
seq_printf(s, "EP=%02i: TD=%08X %s\n",
i % (ci->hw_ep_max / 2),
(u32)node->dma,
((i < ci->hw_ep_max/2) ?
"RX" : "TX"));
for (j = 0; j < qsize; j++)
seq_printf(s, " %04X: %08X\n", j,
*((u32 *)node->ptr + j));
}
}
spin_unlock_irqrestore(&ci->lock, flags);
......@@ -201,7 +206,7 @@ static const struct file_operations ci_requests_fops = {
static int ci_role_show(struct seq_file *s, void *data)
{
struct ci13xxx *ci = s->private;
struct ci_hdrc *ci = s->private;
seq_printf(s, "%s\n", ci_role(ci)->name);
......@@ -212,7 +217,7 @@ static ssize_t ci_role_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
struct seq_file *s = file->private_data;
struct ci13xxx *ci = s->private;
struct ci_hdrc *ci = s->private;
enum ci_role role;
char buf[8];
int ret;
......@@ -254,7 +259,7 @@ static const struct file_operations ci_role_fops = {
*
* This function returns an error code
*/
int dbg_create_files(struct ci13xxx *ci)
int dbg_create_files(struct ci_hdrc *ci)
{
struct dentry *dent;
......@@ -295,7 +300,7 @@ int dbg_create_files(struct ci13xxx *ci)
* dbg_remove_files: destroys the attribute interface
* @ci: device
*/
void dbg_remove_files(struct ci13xxx *ci)
void dbg_remove_files(struct ci_hdrc *ci)
{
debugfs_remove_recursive(ci->debugfs);
}
......@@ -14,15 +14,15 @@
#define __DRIVERS_USB_CHIPIDEA_DEBUG_H
#ifdef CONFIG_USB_CHIPIDEA_DEBUG
int dbg_create_files(struct ci13xxx *ci);
void dbg_remove_files(struct ci13xxx *ci);
int dbg_create_files(struct ci_hdrc *ci);
void dbg_remove_files(struct ci_hdrc *ci);
#else
static inline int dbg_create_files(struct ci13xxx *ci)
static inline int dbg_create_files(struct ci_hdrc *ci)
{
return 0;
}
static inline void dbg_remove_files(struct ci13xxx *ci)
static inline void dbg_remove_files(struct ci_hdrc *ci)
{
}
#endif
......
......@@ -33,12 +33,12 @@
static struct hc_driver __read_mostly ci_ehci_hc_driver;
static irqreturn_t host_irq(struct ci13xxx *ci)
static irqreturn_t host_irq(struct ci_hdrc *ci)
{
return usb_hcd_irq(ci->irq, ci->hcd);
}
static int host_start(struct ci13xxx *ci)
static int host_start(struct ci_hdrc *ci)
{
struct usb_hcd *hcd;
struct ehci_hcd *ehci;
......@@ -70,13 +70,13 @@ static int host_start(struct ci13xxx *ci)
else
ci->hcd = hcd;
if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING)
if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING)
hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
return ret;
}
static void host_stop(struct ci13xxx *ci)
static void host_stop(struct ci_hdrc *ci)
{
struct usb_hcd *hcd = ci->hcd;
......@@ -84,7 +84,7 @@ static void host_stop(struct ci13xxx *ci)
usb_put_hcd(hcd);
}
int ci_hdrc_host_init(struct ci13xxx *ci)
int ci_hdrc_host_init(struct ci_hdrc *ci)
{
struct ci_role_driver *rdrv;
......
......@@ -3,11 +3,11 @@
#ifdef CONFIG_USB_CHIPIDEA_HOST
int ci_hdrc_host_init(struct ci13xxx *ci);
int ci_hdrc_host_init(struct ci_hdrc *ci);
#else
static inline int ci_hdrc_host_init(struct ci13xxx *ci)
static inline int ci_hdrc_host_init(struct ci_hdrc *ci)
{
return -ENXIO;
}
......
This diff is collapsed.
......@@ -20,7 +20,7 @@
#define TX 1 /* similar to USB_DIR_IN but can be used as an index */
/* DMA layout of transfer descriptors */
struct ci13xxx_td {
struct ci_hw_td {
/* 0 */
u32 next;
#define TD_TERMINATE BIT(0)
......@@ -43,24 +43,31 @@ struct ci13xxx_td {
} __attribute__ ((packed, aligned(4)));
/* DMA layout of queue heads */
struct ci13xxx_qh {
struct ci_hw_qh {
/* 0 */
u32 cap;
#define QH_IOS BIT(15)
#define QH_MAX_PKT (0x07FFUL << 16)
#define QH_ZLT BIT(29)
#define QH_MULT (0x0003UL << 30)
#define QH_ISO_MULT(x) ((x >> 11) & 0x03)
/* 1 */
u32 curr;
/* 2 - 8 */
struct ci13xxx_td td;
struct ci_hw_td td;
/* 9 */
u32 RESERVED;
struct usb_ctrlrequest setup;
} __attribute__ ((packed, aligned(4)));
struct td_node {
struct list_head td;
dma_addr_t dma;
struct ci_hw_td *ptr;
};
/**
* struct ci13xxx_req - usb request representation
* struct ci_hw_req - usb request representation
* @req: request structure for gadget drivers
* @queue: link to QH list
* @ptr: transfer descriptor for this request
......@@ -68,22 +75,19 @@ struct ci13xxx_qh {
* @zptr: transfer descriptor for the zero packet
* @zdma: dma address of the zero packet's transfer descriptor
*/
struct ci13xxx_req {
struct ci_hw_req {
struct usb_request req;
struct list_head queue;
struct ci13xxx_td *ptr;
dma_addr_t dma;
struct ci13xxx_td *zptr;
dma_addr_t zdma;
struct list_head tds;
};
#ifdef CONFIG_USB_CHIPIDEA_UDC
int ci_hdrc_gadget_init(struct ci13xxx *ci);
int ci_hdrc_gadget_init(struct ci_hdrc *ci);
#else
static inline int ci_hdrc_gadget_init(struct ci13xxx *ci)
static inline int ci_hdrc_gadget_init(struct ci_hdrc *ci)
{
return -ENXIO;
}
......
......@@ -16,7 +16,7 @@
#include <linux/io.h>
#include <linux/delay.h>
#include "ci13xxx_imx.h"
#include "ci_hdrc_imx.h"
#define USB_DEV_MAX 4
......@@ -175,6 +175,7 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = {
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
static int usbmisc_imx_probe(struct platform_device *pdev)
{
......@@ -243,17 +244,7 @@ static struct platform_driver usbmisc_imx_driver = {
},
};
int usbmisc_imx_drv_init(void)
{
return platform_driver_register(&usbmisc_imx_driver);
}
subsys_initcall(usbmisc_imx_drv_init);
void usbmisc_imx_drv_exit(void)
{
platform_driver_unregister(&usbmisc_imx_driver);
}
module_exit(usbmisc_imx_drv_exit);
module_platform_driver(usbmisc_imx_driver);
MODULE_ALIAS("platform:usbmisc-imx");
MODULE_LICENSE("GPL v2");
......
......@@ -216,38 +216,6 @@ static int acm_start_wb(struct acm *acm, struct acm_wb *wb)
return rc;
}
static int acm_write_start(struct acm *acm, int wbn)
{
unsigned long flags;
struct acm_wb *wb = &acm->wb[wbn];
int rc;
spin_lock_irqsave(&acm->write_lock, flags);
if (!acm->dev) {
wb->use = 0;
spin_unlock_irqrestore(&acm->write_lock, flags);
return -ENODEV;
}
dev_vdbg(&acm->data->dev, "%s - susp_count %d\n", __func__,
acm->susp_count);
usb_autopm_get_interface_async(acm->control);
if (acm->susp_count) {
if (!acm->delayed_wb)
acm->delayed_wb = wb;
else
usb_autopm_put_interface_async(acm->control);
spin_unlock_irqrestore(&acm->write_lock, flags);
return 0; /* A white lie */
}
usb_mark_last_busy(acm->dev);
rc = acm_start_wb(acm, wb);
spin_unlock_irqrestore(&acm->write_lock, flags);
return rc;
}
/*
* attributes exported through sysfs
*/
......@@ -653,13 +621,31 @@ static int acm_tty_write(struct tty_struct *tty,
}
wb = &acm->wb[wbn];
if (!acm->dev) {
wb->use = 0;
spin_unlock_irqrestore(&acm->write_lock, flags);
return -ENODEV;
}
count = (count > acm->writesize) ? acm->writesize : count;
dev_vdbg(&acm->data->dev, "%s - write %d\n", __func__, count);
memcpy(wb->buf, buf, count);
wb->len = count;
usb_autopm_get_interface_async(acm->control);
if (acm->susp_count) {
if (!acm->delayed_wb)
acm->delayed_wb = wb;
else
usb_autopm_put_interface_async(acm->control);
spin_unlock_irqrestore(&acm->write_lock, flags);
return count; /* A white lie */
}
usb_mark_last_busy(acm->dev);
stat = acm_start_wb(acm, wb);
spin_unlock_irqrestore(&acm->write_lock, flags);
stat = acm_write_start(acm, wbn);
if (stat < 0)
return stat;
return count;
......
This diff is collapsed.
......@@ -49,14 +49,14 @@
#include <linux/security.h>
#include <linux/user_namespace.h>
#include <linux/scatterlist.h>
#include <asm/uaccess.h>
#include <linux/uaccess.h>
#include <asm/byteorder.h>
#include <linux/moduleparam.h>
#include "usb.h"
#define USB_MAXBUS 64
#define USB_DEVICE_MAX USB_MAXBUS * 128
#define USB_DEVICE_MAX (USB_MAXBUS * 128)
#define USB_SG_SIZE 16384 /* split-size for large txs */
/* Mutual exclusion for removal, open, and release */
......@@ -1804,7 +1804,8 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
/* alloc buffer */
if ((size = _IOC_SIZE(ctl->ioctl_code)) > 0) {
if ((buf = kmalloc(size, GFP_KERNEL)) == NULL)
buf = kmalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) {
if (copy_from_user(buf, ctl->data, size)) {
......
......@@ -94,7 +94,7 @@ static int init_usb_class(void)
kref_init(&usb_class->kref);
usb_class->class = class_create(THIS_MODULE, "usbmisc");
if (IS_ERR(usb_class->class)) {
result = IS_ERR(usb_class->class);
result = PTR_ERR(usb_class->class);
printk(KERN_ERR "class_create failed for usb devices\n");
kfree(usb_class);
usb_class = NULL;
......
......@@ -149,6 +149,27 @@ static const u8 usb3_rh_dev_descriptor[18] = {
0x01 /* __u8 bNumConfigurations; */
};
/* usb 2.5 (wireless USB 1.0) root hub device descriptor */
static const u8 usb25_rh_dev_descriptor[18] = {
0x12, /* __u8 bLength; */
0x01, /* __u8 bDescriptorType; Device */
0x50, 0x02, /* __le16 bcdUSB; v2.5 */
0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
0x00, /* __u8 bDeviceSubClass; */
0x00, /* __u8 bDeviceProtocol; [ usb 2.0 no TT ] */
0xFF, /* __u8 bMaxPacketSize0; always 0xFF (WUSB Spec 7.4.1). */
0x6b, 0x1d, /* __le16 idVendor; Linux Foundation 0x1d6b */
0x02, 0x00, /* __le16 idProduct; device 0x0002 */
KERNEL_VER, KERNEL_REL, /* __le16 bcdDevice */
0x03, /* __u8 iManufacturer; */
0x02, /* __u8 iProduct; */
0x01, /* __u8 iSerialNumber; */
0x01 /* __u8 bNumConfigurations; */
};
/* usb 2.0 root hub device descriptor */
static const u8 usb2_rh_dev_descriptor [18] = {
0x12, /* __u8 bLength; */
......@@ -527,6 +548,9 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
case HCD_USB3:
bufp = usb3_rh_dev_descriptor;
break;
case HCD_USB25:
bufp = usb25_rh_dev_descriptor;
break;
case HCD_USB2:
bufp = usb2_rh_dev_descriptor;
break;
......@@ -546,6 +570,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
bufp = ss_rh_config_descriptor;
len = sizeof ss_rh_config_descriptor;
break;
case HCD_USB25:
case HCD_USB2:
bufp = hs_rh_config_descriptor;
len = sizeof hs_rh_config_descriptor;
......@@ -2511,6 +2536,9 @@ int usb_add_hcd(struct usb_hcd *hcd,
case HCD_USB2:
rhdev->speed = USB_SPEED_HIGH;
break;
case HCD_USB25:
rhdev->speed = USB_SPEED_WIRELESS;
break;
case HCD_USB3:
rhdev->speed = USB_SPEED_SUPER;
break;
......
......@@ -718,18 +718,18 @@ static void hub_tt_work(struct work_struct *work)
/**
* usb_hub_set_port_power - control hub port's power state
* @hdev: target hub
* @hdev: USB device belonging to the usb hub
* @hub: target hub
* @port1: port index
* @set: expected status
*
* call this function to control port's power via setting or
* clearing the port's PORT_POWER feature.
*/
int usb_hub_set_port_power(struct usb_device *hdev, int port1,
bool set)
int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
int port1, bool set)
{
int ret;
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
struct usb_port *port_dev = hub->ports[port1 - 1];
if (set)
......@@ -1769,15 +1769,17 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
static int find_port_owner(struct usb_device *hdev, unsigned port1,
struct dev_state ***ppowner)
{
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
if (hdev->state == USB_STATE_NOTATTACHED)
return -ENODEV;
if (port1 == 0 || port1 > hdev->maxchild)
return -EINVAL;
/* This assumes that devices not managed by the hub driver
/* Devices not managed by the hub driver
* will always have maxchild equal to 0.
*/
*ppowner = &(usb_hub_to_struct_hub(hdev)->ports[port1 - 1]->port_owner);
*ppowner = &(hub->ports[port1 - 1]->port_owner);
return 0;
}
......@@ -5323,7 +5325,8 @@ void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1,
{
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
hub->ports[port1 - 1]->connect_type = type;
if (hub)
hub->ports[port1 - 1]->connect_type = type;
}
/**
......@@ -5339,6 +5342,9 @@ usb_get_hub_port_connect_type(struct usb_device *hdev, int port1)
{
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
if (!hub)
return USB_PORT_CONNECT_TYPE_UNKNOWN;
return hub->ports[port1 - 1]->connect_type;
}
......@@ -5397,6 +5403,9 @@ acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev,
{
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
if (!hub)
return NULL;
return DEVICE_ACPI_HANDLE(&hub->ports[port1 - 1]->dev);
}
#endif
......@@ -100,7 +100,7 @@ extern int usb_hub_create_port_device(struct usb_hub *hub,
int port1);
extern void usb_hub_remove_port_device(struct usb_hub *hub,
int port1);
extern int usb_hub_set_port_power(struct usb_device *hdev,
extern int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
int port1, bool set);
extern struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev);
extern int hub_port_debounce(struct usb_hub *hub, int port1,
......
......@@ -252,7 +252,7 @@ static void sg_clean(struct usb_sg_request *io)
{
if (io->urbs) {
while (io->entries--)
usb_free_urb(io->urbs [io->entries]);
usb_free_urb(io->urbs[io->entries]);
kfree(io->urbs);
io->urbs = NULL;
}
......@@ -300,10 +300,10 @@ static void sg_complete(struct urb *urb)
*/
spin_unlock(&io->lock);
for (i = 0, found = 0; i < io->entries; i++) {
if (!io->urbs [i] || !io->urbs [i]->dev)
if (!io->urbs[i] || !io->urbs[i]->dev)
continue;
if (found) {
retval = usb_unlink_urb(io->urbs [i]);
retval = usb_unlink_urb(io->urbs[i]);
if (retval != -EINPROGRESS &&
retval != -ENODEV &&
retval != -EBUSY &&
......@@ -311,7 +311,7 @@ static void sg_complete(struct urb *urb)
dev_err(&io->dev->dev,
"%s, unlink --> %d\n",
__func__, retval);
} else if (urb == io->urbs [i])
} else if (urb == io->urbs[i])
found = 1;
}
spin_lock(&io->lock);
......@@ -379,7 +379,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
}
/* initialize all the urbs we'll use */
io->urbs = kmalloc(io->entries * sizeof *io->urbs, mem_flags);
io->urbs = kmalloc(io->entries * sizeof(*io->urbs), mem_flags);
if (!io->urbs)
goto nomem;
......@@ -511,7 +511,7 @@ void usb_sg_wait(struct usb_sg_request *io)
int retval;
io->urbs[i]->dev = io->dev;
retval = usb_submit_urb(io->urbs [i], GFP_ATOMIC);
retval = usb_submit_urb(io->urbs[i], GFP_ATOMIC);
/* after we submit, let completions or cancelations fire;
* we handshake using io->status.
......@@ -586,9 +586,9 @@ void usb_sg_cancel(struct usb_sg_request *io)
for (i = 0; i < io->entries; i++) {
int retval;
if (!io->urbs [i]->dev)
if (!io->urbs[i]->dev)
continue;
retval = usb_unlink_urb(io->urbs [i]);
retval = usb_unlink_urb(io->urbs[i]);
if (retval != -EINPROGRESS
&& retval != -ENODEV
&& retval != -EBUSY
......
......@@ -86,7 +86,7 @@ static int usb_port_runtime_resume(struct device *dev)
usb_autopm_get_interface(intf);
set_bit(port1, hub->busy_bits);
retval = usb_hub_set_port_power(hdev, port1, true);
retval = usb_hub_set_port_power(hdev, hub, port1, true);
if (port_dev->child && !retval) {
/*
* Wait for usb hub port to be reconnected in order to make
......@@ -128,7 +128,7 @@ static int usb_port_runtime_suspend(struct device *dev)
usb_autopm_get_interface(intf);
set_bit(port1, hub->busy_bits);
retval = usb_hub_set_port_power(hdev, port1, false);
retval = usb_hub_set_port_power(hdev, hub, port1, false);
usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION);
usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);
clear_bit(port1, hub->busy_bits);
......
......@@ -497,8 +497,62 @@ set_usb2_hardware_lpm(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(usb2_hardware_lpm, S_IRUGO | S_IWUSR, show_usb2_hardware_lpm,
set_usb2_hardware_lpm);
static ssize_t
show_usb2_lpm_l1_timeout(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct usb_device *udev = to_usb_device(dev);
return sprintf(buf, "%d\n", udev->l1_params.timeout);
}
static ssize_t
set_usb2_lpm_l1_timeout(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct usb_device *udev = to_usb_device(dev);
u16 timeout;
if (kstrtou16(buf, 0, &timeout))
return -EINVAL;
udev->l1_params.timeout = timeout;
return count;
}
static DEVICE_ATTR(usb2_lpm_l1_timeout, S_IRUGO | S_IWUSR,
show_usb2_lpm_l1_timeout, set_usb2_lpm_l1_timeout);
static ssize_t
show_usb2_lpm_besl(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct usb_device *udev = to_usb_device(dev);
return sprintf(buf, "%d\n", udev->l1_params.besl);
}
static ssize_t
set_usb2_lpm_besl(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct usb_device *udev = to_usb_device(dev);
u8 besl;
if (kstrtou8(buf, 0, &besl) || besl > 15)
return -EINVAL;
udev->l1_params.besl = besl;
return count;
}
static DEVICE_ATTR(usb2_lpm_besl, S_IRUGO | S_IWUSR,
show_usb2_lpm_besl, set_usb2_lpm_besl);
static struct attribute *usb2_hardware_lpm_attr[] = {
&dev_attr_usb2_hardware_lpm.attr,
&dev_attr_usb2_lpm_l1_timeout.attr,
&dev_attr_usb2_lpm_besl.attr,
NULL,
};
static struct attribute_group usb2_hardware_lpm_attr_group = {
......
......@@ -209,6 +209,39 @@ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
}
EXPORT_SYMBOL_GPL(usb_find_interface);
struct each_dev_arg {
void *data;
int (*fn)(struct usb_device *, void *);
};
static int __each_dev(struct device *dev, void *data)
{
struct each_dev_arg *arg = (struct each_dev_arg *)data;
/* There are struct usb_interface on the same bus, filter them out */
if (!is_usb_device(dev))
return 0;
return arg->fn(container_of(dev, struct usb_device, dev), arg->data);
}
/**
* usb_for_each_dev - iterate over all USB devices in the system
* @data: data pointer that will be handed to the callback function
* @fn: callback function to be called for each USB device
*
* Iterate over all USB devices and call @fn for each, passing it @data. If it
* returns anything other than 0, we break the iteration prematurely and return
* that value.
*/
int usb_for_each_dev(void *data, int (*fn)(struct usb_device *, void *))
{
struct each_dev_arg arg = {data, fn};
return bus_for_each_dev(&usb_bus_type, NULL, &arg, __each_dev);
}
EXPORT_SYMBOL_GPL(usb_for_each_dev);
/**
* usb_release_dev - free a usb device structure when all users of it are finished.
* @dev: device that's been disconnected
......
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);
......
This diff is collapsed.
......@@ -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;
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -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.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -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.
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.
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.
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.
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.
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