usb: patches for v3.12 merge window

All patches here have been pending on linux-usb
 and sitting in linux-next for a while now.
 
 The biggest things in this tag are:
 
 DWC3 learned proper usage of threaded IRQ
 handlers and now we spend very little time
 in hardirq context.
 
 MUSB now has proper support for BeagleBone and
 Beaglebone Black.
 
 Tegra's USB support also got quite a bit of love
 and is learning to use PHY layer and generic DT
 attributes.
 
 Other than that, the usual pack of cleanups and
 non-critical fixes follow.
 
 Signed-of-by: Felipe Balbi <balbi@ti.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iQIcBAABAgAGBQJSCpApAAoJEIaOsuA1yqREJl0QAJ6SY4cOVcUrk0gMcbPcU6ah
 mhGJAzA5xcOrRzsrA/r9+mT4aN5zMtOmPtYNJGLgHxPxtmrkWDnUqnpUqBSCJXpt
 45GZTIY/TNbe0USteVg0sGz9y8FEokpcLsXk2bBpdnpb0eCC/6UiEl4kVgvNbtTu
 z8+vooY9O++Y5bcR6L5QJVBwm+YiIm/rReoLb17aYQCWVLkPvQ5J5dNdfRF/5FUS
 uzA4bZdcQCaUtzAAUroIL8z8TgVFOZUCrUalRCs7fE5+7gh9+i/JlVQKMuol/3rR
 1bfOdYwuG9XVu3iYKssRLSGUSUXU68ZviLBxwO24cz7EFkCxiKSF6+JT2PHrG1hj
 XPxPGuKx4zqn4Lol2KdE5iban9AdgN+2JgjwZ8w9hBob+O14HfRTafKRlwBc27Mt
 BiXJv+5mEVmAbi8Xya1w3J/mWHAh+Qxhi1SlPEyT5FfUG3b+2D/Kv1dgpApdVdYL
 BW3CFSBgkFK8+WYGifnkNYtjj0v8z0eDaEU0cPmpy2L1pKgL3czNMNv/rgSH6r2n
 ilF5kR05CkEYsP56ZpuYg0VYCkpchhW1REDwaMx/2Nt1W4GXRql15aAyN9CcS+v4
 Xq0HVOSDyOV4juEryi296DDJPid6COELP8UtsKQLD+3nmifQEB58/S0NdNXJWcqs
 GocgpeGXdnzyk5y14FdJ
 =3NS9
 -----END PGP SIGNATURE-----

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

Felipe writes:

usb: patches for v3.12 merge window

All patches here have been pending on linux-usb
and sitting in linux-next for a while now.

The biggest things in this tag are:

DWC3 learned proper usage of threaded IRQ
handlers and now we spend very little time
in hardirq context.

MUSB now has proper support for BeagleBone and
Beaglebone Black.

Tegra's USB support also got quite a bit of love
and is learning to use PHY layer and generic DT
attributes.

Other than that, the usual pack of cleanups and
non-critical fixes follow.

Signed-of-by: Felipe Balbi <balbi@ti.com>

Conflicts:
	drivers/usb/gadget/udc-core.c
	drivers/usb/host/ehci-tegra.c
	drivers/usb/musb/omap2430.c
	drivers/usb/musb/tusb6010.c
This commit is contained in:
Greg Kroah-Hartman 2013-08-13 15:28:01 -07:00
commit 165f60642a
123 changed files with 3627 additions and 3529 deletions

View File

@ -3,10 +3,12 @@ synopsys DWC3 CORE
DWC3- USB3 CONTROLLER
Required properties:
- compatible: must be "synopsys,dwc3"
- compatible: must be "snps,dwc3"
- reg : Address and length of the register set for the device
- interrupts: Interrupts used by the dwc3 controller.
- usb-phy : array of phandle for the PHY device
- usb-phy : array of phandle for the PHY device. The first element
in the array is expected to be a handle to the USB2/HS PHY and
the second element is expected to be a handle to the USB3/SS PHY
Optional properties:
- tx-fifo-resize: determines if the FIFO *has* to be reallocated.
@ -14,7 +16,7 @@ Optional properties:
This is usually a subnode to DWC3 glue to which it is connected.
dwc3@4a030000 {
compatible = "synopsys,dwc3";
compatible = "snps,dwc3";
reg = <0x4a030000 0xcfff>;
interrupts = <0 92 4>
usb-phy = <&usb2_phy>, <&usb3,phy>;

View File

@ -0,0 +1,24 @@
Generic USB Properties
Optional properties:
- maximum-speed: tells USB controllers we want to work up to a certain
speed. Valid arguments are "super-speed", "high-speed",
"full-speed" and "low-speed". In case this isn't passed
via DT, USB controllers should default to their maximum
HW capability.
- dr_mode: tells Dual-Role USB controllers that we want to work on a
particular mode. Valid arguments are "host",
"peripheral" and "otg". In case this attribute isn't
passed via DT, USB DRD controllers should default to
OTG.
This is an attribute to a USB controller such as:
dwc3@4a030000 {
compatible = "synopsys,dwc3";
reg = <0x4a030000 0xcfff>;
interrupts = <0 92 4>
usb-phy = <&usb2_phy>, <&usb3,phy>;
maximum-speed = "super-speed";
dr_mode = "otg";
};

View File

@ -3,7 +3,7 @@ Tegra SOC USB PHY
The device node for Tegra SOC USB PHY:
Required properties :
- compatible : Should be "nvidia,tegra20-usb-phy".
- compatible : Should be "nvidia,tegra<chip>-usb-phy".
- reg : Defines the following set of registers, in the order listed:
- The PHY's own register set.
Always present.
@ -24,17 +24,26 @@ Required properties :
Required properties for phy_type == ulpi:
- nvidia,phy-reset-gpio : The GPIO used to reset the PHY.
Required PHY timing params for utmi phy:
Required PHY timing params for utmi phy, for all chips:
- 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
- Either one of the following for HS driver output control:
- nvidia,xcvr-setup : integer, uses the provided value.
- nvidia,xcvr-setup-use-fuses : boolean, indicates that the value is read
from the on-chip fuses
If both are provided, nvidia,xcvr-setup-use-fuses takes precedence.
- nvidia,xcvr-lsfslew : LS falling slew rate control.
- nvidia,xcvr-lsrslew : LS rising slew rate control.
Required PHY timing params for utmi phy, only on Tegra30 and above:
- nvidia,xcvr-hsslew : HS slew rate control.
- nvidia,hssquelch-level : HS squelch detector level.
- nvidia,hsdiscon-level : HS disconnect detector level.
Optional properties:
- nvidia,has-legacy-mode : boolean indicates whether this controller can
operate in legacy mode (as APX 2500 / 2600). In legacy mode some
@ -48,5 +57,5 @@ Optional properties:
peripheral means it is device controller
otg means it can operate as either ("on the go")
Required properties for dr_mode == otg:
VBUS control (required for dr_mode == otg, optional for dr_mode == host):
- vbus-supply: regulator for VBUS

View File

@ -0,0 +1,40 @@
Samsung High Speed USB OTG controller
-----------------------------
The Samsung HSOTG IP can be found on Samsung SoCs, from S3C6400 onwards.
It gives functionality of OTG-compliant USB 2.0 host and device with
support for USB 2.0 high-speed (480Mbps) and full-speed (12 Mbps)
operation.
Currently only device mode is supported.
Binding details
-----
Required properties:
- compatible: "samsung,s3c6400-hsotg" should be used for all currently
supported SoC,
- interrupt-parent: phandle for the interrupt controller to which the
interrupt signal of the HSOTG block is routed,
- interrupts: specifier of interrupt signal of interrupt controller,
according to bindings of interrupt controller,
- clocks: contains an array of clock specifiers:
- first entry: OTG clock
- clock-names: contains array of clock names:
- first entry: must be "otg"
- vusb_d-supply: phandle to voltage regulator of digital section,
- vusb_a-supply: phandle to voltage regulator of analog section.
Example
-----
hsotg@12480000 {
compatible = "samsung,s3c6400-hsotg";
reg = <0x12480000 0x20000>;
interrupts = <0 71 0>;
clocks = <&clock 305>;
clock-names = "otg";
vusb_d-supply = <&vusb_reg>;
vusb_a-supply = <&vusbdac_reg>;
};

View File

@ -120,6 +120,22 @@
status = "okay";
};
musb: usb@47400000 {
status = "okay";
control@44e10000 {
status = "okay";
};
phy@47401300 {
status = "okay";
};
usb@47401000 {
status = "okay";
};
};
i2c0: i2c@44e0b000 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;

View File

@ -171,6 +171,34 @@
};
};
musb: usb@47400000 {
status = "okay";
control@44e10000 {
status = "okay";
};
phy@47401300 {
status = "okay";
};
phy@47401b00 {
status = "okay";
};
usb@47401000 {
status = "okay";
};
usb@47401800 {
status = "okay";
};
dma@07402000 {
status = "okay";
};
};
i2c1: i2c@4802a000 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;

View File

@ -207,6 +207,22 @@
};
};
musb: usb@47400000 {
status = "okay";
control@44e10000 {
status = "okay";
};
phy@47401300 {
status = "okay";
};
usb@47401000 {
status = "okay";
};
};
epwmss2: epwmss@48304000 {
status = "okay";

View File

@ -26,6 +26,10 @@
serial5 = &uart5;
d_can0 = &dcan0;
d_can1 = &dcan1;
usb0 = &usb0;
usb1 = &usb1;
phy0 = &usb0_phy;
phy1 = &usb1_phy;
};
cpus {
@ -333,21 +337,147 @@
status = "disabled";
};
usb@47400000 {
compatible = "ti,musb-am33xx";
reg = <0x47400000 0x1000 /* usbss */
0x47401000 0x800 /* musb instance 0 */
0x47401800 0x800>; /* musb instance 1 */
interrupts = <17 /* usbss */
18 /* musb instance 0 */
19>; /* musb instance 1 */
multipoint = <1>;
num-eps = <16>;
ram-bits = <12>;
port0-mode = <3>;
port1-mode = <3>;
power = <250>;
usb: usb@47400000 {
compatible = "ti,am33xx-usb";
reg = <0x47400000 0x1000>;
ranges;
#address-cells = <1>;
#size-cells = <1>;
ti,hwmods = "usb_otg_hs";
status = "disabled";
ctrl_mod: control@44e10000 {
compatible = "ti,am335x-usb-ctrl-module";
reg = <0x44e10620 0x10
0x44e10648 0x4>;
reg-names = "phy_ctrl", "wakeup";
status = "disabled";
};
usb0_phy: phy@47401300 {
compatible = "ti,am335x-usb-phy";
reg = <0x47401300 0x100>;
reg-names = "phy";
status = "disabled";
ti,ctrl_mod = <&ctrl_mod>;
};
usb0: usb@47401000 {
compatible = "ti,musb-am33xx";
ranges;
#address-cells = <1>;
#size-cells = <1>;
reg = <0x47401000 0x200>;
reg-names = "control";
status = "disabled";
musb0: usb@47401400 {
compatible = "mg,musbmhdrc";
reg = <0x47401400 0x400>;
reg-names = "mc";
interrupts = <18>;
interrupt-names = "mc";
multipoint = <1>;
num-eps = <16>;
ram-bits = <12>;
port-mode = <3>;
power = <250>;
phys = <&usb0_phy>;
dmas = <&cppi41dma 0 0 &cppi41dma 1 0
&cppi41dma 2 0 &cppi41dma 3 0
&cppi41dma 4 0 &cppi41dma 5 0
&cppi41dma 6 0 &cppi41dma 7 0
&cppi41dma 8 0 &cppi41dma 9 0
&cppi41dma 10 0 &cppi41dma 11 0
&cppi41dma 12 0 &cppi41dma 13 0
&cppi41dma 14 0 &cppi41dma 0 1
&cppi41dma 1 1 &cppi41dma 2 1
&cppi41dma 3 1 &cppi41dma 4 1
&cppi41dma 5 1 &cppi41dma 6 1
&cppi41dma 7 1 &cppi41dma 8 1
&cppi41dma 9 1 &cppi41dma 10 1
&cppi41dma 11 1 &cppi41dma 12 1
&cppi41dma 13 1 &cppi41dma 14 1>;
dma-names =
"rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7",
"rx8", "rx9", "rx10", "rx11", "rx12", "rx13",
"rx14", "rx15",
"tx1", "tx2", "tx3", "tx4", "tx5", "tx6", "tx7",
"tx8", "tx9", "tx10", "tx11", "tx12", "tx13",
"tx14", "tx15";
};
};
usb1_phy: phy@47401b00 {
compatible = "ti,am335x-usb-phy";
reg = <0x47401b00 0x100>;
reg-names = "phy";
status = "disabled";
ti,ctrl_mod = <&ctrl_mod>;
};
usb1: usb@47401800 {
compatible = "ti,musb-am33xx";
ranges;
#address-cells = <1>;
#size-cells = <1>;
reg = <0x47401800 0x200>;
reg-names = "control";
status = "disabled";
musb1: usb@47401c00 {
compatible = "mg,musbmhdrc";
reg = <0x47401c00 0x400>;
reg-names = "mc";
interrupts = <19>;
interrupt-names = "mc";
multipoint = <1>;
num-eps = <16>;
ram-bits = <12>;
port-mode = <3>;
power = <250>;
phys = <&usb1_phy>;
dmas = <&cppi41dma 15 0 &cppi41dma 16 0
&cppi41dma 17 0 &cppi41dma 18 0
&cppi41dma 19 0 &cppi41dma 20 0
&cppi41dma 21 0 &cppi41dma 22 0
&cppi41dma 23 0 &cppi41dma 24 0
&cppi41dma 25 0 &cppi41dma 26 0
&cppi41dma 27 0 &cppi41dma 28 0
&cppi41dma 29 0 &cppi41dma 15 1
&cppi41dma 16 1 &cppi41dma 17 1
&cppi41dma 18 1 &cppi41dma 19 1
&cppi41dma 20 1 &cppi41dma 21 1
&cppi41dma 22 1 &cppi41dma 23 1
&cppi41dma 24 1 &cppi41dma 25 1
&cppi41dma 26 1 &cppi41dma 27 1
&cppi41dma 28 1 &cppi41dma 29 1>;
dma-names =
"rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7",
"rx8", "rx9", "rx10", "rx11", "rx12", "rx13",
"rx14", "rx15",
"tx1", "tx2", "tx3", "tx4", "tx5", "tx6", "tx7",
"tx8", "tx9", "tx10", "tx11", "tx12", "tx13",
"tx14", "tx15";
};
};
cppi41dma: dma@07402000 {
compatible = "ti,am3359-cppi41";
reg = <0x47400000 0x1000
0x47402000 0x1000
0x47403000 0x1000
0x47404000 0x4000>;
reg-names = "glue controller scheduler queuemgr";
interrupts = <17>;
interrupt-names = "glue";
#dma-cells = <2>;
#dma-channels = <30>;
#dma-requests = <256>;
status = "disabled";
};
};
epwmss0: epwmss@48300000 {

View File

@ -644,7 +644,7 @@
utmi-mode = <2>;
ranges;
dwc3@4a030000 {
compatible = "synopsys,dwc3";
compatible = "snps,dwc3";
reg = <0x4a030000 0x1000>;
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
usb-phy = <&usb2_phy>, <&usb3_phy>;

View File

@ -566,7 +566,6 @@
usb@c5000000 {
status = "okay";
nvidia,vbus-gpio = <&gpio TEGRA_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
dr_mode = "otg";
};

View File

@ -312,7 +312,6 @@
usb@c5000000 {
status = "okay";
nvidia,vbus-gpio = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
};
usb-phy@c5000000 {

View File

@ -509,7 +509,6 @@
usb@c5000000 {
status = "okay";
nvidia,vbus-gpio = <&tca6416 0 GPIO_ACTIVE_HIGH>;
};
usb-phy@c5000000 {
@ -519,7 +518,6 @@
usb@c5008000 {
status = "okay";
nvidia,vbus-gpio = <&tca6416 1 GPIO_ACTIVE_HIGH>;
};
usb-phy@c5008000 {

View File

@ -477,13 +477,13 @@
<&tegra_car TEGRA20_CLK_USBD>;
clock-names = "reg", "pll_u", "timer", "utmi-pads";
nvidia,has-legacy-mode;
hssync_start_delay = <9>;
idle_wait_delay = <17>;
elastic_limit = <16>;
term_range_adj = <6>;
xcvr_setup = <9>;
xcvr_lsfslew = <1>;
xcvr_lsrslew = <1>;
nvidia,hssync-start-delay = <9>;
nvidia,idle-wait-delay = <17>;
nvidia,elastic-limit = <16>;
nvidia,term-range-adj = <6>;
nvidia,xcvr-setup = <9>;
nvidia,xcvr-lsfslew = <1>;
nvidia,xcvr-lsrslew = <1>;
status = "disabled";
};
@ -527,13 +527,13 @@
<&tegra_car TEGRA20_CLK_CLK_M>,
<&tegra_car TEGRA20_CLK_USBD>;
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>;
nvidia,hssync-start-delay = <9>;
nvidia,idle-wait-delay = <17>;
nvidia,elastic-limit = <16>;
nvidia,term-range-adj = <6>;
nvidia,xcvr-setup = <9>;
nvidia,xcvr-lsfslew = <2>;
nvidia,xcvr-lsrslew = <2>;
status = "disabled";
};

View File

@ -33,7 +33,7 @@
#include <linux/mtd/nand.h>
#include <linux/mmc/host.h>
#include <linux/usb/phy.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/usb/usb_phy_gen_xceiv.h>
#include <linux/regulator/machine.h>
#include <linux/i2c/twl.h>
@ -279,7 +279,7 @@ static struct regulator_consumer_supply beagle_vsim_supply[] = {
static struct gpio_led gpio_leds[];
/* PHY's VCC regulator might be added later, so flag that we need it */
static struct nop_usb_xceiv_platform_data hsusb2_phy_data = {
static struct usb_phy_gen_xceiv_platform_data hsusb2_phy_data = {
.needs_vcc = true,
};

View File

@ -33,7 +33,7 @@
#include <linux/i2c/twl.h>
#include <linux/usb/otg.h>
#include <linux/usb/musb.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/usb/usb_phy_gen_xceiv.h>
#include <linux/smsc911x.h>
#include <linux/wl12xx.h>
@ -468,7 +468,7 @@ struct wl12xx_platform_data omap3evm_wlan_data __initdata = {
static struct regulator_consumer_supply omap3evm_vaux2_supplies[] = {
REGULATOR_SUPPLY("VDD_CSIPHY1", "omap3isp"), /* OMAP ISP */
REGULATOR_SUPPLY("VDD_CSIPHY2", "omap3isp"), /* OMAP ISP */
REGULATOR_SUPPLY("vcc", "nop_usb_xceiv.2"), /* hsusb port 2 */
REGULATOR_SUPPLY("vcc", "usb_phy_gen_xceiv.2"), /* hsusb port 2 */
REGULATOR_SUPPLY("vaux2", NULL),
};

View File

@ -352,7 +352,7 @@ static struct regulator_consumer_supply pandora_vcc_lcd_supply[] = {
};
static struct regulator_consumer_supply pandora_usb_phy_supply[] = {
REGULATOR_SUPPLY("vcc", "nop_usb_xceiv.2"), /* hsusb port 2 */
REGULATOR_SUPPLY("vcc", "usb_phy_gen_xceiv.2"), /* hsusb port 2 */
};
/* ads7846 on SPI and 2 nub controllers on I2C */

View File

@ -28,7 +28,7 @@
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/usb/phy.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/usb/usb_phy_gen_xceiv.h>
#include "soc.h"
#include "omap_device.h"
@ -349,7 +349,7 @@ static struct fixed_voltage_config hsusb_reg_config = {
/* .init_data filled later */
};
static const char *nop_name = "nop_usb_xceiv"; /* NOP PHY driver */
static const char *nop_name = "usb_phy_gen_xceiv"; /* NOP PHY driver */
static const char *reg_name = "reg-fixed-voltage"; /* Regulator driver */
/**
@ -460,9 +460,9 @@ int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys)
pdevinfo.name = nop_name;
pdevinfo.id = phy->port;
pdevinfo.data = phy->platform_data;
pdevinfo.size_data = sizeof(struct nop_usb_xceiv_platform_data);
scnprintf(phy_id, MAX_STR, "nop_usb_xceiv.%d",
pdevinfo.size_data =
sizeof(struct usb_phy_gen_xceiv_platform_data);
scnprintf(phy_id, MAX_STR, "usb_phy_gen_xceiv.%d",
phy->port);
pdev = platform_device_register_full(&pdevinfo);
if (IS_ERR(pdev)) {

View File

@ -29,7 +29,6 @@
#include <linux/of_fdt.h>
#include <linux/of_platform.h>
#include <linux/pda_power.h>
#include <linux/platform_data/tegra_usb.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
@ -46,40 +45,6 @@
#include "fuse.h"
#include "iomap.h"
static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
.operating_mode = TEGRA_USB_OTG,
.power_down_on_bus_suspend = 1,
.vbus_gpio = -1,
};
static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
.reset_gpio = -1,
.clk = "cdev2",
};
static struct tegra_ehci_platform_data tegra_ehci2_pdata = {
.phy_config = &tegra_ehci2_ulpi_phy_config,
.operating_mode = TEGRA_USB_HOST,
.power_down_on_bus_suspend = 1,
.vbus_gpio = -1,
};
static struct tegra_ehci_platform_data tegra_ehci3_pdata = {
.operating_mode = TEGRA_USB_HOST,
.power_down_on_bus_suspend = 1,
.vbus_gpio = -1,
};
static struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5000000, "tegra-ehci.0",
&tegra_ehci1_pdata),
OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5004000, "tegra-ehci.1",
&tegra_ehci2_pdata),
OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5008000, "tegra-ehci.2",
&tegra_ehci3_pdata),
{}
};
static void __init tegra_dt_init(void)
{
struct soc_device_attribute *soc_dev_attr;
@ -112,8 +77,7 @@ static void __init tegra_dt_init(void)
* devices
*/
out:
of_platform_populate(NULL, of_default_bus_match_table,
tegra20_auxdata_lookup, parent);
of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
}
static void __init trimslice_init(void)

View File

@ -287,6 +287,14 @@ config DMA_OMAP
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
config TI_CPPI41
tristate "AM33xx CPPI41 DMA support"
depends on ARCH_OMAP
select DMA_ENGINE
help
The Communications Port Programming Interface (CPPI) 4.1 DMA engine
is currently used by the USB driver on AM335x platforms.
config MMP_PDMA
bool "MMP PDMA support"
depends on (ARCH_MMP || ARCH_PXA)

View File

@ -39,3 +39,4 @@ obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o
obj-$(CONFIG_DMA_OMAP) += omap-dma.o
obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o
obj-$(CONFIG_TI_CPPI41) += cppi41.o

1048
drivers/dma/cppi41.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -46,7 +46,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/
obj-$(CONFIG_USB_SERIAL) += serial/
obj-$(CONFIG_USB) += misc/
obj-$(CONFIG_USB_PHY) += phy/
obj-$(CONFIG_USB_SUPPORT) += phy/
obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/
obj-$(CONFIG_USB_ATM) += atm/

View File

@ -63,6 +63,7 @@ static int host_start(struct ci_hdrc *ci)
ehci = hcd_to_ehci(hcd);
ehci->caps = ci->hw_bank.cap;
ehci->has_hostpc = ci->hw_bank.lpm;
ehci->has_tdi_phy_lpm = ci->hw_bank.lpm;
ret = usb_add_hcd(hcd, 0, 0);
if (ret)

View File

@ -40,6 +40,38 @@ config USB_DWC3_DUAL_ROLE
endchoice
comment "Platform Glue Driver Support"
config USB_DWC3_OMAP
tristate "Texas Instruments OMAP5 and similar Platforms"
depends on EXTCON
default USB_DWC3
help
Some platforms from Texas Instruments like OMAP5, DRA7xxx and
AM437x use this IP for USB2/3 functionality.
Say 'Y' or 'M' here if you have one such device
config USB_DWC3_EXYNOS
tristate "Samsung Exynos Platform"
default USB_DWC3
help
Recent Exynos5 SoCs ship with one DesignWare Core USB3 IP inside,
say 'Y' or 'M' if you have one such device.
config USB_DWC3_PCI
tristate "PCIe-based Platforms"
depends on PCI
default USB_DWC3
help
If you're using the DesignWare Core IP with a PCIe, please say
'Y' or 'M' here.
One such PCIe-based platform is Synopsys' PCIe HAPS model of
this IP.
comment "Debugging features"
config USB_DWC3_DEBUG
bool "Enable Debugging Messages"
help

View File

@ -27,15 +27,8 @@ endif
# the entire driver (with all its glue layers) on several architectures
# and make sure it compiles fine. This will also help with allmodconfig
# and allyesconfig builds.
#
# The only exception is the PCI glue layer, but that's only because
# PCI doesn't provide nops if CONFIG_PCI isn't enabled.
##
obj-$(CONFIG_USB_DWC3) += dwc3-omap.o
obj-$(CONFIG_USB_DWC3) += dwc3-exynos.o
ifneq ($(CONFIG_PCI),)
obj-$(CONFIG_USB_DWC3) += dwc3-pci.o
endif
obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o
obj-$(CONFIG_USB_DWC3_EXYNOS) += dwc3-exynos.o
obj-$(CONFIG_USB_DWC3_PCI) += dwc3-pci.o

View File

@ -6,34 +6,17 @@
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the above-listed copyright holders may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2, as published by the Free
* Software Foundation.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/module.h>
@ -53,17 +36,16 @@
#include <linux/usb/otg.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/of.h>
#include <linux/usb/otg.h>
#include "platform_data.h"
#include "core.h"
#include "gadget.h"
#include "io.h"
#include "debug.h"
static char *maximum_speed = "super";
module_param(maximum_speed, charp, 0);
MODULE_PARM_DESC(maximum_speed, "Maximum supported speed.");
/* -------------------------------------------------------------------------- */
void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
@ -236,7 +218,7 @@ static int dwc3_event_buffers_setup(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
upper_32_bits(evt->dma));
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n),
evt->length & 0xffff);
DWC3_GEVNTSIZ_SIZE(evt->length));
dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
}
@ -255,7 +237,8 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0);
dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0);
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0);
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK
| DWC3_GEVNTSIZ_SIZE(0));
dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
}
}
@ -367,18 +350,17 @@ static void dwc3_core_exit(struct dwc3 *dwc)
static int dwc3_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct device *dev = &pdev->dev;
struct dwc3_platform_data *pdata = dev_get_platdata(dev);
struct device_node *node = dev->of_node;
struct resource *res;
struct dwc3 *dwc;
struct device *dev = &pdev->dev;
int ret = -ENOMEM;
void __iomem *regs;
void *mem;
u8 mode;
mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
if (!mem) {
dev_err(dev, "not enough memory\n");
@ -402,38 +384,29 @@ static int dwc3_probe(struct platform_device *pdev)
dev_err(dev, "missing memory resource\n");
return -ENODEV;
}
dwc->xhci_resources[0].start = res->start;
dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
DWC3_XHCI_REGS_END;
dwc->xhci_resources[0].flags = res->flags;
dwc->xhci_resources[0].name = res->name;
/*
* Request memory region but exclude xHCI regs,
* since it will be requested by the xhci-plat driver.
*/
res = devm_request_mem_region(dev, res->start + DWC3_GLOBALS_REGS_START,
resource_size(res) - DWC3_GLOBALS_REGS_START,
dev_name(dev));
if (!res) {
dev_err(dev, "can't request mem region\n");
return -ENOMEM;
}
regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
if (!regs) {
dev_err(dev, "ioremap failed\n");
return -ENOMEM;
}
if (node) {
dwc->maximum_speed = of_usb_get_maximum_speed(node);
dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
dwc->dr_mode = of_usb_get_dr_mode(node);
} else {
dwc->maximum_speed = pdata->maximum_speed;
dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
dwc->needs_fifo_resize = pdata->tx_fifo_resize;
dwc->dr_mode = pdata->dr_mode;
}
/* default to superspeed if no maximum_speed passed */
if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
dwc->maximum_speed = USB_SPEED_SUPER;
if (IS_ERR(dwc->usb2_phy)) {
ret = PTR_ERR(dwc->usb2_phy);
@ -464,6 +437,22 @@ static int dwc3_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}
dwc->xhci_resources[0].start = res->start;
dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
DWC3_XHCI_REGS_END;
dwc->xhci_resources[0].flags = res->flags;
dwc->xhci_resources[0].name = res->name;
res->start += DWC3_GLOBALS_REGS_START;
/*
* Request memory region but exclude xHCI regs,
* since it will be requested by the xhci-plat driver.
*/
regs = devm_ioremap_resource(dev, res);
if (IS_ERR(regs))
return PTR_ERR(regs);
usb_phy_set_suspend(dwc->usb2_phy, 0);
usb_phy_set_suspend(dwc->usb3_phy, 0);
@ -478,19 +467,6 @@ static int dwc3_probe(struct platform_device *pdev)
dev->dma_parms = dev->parent->dma_parms;
dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
if (!strncmp("super", maximum_speed, 5))
dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
else if (!strncmp("high", maximum_speed, 4))
dwc->maximum_speed = DWC3_DCFG_HIGHSPEED;
else if (!strncmp("full", maximum_speed, 4))
dwc->maximum_speed = DWC3_DCFG_FULLSPEED1;
else if (!strncmp("low", maximum_speed, 3))
dwc->maximum_speed = DWC3_DCFG_LOWSPEED;
else
dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
pm_runtime_forbid(dev);
@ -517,14 +493,15 @@ static int dwc3_probe(struct platform_device *pdev)
}
if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
mode = DWC3_MODE_HOST;
dwc->dr_mode = USB_DR_MODE_HOST;
else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
mode = DWC3_MODE_DEVICE;
else
mode = DWC3_MODE_DRD;
dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
switch (mode) {
case DWC3_MODE_DEVICE:
if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
dwc->dr_mode = USB_DR_MODE_OTG;
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
ret = dwc3_gadget_init(dwc);
if (ret) {
@ -532,7 +509,7 @@ static int dwc3_probe(struct platform_device *pdev)
goto err2;
}
break;
case DWC3_MODE_HOST:
case USB_DR_MODE_HOST:
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
ret = dwc3_host_init(dwc);
if (ret) {
@ -540,7 +517,7 @@ static int dwc3_probe(struct platform_device *pdev)
goto err2;
}
break;
case DWC3_MODE_DRD:
case USB_DR_MODE_OTG:
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
ret = dwc3_host_init(dwc);
if (ret) {
@ -555,10 +532,9 @@ static int dwc3_probe(struct platform_device *pdev)
}
break;
default:
dev_err(dev, "Unsupported mode of operation %d\n", mode);
dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);
goto err2;
}
dwc->mode = mode;
ret = dwc3_debugfs_init(dwc);
if (ret) {
@ -571,14 +547,14 @@ static int dwc3_probe(struct platform_device *pdev)
return 0;
err3:
switch (mode) {
case DWC3_MODE_DEVICE:
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
dwc3_gadget_exit(dwc);
break;
case DWC3_MODE_HOST:
case USB_DR_MODE_HOST:
dwc3_host_exit(dwc);
break;
case DWC3_MODE_DRD:
case USB_DR_MODE_OTG:
dwc3_host_exit(dwc);
dwc3_gadget_exit(dwc);
break;
@ -611,14 +587,14 @@ static int dwc3_remove(struct platform_device *pdev)
dwc3_debugfs_exit(dwc);
switch (dwc->mode) {
case DWC3_MODE_DEVICE:
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
dwc3_gadget_exit(dwc);
break;
case DWC3_MODE_HOST:
case USB_DR_MODE_HOST:
dwc3_host_exit(dwc);
break;
case DWC3_MODE_DRD:
case USB_DR_MODE_OTG:
dwc3_host_exit(dwc);
dwc3_gadget_exit(dwc);
break;
@ -642,12 +618,12 @@ static int dwc3_prepare(struct device *dev)
spin_lock_irqsave(&dwc->lock, flags);
switch (dwc->mode) {
case DWC3_MODE_DEVICE:
case DWC3_MODE_DRD:
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
case USB_DR_MODE_OTG:
dwc3_gadget_prepare(dwc);
/* FALLTHROUGH */
case DWC3_MODE_HOST:
case USB_DR_MODE_HOST:
default:
dwc3_event_buffers_cleanup(dwc);
break;
@ -665,12 +641,12 @@ static void dwc3_complete(struct device *dev)
spin_lock_irqsave(&dwc->lock, flags);
switch (dwc->mode) {
case DWC3_MODE_DEVICE:
case DWC3_MODE_DRD:
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
case USB_DR_MODE_OTG:
dwc3_gadget_complete(dwc);
/* FALLTHROUGH */
case DWC3_MODE_HOST:
case USB_DR_MODE_HOST:
default:
dwc3_event_buffers_setup(dwc);
break;
@ -686,12 +662,12 @@ static int dwc3_suspend(struct device *dev)
spin_lock_irqsave(&dwc->lock, flags);
switch (dwc->mode) {
case DWC3_MODE_DEVICE:
case DWC3_MODE_DRD:
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
case USB_DR_MODE_OTG:
dwc3_gadget_suspend(dwc);
/* FALLTHROUGH */
case DWC3_MODE_HOST:
case USB_DR_MODE_HOST:
default:
/* do nothing */
break;
@ -719,12 +695,12 @@ static int dwc3_resume(struct device *dev)
dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl);
switch (dwc->mode) {
case DWC3_MODE_DEVICE:
case DWC3_MODE_DRD:
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
case USB_DR_MODE_OTG:
dwc3_gadget_resume(dwc);
/* FALLTHROUGH */
case DWC3_MODE_HOST:
case USB_DR_MODE_HOST:
default:
/* do nothing */
break;
@ -753,6 +729,9 @@ static const struct dev_pm_ops dwc3_dev_pm_ops = {
#ifdef CONFIG_OF
static const struct of_device_id of_dwc3_match[] = {
{
.compatible = "snps,dwc3"
},
{
.compatible = "synopsys,dwc3"
},
@ -775,5 +754,5 @@ module_platform_driver(dwc3_driver);
MODULE_ALIAS("platform:dwc3");
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");

View File

@ -6,34 +6,14 @@
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the above-listed copyright holders may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2, as published by the Free
* Software Foundation.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __DRIVERS_USB_DWC3_CORE_H
@ -49,6 +29,7 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
/* Global constants */
#define DWC3_EP0_BOUNCE_SIZE 512
@ -194,6 +175,10 @@
#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff)
#define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000)
/* Global Event Size Registers */
#define DWC3_GEVNTSIZ_INTMASK (1 << 31)
#define DWC3_GEVNTSIZ_SIZE(n) ((n) & 0xffff)
/* Global HWPARAMS1 Register */
#define DWC3_GHWPARAMS1_EN_PWROPT(n) (((n) & (3 << 24)) >> 24)
#define DWC3_GHWPARAMS1_EN_PWROPT_NO 0
@ -207,7 +192,6 @@
#define DWC3_MAX_HIBER_SCRATCHBUFS 15
/* Device Configuration Register */
#define DWC3_DCFG_LPM_CAP (1 << 22)
#define DWC3_DCFG_DEVADDR(addr) ((addr) << 3)
#define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f)
@ -367,7 +351,6 @@ struct dwc3_trb;
/**
* struct dwc3_event_buffer - Software event buffer representation
* @list: a list of event buffers
* @buf: _THE_ buffer
* @length: size of this buffer
* @lpos: event offset
@ -415,7 +398,7 @@ struct dwc3_event_buffer {
* @number: endpoint number (1 - 15)
* @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK
* @resource_index: Resource transfer index
* @interval: the intervall on which the ISOC transfer is started
* @interval: the interval on which the ISOC transfer is started
* @name: a human readable name e.g. ep1out-bulk
* @direction: true for TX, false for RX
* @stream_capable: true when streams are enabled
@ -566,11 +549,6 @@ struct dwc3_hwparams {
/* HWPARAMS0 */
#define DWC3_MODE(n) ((n) & 0x7)
#define DWC3_MODE_DEVICE 0
#define DWC3_MODE_HOST 1
#define DWC3_MODE_DRD 2
#define DWC3_MODE_HUB 3
#define DWC3_MDWIDTH(n) (((n) & 0xff00) >> 8)
/* HWPARAMS1 */
@ -632,7 +610,7 @@ struct dwc3_scratchpad_array {
* @u1u2: only used on revisions <1.83a for workaround
* @maximum_speed: maximum speed requested (mainly for testing purposes)
* @revision: revision register contents
* @mode: mode of operation
* @dr_mode: requested mode of operation
* @usb2_phy: pointer to USB2 PHY
* @usb3_phy: pointer to USB3 PHY
* @dcfg: saved contents of DCFG register
@ -690,6 +668,8 @@ struct dwc3 {
void __iomem *regs;
size_t regs_size;
enum usb_dr_mode dr_mode;
/* used for suspend/resume */
u32 dcfg;
u32 gctl;
@ -698,7 +678,6 @@ struct dwc3 {
u32 u1u2;
u32 maximum_speed;
u32 revision;
u32 mode;
#define DWC3_REVISION_173A 0x5533173a
#define DWC3_REVISION_175A 0x5533175a

View File

@ -6,34 +6,14 @@
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the above-listed copyright holders may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2, as published by the Free
* Software Foundation.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "core.h"

View File

@ -6,34 +6,14 @@
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the above-listed copyright holders may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2, as published by the Free
* Software Foundation.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>

View File

@ -6,10 +6,14 @@
*
* Author: Anton Tikhomirov <av.tikhomirov@samsung.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.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/module.h>
@ -20,7 +24,7 @@
#include <linux/dma-mapping.h>
#include <linux/clk.h>
#include <linux/usb/otg.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/usb/usb_phy_gen_xceiv.h>
#include <linux/of.h>
#include <linux/of_platform.h>
@ -34,13 +38,13 @@ struct dwc3_exynos {
static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
{
struct nop_usb_xceiv_platform_data pdata;
struct usb_phy_gen_xceiv_platform_data pdata;
struct platform_device *pdev;
int ret;
memset(&pdata, 0x00, sizeof(pdata));
pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
pdev = platform_device_alloc("usb_phy_gen_xceiv", PLATFORM_DEVID_AUTO);
if (!pdev)
return -ENOMEM;
@ -51,7 +55,7 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
if (ret)
goto err1;
pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
pdev = platform_device_alloc("usb_phy_gen_xceiv", PLATFORM_DEVID_AUTO);
if (!pdev) {
ret = -ENOMEM;
goto err1;
@ -228,5 +232,5 @@ module_platform_driver(dwc3_exynos_driver);
MODULE_ALIAS("platform:exynos-dwc3");
MODULE_AUTHOR("Anton Tikhomirov <av.tikhomirov@samsung.com>");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("DesignWare USB3 EXYNOS Glue Layer");

View File

@ -6,34 +6,14 @@
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the above-listed copyright holders may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2, as published by the Free
* Software Foundation.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/module.h>
@ -409,11 +389,9 @@ static int dwc3_omap_probe(struct platform_device *pdev)
return -EINVAL;
}
base = devm_ioremap_nocache(dev, res->start, resource_size(res));
if (!base) {
dev_err(dev, "ioremap failed\n");
return -ENOMEM;
}
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
spin_lock_init(&omap->lock);
@ -610,5 +588,5 @@ module_platform_driver(dwc3_omap_driver);
MODULE_ALIAS("platform:omap-dwc3");
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("DesignWare USB3 OMAP Glue Layer");

View File

@ -6,34 +6,14 @@
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the above-listed copyright holders may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2, as published by the Free
* Software Foundation.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
@ -43,7 +23,7 @@
#include <linux/platform_device.h>
#include <linux/usb/otg.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/usb/usb_phy_gen_xceiv.h>
/* FIXME define these in <linux/pci_ids.h> */
#define PCI_VENDOR_ID_SYNOPSYS 0x16c3
@ -58,13 +38,13 @@ struct dwc3_pci {
static int dwc3_pci_register_phys(struct dwc3_pci *glue)
{
struct nop_usb_xceiv_platform_data pdata;
struct usb_phy_gen_xceiv_platform_data pdata;
struct platform_device *pdev;
int ret;
memset(&pdata, 0x00, sizeof(pdata));
pdev = platform_device_alloc("nop_usb_xceiv", 0);
pdev = platform_device_alloc("usb_phy_gen_xceiv", 0);
if (!pdev)
return -ENOMEM;
@ -75,7 +55,7 @@ static int dwc3_pci_register_phys(struct dwc3_pci *glue)
if (ret)
goto err1;
pdev = platform_device_alloc("nop_usb_xceiv", 1);
pdev = platform_device_alloc("usb_phy_gen_xceiv", 1);
if (!pdev) {
ret = -ENOMEM;
goto err1;
@ -211,7 +191,7 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
};
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static int dwc3_pci_suspend(struct device *dev)
{
struct pci_dev *pci = to_pci_dev(dev);
@ -236,28 +216,24 @@ static int dwc3_pci_resume(struct device *dev)
return 0;
}
#endif /* CONFIG_PM_SLEEP */
static const struct dev_pm_ops dwc3_pci_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume)
};
#define DEV_PM_OPS (&dwc3_pci_dev_pm_ops)
#else
#define DEV_PM_OPS NULL
#endif /* CONFIG_PM */
static struct pci_driver dwc3_pci_driver = {
.name = "dwc3-pci",
.id_table = dwc3_pci_id_table,
.probe = dwc3_pci_probe,
.remove = dwc3_pci_remove,
.driver = {
.pm = DEV_PM_OPS,
.pm = &dwc3_pci_dev_pm_ops,
},
};
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("DesignWare USB3 PCI Glue Layer");
module_pci_driver(dwc3_pci_driver);

View File

@ -6,34 +6,14 @@
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the above-listed copyright holders may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2, as published by the Free
* Software Foundation.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
@ -168,6 +148,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
direction = !dwc->ep0_expect_in;
dwc->delayed_status = false;
usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED);
if (dwc->ep0state == EP0_STATUS_PHASE)
__dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
@ -553,8 +534,16 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
ret = dwc3_ep0_delegate_req(dwc, ctrl);
/* if the cfg matches and the cfg is non zero */
if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
usb_gadget_set_state(&dwc->gadget,
USB_STATE_CONFIGURED);
/*
* only change state if set_config has already
* been processed. If gadget driver returns
* USB_GADGET_DELAYED_STATUS, we will wait
* to change the state on the next usb_ep_queue()
*/
if (ret == 0)
usb_gadget_set_state(&dwc->gadget,
USB_STATE_CONFIGURED);
/*
* Enable transition to U1/U2 state when
@ -571,7 +560,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
case USB_STATE_CONFIGURED:
ret = dwc3_ep0_delegate_req(dwc, ctrl);
if (!cfg)
if (!cfg && !ret)
usb_gadget_set_state(&dwc->gadget,
USB_STATE_ADDRESS);
break;

View File

@ -6,34 +6,14 @@
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the above-listed copyright holders may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2, as published by the Free
* Software Foundation.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
@ -520,6 +500,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
u32 reg;
int ret = -ENOMEM;
dev_vdbg(dwc->dev, "Enabling %s\n", dep->name);
if (!(dep->flags & DWC3_EP_ENABLED)) {
ret = dwc3_gadget_start_config(dwc, dep);
if (ret)
@ -676,8 +658,6 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep,
dev_err(dwc->dev, "invalid endpoint transfer type\n");
}
dev_vdbg(dwc->dev, "Enabling %s\n", dep->name);
spin_lock_irqsave(&dwc->lock, flags);
ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc, false);
spin_unlock_irqrestore(&dwc->lock, flags);
@ -1508,6 +1488,15 @@ static int dwc3_gadget_start(struct usb_gadget *g,
int irq;
u32 reg;
irq = platform_get_irq(to_platform_device(dwc->dev), 0);
ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
IRQF_SHARED, "dwc3", dwc);
if (ret) {
dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
irq, ret);
goto err0;
}
spin_lock_irqsave(&dwc->lock, flags);
if (dwc->gadget_driver) {
@ -1515,7 +1504,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
dwc->gadget.name,
dwc->gadget_driver->driver.name);
ret = -EBUSY;
goto err0;
goto err1;
}
dwc->gadget_driver = driver;
@ -1536,10 +1525,25 @@ static int dwc3_gadget_start(struct usb_gadget *g,
* STAR#9000525659: Clock Domain Crossing on DCTL in
* USB 2.0 Mode
*/
if (dwc->revision < DWC3_REVISION_220A)
if (dwc->revision < DWC3_REVISION_220A) {
reg |= DWC3_DCFG_SUPERSPEED;
else
reg |= dwc->maximum_speed;
} else {
switch (dwc->maximum_speed) {
case USB_SPEED_LOW:
reg |= DWC3_DSTS_LOWSPEED;
break;
case USB_SPEED_FULL:
reg |= DWC3_DSTS_FULLSPEED1;
break;
case USB_SPEED_HIGH:
reg |= DWC3_DSTS_HIGHSPEED;
break;
case USB_SPEED_SUPER: /* FALLTHROUGH */
case USB_SPEED_UNKNOWN: /* FALTHROUGH */
default:
reg |= DWC3_DSTS_SUPERSPEED;
}
}
dwc3_writel(dwc->regs, DWC3_DCFG, reg);
dwc->start_config_issued = false;
@ -1551,42 +1555,38 @@ static int dwc3_gadget_start(struct usb_gadget *g,
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
if (ret) {
dev_err(dwc->dev, "failed to enable %s\n", dep->name);
goto err0;
goto err2;
}
dep = dwc->eps[1];
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
if (ret) {
dev_err(dwc->dev, "failed to enable %s\n", dep->name);
goto err1;
goto err3;
}
/* begin to receive SETUP packets */
dwc->ep0state = EP0_SETUP_PHASE;
dwc3_ep0_out_start(dwc);
irq = platform_get_irq(to_platform_device(dwc->dev), 0);
ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
if (ret) {
dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
irq, ret);
goto err1;
}
dwc3_gadget_enable_irq(dwc);
spin_unlock_irqrestore(&dwc->lock, flags);
return 0;
err1:
err3:
__dwc3_gadget_ep_disable(dwc->eps[0]);
err0:
err2:
dwc->gadget_driver = NULL;
err1:
spin_unlock_irqrestore(&dwc->lock, flags);
free_irq(irq, dwc);
err0:
return ret;
}
@ -1600,9 +1600,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
spin_lock_irqsave(&dwc->lock, flags);
dwc3_gadget_disable_irq(dwc);
irq = platform_get_irq(to_platform_device(dwc->dev), 0);
free_irq(irq, dwc);
__dwc3_gadget_ep_disable(dwc->eps[0]);
__dwc3_gadget_ep_disable(dwc->eps[1]);
@ -1610,6 +1607,9 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
spin_unlock_irqrestore(&dwc->lock, flags);
irq = platform_get_irq(to_platform_device(dwc->dev), 0);
free_irq(irq, dwc);
return 0;
}
@ -1642,13 +1642,15 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
dep->dwc = dwc;
dep->number = epnum;
dep->direction = !!direction;
dwc->eps[epnum] = dep;
snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,
(epnum & 1) ? "in" : "out");
dep->endpoint.name = dep->name;
dep->direction = (epnum & 1);
dev_vdbg(dwc->dev, "initializing %s\n", dep->name);
if (epnum == 0 || epnum == 1) {
dep->endpoint.maxpacket = 512;
@ -2105,34 +2107,6 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
dwc->setup_packet_pending = false;
}
static void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend)
{
u32 reg;
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
if (suspend)
reg |= DWC3_GUSB3PIPECTL_SUSPHY;
else
reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
}
static void dwc3_gadget_usb2_phy_suspend(struct dwc3 *dwc, int suspend)
{
u32 reg;
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
if (suspend)
reg |= DWC3_GUSB2PHYCFG_SUSPHY;
else
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
}
static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
{
u32 reg;
@ -2173,13 +2147,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
/* after reset -> Default State */
usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
/* Recent versions support automatic phy suspend and don't need this */
if (dwc->revision < DWC3_REVISION_194A) {
/* Resume PHYs */
dwc3_gadget_usb2_phy_suspend(dwc, false);
dwc3_gadget_usb3_phy_suspend(dwc, false);
}
if (dwc->gadget.speed != USB_SPEED_UNKNOWN)
dwc3_disconnect_gadget(dwc);
@ -2223,20 +2190,6 @@ static void dwc3_update_ram_clk_sel(struct dwc3 *dwc, u32 speed)
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
}
static void dwc3_gadget_phy_suspend(struct dwc3 *dwc, u8 speed)
{
switch (speed) {
case USB_SPEED_SUPER:
dwc3_gadget_usb2_phy_suspend(dwc, true);
break;
case USB_SPEED_HIGH:
case USB_SPEED_FULL:
case USB_SPEED_LOW:
dwc3_gadget_usb3_phy_suspend(dwc, true);
break;
}
}
static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
{
struct dwc3_ep *dep;
@ -2312,12 +2265,6 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
}
/* Recent versions support automatic phy suspend and don't need this */
if (dwc->revision < DWC3_REVISION_194A) {
/* Suspend unneeded PHY */
dwc3_gadget_phy_suspend(dwc, dwc->gadget.speed);
}
dep = dwc->eps[0];
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true);
if (ret) {
@ -2495,6 +2442,53 @@ static void dwc3_process_event_entry(struct dwc3 *dwc,
}
}
static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
{
struct dwc3_event_buffer *evt;
irqreturn_t ret = IRQ_NONE;
int left;
u32 reg;
evt = dwc->ev_buffs[buf];
left = evt->count;
if (!(evt->flags & DWC3_EVENT_PENDING))
return IRQ_NONE;
while (left > 0) {
union dwc3_event event;
event.raw = *(u32 *) (evt->buf + evt->lpos);
dwc3_process_event_entry(dwc, &event);
/*
* FIXME we wrap around correctly to the next entry as
* almost all entries are 4 bytes in size. There is one
* entry which has 12 bytes which is a regular entry
* followed by 8 bytes data. ATM I don't know how
* things are organized if we get next to the a
* boundary so I worry about that once we try to handle
* that.
*/
evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
left -= 4;
dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4);
}
evt->count = 0;
evt->flags &= ~DWC3_EVENT_PENDING;
ret = IRQ_HANDLED;
/* Unmask interrupt */
reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(buf));
reg &= ~DWC3_GEVNTSIZ_INTMASK;
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(buf), reg);
return ret;
}
static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
{
struct dwc3 *dwc = _dwc;
@ -2504,52 +2498,19 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
spin_lock_irqsave(&dwc->lock, flags);
for (i = 0; i < dwc->num_event_buffers; i++) {
struct dwc3_event_buffer *evt;
int left;
evt = dwc->ev_buffs[i];
left = evt->count;
if (!(evt->flags & DWC3_EVENT_PENDING))
continue;
while (left > 0) {
union dwc3_event event;
event.raw = *(u32 *) (evt->buf + evt->lpos);
dwc3_process_event_entry(dwc, &event);
/*
* FIXME we wrap around correctly to the next entry as
* almost all entries are 4 bytes in size. There is one
* entry which has 12 bytes which is a regular entry
* followed by 8 bytes data. ATM I don't know how
* things are organized if we get next to the a
* boundary so I worry about that once we try to handle
* that.
*/
evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
left -= 4;
dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(i), 4);
}
evt->count = 0;
evt->flags &= ~DWC3_EVENT_PENDING;
ret = IRQ_HANDLED;
}
for (i = 0; i < dwc->num_event_buffers; i++)
ret |= dwc3_process_event_buf(dwc, i);
spin_unlock_irqrestore(&dwc->lock, flags);
return ret;
}
static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc, u32 buf)
{
struct dwc3_event_buffer *evt;
u32 count;
u32 reg;
evt = dwc->ev_buffs[buf];
@ -2561,6 +2522,11 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
evt->count = count;
evt->flags |= DWC3_EVENT_PENDING;
/* Mask interrupt */
reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(buf));
reg |= DWC3_GEVNTSIZ_INTMASK;
dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(buf), reg);
return IRQ_WAKE_THREAD;
}
@ -2575,7 +2541,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
for (i = 0; i < dwc->num_event_buffers; i++) {
irqreturn_t status;
status = dwc3_process_event_buf(dwc, i);
status = dwc3_check_event_buf(dwc, i);
if (status == IRQ_WAKE_THREAD)
ret = status;
}
@ -2593,7 +2559,6 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
*/
int dwc3_gadget_init(struct dwc3 *dwc)
{
u32 reg;
int ret;
dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
@ -2643,16 +2608,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
if (ret)
goto err4;
reg = dwc3_readl(dwc->regs, DWC3_DCFG);
reg |= DWC3_DCFG_LPM_CAP;
dwc3_writel(dwc->regs, DWC3_DCFG, reg);
/* Enable USB2 LPM and automatic phy suspend only on recent versions */
if (dwc->revision >= DWC3_REVISION_194A) {
dwc3_gadget_usb2_phy_suspend(dwc, false);
dwc3_gadget_usb3_phy_suspend(dwc, false);
}
ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
if (ret) {
dev_err(dwc->dev, "failed to register udc\n");

View File

@ -6,34 +6,14 @@
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the above-listed copyright holders may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2, as published by the Free
* Software Foundation.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __DRIVERS_USB_DWC3_GADGET_H

View File

@ -5,34 +5,14 @@
*
* Authors: Felipe Balbi <balbi@ti.com>,
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the above-listed copyright holders may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2, as published by the Free
* Software Foundation.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/platform_device.h>

View File

@ -6,34 +6,14 @@
* Authors: Felipe Balbi <balbi@ti.com>,
* Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the above-listed copyright holders may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2, as published by the Free
* Software Foundation.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __DRIVERS_USB_DWC3_IO_H

View File

@ -0,0 +1,27 @@
/**
* platform_data.h - USB DWC3 Platform Data Support
*
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
* Author: Felipe Balbi <balbi@ti.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/usb/ch9.h>
#include <linux/usb/otg.h>
struct dwc3_platform_data {
enum usb_device_speed maximum_speed;
enum usb_dr_mode dr_mode;
bool tx_fifo_resize;
};

View File

@ -144,7 +144,6 @@ config USB_AT91
config USB_LPC32XX
tristate "LPC32XX USB Peripheral Controller"
depends on ARCH_LPC32XX
depends on USB_PHY
select USB_ISP1301
help
This option selects the USB device controller in the LPC32xx SoC.
@ -206,7 +205,6 @@ config USB_FOTG210_UDC
config USB_OMAP
tristate "OMAP USB Device Controller"
depends on ARCH_OMAP1
depends on USB_PHY
select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
help
Many Texas Instruments OMAP processors have flexible full
@ -287,21 +285,6 @@ config USB_S3C_HSOTG
The Samsung S3C64XX USB2.0 high-speed gadget controller
integrated into the S3C64XX series SoC.
config USB_IMX
tristate "Freescale i.MX1 USB Peripheral Controller"
depends on ARCH_MXC
depends on BROKEN
help
Freescale's i.MX1 includes an integrated full speed
USB 1.1 device controller.
It has Six fixed-function endpoints, as well as endpoint
zero (for control transfers).
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "imx_udc" and force all
gadget drivers to also be dynamically linked.
config USB_S3C2410
tristate "S3C2410 USB Device Controller"
depends on ARCH_S3C24XX

View File

@ -13,7 +13,6 @@ obj-$(CONFIG_USB_NET2280) += net2280.o
obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc.o
obj-$(CONFIG_USB_PXA25X) += pxa25x_udc.o
obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o
obj-$(CONFIG_USB_IMX) += imx_udc.o
obj-$(CONFIG_USB_GOKU) += goku_udc.o
obj-$(CONFIG_USB_OMAP) += omap_udc.o
obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o

View File

@ -1122,7 +1122,7 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
goto finished;
}
if (ep->dma) {
retval = prep_dma(ep, req, gfp);
retval = prep_dma(ep, req, GFP_ATOMIC);
if (retval != 0)
goto finished;
/* write desc pointer to enable DMA */
@ -1190,7 +1190,7 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
* for PPB modes, because of chain creation reasons
*/
if (ep->in) {
retval = prep_dma(ep, req, gfp);
retval = prep_dma(ep, req, GFP_ATOMIC);
if (retval != 0)
goto finished;
}

View File

@ -870,6 +870,11 @@ static void clk_on(struct at91_udc *udc)
if (udc->clocked)
return;
udc->clocked = 1;
if (IS_ENABLED(CONFIG_COMMON_CLK)) {
clk_set_rate(udc->uclk, 48000000);
clk_prepare_enable(udc->uclk);
}
clk_prepare_enable(udc->iclk);
clk_prepare_enable(udc->fclk);
}
@ -882,6 +887,8 @@ static void clk_off(struct at91_udc *udc)
udc->gadget.speed = USB_SPEED_UNKNOWN;
clk_disable_unprepare(udc->fclk);
clk_disable_unprepare(udc->iclk);
if (IS_ENABLED(CONFIG_COMMON_CLK))
clk_disable_unprepare(udc->uclk);
}
/*
@ -1697,7 +1704,7 @@ static int at91udc_probe(struct platform_device *pdev)
int retval;
struct resource *res;
if (!dev->platform_data && !pdev->dev.of_node) {
if (!dev_get_platdata(dev) && !pdev->dev.of_node) {
/* small (so we copy it) but critical! */
DBG("missing platform_data\n");
return -ENODEV;
@ -1728,7 +1735,7 @@ static int at91udc_probe(struct platform_device *pdev)
if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
at91udc_of_init(udc, pdev->dev.of_node);
else
memcpy(&udc->board, dev->platform_data,
memcpy(&udc->board, dev_get_platdata(dev),
sizeof(struct at91_udc_data));
udc->pdev = pdev;
udc->enabled = 0;
@ -1774,10 +1781,12 @@ static int at91udc_probe(struct platform_device *pdev)
/* get interface and function clocks */
udc->iclk = clk_get(dev, "udc_clk");
udc->fclk = clk_get(dev, "udpck");
if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) {
if (IS_ENABLED(CONFIG_COMMON_CLK))
udc->uclk = clk_get(dev, "usb_clk");
if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk) ||
(IS_ENABLED(CONFIG_COMMON_CLK) && IS_ERR(udc->uclk))) {
DBG("clocks missing\n");
retval = -ENODEV;
/* NOTE: we "know" here that refcounts on these are NOPs */
goto fail1;
}
@ -1851,6 +1860,12 @@ fail3:
fail2:
free_irq(udc->udp_irq, udc);
fail1:
if (IS_ENABLED(CONFIG_COMMON_CLK) && !IS_ERR(udc->uclk))
clk_put(udc->uclk);
if (!IS_ERR(udc->fclk))
clk_put(udc->fclk);
if (!IS_ERR(udc->iclk))
clk_put(udc->iclk);
iounmap(udc->udp_baseaddr);
fail0a:
if (cpu_is_at91rm9200())
@ -1894,6 +1909,8 @@ static int __exit at91udc_remove(struct platform_device *pdev)
clk_put(udc->iclk);
clk_put(udc->fclk);
if (IS_ENABLED(CONFIG_COMMON_CLK))
clk_put(udc->uclk);
return 0;
}

View File

@ -126,7 +126,7 @@ struct at91_udc {
unsigned active_suspend:1;
u8 addr;
struct at91_udc_data board;
struct clk *iclk, *fclk;
struct clk *iclk, *fclk, *uclk;
struct platform_device *pdev;
struct proc_dir_entry *pde;
void __iomem *udp_baseaddr;

View File

@ -1772,6 +1772,7 @@ out:
static int atmel_usba_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver)
{
int ret = 0;
struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget);
unsigned long flags;
@ -1781,8 +1782,14 @@ static int atmel_usba_start(struct usb_gadget *gadget,
udc->driver = driver;
spin_unlock_irqrestore(&udc->lock, flags);
clk_enable(udc->pclk);
clk_enable(udc->hclk);
ret = clk_prepare_enable(udc->pclk);
if (ret)
goto out;
ret = clk_prepare_enable(udc->hclk);
if (ret) {
clk_disable_unprepare(udc->pclk);
goto out;
}
DBG(DBG_GADGET, "registered driver `%s'\n", driver->driver.name);
@ -1797,9 +1804,11 @@ static int atmel_usba_start(struct usb_gadget *gadget,
usba_writel(udc, CTRL, USBA_ENABLE_MASK);
usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
}
out:
spin_unlock_irqrestore(&udc->lock, flags);
return 0;
return ret;
}
static int atmel_usba_stop(struct usb_gadget *gadget,
@ -1822,8 +1831,8 @@ static int atmel_usba_stop(struct usb_gadget *gadget,
udc->driver = NULL;
clk_disable(udc->hclk);
clk_disable(udc->pclk);
clk_disable_unprepare(udc->hclk);
clk_disable_unprepare(udc->pclk);
DBG(DBG_GADGET, "unregistered driver `%s'\n", driver->driver.name);
@ -1922,7 +1931,7 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
static struct usba_ep * usba_udc_pdata(struct platform_device *pdev,
struct usba_udc *udc)
{
struct usba_platform_data *pdata = pdev->dev.platform_data;
struct usba_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct usba_ep *eps;
int i;
@ -2022,10 +2031,14 @@ static int __init usba_udc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, udc);
/* Make sure we start from a clean slate */
clk_enable(pclk);
ret = clk_prepare_enable(pclk);
if (ret) {
dev_err(&pdev->dev, "Unable to enable pclk, aborting.\n");
goto err_clk_enable;
}
toggle_bias(0);
usba_writel(udc, CTRL, USBA_DISABLE_MASK);
clk_disable(pclk);
clk_disable_unprepare(pclk);
if (pdev->dev.of_node)
udc->usba_ep = atmel_udc_of_init(pdev, udc);
@ -2081,6 +2094,7 @@ err_add_udc:
free_irq(irq, udc);
err_request_irq:
err_alloc_ep:
err_clk_enable:
iounmap(udc->fifo);
err_map_fifo:
iounmap(udc->regs);

View File

@ -2313,7 +2313,7 @@ static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc)
static int bcm63xx_udc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct bcm63xx_usbd_platform_data *pd = dev->platform_data;
struct bcm63xx_usbd_platform_data *pd = dev_get_platdata(dev);
struct bcm63xx_udc *udc;
struct resource *res;
int rc = -ENOMEM, i, irq;

View File

@ -3043,12 +3043,12 @@ fsg_config_from_params(struct fsg_config *cfg,
lun->filename =
params->file_count > i && params->file[i][0]
? params->file[i]
: 0;
: NULL;
}
/* Let MSF use defaults */
cfg->vendor_name = 0;
cfg->product_name = 0;
cfg->vendor_name = NULL;
cfg->product_name = NULL;
cfg->ops = NULL;
cfg->private_data = NULL;

View File

@ -695,7 +695,7 @@ static int generic_get_cmd(struct usb_audio_control *con, u8 cmd)
}
/* Todo: add more control selecotor dynamically */
int __init control_selector_init(struct f_audio *audio)
static int __init control_selector_init(struct f_audio *audio)
{
INIT_LIST_HEAD(&audio->cs);
list_add(&feature_unit.list, &audio->cs);
@ -719,7 +719,7 @@ int __init control_selector_init(struct f_audio *audio)
*
* Returns zero on success, else negative errno.
*/
int __init audio_bind_config(struct usb_configuration *c)
static int __init audio_bind_config(struct usb_configuration *c)
{
struct f_audio *audio;
int status;

View File

@ -33,7 +33,7 @@ int fsl_udc_clk_init(struct platform_device *pdev)
unsigned long freq;
int ret;
pdata = pdev->dev.platform_data;
pdata = dev_get_platdata(&pdev->dev);
mxc_ipg_clk = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(mxc_ipg_clk)) {
@ -80,7 +80,7 @@ eclkrate:
int fsl_udc_clk_finalize(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
int ret = 0;
/* workaround ENGcm09152 for i.MX35 */

View File

@ -2248,7 +2248,7 @@ static int __init struct_udc_setup(struct fsl_udc *udc,
struct fsl_usb2_platform_data *pdata;
size_t size;
pdata = pdev->dev.platform_data;
pdata = dev_get_platdata(&pdev->dev);
udc->phy_mode = pdata->phy_mode;
udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL);
@ -2343,7 +2343,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
return -ENOMEM;
}
pdata = pdev->dev.platform_data;
pdata = dev_get_platdata(&pdev->dev);
udc_controller->pdata = pdata;
spin_lock_init(&udc_controller->lock);
udc_controller->stopped = 1;
@ -2524,7 +2524,7 @@ err_kfree:
static int __exit fsl_udc_remove(struct platform_device *pdev)
{
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
DECLARE_COMPLETION(done);

View File

@ -557,7 +557,7 @@ static void fusb300_set_cxdone(struct fusb300 *fusb300)
}
/* read data from cx fifo */
void fusb300_rdcxf(struct fusb300 *fusb300,
static void fusb300_rdcxf(struct fusb300 *fusb300,
u8 *buffer, u32 length)
{
int i = 0;

View File

@ -772,7 +772,7 @@ goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
} /* else pio or dma irq handler advances the queue. */
if (likely(req != 0))
if (likely(req != NULL))
list_add_tail(&req->queue, &ep->queue);
if (likely(!list_empty(&ep->queue))

View File

@ -185,7 +185,7 @@ static int __exit hid_unbind(struct usb_composite_dev *cdev)
static int __init hidg_plat_driver_probe(struct platform_device *pdev)
{
struct hidg_func_descriptor *func = pdev->dev.platform_data;
struct hidg_func_descriptor *func = dev_get_platdata(&pdev->dev);
struct hidg_func_node *entry;
if (!func) {

File diff suppressed because it is too large Load Diff

View File

@ -1,351 +0,0 @@
/*
* Copyright (C) 2005 Mike Lee(eemike@gmail.com)
*
* This udc driver is now under testing and code is based on pxa2xx_udc.h
* Please use it with your own risk!
*
* 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.
*/
#ifndef __LINUX_USB_GADGET_IMX_H
#define __LINUX_USB_GADGET_IMX_H
#include <linux/types.h>
/* Helper macros */
#define EP_NO(ep) ((ep->bEndpointAddress) & ~USB_DIR_IN) /* IN:1, OUT:0 */
#define EP_DIR(ep) ((ep->bEndpointAddress) & USB_DIR_IN ? 1 : 0)
#define IMX_USB_NB_EP 6
/* Driver structures */
struct imx_request {
struct usb_request req;
struct list_head queue;
unsigned int in_use;
};
enum ep0_state {
EP0_IDLE,
EP0_IN_DATA_PHASE,
EP0_OUT_DATA_PHASE,
EP0_CONFIG,
EP0_STALL,
};
struct imx_ep_struct {
struct usb_ep ep;
struct imx_udc_struct *imx_usb;
struct list_head queue;
unsigned char stopped;
unsigned char fifosize;
unsigned char bEndpointAddress;
unsigned char bmAttributes;
};
struct imx_udc_struct {
struct usb_gadget gadget;
struct usb_gadget_driver *driver;
struct device *dev;
struct imx_ep_struct imx_ep[IMX_USB_NB_EP];
struct clk *clk;
struct timer_list timer;
enum ep0_state ep0state;
struct resource *res;
void __iomem *base;
unsigned char set_config;
int cfg,
intf,
alt,
usbd_int[7];
};
/* USB registers */
#define USB_FRAME (0x00) /* USB frame */
#define USB_SPEC (0x04) /* USB Spec */
#define USB_STAT (0x08) /* USB Status */
#define USB_CTRL (0x0C) /* USB Control */
#define USB_DADR (0x10) /* USB Desc RAM addr */
#define USB_DDAT (0x14) /* USB Desc RAM/EP buffer data */
#define USB_INTR (0x18) /* USB interrupt */
#define USB_MASK (0x1C) /* USB Mask */
#define USB_ENAB (0x24) /* USB Enable */
#define USB_EP_STAT(x) (0x30 + (x*0x30)) /* USB status/control */
#define USB_EP_INTR(x) (0x34 + (x*0x30)) /* USB interrupt */
#define USB_EP_MASK(x) (0x38 + (x*0x30)) /* USB mask */
#define USB_EP_FDAT(x) (0x3C + (x*0x30)) /* USB FIFO data */
#define USB_EP_FDAT0(x) (0x3C + (x*0x30)) /* USB FIFO data */
#define USB_EP_FDAT1(x) (0x3D + (x*0x30)) /* USB FIFO data */
#define USB_EP_FDAT2(x) (0x3E + (x*0x30)) /* USB FIFO data */
#define USB_EP_FDAT3(x) (0x3F + (x*0x30)) /* USB FIFO data */
#define USB_EP_FSTAT(x) (0x40 + (x*0x30)) /* USB FIFO status */
#define USB_EP_FCTRL(x) (0x44 + (x*0x30)) /* USB FIFO control */
#define USB_EP_LRFP(x) (0x48 + (x*0x30)) /* USB last rd f. pointer */
#define USB_EP_LWFP(x) (0x4C + (x*0x30)) /* USB last wr f. pointer */
#define USB_EP_FALRM(x) (0x50 + (x*0x30)) /* USB FIFO alarm */
#define USB_EP_FRDP(x) (0x54 + (x*0x30)) /* USB FIFO read pointer */
#define USB_EP_FWRP(x) (0x58 + (x*0x30)) /* USB FIFO write pointer */
/* USB Control Register Bit Fields.*/
#define CTRL_CMDOVER (1<<6) /* UDC status */
#define CTRL_CMDERROR (1<<5) /* UDC status */
#define CTRL_FE_ENA (1<<3) /* Enable Font End logic */
#define CTRL_UDC_RST (1<<2) /* UDC reset */
#define CTRL_AFE_ENA (1<<1) /* Analog Font end enable */
#define CTRL_RESUME (1<<0) /* UDC resume */
/* USB Status Register Bit Fields.*/
#define STAT_RST (1<<8)
#define STAT_SUSP (1<<7)
#define STAT_CFG (3<<5)
#define STAT_INTF (3<<3)
#define STAT_ALTSET (7<<0)
/* USB Interrupt Status/Mask Registers Bit fields */
#define INTR_WAKEUP (1<<31) /* Wake up Interrupt */
#define INTR_MSOF (1<<7) /* Missed Start of Frame */
#define INTR_SOF (1<<6) /* Start of Frame */
#define INTR_RESET_STOP (1<<5) /* Reset Signaling stop */
#define INTR_RESET_START (1<<4) /* Reset Signaling start */
#define INTR_RESUME (1<<3) /* Suspend to resume */
#define INTR_SUSPEND (1<<2) /* Active to suspend */
#define INTR_FRAME_MATCH (1<<1) /* Frame matched */
#define INTR_CFG_CHG (1<<0) /* Configuration change occurred */
/* USB Enable Register Bit Fields.*/
#define ENAB_RST (1<<31) /* Reset USB modules */
#define ENAB_ENAB (1<<30) /* Enable USB modules*/
#define ENAB_SUSPEND (1<<29) /* Suspend USB modules */
#define ENAB_ENDIAN (1<<28) /* Endian of USB modules */
#define ENAB_PWRMD (1<<0) /* Power mode of USB modules */
/* USB Descriptor Ram Address Register bit fields */
#define DADR_CFG (1<<31) /* Configuration */
#define DADR_BSY (1<<30) /* Busy status */
#define DADR_DADR (0x1FF) /* Descriptor Ram Address */
/* USB Descriptor RAM/Endpoint Buffer Data Register bit fields */
#define DDAT_DDAT (0xFF) /* Descriptor Endpoint Buffer */
/* USB Endpoint Status Register bit fields */
#define EPSTAT_BCOUNT (0x7F<<16) /* Endpoint FIFO byte count */
#define EPSTAT_SIP (1<<8) /* Endpoint setup in progress */
#define EPSTAT_DIR (1<<7) /* Endpoint transfer direction */
#define EPSTAT_MAX (3<<5) /* Endpoint Max packet size */
#define EPSTAT_TYP (3<<3) /* Endpoint type */
#define EPSTAT_ZLPS (1<<2) /* Send zero length packet */
#define EPSTAT_FLUSH (1<<1) /* Endpoint FIFO Flush */
#define EPSTAT_STALL (1<<0) /* Force stall */
/* USB Endpoint FIFO Status Register bit fields */
#define FSTAT_FRAME_STAT (0xF<<24) /* Frame status bit [0-3] */
#define FSTAT_ERR (1<<22) /* FIFO error */
#define FSTAT_UF (1<<21) /* FIFO underflow */
#define FSTAT_OF (1<<20) /* FIFO overflow */
#define FSTAT_FR (1<<19) /* FIFO frame ready */
#define FSTAT_FULL (1<<18) /* FIFO full */
#define FSTAT_ALRM (1<<17) /* FIFO alarm */
#define FSTAT_EMPTY (1<<16) /* FIFO empty */
/* USB Endpoint FIFO Control Register bit fields */
#define FCTRL_WFR (1<<29) /* Write frame end */
/* USB Endpoint Interrupt Status Regsiter bit fields */
#define EPINTR_FIFO_FULL (1<<8) /* fifo full */
#define EPINTR_FIFO_EMPTY (1<<7) /* fifo empty */
#define EPINTR_FIFO_ERROR (1<<6) /* fifo error */
#define EPINTR_FIFO_HIGH (1<<5) /* fifo high */
#define EPINTR_FIFO_LOW (1<<4) /* fifo low */
#define EPINTR_MDEVREQ (1<<3) /* multi Device request */
#define EPINTR_EOT (1<<2) /* fifo end of transfer */
#define EPINTR_DEVREQ (1<<1) /* Device request */
#define EPINTR_EOF (1<<0) /* fifo end of frame */
/* Debug macros */
#ifdef DEBUG
/* #define DEBUG_REQ */
/* #define DEBUG_TRX */
/* #define DEBUG_INIT */
/* #define DEBUG_EP0 */
/* #define DEBUG_EPX */
/* #define DEBUG_IRQ */
/* #define DEBUG_EPIRQ */
/* #define DEBUG_DUMP */
/* #define DEBUG_ERR */
#ifdef DEBUG_REQ
#define D_REQ(dev, args...) dev_dbg(dev, ## args)
#else
#define D_REQ(dev, args...) do {} while (0)
#endif /* DEBUG_REQ */
#ifdef DEBUG_TRX
#define D_TRX(dev, args...) dev_dbg(dev, ## args)
#else
#define D_TRX(dev, args...) do {} while (0)
#endif /* DEBUG_TRX */
#ifdef DEBUG_INIT
#define D_INI(dev, args...) dev_dbg(dev, ## args)
#else
#define D_INI(dev, args...) do {} while (0)
#endif /* DEBUG_INIT */
#ifdef DEBUG_EP0
static const char *state_name[] = {
"EP0_IDLE",
"EP0_IN_DATA_PHASE",
"EP0_OUT_DATA_PHASE",
"EP0_CONFIG",
"EP0_STALL"
};
#define D_EP0(dev, args...) dev_dbg(dev, ## args)
#else
#define D_EP0(dev, args...) do {} while (0)
#endif /* DEBUG_EP0 */
#ifdef DEBUG_EPX
#define D_EPX(dev, args...) dev_dbg(dev, ## args)
#else
#define D_EPX(dev, args...) do {} while (0)
#endif /* DEBUG_EP0 */
#ifdef DEBUG_IRQ
static void dump_intr(const char *label, int irqreg, struct device *dev)
{
dev_dbg(dev, "<%s> USB_INTR=[%s%s%s%s%s%s%s%s%s]\n", label,
(irqreg & INTR_WAKEUP) ? " wake" : "",
(irqreg & INTR_MSOF) ? " msof" : "",
(irqreg & INTR_SOF) ? " sof" : "",
(irqreg & INTR_RESUME) ? " resume" : "",
(irqreg & INTR_SUSPEND) ? " suspend" : "",
(irqreg & INTR_RESET_STOP) ? " noreset" : "",
(irqreg & INTR_RESET_START) ? " reset" : "",
(irqreg & INTR_FRAME_MATCH) ? " fmatch" : "",
(irqreg & INTR_CFG_CHG) ? " config" : "");
}
#else
#define dump_intr(x, y, z) do {} while (0)
#endif /* DEBUG_IRQ */
#ifdef DEBUG_EPIRQ
static void dump_ep_intr(const char *label, int nr, int irqreg,
struct device *dev)
{
dev_dbg(dev, "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, nr,
(irqreg & EPINTR_FIFO_FULL) ? " full" : "",
(irqreg & EPINTR_FIFO_EMPTY) ? " fempty" : "",
(irqreg & EPINTR_FIFO_ERROR) ? " ferr" : "",
(irqreg & EPINTR_FIFO_HIGH) ? " fhigh" : "",
(irqreg & EPINTR_FIFO_LOW) ? " flow" : "",
(irqreg & EPINTR_MDEVREQ) ? " mreq" : "",
(irqreg & EPINTR_EOF) ? " eof" : "",
(irqreg & EPINTR_DEVREQ) ? " devreq" : "",
(irqreg & EPINTR_EOT) ? " eot" : "");
}
#else
#define dump_ep_intr(x, y, z, i) do {} while (0)
#endif /* DEBUG_IRQ */
#ifdef DEBUG_DUMP
static void dump_usb_stat(const char *label,
struct imx_udc_struct *imx_usb)
{
int temp = __raw_readl(imx_usb->base + USB_STAT);
dev_dbg(imx_usb->dev,
"<%s> USB_STAT=[%s%s CFG=%d, INTF=%d, ALTR=%d]\n", label,
(temp & STAT_RST) ? " reset" : "",
(temp & STAT_SUSP) ? " suspend" : "",
(temp & STAT_CFG) >> 5,
(temp & STAT_INTF) >> 3,
(temp & STAT_ALTSET));
}
static void dump_ep_stat(const char *label,
struct imx_ep_struct *imx_ep)
{
int temp = __raw_readl(imx_ep->imx_usb->base
+ USB_EP_INTR(EP_NO(imx_ep)));
dev_dbg(imx_ep->imx_usb->dev,
"<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n",
label, EP_NO(imx_ep),
(temp & EPINTR_FIFO_FULL) ? " full" : "",
(temp & EPINTR_FIFO_EMPTY) ? " fempty" : "",
(temp & EPINTR_FIFO_ERROR) ? " ferr" : "",
(temp & EPINTR_FIFO_HIGH) ? " fhigh" : "",
(temp & EPINTR_FIFO_LOW) ? " flow" : "",
(temp & EPINTR_MDEVREQ) ? " mreq" : "",
(temp & EPINTR_EOF) ? " eof" : "",
(temp & EPINTR_DEVREQ) ? " devreq" : "",
(temp & EPINTR_EOT) ? " eot" : "");
temp = __raw_readl(imx_ep->imx_usb->base
+ USB_EP_STAT(EP_NO(imx_ep)));
dev_dbg(imx_ep->imx_usb->dev,
"<%s> EP%d_STAT=[%s%s bcount=%d]\n",
label, EP_NO(imx_ep),
(temp & EPSTAT_SIP) ? " sip" : "",
(temp & EPSTAT_STALL) ? " stall" : "",
(temp & EPSTAT_BCOUNT) >> 16);
temp = __raw_readl(imx_ep->imx_usb->base
+ USB_EP_FSTAT(EP_NO(imx_ep)));
dev_dbg(imx_ep->imx_usb->dev,
"<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n",
label, EP_NO(imx_ep),
(temp & FSTAT_ERR) ? " ferr" : "",
(temp & FSTAT_UF) ? " funder" : "",
(temp & FSTAT_OF) ? " fover" : "",
(temp & FSTAT_FR) ? " fready" : "",
(temp & FSTAT_FULL) ? " ffull" : "",
(temp & FSTAT_ALRM) ? " falarm" : "",
(temp & FSTAT_EMPTY) ? " fempty" : "");
}
static void dump_req(const char *label, struct imx_ep_struct *imx_ep,
struct usb_request *req)
{
int i;
if (!req || !req->buf) {
dev_dbg(imx_ep->imx_usb->dev,
"<%s> req or req buf is free\n", label);
return;
}
if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state
== EP0_IN_DATA_PHASE)
|| (EP_NO(imx_ep) && EP_DIR(imx_ep))) {
dev_dbg(imx_ep->imx_usb->dev,
"<%s> request dump <", label);
for (i = 0; i < req->length; i++)
printk("%02x-", *((u8 *)req->buf + i));
printk(">\n");
}
}
#else
#define dump_ep_stat(x, y) do {} while (0)
#define dump_usb_stat(x, y) do {} while (0)
#define dump_req(x, y, z) do {} while (0)
#endif /* DEBUG_DUMP */
#ifdef DEBUG_ERR
#define D_ERR(dev, args...) dev_dbg(dev, ## args)
#else
#define D_ERR(dev, args...) do {} while (0)
#endif
#else
#define D_REQ(dev, args...) do {} while (0)
#define D_TRX(dev, args...) do {} while (0)
#define D_INI(dev, args...) do {} while (0)
#define D_EP0(dev, args...) do {} while (0)
#define D_EPX(dev, args...) do {} while (0)
#define dump_ep_intr(x, y, z, i) do {} while (0)
#define dump_intr(x, y, z) do {} while (0)
#define dump_ep_stat(x, y) do {} while (0)
#define dump_usb_stat(x, y) do {} while (0)
#define dump_req(x, y, z) do {} while (0)
#define D_ERR(dev, args...) do {} while (0)
#endif /* DEBUG */
#endif /* __LINUX_USB_GADGET_IMX_H */

View File

@ -1584,7 +1584,7 @@ static int __init m66592_probe(struct platform_device *pdev)
goto clean_up;
}
if (pdev->dev.platform_data == NULL) {
if (dev_get_platdata(&pdev->dev) == NULL) {
dev_err(&pdev->dev, "no platform data\n");
ret = -ENODEV;
goto clean_up;
@ -1598,7 +1598,7 @@ static int __init m66592_probe(struct platform_device *pdev)
goto clean_up;
}
m66592->pdata = pdev->dev.platform_data;
m66592->pdata = dev_get_platdata(&pdev->dev);
m66592->irq_trigger = ires->flags & IRQF_TRIGGER_MASK;
spin_lock_init(&m66592->lock);

View File

@ -1109,7 +1109,7 @@ static int mv_u3d_controller_reset(struct mv_u3d *u3d)
static int mv_u3d_enable(struct mv_u3d *u3d)
{
struct mv_usb_platform_data *pdata = u3d->dev->platform_data;
struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
int retval;
if (u3d->active)
@ -1138,7 +1138,7 @@ static int mv_u3d_enable(struct mv_u3d *u3d)
static void mv_u3d_disable(struct mv_u3d *u3d)
{
struct mv_usb_platform_data *pdata = u3d->dev->platform_data;
struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
if (u3d->clock_gating && u3d->active) {
dev_dbg(u3d->dev, "disable u3d\n");
if (pdata->phy_deinit)
@ -1246,7 +1246,7 @@ static int mv_u3d_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct mv_u3d *u3d = container_of(g, struct mv_u3d, gadget);
struct mv_usb_platform_data *pdata = u3d->dev->platform_data;
struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
unsigned long flags;
if (u3d->driver)
@ -1277,7 +1277,7 @@ static int mv_u3d_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct mv_u3d *u3d = container_of(g, struct mv_u3d, gadget);
struct mv_usb_platform_data *pdata = u3d->dev->platform_data;
struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev);
unsigned long flags;
u3d->vbus_valid_detect = 0;
@ -1794,12 +1794,12 @@ static int mv_u3d_remove(struct platform_device *dev)
static int mv_u3d_probe(struct platform_device *dev)
{
struct mv_u3d *u3d = NULL;
struct mv_usb_platform_data *pdata = dev->dev.platform_data;
struct mv_usb_platform_data *pdata = dev_get_platdata(&dev->dev);
int retval = 0;
struct resource *r;
size_t size;
if (!dev->dev.platform_data) {
if (!dev_get_platdata(&dev->dev)) {
dev_err(&dev->dev, "missing platform_data\n");
retval = -ENODEV;
goto err_pdata;

View File

@ -2100,7 +2100,7 @@ static int mv_udc_remove(struct platform_device *pdev)
static int mv_udc_probe(struct platform_device *pdev)
{
struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
struct mv_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct mv_udc *udc;
int retval = 0;
struct resource *r;
@ -2118,7 +2118,7 @@ static int mv_udc_probe(struct platform_device *pdev)
}
udc->done = &release_done;
udc->pdata = pdev->dev.platform_data;
udc->pdata = dev_get_platdata(&pdev->dev);
spin_lock_init(&udc->lock);
udc->dev = pdev;

View File

@ -2734,7 +2734,7 @@ static int omap_udc_probe(struct platform_device *pdev)
int hmc;
struct usb_phy *xceiv = NULL;
const char *type = NULL;
struct omap_usb_config *config = pdev->dev.platform_data;
struct omap_usb_config *config = dev_get_platdata(&pdev->dev);
struct clk *dc_clk = NULL;
struct clk *hhc_clk = NULL;

View File

@ -2117,7 +2117,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
/* other non-static parts of init */
dev->dev = &pdev->dev;
dev->mach = pdev->dev.platform_data;
dev->mach = dev_get_platdata(&pdev->dev);
dev->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);

View File

@ -2422,7 +2422,7 @@ static int pxa_udc_probe(struct platform_device *pdev)
return udc->irq;
udc->dev = &pdev->dev;
udc->mach = pdev->dev.platform_data;
udc->mach = dev_get_platdata(&pdev->dev);
udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
gpio = udc->mach->gpio_pullup;

View File

@ -1910,7 +1910,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
spin_lock_init(&r8a66597->lock);
platform_set_drvdata(pdev, r8a66597);
r8a66597->pdata = pdev->dev.platform_data;
r8a66597->pdata = dev_get_platdata(&pdev->dev);
r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
r8a66597->gadget.ops = &r8a66597_gadget_ops;

View File

@ -1142,7 +1142,7 @@ static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
int rndis_init(void)
static int rndis_init(void)
{
u8 i;
@ -1176,7 +1176,7 @@ int rndis_init(void)
}
module_init(rndis_init);
void rndis_exit(void)
static void rndis_exit(void)
{
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
u8 i;

View File

@ -29,6 +29,7 @@
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/of_platform.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
@ -3450,7 +3451,7 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
static int s3c_hsotg_probe(struct platform_device *pdev)
{
struct s3c_hsotg_plat *plat = pdev->dev.platform_data;
struct s3c_hsotg_plat *plat = dev_get_platdata(&pdev->dev);
struct usb_phy *phy;
struct device *dev = &pdev->dev;
struct s3c_hsotg_ep *eps;
@ -3469,7 +3470,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
if (IS_ERR(phy)) {
/* Fallback for pdata */
plat = pdev->dev.platform_data;
plat = dev_get_platdata(&pdev->dev);
if (!plat) {
dev_err(&pdev->dev, "no platform data or transceiver defined\n");
return -EPROBE_DEFER;
@ -3648,10 +3649,19 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
#define s3c_hsotg_resume NULL
#endif
#ifdef CONFIG_OF
static const struct of_device_id s3c_hsotg_of_ids[] = {
{ .compatible = "samsung,s3c6400-hsotg", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, s3c_hsotg_of_ids);
#endif
static struct platform_driver s3c_hsotg_driver = {
.driver = {
.name = "s3c-hsotg",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(s3c_hsotg_of_ids),
},
.probe = s3c_hsotg_probe,
.remove = s3c_hsotg_remove,

View File

@ -1262,7 +1262,7 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct resource *res;
struct s3c_hsudc *hsudc;
struct s3c24xx_hsudc_platdata *pd = pdev->dev.platform_data;
struct s3c24xx_hsudc_platdata *pd = dev_get_platdata(&pdev->dev);
int ret, i;
hsudc = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsudc) +
@ -1275,7 +1275,7 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dev);
hsudc->dev = dev;
hsudc->pd = pdev->dev.platform_data;
hsudc->pd = dev_get_platdata(&pdev->dev);
hsudc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);

View File

@ -1809,7 +1809,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
}
spin_lock_init(&udc->lock);
udc_info = pdev->dev.platform_data;
udc_info = dev_get_platdata(&pdev->dev);
rsrc_start = S3C2410_PA_USBDEV;
rsrc_len = S3C24XX_SZ_USBDEV;

View File

@ -191,7 +191,7 @@ try_again:
frames = bytes_to_frames(runtime, count);
old_fs = get_fs();
set_fs(KERNEL_DS);
result = snd_pcm_lib_write(snd->substream, buf, frames);
result = snd_pcm_lib_write(snd->substream, (void __user *)buf, frames);
if (result != frames) {
ERROR(card, "Playback error: %d\n", (int)result);
set_fs(old_fs);

View File

@ -23,6 +23,7 @@
#include <linux/list.h>
#include <linux/err.h>
#include <linux/dma-mapping.h>
#include <linux/workqueue.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
@ -105,11 +106,18 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
/* ------------------------------------------------------------------------- */
static void usb_gadget_state_work(struct work_struct *work)
{
struct usb_gadget *gadget = work_to_gadget(work);
sysfs_notify(&gadget->dev.kobj, NULL, "state");
}
void usb_gadget_set_state(struct usb_gadget *gadget,
enum usb_device_state state)
{
gadget->state = state;
sysfs_notify(&gadget->dev.kobj, NULL, "state");
schedule_work(&gadget->work);
}
EXPORT_SYMBOL_GPL(usb_gadget_set_state);
@ -196,6 +204,7 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
goto err1;
dev_set_name(&gadget->dev, "gadget");
INIT_WORK(&gadget->work, usb_gadget_state_work);
gadget->dev.parent = parent;
#ifdef CONFIG_HAS_DMA
@ -315,6 +324,7 @@ found:
usb_gadget_remove_driver(udc);
kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
flush_work(&gadget->work);
device_unregister(&udc->dev);
device_unregister(&gadget->dev);
}

View File

@ -193,12 +193,16 @@ static int uvc_queue_buffer(struct uvc_video_queue *queue,
mutex_lock(&queue->mutex);
ret = vb2_qbuf(&queue->queue, buf);
if (ret < 0)
goto done;
spin_lock_irqsave(&queue->irqlock, flags);
ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
queue->flags &= ~UVC_QUEUE_PAUSED;
spin_unlock_irqrestore(&queue->irqlock, flags);
mutex_unlock(&queue->mutex);
done:
mutex_unlock(&queue->mutex);
return ret;
}

View File

@ -142,13 +142,11 @@ config USB_EHCI_MXC
config USB_EHCI_HCD_OMAP
tristate "EHCI support for OMAP3 and later chips"
depends on ARCH_OMAP
select NOP_USB_XCEIV
default y
---help---
Enables support for the on-chip EHCI controller on
OMAP3 and later chips.
If your system uses a PHY on the USB port, you will need to
enable USB_PHY and the appropriate PHY driver as well. Most
boards need the NOP_USB_XCEIV PHY driver.
config USB_EHCI_HCD_ORION
tristate "Support for Marvell EBU on-chip EHCI USB controller"
@ -180,7 +178,6 @@ config USB_EHCI_HCD_AT91
config USB_EHCI_MSM
tristate "Support for Qualcomm QSD/MSM on-chip EHCI USB controller"
depends on ARCH_MSM
depends on USB_PHY
select USB_EHCI_ROOT_HUB_TT
select USB_MSM_OTG
---help---

View File

@ -183,7 +183,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
spin_lock_irq(&ehci->lock);
/* clear phy low-power mode before changing wakeup flags */
if (ehci->has_hostpc) {
if (ehci->has_tdi_phy_lpm) {
port = HCS_N_PORTS(ehci->hcs_params);
while (port--) {
u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port];
@ -217,7 +217,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
}
/* enter phy low-power mode again */
if (ehci->has_hostpc) {
if (ehci->has_tdi_phy_lpm) {
port = HCS_N_PORTS(ehci->hcs_params);
while (port--) {
u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port];
@ -309,7 +309,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
}
}
if (changed && ehci->has_hostpc) {
if (changed && ehci->has_tdi_phy_lpm) {
spin_unlock_irq(&ehci->lock);
msleep(5); /* 5 ms for HCD to enter low-power mode */
spin_lock_irq(&ehci->lock);
@ -436,7 +436,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
goto shutdown;
/* clear phy low-power mode before resume */
if (ehci->bus_suspended && ehci->has_hostpc) {
if (ehci->bus_suspended && ehci->has_tdi_phy_lpm) {
i = HCS_N_PORTS(ehci->hcs_params);
while (i--) {
if (test_bit(i, &ehci->bus_suspended)) {
@ -925,7 +925,7 @@ static int ehci_hub_control (
goto error;
/* clear phy low-power mode before resume */
if (ehci->has_hostpc) {
if (ehci->has_tdi_phy_lpm) {
temp1 = ehci_readl(ehci, hostpc_reg);
ehci_writel(ehci, temp1 & ~HOSTPC_PHCD,
hostpc_reg);
@ -1162,12 +1162,12 @@ static int ehci_hub_control (
/* After above check the port must be connected.
* Set appropriate bit thus could put phy into low power
* mode if we have hostpc feature
* mode if we have tdi_phy_lpm feature
*/
temp &= ~PORT_WKCONN_E;
temp |= PORT_WKDISC_E | PORT_WKOC_E;
ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
if (ehci->has_hostpc) {
if (ehci->has_tdi_phy_lpm) {
spin_unlock_irqrestore(&ehci->lock, flags);
msleep(5);/* 5ms for HCD enter low pwr mode */
spin_lock_irqsave(&ehci->lock, flags);

View File

@ -25,9 +25,9 @@
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/platform_data/tegra_usb.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/usb/ehci_def.h>
@ -51,6 +51,10 @@
static struct hc_driver __read_mostly tegra_ehci_hc_driver;
struct tegra_ehci_soc_config {
bool has_hostpc;
};
static int (*orig_hub_control)(struct usb_hcd *hcd,
u16 typeReq, u16 wValue, u16 wIndex,
char *buf, u16 wLength);
@ -58,7 +62,6 @@ static int (*orig_hub_control)(struct usb_hcd *hcd,
struct tegra_ehci_hcd {
struct tegra_usb_phy *phy;
struct clk *clk;
struct usb_phy *transceiver;
int port_resuming;
bool needs_double_reset;
enum tegra_usb_phy_port_speed port_speed;
@ -322,50 +325,38 @@ static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
free_dma_aligned_buffer(urb);
}
static int setup_vbus_gpio(struct platform_device *pdev,
struct tegra_ehci_platform_data *pdata)
{
int err = 0;
int gpio;
static const struct tegra_ehci_soc_config tegra30_soc_config = {
.has_hostpc = true,
};
gpio = pdata->vbus_gpio;
if (!gpio_is_valid(gpio))
gpio = of_get_named_gpio(pdev->dev.of_node,
"nvidia,vbus-gpio", 0);
if (!gpio_is_valid(gpio))
return 0;
static const struct tegra_ehci_soc_config tegra20_soc_config = {
.has_hostpc = false,
};
err = gpio_request(gpio, "vbus_gpio");
if (err) {
dev_err(&pdev->dev, "can't request vbus gpio %d", gpio);
return err;
}
err = gpio_direction_output(gpio, 1);
if (err) {
dev_err(&pdev->dev, "can't enable vbus\n");
return err;
}
return err;
}
static struct of_device_id tegra_ehci_of_match[] = {
{ .compatible = "nvidia,tegra30-ehci", .data = &tegra30_soc_config },
{ .compatible = "nvidia,tegra20-ehci", .data = &tegra20_soc_config },
{ },
};
static int tegra_ehci_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
const struct tegra_ehci_soc_config *soc_config;
struct resource *res;
struct usb_hcd *hcd;
struct ehci_hcd *ehci;
struct tegra_ehci_hcd *tegra;
struct tegra_ehci_platform_data *pdata;
int err = 0;
int irq;
struct device_node *np_phy;
struct usb_phy *u_phy;
pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_err(&pdev->dev, "Platform data missing\n");
return -EINVAL;
match = of_match_device(tegra_ehci_of_match, &pdev->dev);
if (!match) {
dev_err(&pdev->dev, "Error: No device match found\n");
return -ENODEV;
}
soc_config = match->data;
/* Right now device-tree probed devices don't get dma_mask set.
* Since shared usb code relies on it, set it here for now.
@ -376,14 +367,11 @@ static int tegra_ehci_probe(struct platform_device *pdev)
if (!pdev->dev.coherent_dma_mask)
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
setup_vbus_gpio(pdev, pdata);
hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev,
dev_name(&pdev->dev));
if (!hcd) {
dev_err(&pdev->dev, "Unable to create HCD\n");
err = -ENOMEM;
goto cleanup_vbus_gpio;
return -ENOMEM;
}
platform_set_drvdata(pdev, hcd);
ehci = hcd_to_ehci(hcd);
@ -406,13 +394,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
udelay(1);
tegra_periph_reset_deassert(tegra->clk);
np_phy = of_parse_phandle(pdev->dev.of_node, "nvidia,phy", 0);
if (!np_phy) {
err = -ENODEV;
goto cleanup_clk_en;
}
u_phy = tegra_usb_get_phy(np_phy);
u_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0);
if (IS_ERR(u_phy)) {
err = PTR_ERR(u_phy);
goto cleanup_clk_en;
@ -437,6 +419,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
goto cleanup_clk_en;
}
ehci->caps = hcd->regs + 0x100;
ehci->has_hostpc = soc_config->has_hostpc;
err = usb_phy_init(hcd->phy);
if (err) {
@ -466,26 +449,18 @@ static int tegra_ehci_probe(struct platform_device *pdev)
goto cleanup_phy;
}
if (pdata->operating_mode == TEGRA_USB_OTG) {
tegra->transceiver =
devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
if (!IS_ERR(tegra->transceiver))
otg_set_host(tegra->transceiver->otg, &hcd->self);
} else {
tegra->transceiver = ERR_PTR(-ENODEV);
}
otg_set_host(u_phy->otg, &hcd->self);
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err) {
dev_err(&pdev->dev, "Failed to add USB HCD\n");
goto cleanup_transceiver;
goto cleanup_otg_set_host;
}
return err;
cleanup_transceiver:
if (!IS_ERR(tegra->transceiver))
otg_set_host(tegra->transceiver->otg, NULL);
cleanup_otg_set_host:
otg_set_host(u_phy->otg, NULL);
cleanup_phy:
usb_phy_shutdown(hcd->phy);
cleanup_clk_en:
@ -494,8 +469,6 @@ cleanup_clk_get:
clk_put(tegra->clk);
cleanup_hcd_create:
usb_put_hcd(hcd);
cleanup_vbus_gpio:
/* FIXME: Undo setup_vbus_gpio() here */
return err;
}
@ -505,8 +478,7 @@ static int tegra_ehci_remove(struct platform_device *pdev)
struct tegra_ehci_hcd *tegra =
(struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv;
if (!IS_ERR(tegra->transceiver))
otg_set_host(tegra->transceiver->otg, NULL);
otg_set_host(hcd->phy->otg, NULL);
usb_phy_shutdown(hcd->phy);
usb_remove_hcd(hcd);
@ -525,11 +497,6 @@ static void tegra_ehci_hcd_shutdown(struct platform_device *pdev)
hcd->driver->shutdown(hcd);
}
static struct of_device_id tegra_ehci_of_match[] = {
{ .compatible = "nvidia,tegra20-ehci", },
{ },
};
static struct platform_driver tegra_ehci_driver = {
.probe = tegra_ehci_probe,
.remove = tegra_ehci_remove,

View File

@ -213,6 +213,7 @@ struct ehci_hcd { /* one per controller */
#define OHCI_HCCTRL_LEN 0x4
__hc32 *ohci_hcctrl_reg;
unsigned has_hostpc:1;
unsigned has_tdi_phy_lpm:1;
unsigned has_ppcd:1; /* support per-port change bits */
u8 sbrn; /* packed release number */

View File

@ -83,6 +83,8 @@ config USB_MUSB_AM35X
config USB_MUSB_DSPS
tristate "TI DSPS platforms"
select USB_MUSB_AM335X_CHILD
depends on OF_IRQ
config USB_MUSB_BLACKFIN
tristate "Blackfin"
@ -93,6 +95,9 @@ config USB_MUSB_UX500
endchoice
config USB_MUSB_AM335X_CHILD
tristate
choice
prompt 'MUSB DMA mode'
default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM
@ -125,6 +130,10 @@ config USB_TI_CPPI_DMA
help
Enable DMA transfers when TI CPPI DMA is available.
config USB_TI_CPPI41_DMA
bool 'TI CPPI 4.1 (AM335x)'
depends on ARCH_OMAP
config USB_TUSB_OMAP_DMA
bool 'TUSB 6010'
depends on USB_MUSB_TUSB6010

View File

@ -20,6 +20,9 @@ obj-$(CONFIG_USB_MUSB_DA8XX) += da8xx.o
obj-$(CONFIG_USB_MUSB_BLACKFIN) += blackfin.o
obj-$(CONFIG_USB_MUSB_UX500) += ux500.o
obj-$(CONFIG_USB_MUSB_AM335X_CHILD) += musb_am335x.o
# the kconfig must guarantee that only one of the
# possible I/O schemes will be enabled at a time ...
# PIO only, or DMA (several potential schemes).
@ -29,3 +32,4 @@ musb_hdrc-$(CONFIG_USB_INVENTRA_DMA) += musbhsdma.o
musb_hdrc-$(CONFIG_USB_TI_CPPI_DMA) += cppi_dma.o
musb_hdrc-$(CONFIG_USB_TUSB_OMAP_DMA) += tusb6010_omap.o
musb_hdrc-$(CONFIG_USB_UX500_DMA) += ux500_dma.o
musb_hdrc-$(CONFIG_USB_TI_CPPI41_DMA) += musb_cppi41.o

View File

@ -33,7 +33,7 @@
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/usb/usb_phy_gen_xceiv.h>
#include <linux/platform_data/usb-omap.h>
#include "musb_core.h"
@ -218,7 +218,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
struct musb *musb = hci;
void __iomem *reg_base = musb->ctrl_base;
struct device *dev = musb->controller;
struct musb_hdrc_platform_data *plat = dev->platform_data;
struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
struct omap_musb_board_data *data = plat->board_data;
struct usb_otg *otg = musb->xceiv->otg;
unsigned long flags;
@ -335,7 +335,7 @@ eoi:
static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode)
{
struct device *dev = musb->controller;
struct musb_hdrc_platform_data *plat = dev->platform_data;
struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
struct omap_musb_board_data *data = plat->board_data;
int retval = 0;
@ -350,7 +350,7 @@ static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode)
static int am35x_musb_init(struct musb *musb)
{
struct device *dev = musb->controller;
struct musb_hdrc_platform_data *plat = dev->platform_data;
struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
struct omap_musb_board_data *data = plat->board_data;
void __iomem *reg_base = musb->ctrl_base;
u32 rev;
@ -394,7 +394,7 @@ static int am35x_musb_init(struct musb *musb)
static int am35x_musb_exit(struct musb *musb)
{
struct device *dev = musb->controller;
struct musb_hdrc_platform_data *plat = dev->platform_data;
struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
struct omap_musb_board_data *data = plat->board_data;
del_timer_sync(&otg_workaround);
@ -456,7 +456,7 @@ static u64 am35x_dmamask = DMA_BIT_MASK(32);
static int am35x_probe(struct platform_device *pdev)
{
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct platform_device *musb;
struct am35x_glue *glue;
@ -577,7 +577,7 @@ static int am35x_remove(struct platform_device *pdev)
static int am35x_suspend(struct device *dev)
{
struct am35x_glue *glue = dev_get_drvdata(dev);
struct musb_hdrc_platform_data *plat = dev->platform_data;
struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
struct omap_musb_board_data *data = plat->board_data;
/* Shutdown the on-chip PHY and its PLL. */
@ -593,7 +593,7 @@ static int am35x_suspend(struct device *dev)
static int am35x_resume(struct device *dev)
{
struct am35x_glue *glue = dev_get_drvdata(dev);
struct musb_hdrc_platform_data *plat = dev->platform_data;
struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
struct omap_musb_board_data *data = plat->board_data;
int ret;

View File

@ -19,7 +19,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/prefetch.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/usb/usb_phy_gen_xceiv.h>
#include <asm/cacheflush.h>
@ -451,7 +451,7 @@ static u64 bfin_dmamask = DMA_BIT_MASK(32);
static int bfin_probe(struct platform_device *pdev)
{
struct resource musb_resources[2];
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct platform_device *musb;
struct bfin_glue *glue;

View File

@ -150,14 +150,11 @@ static void cppi_pool_free(struct cppi_channel *c)
c->last_processed = NULL;
}
static int cppi_controller_start(struct dma_controller *c)
static void cppi_controller_start(struct cppi *controller)
{
struct cppi *controller;
void __iomem *tibase;
int i;
controller = container_of(c, struct cppi, controller);
/* do whatever is necessary to start controller */
for (i = 0; i < ARRAY_SIZE(controller->tx); i++) {
controller->tx[i].transmit = true;
@ -212,8 +209,6 @@ static int cppi_controller_start(struct dma_controller *c)
/* disable RNDIS mode, also host rx RNDIS autorequest */
musb_writel(tibase, DAVINCI_RNDIS_REG, 0);
musb_writel(tibase, DAVINCI_AUTOREQ_REG, 0);
return 0;
}
/*
@ -222,14 +217,12 @@ static int cppi_controller_start(struct dma_controller *c)
* De-Init the DMA controller as necessary.
*/
static int cppi_controller_stop(struct dma_controller *c)
static void cppi_controller_stop(struct cppi *controller)
{
struct cppi *controller;
void __iomem *tibase;
int i;
struct musb *musb;
controller = container_of(c, struct cppi, controller);
musb = controller->musb;
tibase = controller->tibase;
@ -255,8 +248,6 @@ static int cppi_controller_stop(struct dma_controller *c)
/*disable tx/rx cppi */
musb_writel(tibase, DAVINCI_TXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_DISABLE);
musb_writel(tibase, DAVINCI_RXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_DISABLE);
return 0;
}
/* While dma channel is allocated, we only want the core irqs active
@ -1321,8 +1312,6 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *mr
controller->tibase = mregs - DAVINCI_BASE_OFFSET;
controller->musb = musb;
controller->controller.start = cppi_controller_start;
controller->controller.stop = cppi_controller_stop;
controller->controller.channel_alloc = cppi_channel_allocate;
controller->controller.channel_release = cppi_channel_release;
controller->controller.channel_program = cppi_channel_program;
@ -1351,6 +1340,7 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *mr
controller->irq = irq;
}
cppi_controller_start(controller);
return &controller->controller;
}
@ -1363,6 +1353,8 @@ void dma_controller_destroy(struct dma_controller *c)
cppi = container_of(c, struct cppi, controller);
cppi_controller_stop(cppi);
if (cppi->irq)
free_irq(cppi->irq, cppi->musb);

View File

@ -33,7 +33,7 @@
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/usb/usb_phy_gen_xceiv.h>
#include <mach/da8xx.h>
#include <linux/platform_data/usb-davinci.h>
@ -477,7 +477,7 @@ static u64 da8xx_dmamask = DMA_BIT_MASK(32);
static int da8xx_probe(struct platform_device *pdev)
{
struct resource musb_resources[2];
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct platform_device *musb;
struct da8xx_glue *glue;

View File

@ -33,7 +33,7 @@
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/usb/usb_phy_gen_xceiv.h>
#include <mach/cputype.h>
#include <mach/hardware.h>
@ -510,7 +510,7 @@ static u64 davinci_dmamask = DMA_BIT_MASK(32);
static int davinci_probe(struct platform_device *pdev)
{
struct resource musb_resources[2];
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct platform_device *musb;
struct davinci_glue *glue;
struct clk *clk;

View File

@ -0,0 +1,55 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/module.h>
#include <linux/of_platform.h>
static int am335x_child_probe(struct platform_device *pdev)
{
int ret;
pm_runtime_enable(&pdev->dev);
ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
if (ret)
goto err;
return 0;
err:
pm_runtime_disable(&pdev->dev);
return ret;
}
static int of_remove_populated_child(struct device *dev, void *d)
{
struct platform_device *pdev = to_platform_device(dev);
of_device_unregister(pdev);
return 0;
}
static int am335x_child_remove(struct platform_device *pdev)
{
device_for_each_child(&pdev->dev, NULL, of_remove_populated_child);
pm_runtime_disable(&pdev->dev);
return 0;
}
static const struct of_device_id am335x_child_of_match[] = {
{ .compatible = "ti,am33xx-usb" },
{ },
};
MODULE_DEVICE_TABLE(of, am335x_child_of_match);
static struct platform_driver am335x_child_driver = {
.probe = am335x_child_probe,
.remove = am335x_child_remove,
.driver = {
.name = "am335x-usb-childs",
.of_match_table = of_match_ptr(am335x_child_of_match),
},
};
module_platform_driver(am335x_child_driver);
MODULE_DESCRIPTION("AM33xx child devices");
MODULE_LICENSE("GPL v2");

View File

@ -1763,12 +1763,8 @@ static void musb_free(struct musb *musb)
disable_irq_wake(musb->nIrq);
free_irq(musb->nIrq, musb);
}
if (is_dma_capable() && musb->dma_controller) {
struct dma_controller *c = musb->dma_controller;
(void) c->stop(c);
dma_controller_destroy(c);
}
if (musb->dma_controller)
dma_controller_destroy(musb->dma_controller);
musb_host_free(musb);
}
@ -1786,7 +1782,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
{
int status;
struct musb *musb;
struct musb_hdrc_platform_data *plat = dev->platform_data;
struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
/* The driver might handle more features than the board; OK.
* Fail when the board needs a feature that's not enabled.
@ -1843,19 +1839,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
pm_runtime_get_sync(musb->controller);
#ifndef CONFIG_MUSB_PIO_ONLY
if (use_dma && dev->dma_mask) {
struct dma_controller *c;
c = dma_controller_create(musb, musb->mregs);
musb->dma_controller = c;
if (c)
(void) c->start(c);
}
#endif
/* ideally this would be abstracted in platform setup */
if (!is_dma_capable() || !musb->dma_controller)
dev->dma_mask = NULL;
if (use_dma && dev->dma_mask)
musb->dma_controller = dma_controller_create(musb, musb->mregs);
/* be sure interrupts are disabled before connecting ISR */
musb_platform_disable(musb);
@ -1943,6 +1928,8 @@ fail4:
musb_gadget_cleanup(musb);
fail3:
if (musb->dma_controller)
dma_controller_destroy(musb->dma_controller);
pm_runtime_put_sync(musb->controller);
fail2:
@ -2001,9 +1988,6 @@ static int musb_remove(struct platform_device *pdev)
musb_free(musb);
device_init_wakeup(dev, 0);
#ifndef CONFIG_MUSB_PIO_ONLY
dma_set_mask(dev, *dev->parent->dma_mask);
#endif
return 0;
}

View File

@ -83,11 +83,6 @@ enum {
MUSB_PORT_MODE_DUAL_ROLE,
};
#ifdef CONFIG_PROC_FS
#include <linux/fs.h>
#define MUSB_CONFIG_PROC_FS
#endif
/****************************** CONSTANTS ********************************/
#ifndef MUSB_C_NUM_EPS
@ -425,9 +420,6 @@ struct musb {
struct musb_hdrc_config *config;
#ifdef MUSB_CONFIG_PROC_FS
struct proc_dir_entry *proc_entry;
#endif
int xceiv_old_state;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_root;

View File

@ -0,0 +1,555 @@
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/sizes.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include "musb_core.h"
#define RNDIS_REG(x) (0x80 + ((x - 1) * 4))
#define EP_MODE_AUTOREG_NONE 0
#define EP_MODE_AUTOREG_ALL_NEOP 1
#define EP_MODE_AUTOREG_ALWAYS 3
#define EP_MODE_DMA_TRANSPARENT 0
#define EP_MODE_DMA_RNDIS 1
#define EP_MODE_DMA_GEN_RNDIS 3
#define USB_CTRL_TX_MODE 0x70
#define USB_CTRL_RX_MODE 0x74
#define USB_CTRL_AUTOREQ 0xd0
#define USB_TDOWN 0xd8
struct cppi41_dma_channel {
struct dma_channel channel;
struct cppi41_dma_controller *controller;
struct musb_hw_ep *hw_ep;
struct dma_chan *dc;
dma_cookie_t cookie;
u8 port_num;
u8 is_tx;
u8 is_allocated;
u8 usb_toggle;
dma_addr_t buf_addr;
u32 total_len;
u32 prog_len;
u32 transferred;
u32 packet_sz;
};
#define MUSB_DMA_NUM_CHANNELS 15
struct cppi41_dma_controller {
struct dma_controller controller;
struct cppi41_dma_channel rx_channel[MUSB_DMA_NUM_CHANNELS];
struct cppi41_dma_channel tx_channel[MUSB_DMA_NUM_CHANNELS];
struct musb *musb;
u32 rx_mode;
u32 tx_mode;
u32 auto_req;
};
static void save_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
{
u16 csr;
u8 toggle;
if (cppi41_channel->is_tx)
return;
if (!is_host_active(cppi41_channel->controller->musb))
return;
csr = musb_readw(cppi41_channel->hw_ep->regs, MUSB_RXCSR);
toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0;
cppi41_channel->usb_toggle = toggle;
}
static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
{
u16 csr;
u8 toggle;
if (cppi41_channel->is_tx)
return;
if (!is_host_active(cppi41_channel->controller->musb))
return;
csr = musb_readw(cppi41_channel->hw_ep->regs, MUSB_RXCSR);
toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0;
/*
* AM335x Advisory 1.0.13: Due to internal synchronisation error the
* data toggle may reset from DATA1 to DATA0 during receiving data from
* more than one endpoint.
*/
if (!toggle && toggle == cppi41_channel->usb_toggle) {
csr |= MUSB_RXCSR_H_DATATOGGLE | MUSB_RXCSR_H_WR_DATATOGGLE;
musb_writew(cppi41_channel->hw_ep->regs, MUSB_RXCSR, csr);
dev_dbg(cppi41_channel->controller->musb->controller,
"Restoring DATA1 toggle.\n");
}
cppi41_channel->usb_toggle = toggle;
}
static void cppi41_dma_callback(void *private_data)
{
struct dma_channel *channel = private_data;
struct cppi41_dma_channel *cppi41_channel = channel->private_data;
struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
struct musb *musb = hw_ep->musb;
unsigned long flags;
struct dma_tx_state txstate;
u32 transferred;
spin_lock_irqsave(&musb->lock, flags);
dmaengine_tx_status(cppi41_channel->dc, cppi41_channel->cookie,
&txstate);
transferred = cppi41_channel->prog_len - txstate.residue;
cppi41_channel->transferred += transferred;
dev_dbg(musb->controller, "DMA transfer done on hw_ep=%d bytes=%d/%d\n",
hw_ep->epnum, cppi41_channel->transferred,
cppi41_channel->total_len);
update_rx_toggle(cppi41_channel);
if (cppi41_channel->transferred == cppi41_channel->total_len ||
transferred < cppi41_channel->packet_sz) {
/* done, complete */
cppi41_channel->channel.actual_len =
cppi41_channel->transferred;
cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE;
musb_dma_completion(musb, hw_ep->epnum, cppi41_channel->is_tx);
} else {
/* next iteration, reload */
struct dma_chan *dc = cppi41_channel->dc;
struct dma_async_tx_descriptor *dma_desc;
enum dma_transfer_direction direction;
u16 csr;
u32 remain_bytes;
void __iomem *epio = cppi41_channel->hw_ep->regs;
cppi41_channel->buf_addr += cppi41_channel->packet_sz;
remain_bytes = cppi41_channel->total_len;
remain_bytes -= cppi41_channel->transferred;
remain_bytes = min(remain_bytes, cppi41_channel->packet_sz);
cppi41_channel->prog_len = remain_bytes;
direction = cppi41_channel->is_tx ? DMA_MEM_TO_DEV
: DMA_DEV_TO_MEM;
dma_desc = dmaengine_prep_slave_single(dc,
cppi41_channel->buf_addr,
remain_bytes,
direction,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (WARN_ON(!dma_desc))
return;
dma_desc->callback = cppi41_dma_callback;
dma_desc->callback_param = channel;
cppi41_channel->cookie = dma_desc->tx_submit(dma_desc);
dma_async_issue_pending(dc);
if (!cppi41_channel->is_tx) {
csr = musb_readw(epio, MUSB_RXCSR);
csr |= MUSB_RXCSR_H_REQPKT;
musb_writew(epio, MUSB_RXCSR, csr);
}
}
spin_unlock_irqrestore(&musb->lock, flags);
}
static u32 update_ep_mode(unsigned ep, unsigned mode, u32 old)
{
unsigned shift;
shift = (ep - 1) * 2;
old &= ~(3 << shift);
old |= mode << shift;
return old;
}
static void cppi41_set_dma_mode(struct cppi41_dma_channel *cppi41_channel,
unsigned mode)
{
struct cppi41_dma_controller *controller = cppi41_channel->controller;
u32 port;
u32 new_mode;
u32 old_mode;
if (cppi41_channel->is_tx)
old_mode = controller->tx_mode;
else
old_mode = controller->rx_mode;
port = cppi41_channel->port_num;
new_mode = update_ep_mode(port, mode, old_mode);
if (new_mode == old_mode)
return;
if (cppi41_channel->is_tx) {
controller->tx_mode = new_mode;
musb_writel(controller->musb->ctrl_base, USB_CTRL_TX_MODE,
new_mode);
} else {
controller->rx_mode = new_mode;
musb_writel(controller->musb->ctrl_base, USB_CTRL_RX_MODE,
new_mode);
}
}
static void cppi41_set_autoreq_mode(struct cppi41_dma_channel *cppi41_channel,
unsigned mode)
{
struct cppi41_dma_controller *controller = cppi41_channel->controller;
u32 port;
u32 new_mode;
u32 old_mode;
old_mode = controller->auto_req;
port = cppi41_channel->port_num;
new_mode = update_ep_mode(port, mode, old_mode);
if (new_mode == old_mode)
return;
controller->auto_req = new_mode;
musb_writel(controller->musb->ctrl_base, USB_CTRL_AUTOREQ, new_mode);
}
static bool cppi41_configure_channel(struct dma_channel *channel,
u16 packet_sz, u8 mode,
dma_addr_t dma_addr, u32 len)
{
struct cppi41_dma_channel *cppi41_channel = channel->private_data;
struct dma_chan *dc = cppi41_channel->dc;
struct dma_async_tx_descriptor *dma_desc;
enum dma_transfer_direction direction;
struct musb *musb = cppi41_channel->controller->musb;
unsigned use_gen_rndis = 0;
dev_dbg(musb->controller,
"configure ep%d/%x packet_sz=%d, mode=%d, dma_addr=0x%llx, len=%d is_tx=%d\n",
cppi41_channel->port_num, RNDIS_REG(cppi41_channel->port_num),
packet_sz, mode, (unsigned long long) dma_addr,
len, cppi41_channel->is_tx);
cppi41_channel->buf_addr = dma_addr;
cppi41_channel->total_len = len;
cppi41_channel->transferred = 0;
cppi41_channel->packet_sz = packet_sz;
/*
* Due to AM335x' Advisory 1.0.13 we are not allowed to transfer more
* than max packet size at a time.
*/
if (cppi41_channel->is_tx)
use_gen_rndis = 1;
if (use_gen_rndis) {
/* RNDIS mode */
if (len > packet_sz) {
musb_writel(musb->ctrl_base,
RNDIS_REG(cppi41_channel->port_num), len);
/* gen rndis */
cppi41_set_dma_mode(cppi41_channel,
EP_MODE_DMA_GEN_RNDIS);
/* auto req */
cppi41_set_autoreq_mode(cppi41_channel,
EP_MODE_AUTOREG_ALL_NEOP);
} else {
musb_writel(musb->ctrl_base,
RNDIS_REG(cppi41_channel->port_num), 0);
cppi41_set_dma_mode(cppi41_channel,
EP_MODE_DMA_TRANSPARENT);
cppi41_set_autoreq_mode(cppi41_channel,
EP_MODE_AUTOREG_NONE);
}
} else {
/* fallback mode */
cppi41_set_dma_mode(cppi41_channel, EP_MODE_DMA_TRANSPARENT);
cppi41_set_autoreq_mode(cppi41_channel, EP_MODE_AUTOREG_NONE);
len = min_t(u32, packet_sz, len);
}
cppi41_channel->prog_len = len;
direction = cppi41_channel->is_tx ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
dma_desc = dmaengine_prep_slave_single(dc, dma_addr, len, direction,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!dma_desc)
return false;
dma_desc->callback = cppi41_dma_callback;
dma_desc->callback_param = channel;
cppi41_channel->cookie = dma_desc->tx_submit(dma_desc);
save_rx_toggle(cppi41_channel);
dma_async_issue_pending(dc);
return true;
}
static struct dma_channel *cppi41_dma_channel_allocate(struct dma_controller *c,
struct musb_hw_ep *hw_ep, u8 is_tx)
{
struct cppi41_dma_controller *controller = container_of(c,
struct cppi41_dma_controller, controller);
struct cppi41_dma_channel *cppi41_channel = NULL;
u8 ch_num = hw_ep->epnum - 1;
if (ch_num >= MUSB_DMA_NUM_CHANNELS)
return NULL;
if (is_tx)
cppi41_channel = &controller->tx_channel[ch_num];
else
cppi41_channel = &controller->rx_channel[ch_num];
if (!cppi41_channel->dc)
return NULL;
if (cppi41_channel->is_allocated)
return NULL;
cppi41_channel->hw_ep = hw_ep;
cppi41_channel->is_allocated = 1;
return &cppi41_channel->channel;
}
static void cppi41_dma_channel_release(struct dma_channel *channel)
{
struct cppi41_dma_channel *cppi41_channel = channel->private_data;
if (cppi41_channel->is_allocated) {
cppi41_channel->is_allocated = 0;
channel->status = MUSB_DMA_STATUS_FREE;
channel->actual_len = 0;
}
}
static int cppi41_dma_channel_program(struct dma_channel *channel,
u16 packet_sz, u8 mode,
dma_addr_t dma_addr, u32 len)
{
int ret;
BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN ||
channel->status == MUSB_DMA_STATUS_BUSY);
channel->status = MUSB_DMA_STATUS_BUSY;
channel->actual_len = 0;
ret = cppi41_configure_channel(channel, packet_sz, mode, dma_addr, len);
if (!ret)
channel->status = MUSB_DMA_STATUS_FREE;
return ret;
}
static int cppi41_is_compatible(struct dma_channel *channel, u16 maxpacket,
void *buf, u32 length)
{
struct cppi41_dma_channel *cppi41_channel = channel->private_data;
struct cppi41_dma_controller *controller = cppi41_channel->controller;
struct musb *musb = controller->musb;
if (is_host_active(musb)) {
WARN_ON(1);
return 1;
}
if (cppi41_channel->is_tx)
return 1;
/* AM335x Advisory 1.0.13. No workaround for device RX mode */
return 0;
}
static int cppi41_dma_channel_abort(struct dma_channel *channel)
{
struct cppi41_dma_channel *cppi41_channel = channel->private_data;
struct cppi41_dma_controller *controller = cppi41_channel->controller;
struct musb *musb = controller->musb;
void __iomem *epio = cppi41_channel->hw_ep->regs;
int tdbit;
int ret;
unsigned is_tx;
u16 csr;
is_tx = cppi41_channel->is_tx;
dev_dbg(musb->controller, "abort channel=%d, is_tx=%d\n",
cppi41_channel->port_num, is_tx);
if (cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE)
return 0;
if (is_tx) {
csr = musb_readw(epio, MUSB_TXCSR);
csr &= ~MUSB_TXCSR_DMAENAB;
musb_writew(epio, MUSB_TXCSR, csr);
} else {
csr = musb_readw(epio, MUSB_RXCSR);
csr &= ~(MUSB_RXCSR_H_REQPKT | MUSB_RXCSR_DMAENAB);
musb_writew(epio, MUSB_RXCSR, csr);
csr = musb_readw(epio, MUSB_RXCSR);
if (csr & MUSB_RXCSR_RXPKTRDY) {
csr |= MUSB_RXCSR_FLUSHFIFO;
musb_writew(epio, MUSB_RXCSR, csr);
musb_writew(epio, MUSB_RXCSR, csr);
}
}
tdbit = 1 << cppi41_channel->port_num;
if (is_tx)
tdbit <<= 16;
do {
musb_writel(musb->ctrl_base, USB_TDOWN, tdbit);
ret = dmaengine_terminate_all(cppi41_channel->dc);
} while (ret == -EAGAIN);
musb_writel(musb->ctrl_base, USB_TDOWN, tdbit);
if (is_tx) {
csr = musb_readw(epio, MUSB_TXCSR);
if (csr & MUSB_TXCSR_TXPKTRDY) {
csr |= MUSB_TXCSR_FLUSHFIFO;
musb_writew(epio, MUSB_TXCSR, csr);
}
}
cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE;
return 0;
}
static void cppi41_release_all_dma_chans(struct cppi41_dma_controller *ctrl)
{
struct dma_chan *dc;
int i;
for (i = 0; i < MUSB_DMA_NUM_CHANNELS; i++) {
dc = ctrl->tx_channel[i].dc;
if (dc)
dma_release_channel(dc);
dc = ctrl->rx_channel[i].dc;
if (dc)
dma_release_channel(dc);
}
}
static void cppi41_dma_controller_stop(struct cppi41_dma_controller *controller)
{
cppi41_release_all_dma_chans(controller);
}
static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
{
struct musb *musb = controller->musb;
struct device *dev = musb->controller;
struct device_node *np = dev->of_node;
struct cppi41_dma_channel *cppi41_channel;
int count;
int i;
int ret;
count = of_property_count_strings(np, "dma-names");
if (count < 0)
return count;
for (i = 0; i < count; i++) {
struct dma_chan *dc;
struct dma_channel *musb_dma;
const char *str;
unsigned is_tx;
unsigned int port;
ret = of_property_read_string_index(np, "dma-names", i, &str);
if (ret)
goto err;
if (!strncmp(str, "tx", 2))
is_tx = 1;
else if (!strncmp(str, "rx", 2))
is_tx = 0;
else {
dev_err(dev, "Wrong dmatype %s\n", str);
goto err;
}
ret = kstrtouint(str + 2, 0, &port);
if (ret)
goto err;
if (port > MUSB_DMA_NUM_CHANNELS || !port)
goto err;
if (is_tx)
cppi41_channel = &controller->tx_channel[port - 1];
else
cppi41_channel = &controller->rx_channel[port - 1];
cppi41_channel->controller = controller;
cppi41_channel->port_num = port;
cppi41_channel->is_tx = is_tx;
musb_dma = &cppi41_channel->channel;
musb_dma->private_data = cppi41_channel;
musb_dma->status = MUSB_DMA_STATUS_FREE;
musb_dma->max_len = SZ_4M;
dc = dma_request_slave_channel(dev, str);
if (!dc) {
dev_err(dev, "Falied to request %s.\n", str);
goto err;
}
cppi41_channel->dc = dc;
}
return 0;
err:
cppi41_release_all_dma_chans(controller);
return -EINVAL;
}
void dma_controller_destroy(struct dma_controller *c)
{
struct cppi41_dma_controller *controller = container_of(c,
struct cppi41_dma_controller, controller);
cppi41_dma_controller_stop(controller);
kfree(controller);
}
struct dma_controller *dma_controller_create(struct musb *musb,
void __iomem *base)
{
struct cppi41_dma_controller *controller;
int ret;
if (!musb->controller->of_node) {
dev_err(musb->controller, "Need DT for the DMA engine.\n");
return NULL;
}
controller = kzalloc(sizeof(*controller), GFP_KERNEL);
if (!controller)
goto kzalloc_fail;
controller->musb = musb;
controller->controller.channel_alloc = cppi41_dma_channel_allocate;
controller->controller.channel_release = cppi41_dma_channel_release;
controller->controller.channel_program = cppi41_dma_channel_program;
controller->controller.channel_abort = cppi41_dma_channel_abort;
controller->controller.is_compatible = cppi41_is_compatible;
ret = cppi41_dma_controller_start(controller);
if (ret)
goto plat_get_fail;
return &controller->controller;
plat_get_fail:
kfree(controller);
kzalloc_fail:
return NULL;
}

View File

@ -62,13 +62,13 @@ struct musb_hw_ep;
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#ifndef CONFIG_MUSB_PIO_ONLY
#define is_dma_capable() (1)
#else
#ifdef CONFIG_MUSB_PIO_ONLY
#define is_dma_capable() (0)
#else
#define is_dma_capable() (1)
#endif
#ifdef CONFIG_USB_TI_CPPI_DMA
#if defined(CONFIG_USB_TI_CPPI_DMA) || defined(CONFIG_USB_TI_CPPI41_DMA)
#define is_cppi_enabled() 1
#else
#define is_cppi_enabled() 0
@ -159,8 +159,6 @@ dma_channel_status(struct dma_channel *c)
* Controllers manage dma channels.
*/
struct dma_controller {
int (*start)(struct dma_controller *);
int (*stop)(struct dma_controller *);
struct dma_channel *(*channel_alloc)(struct dma_controller *,
struct musb_hw_ep *, u8 is_tx);
void (*channel_release)(struct dma_channel *);
@ -177,9 +175,20 @@ struct dma_controller {
/* called after channel_program(), may indicate a fault */
extern void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit);
#ifdef CONFIG_MUSB_PIO_ONLY
static inline struct dma_controller *dma_controller_create(struct musb *m,
void __iomem *io)
{
return NULL;
}
static inline void dma_controller_destroy(struct dma_controller *d) { }
#else
extern struct dma_controller *dma_controller_create(struct musb *, void __iomem *);
extern void dma_controller_destroy(struct dma_controller *);
#endif
#endif /* __MUSB_DMA_H__ */

View File

@ -36,19 +36,18 @@
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/module.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/usb/usb_phy_gen_xceiv.h>
#include <linux/platform_data/usb-omap.h>
#include <linux/sizes.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include "musb_core.h"
#ifdef CONFIG_OF
static const struct of_device_id musb_dsps_of_match[];
#endif
/**
* avoid using musb_readx()/musb_writex() as glue layer should not be
@ -75,7 +74,6 @@ struct dsps_musb_wrapper {
u16 revision;
u16 control;
u16 status;
u16 eoi;
u16 epintr_set;
u16 epintr_clear;
u16 epintr_status;
@ -108,10 +106,7 @@ struct dsps_musb_wrapper {
/* bit positions for mode */
unsigned iddig:5;
/* miscellaneous stuff */
u32 musb_core_offset;
u8 poll_seconds;
/* number of musb instances */
u8 instances;
};
/**
@ -119,53 +114,12 @@ struct dsps_musb_wrapper {
*/
struct dsps_glue {
struct device *dev;
struct platform_device *musb[2]; /* child musb pdev */
struct platform_device *musb; /* child musb pdev */
const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
struct timer_list timer[2]; /* otg_workaround timer */
unsigned long last_timer[2]; /* last timer data for each instance */
u32 __iomem *usb_ctrl[2];
struct timer_list timer; /* otg_workaround timer */
unsigned long last_timer; /* last timer data for each instance */
};
#define DSPS_AM33XX_CONTROL_MODULE_PHYS_0 0x44e10620
#define DSPS_AM33XX_CONTROL_MODULE_PHYS_1 0x44e10628
static const resource_size_t dsps_control_module_phys[] = {
DSPS_AM33XX_CONTROL_MODULE_PHYS_0,
DSPS_AM33XX_CONTROL_MODULE_PHYS_1,
};
#define USBPHY_CM_PWRDN (1 << 0)
#define USBPHY_OTG_PWRDN (1 << 1)
#define USBPHY_OTGVDET_EN (1 << 19)
#define USBPHY_OTGSESSEND_EN (1 << 20)
/**
* musb_dsps_phy_control - phy on/off
* @glue: struct dsps_glue *
* @id: musb instance
* @on: flag for phy to be switched on or off
*
* This is to enable the PHY using usb_ctrl register in system control
* module space.
*
* XXX: This function will be removed once we have a seperate driver for
* control module
*/
static void musb_dsps_phy_control(struct dsps_glue *glue, u8 id, u8 on)
{
u32 usbphycfg;
usbphycfg = readl(glue->usb_ctrl[id]);
if (on) {
usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN);
usbphycfg |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN;
} else {
usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
}
writel(usbphycfg, glue->usb_ctrl[id]);
}
/**
* dsps_musb_enable - enable interrupts
*/
@ -205,7 +159,6 @@ static void dsps_musb_disable(struct musb *musb)
dsps_writel(reg_base, wrp->epintr_clear,
wrp->txep_bitmap | wrp->rxep_bitmap);
dsps_writeb(musb->mregs, MUSB_DEVCTL, 0);
dsps_writel(reg_base, wrp->eoi, 0);
}
static void otg_timer(unsigned long _musb)
@ -213,7 +166,6 @@ static void otg_timer(unsigned long _musb)
struct musb *musb = (void *)_musb;
void __iomem *mregs = musb->mregs;
struct device *dev = musb->controller;
struct platform_device *pdev = to_platform_device(dev);
struct dsps_glue *glue = dev_get_drvdata(dev->parent);
const struct dsps_musb_wrapper *wrp = glue->wrp;
u8 devctl;
@ -250,7 +202,7 @@ static void otg_timer(unsigned long _musb)
case OTG_STATE_B_IDLE:
devctl = dsps_readb(mregs, MUSB_DEVCTL);
if (devctl & MUSB_DEVCTL_BDEVICE)
mod_timer(&glue->timer[pdev->id],
mod_timer(&glue->timer,
jiffies + wrp->poll_seconds * HZ);
else
musb->xceiv->state = OTG_STATE_A_IDLE;
@ -264,7 +216,6 @@ static void otg_timer(unsigned long _musb)
static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
{
struct device *dev = musb->controller;
struct platform_device *pdev = to_platform_device(dev);
struct dsps_glue *glue = dev_get_drvdata(dev->parent);
if (timeout == 0)
@ -275,23 +226,23 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
dev_dbg(musb->controller, "%s active, deleting timer\n",
usb_otg_state_string(musb->xceiv->state));
del_timer(&glue->timer[pdev->id]);
glue->last_timer[pdev->id] = jiffies;
del_timer(&glue->timer);
glue->last_timer = jiffies;
return;
}
if (time_after(glue->last_timer[pdev->id], timeout) &&
timer_pending(&glue->timer[pdev->id])) {
if (time_after(glue->last_timer, timeout) &&
timer_pending(&glue->timer)) {
dev_dbg(musb->controller,
"Longer idle timer already pending, ignoring...\n");
return;
}
glue->last_timer[pdev->id] = timeout;
glue->last_timer = timeout;
dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
usb_otg_state_string(musb->xceiv->state),
jiffies_to_msecs(timeout - jiffies));
mod_timer(&glue->timer[pdev->id], timeout);
mod_timer(&glue->timer, timeout);
}
static irqreturn_t dsps_interrupt(int irq, void *hci)
@ -299,7 +250,6 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
struct musb *musb = hci;
void __iomem *reg_base = musb->ctrl_base;
struct device *dev = musb->controller;
struct platform_device *pdev = to_platform_device(dev);
struct dsps_glue *glue = dev_get_drvdata(dev->parent);
const struct dsps_musb_wrapper *wrp = glue->wrp;
unsigned long flags;
@ -319,7 +269,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
/* Get usb core interrupts */
usbintr = dsps_readl(reg_base, wrp->coreintr_status);
if (!usbintr && !epintr)
goto eoi;
goto out;
musb->int_usb = (usbintr & wrp->usb_bitmap) >> wrp->usb_shift;
if (usbintr)
@ -359,7 +309,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
*/
musb->int_usb &= ~MUSB_INTR_VBUSERROR;
musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
mod_timer(&glue->timer[pdev->id],
mod_timer(&glue->timer,
jiffies + wrp->poll_seconds * HZ);
WARNING("VBUS error workaround (delay coming)\n");
} else if (drvvbus) {
@ -367,7 +317,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
MUSB_HST_MODE(musb);
musb->xceiv->otg->default_a = 1;
musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
del_timer(&glue->timer[pdev->id]);
del_timer(&glue->timer);
} else {
musb->is_active = 0;
MUSB_DEV_MODE(musb);
@ -387,16 +337,10 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
if (musb->int_tx || musb->int_rx || musb->int_usb)
ret |= musb_interrupt(musb);
eoi:
/* EOI needs to be written for the IRQ to be re-asserted. */
if (ret == IRQ_HANDLED || epintr || usbintr)
dsps_writel(reg_base, wrp->eoi, 1);
/* Poll for ID change */
if (musb->xceiv->state == OTG_STATE_B_IDLE)
mod_timer(&glue->timer[pdev->id],
jiffies + wrp->poll_seconds * HZ);
mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
out:
spin_unlock_irqrestore(&musb->lock, flags);
return ret;
@ -405,37 +349,38 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
static int dsps_musb_init(struct musb *musb)
{
struct device *dev = musb->controller;
struct platform_device *pdev = to_platform_device(dev);
struct dsps_glue *glue = dev_get_drvdata(dev->parent);
struct platform_device *parent = to_platform_device(dev->parent);
const struct dsps_musb_wrapper *wrp = glue->wrp;
void __iomem *reg_base = musb->ctrl_base;
void __iomem *reg_base;
struct resource *r;
u32 rev, val;
int status;
/* mentor core register starts at offset of 0x400 from musb base */
musb->mregs += wrp->musb_core_offset;
r = platform_get_resource_byname(parent, IORESOURCE_MEM, "control");
if (!r)
return -EINVAL;
reg_base = devm_ioremap_resource(dev, r);
if (!musb->ctrl_base)
return -EINVAL;
musb->ctrl_base = reg_base;
/* NOP driver needs change if supporting dual instance */
usb_nop_xceiv_register();
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(musb->xceiv))
return -EPROBE_DEFER;
musb->xceiv = devm_usb_get_phy_by_phandle(dev, "phys", 0);
if (IS_ERR(musb->xceiv))
return PTR_ERR(musb->xceiv);
/* Returns zero if e.g. not clocked */
rev = dsps_readl(reg_base, wrp->revision);
if (!rev) {
status = -ENODEV;
goto err0;
}
if (!rev)
return -ENODEV;
setup_timer(&glue->timer[pdev->id], otg_timer, (unsigned long) musb);
usb_phy_init(musb->xceiv);
setup_timer(&glue->timer, otg_timer, (unsigned long) musb);
/* Reset the musb */
dsps_writel(reg_base, wrp->control, (1 << wrp->reset));
/* Start the on-chip PHY and its PLL. */
musb_dsps_phy_control(glue, pdev->id, 1);
musb->isr = dsps_interrupt;
/* reset the otgdisable bit, needed for host mode to work */
@ -443,31 +388,17 @@ static int dsps_musb_init(struct musb *musb)
val &= ~(1 << wrp->otg_disable);
dsps_writel(musb->ctrl_base, wrp->phy_utmi, val);
/* clear level interrupt */
dsps_writel(reg_base, wrp->eoi, 0);
return 0;
err0:
usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return status;
}
static int dsps_musb_exit(struct musb *musb)
{
struct device *dev = musb->controller;
struct platform_device *pdev = to_platform_device(dev);
struct dsps_glue *glue = dev_get_drvdata(dev->parent);
del_timer_sync(&glue->timer[pdev->id]);
/* Shutdown the on-chip PHY and its PLL. */
musb_dsps_phy_control(glue, pdev->id, 0);
/* NOP driver needs change if supporting dual instance */
usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
del_timer_sync(&glue->timer);
usb_phy_shutdown(musb->xceiv);
return 0;
}
@ -483,116 +414,98 @@ static struct musb_platform_ops dsps_ops = {
static u64 musb_dmamask = DMA_BIT_MASK(32);
static int dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
static int get_int_prop(struct device_node *dn, const char *s)
{
struct device *dev = glue->dev;
struct platform_device *pdev = to_platform_device(dev);
struct musb_hdrc_platform_data *pdata = dev->platform_data;
struct device_node *np = pdev->dev.of_node;
struct musb_hdrc_config *config;
struct platform_device *musb;
struct resource *res;
int ret;
u32 val;
ret = of_property_read_u32(dn, s, &val);
if (ret)
return 0;
return val;
}
static int dsps_create_musb_pdev(struct dsps_glue *glue,
struct platform_device *parent)
{
struct musb_hdrc_platform_data pdata;
struct resource resources[2];
char res_name[11];
struct device *dev = &parent->dev;
struct musb_hdrc_config *config;
struct platform_device *musb;
struct device_node *dn = parent->dev.of_node;
struct device_node *child_node;
int ret;
resources[0].start = dsps_control_module_phys[id];
resources[0].end = resources[0].start + SZ_4 - 1;
resources[0].flags = IORESOURCE_MEM;
child_node = of_get_child_by_name(dn, "usb");
if (!child_node)
return -EINVAL;
glue->usb_ctrl[id] = devm_ioremap_resource(&pdev->dev, resources);
if (IS_ERR(glue->usb_ctrl[id])) {
ret = PTR_ERR(glue->usb_ctrl[id]);
goto err0;
memset(resources, 0, sizeof(resources));
ret = of_address_to_resource(child_node, 0, &resources[0]);
if (ret) {
dev_err(dev, "failed to get memory.\n");
return ret;
}
/* first resource is for usbss, so start index from 1 */
res = platform_get_resource(pdev, IORESOURCE_MEM, id + 1);
if (!res) {
dev_err(dev, "failed to get memory for instance %d\n", id);
ret = -ENODEV;
goto err0;
ret = of_irq_to_resource(child_node, 0, &resources[1]);
if (ret == 0) {
dev_err(dev, "failed to get irq.\n");
ret = -EINVAL;
return ret;
}
res->parent = NULL;
resources[0] = *res;
/* first resource is for usbss, so start index from 1 */
res = platform_get_resource(pdev, IORESOURCE_IRQ, id + 1);
if (!res) {
dev_err(dev, "failed to get irq for instance %d\n", id);
ret = -ENODEV;
goto err0;
}
res->parent = NULL;
resources[1] = *res;
resources[1].name = "mc";
/* allocate the child platform device */
musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
if (!musb) {
dev_err(dev, "failed to allocate musb device\n");
ret = -ENOMEM;
goto err0;
return -ENOMEM;
}
musb->dev.parent = dev;
musb->dev.dma_mask = &musb_dmamask;
musb->dev.coherent_dma_mask = musb_dmamask;
musb->dev.of_node = of_node_get(child_node);
glue->musb[id] = musb;
glue->musb = musb;
ret = platform_device_add_resources(musb, resources, 2);
ret = platform_device_add_resources(musb, resources,
ARRAY_SIZE(resources));
if (ret) {
dev_err(dev, "failed to add resources\n");
goto err2;
goto err;
}
if (np) {
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(&pdev->dev,
"failed to allocate musb platform data\n");
ret = -ENOMEM;
goto err2;
}
config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
if (!config) {
dev_err(&pdev->dev,
"failed to allocate musb hdrc config\n");
ret = -ENOMEM;
goto err2;
}
of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
snprintf(res_name, sizeof(res_name), "port%d-mode", id);
of_property_read_u32(np, res_name, (u32 *)&pdata->mode);
of_property_read_u32(np, "power", (u32 *)&pdata->power);
config->multipoint = of_property_read_bool(np, "multipoint");
pdata->config = config;
config = devm_kzalloc(&parent->dev, sizeof(*config), GFP_KERNEL);
if (!config) {
dev_err(dev, "failed to allocate musb hdrc config\n");
ret = -ENOMEM;
goto err;
}
pdata.config = config;
pdata.platform_ops = &dsps_ops;
pdata->platform_ops = &dsps_ops;
config->num_eps = get_int_prop(child_node, "num-eps");
config->ram_bits = get_int_prop(child_node, "ram-bits");
pdata.mode = get_int_prop(child_node, "port-mode");
pdata.power = get_int_prop(child_node, "power");
config->multipoint = of_property_read_bool(child_node, "multipoint");
ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
ret = platform_device_add_data(musb, &pdata, sizeof(pdata));
if (ret) {
dev_err(dev, "failed to add platform_data\n");
goto err2;
goto err;
}
ret = platform_device_add(musb);
if (ret) {
dev_err(dev, "failed to register musb device\n");
goto err2;
goto err;
}
return 0;
err2:
err:
platform_device_put(musb);
err0:
return ret;
}
@ -601,14 +514,12 @@ static int dsps_probe(struct platform_device *pdev)
const struct of_device_id *match;
const struct dsps_musb_wrapper *wrp;
struct dsps_glue *glue;
struct resource *iomem;
int ret, i;
int ret;
match = of_match_node(musb_dsps_of_match, pdev->dev.of_node);
if (!match) {
dev_err(&pdev->dev, "fail to get matching of_match struct\n");
ret = -EINVAL;
goto err0;
return -EINVAL;
}
wrp = match->data;
@ -616,29 +527,13 @@ static int dsps_probe(struct platform_device *pdev)
glue = kzalloc(sizeof(*glue), GFP_KERNEL);
if (!glue) {
dev_err(&pdev->dev, "unable to allocate glue memory\n");
ret = -ENOMEM;
goto err0;
}
/* get memory resource */
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!iomem) {
dev_err(&pdev->dev, "failed to get usbss mem resourse\n");
ret = -ENODEV;
goto err1;
return -ENOMEM;
}
glue->dev = &pdev->dev;
glue->wrp = wrp;
glue->wrp = kmemdup(wrp, sizeof(*wrp), GFP_KERNEL);
if (!glue->wrp) {
dev_err(&pdev->dev, "failed to duplicate wrapper struct memory\n");
ret = -ENOMEM;
goto err1;
}
platform_set_drvdata(pdev, glue);
/* enable the usbss clocks */
pm_runtime_enable(&pdev->dev);
ret = pm_runtime_get_sync(&pdev->dev);
@ -647,17 +542,9 @@ static int dsps_probe(struct platform_device *pdev)
goto err2;
}
/* create the child platform device for all instances of musb */
for (i = 0; i < wrp->instances ; i++) {
ret = dsps_create_musb_pdev(glue, i);
if (ret != 0) {
dev_err(&pdev->dev, "failed to create child pdev\n");
/* release resources of previously created instances */
for (i--; i >= 0 ; i--)
platform_device_unregister(glue->musb[i]);
goto err3;
}
}
ret = dsps_create_musb_pdev(glue, pdev);
if (ret)
goto err3;
return 0;
@ -665,65 +552,27 @@ err3:
pm_runtime_put(&pdev->dev);
err2:
pm_runtime_disable(&pdev->dev);
kfree(glue->wrp);
err1:
kfree(glue);
err0:
return ret;
}
static int dsps_remove(struct platform_device *pdev)
{
struct dsps_glue *glue = platform_get_drvdata(pdev);
const struct dsps_musb_wrapper *wrp = glue->wrp;
int i;
/* delete the child platform device */
for (i = 0; i < wrp->instances ; i++)
platform_device_unregister(glue->musb[i]);
platform_device_unregister(glue->musb);
/* disable usbss clocks */
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
kfree(glue->wrp);
kfree(glue);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int dsps_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev->parent);
struct dsps_glue *glue = platform_get_drvdata(pdev);
const struct dsps_musb_wrapper *wrp = glue->wrp;
int i;
for (i = 0; i < wrp->instances; i++)
musb_dsps_phy_control(glue, i, 0);
return 0;
}
static int dsps_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev->parent);
struct dsps_glue *glue = platform_get_drvdata(pdev);
const struct dsps_musb_wrapper *wrp = glue->wrp;
int i;
for (i = 0; i < wrp->instances; i++)
musb_dsps_phy_control(glue, i, 1);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
static const struct dsps_musb_wrapper ti81xx_driver_data = {
static const struct dsps_musb_wrapper am33xx_driver_data = {
.revision = 0x00,
.control = 0x14,
.status = 0x18,
.eoi = 0x24,
.epintr_set = 0x38,
.epintr_clear = 0x40,
.epintr_status = 0x30,
@ -745,38 +594,23 @@ static const struct dsps_musb_wrapper ti81xx_driver_data = {
.rxep_shift = 16,
.rxep_mask = 0xfffe,
.rxep_bitmap = (0xfffe << 16),
.musb_core_offset = 0x400,
.poll_seconds = 2,
.instances = 1,
};
static const struct platform_device_id musb_dsps_id_table[] = {
{
.name = "musb-ti81xx",
.driver_data = (kernel_ulong_t) &ti81xx_driver_data,
},
{ }, /* Terminating Entry */
};
MODULE_DEVICE_TABLE(platform, musb_dsps_id_table);
#ifdef CONFIG_OF
static const struct of_device_id musb_dsps_of_match[] = {
{ .compatible = "ti,musb-am33xx",
.data = (void *) &ti81xx_driver_data, },
.data = (void *) &am33xx_driver_data, },
{ },
};
MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
#endif
static struct platform_driver dsps_usbss_driver = {
.probe = dsps_probe,
.remove = dsps_remove,
.driver = {
.name = "musb-dsps",
.pm = &dsps_pm_ops,
.of_match_table = of_match_ptr(musb_dsps_of_match),
},
.id_table = musb_dsps_id_table,
};
MODULE_DESCRIPTION("TI DSPS MUSB Glue Layer");
@ -784,14 +618,4 @@ MODULE_AUTHOR("Ravi B <ravibabu@ti.com>");
MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
MODULE_LICENSE("GPL v2");
static int __init dsps_init(void)
{
return platform_driver_register(&dsps_usbss_driver);
}
subsys_initcall(dsps_init);
static void __exit dsps_exit(void)
{
platform_driver_unregister(&dsps_usbss_driver);
}
module_exit(dsps_exit);
module_platform_driver(dsps_usbss_driver);

View File

@ -357,47 +357,49 @@ static void txstate(struct musb *musb, struct musb_request *req)
}
}
#elif defined(CONFIG_USB_TI_CPPI_DMA)
/* program endpoint CSR first, then setup DMA */
csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
csr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE |
MUSB_TXCSR_MODE;
musb_writew(epio, MUSB_TXCSR,
(MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN)
| csr);
/* ensure writebuffer is empty */
csr = musb_readw(epio, MUSB_TXCSR);
/* NOTE host side sets DMAENAB later than this; both are
* OK since the transfer dma glue (between CPPI and Mentor
* fifos) just tells CPPI it could start. Data only moves
* to the USB TX fifo when both fifos are ready.
*/
/* "mode" is irrelevant here; handle terminating ZLPs like
* PIO does, since the hardware RNDIS mode seems unreliable
* except for the last-packet-is-already-short case.
*/
use_dma = use_dma && c->channel_program(
musb_ep->dma, musb_ep->packet_sz,
0,
request->dma + request->actual,
request_size);
if (!use_dma) {
c->channel_release(musb_ep->dma);
musb_ep->dma = NULL;
csr &= ~MUSB_TXCSR_DMAENAB;
musb_writew(epio, MUSB_TXCSR, csr);
/* invariant: prequest->buf is non-null */
}
#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
use_dma = use_dma && c->channel_program(
musb_ep->dma, musb_ep->packet_sz,
request->zero,
request->dma + request->actual,
request_size);
#endif
if (is_cppi_enabled()) {
/* program endpoint CSR first, then setup DMA */
csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
csr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE |
MUSB_TXCSR_MODE;
musb_writew(epio, MUSB_TXCSR, (MUSB_TXCSR_P_WZC_BITS &
~MUSB_TXCSR_P_UNDERRUN) | csr);
/* ensure writebuffer is empty */
csr = musb_readw(epio, MUSB_TXCSR);
/*
* NOTE host side sets DMAENAB later than this; both are
* OK since the transfer dma glue (between CPPI and
* Mentor fifos) just tells CPPI it could start. Data
* only moves to the USB TX fifo when both fifos are
* ready.
*/
/*
* "mode" is irrelevant here; handle terminating ZLPs
* like PIO does, since the hardware RNDIS mode seems
* unreliable except for the
* last-packet-is-already-short case.
*/
use_dma = use_dma && c->channel_program(
musb_ep->dma, musb_ep->packet_sz,
0,
request->dma + request->actual,
request_size);
if (!use_dma) {
c->channel_release(musb_ep->dma);
musb_ep->dma = NULL;
csr &= ~MUSB_TXCSR_DMAENAB;
musb_writew(epio, MUSB_TXCSR, csr);
/* invariant: prequest->buf is non-null */
}
} else if (tusb_dma_omap())
use_dma = use_dma && c->channel_program(
musb_ep->dma, musb_ep->packet_sz,
request->zero,
request->dma + request->actual,
request_size);
}
#endif
@ -1266,7 +1268,8 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
dev_dbg(musb->controller, "req %p queued to %s while ep %s\n",
req, ep->name, "disabled");
status = -ESHUTDOWN;
goto cleanup;
unmap_dma_buffer(request, musb);
goto unlock;
}
/* add request to the list */
@ -1276,7 +1279,7 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
if (!musb_ep->busy && &request->list == musb_ep->req_list.next)
musb_ep_restart(musb, request);
cleanup:
unlock:
spin_unlock_irqrestore(&musb->lock, lockflags);
return status;
}

View File

@ -37,18 +37,10 @@
#include "musb_core.h"
#include "musbhsdma.h"
static int dma_controller_start(struct dma_controller *c)
{
/* nothing to do */
return 0;
}
static void dma_channel_release(struct dma_channel *channel);
static int dma_controller_stop(struct dma_controller *c)
static void dma_controller_stop(struct musb_dma_controller *controller)
{
struct musb_dma_controller *controller = container_of(c,
struct musb_dma_controller, controller);
struct musb *musb = controller->private_data;
struct dma_channel *channel;
u8 bit;
@ -67,8 +59,6 @@ static int dma_controller_stop(struct dma_controller *c)
}
}
}
return 0;
}
static struct dma_channel *dma_channel_allocate(struct dma_controller *c,
@ -371,8 +361,7 @@ void dma_controller_destroy(struct dma_controller *c)
struct musb_dma_controller *controller = container_of(c,
struct musb_dma_controller, controller);
if (!controller)
return;
dma_controller_stop(controller);
if (controller->irq)
free_irq(controller->irq, c);
@ -400,8 +389,6 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba
controller->private_data = musb;
controller->base = base;
controller->controller.start = dma_controller_start;
controller->controller.stop = dma_controller_stop;
controller->controller.channel_alloc = dma_channel_allocate;
controller->controller.channel_release = dma_channel_release;
controller->controller.channel_program = dma_channel_program;

View File

@ -255,7 +255,7 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
{
struct musb *musb = glue_to_musb(glue);
struct device *dev = musb->controller;
struct musb_hdrc_platform_data *pdata = dev->platform_data;
struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
struct omap_musb_board_data *data = pdata->board_data;
struct usb_otg *otg = musb->xceiv->otg;
@ -341,7 +341,7 @@ static int omap2430_musb_init(struct musb *musb)
int status = 0;
struct device *dev = musb->controller;
struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
struct musb_hdrc_platform_data *plat = dev->platform_data;
struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
struct omap_musb_board_data *data = plat->board_data;
/* We require some kind of external transceiver, hooked
@ -412,7 +412,7 @@ static void omap2430_musb_enable(struct musb *musb)
unsigned long timeout = jiffies + msecs_to_jiffies(1000);
struct device *dev = musb->controller;
struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
struct musb_hdrc_platform_data *pdata = dev->platform_data;
struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
struct omap_musb_board_data *data = pdata->board_data;
switch (glue->status) {
@ -482,7 +482,7 @@ static u64 omap2430_dmamask = DMA_BIT_MASK(32);
static int omap2430_probe(struct platform_device *pdev)
{
struct resource musb_resources[3];
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct omap_musb_board_data *data;
struct platform_device *musb;
struct omap2430_glue *glue;

View File

@ -25,7 +25,7 @@
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/usb/usb_phy_gen_xceiv.h>
#include "musb_core.h"
@ -1157,7 +1157,7 @@ static u64 tusb_dmamask = DMA_BIT_MASK(32);
static int tusb_probe(struct platform_device *pdev)
{
struct resource musb_resources[3];
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct platform_device *musb;
struct tusb6010_glue *glue;

View File

@ -66,28 +66,6 @@ struct tusb_omap_dma {
unsigned multichannel:1;
};
static int tusb_omap_dma_start(struct dma_controller *c)
{
struct tusb_omap_dma *tusb_dma;
tusb_dma = container_of(c, struct tusb_omap_dma, controller);
/* dev_dbg(musb->controller, "ep%i ch: %i\n", chdat->epnum, chdat->ch); */
return 0;
}
static int tusb_omap_dma_stop(struct dma_controller *c)
{
struct tusb_omap_dma *tusb_dma;
tusb_dma = container_of(c, struct tusb_omap_dma, controller);
/* dev_dbg(musb->controller, "ep%i ch: %i\n", chdat->epnum, chdat->ch); */
return 0;
}
/*
* Allocate dmareq0 to the current channel unless it's already taken
*/
@ -695,8 +673,6 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba
tusb_dma->dmareq = -1;
tusb_dma->sync_dev = -1;
tusb_dma->controller.start = tusb_omap_dma_start;
tusb_dma->controller.stop = tusb_omap_dma_stop;
tusb_dma->controller.channel_alloc = tusb_omap_dma_allocate;
tusb_dma->controller.channel_release = tusb_omap_dma_release;
tusb_dma->controller.channel_program = tusb_omap_dma_program;

View File

@ -227,7 +227,7 @@ ux500_of_probe(struct platform_device *pdev, struct device_node *np)
static int ux500_probe(struct platform_device *pdev)
{
struct resource musb_resources[2];
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct device_node *np = pdev->dev.of_node;
struct platform_device *musb;
struct ux500_glue *glue;

View File

@ -254,10 +254,8 @@ static int ux500_dma_channel_abort(struct dma_channel *channel)
return 0;
}
static int ux500_dma_controller_stop(struct dma_controller *c)
static void ux500_dma_controller_stop(struct ux500_dma_controller *controller)
{
struct ux500_dma_controller *controller = container_of(c,
struct ux500_dma_controller, controller);
struct ux500_dma_channel *ux500_channel;
struct dma_channel *channel;
u8 ch_num;
@ -281,18 +279,14 @@ static int ux500_dma_controller_stop(struct dma_controller *c)
if (ux500_channel->dma_chan)
dma_release_channel(ux500_channel->dma_chan);
}
return 0;
}
static int ux500_dma_controller_start(struct dma_controller *c)
static int ux500_dma_controller_start(struct ux500_dma_controller *controller)
{
struct ux500_dma_controller *controller = container_of(c,
struct ux500_dma_controller, controller);
struct ux500_dma_channel *ux500_channel = NULL;
struct musb *musb = controller->private_data;
struct device *dev = musb->controller;
struct musb_hdrc_platform_data *plat = dev->platform_data;
struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
struct ux500_musb_board_data *data;
struct dma_channel *dma_channel = NULL;
char **chan_names;
@ -347,7 +341,7 @@ static int ux500_dma_controller_start(struct dma_controller *c)
dir, ch_num);
/* Release already allocated channels */
ux500_dma_controller_stop(c);
ux500_dma_controller_stop(controller);
return -EBUSY;
}
@ -369,6 +363,7 @@ void dma_controller_destroy(struct dma_controller *c)
struct ux500_dma_controller *controller = container_of(c,
struct ux500_dma_controller, controller);
ux500_dma_controller_stop(controller);
kfree(controller);
}
@ -378,6 +373,7 @@ struct dma_controller *dma_controller_create(struct musb *musb,
struct ux500_dma_controller *controller;
struct platform_device *pdev = to_platform_device(musb->controller);
struct resource *iomem;
int ret;
controller = kzalloc(sizeof(*controller), GFP_KERNEL);
if (!controller)
@ -394,14 +390,15 @@ struct dma_controller *dma_controller_create(struct musb *musb,
controller->phy_base = (dma_addr_t) iomem->start;
controller->controller.start = ux500_dma_controller_start;
controller->controller.stop = ux500_dma_controller_stop;
controller->controller.channel_alloc = ux500_dma_channel_allocate;
controller->controller.channel_release = ux500_dma_channel_release;
controller->controller.channel_program = ux500_dma_channel_program;
controller->controller.channel_abort = ux500_dma_channel_abort;
controller->controller.is_compatible = ux500_dma_is_compatible;
ret = ux500_dma_controller_start(controller);
if (ret)
goto plat_get_fail;
return &controller->controller;
plat_get_fail:

View File

@ -1,22 +1,10 @@
#
# Physical Layer USB driver configuration
#
menuconfig USB_PHY
bool "USB Physical Layer drivers"
help
Most USB controllers have the physical layer signalling part
(commonly called a PHY) built in. However, dual-role devices
(a.k.a. USB on-the-go) which support being USB master or slave
with the same connector often use an external PHY.
menu "USB Physical Layer drivers"
The drivers in this submenu add support for such PHY devices.
They are not needed for standard master-only (or the vast
majority of slave-only) USB interfaces.
If you're not sure if this applies to you, it probably doesn't;
say N here.
if USB_PHY
config USB_PHY
def_bool n
#
# USB Transceiver Drivers
@ -24,6 +12,7 @@ if USB_PHY
config AB8500_USB
tristate "AB8500 USB Transceiver Driver"
depends on AB8500_CORE
select USB_PHY
help
Enable this to support the USB OTG transceiver in AB8500 chip.
This transceiver supports high and full speed devices plus,
@ -33,12 +22,14 @@ config FSL_USB2_OTG
bool "Freescale USB OTG Transceiver Driver"
depends on USB_EHCI_FSL && USB_FSL_USB2 && PM_RUNTIME
select USB_OTG
select USB_PHY
help
Enable this to support Freescale USB OTG transceiver.
config ISP1301_OMAP
tristate "Philips ISP1301 with OMAP OTG"
depends on I2C && ARCH_OMAP_OTG
select USB_PHY
help
If you say yes here you get support for the Philips ISP1301
USB-On-The-Go transceiver working with the OMAP OTG controller.
@ -52,12 +43,14 @@ config ISP1301_OMAP
config MV_U3D_PHY
bool "Marvell USB 3.0 PHY controller Driver"
depends on CPU_MMP3
select USB_PHY
help
Enable this to support Marvell USB 3.0 phy controller for Marvell
SoC.
config NOP_USB_XCEIV
tristate "NOP USB Transceiver Driver"
select USB_PHY
help
This driver is to be used by all the usb transceiver which are either
built-in with usb ip or which are autonomous and doesn't require any
@ -77,6 +70,7 @@ config OMAP_USB2
tristate "OMAP USB2 PHY Driver"
depends on ARCH_OMAP2PLUS
select OMAP_CONTROL_USB
select USB_PHY
help
Enable this to support the transceiver that is part of SOC. This
driver takes care of all the PHY functionality apart from comparator.
@ -87,12 +81,25 @@ config OMAP_USB3
tristate "OMAP USB3 PHY Driver"
depends on ARCH_OMAP2PLUS || COMPILE_TEST
select OMAP_CONTROL_USB
select USB_PHY
help
Enable this to support the USB3 PHY that is part of SOC. This
driver takes care of all the PHY functionality apart from comparator.
This driver interacts with the "OMAP Control USB Driver" to power
on/off the PHY.
config AM335X_CONTROL_USB
tristate
config AM335X_PHY_USB
tristate "AM335x USB PHY Driver"
select USB_PHY
select AM335X_CONTROL_USB
select NOP_USB_XCEIV
help
This driver provides PHY support for that phy which part for the
AM335x SoC.
config SAMSUNG_USBPHY
tristate
help
@ -103,6 +110,7 @@ config SAMSUNG_USBPHY
config SAMSUNG_USB2PHY
tristate "Samsung USB 2.0 PHY controller Driver"
select SAMSUNG_USBPHY
select USB_PHY
help
Enable this to support Samsung USB 2.0 (High Speed) PHY controller
driver for Samsung SoCs.
@ -110,6 +118,7 @@ config SAMSUNG_USB2PHY
config SAMSUNG_USB3PHY
tristate "Samsung USB 3.0 PHY controller Driver"
select SAMSUNG_USBPHY
select USB_PHY
help
Enable this to support Samsung USB 3.0 (Super Speed) phy controller
for samsung SoCs.
@ -117,6 +126,7 @@ config SAMSUNG_USB3PHY
config TWL4030_USB
tristate "TWL4030 USB Transceiver Driver"
depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
select USB_PHY
help
Enable this to support the USB OTG transceiver on TWL4030
family chips (including the TWL5030 and TPS659x0 devices).
@ -137,6 +147,7 @@ config TWL6030_USB
config USB_GPIO_VBUS
tristate "GPIO based peripheral-only VBUS sensing 'transceiver'"
depends on GPIOLIB
select USB_PHY
help
Provides simple GPIO VBUS sensing for controllers with an
internal transceiver via the usb_phy interface, and
@ -147,6 +158,7 @@ config USB_ISP1301
tristate "NXP ISP1301 USB transceiver support"
depends on USB || USB_GADGET
depends on I2C
select USB_PHY
help
Say Y here to add support for the NXP ISP1301 USB transceiver driver.
This chip is typically used as USB transceiver for USB host, gadget
@ -158,6 +170,7 @@ config USB_ISP1301
config USB_MSM_OTG
tristate "OTG support for Qualcomm on-chip USB controller"
depends on (USB || USB_GADGET) && ARCH_MSM
select USB_PHY
help
Enable this to support the USB OTG transceiver on MSM chips. It
handles PHY initialization, clock management, and workarounds
@ -171,6 +184,7 @@ config USB_MV_OTG
tristate "Marvell USB OTG support"
depends on USB_EHCI_MV && USB_MV_UDC && PM_RUNTIME
select USB_OTG
select USB_PHY
help
Say Y here if you want to build Marvell USB OTG transciever
driver in kernel (including PXA and MMP series). This driver
@ -182,6 +196,7 @@ config USB_MXS_PHY
tristate "Freescale MXS USB PHY support"
depends on ARCH_MXC || ARCH_MXS
select STMP_DEVICE
select USB_PHY
help
Enable this to support the Freescale MXS USB PHY.
@ -190,6 +205,7 @@ config USB_MXS_PHY
config USB_RCAR_PHY
tristate "Renesas R-Car USB PHY support"
depends on USB || USB_GADGET
select USB_PHY
help
Say Y here to add support for the Renesas R-Car USB common PHY driver.
This chip is typically used as USB PHY for USB host, gadget.
@ -212,4 +228,4 @@ config USB_ULPI_VIEWPORT
Provides read/write operations to the ULPI phy register set for
controllers with a viewport register (e.g. Chipidea/ARC controllers).
endif # USB_PHY
endmenu

View File

@ -11,8 +11,10 @@ phy-fsl-usb2-objs := phy-fsl-usb.o phy-fsm-usb.o
obj-$(CONFIG_FSL_USB2_OTG) += phy-fsl-usb2.o
obj-$(CONFIG_ISP1301_OMAP) += phy-isp1301-omap.o
obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o
obj-$(CONFIG_NOP_USB_XCEIV) += phy-nop.o
obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o
obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o
obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o
obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o
obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o
obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o

View File

@ -0,0 +1,21 @@
#ifndef _AM335x_PHY_CONTROL_H_
#define _AM335x_PHY_CONTROL_H_
struct phy_control {
void (*phy_power)(struct phy_control *phy_ctrl, u32 id, bool on);
void (*phy_wkup)(struct phy_control *phy_ctrl, u32 id, bool on);
};
static inline void phy_ctrl_power(struct phy_control *phy_ctrl, u32 id, bool on)
{
phy_ctrl->phy_power(phy_ctrl, id, on);
}
static inline void phy_ctrl_wkup(struct phy_control *phy_ctrl, u32 id, bool on)
{
phy_ctrl->phy_wkup(phy_ctrl, id, on);
}
struct phy_control *am335x_get_phy_control(struct device *dev);
#endif

View File

@ -0,0 +1,137 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/io.h>
struct phy_control {
void (*phy_power)(struct phy_control *phy_ctrl, u32 id, bool on);
void (*phy_wkup)(struct phy_control *phy_ctrl, u32 id, bool on);
};
struct am335x_control_usb {
struct device *dev;
void __iomem *phy_reg;
void __iomem *wkup;
spinlock_t lock;
struct phy_control phy_ctrl;
};
#define AM335X_USB0_CTRL 0x0
#define AM335X_USB1_CTRL 0x8
#define AM335x_USB_WKUP 0x0
#define USBPHY_CM_PWRDN (1 << 0)
#define USBPHY_OTG_PWRDN (1 << 1)
#define USBPHY_OTGVDET_EN (1 << 19)
#define USBPHY_OTGSESSEND_EN (1 << 20)
static void am335x_phy_power(struct phy_control *phy_ctrl, u32 id, bool on)
{
struct am335x_control_usb *usb_ctrl;
u32 val;
u32 reg;
usb_ctrl = container_of(phy_ctrl, struct am335x_control_usb, phy_ctrl);
switch (id) {
case 0:
reg = AM335X_USB0_CTRL;
break;
case 1:
reg = AM335X_USB1_CTRL;
break;
default:
__WARN();
return;
}
val = readl(usb_ctrl->phy_reg + reg);
if (on) {
val &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN);
val |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN;
} else {
val |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
}
writel(val, usb_ctrl->phy_reg + reg);
}
static const struct phy_control ctrl_am335x = {
.phy_power = am335x_phy_power,
};
static const struct of_device_id omap_control_usb_id_table[] = {
{ .compatible = "ti,am335x-usb-ctrl-module", .data = &ctrl_am335x },
{}
};
MODULE_DEVICE_TABLE(of, omap_control_usb_id_table);
static struct platform_driver am335x_control_driver;
static int match(struct device *dev, void *data)
{
struct device_node *node = (struct device_node *)data;
return dev->of_node == node &&
dev->driver == &am335x_control_driver.driver;
}
struct phy_control *am335x_get_phy_control(struct device *dev)
{
struct device_node *node;
struct am335x_control_usb *ctrl_usb;
node = of_parse_phandle(dev->of_node, "ti,ctrl_mod", 0);
if (!node)
return NULL;
dev = bus_find_device(&platform_bus_type, NULL, node, match);
ctrl_usb = dev_get_drvdata(dev);
if (!ctrl_usb)
return NULL;
return &ctrl_usb->phy_ctrl;
}
EXPORT_SYMBOL_GPL(am335x_get_phy_control);
static int am335x_control_usb_probe(struct platform_device *pdev)
{
struct resource *res;
struct am335x_control_usb *ctrl_usb;
const struct of_device_id *of_id;
const struct phy_control *phy_ctrl;
of_id = of_match_node(omap_control_usb_id_table, pdev->dev.of_node);
if (!of_id)
return -EINVAL;
phy_ctrl = of_id->data;
ctrl_usb = devm_kzalloc(&pdev->dev, sizeof(*ctrl_usb), GFP_KERNEL);
if (!ctrl_usb) {
dev_err(&pdev->dev, "unable to alloc memory for control usb\n");
return -ENOMEM;
}
ctrl_usb->dev = &pdev->dev;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
ctrl_usb->phy_reg = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ctrl_usb->phy_reg))
return PTR_ERR(ctrl_usb->phy_reg);
spin_lock_init(&ctrl_usb->lock);
ctrl_usb->phy_ctrl = *phy_ctrl;
dev_set_drvdata(ctrl_usb->dev, ctrl_usb);
return 0;
}
static struct platform_driver am335x_control_driver = {
.probe = am335x_control_usb_probe,
.driver = {
.name = "am335x-control-usb",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(omap_control_usb_id_table),
},
};
module_platform_driver(am335x_control_driver);
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,99 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/usb/otg.h>
#include <linux/usb/usb_phy_gen_xceiv.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include "am35x-phy-control.h"
#include "phy-generic.h"
struct am335x_phy {
struct usb_phy_gen_xceiv usb_phy_gen;
struct phy_control *phy_ctrl;
int id;
};
static int am335x_init(struct usb_phy *phy)
{
struct am335x_phy *am_phy = dev_get_drvdata(phy->dev);
phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, true);
return 0;
}
static void am335x_shutdown(struct usb_phy *phy)
{
struct am335x_phy *am_phy = dev_get_drvdata(phy->dev);
phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, false);
}
static int am335x_phy_probe(struct platform_device *pdev)
{
struct am335x_phy *am_phy;
struct device *dev = &pdev->dev;
int ret;
am_phy = devm_kzalloc(dev, sizeof(*am_phy), GFP_KERNEL);
if (!am_phy)
return -ENOMEM;
am_phy->phy_ctrl = am335x_get_phy_control(dev);
if (!am_phy->phy_ctrl)
return -EPROBE_DEFER;
am_phy->id = of_alias_get_id(pdev->dev.of_node, "phy");
if (am_phy->id < 0) {
dev_err(&pdev->dev, "Missing PHY id: %d\n", am_phy->id);
return am_phy->id;
}
ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen,
USB_PHY_TYPE_USB2, 0, false, false);
if (ret)
return ret;
ret = usb_add_phy_dev(&am_phy->usb_phy_gen.phy);
if (ret)
goto err_add;
am_phy->usb_phy_gen.phy.init = am335x_init;
am_phy->usb_phy_gen.phy.shutdown = am335x_shutdown;
platform_set_drvdata(pdev, am_phy);
return 0;
err_add:
usb_phy_gen_cleanup_phy(&am_phy->usb_phy_gen);
return ret;
}
static int am335x_phy_remove(struct platform_device *pdev)
{
struct am335x_phy *am_phy = platform_get_drvdata(pdev);
usb_remove_phy(&am_phy->usb_phy_gen.phy);
return 0;
}
static const struct of_device_id am335x_phy_ids[] = {
{ .compatible = "ti,am335x-usb-phy" },
{ }
};
MODULE_DEVICE_TABLE(of, am335x_phy_ids);
static struct platform_driver am335x_phy_driver = {
.probe = am335x_phy_probe,
.remove = am335x_phy_remove,
.driver = {
.name = "am335x-phy-driver",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(am335x_phy_ids),
},
};
module_platform_driver(am335x_phy_driver);
MODULE_LICENSE("GPL v2");

View File

@ -834,7 +834,7 @@ int usb_otg_start(struct platform_device *pdev)
int status;
struct resource *res;
u32 temp;
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
p_otg = container_of(otg_trans, struct fsl_otg, phy);
fsm = &p_otg->fsm;
@ -1105,7 +1105,7 @@ static int fsl_otg_probe(struct platform_device *pdev)
{
int ret;
if (!pdev->dev.platform_data)
if (!dev_get_platdata(&pdev->dev))
return -ENODEV;
/* configure the OTG */
@ -1137,7 +1137,7 @@ static int fsl_otg_probe(struct platform_device *pdev)
static int fsl_otg_remove(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
usb_remove_phy(&fsl_otg_dev->phy);
free_irq(fsl_otg_dev->irq, fsl_otg_dev);

View File

@ -30,19 +30,13 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/usb/otg.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/usb/usb_phy_gen_xceiv.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/of.h>
struct nop_usb_xceiv {
struct usb_phy phy;
struct device *dev;
struct clk *clk;
struct regulator *vcc;
struct regulator *reset;
};
#include "phy-generic.h"
static struct platform_device *pd;
@ -50,9 +44,9 @@ void usb_nop_xceiv_register(void)
{
if (pd)
return;
pd = platform_device_register_simple("nop_usb_xceiv", -1, NULL, 0);
pd = platform_device_register_simple("usb_phy_gen_xceiv", -1, NULL, 0);
if (!pd) {
printk(KERN_ERR "Unable to register usb nop transceiver\n");
pr_err("Unable to register generic usb transceiver\n");
return;
}
}
@ -70,9 +64,9 @@ static int nop_set_suspend(struct usb_phy *x, int suspend)
return 0;
}
static int nop_init(struct usb_phy *phy)
int usb_gen_phy_init(struct usb_phy *phy)
{
struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev);
struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev);
if (!IS_ERR(nop->vcc)) {
if (regulator_enable(nop->vcc))
@ -90,10 +84,11 @@ static int nop_init(struct usb_phy *phy)
return 0;
}
EXPORT_SYMBOL_GPL(usb_gen_phy_init);
static void nop_shutdown(struct usb_phy *phy)
void usb_gen_phy_shutdown(struct usb_phy *phy)
{
struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev);
struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev);
if (!IS_ERR(nop->reset)) {
/* Assert RESET */
@ -109,6 +104,7 @@ static void nop_shutdown(struct usb_phy *phy)
dev_err(phy->dev, "Failed to disable power\n");
}
}
EXPORT_SYMBOL_GPL(usb_gen_phy_shutdown);
static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
{
@ -139,26 +135,90 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
return 0;
}
static int nop_usb_xceiv_probe(struct platform_device *pdev)
int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
enum usb_phy_type type, u32 clk_rate, bool needs_vcc,
bool needs_reset)
{
int err;
nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg),
GFP_KERNEL);
if (!nop->phy.otg)
return -ENOMEM;
nop->clk = devm_clk_get(dev, "main_clk");
if (IS_ERR(nop->clk)) {
dev_dbg(dev, "Can't get phy clock: %ld\n",
PTR_ERR(nop->clk));
}
if (!IS_ERR(nop->clk) && clk_rate) {
err = clk_set_rate(nop->clk, clk_rate);
if (err) {
dev_err(dev, "Error setting clock rate\n");
return err;
}
}
if (!IS_ERR(nop->clk)) {
err = clk_prepare(nop->clk);
if (err) {
dev_err(dev, "Error preparing clock\n");
return err;
}
}
nop->vcc = devm_regulator_get(dev, "vcc");
if (IS_ERR(nop->vcc)) {
dev_dbg(dev, "Error getting vcc regulator: %ld\n",
PTR_ERR(nop->vcc));
if (needs_vcc)
return -EPROBE_DEFER;
}
nop->reset = devm_regulator_get(dev, "reset");
if (IS_ERR(nop->reset)) {
dev_dbg(dev, "Error getting reset regulator: %ld\n",
PTR_ERR(nop->reset));
if (needs_reset)
return -EPROBE_DEFER;
}
nop->dev = dev;
nop->phy.dev = nop->dev;
nop->phy.label = "nop-xceiv";
nop->phy.set_suspend = nop_set_suspend;
nop->phy.state = OTG_STATE_UNDEFINED;
nop->phy.type = type;
nop->phy.otg->phy = &nop->phy;
nop->phy.otg->set_host = nop_set_host;
nop->phy.otg->set_peripheral = nop_set_peripheral;
ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
return 0;
}
EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy);
void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop)
{
if (!IS_ERR(nop->clk))
clk_unprepare(nop->clk);
}
EXPORT_SYMBOL_GPL(usb_phy_gen_cleanup_phy);
static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data;
struct nop_usb_xceiv *nop;
struct usb_phy_gen_xceiv_platform_data *pdata =
dev_get_platdata(&pdev->dev);
struct usb_phy_gen_xceiv *nop;
enum usb_phy_type type = USB_PHY_TYPE_USB2;
int err;
u32 clk_rate = 0;
bool needs_vcc = false;
bool needs_reset = false;
nop = devm_kzalloc(&pdev->dev, sizeof(*nop), GFP_KERNEL);
if (!nop)
return -ENOMEM;
nop->phy.otg = devm_kzalloc(&pdev->dev, sizeof(*nop->phy.otg),
GFP_KERNEL);
if (!nop->phy.otg)
return -ENOMEM;
if (dev->of_node) {
struct device_node *node = dev->of_node;
@ -175,56 +235,18 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev)
needs_reset = pdata->needs_reset;
}
nop->clk = devm_clk_get(&pdev->dev, "main_clk");
if (IS_ERR(nop->clk)) {
dev_dbg(&pdev->dev, "Can't get phy clock: %ld\n",
PTR_ERR(nop->clk));
}
nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL);
if (!nop)
return -ENOMEM;
if (!IS_ERR(nop->clk) && clk_rate) {
err = clk_set_rate(nop->clk, clk_rate);
if (err) {
dev_err(&pdev->dev, "Error setting clock rate\n");
return err;
}
}
if (!IS_ERR(nop->clk)) {
err = clk_prepare(nop->clk);
if (err) {
dev_err(&pdev->dev, "Error preparing clock\n");
return err;
}
}
err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc,
needs_reset);
if (err)
return err;
nop->vcc = devm_regulator_get(&pdev->dev, "vcc");
if (IS_ERR(nop->vcc)) {
dev_dbg(&pdev->dev, "Error getting vcc regulator: %ld\n",
PTR_ERR(nop->vcc));
if (needs_vcc)
return -EPROBE_DEFER;
}
nop->reset = devm_regulator_get(&pdev->dev, "reset");
if (IS_ERR(nop->reset)) {
dev_dbg(&pdev->dev, "Error getting reset regulator: %ld\n",
PTR_ERR(nop->reset));
if (needs_reset)
return -EPROBE_DEFER;
}
nop->dev = &pdev->dev;
nop->phy.dev = nop->dev;
nop->phy.label = "nop-xceiv";
nop->phy.set_suspend = nop_set_suspend;
nop->phy.init = nop_init;
nop->phy.shutdown = nop_shutdown;
nop->phy.state = OTG_STATE_UNDEFINED;
nop->phy.type = type;
nop->phy.otg->phy = &nop->phy;
nop->phy.otg->set_host = nop_set_host;
nop->phy.otg->set_peripheral = nop_set_peripheral;
nop->phy.init = usb_gen_phy_init;
nop->phy.shutdown = usb_gen_phy_shutdown;
err = usb_add_phy_dev(&nop->phy);
if (err) {
@ -235,23 +257,18 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, nop);
ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
return 0;
err_add:
if (!IS_ERR(nop->clk))
clk_unprepare(nop->clk);
usb_phy_gen_cleanup_phy(nop);
return err;
}
static int nop_usb_xceiv_remove(struct platform_device *pdev)
static int usb_phy_gen_xceiv_remove(struct platform_device *pdev)
{
struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
if (!IS_ERR(nop->clk))
clk_unprepare(nop->clk);
struct usb_phy_gen_xceiv *nop = platform_get_drvdata(pdev);
usb_phy_gen_cleanup_phy(nop);
usb_remove_phy(&nop->phy);
return 0;
@ -264,29 +281,29 @@ static const struct of_device_id nop_xceiv_dt_ids[] = {
MODULE_DEVICE_TABLE(of, nop_xceiv_dt_ids);
static struct platform_driver nop_usb_xceiv_driver = {
.probe = nop_usb_xceiv_probe,
.remove = nop_usb_xceiv_remove,
static struct platform_driver usb_phy_gen_xceiv_driver = {
.probe = usb_phy_gen_xceiv_probe,
.remove = usb_phy_gen_xceiv_remove,
.driver = {
.name = "nop_usb_xceiv",
.name = "usb_phy_gen_xceiv",
.owner = THIS_MODULE,
.of_match_table = nop_xceiv_dt_ids,
},
};
static int __init nop_usb_xceiv_init(void)
static int __init usb_phy_gen_xceiv_init(void)
{
return platform_driver_register(&nop_usb_xceiv_driver);
return platform_driver_register(&usb_phy_gen_xceiv_driver);
}
subsys_initcall(nop_usb_xceiv_init);
subsys_initcall(usb_phy_gen_xceiv_init);
static void __exit nop_usb_xceiv_exit(void)
static void __exit usb_phy_gen_xceiv_exit(void)
{
platform_driver_unregister(&nop_usb_xceiv_driver);
platform_driver_unregister(&usb_phy_gen_xceiv_driver);
}
module_exit(nop_usb_xceiv_exit);
module_exit(usb_phy_gen_xceiv_exit);
MODULE_ALIAS("platform:nop_usb_xceiv");
MODULE_ALIAS("platform:usb_phy_gen_xceiv");
MODULE_AUTHOR("Texas Instruments Inc");
MODULE_DESCRIPTION("NOP USB Transceiver driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,20 @@
#ifndef _PHY_GENERIC_H_
#define _PHY_GENERIC_H_
struct usb_phy_gen_xceiv {
struct usb_phy phy;
struct device *dev;
struct clk *clk;
struct regulator *vcc;
struct regulator *reset;
};
int usb_gen_phy_init(struct usb_phy *phy);
void usb_gen_phy_shutdown(struct usb_phy *phy);
int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
enum usb_phy_type type, u32 clk_rate, bool needs_vcc,
bool needs_reset);
void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop);
#endif

Some files were not shown because too many files have changed in this diff Show More