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

Pull USB patches from Greg Kroah-Hartman:
 "Here's the big USB patch set for the 3.6-rc1 merge window.

  Lots of little changes in here, primarily for gadget controllers and
  drivers.  There's some scsi changes that I think also went in through
  the scsi tree, but they merge just fine.  All of these patches have
  been in the linux-next tree for a while now.

  Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"

Fix up trivial conflicts in include/scsi/scsi_device.h (same libata
conflict that Jeff had already encountered)

* tag 'usb-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (207 commits)
  usb: Add USB_QUIRK_RESET_RESUME for all Logitech UVC webcams
  usb: Add quirk detection based on interface information
  usb: s3c-hsotg: Add header file protection macros in s3c-hsotg.h
  USB: ehci-s5p: Add vbus setup function to the s5p ehci glue layer
  USB: add USB_VENDOR_AND_INTERFACE_INFO() macro
  USB: notify phy when root hub port connect change
  USB: remove 8 bytes of padding from usb_host_interface on 64 bit builds
  USB: option: add ZTE MF821D
  USB: sierra: QMI mode MC7710 moved to qcserial
  USB: qcserial: adding Sierra Wireless devices
  USB: qcserial: support generic Qualcomm serial ports
  USB: qcserial: make probe more flexible
  USB: qcserial: centralize probe exit path
  USB: qcserial: consolidate usb_set_interface calls
  USB: ehci-s5p: Add support for device tree
  USB: ohci-exynos: Add support for device tree
  USB: ehci-omap: fix compile failure(v1)
  usb: host: tegra: pass correct pointer in ehci_setup()
  USB: ehci-fsl: Update ifdef check to work on 64-bit ppc
  USB: serial: keyspan: Removed unrequired parentheses.
  ...
This commit is contained in:
Linus Torvalds
2012-07-26 10:23:47 -07:00
159 changed files with 8063 additions and 4146 deletions

View File

@@ -208,3 +208,15 @@ Description:
such as ACPI. This file will read either "removable" or
"fixed" if the information is available, and "unknown"
otherwise.
What: /sys/bus/usb/devices/.../ltm_capable
Date: July 2012
Contact: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Description:
USB 3.0 devices may optionally support Latency Tolerance
Messaging (LTM). They indicate their support by setting a bit
in the bmAttributes field of their SuperSpeed BOS descriptors.
If that bit is set for the device, ltm_capable will read "yes".
If the device doesn't support LTM, the file will read "no".
The file will be present for all speeds of USB devices, and will
always read "no" for USB 1.1 and USB 2.0 devices.

View File

@@ -0,0 +1,18 @@
* Freescale i.MX ci13xxx usb controllers
Required properties:
- compatible: Should be "fsl,imx27-usb"
- reg: Should contain registers location and length
- interrupts: Should contain controller interrupt
Optional properties:
- fsl,usbphy: phandler of usb phy that connects to the only one port
- vbus-supply: regulator for vbus
Examples:
usb@02184000 { /* USB OTG */
compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
reg = <0x02184000 0x200>;
interrupts = <0 43 0x04>;
fsl,usbphy = <&usbphy1>;
};

View File

@@ -0,0 +1,13 @@
* Freescale MXS USB Phy Device
Required properties:
- compatible: Should be "fsl,imx23-usbphy"
- reg: Should contain registers location and length
- interrupts: Should contain phy interrupt
Example:
usbphy1: usbphy@020c9000 {
compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
reg = <0x020c9000 0x1000>;
interrupts = <0 44 0x04>;
};

View File

@@ -0,0 +1,226 @@
* Overview
Mass Storage Gadget (or MSG) acts as a USB Mass Storage device,
appearing to the host as a disk or a CD-ROM drive. It supports
multiple logical units (LUNs). Backing storage for each LUN is
provided by a regular file or a block device, access can be limited
to read-only, and gadget can indicate that it is removable and/or
CD-ROM (the latter implies read-only access).
Its requirements are modest; only a bulk-in and a bulk-out endpoint
are needed. The memory requirement amounts to two 16K buffers.
Support is included for full-speed, high-speed and SuperSpeed
operation.
Note that the driver is slightly non-portable in that it assumes
a single memory/DMA buffer will be useable for bulk-in and bulk-out
endpoints. With most device controllers this is not an issue, but
there may be some with hardware restrictions that prevent a buffer
from being used by more than one endpoint.
This document describes how to use the gadget from user space, its
relation to mass storage function (or MSF) and different gadgets
using it, and how it differs from File Storage Gadget (or FSG). It
will talk only briefly about how to use MSF within composite
gadgets.
* Module parameters
The mass storage gadget accepts the following mass storage specific
module parameters:
- file=filename[,filename...]
This parameter lists paths to files or block devices used for
backing storage for each logical unit. There may be at most
FSG_MAX_LUNS (8) LUNs set. If more files are specified, they will
be silently ignored. See also “luns” parameter.
*BEWARE* that if a file is used as a backing storage, it may not
be modified by any other process. This is because the host
assumes the data does not change without its knowledge. It may be
read, but (if the logical unit is writable) due to buffering on
the host side, the contents are not well defined.
The size of the logical unit will be rounded down to a full
logical block. The logical block size is 2048 bytes for LUNs
simulating CD-ROM, block size of the device if the backing file is
a block device, or 512 bytes otherwise.
- removable=b[,b...]
This parameter specifies whether each logical unit should be
removable. “b” here is either “y”, “Y” or “1” for true or “n”,
“N” or “0” for false.
If this option is set for a logical unit, gadget will accept an
“eject” SCSI request (Start/Stop Unit). When it is sent, the
backing file will be closed to simulate ejection and the logical
unit will not be mountable by the host until a new backing file is
specified by userspace on the device (see “sysfs entries”
section).
If a logical unit is not removable (the default), a backing file
must be specified for it with the “file” parameter as the module
is loaded. The same applies if the module is built in, no
exceptions.
The default value of the flag is false, *HOWEVER* it used to be
true. This has been changed to better match File Storage Gadget
and because it seems like a saner default after all. Thus to
maintain compatibility with older kernels, it's best to specify
the default values. Also, if one relied on old default, explicit
“n” needs to be specified now.
Note that “removable” means the logical unit's media can be
ejected or removed (as is true for a CD-ROM drive or a card
reader). It does *not* mean that the entire gadget can be
unplugged from the host; the proper term for that is
“hot-unpluggable”.
- cdrom=b[,b...]
This parameter specifies whether each logical unit should simulate
CD-ROM. The default is false.
- ro=b[,b...]
This parameter specifies whether each logical unit should be
reported as read only. This will prevent host from modifying the
backing files.
Note that if this flag for given logical unit is false but the
backing file could not be opened in read/write mode, the gadget
will fall back to read only mode anyway.
The default value for non-CD-ROM logical units is false; for
logical units simulating CD-ROM it is forced to true.
- nofua=b[,b...]
This parameter specifies whether FUA flag should be ignored in SCSI
Write10 and Write12 commands sent to given logical units.
MS Windows mounts removable storage in “Removal optimised mode” by
default. All the writes to the media are synchronous, which is
achieved by setting the FUA (Force Unit Access) bit in SCSI
Write(10,12) commands. This forces each write to wait until the
data has actually been written out and prevents I/O requests
aggregation in block layer dramatically decreasing performance.
Note that this may mean that if the device is powered from USB and
the user unplugs the device without unmounting it first (which at
least some Windows users do), the data may be lost.
The default value is false.
- luns=N
This parameter specifies number of logical units the gadget will
have. It is limited by FSG_MAX_LUNS (8) and higher value will be
capped.
If this parameter is provided, and the number of files specified
in “file” argument is greater then the value of “luns”, all excess
files will be ignored.
If this parameter is not present, the number of logical units will
be deduced from the number of files specified in the “file”
parameter. If the file parameter is missing as well, one is
assumed.
- stall=b
Specifies whether the gadget is allowed to halt bulk endpoints.
The default is determined according to the type of USB device
controller, but usually true.
In addition to the above, the gadget also accepts the following
parameters defined by the composite framework (they are common to
all composite gadgets so just a quick listing):
- idVendor -- USB Vendor ID (16 bit integer)
- idProduct -- USB Product ID (16 bit integer)
- bcdDevice -- USB Device version (BCD) (16 bit integer)
- iManufacturer -- USB Manufacturer string (string)
- iProduct -- USB Product string (string)
- iSerialNumber -- SerialNumber string (sting)
* sysfs entries
For each logical unit, the gadget creates a directory in the sysfs
hierarchy. Inside of it the following three files are created:
- file
When read it returns the path to the backing file for the given
logical unit. If there is no backing file (possible only if the
logical unit is removable), the content is empty.
When written into, it changes the backing file for given logical
unit. This change can be performed even if given logical unit is
not specified as removable (but that may look strange to the
host). It may fail, however, if host disallowed medium removal
with the Prevent-Allow Medium Removal SCSI command.
- ro
Reflects the state of ro flag for the given logical unit. It can
be read any time, and written to when there is no backing file
open for given logical unit.
- nofua
Reflects the state of nofua flag for given logical unit. It can
be read and written.
Other then those, as usual, the values of module parameters can be
read from /sys/module/g_mass_storage/parameters/* files.
* Other gadgets using mass storage function
The Mass Storage Gadget uses the Mass Storage Function to handle
mass storage protocol. As a composite function, MSF may be used by
other gadgets as well (eg. g_multi and acm_ms).
All of the information in previous sections are valid for other
gadgets using MSF, except that support for mass storage related
module parameters may be missing, or the parameters may have
a prefix. To figure out whether any of this is true one needs to
consult the gadget's documentation or its source code.
For examples of how to include mass storage function in gadgets, one
may take a look at mass_storage.c, acm_ms.c and multi.c (sorted by
complexity).
* Relation to file storage gadget
The Mass Storage Function and thus the Mass Storage Gadget has been
based on the File Storage Gadget. The difference between the two is
that MSG is a composite gadget (ie. uses the composite framework)
while file storage gadget is a traditional gadget. From userspace
point of view this distinction does not really matter, but from
kernel hacker's point of view, this means that (i) MSG does not
duplicate code needed for handling basic USB protocol commands and
(ii) MSF can be used in any other composite gadget.
Because of that, File Storage Gadget has been deprecated and
scheduled to be removed in Linux 3.8. All users need to transition
to the Mass Storage Gadget by that time. The two gadgets behave
mostly the same from the outside except:
1. In FSG the “removable” and “cdrom” module parameters set the flag
for all logical units whereas in MSG they accept a list of y/n
values for each logical unit. If one uses only a single logical
unit this does not matter, but if there are more, the y/n value
needs to be repeated for each logical unit.
2. FSG's “serial”, “vendor”, “product” and “release” module
parameters are handled in MSG by the composite layer's parameters
named respectively: “iSerialnumber”, “idVendor”, “idProduct” and
“bcdDevice”.
3. MSG does not support FSG's test mode, thus “transport”,
“protocol” and “buflen” FSG's module parameters are not
supported. MSG always uses SCSI protocol with bulk only
transport mode and 16 KiB buffers.

View File

@@ -3376,15 +3376,15 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
CLK("usbhs_omap", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
CLK("usbhs_omap", "utmi_p1_gfclk", &dummy_ck, CK_3XXX),
CLK("usbhs_omap", "utmi_p2_gfclk", &dummy_ck, CK_3XXX),
CLK("usbhs_omap", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX),
CLK("usbhs_omap", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX),
CLK("usbhs_omap", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX),
CLK("usbhs_omap", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX),
CLK(NULL, "utmi_p1_gfclk", &dummy_ck, CK_3XXX),
CLK(NULL, "utmi_p2_gfclk", &dummy_ck, CK_3XXX),
CLK(NULL, "xclk60mhsp1_ck", &dummy_ck, CK_3XXX),
CLK(NULL, "xclk60mhsp2_ck", &dummy_ck, CK_3XXX),
CLK(NULL, "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX),
CLK(NULL, "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX),
CLK("usbhs_omap", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX),
CLK("usbhs_omap", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX),
CLK("usbhs_omap", "init_60m_fclk", &dummy_ck, CK_3XXX),
CLK(NULL, "init_60m_fclk", &dummy_ck, CK_3XXX),
CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2PLUS | CK_36XX),
CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX),
CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX),

View File

@@ -2517,7 +2517,7 @@ static int __devexit ab8500_charger_remove(struct platform_device *pdev)
dev_err(di->dev, "%s mask and set failed\n", __func__);
usb_unregister_notifier(di->usb_phy, &di->nb);
usb_put_transceiver(di->usb_phy);
usb_put_phy(di->usb_phy);
/* Delete the work queue */
destroy_workqueue(di->charger_wq);
@@ -2688,8 +2688,8 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev)
goto free_ac;
}
di->usb_phy = usb_get_transceiver();
if (!di->usb_phy) {
di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(di->usb_phy)) {
dev_err(di->dev, "failed to get usb transceiver\n");
ret = -EINVAL;
goto free_usb;
@@ -2747,7 +2747,7 @@ free_irq:
free_irq(irq, di);
}
put_usb_phy:
usb_put_transceiver(di->usb_phy);
usb_put_phy(di->usb_phy);
free_usb:
power_supply_unregister(&di->usb_chg.psy);
free_ac:

View File

@@ -415,8 +415,8 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev)
if (!isp)
return -ENOMEM;
isp->phy = usb_get_transceiver();
if (!isp->phy)
isp->phy = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(isp->phy))
goto fail0;
isp->dev = &pdev->dev;
@@ -475,7 +475,7 @@ fail2:
power_supply_unregister(&isp->psy);
fail1:
isp1704_charger_set_power(isp, 0);
usb_put_transceiver(isp->phy);
usb_put_phy(isp->phy);
fail0:
kfree(isp);
@@ -490,7 +490,7 @@ static int __devexit isp1704_charger_remove(struct platform_device *pdev)
usb_unregister_notifier(isp->phy, &isp->nb);
power_supply_unregister(&isp->psy);
usb_put_transceiver(isp->phy);
usb_put_phy(isp->phy);
isp1704_charger_set_power(isp, 0);
kfree(isp);

View File

@@ -321,12 +321,12 @@ static int pda_power_probe(struct platform_device *pdev)
}
#ifdef CONFIG_USB_OTG_UTILS
transceiver = usb_get_transceiver();
if (transceiver && !pdata->is_usb_online) {
pdata->is_usb_online = otg_is_usb_online;
}
if (transceiver && !pdata->is_ac_online) {
pdata->is_ac_online = otg_is_ac_online;
transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
if (!IS_ERR_OR_NULL(transceiver)) {
if (!pdata->is_usb_online)
pdata->is_usb_online = otg_is_usb_online;
if (!pdata->is_ac_online)
pdata->is_ac_online = otg_is_ac_online;
}
#endif
@@ -373,7 +373,7 @@ static int pda_power_probe(struct platform_device *pdev)
}
#ifdef CONFIG_USB_OTG_UTILS
if (transceiver && pdata->use_otg_notifier) {
if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
otg_nb.notifier_call = otg_handle_notification;
ret = usb_register_notifier(transceiver, &otg_nb);
if (ret) {
@@ -408,8 +408,8 @@ usb_supply_failed:
if (pdata->is_ac_online && ac_irq)
free_irq(ac_irq->start, &pda_psy_ac);
#ifdef CONFIG_USB_OTG_UTILS
if (transceiver)
usb_put_transceiver(transceiver);
if (!IS_ERR_OR_NULL(transceiver))
usb_put_phy(transceiver);
#endif
ac_irq_failed:
if (pdata->is_ac_online)
@@ -443,8 +443,8 @@ static int pda_power_remove(struct platform_device *pdev)
if (pdata->is_ac_online)
power_supply_unregister(&pda_psy_ac);
#ifdef CONFIG_USB_OTG_UTILS
if (transceiver)
usb_put_transceiver(transceiver);
if (!IS_ERR_OR_NULL(transceiver))
usb_put_phy(transceiver);
#endif
if (ac_draw) {
regulator_put(ac_draw);

View File

@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/i2c/twl.h>
@@ -479,8 +480,8 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
INIT_WORK(&bci->work, twl4030_bci_usb_work);
bci->transceiver = usb_get_transceiver();
if (bci->transceiver != NULL) {
bci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
if (!IS_ERR_OR_NULL(bci->transceiver)) {
bci->usb_nb.notifier_call = twl4030_bci_usb_ncb;
usb_register_notifier(bci->transceiver, &bci->usb_nb);
}
@@ -507,9 +508,9 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
return 0;
fail_unmask_interrupts:
if (bci->transceiver != NULL) {
if (!IS_ERR_OR_NULL(bci->transceiver)) {
usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
usb_put_transceiver(bci->transceiver);
usb_put_phy(bci->transceiver);
}
free_irq(bci->irq_bci, bci);
fail_bci_irq:
@@ -538,9 +539,9 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev)
twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
TWL4030_INTERRUPTS_BCIIMR2A);
if (bci->transceiver != NULL) {
if (!IS_ERR_OR_NULL(bci->transceiver)) {
usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
usb_put_transceiver(bci->transceiver);
usb_put_phy(bci->transceiver);
}
free_irq(bci->irq_bci, bci);
free_irq(bci->irq_chg, bci);

View File

@@ -20,6 +20,7 @@ config USB_CHIPIDEA_UDC
config USB_CHIPIDEA_HOST
bool "ChipIdea host controller"
select USB_EHCI_ROOT_HUB_TT
help
Say Y here to enable host controller functionality of the
ChipIdea driver.

View File

@@ -5,10 +5,15 @@ ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o
ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o
ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o
# Glue/Bridge layers go here
obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_msm.o
# PCI doesn't provide stubs, need to check
ifneq ($(CONFIG_PCI),)
obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_pci.o
endif
ifneq ($(CONFIG_ARCH_MSM),)
obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_msm.o
ifneq ($(CONFIG_OF_DEVICE),)
obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_imx.o
endif

View File

@@ -36,7 +36,7 @@
* @name: string description of the endpoint
* @qh: queue head for this endpoint
* @wedge: is the endpoint wedged
* @udc: pointer to the controller
* @ci: pointer to the controller
* @lock: pointer to controller's spinlock
* @td_pool: pointer to controller's TD pool
*/
@@ -54,7 +54,7 @@ struct ci13xxx_ep {
int wedge;
/* global resources */
struct ci13xxx *udc;
struct ci13xxx *ci;
spinlock_t *lock;
struct dma_pool *td_pool;
};
@@ -125,7 +125,7 @@ struct hw_bank {
* @remote_wakeup: host-enabled remote wakeup
* @suspended: suspended by host
* @test_mode: the selected test mode
* @udc_driver: platform specific information supplied by parent device
* @platdata: platform specific information supplied by parent device
* @vbus_active: is VBUS active
* @transceiver: pointer to USB PHY, if any
* @hcd: pointer to usb_hcd for ehci host driver
@@ -158,8 +158,10 @@ struct ci13xxx {
u8 suspended;
u8 test_mode;
struct ci13xxx_udc_driver *udc_driver;
struct ci13xxx_platform_data *platdata;
int vbus_active;
/* FIXME: some day, we'll not use global phy */
bool global_phy;
struct usb_phy *transceiver;
struct usb_hcd *hcd;
};
@@ -250,9 +252,9 @@ static inline int ffs_nr(u32 x)
*
* This function returns register contents
*/
static inline u32 hw_read(struct ci13xxx *udc, enum ci13xxx_regs reg, u32 mask)
static inline u32 hw_read(struct ci13xxx *ci, enum ci13xxx_regs reg, u32 mask)
{
return ioread32(udc->hw_bank.regmap[reg]) & mask;
return ioread32(ci->hw_bank.regmap[reg]) & mask;
}
/**
@@ -261,14 +263,14 @@ static inline u32 hw_read(struct ci13xxx *udc, enum ci13xxx_regs reg, u32 mask)
* @mask: bitfield mask
* @data: new value
*/
static inline void hw_write(struct ci13xxx *udc, enum ci13xxx_regs reg,
static inline void hw_write(struct ci13xxx *ci, enum ci13xxx_regs reg,
u32 mask, u32 data)
{
if (~mask)
data = (ioread32(udc->hw_bank.regmap[reg]) & ~mask)
data = (ioread32(ci->hw_bank.regmap[reg]) & ~mask)
| (data & mask);
iowrite32(data, udc->hw_bank.regmap[reg]);
iowrite32(data, ci->hw_bank.regmap[reg]);
}
/**
@@ -278,12 +280,12 @@ static inline void hw_write(struct ci13xxx *udc, enum ci13xxx_regs reg,
*
* This function returns register contents
*/
static inline u32 hw_test_and_clear(struct ci13xxx *udc, enum ci13xxx_regs reg,
static inline u32 hw_test_and_clear(struct ci13xxx *ci, enum ci13xxx_regs reg,
u32 mask)
{
u32 val = ioread32(udc->hw_bank.regmap[reg]) & mask;
u32 val = ioread32(ci->hw_bank.regmap[reg]) & mask;
iowrite32(val, udc->hw_bank.regmap[reg]);
iowrite32(val, ci->hw_bank.regmap[reg]);
return val;
}
@@ -295,12 +297,12 @@ static inline u32 hw_test_and_clear(struct ci13xxx *udc, enum ci13xxx_regs reg,
*
* This function returns register contents
*/
static inline u32 hw_test_and_write(struct ci13xxx *udc, enum ci13xxx_regs reg,
static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg,
u32 mask, u32 data)
{
u32 val = hw_read(udc, reg, ~0);
u32 val = hw_read(ci, reg, ~0);
hw_write(udc, reg, mask, data);
hw_write(ci, reg, mask, data);
return (val & mask) >> ffs_nr(mask);
}

View File

@@ -0,0 +1,198 @@
/*
* Copyright 2012 Freescale Semiconductor, Inc.
* Copyright (C) 2012 Marek Vasut <marex@denx.de>
* on behalf of DENX Software Engineering GmbH
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/dma-mapping.h>
#include <linux/usb/chipidea.h>
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include "ci.h"
#define pdev_to_phy(pdev) \
((struct usb_phy *)platform_get_drvdata(pdev))
struct ci13xxx_imx_data {
struct device_node *phy_np;
struct usb_phy *phy;
struct platform_device *ci_pdev;
struct clk *clk;
struct regulator *reg_vbus;
};
static struct ci13xxx_platform_data ci13xxx_imx_platdata __devinitdata = {
.name = "ci13xxx_imx",
.flags = CI13XXX_REQUIRE_TRANSCEIVER |
CI13XXX_PULLUP_ON_VBUS |
CI13XXX_DISABLE_STREAMING,
.capoffset = DEF_CAPOFFSET,
};
static int __devinit ci13xxx_imx_probe(struct platform_device *pdev)
{
struct ci13xxx_imx_data *data;
struct platform_device *plat_ci, *phy_pdev;
struct device_node *phy_np;
struct resource *res;
struct regulator *reg_vbus;
int ret;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data) {
dev_err(&pdev->dev, "Failed to allocate CI13xxx-IMX data!\n");
return -ENOMEM;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "Can't get device resources!\n");
return -ENOENT;
}
data->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(data->clk)) {
dev_err(&pdev->dev,
"Failed to get clock, err=%ld\n", PTR_ERR(data->clk));
return PTR_ERR(data->clk);
}
ret = clk_prepare_enable(data->clk);
if (ret) {
dev_err(&pdev->dev,
"Failed to prepare or enable clock, err=%d\n", ret);
return ret;
}
phy_np = of_parse_phandle(pdev->dev.of_node, "fsl,usbphy", 0);
if (phy_np) {
data->phy_np = phy_np;
phy_pdev = of_find_device_by_node(phy_np);
if (phy_pdev) {
struct usb_phy *phy;
phy = pdev_to_phy(phy_pdev);
if (phy &&
try_module_get(phy_pdev->dev.driver->owner)) {
usb_phy_init(phy);
data->phy = phy;
}
}
}
/* we only support host now, so enable vbus here */
reg_vbus = devm_regulator_get(&pdev->dev, "vbus");
if (!IS_ERR(reg_vbus)) {
ret = regulator_enable(reg_vbus);
if (ret) {
dev_err(&pdev->dev,
"Failed to enable vbus regulator, err=%d\n",
ret);
goto put_np;
}
data->reg_vbus = reg_vbus;
} else {
reg_vbus = NULL;
}
ci13xxx_imx_platdata.phy = data->phy;
if (!pdev->dev.dma_mask) {
pdev->dev.dma_mask = devm_kzalloc(&pdev->dev,
sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
if (!pdev->dev.dma_mask) {
ret = -ENOMEM;
dev_err(&pdev->dev, "Failed to alloc dma_mask!\n");
goto err;
}
*pdev->dev.dma_mask = DMA_BIT_MASK(32);
dma_set_coherent_mask(&pdev->dev, *pdev->dev.dma_mask);
}
plat_ci = ci13xxx_add_device(&pdev->dev,
pdev->resource, pdev->num_resources,
&ci13xxx_imx_platdata);
if (IS_ERR(plat_ci)) {
ret = PTR_ERR(plat_ci);
dev_err(&pdev->dev,
"Can't register ci_hdrc platform device, err=%d\n",
ret);
goto err;
}
data->ci_pdev = plat_ci;
platform_set_drvdata(pdev, data);
pm_runtime_no_callbacks(&pdev->dev);
pm_runtime_enable(&pdev->dev);
return 0;
err:
if (reg_vbus)
regulator_disable(reg_vbus);
put_np:
if (phy_np)
of_node_put(phy_np);
clk_disable_unprepare(data->clk);
return ret;
}
static int __devexit ci13xxx_imx_remove(struct platform_device *pdev)
{
struct ci13xxx_imx_data *data = platform_get_drvdata(pdev);
pm_runtime_disable(&pdev->dev);
ci13xxx_remove_device(data->ci_pdev);
if (data->reg_vbus)
regulator_disable(data->reg_vbus);
if (data->phy) {
usb_phy_shutdown(data->phy);
module_put(data->phy->dev->driver->owner);
}
of_node_put(data->phy_np);
clk_disable_unprepare(data->clk);
platform_set_drvdata(pdev, NULL);
return 0;
}
static const struct of_device_id ci13xxx_imx_dt_ids[] = {
{ .compatible = "fsl,imx27-usb", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ci13xxx_imx_dt_ids);
static struct platform_driver ci13xxx_imx_driver = {
.probe = ci13xxx_imx_probe,
.remove = __devexit_p(ci13xxx_imx_remove),
.driver = {
.name = "imx_usb",
.owner = THIS_MODULE,
.of_match_table = ci13xxx_imx_dt_ids,
},
};
module_platform_driver(ci13xxx_imx_driver);
MODULE_ALIAS("platform:imx-usb");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("CI13xxx i.MX USB binding");
MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");

View File

@@ -15,11 +15,11 @@
#include "ci.h"
#define MSM_USB_BASE (udc->hw_bank.abs)
#define MSM_USB_BASE (ci->hw_bank.abs)
static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event)
static void ci13xxx_msm_notify_event(struct ci13xxx *ci, unsigned event)
{
struct device *dev = udc->gadget.dev.parent;
struct device *dev = ci->gadget.dev.parent;
int val;
switch (event) {
@@ -34,18 +34,18 @@ static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event)
* Put the transceiver in non-driving mode. Otherwise host
* may not detect soft-disconnection.
*/
val = usb_phy_io_read(udc->transceiver, ULPI_FUNC_CTRL);
val = usb_phy_io_read(ci->transceiver, ULPI_FUNC_CTRL);
val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
usb_phy_io_write(udc->transceiver, val, ULPI_FUNC_CTRL);
usb_phy_io_write(ci->transceiver, val, ULPI_FUNC_CTRL);
break;
default:
dev_dbg(dev, "unknown ci13xxx_udc event\n");
dev_dbg(dev, "unknown ci13xxx event\n");
break;
}
}
static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
static struct ci13xxx_platform_data ci13xxx_msm_platdata = {
.name = "ci13xxx_msm",
.flags = CI13XXX_REGS_SHARED |
CI13XXX_REQUIRE_TRANSCEIVER |
@@ -55,56 +55,45 @@ static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
.notify_event = ci13xxx_msm_notify_event,
};
static int ci13xxx_msm_probe(struct platform_device *pdev)
static int __devinit ci13xxx_msm_probe(struct platform_device *pdev)
{
struct platform_device *plat_ci;
int ret;
dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n");
plat_ci = platform_device_alloc("ci_hdrc", -1);
if (!plat_ci) {
dev_err(&pdev->dev, "can't allocate ci_hdrc platform device\n");
return -ENOMEM;
plat_ci = ci13xxx_add_device(&pdev->dev,
pdev->resource, pdev->num_resources,
&ci13xxx_msm_platdata);
if (IS_ERR(plat_ci)) {
dev_err(&pdev->dev, "ci13xxx_add_device failed!\n");
return PTR_ERR(plat_ci);
}
ret = platform_device_add_resources(plat_ci, pdev->resource,
pdev->num_resources);
if (ret) {
dev_err(&pdev->dev, "can't add resources to platform device\n");
goto put_platform;
}
ret = platform_device_add_data(plat_ci, &ci13xxx_msm_udc_driver,
sizeof(ci13xxx_msm_udc_driver));
if (ret)
goto put_platform;
ret = platform_device_add(plat_ci);
if (ret)
goto put_platform;
platform_set_drvdata(pdev, plat_ci);
pm_runtime_no_callbacks(&pdev->dev);
pm_runtime_enable(&pdev->dev);
return 0;
}
put_platform:
platform_device_put(plat_ci);
static int __devexit ci13xxx_msm_remove(struct platform_device *pdev)
{
struct platform_device *plat_ci = platform_get_drvdata(pdev);
return ret;
pm_runtime_disable(&pdev->dev);
ci13xxx_remove_device(plat_ci);
return 0;
}
static struct platform_driver ci13xxx_msm_driver = {
.probe = ci13xxx_msm_probe,
.remove = __devexit_p(ci13xxx_msm_remove),
.driver = { .name = "msm_hsusb", },
};
module_platform_driver(ci13xxx_msm_driver);
MODULE_ALIAS("platform:msm_hsusb");
static int __init ci13xxx_msm_init(void)
{
return platform_driver_register(&ci13xxx_msm_driver);
}
module_init(ci13xxx_msm_init);
MODULE_LICENSE("GPL v2");

View File

@@ -23,17 +23,17 @@
/******************************************************************************
* PCI block
*****************************************************************************/
struct ci13xxx_udc_driver pci_driver = {
struct ci13xxx_platform_data pci_platdata = {
.name = UDC_DRIVER_NAME,
.capoffset = DEF_CAPOFFSET,
};
struct ci13xxx_udc_driver langwell_pci_driver = {
struct ci13xxx_platform_data langwell_pci_platdata = {
.name = UDC_DRIVER_NAME,
.capoffset = 0,
};
struct ci13xxx_udc_driver penwell_pci_driver = {
struct ci13xxx_platform_data penwell_pci_platdata = {
.name = UDC_DRIVER_NAME,
.capoffset = 0,
.power_budget = 200,
@@ -51,12 +51,12 @@ struct ci13xxx_udc_driver penwell_pci_driver = {
static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct ci13xxx_udc_driver *driver = (void *)id->driver_data;
struct ci13xxx_platform_data *platdata = (void *)id->driver_data;
struct platform_device *plat_ci;
struct resource res[3];
int retval = 0, nres = 2;
if (!driver) {
if (!platdata) {
dev_err(&pdev->dev, "device doesn't provide driver data\n");
return -ENODEV;
}
@@ -75,13 +75,6 @@ static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
pci_set_master(pdev);
pci_try_set_mwi(pdev);
plat_ci = platform_device_alloc("ci_hdrc", -1);
if (!plat_ci) {
dev_err(&pdev->dev, "can't allocate ci_hdrc platform device\n");
retval = -ENOMEM;
goto disable_device;
}
memset(res, 0, sizeof(res));
res[0].start = pci_resource_start(pdev, 0);
res[0].end = pci_resource_end(pdev, 0);
@@ -89,32 +82,17 @@ static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
res[1].start = pdev->irq;
res[1].flags = IORESOURCE_IRQ;
retval = platform_device_add_resources(plat_ci, res, nres);
if (retval) {
dev_err(&pdev->dev, "can't add resources to platform device\n");
goto put_platform;
plat_ci = ci13xxx_add_device(&pdev->dev, res, nres, platdata);
if (IS_ERR(plat_ci)) {
dev_err(&pdev->dev, "ci13xxx_add_device failed!\n");
retval = PTR_ERR(plat_ci);
goto disable_device;
}
retval = platform_device_add_data(plat_ci, driver, sizeof(*driver));
if (retval)
goto put_platform;
dma_set_coherent_mask(&plat_ci->dev, pdev->dev.coherent_dma_mask);
plat_ci->dev.dma_mask = pdev->dev.dma_mask;
plat_ci->dev.dma_parms = pdev->dev.dma_parms;
plat_ci->dev.parent = &pdev->dev;
pci_set_drvdata(pdev, plat_ci);
retval = platform_device_add(plat_ci);
if (retval)
goto put_platform;
return 0;
put_platform:
pci_set_drvdata(pdev, NULL);
platform_device_put(plat_ci);
disable_device:
pci_disable_device(pdev);
done:
@@ -133,7 +111,7 @@ static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
{
struct platform_device *plat_ci = pci_get_drvdata(pdev);
platform_device_unregister(plat_ci);
ci13xxx_remove_device(plat_ci);
pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
}
@@ -147,19 +125,19 @@ static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = {
{
PCI_DEVICE(0x153F, 0x1004),
.driver_data = (kernel_ulong_t)&pci_driver,
.driver_data = (kernel_ulong_t)&pci_platdata,
},
{
PCI_DEVICE(0x153F, 0x1006),
.driver_data = (kernel_ulong_t)&pci_driver,
.driver_data = (kernel_ulong_t)&pci_platdata,
},
{
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0811),
.driver_data = (kernel_ulong_t)&langwell_pci_driver,
.driver_data = (kernel_ulong_t)&langwell_pci_platdata,
},
{
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0829),
.driver_data = (kernel_ulong_t)&penwell_pci_driver,
.driver_data = (kernel_ulong_t)&penwell_pci_platdata,
},
{ 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ }
};

View File

@@ -56,6 +56,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/idr.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
@@ -179,7 +180,7 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
ci->hw_bank.abs = base;
ci->hw_bank.cap = ci->hw_bank.abs;
ci->hw_bank.cap += ci->udc_driver->capoffset;
ci->hw_bank.cap += ci->platdata->capoffset;
ci->hw_bank.op = ci->hw_bank.cap + ioread8(ci->hw_bank.cap);
hw_alloc_regmap(ci, false);
@@ -227,11 +228,11 @@ int hw_device_reset(struct ci13xxx *ci, u32 mode)
udelay(10); /* not RTOS friendly */
if (ci->udc_driver->notify_event)
ci->udc_driver->notify_event(ci,
if (ci->platdata->notify_event)
ci->platdata->notify_event(ci,
CI13XXX_CONTROLLER_RESET_EVENT);
if (ci->udc_driver->flags & CI13XXX_DISABLE_STREAMING)
if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING)
hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
/* USBMODE should be configured step by step */
@@ -332,6 +333,59 @@ static irqreturn_t ci_irq(int irq, void *data)
return ci->role == CI_ROLE_END ? ret : ci_role(ci)->irq(ci);
}
static DEFINE_IDA(ci_ida);
struct platform_device *ci13xxx_add_device(struct device *dev,
struct resource *res, int nres,
struct ci13xxx_platform_data *platdata)
{
struct platform_device *pdev;
int id, ret;
id = ida_simple_get(&ci_ida, 0, 0, GFP_KERNEL);
if (id < 0)
return ERR_PTR(id);
pdev = platform_device_alloc("ci_hdrc", id);
if (!pdev) {
ret = -ENOMEM;
goto put_id;
}
pdev->dev.parent = dev;
pdev->dev.dma_mask = dev->dma_mask;
pdev->dev.dma_parms = dev->dma_parms;
dma_set_coherent_mask(&pdev->dev, dev->coherent_dma_mask);
ret = platform_device_add_resources(pdev, res, nres);
if (ret)
goto err;
ret = platform_device_add_data(pdev, platdata, sizeof(*platdata));
if (ret)
goto err;
ret = platform_device_add(pdev);
if (ret)
goto err;
return pdev;
err:
platform_device_put(pdev);
put_id:
ida_simple_remove(&ci_ida, id);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(ci13xxx_add_device);
void ci13xxx_remove_device(struct platform_device *pdev)
{
platform_device_unregister(pdev);
ida_simple_remove(&ci_ida, pdev->id);
}
EXPORT_SYMBOL_GPL(ci13xxx_remove_device);
static int __devinit ci_hdrc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -364,7 +418,11 @@ static int __devinit ci_hdrc_probe(struct platform_device *pdev)
}
ci->dev = dev;
ci->udc_driver = dev->platform_data;
ci->platdata = dev->platform_data;
if (ci->platdata->phy)
ci->transceiver = ci->platdata->phy;
else
ci->global_phy = true;
ret = hw_device_init(ci, base);
if (ret < 0) {
@@ -419,7 +477,7 @@ static int __devinit ci_hdrc_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, ci);
ret = request_irq(ci->irq, ci_irq, IRQF_SHARED, ci->udc_driver->name,
ret = request_irq(ci->irq, ci_irq, IRQF_SHARED, ci->platdata->name,
ci);
if (ret)
goto stop;

View File

@@ -68,15 +68,15 @@ void dbg_interrupt(u32 intmask)
*
* This function returns number of registers read
*/
static size_t hw_register_read(struct ci13xxx *udc, u32 *buf, size_t size)
static size_t hw_register_read(struct ci13xxx *ci, u32 *buf, size_t size)
{
unsigned i;
if (size > udc->hw_bank.size)
size = udc->hw_bank.size;
if (size > ci->hw_bank.size)
size = ci->hw_bank.size;
for (i = 0; i < size; i++)
buf[i] = hw_read(udc, i * sizeof(u32), ~0);
buf[i] = hw_read(ci, i * sizeof(u32), ~0);
return size;
}
@@ -88,18 +88,18 @@ static size_t hw_register_read(struct ci13xxx *udc, u32 *buf, size_t size)
*
* This function returns an error code
*/
static int hw_register_write(struct ci13xxx *udc, u16 addr, u32 data)
static int hw_register_write(struct ci13xxx *ci, u16 addr, u32 data)
{
/* align */
addr /= sizeof(u32);
if (addr >= udc->hw_bank.size)
if (addr >= ci->hw_bank.size)
return -EINVAL;
/* align */
addr *= sizeof(u32);
hw_write(udc, addr, ~0, data);
hw_write(ci, addr, ~0, data);
return 0;
}
@@ -110,13 +110,13 @@ static int hw_register_write(struct ci13xxx *udc, u16 addr, u32 data)
*
* This function returns an error code
*/
static int hw_intr_clear(struct ci13xxx *udc, int n)
static int hw_intr_clear(struct ci13xxx *ci, int n)
{
if (n >= REG_BITS)
return -EINVAL;
hw_write(udc, OP_USBINTR, BIT(n), 0);
hw_write(udc, OP_USBSTS, BIT(n), BIT(n));
hw_write(ci, OP_USBINTR, BIT(n), 0);
hw_write(ci, OP_USBSTS, BIT(n), BIT(n));
return 0;
}
@@ -127,15 +127,15 @@ static int hw_intr_clear(struct ci13xxx *udc, int n)
*
* This function returns an error code
*/
static int hw_intr_force(struct ci13xxx *udc, int n)
static int hw_intr_force(struct ci13xxx *ci, int n)
{
if (n >= REG_BITS)
return -EINVAL;
hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
hw_write(udc, OP_USBINTR, BIT(n), BIT(n));
hw_write(udc, OP_USBSTS, BIT(n), BIT(n));
hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, 0);
hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
hw_write(ci, OP_USBINTR, BIT(n), BIT(n));
hw_write(ci, OP_USBSTS, BIT(n), BIT(n));
hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, 0);
return 0;
}
@@ -147,12 +147,12 @@ static int hw_intr_force(struct ci13xxx *udc, int n)
static ssize_t show_device(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
struct usb_gadget *gadget = &udc->gadget;
struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
struct usb_gadget *gadget = &ci->gadget;
int n = 0;
if (attr == NULL || buf == NULL) {
dev_err(udc->dev, "[%s] EINVAL\n", __func__);
dev_err(ci->dev, "[%s] EINVAL\n", __func__);
return 0;
}
@@ -188,8 +188,8 @@ static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
struct usb_gadget_driver *driver = udc->driver;
struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
struct usb_gadget_driver *driver = ci->driver;
int n = 0;
if (attr == NULL || buf == NULL) {
@@ -412,22 +412,22 @@ static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
u32 intr;
unsigned i, j, n = 0;
if (attr == NULL || buf == NULL) {
dev_err(udc->dev, "[%s] EINVAL\n", __func__);
dev_err(ci->dev, "[%s] EINVAL\n", __func__);
return 0;
}
spin_lock_irqsave(&udc->lock, flags);
spin_lock_irqsave(&ci->lock, flags);
/*n += scnprintf(buf + n, PAGE_SIZE - n,
"status = %08x\n", hw_read_intr_status(udc));
"status = %08x\n", hw_read_intr_status(ci));
n += scnprintf(buf + n, PAGE_SIZE - n,
"enable = %08x\n", hw_read_intr_enable(udc));*/
"enable = %08x\n", hw_read_intr_enable(ci));*/
n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
isr_statistics.test);
@@ -471,7 +471,7 @@ static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
}
spin_unlock_irqrestore(&udc->lock, flags);
spin_unlock_irqrestore(&ci->lock, flags);
return n;
}
@@ -485,31 +485,31 @@ static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
unsigned en, bit;
if (attr == NULL || buf == NULL) {
dev_err(udc->dev, "EINVAL\n");
dev_err(ci->dev, "EINVAL\n");
goto done;
}
if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
dev_err(udc->dev, "<1|0> <bit>: enable|disable interrupt\n");
dev_err(ci->dev, "<1|0> <bit>: enable|disable interrupt\n");
goto done;
}
spin_lock_irqsave(&udc->lock, flags);
spin_lock_irqsave(&ci->lock, flags);
if (en) {
if (hw_intr_force(udc, bit))
if (hw_intr_force(ci, bit))
dev_err(dev, "invalid bit number\n");
else
isr_statistics.test++;
} else {
if (hw_intr_clear(udc, bit))
if (hw_intr_clear(ci, bit))
dev_err(dev, "invalid bit number\n");
}
spin_unlock_irqrestore(&udc->lock, flags);
spin_unlock_irqrestore(&ci->lock, flags);
done:
return count;
@@ -524,18 +524,18 @@ static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
static ssize_t show_port_test(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
unsigned mode;
if (attr == NULL || buf == NULL) {
dev_err(udc->dev, "EINVAL\n");
dev_err(ci->dev, "EINVAL\n");
return 0;
}
spin_lock_irqsave(&udc->lock, flags);
mode = hw_port_test_get(udc);
spin_unlock_irqrestore(&udc->lock, flags);
spin_lock_irqsave(&ci->lock, flags);
mode = hw_port_test_get(ci);
spin_unlock_irqrestore(&ci->lock, flags);
return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
}
@@ -549,24 +549,24 @@ static ssize_t store_port_test(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
unsigned mode;
if (attr == NULL || buf == NULL) {
dev_err(udc->dev, "[%s] EINVAL\n", __func__);
dev_err(ci->dev, "[%s] EINVAL\n", __func__);
goto done;
}
if (sscanf(buf, "%u", &mode) != 1) {
dev_err(udc->dev, "<mode>: set port test mode");
dev_err(ci->dev, "<mode>: set port test mode");
goto done;
}
spin_lock_irqsave(&udc->lock, flags);
if (hw_port_test_set(udc, mode))
dev_err(udc->dev, "invalid mode\n");
spin_unlock_irqrestore(&udc->lock, flags);
spin_lock_irqsave(&ci->lock, flags);
if (hw_port_test_set(ci, mode))
dev_err(ci->dev, "invalid mode\n");
spin_unlock_irqrestore(&ci->lock, flags);
done:
return count;
@@ -582,20 +582,20 @@ static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
unsigned i, j, n = 0;
if (attr == NULL || buf == NULL) {
dev_err(udc->dev, "[%s] EINVAL\n", __func__);
dev_err(ci->dev, "[%s] EINVAL\n", __func__);
return 0;
}
spin_lock_irqsave(&udc->lock, flags);
for (i = 0; i < udc->hw_ep_max/2; i++) {
struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
spin_lock_irqsave(&ci->lock, flags);
for (i = 0; i < ci->hw_ep_max/2; i++) {
struct ci13xxx_ep *mEpRx = &ci->ci13xxx_ep[i];
struct ci13xxx_ep *mEpTx =
&udc->ci13xxx_ep[i + udc->hw_ep_max/2];
&ci->ci13xxx_ep[i + ci->hw_ep_max/2];
n += scnprintf(buf + n, PAGE_SIZE - n,
"EP=%02i: RX=%08X TX=%08X\n",
i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
@@ -606,7 +606,7 @@ static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
*((u32 *)mEpTx->qh.ptr + j));
}
}
spin_unlock_irqrestore(&udc->lock, flags);
spin_unlock_irqrestore(&ci->lock, flags);
return n;
}
@@ -621,25 +621,25 @@ static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
static ssize_t show_registers(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
u32 *dump;
unsigned i, k, n = 0;
if (attr == NULL || buf == NULL) {
dev_err(udc->dev, "[%s] EINVAL\n", __func__);
dev_err(ci->dev, "[%s] EINVAL\n", __func__);
return 0;
}
dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
if (!dump) {
dev_err(udc->dev, "%s: out of memory\n", __func__);
dev_err(ci->dev, "%s: out of memory\n", __func__);
return 0;
}
spin_lock_irqsave(&udc->lock, flags);
k = hw_register_read(udc, dump, DUMP_ENTRIES);
spin_unlock_irqrestore(&udc->lock, flags);
spin_lock_irqsave(&ci->lock, flags);
k = hw_register_read(ci, dump, DUMP_ENTRIES);
spin_unlock_irqrestore(&ci->lock, flags);
for (i = 0; i < k; i++) {
n += scnprintf(buf + n, PAGE_SIZE - n,
@@ -660,24 +660,24 @@ static ssize_t store_registers(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long addr, data, flags;
if (attr == NULL || buf == NULL) {
dev_err(udc->dev, "[%s] EINVAL\n", __func__);
dev_err(ci->dev, "[%s] EINVAL\n", __func__);
goto done;
}
if (sscanf(buf, "%li %li", &addr, &data) != 2) {
dev_err(udc->dev,
dev_err(ci->dev,
"<addr> <data>: write data to register address\n");
goto done;
}
spin_lock_irqsave(&udc->lock, flags);
if (hw_register_write(udc, addr, data))
dev_err(udc->dev, "invalid address range\n");
spin_unlock_irqrestore(&udc->lock, flags);
spin_lock_irqsave(&ci->lock, flags);
if (hw_register_write(ci, addr, data))
dev_err(ci->dev, "invalid address range\n");
spin_unlock_irqrestore(&ci->lock, flags);
done:
return count;
@@ -693,34 +693,34 @@ static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
struct list_head *ptr = NULL;
struct ci13xxx_req *req = NULL;
unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
if (attr == NULL || buf == NULL) {
dev_err(udc->dev, "[%s] EINVAL\n", __func__);
dev_err(ci->dev, "[%s] EINVAL\n", __func__);
return 0;
}
spin_lock_irqsave(&udc->lock, flags);
for (i = 0; i < udc->hw_ep_max; i++)
list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
spin_lock_irqsave(&ci->lock, flags);
for (i = 0; i < ci->hw_ep_max; i++)
list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue)
{
req = list_entry(ptr, struct ci13xxx_req, queue);
n += scnprintf(buf + n, PAGE_SIZE - n,
"EP=%02i: TD=%08X %s\n",
i % udc->hw_ep_max/2, (u32)req->dma,
((i < udc->hw_ep_max/2) ? "RX" : "TX"));
i % ci->hw_ep_max/2, (u32)req->dma,
((i < ci->hw_ep_max/2) ? "RX" : "TX"));
for (j = 0; j < qSize; j++)
n += scnprintf(buf + n, PAGE_SIZE - n,
" %04X: %08X\n", j,
*((u32 *)req->ptr + j));
}
spin_unlock_irqrestore(&udc->lock, flags);
spin_unlock_irqrestore(&ci->lock, flags);
return n;
}

View File

@@ -116,7 +116,8 @@ static int host_start(struct ci13xxx *ci)
hcd->regs = ci->hw_bank.abs;
hcd->has_tt = 1;
hcd->power_budget = ci->udc_driver->power_budget;
hcd->power_budget = ci->platdata->power_budget;
hcd->phy = ci->transceiver;
ehci = hcd_to_ehci(hcd);
ehci->caps = ci->hw_bank.cap;

File diff suppressed because it is too large Load Diff

View File

@@ -996,7 +996,7 @@ static int acm_probe(struct usb_interface *intf,
case USB_CDC_CALL_MANAGEMENT_TYPE:
call_management_function = buffer[3];
call_interface_num = buffer[4];
if ( (quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3)
if ((quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3)
dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n");
break;
default:

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