xref: /openbmc/u-boot/drivers/usb/musb/musb_core.c (revision e8f80a5a)
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