1 /*****************************************************************************/
\r
3 ** /brief PCI support for AP91/93 board
\r
5 ** This provides the support code required for PCI support on the AP91/93
\r
6 ** board in the U-Boot environment. This board is a Python based system
\r
7 ** with a Merlin WLAN interface. This file also contains the support
\r
8 ** for initialization of the Merlin radios on the PCi bus, required for
\r
9 ** pre-configuration for use by Linux.
\r
11 ** Copyright (c) 2008 Atheros Communications Inc. All rights reserved.
\r
16 #include <command.h>
\r
17 #include <asm/mipsregs.h>
\r
18 #include <asm/addrspace.h>
\r
20 #include <version.h>
\r
22 #include "ar7240_soc.h"
\r
25 ** PCI controller "hose" value
\r
27 static int ar7240_local_write_config(int where, int size, uint32_t value){
\r
28 ar7240_reg_wr((AR7240_PCI_CRP + where),value);
\r
33 ** We will use the ART configuration information stored in flash to initialize
\r
34 ** these devices as required.
\r
37 // TODO: calibration data doesn't exist?
\r
39 void plat_dev_init(void){
\r
42 u32 BaseAddr = 0x10000000;
\r
43 u32 CalAddr = WLANCAL;
\r
44 volatile u16 *calData;
\r
45 calData = (u16 *)CalAddr;
\r
47 if(calData[0] != 0xa55a && calData[0] != 0x5aa5){
\r
48 printf("BOARD IS NOT CALIBRATED!!!\n");
\r
54 /******************************************************************************/
\r
56 ** \brief pci host initialization
\r
58 ** Sets up the PCI controller on the host. For AR7240 this may not be necessary,
\r
59 ** but this function is required for board support.
\r
61 ** We want a 1:1 mapping between PCI and DDR for inbound and outbound.
\r
62 ** The PCI<---AHB decoding works as follows:
\r
64 ** 8 registers in the DDR unit provide software configurable 32 bit offsets
\r
65 ** for each of the eight 16MB PCI windows in the 128MB. The offsets will be
\r
66 ** added to any address in the 16MB segment before being sent to the PCI unit.
\r
68 ** Essentially for any AHB address generated by the CPU,
\r
69 ** 1. the MSB four bits are stripped off, [31:28],
\r
70 ** 2. Bit 27 is used to decide between the lower 128Mb (PCI) or the rest of
\r
72 ** 3. Bits 26:24 are used to access one of the 8 window registers and are
\r
74 ** 4. If it is a PCI address, then the WINDOW offset in the WINDOW register
\r
75 ** corresponding to the next 3 bits (bit 26:24) is ADDED to the address,
\r
76 ** to generate the address to PCI unit.
\r
78 ** eg. CPU address = 0x100000ff
\r
79 ** window 0 offset = 0x10000000
\r
80 ** This points to lowermost 16MB window in PCI space.
\r
81 ** So the resulting address would be 0x000000ff+0x10000000
\r
84 ** eg2. CPU address = 0x120000ff
\r
85 ** WINDOW 2 offset = 0x12000000
\r
86 ** resulting address would be 0x000000ff+0x12000000
\r
89 ** There is no translation for inbound access (PCI device as a master)
\r
95 static int ar7240_pcibios_init(void){
\r
100 if(((ar7240_reg_rd(AR7240_PCI_LCL_RESET)) & 0x1) == 0x0){
\r
101 printf("***** Warning *****: PCIe WLAN H/W not found !!!\n");
\r
109 #define pci_udelay(n) do { uint32_t i; for(i = 0; i < ((n)/10); i++) udelay(10); } while(0)
\r
111 int pci_init_board(void){
\r
112 uint32_t cmd = 0, reg_val;
\r
114 reg_val = ar7240_reg_rd(0xb804006c);
\r
115 ar7240_reg_wr(0xb804006c, reg_val | 2);
\r
117 ar7240_reg_wr(0xb804000c, 1 << 2);
\r
119 pci_udelay(100000);
\r
122 if((ar7240_reg_rd(WASP_BOOTSTRAP_REG) & WASP_REF_CLK_25) == 0){
\r
123 ar7240_reg_wr_nf(AR934X_PCIE_PLL_DITHER_DIV_MAX,
\r
124 PCIE_PLL_DITHER_DIV_MAX_EN_DITHER_SET(0) |
\r
125 PCIE_PLL_DITHER_DIV_MAX_USE_MAX_SET(1) |
\r
126 PCIE_PLL_DITHER_DIV_MAX_DIV_MAX_INT_SET(0x20) |
\r
127 PCIE_PLL_DITHER_DIV_MAX_DIV_MAX_FRAC_SET(0)
\r
130 printf("%s: PCIe PLL not set for 40MHz refclk\n", __func__);
\r
134 ar7240_reg_rmw_set(AR7240_RESET, AR7240_RESET_PCIE); // core in reset
\r
137 ar7240_reg_rmw_set(AR7240_RESET, AR7240_RESET_PCIE_PHY);// phy in reset
\r
140 ar7240_reg_rmw_clear(RST_MISC2_ADDRESS, RST_MISC2_PERSTN_RCPHY_SET(1)); // pci phy analog in reset
\r
143 ar7240_reg_wr(0x180f0000, 0x1ffc0); // ltssm is disabled
\r
146 ar7240_reg_wr_nf(AR7240_PCI_LCL_RESET, 0); // End point in reset
\r
147 pci_udelay(100000);
\r
149 //ar7240_reg_rmw_clear(AR7240_RESET, AR7240_RESET_PCIE_PHY);
\r
152 if((ar7240_reg_rd(AR7240_REV_ID) & 0xf) == 0){
\r
153 ar7240_reg_wr_nf(AR934X_PCIE_PLL_CONFIG,
\r
154 PCIE_PLL_CONFIG_REFDIV_SET(1) |
\r
155 PCIE_PLL_CONFIG_BYPASS_SET(1) |
\r
156 PCIE_PLL_CONFIG_PLLPWD_SET(1)
\r
160 ar7240_reg_wr_nf(AR934X_PCIE_PLL_CONFIG,
\r
161 PCIE_PLL_CONFIG_REFDIV_SET(1) |
\r
162 PCIE_PLL_CONFIG_BYPASS_SET(1) |
\r
163 PCIE_PLL_CONFIG_PLLPWD_SET(0)
\r
167 ar7240_reg_wr_nf(AR934X_PCIE_PLL_CONFIG,
\r
168 ar7240_reg_rd(AR934X_PCIE_PLL_CONFIG) &
\r
169 (~PCIE_PLL_CONFIG_BYPASS_SET(1))
\r
174 ar7240_reg_wr_nf(0xb8116c04, (0x0 << 30) | (0x4 << 26) | (0x32 << 19) | (1 << 16) | (3 << 13) | (0x1e << 7));
\r
177 ar7240_reg_wr_nf(0xb8116c08, (6 << 23));
\r
180 ar7240_reg_wr_nf(0xb8050010, 0x40010800);
\r
183 ar7240_reg_wr_nf(0xb8050014, 0xc013fffe);
\r
186 ar7240_reg_wr_nf(0xb8050018, 0x00138000);
\r
189 ar7240_reg_wr_nf(0xb8050010, 0x00010800);
\r
190 pci_udelay(100000);
\r
192 ar7240_reg_wr_nf(0xb8050010, 0x00000800);
\r
198 ar7240_reg_rmw_set(RST_MISC2_ADDRESS, RST_MISC2_PERSTN_RCPHY_SET(1)); // pci phy analog out of reset
\r
201 ar7240_reg_rmw_clear(AR7240_RESET, AR7240_RESET_PCIE_PHY); // phy out of reset
\r
204 ar7240_reg_rmw_clear(AR7240_RESET, AR7240_RESET_PCIE); // core out of reset
\r
207 cmd = PCI_COMMAND_MEMORY |
\r
208 PCI_COMMAND_MASTER |
\r
209 PCI_COMMAND_INVALIDATE |
\r
210 PCI_COMMAND_PARITY |
\r
212 PCI_COMMAND_FAST_BACK;
\r
214 ar7240_local_write_config(PCI_COMMAND, 4, cmd); // pci cmd reg init
\r
215 ar7240_local_write_config(0x20, 4, 0x1ff01000); // membase setting
\r
216 ar7240_local_write_config(0x24, 4, 0x1ff01000); // prefetch membase setting
\r
218 //if((is_ar7241() || is_ar7242() || is_wasp())){
\r
219 ar7240_reg_wr(0x180f0000, 0x1ffc1); // ltssm enable
\r
221 // ar7240_reg_wr(0x180f0000, 0x1);
\r
223 pci_udelay(100000);
\r
225 ar7240_reg_wr_nf(AR7240_PCI_LCL_RESET, 4); // EP out of reset
\r
226 //pci_udelay(100000);
\r
229 * Delay increased from 100 to 1000, so as to
\r
230 * get the correct status from PCI LCL RESET register
\r
232 // pci_udelay(100000);
\r
235 * Check if the WLAN PCI-E H/W is present, If the
\r
236 * WLAN H/W is not present, skip the PCI platform
\r
237 * initialization code and return
\r
239 //if(((ar7240_reg_rd(AR7240_PCI_LCL_RESET)) & 0x1) == 0x0){
\r
240 // printf("## Error: PCIe WLAN Module not found!\n");
\r