1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * am35x.c - TI's AM35x platform specific usb wrapper functions. 4 * 5 * Author: Ajay Kumar Gupta <ajay.gupta@ti.com> 6 * 7 * Based on drivers/usb/musb/da8xx.c 8 * 9 * Copyright (c) 2010 Texas Instruments Incorporated 10 */ 11 12 #include <common.h> 13 14 #include "am35x.h" 15 16 /* MUSB platform configuration */ 17 struct musb_config musb_cfg = { 18 .regs = (struct musb_regs *)AM35X_USB_OTG_CORE_BASE, 19 .timeout = AM35X_USB_OTG_TIMEOUT, 20 .musb_speed = 0, 21 }; 22 23 /* 24 * Enable the USB phy 25 */ 26 static u8 phy_on(void) 27 { 28 u32 devconf2; 29 u32 timeout; 30 31 devconf2 = readl(&am35x_scm_general_regs->devconf2); 32 33 devconf2 &= ~(DEVCONF2_RESET | DEVCONF2_PHYPWRDN | DEVCONF2_OTGPWRDN | 34 DEVCONF2_OTGMODE | DEVCONF2_REFFREQ | 35 DEVCONF2_PHY_GPIOMODE); 36 devconf2 |= DEVCONF2_SESENDEN | DEVCONF2_VBDTCTEN | DEVCONF2_PHY_PLLON | 37 DEVCONF2_REFFREQ_13MHZ | DEVCONF2_DATPOL; 38 39 writel(devconf2, &am35x_scm_general_regs->devconf2); 40 41 /* wait until the USB phy is turned on */ 42 timeout = musb_cfg.timeout; 43 while (timeout--) 44 if (readl(&am35x_scm_general_regs->devconf2) & DEVCONF2_PHYCKGD) 45 return 1; 46 47 /* USB phy was not turned on */ 48 return 0; 49 } 50 51 /* 52 * Disable the USB phy 53 */ 54 static void phy_off(void) 55 { 56 u32 devconf2; 57 58 /* 59 * Power down the on-chip PHY. 60 */ 61 devconf2 = readl(&am35x_scm_general_regs->devconf2); 62 63 devconf2 &= ~DEVCONF2_PHY_PLLON; 64 devconf2 |= DEVCONF2_PHYPWRDN | DEVCONF2_OTGPWRDN; 65 writel(devconf2, &am35x_scm_general_regs->devconf2); 66 } 67 68 /* 69 * This function performs platform specific initialization for usb0. 70 */ 71 int musb_platform_init(void) 72 { 73 u32 revision; 74 u32 sw_reset; 75 76 /* global usb reset */ 77 sw_reset = readl(&am35x_scm_general_regs->ip_sw_reset); 78 sw_reset |= (1 << 0); 79 writel(sw_reset, &am35x_scm_general_regs->ip_sw_reset); 80 sw_reset &= ~(1 << 0); 81 writel(sw_reset, &am35x_scm_general_regs->ip_sw_reset); 82 83 /* reset the controller */ 84 writel(0x1, &am35x_usb_regs->control); 85 udelay(5000); 86 87 /* start the on-chip usb phy and its pll */ 88 if (phy_on() == 0) 89 return -1; 90 91 /* Returns zero if e.g. not clocked */ 92 revision = readl(&am35x_usb_regs->revision); 93 if (revision == 0) 94 return -1; 95 96 return 0; 97 } 98 99 /* 100 * This function performs platform specific deinitialization for usb0. 101 */ 102 void musb_platform_deinit(void) 103 { 104 /* Turn off the phy */ 105 phy_off(); 106 } 107 108 /* 109 * This function reads data from endpoint fifo for AM35x 110 * which supports only 32bit read operation. 111 * 112 * ep - endpoint number 113 * length - number of bytes to read from FIFO 114 * fifo_data - pointer to data buffer into which data is read 115 */ 116 __attribute__((weak)) 117 void read_fifo(u8 ep, u32 length, void *fifo_data) 118 { 119 u8 *data = (u8 *)fifo_data; 120 u32 val; 121 int i; 122 123 /* select the endpoint index */ 124 writeb(ep, &musbr->index); 125 126 if (length > 4) { 127 for (i = 0; i < (length >> 2); i++) { 128 val = readl(&musbr->fifox[ep]); 129 memcpy(data, &val, 4); 130 data += 4; 131 } 132 length %= 4; 133 } 134 if (length > 0) { 135 val = readl(&musbr->fifox[ep]); 136 memcpy(data, &val, length); 137 } 138 } 139