Op 11-06-10 10:20, Ben Dooks schreef: > 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@xxxxxxxxx? Shouldn't this be s/\?/>/ ? > --- > .../arm/plat-samsung/include/plat/regs-usb-hsotg.h | 2 + > 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 8d18d9d..dc90f5e 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 @@ > > #define S3C_DIEPMSK S3C_HSOTG_REG(0x810) > > +#define S3C_DIEPMSK_TxFIFOEmpty (1 << 7) > #define S3C_DIEPMSK_INEPNakEffMsk (1 << 6) > #define S3C_DIEPMSK_INTknEPMisMsk (1 << 5) > #define S3C_DIEPMSK_INTknTXFEmpMsk (1 << 4) > @@ -371,6 +372,7 @@ > > #define S3C_DIEPDMA(_a) S3C_HSOTG_REG(0x914 + ((_a) * 0x20)) > #define S3C_DOEPDMA(_a) S3C_HSOTG_REG(0xB14 + ((_a) * 0x20)) > +#define S3C_DTXFSTS(_a) S3C_HSOTG_REG(0x918 + ((_a) * 0x20)) > > #define S3C_EPFIFO(_a) S3C_HSOTG_REG(0x1000 + ((_a) * 0x1000)) > > diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c > index 5b61bcf..819e75a 100644 > --- a/drivers/usb/gadget/s3c-hsotg.c > +++ b/drivers/usb/gadget/s3c-hsotg.c > @@ -12,6 +12,8 @@ > * published by the Free Software Foundation. > */ > > +#define DEBUG I don't think this is an intended change? > + > #include <linux/kernel.h> > #include <linux/module.h> > #include <linux/spinlock.h> > @@ -131,6 +133,7 @@ struct s3c_hsotg_ep { > * @regs: The memory area mapped for accessing registers. > * @regs_res: The resource that was allocated when claiming register space. > * @irq: The IRQ number we are using > + * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos. > * @debug_root: root directrory for debugfs. > * @debug_file: main status file for debugfs. > * @debug_fifo: FIFO status file for debugfs. > @@ -149,6 +152,8 @@ struct s3c_hsotg { > struct resource *regs_res; > int irq; > > + unsigned int dedicated_fifos:1; > + > struct dentry *debug_root; > struct dentry *debug_file; > struct dentry *debug_fifo; > @@ -467,7 +472,7 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, > if (to_write == 0) > return 0; > > - if (periodic) { > + if (periodic && !hsotg->dedicated_fifos) { > u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index)); > int size_left; > int size_done; > @@ -505,6 +510,11 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, > s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp); > return -ENOSPC; > } > + } else if (hsotg->dedicated_fifos && hs_ep->index != 0) { > + can_write = readl(hsotg->regs + S3C_DTXFSTS(hs_ep->index)); > + > + can_write &= 0xffff; > + can_write *= 4; > } else { > if (S3C_GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) { > dev_dbg(hsotg->dev, > @@ -1830,6 +1840,15 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, > __func__, idx); > clear |= S3C_DIEPMSK_INTknEPMisMsk; > } > + > + /* FIFO has space or is empty (see GAHBCFG) */ > + if (hsotg->dedicated_fifos && > + ints & S3C_DIEPMSK_TxFIFOEmpty) { > + dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n", > + __func__, idx); > + s3c_hsotg_trytx(hsotg, hs_ep); > + clear |= S3C_DIEPMSK_TxFIFOEmpty; > + } > } > > writel(clear, hsotg->regs + epint_reg); > @@ -2281,6 +2300,12 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, > break; > } > > + /* if the hardware has dedicated fifos, we must give each IN EP > + * a unique tx-fifo even if it is non-periodic. > + */ > + if (dir_in && hsotg->dedicated_fifos) > + epctrl |= S3C_DxEPCTL_TxFNum(index); > + > /* for non control endpoints, set PID to D0 */ > if (index) > epctrl |= S3C_DxEPCTL_SetD0PID; > @@ -2570,7 +2595,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) > > writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk | > S3C_DIEPMSK_INTknEPMisMsk | > - S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk, > + S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk | > + ((hsotg->dedicated_fifos) ? S3C_DIEPMSK_TxFIFOEmpty : 0), > hsotg->regs + S3C_DIEPMSK); > > /* don't need XferCompl, we get that from RXFIFO in slave mode. In > @@ -2797,6 +2823,8 @@ static void s3c_hsotg_otgreset(struct s3c_hsotg *hsotg) > > static void s3c_hsotg_init(struct s3c_hsotg *hsotg) > { > + u32 cfg4; > + > /* unmask subset of endpoint interrupts */ > > writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk | > @@ -2832,6 +2860,14 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg) > > writel(using_dma(hsotg) ? S3C_GAHBCFG_DMAEn : 0x0, > hsotg->regs + S3C_GAHBCFG); > + > + /* check hardware configuration */ > + > + cfg4 = readl(hsotg->regs + 0x50); > + hsotg->dedicated_fifos = (cfg4 >> 25) & 1; > + > + dev_info(hsotg->dev, "%s fifos\n", > + hsotg->dedicated_fifos ? "dedicated" : "shared"); > } > > static void s3c_hsotg_dump(struct s3c_hsotg *hsotg) -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html