Commit | Line | Data |
---|---|---|
a9533e7e HP |
1 | /* |
2 | * Copyright (c) 2010 Broadcom Corporation | |
3 | * | |
4 | * Permission to use, copy, modify, and/or distribute this software for any | |
5 | * purpose with or without fee is hereby granted, provided that the above | |
6 | * copyright notice and this permission notice appear in all copies. | |
7 | * | |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | |
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | |
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 | */ | |
16 | ||
01d11441 | 17 | #include <linux/delay.h> |
3327989a | 18 | #include <linux/string.h> |
c6ac24e9 | 19 | #include <linux/pci.h> |
cc3cea5a RV |
20 | #include <defs.h> |
21 | #include "types.h" | |
f97e956a | 22 | #include <brcmu_utils.h> |
b21c892d | 23 | #include <aiutils.h> |
cc3cea5a RV |
24 | #include <soc.h> |
25 | #include <brcm_hw_ids.h> | |
745c9e6e | 26 | #include <chipcommon.h> |
cc3cea5a RV |
27 | #include <scb.h> |
28 | #include <pub.h> | |
a9533e7e | 29 | #include <nicpci.h> |
a9533e7e | 30 | |
fd24b0fd AS |
31 | /* SPROM offsets */ |
32 | #define SRSH_ASPM_OFFSET 4 /* word 4 */ | |
33 | #define SRSH_ASPM_ENB 0x18 /* bit 3, 4 */ | |
34 | #define SRSH_ASPM_L1_ENB 0x10 /* bit 4 */ | |
35 | #define SRSH_ASPM_L0s_ENB 0x8 /* bit 3 */ | |
36 | ||
37 | #define SRSH_PCIE_MISC_CONFIG 5 /* word 5 */ | |
38 | #define SRSH_L23READY_EXIT_NOPERST 0x8000 /* bit 15 */ | |
39 | #define SRSH_CLKREQ_OFFSET_REV5 20 /* word 20 for srom rev <= 5 */ | |
40 | #define SRSH_CLKREQ_ENB 0x0800 /* bit 11 */ | |
41 | #define SRSH_BD_OFFSET 6 /* word 6 */ | |
42 | ||
b6fe70c3 RV |
43 | /* chipcontrol */ |
44 | #define CHIPCTRL_4321_PLL_DOWN 0x800000 /* serdes PLL down override */ | |
45 | ||
fd24b0fd AS |
46 | /* MDIO control */ |
47 | #define MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */ | |
48 | #define MDIOCTL_DIVISOR_VAL 0x2 | |
49 | #define MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */ | |
50 | #define MDIOCTL_ACCESS_DONE 0x100 /* Tranaction complete */ | |
51 | ||
52 | /* MDIO Data */ | |
53 | #define MDIODATA_MASK 0x0000ffff /* data 2 bytes */ | |
54 | #define MDIODATA_TA 0x00020000 /* Turnaround */ | |
55 | #define MDIODATA_REGADDR_SHF_OLD 18 /* Regaddr shift (rev < 10) */ | |
56 | #define MDIODATA_REGADDR_MASK_OLD 0x003c0000 /* Regaddr Mask (rev < 10) */ | |
57 | #define MDIODATA_DEVADDR_SHF_OLD 22 /* Physmedia devaddr shift (rev < 10) */ | |
58 | #define MDIODATA_DEVADDR_MASK_OLD 0x0fc00000 /* Physmedia devaddr Mask (rev < 10) */ | |
59 | #define MDIODATA_REGADDR_SHF 18 /* Regaddr shift */ | |
60 | #define MDIODATA_REGADDR_MASK 0x007c0000 /* Regaddr Mask */ | |
61 | #define MDIODATA_DEVADDR_SHF 23 /* Physmedia devaddr shift */ | |
62 | #define MDIODATA_DEVADDR_MASK 0x0f800000 /* Physmedia devaddr Mask */ | |
63 | #define MDIODATA_WRITE 0x10000000 /* write Transaction */ | |
64 | #define MDIODATA_READ 0x20000000 /* Read Transaction */ | |
65 | #define MDIODATA_START 0x40000000 /* start of Transaction */ | |
66 | ||
67 | #define MDIODATA_DEV_ADDR 0x0 /* dev address for serdes */ | |
68 | #define MDIODATA_BLK_ADDR 0x1F /* blk address for serdes */ | |
69 | ||
70 | /* serdes regs (rev < 10) */ | |
71 | #define MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */ | |
72 | #define MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */ | |
73 | #define MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */ | |
74 | ||
75 | /* SERDES RX registers */ | |
76 | #define SERDES_RX_CTRL 1 /* Rx cntrl */ | |
77 | #define SERDES_RX_TIMER1 2 /* Rx Timer1 */ | |
78 | #define SERDES_RX_CDR 6 /* CDR */ | |
79 | #define SERDES_RX_CDRBW 7 /* CDR BW */ | |
80 | /* SERDES RX control register */ | |
81 | #define SERDES_RX_CTRL_FORCE 0x80 /* rxpolarity_force */ | |
82 | #define SERDES_RX_CTRL_POLARITY 0x40 /* rxpolarity_value */ | |
83 | ||
84 | /* SERDES PLL registers */ | |
85 | #define SERDES_PLL_CTRL 1 /* PLL control reg */ | |
86 | #define PLL_CTRL_FREQDET_EN 0x4000 /* bit 14 is FREQDET on */ | |
87 | ||
88 | /* Linkcontrol reg offset in PCIE Cap */ | |
89 | #define PCIE_CAP_LINKCTRL_OFFSET 16 /* linkctrl offset in pcie cap */ | |
90 | #define PCIE_CAP_LCREG_ASPML0s 0x01 /* ASPM L0s in linkctrl */ | |
91 | #define PCIE_CAP_LCREG_ASPML1 0x02 /* ASPM L1 in linkctrl */ | |
92 | #define PCIE_CLKREQ_ENAB 0x100 /* CLKREQ Enab in linkctrl */ | |
93 | ||
94 | #define PCIE_ASPM_ENAB 3 /* ASPM L0s & L1 in linkctrl */ | |
95 | #define PCIE_ASPM_L1_ENAB 2 /* ASPM L0s & L1 in linkctrl */ | |
96 | #define PCIE_ASPM_L0s_ENAB 1 /* ASPM L0s & L1 in linkctrl */ | |
97 | #define PCIE_ASPM_DISAB 0 /* ASPM L0s & L1 in linkctrl */ | |
98 | ||
99 | /* Power management threshold */ | |
100 | #define PCIE_L1THRESHOLDTIME_MASK 0xFF00 /* bits 8 - 15 */ | |
101 | #define PCIE_L1THRESHOLDTIME_SHIFT 8 /* PCIE_L1THRESHOLDTIME_SHIFT */ | |
102 | #define PCIE_L1THRESHOLD_WARVAL 0x72 /* WAR value */ | |
103 | #define PCIE_ASPMTIMER_EXTEND 0x01000000 /* > rev7: enable extend ASPM timer */ | |
104 | ||
105 | /* different register spaces to access thr'u pcie indirect access */ | |
106 | #define PCIE_CONFIGREGS 1 /* Access to config space */ | |
107 | #define PCIE_PCIEREGS 2 /* Access to pcie registers */ | |
108 | ||
109 | /* PCIE protocol PHY diagnostic registers */ | |
110 | #define PCIE_PLP_STATUSREG 0x204 /* Status */ | |
111 | ||
112 | /* Status reg PCIE_PLP_STATUSREG */ | |
113 | #define PCIE_PLP_POLARITYINV_STAT 0x10 | |
114 | ||
115 | /* PCIE protocol DLLP diagnostic registers */ | |
116 | #define PCIE_DLLP_LCREG 0x100 /* Link Control */ | |
117 | #define PCIE_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold */ | |
118 | ||
119 | /* PCIE protocol TLP diagnostic registers */ | |
120 | #define PCIE_TLP_WORKAROUNDSREG 0x004 /* TLP Workarounds */ | |
121 | ||
fd24b0fd AS |
122 | /* Sonics side: PCI core and host control registers */ |
123 | struct sbpciregs { | |
124 | u32 control; /* PCI control */ | |
125 | u32 PAD[3]; | |
126 | u32 arbcontrol; /* PCI arbiter control */ | |
127 | u32 clkrun; /* Clkrun Control (>=rev11) */ | |
128 | u32 PAD[2]; | |
129 | u32 intstatus; /* Interrupt status */ | |
130 | u32 intmask; /* Interrupt mask */ | |
131 | u32 sbtopcimailbox; /* Sonics to PCI mailbox */ | |
132 | u32 PAD[9]; | |
133 | u32 bcastaddr; /* Sonics broadcast address */ | |
134 | u32 bcastdata; /* Sonics broadcast data */ | |
135 | u32 PAD[2]; | |
136 | u32 gpioin; /* ro: gpio input (>=rev2) */ | |
137 | u32 gpioout; /* rw: gpio output (>=rev2) */ | |
138 | u32 gpioouten; /* rw: gpio output enable (>= rev2) */ | |
139 | u32 gpiocontrol; /* rw: gpio control (>= rev2) */ | |
140 | u32 PAD[36]; | |
141 | u32 sbtopci0; /* Sonics to PCI translation 0 */ | |
142 | u32 sbtopci1; /* Sonics to PCI translation 1 */ | |
143 | u32 sbtopci2; /* Sonics to PCI translation 2 */ | |
144 | u32 PAD[189]; | |
145 | u32 pcicfg[4][64]; /* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */ | |
146 | u16 sprom[36]; /* SPROM shadow Area */ | |
147 | u32 PAD[46]; | |
148 | }; | |
149 | ||
150 | /* SB side: PCIE core and host control registers */ | |
151 | typedef struct sbpcieregs { | |
152 | u32 control; /* host mode only */ | |
153 | u32 PAD[2]; | |
154 | u32 biststatus; /* bist Status: 0x00C */ | |
155 | u32 gpiosel; /* PCIE gpio sel: 0x010 */ | |
156 | u32 gpioouten; /* PCIE gpio outen: 0x14 */ | |
157 | u32 PAD[2]; | |
158 | u32 intstatus; /* Interrupt status: 0x20 */ | |
159 | u32 intmask; /* Interrupt mask: 0x24 */ | |
160 | u32 sbtopcimailbox; /* sb to pcie mailbox: 0x028 */ | |
161 | u32 PAD[53]; | |
162 | u32 sbtopcie0; /* sb to pcie translation 0: 0x100 */ | |
163 | u32 sbtopcie1; /* sb to pcie translation 1: 0x104 */ | |
164 | u32 sbtopcie2; /* sb to pcie translation 2: 0x108 */ | |
165 | u32 PAD[5]; | |
166 | ||
167 | /* pcie core supports in direct access to config space */ | |
168 | u32 configaddr; /* pcie config space access: Address field: 0x120 */ | |
169 | u32 configdata; /* pcie config space access: Data field: 0x124 */ | |
170 | ||
171 | /* mdio access to serdes */ | |
172 | u32 mdiocontrol; /* controls the mdio access: 0x128 */ | |
173 | u32 mdiodata; /* Data to the mdio access: 0x12c */ | |
174 | ||
175 | /* pcie protocol phy/dllp/tlp register indirect access mechanism */ | |
176 | u32 pcieindaddr; /* indirect access to the internal register: 0x130 */ | |
177 | u32 pcieinddata; /* Data to/from the internal regsiter: 0x134 */ | |
178 | ||
179 | u32 clkreqenctrl; /* >= rev 6, Clkreq rdma control : 0x138 */ | |
180 | u32 PAD[177]; | |
181 | u32 pciecfg[4][64]; /* 0x400 - 0x7FF, PCIE Cfg Space */ | |
182 | u16 sprom[64]; /* SPROM shadow Area */ | |
183 | } sbpcieregs_t; | |
184 | ||
a9533e7e HP |
185 | typedef struct { |
186 | union { | |
187 | sbpcieregs_t *pcieregs; | |
c11b0ef8 | 188 | struct sbpciregs *pciregs; |
a9533e7e HP |
189 | } regs; /* Memory mapped register to the core */ |
190 | ||
d5f27a8f | 191 | struct si_pub *sih; /* System interconnect handle */ |
06d278c5 | 192 | struct pci_dev *dev; |
36ef9a1e | 193 | u8 pciecap_lcreg_offset; /* PCIE capability LCreg offset in the config space */ |
a9533e7e | 194 | bool pcie_pr42767; |
36ef9a1e GKH |
195 | u8 pcie_polarity; |
196 | u8 pcie_war_aspm_ovr; /* Override ASPM/Clkreq settings */ | |
a9533e7e | 197 | |
36ef9a1e | 198 | u8 pmecap_offset; /* PM Capability offset in the config space */ |
a9533e7e HP |
199 | bool pmecap; /* Capable of generating PME */ |
200 | } pcicore_info_t; | |
201 | ||
202 | /* debug/trace */ | |
203 | #define PCI_ERROR(args) | |
fa7a1db2 BR |
204 | #define PCIE_PUB(sih) \ |
205 | (((sih)->bustype == PCI_BUS) && ((sih)->buscoretype == PCIE_CORE_ID)) | |
a9533e7e HP |
206 | |
207 | /* routines to access mdio slave device registers */ | |
7cc4a4c0 JC |
208 | static bool pcie_mdiosetblock(pcicore_info_t *pi, uint blk); |
209 | static int pcie_mdioop(pcicore_info_t *pi, uint physmedia, uint regaddr, | |
210 | bool write, uint *val); | |
211 | static int pcie_mdiowrite(pcicore_info_t *pi, uint physmedia, uint readdr, | |
a9533e7e | 212 | uint val); |
7cc4a4c0 JC |
213 | static int pcie_mdioread(pcicore_info_t *pi, uint physmedia, uint readdr, |
214 | uint *ret_val); | |
a9533e7e | 215 | |
7cc4a4c0 JC |
216 | static void pcie_extendL1timer(pcicore_info_t *pi, bool extend); |
217 | static void pcie_clkreq_upd(pcicore_info_t *pi, uint state); | |
a9533e7e | 218 | |
7cc4a4c0 JC |
219 | static void pcie_war_aspm_clkreq(pcicore_info_t *pi); |
220 | static void pcie_war_serdes(pcicore_info_t *pi); | |
221 | static void pcie_war_noplldown(pcicore_info_t *pi); | |
222 | static void pcie_war_polarity(pcicore_info_t *pi); | |
223 | static void pcie_war_pci_setup(pcicore_info_t *pi); | |
a9533e7e | 224 | |
a9533e7e HP |
225 | #define PCIE_ASPM(sih) ((PCIE_PUB(sih)) && (((sih)->buscorerev >= 3) && ((sih)->buscorerev <= 5))) |
226 | ||
a9533e7e HP |
227 | |
228 | /* delay needed between the mdio control/ mdiodata register data access */ | |
7383141b | 229 | #define PR28829_DELAY() udelay(10) |
a9533e7e HP |
230 | |
231 | /* Initialize the PCI core. It's caller's responsibility to make sure that this is done | |
232 | * only once | |
233 | */ | |
4b168116 | 234 | void *pcicore_init(struct si_pub *sih, void *pdev, void *regs) |
a9533e7e HP |
235 | { |
236 | pcicore_info_t *pi; | |
237 | ||
a9533e7e | 238 | /* alloc pcicore_info_t */ |
5fcc1fcb | 239 | pi = kzalloc(sizeof(pcicore_info_t), GFP_ATOMIC); |
ca8c1e59 | 240 | if (pi == NULL) { |
97e17d0e | 241 | PCI_ERROR(("pci_attach: malloc failed!\n")); |
90ea2296 | 242 | return NULL; |
a9533e7e HP |
243 | } |
244 | ||
a9533e7e | 245 | pi->sih = sih; |
26bcc181 | 246 | pi->dev = pdev; |
a9533e7e HP |
247 | |
248 | if (sih->buscoretype == PCIE_CORE_ID) { | |
36ef9a1e | 249 | u8 cap_ptr; |
a9533e7e | 250 | pi->regs.pcieregs = (sbpcieregs_t *) regs; |
d8394285 SF |
251 | cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP, |
252 | NULL, NULL); | |
a9533e7e HP |
253 | pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET; |
254 | } else | |
c11b0ef8 | 255 | pi->regs.pciregs = (struct sbpciregs *) regs; |
a9533e7e HP |
256 | |
257 | return pi; | |
258 | } | |
259 | ||
260 | void pcicore_deinit(void *pch) | |
261 | { | |
262 | pcicore_info_t *pi = (pcicore_info_t *) pch; | |
263 | ||
264 | if (pi == NULL) | |
265 | return; | |
182acb3c | 266 | kfree(pi); |
a9533e7e HP |
267 | } |
268 | ||
269 | /* return cap_offset if requested capability exists in the PCI config space */ | |
270 | /* Note that it's caller's responsibility to make sure it's a pci bus */ | |
36ef9a1e | 271 | u8 |
06d278c5 | 272 | pcicore_find_pci_capability(void *dev, u8 req_cap_id, |
e69284f2 | 273 | unsigned char *buf, u32 *buflen) |
a9533e7e | 274 | { |
36ef9a1e GKH |
275 | u8 cap_id; |
276 | u8 cap_ptr = 0; | |
66cbd3ab | 277 | u32 bufsize; |
36ef9a1e | 278 | u8 byte_val; |
a9533e7e HP |
279 | |
280 | /* check for Header type 0 */ | |
d108b7a4 | 281 | pci_read_config_byte(dev, PCI_HEADER_TYPE, &byte_val); |
85633f62 | 282 | if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL) |
a9533e7e HP |
283 | goto end; |
284 | ||
285 | /* check if the capability pointer field exists */ | |
d108b7a4 | 286 | pci_read_config_byte(dev, PCI_STATUS, &byte_val); |
d8394285 | 287 | if (!(byte_val & PCI_STATUS_CAP_LIST)) |
a9533e7e HP |
288 | goto end; |
289 | ||
d108b7a4 | 290 | pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &cap_ptr); |
a9533e7e HP |
291 | /* check if the capability pointer is 0x00 */ |
292 | if (cap_ptr == 0x00) | |
293 | goto end; | |
294 | ||
295 | /* loop thr'u the capability list and see if the pcie capabilty exists */ | |
296 | ||
06d278c5 | 297 | pci_read_config_byte(dev, cap_ptr, &cap_id); |
a9533e7e HP |
298 | |
299 | while (cap_id != req_cap_id) { | |
06d278c5 | 300 | pci_read_config_byte(dev, cap_ptr + 1, &cap_ptr); |
a9533e7e HP |
301 | if (cap_ptr == 0x00) |
302 | break; | |
06d278c5 | 303 | pci_read_config_byte(dev, cap_ptr, &cap_id); |
a9533e7e HP |
304 | } |
305 | if (cap_id != req_cap_id) { | |
306 | goto end; | |
307 | } | |
308 | /* found the caller requested capability */ | |
309 | if ((buf != NULL) && (buflen != NULL)) { | |
36ef9a1e | 310 | u8 cap_data; |
a9533e7e HP |
311 | |
312 | bufsize = *buflen; | |
313 | if (!bufsize) | |
314 | goto end; | |
315 | *buflen = 0; | |
316 | /* copy the cpability data excluding cap ID and next ptr */ | |
317 | cap_data = cap_ptr + 2; | |
6b80b247 SF |
318 | if ((bufsize + cap_data) > PCI_SZPCR) |
319 | bufsize = PCI_SZPCR - cap_data; | |
a9533e7e HP |
320 | *buflen = bufsize; |
321 | while (bufsize--) { | |
06d278c5 | 322 | pci_read_config_byte(dev, cap_data, buf); |
a9533e7e HP |
323 | cap_data++; |
324 | buf++; | |
325 | } | |
326 | } | |
327 | end: | |
328 | return cap_ptr; | |
329 | } | |
330 | ||
331 | /* ***** Register Access API */ | |
e4eb6864 | 332 | static uint |
26bcc181 | 333 | pcie_readreg(sbpcieregs_t *pcieregs, uint addrtype, |
e69284f2 | 334 | uint offset) |
a9533e7e HP |
335 | { |
336 | uint retval = 0xFFFFFFFF; | |
337 | ||
a9533e7e HP |
338 | switch (addrtype) { |
339 | case PCIE_CONFIGREGS: | |
ff31c54c AS |
340 | W_REG((&pcieregs->configaddr), offset); |
341 | (void)R_REG((&pcieregs->configaddr)); | |
342 | retval = R_REG(&(pcieregs->configdata)); | |
a9533e7e HP |
343 | break; |
344 | case PCIE_PCIEREGS: | |
ff31c54c AS |
345 | W_REG(&(pcieregs->pcieindaddr), offset); |
346 | (void)R_REG((&pcieregs->pcieindaddr)); | |
347 | retval = R_REG(&(pcieregs->pcieinddata)); | |
a9533e7e HP |
348 | break; |
349 | default: | |
a9533e7e HP |
350 | break; |
351 | } | |
352 | ||
353 | return retval; | |
354 | } | |
355 | ||
e4eb6864 | 356 | static uint |
26bcc181 | 357 | pcie_writereg(sbpcieregs_t *pcieregs, uint addrtype, |
e69284f2 | 358 | uint offset, uint val) |
a9533e7e | 359 | { |
a9533e7e HP |
360 | switch (addrtype) { |
361 | case PCIE_CONFIGREGS: | |
ff31c54c AS |
362 | W_REG((&pcieregs->configaddr), offset); |
363 | W_REG((&pcieregs->configdata), val); | |
a9533e7e HP |
364 | break; |
365 | case PCIE_PCIEREGS: | |
ff31c54c AS |
366 | W_REG((&pcieregs->pcieindaddr), offset); |
367 | W_REG((&pcieregs->pcieinddata), val); | |
a9533e7e HP |
368 | break; |
369 | default: | |
a9533e7e HP |
370 | break; |
371 | } | |
372 | return 0; | |
373 | } | |
374 | ||
7cc4a4c0 | 375 | static bool pcie_mdiosetblock(pcicore_info_t *pi, uint blk) |
a9533e7e HP |
376 | { |
377 | sbpcieregs_t *pcieregs = pi->regs.pcieregs; | |
378 | uint mdiodata, i = 0; | |
379 | uint pcie_serdes_spinwait = 200; | |
380 | ||
381 | mdiodata = | |
382 | MDIODATA_START | MDIODATA_WRITE | (MDIODATA_DEV_ADDR << | |
383 | MDIODATA_DEVADDR_SHF) | | |
384 | (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) | MDIODATA_TA | (blk << | |
385 | 4); | |
ff31c54c | 386 | W_REG(&pcieregs->mdiodata, mdiodata); |
a9533e7e HP |
387 | |
388 | PR28829_DELAY(); | |
389 | /* retry till the transaction is complete */ | |
390 | while (i < pcie_serdes_spinwait) { | |
ff31c54c | 391 | if (R_REG(&(pcieregs->mdiocontrol)) & |
a9533e7e HP |
392 | MDIOCTL_ACCESS_DONE) { |
393 | break; | |
394 | } | |
7383141b | 395 | udelay(1000); |
a9533e7e HP |
396 | i++; |
397 | } | |
398 | ||
399 | if (i >= pcie_serdes_spinwait) { | |
400 | PCI_ERROR(("pcie_mdiosetblock: timed out\n")); | |
0965ae88 | 401 | return false; |
a9533e7e HP |
402 | } |
403 | ||
0f0881b0 | 404 | return true; |
a9533e7e HP |
405 | } |
406 | ||
407 | static int | |
7cc4a4c0 JC |
408 | pcie_mdioop(pcicore_info_t *pi, uint physmedia, uint regaddr, bool write, |
409 | uint *val) | |
a9533e7e HP |
410 | { |
411 | sbpcieregs_t *pcieregs = pi->regs.pcieregs; | |
412 | uint mdiodata; | |
413 | uint i = 0; | |
414 | uint pcie_serdes_spinwait = 10; | |
415 | ||
416 | /* enable mdio access to SERDES */ | |
ff31c54c | 417 | W_REG((&pcieregs->mdiocontrol), |
a9533e7e HP |
418 | MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); |
419 | ||
420 | if (pi->sih->buscorerev >= 10) { | |
421 | /* new serdes is slower in rw, using two layers of reg address mapping */ | |
422 | if (!pcie_mdiosetblock(pi, physmedia)) | |
423 | return 1; | |
424 | mdiodata = (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | | |
425 | (regaddr << MDIODATA_REGADDR_SHF); | |
426 | pcie_serdes_spinwait *= 20; | |
427 | } else { | |
428 | mdiodata = (physmedia << MDIODATA_DEVADDR_SHF_OLD) | | |
429 | (regaddr << MDIODATA_REGADDR_SHF_OLD); | |
430 | } | |
431 | ||
432 | if (!write) | |
433 | mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA); | |
434 | else | |
435 | mdiodata |= | |
436 | (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | *val); | |
437 | ||
ff31c54c | 438 | W_REG(&pcieregs->mdiodata, mdiodata); |
a9533e7e HP |
439 | |
440 | PR28829_DELAY(); | |
441 | ||
442 | /* retry till the transaction is complete */ | |
443 | while (i < pcie_serdes_spinwait) { | |
ff31c54c | 444 | if (R_REG(&(pcieregs->mdiocontrol)) & |
a9533e7e HP |
445 | MDIOCTL_ACCESS_DONE) { |
446 | if (!write) { | |
447 | PR28829_DELAY(); | |
448 | *val = | |
ff31c54c | 449 | (R_REG(&(pcieregs->mdiodata)) & |
a9533e7e HP |
450 | MDIODATA_MASK); |
451 | } | |
452 | /* Disable mdio access to SERDES */ | |
ff31c54c | 453 | W_REG((&pcieregs->mdiocontrol), 0); |
a9533e7e HP |
454 | return 0; |
455 | } | |
7383141b | 456 | udelay(1000); |
a9533e7e HP |
457 | i++; |
458 | } | |
459 | ||
460 | PCI_ERROR(("pcie_mdioop: timed out op: %d\n", write)); | |
461 | /* Disable mdio access to SERDES */ | |
ff31c54c | 462 | W_REG((&pcieregs->mdiocontrol), 0); |
a9533e7e HP |
463 | return 1; |
464 | } | |
465 | ||
466 | /* use the mdio interface to read from mdio slaves */ | |
467 | static int | |
7cc4a4c0 | 468 | pcie_mdioread(pcicore_info_t *pi, uint physmedia, uint regaddr, uint *regval) |
a9533e7e | 469 | { |
0965ae88 | 470 | return pcie_mdioop(pi, physmedia, regaddr, false, regval); |
a9533e7e HP |
471 | } |
472 | ||
473 | /* use the mdio interface to write to mdio slaves */ | |
474 | static int | |
7cc4a4c0 | 475 | pcie_mdiowrite(pcicore_info_t *pi, uint physmedia, uint regaddr, uint val) |
a9533e7e | 476 | { |
0f0881b0 | 477 | return pcie_mdioop(pi, physmedia, regaddr, true, &val); |
a9533e7e HP |
478 | } |
479 | ||
480 | /* ***** Support functions ***** */ | |
e4eb6864 | 481 | static u8 pcie_clkreq(void *pch, u32 mask, u32 val) |
a9533e7e HP |
482 | { |
483 | pcicore_info_t *pi = (pcicore_info_t *) pch; | |
66cbd3ab | 484 | u32 reg_val; |
36ef9a1e | 485 | u8 offset; |
a9533e7e HP |
486 | |
487 | offset = pi->pciecap_lcreg_offset; | |
488 | if (!offset) | |
489 | return 0; | |
490 | ||
06d278c5 | 491 | pci_read_config_dword(pi->dev, offset, ®_val); |
a9533e7e HP |
492 | /* set operation */ |
493 | if (mask) { | |
494 | if (val) | |
495 | reg_val |= PCIE_CLKREQ_ENAB; | |
496 | else | |
497 | reg_val &= ~PCIE_CLKREQ_ENAB; | |
06d278c5 AS |
498 | pci_write_config_dword(pi->dev, offset, reg_val); |
499 | pci_read_config_dword(pi->dev, offset, ®_val); | |
a9533e7e HP |
500 | } |
501 | if (reg_val & PCIE_CLKREQ_ENAB) | |
502 | return 1; | |
503 | else | |
504 | return 0; | |
505 | } | |
506 | ||
7cc4a4c0 | 507 | static void pcie_extendL1timer(pcicore_info_t *pi, bool extend) |
a9533e7e | 508 | { |
66cbd3ab | 509 | u32 w; |
d5f27a8f | 510 | struct si_pub *sih = pi->sih; |
a9533e7e HP |
511 | sbpcieregs_t *pcieregs = pi->regs.pcieregs; |
512 | ||
513 | if (!PCIE_PUB(sih) || sih->buscorerev < 7) | |
514 | return; | |
515 | ||
26bcc181 | 516 | w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); |
a9533e7e HP |
517 | if (extend) |
518 | w |= PCIE_ASPMTIMER_EXTEND; | |
519 | else | |
520 | w &= ~PCIE_ASPMTIMER_EXTEND; | |
26bcc181 AS |
521 | pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w); |
522 | w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); | |
a9533e7e HP |
523 | } |
524 | ||
525 | /* centralized clkreq control policy */ | |
7cc4a4c0 | 526 | static void pcie_clkreq_upd(pcicore_info_t *pi, uint state) |
a9533e7e | 527 | { |
d5f27a8f | 528 | struct si_pub *sih = pi->sih; |
a9533e7e HP |
529 | |
530 | switch (state) { | |
531 | case SI_DOATTACH: | |
532 | if (PCIE_ASPM(sih)) | |
533 | pcie_clkreq((void *)pi, 1, 0); | |
534 | break; | |
535 | case SI_PCIDOWN: | |
536 | if (sih->buscorerev == 6) { /* turn on serdes PLL down */ | |
b21c892d | 537 | ai_corereg(sih, SI_CC_IDX, |
ce0f1b8c | 538 | offsetof(chipcregs_t, chipcontrol_addr), ~0, |
a9533e7e | 539 | 0); |
b21c892d | 540 | ai_corereg(sih, SI_CC_IDX, |
ce0f1b8c | 541 | offsetof(chipcregs_t, chipcontrol_data), |
a9533e7e HP |
542 | ~0x40, 0); |
543 | } else if (pi->pcie_pr42767) { | |
544 | pcie_clkreq((void *)pi, 1, 1); | |
545 | } | |
546 | break; | |
547 | case SI_PCIUP: | |
548 | if (sih->buscorerev == 6) { /* turn off serdes PLL down */ | |
b21c892d | 549 | ai_corereg(sih, SI_CC_IDX, |
ce0f1b8c | 550 | offsetof(chipcregs_t, chipcontrol_addr), ~0, |
a9533e7e | 551 | 0); |
b21c892d | 552 | ai_corereg(sih, SI_CC_IDX, |
ce0f1b8c | 553 | offsetof(chipcregs_t, chipcontrol_data), |
a9533e7e HP |
554 | ~0x40, 0x40); |
555 | } else if (PCIE_ASPM(sih)) { /* disable clkreq */ | |
556 | pcie_clkreq((void *)pi, 1, 0); | |
557 | } | |
558 | break; | |
559 | default: | |
a9533e7e HP |
560 | break; |
561 | } | |
562 | } | |
563 | ||
564 | /* ***** PCI core WARs ***** */ | |
565 | /* Done only once at attach time */ | |
7cc4a4c0 | 566 | static void pcie_war_polarity(pcicore_info_t *pi) |
a9533e7e | 567 | { |
66cbd3ab | 568 | u32 w; |
a9533e7e HP |
569 | |
570 | if (pi->pcie_polarity != 0) | |
571 | return; | |
572 | ||
26bcc181 | 573 | w = pcie_readreg(pi->regs.pcieregs, PCIE_PCIEREGS, |
a9533e7e HP |
574 | PCIE_PLP_STATUSREG); |
575 | ||
576 | /* Detect the current polarity at attach and force that polarity and | |
577 | * disable changing the polarity | |
578 | */ | |
579 | if ((w & PCIE_PLP_POLARITYINV_STAT) == 0) | |
580 | pi->pcie_polarity = (SERDES_RX_CTRL_FORCE); | |
581 | else | |
582 | pi->pcie_polarity = | |
583 | (SERDES_RX_CTRL_FORCE | SERDES_RX_CTRL_POLARITY); | |
584 | } | |
585 | ||
586 | /* enable ASPM and CLKREQ if srom doesn't have it */ | |
587 | /* Needs to happen when update to shadow SROM is needed | |
588 | * : Coming out of 'standby'/'hibernate' | |
589 | * : If pcie_war_aspm_ovr state changed | |
590 | */ | |
7cc4a4c0 | 591 | static void pcie_war_aspm_clkreq(pcicore_info_t *pi) |
a9533e7e HP |
592 | { |
593 | sbpcieregs_t *pcieregs = pi->regs.pcieregs; | |
d5f27a8f | 594 | struct si_pub *sih = pi->sih; |
7d4df48e | 595 | u16 val16, *reg16; |
66cbd3ab | 596 | u32 w; |
a9533e7e HP |
597 | |
598 | if (!PCIE_ASPM(sih)) | |
599 | return; | |
600 | ||
601 | /* bypass this on QT or VSIM */ | |
602 | if (!ISSIM_ENAB(sih)) { | |
603 | ||
604 | reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET]; | |
ff31c54c | 605 | val16 = R_REG(reg16); |
a9533e7e HP |
606 | |
607 | val16 &= ~SRSH_ASPM_ENB; | |
608 | if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB) | |
609 | val16 |= SRSH_ASPM_ENB; | |
610 | else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L1_ENAB) | |
611 | val16 |= SRSH_ASPM_L1_ENB; | |
612 | else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB) | |
613 | val16 |= SRSH_ASPM_L0s_ENB; | |
614 | ||
ff31c54c | 615 | W_REG(reg16, val16); |
a9533e7e | 616 | |
06d278c5 | 617 | pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, |
93760716 | 618 | &w); |
a9533e7e HP |
619 | w &= ~PCIE_ASPM_ENAB; |
620 | w |= pi->pcie_war_aspm_ovr; | |
06d278c5 | 621 | pci_write_config_dword(pi->dev, |
93760716 | 622 | pi->pciecap_lcreg_offset, w); |
a9533e7e HP |
623 | } |
624 | ||
625 | reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET_REV5]; | |
ff31c54c | 626 | val16 = R_REG(reg16); |
a9533e7e HP |
627 | |
628 | if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) { | |
629 | val16 |= SRSH_CLKREQ_ENB; | |
0f0881b0 | 630 | pi->pcie_pr42767 = true; |
a9533e7e HP |
631 | } else |
632 | val16 &= ~SRSH_CLKREQ_ENB; | |
633 | ||
ff31c54c | 634 | W_REG(reg16, val16); |
a9533e7e HP |
635 | } |
636 | ||
637 | /* Apply the polarity determined at the start */ | |
638 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | |
7cc4a4c0 | 639 | static void pcie_war_serdes(pcicore_info_t *pi) |
a9533e7e | 640 | { |
66cbd3ab | 641 | u32 w = 0; |
a9533e7e HP |
642 | |
643 | if (pi->pcie_polarity != 0) | |
644 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CTRL, | |
645 | pi->pcie_polarity); | |
646 | ||
647 | pcie_mdioread(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w); | |
648 | if (w & PLL_CTRL_FREQDET_EN) { | |
649 | w &= ~PLL_CTRL_FREQDET_EN; | |
650 | pcie_mdiowrite(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w); | |
651 | } | |
652 | } | |
653 | ||
654 | /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */ | |
655 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | |
b4f790ee | 656 | static void pcie_misc_config_fixup(pcicore_info_t *pi) |
a2627bc0 | 657 | { |
a9533e7e | 658 | sbpcieregs_t *pcieregs = pi->regs.pcieregs; |
7d4df48e | 659 | u16 val16, *reg16; |
a9533e7e HP |
660 | |
661 | reg16 = &pcieregs->sprom[SRSH_PCIE_MISC_CONFIG]; | |
ff31c54c | 662 | val16 = R_REG(reg16); |
a9533e7e HP |
663 | |
664 | if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) { | |
665 | val16 |= SRSH_L23READY_EXIT_NOPERST; | |
ff31c54c | 666 | W_REG(reg16, val16); |
a9533e7e HP |
667 | } |
668 | } | |
669 | ||
670 | /* quick hack for testing */ | |
671 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | |
7cc4a4c0 | 672 | static void pcie_war_noplldown(pcicore_info_t *pi) |
a9533e7e HP |
673 | { |
674 | sbpcieregs_t *pcieregs = pi->regs.pcieregs; | |
7d4df48e | 675 | u16 *reg16; |
a9533e7e | 676 | |
a9533e7e | 677 | /* turn off serdes PLL down */ |
b21c892d | 678 | ai_corereg(pi->sih, SI_CC_IDX, offsetof(chipcregs_t, chipcontrol), |
a9533e7e HP |
679 | CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN); |
680 | ||
681 | /* clear srom shadow backdoor */ | |
682 | reg16 = &pcieregs->sprom[SRSH_BD_OFFSET]; | |
ff31c54c | 683 | W_REG(reg16, 0); |
a9533e7e HP |
684 | } |
685 | ||
686 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | |
7cc4a4c0 | 687 | static void pcie_war_pci_setup(pcicore_info_t *pi) |
a9533e7e | 688 | { |
d5f27a8f | 689 | struct si_pub *sih = pi->sih; |
a9533e7e | 690 | sbpcieregs_t *pcieregs = pi->regs.pcieregs; |
66cbd3ab | 691 | u32 w; |
a9533e7e HP |
692 | |
693 | if ((sih->buscorerev == 0) || (sih->buscorerev == 1)) { | |
26bcc181 | 694 | w = pcie_readreg(pcieregs, PCIE_PCIEREGS, |
a9533e7e HP |
695 | PCIE_TLP_WORKAROUNDSREG); |
696 | w |= 0x8; | |
26bcc181 | 697 | pcie_writereg(pcieregs, PCIE_PCIEREGS, |
a9533e7e HP |
698 | PCIE_TLP_WORKAROUNDSREG, w); |
699 | } | |
700 | ||
701 | if (sih->buscorerev == 1) { | |
26bcc181 | 702 | w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG); |
a9533e7e | 703 | w |= (0x40); |
26bcc181 | 704 | pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w); |
a9533e7e HP |
705 | } |
706 | ||
707 | if (sih->buscorerev == 0) { | |
708 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128); | |
709 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100); | |
710 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466); | |
711 | } else if (PCIE_ASPM(sih)) { | |
712 | /* Change the L1 threshold for better performance */ | |
26bcc181 | 713 | w = pcie_readreg(pcieregs, PCIE_PCIEREGS, |
a9533e7e HP |
714 | PCIE_DLLP_PMTHRESHREG); |
715 | w &= ~(PCIE_L1THRESHOLDTIME_MASK); | |
716 | w |= (PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT); | |
26bcc181 | 717 | pcie_writereg(pcieregs, PCIE_PCIEREGS, |
a9533e7e HP |
718 | PCIE_DLLP_PMTHRESHREG, w); |
719 | ||
720 | pcie_war_serdes(pi); | |
721 | ||
722 | pcie_war_aspm_clkreq(pi); | |
723 | } else if (pi->sih->buscorerev == 7) | |
724 | pcie_war_noplldown(pi); | |
725 | ||
726 | /* Note that the fix is actually in the SROM, that's why this is open-ended */ | |
727 | if (pi->sih->buscorerev >= 6) | |
728 | pcie_misc_config_fixup(pi); | |
729 | } | |
730 | ||
a9533e7e | 731 | /* ***** Functions called during driver state changes ***** */ |
0d2f0724 | 732 | void pcicore_attach(void *pch, char *pvars, int state) |
a2627bc0 | 733 | { |
a9533e7e | 734 | pcicore_info_t *pi = (pcicore_info_t *) pch; |
d5f27a8f | 735 | struct si_pub *sih = pi->sih; |
a9533e7e HP |
736 | |
737 | /* Determine if this board needs override */ | |
738 | if (PCIE_ASPM(sih)) { | |
66cbd3ab | 739 | if ((u32) getintvar(pvars, "boardflags2") & BFL2_PCIEWAR_OVR) { |
a9533e7e HP |
740 | pi->pcie_war_aspm_ovr = PCIE_ASPM_DISAB; |
741 | } else { | |
742 | pi->pcie_war_aspm_ovr = PCIE_ASPM_ENAB; | |
743 | } | |
744 | } | |
745 | ||
746 | /* These need to happen in this order only */ | |
747 | pcie_war_polarity(pi); | |
748 | ||
749 | pcie_war_serdes(pi); | |
750 | ||
751 | pcie_war_aspm_clkreq(pi); | |
752 | ||
753 | pcie_clkreq_upd(pi, state); | |
754 | ||
755 | } | |
756 | ||
757 | void pcicore_hwup(void *pch) | |
758 | { | |
759 | pcicore_info_t *pi = (pcicore_info_t *) pch; | |
760 | ||
761 | if (!pi || !PCIE_PUB(pi->sih)) | |
762 | return; | |
763 | ||
764 | pcie_war_pci_setup(pi); | |
765 | } | |
766 | ||
767 | void pcicore_up(void *pch, int state) | |
768 | { | |
769 | pcicore_info_t *pi = (pcicore_info_t *) pch; | |
770 | ||
771 | if (!pi || !PCIE_PUB(pi->sih)) | |
772 | return; | |
773 | ||
774 | /* Restore L1 timer for better performance */ | |
0f0881b0 | 775 | pcie_extendL1timer(pi, true); |
a9533e7e HP |
776 | |
777 | pcie_clkreq_upd(pi, state); | |
778 | } | |
779 | ||
780 | /* When the device is going to enter D3 state (or the system is going to enter S3/S4 states */ | |
781 | void pcicore_sleep(void *pch) | |
782 | { | |
783 | pcicore_info_t *pi = (pcicore_info_t *) pch; | |
66cbd3ab | 784 | u32 w; |
a9533e7e HP |
785 | |
786 | if (!pi || !PCIE_ASPM(pi->sih)) | |
787 | return; | |
788 | ||
06d278c5 | 789 | pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w); |
a9533e7e | 790 | w &= ~PCIE_CAP_LCREG_ASPML1; |
06d278c5 | 791 | pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w); |
a9533e7e | 792 | |
0965ae88 | 793 | pi->pcie_pr42767 = false; |
a9533e7e HP |
794 | } |
795 | ||
796 | void pcicore_down(void *pch, int state) | |
797 | { | |
798 | pcicore_info_t *pi = (pcicore_info_t *) pch; | |
799 | ||
800 | if (!pi || !PCIE_PUB(pi->sih)) | |
801 | return; | |
802 | ||
803 | pcie_clkreq_upd(pi, state); | |
804 | ||
805 | /* Reduce L1 timer for better power savings */ | |
0965ae88 | 806 | pcie_extendL1timer(pi, false); |
a9533e7e | 807 | } |
8543df3a AS |
808 | |
809 | /* | |
810 | * precondition: current core is sii->buscoretype | |
811 | */ | |
812 | void pcicore_fixcfg(void *pch, void *regs) | |
813 | { | |
814 | pcicore_info_t *pi = (pcicore_info_t *) pch; | |
815 | struct si_info *sii = SI_INFO(pi->sih); | |
816 | struct sbpciregs *pciregs = regs; | |
817 | sbpcieregs_t *pcieregs = regs; | |
818 | u16 val16, *reg16 = NULL; | |
819 | uint pciidx; | |
820 | ||
821 | /* check 'pi' is correct and fix it if not */ | |
822 | if (sii->pub.buscoretype == PCIE_CORE_ID) { | |
823 | reg16 = &pcieregs->sprom[SRSH_PI_OFFSET]; | |
824 | } else if (sii->pub.buscoretype == PCI_CORE_ID) { | |
825 | reg16 = &pciregs->sprom[SRSH_PI_OFFSET]; | |
826 | } | |
827 | pciidx = ai_coreidx(&sii->pub); | |
828 | val16 = R_REG(reg16); | |
829 | if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16) pciidx) { | |
830 | val16 = | |
831 | (u16) (pciidx << SRSH_PI_SHIFT) | (val16 & | |
832 | ~SRSH_PI_MASK); | |
833 | W_REG(reg16, val16); | |
834 | } | |
835 | } | |
836 | ||
837 | /* | |
838 | * precondition: current core is pci core | |
839 | */ | |
840 | void pcicore_pci_setup(void *pch, void *regs) | |
841 | { | |
842 | pcicore_info_t *pi = (pcicore_info_t *) pch; | |
843 | struct sbpciregs *pciregs = regs; | |
844 | u32 w; | |
845 | ||
846 | OR_REG(&pciregs->sbtopci2, | |
847 | (SBTOPCI_PREF | SBTOPCI_BURST)); | |
848 | ||
849 | if (SI_INFO(pi->sih)->pub.buscorerev >= 11) { | |
850 | OR_REG(&pciregs->sbtopci2, | |
851 | SBTOPCI_RC_READMULTI); | |
852 | w = R_REG(&pciregs->clkrun); | |
853 | W_REG(&pciregs->clkrun, | |
854 | (w | PCI_CLKRUN_DSBL)); | |
855 | w = R_REG(&pciregs->clkrun); | |
856 | } | |
857 | } |