Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.38-rc8 185 lines 4.6 kB view raw
1/* 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 * 6 * Copyright (C) 2010 Cavium Networks 7 */ 8 9#include <linux/module.h> 10#include <linux/delay.h> 11 12#include <asm/atomic.h> 13 14#include <asm/octeon/octeon.h> 15#include <asm/octeon/cvmx-uctlx-defs.h> 16 17static atomic_t octeon2_usb_clock_start_cnt = ATOMIC_INIT(0); 18 19void octeon2_usb_clocks_start(void) 20{ 21 u64 div; 22 union cvmx_uctlx_if_ena if_ena; 23 union cvmx_uctlx_clk_rst_ctl clk_rst_ctl; 24 union cvmx_uctlx_uphy_ctl_status uphy_ctl_status; 25 union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status; 26 int i; 27 unsigned long io_clk_64_to_ns; 28 29 if (atomic_inc_return(&octeon2_usb_clock_start_cnt) != 1) 30 return; 31 32 io_clk_64_to_ns = 64000000000ull / octeon_get_io_clock_rate(); 33 34 /* 35 * Step 1: Wait for voltages stable. That surely happened 36 * before starting the kernel. 37 * 38 * Step 2: Enable SCLK of UCTL by writing UCTL0_IF_ENA[EN] = 1 39 */ 40 if_ena.u64 = 0; 41 if_ena.s.en = 1; 42 cvmx_write_csr(CVMX_UCTLX_IF_ENA(0), if_ena.u64); 43 44 /* Step 3: Configure the reference clock, PHY, and HCLK */ 45 clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0)); 46 /* 3a */ 47 clk_rst_ctl.s.p_por = 1; 48 clk_rst_ctl.s.hrst = 0; 49 clk_rst_ctl.s.p_prst = 0; 50 clk_rst_ctl.s.h_clkdiv_rst = 0; 51 clk_rst_ctl.s.o_clkdiv_rst = 0; 52 clk_rst_ctl.s.h_clkdiv_en = 0; 53 clk_rst_ctl.s.o_clkdiv_en = 0; 54 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); 55 56 /* 3b */ 57 /* 12MHz crystal. */ 58 clk_rst_ctl.s.p_refclk_sel = 0; 59 clk_rst_ctl.s.p_refclk_div = 0; 60 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); 61 62 /* 3c */ 63 div = octeon_get_io_clock_rate() / 130000000ull; 64 65 switch (div) { 66 case 0: 67 div = 1; 68 break; 69 case 1: 70 case 2: 71 case 3: 72 case 4: 73 break; 74 case 5: 75 div = 4; 76 break; 77 case 6: 78 case 7: 79 div = 6; 80 break; 81 case 8: 82 case 9: 83 case 10: 84 case 11: 85 div = 8; 86 break; 87 default: 88 div = 12; 89 break; 90 } 91 clk_rst_ctl.s.h_div = div; 92 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); 93 /* Read it back, */ 94 clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0)); 95 clk_rst_ctl.s.h_clkdiv_en = 1; 96 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); 97 /* 3d */ 98 clk_rst_ctl.s.h_clkdiv_rst = 1; 99 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); 100 101 /* 3e: delay 64 io clocks */ 102 ndelay(io_clk_64_to_ns); 103 104 /* 105 * Step 4: Program the power-on reset field in the UCTL 106 * clock-reset-control register. 107 */ 108 clk_rst_ctl.s.p_por = 0; 109 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); 110 111 /* Step 5: Wait 1 ms for the PHY clock to start. */ 112 mdelay(1); 113 114 /* 115 * Step 6: Program the reset input from automatic test 116 * equipment field in the UPHY CSR 117 */ 118 uphy_ctl_status.u64 = cvmx_read_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0)); 119 uphy_ctl_status.s.ate_reset = 1; 120 cvmx_write_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0), uphy_ctl_status.u64); 121 122 /* Step 7: Wait for at least 10ns. */ 123 ndelay(10); 124 125 /* Step 8: Clear the ATE_RESET field in the UPHY CSR. */ 126 uphy_ctl_status.s.ate_reset = 0; 127 cvmx_write_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0), uphy_ctl_status.u64); 128 129 /* 130 * Step 9: Wait for at least 20ns for UPHY to output PHY clock 131 * signals and OHCI_CLK48 132 */ 133 ndelay(20); 134 135 /* Step 10: Configure the OHCI_CLK48 and OHCI_CLK12 clocks. */ 136 /* 10a */ 137 clk_rst_ctl.s.o_clkdiv_rst = 1; 138 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); 139 140 /* 10b */ 141 clk_rst_ctl.s.o_clkdiv_en = 1; 142 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); 143 144 /* 10c */ 145 ndelay(io_clk_64_to_ns); 146 147 /* 148 * Step 11: Program the PHY reset field: 149 * UCTL0_CLK_RST_CTL[P_PRST] = 1 150 */ 151 clk_rst_ctl.s.p_prst = 1; 152 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); 153 154 /* Step 12: Wait 1 uS. */ 155 udelay(1); 156 157 /* Step 13: Program the HRESET_N field: UCTL0_CLK_RST_CTL[HRST] = 1 */ 158 clk_rst_ctl.s.hrst = 1; 159 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); 160 161 /* Now we can set some other registers. */ 162 163 for (i = 0; i <= 1; i++) { 164 port_ctl_status.u64 = 165 cvmx_read_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0)); 166 /* Set txvreftune to 15 to obtain complient 'eye' diagram. */ 167 port_ctl_status.s.txvreftune = 15; 168 cvmx_write_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0), 169 port_ctl_status.u64); 170 } 171} 172EXPORT_SYMBOL(octeon2_usb_clocks_start); 173 174void octeon2_usb_clocks_stop(void) 175{ 176 union cvmx_uctlx_if_ena if_ena; 177 178 if (atomic_dec_return(&octeon2_usb_clock_start_cnt) != 0) 179 return; 180 181 if_ena.u64 = 0; 182 if_ena.s.en = 0; 183 cvmx_write_csr(CVMX_UCTLX_IF_ENA(0), if_ena.u64); 184} 185EXPORT_SYMBOL(octeon2_usb_clocks_stop);