12731b9a8SJean-Christophe PLAGNIOL-VILLARD /*
22731b9a8SJean-Christophe PLAGNIOL-VILLARD * Mentor USB OTG Core functionality common for both Host and Device
32731b9a8SJean-Christophe PLAGNIOL-VILLARD * functionality.
42731b9a8SJean-Christophe PLAGNIOL-VILLARD *
52731b9a8SJean-Christophe PLAGNIOL-VILLARD * Copyright (c) 2008 Texas Instruments
62731b9a8SJean-Christophe PLAGNIOL-VILLARD *
71a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
82731b9a8SJean-Christophe PLAGNIOL-VILLARD *
92731b9a8SJean-Christophe PLAGNIOL-VILLARD * Author: Thomas Abraham t-abraham@ti.com, Texas Instruments
102731b9a8SJean-Christophe PLAGNIOL-VILLARD */
112731b9a8SJean-Christophe PLAGNIOL-VILLARD
122731b9a8SJean-Christophe PLAGNIOL-VILLARD #include <common.h>
132731b9a8SJean-Christophe PLAGNIOL-VILLARD
142731b9a8SJean-Christophe PLAGNIOL-VILLARD #include "musb_core.h"
152731b9a8SJean-Christophe PLAGNIOL-VILLARD struct musb_regs *musbr;
162731b9a8SJean-Christophe PLAGNIOL-VILLARD
172731b9a8SJean-Christophe PLAGNIOL-VILLARD /*
182731b9a8SJean-Christophe PLAGNIOL-VILLARD * program the mentor core to start (enable interrupts, dma, etc.)
192731b9a8SJean-Christophe PLAGNIOL-VILLARD */
musb_start(void)202731b9a8SJean-Christophe PLAGNIOL-VILLARD void musb_start(void)
212731b9a8SJean-Christophe PLAGNIOL-VILLARD {
22*95de1e2fSPaul Kocialkowski #if defined(CONFIG_USB_MUSB_HCD)
232731b9a8SJean-Christophe PLAGNIOL-VILLARD u8 devctl;
249bb47abfSAjay Kumar Gupta u8 busctl;
25f298e4b6STom Rix #endif
262731b9a8SJean-Christophe PLAGNIOL-VILLARD
272731b9a8SJean-Christophe PLAGNIOL-VILLARD /* disable all interrupts */
282731b9a8SJean-Christophe PLAGNIOL-VILLARD writew(0, &musbr->intrtxe);
292731b9a8SJean-Christophe PLAGNIOL-VILLARD writew(0, &musbr->intrrxe);
302731b9a8SJean-Christophe PLAGNIOL-VILLARD writeb(0, &musbr->intrusbe);
312731b9a8SJean-Christophe PLAGNIOL-VILLARD writeb(0, &musbr->testmode);
322731b9a8SJean-Christophe PLAGNIOL-VILLARD
332731b9a8SJean-Christophe PLAGNIOL-VILLARD /* put into basic highspeed mode and start session */
342731b9a8SJean-Christophe PLAGNIOL-VILLARD writeb(MUSB_POWER_HSENAB, &musbr->power);
35*95de1e2fSPaul Kocialkowski #if defined(CONFIG_USB_MUSB_HCD)
369bb47abfSAjay Kumar Gupta /* Program PHY to use EXT VBUS if required */
379bb47abfSAjay Kumar Gupta if (musb_cfg.extvbus == 1) {
389bb47abfSAjay Kumar Gupta busctl = musb_read_ulpi_buscontrol(musbr);
399bb47abfSAjay Kumar Gupta musb_write_ulpi_buscontrol(musbr, busctl | ULPI_USE_EXTVBUS);
409bb47abfSAjay Kumar Gupta }
419bb47abfSAjay Kumar Gupta
422731b9a8SJean-Christophe PLAGNIOL-VILLARD devctl = readb(&musbr->devctl);
432731b9a8SJean-Christophe PLAGNIOL-VILLARD writeb(devctl | MUSB_DEVCTL_SESSION, &musbr->devctl);
442731b9a8SJean-Christophe PLAGNIOL-VILLARD #endif
452731b9a8SJean-Christophe PLAGNIOL-VILLARD }
462731b9a8SJean-Christophe PLAGNIOL-VILLARD
47df402ba3SBryan Wu #ifdef MUSB_NO_DYNAMIC_FIFO
48df402ba3SBryan Wu # define config_fifo(dir, idx, addr)
49df402ba3SBryan Wu #else
50df402ba3SBryan Wu # define config_fifo(dir, idx, addr) \
51df402ba3SBryan Wu do { \
52df402ba3SBryan Wu writeb(idx, &musbr->dir##fifosz); \
53df402ba3SBryan Wu writew(fifoaddr >> 3, &musbr->dir##fifoadd); \
54df402ba3SBryan Wu } while (0)
55df402ba3SBryan Wu #endif
56df402ba3SBryan Wu
572731b9a8SJean-Christophe PLAGNIOL-VILLARD /*
582731b9a8SJean-Christophe PLAGNIOL-VILLARD * This function configures the endpoint configuration. The musb hcd or musb
592731b9a8SJean-Christophe PLAGNIOL-VILLARD * device implementation can use this function to configure the endpoints
602731b9a8SJean-Christophe PLAGNIOL-VILLARD * and set the FIFO sizes. Note: The summation of FIFO sizes of all endpoints
612731b9a8SJean-Christophe PLAGNIOL-VILLARD * should not be more than the available FIFO size.
622731b9a8SJean-Christophe PLAGNIOL-VILLARD *
632731b9a8SJean-Christophe PLAGNIOL-VILLARD * epinfo - Pointer to EP configuration table
642731b9a8SJean-Christophe PLAGNIOL-VILLARD * cnt - Number of entries in the EP conf table.
652731b9a8SJean-Christophe PLAGNIOL-VILLARD */
musb_configure_ep(const struct musb_epinfo * epinfo,u8 cnt)660228348eSMike Frysinger void musb_configure_ep(const struct musb_epinfo *epinfo, u8 cnt)
672731b9a8SJean-Christophe PLAGNIOL-VILLARD {
682731b9a8SJean-Christophe PLAGNIOL-VILLARD u16 csr;
692731b9a8SJean-Christophe PLAGNIOL-VILLARD u16 fifoaddr = 64; /* First 64 bytes of FIFO reserved for EP0 */
702731b9a8SJean-Christophe PLAGNIOL-VILLARD u32 fifosize;
712731b9a8SJean-Christophe PLAGNIOL-VILLARD u8 idx;
722731b9a8SJean-Christophe PLAGNIOL-VILLARD
732731b9a8SJean-Christophe PLAGNIOL-VILLARD while (cnt--) {
742731b9a8SJean-Christophe PLAGNIOL-VILLARD /* prepare fifosize to write to register */
752731b9a8SJean-Christophe PLAGNIOL-VILLARD fifosize = epinfo->epsize >> 3;
762731b9a8SJean-Christophe PLAGNIOL-VILLARD idx = ffs(fifosize) - 1;
772731b9a8SJean-Christophe PLAGNIOL-VILLARD
782731b9a8SJean-Christophe PLAGNIOL-VILLARD writeb(epinfo->epnum, &musbr->index);
792731b9a8SJean-Christophe PLAGNIOL-VILLARD if (epinfo->epdir) {
802731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Configure fifo size and fifo base address */
81df402ba3SBryan Wu config_fifo(tx, idx, fifoaddr);
82f298e4b6STom Rix
83f298e4b6STom Rix csr = readw(&musbr->txcsr);
84*95de1e2fSPaul Kocialkowski #if defined(CONFIG_USB_MUSB_HCD)
852731b9a8SJean-Christophe PLAGNIOL-VILLARD /* clear the data toggle bit */
862731b9a8SJean-Christophe PLAGNIOL-VILLARD writew(csr | MUSB_TXCSR_CLRDATATOG, &musbr->txcsr);
872731b9a8SJean-Christophe PLAGNIOL-VILLARD #endif
882731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Flush fifo if required */
892731b9a8SJean-Christophe PLAGNIOL-VILLARD if (csr & MUSB_TXCSR_TXPKTRDY)
902731b9a8SJean-Christophe PLAGNIOL-VILLARD writew(csr | MUSB_TXCSR_FLUSHFIFO,
912731b9a8SJean-Christophe PLAGNIOL-VILLARD &musbr->txcsr);
922731b9a8SJean-Christophe PLAGNIOL-VILLARD } else {
932731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Configure fifo size and fifo base address */
94df402ba3SBryan Wu config_fifo(rx, idx, fifoaddr);
95f298e4b6STom Rix
96f298e4b6STom Rix csr = readw(&musbr->rxcsr);
97*95de1e2fSPaul Kocialkowski #if defined(CONFIG_USB_MUSB_HCD)
982731b9a8SJean-Christophe PLAGNIOL-VILLARD /* clear the data toggle bit */
992731b9a8SJean-Christophe PLAGNIOL-VILLARD writew(csr | MUSB_RXCSR_CLRDATATOG, &musbr->rxcsr);
1002731b9a8SJean-Christophe PLAGNIOL-VILLARD #endif
1012731b9a8SJean-Christophe PLAGNIOL-VILLARD /* Flush fifo if required */
1022731b9a8SJean-Christophe PLAGNIOL-VILLARD if (csr & MUSB_RXCSR_RXPKTRDY)
1032731b9a8SJean-Christophe PLAGNIOL-VILLARD writew(csr | MUSB_RXCSR_FLUSHFIFO,
1042731b9a8SJean-Christophe PLAGNIOL-VILLARD &musbr->rxcsr);
1052731b9a8SJean-Christophe PLAGNIOL-VILLARD }
1062731b9a8SJean-Christophe PLAGNIOL-VILLARD fifoaddr += epinfo->epsize;
1072731b9a8SJean-Christophe PLAGNIOL-VILLARD epinfo++;
1082731b9a8SJean-Christophe PLAGNIOL-VILLARD }
1092731b9a8SJean-Christophe PLAGNIOL-VILLARD }
1102731b9a8SJean-Christophe PLAGNIOL-VILLARD
1112731b9a8SJean-Christophe PLAGNIOL-VILLARD /*
1122731b9a8SJean-Christophe PLAGNIOL-VILLARD * This function writes data to endpoint fifo
1132731b9a8SJean-Christophe PLAGNIOL-VILLARD *
1142731b9a8SJean-Christophe PLAGNIOL-VILLARD * ep - endpoint number
1152731b9a8SJean-Christophe PLAGNIOL-VILLARD * length - number of bytes to write to FIFO
1162731b9a8SJean-Christophe PLAGNIOL-VILLARD * fifo_data - Pointer to data buffer that contains the data to write
1172731b9a8SJean-Christophe PLAGNIOL-VILLARD */
118df402ba3SBryan Wu __attribute__((weak))
write_fifo(u8 ep,u32 length,void * fifo_data)1192731b9a8SJean-Christophe PLAGNIOL-VILLARD void write_fifo(u8 ep, u32 length, void *fifo_data)
1202731b9a8SJean-Christophe PLAGNIOL-VILLARD {
1212731b9a8SJean-Christophe PLAGNIOL-VILLARD u8 *data = (u8 *)fifo_data;
1222731b9a8SJean-Christophe PLAGNIOL-VILLARD
1232731b9a8SJean-Christophe PLAGNIOL-VILLARD /* select the endpoint index */
1242731b9a8SJean-Christophe PLAGNIOL-VILLARD writeb(ep, &musbr->index);
1252731b9a8SJean-Christophe PLAGNIOL-VILLARD
1262731b9a8SJean-Christophe PLAGNIOL-VILLARD /* write the data to the fifo */
1272731b9a8SJean-Christophe PLAGNIOL-VILLARD while (length--)
1282731b9a8SJean-Christophe PLAGNIOL-VILLARD writeb(*data++, &musbr->fifox[ep]);
1292731b9a8SJean-Christophe PLAGNIOL-VILLARD }
1302731b9a8SJean-Christophe PLAGNIOL-VILLARD
1312731b9a8SJean-Christophe PLAGNIOL-VILLARD /*
1325689f4b5SAjay Kumar Gupta * AM35x supports only 32bit read operations so
1335689f4b5SAjay Kumar Gupta * use seperate read_fifo() function for it.
1345689f4b5SAjay Kumar Gupta */
1355689f4b5SAjay Kumar Gupta #ifndef CONFIG_USB_AM35X
1365689f4b5SAjay Kumar Gupta /*
1372731b9a8SJean-Christophe PLAGNIOL-VILLARD * This function reads data from endpoint fifo
1382731b9a8SJean-Christophe PLAGNIOL-VILLARD *
1392731b9a8SJean-Christophe PLAGNIOL-VILLARD * ep - endpoint number
1402731b9a8SJean-Christophe PLAGNIOL-VILLARD * length - number of bytes to read from FIFO
1412731b9a8SJean-Christophe PLAGNIOL-VILLARD * fifo_data - pointer to data buffer into which data is read
1422731b9a8SJean-Christophe PLAGNIOL-VILLARD */
143df402ba3SBryan Wu __attribute__((weak))
read_fifo(u8 ep,u32 length,void * fifo_data)1442731b9a8SJean-Christophe PLAGNIOL-VILLARD void read_fifo(u8 ep, u32 length, void *fifo_data)
1452731b9a8SJean-Christophe PLAGNIOL-VILLARD {
1462731b9a8SJean-Christophe PLAGNIOL-VILLARD u8 *data = (u8 *)fifo_data;
1472731b9a8SJean-Christophe PLAGNIOL-VILLARD
1482731b9a8SJean-Christophe PLAGNIOL-VILLARD /* select the endpoint index */
1492731b9a8SJean-Christophe PLAGNIOL-VILLARD writeb(ep, &musbr->index);
1502731b9a8SJean-Christophe PLAGNIOL-VILLARD
1512731b9a8SJean-Christophe PLAGNIOL-VILLARD /* read the data to the fifo */
1522731b9a8SJean-Christophe PLAGNIOL-VILLARD while (length--)
1532731b9a8SJean-Christophe PLAGNIOL-VILLARD *data++ = readb(&musbr->fifox[ep]);
1542731b9a8SJean-Christophe PLAGNIOL-VILLARD }
1555689f4b5SAjay Kumar Gupta #endif /* CONFIG_USB_AM35X */
156