diff options
author | Rafał Miłecki <zajec5@gmail.com> | 2014-07-04 19:10:41 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-07-07 16:32:16 -0400 |
commit | f473832fece16611520bf54ad52b16c3f6db0a94 (patch) | |
tree | f05540f9ee9ed3b93c065dc631d73f3e9491905b /drivers | |
parent | fe5e499f427dadbeeb079e0a796702f4a3da78a0 (diff) |
bcma: add driver for PCIe Gen 2 core
New Broadcom PCIe devices (802.11ac ones?) use Gen2 and have to be
initialized differently.
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/bcma/Makefile | 1 | ||||
-rw-r--r-- | drivers/bcma/driver_pcie2.c | 175 | ||||
-rw-r--r-- | drivers/bcma/main.c | 8 |
3 files changed, 184 insertions, 0 deletions
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile index 734b32f09c0a..91290f7f61b8 100644 --- a/drivers/bcma/Makefile +++ b/drivers/bcma/Makefile | |||
@@ -3,6 +3,7 @@ bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o | |||
3 | bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o | 3 | bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o |
4 | bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o | 4 | bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o |
5 | bcma-y += driver_pci.o | 5 | bcma-y += driver_pci.o |
6 | bcma-y += driver_pcie2.o | ||
6 | bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o | 7 | bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o |
7 | bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o | 8 | bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o |
8 | bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o | 9 | bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o |
diff --git a/drivers/bcma/driver_pcie2.c b/drivers/bcma/driver_pcie2.c new file mode 100644 index 000000000000..e4be537b0c66 --- /dev/null +++ b/drivers/bcma/driver_pcie2.c | |||
@@ -0,0 +1,175 @@ | |||
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> | ||
13 | |||
14 | /************************************************** | ||
15 | * R/W ops. | ||
16 | **************************************************/ | ||
17 | |||
18 | #if 0 | ||
19 | static u32 bcma_core_pcie2_cfg_read(struct bcma_drv_pcie2 *pcie2, u32 addr) | ||
20 | { | ||
21 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr); | ||
22 | pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR); | ||
23 | return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA); | ||
24 | } | ||
25 | #endif | ||
26 | |||
27 | static void bcma_core_pcie2_cfg_write(struct bcma_drv_pcie2 *pcie2, u32 addr, | ||
28 | u32 val) | ||
29 | { | ||
30 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr); | ||
31 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, val); | ||
32 | } | ||
33 | |||
34 | /************************************************** | ||
35 | * Init. | ||
36 | **************************************************/ | ||
37 | |||
38 | static u32 bcma_core_pcie2_war_delay_perst_enab(struct bcma_drv_pcie2 *pcie2, | ||
39 | bool enable) | ||
40 | { | ||
41 | u32 val; | ||
42 | |||
43 | /* restore back to default */ | ||
44 | val = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL); | ||
45 | val |= PCIE2_CLKC_DLYPERST; | ||
46 | val &= ~PCIE2_CLKC_DISSPROMLD; | ||
47 | if (enable) { | ||
48 | val &= ~PCIE2_CLKC_DLYPERST; | ||
49 | val |= PCIE2_CLKC_DISSPROMLD; | ||
50 | } | ||
51 | pcie2_write32(pcie2, (BCMA_CORE_PCIE2_CLK_CONTROL), val); | ||
52 | /* flush */ | ||
53 | return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL); | ||
54 | } | ||
55 | |||
56 | static void bcma_core_pcie2_set_ltr_vals(struct bcma_drv_pcie2 *pcie2) | ||
57 | { | ||
58 | /* LTR0 */ | ||
59 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x844); | ||
60 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x883c883c); | ||
61 | /* LTR1 */ | ||
62 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x848); | ||
63 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x88648864); | ||
64 | /* LTR2 */ | ||
65 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x84C); | ||
66 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x90039003); | ||
67 | } | ||
68 | |||
69 | static void bcma_core_pcie2_hw_ltr_war(struct bcma_drv_pcie2 *pcie2) | ||
70 | { | ||
71 | u8 core_rev = pcie2->core->id.rev; | ||
72 | u32 devstsctr2; | ||
73 | |||
74 | if (core_rev < 2 || core_rev == 10 || core_rev > 13) | ||
75 | return; | ||
76 | |||
77 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, | ||
78 | PCIE2_CAP_DEVSTSCTRL2_OFFSET); | ||
79 | devstsctr2 = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA); | ||
80 | if (devstsctr2 & PCIE2_CAP_DEVSTSCTRL2_LTRENAB) { | ||
81 | /* force the right LTR values */ | ||
82 | bcma_core_pcie2_set_ltr_vals(pcie2); | ||
83 | |||
84 | /* TODO: | ||
85 | si_core_wrapperreg(pcie2, 3, 0x60, 0x8080, 0); */ | ||
86 | |||
87 | /* enable the LTR */ | ||
88 | devstsctr2 |= PCIE2_CAP_DEVSTSCTRL2_LTRENAB; | ||
89 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, | ||
90 | PCIE2_CAP_DEVSTSCTRL2_OFFSET); | ||
91 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, devstsctr2); | ||
92 | |||
93 | /* set the LTR state to be active */ | ||
94 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE, | ||
95 | PCIE2_LTR_ACTIVE); | ||
96 | usleep_range(1000, 2000); | ||
97 | |||
98 | /* set the LTR state to be sleep */ | ||
99 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE, | ||
100 | PCIE2_LTR_SLEEP); | ||
101 | usleep_range(1000, 2000); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | static void pciedev_crwlpciegen2(struct bcma_drv_pcie2 *pcie2) | ||
106 | { | ||
107 | u8 core_rev = pcie2->core->id.rev; | ||
108 | bool pciewar160, pciewar162; | ||
109 | |||
110 | pciewar160 = core_rev == 7 || core_rev == 9 || core_rev == 11; | ||
111 | pciewar162 = core_rev == 5 || core_rev == 7 || core_rev == 8 || | ||
112 | core_rev == 9 || core_rev == 11; | ||
113 | |||
114 | if (!pciewar160 && !pciewar162) | ||
115 | return; | ||
116 | |||
117 | /* TODO */ | ||
118 | #if 0 | ||
119 | pcie2_set32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL, | ||
120 | PCIE_DISABLE_L1CLK_GATING); | ||
121 | #if 0 | ||
122 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, | ||
123 | PCIEGEN2_COE_PVT_TL_CTRL_0); | ||
124 | pcie2_mask32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, | ||
125 | ~(1 << COE_PVT_TL_CTRL_0_PM_DIS_L1_REENTRY_BIT)); | ||
126 | #endif | ||
127 | #endif | ||
128 | } | ||
129 | |||
130 | static void pciedev_crwlpciegen2_180(struct bcma_drv_pcie2 *pcie2) | ||
131 | { | ||
132 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_PMCR_REFUP); | ||
133 | pcie2_set32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x1f); | ||
134 | } | ||
135 | |||
136 | static void pciedev_crwlpciegen2_182(struct bcma_drv_pcie2 *pcie2) | ||
137 | { | ||
138 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_SBMBX); | ||
139 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 1 << 0); | ||
140 | } | ||
141 | |||
142 | static void pciedev_reg_pm_clk_period(struct bcma_drv_pcie2 *pcie2) | ||
143 | { | ||
144 | struct bcma_drv_cc *drv_cc = &pcie2->core->bus->drv_cc; | ||
145 | u8 core_rev = pcie2->core->id.rev; | ||
146 | u32 alp_khz, pm_value; | ||
147 | |||
148 | if (core_rev <= 13) { | ||
149 | alp_khz = bcma_pmu_get_alp_clock(drv_cc) / 1000; | ||
150 | pm_value = (1000000 * 2) / alp_khz; | ||
151 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, | ||
152 | PCIE2_PVT_REG_PM_CLK_PERIOD); | ||
153 | pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, pm_value); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | void bcma_core_pcie2_init(struct bcma_drv_pcie2 *pcie2) | ||
158 | { | ||
159 | struct bcma_chipinfo *ci = &pcie2->core->bus->chipinfo; | ||
160 | u32 tmp; | ||
161 | |||
162 | tmp = pcie2_read32(pcie2, BCMA_CORE_PCIE2_SPROM(54)); | ||
163 | if ((tmp & 0xe) >> 1 == 2) | ||
164 | bcma_core_pcie2_cfg_write(pcie2, 0x4e0, 0x17); | ||
165 | |||
166 | /* TODO: Do we need pcie_reqsize? */ | ||
167 | |||
168 | if (ci->id == BCMA_CHIP_ID_BCM4360 && ci->rev > 3) | ||
169 | bcma_core_pcie2_war_delay_perst_enab(pcie2, true); | ||
170 | bcma_core_pcie2_hw_ltr_war(pcie2); | ||
171 | pciedev_crwlpciegen2(pcie2); | ||
172 | pciedev_reg_pm_clk_period(pcie2); | ||
173 | pciedev_crwlpciegen2_180(pcie2); | ||
174 | pciedev_crwlpciegen2_182(pcie2); | ||
175 | } | ||
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 34ea4c588d36..0ff8d58831ef 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c | |||
@@ -132,6 +132,7 @@ static int bcma_register_cores(struct bcma_bus *bus) | |||
132 | case BCMA_CORE_CHIPCOMMON: | 132 | case BCMA_CORE_CHIPCOMMON: |
133 | case BCMA_CORE_PCI: | 133 | case BCMA_CORE_PCI: |
134 | case BCMA_CORE_PCIE: | 134 | case BCMA_CORE_PCIE: |
135 | case BCMA_CORE_PCIE2: | ||
135 | case BCMA_CORE_MIPS_74K: | 136 | case BCMA_CORE_MIPS_74K: |
136 | case BCMA_CORE_4706_MAC_GBIT_COMMON: | 137 | case BCMA_CORE_4706_MAC_GBIT_COMMON: |
137 | continue; | 138 | continue; |
@@ -281,6 +282,13 @@ int bcma_bus_register(struct bcma_bus *bus) | |||
281 | bcma_core_pci_init(&bus->drv_pci[1]); | 282 | bcma_core_pci_init(&bus->drv_pci[1]); |
282 | } | 283 | } |
283 | 284 | ||
285 | /* Init PCIe Gen 2 core */ | ||
286 | core = bcma_find_core_unit(bus, BCMA_CORE_PCIE2, 0); | ||
287 | if (core) { | ||
288 | bus->drv_pcie2.core = core; | ||
289 | bcma_core_pcie2_init(&bus->drv_pcie2); | ||
290 | } | ||
291 | |||
284 | /* Init GBIT MAC COMMON core */ | 292 | /* Init GBIT MAC COMMON core */ |
285 | core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON); | 293 | core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON); |
286 | if (core) { | 294 | if (core) { |