diff options
59 files changed, 2221 insertions, 2139 deletions
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c index ed90aef404c3..9c97d7ca389c 100644 --- a/arch/arm/mach-exynos/mach-nuri.c +++ b/arch/arm/mach-exynos/mach-nuri.c @@ -44,6 +44,7 @@ #include <plat/fb.h> #include <plat/sdhci.h> #include <plat/ehci.h> +#include <linux/platform_data/s3c-hsotg.h> #include <plat/clock.h> #include <plat/gpio-cfg.h> #include <plat/iic.h> diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c index cb2b027f09a6..62f159a6583c 100644 --- a/arch/arm/mach-exynos/mach-universal_c210.c +++ b/arch/arm/mach-exynos/mach-universal_c210.c @@ -42,6 +42,7 @@ #include <plat/fimc-core.h> #include <plat/camport.h> #include <plat/mipi_csis.h> +#include <linux/platform_data/s3c-hsotg.h> #include <mach/map.h> diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c index e20bf5835365..a02f204d99ed 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410.c @@ -61,7 +61,7 @@ #include <plat/sdhci.h> #include <plat/gpio-cfg.h> #include <plat/s3c64xx-spi.h> -#include <plat/udc-hs.h> +#include <linux/platform_data/s3c-hsotg.h> #include <plat/keypad.h> #include <plat/clock.h> diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c index ce745e19aa27..ee0d13c98378 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq.c +++ b/arch/arm/mach-s3c64xx/mach-smartq.c @@ -33,7 +33,7 @@ #include <plat/gpio-cfg.h> #include <plat/hwmon.h> #include <plat/regs-serial.h> -#include <plat/udc-hs.h> +#include <linux/platform_data/s3c-hsotg.h> #include <plat/usb-control.h> #include <plat/sdhci.h> #include <plat/ts.h> diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c index d55bc96d9582..bf477e33f0ee 100644 --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c @@ -72,7 +72,7 @@ #include <plat/keypad.h> #include <plat/backlight.h> #include <plat/regs-fb-v4.h> -#include <plat/udc-hs.h> +#include <linux/platform_data/s3c-hsotg.h> #include "common.h" diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index 32395664e879..781fed689cd8 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -50,6 +50,7 @@ #include <plat/mfc.h> #include <plat/regs-fb-v4.h> #include <plat/camport.h> +#include <linux/platform_data/s3c-hsotg.h> #include <media/v4l2-mediabus.h> #include <media/s5p_fimc.h> diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index 8b928f9bc1c3..a41c808847c0 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c @@ -57,7 +57,7 @@ #include <plat/sdhci.h> #include <plat/ts.h> #include <plat/udc.h> -#include <plat/udc-hs.h> +#include <linux/platform_data/s3c-hsotg.h> #include <plat/usb-control.h> #include <plat/usb-phy.h> #include <plat/regs-iic.h> diff --git a/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h deleted file mode 100644 index dc90f5ede88f..000000000000 --- a/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h +++ /dev/null @@ -1,379 +0,0 @@ -/* arch/arm/plat-s3c/include/plat/regs-usb-hsotg.h - * - * Copyright 2008 Openmoko, Inc. - * Copyright 2008 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks <ben@simtec.co.uk> - * - * S3C - USB2.0 Highspeed/OtG device block registers - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#ifndef __PLAT_S3C64XX_REGS_USB_HSOTG_H -#define __PLAT_S3C64XX_REGS_USB_HSOTG_H __FILE__ - -#define S3C_HSOTG_REG(x) (x) - -#define S3C_GOTGCTL S3C_HSOTG_REG(0x000) -#define S3C_GOTGCTL_BSESVLD (1 << 19) -#define S3C_GOTGCTL_ASESVLD (1 << 18) -#define S3C_GOTGCTL_DBNC_SHORT (1 << 17) -#define S3C_GOTGCTL_CONID_B (1 << 16) -#define S3C_GOTGCTL_DEVHNPEN (1 << 11) -#define S3C_GOTGCTL_HSSETHNPEN (1 << 10) -#define S3C_GOTGCTL_HNPREQ (1 << 9) -#define S3C_GOTGCTL_HSTNEGSCS (1 << 8) -#define S3C_GOTGCTL_SESREQ (1 << 1) -#define S3C_GOTGCTL_SESREQSCS (1 << 0) - -#define S3C_GOTGINT S3C_HSOTG_REG(0x004) -#define S3C_GOTGINT_DbnceDone (1 << 19) -#define S3C_GOTGINT_ADevTOUTChg (1 << 18) -#define S3C_GOTGINT_HstNegDet (1 << 17) -#define S3C_GOTGINT_HstnegSucStsChng (1 << 9) -#define S3C_GOTGINT_SesReqSucStsChng (1 << 8) -#define S3C_GOTGINT_SesEndDet (1 << 2) - -#define S3C_GAHBCFG S3C_HSOTG_REG(0x008) -#define S3C_GAHBCFG_PTxFEmpLvl (1 << 8) -#define S3C_GAHBCFG_NPTxFEmpLvl (1 << 7) -#define S3C_GAHBCFG_DMAEn (1 << 5) -#define S3C_GAHBCFG_HBstLen_MASK (0xf << 1) -#define S3C_GAHBCFG_HBstLen_SHIFT (1) -#define S3C_GAHBCFG_HBstLen_Single (0x0 << 1) -#define S3C_GAHBCFG_HBstLen_Incr (0x1 << 1) -#define S3C_GAHBCFG_HBstLen_Incr4 (0x3 << 1) -#define S3C_GAHBCFG_HBstLen_Incr8 (0x5 << 1) -#define S3C_GAHBCFG_HBstLen_Incr16 (0x7 << 1) -#define S3C_GAHBCFG_GlblIntrEn (1 << 0) - -#define S3C_GUSBCFG S3C_HSOTG_REG(0x00C) -#define S3C_GUSBCFG_PHYLPClkSel (1 << 15) -#define S3C_GUSBCFG_HNPCap (1 << 9) -#define S3C_GUSBCFG_SRPCap (1 << 8) -#define S3C_GUSBCFG_PHYIf16 (1 << 3) -#define S3C_GUSBCFG_TOutCal_MASK (0x7 << 0) -#define S3C_GUSBCFG_TOutCal_SHIFT (0) -#define S3C_GUSBCFG_TOutCal_LIMIT (0x7) -#define S3C_GUSBCFG_TOutCal(_x) ((_x) << 0) - -#define S3C_GRSTCTL S3C_HSOTG_REG(0x010) - -#define S3C_GRSTCTL_AHBIdle (1 << 31) -#define S3C_GRSTCTL_DMAReq (1 << 30) -#define S3C_GRSTCTL_TxFNum_MASK (0x1f << 6) -#define S3C_GRSTCTL_TxFNum_SHIFT (6) -#define S3C_GRSTCTL_TxFNum_LIMIT (0x1f) -#define S3C_GRSTCTL_TxFNum(_x) ((_x) << 6) -#define S3C_GRSTCTL_TxFFlsh (1 << 5) -#define S3C_GRSTCTL_RxFFlsh (1 << 4) -#define S3C_GRSTCTL_INTknQFlsh (1 << 3) -#define S3C_GRSTCTL_FrmCntrRst (1 << 2) -#define S3C_GRSTCTL_HSftRst (1 << 1) -#define S3C_GRSTCTL_CSftRst (1 << 0) - -#define S3C_GINTSTS S3C_HSOTG_REG(0x014) -#define S3C_GINTMSK S3C_HSOTG_REG(0x018) - -#define S3C_GINTSTS_WkUpInt (1 << 31) -#define S3C_GINTSTS_SessReqInt (1 << 30) -#define S3C_GINTSTS_DisconnInt (1 << 29) -#define S3C_GINTSTS_ConIDStsChng (1 << 28) -#define S3C_GINTSTS_PTxFEmp (1 << 26) -#define S3C_GINTSTS_HChInt (1 << 25) -#define S3C_GINTSTS_PrtInt (1 << 24) -#define S3C_GINTSTS_FetSusp (1 << 22) -#define S3C_GINTSTS_incompIP (1 << 21) -#define S3C_GINTSTS_IncomplSOIN (1 << 20) -#define S3C_GINTSTS_OEPInt (1 << 19) -#define S3C_GINTSTS_IEPInt (1 << 18) -#define S3C_GINTSTS_EPMis (1 << 17) -#define S3C_GINTSTS_EOPF (1 << 15) -#define S3C_GINTSTS_ISOutDrop (1 << 14) -#define S3C_GINTSTS_EnumDone (1 << 13) -#define S3C_GINTSTS_USBRst (1 << 12) -#define S3C_GINTSTS_USBSusp (1 << 11) -#define S3C_GINTSTS_ErlySusp (1 << 10) -#define S3C_GINTSTS_GOUTNakEff (1 << 7) -#define S3C_GINTSTS_GINNakEff (1 << 6) -#define S3C_GINTSTS_NPTxFEmp (1 << 5) -#define S3C_GINTSTS_RxFLvl (1 << 4) -#define S3C_GINTSTS_SOF (1 << 3) -#define S3C_GINTSTS_OTGInt (1 << 2) -#define S3C_GINTSTS_ModeMis (1 << 1) -#define S3C_GINTSTS_CurMod_Host (1 << 0) - -#define S3C_GRXSTSR S3C_HSOTG_REG(0x01C) -#define S3C_GRXSTSP S3C_HSOTG_REG(0x020) - -#define S3C_GRXSTS_FN_MASK (0x7f << 25) -#define S3C_GRXSTS_FN_SHIFT (25) - -#define S3C_GRXSTS_PktSts_MASK (0xf << 17) -#define S3C_GRXSTS_PktSts_SHIFT (17) -#define S3C_GRXSTS_PktSts_GlobalOutNAK (0x1 << 17) -#define S3C_GRXSTS_PktSts_OutRX (0x2 << 17) -#define S3C_GRXSTS_PktSts_OutDone (0x3 << 17) -#define S3C_GRXSTS_PktSts_SetupDone (0x4 << 17) -#define S3C_GRXSTS_PktSts_SetupRX (0x6 << 17) - -#define S3C_GRXSTS_DPID_MASK (0x3 << 15) -#define S3C_GRXSTS_DPID_SHIFT (15) -#define S3C_GRXSTS_ByteCnt_MASK (0x7ff << 4) -#define S3C_GRXSTS_ByteCnt_SHIFT (4) -#define S3C_GRXSTS_EPNum_MASK (0xf << 0) -#define S3C_GRXSTS_EPNum_SHIFT (0) - -#define S3C_GRXFSIZ S3C_HSOTG_REG(0x024) - -#define S3C_GNPTXFSIZ S3C_HSOTG_REG(0x028) - -#define S3C_GNPTXFSIZ_NPTxFDep_MASK (0xffff << 16) -#define S3C_GNPTXFSIZ_NPTxFDep_SHIFT (16) -#define S3C_GNPTXFSIZ_NPTxFDep_LIMIT (0xffff) -#define S3C_GNPTXFSIZ_NPTxFDep(_x) ((_x) << 16) -#define S3C_GNPTXFSIZ_NPTxFStAddr_MASK (0xffff << 0) -#define S3C_GNPTXFSIZ_NPTxFStAddr_SHIFT (0) -#define S3C_GNPTXFSIZ_NPTxFStAddr_LIMIT (0xffff) -#define S3C_GNPTXFSIZ_NPTxFStAddr(_x) ((_x) << 0) - -#define S3C_GNPTXSTS S3C_HSOTG_REG(0x02C) - -#define S3C_GNPTXSTS_NPtxQTop_MASK (0x7f << 24) -#define S3C_GNPTXSTS_NPtxQTop_SHIFT (24) - -#define S3C_GNPTXSTS_NPTxQSpcAvail_MASK (0xff << 16) -#define S3C_GNPTXSTS_NPTxQSpcAvail_SHIFT (16) -#define S3C_GNPTXSTS_NPTxQSpcAvail_GET(_v) (((_v) >> 16) & 0xff) - -#define S3C_GNPTXSTS_NPTxFSpcAvail_MASK (0xffff << 0) -#define S3C_GNPTXSTS_NPTxFSpcAvail_SHIFT (0) -#define S3C_GNPTXSTS_NPTxFSpcAvail_GET(_v) (((_v) >> 0) & 0xffff) - - -#define S3C_HPTXFSIZ S3C_HSOTG_REG(0x100) - -#define S3C_DPTXFSIZn(_a) S3C_HSOTG_REG(0x104 + (((_a) - 1) * 4)) - -#define S3C_DPTXFSIZn_DPTxFSize_MASK (0xffff << 16) -#define S3C_DPTXFSIZn_DPTxFSize_SHIFT (16) -#define S3C_DPTXFSIZn_DPTxFSize_GET(_v) (((_v) >> 16) & 0xffff) -#define S3C_DPTXFSIZn_DPTxFSize_LIMIT (0xffff) -#define S3C_DPTXFSIZn_DPTxFSize(_x) ((_x) << 16) - -#define S3C_DPTXFSIZn_DPTxFStAddr_MASK (0xffff << 0) -#define S3C_DPTXFSIZn_DPTxFStAddr_SHIFT (0) - -/* Device mode registers */ -#define S3C_DCFG S3C_HSOTG_REG(0x800) - -#define S3C_DCFG_EPMisCnt_MASK (0x1f << 18) -#define S3C_DCFG_EPMisCnt_SHIFT (18) -#define S3C_DCFG_EPMisCnt_LIMIT (0x1f) -#define S3C_DCFG_EPMisCnt(_x) ((_x) << 18) - -#define S3C_DCFG_PerFrInt_MASK (0x3 << 11) -#define S3C_DCFG_PerFrInt_SHIFT (11) -#define S3C_DCFG_PerFrInt_LIMIT (0x3) -#define S3C_DCFG_PerFrInt(_x) ((_x) << 11) - -#define S3C_DCFG_DevAddr_MASK (0x7f << 4) -#define S3C_DCFG_DevAddr_SHIFT (4) -#define S3C_DCFG_DevAddr_LIMIT (0x7f) -#define S3C_DCFG_DevAddr(_x) ((_x) << 4) - -#define S3C_DCFG_NZStsOUTHShk (1 << 2) - -#define S3C_DCFG_DevSpd_MASK (0x3 << 0) -#define S3C_DCFG_DevSpd_SHIFT (0) -#define S3C_DCFG_DevSpd_HS (0x0 << 0) -#define S3C_DCFG_DevSpd_FS (0x1 << 0) -#define S3C_DCFG_DevSpd_LS (0x2 << 0) -#define S3C_DCFG_DevSpd_FS48 (0x3 << 0) - -#define S3C_DCTL S3C_HSOTG_REG(0x804) - -#define S3C_DCTL_PWROnPrgDone (1 << 11) -#define S3C_DCTL_CGOUTNak (1 << 10) -#define S3C_DCTL_SGOUTNak (1 << 9) -#define S3C_DCTL_CGNPInNAK (1 << 8) -#define S3C_DCTL_SGNPInNAK (1 << 7) -#define S3C_DCTL_TstCtl_MASK (0x7 << 4) -#define S3C_DCTL_TstCtl_SHIFT (4) -#define S3C_DCTL_GOUTNakSts (1 << 3) -#define S3C_DCTL_GNPINNakSts (1 << 2) -#define S3C_DCTL_SftDiscon (1 << 1) -#define S3C_DCTL_RmtWkUpSig (1 << 0) - -#define S3C_DSTS S3C_HSOTG_REG(0x808) - -#define S3C_DSTS_SOFFN_MASK (0x3fff << 8) -#define S3C_DSTS_SOFFN_SHIFT (8) -#define S3C_DSTS_SOFFN_LIMIT (0x3fff) -#define S3C_DSTS_SOFFN(_x) ((_x) << 8) -#define S3C_DSTS_ErraticErr (1 << 3) -#define S3C_DSTS_EnumSpd_MASK (0x3 << 1) -#define S3C_DSTS_EnumSpd_SHIFT (1) -#define S3C_DSTS_EnumSpd_HS (0x0 << 1) -#define S3C_DSTS_EnumSpd_FS (0x1 << 1) -#define S3C_DSTS_EnumSpd_LS (0x2 << 1) -#define S3C_DSTS_EnumSpd_FS48 (0x3 << 1) - -#define S3C_DSTS_SuspSts (1 << 0) - -#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) -#define S3C_DIEPMSK_TimeOUTMsk (1 << 3) -#define S3C_DIEPMSK_AHBErrMsk (1 << 2) -#define S3C_DIEPMSK_EPDisbldMsk (1 << 1) -#define S3C_DIEPMSK_XferComplMsk (1 << 0) - -#define S3C_DOEPMSK S3C_HSOTG_REG(0x814) - -#define S3C_DOEPMSK_Back2BackSetup (1 << 6) -#define S3C_DOEPMSK_OUTTknEPdisMsk (1 << 4) -#define S3C_DOEPMSK_SetupMsk (1 << 3) -#define S3C_DOEPMSK_AHBErrMsk (1 << 2) -#define S3C_DOEPMSK_EPDisbldMsk (1 << 1) -#define S3C_DOEPMSK_XferComplMsk (1 << 0) - -#define S3C_DAINT S3C_HSOTG_REG(0x818) -#define S3C_DAINTMSK S3C_HSOTG_REG(0x81C) - -#define S3C_DAINT_OutEP_SHIFT (16) -#define S3C_DAINT_OutEP(x) (1 << ((x) + 16)) -#define S3C_DAINT_InEP(x) (1 << (x)) - -#define S3C_DTKNQR1 S3C_HSOTG_REG(0x820) -#define S3C_DTKNQR2 S3C_HSOTG_REG(0x824) -#define S3C_DTKNQR3 S3C_HSOTG_REG(0x830) -#define S3C_DTKNQR4 S3C_HSOTG_REG(0x834) - -#define S3C_DVBUSDIS S3C_HSOTG_REG(0x828) -#define S3C_DVBUSPULSE S3C_HSOTG_REG(0x82C) - -#define S3C_DIEPCTL0 S3C_HSOTG_REG(0x900) -#define S3C_DOEPCTL0 S3C_HSOTG_REG(0xB00) -#define S3C_DIEPCTL(_a) S3C_HSOTG_REG(0x900 + ((_a) * 0x20)) -#define S3C_DOEPCTL(_a) S3C_HSOTG_REG(0xB00 + ((_a) * 0x20)) - -/* EP0 specialness: - * bits[29..28] - reserved (no SetD0PID, SetD1PID) - * bits[25..22] - should always be zero, this isn't a periodic endpoint - * bits[10..0] - MPS setting differenct for EP0 -*/ -#define S3C_D0EPCTL_MPS_MASK (0x3 << 0) -#define S3C_D0EPCTL_MPS_SHIFT (0) -#define S3C_D0EPCTL_MPS_64 (0x0 << 0) -#define S3C_D0EPCTL_MPS_32 (0x1 << 0) -#define S3C_D0EPCTL_MPS_16 (0x2 << 0) -#define S3C_D0EPCTL_MPS_8 (0x3 << 0) - -#define S3C_DxEPCTL_EPEna (1 << 31) -#define S3C_DxEPCTL_EPDis (1 << 30) -#define S3C_DxEPCTL_SetD1PID (1 << 29) -#define S3C_DxEPCTL_SetOddFr (1 << 29) -#define S3C_DxEPCTL_SetD0PID (1 << 28) -#define S3C_DxEPCTL_SetEvenFr (1 << 28) -#define S3C_DxEPCTL_SNAK (1 << 27) -#define S3C_DxEPCTL_CNAK (1 << 26) -#define S3C_DxEPCTL_TxFNum_MASK (0xf << 22) -#define S3C_DxEPCTL_TxFNum_SHIFT (22) -#define S3C_DxEPCTL_TxFNum_LIMIT (0xf) -#define S3C_DxEPCTL_TxFNum(_x) ((_x) << 22) - -#define S3C_DxEPCTL_Stall (1 << 21) -#define S3C_DxEPCTL_Snp (1 << 20) -#define S3C_DxEPCTL_EPType_MASK (0x3 << 18) -#define S3C_DxEPCTL_EPType_SHIFT (18) -#define S3C_DxEPCTL_EPType_Control (0x0 << 18) -#define S3C_DxEPCTL_EPType_Iso (0x1 << 18) -#define S3C_DxEPCTL_EPType_Bulk (0x2 << 18) -#define S3C_DxEPCTL_EPType_Intterupt (0x3 << 18) - -#define S3C_DxEPCTL_NAKsts (1 << 17) -#define S3C_DxEPCTL_DPID (1 << 16) -#define S3C_DxEPCTL_EOFrNum (1 << 16) -#define S3C_DxEPCTL_USBActEp (1 << 15) -#define S3C_DxEPCTL_NextEp_MASK (0xf << 11) -#define S3C_DxEPCTL_NextEp_SHIFT (11) -#define S3C_DxEPCTL_NextEp_LIMIT (0xf) -#define S3C_DxEPCTL_NextEp(_x) ((_x) << 11) - -#define S3C_DxEPCTL_MPS_MASK (0x7ff << 0) -#define S3C_DxEPCTL_MPS_SHIFT (0) -#define S3C_DxEPCTL_MPS_LIMIT (0x7ff) -#define S3C_DxEPCTL_MPS(_x) ((_x) << 0) - -#define S3C_DIEPINT(_a) S3C_HSOTG_REG(0x908 + ((_a) * 0x20)) -#define S3C_DOEPINT(_a) S3C_HSOTG_REG(0xB08 + ((_a) * 0x20)) - -#define S3C_DxEPINT_INEPNakEff (1 << 6) -#define S3C_DxEPINT_Back2BackSetup (1 << 6) -#define S3C_DxEPINT_INTknEPMis (1 << 5) -#define S3C_DxEPINT_INTknTXFEmp (1 << 4) -#define S3C_DxEPINT_OUTTknEPdis (1 << 4) -#define S3C_DxEPINT_Timeout (1 << 3) -#define S3C_DxEPINT_Setup (1 << 3) -#define S3C_DxEPINT_AHBErr (1 << 2) -#define S3C_DxEPINT_EPDisbld (1 << 1) -#define S3C_DxEPINT_XferCompl (1 << 0) - -#define S3C_DIEPTSIZ0 S3C_HSOTG_REG(0x910) - -#define S3C_DIEPTSIZ0_PktCnt_MASK (0x3 << 19) -#define S3C_DIEPTSIZ0_PktCnt_SHIFT (19) -#define S3C_DIEPTSIZ0_PktCnt_LIMIT (0x3) -#define S3C_DIEPTSIZ0_PktCnt(_x) ((_x) << 19) - -#define S3C_DIEPTSIZ0_XferSize_MASK (0x7f << 0) -#define S3C_DIEPTSIZ0_XferSize_SHIFT (0) -#define S3C_DIEPTSIZ0_XferSize_LIMIT (0x7f) -#define S3C_DIEPTSIZ0_XferSize(_x) ((_x) << 0) - - -#define DOEPTSIZ0 S3C_HSOTG_REG(0xB10) -#define S3C_DOEPTSIZ0_SUPCnt_MASK (0x3 << 29) -#define S3C_DOEPTSIZ0_SUPCnt_SHIFT (29) -#define S3C_DOEPTSIZ0_SUPCnt_LIMIT (0x3) -#define S3C_DOEPTSIZ0_SUPCnt(_x) ((_x) << 29) - -#define S3C_DOEPTSIZ0_PktCnt (1 << 19) -#define S3C_DOEPTSIZ0_XferSize_MASK (0x7f << 0) -#define S3C_DOEPTSIZ0_XferSize_SHIFT (0) - -#define S3C_DIEPTSIZ(_a) S3C_HSOTG_REG(0x910 + ((_a) * 0x20)) -#define S3C_DOEPTSIZ(_a) S3C_HSOTG_REG(0xB10 + ((_a) * 0x20)) - -#define S3C_DxEPTSIZ_MC_MASK (0x3 << 29) -#define S3C_DxEPTSIZ_MC_SHIFT (29) -#define S3C_DxEPTSIZ_MC_LIMIT (0x3) -#define S3C_DxEPTSIZ_MC(_x) ((_x) << 29) - -#define S3C_DxEPTSIZ_PktCnt_MASK (0x3ff << 19) -#define S3C_DxEPTSIZ_PktCnt_SHIFT (19) -#define S3C_DxEPTSIZ_PktCnt_GET(_v) (((_v) >> 19) & 0x3ff) -#define S3C_DxEPTSIZ_PktCnt_LIMIT (0x3ff) -#define S3C_DxEPTSIZ_PktCnt(_x) ((_x) << 19) - -#define S3C_DxEPTSIZ_XferSize_MASK (0x7ffff << 0) -#define S3C_DxEPTSIZ_XferSize_SHIFT (0) -#define S3C_DxEPTSIZ_XferSize_GET(_v) (((_v) >> 0) & 0x7ffff) -#define S3C_DxEPTSIZ_XferSize_LIMIT (0x7ffff) -#define S3C_DxEPTSIZ_XferSize(_x) ((_x) << 0) - - -#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)) - -#endif /* __PLAT_S3C64XX_REGS_USB_HSOTG_H */ diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 6c7945b4cad3..9c5c73aae4f4 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -361,7 +361,6 @@ struct dwc3_ep { dma_addr_t trb_pool_dma; u32 free_slot; u32 busy_slot; - const struct usb_endpoint_descriptor *desc; const struct usb_ss_ep_comp_descriptor *comp_desc; struct dwc3 *dwc; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 3584a169886f..3453ca1f7479 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -179,7 +179,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, int ret; spin_lock_irqsave(&dwc->lock, flags); - if (!dep->desc) { + if (!dep->endpoint.desc) { dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", request, dep->name); ret = -ESHUTDOWN; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 5255fe975ea1..561625a1284d 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -178,8 +178,8 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc) if (!(dep->flags & DWC3_EP_ENABLED)) continue; - if (usb_endpoint_xfer_bulk(dep->desc) - || usb_endpoint_xfer_isoc(dep->desc)) + if (usb_endpoint_xfer_bulk(dep->endpoint.desc) + || usb_endpoint_xfer_isoc(dep->endpoint.desc)) mult = 3; /* @@ -229,7 +229,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, * completed (not the LINK TRB). */ if (((dep->busy_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && - usb_endpoint_xfer_isoc(dep->desc)) + usb_endpoint_xfer_isoc(dep->endpoint.desc)) dep->busy_slot++; } list_del(&req->list); @@ -470,7 +470,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, if (ret) return ret; - dep->desc = desc; + dep->endpoint.desc = desc; dep->comp_desc = comp_desc; dep->type = usb_endpoint_type(desc); dep->flags |= DWC3_EP_ENABLED; @@ -533,7 +533,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); dep->stream_capable = false; - dep->desc = NULL; dep->endpoint.desc = NULL; dep->comp_desc = NULL; dep->type = 0; @@ -694,7 +693,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, /* Skip the LINK-TRB on ISOC */ if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && - usb_endpoint_xfer_isoc(dep->desc)) + usb_endpoint_xfer_isoc(dep->endpoint.desc)) return; if (!req->trb) { @@ -707,7 +706,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, trb->bpl = lower_32_bits(dma); trb->bph = upper_32_bits(dma); - switch (usb_endpoint_type(dep->desc)) { + switch (usb_endpoint_type(dep->endpoint.desc)) { case USB_ENDPOINT_XFER_CONTROL: trb->ctrl = DWC3_TRBCTL_CONTROL_SETUP; break; @@ -732,7 +731,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, BUG(); } - if (usb_endpoint_xfer_isoc(dep->desc)) { + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; trb->ctrl |= DWC3_TRB_CTRL_CSP; } else { @@ -743,7 +742,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, trb->ctrl |= DWC3_TRB_CTRL_LST; } - if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) + if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable) trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id); trb->ctrl |= DWC3_TRB_CTRL_HWO; @@ -771,7 +770,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK; /* Can't wrap around on a non-isoc EP since there's no link TRB */ - if (!usb_endpoint_xfer_isoc(dep->desc)) { + if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) { max = DWC3_TRB_NUM - (dep->free_slot & DWC3_TRB_MASK); if (trbs_left > max) trbs_left = max; @@ -797,7 +796,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) * processed from the first TRB until the last one. Since we * don't wrap around we have to start at the beginning. */ - if (usb_endpoint_xfer_isoc(dep->desc)) { + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dep->busy_slot = 1; dep->free_slot = 1; } else { @@ -807,7 +806,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) } /* The last TRB is a link TRB, not used for xfer */ - if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->desc)) + if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->endpoint.desc)) return; list_for_each_entry_safe(req, n, &dep->request_list, list) { @@ -984,7 +983,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) int start_trans; start_trans = 1; - if (usb_endpoint_xfer_isoc(dep->desc) && + if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && (dep->flags & DWC3_EP_BUSY)) start_trans = 0; @@ -1011,7 +1010,7 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, int ret; - if (!dep->desc) { + if (!dep->endpoint.desc) { dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", request, ep->name); return -ESHUTDOWN; @@ -1125,7 +1124,7 @@ static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value) spin_lock_irqsave(&dwc->lock, flags); - if (usb_endpoint_xfer_isoc(dep->desc)) { + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name); ret = -EINVAL; goto out; @@ -1681,7 +1680,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, case DWC3_DEPEVT_XFERCOMPLETE: dep->res_trans_idx = 0; - if (usb_endpoint_xfer_isoc(dep->desc)) { + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dev_dbg(dwc->dev, "%s is an Isochronous endpoint\n", dep->name); return; @@ -1690,7 +1689,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, dwc3_endpoint_transfer_complete(dwc, dep, event, 1); break; case DWC3_DEPEVT_XFERINPROGRESS: - if (!usb_endpoint_xfer_isoc(dep->desc)) { + if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dev_dbg(dwc->dev, "%s is not an Isochronous endpoint\n", dep->name); return; @@ -1699,7 +1698,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, dwc3_endpoint_transfer_complete(dwc, dep, event, 0); break; case DWC3_DEPEVT_XFERNOTREADY: - if (usb_endpoint_xfer_isoc(dep->desc)) { + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dwc3_gadget_start_isoc(dwc, dep, event); } else { int ret; @@ -1720,7 +1719,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, break; case DWC3_DEPEVT_STREAMEVT: - if (!usb_endpoint_xfer_bulk(dep->desc)) { + if (!usb_endpoint_xfer_bulk(dep->endpoint.desc)) { dev_err(dwc->dev, "Stream event for non-Bulk %s\n", dep->name); return; diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 827697271316..fb883e1405bc 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -172,7 +172,7 @@ config USB_FSL_USB2 select USB_GADGET_DUALSPEED select USB_FSL_MPH_DR_OF if OF help - Some of Freescale PowerPC processors have a High Speed + Some of Freescale PowerPC and i.MX processors have a High Speed Dual-Role(DR) USB controller, which supports device mode. The number of programmable endpoints is different through diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 77779271f487..187d21181cd5 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -333,7 +333,7 @@ udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc) return -ESHUTDOWN; spin_lock_irqsave(&dev->lock, iflags); - ep->desc = desc; + ep->ep.desc = desc; ep->halted = 0; @@ -442,7 +442,6 @@ static void ep_init(struct udc_regs __iomem *regs, struct udc_ep *ep) u32 tmp; VDBG(ep->dev, "ep-%d reset\n", ep->num); - ep->desc = NULL; ep->ep.desc = NULL; ep->ep.ops = &udc_ep_ops; INIT_LIST_HEAD(&ep->queue); @@ -489,7 +488,7 @@ static int udc_ep_disable(struct usb_ep *usbep) return -EINVAL; ep = container_of(usbep, struct udc_ep, ep); - if (usbep->name == ep0_string || !ep->desc) + if (usbep->name == ep0_string || !ep->ep.desc) return -EINVAL; DBG(ep->dev, "Disable ep-%d\n", ep->num); @@ -1066,7 +1065,7 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp) return -EINVAL; ep = container_of(usbep, struct udc_ep, ep); - if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX)) + if (!ep->ep.desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX)) return -EINVAL; VDBG(ep->dev, "udc_queue(): ep%d-in=%d\n", ep->num, ep->in); @@ -1257,7 +1256,7 @@ static int udc_dequeue(struct usb_ep *usbep, struct usb_request *usbreq) unsigned long iflags; ep = container_of(usbep, struct udc_ep, ep); - if (!usbep || !usbreq || (!ep->desc && (ep->num != 0 + if (!usbep || !usbreq || (!ep->ep.desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))) return -EINVAL; @@ -1317,7 +1316,7 @@ udc_set_halt(struct usb_ep *usbep, int halt) pr_debug("set_halt %s: halt=%d\n", usbep->name, halt); ep = container_of(usbep, struct udc_ep, ep); - if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX)) + if (!ep->ep.desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX)) return -EINVAL; if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN) return -ESHUTDOWN; @@ -1539,7 +1538,7 @@ static void udc_setup_endpoints(struct udc *dev) * disabling ep interrupts when ENUM interrupt occurs but ep is * not enabled by gadget driver */ - if (!ep->desc) + if (!ep->ep.desc) ep_init(dev->regs, ep); if (use_dma) { @@ -3402,19 +3401,7 @@ static struct pci_driver udc_pci_driver = { .remove = udc_pci_remove, }; -/* Inits driver */ -static int __init init(void) -{ - return pci_register_driver(&udc_pci_driver); -} -module_init(init); - -/* Cleans driver */ -static void __exit cleanup(void) -{ - pci_unregister_driver(&udc_pci_driver); -} -module_exit(cleanup); +module_pci_driver(udc_pci_driver); MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION); MODULE_AUTHOR("Thomas Dahlmann"); diff --git a/drivers/usb/gadget/amd5536udc.h b/drivers/usb/gadget/amd5536udc.h index f87e29c65325..14af87d65caa 100644 --- a/drivers/usb/gadget/amd5536udc.h +++ b/drivers/usb/gadget/amd5536udc.h @@ -512,7 +512,6 @@ struct udc_ep { /* queue for requests */ struct list_head queue; - const struct usb_endpoint_descriptor *desc; unsigned halted; unsigned cancel_transfer; unsigned num : 5, diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 9d7bcd910074..43943aa965dc 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -212,7 +212,7 @@ static int proc_udc_show(struct seq_file *s, void *unused) if (udc->enabled && udc->vbus) { proc_ep_show(s, &udc->ep[0]); list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) { - if (ep->desc) + if (ep->ep.desc) proc_ep_show(s, ep); } } @@ -530,7 +530,7 @@ ok: tmp |= AT91_UDP_EPEDS; __raw_writel(tmp, ep->creg); - ep->desc = desc; + ep->ep.desc = desc; ep->ep.maxpacket = maxpacket; /* @@ -558,7 +558,6 @@ static int at91_ep_disable (struct usb_ep * _ep) nuke(ep, -ESHUTDOWN); /* restore the endpoint's pristine config */ - ep->desc = NULL; ep->ep.desc = NULL; ep->ep.maxpacket = ep->maxpacket; @@ -618,7 +617,7 @@ static int at91_ep_queue(struct usb_ep *_ep, return -EINVAL; } - if (!_ep || (!ep->desc && ep->ep.name != ep0name)) { + if (!_ep || (!ep->ep.desc && ep->ep.name != ep0name)) { DBG("invalid ep\n"); return -EINVAL; } @@ -833,7 +832,7 @@ static void udc_reinit(struct at91_udc *udc) if (i != 0) list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); - ep->desc = NULL; + ep->ep.desc = NULL; ep->stopped = 0; ep->fifo_bank = 0; ep->ep.maxpacket = ep->maxpacket; @@ -978,18 +977,18 @@ static int at91_set_selfpowered(struct usb_gadget *gadget, int is_on) return 0; } -static int at91_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); -static int at91_stop(struct usb_gadget_driver *driver); - +static int at91_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); +static int at91_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); static const struct usb_gadget_ops at91_udc_ops = { .get_frame = at91_get_frame, .wakeup = at91_wakeup, .set_selfpowered = at91_set_selfpowered, .vbus_session = at91_vbus_session, .pullup = at91_pullup, - .start = at91_start, - .stop = at91_stop, + .udc_start = at91_start, + .udc_stop = at91_stop, /* * VBUS-powered devices may also also want to support bigger @@ -1172,7 +1171,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr) | USB_REQ_GET_STATUS: tmp = w_index & USB_ENDPOINT_NUMBER_MASK; ep = &udc->ep[tmp]; - if (tmp >= NUM_ENDPOINTS || (tmp && !ep->desc)) + if (tmp >= NUM_ENDPOINTS || (tmp && !ep->ep.desc)) goto stall; if (tmp) { @@ -1197,7 +1196,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr) ep = &udc->ep[tmp]; if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS) goto stall; - if (!ep->desc || ep->is_iso) + if (!ep->ep.desc || ep->is_iso) goto stall; if ((w_index & USB_DIR_IN)) { if (!ep->is_in) @@ -1218,7 +1217,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr) goto stall; if (tmp == 0) goto succeed; - if (!ep->desc || ep->is_iso) + if (!ep->ep.desc || ep->is_iso) goto stall; if ((w_index & USB_DIR_IN)) { if (!ep->is_in) @@ -1627,66 +1626,34 @@ static void at91_vbus_timer(unsigned long data) schedule_work(&udc->vbus_timer_work); } -static int at91_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) +static int at91_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct at91_udc *udc = &controller; - int retval; - unsigned long flags; - - if (!driver - || driver->max_speed < USB_SPEED_FULL - || !bind - || !driver->setup) { - DBG("bad parameter.\n"); - return -EINVAL; - } - - if (udc->driver) { - DBG("UDC already has a gadget driver\n"); - return -EBUSY; - } + struct at91_udc *udc; + udc = container_of(gadget, struct at91_udc, gadget); udc->driver = driver; udc->gadget.dev.driver = &driver->driver; dev_set_drvdata(&udc->gadget.dev, &driver->driver); udc->enabled = 1; udc->selfpowered = 1; - retval = bind(&udc->gadget); - if (retval) { - DBG("bind() returned %d\n", retval); - udc->driver = NULL; - udc->gadget.dev.driver = NULL; - dev_set_drvdata(&udc->gadget.dev, NULL); - udc->enabled = 0; - udc->selfpowered = 0; - return retval; - } - - spin_lock_irqsave(&udc->lock, flags); - pullup(udc, 1); - spin_unlock_irqrestore(&udc->lock, flags); - DBG("bound to %s\n", driver->driver.name); return 0; } -static int at91_stop(struct usb_gadget_driver *driver) +static int at91_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct at91_udc *udc = &controller; + struct at91_udc *udc; unsigned long flags; - if (!driver || driver != udc->driver || !driver->unbind) - return -EINVAL; - + udc = container_of(gadget, struct at91_udc, gadget); spin_lock_irqsave(&udc->lock, flags); udc->enabled = 0; at91_udp_write(udc, AT91_UDP_IDR, ~0); - pullup(udc, 0); spin_unlock_irqrestore(&udc->lock, flags); - driver->unbind(&udc->gadget); udc->gadget.dev.driver = NULL; dev_set_drvdata(&udc->gadget.dev, NULL); udc->driver = NULL; diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h index 3c0315b86ace..e647d1c2ada4 100644 --- a/drivers/usb/gadget/at91_udc.h +++ b/drivers/usb/gadget/at91_udc.h @@ -105,9 +105,6 @@ struct at91_ep { unsigned is_in:1; unsigned is_iso:1; unsigned fifo_bank:1; - - const struct usb_endpoint_descriptor - *desc; }; /* diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 9f98508966d1..e23bf7984aaf 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -599,13 +599,13 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) spin_lock_irqsave(&ep->udc->lock, flags); - if (ep->desc) { + if (ep->ep.desc) { spin_unlock_irqrestore(&ep->udc->lock, flags); DBG(DBG_ERR, "ep%d already enabled\n", ep->index); return -EBUSY; } - ep->desc = desc; + ep->ep.desc = desc; ep->ep.maxpacket = maxpacket; usba_ep_writel(ep, CFG, ept_cfg); @@ -647,7 +647,7 @@ static int usba_ep_disable(struct usb_ep *_ep) spin_lock_irqsave(&udc->lock, flags); - if (!ep->desc) { + if (!ep->ep.desc) { spin_unlock_irqrestore(&udc->lock, flags); /* REVISIT because this driver disables endpoints in * reset_all_endpoints() before calling disconnect(), @@ -658,7 +658,6 @@ static int usba_ep_disable(struct usb_ep *_ep) ep->ep.name); return -EINVAL; } - ep->desc = NULL; ep->ep.desc = NULL; list_splice_init(&ep->queue, &req_list); @@ -752,7 +751,7 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep, */ ret = -ESHUTDOWN; spin_lock_irqsave(&udc->lock, flags); - if (ep->desc) { + if (ep->ep.desc) { if (list_empty(&ep->queue)) submit_request(ep, req); @@ -776,7 +775,8 @@ usba_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) DBG(DBG_GADGET | DBG_QUEUE | DBG_REQ, "%s: queue req %p, len %u\n", ep->ep.name, req, _req->length); - if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN || !ep->desc) + if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN || + !ep->ep.desc) return -ESHUTDOWN; req->submitted = 0; @@ -792,7 +792,7 @@ usba_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) /* May have received a reset since last time we checked */ ret = -ESHUTDOWN; spin_lock_irqsave(&udc->lock, flags); - if (ep->desc) { + if (ep->ep.desc) { list_add_tail(&req->queue, &ep->queue); if ((!ep_is_control(ep) && ep->is_in) || @@ -905,7 +905,7 @@ static int usba_ep_set_halt(struct usb_ep *_ep, int value) DBG(DBG_GADGET, "endpoint %s: %s HALT\n", ep->ep.name, value ? "set" : "clear"); - if (!ep->desc) { + if (!ep->ep.desc) { DBG(DBG_ERR, "Attempted to halt uninitialized ep %s\n", ep->ep.name); return -ENODEV; @@ -1008,16 +1008,16 @@ usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered) return 0; } -static int atmel_usba_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); -static int atmel_usba_stop(struct usb_gadget_driver *driver); - +static int atmel_usba_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); +static int atmel_usba_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); static const struct usb_gadget_ops usba_udc_ops = { .get_frame = usba_udc_get_frame, .wakeup = usba_udc_wakeup, .set_selfpowered = usba_udc_set_selfpowered, - .start = atmel_usba_start, - .stop = atmel_usba_stop, + .udc_start = atmel_usba_start, + .udc_stop = atmel_usba_stop, }; static struct usb_endpoint_descriptor usba_ep0_desc = { @@ -1071,7 +1071,7 @@ static void reset_all_endpoints(struct usba_udc *udc) * FIXME remove this code ... and retest thoroughly. */ list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { - if (ep->desc) { + if (ep->ep.desc) { spin_unlock(&udc->lock); usba_ep_disable(&ep->ep); spin_lock(&udc->lock); @@ -1089,9 +1089,9 @@ static struct usba_ep *get_ep_by_addr(struct usba_udc *udc, u16 wIndex) list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) { u8 bEndpointAddress; - if (!ep->desc) + if (!ep->ep.desc) continue; - bEndpointAddress = ep->desc->bEndpointAddress; + bEndpointAddress = ep->ep.desc->bEndpointAddress; if ((wIndex ^ bEndpointAddress) & USB_DIR_IN) continue; if ((bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) @@ -1727,7 +1727,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) usb_speed_string(udc->gadget.speed)); ep0 = &usba_ep[0]; - ep0->desc = &usba_ep0_desc; + ep0->ep.desc = &usba_ep0_desc; ep0->state = WAIT_FOR_SETUP; usba_ep_writel(ep0, CFG, (USBA_BF(EPT_SIZE, EP0_EPT_SIZE) @@ -1795,21 +1795,13 @@ out: return IRQ_HANDLED; } -static int atmel_usba_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) +static int atmel_usba_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct usba_udc *udc = &the_udc; + struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget); unsigned long flags; - int ret; - - if (!udc->pdev) - return -ENODEV; spin_lock_irqsave(&udc->lock, flags); - if (udc->driver) { - spin_unlock_irqrestore(&udc->lock, flags); - return -EBUSY; - } udc->devstatus = 1 << USB_DEVICE_SELF_POWERED; udc->driver = driver; @@ -1819,13 +1811,6 @@ static int atmel_usba_start(struct usb_gadget_driver *driver, clk_enable(udc->pclk); clk_enable(udc->hclk); - ret = bind(&udc->gadget); - if (ret) { - DBG(DBG_ERR, "Could not bind to driver %s: error %d\n", - driver->driver.name, ret); - goto err_driver_bind; - } - DBG(DBG_GADGET, "registered driver `%s'\n", driver->driver.name); udc->vbus_prev = 0; @@ -1842,23 +1827,14 @@ static int atmel_usba_start(struct usb_gadget_driver *driver, spin_unlock_irqrestore(&udc->lock, flags); return 0; - -err_driver_bind: - udc->driver = NULL; - udc->gadget.dev.driver = NULL; - return ret; } -static int atmel_usba_stop(struct usb_gadget_driver *driver) +static int atmel_usba_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct usba_udc *udc = &the_udc; + struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget); unsigned long flags; - if (!udc->pdev) - return -ENODEV; - if (driver != udc->driver || !driver->unbind) - return -EINVAL; - if (gpio_is_valid(udc->vbus_pin)) disable_irq(gpio_to_irq(udc->vbus_pin)); @@ -1871,10 +1847,6 @@ static int atmel_usba_stop(struct usb_gadget_driver *driver) toggle_bias(0); usba_writel(udc, CTRL, USBA_DISABLE_MASK); - if (udc->driver->disconnect) - udc->driver->disconnect(&udc->gadget); - - driver->unbind(&udc->gadget); udc->gadget.dev.driver = NULL; udc->driver = NULL; diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h index 88a2e07a11a8..9791259cbda7 100644 --- a/drivers/usb/gadget/atmel_usba_udc.h +++ b/drivers/usb/gadget/atmel_usba_udc.h @@ -280,7 +280,6 @@ struct usba_ep { struct usba_udc *udc; struct list_head queue; - const struct usb_endpoint_descriptor *desc; u16 fifo_size; u8 nr_banks; diff --git a/drivers/usb/gadget/ci13xxx_pci.c b/drivers/usb/gadget/ci13xxx_pci.c index 883ab5e832d1..63ef96c04bb7 100644 --- a/drivers/usb/gadget/ci13xxx_pci.c +++ b/drivers/usb/gadget/ci13xxx_pci.c @@ -148,27 +148,7 @@ static struct pci_driver ci13xxx_pci_driver = { .remove = __devexit_p(ci13xxx_pci_remove), }; -/** - * ci13xxx_pci_init: module init - * - * Driver load - */ -static int __init ci13xxx_pci_init(void) -{ - return pci_register_driver(&ci13xxx_pci_driver); -} -module_init(ci13xxx_pci_init); - -/** - * ci13xxx_pci_exit: module exit - * - * Driver unload - */ -static void __exit ci13xxx_pci_exit(void) -{ - pci_unregister_driver(&ci13xxx_pci_driver); -} -module_exit(ci13xxx_pci_exit); +module_pci_driver(ci13xxx_pci_driver); MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>"); MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller"); diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 3ebc036b1934..1a44bf9c374f 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -1916,7 +1916,7 @@ __acquires(udc->lock) int type, num, dir, err = -EINVAL; struct usb_ctrlrequest req; - if (mEp->desc == NULL) + if (mEp->ep.desc == NULL) continue; /* not configured */ if (hw_test_and_clear_complete(i)) { @@ -2112,7 +2112,7 @@ static int ep_enable(struct usb_ep *ep, /* only internal SW should enable ctrl endpts */ - mEp->desc = desc; + mEp->ep.desc = desc; if (!list_empty(&mEp->qh.queue)) warn("enabling a non-empty endpoint!"); @@ -2164,7 +2164,7 @@ static int ep_disable(struct usb_ep *ep) if (ep == NULL) return -EINVAL; - else if (mEp->desc == NULL) + else if (mEp->ep.desc == NULL) return -EBUSY; spin_lock_irqsave(mEp->lock, flags); @@ -2183,7 +2183,6 @@ static int ep_disable(struct usb_ep *ep) } while (mEp->dir != direction); - mEp->desc = NULL; mEp->ep.desc = NULL; spin_unlock_irqrestore(mEp->lock, flags); @@ -2272,7 +2271,7 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, trace("%p, %p, %X", ep, req, gfp_flags); - if (ep == NULL || req == NULL || mEp->desc == NULL) + if (ep == NULL || req == NULL || mEp->ep.desc == NULL) return -EINVAL; spin_lock_irqsave(mEp->lock, flags); @@ -2335,7 +2334,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) trace("%p, %p", ep, req); if (ep == NULL || req == NULL || mReq->req.status != -EALREADY || - mEp->desc == NULL || list_empty(&mReq->queue) || + mEp->ep.desc == NULL || list_empty(&mReq->queue) || list_empty(&mEp->qh.queue)) return -EINVAL; @@ -2378,7 +2377,7 @@ static int ep_set_halt(struct usb_ep *ep, int value) trace("%p, %i", ep, value); - if (ep == NULL || mEp->desc == NULL) + if (ep == NULL || mEp->ep.desc == NULL) return -EINVAL; spin_lock_irqsave(mEp->lock, flags); @@ -2421,7 +2420,7 @@ static int ep_set_wedge(struct usb_ep *ep) trace("%p", ep); - if (ep == NULL || mEp->desc == NULL) + if (ep == NULL || mEp->ep.desc == NULL) return -EINVAL; spin_lock_irqsave(mEp->lock, flags); diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h index c4cec6a43d5e..6490cf872adb 100644 --- a/drivers/usb/gadget/ci13xxx_udc.h +++ b/drivers/usb/gadget/ci13xxx_udc.h @@ -82,7 +82,6 @@ struct ci13xxx_req { /* Extension of usb_ep */ struct ci13xxx_ep { struct usb_ep ep; - const struct usb_endpoint_descriptor *desc; u8 dir; u8 num; u8 type; diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index baaebf2830fc..a3b19fe37f53 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -737,6 +737,19 @@ int usb_add_config(struct usb_composite_dev *cdev, status = bind(config); if (status < 0) { + while (!list_empty(&config->functions)) { + struct usb_function *f; + + f = list_first_entry(&config->functions, + struct usb_function, list); + list_del(&f->list); + if (f->unbind) { + DBG(cdev, "unbind function '%s'/%p\n", + f->name, f); + f->unbind(config, f); + /* may free memory for "f" */ + } + } list_del(&config->list); config->cdev = NULL; } else { @@ -785,7 +798,7 @@ done: static void collect_langs(struct usb_gadget_strings **sp, __le16 *buf) { const struct usb_gadget_strings *s; - u16 language; + __le16 language; __le16 *tmp; while (*sp) { diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 170cbe89d9f8..83bb2e3fa861 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -595,14 +595,12 @@ static struct usb_request *dummy_alloc_request(struct usb_ep *_ep, static void dummy_free_request(struct usb_ep *_ep, struct usb_request *_req) { - struct dummy_ep *ep; struct dummy_request *req; - if (!_ep || !_req) - return; - ep = usb_ep_to_dummy_ep(_ep); - if (!ep->desc && _ep->name != ep0name) + if (!_ep || !_req) { + __WARN(); return; + } req = usb_request_to_dummy_request(_req); WARN_ON(!list_empty(&req->queue)); diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index f52cb1ae45d9..1d4c535671a7 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -1473,8 +1473,22 @@ static int functionfs_bind_config(struct usb_composite_dev *cdev, static void ffs_func_free(struct ffs_function *func) { + struct ffs_ep *ep = func->eps; + unsigned count = func->ffs->eps_count; + unsigned long flags; + ENTER(); + /* cleanup after autoconfig */ + spin_lock_irqsave(&func->ffs->eps_lock, flags); + do { + if (ep->ep && ep->req) + usb_ep_free_request(ep->ep, ep->req); + ep->req = NULL; + ++ep; + } while (--count); + spin_unlock_irqrestore(&func->ffs->eps_lock, flags); + ffs_data_put(func->ffs); kfree(func->eps); diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index 2c0cd824c667..7275706caeb0 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -286,7 +286,7 @@ static void disable_loopback(struct f_loopback *loop) struct usb_composite_dev *cdev; cdev = loop->function.config->cdev; - disable_endpoints(cdev, loop->in_ep, loop->out_ep); + disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL); VDBG(cdev, "%s disabled\n", loop->function.name); } @@ -329,7 +329,7 @@ fail0: * than 'buflen' bytes each. */ for (i = 0; i < qlen && result == 0; i++) { - req = alloc_ep_req(ep); + req = alloc_ep_req(ep, 0); if (req) { req->complete = loopback_complete; result = usb_ep_queue(ep, req, GFP_ATOMIC); diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index cb8c162cae5a..f67b453740bd 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -3110,13 +3110,6 @@ static int fsg_bind_config(struct usb_composite_dev *cdev, return rc; } -static inline int __deprecated __maybe_unused -fsg_add(struct usb_composite_dev *cdev, struct usb_configuration *c, - struct fsg_common *common) -{ - return fsg_bind_config(cdev, c, common); -} - /************************* Module parameters *************************/ diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index 7aa7ac82c02c..5c1b68b63c98 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -51,6 +51,9 @@ struct f_sourcesink { struct usb_ep *in_ep; struct usb_ep *out_ep; + struct usb_ep *iso_in_ep; + struct usb_ep *iso_out_ep; + int cur_alt; }; static inline struct f_sourcesink *func_to_ss(struct usb_function *f) @@ -59,18 +62,45 @@ static inline struct f_sourcesink *func_to_ss(struct usb_function *f) } static unsigned pattern; -module_param(pattern, uint, 0); -MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 "); +module_param(pattern, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63, 2 = none"); + +static unsigned isoc_interval = 4; +module_param(isoc_interval, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(isoc_interval, "1 - 16"); + +static unsigned isoc_maxpacket = 1024; +module_param(isoc_maxpacket, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(isoc_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)"); + +static unsigned isoc_mult; +module_param(isoc_mult, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(isoc_mult, "0 - 2 (hs/ss only)"); + +static unsigned isoc_maxburst; +module_param(isoc_maxburst, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(isoc_maxburst, "0 - 15 (ss only)"); /*-------------------------------------------------------------------------*/ -static struct usb_interface_descriptor source_sink_intf = { - .bLength = sizeof source_sink_intf, +static struct usb_interface_descriptor source_sink_intf_alt0 = { + .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, + .bAlternateSetting = 0, .bNumEndpoints = 2, .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - /* .iInterface = DYNAMIC */ + /* .iInterface = DYNAMIC */ +}; + +static struct usb_interface_descriptor source_sink_intf_alt1 = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + + .bAlternateSetting = 1, + .bNumEndpoints = 4, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + /* .iInterface = DYNAMIC */ }; /* full speed support: */ @@ -91,10 +121,36 @@ static struct usb_endpoint_descriptor fs_sink_desc = { .bmAttributes = USB_ENDPOINT_XFER_BULK, }; +static struct usb_endpoint_descriptor fs_iso_source_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1023), + .bInterval = 4, +}; + +static struct usb_endpoint_descriptor fs_iso_sink_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1023), + .bInterval = 4, +}; + static struct usb_descriptor_header *fs_source_sink_descs[] = { - (struct usb_descriptor_header *) &source_sink_intf, + (struct usb_descriptor_header *) &source_sink_intf_alt0, (struct usb_descriptor_header *) &fs_sink_desc, (struct usb_descriptor_header *) &fs_source_desc, + (struct usb_descriptor_header *) &source_sink_intf_alt1, +#define FS_ALT_IFC_1_OFFSET 3 + (struct usb_descriptor_header *) &fs_sink_desc, + (struct usb_descriptor_header *) &fs_source_desc, + (struct usb_descriptor_header *) &fs_iso_sink_desc, + (struct usb_descriptor_header *) &fs_iso_source_desc, NULL, }; @@ -116,10 +172,34 @@ static struct usb_endpoint_descriptor hs_sink_desc = { .wMaxPacketSize = cpu_to_le16(512), }; +static struct usb_endpoint_descriptor hs_iso_source_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1024), + .bInterval = 4, +}; + +static struct usb_endpoint_descriptor hs_iso_sink_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1024), + .bInterval = 4, +}; + static struct usb_descriptor_header *hs_source_sink_descs[] = { - (struct usb_descriptor_header *) &source_sink_intf, + (struct usb_descriptor_header *) &source_sink_intf_alt0, (struct usb_descriptor_header *) &hs_source_desc, (struct usb_descriptor_header *) &hs_sink_desc, + (struct usb_descriptor_header *) &source_sink_intf_alt1, +#define HS_ALT_IFC_1_OFFSET 3 + (struct usb_descriptor_header *) &hs_source_desc, + (struct usb_descriptor_header *) &hs_sink_desc, + (struct usb_descriptor_header *) &hs_iso_source_desc, + (struct usb_descriptor_header *) &hs_iso_sink_desc, NULL, }; @@ -136,6 +216,7 @@ static struct usb_endpoint_descriptor ss_source_desc = { struct usb_ss_ep_comp_descriptor ss_source_comp_desc = { .bLength = USB_DT_SS_EP_COMP_SIZE, .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bMaxBurst = 0, .bmAttributes = 0, .wBytesPerInterval = 0, @@ -152,17 +233,64 @@ static struct usb_endpoint_descriptor ss_sink_desc = { struct usb_ss_ep_comp_descriptor ss_sink_comp_desc = { .bLength = USB_DT_SS_EP_COMP_SIZE, .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bMaxBurst = 0, .bmAttributes = 0, .wBytesPerInterval = 0, }; +static struct usb_endpoint_descriptor ss_iso_source_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1024), + .bInterval = 4, +}; + +struct usb_ss_ep_comp_descriptor ss_iso_source_comp_desc = { + .bLength = USB_DT_SS_EP_COMP_SIZE, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + .bMaxBurst = 0, + .bmAttributes = 0, + .wBytesPerInterval = cpu_to_le16(1024), +}; + +static struct usb_endpoint_descriptor ss_iso_sink_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1024), + .bInterval = 4, +}; + +struct usb_ss_ep_comp_descriptor ss_iso_sink_comp_desc = { + .bLength = USB_DT_SS_EP_COMP_SIZE, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + .bMaxBurst = 0, + .bmAttributes = 0, + .wBytesPerInterval = cpu_to_le16(1024), +}; + static struct usb_descriptor_header *ss_source_sink_descs[] = { - (struct usb_descriptor_header *) &source_sink_intf, + (struct usb_descriptor_header *) &source_sink_intf_alt0, (struct usb_descriptor_header *) &ss_source_desc, (struct usb_descriptor_header *) &ss_source_comp_desc, (struct usb_descriptor_header *) &ss_sink_desc, (struct usb_descriptor_header *) &ss_sink_comp_desc, + (struct usb_descriptor_header *) &source_sink_intf_alt1, +#define SS_ALT_IFC_1_OFFSET 5 + (struct usb_descriptor_header *) &ss_source_desc, + (struct usb_descriptor_header *) &ss_source_comp_desc, + (struct usb_descriptor_header *) &ss_sink_desc, + (struct usb_descriptor_header *) &ss_sink_comp_desc, + (struct usb_descriptor_header *) &ss_iso_source_desc, + (struct usb_descriptor_header *) &ss_iso_source_comp_desc, + (struct usb_descriptor_header *) &ss_iso_sink_desc, + (struct usb_descriptor_header *) &ss_iso_sink_comp_desc, NULL, }; @@ -196,9 +324,10 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f) id = usb_interface_id(c, f); if (id < 0) return id; - source_sink_intf.bInterfaceNumber = id; + source_sink_intf_alt0.bInterfaceNumber = id; + source_sink_intf_alt1.bInterfaceNumber = id; - /* allocate endpoints */ + /* allocate bulk endpoints */ ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc); if (!ss->in_ep) { autoconf_fail: @@ -213,12 +342,74 @@ autoconf_fail: goto autoconf_fail; ss->out_ep->driver_data = cdev; /* claim */ + /* sanity check the isoc module parameters */ + if (isoc_interval < 1) + isoc_interval = 1; + if (isoc_interval > 16) + isoc_interval = 16; + if (isoc_mult > 2) + isoc_mult = 2; + if (isoc_maxburst > 15) + isoc_maxburst = 15; + + /* fill in the FS isoc descriptors from the module parameters */ + fs_iso_source_desc.wMaxPacketSize = isoc_maxpacket > 1023 ? + 1023 : isoc_maxpacket; + fs_iso_source_desc.bInterval = isoc_interval; + fs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket > 1023 ? + 1023 : isoc_maxpacket; + fs_iso_sink_desc.bInterval = isoc_interval; + + /* allocate iso endpoints */ + ss->iso_in_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_source_desc); + if (!ss->iso_in_ep) + goto no_iso; + ss->iso_in_ep->driver_data = cdev; /* claim */ + + ss->iso_out_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_sink_desc); + if (ss->iso_out_ep) { + ss->iso_out_ep->driver_data = cdev; /* claim */ + } else { + ss->iso_in_ep->driver_data = NULL; + ss->iso_in_ep = NULL; +no_iso: + /* + * We still want to work even if the UDC doesn't have isoc + * endpoints, so null out the alt interface that contains + * them and continue. + */ + fs_source_sink_descs[FS_ALT_IFC_1_OFFSET] = NULL; + hs_source_sink_descs[HS_ALT_IFC_1_OFFSET] = NULL; + ss_source_sink_descs[SS_ALT_IFC_1_OFFSET] = NULL; + } + + if (isoc_maxpacket > 1024) + isoc_maxpacket = 1024; + /* support high speed hardware */ if (gadget_is_dualspeed(c->cdev->gadget)) { hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; + + /* + * Fill in the HS isoc descriptors from the module parameters. + * We assume that the user knows what they are doing and won't + * give parameters that their UDC doesn't support. + */ + hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket; + hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11; + hs_iso_source_desc.bInterval = isoc_interval; + hs_iso_source_desc.bEndpointAddress = + fs_iso_source_desc.bEndpointAddress; + + hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket; + hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11; + hs_iso_sink_desc.bInterval = isoc_interval; + hs_iso_sink_desc.bEndpointAddress = + fs_iso_sink_desc.bEndpointAddress; + f->hs_descriptors = hs_source_sink_descs; } @@ -228,13 +419,39 @@ autoconf_fail: fs_source_desc.bEndpointAddress; ss_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; + + /* + * Fill in the SS isoc descriptors from the module parameters. + * We assume that the user knows what they are doing and won't + * give parameters that their UDC doesn't support. + */ + ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket; + ss_iso_source_desc.bInterval = isoc_interval; + ss_iso_source_comp_desc.bmAttributes = isoc_mult; + ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst; + ss_iso_source_comp_desc.wBytesPerInterval = + isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1); + ss_iso_source_desc.bEndpointAddress = + fs_iso_source_desc.bEndpointAddress; + + ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket; + ss_iso_sink_desc.bInterval = isoc_interval; + ss_iso_sink_comp_desc.bmAttributes = isoc_mult; + ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst; + ss_iso_sink_comp_desc.wBytesPerInterval = + isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1); + ss_iso_sink_desc.bEndpointAddress = + fs_iso_sink_desc.bEndpointAddress; + f->ss_descriptors = ss_source_sink_descs; } - DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", + DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s\n", (gadget_is_superspeed(c->cdev->gadget) ? "super" : (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")), - f->name, ss->in_ep->name, ss->out_ep->name); + f->name, ss->in_ep->name, ss->out_ep->name, + ss->iso_in_ep ? ss->iso_in_ep->name : "<none>", + ss->iso_out_ep ? ss->iso_out_ep->name : "<none>"); return 0; } @@ -251,6 +468,9 @@ static int check_read_data(struct f_sourcesink *ss, struct usb_request *req) u8 *buf = req->buf; struct usb_composite_dev *cdev = ss->function.config->cdev; + if (pattern == 2) + return 0; + for (i = 0; i < req->actual; i++, buf++) { switch (pattern) { @@ -265,7 +485,7 @@ static int check_read_data(struct f_sourcesink *ss, struct usb_request *req) * each usb transfer request should be. Resync is done * with set_interface or set_config. (We *WANT* it to * get quickly out of sync if controllers or their drivers - * stutter for any reason, including buffer duplcation...) + * stutter for any reason, including buffer duplication...) */ case 1: if (*buf == (u8)(i % 63)) @@ -292,21 +512,30 @@ static void reinit_write_data(struct usb_ep *ep, struct usb_request *req) for (i = 0; i < req->length; i++) *buf++ = (u8) (i % 63); break; + case 2: + break; } } static void source_sink_complete(struct usb_ep *ep, struct usb_request *req) { - struct f_sourcesink *ss = ep->driver_data; - struct usb_composite_dev *cdev = ss->function.config->cdev; - int status = req->status; + struct usb_composite_dev *cdev; + struct f_sourcesink *ss = ep->driver_data; + int status = req->status; + + /* driver_data will be null if ep has been disabled */ + if (!ss) + return; + + cdev = ss->function.config->cdev; switch (status) { case 0: /* normal completion? */ if (ep == ss->out_ep) { check_read_data(ss, req); - memset(req->buf, 0x55, req->length); + if (pattern != 2) + memset(req->buf, 0x55, req->length); } else reinit_write_data(ep, req); break; @@ -344,32 +573,57 @@ static void source_sink_complete(struct usb_ep *ep, struct usb_request *req) } } -static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in) +static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in, + bool is_iso, int speed) { struct usb_ep *ep; struct usb_request *req; - int status; + int i, size, status; + + for (i = 0; i < 8; i++) { + if (is_iso) { + switch (speed) { + case USB_SPEED_SUPER: + size = isoc_maxpacket * (isoc_mult + 1) * + (isoc_maxburst + 1); + break; + case USB_SPEED_HIGH: + size = isoc_maxpacket * (isoc_mult + 1); + break; + default: + size = isoc_maxpacket > 1023 ? + 1023 : isoc_maxpacket; + break; + } + ep = is_in ? ss->iso_in_ep : ss->iso_out_ep; + req = alloc_ep_req(ep, size); + } else { + ep = is_in ? ss->in_ep : ss->out_ep; + req = alloc_ep_req(ep, 0); + } - ep = is_in ? ss->in_ep : ss->out_ep; - req = alloc_ep_req(ep); - if (!req) - return -ENOMEM; + if (!req) + return -ENOMEM; - req->complete = source_sink_complete; - if (is_in) - reinit_write_data(ep, req); - else - memset(req->buf, 0x55, req->length); + req->complete = source_sink_complete; + if (is_in) + reinit_write_data(ep, req); + else if (pattern != 2) + memset(req->buf, 0x55, req->length); - status = usb_ep_queue(ep, req, GFP_ATOMIC); - if (status) { - struct usb_composite_dev *cdev; + status = usb_ep_queue(ep, req, GFP_ATOMIC); + if (status) { + struct usb_composite_dev *cdev; - cdev = ss->function.config->cdev; - ERROR(cdev, "start %s %s --> %d\n", - is_in ? "IN" : "OUT", - ep->name, status); - free_ep_req(ep, req); + cdev = ss->function.config->cdev; + ERROR(cdev, "start %s%s %s --> %d\n", + is_iso ? "ISO-" : "", is_in ? "IN" : "OUT", + ep->name, status); + free_ep_req(ep, req); + } + + if (!is_iso) + break; } return status; @@ -380,17 +634,20 @@ static void disable_source_sink(struct f_sourcesink *ss) struct usb_composite_dev *cdev; cdev = ss->function.config->cdev; - disable_endpoints(cdev, ss->in_ep, ss->out_ep); + disable_endpoints(cdev, ss->in_ep, ss->out_ep, ss->iso_in_ep, + ss->iso_out_ep); VDBG(cdev, "%s disabled\n", ss->function.name); } static int -enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss) +enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss, + int alt) { int result = 0; + int speed = cdev->gadget->speed; struct usb_ep *ep; - /* one endpoint writes (sources) zeroes IN (to the host) */ + /* one bulk endpoint writes (sources) zeroes IN (to the host) */ ep = ss->in_ep; result = config_ep_by_speed(cdev->gadget, &(ss->function), ep); if (result) @@ -400,7 +657,7 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss) return result; ep->driver_data = ss; - result = source_sink_start_ep(ss, true); + result = source_sink_start_ep(ss, true, false, speed); if (result < 0) { fail: ep = ss->in_ep; @@ -409,7 +666,7 @@ fail: return result; } - /* one endpoint reads (sinks) anything OUT (from the host) */ + /* one bulk endpoint reads (sinks) anything OUT (from the host) */ ep = ss->out_ep; result = config_ep_by_speed(cdev->gadget, &(ss->function), ep); if (result) @@ -419,27 +676,82 @@ fail: goto fail; ep->driver_data = ss; - result = source_sink_start_ep(ss, false); + result = source_sink_start_ep(ss, false, false, speed); if (result < 0) { +fail2: + ep = ss->out_ep; usb_ep_disable(ep); ep->driver_data = NULL; goto fail; } - DBG(cdev, "%s enabled\n", ss->function.name); + if (alt == 0) + goto out; + + /* one iso endpoint writes (sources) zeroes IN (to the host) */ + ep = ss->iso_in_ep; + if (ep) { + result = config_ep_by_speed(cdev->gadget, &(ss->function), ep); + if (result) + goto fail2; + result = usb_ep_enable(ep); + if (result < 0) + goto fail2; + ep->driver_data = ss; + + result = source_sink_start_ep(ss, true, true, speed); + if (result < 0) { +fail3: + ep = ss->iso_in_ep; + if (ep) { + usb_ep_disable(ep); + ep->driver_data = NULL; + } + goto fail2; + } + } + + /* one iso endpoint reads (sinks) anything OUT (from the host) */ + ep = ss->iso_out_ep; + if (ep) { + result = config_ep_by_speed(cdev->gadget, &(ss->function), ep); + if (result) + goto fail3; + result = usb_ep_enable(ep); + if (result < 0) + goto fail3; + ep->driver_data = ss; + + result = source_sink_start_ep(ss, false, true, speed); + if (result < 0) { + usb_ep_disable(ep); + ep->driver_data = NULL; + goto fail3; + } + } +out: + ss->cur_alt = alt; + + DBG(cdev, "%s enabled, alt intf %d\n", ss->function.name, alt); return result; } static int sourcesink_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { - struct f_sourcesink *ss = func_to_ss(f); - struct usb_composite_dev *cdev = f->config->cdev; + struct f_sourcesink *ss = func_to_ss(f); + struct usb_composite_dev *cdev = f->config->cdev; - /* we know alt is zero */ if (ss->in_ep->driver_data) disable_source_sink(ss); - return enable_source_sink(cdev, ss); + return enable_source_sink(cdev, ss, alt); +} + +static int sourcesink_get_alt(struct usb_function *f, unsigned intf) +{ + struct f_sourcesink *ss = func_to_ss(f); + + return ss->cur_alt; } static void sourcesink_disable(struct usb_function *f) @@ -465,6 +777,7 @@ static int __init sourcesink_bind_config(struct usb_configuration *c) ss->function.bind = sourcesink_bind; ss->function.unbind = sourcesink_unbind; ss->function.set_alt = sourcesink_set_alt; + ss->function.get_alt = sourcesink_get_alt; ss->function.disable = sourcesink_disable; status = usb_add_function(c, &ss->function); @@ -536,7 +849,7 @@ unknown: req->length = value; value = usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC); if (value < 0) - ERROR(c->cdev, "source/sinkc response, err %d\n", + ERROR(c->cdev, "source/sink response, err %d\n", value); } @@ -545,12 +858,12 @@ unknown: } static struct usb_configuration sourcesink_driver = { - .label = "source/sink", - .strings = sourcesink_strings, - .setup = sourcesink_setup, - .bConfigurationValue = 3, - .bmAttributes = USB_CONFIG_ATT_SELFPOWER, - /* .iConfiguration = DYNAMIC */ + .label = "source/sink", + .strings = sourcesink_strings, + .setup = sourcesink_setup, + .bConfigurationValue = 3, + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, + /* .iConfiguration = DYNAMIC */ }; /** @@ -567,7 +880,8 @@ int __init sourcesink_add(struct usb_composite_dev *cdev, bool autoresume) return id; strings_sourcesink[0].id = id; - source_sink_intf.iInterface = id; + source_sink_intf_alt0.iInterface = id; + source_sink_intf_alt1.iInterface = id; sourcesink_driver.iConfiguration = id; /* support autoresume for remote wakeup testing */ diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 877a2c46672b..51881f3bd07a 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -71,9 +71,6 @@ static struct usb_endpoint_descriptor qe_ep0_desc = { .wMaxPacketSize = USB_MAX_CTRL_PAYLOAD, }; -/* it is initialized in probe() */ -static struct qe_udc *udc_controller; - /******************************************************************** * Internal Used Function Start ********************************************************************/ @@ -188,8 +185,8 @@ static int qe_ep0_stall(struct qe_udc *udc) { qe_eptx_stall_change(&udc->eps[0], 1); qe_eprx_stall_change(&udc->eps[0], 1); - udc_controller->ep0_state = WAIT_FOR_SETUP; - udc_controller->ep0_dir = 0; + udc->ep0_state = WAIT_FOR_SETUP; + udc->ep0_dir = 0; return 0; } @@ -450,13 +447,13 @@ static int qe_ep_rxbd_update(struct qe_ep *ep) ep->rxbuf_d = virt_to_phys((void *)ep->rxbuffer); if (ep->rxbuf_d == DMA_ADDR_INVALID) { - ep->rxbuf_d = dma_map_single(udc_controller->gadget.dev.parent, + ep->rxbuf_d = dma_map_single(ep->udc->gadget.dev.parent, ep->rxbuffer, size, DMA_FROM_DEVICE); ep->rxbufmap = 1; } else { - dma_sync_single_for_device(udc_controller->gadget.dev.parent, + dma_sync_single_for_device(ep->udc->gadget.dev.parent, ep->rxbuf_d, size, DMA_FROM_DEVICE); ep->rxbufmap = 0; @@ -489,10 +486,10 @@ static int qe_ep_register_init(struct qe_udc *udc, unsigned char pipe_num) epparam = udc->ep_param[pipe_num]; usep = 0; - logepnum = (ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + logepnum = (ep->ep.desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); usep |= (logepnum << USB_EPNUM_SHIFT); - switch (ep->desc->bmAttributes & 0x03) { + switch (ep->ep.desc->bmAttributes & 0x03) { case USB_ENDPOINT_XFER_BULK: usep |= USB_TRANS_BULK; break; @@ -644,7 +641,7 @@ static int qe_ep_init(struct qe_udc *udc, /* initialize ep structure */ ep->ep.maxpacket = max; ep->tm = (u8)(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); - ep->desc = desc; + ep->ep.desc = desc; ep->stopped = 0; ep->init = 1; @@ -698,14 +695,14 @@ en_done: return -ENODEV; } -static inline void qe_usb_enable(void) +static inline void qe_usb_enable(struct qe_udc *udc) { - setbits8(&udc_controller->usb_regs->usb_usmod, USB_MODE_EN); + setbits8(&udc->usb_regs->usb_usmod, USB_MODE_EN); } -static inline void qe_usb_disable(void) +static inline void qe_usb_disable(struct qe_udc *udc) { - clrbits8(&udc_controller->usb_regs->usb_usmod, USB_MODE_EN); + clrbits8(&udc->usb_regs->usb_usmod, USB_MODE_EN); } /*----------------------------------------------------------------------------* @@ -1599,7 +1596,7 @@ static int qe_ep_enable(struct usb_ep *_ep, ep = container_of(_ep, struct qe_ep, ep); /* catch various bogus parameters */ - if (!_ep || !desc || ep->desc || _ep->name == ep_name[0] || + if (!_ep || !desc || ep->ep.desc || _ep->name == ep_name[0] || (desc->bDescriptorType != USB_DT_ENDPOINT)) return -EINVAL; @@ -1629,7 +1626,7 @@ static int qe_ep_disable(struct usb_ep *_ep) ep = container_of(_ep, struct qe_ep, ep); udc = ep->udc; - if (!_ep || !ep->desc) { + if (!_ep || !ep->ep.desc) { dev_dbg(udc->dev, "%s not enabled\n", _ep ? ep->ep.name : NULL); return -EINVAL; } @@ -1637,7 +1634,6 @@ static int qe_ep_disable(struct usb_ep *_ep) spin_lock_irqsave(&udc->lock, flags); /* Nuke all pending requests (does flush) */ nuke(ep, -ESHUTDOWN); - ep->desc = NULL; ep->ep.desc = NULL; ep->stopped = 1; ep->tx_req = NULL; @@ -1656,13 +1652,13 @@ static int qe_ep_disable(struct usb_ep *_ep) if (ep->dir != USB_DIR_IN) { kfree(ep->rxframe); if (ep->rxbufmap) { - dma_unmap_single(udc_controller->gadget.dev.parent, + dma_unmap_single(udc->gadget.dev.parent, ep->rxbuf_d, size, DMA_FROM_DEVICE); ep->rxbuf_d = DMA_ADDR_INVALID; } else { dma_sync_single_for_cpu( - udc_controller->gadget.dev.parent, + udc->gadget.dev.parent, ep->rxbuf_d, size, DMA_FROM_DEVICE); } @@ -1715,7 +1711,7 @@ static int __qe_ep_queue(struct usb_ep *_ep, struct usb_request *_req) dev_dbg(udc->dev, "bad params\n"); return -EINVAL; } - if (!_ep || (!ep->desc && ep_index(ep))) { + if (!_ep || (!ep->ep.desc && ep_index(ep))) { dev_dbg(udc->dev, "bad ep\n"); return -EINVAL; } @@ -1826,7 +1822,7 @@ static int qe_ep_set_halt(struct usb_ep *_ep, int value) struct qe_udc *udc; ep = container_of(_ep, struct qe_ep, ep); - if (!_ep || !ep->desc) { + if (!_ep || !ep->ep.desc) { status = -EINVAL; goto out; } @@ -1880,9 +1876,10 @@ static struct usb_ep_ops qe_ep_ops = { /* Get the current frame number */ static int qe_get_frame(struct usb_gadget *gadget) { + struct qe_udc *udc = container_of(gadget, struct qe_udc, gadget); u16 tmp; - tmp = in_be16(&udc_controller->usb_param->frame_n); + tmp = in_be16(&udc->usb_param->frame_n); if (tmp & 0x8000) tmp = tmp & 0x07ff; else @@ -1891,57 +1888,16 @@ static int qe_get_frame(struct usb_gadget *gadget) return (int)tmp; } -/* Tries to wake up the host connected to this gadget - * - * Return : 0-success - * Negative-this feature not enabled by host or not supported by device hw - */ -static int qe_wakeup(struct usb_gadget *gadget) -{ - return -ENOTSUPP; -} - -/* Notify controller that VBUS is powered, Called by whatever - detects VBUS sessions */ -static int qe_vbus_session(struct usb_gadget *gadget, int is_active) -{ - return -ENOTSUPP; -} - -/* constrain controller's VBUS power usage - * This call is used by gadget drivers during SET_CONFIGURATION calls, - * reporting how much power the device may consume. For example, this - * could affect how quickly batteries are recharged. - * - * Returns zero on success, else negative errno. - */ -static int qe_vbus_draw(struct usb_gadget *gadget, unsigned mA) -{ - return -ENOTSUPP; -} - -/* Change Data+ pullup status - * this func is used by usb_gadget_connect/disconnect - */ -static int qe_pullup(struct usb_gadget *gadget, int is_on) -{ - return -ENOTSUPP; -} - -static int fsl_qe_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); -static int fsl_qe_stop(struct usb_gadget_driver *driver); +static int fsl_qe_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); +static int fsl_qe_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); /* defined in usb_gadget.h */ static struct usb_gadget_ops qe_gadget_ops = { .get_frame = qe_get_frame, - .wakeup = qe_wakeup, -/* .set_selfpowered = qe_set_selfpowered,*/ /* always selfpowered */ - .vbus_session = qe_vbus_session, - .vbus_draw = qe_vbus_draw, - .pullup = qe_pullup, - .start = fsl_qe_start, - .stop = fsl_qe_stop, + .udc_start = fsl_qe_start, + .udc_stop = fsl_qe_stop, }; /*------------------------------------------------------------------------- @@ -2015,7 +1971,7 @@ static void ch9getstatus(struct qe_udc *udc, u8 request_type, u16 value, u16 usep; /* stall if endpoint doesn't exist */ - if (!target_ep->desc) + if (!target_ep->ep.desc) goto stall; usep = in_be16(&udc->usb_regs->usb_usep[pipe]); @@ -2190,7 +2146,7 @@ static int reset_irq(struct qe_udc *udc) if (udc->usb_state == USB_STATE_DEFAULT) return 0; - qe_usb_disable(); + qe_usb_disable(udc); out_8(&udc->usb_regs->usb_usadr, 0); for (i = 0; i < USB_MAX_ENDPOINTS; i++) { @@ -2202,7 +2158,7 @@ static int reset_irq(struct qe_udc *udc) udc->usb_state = USB_STATE_DEFAULT; udc->ep0_state = WAIT_FOR_SETUP; udc->ep0_dir = USB_DIR_OUT; - qe_usb_enable(); + qe_usb_enable(udc); return 0; } @@ -2327,92 +2283,65 @@ static irqreturn_t qe_udc_irq(int irq, void *_udc) /*------------------------------------------------------------------------- Gadget driver probe and unregister. --------------------------------------------------------------------------*/ -static int fsl_qe_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) +static int fsl_qe_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - int retval; - unsigned long flags = 0; - - /* standard operations */ - if (!udc_controller) - return -ENODEV; - - if (!driver || driver->max_speed < USB_SPEED_FULL - || !bind || !driver->disconnect || !driver->setup) - return -EINVAL; - - if (udc_controller->driver) - return -EBUSY; + struct qe_udc *udc; + unsigned long flags; + udc = container_of(gadget, struct qe_udc, gadget); /* lock is needed but whether should use this lock or another */ - spin_lock_irqsave(&udc_controller->lock, flags); + spin_lock_irqsave(&udc->lock, flags); driver->driver.bus = NULL; /* hook up the driver */ - udc_controller->driver = driver; - udc_controller->gadget.dev.driver = &driver->driver; - udc_controller->gadget.speed = driver->max_speed; - spin_unlock_irqrestore(&udc_controller->lock, flags); - - retval = bind(&udc_controller->gadget); - if (retval) { - dev_err(udc_controller->dev, "bind to %s --> %d", - driver->driver.name, retval); - udc_controller->gadget.dev.driver = NULL; - udc_controller->driver = NULL; - return retval; - } + udc->driver = driver; + udc->gadget.dev.driver = &driver->driver; + udc->gadget.speed = driver->max_speed; /* Enable IRQ reg and Set usbcmd reg EN bit */ - qe_usb_enable(); - - out_be16(&udc_controller->usb_regs->usb_usber, 0xffff); - out_be16(&udc_controller->usb_regs->usb_usbmr, USB_E_DEFAULT_DEVICE); - udc_controller->usb_state = USB_STATE_ATTACHED; - udc_controller->ep0_state = WAIT_FOR_SETUP; - udc_controller->ep0_dir = USB_DIR_OUT; - dev_info(udc_controller->dev, "%s bind to driver %s \n", - udc_controller->gadget.name, driver->driver.name); + qe_usb_enable(udc); + + out_be16(&udc->usb_regs->usb_usber, 0xffff); + out_be16(&udc->usb_regs->usb_usbmr, USB_E_DEFAULT_DEVICE); + udc->usb_state = USB_STATE_ATTACHED; + udc->ep0_state = WAIT_FOR_SETUP; + udc->ep0_dir = USB_DIR_OUT; + spin_unlock_irqrestore(&udc->lock, flags); + + dev_info(udc->dev, "%s bind to driver %s\n", udc->gadget.name, + driver->driver.name); return 0; } -static int fsl_qe_stop(struct usb_gadget_driver *driver) +static int fsl_qe_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { + struct qe_udc *udc; struct qe_ep *loop_ep; unsigned long flags; - if (!udc_controller) - return -ENODEV; - - if (!driver || driver != udc_controller->driver) - return -EINVAL; - + udc = container_of(gadget, struct qe_udc, gadget); /* stop usb controller, disable intr */ - qe_usb_disable(); + qe_usb_disable(udc); /* in fact, no needed */ - udc_controller->usb_state = USB_STATE_ATTACHED; - udc_controller->ep0_state = WAIT_FOR_SETUP; - udc_controller->ep0_dir = 0; + udc->usb_state = USB_STATE_ATTACHED; + udc->ep0_state = WAIT_FOR_SETUP; + udc->ep0_dir = 0; /* stand operation */ - spin_lock_irqsave(&udc_controller->lock, flags); - udc_controller->gadget.speed = USB_SPEED_UNKNOWN; - nuke(&udc_controller->eps[0], -ESHUTDOWN); - list_for_each_entry(loop_ep, &udc_controller->gadget.ep_list, - ep.ep_list) + spin_lock_irqsave(&udc->lock, flags); + udc->gadget.speed = USB_SPEED_UNKNOWN; + nuke(&udc->eps[0], -ESHUTDOWN); + list_for_each_entry(loop_ep, &udc->gadget.ep_list, ep.ep_list) nuke(loop_ep, -ESHUTDOWN); - spin_unlock_irqrestore(&udc_controller->lock, flags); - - /* report disconnect; the controller is already quiesced */ - driver->disconnect(&udc_controller->gadget); + spin_unlock_irqrestore(&udc->lock, flags); - /* unbind gadget and unhook driver. */ - driver->unbind(&udc_controller->gadget); - udc_controller->gadget.dev.driver = NULL; - udc_controller->driver = NULL; + udc->gadget.dev.driver = NULL; + udc->driver = NULL; - dev_info(udc_controller->dev, "unregistered gadget driver '%s'\r\n", + dev_info(udc->dev, "unregistered gadget driver '%s'\r\n", driver->driver.name); return 0; } @@ -2502,7 +2431,7 @@ static int __devinit qe_ep_config(struct qe_udc *udc, unsigned char pipe_num) ep->ep.ops = &qe_ep_ops; ep->stopped = 1; ep->ep.maxpacket = (unsigned short) ~0; - ep->desc = NULL; + ep->ep.desc = NULL; ep->dir = 0xff; ep->epnum = (u8)pipe_num; ep->sent = 0; @@ -2531,21 +2460,22 @@ static int __devinit qe_ep_config(struct qe_udc *udc, unsigned char pipe_num) *----------------------------------------------------------------------*/ static void qe_udc_release(struct device *dev) { - int i = 0; + struct qe_udc *udc = container_of(dev, struct qe_udc, gadget.dev); + int i; - complete(udc_controller->done); - cpm_muram_free(cpm_muram_offset(udc_controller->ep_param[0])); + complete(udc->done); + cpm_muram_free(cpm_muram_offset(udc->ep_param[0])); for (i = 0; i < USB_MAX_ENDPOINTS; i++) - udc_controller->ep_param[i] = NULL; + udc->ep_param[i] = NULL; - kfree(udc_controller); - udc_controller = NULL; + kfree(udc); } /* Driver probe functions */ static const struct of_device_id qe_udc_match[]; static int __devinit qe_udc_probe(struct platform_device *ofdev) { + struct qe_udc *udc; const struct of_device_id *match; struct device_node *np = ofdev->dev.of_node; struct qe_ep *ep; @@ -2562,44 +2492,44 @@ static int __devinit qe_udc_probe(struct platform_device *ofdev) return -ENODEV; /* Initialize the udc structure including QH member and other member */ - udc_controller = qe_udc_config(ofdev); - if (!udc_controller) { + udc = qe_udc_config(ofdev); + if (!udc) { dev_err(&ofdev->dev, "failed to initialize\n"); return -ENOMEM; } - udc_controller->soc_type = (unsigned long)match->data; - udc_controller->usb_regs = of_iomap(np, 0); - if (!udc_controller->usb_regs) { + udc->soc_type = (unsigned long)match->data; + udc->usb_regs = of_iomap(np, 0); + if (!udc->usb_regs) { ret = -ENOMEM; goto err1; } /* initialize usb hw reg except for regs for EP, * leave usbintr reg untouched*/ - qe_udc_reg_init(udc_controller); + qe_udc_reg_init(udc); /* here comes the stand operations for probe * set the qe_udc->gadget.xxx */ - udc_controller->gadget.ops = &qe_gadget_ops; + udc->gadget.ops = &qe_gadget_ops; /* gadget.ep0 is a pointer */ - udc_controller->gadget.ep0 = &udc_controller->eps[0].ep; + udc->gadget.ep0 = &udc->eps[0].ep; - INIT_LIST_HEAD(&udc_controller->gadget.ep_list); + INIT_LIST_HEAD(&udc->gadget.ep_list); /* modify in register gadget process */ - udc_controller->gadget.speed = USB_SPEED_UNKNOWN; + udc->gadget.speed = USB_SPEED_UNKNOWN; /* name: Identifies the controller hardware type. */ - udc_controller->gadget.name = driver_name; + udc->gadget.name = driver_name; - device_initialize(&udc_controller->gadget.dev); + device_initialize(&udc->gadget.dev); - dev_set_name(&udc_controller->gadget.dev, "gadget"); + dev_set_name(&udc->gadget.dev, "gadget"); - udc_controller->gadget.dev.release = qe_udc_release; - udc_controller->gadget.dev.parent = &ofdev->dev; + udc->gadget.dev.release = qe_udc_release; + udc->gadget.dev.parent = &ofdev->dev; /* initialize qe_ep struct */ for (i = 0; i < USB_MAX_ENDPOINTS ; i++) { @@ -2608,104 +2538,104 @@ static int __devinit qe_udc_probe(struct platform_device *ofdev) /* setup the qe_ep struct and link ep.ep.list * into gadget.ep_list */ - qe_ep_config(udc_controller, (unsigned char)i); + qe_ep_config(udc, (unsigned char)i); } /* ep0 initialization in here */ - ret = qe_ep_init(udc_controller, 0, &qe_ep0_desc); + ret = qe_ep_init(udc, 0, &qe_ep0_desc); if (ret) goto err2; /* create a buf for ZLP send, need to remain zeroed */ - udc_controller->nullbuf = kzalloc(256, GFP_KERNEL); - if (udc_controller->nullbuf == NULL) { - dev_err(udc_controller->dev, "cannot alloc nullbuf\n"); + udc->nullbuf = kzalloc(256, GFP_KERNEL); + if (udc->nullbuf == NULL) { + dev_err(udc->dev, "cannot alloc nullbuf\n"); ret = -ENOMEM; goto err3; } /* buffer for data of get_status request */ - udc_controller->statusbuf = kzalloc(2, GFP_KERNEL); - if (udc_controller->statusbuf == NULL) { + udc->statusbuf = kzalloc(2, GFP_KERNEL); + if (udc->statusbuf == NULL) { ret = -ENOMEM; goto err4; } - udc_controller->nullp = virt_to_phys((void *)udc_controller->nullbuf); - if (udc_controller->nullp == DMA_ADDR_INVALID) { - udc_controller->nullp = dma_map_single( - udc_controller->gadget.dev.parent, - udc_controller->nullbuf, + udc->nullp = virt_to_phys((void *)udc->nullbuf); + if (udc->nullp == DMA_ADDR_INVALID) { + udc->nullp = dma_map_single( + udc->gadget.dev.parent, + udc->nullbuf, 256, DMA_TO_DEVICE); - udc_controller->nullmap = 1; + udc->nullmap = 1; } else { - dma_sync_single_for_device(udc_controller->gadget.dev.parent, - udc_controller->nullp, 256, + dma_sync_single_for_device(udc->gadget.dev.parent, + udc->nullp, 256, DMA_TO_DEVICE); } - tasklet_init(&udc_controller->rx_tasklet, ep_rx_tasklet, - (unsigned long)udc_controller); + tasklet_init(&udc->rx_tasklet, ep_rx_tasklet, + (unsigned long)udc); /* request irq and disable DR */ - udc_controller->usb_irq = irq_of_parse_and_map(np, 0); - if (!udc_controller->usb_irq) { + udc->usb_irq = irq_of_parse_and_map(np, 0); + if (!udc->usb_irq) { ret = -EINVAL; goto err_noirq; } - ret = request_irq(udc_controller->usb_irq, qe_udc_irq, 0, - driver_name, udc_controller); + ret = request_irq(udc->usb_irq, qe_udc_irq, 0, + driver_name, udc); if (ret) { - dev_err(udc_controller->dev, "cannot request irq %d err %d \n", - udc_controller->usb_irq, ret); + dev_err(udc->dev, "cannot request irq %d err %d\n", + udc->usb_irq, ret); goto err5; } - ret = device_add(&udc_controller->gadget.dev); + ret = device_add(&udc->gadget.dev); if (ret) goto err6; - ret = usb_add_gadget_udc(&ofdev->dev, &udc_controller->gadget); + ret = usb_add_gadget_udc(&ofdev->dev, &udc->gadget); if (ret) goto err7; - dev_info(udc_controller->dev, + dev_set_drvdata(&ofdev->dev, udc); + dev_info(udc->dev, "%s USB controller initialized as device\n", - (udc_controller->soc_type == PORT_QE) ? "QE" : "CPM"); + (udc->soc_type == PORT_QE) ? "QE" : "CPM"); return 0; err7: - device_unregister(&udc_controller->gadget.dev); + device_unregister(&udc->gadget.dev); err6: - free_irq(udc_controller->usb_irq, udc_controller); + free_irq(udc->usb_irq, udc); err5: - irq_dispose_mapping(udc_controller->usb_irq); + irq_dispose_mapping(udc->usb_irq); err_noirq: - if (udc_controller->nullmap) { - dma_unmap_single(udc_controller->gadget.dev.parent, - udc_controller->nullp, 256, + if (udc->nullmap) { + dma_unmap_single(udc->gadget.dev.parent, + udc->nullp, 256, DMA_TO_DEVICE); - udc_controller->nullp = DMA_ADDR_INVALID; + udc->nullp = DMA_ADDR_INVALID; } else { - dma_sync_single_for_cpu(udc_controller->gadget.dev.parent, - udc_controller->nullp, 256, + dma_sync_single_for_cpu(udc->gadget.dev.parent, + udc->nullp, 256, DMA_TO_DEVICE); } - kfree(udc_controller->statusbuf); + kfree(udc->statusbuf); err4: - kfree(udc_controller->nullbuf); + kfree(udc->nullbuf); err3: - ep = &udc_controller->eps[0]; + ep = &udc->eps[0]; cpm_muram_free(cpm_muram_offset(ep->rxbase)); kfree(ep->rxframe); kfree(ep->rxbuffer); kfree(ep->txframe); err2: - iounmap(udc_controller->usb_regs); + iounmap(udc->usb_regs); err1: - kfree(udc_controller); - udc_controller = NULL; + kfree(udc); return ret; } @@ -2723,44 +2653,41 @@ static int qe_udc_resume(struct platform_device *dev) static int __devexit qe_udc_remove(struct platform_device *ofdev) { + struct qe_udc *udc = dev_get_drvdata(&ofdev->dev); struct qe_ep *ep; unsigned int size; - DECLARE_COMPLETION(done); - if (!udc_controller) - return -ENODEV; - - usb_del_gadget_udc(&udc_controller->gadget); + usb_del_gadget_udc(&udc->gadget); - udc_controller->done = &done; - tasklet_disable(&udc_controller->rx_tasklet); + udc->done = &done; + tasklet_disable(&udc->rx_tasklet); - if (udc_controller->nullmap) { - dma_unmap_single(udc_controller->gadget.dev.parent, - udc_controller->nullp, 256, + if (udc->nullmap) { + dma_unmap_single(udc->gadget.dev.parent, + udc->nullp, 256, DMA_TO_DEVICE); - udc_controller->nullp = DMA_ADDR_INVALID; + udc->nullp = DMA_ADDR_INVALID; } else { - dma_sync_single_for_cpu(udc_controller->gadget.dev.parent, - udc_controller->nullp, 256, + dma_sync_single_for_cpu(udc->gadget.dev.parent, + udc->nullp, 256, DMA_TO_DEVICE); } - kfree(udc_controller->statusbuf); - kfree(udc_controller->nullbuf); + kfree(udc->statusbuf); + kfree(udc->nullbuf); - ep = &udc_controller->eps[0]; + ep = &udc->eps[0]; cpm_muram_free(cpm_muram_offset(ep->rxbase)); size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) * (USB_BDRING_LEN + 1); kfree(ep->rxframe); if (ep->rxbufmap) { - dma_unmap_single(udc_controller->gadget.dev.parent, + dma_unmap_single(udc->gadget.dev.parent, ep->rxbuf_d, size, DMA_FROM_DEVICE); ep->rxbuf_d = DMA_ADDR_INVALID; } else { - dma_sync_single_for_cpu(udc_controller->gadget.dev.parent, + dma_sync_single_for_cpu(udc->gadget.dev.parent, ep->rxbuf_d, size, DMA_FROM_DEVICE); } @@ -2768,14 +2695,14 @@ static int __devexit qe_udc_remove(struct platform_device *ofdev) kfree(ep->rxbuffer); kfree(ep->txframe); - free_irq(udc_controller->usb_irq, udc_controller); - irq_dispose_mapping(udc_controller->usb_irq); + free_irq(udc->usb_irq, udc); + irq_dispose_mapping(udc->usb_irq); - tasklet_kill(&udc_controller->rx_tasklet); + tasklet_kill(&udc->rx_tasklet); - iounmap(udc_controller->usb_regs); + iounmap(udc->usb_regs); - device_unregister(&udc_controller->gadget.dev); + device_unregister(&udc->gadget.dev); /* wait for release() of gadget.dev to free udc */ wait_for_completion(&done); diff --git a/drivers/usb/gadget/fsl_qe_udc.h b/drivers/usb/gadget/fsl_qe_udc.h index 1da5fb03d218..4c07ca9cebf3 100644 --- a/drivers/usb/gadget/fsl_qe_udc.h +++ b/drivers/usb/gadget/fsl_qe_udc.h @@ -266,7 +266,6 @@ struct qe_ep { struct usb_ep ep; struct list_head queue; struct qe_udc *udc; - const struct usb_endpoint_descriptor *desc; struct usb_gadget *gadget; u8 state; diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 0d9b2fa45af3..28316858208b 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -567,7 +567,7 @@ static int fsl_ep_enable(struct usb_ep *_ep, ep = container_of(_ep, struct fsl_ep, ep); /* catch various bogus parameters */ - if (!_ep || !desc || ep->desc + if (!_ep || !desc || ep->ep.desc || (desc->bDescriptorType != USB_DT_ENDPOINT)) return -EINVAL; @@ -608,7 +608,7 @@ static int fsl_ep_enable(struct usb_ep *_ep, spin_lock_irqsave(&udc->lock, flags); ep->ep.maxpacket = max; - ep->desc = desc; + ep->ep.desc = desc; ep->stopped = 0; /* Controller related setup */ @@ -632,7 +632,7 @@ static int fsl_ep_enable(struct usb_ep *_ep, retval = 0; VDBG("enabled %s (ep%d%s) maxpacket %d",ep->ep.name, - ep->desc->bEndpointAddress & 0x0f, + ep->ep.desc->bEndpointAddress & 0x0f, (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out", max); en_done: @@ -652,7 +652,7 @@ static int fsl_ep_disable(struct usb_ep *_ep) int ep_num; ep = container_of(_ep, struct fsl_ep, ep); - if (!_ep || !ep->desc) { + if (!_ep || !ep->ep.desc) { VDBG("%s not enabled", _ep ? ep->ep.name : NULL); return -EINVAL; } @@ -675,7 +675,6 @@ static int fsl_ep_disable(struct usb_ep *_ep) /* nuke all pending requests (does flush) */ nuke(ep, -ESHUTDOWN); - ep->desc = NULL; ep->ep.desc = NULL; ep->stopped = 1; spin_unlock_irqrestore(&udc->lock, flags); @@ -754,6 +753,8 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) lastreq = list_entry(ep->queue.prev, struct fsl_req, queue); lastreq->tail->next_td_ptr = cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK); + /* Ensure dTD's next dtd pointer to be updated */ + wmb(); /* Read prime bit, if 1 goto done */ if (fsl_readl(&dr_regs->endpointprime) & bitmask) return; @@ -892,11 +893,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) VDBG("%s, bad params", __func__); return -EINVAL; } - if (unlikely(!_ep || !ep->desc)) { + if (unlikely(!_ep || !ep->ep.desc)) { VDBG("%s, bad ep", __func__); return -EINVAL; } - if (usb_endpoint_xfer_isoc(ep->desc)) { + if (usb_endpoint_xfer_isoc(ep->ep.desc)) { if (req->req.length > ep->ep.maxpacket) return -EMSGSIZE; } @@ -1035,12 +1036,12 @@ static int fsl_ep_set_halt(struct usb_ep *_ep, int value) ep = container_of(_ep, struct fsl_ep, ep); udc = ep->udc; - if (!_ep || !ep->desc) { + if (!_ep || !ep->ep.desc) { status = -EINVAL; goto out; } - if (usb_endpoint_xfer_isoc(ep->desc)) { + if (usb_endpoint_xfer_isoc(ep->ep.desc)) { status = -EOPNOTSUPP; goto out; } @@ -1079,7 +1080,7 @@ static int fsl_ep_fifo_status(struct usb_ep *_ep) struct ep_queue_head *qh; ep = container_of(_ep, struct fsl_ep, ep); - if (!_ep || (!ep->desc && ep_index(ep) != 0)) + if (!_ep || (!ep->ep.desc && ep_index(ep) != 0)) return -ENODEV; udc = (struct fsl_udc *)ep->udc; @@ -1112,7 +1113,7 @@ static void fsl_ep_fifo_flush(struct usb_ep *_ep) return; } else { ep = container_of(_ep, struct fsl_ep, ep); - if (!ep->desc) + if (!ep->ep.desc) return; } ep_num = ep_index(ep); @@ -1367,7 +1368,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, target_ep = get_ep_by_pipe(udc, get_pipe_by_windex(index)); /* stall if endpoint doesn't exist */ - if (!target_ep->desc) + if (!target_ep->ep.desc) goto stall; tmp = dr_ep_get_stall(ep_index(target_ep), ep_is_in(target_ep)) << USB_ENDPOINT_HALT; @@ -2277,7 +2278,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count, } /* other gadget->eplist ep */ list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { - if (ep->desc) { + if (ep->ep.desc) { t = scnprintf(next, size, "\nFor %s Maxpkt is 0x%x " "index is 0x%x\n", diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index 1212646841a3..5cd7b7e7ddb4 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -461,7 +461,6 @@ struct fsl_ep { struct list_head queue; struct fsl_udc *udc; struct ep_queue_head *qh; - const struct usb_endpoint_descriptor *desc; struct usb_gadget *gadget; char name[14]; diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index 5831cb4a0b35..cdd94540e1cd 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c @@ -203,7 +203,7 @@ static int config_ep(struct fusb300_ep *ep, struct fusb300 *fusb300 = ep->fusb300; struct fusb300_ep_info info; - ep->desc = desc; + ep->ep.desc = desc; info.interval = 0; info.addrofs = 0; @@ -443,7 +443,7 @@ static int fusb300_queue(struct usb_ep *_ep, struct usb_request *_req, req->req.actual = 0; req->req.status = -EINPROGRESS; - if (ep->desc == NULL) /* ep0 */ + if (ep->ep.desc == NULL) /* ep0 */ ep0_queue(ep, req); else if (request && !ep->stall) enable_fifo_int(ep); diff --git a/drivers/usb/gadget/fusb300_udc.h b/drivers/usb/gadget/fusb300_udc.h index 92745bd03064..542cd83cc806 100644 --- a/drivers/usb/gadget/fusb300_udc.h +++ b/drivers/usb/gadget/fusb300_udc.h @@ -650,7 +650,6 @@ struct fusb300_ep { unsigned char epnum; unsigned char type; - const struct usb_endpoint_descriptor *desc; }; struct fusb300 { diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h index e84b3c47ed3c..71ca193358b8 100644 --- a/drivers/usb/gadget/g_zero.h +++ b/drivers/usb/gadget/g_zero.h @@ -13,10 +13,11 @@ extern unsigned buflen; extern const struct usb_descriptor_header *otg_desc[]; /* common utilities */ -struct usb_request *alloc_ep_req(struct usb_ep *ep); +struct usb_request *alloc_ep_req(struct usb_ep *ep, int len); void free_ep_req(struct usb_ep *ep, struct usb_request *req); void disable_endpoints(struct usb_composite_dev *cdev, - struct usb_ep *in, struct usb_ep *out); + struct usb_ep *in, struct usb_ep *out, + struct usb_ep *iso_in, struct usb_ep *iso_out); /* configuration-specific linkup */ int sourcesink_add(struct usb_composite_dev *cdev, bool autoresume); diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index e151d6b87dee..b241e6c6a7f2 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -102,7 +102,7 @@ goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) unsigned long flags; ep = container_of(_ep, struct goku_ep, ep); - if (!_ep || !desc || ep->desc + if (!_ep || !desc || ep->ep.desc || desc->bDescriptorType != USB_DT_ENDPOINT) return -EINVAL; dev = ep->dev; @@ -176,7 +176,7 @@ goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) command(ep->dev->regs, COMMAND_RESET, ep->num); ep->ep.maxpacket = max; ep->stopped = 0; - ep->desc = desc; + ep->ep.desc = desc; spin_unlock_irqrestore(&ep->dev->lock, flags); DBG(dev, "enable %s %s %s maxpacket %u\n", ep->ep.name, @@ -233,7 +233,6 @@ static void ep_reset(struct goku_udc_regs __iomem *regs, struct goku_ep *ep) } ep->ep.maxpacket = MAX_FIFO_SIZE; - ep->desc = NULL; ep->ep.desc = NULL; ep->stopped = 1; ep->irqs = 0; @@ -247,7 +246,7 @@ static int goku_ep_disable(struct usb_ep *_ep) unsigned long flags; ep = container_of(_ep, struct goku_ep, ep); - if (!_ep || !ep->desc) + if (!_ep || !ep->ep.desc) return -ENODEV; dev = ep->dev; if (dev->ep0state == EP0_SUSPEND) @@ -722,7 +721,7 @@ goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) || !_req->buf || !list_empty(&req->queue))) return -EINVAL; ep = container_of(_ep, struct goku_ep, ep); - if (unlikely(!_ep || (!ep->desc && ep->num != 0))) + if (unlikely(!_ep || (!ep->ep.desc && ep->num != 0))) return -EINVAL; dev = ep->dev; if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) @@ -815,7 +814,7 @@ static int goku_dequeue(struct usb_ep *_ep, struct usb_request *_req) unsigned long flags; ep = container_of(_ep, struct goku_ep, ep); - if (!_ep || !_req || (!ep->desc && ep->num != 0)) + if (!_ep || !_req || (!ep->ep.desc && ep->num != 0)) return -EINVAL; dev = ep->dev; if (!dev->driver) @@ -896,7 +895,7 @@ static int goku_set_halt(struct usb_ep *_ep, int value) return -EINVAL; /* don't change EPxSTATUS_EP_INVALID to READY */ - } else if (!ep->desc) { + } else if (!ep->ep.desc) { DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name); return -EINVAL; } @@ -955,7 +954,7 @@ static void goku_fifo_flush(struct usb_ep *_ep) VDBG(ep->dev, "%s %s\n", __func__, ep->ep.name); /* don't change EPxSTATUS_EP_INVALID to READY */ - if (!ep->desc && ep->num != 0) { + if (!ep->ep.desc && ep->num != 0) { DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name); return; } @@ -1152,7 +1151,7 @@ udc_proc_read(char *buffer, char **start, off_t off, int count, struct goku_ep *ep = &dev->ep [i]; struct goku_request *req; - if (i && !ep->desc) + if (i && !ep->ep.desc) continue; tmp = readl(ep->reg_status); @@ -1473,7 +1472,8 @@ static void ep0_setup(struct goku_udc *dev) case USB_RECIP_ENDPOINT: tmp = le16_to_cpu(ctrl.wIndex) & 0x0f; /* active endpoint */ - if (tmp > 3 || (!dev->ep[tmp].desc && tmp != 0)) + if (tmp > 3 || + (!dev->ep[tmp].ep.desc && tmp != 0)) goto stall; if (ctrl.wIndex & cpu_to_le16( USB_DIR_IN)) { @@ -1895,14 +1895,4 @@ static struct pci_driver goku_pci_driver = { /* FIXME add power management support */ }; -static int __init init (void) -{ - return pci_register_driver (&goku_pci_driver); -} -module_init (init); - -static void __exit cleanup (void) -{ - pci_unregister_driver (&goku_pci_driver); -} -module_exit (cleanup); +module_pci_driver(goku_pci_driver); diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h index e7e0c69d3b1f..85cdce0d1901 100644 --- a/drivers/usb/gadget/goku_udc.h +++ b/drivers/usb/gadget/goku_udc.h @@ -216,7 +216,6 @@ struct goku_ep { /* analogous to a host-side qh */ struct list_head queue; - const struct usb_endpoint_descriptor *desc; u32 __iomem *reg_fifo; u32 __iomem *reg_mode; diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 8d1c75abd73d..54034f84f992 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1237,14 +1237,15 @@ irq_handler_t intr_handler(int i) ******************************************************************************* */ -static int imx_udc_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); -static int imx_udc_stop(struct usb_gadget_driver *driver); +static int imx_udc_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); +static int imx_udc_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); static const struct usb_gadget_ops imx_udc_ops = { - .get_frame = imx_udc_get_frame, - .wakeup = imx_udc_wakeup, - .start = imx_udc_start, - .stop = imx_udc_stop, + .get_frame = imx_udc_get_frame, + .wakeup = imx_udc_wakeup, + .udc_start = imx_udc_start, + .udc_stop = imx_udc_stop, }; static struct imx_udc_struct controller = { @@ -1329,23 +1330,13 @@ static struct imx_udc_struct controller = { * USB gadget driver functions ******************************************************************************* */ -static int imx_udc_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) +static int imx_udc_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct imx_udc_struct *imx_usb = &controller; + struct imx_udc_struct *imx_usb; int retval; - if (!driver - || driver->max_speed < USB_SPEED_FULL - || !bind - || !driver->disconnect - || !driver->setup) - return -EINVAL; - if (!imx_usb) - return -ENODEV; - if (imx_usb->driver) - return -EBUSY; - + imx_usb = container_of(gadget, struct imx_udc_struct, gadget); /* first hook up the driver ... */ imx_usb->driver = driver; imx_usb->gadget.dev.driver = &driver->driver; @@ -1353,14 +1344,6 @@ static int imx_udc_start(struct usb_gadget_driver *driver, retval = device_add(&imx_usb->gadget.dev); if (retval) goto fail; - retval = bind(&imx_usb->gadget); - if (retval) { - D_ERR(imx_usb->dev, "<%s> bind to driver %s --> error %d\n", - __func__, driver->driver.name, retval); - device_del(&imx_usb->gadget.dev); - - goto fail; - } D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n", __func__, driver->driver.name); @@ -1374,20 +1357,16 @@ fail: return retval; } -static int imx_udc_stop(struct usb_gadget_driver *driver) +static int imx_udc_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct imx_udc_struct *imx_usb = &controller; - - if (!imx_usb) - return -ENODEV; - if (!driver || driver != imx_usb->driver || !driver->unbind) - return -EINVAL; + struct imx_udc_struct *imx_usb = container_of(gadget, + struct imx_udc_struct, gadget); udc_stop_activity(imx_usb, driver); imx_udc_disable(imx_usb); del_timer(&imx_usb->timer); - driver->unbind(&imx_usb->gadget); imx_usb->gadget.dev.driver = NULL; imx_usb->driver = NULL; diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index f9cedd52cf20..e119519cdaf4 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -154,7 +154,7 @@ static inline void print_all_registers(struct langwell_udc *dev) /*-------------------------------------------------------------------------*/ #define is_in(ep) (((ep)->ep_num == 0) ? ((ep)->dev->ep0_dir == \ - USB_DIR_IN) : (usb_endpoint_dir_in((ep)->desc))) + USB_DIR_IN) : (usb_endpoint_dir_in((ep)->ep.desc))) #define DIR_STRING(ep) (is_in(ep) ? "in" : "out") @@ -257,7 +257,7 @@ static int langwell_ep_enable(struct usb_ep *_ep, dev = ep->dev; dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); - if (!_ep || !desc || ep->desc + if (!_ep || !desc || ep->ep.desc || desc->bDescriptorType != USB_DT_ENDPOINT) return -EINVAL; @@ -337,7 +337,7 @@ static int langwell_ep_enable(struct usb_ep *_ep, spin_lock_irqsave(&dev->lock, flags); ep->ep.maxpacket = max; - ep->desc = desc; + ep->ep.desc = desc; ep->stopped = 0; ep->ep_num = usb_endpoint_num(desc); @@ -432,7 +432,7 @@ static void nuke(struct langwell_ep *ep, int status) ep->stopped = 1; /* endpoint fifo flush */ - if (&ep->ep && ep->desc) + if (&ep->ep && ep->ep.desc) langwell_ep_fifo_flush(&ep->ep); while (!list_empty(&ep->queue)) { @@ -459,7 +459,7 @@ static int langwell_ep_disable(struct usb_ep *_ep) dev = ep->dev; dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); - if (!_ep || !ep->desc) + if (!_ep || !ep->ep.desc) return -EINVAL; spin_lock_irqsave(&dev->lock, flags); @@ -476,7 +476,6 @@ static int langwell_ep_disable(struct usb_ep *_ep) /* nuke all pending requests (does flush) */ nuke(ep, -ESHUTDOWN); - ep->desc = NULL; ep->ep.desc = NULL; ep->stopped = 1; @@ -752,14 +751,14 @@ static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req, return -EINVAL; } - if (unlikely(!_ep || !ep->desc)) + if (unlikely(!_ep || !ep->ep.desc)) return -EINVAL; dev = ep->dev; req->ep = ep; dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); - if (usb_endpoint_xfer_isoc(ep->desc)) { + if (usb_endpoint_xfer_isoc(ep->ep.desc)) { if (req->req.length > ep->ep.maxpacket) return -EMSGSIZE; is_iso = 1; @@ -822,7 +821,7 @@ static int langwell_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) dev = ep->dev; dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); - if (!_ep || !ep->desc || !_req) + if (!_ep || !ep->ep.desc || !_req) return -EINVAL; if (!dev->driver) @@ -950,13 +949,13 @@ static int langwell_ep_set_halt(struct usb_ep *_ep, int value) dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); - if (!_ep || !ep->desc) + if (!_ep || !ep->ep.desc) return -EINVAL; if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) return -ESHUTDOWN; - if (usb_endpoint_xfer_isoc(ep->desc)) + if (usb_endpoint_xfer_isoc(ep->ep.desc)) return -EOPNOTSUPP; spin_lock_irqsave(&dev->lock, flags); @@ -999,7 +998,7 @@ static int langwell_ep_set_wedge(struct usb_ep *_ep) dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); - if (!_ep || !ep->desc) + if (!_ep || !ep->ep.desc) return -EINVAL; dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); @@ -1020,8 +1019,8 @@ static void langwell_ep_fifo_flush(struct usb_ep *_ep) dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); - if (!_ep || !ep->desc) { - dev_vdbg(&dev->pdev->dev, "ep or ep->desc is NULL\n"); + if (!_ep || !ep->ep.desc) { + dev_vdbg(&dev->pdev->dev, "ep or ep->ep.desc is NULL\n"); dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return; } @@ -1402,7 +1401,7 @@ static int eps_reinit(struct langwell_udc *dev) ep->stopped = 0; ep->ep.maxpacket = EP0_MAX_PKT_SIZE; ep->ep_num = 0; - ep->desc = &langwell_ep0_desc; + ep->ep.desc = &langwell_ep0_desc; INIT_LIST_HEAD(&ep->queue); ep->ep_type = USB_ENDPOINT_XFER_CONTROL; @@ -1737,7 +1736,7 @@ static ssize_t show_langwell_udc(struct device *_dev, } /* other gadget->eplist ep */ list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) { - if (ep->desc) { + if (ep->ep.desc) { t = scnprintf(next, size, "\n%s MaxPacketSize: 0x%x, " "ep_num: %d\n", @@ -2046,10 +2045,10 @@ static struct langwell_ep *get_ep_by_windex(struct langwell_udc *dev, list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) { u8 bEndpointAddress; - if (!ep->desc) + if (!ep->ep.desc) continue; - bEndpointAddress = ep->desc->bEndpointAddress; + bEndpointAddress = ep->ep.desc->bEndpointAddress; if ((wIndex ^ bEndpointAddress) & USB_DIR_IN) continue; @@ -3412,23 +3411,9 @@ static struct pci_driver langwell_pci_driver = { .shutdown = langwell_udc_shutdown, }; - -static int __init init(void) -{ - return pci_register_driver(&langwell_pci_driver); -} -module_init(init); - - -static void __exit cleanup(void) -{ - pci_unregister_driver(&langwell_pci_driver); -} -module_exit(cleanup); - +module_pci_driver(langwell_pci_driver); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR("Xiaochen Shen <xiaochen.shen@intel.com>"); MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); - diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h index 8c8087abb481..38fa3c86d85c 100644 --- a/drivers/usb/gadget/langwell_udc.h +++ b/drivers/usb/gadget/langwell_udc.h @@ -116,7 +116,6 @@ struct langwell_ep { unsigned long irqs; struct list_head queue; struct langwell_dqh *dqh; - const struct usb_endpoint_descriptor *desc; char name[14]; unsigned stopped:1, ep_type:2, diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 3608b3bd5732..8981fbb5748c 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -390,7 +390,7 @@ static int alloc_pipe_config(struct m66592_ep *ep, int *counter; int ret; - ep->desc = desc; + ep->ep.desc = desc; BUG_ON(ep->pipenum); @@ -558,7 +558,7 @@ static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req) static void start_packet(struct m66592_ep *ep, struct m66592_request *req) { - if (ep->desc->bEndpointAddress & USB_DIR_IN) + if (ep->ep.desc->bEndpointAddress & USB_DIR_IN) start_packet_write(ep, req); else start_packet_read(ep, req); @@ -734,7 +734,7 @@ __acquires(m66592->lock) if (restart) { req = list_entry(ep->queue.next, struct m66592_request, queue); - if (ep->desc) + if (ep->ep.desc) start_packet(ep, req); } } @@ -917,7 +917,7 @@ static void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb) ep = m66592->pipenum2ep[pipenum]; req = list_entry(ep->queue.next, struct m66592_request, queue); - if (ep->desc->bEndpointAddress & USB_DIR_IN) + if (ep->ep.desc->bEndpointAddress & USB_DIR_IN) irq_packet_write(ep, req); else irq_packet_read(ep, req); @@ -1377,7 +1377,7 @@ static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req, req->req.actual = 0; req->req.status = -EINPROGRESS; - if (ep->desc == NULL) /* control */ + if (ep->ep.desc == NULL) /* control */ start_ep0(ep, req); else { if (request && !ep->busy) diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h index 9d9f7e39f037..88c85b4116a2 100644 --- a/drivers/usb/gadget/m66592-udc.h +++ b/drivers/usb/gadget/m66592-udc.h @@ -456,7 +456,7 @@ struct m66592_ep { unsigned use_dma:1; u16 pipenum; u16 type; - const struct usb_endpoint_descriptor *desc; + /* register address */ unsigned long fifoaddr; unsigned long fifosel; diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h index e2be9519abbe..9073436d8b24 100644 --- a/drivers/usb/gadget/mv_udc.h +++ b/drivers/usb/gadget/mv_udc.h @@ -232,7 +232,6 @@ struct mv_ep { struct mv_udc *udc; struct list_head queue; struct mv_dqh *dqh; - const struct usb_endpoint_descriptor *desc; u32 direction; char name[14]; unsigned stopped:1, diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index a73cf406e2a4..dbcd1329495e 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -464,7 +464,7 @@ static int mv_ep_enable(struct usb_ep *_ep, ep = container_of(_ep, struct mv_ep, ep); udc = ep->udc; - if (!_ep || !desc || ep->desc + if (!_ep || !desc || ep->ep.desc || desc->bDescriptorType != USB_DT_ENDPOINT) return -EINVAL; @@ -528,7 +528,7 @@ static int mv_ep_enable(struct usb_ep *_ep, dqh->size_ioc_int_sts = 0; ep->ep.maxpacket = max; - ep->desc = desc; + ep->ep.desc = desc; ep->stopped = 0; /* Enable the endpoint for Rx or Tx and set the endpoint type */ @@ -580,7 +580,7 @@ static int mv_ep_disable(struct usb_ep *_ep) unsigned long flags; ep = container_of(_ep, struct mv_ep, ep); - if ((_ep == NULL) || !ep->desc) + if ((_ep == NULL) || !ep->ep.desc) return -EINVAL; udc = ep->udc; @@ -606,7 +606,6 @@ static int mv_ep_disable(struct usb_ep *_ep) /* nuke all pending requests (does flush) */ nuke(ep, -ESHUTDOWN); - ep->desc = NULL; ep->ep.desc = NULL; ep->stopped = 1; @@ -651,7 +650,7 @@ static void mv_ep_fifo_flush(struct usb_ep *_ep) return; ep = container_of(_ep, struct mv_ep, ep); - if (!ep->desc) + if (!ep->ep.desc) return; udc = ep->udc; @@ -715,11 +714,11 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) dev_err(&udc->dev->dev, "%s, bad params", __func__); return -EINVAL; } - if (unlikely(!_ep || !ep->desc)) { + if (unlikely(!_ep || !ep->ep.desc)) { dev_err(&udc->dev->dev, "%s, bad ep", __func__); return -EINVAL; } - if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { + if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { if (req->req.length > ep->ep.maxpacket) return -EMSGSIZE; } @@ -925,12 +924,12 @@ static int mv_ep_set_halt_wedge(struct usb_ep *_ep, int halt, int wedge) ep = container_of(_ep, struct mv_ep, ep); udc = ep->udc; - if (!_ep || !ep->desc) { + if (!_ep || !ep->ep.desc) { status = -EINVAL; goto out; } - if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { + if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { status = -EOPNOTSUPP; goto out; } @@ -1279,7 +1278,7 @@ static int eps_init(struct mv_udc *udc) ep->stopped = 0; ep->ep.maxpacket = EP0_MAX_PKT_SIZE; ep->ep_num = 0; - ep->desc = &mv_ep0_desc; + ep->ep.desc = &mv_ep0_desc; INIT_LIST_HEAD(&ep->queue); ep->ep_type = USB_ENDPOINT_XFER_CONTROL; diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 3b4b6dd0f95a..7ba32469c5bd 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -153,7 +153,7 @@ static int omap_ep_enable(struct usb_ep *_ep, u16 maxp; /* catch various bogus parameters */ - if (!_ep || !desc || ep->desc + if (!_ep || !desc || ep->ep.desc || desc->bDescriptorType != USB_DT_ENDPOINT || ep->bEndpointAddress != desc->bEndpointAddress || ep->maxpacket < usb_endpoint_maxp(desc)) { @@ -200,7 +200,7 @@ static int omap_ep_enable(struct usb_ep *_ep, spin_lock_irqsave(&udc->lock, flags); - ep->desc = desc; + ep->ep.desc = desc; ep->irqs = 0; ep->stopped = 0; ep->ep.maxpacket = maxp; @@ -242,14 +242,13 @@ static int omap_ep_disable(struct usb_ep *_ep) struct omap_ep *ep = container_of(_ep, struct omap_ep, ep); unsigned long flags; - if (!_ep || !ep->desc) { + if (!_ep || !ep->ep.desc) { DBG("%s, %s not enabled\n", __func__, _ep ? ep->ep.name : NULL); return -EINVAL; } spin_lock_irqsave(&ep->udc->lock, flags); - ep->desc = NULL; ep->ep.desc = NULL; nuke (ep, -ESHUTDOWN); ep->ep.maxpacket = ep->maxpacket; @@ -917,7 +916,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) DBG("%s, bad params\n", __func__); return -EINVAL; } - if (!_ep || (!ep->desc && ep->bEndpointAddress)) { + if (!_ep || (!ep->ep.desc && ep->bEndpointAddress)) { DBG("%s, bad ep\n", __func__); return -EINVAL; } @@ -1121,7 +1120,7 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value) status = 0; /* otherwise, all active non-ISO endpoints can halt */ - } else if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC && ep->desc) { + } else if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC && ep->ep.desc) { /* IN endpoints must already be idle */ if ((ep->bEndpointAddress & USB_DIR_IN) @@ -1625,7 +1624,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) if (w_index & USB_DIR_IN) ep += 16; if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC - || !ep->desc) + || !ep->ep.desc) goto do_stall; use_ep(ep, 0); omap_writew(udc->clr_halt, UDC_CTRL); @@ -1653,7 +1652,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) if (w_index & USB_DIR_IN) ep += 16; if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC - || ep == ep0 || !ep->desc) + || ep == ep0 || !ep->ep.desc) goto do_stall; if (use_dma && ep->has_dma) { /* this has rude side-effects (aborts) and @@ -1688,7 +1687,7 @@ ep0out_status_stage: ep = &udc->ep[w_index & 0xf]; if (w_index & USB_DIR_IN) ep += 16; - if (!ep->desc) + if (!ep->ep.desc) goto do_stall; /* iso never stalls */ @@ -2509,7 +2508,7 @@ static int proc_udc_show(struct seq_file *s, void *_) if (tmp & UDC_ADD) { list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) { - if (ep->desc) + if (ep->ep.desc) proc_ep_show(s, ep); } } diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h index 59d3b2213cb1..cfadeb5fc5de 100644 --- a/drivers/usb/gadget/omap_udc.h +++ b/drivers/usb/gadget/omap_udc.h @@ -140,7 +140,6 @@ struct omap_ep { struct list_head queue; unsigned long irqs; struct list_head iso; - const struct usb_endpoint_descriptor *desc; char name[14]; u16 maxpacket; u8 bEndpointAddress; diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 65307064a6fd..1cfcc9ecbfbc 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -295,7 +295,6 @@ struct pch_udc_ep { struct pch_udc_data_dma_desc *td_data; struct pch_udc_dev *dev; unsigned long offset_addr; - const struct usb_endpoint_descriptor *desc; struct list_head queue; unsigned num:5, in:1, @@ -1705,7 +1704,7 @@ static int pch_udc_pcd_ep_enable(struct usb_ep *usbep, if (!dev->driver || (dev->gadget.speed == USB_SPEED_UNKNOWN)) return -ESHUTDOWN; spin_lock_irqsave(&dev->lock, iflags); - ep->desc = desc; + ep->ep.desc = desc; ep->halted = 0; pch_udc_ep_enable(ep, &ep->dev->cfg_data, desc); ep->ep.maxpacket = usb_endpoint_maxp(desc); @@ -1734,7 +1733,7 @@ static int pch_udc_pcd_ep_disable(struct usb_ep *usbep) ep = container_of(usbep, struct pch_udc_ep, ep); dev = ep->dev; - if ((usbep->name == ep0_string) || !ep->desc) + if ((usbep->name == ep0_string) || !ep->ep.desc) return -EINVAL; spin_lock_irqsave(&ep->dev->lock, iflags); @@ -1742,7 +1741,6 @@ static int pch_udc_pcd_ep_disable(struct usb_ep *usbep) ep->halted = 1; pch_udc_ep_disable(ep); pch_udc_disable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num)); - ep->desc = NULL; ep->ep.desc = NULL; INIT_LIST_HEAD(&ep->queue); spin_unlock_irqrestore(&ep->dev->lock, iflags); @@ -1849,7 +1847,7 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq, return -EINVAL; ep = container_of(usbep, struct pch_udc_ep, ep); dev = ep->dev; - if (!ep->desc && ep->num) + if (!ep->ep.desc && ep->num) return -EINVAL; req = container_of(usbreq, struct pch_udc_request, req); if (!list_empty(&req->queue)) @@ -1949,7 +1947,7 @@ static int pch_udc_pcd_dequeue(struct usb_ep *usbep, ep = container_of(usbep, struct pch_udc_ep, ep); dev = ep->dev; - if (!usbep || !usbreq || (!ep->desc && ep->num)) + if (!usbep || !usbreq || (!ep->ep.desc && ep->num)) return ret; req = container_of(usbreq, struct pch_udc_request, req); spin_lock_irqsave(&ep->dev->lock, flags); @@ -1988,7 +1986,7 @@ static int pch_udc_pcd_set_halt(struct usb_ep *usbep, int halt) return -EINVAL; ep = container_of(usbep, struct pch_udc_ep, ep); dev = ep->dev; - if (!ep->desc && !ep->num) + if (!ep->ep.desc && !ep->num) return -EINVAL; if (!ep->dev->driver || (ep->dev->gadget.speed == USB_SPEED_UNKNOWN)) return -ESHUTDOWN; @@ -2033,7 +2031,7 @@ static int pch_udc_pcd_set_wedge(struct usb_ep *usbep) return -EINVAL; ep = container_of(usbep, struct pch_udc_ep, ep); dev = ep->dev; - if (!ep->desc && !ep->num) + if (!ep->ep.desc && !ep->num) return -EINVAL; if (!ep->dev->driver || (ep->dev->gadget.speed == USB_SPEED_UNKNOWN)) return -ESHUTDOWN; @@ -2065,7 +2063,7 @@ static void pch_udc_pcd_fifo_flush(struct usb_ep *usbep) return; ep = container_of(usbep, struct pch_udc_ep, ep); - if (ep->desc || !ep->num) + if (ep->ep.desc || !ep->num) pch_udc_ep_fifo_flush(ep, ep->in); } @@ -3282,7 +3280,6 @@ static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = { MODULE_DEVICE_TABLE(pci, pch_udc_pcidev_id); - static struct pci_driver pch_udc_driver = { .name = KBUILD_MODNAME, .id_table = pch_udc_pcidev_id, @@ -3293,17 +3290,7 @@ static struct pci_driver pch_udc_driver = { .shutdown = pch_udc_shutdown, }; -static int __init pch_udc_pci_init(void) -{ - return pci_register_driver(&pch_udc_driver); -} -module_init(pch_udc_pci_init); - -static void __exit pch_udc_pci_exit(void) -{ - pci_unregister_driver(&pch_udc_driver); -} -module_exit(pch_udc_pci_exit); +module_pci_driver(pch_udc_driver); MODULE_DESCRIPTION("Intel EG20T USB Device Controller"); MODULE_AUTHOR("LAPIS Semiconductor, <tomoya-linux@dsn.lapis-semi.com>"); diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 4e4dc1f5f388..f1f9290a2f47 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -51,6 +51,7 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ +#include "composite.c" #include "usbstring.c" #include "config.c" #include "epautoconf.c" @@ -75,8 +76,6 @@ struct printer_dev { /* lock buffer lists during read/write calls */ struct mutex lock_printer_io; struct usb_gadget *gadget; - struct usb_request *req; /* for control responses */ - u8 config; s8 interface; struct usb_ep *in_ep, *out_ep; @@ -100,6 +99,7 @@ struct printer_dev { struct device *pdev; u8 printer_cdev_open; wait_queue_head_t wait; + struct usb_function function; }; static struct printer_dev usb_printer_gadget; @@ -120,26 +120,6 @@ static struct printer_dev usb_printer_gadget; * parameters are in UTF-8 (superset of ASCII's 7 bit characters). */ -static ushort idVendor; -module_param(idVendor, ushort, S_IRUGO); -MODULE_PARM_DESC(idVendor, "USB Vendor ID"); - -static ushort idProduct; -module_param(idProduct, ushort, S_IRUGO); -MODULE_PARM_DESC(idProduct, "USB Product ID"); - -static ushort bcdDevice; -module_param(bcdDevice, ushort, S_IRUGO); -MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); - -static char *iManufacturer; -module_param(iManufacturer, charp, S_IRUGO); -MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); - -static char *iProduct; -module_param(iProduct, charp, S_IRUGO); -MODULE_PARM_DESC(iProduct, "USB Product string"); - static char *iSerialNum; module_param(iSerialNum, charp, S_IRUGO); MODULE_PARM_DESC(iSerialNum, "1"); @@ -154,47 +134,8 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR); #define QLEN qlen -#ifdef CONFIG_USB_GADGET_DUALSPEED -#define DEVSPEED USB_SPEED_HIGH -#else /* full speed (low speed doesn't do bulk) */ -#define DEVSPEED USB_SPEED_FULL -#endif - /*-------------------------------------------------------------------------*/ -#define xprintk(d, level, fmt, args...) \ - printk(level "%s: " fmt, DRIVER_DESC, ## args) - -#ifdef DEBUG -#define DBG(dev, fmt, args...) \ - xprintk(dev, KERN_DEBUG, fmt, ## args) -#else -#define DBG(dev, fmt, args...) \ - do { } while (0) -#endif /* DEBUG */ - -#ifdef VERBOSE -#define VDBG(dev, fmt, args...) \ - xprintk(dev, KERN_DEBUG, fmt, ## args) -#else -#define VDBG(dev, fmt, args...) \ - do { } while (0) -#endif /* VERBOSE */ - -#define ERROR(dev, fmt, args...) \ - xprintk(dev, KERN_ERR, fmt, ## args) -#define WARNING(dev, fmt, args...) \ - xprintk(dev, KERN_WARNING, fmt, ## args) -#define INFO(dev, fmt, args...) \ - xprintk(dev, KERN_INFO, fmt, ## args) - -/*-------------------------------------------------------------------------*/ - -/* USB DRIVER HOOKUP (to the hardware driver, below us), mostly - * ep0 implementation: descriptors, config management, setup(). - * also optional class-specific notification interrupt transfer. - */ - /* * DESCRIPTORS ... most are static, but strings and (full) configuration * descriptors are built on demand. @@ -227,24 +168,6 @@ static struct usb_device_descriptor device_desc = { .bNumConfigurations = 1 }; -static struct usb_otg_descriptor otg_desc = { - .bLength = sizeof otg_desc, - .bDescriptorType = USB_DT_OTG, - .bmAttributes = USB_OTG_SRP -}; - -static struct usb_config_descriptor config_desc = { - .bLength = sizeof config_desc, - .bDescriptorType = USB_DT_CONFIG, - - /* compute wTotalLength on the fly */ - .bNumInterfaces = 1, - .bConfigurationValue = DEV_CONFIG_VALUE, - .iConfiguration = 0, - .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2, -}; - static struct usb_interface_descriptor intf_desc = { .bLength = sizeof intf_desc, .bDescriptorType = USB_DT_INTERFACE, @@ -270,16 +193,13 @@ static struct usb_endpoint_descriptor fs_ep_out_desc = { .bmAttributes = USB_ENDPOINT_XFER_BULK }; -static const struct usb_descriptor_header *fs_printer_function [11] = { - (struct usb_descriptor_header *) &otg_desc, +static struct usb_descriptor_header *fs_printer_function[] = { (struct usb_descriptor_header *) &intf_desc, (struct usb_descriptor_header *) &fs_ep_in_desc, (struct usb_descriptor_header *) &fs_ep_out_desc, NULL }; -#ifdef CONFIG_USB_GADGET_DUALSPEED - /* * usb 2.0 devices need to expose both high speed and full speed * descriptors, unless they only run at full speed. @@ -307,23 +227,26 @@ static struct usb_qualifier_descriptor dev_qualifier = { .bNumConfigurations = 1 }; -static const struct usb_descriptor_header *hs_printer_function [11] = { - (struct usb_descriptor_header *) &otg_desc, +static struct usb_descriptor_header *hs_printer_function[] = { (struct usb_descriptor_header *) &intf_desc, (struct usb_descriptor_header *) &hs_ep_in_desc, (struct usb_descriptor_header *) &hs_ep_out_desc, NULL }; -/* maxpacket and other transfer characteristics vary by speed. */ -#define ep_desc(g, hs, fs) (((g)->speed == USB_SPEED_HIGH)?(hs):(fs)) - -#else +static struct usb_otg_descriptor otg_descriptor = { + .bLength = sizeof otg_descriptor, + .bDescriptorType = USB_DT_OTG, + .bmAttributes = USB_OTG_SRP, +}; -/* if there's no high speed support, maxpacket doesn't change. */ -#define ep_desc(g, hs, fs) (((void)(g)), (fs)) +static const struct usb_descriptor_header *otg_desc[] = { + (struct usb_descriptor_header *) &otg_descriptor, + NULL, +}; -#endif /* !CONFIG_USB_GADGET_DUALSPEED */ +/* maxpacket and other transfer characteristics vary by speed. */ +#define ep_desc(g, hs, fs) (((g)->speed == USB_SPEED_HIGH)?(hs):(fs)) /*-------------------------------------------------------------------------*/ @@ -343,11 +266,16 @@ static struct usb_string strings [] = { { } /* end of list */ }; -static struct usb_gadget_strings stringtab = { +static struct usb_gadget_strings stringtab_dev = { .language = 0x0409, /* en-us */ .strings = strings, }; +static struct usb_gadget_strings *dev_strings[] = { + &stringtab_dev, + NULL, +}; + /*-------------------------------------------------------------------------*/ static struct usb_request * @@ -937,82 +865,8 @@ static void printer_reset_interface(struct printer_dev *dev) dev->interface = -1; } -/* change our operational config. must agree with the code - * that returns config descriptors, and altsetting code. - */ -static int -printer_set_config(struct printer_dev *dev, unsigned number) -{ - int result = 0; - struct usb_gadget *gadget = dev->gadget; - - switch (number) { - case DEV_CONFIG_VALUE: - result = 0; - break; - default: - result = -EINVAL; - /* FALL THROUGH */ - case 0: - break; - } - - if (result) { - usb_gadget_vbus_draw(dev->gadget, - dev->gadget->is_otg ? 8 : 100); - } else { - unsigned power; - - power = 2 * config_desc.bMaxPower; - usb_gadget_vbus_draw(dev->gadget, power); - - dev->config = number; - INFO(dev, "%s config #%d: %d mA, %s\n", - usb_speed_string(gadget->speed), - number, power, driver_desc); - } - return result; -} - -static int -config_buf(enum usb_device_speed speed, u8 *buf, u8 type, unsigned index, - int is_otg) -{ - int len; - const struct usb_descriptor_header **function; -#ifdef CONFIG_USB_GADGET_DUALSPEED - int hs = (speed == USB_SPEED_HIGH); - - if (type == USB_DT_OTHER_SPEED_CONFIG) - hs = !hs; - - if (hs) { - function = hs_printer_function; - } else { - function = fs_printer_function; - } -#else - function = fs_printer_function; -#endif - - if (index >= device_desc.bNumConfigurations) - return -EINVAL; - - /* for now, don't advertise srp-only devices */ - if (!is_otg) - function++; - - len = usb_gadget_config_buf(&config_desc, buf, USB_DESC_BUFSIZE, - function); - if (len < 0) - return len; - ((struct usb_config_descriptor *) buf)->bDescriptorType = type; - return len; -} - /* Change our operational Interface. */ -static int -set_interface(struct printer_dev *dev, unsigned number) +static int set_interface(struct printer_dev *dev, unsigned number) { int result = 0; @@ -1043,14 +897,6 @@ set_interface(struct printer_dev *dev, unsigned number) return result; } -static void printer_setup_complete(struct usb_ep *ep, struct usb_request *req) -{ - if (req->status || req->actual != req->length) - DBG((struct printer_dev *) ep->driver_data, - "setup complete --> %d, %d/%d\n", - req->status, req->actual, req->length); -} - static void printer_soft_reset(struct printer_dev *dev) { struct usb_request *req; @@ -1107,11 +953,12 @@ static void printer_soft_reset(struct printer_dev *dev) * The setup() callback implements all the ep0 functionality that's not * handled lower down. */ -static int -printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) +static int printer_func_setup(struct usb_function *f, + const struct usb_ctrlrequest *ctrl) { - struct printer_dev *dev = get_gadget_data(gadget); - struct usb_request *req = dev->req; + struct printer_dev *dev = container_of(f, struct printer_dev, function); + struct usb_composite_dev *cdev = f->config->cdev; + struct usb_request *req = cdev->req; int value = -EOPNOTSUPP; u16 wIndex = le16_to_cpu(ctrl->wIndex); u16 wValue = le16_to_cpu(ctrl->wValue); @@ -1120,102 +967,7 @@ printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) DBG(dev, "ctrl req%02x.%02x v%04x i%04x l%d\n", ctrl->bRequestType, ctrl->bRequest, wValue, wIndex, wLength); - req->complete = printer_setup_complete; - switch (ctrl->bRequestType&USB_TYPE_MASK) { - - case USB_TYPE_STANDARD: - switch (ctrl->bRequest) { - - case USB_REQ_GET_DESCRIPTOR: - if (ctrl->bRequestType != USB_DIR_IN) - break; - switch (wValue >> 8) { - - case USB_DT_DEVICE: - device_desc.bMaxPacketSize0 = - gadget->ep0->maxpacket; - value = min(wLength, (u16) sizeof device_desc); - memcpy(req->buf, &device_desc, value); - break; -#ifdef CONFIG_USB_GADGET_DUALSPEED - case USB_DT_DEVICE_QUALIFIER: - if (!gadget_is_dualspeed(gadget)) - break; - /* - * assumes ep0 uses the same value for both - * speeds - */ - dev_qualifier.bMaxPacketSize0 = - gadget->ep0->maxpacket; - value = min(wLength, - (u16) sizeof dev_qualifier); - memcpy(req->buf, &dev_qualifier, value); - break; - - case USB_DT_OTHER_SPEED_CONFIG: - if (!gadget_is_dualspeed(gadget)) - break; - /* FALLTHROUGH */ -#endif /* CONFIG_USB_GADGET_DUALSPEED */ - case USB_DT_CONFIG: - value = config_buf(gadget->speed, req->buf, - wValue >> 8, - wValue & 0xff, - gadget->is_otg); - if (value >= 0) - value = min(wLength, (u16) value); - break; - - case USB_DT_STRING: - value = usb_gadget_get_string(&stringtab, - wValue & 0xff, req->buf); - if (value >= 0) - value = min(wLength, (u16) value); - break; - } - break; - - case USB_REQ_SET_CONFIGURATION: - if (ctrl->bRequestType != 0) - break; - if (gadget->a_hnp_support) - DBG(dev, "HNP available\n"); - else if (gadget->a_alt_hnp_support) - DBG(dev, "HNP needs a different root port\n"); - value = printer_set_config(dev, wValue); - if (!value) - value = set_interface(dev, PRINTER_INTERFACE); - break; - case USB_REQ_GET_CONFIGURATION: - if (ctrl->bRequestType != USB_DIR_IN) - break; - *(u8 *)req->buf = dev->config; - value = min(wLength, (u16) 1); - break; - - case USB_REQ_SET_INTERFACE: - if (ctrl->bRequestType != USB_RECIP_INTERFACE || - !dev->config) - break; - - value = set_interface(dev, PRINTER_INTERFACE); - break; - case USB_REQ_GET_INTERFACE: - if (ctrl->bRequestType != - (USB_DIR_IN|USB_RECIP_INTERFACE) - || !dev->config) - break; - - *(u8 *)req->buf = dev->interface; - value = min(wLength, (u16) 1); - break; - - default: - goto unknown; - } - break; - case USB_TYPE_CLASS: switch (ctrl->bRequest) { case 0: /* Get the IEEE-1284 PNP String */ @@ -1261,44 +1013,50 @@ unknown: wValue, wIndex, wLength); break; } - - /* respond with data transfer before status phase? */ - if (value >= 0) { - req->length = value; - req->zero = value < wLength; - value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); - if (value < 0) { - DBG(dev, "ep_queue --> %d\n", value); - req->status = 0; - printer_setup_complete(gadget->ep0, req); - } - } - /* host either stalls (value < 0) or reports success */ return value; } -static void -printer_disconnect(struct usb_gadget *gadget) +static int __init printer_func_bind(struct usb_configuration *c, + struct usb_function *f) { - struct printer_dev *dev = get_gadget_data(gadget); + return 0; +} + +static void printer_func_unbind(struct usb_configuration *c, + struct usb_function *f) +{ +} + +static int printer_func_set_alt(struct usb_function *f, + unsigned intf, unsigned alt) +{ + struct printer_dev *dev = container_of(f, struct printer_dev, function); + int ret = -ENOTSUPP; + + if (!alt) + ret = set_interface(dev, PRINTER_INTERFACE); + return ret; +} + +static void printer_func_disable(struct usb_function *f) +{ + struct printer_dev *dev = container_of(f, struct printer_dev, function); unsigned long flags; DBG(dev, "%s\n", __func__); spin_lock_irqsave(&dev->lock, flags); - printer_reset_interface(dev); - spin_unlock_irqrestore(&dev->lock, flags); } -static void -printer_unbind(struct usb_gadget *gadget) +static void printer_cfg_unbind(struct usb_configuration *c) { - struct printer_dev *dev = get_gadget_data(gadget); + struct printer_dev *dev; struct usb_request *req; + dev = &usb_printer_gadget; DBG(dev, "%s\n", __func__); @@ -1336,18 +1094,18 @@ printer_unbind(struct usb_gadget *gadget) list_del(&req->list); printer_req_free(dev->out_ep, req); } - - if (dev->req) { - printer_req_free(gadget->ep0, dev->req); - dev->req = NULL; - } - - set_gadget_data(gadget, NULL); } -static int __init -printer_bind(struct usb_gadget *gadget) +static struct usb_configuration printer_cfg_driver = { + .label = "printer", + .unbind = printer_cfg_unbind, + .bConfigurationValue = 1, + .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, +}; + +static int __init printer_bind_config(struct usb_configuration *c) { + struct usb_gadget *gadget = c->cdev->gadget; struct printer_dev *dev; struct usb_ep *in_ep, *out_ep; int status = -ENOMEM; @@ -1358,6 +1116,14 @@ printer_bind(struct usb_gadget *gadget) dev = &usb_printer_gadget; + dev->function.name = shortname; + dev->function.descriptors = fs_printer_function; + dev->function.hs_descriptors = hs_printer_function; + dev->function.bind = printer_func_bind; + dev->function.setup = printer_func_setup; + dev->function.unbind = printer_func_unbind; + dev->function.set_alt = printer_func_set_alt; + dev->function.disable = printer_func_disable; /* Setup the sysfs files for the printer gadget. */ dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno, @@ -1393,29 +1159,6 @@ printer_bind(struct usb_gadget *gadget) init_utsname()->sysname, init_utsname()->release, gadget->name); - device_desc.idVendor = - cpu_to_le16(PRINTER_VENDOR_NUM); - device_desc.idProduct = - cpu_to_le16(PRINTER_PRODUCT_NUM); - - /* support optional vendor/distro customization */ - if (idVendor) { - if (!idProduct) { - dev_err(&gadget->dev, "idVendor needs idProduct!\n"); - return -ENODEV; - } - device_desc.idVendor = cpu_to_le16(idVendor); - device_desc.idProduct = cpu_to_le16(idProduct); - if (bcdDevice) - device_desc.bcdDevice = cpu_to_le16(bcdDevice); - } - - if (iManufacturer) - strlcpy(manufacturer, iManufacturer, sizeof manufacturer); - - if (iProduct) - strlcpy(product_desc, iProduct, sizeof product_desc); - if (iSerialNum) strlcpy(serial_num, iSerialNum, sizeof serial_num); @@ -1442,17 +1185,16 @@ autoconf_fail: goto autoconf_fail; out_ep->driver_data = out_ep; /* claim */ -#ifdef CONFIG_USB_GADGET_DUALSPEED /* assumes that all endpoints are dual-speed */ hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress; hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress; -#endif /* DUALSPEED */ usb_gadget_set_selfpowered(gadget); if (gadget->is_otg) { - otg_desc.bmAttributes |= USB_OTG_HNP, - config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + otg_descriptor.bmAttributes |= USB_OTG_HNP; + printer_cfg_driver.descriptors = otg_desc; + printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; } spin_lock_init(&dev->lock); @@ -1466,7 +1208,6 @@ autoconf_fail: init_waitqueue_head(&dev->tx_wait); init_waitqueue_head(&dev->tx_flush_wait); - dev->config = 0; dev->interface = -1; dev->printer_cdev_open = 0; dev->printer_status = PRINTER_NOT_ERROR; @@ -1477,14 +1218,6 @@ autoconf_fail: dev->in_ep = in_ep; dev->out_ep = out_ep; - /* preallocate control message data and buffer */ - dev->req = printer_req_alloc(gadget->ep0, USB_DESC_BUFSIZE, - GFP_KERNEL); - if (!dev->req) { - status = -ENOMEM; - goto fail; - } - for (i = 0; i < QLEN; i++) { req = printer_req_alloc(dev->in_ep, USB_BUFSIZE, GFP_KERNEL); if (!req) { @@ -1513,45 +1246,37 @@ autoconf_fail: list_add(&req->list, &dev->rx_reqs); } - dev->req->complete = printer_setup_complete; - /* finish hookup to lower layer ... */ dev->gadget = gadget; - set_gadget_data(gadget, dev); - gadget->ep0->driver_data = dev; INFO(dev, "%s, version: " DRIVER_VERSION "\n", driver_desc); INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, out_ep->name, in_ep->name); - return 0; fail: - printer_unbind(gadget); + printer_cfg_unbind(c); return status; } -/*-------------------------------------------------------------------------*/ +static int printer_unbind(struct usb_composite_dev *cdev) +{ + return 0; +} -static struct usb_gadget_driver printer_driver = { - .max_speed = DEVSPEED, +static int __init printer_bind(struct usb_composite_dev *cdev) +{ + return usb_add_config(cdev, &printer_cfg_driver, printer_bind_config); +} - .function = (char *) driver_desc, +static struct usb_composite_driver printer_driver = { + .name = shortname, + .dev = &device_desc, + .strings = dev_strings, + .max_speed = USB_SPEED_HIGH, .unbind = printer_unbind, - - .setup = printer_setup, - .disconnect = printer_disconnect, - - .driver = { - .name = (char *) shortname, - .owner = THIS_MODULE, - }, }; -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR("Craig Nadler"); -MODULE_LICENSE("GPL"); - static int __init init(void) { @@ -1560,23 +1285,23 @@ init(void) usb_gadget_class = class_create(THIS_MODULE, "usb_printer_gadget"); if (IS_ERR(usb_gadget_class)) { status = PTR_ERR(usb_gadget_class); - ERROR(dev, "unable to create usb_gadget class %d\n", status); + pr_err("unable to create usb_gadget class %d\n", status); return status; } status = alloc_chrdev_region(&g_printer_devno, 0, 1, "USB printer gadget"); if (status) { - ERROR(dev, "alloc_chrdev_region %d\n", status); + pr_err("alloc_chrdev_region %d\n", status); class_destroy(usb_gadget_class); return status; } - status = usb_gadget_probe_driver(&printer_driver, printer_bind); + status = usb_composite_probe(&printer_driver, printer_bind); if (status) { class_destroy(usb_gadget_class); unregister_chrdev_region(g_printer_devno, 1); - DBG(dev, "usb_gadget_probe_driver %x\n", status); + pr_err("usb_gadget_probe_driver %x\n", status); } return status; @@ -1586,15 +1311,14 @@ module_init(init); static void __exit cleanup(void) { - int status; - mutex_lock(&usb_printer_gadget.lock_printer_io); - status = usb_gadget_unregister_driver(&printer_driver); - if (status) - ERROR(dev, "usb_gadget_unregister_driver %x\n", status); - + usb_composite_unregister(&printer_driver); unregister_chrdev_region(g_printer_devno, 1); class_destroy(usb_gadget_class); mutex_unlock(&usb_printer_gadget.lock_printer_io); } module_exit(cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Craig Nadler"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 41ed69c96d8c..d7c8cb3bf759 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -218,7 +218,7 @@ static int pxa25x_ep_enable (struct usb_ep *_ep, struct pxa25x_udc *dev; ep = container_of (_ep, struct pxa25x_ep, ep); - if (!_ep || !desc || ep->desc || _ep->name == ep0name + if (!_ep || !desc || ep->ep.desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT || ep->bEndpointAddress != desc->bEndpointAddress || ep->fifo_size < usb_endpoint_maxp (desc)) { @@ -249,7 +249,7 @@ static int pxa25x_ep_enable (struct usb_ep *_ep, return -ESHUTDOWN; } - ep->desc = desc; + ep->ep.desc = desc; ep->stopped = 0; ep->pio_irqs = 0; ep->ep.maxpacket = usb_endpoint_maxp (desc); @@ -269,7 +269,7 @@ static int pxa25x_ep_disable (struct usb_ep *_ep) unsigned long flags; ep = container_of (_ep, struct pxa25x_ep, ep); - if (!_ep || !ep->desc) { + if (!_ep || !ep->ep.desc) { DMSG("%s, %s not enabled\n", __func__, _ep ? ep->ep.name : NULL); return -EINVAL; @@ -281,7 +281,6 @@ static int pxa25x_ep_disable (struct usb_ep *_ep) /* flush fifo (mostly for IN buffers) */ pxa25x_ep_fifo_flush (_ep); - ep->desc = NULL; ep->ep.desc = NULL; ep->stopped = 1; @@ -390,7 +389,7 @@ write_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) { unsigned max; - max = usb_endpoint_maxp(ep->desc); + max = usb_endpoint_maxp(ep->ep.desc); do { unsigned count; int is_last, is_short; @@ -644,7 +643,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) } ep = container_of(_ep, struct pxa25x_ep, ep); - if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) { + if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) { DMSG("%s, bad ep\n", __func__); return -EINVAL; } @@ -660,7 +659,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) * we can report per-packet status. that also helps with dma. */ if (unlikely (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC - && req->req.length > usb_endpoint_maxp (ep->desc))) + && req->req.length > usb_endpoint_maxp(ep->ep.desc))) return -EMSGSIZE; DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n", @@ -673,7 +672,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) /* kickstart this i/o queue? */ if (list_empty(&ep->queue) && !ep->stopped) { - if (ep->desc == NULL/* ep0 */) { + if (ep->ep.desc == NULL/* ep0 */) { unsigned length = _req->length; switch (dev->ep0state) { @@ -722,7 +721,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) req = NULL; } - if (likely (req && ep->desc)) + if (likely(req && ep->ep.desc)) pio_irq_enable(ep->bEndpointAddress); } @@ -749,7 +748,7 @@ static void nuke(struct pxa25x_ep *ep, int status) queue); done(ep, req, status); } - if (ep->desc) + if (ep->ep.desc) pio_irq_disable (ep->bEndpointAddress); } @@ -792,7 +791,7 @@ static int pxa25x_ep_set_halt(struct usb_ep *_ep, int value) ep = container_of(_ep, struct pxa25x_ep, ep); if (unlikely (!_ep - || (!ep->desc && ep->ep.name != ep0name)) + || (!ep->ep.desc && ep->ep.name != ep0name)) || ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) { DMSG("%s, bad ep\n", __func__); return -EINVAL; @@ -820,7 +819,7 @@ static int pxa25x_ep_set_halt(struct usb_ep *_ep, int value) *ep->reg_udccs = UDCCS_BI_FST|UDCCS_BI_FTF; /* ep0 needs special care */ - if (!ep->desc) { + if (!ep->ep.desc) { start_watchdog(ep->dev); ep->dev->req_pending = 0; ep->dev->ep0state = EP0_STALL; @@ -1087,7 +1086,7 @@ udc_seq_show(struct seq_file *m, void *_d) if (i != 0) { const struct usb_endpoint_descriptor *desc; - desc = ep->desc; + desc = ep->ep.desc; if (!desc) continue; tmp = *dev->ep [i].reg_udccs; @@ -1191,7 +1190,6 @@ static void udc_reinit(struct pxa25x_udc *dev) if (i != 0) list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list); - ep->desc = NULL; ep->ep.desc = NULL; ep->stopped = 0; INIT_LIST_HEAD (&ep->queue); diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/pxa25x_udc.h index 893e917f048e..861f4df6ea22 100644 --- a/drivers/usb/gadget/pxa25x_udc.h +++ b/drivers/usb/gadget/pxa25x_udc.h @@ -41,7 +41,6 @@ struct pxa25x_ep { struct usb_ep ep; struct pxa25x_udc *dev; - const struct usb_endpoint_descriptor *desc; struct list_head queue; unsigned long pio_irqs; diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index c4401e7dd3a6..f3ac2a20c27c 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -459,7 +459,7 @@ static int alloc_pipe_config(struct r8a66597_ep *ep, unsigned char *counter; int ret; - ep->desc = desc; + ep->ep.desc = desc; if (ep->pipenum) /* already allocated pipe */ return 0; @@ -648,7 +648,7 @@ static int sudmac_alloc_channel(struct r8a66597 *r8a66597, /* set SUDMAC parameters */ dma = &r8a66597->dma; dma->used = 1; - if (ep->desc->bEndpointAddress & USB_DIR_IN) { + if (ep->ep.desc->bEndpointAddress & USB_DIR_IN) { dma->dir = 1; } else { dma->dir = 0; @@ -770,7 +770,7 @@ static void start_packet_read(struct r8a66597_ep *ep, static void start_packet(struct r8a66597_ep *ep, struct r8a66597_request *req) { - if (ep->desc->bEndpointAddress & USB_DIR_IN) + if (ep->ep.desc->bEndpointAddress & USB_DIR_IN) start_packet_write(ep, req); else start_packet_read(ep, req); @@ -930,7 +930,7 @@ __acquires(r8a66597->lock) if (restart) { req = get_request_from_ep(ep); - if (ep->desc) + if (ep->ep.desc) start_packet(ep, req); } } @@ -1116,7 +1116,7 @@ static void irq_pipe_ready(struct r8a66597 *r8a66597, u16 status, u16 enb) r8a66597_write(r8a66597, ~check, BRDYSTS); ep = r8a66597->pipenum2ep[pipenum]; req = get_request_from_ep(ep); - if (ep->desc->bEndpointAddress & USB_DIR_IN) + if (ep->ep.desc->bEndpointAddress & USB_DIR_IN) irq_packet_write(ep, req); else irq_packet_read(ep, req); @@ -1170,7 +1170,7 @@ __acquires(r8a66597->lock) switch (ctrl->bRequestType & USB_RECIP_MASK) { case USB_RECIP_DEVICE: - status = 1 << USB_DEVICE_SELF_POWERED; + status = r8a66597->device_status; break; case USB_RECIP_INTERFACE: status = 0; @@ -1627,7 +1627,7 @@ static int r8a66597_queue(struct usb_ep *_ep, struct usb_request *_req, req->req.actual = 0; req->req.status = -EINPROGRESS; - if (ep->desc == NULL) /* control */ + if (ep->ep.desc == NULL) /* control */ start_ep0(ep, req); else { if (request && !ep->busy) @@ -1692,7 +1692,7 @@ static int r8a66597_set_wedge(struct usb_ep *_ep) ep = container_of(_ep, struct r8a66597_ep, ep); - if (!ep || !ep->desc) + if (!ep || !ep->ep.desc) return -EINVAL; spin_lock_irqsave(&ep->r8a66597->lock, flags); @@ -1800,11 +1800,24 @@ static int r8a66597_pullup(struct usb_gadget *gadget, int is_on) return 0; } +static int r8a66597_set_selfpowered(struct usb_gadget *gadget, int is_self) +{ + struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget); + + if (is_self) + r8a66597->device_status |= 1 << USB_DEVICE_SELF_POWERED; + else + r8a66597->device_status &= ~(1 << USB_DEVICE_SELF_POWERED); + + return 0; +} + static struct usb_gadget_ops r8a66597_gadget_ops = { .get_frame = r8a66597_get_frame, .udc_start = r8a66597_start, .udc_stop = r8a66597_stop, .pullup = r8a66597_pullup, + .set_selfpowered = r8a66597_set_selfpowered, }; static int __exit r8a66597_remove(struct platform_device *pdev) diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h index 8e3de61cd4b8..99908c76ccd1 100644 --- a/drivers/usb/gadget/r8a66597-udc.h +++ b/drivers/usb/gadget/r8a66597-udc.h @@ -72,7 +72,7 @@ struct r8a66597_ep { unsigned use_dma:1; u16 pipenum; u16 type; - const struct usb_endpoint_descriptor *desc; + /* register address */ unsigned char fifoaddr; unsigned char fifosel; @@ -111,6 +111,7 @@ struct r8a66597 { u16 old_vbus; u16 scount; u16 old_dvsq; + u16 device_status; /* for GET_STATUS */ /* pipe config */ unsigned char bulk; diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 105b206cd844..5061a2fe9620 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -1,4 +1,5 @@ -/* linux/drivers/usb/gadget/s3c-hsotg.c +/** + * linux/drivers/usb/gadget/s3c-hsotg.c * * Copyright (c) 2011 Samsung Electronics Co., Ltd. * http://www.samsung.com @@ -13,7 +14,7 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. -*/ + */ #include <linux/kernel.h> #include <linux/module.h> @@ -27,21 +28,25 @@ #include <linux/io.h> #include <linux/slab.h> #include <linux/clk.h> +#include <linux/regulator/consumer.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> #include <mach/map.h> -#include <plat/regs-usb-hsotg-phy.h> -#include <plat/regs-usb-hsotg.h> -#include <mach/regs-sys.h> -#include <plat/udc-hs.h> -#include <plat/cpu.h> +#include "s3c-hsotg.h" +#include <linux/platform_data/s3c-hsotg.h> #define DMA_ADDR_INVALID (~((dma_addr_t)0)) -/* EP0_MPS_LIMIT +static const char * const s3c_hsotg_supply_names[] = { + "vusb_d", /* digital USB supply, 1.2V */ + "vusb_a", /* analog USB supply, 1.1V */ +}; + +/* + * EP0_MPS_LIMIT * * Unfortunately there seems to be a limit of the amount of data that can * be transferred by IN transactions on EP0. This is either 127 bytes or 3 @@ -125,8 +130,6 @@ struct s3c_hsotg_ep { char name[10]; }; -#define S3C_HSOTG_EPS (8+1) /* limit to 9 for the moment */ - /** * struct s3c_hsotg - driver state. * @dev: The parent device supplied to the probe function @@ -135,7 +138,9 @@ 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 + * @supplies: Definition of USB power supplies * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos. + * @num_of_eps: Number of available EPs (excluding EP0) * @debug_root: root directrory for debugfs. * @debug_file: main status file for debugfs. * @debug_fifo: FIFO status file for debugfs. @@ -143,6 +148,8 @@ struct s3c_hsotg_ep { * @ep0_buff: Buffer for EP0 reply data, if needed. * @ctrl_buff: Buffer for EP0 control requests. * @ctrl_req: Request for EP0 control packets. + * @setup: NAK management for EP0 SETUP + * @last_rst: Time of last reset * @eps: The endpoints being supplied to the gadget framework */ struct s3c_hsotg { @@ -155,7 +162,10 @@ struct s3c_hsotg { int irq; struct clk *clk; + struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsotg_supply_names)]; + unsigned int dedicated_fifos:1; + unsigned char num_of_eps; struct dentry *debug_root; struct dentry *debug_file; @@ -167,7 +177,9 @@ struct s3c_hsotg { u8 ctrl_buff[8]; struct usb_gadget gadget; - struct s3c_hsotg_ep eps[]; + unsigned int setup; + unsigned long last_rst; + struct s3c_hsotg_ep *eps; }; /** @@ -244,14 +256,14 @@ static inline bool using_dma(struct s3c_hsotg *hsotg) */ static void s3c_hsotg_en_gsint(struct s3c_hsotg *hsotg, u32 ints) { - u32 gsintmsk = readl(hsotg->regs + S3C_GINTMSK); + u32 gsintmsk = readl(hsotg->regs + GINTMSK); u32 new_gsintmsk; new_gsintmsk = gsintmsk | ints; if (new_gsintmsk != gsintmsk) { dev_dbg(hsotg->dev, "gsintmsk now 0x%08x\n", new_gsintmsk); - writel(new_gsintmsk, hsotg->regs + S3C_GINTMSK); + writel(new_gsintmsk, hsotg->regs + GINTMSK); } } @@ -262,13 +274,13 @@ static void s3c_hsotg_en_gsint(struct s3c_hsotg *hsotg, u32 ints) */ static void s3c_hsotg_disable_gsint(struct s3c_hsotg *hsotg, u32 ints) { - u32 gsintmsk = readl(hsotg->regs + S3C_GINTMSK); + u32 gsintmsk = readl(hsotg->regs + GINTMSK); u32 new_gsintmsk; new_gsintmsk = gsintmsk & ~ints; if (new_gsintmsk != gsintmsk) - writel(new_gsintmsk, hsotg->regs + S3C_GINTMSK); + writel(new_gsintmsk, hsotg->regs + GINTMSK); } /** @@ -293,12 +305,12 @@ static void s3c_hsotg_ctrl_epint(struct s3c_hsotg *hsotg, bit <<= 16; local_irq_save(flags); - daint = readl(hsotg->regs + S3C_DAINTMSK); + daint = readl(hsotg->regs + DAINTMSK); if (en) daint |= bit; else daint &= ~bit; - writel(daint, hsotg->regs + S3C_DAINTMSK); + writel(daint, hsotg->regs + DAINTMSK); local_irq_restore(flags); } @@ -314,52 +326,51 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg) int timeout; u32 val; - /* the ryu 2.6.24 release ahs - writel(0x1C0, hsotg->regs + S3C_GRXFSIZ); - writel(S3C_GNPTXFSIZ_NPTxFStAddr(0x200) | - S3C_GNPTXFSIZ_NPTxFDep(0x1C0), - hsotg->regs + S3C_GNPTXFSIZ); - */ - /* set FIFO sizes to 2048/1024 */ - writel(2048, hsotg->regs + S3C_GRXFSIZ); - writel(S3C_GNPTXFSIZ_NPTxFStAddr(2048) | - S3C_GNPTXFSIZ_NPTxFDep(1024), - hsotg->regs + S3C_GNPTXFSIZ); + writel(2048, hsotg->regs + GRXFSIZ); + writel(GNPTXFSIZ_NPTxFStAddr(2048) | + GNPTXFSIZ_NPTxFDep(1024), + hsotg->regs + GNPTXFSIZ); - /* arange all the rest of the TX FIFOs, as some versions of this + /* + * arange all the rest of the TX FIFOs, as some versions of this * block have overlapping default addresses. This also ensures * that if the settings have been changed, then they are set to - * known values. */ + * known values. + */ /* start at the end of the GNPTXFSIZ, rounded up */ addr = 2048 + 1024; size = 768; - /* currently we allocate TX FIFOs for all possible endpoints, - * and assume that they are all the same size. */ + /* + * currently we allocate TX FIFOs for all possible endpoints, + * and assume that they are all the same size. + */ for (ep = 1; ep <= 15; ep++) { val = addr; - val |= size << S3C_DPTXFSIZn_DPTxFSize_SHIFT; + val |= size << DPTXFSIZn_DPTxFSize_SHIFT; addr += size; - writel(val, hsotg->regs + S3C_DPTXFSIZn(ep)); + writel(val, hsotg->regs + DPTXFSIZn(ep)); } - /* according to p428 of the design guide, we need to ensure that - * all fifos are flushed before continuing */ + /* + * according to p428 of the design guide, we need to ensure that + * all fifos are flushed before continuing + */ - writel(S3C_GRSTCTL_TxFNum(0x10) | S3C_GRSTCTL_TxFFlsh | - S3C_GRSTCTL_RxFFlsh, hsotg->regs + S3C_GRSTCTL); + writel(GRSTCTL_TxFNum(0x10) | GRSTCTL_TxFFlsh | + GRSTCTL_RxFFlsh, hsotg->regs + GRSTCTL); /* wait until the fifos are both flushed */ timeout = 100; while (1) { - val = readl(hsotg->regs + S3C_GRSTCTL); + val = readl(hsotg->regs + GRSTCTL); - if ((val & (S3C_GRSTCTL_TxFFlsh | S3C_GRSTCTL_RxFFlsh)) == 0) + if ((val & (GRSTCTL_TxFFlsh | GRSTCTL_RxFFlsh)) == 0) break; if (--timeout == 0) { @@ -415,7 +426,7 @@ static inline int is_ep_periodic(struct s3c_hsotg_ep *hs_ep) * * This is the reverse of s3c_hsotg_map_dma(), called for the completion * of a request to ensure the buffer is ready for access by the caller. -*/ + */ static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg, struct s3c_hsotg_ep *hs_ep, struct s3c_hsotg_req *hs_req) @@ -456,13 +467,13 @@ static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg, * otherwise -ENOSPC is returned if the FIFO space was used up. * * This routine is only needed for PIO -*/ + */ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, struct s3c_hsotg_ep *hs_ep, struct s3c_hsotg_req *hs_req) { bool periodic = is_ep_periodic(hs_ep); - u32 gnptxsts = readl(hsotg->regs + S3C_GNPTXSTS); + u32 gnptxsts = readl(hsotg->regs + GNPTXSTS); int buf_pos = hs_req->req.actual; int to_write = hs_ep->size_loaded; void *data; @@ -476,20 +487,23 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, return 0; if (periodic && !hsotg->dedicated_fifos) { - u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index)); + u32 epsize = readl(hsotg->regs + DIEPTSIZ(hs_ep->index)); int size_left; int size_done; - /* work out how much data was loaded so we can calculate - * how much data is left in the fifo. */ + /* + * work out how much data was loaded so we can calculate + * how much data is left in the fifo. + */ - size_left = S3C_DxEPTSIZ_XferSize_GET(epsize); + size_left = DxEPTSIZ_XferSize_GET(epsize); - /* if shared fifo, we cannot write anything until the + /* + * if shared fifo, we cannot write anything until the * previous data has been completely sent. */ if (hs_ep->fifo_load != 0) { - s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp); + s3c_hsotg_en_gsint(hsotg, GINTSTS_PTxFEmp); return -ENOSPC; } @@ -510,47 +524,50 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, __func__, can_write); if (can_write <= 0) { - s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp); + s3c_hsotg_en_gsint(hsotg, 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 = readl(hsotg->regs + DTXFSTS(hs_ep->index)); can_write &= 0xffff; can_write *= 4; } else { - if (S3C_GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) { + if (GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) { dev_dbg(hsotg->dev, "%s: no queue slots available (0x%08x)\n", __func__, gnptxsts); - s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_NPTxFEmp); + s3c_hsotg_en_gsint(hsotg, GINTSTS_NPTxFEmp); return -ENOSPC; } - can_write = S3C_GNPTXSTS_NPTxFSpcAvail_GET(gnptxsts); + can_write = GNPTXSTS_NPTxFSpcAvail_GET(gnptxsts); can_write *= 4; /* fifo size is in 32bit quantities. */ } dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, mps %d\n", __func__, gnptxsts, can_write, to_write, hs_ep->ep.maxpacket); - /* limit to 512 bytes of data, it seems at least on the non-periodic + /* + * limit to 512 bytes of data, it seems at least on the non-periodic * FIFO, requests of >512 cause the endpoint to get stuck with a * fragment of the end of the transfer in it. */ if (can_write > 512) can_write = 512; - /* limit the write to one max-packet size worth of data, but allow + /* + * limit the write to one max-packet size worth of data, but allow * the transfer to return that it did not run out of fifo space - * doing it. */ + * doing it. + */ if (to_write > hs_ep->ep.maxpacket) { to_write = hs_ep->ep.maxpacket; s3c_hsotg_en_gsint(hsotg, - periodic ? S3C_GINTSTS_PTxFEmp : - S3C_GINTSTS_NPTxFEmp); + periodic ? GINTSTS_PTxFEmp : + GINTSTS_NPTxFEmp); } /* see if we can write data */ @@ -559,8 +576,8 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, to_write = can_write; pkt_round = to_write % hs_ep->ep.maxpacket; - /* Not sure, but we probably shouldn't be writing partial - * packets into the FIFO, so round the write down to an + /* + * Round the write down to an * exact number of packets. * * Note, we do not currently check to see if we can ever @@ -570,12 +587,14 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, if (pkt_round) to_write -= pkt_round; - /* enable correct FIFO interrupt to alert us when there - * is more room left. */ + /* + * enable correct FIFO interrupt to alert us when there + * is more room left. + */ s3c_hsotg_en_gsint(hsotg, - periodic ? S3C_GINTSTS_PTxFEmp : - S3C_GINTSTS_NPTxFEmp); + periodic ? GINTSTS_PTxFEmp : + GINTSTS_NPTxFEmp); } dev_dbg(hsotg->dev, "write %d/%d, can_write %d, done %d\n", @@ -593,7 +612,7 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, to_write = DIV_ROUND_UP(to_write, 4); data = hs_req->req.buf + buf_pos; - writesl(hsotg->regs + S3C_EPFIFO(hs_ep->index), data, to_write); + writesl(hsotg->regs + EPFIFO(hs_ep->index), data, to_write); return (to_write >= can_write) ? -ENOSPC : 0; } @@ -612,12 +631,12 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep) unsigned maxpkt; if (index != 0) { - maxsize = S3C_DxEPTSIZ_XferSize_LIMIT + 1; - maxpkt = S3C_DxEPTSIZ_PktCnt_LIMIT + 1; + maxsize = DxEPTSIZ_XferSize_LIMIT + 1; + maxpkt = DxEPTSIZ_PktCnt_LIMIT + 1; } else { maxsize = 64+64; if (hs_ep->dir_in) - maxpkt = S3C_DIEPTSIZ0_PktCnt_LIMIT + 1; + maxpkt = DIEPTSIZ0_PktCnt_LIMIT + 1; else maxpkt = 2; } @@ -626,8 +645,10 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep) maxpkt--; maxsize--; - /* constrain by packet count if maxpkts*pktsize is greater - * than the length register size. */ + /* + * constrain by packet count if maxpkts*pktsize is greater + * than the length register size. + */ if ((maxpkt * hs_ep->ep.maxpacket) < maxsize) maxsize = maxpkt * hs_ep->ep.maxpacket; @@ -674,8 +695,8 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, } } - epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index); - epsize_reg = dir_in ? S3C_DIEPTSIZ(index) : S3C_DOEPTSIZ(index); + epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); + epsize_reg = dir_in ? DIEPTSIZ(index) : DOEPTSIZ(index); dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x, ep %d, dir %s\n", __func__, readl(hsotg->regs + epctrl_reg), index, @@ -684,13 +705,14 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, /* If endpoint is stalled, we will restart request later */ ctrl = readl(hsotg->regs + epctrl_reg); - if (ctrl & S3C_DxEPCTL_Stall) { + if (ctrl & DxEPCTL_Stall) { dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index); return; } length = ureq->length - ureq->actual; - + dev_dbg(hsotg->dev, "ureq->length:%d ureq->actual:%d\n", + ureq->length, ureq->actual); if (0) dev_dbg(hsotg->dev, "REQ buf %p len %d dma 0x%08x noi=%d zp=%d snok=%d\n", @@ -717,20 +739,22 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, packets = 1; /* send one packet if length is zero. */ if (dir_in && index != 0) - epsize = S3C_DxEPTSIZ_MC(1); + epsize = DxEPTSIZ_MC(1); else epsize = 0; if (index != 0 && ureq->zero) { - /* test for the packets being exactly right for the - * transfer */ + /* + * test for the packets being exactly right for the + * transfer + */ if (length == (packets * hs_ep->ep.maxpacket)) packets++; } - epsize |= S3C_DxEPTSIZ_PktCnt(packets); - epsize |= S3C_DxEPTSIZ_XferSize(length); + epsize |= DxEPTSIZ_PktCnt(packets); + epsize |= DxEPTSIZ_XferSize(length); dev_dbg(hsotg->dev, "%s: %d@%d/%d, 0x%08x => 0x%08x\n", __func__, packets, length, ureq->length, epsize, epsize_reg); @@ -744,26 +768,38 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, if (using_dma(hsotg) && !continuing) { unsigned int dma_reg; - /* write DMA address to control register, buffer already - * synced by s3c_hsotg_ep_queue(). */ + /* + * write DMA address to control register, buffer already + * synced by s3c_hsotg_ep_queue(). + */ - dma_reg = dir_in ? S3C_DIEPDMA(index) : S3C_DOEPDMA(index); + dma_reg = dir_in ? DIEPDMA(index) : DOEPDMA(index); writel(ureq->dma, hsotg->regs + dma_reg); dev_dbg(hsotg->dev, "%s: 0x%08x => 0x%08x\n", __func__, ureq->dma, dma_reg); } - ctrl |= S3C_DxEPCTL_EPEna; /* ensure ep enabled */ - ctrl |= S3C_DxEPCTL_USBActEp; - ctrl |= S3C_DxEPCTL_CNAK; /* clear NAK set by core */ + ctrl |= DxEPCTL_EPEna; /* ensure ep enabled */ + ctrl |= DxEPCTL_USBActEp; + + dev_dbg(hsotg->dev, "setup req:%d\n", hsotg->setup); + + /* For Setup request do not clear NAK */ + if (hsotg->setup && index == 0) + hsotg->setup = 0; + else + ctrl |= DxEPCTL_CNAK; /* clear NAK set by core */ + dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl); writel(ctrl, hsotg->regs + epctrl_reg); - /* set these, it seems that DMA support increments past the end + /* + * set these, it seems that DMA support increments past the end * of the packet buffer so we need to calculate the length from - * this information. */ + * this information. + */ hs_ep->size_loaded = length; hs_ep->last_load = ureq->actual; @@ -774,17 +810,21 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, s3c_hsotg_write_fifo(hsotg, hs_ep, hs_req); } - /* clear the INTknTXFEmpMsk when we start request, more as a aide - * to debugging to see what is going on. */ + /* + * clear the INTknTXFEmpMsk when we start request, more as a aide + * to debugging to see what is going on. + */ if (dir_in) - writel(S3C_DIEPMSK_INTknTXFEmpMsk, - hsotg->regs + S3C_DIEPINT(index)); + writel(DIEPMSK_INTknTXFEmpMsk, + hsotg->regs + DIEPINT(index)); - /* Note, trying to clear the NAK here causes problems with transmit - * on the S3C6400 ending up with the TXFIFO becoming full. */ + /* + * Note, trying to clear the NAK here causes problems with transmit + * on the S3C6400 ending up with the TXFIFO becoming full. + */ /* check ep is enabled */ - if (!(readl(hsotg->regs + epctrl_reg) & S3C_DxEPCTL_EPEna)) + if (!(readl(hsotg->regs + epctrl_reg) & DxEPCTL_EPEna)) dev_warn(hsotg->dev, "ep%d: failed to become enabled (DxEPCTL=0x%08x)?\n", index, readl(hsotg->regs + epctrl_reg)); @@ -804,7 +844,7 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, * then ensure the buffer has been synced to memory. If our buffer has no * DMA memory, then we map the memory and mark our request to allow us to * cleanup on completion. -*/ + */ static int s3c_hsotg_map_dma(struct s3c_hsotg *hsotg, struct s3c_hsotg_ep *hs_ep, struct usb_request *req) @@ -922,7 +962,7 @@ static void s3c_hsotg_complete_oursetup(struct usb_ep *ep, * * Convert the given wIndex into a pointer to an driver endpoint * structure, or return NULL if it is not a valid endpoint. -*/ + */ static struct s3c_hsotg_ep *ep_from_windex(struct s3c_hsotg *hsotg, u32 windex) { @@ -933,7 +973,7 @@ static struct s3c_hsotg_ep *ep_from_windex(struct s3c_hsotg *hsotg, if (windex >= 0x100) return NULL; - if (idx > S3C_HSOTG_EPS) + if (idx > hsotg->num_of_eps) return NULL; if (idx && ep->dir_in != dir) @@ -1151,24 +1191,28 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, ctrl->bRequest, ctrl->bRequestType, ctrl->wValue, ctrl->wLength); - /* record the direction of the request, for later use when enquing - * packets onto EP0. */ + /* + * record the direction of the request, for later use when enquing + * packets onto EP0. + */ ep0->dir_in = (ctrl->bRequestType & USB_DIR_IN) ? 1 : 0; dev_dbg(hsotg->dev, "ctrl: dir_in=%d\n", ep0->dir_in); - /* if we've no data with this request, then the last part of the - * transaction is going to implicitly be IN. */ + /* + * if we've no data with this request, then the last part of the + * transaction is going to implicitly be IN. + */ if (ctrl->wLength == 0) ep0->dir_in = 1; if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { switch (ctrl->bRequest) { case USB_REQ_SET_ADDRESS: - dcfg = readl(hsotg->regs + S3C_DCFG); - dcfg &= ~S3C_DCFG_DevAddr_MASK; - dcfg |= ctrl->wValue << S3C_DCFG_DevAddr_SHIFT; - writel(dcfg, hsotg->regs + S3C_DCFG); + dcfg = readl(hsotg->regs + DCFG); + dcfg &= ~DCFG_DevAddr_MASK; + dcfg |= ctrl->wValue << DCFG_DevAddr_SHIFT; + writel(dcfg, hsotg->regs + DCFG); dev_info(hsotg->dev, "new address %d\n", ctrl->wValue); @@ -1194,7 +1238,8 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret); } - /* the request is either unhandlable, or is not formatted correctly + /* + * the request is either unhandlable, or is not formatted correctly * so respond with a STALL for the status stage to indicate failure. */ @@ -1203,22 +1248,26 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, u32 ctrl; dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in); - reg = (ep0->dir_in) ? S3C_DIEPCTL0 : S3C_DOEPCTL0; + reg = (ep0->dir_in) ? DIEPCTL0 : DOEPCTL0; - /* S3C_DxEPCTL_Stall will be cleared by EP once it has - * taken effect, so no need to clear later. */ + /* + * DxEPCTL_Stall will be cleared by EP once it has + * taken effect, so no need to clear later. + */ ctrl = readl(hsotg->regs + reg); - ctrl |= S3C_DxEPCTL_Stall; - ctrl |= S3C_DxEPCTL_CNAK; + ctrl |= DxEPCTL_Stall; + ctrl |= DxEPCTL_CNAK; writel(ctrl, hsotg->regs + reg); dev_dbg(hsotg->dev, "written DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n", ctrl, reg, readl(hsotg->regs + reg)); - /* don't believe we need to anything more to get the EP - * to reply with a STALL packet */ + /* + * don't believe we need to anything more to get the EP + * to reply with a STALL packet + */ } } @@ -1279,8 +1328,10 @@ static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg) ret = s3c_hsotg_ep_queue(&hsotg->eps[0].ep, req, GFP_ATOMIC); if (ret < 0) { dev_err(hsotg->dev, "%s: failed queue (%d)\n", __func__, ret); - /* Don't think there's much we can do other than watch the - * driver fail. */ + /* + * Don't think there's much we can do other than watch the + * driver fail. + */ } } @@ -1296,7 +1347,7 @@ static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg) * on the endpoint. * * Note, expects the ep to already be locked as appropriate. -*/ + */ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, struct s3c_hsotg_ep *hs_ep, struct s3c_hsotg_req *hs_req, @@ -1312,8 +1363,10 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, dev_dbg(hsotg->dev, "complete: ep %p %s, req %p, %d => %p\n", hs_ep, hs_ep->ep.name, hs_req, result, hs_req->req.complete); - /* only replace the status if we've not already set an error - * from a previous transaction */ + /* + * only replace the status if we've not already set an error + * from a previous transaction + */ if (hs_req->req.status == -EINPROGRESS) hs_req->req.status = result; @@ -1324,8 +1377,10 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, if (using_dma(hsotg)) s3c_hsotg_unmap_dma(hsotg, hs_ep, hs_req); - /* call the complete request with the locks off, just in case the - * request tries to queue more work for this endpoint. */ + /* + * call the complete request with the locks off, just in case the + * request tries to queue more work for this endpoint. + */ if (hs_req->req.complete) { spin_unlock(&hs_ep->lock); @@ -1333,9 +1388,11 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, spin_lock(&hs_ep->lock); } - /* Look to see if there is anything else to do. Note, the completion + /* + * Look to see if there is anything else to do. Note, the completion * of the previous request may have caused a new request to be started - * so be careful when doing this. */ + * so be careful when doing this. + */ if (!hs_ep->req && result >= 0) { restart = !list_empty(&hs_ep->queue); @@ -1355,7 +1412,7 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, * * See s3c_hsotg_complete_request(), but called with the endpoint's * lock held. -*/ + */ static void s3c_hsotg_complete_request_lock(struct s3c_hsotg *hsotg, struct s3c_hsotg_ep *hs_ep, struct s3c_hsotg_req *hs_req, @@ -1382,13 +1439,13 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) { struct s3c_hsotg_ep *hs_ep = &hsotg->eps[ep_idx]; struct s3c_hsotg_req *hs_req = hs_ep->req; - void __iomem *fifo = hsotg->regs + S3C_EPFIFO(ep_idx); + void __iomem *fifo = hsotg->regs + EPFIFO(ep_idx); int to_read; int max_req; int read_ptr; if (!hs_req) { - u32 epctl = readl(hsotg->regs + S3C_DOEPCTL(ep_idx)); + u32 epctl = readl(hsotg->regs + DOEPCTL(ep_idx)); int ptr; dev_warn(hsotg->dev, @@ -1412,7 +1469,8 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) __func__, to_read, max_req, read_ptr, hs_req->req.length); if (to_read > max_req) { - /* more data appeared than we where willing + /* + * more data appeared than we where willing * to deal with in this request. */ @@ -1424,8 +1482,10 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) hs_req->req.actual += to_read; to_read = DIV_ROUND_UP(to_read, 4); - /* note, we might over-write the buffer end by 3 bytes depending on - * alignment of the data. */ + /* + * note, we might over-write the buffer end by 3 bytes depending on + * alignment of the data. + */ readsl(fifo, hs_req->req.buf + read_ptr, to_read); spin_unlock(&hs_ep->lock); @@ -1465,14 +1525,14 @@ static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg, dev_dbg(hsotg->dev, "sending zero-length packet\n"); /* issue a zero-sized packet to terminate this */ - writel(S3C_DxEPTSIZ_MC(1) | S3C_DxEPTSIZ_PktCnt(1) | - S3C_DxEPTSIZ_XferSize(0), hsotg->regs + S3C_DIEPTSIZ(0)); + writel(DxEPTSIZ_MC(1) | DxEPTSIZ_PktCnt(1) | + DxEPTSIZ_XferSize(0), hsotg->regs + DIEPTSIZ(0)); - ctrl = readl(hsotg->regs + S3C_DIEPCTL0); - ctrl |= S3C_DxEPCTL_CNAK; /* clear NAK set by core */ - ctrl |= S3C_DxEPCTL_EPEna; /* ensure ep enabled */ - ctrl |= S3C_DxEPCTL_USBActEp; - writel(ctrl, hsotg->regs + S3C_DIEPCTL0); + ctrl = readl(hsotg->regs + DIEPCTL0); + ctrl |= DxEPCTL_CNAK; /* clear NAK set by core */ + ctrl |= DxEPCTL_EPEna; /* ensure ep enabled */ + ctrl |= DxEPCTL_USBActEp; + writel(ctrl, hsotg->regs + DIEPCTL0); } /** @@ -1484,15 +1544,15 @@ static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg, * The RXFIFO has delivered an OutDone event, which means that the data * transfer for an OUT endpoint has been completed, either by a short * packet or by the finish of a transfer. -*/ + */ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, int epnum, bool was_setup) { - u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum)); + u32 epsize = readl(hsotg->regs + DOEPTSIZ(epnum)); struct s3c_hsotg_ep *hs_ep = &hsotg->eps[epnum]; struct s3c_hsotg_req *hs_req = hs_ep->req; struct usb_request *req = &hs_req->req; - unsigned size_left = S3C_DxEPTSIZ_XferSize_GET(epsize); + unsigned size_left = DxEPTSIZ_XferSize_GET(epsize); int result = 0; if (!hs_req) { @@ -1503,7 +1563,8 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, if (using_dma(hsotg)) { unsigned size_done; - /* Calculate the size of the transfer by checking how much + /* + * Calculate the size of the transfer by checking how much * is left in the endpoint size register and then working it * out from the amount we loaded for the transfer. * @@ -1521,17 +1582,29 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, if (req->actual < req->length && size_left == 0) { s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true); return; + } else if (epnum == 0) { + /* + * After was_setup = 1 => + * set CNAK for non Setup requests + */ + hsotg->setup = was_setup ? 0 : 1; } if (req->actual < req->length && req->short_not_ok) { dev_dbg(hsotg->dev, "%s: got %d/%d (short not ok) => error\n", __func__, req->actual, req->length); - /* todo - what should we return here? there's no one else - * even bothering to check the status. */ + /* + * todo - what should we return here? there's no one else + * even bothering to check the status. + */ } if (epnum == 0) { + /* + * Condition req->complete != s3c_hsotg_complete_setup says: + * send ZLP when we have an asynchronous request from gadget + */ if (!was_setup && req->complete != s3c_hsotg_complete_setup) s3c_hsotg_send_zlp(hsotg, hs_req); } @@ -1544,14 +1617,14 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, * @hsotg: The device instance * * Return the current frame number -*/ + */ static u32 s3c_hsotg_read_frameno(struct s3c_hsotg *hsotg) { u32 dsts; - dsts = readl(hsotg->regs + S3C_DSTS); - dsts &= S3C_DSTS_SOFFN_MASK; - dsts >>= S3C_DSTS_SOFFN_SHIFT; + dsts = readl(hsotg->regs + DSTS); + dsts &= DSTS_SOFFN_MASK; + dsts >>= DSTS_SOFFN_SHIFT; return dsts; } @@ -1574,29 +1647,29 @@ static u32 s3c_hsotg_read_frameno(struct s3c_hsotg *hsotg) */ static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg) { - u32 grxstsr = readl(hsotg->regs + S3C_GRXSTSP); + u32 grxstsr = readl(hsotg->regs + GRXSTSP); u32 epnum, status, size; WARN_ON(using_dma(hsotg)); - epnum = grxstsr & S3C_GRXSTS_EPNum_MASK; - status = grxstsr & S3C_GRXSTS_PktSts_MASK; + epnum = grxstsr & GRXSTS_EPNum_MASK; + status = grxstsr & GRXSTS_PktSts_MASK; - size = grxstsr & S3C_GRXSTS_ByteCnt_MASK; - size >>= S3C_GRXSTS_ByteCnt_SHIFT; + size = grxstsr & GRXSTS_ByteCnt_MASK; + size >>= GRXSTS_ByteCnt_SHIFT; if (1) dev_dbg(hsotg->dev, "%s: GRXSTSP=0x%08x (%d@%d)\n", __func__, grxstsr, size, epnum); -#define __status(x) ((x) >> S3C_GRXSTS_PktSts_SHIFT) +#define __status(x) ((x) >> GRXSTS_PktSts_SHIFT) - switch (status >> S3C_GRXSTS_PktSts_SHIFT) { - case __status(S3C_GRXSTS_PktSts_GlobalOutNAK): + switch (status >> GRXSTS_PktSts_SHIFT) { + case __status(GRXSTS_PktSts_GlobalOutNAK): dev_dbg(hsotg->dev, "GlobalOutNAK\n"); break; - case __status(S3C_GRXSTS_PktSts_OutDone): + case __status(GRXSTS_PktSts_OutDone): dev_dbg(hsotg->dev, "OutDone (Frame=0x%08x)\n", s3c_hsotg_read_frameno(hsotg)); @@ -1604,24 +1677,24 @@ static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg) s3c_hsotg_handle_outdone(hsotg, epnum, false); break; - case __status(S3C_GRXSTS_PktSts_SetupDone): + case __status(GRXSTS_PktSts_SetupDone): dev_dbg(hsotg->dev, "SetupDone (Frame=0x%08x, DOPEPCTL=0x%08x)\n", s3c_hsotg_read_frameno(hsotg), - readl(hsotg->regs + S3C_DOEPCTL(0))); + readl(hsotg->regs + DOEPCTL(0))); s3c_hsotg_handle_outdone(hsotg, epnum, true); break; - case __status(S3C_GRXSTS_PktSts_OutRX): + case __status(GRXSTS_PktSts_OutRX): s3c_hsotg_rx_data(hsotg, epnum, size); break; - case __status(S3C_GRXSTS_PktSts_SetupRX): + case __status(GRXSTS_PktSts_SetupRX): dev_dbg(hsotg->dev, "SetupRX (Frame=0x%08x, DOPEPCTL=0x%08x)\n", s3c_hsotg_read_frameno(hsotg), - readl(hsotg->regs + S3C_DOEPCTL(0))); + readl(hsotg->regs + DOEPCTL(0))); s3c_hsotg_rx_data(hsotg, epnum, size); break; @@ -1638,18 +1711,18 @@ static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg) /** * s3c_hsotg_ep0_mps - turn max packet size into register setting * @mps: The maximum packet size in bytes. -*/ + */ static u32 s3c_hsotg_ep0_mps(unsigned int mps) { switch (mps) { case 64: - return S3C_D0EPCTL_MPS_64; + return D0EPCTL_MPS_64; case 32: - return S3C_D0EPCTL_MPS_32; + return D0EPCTL_MPS_32; case 16: - return S3C_D0EPCTL_MPS_16; + return D0EPCTL_MPS_16; case 8: - return S3C_D0EPCTL_MPS_8; + return D0EPCTL_MPS_8; } /* bad max packet size, warn and return invalid result */ @@ -1680,7 +1753,7 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg, if (mpsval > 3) goto bad_mps; } else { - if (mps >= S3C_DxEPCTL_MPS_LIMIT+1) + if (mps >= DxEPCTL_MPS_LIMIT+1) goto bad_mps; mpsval = mps; @@ -1688,19 +1761,21 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg, hs_ep->ep.maxpacket = mps; - /* update both the in and out endpoint controldir_ registers, even - * if one of the directions may not be in use. */ + /* + * update both the in and out endpoint controldir_ registers, even + * if one of the directions may not be in use. + */ - reg = readl(regs + S3C_DIEPCTL(ep)); - reg &= ~S3C_DxEPCTL_MPS_MASK; + reg = readl(regs + DIEPCTL(ep)); + reg &= ~DxEPCTL_MPS_MASK; reg |= mpsval; - writel(reg, regs + S3C_DIEPCTL(ep)); + writel(reg, regs + DIEPCTL(ep)); if (ep) { - reg = readl(regs + S3C_DOEPCTL(ep)); - reg &= ~S3C_DxEPCTL_MPS_MASK; + reg = readl(regs + DOEPCTL(ep)); + reg &= ~DxEPCTL_MPS_MASK; reg |= mpsval; - writel(reg, regs + S3C_DOEPCTL(ep)); + writel(reg, regs + DOEPCTL(ep)); } return; @@ -1719,16 +1794,16 @@ static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx) int timeout; int val; - writel(S3C_GRSTCTL_TxFNum(idx) | S3C_GRSTCTL_TxFFlsh, - hsotg->regs + S3C_GRSTCTL); + writel(GRSTCTL_TxFNum(idx) | GRSTCTL_TxFFlsh, + hsotg->regs + GRSTCTL); /* wait until the fifo is flushed */ timeout = 100; while (1) { - val = readl(hsotg->regs + S3C_GRSTCTL); + val = readl(hsotg->regs + GRSTCTL); - if ((val & (S3C_GRSTCTL_TxFFlsh)) == 0) + if ((val & (GRSTCTL_TxFFlsh)) == 0) break; if (--timeout == 0) { @@ -1778,7 +1853,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, struct s3c_hsotg_ep *hs_ep) { struct s3c_hsotg_req *hs_req = hs_ep->req; - u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index)); + u32 epsize = readl(hsotg->regs + DIEPTSIZ(hs_ep->index)); int size_left, size_done; if (!hs_req) { @@ -1786,7 +1861,15 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, return; } - /* Calculate the size of the transfer by checking how much is left + /* Finish ZLP handling for IN EP0 transactions */ + if (hsotg->eps[0].sent_zlp) { + dev_dbg(hsotg->dev, "zlp packet received\n"); + s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, 0); + return; + } + + /* + * Calculate the size of the transfer by checking how much is left * in the endpoint size register and then working it out from * the amount we loaded for the transfer. * @@ -1795,7 +1878,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, * aligned). */ - size_left = S3C_DxEPTSIZ_XferSize_GET(epsize); + size_left = DxEPTSIZ_XferSize_GET(epsize); size_done = hs_ep->size_loaded - size_left; size_done += hs_ep->last_load; @@ -1805,9 +1888,28 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, __func__, hs_req->req.actual, size_done); hs_req->req.actual = size_done; + dev_dbg(hsotg->dev, "req->length:%d req->actual:%d req->zero:%d\n", + hs_req->req.length, hs_req->req.actual, hs_req->req.zero); + + /* + * Check if dealing with Maximum Packet Size(MPS) IN transfer at EP0 + * When sent data is a multiple MPS size (e.g. 64B ,128B ,192B + * ,256B ... ), after last MPS sized packet send IN ZLP packet to + * inform the host that no more data is available. + * The state of req.zero member is checked to be sure that the value to + * send is smaller than wValue expected from host. + * Check req.length to NOT send another ZLP when the current one is + * under completion (the one for which this completion has been called). + */ + if (hs_req->req.length && hs_ep->index == 0 && hs_req->req.zero && + hs_req->req.length == hs_req->req.actual && + !(hs_req->req.length % hs_ep->ep.maxpacket)) { - /* if we did all of the transfer, and there is more data left - * around, then try restarting the rest of the request */ + dev_dbg(hsotg->dev, "ep0 zlp IN packet sent\n"); + s3c_hsotg_send_zlp(hsotg, hs_req); + + return; + } if (!size_left && hs_req->req.actual < hs_req->req.length) { dev_dbg(hsotg->dev, "%s trying more for req...\n", __func__); @@ -1823,14 +1925,14 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, * @dir_in: Set if this is an IN endpoint * * Process and clear any interrupt pending for an individual endpoint -*/ + */ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, int dir_in) { struct s3c_hsotg_ep *hs_ep = &hsotg->eps[idx]; - u32 epint_reg = dir_in ? S3C_DIEPINT(idx) : S3C_DOEPINT(idx); - u32 epctl_reg = dir_in ? S3C_DIEPCTL(idx) : S3C_DOEPCTL(idx); - u32 epsiz_reg = dir_in ? S3C_DIEPTSIZ(idx) : S3C_DOEPTSIZ(idx); + u32 epint_reg = dir_in ? DIEPINT(idx) : DOEPINT(idx); + u32 epctl_reg = dir_in ? DIEPCTL(idx) : DOEPCTL(idx); + u32 epsiz_reg = dir_in ? DIEPTSIZ(idx) : DOEPTSIZ(idx); u32 ints; ints = readl(hsotg->regs + epint_reg); @@ -1841,28 +1943,32 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, dev_dbg(hsotg->dev, "%s: ep%d(%s) DxEPINT=0x%08x\n", __func__, idx, dir_in ? "in" : "out", ints); - if (ints & S3C_DxEPINT_XferCompl) { + if (ints & DxEPINT_XferCompl) { dev_dbg(hsotg->dev, "%s: XferCompl: DxEPCTL=0x%08x, DxEPTSIZ=%08x\n", __func__, readl(hsotg->regs + epctl_reg), readl(hsotg->regs + epsiz_reg)); - /* we get OutDone from the FIFO, so we only need to look - * at completing IN requests here */ + /* + * we get OutDone from the FIFO, so we only need to look + * at completing IN requests here + */ if (dir_in) { s3c_hsotg_complete_in(hsotg, hs_ep); if (idx == 0 && !hs_ep->req) s3c_hsotg_enqueue_setup(hsotg); } else if (using_dma(hsotg)) { - /* We're using DMA, we need to fire an OutDone here - * as we ignore the RXFIFO. */ + /* + * We're using DMA, we need to fire an OutDone here + * as we ignore the RXFIFO. + */ s3c_hsotg_handle_outdone(hsotg, idx, false); } } - if (ints & S3C_DxEPINT_EPDisbld) { + if (ints & DxEPINT_EPDisbld) { dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__); if (dir_in) { @@ -1870,27 +1976,29 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, s3c_hsotg_txfifo_flush(hsotg, idx); - if ((epctl & S3C_DxEPCTL_Stall) && - (epctl & S3C_DxEPCTL_EPType_Bulk)) { - int dctl = readl(hsotg->regs + S3C_DCTL); + if ((epctl & DxEPCTL_Stall) && + (epctl & DxEPCTL_EPType_Bulk)) { + int dctl = readl(hsotg->regs + DCTL); - dctl |= S3C_DCTL_CGNPInNAK; - writel(dctl, hsotg->regs + S3C_DCTL); + dctl |= DCTL_CGNPInNAK; + writel(dctl, hsotg->regs + DCTL); } } } - if (ints & S3C_DxEPINT_AHBErr) + if (ints & DxEPINT_AHBErr) dev_dbg(hsotg->dev, "%s: AHBErr\n", __func__); - if (ints & S3C_DxEPINT_Setup) { /* Setup or Timeout */ + if (ints & DxEPINT_Setup) { /* Setup or Timeout */ dev_dbg(hsotg->dev, "%s: Setup/Timeout\n", __func__); if (using_dma(hsotg) && idx == 0) { - /* this is the notification we've received a + /* + * this is the notification we've received a * setup packet. In non-DMA mode we'd get this * from the RXFIFO, instead we need to process - * the setup here. */ + * the setup here. + */ if (dir_in) WARN_ON_ONCE(1); @@ -1899,26 +2007,25 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, } } - if (ints & S3C_DxEPINT_Back2BackSetup) + if (ints & DxEPINT_Back2BackSetup) dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__); if (dir_in) { - /* not sure if this is important, but we'll clear it anyway - */ - if (ints & S3C_DIEPMSK_INTknTXFEmpMsk) { + /* not sure if this is important, but we'll clear it anyway */ + if (ints & DIEPMSK_INTknTXFEmpMsk) { dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n", __func__, idx); } /* this probably means something bad is happening */ - if (ints & S3C_DIEPMSK_INTknEPMisMsk) { + if (ints & DIEPMSK_INTknEPMisMsk) { dev_warn(hsotg->dev, "%s: ep%d: INTknEP\n", __func__, idx); } /* FIFO has space or is empty (see GAHBCFG) */ if (hsotg->dedicated_fifos && - ints & S3C_DIEPMSK_TxFIFOEmpty) { + ints & DIEPMSK_TxFIFOEmpty) { dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n", __func__, idx); if (!using_dma(hsotg)) @@ -1933,40 +2040,45 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, * * Handle updating the device settings after the enumeration phase has * been completed. -*/ + */ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg) { - u32 dsts = readl(hsotg->regs + S3C_DSTS); + u32 dsts = readl(hsotg->regs + DSTS); int ep0_mps = 0, ep_mps; - /* This should signal the finish of the enumeration phase + /* + * This should signal the finish of the enumeration phase * of the USB handshaking, so we should now know what rate - * we connected at. */ + * we connected at. + */ dev_dbg(hsotg->dev, "EnumDone (DSTS=0x%08x)\n", dsts); - /* note, since we're limited by the size of transfer on EP0, and + /* + * note, since we're limited by the size of transfer on EP0, and * it seems IN transfers must be a even number of packets we do - * not advertise a 64byte MPS on EP0. */ + * not advertise a 64byte MPS on EP0. + */ /* catch both EnumSpd_FS and EnumSpd_FS48 */ - switch (dsts & S3C_DSTS_EnumSpd_MASK) { - case S3C_DSTS_EnumSpd_FS: - case S3C_DSTS_EnumSpd_FS48: + switch (dsts & DSTS_EnumSpd_MASK) { + case DSTS_EnumSpd_FS: + case DSTS_EnumSpd_FS48: hsotg->gadget.speed = USB_SPEED_FULL; ep0_mps = EP0_MPS_LIMIT; ep_mps = 64; break; - case S3C_DSTS_EnumSpd_HS: + case DSTS_EnumSpd_HS: hsotg->gadget.speed = USB_SPEED_HIGH; ep0_mps = EP0_MPS_LIMIT; ep_mps = 512; break; - case S3C_DSTS_EnumSpd_LS: + case DSTS_EnumSpd_LS: hsotg->gadget.speed = USB_SPEED_LOW; - /* note, we don't actually support LS in this driver at the + /* + * note, we don't actually support LS in this driver at the * moment, and the documentation seems to imply that it isn't * supported by the PHYs on some of the devices. */ @@ -1975,13 +2087,15 @@ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg) dev_info(hsotg->dev, "new device is %s\n", usb_speed_string(hsotg->gadget.speed)); - /* we should now know the maximum packet size for an - * endpoint, so set the endpoints to a default value. */ + /* + * we should now know the maximum packet size for an + * endpoint, so set the endpoints to a default value. + */ if (ep0_mps) { int i; s3c_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps); - for (i = 1; i < S3C_HSOTG_EPS; i++) + for (i = 1; i < hsotg->num_of_eps; i++) s3c_hsotg_set_ep_maxpacket(hsotg, i, ep_mps); } @@ -1990,8 +2104,8 @@ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg) s3c_hsotg_enqueue_setup(hsotg); dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", - readl(hsotg->regs + S3C_DIEPCTL0), - readl(hsotg->regs + S3C_DOEPCTL0)); + readl(hsotg->regs + DIEPCTL0), + readl(hsotg->regs + DOEPCTL0)); } /** @@ -2014,8 +2128,10 @@ static void kill_all_requests(struct s3c_hsotg *hsotg, spin_lock_irqsave(&ep->lock, flags); list_for_each_entry_safe(req, treq, &ep->queue, queue) { - /* currently, we can't do much about an already - * running request on an in endpoint */ + /* + * currently, we can't do much about an already + * running request on an in endpoint + */ if (ep->req == req && ep->dir_in && !force) continue; @@ -2033,18 +2149,18 @@ static void kill_all_requests(struct s3c_hsotg *hsotg, (_hs)->driver->_entry(&(_hs)->gadget); /** - * s3c_hsotg_disconnect_irq - disconnect irq service + * s3c_hsotg_disconnect - disconnect service * @hsotg: The device state. * - * A disconnect IRQ has been received, meaning that the host has - * lost contact with the bus. Remove all current transactions - * and signal the gadget driver that this has happened. -*/ -static void s3c_hsotg_disconnect_irq(struct s3c_hsotg *hsotg) + * The device has been disconnected. Remove all current + * transactions and signal the gadget driver that this + * has happened. + */ +static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg) { unsigned ep; - for (ep = 0; ep < S3C_HSOTG_EPS; ep++) + for (ep = 0; ep < hsotg->num_of_eps; ep++) kill_all_requests(hsotg, &hsotg->eps[ep], -ESHUTDOWN, true); call_gadget(hsotg, disconnect); @@ -2062,7 +2178,7 @@ static void s3c_hsotg_irq_fifoempty(struct s3c_hsotg *hsotg, bool periodic) /* look through for any more data to transmit */ - for (epno = 0; epno < S3C_HSOTG_EPS; epno++) { + for (epno = 0; epno < hsotg->num_of_eps; epno++) { ep = &hsotg->eps[epno]; if (!ep->dir_in) @@ -2078,12 +2194,187 @@ static void s3c_hsotg_irq_fifoempty(struct s3c_hsotg *hsotg, bool periodic) } } -static struct s3c_hsotg *our_hsotg; - /* IRQ flags which will trigger a retry around the IRQ loop */ -#define IRQ_RETRY_MASK (S3C_GINTSTS_NPTxFEmp | \ - S3C_GINTSTS_PTxFEmp | \ - S3C_GINTSTS_RxFLvl) +#define IRQ_RETRY_MASK (GINTSTS_NPTxFEmp | \ + GINTSTS_PTxFEmp | \ + GINTSTS_RxFLvl) + +/** + * s3c_hsotg_corereset - issue softreset to the core + * @hsotg: The device state + * + * Issue a soft reset to the core, and await the core finishing it. + */ +static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg) +{ + int timeout; + u32 grstctl; + + dev_dbg(hsotg->dev, "resetting core\n"); + + /* issue soft reset */ + writel(GRSTCTL_CSftRst, hsotg->regs + GRSTCTL); + + timeout = 1000; + do { + grstctl = readl(hsotg->regs + GRSTCTL); + } while ((grstctl & GRSTCTL_CSftRst) && timeout-- > 0); + + if (grstctl & GRSTCTL_CSftRst) { + dev_err(hsotg->dev, "Failed to get CSftRst asserted\n"); + return -EINVAL; + } + + timeout = 1000; + + while (1) { + u32 grstctl = readl(hsotg->regs + GRSTCTL); + + if (timeout-- < 0) { + dev_info(hsotg->dev, + "%s: reset failed, GRSTCTL=%08x\n", + __func__, grstctl); + return -ETIMEDOUT; + } + + if (!(grstctl & GRSTCTL_AHBIdle)) + continue; + + break; /* reset done */ + } + + dev_dbg(hsotg->dev, "reset successful\n"); + return 0; +} + +/** + * s3c_hsotg_core_init - issue softreset to the core + * @hsotg: The device state + * + * Issue a soft reset to the core, and await the core finishing it. + */ +static void s3c_hsotg_core_init(struct s3c_hsotg *hsotg) +{ + s3c_hsotg_corereset(hsotg); + + /* + * we must now enable ep0 ready for host detection and then + * set configuration. + */ + + /* set the PLL on, remove the HNP/SRP and set the PHY */ + writel(GUSBCFG_PHYIf16 | GUSBCFG_TOutCal(7) | + (0x5 << 10), hsotg->regs + GUSBCFG); + + s3c_hsotg_init_fifo(hsotg); + + __orr32(hsotg->regs + DCTL, DCTL_SftDiscon); + + writel(1 << 18 | DCFG_DevSpd_HS, hsotg->regs + DCFG); + + /* Clear any pending OTG interrupts */ + writel(0xffffffff, hsotg->regs + GOTGINT); + + /* Clear any pending interrupts */ + writel(0xffffffff, hsotg->regs + GINTSTS); + + writel(GINTSTS_ErlySusp | GINTSTS_SessReqInt | + GINTSTS_GOUTNakEff | GINTSTS_GINNakEff | + GINTSTS_ConIDStsChng | GINTSTS_USBRst | + GINTSTS_EnumDone | GINTSTS_OTGInt | + GINTSTS_USBSusp | GINTSTS_WkUpInt, + hsotg->regs + GINTMSK); + + if (using_dma(hsotg)) + writel(GAHBCFG_GlblIntrEn | GAHBCFG_DMAEn | + GAHBCFG_HBstLen_Incr4, + hsotg->regs + GAHBCFG); + else + writel(GAHBCFG_GlblIntrEn, hsotg->regs + GAHBCFG); + + /* + * Enabling INTknTXFEmpMsk here seems to be a big mistake, we end + * up being flooded with interrupts if the host is polling the + * endpoint to try and read data. + */ + + writel(((hsotg->dedicated_fifos) ? DIEPMSK_TxFIFOEmpty : 0) | + DIEPMSK_EPDisbldMsk | DIEPMSK_XferComplMsk | + DIEPMSK_TimeOUTMsk | DIEPMSK_AHBErrMsk | + DIEPMSK_INTknEPMisMsk, + hsotg->regs + DIEPMSK); + + /* + * don't need XferCompl, we get that from RXFIFO in slave mode. In + * DMA mode we may need this. + */ + writel((using_dma(hsotg) ? (DIEPMSK_XferComplMsk | + DIEPMSK_TimeOUTMsk) : 0) | + DOEPMSK_EPDisbldMsk | DOEPMSK_AHBErrMsk | + DOEPMSK_SetupMsk, + hsotg->regs + DOEPMSK); + + writel(0, hsotg->regs + DAINTMSK); + + dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", + readl(hsotg->regs + DIEPCTL0), + readl(hsotg->regs + DOEPCTL0)); + + /* enable in and out endpoint interrupts */ + s3c_hsotg_en_gsint(hsotg, GINTSTS_OEPInt | GINTSTS_IEPInt); + + /* + * Enable the RXFIFO when in slave mode, as this is how we collect + * the data. In DMA mode, we get events from the FIFO but also + * things we cannot process, so do not use it. + */ + if (!using_dma(hsotg)) + s3c_hsotg_en_gsint(hsotg, GINTSTS_RxFLvl); + + /* Enable interrupts for EP0 in and out */ + s3c_hsotg_ctrl_epint(hsotg, 0, 0, 1); + s3c_hsotg_ctrl_epint(hsotg, 0, 1, 1); + + __orr32(hsotg->regs + DCTL, DCTL_PWROnPrgDone); + udelay(10); /* see openiboot */ + __bic32(hsotg->regs + DCTL, DCTL_PWROnPrgDone); + + dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + DCTL)); + + /* + * DxEPCTL_USBActEp says RO in manual, but seems to be set by + * writing to the EPCTL register.. + */ + + /* set to read 1 8byte packet */ + writel(DxEPTSIZ_MC(1) | DxEPTSIZ_PktCnt(1) | + DxEPTSIZ_XferSize(8), hsotg->regs + DOEPTSIZ0); + + writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) | + DxEPCTL_CNAK | DxEPCTL_EPEna | + DxEPCTL_USBActEp, + hsotg->regs + DOEPCTL0); + + /* enable, but don't activate EP0in */ + writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) | + DxEPCTL_USBActEp, hsotg->regs + DIEPCTL0); + + s3c_hsotg_enqueue_setup(hsotg); + + dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", + readl(hsotg->regs + DIEPCTL0), + readl(hsotg->regs + DOEPCTL0)); + + /* clear global NAKs */ + writel(DCTL_CGOUTNak | DCTL_CGNPInNAK, + hsotg->regs + DCTL); + + /* must be at-least 3ms to allow bus to see disconnect */ + mdelay(3); + + /* remove the soft-disconnect and let's go */ + __bic32(hsotg->regs + DCTL, DCTL_SftDiscon); +} /** * s3c_hsotg_irq - handle device interrupt @@ -2098,52 +2389,45 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) u32 gintmsk; irq_retry: - gintsts = readl(hsotg->regs + S3C_GINTSTS); - gintmsk = readl(hsotg->regs + S3C_GINTMSK); + gintsts = readl(hsotg->regs + GINTSTS); + gintmsk = readl(hsotg->regs + GINTMSK); dev_dbg(hsotg->dev, "%s: %08x %08x (%08x) retry %d\n", __func__, gintsts, gintsts & gintmsk, gintmsk, retry_count); gintsts &= gintmsk; - if (gintsts & S3C_GINTSTS_OTGInt) { - u32 otgint = readl(hsotg->regs + S3C_GOTGINT); + if (gintsts & GINTSTS_OTGInt) { + u32 otgint = readl(hsotg->regs + GOTGINT); dev_info(hsotg->dev, "OTGInt: %08x\n", otgint); - writel(otgint, hsotg->regs + S3C_GOTGINT); - } - - if (gintsts & S3C_GINTSTS_DisconnInt) { - dev_dbg(hsotg->dev, "%s: DisconnInt\n", __func__); - writel(S3C_GINTSTS_DisconnInt, hsotg->regs + S3C_GINTSTS); - - s3c_hsotg_disconnect_irq(hsotg); + writel(otgint, hsotg->regs + GOTGINT); } - if (gintsts & S3C_GINTSTS_SessReqInt) { + if (gintsts & GINTSTS_SessReqInt) { dev_dbg(hsotg->dev, "%s: SessReqInt\n", __func__); - writel(S3C_GINTSTS_SessReqInt, hsotg->regs + S3C_GINTSTS); + writel(GINTSTS_SessReqInt, hsotg->regs + GINTSTS); } - if (gintsts & S3C_GINTSTS_EnumDone) { - writel(S3C_GINTSTS_EnumDone, hsotg->regs + S3C_GINTSTS); + if (gintsts & GINTSTS_EnumDone) { + writel(GINTSTS_EnumDone, hsotg->regs + GINTSTS); s3c_hsotg_irq_enumdone(hsotg); } - if (gintsts & S3C_GINTSTS_ConIDStsChng) { + if (gintsts & GINTSTS_ConIDStsChng) { dev_dbg(hsotg->dev, "ConIDStsChg (DSTS=0x%08x, GOTCTL=%08x)\n", - readl(hsotg->regs + S3C_DSTS), - readl(hsotg->regs + S3C_GOTGCTL)); + readl(hsotg->regs + DSTS), + readl(hsotg->regs + GOTGCTL)); - writel(S3C_GINTSTS_ConIDStsChng, hsotg->regs + S3C_GINTSTS); + writel(GINTSTS_ConIDStsChng, hsotg->regs + GINTSTS); } - if (gintsts & (S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt)) { - u32 daint = readl(hsotg->regs + S3C_DAINT); - u32 daint_out = daint >> S3C_DAINT_OutEP_SHIFT; - u32 daint_in = daint & ~(daint_out << S3C_DAINT_OutEP_SHIFT); + if (gintsts & (GINTSTS_OEPInt | GINTSTS_IEPInt)) { + u32 daint = readl(hsotg->regs + DAINT); + u32 daint_out = daint >> DAINT_OutEP_SHIFT; + u32 daint_in = daint & ~(daint_out << DAINT_OutEP_SHIFT); int ep; dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint); @@ -2159,102 +2443,116 @@ irq_retry: } } - if (gintsts & S3C_GINTSTS_USBRst) { + if (gintsts & GINTSTS_USBRst) { + + u32 usb_status = readl(hsotg->regs + GOTGCTL); + dev_info(hsotg->dev, "%s: USBRst\n", __func__); dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n", - readl(hsotg->regs + S3C_GNPTXSTS)); + readl(hsotg->regs + GNPTXSTS)); - writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS); + writel(GINTSTS_USBRst, hsotg->regs + GINTSTS); - kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true); + if (usb_status & GOTGCTL_BSESVLD) { + if (time_after(jiffies, hsotg->last_rst + + msecs_to_jiffies(200))) { - /* it seems after a reset we can end up with a situation - * where the TXFIFO still has data in it... the docs - * suggest resetting all the fifos, so use the init_fifo - * code to relayout and flush the fifos. - */ + kill_all_requests(hsotg, &hsotg->eps[0], + -ECONNRESET, true); - s3c_hsotg_init_fifo(hsotg); - - s3c_hsotg_enqueue_setup(hsotg); + s3c_hsotg_core_init(hsotg); + hsotg->last_rst = jiffies; + } + } } /* check both FIFOs */ - if (gintsts & S3C_GINTSTS_NPTxFEmp) { + if (gintsts & GINTSTS_NPTxFEmp) { dev_dbg(hsotg->dev, "NPTxFEmp\n"); - /* Disable the interrupt to stop it happening again + /* + * Disable the interrupt to stop it happening again * unless one of these endpoint routines decides that - * it needs re-enabling */ + * it needs re-enabling + */ - s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_NPTxFEmp); + s3c_hsotg_disable_gsint(hsotg, GINTSTS_NPTxFEmp); s3c_hsotg_irq_fifoempty(hsotg, false); } - if (gintsts & S3C_GINTSTS_PTxFEmp) { + if (gintsts & GINTSTS_PTxFEmp) { dev_dbg(hsotg->dev, "PTxFEmp\n"); - /* See note in S3C_GINTSTS_NPTxFEmp */ + /* See note in GINTSTS_NPTxFEmp */ - s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_PTxFEmp); + s3c_hsotg_disable_gsint(hsotg, GINTSTS_PTxFEmp); s3c_hsotg_irq_fifoempty(hsotg, true); } - if (gintsts & S3C_GINTSTS_RxFLvl) { - /* note, since GINTSTS_RxFLvl doubles as FIFO-not-empty, + if (gintsts & GINTSTS_RxFLvl) { + /* + * note, since GINTSTS_RxFLvl doubles as FIFO-not-empty, * we need to retry s3c_hsotg_handle_rx if this is still - * set. */ + * set. + */ s3c_hsotg_handle_rx(hsotg); } - if (gintsts & S3C_GINTSTS_ModeMis) { + if (gintsts & GINTSTS_ModeMis) { dev_warn(hsotg->dev, "warning, mode mismatch triggered\n"); - writel(S3C_GINTSTS_ModeMis, hsotg->regs + S3C_GINTSTS); + writel(GINTSTS_ModeMis, hsotg->regs + GINTSTS); } - if (gintsts & S3C_GINTSTS_USBSusp) { - dev_info(hsotg->dev, "S3C_GINTSTS_USBSusp\n"); - writel(S3C_GINTSTS_USBSusp, hsotg->regs + S3C_GINTSTS); + if (gintsts & GINTSTS_USBSusp) { + dev_info(hsotg->dev, "GINTSTS_USBSusp\n"); + writel(GINTSTS_USBSusp, hsotg->regs + GINTSTS); call_gadget(hsotg, suspend); + s3c_hsotg_disconnect(hsotg); } - if (gintsts & S3C_GINTSTS_WkUpInt) { - dev_info(hsotg->dev, "S3C_GINTSTS_WkUpIn\n"); - writel(S3C_GINTSTS_WkUpInt, hsotg->regs + S3C_GINTSTS); + if (gintsts & GINTSTS_WkUpInt) { + dev_info(hsotg->dev, "GINTSTS_WkUpIn\n"); + writel(GINTSTS_WkUpInt, hsotg->regs + GINTSTS); call_gadget(hsotg, resume); } - if (gintsts & S3C_GINTSTS_ErlySusp) { - dev_dbg(hsotg->dev, "S3C_GINTSTS_ErlySusp\n"); - writel(S3C_GINTSTS_ErlySusp, hsotg->regs + S3C_GINTSTS); + if (gintsts & GINTSTS_ErlySusp) { + dev_dbg(hsotg->dev, "GINTSTS_ErlySusp\n"); + writel(GINTSTS_ErlySusp, hsotg->regs + GINTSTS); + + s3c_hsotg_disconnect(hsotg); } - /* these next two seem to crop-up occasionally causing the core + /* + * these next two seem to crop-up occasionally causing the core * to shutdown the USB transfer, so try clearing them and logging - * the occurrence. */ + * the occurrence. + */ - if (gintsts & S3C_GINTSTS_GOUTNakEff) { + if (gintsts & GINTSTS_GOUTNakEff) { dev_info(hsotg->dev, "GOUTNakEff triggered\n"); - writel(S3C_DCTL_CGOUTNak, hsotg->regs + S3C_DCTL); + writel(DCTL_CGOUTNak, hsotg->regs + DCTL); s3c_hsotg_dump(hsotg); } - if (gintsts & S3C_GINTSTS_GINNakEff) { + if (gintsts & GINTSTS_GINNakEff) { dev_info(hsotg->dev, "GINNakEff triggered\n"); - writel(S3C_DCTL_CGNPInNAK, hsotg->regs + S3C_DCTL); + writel(DCTL_CGNPInNAK, hsotg->regs + DCTL); s3c_hsotg_dump(hsotg); } - /* if we've had fifo events, we should try and go around the - * loop again to see if there's any point in returning yet. */ + /* + * if we've had fifo events, we should try and go around the + * loop again to see if there's any point in returning yet. + */ if (gintsts & IRQ_RETRY_MASK && --retry_count > 0) goto irq_retry; @@ -2268,7 +2566,7 @@ irq_retry: * @desc: The USB endpoint descriptor to configure with. * * This is called from the USB gadget code's usb_ep_enable(). -*/ + */ static int s3c_hsotg_ep_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc) { @@ -2300,7 +2598,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, /* note, we handle this here instead of s3c_hsotg_set_ep_maxpacket */ - epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index); + epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); epctrl = readl(hsotg->regs + epctrl_reg); dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n", @@ -2308,20 +2606,23 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, spin_lock_irqsave(&hs_ep->lock, flags); - epctrl &= ~(S3C_DxEPCTL_EPType_MASK | S3C_DxEPCTL_MPS_MASK); - epctrl |= S3C_DxEPCTL_MPS(mps); + epctrl &= ~(DxEPCTL_EPType_MASK | DxEPCTL_MPS_MASK); + epctrl |= DxEPCTL_MPS(mps); - /* mark the endpoint as active, otherwise the core may ignore - * transactions entirely for this endpoint */ - epctrl |= S3C_DxEPCTL_USBActEp; + /* + * mark the endpoint as active, otherwise the core may ignore + * transactions entirely for this endpoint + */ + epctrl |= DxEPCTL_USBActEp; - /* set the NAK status on the endpoint, otherwise we might try and + /* + * set the NAK status on the endpoint, otherwise we might try and * do something with data that we've yet got a request to process * since the RXFIFO will take data for an endpoint even if the * size register hasn't been set. */ - epctrl |= S3C_DxEPCTL_SNAK; + epctrl |= DxEPCTL_SNAK; /* update the endpoint state */ hs_ep->ep.maxpacket = mps; @@ -2336,37 +2637,40 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, goto out; case USB_ENDPOINT_XFER_BULK: - epctrl |= S3C_DxEPCTL_EPType_Bulk; + epctrl |= DxEPCTL_EPType_Bulk; break; case USB_ENDPOINT_XFER_INT: if (dir_in) { - /* Allocate our TxFNum by simply using the index + /* + * Allocate our TxFNum by simply using the index * of the endpoint for the moment. We could do * something better if the host indicates how - * many FIFOs we are expecting to use. */ + * many FIFOs we are expecting to use. + */ hs_ep->periodic = 1; - epctrl |= S3C_DxEPCTL_TxFNum(index); + epctrl |= DxEPCTL_TxFNum(index); } - epctrl |= S3C_DxEPCTL_EPType_Intterupt; + epctrl |= DxEPCTL_EPType_Intterupt; break; case USB_ENDPOINT_XFER_CONTROL: - epctrl |= S3C_DxEPCTL_EPType_Control; + epctrl |= DxEPCTL_EPType_Control; break; } - /* if the hardware has dedicated fifos, we must give each IN EP + /* + * 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); + epctrl |= DxEPCTL_TxFNum(index); /* for non control endpoints, set PID to D0 */ if (index) - epctrl |= S3C_DxEPCTL_SetD0PID; + epctrl |= DxEPCTL_SetD0PID; dev_dbg(hsotg->dev, "%s: write DxEPCTL=0x%08x\n", __func__, epctrl); @@ -2383,6 +2687,10 @@ out: return ret; } +/** + * s3c_hsotg_ep_disable - disable given endpoint + * @ep: The endpoint to disable. + */ static int s3c_hsotg_ep_disable(struct usb_ep *ep) { struct s3c_hsotg_ep *hs_ep = our_ep(ep); @@ -2400,7 +2708,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep) return -EINVAL; } - epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index); + epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); /* terminate all requests with shutdown */ kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false); @@ -2408,9 +2716,9 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep) spin_lock_irqsave(&hs_ep->lock, flags); ctrl = readl(hsotg->regs + epctrl_reg); - ctrl &= ~S3C_DxEPCTL_EPEna; - ctrl &= ~S3C_DxEPCTL_USBActEp; - ctrl |= S3C_DxEPCTL_SNAK; + ctrl &= ~DxEPCTL_EPEna; + ctrl &= ~DxEPCTL_USBActEp; + ctrl |= DxEPCTL_SNAK; dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl); writel(ctrl, hsotg->regs + epctrl_reg); @@ -2426,7 +2734,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep) * on_list - check request is on the given endpoint * @ep: The endpoint to check. * @test: The request to test if it is on the endpoint. -*/ + */ static bool on_list(struct s3c_hsotg_ep *ep, struct s3c_hsotg_req *test) { struct s3c_hsotg_req *req, *treq; @@ -2439,6 +2747,11 @@ static bool on_list(struct s3c_hsotg_ep *ep, struct s3c_hsotg_req *test) return false; } +/** + * s3c_hsotg_ep_dequeue - dequeue given endpoint + * @ep: The endpoint to dequeue. + * @req: The request to be removed from a queue. + */ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) { struct s3c_hsotg_req *hs_req = our_req(req); @@ -2461,6 +2774,11 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) return 0; } +/** + * s3c_hsotg_ep_sethalt - set halt on a given endpoint + * @ep: The endpoint to set halt. + * @value: Set or unset the halt. + */ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) { struct s3c_hsotg_ep *hs_ep = our_ep(ep); @@ -2477,34 +2795,34 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) /* write both IN and OUT control registers */ - epreg = S3C_DIEPCTL(index); + epreg = DIEPCTL(index); epctl = readl(hs->regs + epreg); if (value) { - epctl |= S3C_DxEPCTL_Stall + S3C_DxEPCTL_SNAK; - if (epctl & S3C_DxEPCTL_EPEna) - epctl |= S3C_DxEPCTL_EPDis; + epctl |= DxEPCTL_Stall + DxEPCTL_SNAK; + if (epctl & DxEPCTL_EPEna) + epctl |= DxEPCTL_EPDis; } else { - epctl &= ~S3C_DxEPCTL_Stall; - xfertype = epctl & S3C_DxEPCTL_EPType_MASK; - if (xfertype == S3C_DxEPCTL_EPType_Bulk || - xfertype == S3C_DxEPCTL_EPType_Intterupt) - epctl |= S3C_DxEPCTL_SetD0PID; + epctl &= ~DxEPCTL_Stall; + xfertype = epctl & DxEPCTL_EPType_MASK; + if (xfertype == DxEPCTL_EPType_Bulk || + xfertype == DxEPCTL_EPType_Intterupt) + epctl |= DxEPCTL_SetD0PID; } writel(epctl, hs->regs + epreg); - epreg = S3C_DOEPCTL(index); + epreg = DOEPCTL(index); epctl = readl(hs->regs + epreg); if (value) - epctl |= S3C_DxEPCTL_Stall; + epctl |= DxEPCTL_Stall; else { - epctl &= ~S3C_DxEPCTL_Stall; - xfertype = epctl & S3C_DxEPCTL_EPType_MASK; - if (xfertype == S3C_DxEPCTL_EPType_Bulk || - xfertype == S3C_DxEPCTL_EPType_Intterupt) - epctl |= S3C_DxEPCTL_SetD0PID; + epctl &= ~DxEPCTL_Stall; + xfertype = epctl & DxEPCTL_EPType_MASK; + if (xfertype == DxEPCTL_EPType_Bulk || + xfertype == DxEPCTL_EPType_Intterupt) + epctl |= DxEPCTL_SetD0PID; } writel(epctl, hs->regs + epreg); @@ -2526,57 +2844,91 @@ static struct usb_ep_ops s3c_hsotg_ep_ops = { }; /** - * s3c_hsotg_corereset - issue softreset to the core - * @hsotg: The device state + * s3c_hsotg_phy_enable - enable platform phy dev + * @hsotg: The driver state * - * Issue a soft reset to the core, and await the core finishing it. -*/ -static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg) + * A wrapper for platform code responsible for controlling + * low-level USB code + */ +static void s3c_hsotg_phy_enable(struct s3c_hsotg *hsotg) { - int timeout; - u32 grstctl; + struct platform_device *pdev = to_platform_device(hsotg->dev); - dev_dbg(hsotg->dev, "resetting core\n"); + dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev); + if (hsotg->plat->phy_init) + hsotg->plat->phy_init(pdev, hsotg->plat->phy_type); +} - /* issue soft reset */ - writel(S3C_GRSTCTL_CSftRst, hsotg->regs + S3C_GRSTCTL); +/** + * s3c_hsotg_phy_disable - disable platform phy dev + * @hsotg: The driver state + * + * A wrapper for platform code responsible for controlling + * low-level USB code + */ +static void s3c_hsotg_phy_disable(struct s3c_hsotg *hsotg) +{ + struct platform_device *pdev = to_platform_device(hsotg->dev); - timeout = 1000; - do { - grstctl = readl(hsotg->regs + S3C_GRSTCTL); - } while ((grstctl & S3C_GRSTCTL_CSftRst) && timeout-- > 0); + if (hsotg->plat->phy_exit) + hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type); +} - if (grstctl & S3C_GRSTCTL_CSftRst) { - dev_err(hsotg->dev, "Failed to get CSftRst asserted\n"); - return -EINVAL; - } +/** + * s3c_hsotg_init - initalize the usb core + * @hsotg: The driver state + */ +static void s3c_hsotg_init(struct s3c_hsotg *hsotg) +{ + /* unmask subset of endpoint interrupts */ - timeout = 1000; + writel(DIEPMSK_TimeOUTMsk | DIEPMSK_AHBErrMsk | + DIEPMSK_EPDisbldMsk | DIEPMSK_XferComplMsk, + hsotg->regs + DIEPMSK); - while (1) { - u32 grstctl = readl(hsotg->regs + S3C_GRSTCTL); + writel(DOEPMSK_SetupMsk | DOEPMSK_AHBErrMsk | + DOEPMSK_EPDisbldMsk | DOEPMSK_XferComplMsk, + hsotg->regs + DOEPMSK); - if (timeout-- < 0) { - dev_info(hsotg->dev, - "%s: reset failed, GRSTCTL=%08x\n", - __func__, grstctl); - return -ETIMEDOUT; - } + writel(0, hsotg->regs + DAINTMSK); - if (!(grstctl & S3C_GRSTCTL_AHBIdle)) - continue; + /* Be in disconnected state until gadget is registered */ + __orr32(hsotg->regs + DCTL, DCTL_SftDiscon); - break; /* reset done */ + if (0) { + /* post global nak until we're ready */ + writel(DCTL_SGNPInNAK | DCTL_SGOUTNak, + hsotg->regs + DCTL); } - dev_dbg(hsotg->dev, "reset successful\n"); - return 0; + /* setup fifos */ + + dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n", + readl(hsotg->regs + GRXFSIZ), + readl(hsotg->regs + GNPTXFSIZ)); + + s3c_hsotg_init_fifo(hsotg); + + /* set the PLL on, remove the HNP/SRP and set the PHY */ + writel(GUSBCFG_PHYIf16 | GUSBCFG_TOutCal(7) | (0x5 << 10), + hsotg->regs + GUSBCFG); + + writel(using_dma(hsotg) ? GAHBCFG_DMAEn : 0x0, + hsotg->regs + GAHBCFG); } -static int s3c_hsotg_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) +/** + * s3c_hsotg_udc_start - prepare the udc for work + * @gadget: The usb gadget state + * @driver: The usb gadget driver + * + * Perform initialization to prepare udc device and driver + * to work. + */ +static int s3c_hsotg_udc_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct s3c_hsotg *hsotg = our_hsotg; + struct s3c_hsotg *hsotg = to_hsotg(gadget); int ret; if (!hsotg) { @@ -2592,7 +2944,7 @@ static int s3c_hsotg_start(struct usb_gadget_driver *driver, if (driver->max_speed < USB_SPEED_FULL) dev_err(hsotg->dev, "%s: bad speed\n", __func__); - if (!bind || !driver->setup) { + if (!driver->setup) { dev_err(hsotg->dev, "%s: missing entry points\n", __func__); return -EINVAL; } @@ -2605,135 +2957,17 @@ static int s3c_hsotg_start(struct usb_gadget_driver *driver, hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask; hsotg->gadget.speed = USB_SPEED_UNKNOWN; - ret = device_add(&hsotg->gadget.dev); + ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), + hsotg->supplies); if (ret) { - dev_err(hsotg->dev, "failed to register gadget device\n"); + dev_err(hsotg->dev, "failed to enable supplies: %d\n", ret); goto err; } - ret = bind(&hsotg->gadget); - if (ret) { - dev_err(hsotg->dev, "failed bind %s\n", driver->driver.name); - - hsotg->gadget.dev.driver = NULL; - hsotg->driver = NULL; - goto err; - } - - /* we must now enable ep0 ready for host detection and then - * set configuration. */ - - s3c_hsotg_corereset(hsotg); - - /* set the PLL on, remove the HNP/SRP and set the PHY */ - writel(S3C_GUSBCFG_PHYIf16 | S3C_GUSBCFG_TOutCal(7) | - (0x5 << 10), hsotg->regs + S3C_GUSBCFG); - - /* looks like soft-reset changes state of FIFOs */ - s3c_hsotg_init_fifo(hsotg); - - __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon); - - writel(1 << 18 | S3C_DCFG_DevSpd_HS, hsotg->regs + S3C_DCFG); - - /* Clear any pending OTG interrupts */ - writel(0xffffffff, hsotg->regs + S3C_GOTGINT); - - /* Clear any pending interrupts */ - writel(0xffffffff, hsotg->regs + S3C_GINTSTS); - - writel(S3C_GINTSTS_DisconnInt | S3C_GINTSTS_SessReqInt | - S3C_GINTSTS_ConIDStsChng | S3C_GINTSTS_USBRst | - S3C_GINTSTS_EnumDone | S3C_GINTSTS_OTGInt | - S3C_GINTSTS_USBSusp | S3C_GINTSTS_WkUpInt | - S3C_GINTSTS_GOUTNakEff | S3C_GINTSTS_GINNakEff | - S3C_GINTSTS_ErlySusp, - hsotg->regs + S3C_GINTMSK); - - if (using_dma(hsotg)) - writel(S3C_GAHBCFG_GlblIntrEn | S3C_GAHBCFG_DMAEn | - S3C_GAHBCFG_HBstLen_Incr4, - hsotg->regs + S3C_GAHBCFG); - else - writel(S3C_GAHBCFG_GlblIntrEn, hsotg->regs + S3C_GAHBCFG); - - /* Enabling INTknTXFEmpMsk here seems to be a big mistake, we end - * up being flooded with interrupts if the host is polling the - * endpoint to try and read data. */ - - writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk | - S3C_DIEPMSK_INTknEPMisMsk | - 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 - * DMA mode we may need this. */ - writel(S3C_DOEPMSK_SetupMsk | S3C_DOEPMSK_AHBErrMsk | - S3C_DOEPMSK_EPDisbldMsk | - (using_dma(hsotg) ? (S3C_DIEPMSK_XferComplMsk | - S3C_DIEPMSK_TimeOUTMsk) : 0), - hsotg->regs + S3C_DOEPMSK); - - writel(0, hsotg->regs + S3C_DAINTMSK); - - dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", - readl(hsotg->regs + S3C_DIEPCTL0), - readl(hsotg->regs + S3C_DOEPCTL0)); - - /* enable in and out endpoint interrupts */ - s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt); - - /* Enable the RXFIFO when in slave mode, as this is how we collect - * the data. In DMA mode, we get events from the FIFO but also - * things we cannot process, so do not use it. */ - if (!using_dma(hsotg)) - s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_RxFLvl); - - /* Enable interrupts for EP0 in and out */ - s3c_hsotg_ctrl_epint(hsotg, 0, 0, 1); - s3c_hsotg_ctrl_epint(hsotg, 0, 1, 1); - - __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone); - udelay(10); /* see openiboot */ - __bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone); - - dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + S3C_DCTL)); - - /* S3C_DxEPCTL_USBActEp says RO in manual, but seems to be set by - writing to the EPCTL register.. */ - - /* set to read 1 8byte packet */ - writel(S3C_DxEPTSIZ_MC(1) | S3C_DxEPTSIZ_PktCnt(1) | - S3C_DxEPTSIZ_XferSize(8), hsotg->regs + DOEPTSIZ0); - - writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) | - S3C_DxEPCTL_CNAK | S3C_DxEPCTL_EPEna | - S3C_DxEPCTL_USBActEp, - hsotg->regs + S3C_DOEPCTL0); - - /* enable, but don't activate EP0in */ - writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) | - S3C_DxEPCTL_USBActEp, hsotg->regs + S3C_DIEPCTL0); - - s3c_hsotg_enqueue_setup(hsotg); - - dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", - readl(hsotg->regs + S3C_DIEPCTL0), - readl(hsotg->regs + S3C_DOEPCTL0)); - - /* clear global NAKs */ - writel(S3C_DCTL_CGOUTNak | S3C_DCTL_CGNPInNAK, - hsotg->regs + S3C_DCTL); - - /* must be at-least 3ms to allow bus to see disconnect */ - msleep(3); - - /* remove the soft-disconnect and let's go */ - __bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon); - - /* report to the user, and return */ + s3c_hsotg_phy_enable(hsotg); + s3c_hsotg_core_init(hsotg); + hsotg->last_rst = jiffies; dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name); return 0; @@ -2743,9 +2977,17 @@ err: return ret; } -static int s3c_hsotg_stop(struct usb_gadget_driver *driver) +/** + * s3c_hsotg_udc_stop - stop the udc + * @gadget: The usb gadget state + * @driver: The usb gadget driver + * + * Stop udc hw block and stay tunned for future transmissions + */ +static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct s3c_hsotg *hsotg = our_hsotg; + struct s3c_hsotg *hsotg = to_hsotg(gadget); int ep; if (!hsotg) @@ -2755,16 +2997,15 @@ static int s3c_hsotg_stop(struct usb_gadget_driver *driver) return -EINVAL; /* all endpoints should be shutdown */ - for (ep = 0; ep < S3C_HSOTG_EPS; ep++) + for (ep = 0; ep < hsotg->num_of_eps; ep++) s3c_hsotg_ep_disable(&hsotg->eps[ep].ep); - call_gadget(hsotg, disconnect); + s3c_hsotg_phy_disable(hsotg); + regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); - driver->unbind(&hsotg->gadget); hsotg->driver = NULL; hsotg->gadget.speed = USB_SPEED_UNKNOWN; - - device_del(&hsotg->gadget.dev); + hsotg->gadget.dev.driver = NULL; dev_info(hsotg->dev, "unregistered gadget driver '%s'\n", driver->driver.name); @@ -2772,6 +3013,12 @@ static int s3c_hsotg_stop(struct usb_gadget_driver *driver) return 0; } +/** + * s3c_hsotg_gadget_getframe - read the frame number + * @gadget: The usb gadget state + * + * Read the {micro} frame number + */ static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget) { return s3c_hsotg_read_frameno(to_hsotg(gadget)); @@ -2779,8 +3026,8 @@ static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget) static struct usb_gadget_ops s3c_hsotg_gadget_ops = { .get_frame = s3c_hsotg_gadget_getframe, - .start = s3c_hsotg_start, - .stop = s3c_hsotg_stop, + .udc_start = s3c_hsotg_udc_start, + .udc_stop = s3c_hsotg_udc_stop, }; /** @@ -2827,111 +3074,42 @@ static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg, hs_ep->ep.maxpacket = epnum ? 512 : EP0_MPS_LIMIT; hs_ep->ep.ops = &s3c_hsotg_ep_ops; - /* Read the FIFO size for the Periodic TX FIFO, even if we're + /* + * Read the FIFO size for the Periodic TX FIFO, even if we're * an OUT endpoint, we may as well do this if in future the * code is changed to make each endpoint's direction changeable. */ - ptxfifo = readl(hsotg->regs + S3C_DPTXFSIZn(epnum)); - hs_ep->fifo_size = S3C_DPTXFSIZn_DPTxFSize_GET(ptxfifo) * 4; + ptxfifo = readl(hsotg->regs + DPTXFSIZn(epnum)); + hs_ep->fifo_size = DPTXFSIZn_DPTxFSize_GET(ptxfifo) * 4; - /* if we're using dma, we need to set the next-endpoint pointer + /* + * if we're using dma, we need to set the next-endpoint pointer * to be something valid. */ if (using_dma(hsotg)) { - u32 next = S3C_DxEPCTL_NextEp((epnum + 1) % 15); - writel(next, hsotg->regs + S3C_DIEPCTL(epnum)); - writel(next, hsotg->regs + S3C_DOEPCTL(epnum)); + u32 next = DxEPCTL_NextEp((epnum + 1) % 15); + writel(next, hsotg->regs + DIEPCTL(epnum)); + writel(next, hsotg->regs + DOEPCTL(epnum)); } } /** - * s3c_hsotg_otgreset - reset the OtG phy block - * @hsotg: The host state. + * s3c_hsotg_hw_cfg - read HW configuration registers + * @param: The device state * - * Power up the phy, set the basic configuration and start the PHY. + * Read the USB core HW configuration registers */ -static void s3c_hsotg_otgreset(struct s3c_hsotg *hsotg) -{ - struct clk *xusbxti; - u32 pwr, osc; - - pwr = readl(S3C_PHYPWR); - pwr &= ~0x19; - writel(pwr, S3C_PHYPWR); - mdelay(1); - - osc = hsotg->plat->is_osc ? S3C_PHYCLK_EXT_OSC : 0; - - xusbxti = clk_get(hsotg->dev, "xusbxti"); - if (xusbxti && !IS_ERR(xusbxti)) { - switch (clk_get_rate(xusbxti)) { - case 12*MHZ: - osc |= S3C_PHYCLK_CLKSEL_12M; - break; - case 24*MHZ: - osc |= S3C_PHYCLK_CLKSEL_24M; - break; - default: - case 48*MHZ: - /* default reference clock */ - break; - } - clk_put(xusbxti); - } - - writel(osc | 0x10, S3C_PHYCLK); - - /* issue a full set of resets to the otg and core */ - - writel(S3C_RSTCON_PHY, S3C_RSTCON); - udelay(20); /* at-least 10uS */ - writel(0, S3C_RSTCON); -} - - -static void s3c_hsotg_init(struct s3c_hsotg *hsotg) +static void s3c_hsotg_hw_cfg(struct s3c_hsotg *hsotg) { - u32 cfg4; - - /* unmask subset of endpoint interrupts */ - - writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk | - S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk, - hsotg->regs + S3C_DIEPMSK); - - writel(S3C_DOEPMSK_SetupMsk | S3C_DOEPMSK_AHBErrMsk | - S3C_DOEPMSK_EPDisbldMsk | S3C_DOEPMSK_XferComplMsk, - hsotg->regs + S3C_DOEPMSK); - - writel(0, hsotg->regs + S3C_DAINTMSK); - - /* Be in disconnected state until gadget is registered */ - __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon); - - if (0) { - /* post global nak until we're ready */ - writel(S3C_DCTL_SGNPInNAK | S3C_DCTL_SGOUTNak, - hsotg->regs + S3C_DCTL); - } - - /* setup fifos */ - - dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n", - readl(hsotg->regs + S3C_GRXFSIZ), - readl(hsotg->regs + S3C_GNPTXFSIZ)); - - s3c_hsotg_init_fifo(hsotg); - - /* set the PLL on, remove the HNP/SRP and set the PHY */ - writel(S3C_GUSBCFG_PHYIf16 | S3C_GUSBCFG_TOutCal(7) | (0x5 << 10), - hsotg->regs + S3C_GUSBCFG); + u32 cfg2, cfg4; + /* check hardware configuration */ - writel(using_dma(hsotg) ? S3C_GAHBCFG_DMAEn : 0x0, - hsotg->regs + S3C_GAHBCFG); + cfg2 = readl(hsotg->regs + 0x48); + hsotg->num_of_eps = (cfg2 >> 10) & 0xF; - /* check hardware configuration */ + dev_info(hsotg->dev, "EPs:%d\n", hsotg->num_of_eps); cfg4 = readl(hsotg->regs + 0x50); hsotg->dedicated_fifos = (cfg4 >> 25) & 1; @@ -2940,6 +3118,10 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg) hsotg->dedicated_fifos ? "dedicated" : "shared"); } +/** + * s3c_hsotg_dump - dump state of the udc + * @param: The device state + */ static void s3c_hsotg_dump(struct s3c_hsotg *hsotg) { #ifdef DEBUG @@ -2949,46 +3131,45 @@ static void s3c_hsotg_dump(struct s3c_hsotg *hsotg) int idx; dev_info(dev, "DCFG=0x%08x, DCTL=0x%08x, DIEPMSK=%08x\n", - readl(regs + S3C_DCFG), readl(regs + S3C_DCTL), - readl(regs + S3C_DIEPMSK)); + readl(regs + DCFG), readl(regs + DCTL), + readl(regs + DIEPMSK)); dev_info(dev, "GAHBCFG=0x%08x, 0x44=0x%08x\n", - readl(regs + S3C_GAHBCFG), readl(regs + 0x44)); + readl(regs + GAHBCFG), readl(regs + 0x44)); dev_info(dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n", - readl(regs + S3C_GRXFSIZ), readl(regs + S3C_GNPTXFSIZ)); + readl(regs + GRXFSIZ), readl(regs + GNPTXFSIZ)); /* show periodic fifo settings */ for (idx = 1; idx <= 15; idx++) { - val = readl(regs + S3C_DPTXFSIZn(idx)); + val = readl(regs + DPTXFSIZn(idx)); dev_info(dev, "DPTx[%d] FSize=%d, StAddr=0x%08x\n", idx, - val >> S3C_DPTXFSIZn_DPTxFSize_SHIFT, - val & S3C_DPTXFSIZn_DPTxFStAddr_MASK); + val >> DPTXFSIZn_DPTxFSize_SHIFT, + val & DPTXFSIZn_DPTxFStAddr_MASK); } for (idx = 0; idx < 15; idx++) { dev_info(dev, "ep%d-in: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n", idx, - readl(regs + S3C_DIEPCTL(idx)), - readl(regs + S3C_DIEPTSIZ(idx)), - readl(regs + S3C_DIEPDMA(idx))); + readl(regs + DIEPCTL(idx)), + readl(regs + DIEPTSIZ(idx)), + readl(regs + DIEPDMA(idx))); - val = readl(regs + S3C_DOEPCTL(idx)); + val = readl(regs + DOEPCTL(idx)); dev_info(dev, "ep%d-out: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n", - idx, readl(regs + S3C_DOEPCTL(idx)), - readl(regs + S3C_DOEPTSIZ(idx)), - readl(regs + S3C_DOEPDMA(idx))); + idx, readl(regs + DOEPCTL(idx)), + readl(regs + DOEPTSIZ(idx)), + readl(regs + DOEPDMA(idx))); } dev_info(dev, "DVBUSDIS=0x%08x, DVBUSPULSE=%08x\n", - readl(regs + S3C_DVBUSDIS), readl(regs + S3C_DVBUSPULSE)); + readl(regs + DVBUSDIS), readl(regs + DVBUSPULSE)); #endif } - /** * state_show - debugfs: show overall driver and device state. * @seq: The seq file to write to. @@ -3005,38 +3186,38 @@ static int state_show(struct seq_file *seq, void *v) int idx; seq_printf(seq, "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n", - readl(regs + S3C_DCFG), - readl(regs + S3C_DCTL), - readl(regs + S3C_DSTS)); + readl(regs + DCFG), + readl(regs + DCTL), + readl(regs + DSTS)); seq_printf(seq, "DIEPMSK=0x%08x, DOEPMASK=0x%08x\n", - readl(regs + S3C_DIEPMSK), readl(regs + S3C_DOEPMSK)); + readl(regs + DIEPMSK), readl(regs + DOEPMSK)); seq_printf(seq, "GINTMSK=0x%08x, GINTSTS=0x%08x\n", - readl(regs + S3C_GINTMSK), - readl(regs + S3C_GINTSTS)); + readl(regs + GINTMSK), + readl(regs + GINTSTS)); seq_printf(seq, "DAINTMSK=0x%08x, DAINT=0x%08x\n", - readl(regs + S3C_DAINTMSK), - readl(regs + S3C_DAINT)); + readl(regs + DAINTMSK), + readl(regs + DAINT)); seq_printf(seq, "GNPTXSTS=0x%08x, GRXSTSR=%08x\n", - readl(regs + S3C_GNPTXSTS), - readl(regs + S3C_GRXSTSR)); + readl(regs + GNPTXSTS), + readl(regs + GRXSTSR)); seq_printf(seq, "\nEndpoint status:\n"); for (idx = 0; idx < 15; idx++) { u32 in, out; - in = readl(regs + S3C_DIEPCTL(idx)); - out = readl(regs + S3C_DOEPCTL(idx)); + in = readl(regs + DIEPCTL(idx)); + out = readl(regs + DOEPCTL(idx)); seq_printf(seq, "ep%d: DIEPCTL=0x%08x, DOEPCTL=0x%08x", idx, in, out); - in = readl(regs + S3C_DIEPTSIZ(idx)); - out = readl(regs + S3C_DOEPTSIZ(idx)); + in = readl(regs + DIEPTSIZ(idx)); + out = readl(regs + DOEPTSIZ(idx)); seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x", in, out); @@ -3067,7 +3248,7 @@ static const struct file_operations state_fops = { * * Show the FIFO information for the overall fifo and all the * periodic transmission FIFOs. -*/ + */ static int fifo_show(struct seq_file *seq, void *v) { struct s3c_hsotg *hsotg = seq->private; @@ -3076,21 +3257,21 @@ static int fifo_show(struct seq_file *seq, void *v) int idx; seq_printf(seq, "Non-periodic FIFOs:\n"); - seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + S3C_GRXFSIZ)); + seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + GRXFSIZ)); - val = readl(regs + S3C_GNPTXFSIZ); + val = readl(regs + GNPTXFSIZ); seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n", - val >> S3C_GNPTXFSIZ_NPTxFDep_SHIFT, - val & S3C_GNPTXFSIZ_NPTxFStAddr_MASK); + val >> GNPTXFSIZ_NPTxFDep_SHIFT, + val & GNPTXFSIZ_NPTxFStAddr_MASK); seq_printf(seq, "\nPeriodic TXFIFOs:\n"); for (idx = 1; idx <= 15; idx++) { - val = readl(regs + S3C_DPTXFSIZn(idx)); + val = readl(regs + DPTXFSIZn(idx)); seq_printf(seq, "\tDPTXFIFO%2d: Size %d, Start 0x%08x\n", idx, - val >> S3C_DPTXFSIZn_DPTxFSize_SHIFT, - val & S3C_DPTXFSIZn_DPTxFStAddr_MASK); + val >> DPTXFSIZn_DPTxFSize_SHIFT, + val & DPTXFSIZn_DPTxFStAddr_MASK); } return 0; @@ -3122,7 +3303,7 @@ static const char *decode_direction(int is_in) * * This debugfs entry shows the state of the given endpoint (one is * registered for each available). -*/ + */ static int ep_show(struct seq_file *seq, void *v) { struct s3c_hsotg_ep *ep = seq->private; @@ -3139,20 +3320,20 @@ static int ep_show(struct seq_file *seq, void *v) /* first show the register state */ seq_printf(seq, "\tDIEPCTL=0x%08x, DOEPCTL=0x%08x\n", - readl(regs + S3C_DIEPCTL(index)), - readl(regs + S3C_DOEPCTL(index))); + readl(regs + DIEPCTL(index)), + readl(regs + DOEPCTL(index))); seq_printf(seq, "\tDIEPDMA=0x%08x, DOEPDMA=0x%08x\n", - readl(regs + S3C_DIEPDMA(index)), - readl(regs + S3C_DOEPDMA(index))); + readl(regs + DIEPDMA(index)), + readl(regs + DOEPDMA(index))); seq_printf(seq, "\tDIEPINT=0x%08x, DOEPINT=0x%08x\n", - readl(regs + S3C_DIEPINT(index)), - readl(regs + S3C_DOEPINT(index))); + readl(regs + DIEPINT(index)), + readl(regs + DOEPINT(index))); seq_printf(seq, "\tDIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x\n", - readl(regs + S3C_DIEPTSIZ(index)), - readl(regs + S3C_DOEPTSIZ(index))); + readl(regs + DIEPTSIZ(index)), + readl(regs + DOEPTSIZ(index))); seq_printf(seq, "\n"); seq_printf(seq, "mps %d\n", ep->ep.maxpacket); @@ -3202,7 +3383,7 @@ static const struct file_operations ep_fops = { * about the state of the system. The directory name is created * with the same name as the device itself, in case we end up * with multiple blocks in future systems. -*/ + */ static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg) { struct dentry *root; @@ -3231,7 +3412,7 @@ static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg) /* create one file for each endpoint */ - for (epidx = 0; epidx < S3C_HSOTG_EPS; epidx++) { + for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) { struct s3c_hsotg_ep *ep = &hsotg->eps[epidx]; ep->debugfs = debugfs_create_file(ep->name, 0444, @@ -3248,12 +3429,12 @@ static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg) * @hsotg: The driver state * * Cleanup (remove) the debugfs files for use on module exit. -*/ + */ static void __devexit s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg) { unsigned epidx; - for (epidx = 0; epidx < S3C_HSOTG_EPS; epidx++) { + for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) { struct s3c_hsotg_ep *ep = &hsotg->eps[epidx]; debugfs_remove(ep->debugfs); } @@ -3264,48 +3445,39 @@ static void __devexit s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg) } /** - * s3c_hsotg_gate - set the hardware gate for the block - * @pdev: The device we bound to - * @on: On or off. - * - * Set the hardware gate setting into the block. If we end up on - * something other than an S3C64XX, then we might need to change this - * to using a platform data callback, or some other mechanism. + * s3c_hsotg_release - release callback for hsotg device + * @dev: Device to for which release is called */ -static void s3c_hsotg_gate(struct platform_device *pdev, bool on) +static void s3c_hsotg_release(struct device *dev) { - unsigned long flags; - u32 others; - - local_irq_save(flags); - - others = __raw_readl(S3C64XX_OTHERS); - if (on) - others |= S3C64XX_OTHERS_USBMASK; - else - others &= ~S3C64XX_OTHERS_USBMASK; - __raw_writel(others, S3C64XX_OTHERS); + struct s3c_hsotg *hsotg = dev_get_drvdata(dev); - local_irq_restore(flags); + kfree(hsotg); } -static struct s3c_hsotg_plat s3c_hsotg_default_pdata; +/** + * s3c_hsotg_probe - probe function for hsotg driver + * @pdev: The platform information for the driver + */ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) { struct s3c_hsotg_plat *plat = pdev->dev.platform_data; struct device *dev = &pdev->dev; + struct s3c_hsotg_ep *eps; struct s3c_hsotg *hsotg; struct resource *res; int epnum; int ret; + int i; - if (!plat) - plat = &s3c_hsotg_default_pdata; + plat = pdev->dev.platform_data; + if (!plat) { + dev_err(&pdev->dev, "no platform data defined\n"); + return -EINVAL; + } - hsotg = kzalloc(sizeof(struct s3c_hsotg) + - sizeof(struct s3c_hsotg_ep) * S3C_HSOTG_EPS, - GFP_KERNEL); + hsotg = kzalloc(sizeof(struct s3c_hsotg), GFP_KERNEL); if (!hsotg) { dev_err(dev, "cannot get memory\n"); return -ENOMEM; @@ -3371,6 +3543,54 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) hsotg->gadget.dev.parent = dev; hsotg->gadget.dev.dma_mask = dev->dma_mask; + hsotg->gadget.dev.release = s3c_hsotg_release; + + /* reset the system */ + + clk_prepare_enable(hsotg->clk); + + /* regulators */ + + for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++) + hsotg->supplies[i].supply = s3c_hsotg_supply_names[i]; + + ret = regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies), + hsotg->supplies); + if (ret) { + dev_err(dev, "failed to request supplies: %d\n", ret); + goto err_irq; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), + hsotg->supplies); + + if (ret) { + dev_err(hsotg->dev, "failed to enable supplies: %d\n", ret); + goto err_supplies; + } + + /* usb phy enable */ + s3c_hsotg_phy_enable(hsotg); + + s3c_hsotg_corereset(hsotg); + s3c_hsotg_init(hsotg); + s3c_hsotg_hw_cfg(hsotg); + + /* hsotg->num_of_eps holds number of EPs other than ep0 */ + + if (hsotg->num_of_eps == 0) { + dev_err(dev, "wrong number of EPs (zero)\n"); + goto err_supplies; + } + + eps = kcalloc(hsotg->num_of_eps + 1, sizeof(struct s3c_hsotg_ep), + GFP_KERNEL); + if (!eps) { + dev_err(dev, "cannot get memory\n"); + goto err_supplies; + } + + hsotg->eps = eps; /* setup endpoint information */ @@ -3383,39 +3603,47 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) GFP_KERNEL); if (!hsotg->ctrl_req) { dev_err(dev, "failed to allocate ctrl req\n"); - goto err_regs; + goto err_ep_mem; } - /* reset the system */ + /* initialise the endpoints now the core has been initialised */ + for (epnum = 0; epnum < hsotg->num_of_eps; epnum++) + s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum); - clk_enable(hsotg->clk); + /* disable power and clock */ - s3c_hsotg_gate(pdev, true); + ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), + hsotg->supplies); + if (ret) { + dev_err(hsotg->dev, "failed to disable supplies: %d\n", ret); + goto err_ep_mem; + } - s3c_hsotg_otgreset(hsotg); - s3c_hsotg_corereset(hsotg); - s3c_hsotg_init(hsotg); + s3c_hsotg_phy_disable(hsotg); - /* initialise the endpoints now the core has been initialised */ - for (epnum = 0; epnum < S3C_HSOTG_EPS; epnum++) - s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum); + ret = device_add(&hsotg->gadget.dev); + if (ret) { + put_device(&hsotg->gadget.dev); + goto err_ep_mem; + } ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget); if (ret) - goto err_add_udc; + goto err_ep_mem; s3c_hsotg_create_debug(hsotg); s3c_hsotg_dump(hsotg); - our_hsotg = hsotg; return 0; -err_add_udc: - s3c_hsotg_gate(pdev, false); - clk_disable(hsotg->clk); - clk_put(hsotg->clk); - +err_ep_mem: + kfree(eps); +err_supplies: + s3c_hsotg_phy_disable(hsotg); + regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); +err_irq: + free_irq(hsotg->irq, hsotg); err_regs: iounmap(hsotg->regs); @@ -3423,12 +3651,17 @@ err_regs_res: release_resource(hsotg->regs_res); kfree(hsotg->regs_res); err_clk: + clk_disable_unprepare(hsotg->clk); clk_put(hsotg->clk); err_mem: kfree(hsotg); return ret; } +/** + * s3c_hsotg_remove - remove function for hsotg driver + * @pdev: The platform information for the driver + */ static int __devexit s3c_hsotg_remove(struct platform_device *pdev) { struct s3c_hsotg *hsotg = platform_get_drvdata(pdev); @@ -3437,7 +3670,10 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev) s3c_hsotg_delete_debug(hsotg); - usb_gadget_unregister_driver(hsotg->driver); + if (hsotg->driver) { + /* should have been done already by driver model core */ + usb_gadget_unregister_driver(hsotg->driver); + } free_irq(hsotg->irq, hsotg); iounmap(hsotg->regs); @@ -3445,12 +3681,13 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev) release_resource(hsotg->regs_res); kfree(hsotg->regs_res); - s3c_hsotg_gate(pdev, false); + s3c_hsotg_phy_disable(hsotg); + regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); - clk_disable(hsotg->clk); + clk_disable_unprepare(hsotg->clk); clk_put(hsotg->clk); - kfree(hsotg); + device_unregister(&hsotg->gadget.dev); return 0; } diff --git a/drivers/usb/gadget/s3c-hsotg.h b/drivers/usb/gadget/s3c-hsotg.h new file mode 100644 index 000000000000..d650b1295831 --- /dev/null +++ b/drivers/usb/gadget/s3c-hsotg.h @@ -0,0 +1,377 @@ +/* drivers/usb/gadget/s3c-hsotg.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * USB2.0 Highspeed/OtG Synopsis DWC2 device block registers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __REGS_USB_HSOTG_H +#define __REGS_USB_HSOTG_H __FILE__ + +#define HSOTG_REG(x) (x) + +#define GOTGCTL HSOTG_REG(0x000) +#define GOTGCTL_BSESVLD (1 << 19) +#define GOTGCTL_ASESVLD (1 << 18) +#define GOTGCTL_DBNC_SHORT (1 << 17) +#define GOTGCTL_CONID_B (1 << 16) +#define GOTGCTL_DEVHNPEN (1 << 11) +#define GOTGCTL_HSSETHNPEN (1 << 10) +#define GOTGCTL_HNPREQ (1 << 9) +#define GOTGCTL_HSTNEGSCS (1 << 8) +#define GOTGCTL_SESREQ (1 << 1) +#define GOTGCTL_SESREQSCS (1 << 0) + +#define GOTGINT HSOTG_REG(0x004) +#define GOTGINT_DbnceDone (1 << 19) +#define GOTGINT_ADevTOUTChg (1 << 18) +#define GOTGINT_HstNegDet (1 << 17) +#define GOTGINT_HstnegSucStsChng (1 << 9) +#define GOTGINT_SesReqSucStsChng (1 << 8) +#define GOTGINT_SesEndDet (1 << 2) + +#define GAHBCFG HSOTG_REG(0x008) +#define GAHBCFG_PTxFEmpLvl (1 << 8) +#define GAHBCFG_NPTxFEmpLvl (1 << 7) +#define GAHBCFG_DMAEn (1 << 5) +#define GAHBCFG_HBstLen_MASK (0xf << 1) +#define GAHBCFG_HBstLen_SHIFT (1) +#define GAHBCFG_HBstLen_Single (0x0 << 1) +#define GAHBCFG_HBstLen_Incr (0x1 << 1) +#define GAHBCFG_HBstLen_Incr4 (0x3 << 1) +#define GAHBCFG_HBstLen_Incr8 (0x5 << 1) +#define GAHBCFG_HBstLen_Incr16 (0x7 << 1) +#define GAHBCFG_GlblIntrEn (1 << 0) + +#define GUSBCFG HSOTG_REG(0x00C) +#define GUSBCFG_PHYLPClkSel (1 << 15) +#define GUSBCFG_HNPCap (1 << 9) +#define GUSBCFG_SRPCap (1 << 8) +#define GUSBCFG_PHYIf16 (1 << 3) +#define GUSBCFG_TOutCal_MASK (0x7 << 0) +#define GUSBCFG_TOutCal_SHIFT (0) +#define GUSBCFG_TOutCal_LIMIT (0x7) +#define GUSBCFG_TOutCal(_x) ((_x) << 0) + +#define GRSTCTL HSOTG_REG(0x010) + +#define GRSTCTL_AHBIdle (1 << 31) +#define GRSTCTL_DMAReq (1 << 30) +#define GRSTCTL_TxFNum_MASK (0x1f << 6) +#define GRSTCTL_TxFNum_SHIFT (6) +#define GRSTCTL_TxFNum_LIMIT (0x1f) +#define GRSTCTL_TxFNum(_x) ((_x) << 6) +#define GRSTCTL_TxFFlsh (1 << 5) +#define GRSTCTL_RxFFlsh (1 << 4) +#define GRSTCTL_INTknQFlsh (1 << 3) +#define GRSTCTL_FrmCntrRst (1 << 2) +#define GRSTCTL_HSftRst (1 << 1) +#define GRSTCTL_CSftRst (1 << 0) + +#define GINTSTS HSOTG_REG(0x014) +#define GINTMSK HSOTG_REG(0x018) + +#define GINTSTS_WkUpInt (1 << 31) +#define GINTSTS_SessReqInt (1 << 30) +#define GINTSTS_DisconnInt (1 << 29) +#define GINTSTS_ConIDStsChng (1 << 28) +#define GINTSTS_PTxFEmp (1 << 26) +#define GINTSTS_HChInt (1 << 25) +#define GINTSTS_PrtInt (1 << 24) +#define GINTSTS_FetSusp (1 << 22) +#define GINTSTS_incompIP (1 << 21) +#define GINTSTS_IncomplSOIN (1 << 20) +#define GINTSTS_OEPInt (1 << 19) +#define GINTSTS_IEPInt (1 << 18) +#define GINTSTS_EPMis (1 << 17) +#define GINTSTS_EOPF (1 << 15) +#define GINTSTS_ISOutDrop (1 << 14) +#define GINTSTS_EnumDone (1 << 13) +#define GINTSTS_USBRst (1 << 12) +#define GINTSTS_USBSusp (1 << 11) +#define GINTSTS_ErlySusp (1 << 10) +#define GINTSTS_GOUTNakEff (1 << 7) +#define GINTSTS_GINNakEff (1 << 6) +#define GINTSTS_NPTxFEmp (1 << 5) +#define GINTSTS_RxFLvl (1 << 4) +#define GINTSTS_SOF (1 << 3) +#define GINTSTS_OTGInt (1 << 2) +#define GINTSTS_ModeMis (1 << 1) +#define GINTSTS_CurMod_Host (1 << 0) + +#define GRXSTSR HSOTG_REG(0x01C) +#define GRXSTSP HSOTG_REG(0x020) + +#define GRXSTS_FN_MASK (0x7f << 25) +#define GRXSTS_FN_SHIFT (25) + +#define GRXSTS_PktSts_MASK (0xf << 17) +#define GRXSTS_PktSts_SHIFT (17) +#define GRXSTS_PktSts_GlobalOutNAK (0x1 << 17) +#define GRXSTS_PktSts_OutRX (0x2 << 17) +#define GRXSTS_PktSts_OutDone (0x3 << 17) +#define GRXSTS_PktSts_SetupDone (0x4 << 17) +#define GRXSTS_PktSts_SetupRX (0x6 << 17) + +#define GRXSTS_DPID_MASK (0x3 << 15) +#define GRXSTS_DPID_SHIFT (15) +#define GRXSTS_ByteCnt_MASK (0x7ff << 4) +#define GRXSTS_ByteCnt_SHIFT (4) +#define GRXSTS_EPNum_MASK (0xf << 0) +#define GRXSTS_EPNum_SHIFT (0) + +#define GRXFSIZ HSOTG_REG(0x024) + +#define GNPTXFSIZ HSOTG_REG(0x028) + +#define GNPTXFSIZ_NPTxFDep_MASK (0xffff << 16) +#define GNPTXFSIZ_NPTxFDep_SHIFT (16) +#define GNPTXFSIZ_NPTxFDep_LIMIT (0xffff) +#define GNPTXFSIZ_NPTxFDep(_x) ((_x) << 16) +#define GNPTXFSIZ_NPTxFStAddr_MASK (0xffff << 0) +#define GNPTXFSIZ_NPTxFStAddr_SHIFT (0) +#define GNPTXFSIZ_NPTxFStAddr_LIMIT (0xffff) +#define GNPTXFSIZ_NPTxFStAddr(_x) ((_x) << 0) + +#define GNPTXSTS HSOTG_REG(0x02C) + +#define GNPTXSTS_NPtxQTop_MASK (0x7f << 24) +#define GNPTXSTS_NPtxQTop_SHIFT (24) + +#define GNPTXSTS_NPTxQSpcAvail_MASK (0xff << 16) +#define GNPTXSTS_NPTxQSpcAvail_SHIFT (16) +#define GNPTXSTS_NPTxQSpcAvail_GET(_v) (((_v) >> 16) & 0xff) + +#define GNPTXSTS_NPTxFSpcAvail_MASK (0xffff << 0) +#define GNPTXSTS_NPTxFSpcAvail_SHIFT (0) +#define GNPTXSTS_NPTxFSpcAvail_GET(_v) (((_v) >> 0) & 0xffff) + + +#define HPTXFSIZ HSOTG_REG(0x100) + +#define DPTXFSIZn(_a) HSOTG_REG(0x104 + (((_a) - 1) * 4)) + +#define DPTXFSIZn_DPTxFSize_MASK (0xffff << 16) +#define DPTXFSIZn_DPTxFSize_SHIFT (16) +#define DPTXFSIZn_DPTxFSize_GET(_v) (((_v) >> 16) & 0xffff) +#define DPTXFSIZn_DPTxFSize_LIMIT (0xffff) +#define DPTXFSIZn_DPTxFSize(_x) ((_x) << 16) + +#define DPTXFSIZn_DPTxFStAddr_MASK (0xffff << 0) +#define DPTXFSIZn_DPTxFStAddr_SHIFT (0) + +/* Device mode registers */ +#define DCFG HSOTG_REG(0x800) + +#define DCFG_EPMisCnt_MASK (0x1f << 18) +#define DCFG_EPMisCnt_SHIFT (18) +#define DCFG_EPMisCnt_LIMIT (0x1f) +#define DCFG_EPMisCnt(_x) ((_x) << 18) + +#define DCFG_PerFrInt_MASK (0x3 << 11) +#define DCFG_PerFrInt_SHIFT (11) +#define DCFG_PerFrInt_LIMIT (0x3) +#define DCFG_PerFrInt(_x) ((_x) << 11) + +#define DCFG_DevAddr_MASK (0x7f << 4) +#define DCFG_DevAddr_SHIFT (4) +#define DCFG_DevAddr_LIMIT (0x7f) +#define DCFG_DevAddr(_x) ((_x) << 4) + +#define DCFG_NZStsOUTHShk (1 << 2) + +#define DCFG_DevSpd_MASK (0x3 << 0) +#define DCFG_DevSpd_SHIFT (0) +#define DCFG_DevSpd_HS (0x0 << 0) +#define DCFG_DevSpd_FS (0x1 << 0) +#define DCFG_DevSpd_LS (0x2 << 0) +#define DCFG_DevSpd_FS48 (0x3 << 0) + +#define DCTL HSOTG_REG(0x804) + +#define DCTL_PWROnPrgDone (1 << 11) +#define DCTL_CGOUTNak (1 << 10) +#define DCTL_SGOUTNak (1 << 9) +#define DCTL_CGNPInNAK (1 << 8) +#define DCTL_SGNPInNAK (1 << 7) +#define DCTL_TstCtl_MASK (0x7 << 4) +#define DCTL_TstCtl_SHIFT (4) +#define DCTL_GOUTNakSts (1 << 3) +#define DCTL_GNPINNakSts (1 << 2) +#define DCTL_SftDiscon (1 << 1) +#define DCTL_RmtWkUpSig (1 << 0) + +#define DSTS HSOTG_REG(0x808) + +#define DSTS_SOFFN_MASK (0x3fff << 8) +#define DSTS_SOFFN_SHIFT (8) +#define DSTS_SOFFN_LIMIT (0x3fff) +#define DSTS_SOFFN(_x) ((_x) << 8) +#define DSTS_ErraticErr (1 << 3) +#define DSTS_EnumSpd_MASK (0x3 << 1) +#define DSTS_EnumSpd_SHIFT (1) +#define DSTS_EnumSpd_HS (0x0 << 1) +#define DSTS_EnumSpd_FS (0x1 << 1) +#define DSTS_EnumSpd_LS (0x2 << 1) +#define DSTS_EnumSpd_FS48 (0x3 << 1) + +#define DSTS_SuspSts (1 << 0) + +#define DIEPMSK HSOTG_REG(0x810) + +#define DIEPMSK_TxFIFOEmpty (1 << 7) +#define DIEPMSK_INEPNakEffMsk (1 << 6) +#define DIEPMSK_INTknEPMisMsk (1 << 5) +#define DIEPMSK_INTknTXFEmpMsk (1 << 4) +#define DIEPMSK_TimeOUTMsk (1 << 3) +#define DIEPMSK_AHBErrMsk (1 << 2) +#define DIEPMSK_EPDisbldMsk (1 << 1) +#define DIEPMSK_XferComplMsk (1 << 0) + +#define DOEPMSK HSOTG_REG(0x814) + +#define DOEPMSK_Back2BackSetup (1 << 6) +#define DOEPMSK_OUTTknEPdisMsk (1 << 4) +#define DOEPMSK_SetupMsk (1 << 3) +#define DOEPMSK_AHBErrMsk (1 << 2) +#define DOEPMSK_EPDisbldMsk (1 << 1) +#define DOEPMSK_XferComplMsk (1 << 0) + +#define DAINT HSOTG_REG(0x818) +#define DAINTMSK HSOTG_REG(0x81C) + +#define DAINT_OutEP_SHIFT (16) +#define DAINT_OutEP(x) (1 << ((x) + 16)) +#define DAINT_InEP(x) (1 << (x)) + +#define DTKNQR1 HSOTG_REG(0x820) +#define DTKNQR2 HSOTG_REG(0x824) +#define DTKNQR3 HSOTG_REG(0x830) +#define DTKNQR4 HSOTG_REG(0x834) + +#define DVBUSDIS HSOTG_REG(0x828) +#define DVBUSPULSE HSOTG_REG(0x82C) + +#define DIEPCTL0 HSOTG_REG(0x900) +#define DOEPCTL0 HSOTG_REG(0xB00) +#define DIEPCTL(_a) HSOTG_REG(0x900 + ((_a) * 0x20)) +#define DOEPCTL(_a) HSOTG_REG(0xB00 + ((_a) * 0x20)) + +/* EP0 specialness: + * bits[29..28] - reserved (no SetD0PID, SetD1PID) + * bits[25..22] - should always be zero, this isn't a periodic endpoint + * bits[10..0] - MPS setting differenct for EP0 + */ +#define D0EPCTL_MPS_MASK (0x3 << 0) +#define D0EPCTL_MPS_SHIFT (0) +#define D0EPCTL_MPS_64 (0x0 << 0) +#define D0EPCTL_MPS_32 (0x1 << 0) +#define D0EPCTL_MPS_16 (0x2 << 0) +#define D0EPCTL_MPS_8 (0x3 << 0) + +#define DxEPCTL_EPEna (1 << 31) +#define DxEPCTL_EPDis (1 << 30) +#define DxEPCTL_SetD1PID (1 << 29) +#define DxEPCTL_SetOddFr (1 << 29) +#define DxEPCTL_SetD0PID (1 << 28) +#define DxEPCTL_SetEvenFr (1 << 28) +#define DxEPCTL_SNAK (1 << 27) +#define DxEPCTL_CNAK (1 << 26) +#define DxEPCTL_TxFNum_MASK (0xf << 22) +#define DxEPCTL_TxFNum_SHIFT (22) +#define DxEPCTL_TxFNum_LIMIT (0xf) +#define DxEPCTL_TxFNum(_x) ((_x) << 22) + +#define DxEPCTL_Stall (1 << 21) +#define DxEPCTL_Snp (1 << 20) +#define DxEPCTL_EPType_MASK (0x3 << 18) +#define DxEPCTL_EPType_SHIFT (18) +#define DxEPCTL_EPType_Control (0x0 << 18) +#define DxEPCTL_EPType_Iso (0x1 << 18) +#define DxEPCTL_EPType_Bulk (0x2 << 18) +#define DxEPCTL_EPType_Intterupt (0x3 << 18) + +#define DxEPCTL_NAKsts (1 << 17) +#define DxEPCTL_DPID (1 << 16) +#define DxEPCTL_EOFrNum (1 << 16) +#define DxEPCTL_USBActEp (1 << 15) +#define DxEPCTL_NextEp_MASK (0xf << 11) +#define DxEPCTL_NextEp_SHIFT (11) +#define DxEPCTL_NextEp_LIMIT (0xf) +#define DxEPCTL_NextEp(_x) ((_x) << 11) + +#define DxEPCTL_MPS_MASK (0x7ff << 0) +#define DxEPCTL_MPS_SHIFT (0) +#define DxEPCTL_MPS_LIMIT (0x7ff) +#define DxEPCTL_MPS(_x) ((_x) << 0) + +#define DIEPINT(_a) HSOTG_REG(0x908 + ((_a) * 0x20)) +#define DOEPINT(_a) HSOTG_REG(0xB08 + ((_a) * 0x20)) + +#define DxEPINT_INEPNakEff (1 << 6) +#define DxEPINT_Back2BackSetup (1 << 6) +#define DxEPINT_INTknEPMis (1 << 5) +#define DxEPINT_INTknTXFEmp (1 << 4) +#define DxEPINT_OUTTknEPdis (1 << 4) +#define DxEPINT_Timeout (1 << 3) +#define DxEPINT_Setup (1 << 3) +#define DxEPINT_AHBErr (1 << 2) +#define DxEPINT_EPDisbld (1 << 1) +#define DxEPINT_XferCompl (1 << 0) + +#define DIEPTSIZ0 HSOTG_REG(0x910) + +#define DIEPTSIZ0_PktCnt_MASK (0x3 << 19) +#define DIEPTSIZ0_PktCnt_SHIFT (19) +#define DIEPTSIZ0_PktCnt_LIMIT (0x3) +#define DIEPTSIZ0_PktCnt(_x) ((_x) << 19) + +#define DIEPTSIZ0_XferSize_MASK (0x7f << 0) +#define DIEPTSIZ0_XferSize_SHIFT (0) +#define DIEPTSIZ0_XferSize_LIMIT (0x7f) +#define DIEPTSIZ0_XferSize(_x) ((_x) << 0) + +#define DOEPTSIZ0 HSOTG_REG(0xB10) +#define DOEPTSIZ0_SUPCnt_MASK (0x3 << 29) +#define DOEPTSIZ0_SUPCnt_SHIFT (29) +#define DOEPTSIZ0_SUPCnt_LIMIT (0x3) +#define DOEPTSIZ0_SUPCnt(_x) ((_x) << 29) + +#define DOEPTSIZ0_PktCnt (1 << 19) +#define DOEPTSIZ0_XferSize_MASK (0x7f << 0) +#define DOEPTSIZ0_XferSize_SHIFT (0) + +#define DIEPTSIZ(_a) HSOTG_REG(0x910 + ((_a) * 0x20)) +#define DOEPTSIZ(_a) HSOTG_REG(0xB10 + ((_a) * 0x20)) + +#define DxEPTSIZ_MC_MASK (0x3 << 29) +#define DxEPTSIZ_MC_SHIFT (29) +#define DxEPTSIZ_MC_LIMIT (0x3) +#define DxEPTSIZ_MC(_x) ((_x) << 29) + +#define DxEPTSIZ_PktCnt_MASK (0x3ff << 19) +#define DxEPTSIZ_PktCnt_SHIFT (19) +#define DxEPTSIZ_PktCnt_GET(_v) (((_v) >> 19) & 0x3ff) +#define DxEPTSIZ_PktCnt_LIMIT (0x3ff) +#define DxEPTSIZ_PktCnt(_x) ((_x) << 19) + +#define DxEPTSIZ_XferSize_MASK (0x7ffff << 0) +#define DxEPTSIZ_XferSize_SHIFT (0) +#define DxEPTSIZ_XferSize_GET(_v) (((_v) >> 0) & 0x7ffff) +#define DxEPTSIZ_XferSize_LIMIT (0x7ffff) +#define DxEPTSIZ_XferSize(_x) ((_x) << 0) + +#define DIEPDMA(_a) HSOTG_REG(0x914 + ((_a) * 0x20)) +#define DOEPDMA(_a) HSOTG_REG(0xB14 + ((_a) * 0x20)) +#define DTXFSTS(_a) HSOTG_REG(0x918 + ((_a) * 0x20)) + +#define EPFIFO(_a) HSOTG_REG(0x1000 + ((_a) * 0x1000)) + +#endif /* __REGS_USB_HSOTG_H */ diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index cef9b82ff911..36c6836eeb0f 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -110,7 +110,6 @@ struct s3c_hsudc_ep { struct usb_ep ep; char name[20]; struct s3c_hsudc *dev; - const struct usb_endpoint_descriptor *desc; struct list_head queue; u8 stopped; u8 wedge; @@ -761,7 +760,7 @@ static int s3c_hsudc_ep_enable(struct usb_ep *_ep, u32 ecr = 0; hsep = our_ep(_ep); - if (!_ep || !desc || hsep->desc || _ep->name == ep0name + if (!_ep || !desc || hsep->ep.desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT || hsep->bEndpointAddress != desc->bEndpointAddress || ep_maxpacket(hsep) < usb_endpoint_maxp(desc)) @@ -783,7 +782,7 @@ static int s3c_hsudc_ep_enable(struct usb_ep *_ep, writel(ecr, hsudc->regs + S3C_ECR); hsep->stopped = hsep->wedge = 0; - hsep->desc = desc; + hsep->ep.desc = desc; hsep->ep.maxpacket = usb_endpoint_maxp(desc); s3c_hsudc_set_halt(_ep, 0); @@ -806,7 +805,7 @@ static int s3c_hsudc_ep_disable(struct usb_ep *_ep) struct s3c_hsudc *hsudc = hsep->dev; unsigned long flags; - if (!_ep || !hsep->desc) + if (!_ep || !hsep->ep.desc) return -EINVAL; spin_lock_irqsave(&hsudc->lock, flags); @@ -816,7 +815,6 @@ static int s3c_hsudc_ep_disable(struct usb_ep *_ep) s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN); - hsep->desc = 0; hsep->ep.desc = NULL; hsep->stopped = 1; @@ -1006,7 +1004,6 @@ static void s3c_hsudc_initep(struct s3c_hsudc *hsudc, hsep->ep.maxpacket = epnum ? 512 : 64; hsep->ep.ops = &s3c_hsudc_ep_ops; hsep->fifo = hsudc->regs + S3C_BR(epnum); - hsep->desc = 0; hsep->ep.desc = NULL; hsep->stopped = 0; hsep->wedge = 0; diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 195524cde6c3..3de71d37d75e 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1062,7 +1062,7 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep, ep = to_s3c2410_ep(_ep); - if (!_ep || !desc || ep->desc + if (!_ep || !desc || ep->ep.desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT) return -EINVAL; @@ -1075,7 +1075,7 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep, local_irq_save (flags); _ep->maxpacket = max & 0x7ff; - ep->desc = desc; + ep->ep.desc = desc; ep->halted = 0; ep->bEndpointAddress = desc->bEndpointAddress; @@ -1136,7 +1136,7 @@ static int s3c2410_udc_ep_disable(struct usb_ep *_ep) unsigned long flags; u32 int_en_reg; - if (!_ep || !ep->desc) { + if (!_ep || !ep->ep.desc) { dprintk(DEBUG_NORMAL, "%s not enabled\n", _ep ? ep->ep.name : NULL); return -EINVAL; @@ -1146,7 +1146,6 @@ static int s3c2410_udc_ep_disable(struct usb_ep *_ep) dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name); - ep->desc = NULL; ep->ep.desc = NULL; ep->halted = 1; @@ -1195,7 +1194,7 @@ s3c2410_udc_free_request(struct usb_ep *_ep, struct usb_request *_req) dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req); - if (!ep || !_req || (!ep->desc && _ep->name != ep0name)) + if (!ep || !_req || (!ep->ep.desc && _ep->name != ep0name)) return; WARN_ON (!list_empty (&req->queue)); @@ -1215,7 +1214,7 @@ static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req, int fifo_count = 0; unsigned long flags; - if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) { + if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) { dprintk(DEBUG_NORMAL, "%s: invalid args\n", __func__); return -EINVAL; } @@ -1363,7 +1362,7 @@ static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value) unsigned long flags; u32 idx; - if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) { + if (unlikely(!_ep || (!ep->ep.desc && ep->ep.name != ep0name))) { dprintk(DEBUG_NORMAL, "%s: inval 2\n", __func__); return -EINVAL; } @@ -1629,7 +1628,6 @@ static void s3c2410_udc_reinit(struct s3c2410_udc *dev) list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list); ep->dev = dev; - ep->desc = NULL; ep->ep.desc = NULL; ep->halted = 0; INIT_LIST_HEAD (&ep->queue); diff --git a/drivers/usb/gadget/s3c2410_udc.h b/drivers/usb/gadget/s3c2410_udc.h index 1653bae08b80..3e80fd5c820f 100644 --- a/drivers/usb/gadget/s3c2410_udc.h +++ b/drivers/usb/gadget/s3c2410_udc.h @@ -19,7 +19,6 @@ struct s3c2410_ep { unsigned long last_io; /* jiffies timestamp */ struct usb_gadget *gadget; struct s3c2410_udc *dev; - const struct usb_endpoint_descriptor *desc; struct usb_ep ep; u8 num; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 31d34832907e..12ad516ada77 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -72,7 +72,7 @@ static const char longname[] = "Gadget Zero"; -unsigned buflen = 4096; +unsigned buflen = 4096; /* only used for bulk endpoints */ module_param(buflen, uint, 0); /* @@ -170,14 +170,17 @@ static struct usb_gadget_strings *dev_strings[] = { /*-------------------------------------------------------------------------*/ -struct usb_request *alloc_ep_req(struct usb_ep *ep) +struct usb_request *alloc_ep_req(struct usb_ep *ep, int len) { struct usb_request *req; req = usb_ep_alloc_request(ep, GFP_ATOMIC); if (req) { - req->length = buflen; - req->buf = kmalloc(buflen, GFP_ATOMIC); + if (len) + req->length = len; + else + req->length = buflen; + req->buf = kmalloc(req->length, GFP_ATOMIC); if (!req->buf) { usb_ep_free_request(ep, req); req = NULL; @@ -206,10 +209,15 @@ static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep) } void disable_endpoints(struct usb_composite_dev *cdev, - struct usb_ep *in, struct usb_ep *out) + struct usb_ep *in, struct usb_ep *out, + struct usb_ep *iso_in, struct usb_ep *iso_out) { disable_ep(cdev, in); disable_ep(cdev, out); + if (iso_in) + disable_ep(cdev, iso_in); + if (iso_out) + disable_ep(cdev, iso_out); } /*-------------------------------------------------------------------------*/ @@ -311,7 +319,6 @@ static int __init zero_bind(struct usb_composite_dev *cdev) device_desc.bcdDevice = cpu_to_le16(0x9999); } - INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname); snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 00bd2a5e0362..28478ce26c34 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -55,6 +55,7 @@ struct usbhsg_gpriv { #define USBHSG_STATUS_STARTED (1 << 0) #define USBHSG_STATUS_REGISTERD (1 << 1) #define USBHSG_STATUS_WEDGE (1 << 2) +#define USBHSG_STATUS_SELF_POWERED (1 << 3) }; struct usbhsg_recip_handle { @@ -333,7 +334,10 @@ static int usbhsg_recip_handler_std_get_device(struct usbhs_priv *priv, struct usb_ctrlrequest *ctrl) { struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); - unsigned short status = 1 << USB_DEVICE_SELF_POWERED; + unsigned short status = 0; + + if (usbhsg_status_has(gpriv, USBHSG_STATUS_SELF_POWERED)) + status = 1 << USB_DEVICE_SELF_POWERED; __usbhsg_recip_send_status(gpriv, status); @@ -879,8 +883,21 @@ static int usbhsg_get_frame(struct usb_gadget *gadget) return usbhs_frame_get_num(priv); } +static int usbhsg_set_selfpowered(struct usb_gadget *gadget, int is_self) +{ + struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); + + if (is_self) + usbhsg_status_set(gpriv, USBHSG_STATUS_SELF_POWERED); + else + usbhsg_status_clr(gpriv, USBHSG_STATUS_SELF_POWERED); + + return 0; +} + static struct usb_gadget_ops usbhsg_gadget_ops = { .get_frame = usbhsg_get_frame, + .set_selfpowered = usbhsg_set_selfpowered, .udc_start = usbhsg_gadget_start, .udc_stop = usbhsg_gadget_stop, }; diff --git a/arch/arm/plat-samsung/include/plat/udc-hs.h b/include/linux/platform_data/s3c-hsotg.h index c9e3667cb2b1..97ec12c2ded4 100644 --- a/arch/arm/plat-samsung/include/plat/udc-hs.h +++ b/include/linux/platform_data/s3c-hsotg.h @@ -1,4 +1,4 @@ -/* arch/arm/plat-s3c/include/plat/udc-hs.h +/* include/linux/platform_data/s3c-hsotg.h * * Copyright 2008 Openmoko, Inc. * Copyright 2008 Simtec Electronics @@ -25,7 +25,8 @@ enum s3c_hsotg_dmamode { */ struct s3c_hsotg_plat { enum s3c_hsotg_dmamode dma; - unsigned int is_osc : 1; + unsigned int is_osc:1; + int phy_type; int (*phy_init)(struct platform_device *pdev, int type); int (*phy_exit)(struct platform_device *pdev, int type); |