diff options
22 files changed, 2674 insertions, 1 deletions
@@ -21,6 +21,9 @@ driver-core.current/driver-core-allow-certain-drivers-prohibit-bind-unbind-via-s # USB patches for 2.6.32 ################################# usb.current/usb-rndis_host-debug-info-clobbered-before-it-is-logged.patch +usb.current/usb-serial-sierra-driver-send_setup-autopm-fix.patch +usb.current/usb-r8a66597-hcd-fix-cannot-detect-a-device-when-uses_new_polling-is-set.patch +usb.current/usb-option-tlaytech-tue800-support.patch ################################# @@ -59,6 +62,14 @@ tty/tty-const-constify-remaining-tty_operations.patch tty/tty-esp-remove-broken-driver.patch tty/tty-istallion-kill-off-the-bkl-ioctl.patch tty/tty-stallion-kill-bkl-ioctl.patch +tty/tty_port-add-tty_port_open-helper.patch +tty/tty_port-coding-style-cleaning-pass.patch +tty/usb_serial-use-the-shutdown-operation.patch +tty/usb_serial-kill-port-mutex.patch +tty/opticon-fix-resume-logic.patch +tty/serial-fix-null-pointer-dereference.patch +tty/serial-cascade-needless-conditionals.patch +tty/serial-8250-calculate-irqflags-bitmask-before-loop.patch ################################# # USB stuff (after 2.6.32 is out) @@ -81,6 +92,10 @@ usb/usb-modifications-for-at91sam9g10.patch usb/usb-usbtmc-minor-formatting-cleanups.patch usb/usb-whci-hcd-decode-more-qhead-fields-in-the-debug-files.patch usb/usb-wusb-add-wusb_phy_rate-sysfs-file-to-host-controllers.patch +usb/usb-otg-add-support-for-ulpi-connected-external-transceivers.patch +usb/usb-otg-add-generic-driver-for-ulpi-otg-transceiver.patch +usb/usb-host-ehci-introduce-omap-ehci-hcd-driver.patch +usb/usb-improved-error-handling-in-usb_port_suspend.patch ################################# # Staging stuff @@ -134,6 +149,11 @@ staging/staging-comedi-remove-check-for-have_compat_ioctl.patch staging/staging-comedi-don-t-check-for-enoioctlcmd.patch staging/staging-comedi-remove-__cplusplus-check.patch staging/staging-comedi-remove-extern-macro-since-it-is-not-used.patch +staging/staging-comedi-adl_pci8164-coding-style-fixes.patch +staging/staging-comedi-multiq3-remove-warning-on-braces.patch +staging/staging-comedi-multiq3-add-kern_.patch +staging/staging-comedi-addi-data-cleanup-redundant-tests-on-unsigned.patch +staging/staging-comedi-pcl726-fix-coding-style-issues.patch staging/staging-xvmalloc-memory-allocator.patch staging/staging-virtual-block-device-driver.patch @@ -212,6 +232,7 @@ staging/staging-netwave-move-driver-to-staging.patch staging/staging-netwave-add-todo-file.patch staging/staging-octeon-don-t-ignore-request_irq-return-code.patch staging/staging-vt6656-use-lowercase-for-via-usb-vendor-id.patch +staging/staging-vt6655-correct-unsigned-bound-issue.patch staging/staging-remove-stlc45xx-driver.patch # tty stuff still under work @@ -223,4 +244,3 @@ staging/staging-remove-stlc45xx-driver.patch #tty.work/serial-f81216-helper - diff --git a/staging/staging-comedi-addi-data-cleanup-redundant-tests-on-unsigned.patch b/staging/staging-comedi-addi-data-cleanup-redundant-tests-on-unsigned.patch new file mode 100644 index 00000000000000..1d3c5721aebd7e --- /dev/null +++ b/staging/staging-comedi-addi-data-cleanup-redundant-tests-on-unsigned.patch @@ -0,0 +1,157 @@ +From roel.kluin@gmail.com Tue Oct 27 10:37:41 2009 +From: Roel Kluin <roel.kluin@gmail.com> +Date: Fri, 23 Oct 2009 12:26:25 +0200 +Subject: Staging: comedi: addi-data: Cleanup redundant tests on unsigned +To: Greg Kroah-Hartman <gregkh@suse.de>, Bill Pemberton <wfp5p@virginia.edu>, devel@driverdev.osuosl.org, linux-kernel@vger.kernel.org, Andrew Morton <akpm@linux-foundation.org> +Message-ID: <4AE184D1.4030006@gmail.com> + + +The variables are unsigned so the test `>= 0' is always true, +In these cases the other part of the test catch wrapped values. + +Signed-off-by: Roel Kluin <roel.kluin@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c | 3 +-- + drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c | 2 +- + drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c | 2 +- + drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c | 2 +- + drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c | 2 +- + drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c | 4 ++-- + drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c | 2 +- + drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c | 5 ++--- + drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c | 2 +- + drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c | 2 +- + 10 files changed, 12 insertions(+), 14 deletions(-) + +--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c ++++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c +@@ -1386,8 +1386,7 @@ int i_APCI1710_ReadChronoValue(struct co + /* Test the timout parameter */ + /*****************************/ + +- if ((ui_TimeOut >= 0) +- && (ui_TimeOut <= 65535UL)) { ++ if (ui_TimeOut <= 65535UL) { + + for (;;) { + /*******************/ +--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c ++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c +@@ -150,7 +150,7 @@ int i_APCI1032_Read1DigitalInput(struct + unsigned int ui_TmpValue = 0; + unsigned int ui_Channel; + ui_Channel = CR_CHAN(insn->chanspec); +- if (ui_Channel >= 0 && ui_Channel <= 31) { ++ if (ui_Channel <= 31) { + ui_TmpValue = (unsigned int) inl(devpriv->iobase + APCI1032_DIGITAL_IP); + /* + * since only 1 channel reqd to bring it to last bit it is rotated 8 +--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c ++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +@@ -968,7 +968,7 @@ int i_APCI1500_ReadMoreDigitalInput(stru + + switch (data[0]) { + case 0: +- if (ui_Channel >= 0 && ui_Channel <= 15) { ++ if (ui_Channel <= 15) { + ui_TmpValue = + (unsigned int) inw(devpriv->i_IobaseAddon + + APCI1500_DIGITAL_IP); +--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c ++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c +@@ -79,7 +79,7 @@ int i_APCI1516_Read1DigitalInput(struct + unsigned int ui_TmpValue = 0; + unsigned int ui_Channel; + ui_Channel = CR_CHAN(insn->chanspec); +- if (ui_Channel >= 0 && ui_Channel <= 7) { ++ if (ui_Channel <= 7) { + ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI1516_DIGITAL_IP); + /* since only 1 channel reqd to bring it to last bit it is rotated */ + /* 8 +(chan - 1) times then ANDed with 1 for last bit. */ +--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c ++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c +@@ -154,7 +154,7 @@ int i_APCI1564_Read1DigitalInput(struct + unsigned int ui_Channel; + + ui_Channel = CR_CHAN(insn->chanspec); +- if (ui_Channel >= 0 && ui_Channel <= 31) { ++ if (ui_Channel <= 31) { + ui_TmpValue = + (unsigned int) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP); + /* +--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c ++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c +@@ -117,7 +117,7 @@ int i_APCI2016_WriteDigitalOutput(struct + unsigned int ui_NoOfChannel; + unsigned int ui_Temp, ui_Temp1; + ui_NoOfChannel = CR_CHAN(insn->chanspec); +- if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) { ++ if (ui_NoOfChannel > 15) { + comedi_error(dev, + "Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n"); + return -EINVAL; +@@ -272,7 +272,7 @@ int i_APCI2016_BitsDigitalOutput(struct + unsigned int ui_Temp; + unsigned int ui_NoOfChannel; + ui_NoOfChannel = CR_CHAN(insn->chanspec); +- if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) { ++ if (ui_NoOfChannel > 15) { + comedi_error(dev, + "Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n"); + return -EINVAL; +--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c ++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c +@@ -79,7 +79,7 @@ int i_APCI2200_Read1DigitalInput(struct + unsigned int ui_TmpValue = 0; + unsigned int ui_Channel; + ui_Channel = CR_CHAN(insn->chanspec); +- if (ui_Channel >= 0 && ui_Channel <= 7) { ++ if (ui_Channel <= 7) { + ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI2200_DIGITAL_IP); + *data = (ui_TmpValue >> ui_Channel) & 0x1; + } /* if(ui_Channel >= 0 && ui_Channel <=7) */ +--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c ++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c +@@ -2350,7 +2350,7 @@ int i_APCI3120_InsnReadDigitalInput(stru + ui_Chan = CR_CHAN(insn->chanspec); /* channel specified */ + + /* this_board->i_hwdrv_InsnReadDigitalInput(dev,ui_Chan,data); */ +- if (ui_Chan >= 0 && ui_Chan <= 3) { ++ if (ui_Chan <= 3) { + ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI3120_RD_STATUS); + + /* +@@ -2539,8 +2539,7 @@ int i_APCI3120_InsnWriteDigitalOutput(st + "Not a valid Data !!! ,Data should be 1 or 0\n"); + return -EINVAL; + } +- if ((ui_NoOfChannel > (this_board->i_NbrDoChannel - 1)) +- || (ui_NoOfChannel < 0)) { ++ if (ui_NoOfChannel > this_board->i_NbrDoChannel - 1) { + comedi_error(dev, + "This board doesn't have specified channel !!! \n"); + return -EINVAL; +--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c ++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c +@@ -461,7 +461,7 @@ int i_APCI3200_GetChannelCalibrationValu + if (s_BoardInfos[dev->minor].i_ConnectionType == 1) { + /* if diff */ + +- if ((ui_Channel_num >= 0) && (ui_Channel_num <= 1)) ++ if (ui_Channel_num <= 1) + i_DiffChannel = ui_Channel_num, i_Module = 0; + else if ((ui_Channel_num >= 2) && (ui_Channel_num <= 3)) + i_DiffChannel = ui_Channel_num - 2, i_Module = 1; +--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c ++++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c +@@ -148,7 +148,7 @@ int i_APCI3XXX_AnalogInputConfigOperatin + /* Test the convert time value */ + /*******************************/ + +- if ((dw_ReloadValue >= 0) && (dw_ReloadValue <= 65535)) { ++ if (dw_ReloadValue <= 65535) { + dw_TestReloadValue = dw_ReloadValue; + + if (b_TimeBase == 1) { diff --git a/staging/staging-comedi-adl_pci8164-coding-style-fixes.patch b/staging/staging-comedi-adl_pci8164-coding-style-fixes.patch new file mode 100644 index 00000000000000..1316aa0b96cee5 --- /dev/null +++ b/staging/staging-comedi-adl_pci8164-coding-style-fixes.patch @@ -0,0 +1,122 @@ +From bruno.braga@gmail.com Tue Oct 27 10:33:27 2009 +From: "BRAGA, Bruno" <bruno.braga@gmail.com> +Date: Thu, 22 Oct 2009 11:55:36 +0900 +Subject: Staging: comedi: adl_pci8164 coding style fixes +To: Greg KH <greg@kroah.com> +Message-ID: <86ca47940910211955y4c6083eco32f8a7fe95fdecaf@mail.gmail.com> + +From: BRAGA, Bruno <bruno.braga@gmail.com> + +Corrected coding style: +- excessive curly braces +- printk without KERN_* logging +- 80+ chars per line of code + +Signed-off-by: BRAGA, Bruno <bruno.braga@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/staging/comedi/drivers/adl_pci8164.c | 37 +++++++++++++-------------- + 1 file changed, 19 insertions(+), 18 deletions(-) + +--- a/drivers/staging/comedi/drivers/adl_pci8164.c ++++ b/drivers/staging/comedi/drivers/adl_pci8164.c +@@ -35,6 +35,7 @@ Configuration Options: + */ + + #include "../comedidev.h" ++#include <linux/kernel.h> + #include <linux/delay.h> + #include "comedi_fc.h" + #include "comedi_pci.h" +@@ -128,8 +129,8 @@ static int adl_pci8164_attach(struct com + struct comedi_subdevice *s; + int bus, slot; + +- printk("comedi: attempt to attach...\n"); +- printk("comedi%d: adl_pci8164\n", dev->minor); ++ printk(KERN_INFO "comedi: attempt to attach...\n"); ++ printk(KERN_INFO "comedi%d: adl_pci8164\n", dev->minor); + + dev->board_name = "pci8164"; + bus = it->options[0]; +@@ -150,19 +151,18 @@ static int adl_pci8164_attach(struct com + if (bus || slot) { + /* requested particular bus/slot */ + if (pcidev->bus->number != bus +- || PCI_SLOT(pcidev->devfn) != slot) { ++ || PCI_SLOT(pcidev->devfn) != slot) + continue; +- } + } + devpriv->pci_dev = pcidev; + if (comedi_pci_enable(pcidev, "adl_pci8164") < 0) { +- printk +- ("comedi%d: Failed to enable PCI device and request regions\n", +- dev->minor); ++ printk(KERN_ERR "comedi%d: Failed to enable " ++ "PCI device and request regions\n", dev->minor); + return -EIO; + } + dev->iobase = pci_resource_start(pcidev, 2); +- printk("comedi: base addr %4lx\n", dev->iobase); ++ printk(KERN_DEBUG "comedi: base addr %4lx\n", ++ dev->iobase); + + s = dev->subdevices + 0; + s->type = COMEDI_SUBD_PROC; +@@ -204,25 +204,24 @@ static int adl_pci8164_attach(struct com + s->insn_read = adl_pci8164_insn_read_buf1; + s->insn_write = adl_pci8164_insn_write_buf1; + +- printk("comedi: attached\n"); ++ printk(KERN_INFO "comedi: attached\n"); + + return 1; + } + } + +- printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", +- dev->minor, bus, slot); ++ printk(KERN_ERR "comedi%d: no supported board found!" ++ "(req. bus/slot : %d/%d)\n", dev->minor, bus, slot); + return -EIO; + } + + static int adl_pci8164_detach(struct comedi_device *dev) + { +- printk("comedi%d: pci8164: remove\n", dev->minor); ++ printk(KERN_INFO "comedi%d: pci8164: remove\n", dev->minor); + + if (devpriv && devpriv->pci_dev) { +- if (dev->iobase) { ++ if (dev->iobase) + comedi_pci_disable(devpriv->pci_dev); +- } + pci_dev_put(devpriv->pci_dev); + } + +@@ -267,8 +266,9 @@ static void adl_pci8164_insn_read(struct + } + + data[0] = inw(dev->iobase + axis_reg + offset); +- printk("comedi: pci8164 %s read -> %04X:%04X on axis %s\n", action, +- data[0], data[1], axisname); ++ printk(KERN_DEBUG "comedi: pci8164 %s read -> " ++ "%04X:%04X on axis %s\n", ++ action, data[0], data[1], axisname); + } + + static int adl_pci8164_insn_read_msts(struct comedi_device *dev, +@@ -347,8 +347,9 @@ static void adl_pci8164_insn_out(struct + + outw(data[0], dev->iobase + axis_reg + offset); + +- printk("comedi: pci8164 %s write -> %04X:%04X on axis %s\n", action, +- data[0], data[1], axisname); ++ printk(KERN_DEBUG "comedi: pci8164 %s write -> " ++ "%04X:%04X on axis %s\n", ++ action, data[0], data[1], axisname); + + } + diff --git a/staging/staging-comedi-multiq3-add-kern_.patch b/staging/staging-comedi-multiq3-add-kern_.patch new file mode 100644 index 00000000000000..34d5b575bff232 --- /dev/null +++ b/staging/staging-comedi-multiq3-add-kern_.patch @@ -0,0 +1,55 @@ +From klaas.van.gend@mvista.com Tue Oct 27 10:34:48 2009 +From: Klaas van Gend <klaas.van.gend@mvista.com> +Date: Thu, 22 Oct 2009 07:51:00 +0200 +Subject: staging: comedi: multiq3: add KERN_ +To: gregkh@suse.de +Cc: Klaas van Gend <klaas.van.gend@mvista.com> +Message-ID: <1256190660-14913-2-git-send-email-klaas.van.gend@mvista.com> + + +Add KERN_ to printk statements to reduce the number of warnings +shown by checkpatch.pl. + +Signed-off-by: Klaas van Gend <klaas.van.gend@mvista.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/staging/comedi/drivers/multiq3.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/drivers/staging/comedi/drivers/multiq3.c ++++ b/drivers/staging/comedi/drivers/multiq3.c +@@ -252,9 +252,9 @@ static int multiq3_attach(struct comedi_ + struct comedi_subdevice *s; + + iobase = it->options[0]; +- printk("comedi%d: multiq3: 0x%04lx ", dev->minor, iobase); ++ printk(KERN_INFO "comedi%d: multiq3: 0x%04lx ", dev->minor, iobase); + if (!request_region(iobase, MULTIQ3_SIZE, "multiq3")) { +- printk("comedi%d: I/O port conflict\n", dev->minor); ++ printk(KERN_ERR "comedi%d: I/O port conflict\n", dev->minor); + return -EIO; + } + +@@ -262,9 +262,10 @@ static int multiq3_attach(struct comedi_ + + irq = it->options[1]; + if (irq) +- printk("comedi%d: irq = %u ignored\n", dev->minor, irq); ++ printk(KERN_WARNING "comedi%d: irq = %u ignored\n", ++ dev->minor, irq); + else +- printk("comedi%d: no irq\n", dev->minor); ++ printk(KERN_WARNING "comedi%d: no irq\n", dev->minor); + dev->board_name = "multiq3"; + result = alloc_subdevices(dev, 5); + if (result < 0) +@@ -328,7 +329,7 @@ static int multiq3_attach(struct comedi_ + + static int multiq3_detach(struct comedi_device *dev) + { +- printk("comedi%d: multiq3: remove\n", dev->minor); ++ printk(KERN_INFO "comedi%d: multiq3: remove\n", dev->minor); + + if (dev->iobase) + release_region(dev->iobase, MULTIQ3_SIZE); diff --git a/staging/staging-comedi-multiq3-remove-warning-on-braces.patch b/staging/staging-comedi-multiq3-remove-warning-on-braces.patch new file mode 100644 index 00000000000000..74d8f5318d73d9 --- /dev/null +++ b/staging/staging-comedi-multiq3-remove-warning-on-braces.patch @@ -0,0 +1,61 @@ +From klaas.van.gend@mvista.com Tue Oct 27 10:34:35 2009 +From: Klaas van Gend <klaas.van.gend@mvista.com> +Date: Thu, 22 Oct 2009 07:50:59 +0200 +Subject: staging: comedi: multiq3: remove warning on braces +To: gregkh@suse.de +Cc: Klaas van Gend <klaas.van.gend@mvista.com> +Message-ID: <1256190660-14913-1-git-send-email-klaas.van.gend@mvista.com> + + +Remove braces in if statements to make the file exhibit less warnings +when checked using checkpatch.pl. + +Signed-off-by: Klaas van Gend <klaas.van.gend@mvista.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/staging/comedi/drivers/multiq3.c | 14 +++++--------- + 1 file changed, 5 insertions(+), 9 deletions(-) + +--- a/drivers/staging/comedi/drivers/multiq3.c ++++ b/drivers/staging/comedi/drivers/multiq3.c +@@ -144,9 +144,8 @@ static int multiq3_ao_insn_read(struct c + int i; + int chan = CR_CHAN(insn->chanspec); + +- for (i = 0; i < insn->n; i++) { ++ for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_readback[chan]; +- } + + return i; + } +@@ -262,11 +261,10 @@ static int multiq3_attach(struct comedi_ + dev->iobase = iobase; + + irq = it->options[1]; +- if (irq) { ++ if (irq) + printk("comedi%d: irq = %u ignored\n", dev->minor, irq); +- } else { ++ else + printk("comedi%d: no irq\n", dev->minor); +- } + dev->board_name = "multiq3"; + result = alloc_subdevices(dev, 5); + if (result < 0) +@@ -332,12 +330,10 @@ static int multiq3_detach(struct comedi_ + { + printk("comedi%d: multiq3: remove\n", dev->minor); + +- if (dev->iobase) { ++ if (dev->iobase) + release_region(dev->iobase, MULTIQ3_SIZE); +- } +- if (dev->irq) { ++ if (dev->irq) + free_irq(dev->irq, dev); +- } + + return 0; + } diff --git a/staging/staging-comedi-pcl726-fix-coding-style-issues.patch b/staging/staging-comedi-pcl726-fix-coding-style-issues.patch new file mode 100644 index 00000000000000..e6fd1d1ab07f9e --- /dev/null +++ b/staging/staging-comedi-pcl726-fix-coding-style-issues.patch @@ -0,0 +1,128 @@ +From kevyn.alexandre.pare@gmail.com Tue Oct 27 10:38:04 2009 +From: Kevyn-Alexandre Par� <kevyn.alexandre.pare@gmail.com> +Date: Fri, 23 Oct 2009 17:34:17 -0400 +Subject: Staging: comedi: pcl726: fix coding style issues +To: greg@kroah.com +Cc: Kevyn-Alexandre Par� <kevyn.alexandre.pare@gmail.com> +Message-ID: <1256333657-12832-1-git-send-email-kevyn.alexandre.pare@gmail.com> +Status: RO +X-Status: A +Content-Length: 3541 +Lines: 115 + + +From: Kevyn-Alexandre Par� <kevyn.alexandre.pare@gmail.com> + +Signed-off-by: Kevyn-Alexandre Par� <kevyn.alexandre.pare@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/staging/comedi/drivers/pcl726.c | 41 +++++++++++++++----------------- + 1 file changed, 20 insertions(+), 21 deletions(-) + +--- a/drivers/staging/comedi/drivers/pcl726.c ++++ b/drivers/staging/comedi/drivers/pcl726.c +@@ -39,27 +39,27 @@ Interrupts are not supported. + Options for PCL-726: + [0] - IO Base + [2]...[7] - D/A output range for channel 1-6: +- 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, +- 4: 4-20mA, 5: unknown (external reference) ++ 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, ++ 4: 4-20mA, 5: unknown (external reference) + + Options for PCL-727: + [0] - IO Base + [2]...[13] - D/A output range for channel 1-12: +- 0: 0-5V, 1: 0-10V, 2: +/-5V, +- 3: 4-20mA ++ 0: 0-5V, 1: 0-10V, 2: +/-5V, ++ 3: 4-20mA + + Options for PCL-728 and ACL-6128: + [0] - IO Base + [2], [3] - D/A output range for channel 1 and 2: +- 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, +- 4: 4-20mA, 5: 0-20mA ++ 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, ++ 4: 4-20mA, 5: 0-20mA + + Options for ACL-6126: + [0] - IO Base + [1] - IRQ (0=disable, 3, 5, 6, 7, 9, 10, 11, 12, 15) (currently ignored) + [2]...[7] - D/A output range for channel 1-6: +- 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, +- 4: 4-20mA ++ 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, ++ 4: 4-20mA + */ + + /* +@@ -127,7 +127,8 @@ struct pcl726_board { + int di_lo; + int do_hi; + int do_lo; +- const struct comedi_lrange *const *range_type_list; /* list of supported ranges */ ++ const struct comedi_lrange *const *range_type_list; ++ /* list of supported ranges */ + }; + + static const struct pcl726_board boardtypes[] = { +@@ -204,9 +205,8 @@ static int pcl726_ao_insn_read(struct co + int chan = CR_CHAN(insn->chanspec); + int n; + +- for (n = 0; n < insn->n; n++) { ++ for (n = 0; n < insn->n; n++) + data[n] = devpriv->ao_readback[chan]; +- } + return n; + } + +@@ -256,10 +256,10 @@ static int pcl726_attach(struct comedi_d + + iobase = it->options[0]; + iorange = this_board->io_range; +- printk("comedi%d: pcl726: board=%s, 0x%03lx ", dev->minor, ++ printk(KERN_WARNING "comedi%d: pcl726: board=%s, 0x%03lx ", dev->minor, + this_board->name, iobase); + if (!request_region(iobase, iorange, "pcl726")) { +- printk("I/O port conflict\n"); ++ printk(KERN_WARNING "I/O port conflict\n"); + return -EIO; + } + +@@ -283,16 +283,16 @@ static int pcl726_attach(struct comedi_d + devpriv->first_chan = 2; + if (irq) { /* we want to use IRQ */ + if (((1 << irq) & boardtypes[board].IRQbits) == 0) { +- printk +- (", IRQ %d is out of allowed range, DISABLING IT", +- irq); ++ printk(KERN_WARNING ++ ", IRQ %d is out of allowed range," ++ " DISABLING IT", irq); + irq = 0; /* Bad IRQ */ + } else { + if (request_irq(irq, interrupt_pcl818, 0, + "pcl726", dev)) { +- printk +- (", unable to allocate IRQ %d, DISABLING IT", +- irq); ++ printk(KERN_WARNING ++ ", unable to allocate IRQ %d," ++ " DISABLING IT", irq); + irq = 0; /* Can't use IRQ */ + } else { + printk(", irq=%d", irq); +@@ -372,9 +372,8 @@ static int pcl726_detach(struct comedi_d + /* printk("comedi%d: pcl726: remove\n",dev->minor); */ + + #ifdef ACL6126_IRQ +- if (dev->irq) { ++ if (dev->irq) + free_irq(dev->irq, dev); +- } + #endif + + if (dev->iobase) diff --git a/staging/staging-vt6655-correct-unsigned-bound-issue.patch b/staging/staging-vt6655-correct-unsigned-bound-issue.patch new file mode 100644 index 00000000000000..4bc6f30dd04793 --- /dev/null +++ b/staging/staging-vt6655-correct-unsigned-bound-issue.patch @@ -0,0 +1,41 @@ +From roel.kluin@gmail.com Tue Oct 27 10:22:28 2009 +From: Roel Kluin <roel.kluin@gmail.com> +Date: Fri, 16 Oct 2009 20:17:57 +0200 +Subject: Staging: vt6655: Correct unsigned bound issue +To: Roel Kluin <roel.kluin@gmail.com> +Cc: devel@driverdev.osuosl.org, Andrew Morton <akpm@linux-foundation.org>, Greg Kroah-Hartman <gregkh@suse.de> +Message-ID: <4AD8B8D5.40906@gmail.com> + + +uNodeIndex is unsigned, check whether it is within bounds instead. + +Signed-off-by: Roel Kluin <roel.kluin@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/staging/vt6655/wroute.c | 2 +- + drivers/staging/vt6656/rxtx.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/staging/vt6655/wroute.c ++++ b/drivers/staging/vt6655/wroute.c +@@ -113,7 +113,7 @@ BOOL ROUTEbRelay (PSDevice pDevice, PBYT + } + + if (pDevice->bEnableHostWEP) { +- if (uNodeIndex >= 0) { ++ if (uNodeIndex < MAX_NODE_NUM + 1) { + pTransmitKey = &STempKey; + pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite; + pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex; +--- a/drivers/staging/vt6656/rxtx.c ++++ b/drivers/staging/vt6656/rxtx.c +@@ -3153,7 +3153,7 @@ bRelayPacketSend ( + } + + if (pDevice->bEnableHostWEP) { +- if (uNodeIndex >= 0) { ++ if (uNodeIndex < MAX_NODE_NUM + 1) { + pTransmitKey = &STempKey; + pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite; + pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex; diff --git a/tty/opticon-fix-resume-logic.patch b/tty/opticon-fix-resume-logic.patch new file mode 100644 index 00000000000000..3335b23dd16710 --- /dev/null +++ b/tty/opticon-fix-resume-logic.patch @@ -0,0 +1,32 @@ +From alan@linux.intel.com Tue Oct 27 10:08:01 2009 +From: Alan Cox <alan@linux.intel.com> +Date: Tue, 06 Oct 2009 16:06:57 +0100 +Subject: [PATCH 5/5] opticon: Fix resume logic +To: greg@kroah.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org +Message-ID: <20091006150651.9431.16939.stgit@localhost.localdomain> + + +Opticon now takes the right mutex to check the port status but the status +check is done wrongly for the modern serial code, so fix it. + +Signed-off-by: Alan Cox <alan@linux.intel.com> +Cc: Alan Stern <stern@rowland.harvard.edu> +Cc: Oliver Neukum <oliver@neukum.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/opticon.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/usb/serial/opticon.c ++++ b/drivers/usb/serial/opticon.c +@@ -502,7 +502,8 @@ static int opticon_resume(struct usb_int + int result; + + mutex_lock(&port->port.mutex); +- if (port->port.count) ++ /* This is protected by the port mutex against close/open */ ++ if (test_bit(ASYNCB_INITIALIZED, &port->port.flags)) + result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO); + else + result = 0; diff --git a/tty/serial-8250-calculate-irqflags-bitmask-before-loop.patch b/tty/serial-8250-calculate-irqflags-bitmask-before-loop.patch new file mode 100644 index 00000000000000..e67d804738ce1d --- /dev/null +++ b/tty/serial-8250-calculate-irqflags-bitmask-before-loop.patch @@ -0,0 +1,72 @@ +From andre.goddard@gmail.com Tue Oct 27 10:44:02 2009 +From: Andr� Goddard Rosa <andre.goddard@gmail.com> +Date: Sun, 25 Oct 2009 12:01:34 -0200 +Subject: serial, 8250: calculate irqflags bitmask before loop +To: alan@linux.intel.com, Andrew Morton <akpm@linux-foundation.org>, ddaney@caviumnetworks.com, tpaoletti@caviumnetworks.com, gregkh@suse.de +Cc: me <andre.goddard@gmail.com> +Message-ID: <b8bf37780910250701r58d25082y12ea482f6c1b2ea4@mail.gmail.com> + + +Signed-off-by: Andr� Goddard Rosa <andre.goddard@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/serial/8250.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +--- a/drivers/serial/8250.c ++++ b/drivers/serial/8250.c +@@ -2646,7 +2646,7 @@ static void __init serial8250_isa_init_p + { + struct uart_8250_port *up; + static int first = 1; +- int i; ++ int i, irqflag = 0; + + if (!first) + return; +@@ -2670,6 +2670,9 @@ static void __init serial8250_isa_init_p + up->port.ops = &serial8250_pops; + } + ++ if (share_irqs) ++ irqflag = IRQF_SHARED; ++ + for (i = 0, up = serial8250_ports; + i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; + i++, up++) { +@@ -2683,8 +2686,7 @@ static void __init serial8250_isa_init_p + up->port.iotype = old_serial_port[i].io_type; + up->port.regshift = old_serial_port[i].iomem_reg_shift; + set_io_from_upio(&up->port); +- if (share_irqs) +- up->port.irqflags |= IRQF_SHARED; ++ up->port.irqflags |= irqflag; + } + } + +@@ -2940,10 +2942,13 @@ static int __devinit serial8250_probe(st + { + struct plat_serial8250_port *p = dev->dev.platform_data; + struct uart_port port; +- int ret, i; ++ int ret, i, irqflag = 0; + + memset(&port, 0, sizeof(struct uart_port)); + ++ if (share_irqs) ++ irqflag = IRQF_SHARED; ++ + for (i = 0; p && p->flags != 0; p++, i++) { + port.iobase = p->iobase; + port.membase = p->membase; +@@ -2960,8 +2965,7 @@ static int __devinit serial8250_probe(st + port.serial_in = p->serial_in; + port.serial_out = p->serial_out; + port.dev = &dev->dev; +- if (share_irqs) +- port.irqflags |= IRQF_SHARED; ++ port.irqflags |= irqflag; + ret = serial8250_register_port(&port); + if (ret < 0) { + dev_err(&dev->dev, "unable to register port at index %d " diff --git a/tty/serial-cascade-needless-conditionals.patch b/tty/serial-cascade-needless-conditionals.patch new file mode 100644 index 00000000000000..a3ac4ac1c8db32 --- /dev/null +++ b/tty/serial-cascade-needless-conditionals.patch @@ -0,0 +1,55 @@ +From andre.goddard@gmail.com Tue Oct 27 10:42:56 2009 +From: Andr� Goddard Rosa <andre.goddard@gmail.com> +Date: Sun, 25 Oct 2009 11:18:26 -0200 +Subject: serial: cascade needless conditionals +To: gregkh@suse.de, alan@linux.intel.com, Andrew Morton <akpm@linux-foundation.org>, adobriyan@gmail.com +Cc: me <andre.goddard@gmail.com> +Message-ID: <b8bf37780910250618h3edce547y41a8dd03e4fb4e71@mail.gmail.com> + + +Signed-off-by: Andr� Goddard Rosa <andre.goddard@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/serial/serial_core.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +--- a/drivers/serial/serial_core.c ++++ b/drivers/serial/serial_core.c +@@ -342,11 +342,11 @@ uart_get_baud_rate(struct uart_port *por + + if (flags == UPF_SPD_HI) + altbaud = 57600; +- if (flags == UPF_SPD_VHI) ++ else if (flags == UPF_SPD_VHI) + altbaud = 115200; +- if (flags == UPF_SPD_SHI) ++ else if (flags == UPF_SPD_SHI) + altbaud = 230400; +- if (flags == UPF_SPD_WARP) ++ else if (flags == UPF_SPD_WARP) + altbaud = 460800; + + for (try = 0; try < 2; try++) { +@@ -1217,9 +1217,8 @@ static void uart_set_termios(struct tty_ + /* Handle transition to B0 status */ + if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) + uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR); +- + /* Handle transition away from B0 status */ +- if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { ++ else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { + unsigned int mask = TIOCM_DTR; + if (!(cflag & CRTSCTS) || + !test_bit(TTY_THROTTLED, &tty->flags)) +@@ -1234,9 +1233,8 @@ static void uart_set_termios(struct tty_ + __uart_start(tty); + spin_unlock_irqrestore(&state->uart_port->lock, flags); + } +- + /* Handle turning on CRTSCTS */ +- if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { ++ else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { + spin_lock_irqsave(&state->uart_port->lock, flags); + if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) { + tty->hw_stopped = 1; diff --git a/tty/serial-fix-null-pointer-dereference.patch b/tty/serial-fix-null-pointer-dereference.patch new file mode 100644 index 00000000000000..772ff351c318bc --- /dev/null +++ b/tty/serial-fix-null-pointer-dereference.patch @@ -0,0 +1,71 @@ +From andre.goddard@gmail.com Tue Oct 27 10:42:06 2009 +From: Andr� Goddard Rosa <andre.goddard@gmail.com> +Date: Sun, 25 Oct 2009 11:16:32 -0200 +Subject: serial: fix NULL pointer dereference +To: gregkh@suse.de, alan@linux.intel.com, Andrew Morton <akpm@linux-foundation.org>, adobriyan@gmail.com +Cc: me <andre.goddard@gmail.com> +Message-ID: <b8bf37780910250616g8f204d2h471bd4d511a4816@mail.gmail.com> + +From: Andr� Goddard Rosa <andre.goddard@gmail.com> + +If kzalloc() or alloc_tty_driver() fails, we call: + put_tty_driver(normal = NULL). + +Then: + put_tty_driver -> tty_driver_kref_put -> kref_put(&NULL->kref, ...) + +Signed-off-by: Andr� Goddard Rosa <andre.goddard@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/serial/serial_core.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +--- a/drivers/serial/serial_core.c ++++ b/drivers/serial/serial_core.c +@@ -2344,7 +2344,7 @@ static const struct tty_operations uart_ + */ + int uart_register_driver(struct uart_driver *drv) + { +- struct tty_driver *normal = NULL; ++ struct tty_driver *normal; + int i, retval; + + BUG_ON(drv->state); +@@ -2354,13 +2354,12 @@ int uart_register_driver(struct uart_dri + * we have a large number of ports to handle. + */ + drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL); +- retval = -ENOMEM; + if (!drv->state) + goto out; + +- normal = alloc_tty_driver(drv->nr); ++ normal = alloc_tty_driver(drv->nr); + if (!normal) +- goto out; ++ goto out_kfree; + + drv->tty_driver = normal; + +@@ -2393,12 +2392,14 @@ int uart_register_driver(struct uart_dri + } + + retval = tty_register_driver(normal); +- out: +- if (retval < 0) { +- put_tty_driver(normal); +- kfree(drv->state); +- } +- return retval; ++ if (retval >= 0) ++ return retval; ++ ++ put_tty_driver(normal); ++out_kfree: ++ kfree(drv->state); ++out: ++ return -ENOMEM; + } + + /** diff --git a/tty/tty_port-add-tty_port_open-helper.patch b/tty/tty_port-add-tty_port_open-helper.patch new file mode 100644 index 00000000000000..968fa62f0458f4 --- /dev/null +++ b/tty/tty_port-add-tty_port_open-helper.patch @@ -0,0 +1,174 @@ +From alan@linux.intel.com Tue Oct 27 10:03:02 2009 +From: Alan Cox <alan@linux.intel.com> +Date: Tue, 06 Oct 2009 16:06:11 +0100 +Subject: tty_port: add "tty_port_open" helper +To: greg@kroah.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org +Message-ID: <20091006150555.9431.34664.stgit@localhost.localdomain> + + +For the moment this just moves the USB logic over and fixes the 'what if +we open and hangup at the same time' race noticed by Oliver Neukum. + +Signed-off-by: Alan Cox <alan@linux.intel.com> +Cc: Alan Stern <stern@rowland.harvard.edu> +Cc: Oliver Neukum <oliver@neukum.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/char/tty_port.c | 36 ++++++++++++++++++++++++++++- + drivers/usb/serial/usb-serial.c | 49 ++++++++++++++++------------------------ + include/linux/tty.h | 10 +++++++- + 3 files changed, 64 insertions(+), 31 deletions(-) + +--- a/drivers/char/tty_port.c ++++ b/drivers/char/tty_port.c +@@ -99,10 +99,11 @@ EXPORT_SYMBOL(tty_port_tty_set); + + static void tty_port_shutdown(struct tty_port *port) + { ++ mutex_lock(&port->mutex); + if (port->ops->shutdown && + test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) + port->ops->shutdown(port); +- ++ mutex_unlock(&port->mutex); + } + + /** +@@ -375,3 +376,36 @@ void tty_port_close(struct tty_port *por + tty_port_tty_set(port, NULL); + } + EXPORT_SYMBOL(tty_port_close); ++ ++int tty_port_open(struct tty_port *port, struct tty_struct *tty, ++ struct file *filp) ++{ ++ spin_lock_irq(&port->lock); ++ if (!tty_hung_up_p(filp)) ++ ++port->count; ++ spin_unlock_irq(&port->lock); ++ tty_port_tty_set(port, tty); ++ ++ /* ++ * Do the device-specific open only if the hardware isn't ++ * already initialized. Serialize open and shutdown using the ++ * port mutex. ++ */ ++ ++ mutex_lock(&port->mutex); ++ ++ if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) { ++ if (port->ops->activate) { ++ int retval = port->ops->activate(port, tty); ++ if (retval) { ++ mutex_unlock(&port->mutex); ++ return retval; ++ } ++ } ++ set_bit(ASYNCB_INITIALIZED, &port->flags); ++ } ++ mutex_unlock(&port->mutex); ++ return tty_port_block_til_ready(port, tty, filp); ++} ++ ++EXPORT_SYMBOL(tty_port_open); +--- a/drivers/usb/serial/usb-serial.c ++++ b/drivers/usb/serial/usb-serial.c +@@ -247,41 +247,31 @@ static int serial_install(struct tty_dri + return retval; + } + +-static int serial_open(struct tty_struct *tty, struct file *filp) ++static int serial_activate(struct tty_port *tport, struct tty_struct *tty) + { +- struct usb_serial_port *port = tty->driver_data; ++ struct usb_serial_port *port = ++ container_of(tport, struct usb_serial_port, port); + struct usb_serial *serial = port->serial; + int retval; + +- dbg("%s - port %d", __func__, port->number); +- +- spin_lock_irq(&port->port.lock); +- if (!tty_hung_up_p(filp)) +- ++port->port.count; +- spin_unlock_irq(&port->port.lock); +- tty_port_tty_set(&port->port, tty); ++ if (mutex_lock_interruptible(&port->mutex)) ++ return -ERESTARTSYS; ++ mutex_lock(&serial->disc_mutex); ++ if (serial->disconnected) ++ retval = -ENODEV; ++ else ++ retval = port->serial->type->open(tty, port); ++ mutex_unlock(&serial->disc_mutex); ++ mutex_unlock(&port->mutex); ++ return retval; ++} + +- /* Do the device-specific open only if the hardware isn't +- * already initialized. +- */ +- if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) { +- if (mutex_lock_interruptible(&port->mutex)) +- return -ERESTARTSYS; +- mutex_lock(&serial->disc_mutex); +- if (serial->disconnected) +- retval = -ENODEV; +- else +- retval = port->serial->type->open(tty, port); +- mutex_unlock(&serial->disc_mutex); +- mutex_unlock(&port->mutex); +- if (retval) +- return retval; +- set_bit(ASYNCB_INITIALIZED, &port->port.flags); +- } ++static int serial_open(struct tty_struct *tty, struct file *filp) ++{ ++ struct usb_serial_port *port = tty->driver_data; + +- /* Now do the correct tty layer semantics */ +- retval = tty_port_block_til_ready(&port->port, tty, filp); +- return retval; ++ dbg("%s - port %d", __func__, port->number); ++ return tty_port_open(&port->port, tty, filp); + } + + /** +@@ -725,6 +715,7 @@ static void serial_dtr_rts(struct tty_po + static const struct tty_port_operations serial_port_ops = { + .carrier_raised = serial_carrier_raised, + .dtr_rts = serial_dtr_rts, ++ .activate = serial_activate, + }; + + int usb_serial_probe(struct usb_interface *interface, +--- a/include/linux/tty.h ++++ b/include/linux/tty.h +@@ -190,9 +190,15 @@ struct tty_port_operations { + /* Control the DTR line */ + void (*dtr_rts)(struct tty_port *port, int raise); + /* Called when the last close completes or a hangup finishes +- IFF the port was initialized. Do not use to free resources */ ++ IFF the port was initialized. Do not use to free resources. Called ++ under the port mutex to serialize against activate/shutdowns */ + void (*shutdown)(struct tty_port *port); + void (*drop)(struct tty_port *port); ++ /* Called under the port mutex from tty_port_open, serialized using ++ the port mutex */ ++ /* FIXME: long term getting the tty argument *out* of this would be ++ good for consoles */ ++ int (*activate)(struct tty_port *port, struct tty_struct *tty); + }; + + struct tty_port { +@@ -467,6 +473,8 @@ extern int tty_port_close_start(struct t + extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty); + extern void tty_port_close(struct tty_port *port, + struct tty_struct *tty, struct file *filp); ++extern int tty_port_open(struct tty_port *port, ++ struct tty_struct *tty, struct file *filp); + extern inline int tty_port_users(struct tty_port *port) + { + return port->count + port->blocked_open; diff --git a/tty/tty_port-coding-style-cleaning-pass.patch b/tty/tty_port-coding-style-cleaning-pass.patch new file mode 100644 index 00000000000000..8c322f6308d063 --- /dev/null +++ b/tty/tty_port-coding-style-cleaning-pass.patch @@ -0,0 +1,98 @@ +From alan@linux.intel.com Tue Oct 27 10:03:21 2009 +From: Alan Cox <alan@linux.intel.com> +Date: Tue, 06 Oct 2009 16:06:21 +0100 +Subject: tty_port: coding style cleaning pass +To: greg@kroah.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org +Message-ID: <20091006150616.9431.29417.stgit@localhost.localdomain> + + +Mind the hoover wire... + +Signed-off-by: Alan Cox <alan@linux.intel.com> +Cc: Alan Stern <stern@rowland.harvard.edu> +Cc: Oliver Neukum <oliver@neukum.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/char/tty_port.c | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +--- a/drivers/char/tty_port.c ++++ b/drivers/char/tty_port.c +@@ -199,7 +199,7 @@ EXPORT_SYMBOL(tty_port_lower_dtr_rts); + * management of these lines. Note that the dtr/rts raise is done each + * iteration as a hangup may have previously dropped them while we wait. + */ +- ++ + int tty_port_block_til_ready(struct tty_port *port, + struct tty_struct *tty, struct file *filp) + { +@@ -248,7 +248,8 @@ int tty_port_block_til_ready(struct tty_ + tty_port_raise_dtr_rts(port); + + prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); +- /* Check for a hangup or uninitialised port. Return accordingly */ ++ /* Check for a hangup or uninitialised port. ++ Return accordingly */ + if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { + if (port->flags & ASYNC_HUP_NOTIFY) + retval = -EAGAIN; +@@ -280,11 +281,11 @@ int tty_port_block_til_ready(struct tty_ + port->flags |= ASYNC_NORMAL_ACTIVE; + spin_unlock_irqrestore(&port->lock, flags); + return retval; +- + } + EXPORT_SYMBOL(tty_port_block_til_ready); + +-int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp) ++int tty_port_close_start(struct tty_port *port, ++ struct tty_struct *tty, struct file *filp) + { + unsigned long flags; + +@@ -294,7 +295,7 @@ int tty_port_close_start(struct tty_port + return 0; + } + +- if( tty->count == 1 && port->count != 1) { ++ if (tty->count == 1 && port->count != 1) { + printk(KERN_WARNING + "tty_port_close_start: tty->count = 1 port count = %d.\n", + port->count); +@@ -326,8 +327,8 @@ int tty_port_close_start(struct tty_port + long timeout; + + if (bps > 1200) +- timeout = max_t(long, (HZ * 10 * port->drain_delay) / bps, +- HZ / 10); ++ timeout = max_t(long, ++ (HZ * 10 * port->drain_delay) / bps, HZ / 10); + else + timeout = 2 * HZ; + schedule_timeout_interruptible(timeout); +@@ -378,7 +379,7 @@ void tty_port_close(struct tty_port *por + EXPORT_SYMBOL(tty_port_close); + + int tty_port_open(struct tty_port *port, struct tty_struct *tty, +- struct file *filp) ++ struct file *filp) + { + spin_lock_irq(&port->lock); + if (!tty_hung_up_p(filp)) +@@ -398,10 +399,10 @@ int tty_port_open(struct tty_port *port, + if (port->ops->activate) { + int retval = port->ops->activate(port, tty); + if (retval) { +- mutex_unlock(&port->mutex); +- return retval; +- } +- } ++ mutex_unlock(&port->mutex); ++ return retval; ++ } ++ } + set_bit(ASYNCB_INITIALIZED, &port->flags); + } + mutex_unlock(&port->mutex); diff --git a/tty/usb_serial-kill-port-mutex.patch b/tty/usb_serial-kill-port-mutex.patch new file mode 100644 index 00000000000000..32b861dffc5506 --- /dev/null +++ b/tty/usb_serial-kill-port-mutex.patch @@ -0,0 +1,68 @@ +From alan@linux.intel.com Tue Oct 27 10:07:10 2009 +From: Alan Cox <alan@linux.intel.com> +Date: Tue, 06 Oct 2009 16:06:46 +0100 +Subject: usb_serial: Kill port mutex +To: greg@kroah.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org +Message-ID: <20091006150641.9431.67880.stgit@localhost.localdomain> + + +The tty port has a port mutex used for all the port related locking so we +don't need the one in the USB serial layer any more. + +Signed-off-by: Alan Cox <alan@linux.intel.com> +Cc: Alan Stern <stern@rowland.harvard.edu> +Cc: Oliver Neukum <oliver@neukum.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/opticon.c | 4 ++-- + drivers/usb/serial/usb-serial.c | 1 - + include/linux/usb/serial.h | 3 --- + 3 files changed, 2 insertions(+), 6 deletions(-) + +--- a/drivers/usb/serial/opticon.c ++++ b/drivers/usb/serial/opticon.c +@@ -501,12 +501,12 @@ static int opticon_resume(struct usb_int + struct usb_serial_port *port = serial->port[0]; + int result; + +- mutex_lock(&port->mutex); ++ mutex_lock(&port->port.mutex); + if (port->port.count) + result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO); + else + result = 0; +- mutex_unlock(&port->mutex); ++ mutex_unlock(&port->port.mutex); + return result; + } + +--- a/drivers/usb/serial/usb-serial.c ++++ b/drivers/usb/serial/usb-serial.c +@@ -897,7 +897,6 @@ int usb_serial_probe(struct usb_interfac + spin_lock_init(&port->lock); + /* Keep this for private driver use for the moment but + should probably go away */ +- mutex_init(&port->mutex); + INIT_WORK(&port->work, usb_serial_port_work); + serial->port[i] = port; + port->dev.parent = &interface->dev; +--- a/include/linux/usb/serial.h ++++ b/include/linux/usb/serial.h +@@ -39,8 +39,6 @@ enum port_dev_state { + * @serial: pointer back to the struct usb_serial owner of this port. + * @port: pointer to the corresponding tty_port for this port. + * @lock: spinlock to grab when updating portions of this structure. +- * @mutex: mutex used to synchronize serial_open() and serial_close() +- * access for this port. + * @number: the number of the port (the minor number). + * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. + * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. +@@ -77,7 +75,6 @@ struct usb_serial_port { + struct usb_serial *serial; + struct tty_port port; + spinlock_t lock; +- struct mutex mutex; + unsigned char number; + + unsigned char *interrupt_in_buffer; diff --git a/tty/usb_serial-use-the-shutdown-operation.patch b/tty/usb_serial-use-the-shutdown-operation.patch new file mode 100644 index 00000000000000..0def7d620d5395 --- /dev/null +++ b/tty/usb_serial-use-the-shutdown-operation.patch @@ -0,0 +1,124 @@ +From alan@linux.intel.com Tue Oct 27 10:05:50 2009 +From: Alan Cox <alan@linux.intel.com> +Date: Tue, 06 Oct 2009 16:06:36 +0100 +Subject: [PATCH 3/5] usb_serial: Use the shutdown() operation +To: greg@kroah.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org +Message-ID: <20091006150626.9431.34542.stgit@localhost.localdomain> + + +As Alan Stern pointed out - now we have tty_port_open the shutdown method +and locking allow us to whack the other bits into the full helper methods +and provide a shutdown op which the tty port code will synchronize with +setup for us. + +Signed-off-by: Alan Cox <alan@linux.intel.com> +Cc: Alan Stern <stern@rowland.harvard.edu> +Cc: Oliver Neukum <oliver@neukum.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/usb/serial/usb-serial.c | 39 +++++++++++---------------------------- + 1 file changed, 11 insertions(+), 28 deletions(-) + +--- a/drivers/usb/serial/usb-serial.c ++++ b/drivers/usb/serial/usb-serial.c +@@ -254,15 +254,12 @@ static int serial_activate(struct tty_po + struct usb_serial *serial = port->serial; + int retval; + +- if (mutex_lock_interruptible(&port->mutex)) +- return -ERESTARTSYS; + mutex_lock(&serial->disc_mutex); + if (serial->disconnected) + retval = -ENODEV; + else + retval = port->serial->type->open(tty, port); + mutex_unlock(&serial->disc_mutex); +- mutex_unlock(&port->mutex); + return retval; + } + +@@ -276,57 +273,40 @@ static int serial_open(struct tty_struct + + /** + * serial_down - shut down hardware +- * @port: port to shut down ++ * @tport: tty port to shut down + * + * Shut down a USB serial port unless it is the console. We never +- * shut down the console hardware as it will always be in use. ++ * shut down the console hardware as it will always be in use. Serialized ++ * against activate by the tport mutex and kept to matching open/close pairs ++ * of calls by the ASYNCB_INITIALIZED flag. + */ +-static void serial_down(struct usb_serial_port *port) ++static void serial_down(struct tty_port *tport) + { ++ struct usb_serial_port *port = ++ container_of(tport, struct usb_serial_port, port); + struct usb_serial_driver *drv = port->serial->type; +- + /* + * The console is magical. Do not hang up the console hardware + * or there will be tears. + */ + if (port->console) + return; +- +- /* Don't call the close method if the hardware hasn't been +- * initialized. +- */ +- if (!test_and_clear_bit(ASYNCB_INITIALIZED, &port->port.flags)) +- return; +- +- mutex_lock(&port->mutex); + if (drv->close) + drv->close(port); +- mutex_unlock(&port->mutex); + } + + static void serial_hangup(struct tty_struct *tty) + { + struct usb_serial_port *port = tty->driver_data; +- + dbg("%s - port %d", __func__, port->number); +- +- serial_down(port); + tty_port_hangup(&port->port); + } + + static void serial_close(struct tty_struct *tty, struct file *filp) + { + struct usb_serial_port *port = tty->driver_data; +- + dbg("%s - port %d", __func__, port->number); +- +- if (tty_hung_up_p(filp)) +- return; +- if (tty_port_close_start(&port->port, tty, filp) == 0) +- return; +- serial_down(port); +- tty_port_close_end(&port->port, tty); +- tty_port_tty_set(&port->port, NULL); ++ tty_port_close(&port->port, tty, filp); + } + + /** +@@ -716,6 +696,7 @@ static const struct tty_port_operations + .carrier_raised = serial_carrier_raised, + .dtr_rts = serial_dtr_rts, + .activate = serial_activate, ++ .shutdown = serial_down, + }; + + int usb_serial_probe(struct usb_interface *interface, +@@ -914,6 +895,8 @@ int usb_serial_probe(struct usb_interfac + port->port.ops = &serial_port_ops; + port->serial = serial; + spin_lock_init(&port->lock); ++ /* Keep this for private driver use for the moment but ++ should probably go away */ + mutex_init(&port->mutex); + INIT_WORK(&port->work, usb_serial_port_work); + serial->port[i] = port; diff --git a/usb.current/usb-option-tlaytech-tue800-support.patch b/usb.current/usb-option-tlaytech-tue800-support.patch new file mode 100644 index 00000000000000..b3d50d9b214f83 --- /dev/null +++ b/usb.current/usb-option-tlaytech-tue800-support.patch @@ -0,0 +1,40 @@ +From bryan.wu@canonical.com Tue Oct 27 10:35:48 2009 +From: Bryan Wu <bryan.wu@canonical.com> +Date: Thu, 22 Oct 2009 15:00:36 +0800 +Subject: USB: option: TLAYTECH TUE800 support +To: smurf@smurf.noris.de +Cc: linux-usb@vger.kernel.org, gregkh@suse.de, linux-kernel@vger.kernel.org +Message-ID: <1256194836-15733-1-git-send-email-bryan.wu@canonical.com> + + +Add ID for Tlaytech TUE800 CDMA modem to the option driver. + +Signed-off-by: Bryan Wu <bryan.wu@canonical.com> +Acked-By: Matthias Urlichs <matthias@urlichs.de> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/option.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -315,6 +315,9 @@ static int option_resume(struct usb_ser + #define QISDA_PRODUCT_H20_4515 0x4515 + #define QISDA_PRODUCT_H20_4519 0x4519 + ++/* TLAYTECH PRODUCTS */ ++#define TLAYTECH_VENDOR_ID 0x20B9 ++#define TLAYTECH_PRODUCT_TEU800 0x1682 + + /* TOSHIBA PRODUCTS */ + #define TOSHIBA_VENDOR_ID 0x0930 +@@ -593,6 +596,7 @@ static struct usb_device_id option_ids[] + { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) }, + { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, ++ { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, + { } /* Terminating entry */ + }; + MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/usb.current/usb-r8a66597-hcd-fix-cannot-detect-a-device-when-uses_new_polling-is-set.patch b/usb.current/usb-r8a66597-hcd-fix-cannot-detect-a-device-when-uses_new_polling-is-set.patch new file mode 100644 index 00000000000000..2ff23a249f8137 --- /dev/null +++ b/usb.current/usb-r8a66597-hcd-fix-cannot-detect-a-device-when-uses_new_polling-is-set.patch @@ -0,0 +1,57 @@ +From shimoda.yoshihiro@renesas.com Tue Oct 27 10:23:57 2009 +From: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> +Date: Wed, 21 Oct 2009 20:33:39 +0900 +Subject: USB: r8a66597-hcd: fix cannot detect a device when uses_new_polling is set +To: Greg Kroah-Hartman <gregkh@suse.de> +Message-ID: <4ADEF193.30204@renesas.com> + + +Signed-off-by: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/r8a66597-hcd.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +--- a/drivers/usb/host/r8a66597-hcd.c ++++ b/drivers/usb/host/r8a66597-hcd.c +@@ -1003,19 +1003,20 @@ static void r8a66597_check_syssts(struct + if (syssts == SE0) { + r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port)); + r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port)); +- return; +- } ++ } else { ++ if (syssts == FS_JSTS) ++ r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port)); ++ else if (syssts == LS_JSTS) ++ r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port)); + +- if (syssts == FS_JSTS) +- r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port)); +- else if (syssts == LS_JSTS) +- r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port)); ++ r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port)); ++ r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port)); + +- r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port)); +- r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port)); ++ if (r8a66597->bus_suspended) ++ usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); ++ } + +- if (r8a66597->bus_suspended) +- usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); ++ usb_hcd_poll_rh_status(r8a66597_to_hcd(r8a66597)); + } + + /* this function must be called with interrupt disabled */ +@@ -1024,6 +1025,8 @@ static void r8a66597_usb_connect(struct + u16 speed = get_rh_usb_speed(r8a66597, port); + struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; + ++ rh->port &= ~((1 << USB_PORT_FEAT_HIGHSPEED) | ++ (1 << USB_PORT_FEAT_LOWSPEED)); + if (speed == HSMODE) + rh->port |= (1 << USB_PORT_FEAT_HIGHSPEED); + else if (speed == LSMODE) diff --git a/usb.current/usb-serial-sierra-driver-send_setup-autopm-fix.patch b/usb.current/usb-serial-sierra-driver-send_setup-autopm-fix.patch new file mode 100644 index 00000000000000..6aa61e5a1d0af9 --- /dev/null +++ b/usb.current/usb-serial-sierra-driver-send_setup-autopm-fix.patch @@ -0,0 +1,82 @@ +From epasheva@sierrawireless.com Tue Oct 27 10:12:48 2009 +From: Elina Pasheva <epasheva@sierrawireless.com> +Date: Fri, 16 Oct 2009 12:04:54 -0700 +Subject: USB: serial: sierra driver send_setup() autopm fix +To: <gregkh@suse.de> +Cc: <epasheva@sierrawireless.com>, <rfiler@sierrawireless.com> +Message-ID: <1255719894.23492.5.camel@Linuxdev4-laptop> + + +From: Elina Pasheva <epasheva@sierrawireless.com> + +This patch presents a fix for the autosuspend feature implementation in +sierra usb serial driver for function sierra_send_setup(). Because it +is possible to call sierra_send_setup() before sierra_open() or after +sierra_close() we added a get/put interface activity to assure that the +usb control can happen even when the device is autosuspended. + +Signed-off-by: Elina Pasheva <epasheva@sierrawireless.com> +Tested-by: Matthew Safar <msafar@sierrawireless.com> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/usb/serial/sierra.c | 24 ++++++++++++++---------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +--- a/drivers/usb/serial/sierra.c ++++ b/drivers/usb/serial/sierra.c +@@ -296,7 +296,6 @@ struct sierra_port_private { + int dsr_state; + int dcd_state; + int ri_state; +- + unsigned int opened:1; + }; + +@@ -306,6 +305,8 @@ static int sierra_send_setup(struct usb_ + struct sierra_port_private *portdata; + __u16 interface = 0; + int val = 0; ++ int do_send = 0; ++ int retval; + + dev_dbg(&port->dev, "%s\n", __func__); + +@@ -324,10 +325,7 @@ static int sierra_send_setup(struct usb_ + */ + if (port->interrupt_in_urb) { + /* send control message */ +- return usb_control_msg(serial->dev, +- usb_rcvctrlpipe(serial->dev, 0), +- 0x22, 0x21, val, interface, +- NULL, 0, USB_CTRL_SET_TIMEOUT); ++ do_send = 1; + } + } + +@@ -339,12 +337,18 @@ static int sierra_send_setup(struct usb_ + interface = 1; + else if (port->bulk_out_endpointAddress == 5) + interface = 2; +- return usb_control_msg(serial->dev, +- usb_rcvctrlpipe(serial->dev, 0), +- 0x22, 0x21, val, interface, +- NULL, 0, USB_CTRL_SET_TIMEOUT); ++ ++ do_send = 1; + } +- return 0; ++ if (!do_send) ++ return 0; ++ ++ usb_autopm_get_interface(serial->interface); ++ retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), ++ 0x22, 0x21, val, interface, NULL, 0, USB_CTRL_SET_TIMEOUT); ++ usb_autopm_put_interface(serial->interface); ++ ++ return retval; + } + + static void sierra_set_termios(struct tty_struct *tty, diff --git a/usb/usb-host-ehci-introduce-omap-ehci-hcd-driver.patch b/usb/usb-host-ehci-introduce-omap-ehci-hcd-driver.patch new file mode 100644 index 00000000000000..d8ac4ccc24891b --- /dev/null +++ b/usb/usb-host-ehci-introduce-omap-ehci-hcd-driver.patch @@ -0,0 +1,797 @@ +From felipe.balbi@nokia.com Tue Oct 27 10:11:17 2009 +From: Felipe Balbi <felipe.balbi@nokia.com> +Date: Wed, 14 Oct 2009 11:44:14 +0300 +Subject: USB: host: ehci: introduce omap ehci-hcd driver +To: linux-usb@vger.kernel.org +Cc: Felipe Balbi <felipe.balbi@nokia.com>, Vikram Pandita <vikram.pandita@ti.com>, Ajay Kumar Gupta <ajay.gupta@ti.com>, Anand Gadiyar <gadiyar@ti.com> +Message-ID: <1255509855-9046-1-git-send-email-felipe.balbi@nokia.com> + + +this driver has been sitting in linux-omap tree for quite +some time. It adds support for omap's ehci controller. + +Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com> +Signed-off-by: Vikram Pandita <vikram.pandita@ti.com> +Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com> +Signed-off-by: Anand Gadiyar <gadiyar@ti.com> +Cc: David Brownell <dbrownell@users.sourceforge.net> +Cc: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/ehci-hcd.c | 5 + drivers/usb/host/ehci-omap.c | 755 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 760 insertions(+) + +--- a/drivers/usb/host/ehci-hcd.c ++++ b/drivers/usb/host/ehci-hcd.c +@@ -1108,6 +1108,11 @@ MODULE_LICENSE ("GPL"); + #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver + #endif + ++#ifdef CONFIG_ARCH_OMAP34XX ++#include "ehci-omap.c" ++#define PLATFORM_DRIVER ehci_hcd_omap_driver ++#endif ++ + #ifdef CONFIG_PPC_PS3 + #include "ehci-ps3.c" + #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver +--- /dev/null ++++ b/drivers/usb/host/ehci-omap.c +@@ -0,0 +1,755 @@ ++/* ++ * ehci-omap.c - driver for USBHOST on OMAP 34xx processor ++ * ++ * Bus Glue for OMAP34xx USBHOST 3 port EHCI controller ++ * Tested on OMAP3430 ES2.0 SDP ++ * ++ * Copyright (C) 2007-2008 Texas Instruments, Inc. ++ * Author: Vikram Pandita <vikram.pandita@ti.com> ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Contact: Felipe Balbi <felipe.balbi@nokia.com> ++ * ++ * Based on "ehci-fsl.c" and "ehci-au1xxx.c" ehci glue layers ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * TODO (last updated Feb 23rd, 2009): ++ * - add kernel-doc ++ * - enable AUTOIDLE ++ * - move DPLL5 programming to clock fw ++ * - add suspend/resume ++ * - move workarounds to board-files ++ */ ++ ++#include <linux/platform_device.h> ++#include <linux/clk.h> ++#include <linux/gpio.h> ++#include <mach/usb.h> ++ ++/* ++ * OMAP USBHOST Register addresses: VIRTUAL ADDRESSES ++ * Use ehci_omap_readl()/ehci_omap_writel() functions ++ */ ++ ++/* TLL Register Set */ ++#define OMAP_USBTLL_REVISION (0x00) ++#define OMAP_USBTLL_SYSCONFIG (0x10) ++#define OMAP_USBTLL_SYSCONFIG_CACTIVITY (1 << 8) ++#define OMAP_USBTLL_SYSCONFIG_SIDLEMODE (1 << 3) ++#define OMAP_USBTLL_SYSCONFIG_ENAWAKEUP (1 << 2) ++#define OMAP_USBTLL_SYSCONFIG_SOFTRESET (1 << 1) ++#define OMAP_USBTLL_SYSCONFIG_AUTOIDLE (1 << 0) ++ ++#define OMAP_USBTLL_SYSSTATUS (0x14) ++#define OMAP_USBTLL_SYSSTATUS_RESETDONE (1 << 0) ++ ++#define OMAP_USBTLL_IRQSTATUS (0x18) ++#define OMAP_USBTLL_IRQENABLE (0x1C) ++ ++#define OMAP_TLL_SHARED_CONF (0x30) ++#define OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN (1 << 6) ++#define OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN (1 << 5) ++#define OMAP_TLL_SHARED_CONF_USB_DIVRATION (1 << 2) ++#define OMAP_TLL_SHARED_CONF_FCLK_REQ (1 << 1) ++#define OMAP_TLL_SHARED_CONF_FCLK_IS_ON (1 << 0) ++ ++#define OMAP_TLL_CHANNEL_CONF(num) (0x040 + 0x004 * num) ++#define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF (1 << 11) ++#define OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE (1 << 10) ++#define OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE (1 << 9) ++#define OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE (1 << 8) ++#define OMAP_TLL_CHANNEL_CONF_CHANEN (1 << 0) ++ ++#define OMAP_TLL_ULPI_FUNCTION_CTRL(num) (0x804 + 0x100 * num) ++#define OMAP_TLL_ULPI_INTERFACE_CTRL(num) (0x807 + 0x100 * num) ++#define OMAP_TLL_ULPI_OTG_CTRL(num) (0x80A + 0x100 * num) ++#define OMAP_TLL_ULPI_INT_EN_RISE(num) (0x80D + 0x100 * num) ++#define OMAP_TLL_ULPI_INT_EN_FALL(num) (0x810 + 0x100 * num) ++#define OMAP_TLL_ULPI_INT_STATUS(num) (0x813 + 0x100 * num) ++#define OMAP_TLL_ULPI_INT_LATCH(num) (0x814 + 0x100 * num) ++#define OMAP_TLL_ULPI_DEBUG(num) (0x815 + 0x100 * num) ++#define OMAP_TLL_ULPI_SCRATCH_REGISTER(num) (0x816 + 0x100 * num) ++ ++#define OMAP_TLL_CHANNEL_COUNT 3 ++#define OMAP_TLL_CHANNEL_1_EN_MASK (1 << 1) ++#define OMAP_TLL_CHANNEL_2_EN_MASK (1 << 2) ++#define OMAP_TLL_CHANNEL_3_EN_MASK (1 << 4) ++ ++/* UHH Register Set */ ++#define OMAP_UHH_REVISION (0x00) ++#define OMAP_UHH_SYSCONFIG (0x10) ++#define OMAP_UHH_SYSCONFIG_MIDLEMODE (1 << 12) ++#define OMAP_UHH_SYSCONFIG_CACTIVITY (1 << 8) ++#define OMAP_UHH_SYSCONFIG_SIDLEMODE (1 << 3) ++#define OMAP_UHH_SYSCONFIG_ENAWAKEUP (1 << 2) ++#define OMAP_UHH_SYSCONFIG_SOFTRESET (1 << 1) ++#define OMAP_UHH_SYSCONFIG_AUTOIDLE (1 << 0) ++ ++#define OMAP_UHH_SYSSTATUS (0x14) ++#define OMAP_UHH_HOSTCONFIG (0x40) ++#define OMAP_UHH_HOSTCONFIG_ULPI_BYPASS (1 << 0) ++#define OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS (1 << 0) ++#define OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS (1 << 11) ++#define OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS (1 << 12) ++#define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN (1 << 2) ++#define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN (1 << 3) ++#define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN (1 << 4) ++#define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN (1 << 5) ++#define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS (1 << 8) ++#define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS (1 << 9) ++#define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS (1 << 10) ++ ++#define OMAP_UHH_DEBUG_CSR (0x44) ++ ++/* EHCI Register Set */ ++#define EHCI_INSNREG05_ULPI (0xA4) ++#define EHCI_INSNREG05_ULPI_CONTROL_SHIFT 31 ++#define EHCI_INSNREG05_ULPI_PORTSEL_SHIFT 24 ++#define EHCI_INSNREG05_ULPI_OPSEL_SHIFT 22 ++#define EHCI_INSNREG05_ULPI_REGADD_SHIFT 16 ++#define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 ++#define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 ++ ++/*-------------------------------------------------------------------------*/ ++ ++static inline void ehci_omap_writel(void __iomem *base, u32 reg, u32 val) ++{ ++ __raw_writel(val, base + reg); ++} ++ ++static inline u32 ehci_omap_readl(void __iomem *base, u32 reg) ++{ ++ return __raw_readl(base + reg); ++} ++ ++static inline void ehci_omap_writeb(void __iomem *base, u8 reg, u8 val) ++{ ++ __raw_writeb(val, base + reg); ++} ++ ++static inline u8 ehci_omap_readb(void __iomem *base, u8 reg) ++{ ++ return __raw_readb(base + reg); ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++struct ehci_hcd_omap { ++ struct ehci_hcd *ehci; ++ struct device *dev; ++ ++ struct clk *usbhost_ick; ++ struct clk *usbhost2_120m_fck; ++ struct clk *usbhost1_48m_fck; ++ struct clk *usbtll_fck; ++ struct clk *usbtll_ick; ++ ++ /* FIXME the following two workarounds are ++ * board specific not silicon-specific so these ++ * should be moved to board-file instead. ++ * ++ * Maybe someone from TI will know better which ++ * board is affected and needs the workarounds ++ * to be applied ++ */ ++ ++ /* gpio for resetting phy */ ++ int reset_gpio_port[OMAP3_HS_USB_PORTS]; ++ ++ /* phy reset workaround */ ++ int phy_reset; ++ ++ /* desired phy_mode: TLL, PHY */ ++ enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS]; ++ ++ void __iomem *uhh_base; ++ void __iomem *tll_base; ++ void __iomem *ehci_base; ++}; ++ ++/*-------------------------------------------------------------------------*/ ++ ++static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask) ++{ ++ unsigned reg; ++ int i; ++ ++ /* Program the 3 TLL channels upfront */ ++ for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { ++ reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); ++ ++ /* Disable AutoIdle, BitStuffing and use SDR Mode */ ++ reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE ++ | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF ++ | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE); ++ ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg); ++ } ++ ++ /* Program Common TLL register */ ++ reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_SHARED_CONF); ++ reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON ++ | OMAP_TLL_SHARED_CONF_USB_DIVRATION ++ | OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN); ++ reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN; ++ ++ ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg); ++ ++ /* Enable channels now */ ++ for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { ++ reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); ++ ++ /* Enable only the reg that is needed */ ++ if (!(tll_channel_mask & 1<<i)) ++ continue; ++ ++ reg |= OMAP_TLL_CHANNEL_CONF_CHANEN; ++ ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg); ++ ++ ehci_omap_writeb(omap->tll_base, ++ OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe); ++ dev_dbg(omap->dev, "ULPI_SCRATCH_REG[ch=%d]= 0x%02x\n", ++ i+1, ehci_omap_readb(omap->tll_base, ++ OMAP_TLL_ULPI_SCRATCH_REGISTER(i))); ++ } ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* omap_start_ehc ++ * - Start the TI USBHOST controller ++ */ ++static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(1000); ++ u8 tll_ch_mask = 0; ++ unsigned reg = 0; ++ int ret = 0; ++ ++ dev_dbg(omap->dev, "starting TI EHCI USB Controller\n"); ++ ++ /* Enable Clocks for USBHOST */ ++ omap->usbhost_ick = clk_get(omap->dev, "usbhost_ick"); ++ if (IS_ERR(omap->usbhost_ick)) { ++ ret = PTR_ERR(omap->usbhost_ick); ++ goto err_host_ick; ++ } ++ clk_enable(omap->usbhost_ick); ++ ++ omap->usbhost2_120m_fck = clk_get(omap->dev, "usbhost_120m_fck"); ++ if (IS_ERR(omap->usbhost2_120m_fck)) { ++ ret = PTR_ERR(omap->usbhost2_120m_fck); ++ goto err_host_120m_fck; ++ } ++ clk_enable(omap->usbhost2_120m_fck); ++ ++ omap->usbhost1_48m_fck = clk_get(omap->dev, "usbhost_48m_fck"); ++ if (IS_ERR(omap->usbhost1_48m_fck)) { ++ ret = PTR_ERR(omap->usbhost1_48m_fck); ++ goto err_host_48m_fck; ++ } ++ clk_enable(omap->usbhost1_48m_fck); ++ ++ if (omap->phy_reset) { ++ /* Refer: ISSUE1 */ ++ if (gpio_is_valid(omap->reset_gpio_port[0])) { ++ gpio_request(omap->reset_gpio_port[0], ++ "USB1 PHY reset"); ++ gpio_direction_output(omap->reset_gpio_port[0], 0); ++ } ++ ++ if (gpio_is_valid(omap->reset_gpio_port[1])) { ++ gpio_request(omap->reset_gpio_port[1], ++ "USB2 PHY reset"); ++ gpio_direction_output(omap->reset_gpio_port[1], 0); ++ } ++ ++ /* Hold the PHY in RESET for enough time till DIR is high */ ++ udelay(10); ++ } ++ ++ /* Configure TLL for 60Mhz clk for ULPI */ ++ omap->usbtll_fck = clk_get(omap->dev, "usbtll_fck"); ++ if (IS_ERR(omap->usbtll_fck)) { ++ ret = PTR_ERR(omap->usbtll_fck); ++ goto err_tll_fck; ++ } ++ clk_enable(omap->usbtll_fck); ++ ++ omap->usbtll_ick = clk_get(omap->dev, "usbtll_ick"); ++ if (IS_ERR(omap->usbtll_ick)) { ++ ret = PTR_ERR(omap->usbtll_ick); ++ goto err_tll_ick; ++ } ++ clk_enable(omap->usbtll_ick); ++ ++ /* perform TLL soft reset, and wait until reset is complete */ ++ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, ++ OMAP_USBTLL_SYSCONFIG_SOFTRESET); ++ ++ /* Wait for TLL reset to complete */ ++ while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS) ++ & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { ++ cpu_relax(); ++ ++ if (time_after(jiffies, timeout)) { ++ dev_dbg(omap->dev, "operation timed out\n"); ++ ret = -EINVAL; ++ goto err_sys_status; ++ } ++ } ++ ++ dev_dbg(omap->dev, "TLL RESET DONE\n"); ++ ++ /* (1<<3) = no idle mode only for initial debugging */ ++ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, ++ OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | ++ OMAP_USBTLL_SYSCONFIG_SIDLEMODE | ++ OMAP_USBTLL_SYSCONFIG_CACTIVITY); ++ ++ ++ /* Put UHH in NoIdle/NoStandby mode */ ++ reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG); ++ reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP ++ | OMAP_UHH_SYSCONFIG_SIDLEMODE ++ | OMAP_UHH_SYSCONFIG_CACTIVITY ++ | OMAP_UHH_SYSCONFIG_MIDLEMODE); ++ reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; ++ ++ ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); ++ ++ reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); ++ ++ /* setup ULPI bypass and burst configurations */ ++ reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN ++ | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN ++ | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); ++ reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; ++ ++ if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN) ++ reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; ++ if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN) ++ reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; ++ if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN) ++ reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; ++ ++ /* Bypass the TLL module for PHY mode operation */ ++ if (omap_rev() <= OMAP3430_REV_ES2_1) { ++ dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1 \n"); ++ if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) || ++ (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) || ++ (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY)) ++ reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; ++ else ++ reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; ++ } else { ++ dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); ++ if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) ++ reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; ++ else if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) ++ reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; ++ ++ if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) ++ reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; ++ else if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) ++ reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; ++ ++ if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY) ++ reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; ++ else if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL) ++ reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; ++ ++ } ++ ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); ++ dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); ++ ++ ++ if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) || ++ (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) || ++ (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) { ++ ++ if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) ++ tll_ch_mask |= OMAP_TLL_CHANNEL_1_EN_MASK; ++ if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) ++ tll_ch_mask |= OMAP_TLL_CHANNEL_2_EN_MASK; ++ if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL) ++ tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK; ++ ++ /* Enable UTMI mode for required TLL channels */ ++ omap_usb_utmi_init(omap, tll_ch_mask); ++ } ++ ++ if (omap->phy_reset) { ++ /* Refer ISSUE1: ++ * Hold the PHY in RESET for enough time till ++ * PHY is settled and ready ++ */ ++ udelay(10); ++ ++ if (gpio_is_valid(omap->reset_gpio_port[0])) ++ gpio_set_value(omap->reset_gpio_port[0], 1); ++ ++ if (gpio_is_valid(omap->reset_gpio_port[1])) ++ gpio_set_value(omap->reset_gpio_port[1], 1); ++ } ++ ++ return 0; ++ ++err_sys_status: ++ clk_disable(omap->usbtll_ick); ++ clk_put(omap->usbtll_ick); ++ ++err_tll_ick: ++ clk_disable(omap->usbtll_fck); ++ clk_put(omap->usbtll_fck); ++ ++err_tll_fck: ++ clk_disable(omap->usbhost1_48m_fck); ++ clk_put(omap->usbhost1_48m_fck); ++ ++ if (omap->phy_reset) { ++ if (gpio_is_valid(omap->reset_gpio_port[0])) ++ gpio_free(omap->reset_gpio_port[0]); ++ ++ if (gpio_is_valid(omap->reset_gpio_port[1])) ++ gpio_free(omap->reset_gpio_port[1]); ++ } ++ ++err_host_48m_fck: ++ clk_disable(omap->usbhost2_120m_fck); ++ clk_put(omap->usbhost2_120m_fck); ++ ++err_host_120m_fck: ++ clk_disable(omap->usbhost_ick); ++ clk_put(omap->usbhost_ick); ++ ++err_host_ick: ++ return ret; ++} ++ ++static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(100); ++ ++ dev_dbg(omap->dev, "stopping TI EHCI USB Controller\n"); ++ ++ /* Reset OMAP modules for insmod/rmmod to work */ ++ ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, ++ OMAP_UHH_SYSCONFIG_SOFTRESET); ++ while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) ++ & (1 << 0))) { ++ cpu_relax(); ++ ++ if (time_after(jiffies, timeout)) ++ dev_dbg(omap->dev, "operation timed out\n"); ++ } ++ ++ while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) ++ & (1 << 1))) { ++ cpu_relax(); ++ ++ if (time_after(jiffies, timeout)) ++ dev_dbg(omap->dev, "operation timed out\n"); ++ } ++ ++ while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) ++ & (1 << 2))) { ++ cpu_relax(); ++ ++ if (time_after(jiffies, timeout)) ++ dev_dbg(omap->dev, "operation timed out\n"); ++ } ++ ++ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1)); ++ ++ while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS) ++ & (1 << 0))) { ++ cpu_relax(); ++ ++ if (time_after(jiffies, timeout)) ++ dev_dbg(omap->dev, "operation timed out\n"); ++ } ++ ++ if (omap->usbtll_fck != NULL) { ++ clk_disable(omap->usbtll_fck); ++ clk_put(omap->usbtll_fck); ++ omap->usbtll_fck = NULL; ++ } ++ ++ if (omap->usbhost_ick != NULL) { ++ clk_disable(omap->usbhost_ick); ++ clk_put(omap->usbhost_ick); ++ omap->usbhost_ick = NULL; ++ } ++ ++ if (omap->usbhost1_48m_fck != NULL) { ++ clk_disable(omap->usbhost1_48m_fck); ++ clk_put(omap->usbhost1_48m_fck); ++ omap->usbhost1_48m_fck = NULL; ++ } ++ ++ if (omap->usbhost2_120m_fck != NULL) { ++ clk_disable(omap->usbhost2_120m_fck); ++ clk_put(omap->usbhost2_120m_fck); ++ omap->usbhost2_120m_fck = NULL; ++ } ++ ++ if (omap->usbtll_ick != NULL) { ++ clk_disable(omap->usbtll_ick); ++ clk_put(omap->usbtll_ick); ++ omap->usbtll_ick = NULL; ++ } ++ ++ if (omap->phy_reset) { ++ if (gpio_is_valid(omap->reset_gpio_port[0])) ++ gpio_free(omap->reset_gpio_port[0]); ++ ++ if (gpio_is_valid(omap->reset_gpio_port[1])) ++ gpio_free(omap->reset_gpio_port[1]); ++ } ++ ++ dev_dbg(omap->dev, "Clock to USB host has been disabled\n"); ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static const struct hc_driver ehci_omap_hc_driver; ++ ++/* configure so an HC device and id are always provided */ ++/* always called with process context; sleeping is OK */ ++ ++/** ++ * ehci_hcd_omap_probe - initialize TI-based HCDs ++ * ++ * Allocates basic resources for this USB host controller, and ++ * then invokes the start() method for the HCD associated with it ++ * through the hotplug entry's driver_data. ++ */ ++static int ehci_hcd_omap_probe(struct platform_device *pdev) ++{ ++ struct ehci_hcd_omap_platform_data *pdata = pdev->dev.platform_data; ++ struct ehci_hcd_omap *omap; ++ struct resource *res; ++ struct usb_hcd *hcd; ++ ++ int irq = platform_get_irq(pdev, 0); ++ int ret = -ENODEV; ++ ++ if (!pdata) { ++ dev_dbg(&pdev->dev, "missing platform_data\n"); ++ goto err_pdata; ++ } ++ ++ if (usb_disabled()) ++ goto err_disabled; ++ ++ omap = kzalloc(sizeof(*omap), GFP_KERNEL); ++ if (!omap) { ++ ret = -ENOMEM; ++ goto err_create_hcd; ++ } ++ ++ hcd = usb_create_hcd(&ehci_omap_hc_driver, &pdev->dev, ++ dev_name(&pdev->dev)); ++ if (!hcd) { ++ dev_dbg(&pdev->dev, "failed to create hcd with err %d\n", ret); ++ ret = -ENOMEM; ++ goto err_create_hcd; ++ } ++ ++ platform_set_drvdata(pdev, omap); ++ omap->dev = &pdev->dev; ++ omap->phy_reset = pdata->phy_reset; ++ omap->reset_gpio_port[0] = pdata->reset_gpio_port[0]; ++ omap->reset_gpio_port[1] = pdata->reset_gpio_port[1]; ++ omap->reset_gpio_port[2] = pdata->reset_gpio_port[2]; ++ omap->port_mode[0] = pdata->port_mode[0]; ++ omap->port_mode[1] = pdata->port_mode[1]; ++ omap->port_mode[2] = pdata->port_mode[2]; ++ omap->ehci = hcd_to_ehci(hcd); ++ omap->ehci->sbrn = 0x20; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ hcd->rsrc_start = res->start; ++ hcd->rsrc_len = resource_size(res); ++ ++ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); ++ if (!hcd->regs) { ++ dev_err(&pdev->dev, "EHCI ioremap failed\n"); ++ ret = -ENOMEM; ++ goto err_ioremap; ++ } ++ ++ /* we know this is the memory we want, no need to ioremap again */ ++ omap->ehci->caps = hcd->regs; ++ omap->ehci_base = hcd->regs; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ omap->uhh_base = ioremap(res->start, resource_size(res)); ++ if (!omap->uhh_base) { ++ dev_err(&pdev->dev, "UHH ioremap failed\n"); ++ ret = -ENOMEM; ++ goto err_uhh_ioremap; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 2); ++ omap->tll_base = ioremap(res->start, resource_size(res)); ++ if (!omap->tll_base) { ++ dev_err(&pdev->dev, "TLL ioremap failed\n"); ++ ret = -ENOMEM; ++ goto err_tll_ioremap; ++ } ++ ++ ret = omap_start_ehc(omap, hcd); ++ if (ret) { ++ dev_dbg(&pdev->dev, "failed to start ehci\n"); ++ goto err_start; ++ } ++ ++ omap->ehci->regs = hcd->regs ++ + HC_LENGTH(readl(&omap->ehci->caps->hc_capbase)); ++ ++ /* cache this readonly data; minimize chip reads */ ++ omap->ehci->hcs_params = readl(&omap->ehci->caps->hcs_params); ++ ++ /* SET 1 micro-frame Interrupt interval */ ++ writel(readl(&omap->ehci->regs->command) | (1 << 16), ++ &omap->ehci->regs->command); ++ ++ ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); ++ if (ret) { ++ dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret); ++ goto err_add_hcd; ++ } ++ ++ return 0; ++ ++err_add_hcd: ++ omap_stop_ehc(omap, hcd); ++ ++err_start: ++ iounmap(omap->tll_base); ++ ++err_tll_ioremap: ++ iounmap(omap->uhh_base); ++ ++err_uhh_ioremap: ++ iounmap(hcd->regs); ++ ++err_ioremap: ++ usb_put_hcd(hcd); ++ ++err_create_hcd: ++err_disabled: ++err_pdata: ++ return ret; ++} ++ ++/* may be called without controller electrically present */ ++/* may be called with controller, bus, and devices active */ ++ ++/** ++ * ehci_hcd_omap_remove - shutdown processing for EHCI HCDs ++ * @pdev: USB Host Controller being removed ++ * ++ * Reverses the effect of usb_ehci_hcd_omap_probe(), first invoking ++ * the HCD's stop() method. It is always called from a thread ++ * context, normally "rmmod", "apmd", or something similar. ++ */ ++static int ehci_hcd_omap_remove(struct platform_device *pdev) ++{ ++ struct ehci_hcd_omap *omap = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = ehci_to_hcd(omap->ehci); ++ ++ usb_remove_hcd(hcd); ++ omap_stop_ehc(omap, hcd); ++ iounmap(hcd->regs); ++ iounmap(omap->tll_base); ++ iounmap(omap->uhh_base); ++ usb_put_hcd(hcd); ++ ++ return 0; ++} ++ ++static void ehci_hcd_omap_shutdown(struct platform_device *pdev) ++{ ++ struct ehci_hcd_omap *omap = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = ehci_to_hcd(omap->ehci); ++ ++ if (hcd->driver->shutdown) ++ hcd->driver->shutdown(hcd); ++} ++ ++static struct platform_driver ehci_hcd_omap_driver = { ++ .probe = ehci_hcd_omap_probe, ++ .remove = ehci_hcd_omap_remove, ++ .shutdown = ehci_hcd_omap_shutdown, ++ /*.suspend = ehci_hcd_omap_suspend, */ ++ /*.resume = ehci_hcd_omap_resume, */ ++ .driver = { ++ .name = "ehci-omap", ++ } ++}; ++ ++/*-------------------------------------------------------------------------*/ ++ ++static const struct hc_driver ehci_omap_hc_driver = { ++ .description = hcd_name, ++ .product_desc = "OMAP-EHCI Host Controller", ++ .hcd_priv_size = sizeof(struct ehci_hcd), ++ ++ /* ++ * generic hardware linkage ++ */ ++ .irq = ehci_irq, ++ .flags = HCD_MEMORY | HCD_USB2, ++ ++ /* ++ * basic lifecycle operations ++ */ ++ .reset = ehci_init, ++ .start = ehci_run, ++ .stop = ehci_stop, ++ .shutdown = ehci_shutdown, ++ ++ /* ++ * managing i/o requests and associated device resources ++ */ ++ .urb_enqueue = ehci_urb_enqueue, ++ .urb_dequeue = ehci_urb_dequeue, ++ .endpoint_disable = ehci_endpoint_disable, ++ .endpoint_reset = ehci_endpoint_reset, ++ ++ /* ++ * scheduling support ++ */ ++ .get_frame_number = ehci_get_frame, ++ ++ /* ++ * root hub support ++ */ ++ .hub_status_data = ehci_hub_status_data, ++ .hub_control = ehci_hub_control, ++ .bus_suspend = ehci_bus_suspend, ++ .bus_resume = ehci_bus_resume, ++ ++ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, ++}; ++ ++MODULE_ALIAS("platform:omap-ehci"); ++MODULE_AUTHOR("Texas Instruments, Inc."); ++MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>"); ++ diff --git a/usb/usb-improved-error-handling-in-usb_port_suspend.patch b/usb/usb-improved-error-handling-in-usb_port_suspend.patch new file mode 100644 index 00000000000000..8bc2d3b0263e5c --- /dev/null +++ b/usb/usb-improved-error-handling-in-usb_port_suspend.patch @@ -0,0 +1,48 @@ +From oliver@neukum.org Tue Oct 27 10:24:50 2009 +From: Oliver Neukum <oliver@neukum.org> +Date: Mon, 19 Oct 2009 13:19:41 +0200 +Subject: USB: improved error handling in usb_port_suspend() +To: Greg KH <greg@kroah.com>, Alan Stern <stern@rowland.harvard.edu>, linux-usb@vger.kernel.org +Message-ID: <200910191319.41745.oliver@neukum.org> + + +usb: better error handling in usb_port_suspend + +- disable remote wakeup only if it was enabled +- refuse to autosuspend if remote wakeup fails to be enabled + +Signed-off-by: Oliver Neukum <oliver@neukum.org> +Cc: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/hub.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2123,9 +2123,13 @@ int usb_port_suspend(struct usb_device * + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); +- if (status) ++ if (status) { + dev_dbg(&udev->dev, "won't remote wakeup, status %d\n", + status); ++ /* bail if autosuspend is requested */ ++ if (msg.event & PM_EVENT_AUTO) ++ return status; ++ } + } + + /* see 7.1.7.6 */ +@@ -2134,7 +2138,8 @@ int usb_port_suspend(struct usb_device * + dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", + port1, status); + /* paranoia: "should not happen" */ +- (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), ++ if (udev->do_remote_wakeup) ++ (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, diff --git a/usb/usb-otg-add-generic-driver-for-ulpi-otg-transceiver.patch b/usb/usb-otg-add-generic-driver-for-ulpi-otg-transceiver.patch new file mode 100644 index 00000000000000..649fa44866392b --- /dev/null +++ b/usb/usb-otg-add-generic-driver-for-ulpi-otg-transceiver.patch @@ -0,0 +1,217 @@ +From ext-heikki.krogerus@nokia.com Tue Oct 27 10:09:38 2009 +From: Heikki Krogerus <ext-heikki.krogerus@nokia.com> +Date: Thu, 15 Oct 2009 17:09:35 +0300 +Subject: USB OTG: Add generic driver for ULPI OTG transceiver +To: krohei@gmail.com +Cc: ext Daniel Mack <daniel@caiaq.de>, Greg Kroah-Hartman <gregkh@suse.de>, David Brownell <dbrownell@users.sourceforge.net>, Sascha Hauer <s.hauer@pengutronix.de>, linux-usb@vger.kernel.org +Message-ID: <1255615776-17460-3-git-send-email-ext-heikki.krogerus@nokia.com> + + +From: Daniel Mack <daniel@caiaq.de> + +This adds a minimal generic driver for ULPI connected transceivers, +using the OTG framework functions recently introduced. + +The driver got a table to match the ULPI chips, which currently only has +one entry for NXP's ISP 1504 transceiver. + +Signed-off-by: Daniel Mack <daniel@caiaq.de> +Cc: Heikki Krogerus <ext-heikki.krogerus@nokia.com> +Cc: David Brownell <dbrownell@users.sourceforge.net> +Cc: Sascha Hauer <s.hauer@pengutronix.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/usb/Makefile | 2 + drivers/usb/otg/Kconfig | 9 +++ + drivers/usb/otg/Makefile | 1 + drivers/usb/otg/ulpi.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/usb/ulpi.h | 7 ++ + 5 files changed, 155 insertions(+) + create mode 100644 drivers/usb/otg/ulpi.c + create mode 100644 include/linux/usb/ulpi.h + +--- a/drivers/usb/Makefile ++++ b/drivers/usb/Makefile +@@ -44,3 +44,5 @@ obj-y += early/ + + obj-$(CONFIG_USB_ATM) += atm/ + obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ ++ ++obj-$(CONFIG_USB_ULPI) += otg/ +--- a/drivers/usb/otg/Kconfig ++++ b/drivers/usb/otg/Kconfig +@@ -41,6 +41,15 @@ config ISP1301_OMAP + This driver can also be built as a module. If so, the module + will be called isp1301_omap. + ++config USB_ULPI ++ bool "Generic ULPI Transceiver Driver" ++ depends on ARM ++ help ++ Enable this to support ULPI connected USB OTG transceivers which ++ are likely found on embedded boards. ++ ++ The only chip currently supported is NXP's ISP1504 ++ + config TWL4030_USB + tristate "TWL4030 USB Transceiver Driver" + depends on TWL4030_CORE && REGULATOR_TWL4030 +--- a/drivers/usb/otg/Makefile ++++ b/drivers/usb/otg/Makefile +@@ -10,6 +10,7 @@ obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus + obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o + obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o + obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o ++obj-$(CONFIG_USB_ULPI) += ulpi.o + + ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG + ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG +--- /dev/null ++++ b/drivers/usb/otg/ulpi.c +@@ -0,0 +1,136 @@ ++/* ++ * Generic ULPI USB transceiver support ++ * ++ * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de> ++ * ++ * Based on sources from ++ * ++ * Sascha Hauer <s.hauer@pengutronix.de> ++ * Freescale Semiconductors ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/usb.h> ++#include <linux/usb/otg.h> ++#include <linux/usb/ulpi.h> ++ ++/* ULPI register addresses */ ++#define ULPI_VID_LOW 0x00 /* Vendor ID low */ ++#define ULPI_VID_HIGH 0x01 /* Vendor ID high */ ++#define ULPI_PID_LOW 0x02 /* Product ID low */ ++#define ULPI_PID_HIGH 0x03 /* Product ID high */ ++#define ULPI_ITFCTL 0x07 /* Interface Control */ ++#define ULPI_OTGCTL 0x0A /* OTG Control */ ++ ++/* add to above register address to access Set/Clear functions */ ++#define ULPI_REG_SET 0x01 ++#define ULPI_REG_CLEAR 0x02 ++ ++/* ULPI OTG Control Register bits */ ++#define ID_PULL_UP (1 << 0) /* enable ID Pull Up */ ++#define DP_PULL_DOWN (1 << 1) /* enable DP Pull Down */ ++#define DM_PULL_DOWN (1 << 2) /* enable DM Pull Down */ ++#define DISCHRG_VBUS (1 << 3) /* Discharge Vbus */ ++#define CHRG_VBUS (1 << 4) /* Charge Vbus */ ++#define DRV_VBUS (1 << 5) /* Drive Vbus */ ++#define DRV_VBUS_EXT (1 << 6) /* Drive Vbus external */ ++#define USE_EXT_VBUS_IND (1 << 7) /* Use ext. Vbus indicator */ ++ ++#define ULPI_ID(vendor, product) (((vendor) << 16) | (product)) ++ ++#define TR_FLAG(flags, a, b) (((flags) & a) ? b : 0) ++ ++/* ULPI hardcoded IDs, used for probing */ ++static unsigned int ulpi_ids[] = { ++ ULPI_ID(0x04cc, 0x1504), /* NXP ISP1504 */ ++}; ++ ++static int ulpi_set_flags(struct otg_transceiver *otg) ++{ ++ unsigned int flags = 0; ++ ++ if (otg->flags & USB_OTG_PULLUP_ID) ++ flags |= ID_PULL_UP; ++ ++ if (otg->flags & USB_OTG_PULLDOWN_DM) ++ flags |= DM_PULL_DOWN; ++ ++ if (otg->flags & USB_OTG_PULLDOWN_DP) ++ flags |= DP_PULL_DOWN; ++ ++ if (otg->flags & USB_OTG_EXT_VBUS_INDICATOR) ++ flags |= USE_EXT_VBUS_IND; ++ ++ return otg_io_write(otg, flags, ULPI_OTGCTL + ULPI_REG_SET); ++} ++ ++static int ulpi_init(struct otg_transceiver *otg) ++{ ++ int i, vid, pid; ++ ++ vid = (otg_io_read(otg, ULPI_VID_HIGH) << 8) | ++ otg_io_read(otg, ULPI_VID_LOW); ++ pid = (otg_io_read(otg, ULPI_PID_HIGH) << 8) | ++ otg_io_read(otg, ULPI_PID_LOW); ++ ++ pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid); ++ ++ for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) ++ if (ulpi_ids[i] == ULPI_ID(vid, pid)) ++ return ulpi_set_flags(otg); ++ ++ pr_err("ULPI ID does not match any known transceiver.\n"); ++ return -ENODEV; ++} ++ ++static int ulpi_set_vbus(struct otg_transceiver *otg, bool on) ++{ ++ unsigned int flags = otg_io_read(otg, ULPI_OTGCTL); ++ ++ flags &= ~(DRV_VBUS | DRV_VBUS_EXT); ++ ++ if (on) { ++ if (otg->flags & USB_OTG_DRV_VBUS) ++ flags |= DRV_VBUS; ++ ++ if (otg->flags & USB_OTG_DRV_VBUS_EXT) ++ flags |= DRV_VBUS_EXT; ++ } ++ ++ return otg_io_write(otg, flags, ULPI_OTGCTL + ULPI_REG_SET); ++} ++ ++struct otg_transceiver * ++otg_ulpi_create(struct otg_io_access_ops *ops, ++ unsigned int flags) ++{ ++ struct otg_transceiver *otg; ++ ++ otg = kzalloc(sizeof(*otg), GFP_KERNEL); ++ if (!otg) ++ return NULL; ++ ++ otg->label = "ULPI"; ++ otg->flags = flags; ++ otg->io_ops = ops; ++ otg->init = ulpi_init; ++ otg->set_vbus = ulpi_set_vbus; ++ ++ return otg; ++} ++EXPORT_SYMBOL_GPL(otg_ulpi_create); ++ +--- /dev/null ++++ b/include/linux/usb/ulpi.h +@@ -0,0 +1,7 @@ ++#ifndef __LINUX_USB_ULPI_H ++#define __LINUX_USB_ULPI_H ++ ++struct otg_transceiver *otg_ulpi_create(struct otg_io_access_ops *ops, ++ unsigned int flags); ++ ++#endif /* __LINUX_USB_ULPI_H */ diff --git a/usb/usb-otg-add-support-for-ulpi-connected-external-transceivers.patch b/usb/usb-otg-add-support-for-ulpi-connected-external-transceivers.patch new file mode 100644 index 00000000000000..924b806fbc43f5 --- /dev/null +++ b/usb/usb-otg-add-support-for-ulpi-connected-external-transceivers.patch @@ -0,0 +1,154 @@ +From ext-heikki.krogerus@nokia.com Tue Oct 27 10:08:40 2009 +From: Heikki Krogerus <ext-heikki.krogerus@nokia.com> +Date: Thu, 15 Oct 2009 17:09:34 +0300 +Subject: USB OTG: add support for ulpi connected external transceivers +To: krohei@gmail.com +Cc: ext Daniel Mack <daniel@caiaq.de>, Greg Kroah-Hartman <gregkh@suse.de>, David Brownell <dbrownell@users.sourceforge.net>, linux-usb@vger.kernel.org +Message-ID: <1255615776-17460-2-git-send-email-ext-heikki.krogerus@nokia.com> + + +From: Daniel Mack <daniel@caiaq.de> + +This adds support for OTG transceivers directly connected to the ULPI +interface. In particular, the following details are added + +- a struct for low level io functions (read/write) +- a priv field to be used as 'viewport' by low level access functions +- an (*init) and (*shutdown) callbacks, along with static inline helpers +- a (*set_vbus) callback to switch the port power on and off +- a flags field for per-transceiver settings +- some defines for the flags bitmask to configure platform specific + details + +Signed-off-by: Daniel Mack <daniel@caiaq.de> +Cc: Heikki Krogerus <ext-heikki.krogerus@nokia.com> +Cc: David Brownell <dbrownell@users.sourceforge.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + include/linux/usb/otg.h | 68 +++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 67 insertions(+), 1 deletion(-) + +--- a/include/linux/usb/otg.h ++++ b/include/linux/usb/otg.h +@@ -33,6 +33,23 @@ enum usb_otg_state { + OTG_STATE_A_VBUS_ERR, + }; + ++#define USB_OTG_PULLUP_ID (1 << 0) ++#define USB_OTG_PULLDOWN_DP (1 << 1) ++#define USB_OTG_PULLDOWN_DM (1 << 2) ++#define USB_OTG_EXT_VBUS_INDICATOR (1 << 3) ++#define USB_OTG_DRV_VBUS (1 << 4) ++#define USB_OTG_DRV_VBUS_EXT (1 << 5) ++ ++struct otg_transceiver; ++ ++/* for transceivers connected thru an ULPI interface, the user must ++ * provide access ops ++ */ ++struct otg_io_access_ops { ++ int (*read)(struct otg_transceiver *otg, u32 reg); ++ int (*write)(struct otg_transceiver *otg, u32 val, u32 reg); ++}; ++ + /* + * the otg driver needs to interact with both device side and host side + * usb controllers. it decides which controller is active at a given +@@ -42,6 +59,7 @@ enum usb_otg_state { + struct otg_transceiver { + struct device *dev; + const char *label; ++ unsigned int flags; + + u8 default_a; + enum usb_otg_state state; +@@ -49,10 +67,17 @@ struct otg_transceiver { + struct usb_bus *host; + struct usb_gadget *gadget; + ++ struct otg_io_access_ops *io_ops; ++ void __iomem *io_priv; ++ + /* to pass extra port status to the root hub */ + u16 port_status; + u16 port_change; + ++ /* initialize/shutdown the OTG controller */ ++ int (*init)(struct otg_transceiver *otg); ++ void (*shutdown)(struct otg_transceiver *otg); ++ + /* bind/unbind the host controller */ + int (*set_host)(struct otg_transceiver *otg, + struct usb_bus *host); +@@ -65,6 +90,10 @@ struct otg_transceiver { + int (*set_power)(struct otg_transceiver *otg, + unsigned mA); + ++ /* effective for A-peripheral, ignored for B devices */ ++ int (*set_vbus)(struct otg_transceiver *otg, ++ bool enabled); ++ + /* for non-OTG B devices: set transceiver into suspend mode */ + int (*set_suspend)(struct otg_transceiver *otg, + int suspend); +@@ -85,6 +114,38 @@ extern int otg_set_transceiver(struct ot + extern void usb_nop_xceiv_register(void); + extern void usb_nop_xceiv_unregister(void); + ++/* helpers for direct access thru low-level io interface */ ++static inline int otg_io_read(struct otg_transceiver *otg, u32 reg) ++{ ++ if (otg->io_ops && otg->io_ops->read) ++ return otg->io_ops->read(otg, reg); ++ ++ return -EINVAL; ++} ++ ++static inline int otg_io_write(struct otg_transceiver *otg, u32 reg, u32 val) ++{ ++ if (otg->io_ops && otg->io_ops->write) ++ return otg->io_ops->write(otg, reg, val); ++ ++ return -EINVAL; ++} ++ ++static inline int ++otg_init(struct otg_transceiver *otg) ++{ ++ if (otg->init) ++ return otg->init(otg); ++ ++ return 0; ++} ++ ++static inline void ++otg_shutdown(struct otg_transceiver *otg) ++{ ++ if (otg->shutdown) ++ otg->shutdown(otg); ++} + + /* for usb host and peripheral controller drivers */ + extern struct otg_transceiver *otg_get_transceiver(void); +@@ -97,6 +158,12 @@ otg_start_hnp(struct otg_transceiver *ot + return otg->start_hnp(otg); + } + ++/* Context: can sleep */ ++static inline int ++otg_set_vbus(struct otg_transceiver *otg, bool enabled) ++{ ++ return otg->set_vbus(otg, enabled); ++} + + /* for HCDs */ + static inline int +@@ -105,7 +172,6 @@ otg_set_host(struct otg_transceiver *otg + return otg->set_host(otg, host); + } + +- + /* for usb peripheral controller drivers */ + + /* Context: can sleep */ |
