diff options
-rw-r--r-- | arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/s3c-hsotg.c | 40 |
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 8d18d9d4d148..dc90f5ede88f 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 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 | ||
2779 | static void s3c_hsotg_init(struct s3c_hsotg *hsotg) | 2805 | static 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 | ||
2818 | static void s3c_hsotg_dump(struct s3c_hsotg *hsotg) | 2854 | static void s3c_hsotg_dump(struct s3c_hsotg *hsotg) |