Commit | Line | Data |
---|---|---|
f473832f RM |
1 | /* |
2 | * Broadcom specific AMBA | |
3 | * PCIe Gen 2 Core | |
4 | * | |
5 | * Copyright 2014, Broadcom Corporation | |
6 | * Copyright 2014, Rafał Miłecki <zajec5@gmail.com> | |
7 | * | |
8 | * Licensed under the GNU/GPL. See COPYING for details. | |
9 | */ | |
10 | ||
11 | #include "bcma_private.h" | |
12 | #include <linux/bcma/bcma.h> | |
2264fc85 | 13 | #include <linux/pci.h> |
f473832f RM |
14 | |
15 | /************************************************** | |
16 | * R/W ops. | |
17 | **************************************************/ | |
18 | ||
19 | #if 0 | |
20 | static u32 bcma_core_pcie2_cfg_read(struct bcma_drv_pcie2 *pcie2, u32 addr) | |
21 | { | |
22 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr); | |
23 | pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR); | |
24 | return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA); | |
25 | } | |
26 | #endif | |
27 | ||
28 | static void bcma_core_pcie2_cfg_write(struct bcma_drv_pcie2 *pcie2, u32 addr, | |
29 | u32 val) | |
30 | { | |
31 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr); | |
32 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, val); | |
33 | } | |
34 | ||
35 | /************************************************** | |
36 | * Init. | |
37 | **************************************************/ | |
38 | ||
39 | static u32 bcma_core_pcie2_war_delay_perst_enab(struct bcma_drv_pcie2 *pcie2, | |
40 | bool enable) | |
41 | { | |
42 | u32 val; | |
43 | ||
44 | /* restore back to default */ | |
45 | val = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL); | |
46 | val |= PCIE2_CLKC_DLYPERST; | |
47 | val &= ~PCIE2_CLKC_DISSPROMLD; | |
48 | if (enable) { | |
49 | val &= ~PCIE2_CLKC_DLYPERST; | |
50 | val |= PCIE2_CLKC_DISSPROMLD; | |
51 | } | |
52 | pcie2_write32(pcie2, (BCMA_CORE_PCIE2_CLK_CONTROL), val); | |
53 | /* flush */ | |
54 | return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL); | |
55 | } | |
56 | ||
57 | static void bcma_core_pcie2_set_ltr_vals(struct bcma_drv_pcie2 *pcie2) | |
58 | { | |
59 | /* LTR0 */ | |
60 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x844); | |
61 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x883c883c); | |
62 | /* LTR1 */ | |
63 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x848); | |
64 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x88648864); | |
65 | /* LTR2 */ | |
66 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x84C); | |
67 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x90039003); | |
68 | } | |
69 | ||
70 | static void bcma_core_pcie2_hw_ltr_war(struct bcma_drv_pcie2 *pcie2) | |
71 | { | |
72 | u8 core_rev = pcie2->core->id.rev; | |
73 | u32 devstsctr2; | |
74 | ||
75 | if (core_rev < 2 || core_rev == 10 || core_rev > 13) | |
76 | return; | |
77 | ||
78 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, | |
79 | PCIE2_CAP_DEVSTSCTRL2_OFFSET); | |
80 | devstsctr2 = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA); | |
81 | if (devstsctr2 & PCIE2_CAP_DEVSTSCTRL2_LTRENAB) { | |
82 | /* force the right LTR values */ | |
83 | bcma_core_pcie2_set_ltr_vals(pcie2); | |
84 | ||
85 | /* TODO: | |
86 | si_core_wrapperreg(pcie2, 3, 0x60, 0x8080, 0); */ | |
87 | ||
88 | /* enable the LTR */ | |
89 | devstsctr2 |= PCIE2_CAP_DEVSTSCTRL2_LTRENAB; | |
90 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, | |
91 | PCIE2_CAP_DEVSTSCTRL2_OFFSET); | |
92 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, devstsctr2); | |
93 | ||
94 | /* set the LTR state to be active */ | |
95 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE, | |
96 | PCIE2_LTR_ACTIVE); | |
97 | usleep_range(1000, 2000); | |
98 | ||
99 | /* set the LTR state to be sleep */ | |
100 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE, | |
101 | PCIE2_LTR_SLEEP); | |
102 | usleep_range(1000, 2000); | |
103 | } | |
104 | } | |
105 | ||
106 | static void pciedev_crwlpciegen2(struct bcma_drv_pcie2 *pcie2) | |
107 | { | |
108 | u8 core_rev = pcie2->core->id.rev; | |
109 | bool pciewar160, pciewar162; | |
110 | ||
111 | pciewar160 = core_rev == 7 || core_rev == 9 || core_rev == 11; | |
112 | pciewar162 = core_rev == 5 || core_rev == 7 || core_rev == 8 || | |
113 | core_rev == 9 || core_rev == 11; | |
114 | ||
115 | if (!pciewar160 && !pciewar162) | |
116 | return; | |
117 | ||
118 | /* TODO */ | |
119 | #if 0 | |
120 | pcie2_set32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL, | |
121 | PCIE_DISABLE_L1CLK_GATING); | |
122 | #if 0 | |
123 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, | |
124 | PCIEGEN2_COE_PVT_TL_CTRL_0); | |
125 | pcie2_mask32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, | |
126 | ~(1 << COE_PVT_TL_CTRL_0_PM_DIS_L1_REENTRY_BIT)); | |
127 | #endif | |
128 | #endif | |
129 | } | |
130 | ||
131 | static void pciedev_crwlpciegen2_180(struct bcma_drv_pcie2 *pcie2) | |
132 | { | |
133 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_PMCR_REFUP); | |
134 | pcie2_set32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x1f); | |
135 | } | |
136 | ||
137 | static void pciedev_crwlpciegen2_182(struct bcma_drv_pcie2 *pcie2) | |
138 | { | |
139 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_SBMBX); | |
140 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 1 << 0); | |
141 | } | |
142 | ||
143 | static void pciedev_reg_pm_clk_period(struct bcma_drv_pcie2 *pcie2) | |
144 | { | |
145 | struct bcma_drv_cc *drv_cc = &pcie2->core->bus->drv_cc; | |
146 | u8 core_rev = pcie2->core->id.rev; | |
147 | u32 alp_khz, pm_value; | |
148 | ||
149 | if (core_rev <= 13) { | |
150 | alp_khz = bcma_pmu_get_alp_clock(drv_cc) / 1000; | |
151 | pm_value = (1000000 * 2) / alp_khz; | |
152 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, | |
153 | PCIE2_PVT_REG_PM_CLK_PERIOD); | |
154 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, pm_value); | |
155 | } | |
156 | } | |
157 | ||
158 | void bcma_core_pcie2_init(struct bcma_drv_pcie2 *pcie2) | |
159 | { | |
804e27de RM |
160 | struct bcma_bus *bus = pcie2->core->bus; |
161 | struct bcma_chipinfo *ci = &bus->chipinfo; | |
f473832f RM |
162 | u32 tmp; |
163 | ||
164 | tmp = pcie2_read32(pcie2, BCMA_CORE_PCIE2_SPROM(54)); | |
165 | if ((tmp & 0xe) >> 1 == 2) | |
166 | bcma_core_pcie2_cfg_write(pcie2, 0x4e0, 0x17); | |
167 | ||
804e27de RM |
168 | switch (bus->chipinfo.id) { |
169 | case BCMA_CHIP_ID_BCM4360: | |
170 | case BCMA_CHIP_ID_BCM4352: | |
171 | pcie2->reqsize = 1024; | |
172 | break; | |
173 | default: | |
174 | pcie2->reqsize = 128; | |
175 | break; | |
176 | } | |
f473832f RM |
177 | |
178 | if (ci->id == BCMA_CHIP_ID_BCM4360 && ci->rev > 3) | |
179 | bcma_core_pcie2_war_delay_perst_enab(pcie2, true); | |
180 | bcma_core_pcie2_hw_ltr_war(pcie2); | |
181 | pciedev_crwlpciegen2(pcie2); | |
182 | pciedev_reg_pm_clk_period(pcie2); | |
183 | pciedev_crwlpciegen2_180(pcie2); | |
184 | pciedev_crwlpciegen2_182(pcie2); | |
185 | } | |
804e27de RM |
186 | |
187 | /************************************************** | |
188 | * Runtime ops. | |
189 | **************************************************/ | |
190 | ||
191 | void bcma_core_pcie2_up(struct bcma_drv_pcie2 *pcie2) | |
192 | { | |
193 | struct bcma_bus *bus = pcie2->core->bus; | |
194 | struct pci_dev *dev = bus->host_pci; | |
195 | int err; | |
196 | ||
197 | err = pcie_set_readrq(dev, pcie2->reqsize); | |
198 | if (err) | |
199 | bcma_err(bus, "Error setting PCI_EXP_DEVCTL_READRQ: %d\n", err); | |
200 | } |