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