aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h2
-rw-r--r--drivers/usb/gadget/s3c-hsotg.c40
2 files changed, 40 insertions, 2 deletions
diff --git a/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h
index 8d18d9d4d14..dc90f5ede88 100644
--- a/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h
+++ b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h
@@ -226,6 +226,7 @@
226 226
227#define S3C_DIEPMSK S3C_HSOTG_REG(0x810) 227#define S3C_DIEPMSK S3C_HSOTG_REG(0x810)
228 228
229#define S3C_DIEPMSK_TxFIFOEmpty (1 << 7)
229#define S3C_DIEPMSK_INEPNakEffMsk (1 << 6) 230#define S3C_DIEPMSK_INEPNakEffMsk (1 << 6)
230#define S3C_DIEPMSK_INTknEPMisMsk (1 << 5) 231#define S3C_DIEPMSK_INTknEPMisMsk (1 << 5)
231#define S3C_DIEPMSK_INTknTXFEmpMsk (1 << 4) 232#define S3C_DIEPMSK_INTknTXFEmpMsk (1 << 4)
@@ -371,6 +372,7 @@
371 372
372#define S3C_DIEPDMA(_a) S3C_HSOTG_REG(0x914 + ((_a) * 0x20)) 373#define S3C_DIEPDMA(_a) S3C_HSOTG_REG(0x914 + ((_a) * 0x20))
373#define S3C_DOEPDMA(_a) S3C_HSOTG_REG(0xB14 + ((_a) * 0x20)) 374#define S3C_DOEPDMA(_a) S3C_HSOTG_REG(0xB14 + ((_a) * 0x20))
375#define S3C_DTXFSTS(_a) S3C_HSOTG_REG(0x918 + ((_a) * 0x20))
374 376
375#define S3C_EPFIFO(_a) S3C_HSOTG_REG(0x1000 + ((_a) * 0x1000)) 377#define S3C_EPFIFO(_a) S3C_HSOTG_REG(0x1000 + ((_a) * 0x1000))
376 378
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 9d32c9ff737..4196e376a34 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)