aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2010-07-19 04:40:44 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-10 17:35:42 -0400
commit10aebc772a10c95e30dff0779cb0f879b8f1554f (patch)
tree79a0cee8dd9a3e9a61fc537f9571429ff5829866 /drivers/usb
parentb3864cedfb576e11d2f9274f14a24840d8b569c3 (diff)
USB: s3c-hsotg: Add initial detection and setup for dedicated FIFO mode
Add support for the dedicated FIFO mode on newer SoCs such as the S5PV210 partly to improve support and to fix the bug where any non-EP0 IN endpoint requires its own FIFO allocation. To fix this, we ensure that any non-zero IN endpoint is given a TXFIFO using the same allocation method as the periodic case (all our current hardware has enough FIFOs and FIFO memory for a 1:1 mapping) and ensure that the necessary transmission done interrupt is enabled. The default settings from reset for the core point all EPs at FIFO0, used for the control endpoint. However, the controller documentation states that all IN endpoints _must_ have a unique FIFO to avoid any contention during transmission. Note, this leaves us with a large IN FIFO for EP0 (which re-uses the old NPTXFIFO) for an endpoint which cannot shift more than a pair of packets at a time... this is a waste, but it looks like we cannot re-allocate space to the individual IN FIFOs as they are already maxed out (to be confirmed). Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/s3c-hsotg.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 9d32c9ff737d..4196e376a346 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -12,6 +12,8 @@
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13*/ 13*/
14 14
15#define DEBUG
16
15#include <linux/kernel.h> 17#include <linux/kernel.h>
16#include <linux/module.h> 18#include <linux/module.h>
17#include <linux/spinlock.h> 19#include <linux/spinlock.h>
@@ -130,6 +132,7 @@ struct s3c_hsotg_ep {
130 * @regs: The memory area mapped for accessing registers. 132 * @regs: The memory area mapped for accessing registers.
131 * @regs_res: The resource that was allocated when claiming register space. 133 * @regs_res: The resource that was allocated when claiming register space.
132 * @irq: The IRQ number we are using 134 * @irq: The IRQ number we are using
135 * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
133 * @debug_root: root directrory for debugfs. 136 * @debug_root: root directrory for debugfs.
134 * @debug_file: main status file for debugfs. 137 * @debug_file: main status file for debugfs.
135 * @debug_fifo: FIFO status file for debugfs. 138 * @debug_fifo: FIFO status file for debugfs.
@@ -148,6 +151,8 @@ struct s3c_hsotg {
148 struct resource *regs_res; 151 struct resource *regs_res;
149 int irq; 152 int irq;
150 153
154 unsigned int dedicated_fifos:1;
155
151 struct dentry *debug_root; 156 struct dentry *debug_root;
152 struct dentry *debug_file; 157 struct dentry *debug_file;
153 struct dentry *debug_fifo; 158 struct dentry *debug_fifo;
@@ -466,7 +471,7 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
466 if (to_write == 0) 471 if (to_write == 0)
467 return 0; 472 return 0;
468 473
469 if (periodic) { 474 if (periodic && !hsotg->dedicated_fifos) {
470 u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index)); 475 u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index));
471 int size_left; 476 int size_left;
472 int size_done; 477 int size_done;
@@ -504,6 +509,11 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
504 s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp); 509 s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp);
505 return -ENOSPC; 510 return -ENOSPC;
506 } 511 }
512 } else if (hsotg->dedicated_fifos && hs_ep->index != 0) {
513 can_write = readl(hsotg->regs + S3C_DTXFSTS(hs_ep->index));
514
515 can_write &= 0xffff;
516 can_write *= 4;
507 } else { 517 } else {
508 if (S3C_GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) { 518 if (S3C_GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) {
509 dev_dbg(hsotg->dev, 519 dev_dbg(hsotg->dev,
@@ -1829,6 +1839,15 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
1829 __func__, idx); 1839 __func__, idx);
1830 clear |= S3C_DIEPMSK_INTknEPMisMsk; 1840 clear |= S3C_DIEPMSK_INTknEPMisMsk;
1831 } 1841 }
1842
1843 /* FIFO has space or is empty (see GAHBCFG) */
1844 if (hsotg->dedicated_fifos &&
1845 ints & S3C_DIEPMSK_TxFIFOEmpty) {
1846 dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n",
1847 __func__, idx);
1848 s3c_hsotg_trytx(hsotg, hs_ep);
1849 clear |= S3C_DIEPMSK_TxFIFOEmpty;
1850 }
1832 } 1851 }
1833 1852
1834 writel(clear, hsotg->regs + epint_reg); 1853 writel(clear, hsotg->regs + epint_reg);
@@ -2280,6 +2299,12 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
2280 break; 2299 break;
2281 } 2300 }
2282 2301
2302 /* if the hardware has dedicated fifos, we must give each IN EP
2303 * a unique tx-fifo even if it is non-periodic.
2304 */
2305 if (dir_in && hsotg->dedicated_fifos)
2306 epctrl |= S3C_DxEPCTL_TxFNum(index);
2307
2283 /* for non control endpoints, set PID to D0 */ 2308 /* for non control endpoints, set PID to D0 */
2284 if (index) 2309 if (index)
2285 epctrl |= S3C_DxEPCTL_SetD0PID; 2310 epctrl |= S3C_DxEPCTL_SetD0PID;
@@ -2569,7 +2594,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
2569 2594
2570 writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk | 2595 writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk |
2571 S3C_DIEPMSK_INTknEPMisMsk | 2596 S3C_DIEPMSK_INTknEPMisMsk |
2572 S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk, 2597 S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk |
2598 ((hsotg->dedicated_fifos) ? S3C_DIEPMSK_TxFIFOEmpty : 0),
2573 hsotg->regs + S3C_DIEPMSK); 2599 hsotg->regs + S3C_DIEPMSK);
2574 2600
2575 /* don't need XferCompl, we get that from RXFIFO in slave mode. In 2601 /* don't need XferCompl, we get that from RXFIFO in slave mode. In
@@ -2778,6 +2804,8 @@ static void s3c_hsotg_otgreset(struct s3c_hsotg *hsotg)
2778 2804
2779static void s3c_hsotg_init(struct s3c_hsotg *hsotg) 2805static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
2780{ 2806{
2807 u32 cfg4;
2808
2781 /* unmask subset of endpoint interrupts */ 2809 /* unmask subset of endpoint interrupts */
2782 2810
2783 writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk | 2811 writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk |
@@ -2813,6 +2841,14 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
2813 2841
2814 writel(using_dma(hsotg) ? S3C_GAHBCFG_DMAEn : 0x0, 2842 writel(using_dma(hsotg) ? S3C_GAHBCFG_DMAEn : 0x0,
2815 hsotg->regs + S3C_GAHBCFG); 2843 hsotg->regs + S3C_GAHBCFG);
2844
2845 /* check hardware configuration */
2846
2847 cfg4 = readl(hsotg->regs + 0x50);
2848 hsotg->dedicated_fifos = (cfg4 >> 25) & 1;
2849
2850 dev_info(hsotg->dev, "%s fifos\n",
2851 hsotg->dedicated_fifos ? "dedicated" : "shared");
2816} 2852}
2817 2853
2818static void s3c_hsotg_dump(struct s3c_hsotg *hsotg) 2854static void s3c_hsotg_dump(struct s3c_hsotg *hsotg)