123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977 |
- /*
- * Renesas USB3.0 Peripheral driver (USB gadget)
- *
- * Copyright (C) 2015 Renesas Electronics Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- */
- #include <linux/delay.h>
- #include <linux/err.h>
- #include <linux/interrupt.h>
- #include <linux/io.h>
- #include <linux/module.h>
- #include <linux/of_device.h>
- #include <linux/platform_device.h>
- #include <linux/pm_runtime.h>
- #include <linux/sizes.h>
- #include <linux/slab.h>
- #include <linux/usb/ch9.h>
- #include <linux/usb/gadget.h>
- /* register definitions */
- #define USB3_AXI_INT_STA 0x008
- #define USB3_AXI_INT_ENA 0x00c
- #define USB3_DMA_INT_STA 0x010
- #define USB3_DMA_INT_ENA 0x014
- #define USB3_USB_COM_CON 0x200
- #define USB3_USB20_CON 0x204
- #define USB3_USB30_CON 0x208
- #define USB3_USB_STA 0x210
- #define USB3_DRD_CON 0x218
- #define USB3_USB_INT_STA_1 0x220
- #define USB3_USB_INT_STA_2 0x224
- #define USB3_USB_INT_ENA_1 0x228
- #define USB3_USB_INT_ENA_2 0x22c
- #define USB3_STUP_DAT_0 0x230
- #define USB3_STUP_DAT_1 0x234
- #define USB3_P0_MOD 0x280
- #define USB3_P0_CON 0x288
- #define USB3_P0_STA 0x28c
- #define USB3_P0_INT_STA 0x290
- #define USB3_P0_INT_ENA 0x294
- #define USB3_P0_LNG 0x2a0
- #define USB3_P0_READ 0x2a4
- #define USB3_P0_WRITE 0x2a8
- #define USB3_PIPE_COM 0x2b0
- #define USB3_PN_MOD 0x2c0
- #define USB3_PN_RAMMAP 0x2c4
- #define USB3_PN_CON 0x2c8
- #define USB3_PN_STA 0x2cc
- #define USB3_PN_INT_STA 0x2d0
- #define USB3_PN_INT_ENA 0x2d4
- #define USB3_PN_LNG 0x2e0
- #define USB3_PN_READ 0x2e4
- #define USB3_PN_WRITE 0x2e8
- #define USB3_SSIFCMD 0x340
- /* AXI_INT_ENA and AXI_INT_STA */
- #define AXI_INT_DMAINT BIT(31)
- #define AXI_INT_EPCINT BIT(30)
- /* LCLKSEL */
- #define LCLKSEL_LSEL BIT(18)
- /* USB_COM_CON */
- #define USB_COM_CON_CONF BIT(24)
- #define USB_COM_CON_SPD_MODE BIT(17)
- #define USB_COM_CON_EP0_EN BIT(16)
- #define USB_COM_CON_DEV_ADDR_SHIFT 8
- #define USB_COM_CON_DEV_ADDR_MASK GENMASK(14, USB_COM_CON_DEV_ADDR_SHIFT)
- #define USB_COM_CON_DEV_ADDR(n) (((n) << USB_COM_CON_DEV_ADDR_SHIFT) & \
- USB_COM_CON_DEV_ADDR_MASK)
- #define USB_COM_CON_RX_DETECTION BIT(1)
- #define USB_COM_CON_PIPE_CLR BIT(0)
- /* USB20_CON */
- #define USB20_CON_B2_PUE BIT(31)
- #define USB20_CON_B2_SUSPEND BIT(24)
- #define USB20_CON_B2_CONNECT BIT(17)
- #define USB20_CON_B2_TSTMOD_SHIFT 8
- #define USB20_CON_B2_TSTMOD_MASK GENMASK(10, USB20_CON_B2_TSTMOD_SHIFT)
- #define USB20_CON_B2_TSTMOD(n) (((n) << USB20_CON_B2_TSTMOD_SHIFT) & \
- USB20_CON_B2_TSTMOD_MASK)
- #define USB20_CON_B2_TSTMOD_EN BIT(0)
- /* USB30_CON */
- #define USB30_CON_POW_SEL_SHIFT 24
- #define USB30_CON_POW_SEL_MASK GENMASK(26, USB30_CON_POW_SEL_SHIFT)
- #define USB30_CON_POW_SEL_IN_U3 BIT(26)
- #define USB30_CON_POW_SEL_IN_DISCON 0
- #define USB30_CON_POW_SEL_P2_TO_P0 BIT(25)
- #define USB30_CON_POW_SEL_P0_TO_P3 BIT(24)
- #define USB30_CON_POW_SEL_P0_TO_P2 0
- #define USB30_CON_B3_PLLWAKE BIT(23)
- #define USB30_CON_B3_CONNECT BIT(17)
- #define USB30_CON_B3_HOTRST_CMP BIT(1)
- /* USB_STA */
- #define USB_STA_SPEED_MASK (BIT(2) | BIT(1))
- #define USB_STA_SPEED_HS BIT(2)
- #define USB_STA_SPEED_FS BIT(1)
- #define USB_STA_SPEED_SS 0
- #define USB_STA_VBUS_STA BIT(0)
- /* DRD_CON */
- #define DRD_CON_PERI_CON BIT(24)
- #define DRD_CON_VBOUT BIT(0)
- /* USB_INT_ENA_1 and USB_INT_STA_1 */
- #define USB_INT_1_B3_PLLWKUP BIT(31)
- #define USB_INT_1_B3_LUPSUCS BIT(30)
- #define USB_INT_1_B3_DISABLE BIT(27)
- #define USB_INT_1_B3_WRMRST BIT(21)
- #define USB_INT_1_B3_HOTRST BIT(20)
- #define USB_INT_1_B2_USBRST BIT(12)
- #define USB_INT_1_B2_L1SPND BIT(11)
- #define USB_INT_1_B2_SPND BIT(9)
- #define USB_INT_1_B2_RSUM BIT(8)
- #define USB_INT_1_SPEED BIT(1)
- #define USB_INT_1_VBUS_CNG BIT(0)
- /* USB_INT_ENA_2 and USB_INT_STA_2 */
- #define USB_INT_2_PIPE(n) BIT(n)
- /* P0_MOD */
- #define P0_MOD_DIR BIT(6)
- /* P0_CON and PN_CON */
- #define PX_CON_BYTE_EN_MASK (BIT(10) | BIT(9))
- #define PX_CON_BYTE_EN_SHIFT 9
- #define PX_CON_BYTE_EN_BYTES(n) (((n) << PX_CON_BYTE_EN_SHIFT) & \
- PX_CON_BYTE_EN_MASK)
- #define PX_CON_SEND BIT(8)
- /* P0_CON */
- #define P0_CON_ST_RES_MASK (BIT(27) | BIT(26))
- #define P0_CON_ST_RES_FORCE_STALL BIT(27)
- #define P0_CON_ST_RES_NORMAL BIT(26)
- #define P0_CON_ST_RES_FORCE_NRDY 0
- #define P0_CON_OT_RES_MASK (BIT(25) | BIT(24))
- #define P0_CON_OT_RES_FORCE_STALL BIT(25)
- #define P0_CON_OT_RES_NORMAL BIT(24)
- #define P0_CON_OT_RES_FORCE_NRDY 0
- #define P0_CON_IN_RES_MASK (BIT(17) | BIT(16))
- #define P0_CON_IN_RES_FORCE_STALL BIT(17)
- #define P0_CON_IN_RES_NORMAL BIT(16)
- #define P0_CON_IN_RES_FORCE_NRDY 0
- #define P0_CON_RES_WEN BIT(7)
- #define P0_CON_BCLR BIT(1)
- /* P0_STA and PN_STA */
- #define PX_STA_BUFSTS BIT(0)
- /* P0_INT_ENA and P0_INT_STA */
- #define P0_INT_STSED BIT(18)
- #define P0_INT_STSST BIT(17)
- #define P0_INT_SETUP BIT(16)
- #define P0_INT_RCVNL BIT(8)
- #define P0_INT_ERDY BIT(7)
- #define P0_INT_FLOW BIT(6)
- #define P0_INT_STALL BIT(2)
- #define P0_INT_NRDY BIT(1)
- #define P0_INT_BFRDY BIT(0)
- #define P0_INT_ALL_BITS (P0_INT_STSED | P0_INT_SETUP | P0_INT_BFRDY)
- /* PN_MOD */
- #define PN_MOD_DIR BIT(6)
- #define PN_MOD_TYPE_SHIFT 4
- #define PN_MOD_TYPE_MASK GENMASK(5, PN_MOD_TYPE_SHIFT)
- #define PN_MOD_TYPE(n) (((n) << PN_MOD_TYPE_SHIFT) & \
- PN_MOD_TYPE_MASK)
- #define PN_MOD_EPNUM_MASK GENMASK(3, 0)
- #define PN_MOD_EPNUM(n) ((n) & PN_MOD_EPNUM_MASK)
- /* PN_RAMMAP */
- #define PN_RAMMAP_RAMAREA_SHIFT 29
- #define PN_RAMMAP_RAMAREA_MASK GENMASK(31, PN_RAMMAP_RAMAREA_SHIFT)
- #define PN_RAMMAP_RAMAREA_16KB BIT(31)
- #define PN_RAMMAP_RAMAREA_8KB (BIT(30) | BIT(29))
- #define PN_RAMMAP_RAMAREA_4KB BIT(30)
- #define PN_RAMMAP_RAMAREA_2KB BIT(29)
- #define PN_RAMMAP_RAMAREA_1KB 0
- #define PN_RAMMAP_MPKT_SHIFT 16
- #define PN_RAMMAP_MPKT_MASK GENMASK(26, PN_RAMMAP_MPKT_SHIFT)
- #define PN_RAMMAP_MPKT(n) (((n) << PN_RAMMAP_MPKT_SHIFT) & \
- PN_RAMMAP_MPKT_MASK)
- #define PN_RAMMAP_RAMIF_SHIFT 14
- #define PN_RAMMAP_RAMIF_MASK GENMASK(15, PN_RAMMAP_RAMIF_SHIFT)
- #define PN_RAMMAP_RAMIF(n) (((n) << PN_RAMMAP_RAMIF_SHIFT) & \
- PN_RAMMAP_RAMIF_MASK)
- #define PN_RAMMAP_BASEAD_MASK GENMASK(13, 0)
- #define PN_RAMMAP_BASEAD(offs) (((offs) >> 3) & PN_RAMMAP_BASEAD_MASK)
- #define PN_RAMMAP_DATA(area, ramif, basead) ((PN_RAMMAP_##area) | \
- (PN_RAMMAP_RAMIF(ramif)) | \
- (PN_RAMMAP_BASEAD(basead)))
- /* PN_CON */
- #define PN_CON_EN BIT(31)
- #define PN_CON_DATAIF_EN BIT(30)
- #define PN_CON_RES_MASK (BIT(17) | BIT(16))
- #define PN_CON_RES_FORCE_STALL BIT(17)
- #define PN_CON_RES_NORMAL BIT(16)
- #define PN_CON_RES_FORCE_NRDY 0
- #define PN_CON_LAST BIT(11)
- #define PN_CON_RES_WEN BIT(7)
- #define PN_CON_CLR BIT(0)
- /* PN_INT_STA and PN_INT_ENA */
- #define PN_INT_LSTTR BIT(4)
- #define PN_INT_BFRDY BIT(0)
- /* USB3_SSIFCMD */
- #define SSIFCMD_URES_U2 BIT(9)
- #define SSIFCMD_URES_U1 BIT(8)
- #define SSIFCMD_UDIR_U2 BIT(7)
- #define SSIFCMD_UDIR_U1 BIT(6)
- #define SSIFCMD_UREQ_U2 BIT(5)
- #define SSIFCMD_UREQ_U1 BIT(4)
- #define USB3_EP0_SS_MAX_PACKET_SIZE 512
- #define USB3_EP0_HSFS_MAX_PACKET_SIZE 64
- #define USB3_EP0_BUF_SIZE 8
- #define USB3_MAX_NUM_PIPES 30
- #define USB3_WAIT_US 3
- struct renesas_usb3;
- struct renesas_usb3_request {
- struct usb_request req;
- struct list_head queue;
- };
- #define USB3_EP_NAME_SIZE 8
- struct renesas_usb3_ep {
- struct usb_ep ep;
- struct renesas_usb3 *usb3;
- int num;
- char ep_name[USB3_EP_NAME_SIZE];
- struct list_head queue;
- u32 rammap_val;
- bool dir_in;
- bool halt;
- bool wedge;
- bool started;
- };
- struct renesas_usb3_priv {
- int ramsize_per_ramif; /* unit = bytes */
- int num_ramif;
- int ramsize_per_pipe; /* unit = bytes */
- bool workaround_for_vbus; /* if true, don't check vbus signal */
- };
- struct renesas_usb3 {
- void __iomem *reg;
- struct usb_gadget gadget;
- struct usb_gadget_driver *driver;
- struct renesas_usb3_ep *usb3_ep;
- int num_usb3_eps;
- spinlock_t lock;
- int disabled_count;
- struct usb_request *ep0_req;
- u16 test_mode;
- u8 ep0_buf[USB3_EP0_BUF_SIZE];
- bool softconnect;
- bool workaround_for_vbus;
- };
- #define gadget_to_renesas_usb3(_gadget) \
- container_of(_gadget, struct renesas_usb3, gadget)
- #define renesas_usb3_to_gadget(renesas_usb3) (&renesas_usb3->gadget)
- #define usb3_to_dev(_usb3) (_usb3->gadget.dev.parent)
- #define usb_ep_to_usb3_ep(_ep) container_of(_ep, struct renesas_usb3_ep, ep)
- #define usb3_ep_to_usb3(_usb3_ep) (_usb3_ep->usb3)
- #define usb_req_to_usb3_req(_req) container_of(_req, \
- struct renesas_usb3_request, req)
- #define usb3_get_ep(usb3, n) ((usb3)->usb3_ep + (n))
- #define usb3_for_each_ep(usb3_ep, usb3, i) \
- for ((i) = 0, usb3_ep = usb3_get_ep(usb3, (i)); \
- (i) < (usb3)->num_usb3_eps; \
- (i)++, usb3_ep = usb3_get_ep(usb3, (i)))
- static const char udc_name[] = "renesas_usb3";
- static void usb3_write(struct renesas_usb3 *usb3, u32 data, u32 offs)
- {
- iowrite32(data, usb3->reg + offs);
- }
- static u32 usb3_read(struct renesas_usb3 *usb3, u32 offs)
- {
- return ioread32(usb3->reg + offs);
- }
- static void usb3_set_bit(struct renesas_usb3 *usb3, u32 bits, u32 offs)
- {
- u32 val = usb3_read(usb3, offs);
- val |= bits;
- usb3_write(usb3, val, offs);
- }
- static void usb3_clear_bit(struct renesas_usb3 *usb3, u32 bits, u32 offs)
- {
- u32 val = usb3_read(usb3, offs);
- val &= ~bits;
- usb3_write(usb3, val, offs);
- }
- static int usb3_wait(struct renesas_usb3 *usb3, u32 reg, u32 mask,
- u32 expected)
- {
- int i;
- for (i = 0; i < USB3_WAIT_US; i++) {
- if ((usb3_read(usb3, reg) & mask) == expected)
- return 0;
- udelay(1);
- }
- dev_dbg(usb3_to_dev(usb3), "%s: timed out (%8x, %08x, %08x)\n",
- __func__, reg, mask, expected);
- return -EBUSY;
- }
- static void usb3_enable_irq_1(struct renesas_usb3 *usb3, u32 bits)
- {
- usb3_set_bit(usb3, bits, USB3_USB_INT_ENA_1);
- }
- static void usb3_disable_irq_1(struct renesas_usb3 *usb3, u32 bits)
- {
- usb3_clear_bit(usb3, bits, USB3_USB_INT_ENA_1);
- }
- static void usb3_enable_pipe_irq(struct renesas_usb3 *usb3, int num)
- {
- usb3_set_bit(usb3, USB_INT_2_PIPE(num), USB3_USB_INT_ENA_2);
- }
- static void usb3_disable_pipe_irq(struct renesas_usb3 *usb3, int num)
- {
- usb3_clear_bit(usb3, USB_INT_2_PIPE(num), USB3_USB_INT_ENA_2);
- }
- static void usb3_init_axi_bridge(struct renesas_usb3 *usb3)
- {
- /* Set AXI_INT */
- usb3_write(usb3, ~0, USB3_DMA_INT_STA);
- usb3_write(usb3, 0, USB3_DMA_INT_ENA);
- usb3_set_bit(usb3, AXI_INT_DMAINT | AXI_INT_EPCINT, USB3_AXI_INT_ENA);
- }
- static void usb3_init_epc_registers(struct renesas_usb3 *usb3)
- {
- /* FIXME: How to change host / peripheral mode as well? */
- usb3_set_bit(usb3, DRD_CON_PERI_CON, USB3_DRD_CON);
- usb3_clear_bit(usb3, DRD_CON_VBOUT, USB3_DRD_CON);
- usb3_write(usb3, ~0, USB3_USB_INT_STA_1);
- usb3_enable_irq_1(usb3, USB_INT_1_VBUS_CNG);
- }
- static bool usb3_wakeup_usb2_phy(struct renesas_usb3 *usb3)
- {
- if (!(usb3_read(usb3, USB3_USB20_CON) & USB20_CON_B2_SUSPEND))
- return true; /* already waked it up */
- usb3_clear_bit(usb3, USB20_CON_B2_SUSPEND, USB3_USB20_CON);
- usb3_enable_irq_1(usb3, USB_INT_1_B2_RSUM);
- return false;
- }
- static void usb3_usb2_pullup(struct renesas_usb3 *usb3, int pullup)
- {
- u32 bits = USB20_CON_B2_PUE | USB20_CON_B2_CONNECT;
- if (usb3->softconnect && pullup)
- usb3_set_bit(usb3, bits, USB3_USB20_CON);
- else
- usb3_clear_bit(usb3, bits, USB3_USB20_CON);
- }
- static void usb3_set_test_mode(struct renesas_usb3 *usb3)
- {
- u32 val = usb3_read(usb3, USB3_USB20_CON);
- val &= ~USB20_CON_B2_TSTMOD_MASK;
- val |= USB20_CON_B2_TSTMOD(usb3->test_mode);
- usb3_write(usb3, val | USB20_CON_B2_TSTMOD_EN, USB3_USB20_CON);
- if (!usb3->test_mode)
- usb3_clear_bit(usb3, USB20_CON_B2_TSTMOD_EN, USB3_USB20_CON);
- }
- static void usb3_start_usb2_connection(struct renesas_usb3 *usb3)
- {
- usb3->disabled_count++;
- usb3_set_bit(usb3, USB_COM_CON_EP0_EN, USB3_USB_COM_CON);
- usb3_set_bit(usb3, USB_COM_CON_SPD_MODE, USB3_USB_COM_CON);
- usb3_usb2_pullup(usb3, 1);
- }
- static int usb3_is_usb3_phy_in_u3(struct renesas_usb3 *usb3)
- {
- return usb3_read(usb3, USB3_USB30_CON) & USB30_CON_POW_SEL_IN_U3;
- }
- static bool usb3_wakeup_usb3_phy(struct renesas_usb3 *usb3)
- {
- if (!usb3_is_usb3_phy_in_u3(usb3))
- return true; /* already waked it up */
- usb3_set_bit(usb3, USB30_CON_B3_PLLWAKE, USB3_USB30_CON);
- usb3_enable_irq_1(usb3, USB_INT_1_B3_PLLWKUP);
- return false;
- }
- static u16 usb3_feature_get_un_enabled(struct renesas_usb3 *usb3)
- {
- u32 mask_u2 = SSIFCMD_UDIR_U2 | SSIFCMD_UREQ_U2;
- u32 mask_u1 = SSIFCMD_UDIR_U1 | SSIFCMD_UREQ_U1;
- u32 val = usb3_read(usb3, USB3_SSIFCMD);
- u16 ret = 0;
- /* Enables {U2,U1} if the bits of UDIR and UREQ are set to 0 */
- if (!(val & mask_u2))
- ret |= 1 << USB_DEV_STAT_U2_ENABLED;
- if (!(val & mask_u1))
- ret |= 1 << USB_DEV_STAT_U1_ENABLED;
- return ret;
- }
- static void usb3_feature_u2_enable(struct renesas_usb3 *usb3, bool enable)
- {
- u32 bits = SSIFCMD_UDIR_U2 | SSIFCMD_UREQ_U2;
- /* Enables U2 if the bits of UDIR and UREQ are set to 0 */
- if (enable)
- usb3_clear_bit(usb3, bits, USB3_SSIFCMD);
- else
- usb3_set_bit(usb3, bits, USB3_SSIFCMD);
- }
- static void usb3_feature_u1_enable(struct renesas_usb3 *usb3, bool enable)
- {
- u32 bits = SSIFCMD_UDIR_U1 | SSIFCMD_UREQ_U1;
- /* Enables U1 if the bits of UDIR and UREQ are set to 0 */
- if (enable)
- usb3_clear_bit(usb3, bits, USB3_SSIFCMD);
- else
- usb3_set_bit(usb3, bits, USB3_SSIFCMD);
- }
- static void usb3_start_operation_for_usb3(struct renesas_usb3 *usb3)
- {
- usb3_set_bit(usb3, USB_COM_CON_EP0_EN, USB3_USB_COM_CON);
- usb3_clear_bit(usb3, USB_COM_CON_SPD_MODE, USB3_USB_COM_CON);
- usb3_set_bit(usb3, USB30_CON_B3_CONNECT, USB3_USB30_CON);
- }
- static void usb3_start_usb3_connection(struct renesas_usb3 *usb3)
- {
- usb3_start_operation_for_usb3(usb3);
- usb3_set_bit(usb3, USB_COM_CON_RX_DETECTION, USB3_USB_COM_CON);
- usb3_enable_irq_1(usb3, USB_INT_1_B3_LUPSUCS | USB_INT_1_B3_DISABLE |
- USB_INT_1_SPEED);
- }
- static void usb3_stop_usb3_connection(struct renesas_usb3 *usb3)
- {
- usb3_clear_bit(usb3, USB30_CON_B3_CONNECT, USB3_USB30_CON);
- }
- static void usb3_transition_to_default_state(struct renesas_usb3 *usb3,
- bool is_usb3)
- {
- usb3_set_bit(usb3, USB_INT_2_PIPE(0), USB3_USB_INT_ENA_2);
- usb3_write(usb3, P0_INT_ALL_BITS, USB3_P0_INT_STA);
- usb3_set_bit(usb3, P0_INT_ALL_BITS, USB3_P0_INT_ENA);
- if (is_usb3)
- usb3_enable_irq_1(usb3, USB_INT_1_B3_WRMRST |
- USB_INT_1_B3_HOTRST);
- else
- usb3_enable_irq_1(usb3, USB_INT_1_B2_SPND |
- USB_INT_1_B2_L1SPND | USB_INT_1_B2_USBRST);
- }
- static void usb3_connect(struct renesas_usb3 *usb3)
- {
- if (usb3_wakeup_usb3_phy(usb3))
- usb3_start_usb3_connection(usb3);
- }
- static void usb3_reset_epc(struct renesas_usb3 *usb3)
- {
- usb3_clear_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON);
- usb3_clear_bit(usb3, USB_COM_CON_EP0_EN, USB3_USB_COM_CON);
- usb3_set_bit(usb3, USB_COM_CON_PIPE_CLR, USB3_USB_COM_CON);
- usb3->test_mode = 0;
- usb3_set_test_mode(usb3);
- }
- static void usb3_disconnect(struct renesas_usb3 *usb3)
- {
- usb3->disabled_count = 0;
- usb3_usb2_pullup(usb3, 0);
- usb3_clear_bit(usb3, USB30_CON_B3_CONNECT, USB3_USB30_CON);
- usb3_reset_epc(usb3);
- if (usb3->driver)
- usb3->driver->disconnect(&usb3->gadget);
- }
- static void usb3_check_vbus(struct renesas_usb3 *usb3)
- {
- if (usb3->workaround_for_vbus) {
- usb3_connect(usb3);
- } else {
- if (usb3_read(usb3, USB3_USB_STA) & USB_STA_VBUS_STA)
- usb3_connect(usb3);
- else
- usb3_disconnect(usb3);
- }
- }
- static void renesas_usb3_init_controller(struct renesas_usb3 *usb3)
- {
- usb3_init_axi_bridge(usb3);
- usb3_init_epc_registers(usb3);
- usb3_check_vbus(usb3);
- }
- static void renesas_usb3_stop_controller(struct renesas_usb3 *usb3)
- {
- usb3_disconnect(usb3);
- usb3_write(usb3, 0, USB3_P0_INT_ENA);
- usb3_write(usb3, 0, USB3_PN_INT_ENA);
- usb3_write(usb3, 0, USB3_USB_INT_ENA_1);
- usb3_write(usb3, 0, USB3_USB_INT_ENA_2);
- usb3_write(usb3, 0, USB3_AXI_INT_ENA);
- }
- static void usb3_irq_epc_int_1_pll_wakeup(struct renesas_usb3 *usb3)
- {
- usb3_disable_irq_1(usb3, USB_INT_1_B3_PLLWKUP);
- usb3_clear_bit(usb3, USB30_CON_B3_PLLWAKE, USB3_USB30_CON);
- usb3_start_usb3_connection(usb3);
- }
- static void usb3_irq_epc_int_1_linkup_success(struct renesas_usb3 *usb3)
- {
- usb3_transition_to_default_state(usb3, true);
- }
- static void usb3_irq_epc_int_1_resume(struct renesas_usb3 *usb3)
- {
- usb3_disable_irq_1(usb3, USB_INT_1_B2_RSUM);
- usb3_start_usb2_connection(usb3);
- usb3_transition_to_default_state(usb3, false);
- }
- static void usb3_irq_epc_int_1_disable(struct renesas_usb3 *usb3)
- {
- usb3_stop_usb3_connection(usb3);
- if (usb3_wakeup_usb2_phy(usb3))
- usb3_irq_epc_int_1_resume(usb3);
- }
- static void usb3_irq_epc_int_1_bus_reset(struct renesas_usb3 *usb3)
- {
- usb3_reset_epc(usb3);
- if (usb3->disabled_count < 3)
- usb3_start_usb3_connection(usb3);
- else
- usb3_start_usb2_connection(usb3);
- }
- static void usb3_irq_epc_int_1_vbus_change(struct renesas_usb3 *usb3)
- {
- usb3_check_vbus(usb3);
- }
- static void usb3_irq_epc_int_1_hot_reset(struct renesas_usb3 *usb3)
- {
- usb3_reset_epc(usb3);
- usb3_set_bit(usb3, USB_COM_CON_EP0_EN, USB3_USB_COM_CON);
- /* This bit shall be set within 12ms from the start of HotReset */
- usb3_set_bit(usb3, USB30_CON_B3_HOTRST_CMP, USB3_USB30_CON);
- }
- static void usb3_irq_epc_int_1_warm_reset(struct renesas_usb3 *usb3)
- {
- usb3_reset_epc(usb3);
- usb3_set_bit(usb3, USB_COM_CON_EP0_EN, USB3_USB_COM_CON);
- usb3_start_operation_for_usb3(usb3);
- usb3_enable_irq_1(usb3, USB_INT_1_SPEED);
- }
- static void usb3_irq_epc_int_1_speed(struct renesas_usb3 *usb3)
- {
- u32 speed = usb3_read(usb3, USB3_USB_STA) & USB_STA_SPEED_MASK;
- switch (speed) {
- case USB_STA_SPEED_SS:
- usb3->gadget.speed = USB_SPEED_SUPER;
- break;
- case USB_STA_SPEED_HS:
- usb3->gadget.speed = USB_SPEED_HIGH;
- break;
- case USB_STA_SPEED_FS:
- usb3->gadget.speed = USB_SPEED_FULL;
- break;
- default:
- usb3->gadget.speed = USB_SPEED_UNKNOWN;
- break;
- }
- }
- static void usb3_irq_epc_int_1(struct renesas_usb3 *usb3, u32 int_sta_1)
- {
- if (int_sta_1 & USB_INT_1_B3_PLLWKUP)
- usb3_irq_epc_int_1_pll_wakeup(usb3);
- if (int_sta_1 & USB_INT_1_B3_LUPSUCS)
- usb3_irq_epc_int_1_linkup_success(usb3);
- if (int_sta_1 & USB_INT_1_B3_HOTRST)
- usb3_irq_epc_int_1_hot_reset(usb3);
- if (int_sta_1 & USB_INT_1_B3_WRMRST)
- usb3_irq_epc_int_1_warm_reset(usb3);
- if (int_sta_1 & USB_INT_1_B3_DISABLE)
- usb3_irq_epc_int_1_disable(usb3);
- if (int_sta_1 & USB_INT_1_B2_USBRST)
- usb3_irq_epc_int_1_bus_reset(usb3);
- if (int_sta_1 & USB_INT_1_B2_RSUM)
- usb3_irq_epc_int_1_resume(usb3);
- if (int_sta_1 & USB_INT_1_SPEED)
- usb3_irq_epc_int_1_speed(usb3);
- if (int_sta_1 & USB_INT_1_VBUS_CNG)
- usb3_irq_epc_int_1_vbus_change(usb3);
- }
- static struct renesas_usb3_request *__usb3_get_request(struct renesas_usb3_ep
- *usb3_ep)
- {
- return list_first_entry_or_null(&usb3_ep->queue,
- struct renesas_usb3_request, queue);
- }
- static struct renesas_usb3_request *usb3_get_request(struct renesas_usb3_ep
- *usb3_ep)
- {
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- struct renesas_usb3_request *usb3_req;
- unsigned long flags;
- spin_lock_irqsave(&usb3->lock, flags);
- usb3_req = __usb3_get_request(usb3_ep);
- spin_unlock_irqrestore(&usb3->lock, flags);
- return usb3_req;
- }
- static void usb3_request_done(struct renesas_usb3_ep *usb3_ep,
- struct renesas_usb3_request *usb3_req, int status)
- {
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- unsigned long flags;
- dev_dbg(usb3_to_dev(usb3), "giveback: ep%2d, %u, %u, %d\n",
- usb3_ep->num, usb3_req->req.length, usb3_req->req.actual,
- status);
- usb3_req->req.status = status;
- spin_lock_irqsave(&usb3->lock, flags);
- usb3_ep->started = false;
- list_del_init(&usb3_req->queue);
- spin_unlock_irqrestore(&usb3->lock, flags);
- usb_gadget_giveback_request(&usb3_ep->ep, &usb3_req->req);
- }
- static void usb3_irq_epc_pipe0_status_end(struct renesas_usb3 *usb3)
- {
- struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, 0);
- struct renesas_usb3_request *usb3_req = usb3_get_request(usb3_ep);
- if (usb3_req)
- usb3_request_done(usb3_ep, usb3_req, 0);
- if (usb3->test_mode)
- usb3_set_test_mode(usb3);
- }
- static void usb3_get_setup_data(struct renesas_usb3 *usb3,
- struct usb_ctrlrequest *ctrl)
- {
- struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, 0);
- u32 *data = (u32 *)ctrl;
- *data++ = usb3_read(usb3, USB3_STUP_DAT_0);
- *data = usb3_read(usb3, USB3_STUP_DAT_1);
- /* update this driver's flag */
- usb3_ep->dir_in = !!(ctrl->bRequestType & USB_DIR_IN);
- }
- static void usb3_set_p0_con_update_res(struct renesas_usb3 *usb3, u32 res)
- {
- u32 val = usb3_read(usb3, USB3_P0_CON);
- val &= ~(P0_CON_ST_RES_MASK | P0_CON_OT_RES_MASK | P0_CON_IN_RES_MASK);
- val |= res | P0_CON_RES_WEN;
- usb3_write(usb3, val, USB3_P0_CON);
- }
- static void usb3_set_p0_con_for_ctrl_read_data(struct renesas_usb3 *usb3)
- {
- usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_FORCE_NRDY |
- P0_CON_OT_RES_FORCE_STALL |
- P0_CON_IN_RES_NORMAL);
- }
- static void usb3_set_p0_con_for_ctrl_read_status(struct renesas_usb3 *usb3)
- {
- usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_NORMAL |
- P0_CON_OT_RES_FORCE_STALL |
- P0_CON_IN_RES_NORMAL);
- }
- static void usb3_set_p0_con_for_ctrl_write_data(struct renesas_usb3 *usb3)
- {
- usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_FORCE_NRDY |
- P0_CON_OT_RES_NORMAL |
- P0_CON_IN_RES_FORCE_STALL);
- }
- static void usb3_set_p0_con_for_ctrl_write_status(struct renesas_usb3 *usb3)
- {
- usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_NORMAL |
- P0_CON_OT_RES_NORMAL |
- P0_CON_IN_RES_FORCE_STALL);
- }
- static void usb3_set_p0_con_for_no_data(struct renesas_usb3 *usb3)
- {
- usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_NORMAL |
- P0_CON_OT_RES_FORCE_STALL |
- P0_CON_IN_RES_FORCE_STALL);
- }
- static void usb3_set_p0_con_stall(struct renesas_usb3 *usb3)
- {
- usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_FORCE_STALL |
- P0_CON_OT_RES_FORCE_STALL |
- P0_CON_IN_RES_FORCE_STALL);
- }
- static void usb3_set_p0_con_stop(struct renesas_usb3 *usb3)
- {
- usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_FORCE_NRDY |
- P0_CON_OT_RES_FORCE_NRDY |
- P0_CON_IN_RES_FORCE_NRDY);
- }
- static int usb3_pn_change(struct renesas_usb3 *usb3, int num)
- {
- if (num == 0 || num > usb3->num_usb3_eps)
- return -ENXIO;
- usb3_write(usb3, num, USB3_PIPE_COM);
- return 0;
- }
- static void usb3_set_pn_con_update_res(struct renesas_usb3 *usb3, u32 res)
- {
- u32 val = usb3_read(usb3, USB3_PN_CON);
- val &= ~PN_CON_RES_MASK;
- val |= res & PN_CON_RES_MASK;
- val |= PN_CON_RES_WEN;
- usb3_write(usb3, val, USB3_PN_CON);
- }
- static void usb3_pn_start(struct renesas_usb3 *usb3)
- {
- usb3_set_pn_con_update_res(usb3, PN_CON_RES_NORMAL);
- }
- static void usb3_pn_stop(struct renesas_usb3 *usb3)
- {
- usb3_set_pn_con_update_res(usb3, PN_CON_RES_FORCE_NRDY);
- }
- static void usb3_pn_stall(struct renesas_usb3 *usb3)
- {
- usb3_set_pn_con_update_res(usb3, PN_CON_RES_FORCE_STALL);
- }
- static int usb3_pn_con_clear(struct renesas_usb3 *usb3)
- {
- usb3_set_bit(usb3, PN_CON_CLR, USB3_PN_CON);
- return usb3_wait(usb3, USB3_PN_CON, PN_CON_CLR, 0);
- }
- static bool usb3_is_transfer_complete(struct renesas_usb3_ep *usb3_ep,
- struct renesas_usb3_request *usb3_req)
- {
- struct usb_request *req = &usb3_req->req;
- if ((!req->zero && req->actual == req->length) ||
- (req->actual % usb3_ep->ep.maxpacket) || (req->length == 0))
- return true;
- else
- return false;
- }
- static int usb3_wait_pipe_status(struct renesas_usb3_ep *usb3_ep, u32 mask)
- {
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- u32 sta_reg = usb3_ep->num ? USB3_PN_STA : USB3_P0_STA;
- return usb3_wait(usb3, sta_reg, mask, mask);
- }
- static void usb3_set_px_con_send(struct renesas_usb3_ep *usb3_ep, int bytes,
- bool last)
- {
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- u32 con_reg = usb3_ep->num ? USB3_PN_CON : USB3_P0_CON;
- u32 val = usb3_read(usb3, con_reg);
- val |= PX_CON_SEND | PX_CON_BYTE_EN_BYTES(bytes);
- val |= (usb3_ep->num && last) ? PN_CON_LAST : 0;
- usb3_write(usb3, val, con_reg);
- }
- static int usb3_write_pipe(struct renesas_usb3_ep *usb3_ep,
- struct renesas_usb3_request *usb3_req,
- u32 fifo_reg)
- {
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- int i;
- int len = min_t(unsigned, usb3_req->req.length - usb3_req->req.actual,
- usb3_ep->ep.maxpacket);
- u8 *buf = usb3_req->req.buf + usb3_req->req.actual;
- u32 tmp = 0;
- bool is_last;
- if (usb3_wait_pipe_status(usb3_ep, PX_STA_BUFSTS) < 0)
- return -EBUSY;
- /* Update gadget driver parameter */
- usb3_req->req.actual += len;
- /* Write data to the register */
- if (len >= 4) {
- iowrite32_rep(usb3->reg + fifo_reg, buf, len / 4);
- buf += (len / 4) * 4;
- len %= 4; /* update len to use usb3_set_pX_con_send() */
- }
- if (len) {
- for (i = 0; i < len; i++)
- tmp |= buf[i] << (8 * i);
- usb3_write(usb3, tmp, fifo_reg);
- }
- is_last = usb3_is_transfer_complete(usb3_ep, usb3_req);
- /* Send the data */
- usb3_set_px_con_send(usb3_ep, len, is_last);
- return is_last ? 0 : -EAGAIN;
- }
- static u32 usb3_get_received_length(struct renesas_usb3_ep *usb3_ep)
- {
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- u32 lng_reg = usb3_ep->num ? USB3_PN_LNG : USB3_P0_LNG;
- return usb3_read(usb3, lng_reg);
- }
- static int usb3_read_pipe(struct renesas_usb3_ep *usb3_ep,
- struct renesas_usb3_request *usb3_req, u32 fifo_reg)
- {
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- int i;
- int len = min_t(unsigned, usb3_req->req.length - usb3_req->req.actual,
- usb3_get_received_length(usb3_ep));
- u8 *buf = usb3_req->req.buf + usb3_req->req.actual;
- u32 tmp = 0;
- if (!len)
- return 0;
- /* Update gadget driver parameter */
- usb3_req->req.actual += len;
- /* Read data from the register */
- if (len >= 4) {
- ioread32_rep(usb3->reg + fifo_reg, buf, len / 4);
- buf += (len / 4) * 4;
- len %= 4;
- }
- if (len) {
- tmp = usb3_read(usb3, fifo_reg);
- for (i = 0; i < len; i++)
- buf[i] = (tmp >> (8 * i)) & 0xff;
- }
- return usb3_is_transfer_complete(usb3_ep, usb3_req) ? 0 : -EAGAIN;
- }
- static void usb3_set_status_stage(struct renesas_usb3_ep *usb3_ep,
- struct renesas_usb3_request *usb3_req)
- {
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- if (usb3_ep->dir_in) {
- usb3_set_p0_con_for_ctrl_read_status(usb3);
- } else {
- if (!usb3_req->req.length)
- usb3_set_p0_con_for_no_data(usb3);
- else
- usb3_set_p0_con_for_ctrl_write_status(usb3);
- }
- }
- static void usb3_p0_xfer(struct renesas_usb3_ep *usb3_ep,
- struct renesas_usb3_request *usb3_req)
- {
- int ret = -EAGAIN;
- if (usb3_ep->dir_in)
- ret = usb3_write_pipe(usb3_ep, usb3_req, USB3_P0_WRITE);
- else
- ret = usb3_read_pipe(usb3_ep, usb3_req, USB3_P0_READ);
- if (!ret)
- usb3_set_status_stage(usb3_ep, usb3_req);
- }
- static void usb3_start_pipe0(struct renesas_usb3_ep *usb3_ep,
- struct renesas_usb3_request *usb3_req)
- {
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- if (usb3_ep->started)
- return;
- usb3_ep->started = true;
- if (usb3_ep->dir_in) {
- usb3_set_bit(usb3, P0_MOD_DIR, USB3_P0_MOD);
- usb3_set_p0_con_for_ctrl_read_data(usb3);
- } else {
- usb3_clear_bit(usb3, P0_MOD_DIR, USB3_P0_MOD);
- usb3_set_p0_con_for_ctrl_write_data(usb3);
- }
- usb3_p0_xfer(usb3_ep, usb3_req);
- }
- static void usb3_start_pipen(struct renesas_usb3_ep *usb3_ep,
- struct renesas_usb3_request *usb3_req)
- {
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- struct renesas_usb3_request *usb3_req_first = usb3_get_request(usb3_ep);
- unsigned long flags;
- int ret = -EAGAIN;
- u32 enable_bits = 0;
- if (usb3_ep->halt || usb3_ep->started)
- return;
- if (usb3_req != usb3_req_first)
- return;
- spin_lock_irqsave(&usb3->lock, flags);
- if (usb3_pn_change(usb3, usb3_ep->num) < 0)
- goto out;
- usb3_ep->started = true;
- usb3_pn_start(usb3);
- if (usb3_ep->dir_in) {
- ret = usb3_write_pipe(usb3_ep, usb3_req, USB3_PN_WRITE);
- enable_bits |= PN_INT_LSTTR;
- }
- if (ret < 0)
- enable_bits |= PN_INT_BFRDY;
- if (enable_bits) {
- usb3_set_bit(usb3, enable_bits, USB3_PN_INT_ENA);
- usb3_enable_pipe_irq(usb3, usb3_ep->num);
- }
- out:
- spin_unlock_irqrestore(&usb3->lock, flags);
- }
- static int renesas_usb3_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
- gfp_t gfp_flags)
- {
- struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep);
- struct renesas_usb3_request *usb3_req = usb_req_to_usb3_req(_req);
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- unsigned long flags;
- dev_dbg(usb3_to_dev(usb3), "ep_queue: ep%2d, %u\n", usb3_ep->num,
- _req->length);
- _req->status = -EINPROGRESS;
- _req->actual = 0;
- spin_lock_irqsave(&usb3->lock, flags);
- list_add_tail(&usb3_req->queue, &usb3_ep->queue);
- spin_unlock_irqrestore(&usb3->lock, flags);
- if (!usb3_ep->num)
- usb3_start_pipe0(usb3_ep, usb3_req);
- else
- usb3_start_pipen(usb3_ep, usb3_req);
- return 0;
- }
- static void usb3_set_device_address(struct renesas_usb3 *usb3, u16 addr)
- {
- /* DEV_ADDR bit field is cleared by WarmReset, HotReset and BusReset */
- usb3_set_bit(usb3, USB_COM_CON_DEV_ADDR(addr), USB3_USB_COM_CON);
- }
- static bool usb3_std_req_set_address(struct renesas_usb3 *usb3,
- struct usb_ctrlrequest *ctrl)
- {
- if (ctrl->wValue >= 128)
- return true; /* stall */
- usb3_set_device_address(usb3, ctrl->wValue);
- usb3_set_p0_con_for_no_data(usb3);
- return false;
- }
- static void usb3_pipe0_internal_xfer(struct renesas_usb3 *usb3,
- void *tx_data, size_t len,
- void (*complete)(struct usb_ep *ep,
- struct usb_request *req))
- {
- struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, 0);
- if (tx_data)
- memcpy(usb3->ep0_buf, tx_data,
- min_t(size_t, len, USB3_EP0_BUF_SIZE));
- usb3->ep0_req->buf = &usb3->ep0_buf;
- usb3->ep0_req->length = len;
- usb3->ep0_req->complete = complete;
- renesas_usb3_ep_queue(&usb3_ep->ep, usb3->ep0_req, GFP_ATOMIC);
- }
- static void usb3_pipe0_get_status_completion(struct usb_ep *ep,
- struct usb_request *req)
- {
- }
- static bool usb3_std_req_get_status(struct renesas_usb3 *usb3,
- struct usb_ctrlrequest *ctrl)
- {
- bool stall = false;
- struct renesas_usb3_ep *usb3_ep;
- int num;
- u16 status = 0;
- switch (ctrl->bRequestType & USB_RECIP_MASK) {
- case USB_RECIP_DEVICE:
- if (usb3->gadget.is_selfpowered)
- status |= 1 << USB_DEVICE_SELF_POWERED;
- if (usb3->gadget.speed == USB_SPEED_SUPER)
- status |= usb3_feature_get_un_enabled(usb3);
- break;
- case USB_RECIP_INTERFACE:
- break;
- case USB_RECIP_ENDPOINT:
- num = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK;
- usb3_ep = usb3_get_ep(usb3, num);
- if (usb3_ep->halt)
- status |= 1 << USB_ENDPOINT_HALT;
- break;
- default:
- stall = true;
- break;
- }
- if (!stall) {
- status = cpu_to_le16(status);
- dev_dbg(usb3_to_dev(usb3), "get_status: req = %p\n",
- usb_req_to_usb3_req(usb3->ep0_req));
- usb3_pipe0_internal_xfer(usb3, &status, sizeof(status),
- usb3_pipe0_get_status_completion);
- }
- return stall;
- }
- static bool usb3_std_req_feature_device(struct renesas_usb3 *usb3,
- struct usb_ctrlrequest *ctrl, bool set)
- {
- bool stall = true;
- u16 w_value = le16_to_cpu(ctrl->wValue);
- switch (w_value) {
- case USB_DEVICE_TEST_MODE:
- if (!set)
- break;
- usb3->test_mode = le16_to_cpu(ctrl->wIndex) >> 8;
- stall = false;
- break;
- case USB_DEVICE_U1_ENABLE:
- case USB_DEVICE_U2_ENABLE:
- if (usb3->gadget.speed != USB_SPEED_SUPER)
- break;
- if (w_value == USB_DEVICE_U1_ENABLE)
- usb3_feature_u1_enable(usb3, set);
- if (w_value == USB_DEVICE_U2_ENABLE)
- usb3_feature_u2_enable(usb3, set);
- stall = false;
- break;
- default:
- break;
- }
- return stall;
- }
- static int usb3_set_halt_p0(struct renesas_usb3_ep *usb3_ep, bool halt)
- {
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- if (unlikely(usb3_ep->num))
- return -EINVAL;
- usb3_ep->halt = halt;
- if (halt)
- usb3_set_p0_con_stall(usb3);
- else
- usb3_set_p0_con_stop(usb3);
- return 0;
- }
- static int usb3_set_halt_pn(struct renesas_usb3_ep *usb3_ep, bool halt,
- bool is_clear_feature)
- {
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- unsigned long flags;
- spin_lock_irqsave(&usb3->lock, flags);
- if (!usb3_pn_change(usb3, usb3_ep->num)) {
- usb3_ep->halt = halt;
- if (halt) {
- usb3_pn_stall(usb3);
- } else if (!is_clear_feature || !usb3_ep->wedge) {
- usb3_pn_con_clear(usb3);
- usb3_set_bit(usb3, PN_CON_EN, USB3_PN_CON);
- usb3_pn_stop(usb3);
- }
- }
- spin_unlock_irqrestore(&usb3->lock, flags);
- return 0;
- }
- static int usb3_set_halt(struct renesas_usb3_ep *usb3_ep, bool halt,
- bool is_clear_feature)
- {
- int ret = 0;
- if (halt && usb3_ep->started)
- return -EAGAIN;
- if (usb3_ep->num)
- ret = usb3_set_halt_pn(usb3_ep, halt, is_clear_feature);
- else
- ret = usb3_set_halt_p0(usb3_ep, halt);
- return ret;
- }
- static bool usb3_std_req_feature_endpoint(struct renesas_usb3 *usb3,
- struct usb_ctrlrequest *ctrl,
- bool set)
- {
- int num = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK;
- struct renesas_usb3_ep *usb3_ep;
- struct renesas_usb3_request *usb3_req;
- if (le16_to_cpu(ctrl->wValue) != USB_ENDPOINT_HALT)
- return true; /* stall */
- usb3_ep = usb3_get_ep(usb3, num);
- usb3_set_halt(usb3_ep, set, true);
- /* Restarts a queue if clear feature */
- if (!set) {
- usb3_ep->started = false;
- usb3_req = usb3_get_request(usb3_ep);
- if (usb3_req)
- usb3_start_pipen(usb3_ep, usb3_req);
- }
- return false;
- }
- static bool usb3_std_req_feature(struct renesas_usb3 *usb3,
- struct usb_ctrlrequest *ctrl, bool set)
- {
- bool stall = false;
- switch (ctrl->bRequestType & USB_RECIP_MASK) {
- case USB_RECIP_DEVICE:
- stall = usb3_std_req_feature_device(usb3, ctrl, set);
- break;
- case USB_RECIP_INTERFACE:
- break;
- case USB_RECIP_ENDPOINT:
- stall = usb3_std_req_feature_endpoint(usb3, ctrl, set);
- break;
- default:
- stall = true;
- break;
- }
- if (!stall)
- usb3_set_p0_con_for_no_data(usb3);
- return stall;
- }
- static void usb3_pipe0_set_sel_completion(struct usb_ep *ep,
- struct usb_request *req)
- {
- /* TODO */
- }
- static bool usb3_std_req_set_sel(struct renesas_usb3 *usb3,
- struct usb_ctrlrequest *ctrl)
- {
- u16 w_length = le16_to_cpu(ctrl->wLength);
- if (w_length != 6)
- return true; /* stall */
- dev_dbg(usb3_to_dev(usb3), "set_sel: req = %p\n",
- usb_req_to_usb3_req(usb3->ep0_req));
- usb3_pipe0_internal_xfer(usb3, NULL, 6, usb3_pipe0_set_sel_completion);
- return false;
- }
- static bool usb3_std_req_set_configuration(struct renesas_usb3 *usb3,
- struct usb_ctrlrequest *ctrl)
- {
- if (ctrl->wValue > 0)
- usb3_set_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON);
- else
- usb3_clear_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON);
- return false;
- }
- /**
- * usb3_handle_standard_request - handle some standard requests
- * @usb3: the renesas_usb3 pointer
- * @ctrl: a pointer of setup data
- *
- * Returns true if this function handled a standard request
- */
- static bool usb3_handle_standard_request(struct renesas_usb3 *usb3,
- struct usb_ctrlrequest *ctrl)
- {
- bool ret = false;
- bool stall = false;
- if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
- switch (ctrl->bRequest) {
- case USB_REQ_SET_ADDRESS:
- stall = usb3_std_req_set_address(usb3, ctrl);
- ret = true;
- break;
- case USB_REQ_GET_STATUS:
- stall = usb3_std_req_get_status(usb3, ctrl);
- ret = true;
- break;
- case USB_REQ_CLEAR_FEATURE:
- stall = usb3_std_req_feature(usb3, ctrl, false);
- ret = true;
- break;
- case USB_REQ_SET_FEATURE:
- stall = usb3_std_req_feature(usb3, ctrl, true);
- ret = true;
- break;
- case USB_REQ_SET_SEL:
- stall = usb3_std_req_set_sel(usb3, ctrl);
- ret = true;
- break;
- case USB_REQ_SET_ISOCH_DELAY:
- /* This hardware doesn't support Isochronous xfer */
- stall = true;
- ret = true;
- break;
- case USB_REQ_SET_CONFIGURATION:
- usb3_std_req_set_configuration(usb3, ctrl);
- break;
- default:
- break;
- }
- }
- if (stall)
- usb3_set_p0_con_stall(usb3);
- return ret;
- }
- static int usb3_p0_con_clear_buffer(struct renesas_usb3 *usb3)
- {
- usb3_set_bit(usb3, P0_CON_BCLR, USB3_P0_CON);
- return usb3_wait(usb3, USB3_P0_CON, P0_CON_BCLR, 0);
- }
- static void usb3_irq_epc_pipe0_setup(struct renesas_usb3 *usb3)
- {
- struct usb_ctrlrequest ctrl;
- struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, 0);
- /* Call giveback function if previous transfer is not completed */
- if (usb3_ep->started)
- usb3_request_done(usb3_ep, usb3_get_request(usb3_ep),
- -ECONNRESET);
- usb3_p0_con_clear_buffer(usb3);
- usb3_get_setup_data(usb3, &ctrl);
- if (!usb3_handle_standard_request(usb3, &ctrl))
- if (usb3->driver->setup(&usb3->gadget, &ctrl) < 0)
- usb3_set_p0_con_stall(usb3);
- }
- static void usb3_irq_epc_pipe0_bfrdy(struct renesas_usb3 *usb3)
- {
- struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, 0);
- struct renesas_usb3_request *usb3_req = usb3_get_request(usb3_ep);
- if (!usb3_req)
- return;
- usb3_p0_xfer(usb3_ep, usb3_req);
- }
- static void usb3_irq_epc_pipe0(struct renesas_usb3 *usb3)
- {
- u32 p0_int_sta = usb3_read(usb3, USB3_P0_INT_STA);
- p0_int_sta &= usb3_read(usb3, USB3_P0_INT_ENA);
- usb3_write(usb3, p0_int_sta, USB3_P0_INT_STA);
- if (p0_int_sta & P0_INT_STSED)
- usb3_irq_epc_pipe0_status_end(usb3);
- if (p0_int_sta & P0_INT_SETUP)
- usb3_irq_epc_pipe0_setup(usb3);
- if (p0_int_sta & P0_INT_BFRDY)
- usb3_irq_epc_pipe0_bfrdy(usb3);
- }
- static void usb3_request_done_pipen(struct renesas_usb3 *usb3,
- struct renesas_usb3_ep *usb3_ep,
- struct renesas_usb3_request *usb3_req,
- int status)
- {
- usb3_pn_stop(usb3);
- usb3_disable_pipe_irq(usb3, usb3_ep->num);
- usb3_request_done(usb3_ep, usb3_req, status);
- /* get next usb3_req */
- usb3_req = usb3_get_request(usb3_ep);
- if (usb3_req)
- usb3_start_pipen(usb3_ep, usb3_req);
- }
- static void usb3_irq_epc_pipen_lsttr(struct renesas_usb3 *usb3, int num)
- {
- struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, num);
- struct renesas_usb3_request *usb3_req = usb3_get_request(usb3_ep);
- if (!usb3_req)
- return;
- if (usb3_ep->dir_in) {
- dev_dbg(usb3_to_dev(usb3), "%s: len = %u, actual = %u\n",
- __func__, usb3_req->req.length, usb3_req->req.actual);
- usb3_request_done_pipen(usb3, usb3_ep, usb3_req, 0);
- }
- }
- static void usb3_irq_epc_pipen_bfrdy(struct renesas_usb3 *usb3, int num)
- {
- struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, num);
- struct renesas_usb3_request *usb3_req = usb3_get_request(usb3_ep);
- if (!usb3_req)
- return;
- if (usb3_ep->dir_in) {
- /* Do not stop the IN pipe here to detect LSTTR interrupt */
- if (!usb3_write_pipe(usb3_ep, usb3_req, USB3_PN_WRITE))
- usb3_clear_bit(usb3, PN_INT_BFRDY, USB3_PN_INT_ENA);
- } else {
- if (!usb3_read_pipe(usb3_ep, usb3_req, USB3_PN_READ))
- usb3_request_done_pipen(usb3, usb3_ep, usb3_req, 0);
- }
- }
- static void usb3_irq_epc_pipen(struct renesas_usb3 *usb3, int num)
- {
- u32 pn_int_sta;
- if (usb3_pn_change(usb3, num) < 0)
- return;
- pn_int_sta = usb3_read(usb3, USB3_PN_INT_STA);
- pn_int_sta &= usb3_read(usb3, USB3_PN_INT_ENA);
- usb3_write(usb3, pn_int_sta, USB3_PN_INT_STA);
- if (pn_int_sta & PN_INT_LSTTR)
- usb3_irq_epc_pipen_lsttr(usb3, num);
- if (pn_int_sta & PN_INT_BFRDY)
- usb3_irq_epc_pipen_bfrdy(usb3, num);
- }
- static void usb3_irq_epc_int_2(struct renesas_usb3 *usb3, u32 int_sta_2)
- {
- int i;
- for (i = 0; i < usb3->num_usb3_eps; i++) {
- if (int_sta_2 & USB_INT_2_PIPE(i)) {
- if (!i)
- usb3_irq_epc_pipe0(usb3);
- else
- usb3_irq_epc_pipen(usb3, i);
- }
- }
- }
- static void usb3_irq_epc(struct renesas_usb3 *usb3)
- {
- u32 int_sta_1 = usb3_read(usb3, USB3_USB_INT_STA_1);
- u32 int_sta_2 = usb3_read(usb3, USB3_USB_INT_STA_2);
- int_sta_1 &= usb3_read(usb3, USB3_USB_INT_ENA_1);
- if (int_sta_1) {
- usb3_write(usb3, int_sta_1, USB3_USB_INT_STA_1);
- usb3_irq_epc_int_1(usb3, int_sta_1);
- }
- int_sta_2 &= usb3_read(usb3, USB3_USB_INT_ENA_2);
- if (int_sta_2)
- usb3_irq_epc_int_2(usb3, int_sta_2);
- }
- static irqreturn_t renesas_usb3_irq(int irq, void *_usb3)
- {
- struct renesas_usb3 *usb3 = _usb3;
- irqreturn_t ret = IRQ_NONE;
- u32 axi_int_sta = usb3_read(usb3, USB3_AXI_INT_STA);
- if (axi_int_sta & AXI_INT_EPCINT) {
- usb3_irq_epc(usb3);
- ret = IRQ_HANDLED;
- }
- return ret;
- }
- static void usb3_write_pn_mod(struct renesas_usb3_ep *usb3_ep,
- const struct usb_endpoint_descriptor *desc)
- {
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- u32 val = 0;
- val |= usb3_ep->dir_in ? PN_MOD_DIR : 0;
- val |= PN_MOD_TYPE(usb_endpoint_type(desc));
- val |= PN_MOD_EPNUM(usb_endpoint_num(desc));
- usb3_write(usb3, val, USB3_PN_MOD);
- }
- static u32 usb3_calc_ramarea(int ram_size)
- {
- WARN_ON(ram_size > SZ_16K);
- if (ram_size <= SZ_1K)
- return PN_RAMMAP_RAMAREA_1KB;
- else if (ram_size <= SZ_2K)
- return PN_RAMMAP_RAMAREA_2KB;
- else if (ram_size <= SZ_4K)
- return PN_RAMMAP_RAMAREA_4KB;
- else if (ram_size <= SZ_8K)
- return PN_RAMMAP_RAMAREA_8KB;
- else
- return PN_RAMMAP_RAMAREA_16KB;
- }
- static u32 usb3_calc_rammap_val(struct renesas_usb3_ep *usb3_ep,
- const struct usb_endpoint_descriptor *desc)
- {
- return usb3_ep->rammap_val | PN_RAMMAP_MPKT(usb_endpoint_maxp(desc));
- }
- static int usb3_enable_pipe_n(struct renesas_usb3_ep *usb3_ep,
- const struct usb_endpoint_descriptor *desc)
- {
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- unsigned long flags;
- usb3_ep->dir_in = usb_endpoint_dir_in(desc);
- spin_lock_irqsave(&usb3->lock, flags);
- if (!usb3_pn_change(usb3, usb3_ep->num)) {
- usb3_write_pn_mod(usb3_ep, desc);
- usb3_write(usb3, usb3_calc_rammap_val(usb3_ep, desc),
- USB3_PN_RAMMAP);
- usb3_pn_con_clear(usb3);
- usb3_set_bit(usb3, PN_CON_EN, USB3_PN_CON);
- }
- spin_unlock_irqrestore(&usb3->lock, flags);
- return 0;
- }
- static int usb3_disable_pipe_n(struct renesas_usb3_ep *usb3_ep)
- {
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- unsigned long flags;
- usb3_ep->halt = false;
- spin_lock_irqsave(&usb3->lock, flags);
- if (!usb3_pn_change(usb3, usb3_ep->num)) {
- usb3_write(usb3, 0, USB3_PN_RAMMAP);
- usb3_clear_bit(usb3, PN_CON_EN, USB3_PN_CON);
- }
- spin_unlock_irqrestore(&usb3->lock, flags);
- return 0;
- }
- /*------- usb_ep_ops -----------------------------------------------------*/
- static int renesas_usb3_ep_enable(struct usb_ep *_ep,
- const struct usb_endpoint_descriptor *desc)
- {
- struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep);
- return usb3_enable_pipe_n(usb3_ep, desc);
- }
- static int renesas_usb3_ep_disable(struct usb_ep *_ep)
- {
- struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep);
- struct renesas_usb3_request *usb3_req;
- do {
- usb3_req = usb3_get_request(usb3_ep);
- if (!usb3_req)
- break;
- usb3_request_done(usb3_ep, usb3_req, -ESHUTDOWN);
- } while (1);
- return usb3_disable_pipe_n(usb3_ep);
- }
- static struct usb_request *__renesas_usb3_ep_alloc_request(gfp_t gfp_flags)
- {
- struct renesas_usb3_request *usb3_req;
- usb3_req = kzalloc(sizeof(struct renesas_usb3_request), gfp_flags);
- if (!usb3_req)
- return NULL;
- INIT_LIST_HEAD(&usb3_req->queue);
- return &usb3_req->req;
- }
- static void __renesas_usb3_ep_free_request(struct usb_request *_req)
- {
- struct renesas_usb3_request *usb3_req = usb_req_to_usb3_req(_req);
- kfree(usb3_req);
- }
- static struct usb_request *renesas_usb3_ep_alloc_request(struct usb_ep *_ep,
- gfp_t gfp_flags)
- {
- return __renesas_usb3_ep_alloc_request(gfp_flags);
- }
- static void renesas_usb3_ep_free_request(struct usb_ep *_ep,
- struct usb_request *_req)
- {
- __renesas_usb3_ep_free_request(_req);
- }
- static int renesas_usb3_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
- {
- struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep);
- struct renesas_usb3_request *usb3_req = usb_req_to_usb3_req(_req);
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- dev_dbg(usb3_to_dev(usb3), "ep_dequeue: ep%2d, %u\n", usb3_ep->num,
- _req->length);
- usb3_request_done_pipen(usb3, usb3_ep, usb3_req, -ECONNRESET);
- return 0;
- }
- static int renesas_usb3_ep_set_halt(struct usb_ep *_ep, int value)
- {
- return usb3_set_halt(usb_ep_to_usb3_ep(_ep), !!value, false);
- }
- static int renesas_usb3_ep_set_wedge(struct usb_ep *_ep)
- {
- struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep);
- usb3_ep->wedge = true;
- return usb3_set_halt(usb3_ep, true, false);
- }
- static void renesas_usb3_ep_fifo_flush(struct usb_ep *_ep)
- {
- struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep);
- struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
- unsigned long flags;
- if (usb3_ep->num) {
- spin_lock_irqsave(&usb3->lock, flags);
- if (!usb3_pn_change(usb3, usb3_ep->num)) {
- usb3_pn_con_clear(usb3);
- usb3_set_bit(usb3, PN_CON_EN, USB3_PN_CON);
- }
- spin_unlock_irqrestore(&usb3->lock, flags);
- } else {
- usb3_p0_con_clear_buffer(usb3);
- }
- }
- static struct usb_ep_ops renesas_usb3_ep_ops = {
- .enable = renesas_usb3_ep_enable,
- .disable = renesas_usb3_ep_disable,
- .alloc_request = renesas_usb3_ep_alloc_request,
- .free_request = renesas_usb3_ep_free_request,
- .queue = renesas_usb3_ep_queue,
- .dequeue = renesas_usb3_ep_dequeue,
- .set_halt = renesas_usb3_ep_set_halt,
- .set_wedge = renesas_usb3_ep_set_wedge,
- .fifo_flush = renesas_usb3_ep_fifo_flush,
- };
- /*------- usb_gadget_ops -------------------------------------------------*/
- static int renesas_usb3_start(struct usb_gadget *gadget,
- struct usb_gadget_driver *driver)
- {
- struct renesas_usb3 *usb3;
- if (!driver || driver->max_speed < USB_SPEED_FULL ||
- !driver->setup)
- return -EINVAL;
- usb3 = gadget_to_renesas_usb3(gadget);
- /* hook up the driver */
- usb3->driver = driver;
- renesas_usb3_init_controller(usb3);
- return 0;
- }
- static int renesas_usb3_stop(struct usb_gadget *gadget)
- {
- struct renesas_usb3 *usb3 = gadget_to_renesas_usb3(gadget);
- unsigned long flags;
- spin_lock_irqsave(&usb3->lock, flags);
- usb3->softconnect = false;
- usb3->gadget.speed = USB_SPEED_UNKNOWN;
- usb3->driver = NULL;
- renesas_usb3_stop_controller(usb3);
- spin_unlock_irqrestore(&usb3->lock, flags);
- return 0;
- }
- static int renesas_usb3_get_frame(struct usb_gadget *_gadget)
- {
- return -EOPNOTSUPP;
- }
- static int renesas_usb3_pullup(struct usb_gadget *gadget, int is_on)
- {
- struct renesas_usb3 *usb3 = gadget_to_renesas_usb3(gadget);
- usb3->softconnect = !!is_on;
- return 0;
- }
- static int renesas_usb3_set_selfpowered(struct usb_gadget *gadget, int is_self)
- {
- gadget->is_selfpowered = !!is_self;
- return 0;
- }
- static const struct usb_gadget_ops renesas_usb3_gadget_ops = {
- .get_frame = renesas_usb3_get_frame,
- .udc_start = renesas_usb3_start,
- .udc_stop = renesas_usb3_stop,
- .pullup = renesas_usb3_pullup,
- .set_selfpowered = renesas_usb3_set_selfpowered,
- };
- /*------- platform_driver ------------------------------------------------*/
- static int renesas_usb3_remove(struct platform_device *pdev)
- {
- struct renesas_usb3 *usb3 = platform_get_drvdata(pdev);
- pm_runtime_put(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
- usb_del_gadget_udc(&usb3->gadget);
- __renesas_usb3_ep_free_request(usb3->ep0_req);
- return 0;
- }
- static int renesas_usb3_init_ep(struct renesas_usb3 *usb3, struct device *dev,
- const struct renesas_usb3_priv *priv)
- {
- struct renesas_usb3_ep *usb3_ep;
- int i;
- /* calculate num_usb3_eps from renesas_usb3_priv */
- usb3->num_usb3_eps = priv->ramsize_per_ramif * priv->num_ramif * 2 /
- priv->ramsize_per_pipe + 1;
- if (usb3->num_usb3_eps > USB3_MAX_NUM_PIPES)
- usb3->num_usb3_eps = USB3_MAX_NUM_PIPES;
- usb3->usb3_ep = devm_kzalloc(dev, sizeof(*usb3_ep) * usb3->num_usb3_eps,
- GFP_KERNEL);
- if (!usb3->usb3_ep)
- return -ENOMEM;
- dev_dbg(dev, "%s: num_usb3_eps = %d\n", __func__, usb3->num_usb3_eps);
- /*
- * This driver prepares pipes as the followings:
- * - odd pipes = IN pipe
- * - even pipes = OUT pipe (except pipe 0)
- */
- usb3_for_each_ep(usb3_ep, usb3, i) {
- snprintf(usb3_ep->ep_name, sizeof(usb3_ep->ep_name), "ep%d", i);
- usb3_ep->usb3 = usb3;
- usb3_ep->num = i;
- usb3_ep->ep.name = usb3_ep->ep_name;
- usb3_ep->ep.ops = &renesas_usb3_ep_ops;
- INIT_LIST_HEAD(&usb3_ep->queue);
- INIT_LIST_HEAD(&usb3_ep->ep.ep_list);
- if (!i) {
- /* for control pipe */
- usb3->gadget.ep0 = &usb3_ep->ep;
- usb_ep_set_maxpacket_limit(&usb3_ep->ep,
- USB3_EP0_HSFS_MAX_PACKET_SIZE);
- usb3_ep->ep.caps.type_control = true;
- usb3_ep->ep.caps.dir_in = true;
- usb3_ep->ep.caps.dir_out = true;
- continue;
- }
- /* for bulk or interrupt pipe */
- usb_ep_set_maxpacket_limit(&usb3_ep->ep, ~0);
- list_add_tail(&usb3_ep->ep.ep_list, &usb3->gadget.ep_list);
- usb3_ep->ep.caps.type_bulk = true;
- usb3_ep->ep.caps.type_int = true;
- if (i & 1)
- usb3_ep->ep.caps.dir_in = true;
- else
- usb3_ep->ep.caps.dir_out = true;
- }
- return 0;
- }
- static void renesas_usb3_init_ram(struct renesas_usb3 *usb3, struct device *dev,
- const struct renesas_usb3_priv *priv)
- {
- struct renesas_usb3_ep *usb3_ep;
- int i;
- u32 ramif[2], basead[2]; /* index 0 = for IN pipes */
- u32 *cur_ramif, *cur_basead;
- u32 val;
- memset(ramif, 0, sizeof(ramif));
- memset(basead, 0, sizeof(basead));
- /*
- * This driver prepares pipes as the followings:
- * - all pipes = the same size as "ramsize_per_pipe"
- * Please refer to the "Method of Specifying RAM Mapping"
- */
- usb3_for_each_ep(usb3_ep, usb3, i) {
- if (!i)
- continue; /* out of scope if ep num = 0 */
- if (usb3_ep->ep.caps.dir_in) {
- cur_ramif = &ramif[0];
- cur_basead = &basead[0];
- } else {
- cur_ramif = &ramif[1];
- cur_basead = &basead[1];
- }
- if (*cur_basead > priv->ramsize_per_ramif)
- continue; /* out of memory for IN or OUT pipe */
- /* calculate rammap_val */
- val = PN_RAMMAP_RAMIF(*cur_ramif);
- val |= usb3_calc_ramarea(priv->ramsize_per_pipe);
- val |= PN_RAMMAP_BASEAD(*cur_basead);
- usb3_ep->rammap_val = val;
- dev_dbg(dev, "ep%2d: val = %08x, ramif = %d, base = %x\n",
- i, val, *cur_ramif, *cur_basead);
- /* update current ramif */
- if (*cur_ramif + 1 == priv->num_ramif) {
- *cur_ramif = 0;
- *cur_basead += priv->ramsize_per_pipe;
- } else {
- (*cur_ramif)++;
- }
- }
- }
- static const struct renesas_usb3_priv renesas_usb3_priv_r8a7795 = {
- .ramsize_per_ramif = SZ_16K,
- .num_ramif = 2,
- .ramsize_per_pipe = SZ_4K,
- .workaround_for_vbus = true,
- };
- static const struct of_device_id usb3_of_match[] = {
- {
- .compatible = "renesas,r8a7795-usb3-peri",
- .data = &renesas_usb3_priv_r8a7795,
- },
- { },
- };
- MODULE_DEVICE_TABLE(of, usb3_of_match);
- static int renesas_usb3_probe(struct platform_device *pdev)
- {
- struct renesas_usb3 *usb3;
- struct resource *res;
- const struct of_device_id *match;
- int irq, ret;
- const struct renesas_usb3_priv *priv;
- match = of_match_node(usb3_of_match, pdev->dev.of_node);
- if (!match)
- return -ENODEV;
- priv = match->data;
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return -ENODEV;
- usb3 = devm_kzalloc(&pdev->dev, sizeof(*usb3), GFP_KERNEL);
- if (!usb3)
- return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- usb3->reg = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(usb3->reg))
- return PTR_ERR(usb3->reg);
- platform_set_drvdata(pdev, usb3);
- spin_lock_init(&usb3->lock);
- usb3->gadget.ops = &renesas_usb3_gadget_ops;
- usb3->gadget.name = udc_name;
- usb3->gadget.max_speed = USB_SPEED_SUPER;
- INIT_LIST_HEAD(&usb3->gadget.ep_list);
- ret = renesas_usb3_init_ep(usb3, &pdev->dev, priv);
- if (ret < 0)
- return ret;
- renesas_usb3_init_ram(usb3, &pdev->dev, priv);
- ret = devm_request_irq(&pdev->dev, irq, renesas_usb3_irq, 0,
- dev_name(&pdev->dev), usb3);
- if (ret < 0)
- return ret;
- /* for ep0 handling */
- usb3->ep0_req = __renesas_usb3_ep_alloc_request(GFP_KERNEL);
- if (!usb3->ep0_req)
- return -ENOMEM;
- ret = usb_add_gadget_udc(&pdev->dev, &usb3->gadget);
- if (ret < 0)
- goto err_add_udc;
- usb3->workaround_for_vbus = priv->workaround_for_vbus;
- pm_runtime_enable(&pdev->dev);
- pm_runtime_get_sync(&pdev->dev);
- dev_info(&pdev->dev, "probed\n");
- return 0;
- err_add_udc:
- __renesas_usb3_ep_free_request(usb3->ep0_req);
- return ret;
- }
- static struct platform_driver renesas_usb3_driver = {
- .probe = renesas_usb3_probe,
- .remove = renesas_usb3_remove,
- .driver = {
- .name = (char *)udc_name,
- .of_match_table = of_match_ptr(usb3_of_match),
- },
- };
- module_platform_driver(renesas_usb3_driver);
- MODULE_DESCRIPTION("Renesas USB3.0 Peripheral driver");
- MODULE_LICENSE("GPL v2");
- MODULE_AUTHOR("Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>");
- MODULE_ALIAS("platform:renesas_usb3");
|