blob: d9df423f3d1209872544f53657e6db1577a4082f [file] [log] [blame]
David Daney1643acc2010-10-08 14:47:52 -07001/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
David Daneyf5ced992011-04-27 10:54:20 -07006 * Copyright (C) 2010, 2011 Cavium Networks
David Daney1643acc2010-10-08 14:47:52 -07007 */
8
9#include <linux/module.h>
David Daneyf5ced992011-04-27 10:54:20 -070010#include <linux/mutex.h>
David Daney1643acc2010-10-08 14:47:52 -070011#include <linux/delay.h>
12
David Daney1643acc2010-10-08 14:47:52 -070013#include <asm/octeon/octeon.h>
14#include <asm/octeon/cvmx-uctlx-defs.h>
15
David Daneyf5ced992011-04-27 10:54:20 -070016static DEFINE_MUTEX(octeon2_usb_clocks_mutex);
17
18static int octeon2_usb_clock_start_cnt;
David Daney1643acc2010-10-08 14:47:52 -070019
20void octeon2_usb_clocks_start(void)
21{
22 u64 div;
23 union cvmx_uctlx_if_ena if_ena;
24 union cvmx_uctlx_clk_rst_ctl clk_rst_ctl;
25 union cvmx_uctlx_uphy_ctl_status uphy_ctl_status;
26 union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status;
27 int i;
28 unsigned long io_clk_64_to_ns;
29
David Daneyf5ced992011-04-27 10:54:20 -070030
31 mutex_lock(&octeon2_usb_clocks_mutex);
32
33 octeon2_usb_clock_start_cnt++;
34 if (octeon2_usb_clock_start_cnt != 1)
35 goto exit;
David Daney1643acc2010-10-08 14:47:52 -070036
37 io_clk_64_to_ns = 64000000000ull / octeon_get_io_clock_rate();
38
39 /*
40 * Step 1: Wait for voltages stable. That surely happened
41 * before starting the kernel.
42 *
43 * Step 2: Enable SCLK of UCTL by writing UCTL0_IF_ENA[EN] = 1
44 */
45 if_ena.u64 = 0;
46 if_ena.s.en = 1;
47 cvmx_write_csr(CVMX_UCTLX_IF_ENA(0), if_ena.u64);
48
49 /* Step 3: Configure the reference clock, PHY, and HCLK */
50 clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
David Daneyf5ced992011-04-27 10:54:20 -070051
52 /*
53 * If the UCTL looks like it has already been started, skip
54 * the initialization, otherwise bus errors are obtained.
55 */
56 if (clk_rst_ctl.s.hrst)
57 goto end_clock;
David Daney1643acc2010-10-08 14:47:52 -070058 /* 3a */
59 clk_rst_ctl.s.p_por = 1;
60 clk_rst_ctl.s.hrst = 0;
61 clk_rst_ctl.s.p_prst = 0;
62 clk_rst_ctl.s.h_clkdiv_rst = 0;
63 clk_rst_ctl.s.o_clkdiv_rst = 0;
64 clk_rst_ctl.s.h_clkdiv_en = 0;
65 clk_rst_ctl.s.o_clkdiv_en = 0;
66 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
67
68 /* 3b */
69 /* 12MHz crystal. */
70 clk_rst_ctl.s.p_refclk_sel = 0;
71 clk_rst_ctl.s.p_refclk_div = 0;
72 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
73
74 /* 3c */
75 div = octeon_get_io_clock_rate() / 130000000ull;
76
77 switch (div) {
78 case 0:
79 div = 1;
80 break;
81 case 1:
82 case 2:
83 case 3:
84 case 4:
85 break;
86 case 5:
87 div = 4;
88 break;
89 case 6:
90 case 7:
91 div = 6;
92 break;
93 case 8:
94 case 9:
95 case 10:
96 case 11:
97 div = 8;
98 break;
99 default:
100 div = 12;
101 break;
102 }
103 clk_rst_ctl.s.h_div = div;
104 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
105 /* Read it back, */
106 clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
107 clk_rst_ctl.s.h_clkdiv_en = 1;
108 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
109 /* 3d */
110 clk_rst_ctl.s.h_clkdiv_rst = 1;
111 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
112
113 /* 3e: delay 64 io clocks */
114 ndelay(io_clk_64_to_ns);
115
116 /*
117 * Step 4: Program the power-on reset field in the UCTL
118 * clock-reset-control register.
119 */
120 clk_rst_ctl.s.p_por = 0;
121 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
122
123 /* Step 5: Wait 1 ms for the PHY clock to start. */
124 mdelay(1);
125
126 /*
127 * Step 6: Program the reset input from automatic test
128 * equipment field in the UPHY CSR
129 */
130 uphy_ctl_status.u64 = cvmx_read_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0));
131 uphy_ctl_status.s.ate_reset = 1;
132 cvmx_write_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0), uphy_ctl_status.u64);
133
134 /* Step 7: Wait for at least 10ns. */
135 ndelay(10);
136
137 /* Step 8: Clear the ATE_RESET field in the UPHY CSR. */
138 uphy_ctl_status.s.ate_reset = 0;
139 cvmx_write_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0), uphy_ctl_status.u64);
140
141 /*
142 * Step 9: Wait for at least 20ns for UPHY to output PHY clock
143 * signals and OHCI_CLK48
144 */
145 ndelay(20);
146
147 /* Step 10: Configure the OHCI_CLK48 and OHCI_CLK12 clocks. */
148 /* 10a */
149 clk_rst_ctl.s.o_clkdiv_rst = 1;
150 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
151
152 /* 10b */
153 clk_rst_ctl.s.o_clkdiv_en = 1;
154 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
155
156 /* 10c */
157 ndelay(io_clk_64_to_ns);
158
159 /*
160 * Step 11: Program the PHY reset field:
161 * UCTL0_CLK_RST_CTL[P_PRST] = 1
162 */
163 clk_rst_ctl.s.p_prst = 1;
164 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
165
166 /* Step 12: Wait 1 uS. */
167 udelay(1);
168
169 /* Step 13: Program the HRESET_N field: UCTL0_CLK_RST_CTL[HRST] = 1 */
170 clk_rst_ctl.s.hrst = 1;
171 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
172
David Daneyf5ced992011-04-27 10:54:20 -0700173end_clock:
David Daney1643acc2010-10-08 14:47:52 -0700174 /* Now we can set some other registers. */
175
176 for (i = 0; i <= 1; i++) {
177 port_ctl_status.u64 =
178 cvmx_read_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0));
David Daneybf541712011-04-27 10:54:21 -0700179 /* Set txvreftune to 15 to obtain compliant 'eye' diagram. */
David Daney1643acc2010-10-08 14:47:52 -0700180 port_ctl_status.s.txvreftune = 15;
David Daneybf541712011-04-27 10:54:21 -0700181 port_ctl_status.s.txrisetune = 1;
182 port_ctl_status.s.txpreemphasistune = 1;
David Daney1643acc2010-10-08 14:47:52 -0700183 cvmx_write_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0),
184 port_ctl_status.u64);
185 }
David Daney14be2492011-04-27 10:54:22 -0700186
187 /* Set uSOF cycle period to 60,000 bits. */
188 cvmx_write_csr(CVMX_UCTLX_EHCI_FLA(0), 0x20ull);
David Daneyf5ced992011-04-27 10:54:20 -0700189exit:
190 mutex_unlock(&octeon2_usb_clocks_mutex);
David Daney1643acc2010-10-08 14:47:52 -0700191}
192EXPORT_SYMBOL(octeon2_usb_clocks_start);
193
194void octeon2_usb_clocks_stop(void)
195{
David Daneyf5ced992011-04-27 10:54:20 -0700196 mutex_lock(&octeon2_usb_clocks_mutex);
197 octeon2_usb_clock_start_cnt--;
198 mutex_unlock(&octeon2_usb_clocks_mutex);
David Daney1643acc2010-10-08 14:47:52 -0700199}
200EXPORT_SYMBOL(octeon2_usb_clocks_stop);