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