mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
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:
@@ -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.
|
||||
|
||||
18
Documentation/devicetree/bindings/usb/ci13xxx-imx.txt
Normal file
18
Documentation/devicetree/bindings/usb/ci13xxx-imx.txt
Normal 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>;
|
||||
};
|
||||
13
Documentation/devicetree/bindings/usb/mxs-phy.txt
Normal file
13
Documentation/devicetree/bindings/usb/mxs-phy.txt
Normal 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>;
|
||||
};
|
||||
226
Documentation/usb/mass-storage.txt
Normal file
226
Documentation/usb/mass-storage.txt
Normal 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.
|
||||
@@ -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),
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
198
drivers/usb/chipidea/ci13xxx_imx.c
Normal file
198
drivers/usb/chipidea/ci13xxx_imx.c
Normal 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>");
|
||||
@@ -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");
|
||||
|
||||
@@ -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 */ }
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
Reference in New Issue
Block a user