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