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#include <linux/delay.h> 14 15#include "am35x.h" 16 17/* MUSB platform configuration */ 18struct 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 */ 27static 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 */ 55static 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 */ 72int 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 */ 103void 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)) 118void 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