1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 2003-2014 Broadcom Corporation
3*4882a593Smuzhiyun * All Rights Reserved
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * This software is available to you under a choice of one of two
6*4882a593Smuzhiyun * licenses. You may choose to be licensed under the terms of the GNU
7*4882a593Smuzhiyun * General Public License (GPL) Version 2, available from the file
8*4882a593Smuzhiyun * COPYING in the main directory of this source tree, or the Broadcom
9*4882a593Smuzhiyun * license below:
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * Redistribution and use in source and binary forms, with or without
12*4882a593Smuzhiyun * modification, are permitted provided that the following conditions
13*4882a593Smuzhiyun * are met:
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * 1. Redistributions of source code must retain the above copyright
16*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer.
17*4882a593Smuzhiyun * 2. Redistributions in binary form must reproduce the above copyright
18*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer in
19*4882a593Smuzhiyun * the documentation and/or other materials provided with the
20*4882a593Smuzhiyun * distribution.
21*4882a593Smuzhiyun *
22*4882a593Smuzhiyun * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
23*4882a593Smuzhiyun * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24*4882a593Smuzhiyun * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*4882a593Smuzhiyun * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
26*4882a593Smuzhiyun * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27*4882a593Smuzhiyun * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28*4882a593Smuzhiyun * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29*4882a593Smuzhiyun * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30*4882a593Smuzhiyun * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31*4882a593Smuzhiyun * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
32*4882a593Smuzhiyun * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*4882a593Smuzhiyun */
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #include <linux/dma-mapping.h>
36*4882a593Smuzhiyun #include <linux/kernel.h>
37*4882a593Smuzhiyun #include <linux/delay.h>
38*4882a593Smuzhiyun #include <linux/init.h>
39*4882a593Smuzhiyun #include <linux/pci.h>
40*4882a593Smuzhiyun #include <linux/irq.h>
41*4882a593Smuzhiyun #include <linux/bitops.h>
42*4882a593Smuzhiyun #include <linux/pci_ids.h>
43*4882a593Smuzhiyun #include <linux/nodemask.h>
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun #include <asm/cpu.h>
46*4882a593Smuzhiyun #include <asm/mipsregs.h>
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #include <asm/netlogic/common.h>
49*4882a593Smuzhiyun #include <asm/netlogic/haldefs.h>
50*4882a593Smuzhiyun #include <asm/netlogic/mips-extns.h>
51*4882a593Smuzhiyun #include <asm/netlogic/xlp-hal/xlp.h>
52*4882a593Smuzhiyun #include <asm/netlogic/xlp-hal/iomap.h>
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun #define SATA_CTL 0x0
55*4882a593Smuzhiyun #define SATA_STATUS 0x1 /* Status Reg */
56*4882a593Smuzhiyun #define SATA_INT 0x2 /* Interrupt Reg */
57*4882a593Smuzhiyun #define SATA_INT_MASK 0x3 /* Interrupt Mask Reg */
58*4882a593Smuzhiyun #define SATA_BIU_TIMEOUT 0x4
59*4882a593Smuzhiyun #define AXIWRSPERRLOG 0x5
60*4882a593Smuzhiyun #define AXIRDSPERRLOG 0x6
61*4882a593Smuzhiyun #define BiuTimeoutLow 0x7
62*4882a593Smuzhiyun #define BiuTimeoutHi 0x8
63*4882a593Smuzhiyun #define BiuSlvErLow 0x9
64*4882a593Smuzhiyun #define BiuSlvErHi 0xa
65*4882a593Smuzhiyun #define IO_CONFIG_SWAP_DIS 0xb
66*4882a593Smuzhiyun #define CR_REG_TIMER 0xc
67*4882a593Smuzhiyun #define CORE_ID 0xd
68*4882a593Smuzhiyun #define AXI_SLAVE_OPT1 0xe
69*4882a593Smuzhiyun #define PHY_MEM_ACCESS 0xf
70*4882a593Smuzhiyun #define PHY0_CNTRL 0x10
71*4882a593Smuzhiyun #define PHY0_STAT 0x11
72*4882a593Smuzhiyun #define PHY0_RX_ALIGN 0x12
73*4882a593Smuzhiyun #define PHY0_RX_EQ_LO 0x13
74*4882a593Smuzhiyun #define PHY0_RX_EQ_HI 0x14
75*4882a593Smuzhiyun #define PHY0_BIST_LOOP 0x15
76*4882a593Smuzhiyun #define PHY1_CNTRL 0x16
77*4882a593Smuzhiyun #define PHY1_STAT 0x17
78*4882a593Smuzhiyun #define PHY1_RX_ALIGN 0x18
79*4882a593Smuzhiyun #define PHY1_RX_EQ_LO 0x19
80*4882a593Smuzhiyun #define PHY1_RX_EQ_HI 0x1a
81*4882a593Smuzhiyun #define PHY1_BIST_LOOP 0x1b
82*4882a593Smuzhiyun #define RdExBase 0x1c
83*4882a593Smuzhiyun #define RdExLimit 0x1d
84*4882a593Smuzhiyun #define CacheAllocBase 0x1e
85*4882a593Smuzhiyun #define CacheAllocLimit 0x1f
86*4882a593Smuzhiyun #define BiuSlaveCmdGstNum 0x20
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun /*SATA_CTL Bits */
89*4882a593Smuzhiyun #define SATA_RST_N BIT(0) /* Active low reset sata_core phy */
90*4882a593Smuzhiyun #define SataCtlReserve0 BIT(1)
91*4882a593Smuzhiyun #define M_CSYSREQ BIT(2) /* AXI master low power, not used */
92*4882a593Smuzhiyun #define S_CSYSREQ BIT(3) /* AXI slave low power, not used */
93*4882a593Smuzhiyun #define P0_CP_DET BIT(8) /* Reserved, bring in from pad */
94*4882a593Smuzhiyun #define P0_MP_SW BIT(9) /* Mech Switch */
95*4882a593Smuzhiyun #define P0_DISABLE BIT(10) /* disable p0 */
96*4882a593Smuzhiyun #define P0_ACT_LED_EN BIT(11) /* Active LED enable */
97*4882a593Smuzhiyun #define P0_IRST_HARD_SYNTH BIT(12) /* PHY hard synth reset */
98*4882a593Smuzhiyun #define P0_IRST_HARD_TXRX BIT(13) /* PHY lane hard reset */
99*4882a593Smuzhiyun #define P0_IRST_POR BIT(14) /* PHY power on reset*/
100*4882a593Smuzhiyun #define P0_IPDTXL BIT(15) /* PHY Tx lane dis/power down */
101*4882a593Smuzhiyun #define P0_IPDRXL BIT(16) /* PHY Rx lane dis/power down */
102*4882a593Smuzhiyun #define P0_IPDIPDMSYNTH BIT(17) /* PHY synthesizer dis/porwer down */
103*4882a593Smuzhiyun #define P0_CP_POD_EN BIT(18) /* CP_POD enable */
104*4882a593Smuzhiyun #define P0_AT_BYPASS BIT(19) /* P0 address translation by pass */
105*4882a593Smuzhiyun #define P1_CP_DET BIT(20) /* Reserved,Cold Detect */
106*4882a593Smuzhiyun #define P1_MP_SW BIT(21) /* Mech Switch */
107*4882a593Smuzhiyun #define P1_DISABLE BIT(22) /* disable p1 */
108*4882a593Smuzhiyun #define P1_ACT_LED_EN BIT(23) /* Active LED enable */
109*4882a593Smuzhiyun #define P1_IRST_HARD_SYNTH BIT(24) /* PHY hard synth reset */
110*4882a593Smuzhiyun #define P1_IRST_HARD_TXRX BIT(25) /* PHY lane hard reset */
111*4882a593Smuzhiyun #define P1_IRST_POR BIT(26) /* PHY power on reset*/
112*4882a593Smuzhiyun #define P1_IPDTXL BIT(27) /* PHY Tx lane dis/porwer down */
113*4882a593Smuzhiyun #define P1_IPDRXL BIT(28) /* PHY Rx lane dis/porwer down */
114*4882a593Smuzhiyun #define P1_IPDIPDMSYNTH BIT(29) /* PHY synthesizer dis/porwer down */
115*4882a593Smuzhiyun #define P1_CP_POD_EN BIT(30)
116*4882a593Smuzhiyun #define P1_AT_BYPASS BIT(31) /* P1 address translation by pass */
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /* Status register */
119*4882a593Smuzhiyun #define M_CACTIVE BIT(0) /* m_cactive, not used */
120*4882a593Smuzhiyun #define S_CACTIVE BIT(1) /* s_cactive, not used */
121*4882a593Smuzhiyun #define P0_PHY_READY BIT(8) /* phy is ready */
122*4882a593Smuzhiyun #define P0_CP_POD BIT(9) /* Cold PowerOn */
123*4882a593Smuzhiyun #define P0_SLUMBER BIT(10) /* power mode slumber */
124*4882a593Smuzhiyun #define P0_PATIAL BIT(11) /* power mode patial */
125*4882a593Smuzhiyun #define P0_PHY_SIG_DET BIT(12) /* phy dignal detect */
126*4882a593Smuzhiyun #define P0_PHY_CALI BIT(13) /* phy calibration done */
127*4882a593Smuzhiyun #define P1_PHY_READY BIT(16) /* phy is ready */
128*4882a593Smuzhiyun #define P1_CP_POD BIT(17) /* Cold PowerOn */
129*4882a593Smuzhiyun #define P1_SLUMBER BIT(18) /* power mode slumber */
130*4882a593Smuzhiyun #define P1_PATIAL BIT(19) /* power mode patial */
131*4882a593Smuzhiyun #define P1_PHY_SIG_DET BIT(20) /* phy dignal detect */
132*4882a593Smuzhiyun #define P1_PHY_CALI BIT(21) /* phy calibration done */
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun /* SATA CR_REG_TIMER bits */
135*4882a593Smuzhiyun #define CR_TIME_SCALE (0x1000 << 0)
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun /* SATA PHY specific registers start and end address */
138*4882a593Smuzhiyun #define RXCDRCALFOSC0 0x0065
139*4882a593Smuzhiyun #define CALDUTY 0x006e
140*4882a593Smuzhiyun #define RXDPIF 0x8065
141*4882a593Smuzhiyun #define PPMDRIFTMAX_HI 0x80A4
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun #define nlm_read_sata_reg(b, r) nlm_read_reg(b, r)
144*4882a593Smuzhiyun #define nlm_write_sata_reg(b, r, v) nlm_write_reg(b, r, v)
145*4882a593Smuzhiyun #define nlm_get_sata_pcibase(node) \
146*4882a593Smuzhiyun nlm_pcicfg_base(XLP9XX_IO_SATA_OFFSET(node))
147*4882a593Smuzhiyun #define nlm_get_sata_regbase(node) \
148*4882a593Smuzhiyun (nlm_get_sata_pcibase(node) + 0x100)
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun /* SATA PHY config for register block 1 0x0065 .. 0x006e */
151*4882a593Smuzhiyun static const u8 sata_phy_config1[] = {
152*4882a593Smuzhiyun 0xC9, 0xC9, 0x07, 0x07, 0x18, 0x18, 0x01, 0x01, 0x22, 0x00
153*4882a593Smuzhiyun };
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun /* SATA PHY config for register block 2 0x8065 .. 0x80A4 */
156*4882a593Smuzhiyun static const u8 sata_phy_config2[] = {
157*4882a593Smuzhiyun 0xAA, 0x00, 0x4C, 0xC9, 0xC9, 0x07, 0x07, 0x18,
158*4882a593Smuzhiyun 0x18, 0x05, 0x0C, 0x10, 0x00, 0x10, 0x00, 0xFF,
159*4882a593Smuzhiyun 0xCF, 0xF7, 0xE1, 0xF5, 0xFD, 0xFD, 0xFF, 0xFF,
160*4882a593Smuzhiyun 0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5, 0xFD, 0xFD,
161*4882a593Smuzhiyun 0xF5, 0xF5, 0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5,
162*4882a593Smuzhiyun 0xFD, 0xFD, 0xF5, 0xF5, 0xFF, 0xFF, 0xFF, 0xF5,
163*4882a593Smuzhiyun 0x3F, 0x00, 0x32, 0x00, 0x03, 0x01, 0x05, 0x05,
164*4882a593Smuzhiyun 0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x04,
165*4882a593Smuzhiyun };
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun const int sata_phy_debug = 0; /* set to verify PHY writes */
168*4882a593Smuzhiyun
sata_clear_glue_reg(u64 regbase,u32 off,u32 bit)169*4882a593Smuzhiyun static void sata_clear_glue_reg(u64 regbase, u32 off, u32 bit)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun u32 reg_val;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun reg_val = nlm_read_sata_reg(regbase, off);
174*4882a593Smuzhiyun nlm_write_sata_reg(regbase, off, (reg_val & ~bit));
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
sata_set_glue_reg(u64 regbase,u32 off,u32 bit)177*4882a593Smuzhiyun static void sata_set_glue_reg(u64 regbase, u32 off, u32 bit)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun u32 reg_val;
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun reg_val = nlm_read_sata_reg(regbase, off);
182*4882a593Smuzhiyun nlm_write_sata_reg(regbase, off, (reg_val | bit));
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
write_phy_reg(u64 regbase,u32 addr,u32 physel,u8 data)185*4882a593Smuzhiyun static void write_phy_reg(u64 regbase, u32 addr, u32 physel, u8 data)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
188*4882a593Smuzhiyun (1u << 31) | (physel << 24) | (data << 16) | addr);
189*4882a593Smuzhiyun udelay(850);
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun
read_phy_reg(u64 regbase,u32 addr,u32 physel)192*4882a593Smuzhiyun static u8 read_phy_reg(u64 regbase, u32 addr, u32 physel)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun u32 val;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
197*4882a593Smuzhiyun (0 << 31) | (physel << 24) | (0 << 16) | addr);
198*4882a593Smuzhiyun udelay(850);
199*4882a593Smuzhiyun val = nlm_read_sata_reg(regbase, PHY_MEM_ACCESS);
200*4882a593Smuzhiyun return (val >> 16) & 0xff;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
config_sata_phy(u64 regbase)203*4882a593Smuzhiyun static void config_sata_phy(u64 regbase)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun u32 port, i, reg;
206*4882a593Smuzhiyun u8 val;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun for (port = 0; port < 2; port++) {
209*4882a593Smuzhiyun for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
210*4882a593Smuzhiyun write_phy_reg(regbase, reg, port, sata_phy_config1[i]);
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
213*4882a593Smuzhiyun write_phy_reg(regbase, reg, port, sata_phy_config2[i]);
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun /* Fix for PHY link up failures at lower temperatures */
216*4882a593Smuzhiyun write_phy_reg(regbase, 0x800F, port, 0x1f);
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun val = read_phy_reg(regbase, 0x0029, port);
219*4882a593Smuzhiyun write_phy_reg(regbase, 0x0029, port, val | (0x7 << 1));
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun val = read_phy_reg(regbase, 0x0056, port);
222*4882a593Smuzhiyun write_phy_reg(regbase, 0x0056, port, val & ~(1 << 3));
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun val = read_phy_reg(regbase, 0x0018, port);
225*4882a593Smuzhiyun write_phy_reg(regbase, 0x0018, port, val & ~(0x7 << 0));
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
check_phy_register(u64 regbase,u32 addr,u32 physel,u8 xdata)229*4882a593Smuzhiyun static void check_phy_register(u64 regbase, u32 addr, u32 physel, u8 xdata)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun u8 data;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun data = read_phy_reg(regbase, addr, physel);
234*4882a593Smuzhiyun pr_info("PHY read addr = 0x%x physel = %d data = 0x%x %s\n",
235*4882a593Smuzhiyun addr, physel, data, data == xdata ? "TRUE" : "FALSE");
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun
verify_sata_phy_config(u64 regbase)238*4882a593Smuzhiyun static void verify_sata_phy_config(u64 regbase)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun u32 port, i, reg;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun for (port = 0; port < 2; port++) {
243*4882a593Smuzhiyun for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
244*4882a593Smuzhiyun check_phy_register(regbase, reg, port,
245*4882a593Smuzhiyun sata_phy_config1[i]);
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
248*4882a593Smuzhiyun check_phy_register(regbase, reg, port,
249*4882a593Smuzhiyun sata_phy_config2[i]);
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun
nlm_sata_firmware_init(int node)253*4882a593Smuzhiyun static void nlm_sata_firmware_init(int node)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun u32 reg_val;
256*4882a593Smuzhiyun u64 regbase;
257*4882a593Smuzhiyun int n;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun pr_info("Initializing XLP9XX On-chip AHCI...\n");
260*4882a593Smuzhiyun regbase = nlm_get_sata_regbase(node);
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun /* Reset port0 */
263*4882a593Smuzhiyun sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
264*4882a593Smuzhiyun sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
265*4882a593Smuzhiyun sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
266*4882a593Smuzhiyun sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
267*4882a593Smuzhiyun sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
268*4882a593Smuzhiyun sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun /* port1 */
271*4882a593Smuzhiyun sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
272*4882a593Smuzhiyun sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
273*4882a593Smuzhiyun sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
274*4882a593Smuzhiyun sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
275*4882a593Smuzhiyun sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
276*4882a593Smuzhiyun sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
277*4882a593Smuzhiyun udelay(300);
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun /* Set PHY */
280*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
281*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
282*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
283*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
284*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
285*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun udelay(1000);
288*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
289*4882a593Smuzhiyun udelay(1000);
290*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
291*4882a593Smuzhiyun udelay(1000);
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun /* setup PHY */
294*4882a593Smuzhiyun config_sata_phy(regbase);
295*4882a593Smuzhiyun if (sata_phy_debug)
296*4882a593Smuzhiyun verify_sata_phy_config(regbase);
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun udelay(1000);
299*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
300*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
301*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
302*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
303*4882a593Smuzhiyun udelay(300);
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun /* Override reset in serial PHY mode */
306*4882a593Smuzhiyun sata_set_glue_reg(regbase, CR_REG_TIMER, CR_TIME_SCALE);
307*4882a593Smuzhiyun /* Set reset SATA */
308*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_CTL, SATA_RST_N);
309*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_CTL, M_CSYSREQ);
310*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_CTL, S_CSYSREQ);
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun pr_debug("Waiting for PHYs to come up.\n");
313*4882a593Smuzhiyun n = 10000;
314*4882a593Smuzhiyun do {
315*4882a593Smuzhiyun reg_val = nlm_read_sata_reg(regbase, SATA_STATUS);
316*4882a593Smuzhiyun if ((reg_val & P1_PHY_READY) && (reg_val & P0_PHY_READY))
317*4882a593Smuzhiyun break;
318*4882a593Smuzhiyun udelay(10);
319*4882a593Smuzhiyun } while (--n > 0);
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun if (reg_val & P0_PHY_READY)
322*4882a593Smuzhiyun pr_info("PHY0 is up.\n");
323*4882a593Smuzhiyun else
324*4882a593Smuzhiyun pr_info("PHY0 is down.\n");
325*4882a593Smuzhiyun if (reg_val & P1_PHY_READY)
326*4882a593Smuzhiyun pr_info("PHY1 is up.\n");
327*4882a593Smuzhiyun else
328*4882a593Smuzhiyun pr_info("PHY1 is down.\n");
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun pr_info("XLP AHCI Init Done.\n");
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
nlm_ahci_init(void)333*4882a593Smuzhiyun static int __init nlm_ahci_init(void)
334*4882a593Smuzhiyun {
335*4882a593Smuzhiyun int node;
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun if (!cpu_is_xlp9xx())
338*4882a593Smuzhiyun return 0;
339*4882a593Smuzhiyun for (node = 0; node < NLM_NR_NODES; node++)
340*4882a593Smuzhiyun if (nlm_node_present(node))
341*4882a593Smuzhiyun nlm_sata_firmware_init(node);
342*4882a593Smuzhiyun return 0;
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun
nlm_sata_intr_ack(struct irq_data * data)345*4882a593Smuzhiyun static void nlm_sata_intr_ack(struct irq_data *data)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun u64 regbase;
348*4882a593Smuzhiyun u32 val;
349*4882a593Smuzhiyun int node;
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun node = data->irq / NLM_IRQS_PER_NODE;
352*4882a593Smuzhiyun regbase = nlm_get_sata_regbase(node);
353*4882a593Smuzhiyun val = nlm_read_sata_reg(regbase, SATA_INT);
354*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_INT, val);
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun
nlm_sata_fixup_bar(struct pci_dev * dev)357*4882a593Smuzhiyun static void nlm_sata_fixup_bar(struct pci_dev *dev)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun dev->resource[5] = dev->resource[0];
360*4882a593Smuzhiyun memset(&dev->resource[0], 0, sizeof(dev->resource[0]));
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun
nlm_sata_fixup_final(struct pci_dev * dev)363*4882a593Smuzhiyun static void nlm_sata_fixup_final(struct pci_dev *dev)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun u32 val;
366*4882a593Smuzhiyun u64 regbase;
367*4882a593Smuzhiyun int node;
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun /* Find end bridge function to find node */
370*4882a593Smuzhiyun node = xlp_socdev_to_node(dev);
371*4882a593Smuzhiyun regbase = nlm_get_sata_regbase(node);
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun /* clear pending interrupts and then enable them */
374*4882a593Smuzhiyun val = nlm_read_sata_reg(regbase, SATA_INT);
375*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_INT, val);
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun /* Enable only the core interrupt */
378*4882a593Smuzhiyun sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1);
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun dev->irq = nlm_irq_to_xirq(node, PIC_SATA_IRQ);
381*4882a593Smuzhiyun nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack);
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun arch_initcall(nlm_ahci_init);
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
387*4882a593Smuzhiyun nlm_sata_fixup_bar);
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
390*4882a593Smuzhiyun nlm_sata_fixup_final);
391