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
6 * Copyright (C) 2010, 2011 Cavium Networks
9 #include <linux/module.h>
10 #include <linux/mutex.h>
11 #include <linux/delay.h>
13 #include <asm/octeon/octeon.h>
14 #include <asm/octeon/cvmx-uctlx-defs.h>
16 static DEFINE_MUTEX(octeon2_usb_clocks_mutex
);
18 static int octeon2_usb_clock_start_cnt
;
20 void octeon2_usb_clocks_start(void)
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
;
28 unsigned long io_clk_64_to_ns
;
31 mutex_lock(&octeon2_usb_clocks_mutex
);
33 octeon2_usb_clock_start_cnt
++;
34 if (octeon2_usb_clock_start_cnt
!= 1)
37 io_clk_64_to_ns
= 64000000000ull / octeon_get_io_clock_rate();
40 * Step 1: Wait for voltages stable. That surely happened
41 * before starting the kernel.
43 * Step 2: Enable SCLK of UCTL by writing UCTL0_IF_ENA[EN] = 1
47 cvmx_write_csr(CVMX_UCTLX_IF_ENA(0), if_ena
.u64
);
49 /* Step 3: Configure the reference clock, PHY, and HCLK */
50 clk_rst_ctl
.u64
= cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
53 * If the UCTL looks like it has already been started, skip
54 * the initialization, otherwise bus errors are obtained.
56 if (clk_rst_ctl
.s
.hrst
)
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
);
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
);
75 div
= octeon_get_io_clock_rate() / 130000000ull;
103 clk_rst_ctl
.s
.h_div
= div
;
104 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl
.u64
);
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
);
110 clk_rst_ctl
.s
.h_clkdiv_rst
= 1;
111 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl
.u64
);
113 /* 3e: delay 64 io clocks */
114 ndelay(io_clk_64_to_ns
);
117 * Step 4: Program the power-on reset field in the UCTL
118 * clock-reset-control register.
120 clk_rst_ctl
.s
.p_por
= 0;
121 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl
.u64
);
123 /* Step 5: Wait 1 ms for the PHY clock to start. */
127 * Step 6: Program the reset input from automatic test
128 * equipment field in the UPHY CSR
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
);
134 /* Step 7: Wait for at least 10ns. */
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
);
142 * Step 9: Wait for at least 20ns for UPHY to output PHY clock
143 * signals and OHCI_CLK48
147 /* Step 10: Configure the OHCI_CLK48 and OHCI_CLK12 clocks. */
149 clk_rst_ctl
.s
.o_clkdiv_rst
= 1;
150 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl
.u64
);
153 clk_rst_ctl
.s
.o_clkdiv_en
= 1;
154 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl
.u64
);
157 ndelay(io_clk_64_to_ns
);
160 * Step 11: Program the PHY reset field:
161 * UCTL0_CLK_RST_CTL[P_PRST] = 1
163 clk_rst_ctl
.s
.p_prst
= 1;
164 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl
.u64
);
166 /* Step 12: Wait 1 uS. */
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
);
174 /* Now we can set some other registers. */
176 for (i
= 0; i
<= 1; i
++) {
177 port_ctl_status
.u64
=
178 cvmx_read_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i
, 0));
179 /* Set txvreftune to 15 to obtain compliant 'eye' diagram. */
180 port_ctl_status
.s
.txvreftune
= 15;
181 port_ctl_status
.s
.txrisetune
= 1;
182 port_ctl_status
.s
.txpreemphasistune
= 1;
183 cvmx_write_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i
, 0),
184 port_ctl_status
.u64
);
187 /* Set uSOF cycle period to 60,000 bits. */
188 cvmx_write_csr(CVMX_UCTLX_EHCI_FLA(0), 0x20ull
);
190 mutex_unlock(&octeon2_usb_clocks_mutex
);
192 EXPORT_SYMBOL(octeon2_usb_clocks_start
);
194 void octeon2_usb_clocks_stop(void)
196 mutex_lock(&octeon2_usb_clocks_mutex
);
197 octeon2_usb_clock_start_cnt
--;
198 mutex_unlock(&octeon2_usb_clocks_mutex
);
200 EXPORT_SYMBOL(octeon2_usb_clocks_stop
);