diff options
-rw-r--r-- | MAINTAINERS | 6 | ||||
-rw-r--r-- | drivers/Kconfig | 2 | ||||
-rw-r--r-- | drivers/Makefile | 1 | ||||
-rw-r--r-- | drivers/ssb/Kconfig | 117 | ||||
-rw-r--r-- | drivers/ssb/Makefile | 18 | ||||
-rw-r--r-- | drivers/ssb/b43_pci_bridge.c | 46 | ||||
-rw-r--r-- | drivers/ssb/driver_chipcommon.c | 446 | ||||
-rw-r--r-- | drivers/ssb/driver_extif.c | 129 | ||||
-rw-r--r-- | drivers/ssb/driver_mipscore.c | 223 | ||||
-rw-r--r-- | drivers/ssb/driver_pcicore.c | 576 | ||||
-rw-r--r-- | drivers/ssb/main.c | 1162 | ||||
-rw-r--r-- | drivers/ssb/pci.c | 740 | ||||
-rw-r--r-- | drivers/ssb/pcihost_wrapper.c | 104 | ||||
-rw-r--r-- | drivers/ssb/pcmcia.c | 271 | ||||
-rw-r--r-- | drivers/ssb/scan.c | 413 | ||||
-rw-r--r-- | drivers/ssb/ssb_private.h | 136 | ||||
-rw-r--r-- | include/linux/mod_devicetable.h | 15 | ||||
-rw-r--r-- | include/linux/ssb/ssb.h | 424 | ||||
-rw-r--r-- | include/linux/ssb/ssb_driver_chipcommon.h | 396 | ||||
-rw-r--r-- | include/linux/ssb/ssb_driver_extif.h | 204 | ||||
-rw-r--r-- | include/linux/ssb/ssb_driver_mips.h | 46 | ||||
-rw-r--r-- | include/linux/ssb/ssb_driver_pci.h | 106 | ||||
-rw-r--r-- | include/linux/ssb/ssb_regs.h | 292 | ||||
-rw-r--r-- | scripts/mod/file2alias.c | 19 |
24 files changed, 5892 insertions, 0 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 3f07d5ff85f1..7524cd802da3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3446,6 +3446,12 @@ M: tsbogend@alpha.franken.de | |||
3446 | L: netdev@vger.kernel.org | 3446 | L: netdev@vger.kernel.org |
3447 | S: Maintained | 3447 | S: Maintained |
3448 | 3448 | ||
3449 | SONICS SILICON BACKPLANE DRIVER (SSB) | ||
3450 | P: Michael Buesch | ||
3451 | M: mb@bu3sch.de | ||
3452 | L: netdev@vger.kernel.org | ||
3453 | S: Maintained | ||
3454 | |||
3449 | SONY VAIO CONTROL DEVICE DRIVER | 3455 | SONY VAIO CONTROL DEVICE DRIVER |
3450 | P: Mattia Dongili | 3456 | P: Mattia Dongili |
3451 | M: malattia@linux.it | 3457 | M: malattia@linux.it |
diff --git a/drivers/Kconfig b/drivers/Kconfig index 3e1c442deff9..7bdae47d6b91 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
@@ -58,6 +58,8 @@ source "drivers/power/Kconfig" | |||
58 | 58 | ||
59 | source "drivers/hwmon/Kconfig" | 59 | source "drivers/hwmon/Kconfig" |
60 | 60 | ||
61 | source "drivers/ssb/Kconfig" | ||
62 | |||
61 | source "drivers/mfd/Kconfig" | 63 | source "drivers/mfd/Kconfig" |
62 | 64 | ||
63 | source "drivers/media/Kconfig" | 65 | source "drivers/media/Kconfig" |
diff --git a/drivers/Makefile b/drivers/Makefile index f0878b2ec55e..a168eacdcd9c 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -88,3 +88,4 @@ obj-$(CONFIG_DMA_ENGINE) += dma/ | |||
88 | obj-$(CONFIG_HID) += hid/ | 88 | obj-$(CONFIG_HID) += hid/ |
89 | obj-$(CONFIG_PPC_PS3) += ps3/ | 89 | obj-$(CONFIG_PPC_PS3) += ps3/ |
90 | obj-$(CONFIG_OF) += of/ | 90 | obj-$(CONFIG_OF) += of/ |
91 | obj-$(CONFIG_SSB) += ssb/ | ||
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig new file mode 100644 index 000000000000..b4a5e5e9d9fc --- /dev/null +++ b/drivers/ssb/Kconfig | |||
@@ -0,0 +1,117 @@ | |||
1 | menu "Sonics Silicon Backplane" | ||
2 | |||
3 | config SSB_POSSIBLE | ||
4 | bool | ||
5 | depends on HAS_IOMEM | ||
6 | default y | ||
7 | |||
8 | config SSB | ||
9 | tristate "Sonics Silicon Backplane support" | ||
10 | depends on SSB_POSSIBLE | ||
11 | help | ||
12 | Support for the Sonics Silicon Backplane bus. | ||
13 | You only need to enable this option, if you are | ||
14 | configuring a kernel for an embedded system with | ||
15 | this bus. | ||
16 | It will be auto-selected if needed in other | ||
17 | environments. | ||
18 | |||
19 | The module will be called ssb. | ||
20 | |||
21 | If unsure, say N. | ||
22 | |||
23 | config SSB_PCIHOST_POSSIBLE | ||
24 | bool | ||
25 | depends on SSB && PCI | ||
26 | default y | ||
27 | |||
28 | config SSB_PCIHOST | ||
29 | bool "Support for SSB on PCI-bus host" | ||
30 | depends on SSB_PCIHOST_POSSIBLE | ||
31 | default y | ||
32 | help | ||
33 | Support for a Sonics Silicon Backplane on top | ||
34 | of a PCI device. | ||
35 | |||
36 | If unsure, say Y | ||
37 | |||
38 | config SSB_PCMCIAHOST_POSSIBLE | ||
39 | bool | ||
40 | depends on SSB && PCMCIA && EXPERIMENTAL | ||
41 | default y | ||
42 | |||
43 | config SSB_PCMCIAHOST | ||
44 | bool "Support for SSB on PCMCIA-bus host (EXPERIMENTAL)" | ||
45 | depends on SSB_PCMCIAHOST_POSSIBLE | ||
46 | help | ||
47 | Support for a Sonics Silicon Backplane on top | ||
48 | of a PCMCIA device. | ||
49 | |||
50 | If unsure, say N | ||
51 | |||
52 | config SSB_SILENT | ||
53 | bool "No SSB kernel messages" | ||
54 | depends on SSB && EMBEDDED | ||
55 | help | ||
56 | This option turns off all Sonics Silicon Backplane printks. | ||
57 | Note that you won't be able to identify problems, once | ||
58 | messages are turned off. | ||
59 | This might only be desired for production kernels on | ||
60 | embedded devices to reduce the kernel size. | ||
61 | |||
62 | Say N | ||
63 | |||
64 | config SSB_DEBUG | ||
65 | bool "SSB debugging" | ||
66 | depends on SSB && !SSB_SILENT | ||
67 | help | ||
68 | This turns on additional runtime checks and debugging | ||
69 | messages. Turn this on for SSB troubleshooting. | ||
70 | |||
71 | If unsure, say N | ||
72 | |||
73 | config SSB_SERIAL | ||
74 | bool | ||
75 | depends on SSB | ||
76 | # ChipCommon and ExtIf serial support routines. | ||
77 | |||
78 | config SSB_DRIVER_PCICORE_POSSIBLE | ||
79 | bool | ||
80 | depends on SSB_PCIHOST | ||
81 | default y | ||
82 | |||
83 | config SSB_DRIVER_PCICORE | ||
84 | bool "SSB PCI core driver" | ||
85 | depends on SSB_DRIVER_PCICORE_POSSIBLE | ||
86 | help | ||
87 | Driver for the Sonics Silicon Backplane attached | ||
88 | Broadcom PCI core. | ||
89 | |||
90 | If unsure, say Y | ||
91 | |||
92 | config SSB_PCICORE_HOSTMODE | ||
93 | bool "Hostmode support for SSB PCI core (EXPERIMENTAL)" | ||
94 | depends on SSB_DRIVER_PCICORE && SSB_DRIVER_MIPS && EXPERIMENTAL | ||
95 | help | ||
96 | PCIcore hostmode operation (external PCI bus). | ||
97 | |||
98 | config SSB_DRIVER_MIPS | ||
99 | bool "SSB Broadcom MIPS core driver (EXPERIMENTAL)" | ||
100 | depends on SSB && MIPS && EXPERIMENTAL | ||
101 | select SSB_SERIAL | ||
102 | help | ||
103 | Driver for the Sonics Silicon Backplane attached | ||
104 | Broadcom MIPS core. | ||
105 | |||
106 | If unsure, say N | ||
107 | |||
108 | config SSB_DRIVER_EXTIF | ||
109 | bool "SSB Broadcom EXTIF core driver (EXPERIMENTAL)" | ||
110 | depends on SSB_DRIVER_MIPS && EXPERIMENTAL | ||
111 | help | ||
112 | Driver for the Sonics Silicon Backplane attached | ||
113 | Broadcom EXTIF core. | ||
114 | |||
115 | If unsure, say N | ||
116 | |||
117 | endmenu | ||
diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile new file mode 100644 index 000000000000..7be397595805 --- /dev/null +++ b/drivers/ssb/Makefile | |||
@@ -0,0 +1,18 @@ | |||
1 | # core | ||
2 | ssb-y += main.o scan.o | ||
3 | |||
4 | # host support | ||
5 | ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o | ||
6 | ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o | ||
7 | |||
8 | # built-in drivers | ||
9 | ssb-y += driver_chipcommon.o | ||
10 | ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o | ||
11 | ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o | ||
12 | ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o | ||
13 | |||
14 | # b43 pci-ssb-bridge driver | ||
15 | # Not strictly a part of SSB, but kept here for convenience | ||
16 | ssb-$(CONFIG_SSB_PCIHOST) += b43_pci_bridge.o | ||
17 | |||
18 | obj-$(CONFIG_SSB) += ssb.o | ||
diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c new file mode 100644 index 000000000000..fa3bd292f5f7 --- /dev/null +++ b/drivers/ssb/b43_pci_bridge.c | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * Broadcom 43xx PCI-SSB bridge module | ||
3 | * | ||
4 | * This technically is a seperate PCI driver module, but | ||
5 | * because of its small size we include it in the SSB core | ||
6 | * instead of creating a standalone module. | ||
7 | * | ||
8 | * Copyright 2007 Michael Buesch <mb@bu3sch.de> | ||
9 | * | ||
10 | * Licensed under the GNU/GPL. See COPYING for details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/pci.h> | ||
14 | #include <linux/ssb/ssb.h> | ||
15 | |||
16 | |||
17 | static const struct pci_device_id b43_pci_bridge_tbl[] = { | ||
18 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4301) }, | ||
19 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4307) }, | ||
20 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4311) }, | ||
21 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4312) }, | ||
22 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4318) }, | ||
23 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) }, | ||
24 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) }, | ||
25 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) }, | ||
26 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) }, | ||
27 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) }, | ||
28 | { 0, }, | ||
29 | }; | ||
30 | MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl); | ||
31 | |||
32 | static struct pci_driver b43_pci_bridge_driver = { | ||
33 | .name = "b43-pci-bridge", | ||
34 | .id_table = b43_pci_bridge_tbl, | ||
35 | }; | ||
36 | |||
37 | |||
38 | int __init b43_pci_ssb_bridge_init(void) | ||
39 | { | ||
40 | return ssb_pcihost_register(&b43_pci_bridge_driver); | ||
41 | } | ||
42 | |||
43 | void __exit b43_pci_ssb_bridge_exit(void) | ||
44 | { | ||
45 | ssb_pcihost_unregister(&b43_pci_bridge_driver); | ||
46 | } | ||
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c new file mode 100644 index 000000000000..a890544e8fba --- /dev/null +++ b/drivers/ssb/driver_chipcommon.c | |||
@@ -0,0 +1,446 @@ | |||
1 | /* | ||
2 | * Sonics Silicon Backplane | ||
3 | * Broadcom ChipCommon core driver | ||
4 | * | ||
5 | * Copyright 2005, Broadcom Corporation | ||
6 | * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de> | ||
7 | * | ||
8 | * Licensed under the GNU/GPL. See COPYING for details. | ||
9 | */ | ||
10 | |||
11 | #include <linux/ssb/ssb.h> | ||
12 | #include <linux/ssb/ssb_regs.h> | ||
13 | #include <linux/pci.h> | ||
14 | |||
15 | #include "ssb_private.h" | ||
16 | |||
17 | |||
18 | /* Clock sources */ | ||
19 | enum ssb_clksrc { | ||
20 | /* PCI clock */ | ||
21 | SSB_CHIPCO_CLKSRC_PCI, | ||
22 | /* Crystal slow clock oscillator */ | ||
23 | SSB_CHIPCO_CLKSRC_XTALOS, | ||
24 | /* Low power oscillator */ | ||
25 | SSB_CHIPCO_CLKSRC_LOPWROS, | ||
26 | }; | ||
27 | |||
28 | |||
29 | static inline u32 chipco_read32(struct ssb_chipcommon *cc, | ||
30 | u16 offset) | ||
31 | { | ||
32 | return ssb_read32(cc->dev, offset); | ||
33 | } | ||
34 | |||
35 | static inline void chipco_write32(struct ssb_chipcommon *cc, | ||
36 | u16 offset, | ||
37 | u32 value) | ||
38 | { | ||
39 | ssb_write32(cc->dev, offset, value); | ||
40 | } | ||
41 | |||
42 | static inline void chipco_write32_masked(struct ssb_chipcommon *cc, u16 offset, | ||
43 | u32 mask, u32 value) | ||
44 | { | ||
45 | value &= mask; | ||
46 | value |= chipco_read32(cc, offset) & ~mask; | ||
47 | chipco_write32(cc, offset, value); | ||
48 | } | ||
49 | |||
50 | void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, | ||
51 | enum ssb_clkmode mode) | ||
52 | { | ||
53 | struct ssb_device *ccdev = cc->dev; | ||
54 | struct ssb_bus *bus; | ||
55 | u32 tmp; | ||
56 | |||
57 | if (!ccdev) | ||
58 | return; | ||
59 | bus = ccdev->bus; | ||
60 | /* chipcommon cores prior to rev6 don't support dynamic clock control */ | ||
61 | if (ccdev->id.revision < 6) | ||
62 | return; | ||
63 | /* chipcommon cores rev10 are a whole new ball game */ | ||
64 | if (ccdev->id.revision >= 10) | ||
65 | return; | ||
66 | if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL)) | ||
67 | return; | ||
68 | |||
69 | switch (mode) { | ||
70 | case SSB_CLKMODE_SLOW: | ||
71 | tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); | ||
72 | tmp |= SSB_CHIPCO_SLOWCLKCTL_FSLOW; | ||
73 | chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); | ||
74 | break; | ||
75 | case SSB_CLKMODE_FAST: | ||
76 | ssb_pci_xtal(bus, SSB_GPIO_XTAL, 1); /* Force crystal on */ | ||
77 | tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); | ||
78 | tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW; | ||
79 | tmp |= SSB_CHIPCO_SLOWCLKCTL_IPLL; | ||
80 | chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); | ||
81 | break; | ||
82 | case SSB_CLKMODE_DYNAMIC: | ||
83 | tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); | ||
84 | tmp &= ~SSB_CHIPCO_SLOWCLKCTL_FSLOW; | ||
85 | tmp &= ~SSB_CHIPCO_SLOWCLKCTL_IPLL; | ||
86 | tmp &= ~SSB_CHIPCO_SLOWCLKCTL_ENXTAL; | ||
87 | if ((tmp & SSB_CHIPCO_SLOWCLKCTL_SRC) != SSB_CHIPCO_SLOWCLKCTL_SRC_XTAL) | ||
88 | tmp |= SSB_CHIPCO_SLOWCLKCTL_ENXTAL; | ||
89 | chipco_write32(cc, SSB_CHIPCO_SLOWCLKCTL, tmp); | ||
90 | |||
91 | /* for dynamic control, we have to release our xtal_pu "force on" */ | ||
92 | if (tmp & SSB_CHIPCO_SLOWCLKCTL_ENXTAL) | ||
93 | ssb_pci_xtal(bus, SSB_GPIO_XTAL, 0); | ||
94 | break; | ||
95 | default: | ||
96 | SSB_WARN_ON(1); | ||
97 | } | ||
98 | } | ||
99 | |||
100 | /* Get the Slow Clock Source */ | ||
101 | static enum ssb_clksrc chipco_pctl_get_slowclksrc(struct ssb_chipcommon *cc) | ||
102 | { | ||
103 | struct ssb_bus *bus = cc->dev->bus; | ||
104 | u32 uninitialized_var(tmp); | ||
105 | |||
106 | if (cc->dev->id.revision < 6) { | ||
107 | if (bus->bustype == SSB_BUSTYPE_SSB || | ||
108 | bus->bustype == SSB_BUSTYPE_PCMCIA) | ||
109 | return SSB_CHIPCO_CLKSRC_XTALOS; | ||
110 | if (bus->bustype == SSB_BUSTYPE_PCI) { | ||
111 | pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &tmp); | ||
112 | if (tmp & 0x10) | ||
113 | return SSB_CHIPCO_CLKSRC_PCI; | ||
114 | return SSB_CHIPCO_CLKSRC_XTALOS; | ||
115 | } | ||
116 | } | ||
117 | if (cc->dev->id.revision < 10) { | ||
118 | tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); | ||
119 | tmp &= 0x7; | ||
120 | if (tmp == 0) | ||
121 | return SSB_CHIPCO_CLKSRC_LOPWROS; | ||
122 | if (tmp == 1) | ||
123 | return SSB_CHIPCO_CLKSRC_XTALOS; | ||
124 | if (tmp == 2) | ||
125 | return SSB_CHIPCO_CLKSRC_PCI; | ||
126 | } | ||
127 | |||
128 | return SSB_CHIPCO_CLKSRC_XTALOS; | ||
129 | } | ||
130 | |||
131 | /* Get maximum or minimum (depending on get_max flag) slowclock frequency. */ | ||
132 | static int chipco_pctl_clockfreqlimit(struct ssb_chipcommon *cc, int get_max) | ||
133 | { | ||
134 | int uninitialized_var(limit); | ||
135 | enum ssb_clksrc clocksrc; | ||
136 | int divisor = 1; | ||
137 | u32 tmp; | ||
138 | |||
139 | clocksrc = chipco_pctl_get_slowclksrc(cc); | ||
140 | if (cc->dev->id.revision < 6) { | ||
141 | switch (clocksrc) { | ||
142 | case SSB_CHIPCO_CLKSRC_PCI: | ||
143 | divisor = 64; | ||
144 | break; | ||
145 | case SSB_CHIPCO_CLKSRC_XTALOS: | ||
146 | divisor = 32; | ||
147 | break; | ||
148 | default: | ||
149 | SSB_WARN_ON(1); | ||
150 | } | ||
151 | } else if (cc->dev->id.revision < 10) { | ||
152 | switch (clocksrc) { | ||
153 | case SSB_CHIPCO_CLKSRC_LOPWROS: | ||
154 | break; | ||
155 | case SSB_CHIPCO_CLKSRC_XTALOS: | ||
156 | case SSB_CHIPCO_CLKSRC_PCI: | ||
157 | tmp = chipco_read32(cc, SSB_CHIPCO_SLOWCLKCTL); | ||
158 | divisor = (tmp >> 16) + 1; | ||
159 | divisor *= 4; | ||
160 | break; | ||
161 | } | ||
162 | } else { | ||
163 | tmp = chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL); | ||
164 | divisor = (tmp >> 16) + 1; | ||
165 | divisor *= 4; | ||
166 | } | ||
167 | |||
168 | switch (clocksrc) { | ||
169 | case SSB_CHIPCO_CLKSRC_LOPWROS: | ||
170 | if (get_max) | ||
171 | limit = 43000; | ||
172 | else | ||
173 | limit = 25000; | ||
174 | break; | ||
175 | case SSB_CHIPCO_CLKSRC_XTALOS: | ||
176 | if (get_max) | ||
177 | limit = 20200000; | ||
178 | else | ||
179 | limit = 19800000; | ||
180 | break; | ||
181 | case SSB_CHIPCO_CLKSRC_PCI: | ||
182 | if (get_max) | ||
183 | limit = 34000000; | ||
184 | else | ||
185 | limit = 25000000; | ||
186 | break; | ||
187 | } | ||
188 | limit /= divisor; | ||
189 | |||
190 | return limit; | ||
191 | } | ||
192 | |||
193 | static void chipco_powercontrol_init(struct ssb_chipcommon *cc) | ||
194 | { | ||
195 | struct ssb_bus *bus = cc->dev->bus; | ||
196 | |||
197 | if (bus->chip_id == 0x4321) { | ||
198 | if (bus->chip_rev == 0) | ||
199 | chipco_write32(cc, SSB_CHIPCO_CHIPCTL, 0x3A4); | ||
200 | else if (bus->chip_rev == 1) | ||
201 | chipco_write32(cc, SSB_CHIPCO_CHIPCTL, 0xA4); | ||
202 | } | ||
203 | |||
204 | if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL)) | ||
205 | return; | ||
206 | |||
207 | if (cc->dev->id.revision >= 10) { | ||
208 | /* Set Idle Power clock rate to 1Mhz */ | ||
209 | chipco_write32(cc, SSB_CHIPCO_SYSCLKCTL, | ||
210 | (chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL) & | ||
211 | 0x0000FFFF) | 0x00040000); | ||
212 | } else { | ||
213 | int maxfreq; | ||
214 | |||
215 | maxfreq = chipco_pctl_clockfreqlimit(cc, 1); | ||
216 | chipco_write32(cc, SSB_CHIPCO_PLLONDELAY, | ||
217 | (maxfreq * 150 + 999999) / 1000000); | ||
218 | chipco_write32(cc, SSB_CHIPCO_FREFSELDELAY, | ||
219 | (maxfreq * 15 + 999999) / 1000000); | ||
220 | } | ||
221 | } | ||
222 | |||
223 | static void calc_fast_powerup_delay(struct ssb_chipcommon *cc) | ||
224 | { | ||
225 | struct ssb_bus *bus = cc->dev->bus; | ||
226 | int minfreq; | ||
227 | unsigned int tmp; | ||
228 | u32 pll_on_delay; | ||
229 | |||
230 | if (bus->bustype != SSB_BUSTYPE_PCI) | ||
231 | return; | ||
232 | if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL)) | ||
233 | return; | ||
234 | |||
235 | minfreq = chipco_pctl_clockfreqlimit(cc, 0); | ||
236 | pll_on_delay = chipco_read32(cc, SSB_CHIPCO_PLLONDELAY); | ||
237 | tmp = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq; | ||
238 | SSB_WARN_ON(tmp & ~0xFFFF); | ||
239 | |||
240 | cc->fast_pwrup_delay = tmp; | ||
241 | } | ||
242 | |||
243 | void ssb_chipcommon_init(struct ssb_chipcommon *cc) | ||
244 | { | ||
245 | if (!cc->dev) | ||
246 | return; /* We don't have a ChipCommon */ | ||
247 | chipco_powercontrol_init(cc); | ||
248 | ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); | ||
249 | calc_fast_powerup_delay(cc); | ||
250 | } | ||
251 | |||
252 | void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state) | ||
253 | { | ||
254 | if (!cc->dev) | ||
255 | return; | ||
256 | ssb_chipco_set_clockmode(cc, SSB_CLKMODE_SLOW); | ||
257 | } | ||
258 | |||
259 | void ssb_chipco_resume(struct ssb_chipcommon *cc) | ||
260 | { | ||
261 | if (!cc->dev) | ||
262 | return; | ||
263 | chipco_powercontrol_init(cc); | ||
264 | ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); | ||
265 | } | ||
266 | |||
267 | /* Get the processor clock */ | ||
268 | void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc, | ||
269 | u32 *plltype, u32 *n, u32 *m) | ||
270 | { | ||
271 | *n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N); | ||
272 | *plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT); | ||
273 | switch (*plltype) { | ||
274 | case SSB_PLLTYPE_2: | ||
275 | case SSB_PLLTYPE_4: | ||
276 | case SSB_PLLTYPE_6: | ||
277 | case SSB_PLLTYPE_7: | ||
278 | *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_MIPS); | ||
279 | break; | ||
280 | case SSB_PLLTYPE_3: | ||
281 | /* 5350 uses m2 to control mips */ | ||
282 | *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_M2); | ||
283 | break; | ||
284 | default: | ||
285 | *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_SB); | ||
286 | break; | ||
287 | } | ||
288 | } | ||
289 | |||
290 | /* Get the bus clock */ | ||
291 | void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc, | ||
292 | u32 *plltype, u32 *n, u32 *m) | ||
293 | { | ||
294 | *n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N); | ||
295 | *plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT); | ||
296 | switch (*plltype) { | ||
297 | case SSB_PLLTYPE_6: /* 100/200 or 120/240 only */ | ||
298 | *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_MIPS); | ||
299 | break; | ||
300 | case SSB_PLLTYPE_3: /* 25Mhz, 2 dividers */ | ||
301 | if (cc->dev->bus->chip_id != 0x5365) { | ||
302 | *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_M2); | ||
303 | break; | ||
304 | } | ||
305 | /* Fallthough */ | ||
306 | default: | ||
307 | *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_SB); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | void ssb_chipco_timing_init(struct ssb_chipcommon *cc, | ||
312 | unsigned long ns) | ||
313 | { | ||
314 | struct ssb_device *dev = cc->dev; | ||
315 | struct ssb_bus *bus = dev->bus; | ||
316 | u32 tmp; | ||
317 | |||
318 | /* set register for external IO to control LED. */ | ||
319 | chipco_write32(cc, SSB_CHIPCO_PROG_CFG, 0x11); | ||
320 | tmp = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT; /* Waitcount-3 = 10ns */ | ||
321 | tmp |= DIV_ROUND_UP(40, ns) << SSB_PROG_WCNT_1_SHIFT; /* Waitcount-1 = 40ns */ | ||
322 | tmp |= DIV_ROUND_UP(240, ns); /* Waitcount-0 = 240ns */ | ||
323 | chipco_write32(cc, SSB_CHIPCO_PROG_WAITCNT, tmp); /* 0x01020a0c for a 100Mhz clock */ | ||
324 | |||
325 | /* Set timing for the flash */ | ||
326 | tmp = DIV_ROUND_UP(10, ns) << SSB_FLASH_WCNT_3_SHIFT; /* Waitcount-3 = 10nS */ | ||
327 | tmp |= DIV_ROUND_UP(10, ns) << SSB_FLASH_WCNT_1_SHIFT; /* Waitcount-1 = 10nS */ | ||
328 | tmp |= DIV_ROUND_UP(120, ns); /* Waitcount-0 = 120nS */ | ||
329 | if ((bus->chip_id == 0x5365) || | ||
330 | (dev->id.revision < 9)) | ||
331 | chipco_write32(cc, SSB_CHIPCO_FLASH_WAITCNT, tmp); | ||
332 | if ((bus->chip_id == 0x5365) || | ||
333 | (dev->id.revision < 9) || | ||
334 | ((bus->chip_id == 0x5350) && (bus->chip_rev == 0))) | ||
335 | chipco_write32(cc, SSB_CHIPCO_PCMCIA_MEMWAIT, tmp); | ||
336 | |||
337 | if (bus->chip_id == 0x5350) { | ||
338 | /* Enable EXTIF */ | ||
339 | tmp = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT; /* Waitcount-3 = 10ns */ | ||
340 | tmp |= DIV_ROUND_UP(20, ns) << SSB_PROG_WCNT_2_SHIFT; /* Waitcount-2 = 20ns */ | ||
341 | tmp |= DIV_ROUND_UP(100, ns) << SSB_PROG_WCNT_1_SHIFT; /* Waitcount-1 = 100ns */ | ||
342 | tmp |= DIV_ROUND_UP(120, ns); /* Waitcount-0 = 120ns */ | ||
343 | chipco_write32(cc, SSB_CHIPCO_PROG_WAITCNT, tmp); /* 0x01020a0c for a 100Mhz clock */ | ||
344 | } | ||
345 | } | ||
346 | |||
347 | /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ | ||
348 | void | ||
349 | ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks) | ||
350 | { | ||
351 | /* instant NMI */ | ||
352 | chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks); | ||
353 | } | ||
354 | |||
355 | u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask) | ||
356 | { | ||
357 | return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask; | ||
358 | } | ||
359 | |||
360 | void ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value) | ||
361 | { | ||
362 | return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value); | ||
363 | } | ||
364 | |||
365 | void ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value) | ||
366 | { | ||
367 | return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value); | ||
368 | } | ||
369 | |||
370 | #ifdef CONFIG_SSB_SERIAL | ||
371 | int ssb_chipco_serial_init(struct ssb_chipcommon *cc, | ||
372 | struct ssb_serial_port *ports) | ||
373 | { | ||
374 | struct ssb_bus *bus = cc->dev->bus; | ||
375 | int nr_ports = 0; | ||
376 | u32 plltype; | ||
377 | unsigned int irq; | ||
378 | u32 baud_base, div; | ||
379 | u32 i, n; | ||
380 | |||
381 | plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT); | ||
382 | irq = ssb_mips_irq(cc->dev); | ||
383 | |||
384 | if (plltype == SSB_PLLTYPE_1) { | ||
385 | /* PLL clock */ | ||
386 | baud_base = ssb_calc_clock_rate(plltype, | ||
387 | chipco_read32(cc, SSB_CHIPCO_CLOCK_N), | ||
388 | chipco_read32(cc, SSB_CHIPCO_CLOCK_M2)); | ||
389 | div = 1; | ||
390 | } else { | ||
391 | if (cc->dev->id.revision >= 11) { | ||
392 | /* Fixed ALP clock */ | ||
393 | baud_base = 20000000; | ||
394 | div = 1; | ||
395 | /* Set the override bit so we don't divide it */ | ||
396 | chipco_write32(cc, SSB_CHIPCO_CORECTL, | ||
397 | SSB_CHIPCO_CORECTL_UARTCLK0); | ||
398 | } else if (cc->dev->id.revision >= 3) { | ||
399 | /* Internal backplane clock */ | ||
400 | baud_base = ssb_clockspeed(bus); | ||
401 | div = chipco_read32(cc, SSB_CHIPCO_CLKDIV) | ||
402 | & SSB_CHIPCO_CLKDIV_UART; | ||
403 | } else { | ||
404 | /* Fixed internal backplane clock */ | ||
405 | baud_base = 88000000; | ||
406 | div = 48; | ||
407 | } | ||
408 | |||
409 | /* Clock source depends on strapping if UartClkOverride is unset */ | ||
410 | if ((cc->dev->id.revision > 0) && | ||
411 | !(chipco_read32(cc, SSB_CHIPCO_CORECTL) & SSB_CHIPCO_CORECTL_UARTCLK0)) { | ||
412 | if ((cc->capabilities & SSB_CHIPCO_CAP_UARTCLK) == | ||
413 | SSB_CHIPCO_CAP_UARTCLK_INT) { | ||
414 | /* Internal divided backplane clock */ | ||
415 | baud_base /= div; | ||
416 | } else { | ||
417 | /* Assume external clock of 1.8432 MHz */ | ||
418 | baud_base = 1843200; | ||
419 | } | ||
420 | } | ||
421 | } | ||
422 | |||
423 | /* Determine the registers of the UARTs */ | ||
424 | n = (cc->capabilities & SSB_CHIPCO_CAP_NRUART); | ||
425 | for (i = 0; i < n; i++) { | ||
426 | void __iomem *cc_mmio; | ||
427 | void __iomem *uart_regs; | ||
428 | |||
429 | cc_mmio = cc->dev->bus->mmio + (cc->dev->core_index * SSB_CORE_SIZE); | ||
430 | uart_regs = cc_mmio + SSB_CHIPCO_UART0_DATA; | ||
431 | /* Offset changed at after rev 0 */ | ||
432 | if (cc->dev->id.revision == 0) | ||
433 | uart_regs += (i * 8); | ||
434 | else | ||
435 | uart_regs += (i * 256); | ||
436 | |||
437 | nr_ports++; | ||
438 | ports[i].regs = uart_regs; | ||
439 | ports[i].irq = irq; | ||
440 | ports[i].baud_base = baud_base; | ||
441 | ports[i].reg_shift = 0; | ||
442 | } | ||
443 | |||
444 | return nr_ports; | ||
445 | } | ||
446 | #endif /* CONFIG_SSB_SERIAL */ | ||
diff --git a/drivers/ssb/driver_extif.c b/drivers/ssb/driver_extif.c new file mode 100644 index 000000000000..fe55eb8b038a --- /dev/null +++ b/drivers/ssb/driver_extif.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Sonics Silicon Backplane | ||
3 | * Broadcom EXTIF core driver | ||
4 | * | ||
5 | * Copyright 2005, Broadcom Corporation | ||
6 | * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de> | ||
7 | * Copyright 2006, 2007, Felix Fietkau <nbd@openwrt.org> | ||
8 | * Copyright 2007, Aurelien Jarno <aurelien@aurel32.net> | ||
9 | * | ||
10 | * Licensed under the GNU/GPL. See COPYING for details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/serial.h> | ||
14 | #include <linux/serial_core.h> | ||
15 | #include <linux/serial_reg.h> | ||
16 | |||
17 | #include "ssb_private.h" | ||
18 | |||
19 | |||
20 | static inline u32 extif_read32(struct ssb_extif *extif, u16 offset) | ||
21 | { | ||
22 | return ssb_read32(extif->dev, offset); | ||
23 | } | ||
24 | |||
25 | static inline void extif_write32(struct ssb_extif *extif, u16 offset, u32 value) | ||
26 | { | ||
27 | ssb_write32(extif->dev, offset, value); | ||
28 | } | ||
29 | |||
30 | static inline void extif_write32_masked(struct ssb_extif *extif, u16 offset, | ||
31 | u32 mask, u32 value) | ||
32 | { | ||
33 | value &= mask; | ||
34 | value |= extif_read32(extif, offset) & ~mask; | ||
35 | extif_write32(extif, offset, value); | ||
36 | } | ||
37 | |||
38 | #ifdef CONFIG_SSB_SERIAL | ||
39 | static bool serial_exists(u8 *regs) | ||
40 | { | ||
41 | u8 save_mcr, msr = 0; | ||
42 | |||
43 | if (regs) { | ||
44 | save_mcr = regs[UART_MCR]; | ||
45 | regs[UART_MCR] = (UART_MCR_LOOP | UART_MCR_OUT2 | UART_MCR_RTS); | ||
46 | msr = regs[UART_MSR] & (UART_MSR_DCD | UART_MSR_RI | ||
47 | | UART_MSR_CTS | UART_MSR_DSR); | ||
48 | regs[UART_MCR] = save_mcr; | ||
49 | } | ||
50 | return (msr == (UART_MSR_DCD | UART_MSR_CTS)); | ||
51 | } | ||
52 | |||
53 | int ssb_extif_serial_init(struct ssb_extif *extif, struct ssb_serial_port *ports) | ||
54 | { | ||
55 | u32 i, nr_ports = 0; | ||
56 | |||
57 | /* Disable GPIO interrupt initially */ | ||
58 | extif_write32(extif, SSB_EXTIF_GPIO_INTPOL, 0); | ||
59 | extif_write32(extif, SSB_EXTIF_GPIO_INTMASK, 0); | ||
60 | |||
61 | for (i = 0; i < 2; i++) { | ||
62 | void __iomem *uart_regs; | ||
63 | |||
64 | uart_regs = ioremap_nocache(SSB_EUART, 16); | ||
65 | if (uart_regs) { | ||
66 | uart_regs += (i * 8); | ||
67 | |||
68 | if (serial_exists(uart_regs) && ports) { | ||
69 | extif_write32(extif, SSB_EXTIF_GPIO_INTMASK, 2); | ||
70 | |||
71 | nr_ports++; | ||
72 | ports[i].regs = uart_regs; | ||
73 | ports[i].irq = 2; | ||
74 | ports[i].baud_base = 13500000; | ||
75 | ports[i].reg_shift = 0; | ||
76 | } | ||
77 | iounmap(uart_regs); | ||
78 | } | ||
79 | } | ||
80 | return nr_ports; | ||
81 | } | ||
82 | #endif /* CONFIG_SSB_SERIAL */ | ||
83 | |||
84 | void ssb_extif_timing_init(struct ssb_extif *extif, unsigned long ns) | ||
85 | { | ||
86 | u32 tmp; | ||
87 | |||
88 | /* Initialize extif so we can get to the LEDs and external UART */ | ||
89 | extif_write32(extif, SSB_EXTIF_PROG_CFG, SSB_EXTCFG_EN); | ||
90 | |||
91 | /* Set timing for the flash */ | ||
92 | tmp = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT; | ||
93 | tmp |= DIV_ROUND_UP(40, ns) << SSB_PROG_WCNT_1_SHIFT; | ||
94 | tmp |= DIV_ROUND_UP(120, ns); | ||
95 | extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp); | ||
96 | |||
97 | /* Set programmable interface timing for external uart */ | ||
98 | tmp = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT; | ||
99 | tmp |= DIV_ROUND_UP(20, ns) << SSB_PROG_WCNT_2_SHIFT; | ||
100 | tmp |= DIV_ROUND_UP(100, ns) << SSB_PROG_WCNT_1_SHIFT; | ||
101 | tmp |= DIV_ROUND_UP(120, ns); | ||
102 | extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp); | ||
103 | } | ||
104 | |||
105 | void ssb_extif_get_clockcontrol(struct ssb_extif *extif, | ||
106 | u32 *pll_type, u32 *n, u32 *m) | ||
107 | { | ||
108 | *pll_type = SSB_PLLTYPE_1; | ||
109 | *n = extif_read32(extif, SSB_EXTIF_CLOCK_N); | ||
110 | *m = extif_read32(extif, SSB_EXTIF_CLOCK_SB); | ||
111 | } | ||
112 | |||
113 | u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) | ||
114 | { | ||
115 | return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask; | ||
116 | } | ||
117 | |||
118 | void ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value) | ||
119 | { | ||
120 | return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0), | ||
121 | mask, value); | ||
122 | } | ||
123 | |||
124 | void ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value) | ||
125 | { | ||
126 | return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0), | ||
127 | mask, value); | ||
128 | } | ||
129 | |||
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c new file mode 100644 index 000000000000..ab8691a32580 --- /dev/null +++ b/drivers/ssb/driver_mipscore.c | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * Sonics Silicon Backplane | ||
3 | * Broadcom MIPS core driver | ||
4 | * | ||
5 | * Copyright 2005, Broadcom Corporation | ||
6 | * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de> | ||
7 | * | ||
8 | * Licensed under the GNU/GPL. See COPYING for details. | ||
9 | */ | ||
10 | |||
11 | #include <linux/ssb/ssb.h> | ||
12 | |||
13 | #include <linux/serial.h> | ||
14 | #include <linux/serial_core.h> | ||
15 | #include <linux/serial_reg.h> | ||
16 | #include <linux/time.h> | ||
17 | |||
18 | #include "ssb_private.h" | ||
19 | |||
20 | |||
21 | static inline u32 mips_read32(struct ssb_mipscore *mcore, | ||
22 | u16 offset) | ||
23 | { | ||
24 | return ssb_read32(mcore->dev, offset); | ||
25 | } | ||
26 | |||
27 | static inline void mips_write32(struct ssb_mipscore *mcore, | ||
28 | u16 offset, | ||
29 | u32 value) | ||
30 | { | ||
31 | ssb_write32(mcore->dev, offset, value); | ||
32 | } | ||
33 | |||
34 | static const u32 ipsflag_irq_mask[] = { | ||
35 | 0, | ||
36 | SSB_IPSFLAG_IRQ1, | ||
37 | SSB_IPSFLAG_IRQ2, | ||
38 | SSB_IPSFLAG_IRQ3, | ||
39 | SSB_IPSFLAG_IRQ4, | ||
40 | }; | ||
41 | |||
42 | static const u32 ipsflag_irq_shift[] = { | ||
43 | 0, | ||
44 | SSB_IPSFLAG_IRQ1_SHIFT, | ||
45 | SSB_IPSFLAG_IRQ2_SHIFT, | ||
46 | SSB_IPSFLAG_IRQ3_SHIFT, | ||
47 | SSB_IPSFLAG_IRQ4_SHIFT, | ||
48 | }; | ||
49 | |||
50 | static inline u32 ssb_irqflag(struct ssb_device *dev) | ||
51 | { | ||
52 | return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; | ||
53 | } | ||
54 | |||
55 | /* Get the MIPS IRQ assignment for a specified device. | ||
56 | * If unassigned, 0 is returned. | ||
57 | */ | ||
58 | unsigned int ssb_mips_irq(struct ssb_device *dev) | ||
59 | { | ||
60 | struct ssb_bus *bus = dev->bus; | ||
61 | u32 irqflag; | ||
62 | u32 ipsflag; | ||
63 | u32 tmp; | ||
64 | unsigned int irq; | ||
65 | |||
66 | irqflag = ssb_irqflag(dev); | ||
67 | ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG); | ||
68 | for (irq = 1; irq <= 4; irq++) { | ||
69 | tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]); | ||
70 | if (tmp == irqflag) | ||
71 | break; | ||
72 | } | ||
73 | if (irq == 5) | ||
74 | irq = 0; | ||
75 | |||
76 | return irq; | ||
77 | } | ||
78 | |||
79 | static void clear_irq(struct ssb_bus *bus, unsigned int irq) | ||
80 | { | ||
81 | struct ssb_device *dev = bus->mipscore.dev; | ||
82 | |||
83 | /* Clear the IRQ in the MIPScore backplane registers */ | ||
84 | if (irq == 0) { | ||
85 | ssb_write32(dev, SSB_INTVEC, 0); | ||
86 | } else { | ||
87 | ssb_write32(dev, SSB_IPSFLAG, | ||
88 | ssb_read32(dev, SSB_IPSFLAG) | | ||
89 | ipsflag_irq_mask[irq]); | ||
90 | } | ||
91 | } | ||
92 | |||
93 | static void set_irq(struct ssb_device *dev, unsigned int irq) | ||
94 | { | ||
95 | unsigned int oldirq = ssb_mips_irq(dev); | ||
96 | struct ssb_bus *bus = dev->bus; | ||
97 | struct ssb_device *mdev = bus->mipscore.dev; | ||
98 | u32 irqflag = ssb_irqflag(dev); | ||
99 | |||
100 | dev->irq = irq + 2; | ||
101 | |||
102 | ssb_dprintk(KERN_INFO PFX | ||
103 | "set_irq: core 0x%04x, irq %d => %d\n", | ||
104 | dev->id.coreid, oldirq, irq); | ||
105 | /* clear the old irq */ | ||
106 | if (oldirq == 0) | ||
107 | ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))); | ||
108 | else | ||
109 | clear_irq(bus, oldirq); | ||
110 | |||
111 | /* assign the new one */ | ||
112 | if (irq == 0) | ||
113 | ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))); | ||
114 | |||
115 | irqflag <<= ipsflag_irq_shift[irq]; | ||
116 | irqflag |= (ssb_read32(mdev, SSB_IPSFLAG) & ~ipsflag_irq_mask[irq]); | ||
117 | ssb_write32(mdev, SSB_IPSFLAG, irqflag); | ||
118 | } | ||
119 | |||
120 | static void ssb_mips_serial_init(struct ssb_mipscore *mcore) | ||
121 | { | ||
122 | struct ssb_bus *bus = mcore->dev->bus; | ||
123 | |||
124 | if (bus->extif.dev) | ||
125 | mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports); | ||
126 | else if (bus->chipco.dev) | ||
127 | mcore->nr_serial_ports = ssb_chipco_serial_init(&bus->chipco, mcore->serial_ports); | ||
128 | else | ||
129 | mcore->nr_serial_ports = 0; | ||
130 | } | ||
131 | |||
132 | static void ssb_mips_flash_detect(struct ssb_mipscore *mcore) | ||
133 | { | ||
134 | struct ssb_bus *bus = mcore->dev->bus; | ||
135 | |||
136 | mcore->flash_buswidth = 2; | ||
137 | if (bus->chipco.dev) { | ||
138 | mcore->flash_window = 0x1c000000; | ||
139 | mcore->flash_window_size = 0x02000000; | ||
140 | if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG) | ||
141 | & SSB_CHIPCO_CFG_DS16) == 0) | ||
142 | mcore->flash_buswidth = 1; | ||
143 | } else { | ||
144 | mcore->flash_window = 0x1fc00000; | ||
145 | mcore->flash_window_size = 0x00400000; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | u32 ssb_cpu_clock(struct ssb_mipscore *mcore) | ||
150 | { | ||
151 | struct ssb_bus *bus = mcore->dev->bus; | ||
152 | u32 pll_type, n, m, rate = 0; | ||
153 | |||
154 | if (bus->extif.dev) { | ||
155 | ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m); | ||
156 | } else if (bus->chipco.dev) { | ||
157 | ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m); | ||
158 | } else | ||
159 | return 0; | ||
160 | |||
161 | if ((pll_type == SSB_PLLTYPE_5) || (bus->chip_id == 0x5365)) { | ||
162 | rate = 200000000; | ||
163 | } else { | ||
164 | rate = ssb_calc_clock_rate(pll_type, n, m); | ||
165 | } | ||
166 | |||
167 | if (pll_type == SSB_PLLTYPE_6) { | ||
168 | rate *= 2; | ||
169 | } | ||
170 | |||
171 | return rate; | ||
172 | } | ||
173 | |||
174 | void ssb_mipscore_init(struct ssb_mipscore *mcore) | ||
175 | { | ||
176 | struct ssb_bus *bus = mcore->dev->bus; | ||
177 | struct ssb_device *dev; | ||
178 | unsigned long hz, ns; | ||
179 | unsigned int irq, i; | ||
180 | |||
181 | if (!mcore->dev) | ||
182 | return; /* We don't have a MIPS core */ | ||
183 | |||
184 | ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n"); | ||
185 | |||
186 | hz = ssb_clockspeed(bus); | ||
187 | if (!hz) | ||
188 | hz = 100000000; | ||
189 | ns = 1000000000 / hz; | ||
190 | |||
191 | if (bus->extif.dev) | ||
192 | ssb_extif_timing_init(&bus->extif, ns); | ||
193 | else if (bus->chipco.dev) | ||
194 | ssb_chipco_timing_init(&bus->chipco, ns); | ||
195 | |||
196 | /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ | ||
197 | for (irq = 2, i = 0; i < bus->nr_devices; i++) { | ||
198 | dev = &(bus->devices[i]); | ||
199 | dev->irq = ssb_mips_irq(dev) + 2; | ||
200 | switch (dev->id.coreid) { | ||
201 | case SSB_DEV_USB11_HOST: | ||
202 | /* shouldn't need a separate irq line for non-4710, most of them have a proper | ||
203 | * external usb controller on the pci */ | ||
204 | if ((bus->chip_id == 0x4710) && (irq <= 4)) { | ||
205 | set_irq(dev, irq++); | ||
206 | break; | ||
207 | } | ||
208 | /* fallthrough */ | ||
209 | case SSB_DEV_PCI: | ||
210 | case SSB_DEV_ETHERNET: | ||
211 | case SSB_DEV_80211: | ||
212 | case SSB_DEV_USB20_HOST: | ||
213 | /* These devices get their own IRQ line if available, the rest goes on IRQ0 */ | ||
214 | if (irq <= 4) { | ||
215 | set_irq(dev, irq++); | ||
216 | break; | ||
217 | } | ||
218 | } | ||
219 | } | ||
220 | |||
221 | ssb_mips_serial_init(mcore); | ||
222 | ssb_mips_flash_detect(mcore); | ||
223 | } | ||
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c new file mode 100644 index 000000000000..2faaa906d5d6 --- /dev/null +++ b/drivers/ssb/driver_pcicore.c | |||
@@ -0,0 +1,576 @@ | |||
1 | /* | ||
2 | * Sonics Silicon Backplane | ||
3 | * Broadcom PCI-core driver | ||
4 | * | ||
5 | * Copyright 2005, Broadcom Corporation | ||
6 | * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de> | ||
7 | * | ||
8 | * Licensed under the GNU/GPL. See COPYING for details. | ||
9 | */ | ||
10 | |||
11 | #include <linux/ssb/ssb.h> | ||
12 | #include <linux/pci.h> | ||
13 | #include <linux/delay.h> | ||
14 | |||
15 | #include "ssb_private.h" | ||
16 | |||
17 | |||
18 | static inline | ||
19 | u32 pcicore_read32(struct ssb_pcicore *pc, u16 offset) | ||
20 | { | ||
21 | return ssb_read32(pc->dev, offset); | ||
22 | } | ||
23 | |||
24 | static inline | ||
25 | void pcicore_write32(struct ssb_pcicore *pc, u16 offset, u32 value) | ||
26 | { | ||
27 | ssb_write32(pc->dev, offset, value); | ||
28 | } | ||
29 | |||
30 | /************************************************** | ||
31 | * Code for hostmode operation. | ||
32 | **************************************************/ | ||
33 | |||
34 | #ifdef CONFIG_SSB_PCICORE_HOSTMODE | ||
35 | |||
36 | #include <asm/paccess.h> | ||
37 | /* Probe a 32bit value on the bus and catch bus exceptions. | ||
38 | * Returns nonzero on a bus exception. | ||
39 | * This is MIPS specific */ | ||
40 | #define mips_busprobe32(val, addr) get_dbe((val), ((u32 *)(addr))) | ||
41 | |||
42 | /* Assume one-hot slot wiring */ | ||
43 | #define SSB_PCI_SLOT_MAX 16 | ||
44 | |||
45 | /* Global lock is OK, as we won't have more than one extpci anyway. */ | ||
46 | static DEFINE_SPINLOCK(cfgspace_lock); | ||
47 | /* Core to access the external PCI config space. Can only have one. */ | ||
48 | static struct ssb_pcicore *extpci_core; | ||
49 | |||
50 | static u32 ssb_pcicore_pcibus_iobase = 0x100; | ||
51 | static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA; | ||
52 | |||
53 | int pcibios_plat_dev_init(struct pci_dev *d) | ||
54 | { | ||
55 | struct resource *res; | ||
56 | int pos, size; | ||
57 | u32 *base; | ||
58 | |||
59 | ssb_printk(KERN_INFO "PCI: Fixing up device %s\n", | ||
60 | pci_name(d)); | ||
61 | |||
62 | /* Fix up resource bases */ | ||
63 | for (pos = 0; pos < 6; pos++) { | ||
64 | res = &d->resource[pos]; | ||
65 | if (res->flags & IORESOURCE_IO) | ||
66 | base = &ssb_pcicore_pcibus_iobase; | ||
67 | else | ||
68 | base = &ssb_pcicore_pcibus_membase; | ||
69 | if (res->end) { | ||
70 | size = res->end - res->start + 1; | ||
71 | if (*base & (size - 1)) | ||
72 | *base = (*base + size) & ~(size - 1); | ||
73 | res->start = *base; | ||
74 | res->end = res->start + size - 1; | ||
75 | *base += size; | ||
76 | pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start); | ||
77 | } | ||
78 | /* Fix up PCI bridge BAR0 only */ | ||
79 | if (d->bus->number == 0 && PCI_SLOT(d->devfn) == 0) | ||
80 | break; | ||
81 | } | ||
82 | /* Fix up interrupt lines */ | ||
83 | d->irq = ssb_mips_irq(extpci_core->dev) + 2; | ||
84 | pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq); | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static void __init ssb_fixup_pcibridge(struct pci_dev *dev) | ||
90 | { | ||
91 | if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0) | ||
92 | return; | ||
93 | |||
94 | ssb_printk(KERN_INFO "PCI: fixing up bridge\n"); | ||
95 | |||
96 | /* Enable PCI bridge bus mastering and memory space */ | ||
97 | pci_set_master(dev); | ||
98 | pcibios_enable_device(dev, ~0); | ||
99 | |||
100 | /* Enable PCI bridge BAR1 prefetch and burst */ | ||
101 | pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3); | ||
102 | |||
103 | /* Make sure our latency is high enough to handle the devices behind us */ | ||
104 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xa8); | ||
105 | } | ||
106 | DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_fixup_pcibridge); | ||
107 | |||
108 | int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | ||
109 | { | ||
110 | return ssb_mips_irq(extpci_core->dev) + 2; | ||
111 | } | ||
112 | |||
113 | static u32 get_cfgspace_addr(struct ssb_pcicore *pc, | ||
114 | unsigned int bus, unsigned int dev, | ||
115 | unsigned int func, unsigned int off) | ||
116 | { | ||
117 | u32 addr = 0; | ||
118 | u32 tmp; | ||
119 | |||
120 | if (unlikely(pc->cardbusmode && dev > 1)) | ||
121 | goto out; | ||
122 | if (bus == 0) { | ||
123 | /* Type 0 transaction */ | ||
124 | if (unlikely(dev >= SSB_PCI_SLOT_MAX)) | ||
125 | goto out; | ||
126 | /* Slide the window */ | ||
127 | tmp = SSB_PCICORE_SBTOPCI_CFG0; | ||
128 | tmp |= ((1 << (dev + 16)) & SSB_PCICORE_SBTOPCI1_MASK); | ||
129 | pcicore_write32(pc, SSB_PCICORE_SBTOPCI1, tmp); | ||
130 | /* Calculate the address */ | ||
131 | addr = SSB_PCI_CFG; | ||
132 | addr |= ((1 << (dev + 16)) & ~SSB_PCICORE_SBTOPCI1_MASK); | ||
133 | addr |= (func << 8); | ||
134 | addr |= (off & ~3); | ||
135 | } else { | ||
136 | /* Type 1 transaction */ | ||
137 | pcicore_write32(pc, SSB_PCICORE_SBTOPCI1, | ||
138 | SSB_PCICORE_SBTOPCI_CFG1); | ||
139 | /* Calculate the address */ | ||
140 | addr = SSB_PCI_CFG; | ||
141 | addr |= (bus << 16); | ||
142 | addr |= (dev << 11); | ||
143 | addr |= (func << 8); | ||
144 | addr |= (off & ~3); | ||
145 | } | ||
146 | out: | ||
147 | return addr; | ||
148 | } | ||
149 | |||
150 | static int ssb_extpci_read_config(struct ssb_pcicore *pc, | ||
151 | unsigned int bus, unsigned int dev, | ||
152 | unsigned int func, unsigned int off, | ||
153 | void *buf, int len) | ||
154 | { | ||
155 | int err = -EINVAL; | ||
156 | u32 addr, val; | ||
157 | void __iomem *mmio; | ||
158 | |||
159 | SSB_WARN_ON(!pc->hostmode); | ||
160 | if (unlikely(len != 1 && len != 2 && len != 4)) | ||
161 | goto out; | ||
162 | addr = get_cfgspace_addr(pc, bus, dev, func, off); | ||
163 | if (unlikely(!addr)) | ||
164 | goto out; | ||
165 | err = -ENOMEM; | ||
166 | mmio = ioremap_nocache(addr, len); | ||
167 | if (!mmio) | ||
168 | goto out; | ||
169 | |||
170 | if (mips_busprobe32(val, mmio)) { | ||
171 | val = 0xffffffff; | ||
172 | goto unmap; | ||
173 | } | ||
174 | |||
175 | val = readl(mmio); | ||
176 | val >>= (8 * (off & 3)); | ||
177 | |||
178 | switch (len) { | ||
179 | case 1: | ||
180 | *((u8 *)buf) = (u8)val; | ||
181 | break; | ||
182 | case 2: | ||
183 | *((u16 *)buf) = (u16)val; | ||
184 | break; | ||
185 | case 4: | ||
186 | *((u32 *)buf) = (u32)val; | ||
187 | break; | ||
188 | } | ||
189 | err = 0; | ||
190 | unmap: | ||
191 | iounmap(mmio); | ||
192 | out: | ||
193 | return err; | ||
194 | } | ||
195 | |||
196 | static int ssb_extpci_write_config(struct ssb_pcicore *pc, | ||
197 | unsigned int bus, unsigned int dev, | ||
198 | unsigned int func, unsigned int off, | ||
199 | const void *buf, int len) | ||
200 | { | ||
201 | int err = -EINVAL; | ||
202 | u32 addr, val = 0; | ||
203 | void __iomem *mmio; | ||
204 | |||
205 | SSB_WARN_ON(!pc->hostmode); | ||
206 | if (unlikely(len != 1 && len != 2 && len != 4)) | ||
207 | goto out; | ||
208 | addr = get_cfgspace_addr(pc, bus, dev, func, off); | ||
209 | if (unlikely(!addr)) | ||
210 | goto out; | ||
211 | err = -ENOMEM; | ||
212 | mmio = ioremap_nocache(addr, len); | ||
213 | if (!mmio) | ||
214 | goto out; | ||
215 | |||
216 | if (mips_busprobe32(val, mmio)) { | ||
217 | val = 0xffffffff; | ||
218 | goto unmap; | ||
219 | } | ||
220 | |||
221 | switch (len) { | ||
222 | case 1: | ||
223 | val = readl(mmio); | ||
224 | val &= ~(0xFF << (8 * (off & 3))); | ||
225 | val |= *((const u8 *)buf) << (8 * (off & 3)); | ||
226 | break; | ||
227 | case 2: | ||
228 | val = readl(mmio); | ||
229 | val &= ~(0xFFFF << (8 * (off & 3))); | ||
230 | val |= *((const u16 *)buf) << (8 * (off & 3)); | ||
231 | break; | ||
232 | case 4: | ||
233 | val = *((const u32 *)buf); | ||
234 | break; | ||
235 | } | ||
236 | writel(val, mmio); | ||
237 | |||
238 | err = 0; | ||
239 | unmap: | ||
240 | iounmap(mmio); | ||
241 | out: | ||
242 | return err; | ||
243 | } | ||
244 | |||
245 | static int ssb_pcicore_read_config(struct pci_bus *bus, unsigned int devfn, | ||
246 | int reg, int size, u32 *val) | ||
247 | { | ||
248 | unsigned long flags; | ||
249 | int err; | ||
250 | |||
251 | spin_lock_irqsave(&cfgspace_lock, flags); | ||
252 | err = ssb_extpci_read_config(extpci_core, bus->number, PCI_SLOT(devfn), | ||
253 | PCI_FUNC(devfn), reg, val, size); | ||
254 | spin_unlock_irqrestore(&cfgspace_lock, flags); | ||
255 | |||
256 | return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
257 | } | ||
258 | |||
259 | static int ssb_pcicore_write_config(struct pci_bus *bus, unsigned int devfn, | ||
260 | int reg, int size, u32 val) | ||
261 | { | ||
262 | unsigned long flags; | ||
263 | int err; | ||
264 | |||
265 | spin_lock_irqsave(&cfgspace_lock, flags); | ||
266 | err = ssb_extpci_write_config(extpci_core, bus->number, PCI_SLOT(devfn), | ||
267 | PCI_FUNC(devfn), reg, &val, size); | ||
268 | spin_unlock_irqrestore(&cfgspace_lock, flags); | ||
269 | |||
270 | return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
271 | } | ||
272 | |||
273 | static struct pci_ops ssb_pcicore_pciops = { | ||
274 | .read = ssb_pcicore_read_config, | ||
275 | .write = ssb_pcicore_write_config, | ||
276 | }; | ||
277 | |||
278 | static struct resource ssb_pcicore_mem_resource = { | ||
279 | .name = "SSB PCIcore external memory", | ||
280 | .start = SSB_PCI_DMA, | ||
281 | .end = SSB_PCI_DMA + SSB_PCI_DMA_SZ - 1, | ||
282 | .flags = IORESOURCE_MEM, | ||
283 | }; | ||
284 | |||
285 | static struct resource ssb_pcicore_io_resource = { | ||
286 | .name = "SSB PCIcore external I/O", | ||
287 | .start = 0x100, | ||
288 | .end = 0x7FF, | ||
289 | .flags = IORESOURCE_IO, | ||
290 | }; | ||
291 | |||
292 | static struct pci_controller ssb_pcicore_controller = { | ||
293 | .pci_ops = &ssb_pcicore_pciops, | ||
294 | .io_resource = &ssb_pcicore_io_resource, | ||
295 | .mem_resource = &ssb_pcicore_mem_resource, | ||
296 | .mem_offset = 0x24000000, | ||
297 | }; | ||
298 | |||
299 | static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) | ||
300 | { | ||
301 | u32 val; | ||
302 | |||
303 | if (WARN_ON(extpci_core)) | ||
304 | return; | ||
305 | extpci_core = pc; | ||
306 | |||
307 | ssb_dprintk(KERN_INFO PFX "PCIcore in host mode found\n"); | ||
308 | /* Reset devices on the external PCI bus */ | ||
309 | val = SSB_PCICORE_CTL_RST_OE; | ||
310 | val |= SSB_PCICORE_CTL_CLK_OE; | ||
311 | pcicore_write32(pc, SSB_PCICORE_CTL, val); | ||
312 | val |= SSB_PCICORE_CTL_CLK; /* Clock on */ | ||
313 | pcicore_write32(pc, SSB_PCICORE_CTL, val); | ||
314 | udelay(150); /* Assertion time demanded by the PCI standard */ | ||
315 | val |= SSB_PCICORE_CTL_RST; /* Deassert RST# */ | ||
316 | pcicore_write32(pc, SSB_PCICORE_CTL, val); | ||
317 | val = SSB_PCICORE_ARBCTL_INTERN; | ||
318 | pcicore_write32(pc, SSB_PCICORE_ARBCTL, val); | ||
319 | udelay(1); /* Assertion time demanded by the PCI standard */ | ||
320 | |||
321 | /*TODO cardbus mode */ | ||
322 | |||
323 | /* 64MB I/O window */ | ||
324 | pcicore_write32(pc, SSB_PCICORE_SBTOPCI0, | ||
325 | SSB_PCICORE_SBTOPCI_IO); | ||
326 | /* 64MB config space */ | ||
327 | pcicore_write32(pc, SSB_PCICORE_SBTOPCI1, | ||
328 | SSB_PCICORE_SBTOPCI_CFG0); | ||
329 | /* 1GB memory window */ | ||
330 | pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, | ||
331 | SSB_PCICORE_SBTOPCI_MEM | SSB_PCI_DMA); | ||
332 | |||
333 | /* Enable PCI bridge BAR0 prefetch and burst */ | ||
334 | val = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; | ||
335 | ssb_extpci_write_config(pc, 0, 0, 0, PCI_COMMAND, &val, 2); | ||
336 | /* Clear error conditions */ | ||
337 | val = 0; | ||
338 | ssb_extpci_write_config(pc, 0, 0, 0, PCI_STATUS, &val, 2); | ||
339 | |||
340 | /* Enable PCI interrupts */ | ||
341 | pcicore_write32(pc, SSB_PCICORE_IMASK, | ||
342 | SSB_PCICORE_IMASK_INTA); | ||
343 | |||
344 | /* Ok, ready to run, register it to the system. | ||
345 | * The following needs change, if we want to port hostmode | ||
346 | * to non-MIPS platform. */ | ||
347 | set_io_port_base((unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000)); | ||
348 | /* Give some time to the PCI controller to configure itself with the new | ||
349 | * values. Not waiting at this point causes crashes of the machine. */ | ||
350 | mdelay(10); | ||
351 | register_pci_controller(&ssb_pcicore_controller); | ||
352 | } | ||
353 | |||
354 | static int pcicore_is_in_hostmode(struct ssb_pcicore *pc) | ||
355 | { | ||
356 | struct ssb_bus *bus = pc->dev->bus; | ||
357 | u16 chipid_top; | ||
358 | u32 tmp; | ||
359 | |||
360 | chipid_top = (bus->chip_id & 0xFF00); | ||
361 | if (chipid_top != 0x4700 && | ||
362 | chipid_top != 0x5300) | ||
363 | return 0; | ||
364 | |||
365 | if (bus->sprom.r1.boardflags_lo & SSB_PCICORE_BFL_NOPCI) | ||
366 | return 0; | ||
367 | |||
368 | /* The 200-pin BCM4712 package does not bond out PCI. Even when | ||
369 | * PCI is bonded out, some boards may leave the pins floating. */ | ||
370 | if (bus->chip_id == 0x4712) { | ||
371 | if (bus->chip_package == SSB_CHIPPACK_BCM4712S) | ||
372 | return 0; | ||
373 | if (bus->chip_package == SSB_CHIPPACK_BCM4712M) | ||
374 | return 0; | ||
375 | } | ||
376 | if (bus->chip_id == 0x5350) | ||
377 | return 0; | ||
378 | |||
379 | return !mips_busprobe32(tmp, (bus->mmio + (pc->dev->core_index * SSB_CORE_SIZE))); | ||
380 | } | ||
381 | #endif /* CONFIG_SSB_PCICORE_HOSTMODE */ | ||
382 | |||
383 | |||
384 | /************************************************** | ||
385 | * Generic and Clientmode operation code. | ||
386 | **************************************************/ | ||
387 | |||
388 | static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc) | ||
389 | { | ||
390 | /* Disable PCI interrupts. */ | ||
391 | ssb_write32(pc->dev, SSB_INTVEC, 0); | ||
392 | } | ||
393 | |||
394 | void ssb_pcicore_init(struct ssb_pcicore *pc) | ||
395 | { | ||
396 | struct ssb_device *dev = pc->dev; | ||
397 | struct ssb_bus *bus; | ||
398 | |||
399 | if (!dev) | ||
400 | return; | ||
401 | bus = dev->bus; | ||
402 | if (!ssb_device_is_enabled(dev)) | ||
403 | ssb_device_enable(dev, 0); | ||
404 | |||
405 | #ifdef CONFIG_SSB_PCICORE_HOSTMODE | ||
406 | pc->hostmode = pcicore_is_in_hostmode(pc); | ||
407 | if (pc->hostmode) | ||
408 | ssb_pcicore_init_hostmode(pc); | ||
409 | #endif /* CONFIG_SSB_PCICORE_HOSTMODE */ | ||
410 | if (!pc->hostmode) | ||
411 | ssb_pcicore_init_clientmode(pc); | ||
412 | } | ||
413 | |||
414 | static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address) | ||
415 | { | ||
416 | pcicore_write32(pc, 0x130, address); | ||
417 | return pcicore_read32(pc, 0x134); | ||
418 | } | ||
419 | |||
420 | static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data) | ||
421 | { | ||
422 | pcicore_write32(pc, 0x130, address); | ||
423 | pcicore_write32(pc, 0x134, data); | ||
424 | } | ||
425 | |||
426 | static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, | ||
427 | u8 address, u16 data) | ||
428 | { | ||
429 | const u16 mdio_control = 0x128; | ||
430 | const u16 mdio_data = 0x12C; | ||
431 | u32 v; | ||
432 | int i; | ||
433 | |||
434 | v = 0x80; /* Enable Preamble Sequence */ | ||
435 | v |= 0x2; /* MDIO Clock Divisor */ | ||
436 | pcicore_write32(pc, mdio_control, v); | ||
437 | |||
438 | v = (1 << 30); /* Start of Transaction */ | ||
439 | v |= (1 << 28); /* Write Transaction */ | ||
440 | v |= (1 << 17); /* Turnaround */ | ||
441 | v |= (u32)device << 22; | ||
442 | v |= (u32)address << 18; | ||
443 | v |= data; | ||
444 | pcicore_write32(pc, mdio_data, v); | ||
445 | /* Wait for the device to complete the transaction */ | ||
446 | udelay(10); | ||
447 | for (i = 0; i < 10; i++) { | ||
448 | v = pcicore_read32(pc, mdio_control); | ||
449 | if (v & 0x100 /* Trans complete */) | ||
450 | break; | ||
451 | msleep(1); | ||
452 | } | ||
453 | pcicore_write32(pc, mdio_control, 0); | ||
454 | } | ||
455 | |||
456 | static void ssb_broadcast_value(struct ssb_device *dev, | ||
457 | u32 address, u32 data) | ||
458 | { | ||
459 | /* This is used for both, PCI and ChipCommon core, so be careful. */ | ||
460 | BUILD_BUG_ON(SSB_PCICORE_BCAST_ADDR != SSB_CHIPCO_BCAST_ADDR); | ||
461 | BUILD_BUG_ON(SSB_PCICORE_BCAST_DATA != SSB_CHIPCO_BCAST_DATA); | ||
462 | |||
463 | ssb_write32(dev, SSB_PCICORE_BCAST_ADDR, address); | ||
464 | ssb_read32(dev, SSB_PCICORE_BCAST_ADDR); /* flush */ | ||
465 | ssb_write32(dev, SSB_PCICORE_BCAST_DATA, data); | ||
466 | ssb_read32(dev, SSB_PCICORE_BCAST_DATA); /* flush */ | ||
467 | } | ||
468 | |||
469 | static void ssb_commit_settings(struct ssb_bus *bus) | ||
470 | { | ||
471 | struct ssb_device *dev; | ||
472 | |||
473 | dev = bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev; | ||
474 | if (WARN_ON(!dev)) | ||
475 | return; | ||
476 | /* This forces an update of the cached registers. */ | ||
477 | ssb_broadcast_value(dev, 0xFD8, 0); | ||
478 | } | ||
479 | |||
480 | int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, | ||
481 | struct ssb_device *dev) | ||
482 | { | ||
483 | struct ssb_device *pdev = pc->dev; | ||
484 | struct ssb_bus *bus; | ||
485 | int err = 0; | ||
486 | u32 tmp; | ||
487 | |||
488 | might_sleep(); | ||
489 | |||
490 | if (!pdev) | ||
491 | goto out; | ||
492 | bus = pdev->bus; | ||
493 | |||
494 | /* Enable interrupts for this device. */ | ||
495 | if (bus->host_pci && | ||
496 | ((pdev->id.revision >= 6) || (pdev->id.coreid == SSB_DEV_PCIE))) { | ||
497 | u32 coremask; | ||
498 | |||
499 | /* Calculate the "coremask" for the device. */ | ||
500 | coremask = (1 << dev->core_index); | ||
501 | |||
502 | err = pci_read_config_dword(bus->host_pci, SSB_PCI_IRQMASK, &tmp); | ||
503 | if (err) | ||
504 | goto out; | ||
505 | tmp |= coremask << 8; | ||
506 | err = pci_write_config_dword(bus->host_pci, SSB_PCI_IRQMASK, tmp); | ||
507 | if (err) | ||
508 | goto out; | ||
509 | } else { | ||
510 | u32 intvec; | ||
511 | |||
512 | intvec = ssb_read32(pdev, SSB_INTVEC); | ||
513 | if ((bus->chip_id & 0xFF00) == 0x4400) { | ||
514 | /* Workaround: On the BCM44XX the BPFLAG routing | ||
515 | * bit is wrong. Use a hardcoded constant. */ | ||
516 | intvec |= 0x00000002; | ||
517 | } else { | ||
518 | tmp = ssb_read32(dev, SSB_TPSFLAG); | ||
519 | tmp &= SSB_TPSFLAG_BPFLAG; | ||
520 | intvec |= tmp; | ||
521 | } | ||
522 | ssb_write32(pdev, SSB_INTVEC, intvec); | ||
523 | } | ||
524 | |||
525 | /* Setup PCIcore operation. */ | ||
526 | if (pc->setup_done) | ||
527 | goto out; | ||
528 | if (pdev->id.coreid == SSB_DEV_PCI) { | ||
529 | tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); | ||
530 | tmp |= SSB_PCICORE_SBTOPCI_PREF; | ||
531 | tmp |= SSB_PCICORE_SBTOPCI_BURST; | ||
532 | pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); | ||
533 | |||
534 | if (pdev->id.revision < 5) { | ||
535 | tmp = ssb_read32(pdev, SSB_IMCFGLO); | ||
536 | tmp &= ~SSB_IMCFGLO_SERTO; | ||
537 | tmp |= 2; | ||
538 | tmp &= ~SSB_IMCFGLO_REQTO; | ||
539 | tmp |= 3 << SSB_IMCFGLO_REQTO_SHIFT; | ||
540 | ssb_write32(pdev, SSB_IMCFGLO, tmp); | ||
541 | ssb_commit_settings(bus); | ||
542 | } else if (pdev->id.revision >= 11) { | ||
543 | tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); | ||
544 | tmp |= SSB_PCICORE_SBTOPCI_MRM; | ||
545 | pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); | ||
546 | } | ||
547 | } else { | ||
548 | WARN_ON(pdev->id.coreid != SSB_DEV_PCIE); | ||
549 | //TODO: Better make defines for all these magic PCIE values. | ||
550 | if ((pdev->id.revision == 0) || (pdev->id.revision == 1)) { | ||
551 | /* TLP Workaround register. */ | ||
552 | tmp = ssb_pcie_read(pc, 0x4); | ||
553 | tmp |= 0x8; | ||
554 | ssb_pcie_write(pc, 0x4, tmp); | ||
555 | } | ||
556 | if (pdev->id.revision == 0) { | ||
557 | const u8 serdes_rx_device = 0x1F; | ||
558 | |||
559 | ssb_pcie_mdio_write(pc, serdes_rx_device, | ||
560 | 2 /* Timer */, 0x8128); | ||
561 | ssb_pcie_mdio_write(pc, serdes_rx_device, | ||
562 | 6 /* CDR */, 0x0100); | ||
563 | ssb_pcie_mdio_write(pc, serdes_rx_device, | ||
564 | 7 /* CDR BW */, 0x1466); | ||
565 | } else if (pdev->id.revision == 1) { | ||
566 | /* DLLP Link Control register. */ | ||
567 | tmp = ssb_pcie_read(pc, 0x100); | ||
568 | tmp |= 0x40; | ||
569 | ssb_pcie_write(pc, 0x100, tmp); | ||
570 | } | ||
571 | } | ||
572 | pc->setup_done = 1; | ||
573 | out: | ||
574 | return err; | ||
575 | } | ||
576 | EXPORT_SYMBOL(ssb_pcicore_dev_irqvecs_enable); | ||
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c new file mode 100644 index 000000000000..74d5182db4b2 --- /dev/null +++ b/drivers/ssb/main.c | |||
@@ -0,0 +1,1162 @@ | |||
1 | /* | ||
2 | * Sonics Silicon Backplane | ||
3 | * Subsystem core | ||
4 | * | ||
5 | * Copyright 2005, Broadcom Corporation | ||
6 | * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de> | ||
7 | * | ||
8 | * Licensed under the GNU/GPL. See COPYING for details. | ||
9 | */ | ||
10 | |||
11 | #include "ssb_private.h" | ||
12 | |||
13 | #include <linux/delay.h> | ||
14 | #include <linux/ssb/ssb.h> | ||
15 | #include <linux/ssb/ssb_regs.h> | ||
16 | #include <linux/dma-mapping.h> | ||
17 | #include <linux/pci.h> | ||
18 | |||
19 | #include <pcmcia/cs_types.h> | ||
20 | #include <pcmcia/cs.h> | ||
21 | #include <pcmcia/cistpl.h> | ||
22 | #include <pcmcia/ds.h> | ||
23 | |||
24 | |||
25 | MODULE_DESCRIPTION("Sonics Silicon Backplane driver"); | ||
26 | MODULE_LICENSE("GPL"); | ||
27 | |||
28 | |||
29 | /* Temporary list of yet-to-be-attached buses */ | ||
30 | static LIST_HEAD(attach_queue); | ||
31 | /* List if running buses */ | ||
32 | static LIST_HEAD(buses); | ||
33 | /* Software ID counter */ | ||
34 | static unsigned int next_busnumber; | ||
35 | /* buses_mutes locks the two buslists and the next_busnumber. | ||
36 | * Don't lock this directly, but use ssb_buses_[un]lock() below. */ | ||
37 | static DEFINE_MUTEX(buses_mutex); | ||
38 | |||
39 | /* There are differences in the codeflow, if the bus is | ||
40 | * initialized from early boot, as various needed services | ||
41 | * are not available early. This is a mechanism to delay | ||
42 | * these initializations to after early boot has finished. | ||
43 | * It's also used to avoid mutex locking, as that's not | ||
44 | * available and needed early. */ | ||
45 | static bool ssb_is_early_boot = 1; | ||
46 | |||
47 | static void ssb_buses_lock(void); | ||
48 | static void ssb_buses_unlock(void); | ||
49 | |||
50 | |||
51 | #ifdef CONFIG_SSB_PCIHOST | ||
52 | struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev) | ||
53 | { | ||
54 | struct ssb_bus *bus; | ||
55 | |||
56 | ssb_buses_lock(); | ||
57 | list_for_each_entry(bus, &buses, list) { | ||
58 | if (bus->bustype == SSB_BUSTYPE_PCI && | ||
59 | bus->host_pci == pdev) | ||
60 | goto found; | ||
61 | } | ||
62 | bus = NULL; | ||
63 | found: | ||
64 | ssb_buses_unlock(); | ||
65 | |||
66 | return bus; | ||
67 | } | ||
68 | #endif /* CONFIG_SSB_PCIHOST */ | ||
69 | |||
70 | static struct ssb_device *ssb_device_get(struct ssb_device *dev) | ||
71 | { | ||
72 | if (dev) | ||
73 | get_device(dev->dev); | ||
74 | return dev; | ||
75 | } | ||
76 | |||
77 | static void ssb_device_put(struct ssb_device *dev) | ||
78 | { | ||
79 | if (dev) | ||
80 | put_device(dev->dev); | ||
81 | } | ||
82 | |||
83 | static int ssb_bus_resume(struct ssb_bus *bus) | ||
84 | { | ||
85 | int err; | ||
86 | |||
87 | ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1); | ||
88 | err = ssb_pcmcia_init(bus); | ||
89 | if (err) { | ||
90 | /* No need to disable XTAL, as we don't have one on PCMCIA. */ | ||
91 | return err; | ||
92 | } | ||
93 | ssb_chipco_resume(&bus->chipco); | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static int ssb_device_resume(struct device *dev) | ||
99 | { | ||
100 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); | ||
101 | struct ssb_driver *ssb_drv; | ||
102 | struct ssb_bus *bus; | ||
103 | int err = 0; | ||
104 | |||
105 | bus = ssb_dev->bus; | ||
106 | if (bus->suspend_cnt == bus->nr_devices) { | ||
107 | err = ssb_bus_resume(bus); | ||
108 | if (err) | ||
109 | return err; | ||
110 | } | ||
111 | bus->suspend_cnt--; | ||
112 | if (dev->driver) { | ||
113 | ssb_drv = drv_to_ssb_drv(dev->driver); | ||
114 | if (ssb_drv && ssb_drv->resume) | ||
115 | err = ssb_drv->resume(ssb_dev); | ||
116 | if (err) | ||
117 | goto out; | ||
118 | } | ||
119 | out: | ||
120 | return err; | ||
121 | } | ||
122 | |||
123 | static void ssb_bus_suspend(struct ssb_bus *bus, pm_message_t state) | ||
124 | { | ||
125 | ssb_chipco_suspend(&bus->chipco, state); | ||
126 | ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0); | ||
127 | |||
128 | /* Reset HW state information in memory, so that HW is | ||
129 | * completely reinitialized on resume. */ | ||
130 | bus->mapped_device = NULL; | ||
131 | #ifdef CONFIG_SSB_DRIVER_PCICORE | ||
132 | bus->pcicore.setup_done = 0; | ||
133 | #endif | ||
134 | #ifdef CONFIG_SSB_DEBUG | ||
135 | bus->powered_up = 0; | ||
136 | #endif | ||
137 | } | ||
138 | |||
139 | static int ssb_device_suspend(struct device *dev, pm_message_t state) | ||
140 | { | ||
141 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); | ||
142 | struct ssb_driver *ssb_drv; | ||
143 | struct ssb_bus *bus; | ||
144 | int err = 0; | ||
145 | |||
146 | if (dev->driver) { | ||
147 | ssb_drv = drv_to_ssb_drv(dev->driver); | ||
148 | if (ssb_drv && ssb_drv->suspend) | ||
149 | err = ssb_drv->suspend(ssb_dev, state); | ||
150 | if (err) | ||
151 | goto out; | ||
152 | } | ||
153 | |||
154 | bus = ssb_dev->bus; | ||
155 | bus->suspend_cnt++; | ||
156 | if (bus->suspend_cnt == bus->nr_devices) { | ||
157 | /* All devices suspended. Shutdown the bus. */ | ||
158 | ssb_bus_suspend(bus, state); | ||
159 | } | ||
160 | |||
161 | out: | ||
162 | return err; | ||
163 | } | ||
164 | |||
165 | #ifdef CONFIG_SSB_PCIHOST | ||
166 | int ssb_devices_freeze(struct ssb_bus *bus) | ||
167 | { | ||
168 | struct ssb_device *dev; | ||
169 | struct ssb_driver *drv; | ||
170 | int err = 0; | ||
171 | int i; | ||
172 | pm_message_t state = PMSG_FREEZE; | ||
173 | |||
174 | /* First check that we are capable to freeze all devices. */ | ||
175 | for (i = 0; i < bus->nr_devices; i++) { | ||
176 | dev = &(bus->devices[i]); | ||
177 | if (!dev->dev || | ||
178 | !dev->dev->driver || | ||
179 | !device_is_registered(dev->dev)) | ||
180 | continue; | ||
181 | drv = drv_to_ssb_drv(dev->dev->driver); | ||
182 | if (!drv) | ||
183 | continue; | ||
184 | if (!drv->suspend) { | ||
185 | /* Nope, can't suspend this one. */ | ||
186 | return -EOPNOTSUPP; | ||
187 | } | ||
188 | } | ||
189 | /* Now suspend all devices */ | ||
190 | for (i = 0; i < bus->nr_devices; i++) { | ||
191 | dev = &(bus->devices[i]); | ||
192 | if (!dev->dev || | ||
193 | !dev->dev->driver || | ||
194 | !device_is_registered(dev->dev)) | ||
195 | continue; | ||
196 | drv = drv_to_ssb_drv(dev->dev->driver); | ||
197 | if (!drv) | ||
198 | continue; | ||
199 | err = drv->suspend(dev, state); | ||
200 | if (err) { | ||
201 | ssb_printk(KERN_ERR PFX "Failed to freeze device %s\n", | ||
202 | dev->dev->bus_id); | ||
203 | goto err_unwind; | ||
204 | } | ||
205 | } | ||
206 | |||
207 | return 0; | ||
208 | err_unwind: | ||
209 | for (i--; i >= 0; i--) { | ||
210 | dev = &(bus->devices[i]); | ||
211 | if (!dev->dev || | ||
212 | !dev->dev->driver || | ||
213 | !device_is_registered(dev->dev)) | ||
214 | continue; | ||
215 | drv = drv_to_ssb_drv(dev->dev->driver); | ||
216 | if (!drv) | ||
217 | continue; | ||
218 | if (drv->resume) | ||
219 | drv->resume(dev); | ||
220 | } | ||
221 | return err; | ||
222 | } | ||
223 | |||
224 | int ssb_devices_thaw(struct ssb_bus *bus) | ||
225 | { | ||
226 | struct ssb_device *dev; | ||
227 | struct ssb_driver *drv; | ||
228 | int err; | ||
229 | int i; | ||
230 | |||
231 | for (i = 0; i < bus->nr_devices; i++) { | ||
232 | dev = &(bus->devices[i]); | ||
233 | if (!dev->dev || | ||
234 | !dev->dev->driver || | ||
235 | !device_is_registered(dev->dev)) | ||
236 | continue; | ||
237 | drv = drv_to_ssb_drv(dev->dev->driver); | ||
238 | if (!drv) | ||
239 | continue; | ||
240 | if (SSB_WARN_ON(!drv->resume)) | ||
241 | continue; | ||
242 | err = drv->resume(dev); | ||
243 | if (err) { | ||
244 | ssb_printk(KERN_ERR PFX "Failed to thaw device %s\n", | ||
245 | dev->dev->bus_id); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | #endif /* CONFIG_SSB_PCIHOST */ | ||
252 | |||
253 | static void ssb_device_shutdown(struct device *dev) | ||
254 | { | ||
255 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); | ||
256 | struct ssb_driver *ssb_drv; | ||
257 | |||
258 | if (!dev->driver) | ||
259 | return; | ||
260 | ssb_drv = drv_to_ssb_drv(dev->driver); | ||
261 | if (ssb_drv && ssb_drv->shutdown) | ||
262 | ssb_drv->shutdown(ssb_dev); | ||
263 | } | ||
264 | |||
265 | static int ssb_device_remove(struct device *dev) | ||
266 | { | ||
267 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); | ||
268 | struct ssb_driver *ssb_drv = drv_to_ssb_drv(dev->driver); | ||
269 | |||
270 | if (ssb_drv && ssb_drv->remove) | ||
271 | ssb_drv->remove(ssb_dev); | ||
272 | ssb_device_put(ssb_dev); | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static int ssb_device_probe(struct device *dev) | ||
278 | { | ||
279 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); | ||
280 | struct ssb_driver *ssb_drv = drv_to_ssb_drv(dev->driver); | ||
281 | int err = 0; | ||
282 | |||
283 | ssb_device_get(ssb_dev); | ||
284 | if (ssb_drv && ssb_drv->probe) | ||
285 | err = ssb_drv->probe(ssb_dev, &ssb_dev->id); | ||
286 | if (err) | ||
287 | ssb_device_put(ssb_dev); | ||
288 | |||
289 | return err; | ||
290 | } | ||
291 | |||
292 | static int ssb_match_devid(const struct ssb_device_id *tabid, | ||
293 | const struct ssb_device_id *devid) | ||
294 | { | ||
295 | if ((tabid->vendor != devid->vendor) && | ||
296 | tabid->vendor != SSB_ANY_VENDOR) | ||
297 | return 0; | ||
298 | if ((tabid->coreid != devid->coreid) && | ||
299 | tabid->coreid != SSB_ANY_ID) | ||
300 | return 0; | ||
301 | if ((tabid->revision != devid->revision) && | ||
302 | tabid->revision != SSB_ANY_REV) | ||
303 | return 0; | ||
304 | return 1; | ||
305 | } | ||
306 | |||
307 | static int ssb_bus_match(struct device *dev, struct device_driver *drv) | ||
308 | { | ||
309 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); | ||
310 | struct ssb_driver *ssb_drv = drv_to_ssb_drv(drv); | ||
311 | const struct ssb_device_id *id; | ||
312 | |||
313 | for (id = ssb_drv->id_table; | ||
314 | id->vendor || id->coreid || id->revision; | ||
315 | id++) { | ||
316 | if (ssb_match_devid(id, &ssb_dev->id)) | ||
317 | return 1; /* found */ | ||
318 | } | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static int ssb_device_uevent(struct device *dev, char **envp, int num_envp, | ||
324 | char *buffer, int buffer_size) | ||
325 | { | ||
326 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); | ||
327 | int ret, i = 0, length = 0; | ||
328 | |||
329 | if (!dev) | ||
330 | return -ENODEV; | ||
331 | |||
332 | ret = add_uevent_var(envp, num_envp, &i, | ||
333 | buffer, buffer_size, &length, | ||
334 | "MODALIAS=ssb:v%04Xid%04Xrev%02X", | ||
335 | ssb_dev->id.vendor, ssb_dev->id.coreid, | ||
336 | ssb_dev->id.revision); | ||
337 | envp[i] = NULL; | ||
338 | |||
339 | return ret; | ||
340 | } | ||
341 | |||
342 | static struct bus_type ssb_bustype = { | ||
343 | .name = "ssb", | ||
344 | .match = ssb_bus_match, | ||
345 | .probe = ssb_device_probe, | ||
346 | .remove = ssb_device_remove, | ||
347 | .shutdown = ssb_device_shutdown, | ||
348 | .suspend = ssb_device_suspend, | ||
349 | .resume = ssb_device_resume, | ||
350 | .uevent = ssb_device_uevent, | ||
351 | }; | ||
352 | |||
353 | static void ssb_buses_lock(void) | ||
354 | { | ||
355 | /* See the comment at the ssb_is_early_boot definition */ | ||
356 | if (!ssb_is_early_boot) | ||
357 | mutex_lock(&buses_mutex); | ||
358 | } | ||
359 | |||
360 | static void ssb_buses_unlock(void) | ||
361 | { | ||
362 | /* See the comment at the ssb_is_early_boot definition */ | ||
363 | if (!ssb_is_early_boot) | ||
364 | mutex_unlock(&buses_mutex); | ||
365 | } | ||
366 | |||
367 | static void ssb_devices_unregister(struct ssb_bus *bus) | ||
368 | { | ||
369 | struct ssb_device *sdev; | ||
370 | int i; | ||
371 | |||
372 | for (i = bus->nr_devices - 1; i >= 0; i--) { | ||
373 | sdev = &(bus->devices[i]); | ||
374 | if (sdev->dev) | ||
375 | device_unregister(sdev->dev); | ||
376 | } | ||
377 | } | ||
378 | |||
379 | void ssb_bus_unregister(struct ssb_bus *bus) | ||
380 | { | ||
381 | ssb_buses_lock(); | ||
382 | ssb_devices_unregister(bus); | ||
383 | list_del(&bus->list); | ||
384 | ssb_buses_unlock(); | ||
385 | |||
386 | /* ssb_pcmcia_exit(bus); */ | ||
387 | ssb_pci_exit(bus); | ||
388 | ssb_iounmap(bus); | ||
389 | } | ||
390 | EXPORT_SYMBOL(ssb_bus_unregister); | ||
391 | |||
392 | static void ssb_release_dev(struct device *dev) | ||
393 | { | ||
394 | struct __ssb_dev_wrapper *devwrap; | ||
395 | |||
396 | devwrap = container_of(dev, struct __ssb_dev_wrapper, dev); | ||
397 | kfree(devwrap); | ||
398 | } | ||
399 | |||
400 | static int ssb_devices_register(struct ssb_bus *bus) | ||
401 | { | ||
402 | struct ssb_device *sdev; | ||
403 | struct device *dev; | ||
404 | struct __ssb_dev_wrapper *devwrap; | ||
405 | int i, err = 0; | ||
406 | int dev_idx = 0; | ||
407 | |||
408 | for (i = 0; i < bus->nr_devices; i++) { | ||
409 | sdev = &(bus->devices[i]); | ||
410 | |||
411 | /* We don't register SSB-system devices to the kernel, | ||
412 | * as the drivers for them are built into SSB. */ | ||
413 | switch (sdev->id.coreid) { | ||
414 | case SSB_DEV_CHIPCOMMON: | ||
415 | case SSB_DEV_PCI: | ||
416 | case SSB_DEV_PCIE: | ||
417 | case SSB_DEV_PCMCIA: | ||
418 | case SSB_DEV_MIPS: | ||
419 | case SSB_DEV_MIPS_3302: | ||
420 | case SSB_DEV_EXTIF: | ||
421 | continue; | ||
422 | } | ||
423 | |||
424 | devwrap = kzalloc(sizeof(*devwrap), GFP_KERNEL); | ||
425 | if (!devwrap) { | ||
426 | ssb_printk(KERN_ERR PFX | ||
427 | "Could not allocate device\n"); | ||
428 | err = -ENOMEM; | ||
429 | goto error; | ||
430 | } | ||
431 | dev = &devwrap->dev; | ||
432 | devwrap->sdev = sdev; | ||
433 | |||
434 | dev->release = ssb_release_dev; | ||
435 | dev->bus = &ssb_bustype; | ||
436 | snprintf(dev->bus_id, sizeof(dev->bus_id), | ||
437 | "ssb%u:%d", bus->busnumber, dev_idx); | ||
438 | |||
439 | switch (bus->bustype) { | ||
440 | case SSB_BUSTYPE_PCI: | ||
441 | #ifdef CONFIG_SSB_PCIHOST | ||
442 | sdev->irq = bus->host_pci->irq; | ||
443 | dev->parent = &bus->host_pci->dev; | ||
444 | #endif | ||
445 | break; | ||
446 | case SSB_BUSTYPE_PCMCIA: | ||
447 | #ifdef CONFIG_SSB_PCMCIAHOST | ||
448 | dev->parent = &bus->host_pcmcia->dev; | ||
449 | #endif | ||
450 | break; | ||
451 | case SSB_BUSTYPE_SSB: | ||
452 | break; | ||
453 | } | ||
454 | |||
455 | sdev->dev = dev; | ||
456 | err = device_register(dev); | ||
457 | if (err) { | ||
458 | ssb_printk(KERN_ERR PFX | ||
459 | "Could not register %s\n", | ||
460 | dev->bus_id); | ||
461 | /* Set dev to NULL to not unregister | ||
462 | * dev on error unwinding. */ | ||
463 | sdev->dev = NULL; | ||
464 | kfree(devwrap); | ||
465 | goto error; | ||
466 | } | ||
467 | dev_idx++; | ||
468 | } | ||
469 | |||
470 | return 0; | ||
471 | error: | ||
472 | /* Unwind the already registered devices. */ | ||
473 | ssb_devices_unregister(bus); | ||
474 | return err; | ||
475 | } | ||
476 | |||
477 | /* Needs ssb_buses_lock() */ | ||
478 | static int ssb_attach_queued_buses(void) | ||
479 | { | ||
480 | struct ssb_bus *bus, *n; | ||
481 | int err = 0; | ||
482 | int drop_them_all = 0; | ||
483 | |||
484 | list_for_each_entry_safe(bus, n, &attach_queue, list) { | ||
485 | if (drop_them_all) { | ||
486 | list_del(&bus->list); | ||
487 | continue; | ||
488 | } | ||
489 | /* Can't init the PCIcore in ssb_bus_register(), as that | ||
490 | * is too early in boot for embedded systems | ||
491 | * (no udelay() available). So do it here in attach stage. | ||
492 | */ | ||
493 | err = ssb_bus_powerup(bus, 0); | ||
494 | if (err) | ||
495 | goto error; | ||
496 | ssb_pcicore_init(&bus->pcicore); | ||
497 | ssb_bus_may_powerdown(bus); | ||
498 | |||
499 | err = ssb_devices_register(bus); | ||
500 | error: | ||
501 | if (err) { | ||
502 | drop_them_all = 1; | ||
503 | list_del(&bus->list); | ||
504 | continue; | ||
505 | } | ||
506 | list_move_tail(&bus->list, &buses); | ||
507 | } | ||
508 | |||
509 | return err; | ||
510 | } | ||
511 | |||
512 | static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset) | ||
513 | { | ||
514 | struct ssb_bus *bus = dev->bus; | ||
515 | |||
516 | offset += dev->core_index * SSB_CORE_SIZE; | ||
517 | return readw(bus->mmio + offset); | ||
518 | } | ||
519 | |||
520 | static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset) | ||
521 | { | ||
522 | struct ssb_bus *bus = dev->bus; | ||
523 | |||
524 | offset += dev->core_index * SSB_CORE_SIZE; | ||
525 | return readl(bus->mmio + offset); | ||
526 | } | ||
527 | |||
528 | static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value) | ||
529 | { | ||
530 | struct ssb_bus *bus = dev->bus; | ||
531 | |||
532 | offset += dev->core_index * SSB_CORE_SIZE; | ||
533 | writew(value, bus->mmio + offset); | ||
534 | } | ||
535 | |||
536 | static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value) | ||
537 | { | ||
538 | struct ssb_bus *bus = dev->bus; | ||
539 | |||
540 | offset += dev->core_index * SSB_CORE_SIZE; | ||
541 | writel(value, bus->mmio + offset); | ||
542 | } | ||
543 | |||
544 | /* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */ | ||
545 | static const struct ssb_bus_ops ssb_ssb_ops = { | ||
546 | .read16 = ssb_ssb_read16, | ||
547 | .read32 = ssb_ssb_read32, | ||
548 | .write16 = ssb_ssb_write16, | ||
549 | .write32 = ssb_ssb_write32, | ||
550 | }; | ||
551 | |||
552 | static int ssb_fetch_invariants(struct ssb_bus *bus, | ||
553 | ssb_invariants_func_t get_invariants) | ||
554 | { | ||
555 | struct ssb_init_invariants iv; | ||
556 | int err; | ||
557 | |||
558 | memset(&iv, 0, sizeof(iv)); | ||
559 | err = get_invariants(bus, &iv); | ||
560 | if (err) | ||
561 | goto out; | ||
562 | memcpy(&bus->boardinfo, &iv.boardinfo, sizeof(iv.boardinfo)); | ||
563 | memcpy(&bus->sprom, &iv.sprom, sizeof(iv.sprom)); | ||
564 | out: | ||
565 | return err; | ||
566 | } | ||
567 | |||
568 | static int ssb_bus_register(struct ssb_bus *bus, | ||
569 | ssb_invariants_func_t get_invariants, | ||
570 | unsigned long baseaddr) | ||
571 | { | ||
572 | int err; | ||
573 | |||
574 | spin_lock_init(&bus->bar_lock); | ||
575 | INIT_LIST_HEAD(&bus->list); | ||
576 | |||
577 | /* Powerup the bus */ | ||
578 | err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1); | ||
579 | if (err) | ||
580 | goto out; | ||
581 | ssb_buses_lock(); | ||
582 | bus->busnumber = next_busnumber; | ||
583 | /* Scan for devices (cores) */ | ||
584 | err = ssb_bus_scan(bus, baseaddr); | ||
585 | if (err) | ||
586 | goto err_disable_xtal; | ||
587 | |||
588 | /* Init PCI-host device (if any) */ | ||
589 | err = ssb_pci_init(bus); | ||
590 | if (err) | ||
591 | goto err_unmap; | ||
592 | /* Init PCMCIA-host device (if any) */ | ||
593 | err = ssb_pcmcia_init(bus); | ||
594 | if (err) | ||
595 | goto err_pci_exit; | ||
596 | |||
597 | /* Initialize basic system devices (if available) */ | ||
598 | err = ssb_bus_powerup(bus, 0); | ||
599 | if (err) | ||
600 | goto err_pcmcia_exit; | ||
601 | ssb_chipcommon_init(&bus->chipco); | ||
602 | ssb_mipscore_init(&bus->mipscore); | ||
603 | err = ssb_fetch_invariants(bus, get_invariants); | ||
604 | if (err) { | ||
605 | ssb_bus_may_powerdown(bus); | ||
606 | goto err_pcmcia_exit; | ||
607 | } | ||
608 | ssb_bus_may_powerdown(bus); | ||
609 | |||
610 | /* Queue it for attach. | ||
611 | * See the comment at the ssb_is_early_boot definition. */ | ||
612 | list_add_tail(&bus->list, &attach_queue); | ||
613 | if (!ssb_is_early_boot) { | ||
614 | /* This is not early boot, so we must attach the bus now */ | ||
615 | err = ssb_attach_queued_buses(); | ||
616 | if (err) | ||
617 | goto err_dequeue; | ||
618 | } | ||
619 | next_busnumber++; | ||
620 | ssb_buses_unlock(); | ||
621 | |||
622 | out: | ||
623 | return err; | ||
624 | |||
625 | err_dequeue: | ||
626 | list_del(&bus->list); | ||
627 | err_pcmcia_exit: | ||
628 | /* ssb_pcmcia_exit(bus); */ | ||
629 | err_pci_exit: | ||
630 | ssb_pci_exit(bus); | ||
631 | err_unmap: | ||
632 | ssb_iounmap(bus); | ||
633 | err_disable_xtal: | ||
634 | ssb_buses_unlock(); | ||
635 | ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0); | ||
636 | return err; | ||
637 | } | ||
638 | |||
639 | #ifdef CONFIG_SSB_PCIHOST | ||
640 | int ssb_bus_pcibus_register(struct ssb_bus *bus, | ||
641 | struct pci_dev *host_pci) | ||
642 | { | ||
643 | int err; | ||
644 | |||
645 | bus->bustype = SSB_BUSTYPE_PCI; | ||
646 | bus->host_pci = host_pci; | ||
647 | bus->ops = &ssb_pci_ops; | ||
648 | |||
649 | err = ssb_bus_register(bus, ssb_pci_get_invariants, 0); | ||
650 | if (!err) { | ||
651 | ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on " | ||
652 | "PCI device %s\n", host_pci->dev.bus_id); | ||
653 | } | ||
654 | |||
655 | return err; | ||
656 | } | ||
657 | EXPORT_SYMBOL(ssb_bus_pcibus_register); | ||
658 | #endif /* CONFIG_SSB_PCIHOST */ | ||
659 | |||
660 | #ifdef CONFIG_SSB_PCMCIAHOST | ||
661 | int ssb_bus_pcmciabus_register(struct ssb_bus *bus, | ||
662 | struct pcmcia_device *pcmcia_dev, | ||
663 | unsigned long baseaddr) | ||
664 | { | ||
665 | int err; | ||
666 | |||
667 | bus->bustype = SSB_BUSTYPE_PCMCIA; | ||
668 | bus->host_pcmcia = pcmcia_dev; | ||
669 | bus->ops = &ssb_pcmcia_ops; | ||
670 | |||
671 | err = ssb_bus_register(bus, ssb_pcmcia_get_invariants, baseaddr); | ||
672 | if (!err) { | ||
673 | ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on " | ||
674 | "PCMCIA device %s\n", pcmcia_dev->devname); | ||
675 | } | ||
676 | |||
677 | return err; | ||
678 | } | ||
679 | EXPORT_SYMBOL(ssb_bus_pcmciabus_register); | ||
680 | #endif /* CONFIG_SSB_PCMCIAHOST */ | ||
681 | |||
682 | int ssb_bus_ssbbus_register(struct ssb_bus *bus, | ||
683 | unsigned long baseaddr, | ||
684 | ssb_invariants_func_t get_invariants) | ||
685 | { | ||
686 | int err; | ||
687 | |||
688 | bus->bustype = SSB_BUSTYPE_SSB; | ||
689 | bus->ops = &ssb_ssb_ops; | ||
690 | |||
691 | err = ssb_bus_register(bus, get_invariants, baseaddr); | ||
692 | if (!err) { | ||
693 | ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found at " | ||
694 | "address 0x%08lX\n", baseaddr); | ||
695 | } | ||
696 | |||
697 | return err; | ||
698 | } | ||
699 | |||
700 | int __ssb_driver_register(struct ssb_driver *drv, struct module *owner) | ||
701 | { | ||
702 | drv->drv.name = drv->name; | ||
703 | drv->drv.bus = &ssb_bustype; | ||
704 | drv->drv.owner = owner; | ||
705 | |||
706 | return driver_register(&drv->drv); | ||
707 | } | ||
708 | EXPORT_SYMBOL(__ssb_driver_register); | ||
709 | |||
710 | void ssb_driver_unregister(struct ssb_driver *drv) | ||
711 | { | ||
712 | driver_unregister(&drv->drv); | ||
713 | } | ||
714 | EXPORT_SYMBOL(ssb_driver_unregister); | ||
715 | |||
716 | void ssb_set_devtypedata(struct ssb_device *dev, void *data) | ||
717 | { | ||
718 | struct ssb_bus *bus = dev->bus; | ||
719 | struct ssb_device *ent; | ||
720 | int i; | ||
721 | |||
722 | for (i = 0; i < bus->nr_devices; i++) { | ||
723 | ent = &(bus->devices[i]); | ||
724 | if (ent->id.vendor != dev->id.vendor) | ||
725 | continue; | ||
726 | if (ent->id.coreid != dev->id.coreid) | ||
727 | continue; | ||
728 | |||
729 | ent->devtypedata = data; | ||
730 | } | ||
731 | } | ||
732 | EXPORT_SYMBOL(ssb_set_devtypedata); | ||
733 | |||
734 | static u32 clkfactor_f6_resolve(u32 v) | ||
735 | { | ||
736 | /* map the magic values */ | ||
737 | switch (v) { | ||
738 | case SSB_CHIPCO_CLK_F6_2: | ||
739 | return 2; | ||
740 | case SSB_CHIPCO_CLK_F6_3: | ||
741 | return 3; | ||
742 | case SSB_CHIPCO_CLK_F6_4: | ||
743 | return 4; | ||
744 | case SSB_CHIPCO_CLK_F6_5: | ||
745 | return 5; | ||
746 | case SSB_CHIPCO_CLK_F6_6: | ||
747 | return 6; | ||
748 | case SSB_CHIPCO_CLK_F6_7: | ||
749 | return 7; | ||
750 | } | ||
751 | return 0; | ||
752 | } | ||
753 | |||
754 | /* Calculate the speed the backplane would run at a given set of clockcontrol values */ | ||
755 | u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m) | ||
756 | { | ||
757 | u32 n1, n2, clock, m1, m2, m3, mc; | ||
758 | |||
759 | n1 = (n & SSB_CHIPCO_CLK_N1); | ||
760 | n2 = ((n & SSB_CHIPCO_CLK_N2) >> SSB_CHIPCO_CLK_N2_SHIFT); | ||
761 | |||
762 | switch (plltype) { | ||
763 | case SSB_PLLTYPE_6: /* 100/200 or 120/240 only */ | ||
764 | if (m & SSB_CHIPCO_CLK_T6_MMASK) | ||
765 | return SSB_CHIPCO_CLK_T6_M0; | ||
766 | return SSB_CHIPCO_CLK_T6_M1; | ||
767 | case SSB_PLLTYPE_1: /* 48Mhz base, 3 dividers */ | ||
768 | case SSB_PLLTYPE_3: /* 25Mhz, 2 dividers */ | ||
769 | case SSB_PLLTYPE_4: /* 48Mhz, 4 dividers */ | ||
770 | case SSB_PLLTYPE_7: /* 25Mhz, 4 dividers */ | ||
771 | n1 = clkfactor_f6_resolve(n1); | ||
772 | n2 += SSB_CHIPCO_CLK_F5_BIAS; | ||
773 | break; | ||
774 | case SSB_PLLTYPE_2: /* 48Mhz, 4 dividers */ | ||
775 | n1 += SSB_CHIPCO_CLK_T2_BIAS; | ||
776 | n2 += SSB_CHIPCO_CLK_T2_BIAS; | ||
777 | SSB_WARN_ON(!((n1 >= 2) && (n1 <= 7))); | ||
778 | SSB_WARN_ON(!((n2 >= 5) && (n2 <= 23))); | ||
779 | break; | ||
780 | case SSB_PLLTYPE_5: /* 25Mhz, 4 dividers */ | ||
781 | return 100000000; | ||
782 | default: | ||
783 | SSB_WARN_ON(1); | ||
784 | } | ||
785 | |||
786 | switch (plltype) { | ||
787 | case SSB_PLLTYPE_3: /* 25Mhz, 2 dividers */ | ||
788 | case SSB_PLLTYPE_7: /* 25Mhz, 4 dividers */ | ||
789 | clock = SSB_CHIPCO_CLK_BASE2 * n1 * n2; | ||
790 | break; | ||
791 | default: | ||
792 | clock = SSB_CHIPCO_CLK_BASE1 * n1 * n2; | ||
793 | } | ||
794 | if (!clock) | ||
795 | return 0; | ||
796 | |||
797 | m1 = (m & SSB_CHIPCO_CLK_M1); | ||
798 | m2 = ((m & SSB_CHIPCO_CLK_M2) >> SSB_CHIPCO_CLK_M2_SHIFT); | ||
799 | m3 = ((m & SSB_CHIPCO_CLK_M3) >> SSB_CHIPCO_CLK_M3_SHIFT); | ||
800 | mc = ((m & SSB_CHIPCO_CLK_MC) >> SSB_CHIPCO_CLK_MC_SHIFT); | ||
801 | |||
802 | switch (plltype) { | ||
803 | case SSB_PLLTYPE_1: /* 48Mhz base, 3 dividers */ | ||
804 | case SSB_PLLTYPE_3: /* 25Mhz, 2 dividers */ | ||
805 | case SSB_PLLTYPE_4: /* 48Mhz, 4 dividers */ | ||
806 | case SSB_PLLTYPE_7: /* 25Mhz, 4 dividers */ | ||
807 | m1 = clkfactor_f6_resolve(m1); | ||
808 | if ((plltype == SSB_PLLTYPE_1) || | ||
809 | (plltype == SSB_PLLTYPE_3)) | ||
810 | m2 += SSB_CHIPCO_CLK_F5_BIAS; | ||
811 | else | ||
812 | m2 = clkfactor_f6_resolve(m2); | ||
813 | m3 = clkfactor_f6_resolve(m3); | ||
814 | |||
815 | switch (mc) { | ||
816 | case SSB_CHIPCO_CLK_MC_BYPASS: | ||
817 | return clock; | ||
818 | case SSB_CHIPCO_CLK_MC_M1: | ||
819 | return (clock / m1); | ||
820 | case SSB_CHIPCO_CLK_MC_M1M2: | ||
821 | return (clock / (m1 * m2)); | ||
822 | case SSB_CHIPCO_CLK_MC_M1M2M3: | ||
823 | return (clock / (m1 * m2 * m3)); | ||
824 | case SSB_CHIPCO_CLK_MC_M1M3: | ||
825 | return (clock / (m1 * m3)); | ||
826 | } | ||
827 | return 0; | ||
828 | case SSB_PLLTYPE_2: | ||
829 | m1 += SSB_CHIPCO_CLK_T2_BIAS; | ||
830 | m2 += SSB_CHIPCO_CLK_T2M2_BIAS; | ||
831 | m3 += SSB_CHIPCO_CLK_T2_BIAS; | ||
832 | SSB_WARN_ON(!((m1 >= 2) && (m1 <= 7))); | ||
833 | SSB_WARN_ON(!((m2 >= 3) && (m2 <= 10))); | ||
834 | SSB_WARN_ON(!((m3 >= 2) && (m3 <= 7))); | ||
835 | |||
836 | if (!(mc & SSB_CHIPCO_CLK_T2MC_M1BYP)) | ||
837 | clock /= m1; | ||
838 | if (!(mc & SSB_CHIPCO_CLK_T2MC_M2BYP)) | ||
839 | clock /= m2; | ||
840 | if (!(mc & SSB_CHIPCO_CLK_T2MC_M3BYP)) | ||
841 | clock /= m3; | ||
842 | return clock; | ||
843 | default: | ||
844 | SSB_WARN_ON(1); | ||
845 | } | ||
846 | return 0; | ||
847 | } | ||
848 | |||
849 | /* Get the current speed the backplane is running at */ | ||
850 | u32 ssb_clockspeed(struct ssb_bus *bus) | ||
851 | { | ||
852 | u32 rate; | ||
853 | u32 plltype; | ||
854 | u32 clkctl_n, clkctl_m; | ||
855 | |||
856 | if (ssb_extif_available(&bus->extif)) | ||
857 | ssb_extif_get_clockcontrol(&bus->extif, &plltype, | ||
858 | &clkctl_n, &clkctl_m); | ||
859 | else if (bus->chipco.dev) | ||
860 | ssb_chipco_get_clockcontrol(&bus->chipco, &plltype, | ||
861 | &clkctl_n, &clkctl_m); | ||
862 | else | ||
863 | return 0; | ||
864 | |||
865 | if (bus->chip_id == 0x5365) { | ||
866 | rate = 100000000; | ||
867 | } else { | ||
868 | rate = ssb_calc_clock_rate(plltype, clkctl_n, clkctl_m); | ||
869 | if (plltype == SSB_PLLTYPE_3) /* 25Mhz, 2 dividers */ | ||
870 | rate /= 2; | ||
871 | } | ||
872 | |||
873 | return rate; | ||
874 | } | ||
875 | EXPORT_SYMBOL(ssb_clockspeed); | ||
876 | |||
877 | static u32 ssb_tmslow_reject_bitmask(struct ssb_device *dev) | ||
878 | { | ||
879 | /* The REJECT bit changed position in TMSLOW between | ||
880 | * Backplane revisions. */ | ||
881 | switch (ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_SSBREV) { | ||
882 | case SSB_IDLOW_SSBREV_22: | ||
883 | return SSB_TMSLOW_REJECT_22; | ||
884 | case SSB_IDLOW_SSBREV_23: | ||
885 | return SSB_TMSLOW_REJECT_23; | ||
886 | default: | ||
887 | WARN_ON(1); | ||
888 | } | ||
889 | return (SSB_TMSLOW_REJECT_22 | SSB_TMSLOW_REJECT_23); | ||
890 | } | ||
891 | |||
892 | int ssb_device_is_enabled(struct ssb_device *dev) | ||
893 | { | ||
894 | u32 val; | ||
895 | u32 reject; | ||
896 | |||
897 | reject = ssb_tmslow_reject_bitmask(dev); | ||
898 | val = ssb_read32(dev, SSB_TMSLOW); | ||
899 | val &= SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET | reject; | ||
900 | |||
901 | return (val == SSB_TMSLOW_CLOCK); | ||
902 | } | ||
903 | EXPORT_SYMBOL(ssb_device_is_enabled); | ||
904 | |||
905 | static void ssb_flush_tmslow(struct ssb_device *dev) | ||
906 | { | ||
907 | /* Make _really_ sure the device has finished the TMSLOW | ||
908 | * register write transaction, as we risk running into | ||
909 | * a machine check exception otherwise. | ||
910 | * Do this by reading the register back to commit the | ||
911 | * PCI write and delay an additional usec for the device | ||
912 | * to react to the change. */ | ||
913 | ssb_read32(dev, SSB_TMSLOW); | ||
914 | udelay(1); | ||
915 | } | ||
916 | |||
917 | void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags) | ||
918 | { | ||
919 | u32 val; | ||
920 | |||
921 | ssb_device_disable(dev, core_specific_flags); | ||
922 | ssb_write32(dev, SSB_TMSLOW, | ||
923 | SSB_TMSLOW_RESET | SSB_TMSLOW_CLOCK | | ||
924 | SSB_TMSLOW_FGC | core_specific_flags); | ||
925 | ssb_flush_tmslow(dev); | ||
926 | |||
927 | /* Clear SERR if set. This is a hw bug workaround. */ | ||
928 | if (ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_SERR) | ||
929 | ssb_write32(dev, SSB_TMSHIGH, 0); | ||
930 | |||
931 | val = ssb_read32(dev, SSB_IMSTATE); | ||
932 | if (val & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) { | ||
933 | val &= ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO); | ||
934 | ssb_write32(dev, SSB_IMSTATE, val); | ||
935 | } | ||
936 | |||
937 | ssb_write32(dev, SSB_TMSLOW, | ||
938 | SSB_TMSLOW_CLOCK | SSB_TMSLOW_FGC | | ||
939 | core_specific_flags); | ||
940 | ssb_flush_tmslow(dev); | ||
941 | |||
942 | ssb_write32(dev, SSB_TMSLOW, SSB_TMSLOW_CLOCK | | ||
943 | core_specific_flags); | ||
944 | ssb_flush_tmslow(dev); | ||
945 | } | ||
946 | EXPORT_SYMBOL(ssb_device_enable); | ||
947 | |||
948 | /* Wait for a bit in a register to get set or unset. | ||
949 | * timeout is in units of ten-microseconds */ | ||
950 | static int ssb_wait_bit(struct ssb_device *dev, u16 reg, u32 bitmask, | ||
951 | int timeout, int set) | ||
952 | { | ||
953 | int i; | ||
954 | u32 val; | ||
955 | |||
956 | for (i = 0; i < timeout; i++) { | ||
957 | val = ssb_read32(dev, reg); | ||
958 | if (set) { | ||
959 | if (val & bitmask) | ||
960 | return 0; | ||
961 | } else { | ||
962 | if (!(val & bitmask)) | ||
963 | return 0; | ||
964 | } | ||
965 | udelay(10); | ||
966 | } | ||
967 | printk(KERN_ERR PFX "Timeout waiting for bitmask %08X on " | ||
968 | "register %04X to %s.\n", | ||
969 | bitmask, reg, (set ? "set" : "clear")); | ||
970 | |||
971 | return -ETIMEDOUT; | ||
972 | } | ||
973 | |||
974 | void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags) | ||
975 | { | ||
976 | u32 reject; | ||
977 | |||
978 | if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_RESET) | ||
979 | return; | ||
980 | |||
981 | reject = ssb_tmslow_reject_bitmask(dev); | ||
982 | ssb_write32(dev, SSB_TMSLOW, reject | SSB_TMSLOW_CLOCK); | ||
983 | ssb_wait_bit(dev, SSB_TMSLOW, reject, 1000, 1); | ||
984 | ssb_wait_bit(dev, SSB_TMSHIGH, SSB_TMSHIGH_BUSY, 1000, 0); | ||
985 | ssb_write32(dev, SSB_TMSLOW, | ||
986 | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | | ||
987 | reject | SSB_TMSLOW_RESET | | ||
988 | core_specific_flags); | ||
989 | ssb_flush_tmslow(dev); | ||
990 | |||
991 | ssb_write32(dev, SSB_TMSLOW, | ||
992 | reject | SSB_TMSLOW_RESET | | ||
993 | core_specific_flags); | ||
994 | ssb_flush_tmslow(dev); | ||
995 | } | ||
996 | EXPORT_SYMBOL(ssb_device_disable); | ||
997 | |||
998 | u32 ssb_dma_translation(struct ssb_device *dev) | ||
999 | { | ||
1000 | switch (dev->bus->bustype) { | ||
1001 | case SSB_BUSTYPE_SSB: | ||
1002 | return 0; | ||
1003 | case SSB_BUSTYPE_PCI: | ||
1004 | case SSB_BUSTYPE_PCMCIA: | ||
1005 | return SSB_PCI_DMA; | ||
1006 | } | ||
1007 | return 0; | ||
1008 | } | ||
1009 | EXPORT_SYMBOL(ssb_dma_translation); | ||
1010 | |||
1011 | int ssb_dma_set_mask(struct ssb_device *ssb_dev, u64 mask) | ||
1012 | { | ||
1013 | struct device *dev = ssb_dev->dev; | ||
1014 | |||
1015 | #ifdef CONFIG_SSB_PCIHOST | ||
1016 | if (ssb_dev->bus->bustype == SSB_BUSTYPE_PCI && | ||
1017 | !dma_supported(dev, mask)) | ||
1018 | return -EIO; | ||
1019 | #endif | ||
1020 | dev->coherent_dma_mask = mask; | ||
1021 | dev->dma_mask = &dev->coherent_dma_mask; | ||
1022 | |||
1023 | return 0; | ||
1024 | } | ||
1025 | EXPORT_SYMBOL(ssb_dma_set_mask); | ||
1026 | |||
1027 | int ssb_bus_may_powerdown(struct ssb_bus *bus) | ||
1028 | { | ||
1029 | struct ssb_chipcommon *cc; | ||
1030 | int err = 0; | ||
1031 | |||
1032 | /* On buses where more than one core may be working | ||
1033 | * at a time, we must not powerdown stuff if there are | ||
1034 | * still cores that may want to run. */ | ||
1035 | if (bus->bustype == SSB_BUSTYPE_SSB) | ||
1036 | goto out; | ||
1037 | |||
1038 | cc = &bus->chipco; | ||
1039 | ssb_chipco_set_clockmode(cc, SSB_CLKMODE_SLOW); | ||
1040 | err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0); | ||
1041 | if (err) | ||
1042 | goto error; | ||
1043 | out: | ||
1044 | #ifdef CONFIG_SSB_DEBUG | ||
1045 | bus->powered_up = 0; | ||
1046 | #endif | ||
1047 | return err; | ||
1048 | error: | ||
1049 | ssb_printk(KERN_ERR PFX "Bus powerdown failed\n"); | ||
1050 | goto out; | ||
1051 | } | ||
1052 | EXPORT_SYMBOL(ssb_bus_may_powerdown); | ||
1053 | |||
1054 | int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl) | ||
1055 | { | ||
1056 | struct ssb_chipcommon *cc; | ||
1057 | int err; | ||
1058 | enum ssb_clkmode mode; | ||
1059 | |||
1060 | err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1); | ||
1061 | if (err) | ||
1062 | goto error; | ||
1063 | cc = &bus->chipco; | ||
1064 | mode = dynamic_pctl ? SSB_CLKMODE_DYNAMIC : SSB_CLKMODE_FAST; | ||
1065 | ssb_chipco_set_clockmode(cc, mode); | ||
1066 | |||
1067 | #ifdef CONFIG_SSB_DEBUG | ||
1068 | bus->powered_up = 1; | ||
1069 | #endif | ||
1070 | return 0; | ||
1071 | error: | ||
1072 | ssb_printk(KERN_ERR PFX "Bus powerup failed\n"); | ||
1073 | return err; | ||
1074 | } | ||
1075 | EXPORT_SYMBOL(ssb_bus_powerup); | ||
1076 | |||
1077 | u32 ssb_admatch_base(u32 adm) | ||
1078 | { | ||
1079 | u32 base = 0; | ||
1080 | |||
1081 | switch (adm & SSB_ADM_TYPE) { | ||
1082 | case SSB_ADM_TYPE0: | ||
1083 | base = (adm & SSB_ADM_BASE0); | ||
1084 | break; | ||
1085 | case SSB_ADM_TYPE1: | ||
1086 | SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */ | ||
1087 | base = (adm & SSB_ADM_BASE1); | ||
1088 | break; | ||
1089 | case SSB_ADM_TYPE2: | ||
1090 | SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */ | ||
1091 | base = (adm & SSB_ADM_BASE2); | ||
1092 | break; | ||
1093 | default: | ||
1094 | SSB_WARN_ON(1); | ||
1095 | } | ||
1096 | |||
1097 | return base; | ||
1098 | } | ||
1099 | EXPORT_SYMBOL(ssb_admatch_base); | ||
1100 | |||
1101 | u32 ssb_admatch_size(u32 adm) | ||
1102 | { | ||
1103 | u32 size = 0; | ||
1104 | |||
1105 | switch (adm & SSB_ADM_TYPE) { | ||
1106 | case SSB_ADM_TYPE0: | ||
1107 | size = ((adm & SSB_ADM_SZ0) >> SSB_ADM_SZ0_SHIFT); | ||
1108 | break; | ||
1109 | case SSB_ADM_TYPE1: | ||
1110 | SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */ | ||
1111 | size = ((adm & SSB_ADM_SZ1) >> SSB_ADM_SZ1_SHIFT); | ||
1112 | break; | ||
1113 | case SSB_ADM_TYPE2: | ||
1114 | SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */ | ||
1115 | size = ((adm & SSB_ADM_SZ2) >> SSB_ADM_SZ2_SHIFT); | ||
1116 | break; | ||
1117 | default: | ||
1118 | SSB_WARN_ON(1); | ||
1119 | } | ||
1120 | size = (1 << (size + 1)); | ||
1121 | |||
1122 | return size; | ||
1123 | } | ||
1124 | EXPORT_SYMBOL(ssb_admatch_size); | ||
1125 | |||
1126 | static int __init ssb_modinit(void) | ||
1127 | { | ||
1128 | int err; | ||
1129 | |||
1130 | /* See the comment at the ssb_is_early_boot definition */ | ||
1131 | ssb_is_early_boot = 0; | ||
1132 | err = bus_register(&ssb_bustype); | ||
1133 | if (err) | ||
1134 | return err; | ||
1135 | |||
1136 | /* Maybe we already registered some buses at early boot. | ||
1137 | * Check for this and attach them | ||
1138 | */ | ||
1139 | ssb_buses_lock(); | ||
1140 | err = ssb_attach_queued_buses(); | ||
1141 | ssb_buses_unlock(); | ||
1142 | if (err) | ||
1143 | bus_unregister(&ssb_bustype); | ||
1144 | |||
1145 | err = b43_pci_ssb_bridge_init(); | ||
1146 | if (err) { | ||
1147 | ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge " | ||
1148 | "initialization failed"); | ||
1149 | /* don't fail SSB init because of this */ | ||
1150 | err = 0; | ||
1151 | } | ||
1152 | |||
1153 | return err; | ||
1154 | } | ||
1155 | subsys_initcall(ssb_modinit); | ||
1156 | |||
1157 | static void __exit ssb_modexit(void) | ||
1158 | { | ||
1159 | b43_pci_ssb_bridge_exit(); | ||
1160 | bus_unregister(&ssb_bustype); | ||
1161 | } | ||
1162 | module_exit(ssb_modexit) | ||
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c new file mode 100644 index 000000000000..3d23ca4befe3 --- /dev/null +++ b/drivers/ssb/pci.c | |||
@@ -0,0 +1,740 @@ | |||
1 | /* | ||
2 | * Sonics Silicon Backplane PCI-Hostbus related functions. | ||
3 | * | ||
4 | * Copyright (C) 2005-2006 Michael Buesch <mb@bu3sch.de> | ||
5 | * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de> | ||
6 | * Copyright (C) 2005 Stefano Brivio <st3@riseup.net> | ||
7 | * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org> | ||
8 | * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> | ||
9 | * | ||
10 | * Derived from the Broadcom 4400 device driver. | ||
11 | * Copyright (C) 2002 David S. Miller (davem@redhat.com) | ||
12 | * Fixed by Pekka Pietikainen (pp@ee.oulu.fi) | ||
13 | * Copyright (C) 2006 Broadcom Corporation. | ||
14 | * | ||
15 | * Licensed under the GNU/GPL. See COPYING for details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/ssb/ssb.h> | ||
19 | #include <linux/ssb/ssb_regs.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/delay.h> | ||
22 | |||
23 | #include "ssb_private.h" | ||
24 | |||
25 | |||
26 | /* Define the following to 1 to enable a printk on each coreswitch. */ | ||
27 | #define SSB_VERBOSE_PCICORESWITCH_DEBUG 0 | ||
28 | |||
29 | |||
30 | /* Lowlevel coreswitching */ | ||
31 | int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx) | ||
32 | { | ||
33 | int err; | ||
34 | int attempts = 0; | ||
35 | u32 cur_core; | ||
36 | |||
37 | while (1) { | ||
38 | err = pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN, | ||
39 | (coreidx * SSB_CORE_SIZE) | ||
40 | + SSB_ENUM_BASE); | ||
41 | if (err) | ||
42 | goto error; | ||
43 | err = pci_read_config_dword(bus->host_pci, SSB_BAR0_WIN, | ||
44 | &cur_core); | ||
45 | if (err) | ||
46 | goto error; | ||
47 | cur_core = (cur_core - SSB_ENUM_BASE) | ||
48 | / SSB_CORE_SIZE; | ||
49 | if (cur_core == coreidx) | ||
50 | break; | ||
51 | |||
52 | if (attempts++ > SSB_BAR0_MAX_RETRIES) | ||
53 | goto error; | ||
54 | udelay(10); | ||
55 | } | ||
56 | return 0; | ||
57 | error: | ||
58 | ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx); | ||
59 | return -ENODEV; | ||
60 | } | ||
61 | |||
62 | int ssb_pci_switch_core(struct ssb_bus *bus, | ||
63 | struct ssb_device *dev) | ||
64 | { | ||
65 | int err; | ||
66 | unsigned long flags; | ||
67 | |||
68 | #if SSB_VERBOSE_PCICORESWITCH_DEBUG | ||
69 | ssb_printk(KERN_INFO PFX | ||
70 | "Switching to %s core, index %d\n", | ||
71 | ssb_core_name(dev->id.coreid), | ||
72 | dev->core_index); | ||
73 | #endif | ||
74 | |||
75 | spin_lock_irqsave(&bus->bar_lock, flags); | ||
76 | err = ssb_pci_switch_coreidx(bus, dev->core_index); | ||
77 | if (!err) | ||
78 | bus->mapped_device = dev; | ||
79 | spin_unlock_irqrestore(&bus->bar_lock, flags); | ||
80 | |||
81 | return err; | ||
82 | } | ||
83 | |||
84 | /* Enable/disable the on board crystal oscillator and/or PLL. */ | ||
85 | int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on) | ||
86 | { | ||
87 | int err; | ||
88 | u32 in, out, outenable; | ||
89 | u16 pci_status; | ||
90 | |||
91 | if (bus->bustype != SSB_BUSTYPE_PCI) | ||
92 | return 0; | ||
93 | |||
94 | err = pci_read_config_dword(bus->host_pci, SSB_GPIO_IN, &in); | ||
95 | if (err) | ||
96 | goto err_pci; | ||
97 | err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &out); | ||
98 | if (err) | ||
99 | goto err_pci; | ||
100 | err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, &outenable); | ||
101 | if (err) | ||
102 | goto err_pci; | ||
103 | |||
104 | outenable |= what; | ||
105 | |||
106 | if (turn_on) { | ||
107 | /* Avoid glitching the clock if GPRS is already using it. | ||
108 | * We can't actually read the state of the PLLPD so we infer it | ||
109 | * by the value of XTAL_PU which *is* readable via gpioin. | ||
110 | */ | ||
111 | if (!(in & SSB_GPIO_XTAL)) { | ||
112 | if (what & SSB_GPIO_XTAL) { | ||
113 | /* Turn the crystal on */ | ||
114 | out |= SSB_GPIO_XTAL; | ||
115 | if (what & SSB_GPIO_PLL) | ||
116 | out |= SSB_GPIO_PLL; | ||
117 | err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out); | ||
118 | if (err) | ||
119 | goto err_pci; | ||
120 | err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, | ||
121 | outenable); | ||
122 | if (err) | ||
123 | goto err_pci; | ||
124 | msleep(1); | ||
125 | } | ||
126 | if (what & SSB_GPIO_PLL) { | ||
127 | /* Turn the PLL on */ | ||
128 | out &= ~SSB_GPIO_PLL; | ||
129 | err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out); | ||
130 | if (err) | ||
131 | goto err_pci; | ||
132 | msleep(5); | ||
133 | } | ||
134 | } | ||
135 | |||
136 | err = pci_read_config_word(bus->host_pci, PCI_STATUS, &pci_status); | ||
137 | if (err) | ||
138 | goto err_pci; | ||
139 | pci_status &= ~PCI_STATUS_SIG_TARGET_ABORT; | ||
140 | err = pci_write_config_word(bus->host_pci, PCI_STATUS, pci_status); | ||
141 | if (err) | ||
142 | goto err_pci; | ||
143 | } else { | ||
144 | if (what & SSB_GPIO_XTAL) { | ||
145 | /* Turn the crystal off */ | ||
146 | out &= ~SSB_GPIO_XTAL; | ||
147 | } | ||
148 | if (what & SSB_GPIO_PLL) { | ||
149 | /* Turn the PLL off */ | ||
150 | out |= SSB_GPIO_PLL; | ||
151 | } | ||
152 | err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out); | ||
153 | if (err) | ||
154 | goto err_pci; | ||
155 | err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, outenable); | ||
156 | if (err) | ||
157 | goto err_pci; | ||
158 | } | ||
159 | |||
160 | out: | ||
161 | return err; | ||
162 | |||
163 | err_pci: | ||
164 | printk(KERN_ERR PFX "Error: ssb_pci_xtal() could not access PCI config space!\n"); | ||
165 | err = -EBUSY; | ||
166 | goto out; | ||
167 | } | ||
168 | |||
169 | /* Get the word-offset for a SSB_SPROM_XXX define. */ | ||
170 | #define SPOFF(offset) (((offset) - SSB_SPROM_BASE) / sizeof(u16)) | ||
171 | /* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */ | ||
172 | #define SPEX(_outvar, _offset, _mask, _shift) \ | ||
173 | out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift)) | ||
174 | |||
175 | static inline u8 ssb_crc8(u8 crc, u8 data) | ||
176 | { | ||
177 | /* Polynomial: x^8 + x^7 + x^6 + x^4 + x^2 + 1 */ | ||
178 | static const u8 t[] = { | ||
179 | 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, | ||
180 | 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, | ||
181 | 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, | ||
182 | 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, | ||
183 | 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, | ||
184 | 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, | ||
185 | 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, | ||
186 | 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, | ||
187 | 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, | ||
188 | 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, | ||
189 | 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, | ||
190 | 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, | ||
191 | 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, | ||
192 | 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, | ||
193 | 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, | ||
194 | 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, | ||
195 | 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, | ||
196 | 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, | ||
197 | 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, | ||
198 | 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, | ||
199 | 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, | ||
200 | 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, | ||
201 | 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, | ||
202 | 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, | ||
203 | 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, | ||
204 | 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, | ||
205 | 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, | ||
206 | 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, | ||
207 | 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, | ||
208 | 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, | ||
209 | 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, | ||
210 | 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F, | ||
211 | }; | ||
212 | return t[crc ^ data]; | ||
213 | } | ||
214 | |||
215 | static u8 ssb_sprom_crc(const u16 *sprom) | ||
216 | { | ||
217 | int word; | ||
218 | u8 crc = 0xFF; | ||
219 | |||
220 | for (word = 0; word < SSB_SPROMSIZE_WORDS - 1; word++) { | ||
221 | crc = ssb_crc8(crc, sprom[word] & 0x00FF); | ||
222 | crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8); | ||
223 | } | ||
224 | crc = ssb_crc8(crc, sprom[SPOFF(SSB_SPROM_REVISION)] & 0x00FF); | ||
225 | crc ^= 0xFF; | ||
226 | |||
227 | return crc; | ||
228 | } | ||
229 | |||
230 | static int sprom_check_crc(const u16 *sprom) | ||
231 | { | ||
232 | u8 crc; | ||
233 | u8 expected_crc; | ||
234 | u16 tmp; | ||
235 | |||
236 | crc = ssb_sprom_crc(sprom); | ||
237 | tmp = sprom[SPOFF(SSB_SPROM_REVISION)] & SSB_SPROM_REVISION_CRC; | ||
238 | expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT; | ||
239 | if (crc != expected_crc) | ||
240 | return -EPROTO; | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static void sprom_do_read(struct ssb_bus *bus, u16 *sprom) | ||
246 | { | ||
247 | int i; | ||
248 | |||
249 | for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) | ||
250 | sprom[i] = readw(bus->mmio + SSB_SPROM_BASE + (i * 2)); | ||
251 | } | ||
252 | |||
253 | static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) | ||
254 | { | ||
255 | struct pci_dev *pdev = bus->host_pci; | ||
256 | int i, err; | ||
257 | u32 spromctl; | ||
258 | |||
259 | ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); | ||
260 | err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); | ||
261 | if (err) | ||
262 | goto err_ctlreg; | ||
263 | spromctl |= SSB_SPROMCTL_WE; | ||
264 | err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl); | ||
265 | if (err) | ||
266 | goto err_ctlreg; | ||
267 | ssb_printk(KERN_NOTICE PFX "[ 0%%"); | ||
268 | msleep(500); | ||
269 | for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) { | ||
270 | if (i == SSB_SPROMSIZE_WORDS / 4) | ||
271 | ssb_printk("25%%"); | ||
272 | else if (i == SSB_SPROMSIZE_WORDS / 2) | ||
273 | ssb_printk("50%%"); | ||
274 | else if (i == (SSB_SPROMSIZE_WORDS / 4) * 3) | ||
275 | ssb_printk("75%%"); | ||
276 | else if (i % 2) | ||
277 | ssb_printk("."); | ||
278 | writew(sprom[i], bus->mmio + SSB_SPROM_BASE + (i * 2)); | ||
279 | mmiowb(); | ||
280 | msleep(20); | ||
281 | } | ||
282 | err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); | ||
283 | if (err) | ||
284 | goto err_ctlreg; | ||
285 | spromctl &= ~SSB_SPROMCTL_WE; | ||
286 | err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl); | ||
287 | if (err) | ||
288 | goto err_ctlreg; | ||
289 | msleep(500); | ||
290 | ssb_printk("100%% ]\n"); | ||
291 | ssb_printk(KERN_NOTICE PFX "SPROM written.\n"); | ||
292 | |||
293 | return 0; | ||
294 | err_ctlreg: | ||
295 | ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n"); | ||
296 | return err; | ||
297 | } | ||
298 | |||
299 | static void sprom_extract_r1(struct ssb_sprom_r1 *out, const u16 *in) | ||
300 | { | ||
301 | int i; | ||
302 | u16 v; | ||
303 | |||
304 | SPEX(pci_spid, SSB_SPROM1_SPID, 0xFFFF, 0); | ||
305 | SPEX(pci_svid, SSB_SPROM1_SVID, 0xFFFF, 0); | ||
306 | SPEX(pci_pid, SSB_SPROM1_PID, 0xFFFF, 0); | ||
307 | for (i = 0; i < 3; i++) { | ||
308 | v = in[SPOFF(SSB_SPROM1_IL0MAC) + i]; | ||
309 | *(((u16 *)out->il0mac) + i) = cpu_to_be16(v); | ||
310 | } | ||
311 | for (i = 0; i < 3; i++) { | ||
312 | v = in[SPOFF(SSB_SPROM1_ET0MAC) + i]; | ||
313 | *(((u16 *)out->et0mac) + i) = cpu_to_be16(v); | ||
314 | } | ||
315 | for (i = 0; i < 3; i++) { | ||
316 | v = in[SPOFF(SSB_SPROM1_ET1MAC) + i]; | ||
317 | *(((u16 *)out->et1mac) + i) = cpu_to_be16(v); | ||
318 | } | ||
319 | SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); | ||
320 | SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, | ||
321 | SSB_SPROM1_ETHPHY_ET1A_SHIFT); | ||
322 | SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14); | ||
323 | SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15); | ||
324 | SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0); | ||
325 | SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, | ||
326 | SSB_SPROM1_BINF_CCODE_SHIFT); | ||
327 | SPEX(antenna_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA, | ||
328 | SSB_SPROM1_BINF_ANTA_SHIFT); | ||
329 | SPEX(antenna_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG, | ||
330 | SSB_SPROM1_BINF_ANTBG_SHIFT); | ||
331 | SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0); | ||
332 | SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0); | ||
333 | SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0); | ||
334 | SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0); | ||
335 | SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0); | ||
336 | SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0); | ||
337 | SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0); | ||
338 | SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1, | ||
339 | SSB_SPROM1_GPIOA_P1_SHIFT); | ||
340 | SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0); | ||
341 | SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3, | ||
342 | SSB_SPROM1_GPIOB_P3_SHIFT); | ||
343 | SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A, | ||
344 | SSB_SPROM1_MAXPWR_A_SHIFT); | ||
345 | SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0); | ||
346 | SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A, | ||
347 | SSB_SPROM1_ITSSI_A_SHIFT); | ||
348 | SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); | ||
349 | SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); | ||
350 | SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0); | ||
351 | SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG, | ||
352 | SSB_SPROM1_AGAIN_BG_SHIFT); | ||
353 | for (i = 0; i < 4; i++) { | ||
354 | v = in[SPOFF(SSB_SPROM1_OEM) + i]; | ||
355 | *(((u16 *)out->oem) + i) = cpu_to_le16(v); | ||
356 | } | ||
357 | } | ||
358 | |||
359 | static void sprom_extract_r2(struct ssb_sprom_r2 *out, const u16 *in) | ||
360 | { | ||
361 | int i; | ||
362 | u16 v; | ||
363 | |||
364 | SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); | ||
365 | SPEX(maxpwr_a_hi, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0); | ||
366 | SPEX(maxpwr_a_lo, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO, | ||
367 | SSB_SPROM2_MAXP_A_LO_SHIFT); | ||
368 | SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0); | ||
369 | SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0); | ||
370 | SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0); | ||
371 | SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0); | ||
372 | SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0); | ||
373 | SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0); | ||
374 | SPEX(ofdm_pwr_off, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0); | ||
375 | for (i = 0; i < 4; i++) { | ||
376 | v = in[SPOFF(SSB_SPROM2_CCODE) + i]; | ||
377 | *(((u16 *)out->country_str) + i) = cpu_to_le16(v); | ||
378 | } | ||
379 | } | ||
380 | |||
381 | static void sprom_extract_r3(struct ssb_sprom_r3 *out, const u16 *in) | ||
382 | { | ||
383 | out->ofdmapo = (in[SPOFF(SSB_SPROM3_OFDMAPO) + 0] & 0xFF00) >> 8; | ||
384 | out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 0] & 0x00FF) << 8; | ||
385 | out->ofdmapo <<= 16; | ||
386 | out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 1] & 0xFF00) >> 8; | ||
387 | out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 1] & 0x00FF) << 8; | ||
388 | |||
389 | out->ofdmalpo = (in[SPOFF(SSB_SPROM3_OFDMALPO) + 0] & 0xFF00) >> 8; | ||
390 | out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 0] & 0x00FF) << 8; | ||
391 | out->ofdmalpo <<= 16; | ||
392 | out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 1] & 0xFF00) >> 8; | ||
393 | out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 1] & 0x00FF) << 8; | ||
394 | |||
395 | out->ofdmahpo = (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 0] & 0xFF00) >> 8; | ||
396 | out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 0] & 0x00FF) << 8; | ||
397 | out->ofdmahpo <<= 16; | ||
398 | out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 1] & 0xFF00) >> 8; | ||
399 | out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 1] & 0x00FF) << 8; | ||
400 | |||
401 | SPEX(gpioldc_on_cnt, SSB_SPROM3_GPIOLDC, SSB_SPROM3_GPIOLDC_ON, | ||
402 | SSB_SPROM3_GPIOLDC_ON_SHIFT); | ||
403 | SPEX(gpioldc_off_cnt, SSB_SPROM3_GPIOLDC, SSB_SPROM3_GPIOLDC_OFF, | ||
404 | SSB_SPROM3_GPIOLDC_OFF_SHIFT); | ||
405 | SPEX(cckpo_1M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_1M, 0); | ||
406 | SPEX(cckpo_2M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_2M, | ||
407 | SSB_SPROM3_CCKPO_2M_SHIFT); | ||
408 | SPEX(cckpo_55M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_55M, | ||
409 | SSB_SPROM3_CCKPO_55M_SHIFT); | ||
410 | SPEX(cckpo_11M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_11M, | ||
411 | SSB_SPROM3_CCKPO_11M_SHIFT); | ||
412 | |||
413 | out->ofdmgpo = (in[SPOFF(SSB_SPROM3_OFDMGPO) + 0] & 0xFF00) >> 8; | ||
414 | out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 0] & 0x00FF) << 8; | ||
415 | out->ofdmgpo <<= 16; | ||
416 | out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0xFF00) >> 8; | ||
417 | out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0x00FF) << 8; | ||
418 | } | ||
419 | |||
420 | static int sprom_extract(struct ssb_bus *bus, | ||
421 | struct ssb_sprom *out, const u16 *in) | ||
422 | { | ||
423 | memset(out, 0, sizeof(*out)); | ||
424 | |||
425 | SPEX(revision, SSB_SPROM_REVISION, SSB_SPROM_REVISION_REV, 0); | ||
426 | SPEX(crc, SSB_SPROM_REVISION, SSB_SPROM_REVISION_CRC, | ||
427 | SSB_SPROM_REVISION_CRC_SHIFT); | ||
428 | |||
429 | if ((bus->chip_id & 0xFF00) == 0x4400) { | ||
430 | /* Workaround: The BCM44XX chip has a stupid revision | ||
431 | * number stored in the SPROM. | ||
432 | * Always extract r1. */ | ||
433 | sprom_extract_r1(&out->r1, in); | ||
434 | } else { | ||
435 | if (out->revision == 0) | ||
436 | goto unsupported; | ||
437 | if (out->revision >= 1 && out->revision <= 3) | ||
438 | sprom_extract_r1(&out->r1, in); | ||
439 | if (out->revision >= 2 && out->revision <= 3) | ||
440 | sprom_extract_r2(&out->r2, in); | ||
441 | if (out->revision == 3) | ||
442 | sprom_extract_r3(&out->r3, in); | ||
443 | if (out->revision >= 4) | ||
444 | goto unsupported; | ||
445 | } | ||
446 | |||
447 | return 0; | ||
448 | unsupported: | ||
449 | ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d " | ||
450 | "detected. Will extract v1\n", out->revision); | ||
451 | sprom_extract_r1(&out->r1, in); | ||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | static int ssb_pci_sprom_get(struct ssb_bus *bus, | ||
456 | struct ssb_sprom *sprom) | ||
457 | { | ||
458 | int err = -ENOMEM; | ||
459 | u16 *buf; | ||
460 | |||
461 | buf = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL); | ||
462 | if (!buf) | ||
463 | goto out; | ||
464 | sprom_do_read(bus, buf); | ||
465 | err = sprom_check_crc(buf); | ||
466 | if (err) { | ||
467 | ssb_printk(KERN_WARNING PFX | ||
468 | "WARNING: Invalid SPROM CRC (corrupt SPROM)\n"); | ||
469 | } | ||
470 | err = sprom_extract(bus, sprom, buf); | ||
471 | |||
472 | kfree(buf); | ||
473 | out: | ||
474 | return err; | ||
475 | } | ||
476 | |||
477 | static void ssb_pci_get_boardinfo(struct ssb_bus *bus, | ||
478 | struct ssb_boardinfo *bi) | ||
479 | { | ||
480 | pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID, | ||
481 | &bi->vendor); | ||
482 | pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID, | ||
483 | &bi->type); | ||
484 | pci_read_config_word(bus->host_pci, PCI_REVISION_ID, | ||
485 | &bi->rev); | ||
486 | } | ||
487 | |||
488 | int ssb_pci_get_invariants(struct ssb_bus *bus, | ||
489 | struct ssb_init_invariants *iv) | ||
490 | { | ||
491 | int err; | ||
492 | |||
493 | err = ssb_pci_sprom_get(bus, &iv->sprom); | ||
494 | if (err) | ||
495 | goto out; | ||
496 | ssb_pci_get_boardinfo(bus, &iv->boardinfo); | ||
497 | |||
498 | out: | ||
499 | return err; | ||
500 | } | ||
501 | |||
502 | #ifdef CONFIG_SSB_DEBUG | ||
503 | static int ssb_pci_assert_buspower(struct ssb_bus *bus) | ||
504 | { | ||
505 | if (likely(bus->powered_up)) | ||
506 | return 0; | ||
507 | |||
508 | printk(KERN_ERR PFX "FATAL ERROR: Bus powered down " | ||
509 | "while accessing PCI MMIO space\n"); | ||
510 | if (bus->power_warn_count <= 10) { | ||
511 | bus->power_warn_count++; | ||
512 | dump_stack(); | ||
513 | } | ||
514 | |||
515 | return -ENODEV; | ||
516 | } | ||
517 | #else /* DEBUG */ | ||
518 | static inline int ssb_pci_assert_buspower(struct ssb_bus *bus) | ||
519 | { | ||
520 | return 0; | ||
521 | } | ||
522 | #endif /* DEBUG */ | ||
523 | |||
524 | static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset) | ||
525 | { | ||
526 | struct ssb_bus *bus = dev->bus; | ||
527 | |||
528 | if (unlikely(ssb_pci_assert_buspower(bus))) | ||
529 | return 0xFFFF; | ||
530 | if (unlikely(bus->mapped_device != dev)) { | ||
531 | if (unlikely(ssb_pci_switch_core(bus, dev))) | ||
532 | return 0xFFFF; | ||
533 | } | ||
534 | return readw(bus->mmio + offset); | ||
535 | } | ||
536 | |||
537 | static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset) | ||
538 | { | ||
539 | struct ssb_bus *bus = dev->bus; | ||
540 | |||
541 | if (unlikely(ssb_pci_assert_buspower(bus))) | ||
542 | return 0xFFFFFFFF; | ||
543 | if (unlikely(bus->mapped_device != dev)) { | ||
544 | if (unlikely(ssb_pci_switch_core(bus, dev))) | ||
545 | return 0xFFFFFFFF; | ||
546 | } | ||
547 | return readl(bus->mmio + offset); | ||
548 | } | ||
549 | |||
550 | static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value) | ||
551 | { | ||
552 | struct ssb_bus *bus = dev->bus; | ||
553 | |||
554 | if (unlikely(ssb_pci_assert_buspower(bus))) | ||
555 | return; | ||
556 | if (unlikely(bus->mapped_device != dev)) { | ||
557 | if (unlikely(ssb_pci_switch_core(bus, dev))) | ||
558 | return; | ||
559 | } | ||
560 | writew(value, bus->mmio + offset); | ||
561 | } | ||
562 | |||
563 | static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value) | ||
564 | { | ||
565 | struct ssb_bus *bus = dev->bus; | ||
566 | |||
567 | if (unlikely(ssb_pci_assert_buspower(bus))) | ||
568 | return; | ||
569 | if (unlikely(bus->mapped_device != dev)) { | ||
570 | if (unlikely(ssb_pci_switch_core(bus, dev))) | ||
571 | return; | ||
572 | } | ||
573 | writel(value, bus->mmio + offset); | ||
574 | } | ||
575 | |||
576 | /* Not "static", as it's used in main.c */ | ||
577 | const struct ssb_bus_ops ssb_pci_ops = { | ||
578 | .read16 = ssb_pci_read16, | ||
579 | .read32 = ssb_pci_read32, | ||
580 | .write16 = ssb_pci_write16, | ||
581 | .write32 = ssb_pci_write32, | ||
582 | }; | ||
583 | |||
584 | static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len) | ||
585 | { | ||
586 | int i, pos = 0; | ||
587 | |||
588 | for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) { | ||
589 | pos += snprintf(buf + pos, buf_len - pos - 1, | ||
590 | "%04X", swab16(sprom[i]) & 0xFFFF); | ||
591 | } | ||
592 | pos += snprintf(buf + pos, buf_len - pos - 1, "\n"); | ||
593 | |||
594 | return pos + 1; | ||
595 | } | ||
596 | |||
597 | static int hex2sprom(u16 *sprom, const char *dump, size_t len) | ||
598 | { | ||
599 | char tmp[5] = { 0 }; | ||
600 | int cnt = 0; | ||
601 | unsigned long parsed; | ||
602 | |||
603 | if (len < SSB_SPROMSIZE_BYTES * 2) | ||
604 | return -EINVAL; | ||
605 | |||
606 | while (cnt < SSB_SPROMSIZE_WORDS) { | ||
607 | memcpy(tmp, dump, 4); | ||
608 | dump += 4; | ||
609 | parsed = simple_strtoul(tmp, NULL, 16); | ||
610 | sprom[cnt++] = swab16((u16)parsed); | ||
611 | } | ||
612 | |||
613 | return 0; | ||
614 | } | ||
615 | |||
616 | static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev, | ||
617 | struct device_attribute *attr, | ||
618 | char *buf) | ||
619 | { | ||
620 | struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev); | ||
621 | struct ssb_bus *bus; | ||
622 | u16 *sprom; | ||
623 | int err = -ENODEV; | ||
624 | ssize_t count = 0; | ||
625 | |||
626 | bus = ssb_pci_dev_to_bus(pdev); | ||
627 | if (!bus) | ||
628 | goto out; | ||
629 | err = -ENOMEM; | ||
630 | sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL); | ||
631 | if (!sprom) | ||
632 | goto out; | ||
633 | |||
634 | /* Use interruptible locking, as the SPROM write might | ||
635 | * be holding the lock for several seconds. So allow userspace | ||
636 | * to cancel operation. */ | ||
637 | err = -ERESTARTSYS; | ||
638 | if (mutex_lock_interruptible(&bus->pci_sprom_mutex)) | ||
639 | goto out_kfree; | ||
640 | sprom_do_read(bus, sprom); | ||
641 | mutex_unlock(&bus->pci_sprom_mutex); | ||
642 | |||
643 | count = sprom2hex(sprom, buf, PAGE_SIZE); | ||
644 | err = 0; | ||
645 | |||
646 | out_kfree: | ||
647 | kfree(sprom); | ||
648 | out: | ||
649 | return err ? err : count; | ||
650 | } | ||
651 | |||
652 | static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev, | ||
653 | struct device_attribute *attr, | ||
654 | const char *buf, size_t count) | ||
655 | { | ||
656 | struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev); | ||
657 | struct ssb_bus *bus; | ||
658 | u16 *sprom; | ||
659 | int res = 0, err = -ENODEV; | ||
660 | |||
661 | bus = ssb_pci_dev_to_bus(pdev); | ||
662 | if (!bus) | ||
663 | goto out; | ||
664 | err = -ENOMEM; | ||
665 | sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL); | ||
666 | if (!sprom) | ||
667 | goto out; | ||
668 | err = hex2sprom(sprom, buf, count); | ||
669 | if (err) { | ||
670 | err = -EINVAL; | ||
671 | goto out_kfree; | ||
672 | } | ||
673 | err = sprom_check_crc(sprom); | ||
674 | if (err) { | ||
675 | err = -EINVAL; | ||
676 | goto out_kfree; | ||
677 | } | ||
678 | |||
679 | /* Use interruptible locking, as the SPROM write might | ||
680 | * be holding the lock for several seconds. So allow userspace | ||
681 | * to cancel operation. */ | ||
682 | err = -ERESTARTSYS; | ||
683 | if (mutex_lock_interruptible(&bus->pci_sprom_mutex)) | ||
684 | goto out_kfree; | ||
685 | err = ssb_devices_freeze(bus); | ||
686 | if (err == -EOPNOTSUPP) { | ||
687 | ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. " | ||
688 | "No suspend support. Is CONFIG_PM enabled?\n"); | ||
689 | goto out_unlock; | ||
690 | } | ||
691 | if (err) { | ||
692 | ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n"); | ||
693 | goto out_unlock; | ||
694 | } | ||
695 | res = sprom_do_write(bus, sprom); | ||
696 | err = ssb_devices_thaw(bus); | ||
697 | if (err) | ||
698 | ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n"); | ||
699 | out_unlock: | ||
700 | mutex_unlock(&bus->pci_sprom_mutex); | ||
701 | out_kfree: | ||
702 | kfree(sprom); | ||
703 | out: | ||
704 | if (res) | ||
705 | return res; | ||
706 | return err ? err : count; | ||
707 | } | ||
708 | |||
709 | static DEVICE_ATTR(ssb_sprom, 0600, | ||
710 | ssb_pci_attr_sprom_show, | ||
711 | ssb_pci_attr_sprom_store); | ||
712 | |||
713 | void ssb_pci_exit(struct ssb_bus *bus) | ||
714 | { | ||
715 | struct pci_dev *pdev; | ||
716 | |||
717 | if (bus->bustype != SSB_BUSTYPE_PCI) | ||
718 | return; | ||
719 | |||
720 | pdev = bus->host_pci; | ||
721 | device_remove_file(&pdev->dev, &dev_attr_ssb_sprom); | ||
722 | } | ||
723 | |||
724 | int ssb_pci_init(struct ssb_bus *bus) | ||
725 | { | ||
726 | struct pci_dev *pdev; | ||
727 | int err; | ||
728 | |||
729 | if (bus->bustype != SSB_BUSTYPE_PCI) | ||
730 | return 0; | ||
731 | |||
732 | pdev = bus->host_pci; | ||
733 | mutex_init(&bus->pci_sprom_mutex); | ||
734 | err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom); | ||
735 | if (err) | ||
736 | goto out; | ||
737 | |||
738 | out: | ||
739 | return err; | ||
740 | } | ||
diff --git a/drivers/ssb/pcihost_wrapper.c b/drivers/ssb/pcihost_wrapper.c new file mode 100644 index 000000000000..82a10abef640 --- /dev/null +++ b/drivers/ssb/pcihost_wrapper.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * Sonics Silicon Backplane | ||
3 | * PCI Hostdevice wrapper | ||
4 | * | ||
5 | * Copyright (c) 2005 Martin Langer <martin-langer@gmx.de> | ||
6 | * Copyright (c) 2005 Stefano Brivio <st3@riseup.net> | ||
7 | * Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org> | ||
8 | * Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> | ||
9 | * Copyright (c) 2005-2007 Michael Buesch <mbuesch@freenet.de> | ||
10 | * | ||
11 | * Licensed under the GNU/GPL. See COPYING for details. | ||
12 | */ | ||
13 | |||
14 | #include <linux/pci.h> | ||
15 | #include <linux/ssb/ssb.h> | ||
16 | |||
17 | |||
18 | #ifdef CONFIG_PM | ||
19 | static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state) | ||
20 | { | ||
21 | pci_save_state(dev); | ||
22 | pci_disable_device(dev); | ||
23 | pci_set_power_state(dev, pci_choose_state(dev, state)); | ||
24 | |||
25 | return 0; | ||
26 | } | ||
27 | |||
28 | static int ssb_pcihost_resume(struct pci_dev *dev) | ||
29 | { | ||
30 | int err; | ||
31 | |||
32 | pci_set_power_state(dev, 0); | ||
33 | err = pci_enable_device(dev); | ||
34 | if (err) | ||
35 | return err; | ||
36 | pci_restore_state(dev); | ||
37 | |||
38 | return 0; | ||
39 | } | ||
40 | #else /* CONFIG_PM */ | ||
41 | # define ssb_pcihost_suspend NULL | ||
42 | # define ssb_pcihost_resume NULL | ||
43 | #endif /* CONFIG_PM */ | ||
44 | |||
45 | static int ssb_pcihost_probe(struct pci_dev *dev, | ||
46 | const struct pci_device_id *id) | ||
47 | { | ||
48 | struct ssb_bus *ssb; | ||
49 | int err = -ENOMEM; | ||
50 | const char *name; | ||
51 | |||
52 | ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); | ||
53 | if (!ssb) | ||
54 | goto out; | ||
55 | err = pci_enable_device(dev); | ||
56 | if (err) | ||
57 | goto err_kfree_ssb; | ||
58 | name = dev->dev.bus_id; | ||
59 | if (dev->driver && dev->driver->name) | ||
60 | name = dev->driver->name; | ||
61 | err = pci_request_regions(dev, name); | ||
62 | if (err) | ||
63 | goto err_pci_disable; | ||
64 | pci_set_master(dev); | ||
65 | |||
66 | err = ssb_bus_pcibus_register(ssb, dev); | ||
67 | if (err) | ||
68 | goto err_pci_release_regions; | ||
69 | |||
70 | pci_set_drvdata(dev, ssb); | ||
71 | |||
72 | out: | ||
73 | return err; | ||
74 | |||
75 | err_pci_release_regions: | ||
76 | pci_release_regions(dev); | ||
77 | err_pci_disable: | ||
78 | pci_disable_device(dev); | ||
79 | err_kfree_ssb: | ||
80 | kfree(ssb); | ||
81 | return err; | ||
82 | } | ||
83 | |||
84 | static void ssb_pcihost_remove(struct pci_dev *dev) | ||
85 | { | ||
86 | struct ssb_bus *ssb = pci_get_drvdata(dev); | ||
87 | |||
88 | ssb_bus_unregister(ssb); | ||
89 | pci_release_regions(dev); | ||
90 | pci_disable_device(dev); | ||
91 | kfree(ssb); | ||
92 | pci_set_drvdata(dev, NULL); | ||
93 | } | ||
94 | |||
95 | int ssb_pcihost_register(struct pci_driver *driver) | ||
96 | { | ||
97 | driver->probe = ssb_pcihost_probe; | ||
98 | driver->remove = ssb_pcihost_remove; | ||
99 | driver->suspend = ssb_pcihost_suspend; | ||
100 | driver->resume = ssb_pcihost_resume; | ||
101 | |||
102 | return pci_register_driver(driver); | ||
103 | } | ||
104 | EXPORT_SYMBOL(ssb_pcihost_register); | ||
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c new file mode 100644 index 000000000000..7c773603b402 --- /dev/null +++ b/drivers/ssb/pcmcia.c | |||
@@ -0,0 +1,271 @@ | |||
1 | /* | ||
2 | * Sonics Silicon Backplane | ||
3 | * PCMCIA-Hostbus related functions | ||
4 | * | ||
5 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
6 | * Copyright 2007 Michael Buesch <mb@bu3sch.de> | ||
7 | * | ||
8 | * Licensed under the GNU/GPL. See COPYING for details. | ||
9 | */ | ||
10 | |||
11 | #include <linux/ssb/ssb.h> | ||
12 | #include <linux/delay.h> | ||
13 | |||
14 | #include <pcmcia/cs_types.h> | ||
15 | #include <pcmcia/cs.h> | ||
16 | #include <pcmcia/cistpl.h> | ||
17 | #include <pcmcia/ciscode.h> | ||
18 | #include <pcmcia/ds.h> | ||
19 | #include <pcmcia/cisreg.h> | ||
20 | |||
21 | #include "ssb_private.h" | ||
22 | |||
23 | |||
24 | /* Define the following to 1 to enable a printk on each coreswitch. */ | ||
25 | #define SSB_VERBOSE_PCMCIACORESWITCH_DEBUG 0 | ||
26 | |||
27 | |||
28 | int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus, | ||
29 | u8 coreidx) | ||
30 | { | ||
31 | struct pcmcia_device *pdev = bus->host_pcmcia; | ||
32 | int err; | ||
33 | int attempts = 0; | ||
34 | u32 cur_core; | ||
35 | conf_reg_t reg; | ||
36 | u32 addr; | ||
37 | u32 read_addr; | ||
38 | |||
39 | addr = (coreidx * SSB_CORE_SIZE) + SSB_ENUM_BASE; | ||
40 | while (1) { | ||
41 | reg.Action = CS_WRITE; | ||
42 | reg.Offset = 0x2E; | ||
43 | reg.Value = (addr & 0x0000F000) >> 12; | ||
44 | err = pcmcia_access_configuration_register(pdev, ®); | ||
45 | if (err != CS_SUCCESS) | ||
46 | goto error; | ||
47 | reg.Offset = 0x30; | ||
48 | reg.Value = (addr & 0x00FF0000) >> 16; | ||
49 | err = pcmcia_access_configuration_register(pdev, ®); | ||
50 | if (err != CS_SUCCESS) | ||
51 | goto error; | ||
52 | reg.Offset = 0x32; | ||
53 | reg.Value = (addr & 0xFF000000) >> 24; | ||
54 | err = pcmcia_access_configuration_register(pdev, ®); | ||
55 | if (err != CS_SUCCESS) | ||
56 | goto error; | ||
57 | |||
58 | read_addr = 0; | ||
59 | |||
60 | reg.Action = CS_READ; | ||
61 | reg.Offset = 0x2E; | ||
62 | err = pcmcia_access_configuration_register(pdev, ®); | ||
63 | if (err != CS_SUCCESS) | ||
64 | goto error; | ||
65 | read_addr |= (reg.Value & 0xF) << 12; | ||
66 | reg.Offset = 0x30; | ||
67 | err = pcmcia_access_configuration_register(pdev, ®); | ||
68 | if (err != CS_SUCCESS) | ||
69 | goto error; | ||
70 | read_addr |= reg.Value << 16; | ||
71 | reg.Offset = 0x32; | ||
72 | err = pcmcia_access_configuration_register(pdev, ®); | ||
73 | if (err != CS_SUCCESS) | ||
74 | goto error; | ||
75 | read_addr |= reg.Value << 24; | ||
76 | |||
77 | cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE; | ||
78 | if (cur_core == coreidx) | ||
79 | break; | ||
80 | |||
81 | if (attempts++ > SSB_BAR0_MAX_RETRIES) | ||
82 | goto error; | ||
83 | udelay(10); | ||
84 | } | ||
85 | |||
86 | return 0; | ||
87 | error: | ||
88 | ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx); | ||
89 | return -ENODEV; | ||
90 | } | ||
91 | |||
92 | int ssb_pcmcia_switch_core(struct ssb_bus *bus, | ||
93 | struct ssb_device *dev) | ||
94 | { | ||
95 | int err; | ||
96 | unsigned long flags; | ||
97 | |||
98 | #if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG | ||
99 | ssb_printk(KERN_INFO PFX | ||
100 | "Switching to %s core, index %d\n", | ||
101 | ssb_core_name(dev->id.coreid), | ||
102 | dev->core_index); | ||
103 | #endif | ||
104 | |||
105 | spin_lock_irqsave(&bus->bar_lock, flags); | ||
106 | err = ssb_pcmcia_switch_coreidx(bus, dev->core_index); | ||
107 | if (!err) | ||
108 | bus->mapped_device = dev; | ||
109 | spin_unlock_irqrestore(&bus->bar_lock, flags); | ||
110 | |||
111 | return err; | ||
112 | } | ||
113 | |||
114 | int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg) | ||
115 | { | ||
116 | int attempts = 0; | ||
117 | unsigned long flags; | ||
118 | conf_reg_t reg; | ||
119 | int res, err = 0; | ||
120 | |||
121 | SSB_WARN_ON((seg != 0) && (seg != 1)); | ||
122 | reg.Offset = 0x34; | ||
123 | reg.Function = 0; | ||
124 | spin_lock_irqsave(&bus->bar_lock, flags); | ||
125 | while (1) { | ||
126 | reg.Action = CS_WRITE; | ||
127 | reg.Value = seg; | ||
128 | res = pcmcia_access_configuration_register(bus->host_pcmcia, ®); | ||
129 | if (unlikely(res != CS_SUCCESS)) | ||
130 | goto error; | ||
131 | reg.Value = 0xFF; | ||
132 | reg.Action = CS_READ; | ||
133 | res = pcmcia_access_configuration_register(bus->host_pcmcia, ®); | ||
134 | if (unlikely(res != CS_SUCCESS)) | ||
135 | goto error; | ||
136 | |||
137 | if (reg.Value == seg) | ||
138 | break; | ||
139 | |||
140 | if (unlikely(attempts++ > SSB_BAR0_MAX_RETRIES)) | ||
141 | goto error; | ||
142 | udelay(10); | ||
143 | } | ||
144 | bus->mapped_pcmcia_seg = seg; | ||
145 | out_unlock: | ||
146 | spin_unlock_irqrestore(&bus->bar_lock, flags); | ||
147 | return err; | ||
148 | error: | ||
149 | ssb_printk(KERN_ERR PFX "Failed to switch pcmcia segment\n"); | ||
150 | err = -ENODEV; | ||
151 | goto out_unlock; | ||
152 | } | ||
153 | |||
154 | /* These are the main device register access functions. | ||
155 | * do_select_core is inline to have the likely hotpath inline. | ||
156 | * All unlikely codepaths are out-of-line. */ | ||
157 | static inline int do_select_core(struct ssb_bus *bus, | ||
158 | struct ssb_device *dev, | ||
159 | u16 *offset) | ||
160 | { | ||
161 | int err; | ||
162 | u8 need_seg = (*offset >= 0x800) ? 1 : 0; | ||
163 | |||
164 | if (unlikely(dev != bus->mapped_device)) { | ||
165 | err = ssb_pcmcia_switch_core(bus, dev); | ||
166 | if (unlikely(err)) | ||
167 | return err; | ||
168 | } | ||
169 | if (unlikely(need_seg != bus->mapped_pcmcia_seg)) { | ||
170 | err = ssb_pcmcia_switch_segment(bus, need_seg); | ||
171 | if (unlikely(err)) | ||
172 | return err; | ||
173 | } | ||
174 | if (need_seg == 1) | ||
175 | *offset -= 0x800; | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset) | ||
181 | { | ||
182 | struct ssb_bus *bus = dev->bus; | ||
183 | u16 x; | ||
184 | |||
185 | if (unlikely(do_select_core(bus, dev, &offset))) | ||
186 | return 0xFFFF; | ||
187 | x = readw(bus->mmio + offset); | ||
188 | |||
189 | return x; | ||
190 | } | ||
191 | |||
192 | static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset) | ||
193 | { | ||
194 | struct ssb_bus *bus = dev->bus; | ||
195 | u32 x; | ||
196 | |||
197 | if (unlikely(do_select_core(bus, dev, &offset))) | ||
198 | return 0xFFFFFFFF; | ||
199 | x = readl(bus->mmio + offset); | ||
200 | |||
201 | return x; | ||
202 | } | ||
203 | |||
204 | static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value) | ||
205 | { | ||
206 | struct ssb_bus *bus = dev->bus; | ||
207 | |||
208 | if (unlikely(do_select_core(bus, dev, &offset))) | ||
209 | return; | ||
210 | writew(value, bus->mmio + offset); | ||
211 | } | ||
212 | |||
213 | static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value) | ||
214 | { | ||
215 | struct ssb_bus *bus = dev->bus; | ||
216 | |||
217 | if (unlikely(do_select_core(bus, dev, &offset))) | ||
218 | return; | ||
219 | readw(bus->mmio + offset); | ||
220 | writew(value >> 16, bus->mmio + offset + 2); | ||
221 | readw(bus->mmio + offset); | ||
222 | writew(value, bus->mmio + offset); | ||
223 | } | ||
224 | |||
225 | /* Not "static", as it's used in main.c */ | ||
226 | const struct ssb_bus_ops ssb_pcmcia_ops = { | ||
227 | .read16 = ssb_pcmcia_read16, | ||
228 | .read32 = ssb_pcmcia_read32, | ||
229 | .write16 = ssb_pcmcia_write16, | ||
230 | .write32 = ssb_pcmcia_write32, | ||
231 | }; | ||
232 | |||
233 | int ssb_pcmcia_get_invariants(struct ssb_bus *bus, | ||
234 | struct ssb_init_invariants *iv) | ||
235 | { | ||
236 | //TODO | ||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | int ssb_pcmcia_init(struct ssb_bus *bus) | ||
241 | { | ||
242 | conf_reg_t reg; | ||
243 | int err; | ||
244 | |||
245 | if (bus->bustype != SSB_BUSTYPE_PCMCIA) | ||
246 | return 0; | ||
247 | |||
248 | /* Switch segment to a known state and sync | ||
249 | * bus->mapped_pcmcia_seg with hardware state. */ | ||
250 | ssb_pcmcia_switch_segment(bus, 0); | ||
251 | |||
252 | /* Init IRQ routing */ | ||
253 | reg.Action = CS_READ; | ||
254 | reg.Function = 0; | ||
255 | if (bus->chip_id == 0x4306) | ||
256 | reg.Offset = 0x00; | ||
257 | else | ||
258 | reg.Offset = 0x80; | ||
259 | err = pcmcia_access_configuration_register(bus->host_pcmcia, ®); | ||
260 | if (err != CS_SUCCESS) | ||
261 | goto error; | ||
262 | reg.Action = CS_WRITE; | ||
263 | reg.Value |= 0x04 | 0x01; | ||
264 | err = pcmcia_access_configuration_register(bus->host_pcmcia, ®); | ||
265 | if (err != CS_SUCCESS) | ||
266 | goto error; | ||
267 | |||
268 | return 0; | ||
269 | error: | ||
270 | return -ENODEV; | ||
271 | } | ||
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c new file mode 100644 index 000000000000..96258c60919d --- /dev/null +++ b/drivers/ssb/scan.c | |||
@@ -0,0 +1,413 @@ | |||
1 | /* | ||
2 | * Sonics Silicon Backplane | ||
3 | * Bus scanning | ||
4 | * | ||
5 | * Copyright (C) 2005-2007 Michael Buesch <mb@bu3sch.de> | ||
6 | * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de> | ||
7 | * Copyright (C) 2005 Stefano Brivio <st3@riseup.net> | ||
8 | * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org> | ||
9 | * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> | ||
10 | * Copyright (C) 2006 Broadcom Corporation. | ||
11 | * | ||
12 | * Licensed under the GNU/GPL. See COPYING for details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/ssb/ssb.h> | ||
16 | #include <linux/ssb/ssb_regs.h> | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/io.h> | ||
19 | |||
20 | #include <pcmcia/cs_types.h> | ||
21 | #include <pcmcia/cs.h> | ||
22 | #include <pcmcia/cistpl.h> | ||
23 | #include <pcmcia/ds.h> | ||
24 | |||
25 | #include "ssb_private.h" | ||
26 | |||
27 | |||
28 | const char *ssb_core_name(u16 coreid) | ||
29 | { | ||
30 | switch (coreid) { | ||
31 | case SSB_DEV_CHIPCOMMON: | ||
32 | return "ChipCommon"; | ||
33 | case SSB_DEV_ILINE20: | ||
34 | return "ILine 20"; | ||
35 | case SSB_DEV_SDRAM: | ||
36 | return "SDRAM"; | ||
37 | case SSB_DEV_PCI: | ||
38 | return "PCI"; | ||
39 | case SSB_DEV_MIPS: | ||
40 | return "MIPS"; | ||
41 | case SSB_DEV_ETHERNET: | ||
42 | return "Fast Ethernet"; | ||
43 | case SSB_DEV_V90: | ||
44 | return "V90"; | ||
45 | case SSB_DEV_USB11_HOSTDEV: | ||
46 | return "USB 1.1 Hostdev"; | ||
47 | case SSB_DEV_ADSL: | ||
48 | return "ADSL"; | ||
49 | case SSB_DEV_ILINE100: | ||
50 | return "ILine 100"; | ||
51 | case SSB_DEV_IPSEC: | ||
52 | return "IPSEC"; | ||
53 | case SSB_DEV_PCMCIA: | ||
54 | return "PCMCIA"; | ||
55 | case SSB_DEV_INTERNAL_MEM: | ||
56 | return "Internal Memory"; | ||
57 | case SSB_DEV_MEMC_SDRAM: | ||
58 | return "MEMC SDRAM"; | ||
59 | case SSB_DEV_EXTIF: | ||
60 | return "EXTIF"; | ||
61 | case SSB_DEV_80211: | ||
62 | return "IEEE 802.11"; | ||
63 | case SSB_DEV_MIPS_3302: | ||
64 | return "MIPS 3302"; | ||
65 | case SSB_DEV_USB11_HOST: | ||
66 | return "USB 1.1 Host"; | ||
67 | case SSB_DEV_USB11_DEV: | ||
68 | return "USB 1.1 Device"; | ||
69 | case SSB_DEV_USB20_HOST: | ||
70 | return "USB 2.0 Host"; | ||
71 | case SSB_DEV_USB20_DEV: | ||
72 | return "USB 2.0 Device"; | ||
73 | case SSB_DEV_SDIO_HOST: | ||
74 | return "SDIO Host"; | ||
75 | case SSB_DEV_ROBOSWITCH: | ||
76 | return "Roboswitch"; | ||
77 | case SSB_DEV_PARA_ATA: | ||
78 | return "PATA"; | ||
79 | case SSB_DEV_SATA_XORDMA: | ||
80 | return "SATA XOR-DMA"; | ||
81 | case SSB_DEV_ETHERNET_GBIT: | ||
82 | return "GBit Ethernet"; | ||
83 | case SSB_DEV_PCIE: | ||
84 | return "PCI-E"; | ||
85 | case SSB_DEV_MIMO_PHY: | ||
86 | return "MIMO PHY"; | ||
87 | case SSB_DEV_SRAM_CTRLR: | ||
88 | return "SRAM Controller"; | ||
89 | case SSB_DEV_MINI_MACPHY: | ||
90 | return "Mini MACPHY"; | ||
91 | case SSB_DEV_ARM_1176: | ||
92 | return "ARM 1176"; | ||
93 | case SSB_DEV_ARM_7TDMI: | ||
94 | return "ARM 7TDMI"; | ||
95 | } | ||
96 | return "UNKNOWN"; | ||
97 | } | ||
98 | |||
99 | static u16 pcidev_to_chipid(struct pci_dev *pci_dev) | ||
100 | { | ||
101 | u16 chipid_fallback = 0; | ||
102 | |||
103 | switch (pci_dev->device) { | ||
104 | case 0x4301: | ||
105 | chipid_fallback = 0x4301; | ||
106 | break; | ||
107 | case 0x4305 ... 0x4307: | ||
108 | chipid_fallback = 0x4307; | ||
109 | break; | ||
110 | case 0x4403: | ||
111 | chipid_fallback = 0x4402; | ||
112 | break; | ||
113 | case 0x4610 ... 0x4615: | ||
114 | chipid_fallback = 0x4610; | ||
115 | break; | ||
116 | case 0x4710 ... 0x4715: | ||
117 | chipid_fallback = 0x4710; | ||
118 | break; | ||
119 | case 0x4320 ... 0x4325: | ||
120 | chipid_fallback = 0x4309; | ||
121 | break; | ||
122 | case PCI_DEVICE_ID_BCM4401: | ||
123 | case PCI_DEVICE_ID_BCM4401B0: | ||
124 | case PCI_DEVICE_ID_BCM4401B1: | ||
125 | chipid_fallback = 0x4401; | ||
126 | break; | ||
127 | default: | ||
128 | ssb_printk(KERN_ERR PFX | ||
129 | "PCI-ID not in fallback list\n"); | ||
130 | } | ||
131 | |||
132 | return chipid_fallback; | ||
133 | } | ||
134 | |||
135 | static u8 chipid_to_nrcores(u16 chipid) | ||
136 | { | ||
137 | switch (chipid) { | ||
138 | case 0x5365: | ||
139 | return 7; | ||
140 | case 0x4306: | ||
141 | return 6; | ||
142 | case 0x4310: | ||
143 | return 8; | ||
144 | case 0x4307: | ||
145 | case 0x4301: | ||
146 | return 5; | ||
147 | case 0x4401: | ||
148 | case 0x4402: | ||
149 | return 3; | ||
150 | case 0x4710: | ||
151 | case 0x4610: | ||
152 | case 0x4704: | ||
153 | return 9; | ||
154 | default: | ||
155 | ssb_printk(KERN_ERR PFX | ||
156 | "CHIPID not in nrcores fallback list\n"); | ||
157 | } | ||
158 | |||
159 | return 1; | ||
160 | } | ||
161 | |||
162 | static u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx, | ||
163 | u16 offset) | ||
164 | { | ||
165 | switch (bus->bustype) { | ||
166 | case SSB_BUSTYPE_SSB: | ||
167 | offset += current_coreidx * SSB_CORE_SIZE; | ||
168 | break; | ||
169 | case SSB_BUSTYPE_PCI: | ||
170 | break; | ||
171 | case SSB_BUSTYPE_PCMCIA: | ||
172 | if (offset >= 0x800) { | ||
173 | ssb_pcmcia_switch_segment(bus, 1); | ||
174 | offset -= 0x800; | ||
175 | } else | ||
176 | ssb_pcmcia_switch_segment(bus, 0); | ||
177 | break; | ||
178 | } | ||
179 | return readl(bus->mmio + offset); | ||
180 | } | ||
181 | |||
182 | static int scan_switchcore(struct ssb_bus *bus, u8 coreidx) | ||
183 | { | ||
184 | switch (bus->bustype) { | ||
185 | case SSB_BUSTYPE_SSB: | ||
186 | break; | ||
187 | case SSB_BUSTYPE_PCI: | ||
188 | return ssb_pci_switch_coreidx(bus, coreidx); | ||
189 | case SSB_BUSTYPE_PCMCIA: | ||
190 | return ssb_pcmcia_switch_coreidx(bus, coreidx); | ||
191 | } | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | void ssb_iounmap(struct ssb_bus *bus) | ||
196 | { | ||
197 | switch (bus->bustype) { | ||
198 | case SSB_BUSTYPE_SSB: | ||
199 | case SSB_BUSTYPE_PCMCIA: | ||
200 | iounmap(bus->mmio); | ||
201 | break; | ||
202 | case SSB_BUSTYPE_PCI: | ||
203 | #ifdef CONFIG_SSB_PCIHOST | ||
204 | pci_iounmap(bus->host_pci, bus->mmio); | ||
205 | #else | ||
206 | SSB_BUG_ON(1); /* Can't reach this code. */ | ||
207 | #endif | ||
208 | break; | ||
209 | } | ||
210 | bus->mmio = NULL; | ||
211 | bus->mapped_device = NULL; | ||
212 | } | ||
213 | |||
214 | static void __iomem *ssb_ioremap(struct ssb_bus *bus, | ||
215 | unsigned long baseaddr) | ||
216 | { | ||
217 | void __iomem *mmio = NULL; | ||
218 | |||
219 | switch (bus->bustype) { | ||
220 | case SSB_BUSTYPE_SSB: | ||
221 | /* Only map the first core for now. */ | ||
222 | /* fallthrough... */ | ||
223 | case SSB_BUSTYPE_PCMCIA: | ||
224 | mmio = ioremap(baseaddr, SSB_CORE_SIZE); | ||
225 | break; | ||
226 | case SSB_BUSTYPE_PCI: | ||
227 | #ifdef CONFIG_SSB_PCIHOST | ||
228 | mmio = pci_iomap(bus->host_pci, 0, ~0UL); | ||
229 | #else | ||
230 | SSB_BUG_ON(1); /* Can't reach this code. */ | ||
231 | #endif | ||
232 | break; | ||
233 | } | ||
234 | |||
235 | return mmio; | ||
236 | } | ||
237 | |||
238 | static int we_support_multiple_80211_cores(struct ssb_bus *bus) | ||
239 | { | ||
240 | /* More than one 802.11 core is only supported by special chips. | ||
241 | * There are chips with two 802.11 cores, but with dangling | ||
242 | * pins on the second core. Be careful and reject them here. | ||
243 | */ | ||
244 | |||
245 | #ifdef CONFIG_SSB_PCIHOST | ||
246 | if (bus->bustype == SSB_BUSTYPE_PCI) { | ||
247 | if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM && | ||
248 | bus->host_pci->device == 0x4324) | ||
249 | return 1; | ||
250 | } | ||
251 | #endif /* CONFIG_SSB_PCIHOST */ | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | int ssb_bus_scan(struct ssb_bus *bus, | ||
256 | unsigned long baseaddr) | ||
257 | { | ||
258 | int err = -ENOMEM; | ||
259 | void __iomem *mmio; | ||
260 | u32 idhi, cc, rev, tmp; | ||
261 | int dev_i, i; | ||
262 | struct ssb_device *dev; | ||
263 | int nr_80211_cores = 0; | ||
264 | |||
265 | mmio = ssb_ioremap(bus, baseaddr); | ||
266 | if (!mmio) | ||
267 | goto out; | ||
268 | bus->mmio = mmio; | ||
269 | |||
270 | err = scan_switchcore(bus, 0); /* Switch to first core */ | ||
271 | if (err) | ||
272 | goto err_unmap; | ||
273 | |||
274 | idhi = scan_read32(bus, 0, SSB_IDHIGH); | ||
275 | cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT; | ||
276 | rev = (idhi & SSB_IDHIGH_RCLO); | ||
277 | rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT; | ||
278 | |||
279 | bus->nr_devices = 0; | ||
280 | if (cc == SSB_DEV_CHIPCOMMON) { | ||
281 | tmp = scan_read32(bus, 0, SSB_CHIPCO_CHIPID); | ||
282 | |||
283 | bus->chip_id = (tmp & SSB_CHIPCO_IDMASK); | ||
284 | bus->chip_rev = (tmp & SSB_CHIPCO_REVMASK) >> | ||
285 | SSB_CHIPCO_REVSHIFT; | ||
286 | bus->chip_package = (tmp & SSB_CHIPCO_PACKMASK) >> | ||
287 | SSB_CHIPCO_PACKSHIFT; | ||
288 | if (rev >= 4) { | ||
289 | bus->nr_devices = (tmp & SSB_CHIPCO_NRCORESMASK) >> | ||
290 | SSB_CHIPCO_NRCORESSHIFT; | ||
291 | } | ||
292 | tmp = scan_read32(bus, 0, SSB_CHIPCO_CAP); | ||
293 | bus->chipco.capabilities = tmp; | ||
294 | } else { | ||
295 | if (bus->bustype == SSB_BUSTYPE_PCI) { | ||
296 | bus->chip_id = pcidev_to_chipid(bus->host_pci); | ||
297 | pci_read_config_word(bus->host_pci, PCI_REVISION_ID, | ||
298 | &bus->chip_rev); | ||
299 | bus->chip_package = 0; | ||
300 | } else { | ||
301 | bus->chip_id = 0x4710; | ||
302 | bus->chip_rev = 0; | ||
303 | bus->chip_package = 0; | ||
304 | } | ||
305 | } | ||
306 | if (!bus->nr_devices) | ||
307 | bus->nr_devices = chipid_to_nrcores(bus->chip_id); | ||
308 | if (bus->nr_devices > ARRAY_SIZE(bus->devices)) { | ||
309 | ssb_printk(KERN_ERR PFX | ||
310 | "More than %d ssb cores found (%d)\n", | ||
311 | SSB_MAX_NR_CORES, bus->nr_devices); | ||
312 | goto err_unmap; | ||
313 | } | ||
314 | if (bus->bustype == SSB_BUSTYPE_SSB) { | ||
315 | /* Now that we know the number of cores, | ||
316 | * remap the whole IO space for all cores. | ||
317 | */ | ||
318 | err = -ENOMEM; | ||
319 | iounmap(mmio); | ||
320 | mmio = ioremap(baseaddr, SSB_CORE_SIZE * bus->nr_devices); | ||
321 | if (!mmio) | ||
322 | goto out; | ||
323 | bus->mmio = mmio; | ||
324 | } | ||
325 | |||
326 | /* Fetch basic information about each core/device */ | ||
327 | for (i = 0, dev_i = 0; i < bus->nr_devices; i++) { | ||
328 | err = scan_switchcore(bus, i); | ||
329 | if (err) | ||
330 | goto err_unmap; | ||
331 | dev = &(bus->devices[dev_i]); | ||
332 | |||
333 | idhi = scan_read32(bus, i, SSB_IDHIGH); | ||
334 | dev->id.coreid = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT; | ||
335 | dev->id.revision = (idhi & SSB_IDHIGH_RCLO); | ||
336 | dev->id.revision |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT; | ||
337 | dev->id.vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT; | ||
338 | dev->core_index = i; | ||
339 | dev->bus = bus; | ||
340 | dev->ops = bus->ops; | ||
341 | |||
342 | ssb_dprintk(KERN_INFO PFX | ||
343 | "Core %d found: %s " | ||
344 | "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n", | ||
345 | i, ssb_core_name(dev->id.coreid), | ||
346 | dev->id.coreid, dev->id.revision, dev->id.vendor); | ||
347 | |||
348 | switch (dev->id.coreid) { | ||
349 | case SSB_DEV_80211: | ||
350 | nr_80211_cores++; | ||
351 | if (nr_80211_cores > 1) { | ||
352 | if (!we_support_multiple_80211_cores(bus)) { | ||
353 | ssb_dprintk(KERN_INFO PFX "Ignoring additional " | ||
354 | "802.11 core\n"); | ||
355 | continue; | ||
356 | } | ||
357 | } | ||
358 | break; | ||
359 | case SSB_DEV_EXTIF: | ||
360 | #ifdef CONFIG_SSB_DRIVER_EXTIF | ||
361 | if (bus->extif.dev) { | ||
362 | ssb_printk(KERN_WARNING PFX | ||
363 | "WARNING: Multiple EXTIFs found\n"); | ||
364 | break; | ||
365 | } | ||
366 | bus->extif.dev = dev; | ||
367 | #endif /* CONFIG_SSB_DRIVER_EXTIF */ | ||
368 | break; | ||
369 | case SSB_DEV_CHIPCOMMON: | ||
370 | if (bus->chipco.dev) { | ||
371 | ssb_printk(KERN_WARNING PFX | ||
372 | "WARNING: Multiple ChipCommon found\n"); | ||
373 | break; | ||
374 | } | ||
375 | bus->chipco.dev = dev; | ||
376 | break; | ||
377 | case SSB_DEV_MIPS: | ||
378 | case SSB_DEV_MIPS_3302: | ||
379 | #ifdef CONFIG_SSB_DRIVER_MIPS | ||
380 | if (bus->mipscore.dev) { | ||
381 | ssb_printk(KERN_WARNING PFX | ||
382 | "WARNING: Multiple MIPS cores found\n"); | ||
383 | break; | ||
384 | } | ||
385 | bus->mipscore.dev = dev; | ||
386 | #endif /* CONFIG_SSB_DRIVER_MIPS */ | ||
387 | break; | ||
388 | case SSB_DEV_PCI: | ||
389 | case SSB_DEV_PCIE: | ||
390 | #ifdef CONFIG_SSB_DRIVER_PCICORE | ||
391 | if (bus->pcicore.dev) { | ||
392 | ssb_printk(KERN_WARNING PFX | ||
393 | "WARNING: Multiple PCI(E) cores found\n"); | ||
394 | break; | ||
395 | } | ||
396 | bus->pcicore.dev = dev; | ||
397 | #endif /* CONFIG_SSB_DRIVER_PCICORE */ | ||
398 | break; | ||
399 | default: | ||
400 | break; | ||
401 | } | ||
402 | |||
403 | dev_i++; | ||
404 | } | ||
405 | bus->nr_devices = dev_i; | ||
406 | |||
407 | err = 0; | ||
408 | out: | ||
409 | return err; | ||
410 | err_unmap: | ||
411 | ssb_iounmap(bus); | ||
412 | goto out; | ||
413 | } | ||
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h new file mode 100644 index 000000000000..a789364264a6 --- /dev/null +++ b/drivers/ssb/ssb_private.h | |||
@@ -0,0 +1,136 @@ | |||
1 | #ifndef LINUX_SSB_PRIVATE_H_ | ||
2 | #define LINUX_SSB_PRIVATE_H_ | ||
3 | |||
4 | #include <linux/ssb/ssb.h> | ||
5 | #include <linux/types.h> | ||
6 | |||
7 | |||
8 | #define PFX "ssb: " | ||
9 | |||
10 | #ifdef CONFIG_SSB_SILENT | ||
11 | # define ssb_printk(fmt, x...) do { /* nothing */ } while (0) | ||
12 | #else | ||
13 | # define ssb_printk printk | ||
14 | #endif /* CONFIG_SSB_SILENT */ | ||
15 | |||
16 | /* dprintk: Debugging printk; vanishes for non-debug compilation */ | ||
17 | #ifdef CONFIG_SSB_DEBUG | ||
18 | # define ssb_dprintk(fmt, x...) ssb_printk(fmt , ##x) | ||
19 | #else | ||
20 | # define ssb_dprintk(fmt, x...) do { /* nothing */ } while (0) | ||
21 | #endif | ||
22 | |||
23 | #ifdef CONFIG_SSB_DEBUG | ||
24 | # define SSB_WARN_ON(x) WARN_ON(x) | ||
25 | # define SSB_BUG_ON(x) BUG_ON(x) | ||
26 | #else | ||
27 | static inline int __ssb_do_nothing(int x) { return x; } | ||
28 | # define SSB_WARN_ON(x) __ssb_do_nothing(unlikely(!!(x))) | ||
29 | # define SSB_BUG_ON(x) __ssb_do_nothing(unlikely(!!(x))) | ||
30 | #endif | ||
31 | |||
32 | |||
33 | /* pci.c */ | ||
34 | #ifdef CONFIG_SSB_PCIHOST | ||
35 | extern int ssb_pci_switch_core(struct ssb_bus *bus, | ||
36 | struct ssb_device *dev); | ||
37 | extern int ssb_pci_switch_coreidx(struct ssb_bus *bus, | ||
38 | u8 coreidx); | ||
39 | extern int ssb_pci_xtal(struct ssb_bus *bus, u32 what, | ||
40 | int turn_on); | ||
41 | extern int ssb_pci_get_invariants(struct ssb_bus *bus, | ||
42 | struct ssb_init_invariants *iv); | ||
43 | extern void ssb_pci_exit(struct ssb_bus *bus); | ||
44 | extern int ssb_pci_init(struct ssb_bus *bus); | ||
45 | extern const struct ssb_bus_ops ssb_pci_ops; | ||
46 | |||
47 | #else /* CONFIG_SSB_PCIHOST */ | ||
48 | |||
49 | static inline int ssb_pci_switch_core(struct ssb_bus *bus, | ||
50 | struct ssb_device *dev) | ||
51 | { | ||
52 | return 0; | ||
53 | } | ||
54 | static inline int ssb_pci_switch_coreidx(struct ssb_bus *bus, | ||
55 | u8 coreidx) | ||
56 | { | ||
57 | return 0; | ||
58 | } | ||
59 | static inline int ssb_pci_xtal(struct ssb_bus *bus, u32 what, | ||
60 | int turn_on) | ||
61 | { | ||
62 | return 0; | ||
63 | } | ||
64 | static inline void ssb_pci_exit(struct ssb_bus *bus) | ||
65 | { | ||
66 | } | ||
67 | static inline int ssb_pci_init(struct ssb_bus *bus) | ||
68 | { | ||
69 | return 0; | ||
70 | } | ||
71 | #endif /* CONFIG_SSB_PCIHOST */ | ||
72 | |||
73 | |||
74 | /* pcmcia.c */ | ||
75 | #ifdef CONFIG_SSB_PCMCIAHOST | ||
76 | extern int ssb_pcmcia_switch_core(struct ssb_bus *bus, | ||
77 | struct ssb_device *dev); | ||
78 | extern int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus, | ||
79 | u8 coreidx); | ||
80 | extern int ssb_pcmcia_switch_segment(struct ssb_bus *bus, | ||
81 | u8 seg); | ||
82 | extern int ssb_pcmcia_get_invariants(struct ssb_bus *bus, | ||
83 | struct ssb_init_invariants *iv); | ||
84 | extern int ssb_pcmcia_init(struct ssb_bus *bus); | ||
85 | extern const struct ssb_bus_ops ssb_pcmcia_ops; | ||
86 | #else /* CONFIG_SSB_PCMCIAHOST */ | ||
87 | static inline int ssb_pcmcia_switch_core(struct ssb_bus *bus, | ||
88 | struct ssb_device *dev) | ||
89 | { | ||
90 | return 0; | ||
91 | } | ||
92 | static inline int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus, | ||
93 | u8 coreidx) | ||
94 | { | ||
95 | return 0; | ||
96 | } | ||
97 | static inline int ssb_pcmcia_switch_segment(struct ssb_bus *bus, | ||
98 | u8 seg) | ||
99 | { | ||
100 | return 0; | ||
101 | } | ||
102 | static inline int ssb_pcmcia_init(struct ssb_bus *bus) | ||
103 | { | ||
104 | return 0; | ||
105 | } | ||
106 | #endif /* CONFIG_SSB_PCMCIAHOST */ | ||
107 | |||
108 | |||
109 | /* scan.c */ | ||
110 | extern const char *ssb_core_name(u16 coreid); | ||
111 | extern int ssb_bus_scan(struct ssb_bus *bus, | ||
112 | unsigned long baseaddr); | ||
113 | extern void ssb_iounmap(struct ssb_bus *ssb); | ||
114 | |||
115 | |||
116 | /* core.c */ | ||
117 | extern u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m); | ||
118 | extern int ssb_devices_freeze(struct ssb_bus *bus); | ||
119 | extern int ssb_devices_thaw(struct ssb_bus *bus); | ||
120 | extern struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev); | ||
121 | |||
122 | /* b43_pci_bridge.c */ | ||
123 | #ifdef CONFIG_SSB_PCIHOST | ||
124 | extern int __init b43_pci_ssb_bridge_init(void); | ||
125 | extern void __exit b43_pci_ssb_bridge_exit(void); | ||
126 | #else /* CONFIG_SSB_PCIHOST */ | ||
127 | static inline int b43_pci_ssb_bridge_init(void) | ||
128 | { | ||
129 | return 0; | ||
130 | } | ||
131 | static inline void b43_pci_ssb_bridge_exit(void) | ||
132 | { | ||
133 | } | ||
134 | #endif /* CONFIG_SSB_PCIHOST */ | ||
135 | |||
136 | #endif /* LINUX_SSB_PRIVATE_H_ */ | ||
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 4dc5fa8be781..0c522e6b0917 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h | |||
@@ -340,4 +340,19 @@ struct parisc_device_id { | |||
340 | #define PA_HVERSION_ANY_ID 0xffff | 340 | #define PA_HVERSION_ANY_ID 0xffff |
341 | #define PA_SVERSION_ANY_ID 0xffffffff | 341 | #define PA_SVERSION_ANY_ID 0xffffffff |
342 | 342 | ||
343 | /* SSB core, see drivers/ssb/ */ | ||
344 | struct ssb_device_id { | ||
345 | __u16 vendor; | ||
346 | __u16 coreid; | ||
347 | __u8 revision; | ||
348 | }; | ||
349 | #define SSB_DEVICE(_vendor, _coreid, _revision) \ | ||
350 | { .vendor = _vendor, .coreid = _coreid, .revision = _revision, } | ||
351 | #define SSB_DEVTABLE_END \ | ||
352 | { 0, }, | ||
353 | |||
354 | #define SSB_ANY_VENDOR 0xFFFF | ||
355 | #define SSB_ANY_ID 0xFFFF | ||
356 | #define SSB_ANY_REV 0xFF | ||
357 | |||
343 | #endif /* LINUX_MOD_DEVICETABLE_H */ | 358 | #endif /* LINUX_MOD_DEVICETABLE_H */ |
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h new file mode 100644 index 000000000000..2b5c312c4960 --- /dev/null +++ b/include/linux/ssb/ssb.h | |||
@@ -0,0 +1,424 @@ | |||
1 | #ifndef LINUX_SSB_H_ | ||
2 | #define LINUX_SSB_H_ | ||
3 | |||
4 | #include <linux/device.h> | ||
5 | #include <linux/list.h> | ||
6 | #include <linux/types.h> | ||
7 | #include <linux/spinlock.h> | ||
8 | #include <linux/pci.h> | ||
9 | #include <linux/mod_devicetable.h> | ||
10 | |||
11 | #include <linux/ssb/ssb_regs.h> | ||
12 | |||
13 | |||
14 | struct pcmcia_device; | ||
15 | struct ssb_bus; | ||
16 | struct ssb_driver; | ||
17 | |||
18 | |||
19 | struct ssb_sprom_r1 { | ||
20 | u16 pci_spid; /* Subsystem Product ID for PCI */ | ||
21 | u16 pci_svid; /* Subsystem Vendor ID for PCI */ | ||
22 | u16 pci_pid; /* Product ID for PCI */ | ||
23 | u8 il0mac[6]; /* MAC address for 802.11b/g */ | ||
24 | u8 et0mac[6]; /* MAC address for Ethernet */ | ||
25 | u8 et1mac[6]; /* MAC address for 802.11a */ | ||
26 | u8 et0phyaddr:5; /* MII address for enet0 */ | ||
27 | u8 et1phyaddr:5; /* MII address for enet1 */ | ||
28 | u8 et0mdcport:1; /* MDIO for enet0 */ | ||
29 | u8 et1mdcport:1; /* MDIO for enet1 */ | ||
30 | u8 board_rev; /* Board revision */ | ||
31 | u8 country_code:4; /* Country Code */ | ||
32 | u8 antenna_a:2; /* Antenna 0/1 available for A-PHY */ | ||
33 | u8 antenna_bg:2; /* Antenna 0/1 available for B-PHY and G-PHY */ | ||
34 | u16 pa0b0; | ||
35 | u16 pa0b1; | ||
36 | u16 pa0b2; | ||
37 | u16 pa1b0; | ||
38 | u16 pa1b1; | ||
39 | u16 pa1b2; | ||
40 | u8 gpio0; /* GPIO pin 0 */ | ||
41 | u8 gpio1; /* GPIO pin 1 */ | ||
42 | u8 gpio2; /* GPIO pin 2 */ | ||
43 | u8 gpio3; /* GPIO pin 3 */ | ||
44 | u16 maxpwr_a; /* A-PHY Power Amplifier Max Power (in dBm Q5.2) */ | ||
45 | u16 maxpwr_bg; /* B/G-PHY Power Amplifier Max Power (in dBm Q5.2) */ | ||
46 | u8 itssi_a; /* Idle TSSI Target for A-PHY */ | ||
47 | u8 itssi_bg; /* Idle TSSI Target for B/G-PHY */ | ||
48 | u16 boardflags_lo; /* Boardflags (low 16 bits) */ | ||
49 | u8 antenna_gain_a; /* A-PHY Antenna gain (in dBm Q5.2) */ | ||
50 | u8 antenna_gain_bg; /* B/G-PHY Antenna gain (in dBm Q5.2) */ | ||
51 | u8 oem[8]; /* OEM string (rev 1 only) */ | ||
52 | }; | ||
53 | |||
54 | struct ssb_sprom_r2 { | ||
55 | u16 boardflags_hi; /* Boardflags (high 16 bits) */ | ||
56 | u8 maxpwr_a_lo; /* A-PHY Max Power Low */ | ||
57 | u8 maxpwr_a_hi; /* A-PHY Max Power High */ | ||
58 | u16 pa1lob0; /* A-PHY PA Low Settings */ | ||
59 | u16 pa1lob1; /* A-PHY PA Low Settings */ | ||
60 | u16 pa1lob2; /* A-PHY PA Low Settings */ | ||
61 | u16 pa1hib0; /* A-PHY PA High Settings */ | ||
62 | u16 pa1hib1; /* A-PHY PA High Settings */ | ||
63 | u16 pa1hib2; /* A-PHY PA High Settings */ | ||
64 | u8 ofdm_pwr_off; /* OFDM Power Offset from CCK Level */ | ||
65 | u8 country_str[2]; /* Two char Country Code */ | ||
66 | }; | ||
67 | |||
68 | struct ssb_sprom_r3 { | ||
69 | u32 ofdmapo; /* A-PHY OFDM Mid Power Offset */ | ||
70 | u32 ofdmalpo; /* A-PHY OFDM Low Power Offset */ | ||
71 | u32 ofdmahpo; /* A-PHY OFDM High Power Offset */ | ||
72 | u8 gpioldc_on_cnt; /* GPIO LED Powersave Duty Cycle ON count */ | ||
73 | u8 gpioldc_off_cnt; /* GPIO LED Powersave Duty Cycle OFF count */ | ||
74 | u8 cckpo_1M:4; /* CCK Power Offset for Rate 1M */ | ||
75 | u8 cckpo_2M:4; /* CCK Power Offset for Rate 2M */ | ||
76 | u8 cckpo_55M:4; /* CCK Power Offset for Rate 5.5M */ | ||
77 | u8 cckpo_11M:4; /* CCK Power Offset for Rate 11M */ | ||
78 | u32 ofdmgpo; /* G-PHY OFDM Power Offset */ | ||
79 | }; | ||
80 | |||
81 | struct ssb_sprom_r4 { | ||
82 | /* TODO */ | ||
83 | }; | ||
84 | |||
85 | struct ssb_sprom { | ||
86 | u8 revision; | ||
87 | u8 crc; | ||
88 | /* The valid r# fields are selected by the "revision". | ||
89 | * Revision 3 and lower inherit from lower revisions. | ||
90 | */ | ||
91 | union { | ||
92 | struct { | ||
93 | struct ssb_sprom_r1 r1; | ||
94 | struct ssb_sprom_r2 r2; | ||
95 | struct ssb_sprom_r3 r3; | ||
96 | }; | ||
97 | struct ssb_sprom_r4 r4; | ||
98 | }; | ||
99 | }; | ||
100 | |||
101 | /* Information about the PCB the circuitry is soldered on. */ | ||
102 | struct ssb_boardinfo { | ||
103 | u16 vendor; | ||
104 | u16 type; | ||
105 | u16 rev; | ||
106 | }; | ||
107 | |||
108 | |||
109 | struct ssb_device; | ||
110 | /* Lowlevel read/write operations on the device MMIO. | ||
111 | * Internal, don't use that outside of ssb. */ | ||
112 | struct ssb_bus_ops { | ||
113 | u16 (*read16)(struct ssb_device *dev, u16 offset); | ||
114 | u32 (*read32)(struct ssb_device *dev, u16 offset); | ||
115 | void (*write16)(struct ssb_device *dev, u16 offset, u16 value); | ||
116 | void (*write32)(struct ssb_device *dev, u16 offset, u32 value); | ||
117 | }; | ||
118 | |||
119 | |||
120 | /* Core-ID values. */ | ||
121 | #define SSB_DEV_CHIPCOMMON 0x800 | ||
122 | #define SSB_DEV_ILINE20 0x801 | ||
123 | #define SSB_DEV_SDRAM 0x803 | ||
124 | #define SSB_DEV_PCI 0x804 | ||
125 | #define SSB_DEV_MIPS 0x805 | ||
126 | #define SSB_DEV_ETHERNET 0x806 | ||
127 | #define SSB_DEV_V90 0x807 | ||
128 | #define SSB_DEV_USB11_HOSTDEV 0x808 | ||
129 | #define SSB_DEV_ADSL 0x809 | ||
130 | #define SSB_DEV_ILINE100 0x80A | ||
131 | #define SSB_DEV_IPSEC 0x80B | ||
132 | #define SSB_DEV_PCMCIA 0x80D | ||
133 | #define SSB_DEV_INTERNAL_MEM 0x80E | ||
134 | #define SSB_DEV_MEMC_SDRAM 0x80F | ||
135 | #define SSB_DEV_EXTIF 0x811 | ||
136 | #define SSB_DEV_80211 0x812 | ||
137 | #define SSB_DEV_MIPS_3302 0x816 | ||
138 | #define SSB_DEV_USB11_HOST 0x817 | ||
139 | #define SSB_DEV_USB11_DEV 0x818 | ||
140 | #define SSB_DEV_USB20_HOST 0x819 | ||
141 | #define SSB_DEV_USB20_DEV 0x81A | ||
142 | #define SSB_DEV_SDIO_HOST 0x81B | ||
143 | #define SSB_DEV_ROBOSWITCH 0x81C | ||
144 | #define SSB_DEV_PARA_ATA 0x81D | ||
145 | #define SSB_DEV_SATA_XORDMA 0x81E | ||
146 | #define SSB_DEV_ETHERNET_GBIT 0x81F | ||
147 | #define SSB_DEV_PCIE 0x820 | ||
148 | #define SSB_DEV_MIMO_PHY 0x821 | ||
149 | #define SSB_DEV_SRAM_CTRLR 0x822 | ||
150 | #define SSB_DEV_MINI_MACPHY 0x823 | ||
151 | #define SSB_DEV_ARM_1176 0x824 | ||
152 | #define SSB_DEV_ARM_7TDMI 0x825 | ||
153 | |||
154 | /* Vendor-ID values */ | ||
155 | #define SSB_VENDOR_BROADCOM 0x4243 | ||
156 | |||
157 | /* Some kernel subsystems poke with dev->drvdata, so we must use the | ||
158 | * following ugly workaround to get from struct device to struct ssb_device */ | ||
159 | struct __ssb_dev_wrapper { | ||
160 | struct device dev; | ||
161 | struct ssb_device *sdev; | ||
162 | }; | ||
163 | |||
164 | struct ssb_device { | ||
165 | /* Having a copy of the ops pointer in each dev struct | ||
166 | * is an optimization. */ | ||
167 | const struct ssb_bus_ops *ops; | ||
168 | |||
169 | struct device *dev; | ||
170 | struct ssb_bus *bus; | ||
171 | struct ssb_device_id id; | ||
172 | |||
173 | u8 core_index; | ||
174 | unsigned int irq; | ||
175 | |||
176 | /* Internal-only stuff follows. */ | ||
177 | void *drvdata; /* Per-device data */ | ||
178 | void *devtypedata; /* Per-devicetype (eg 802.11) data */ | ||
179 | }; | ||
180 | |||
181 | /* Go from struct device to struct ssb_device. */ | ||
182 | static inline | ||
183 | struct ssb_device * dev_to_ssb_dev(struct device *dev) | ||
184 | { | ||
185 | struct __ssb_dev_wrapper *wrap; | ||
186 | wrap = container_of(dev, struct __ssb_dev_wrapper, dev); | ||
187 | return wrap->sdev; | ||
188 | } | ||
189 | |||
190 | /* Device specific user data */ | ||
191 | static inline | ||
192 | void ssb_set_drvdata(struct ssb_device *dev, void *data) | ||
193 | { | ||
194 | dev->drvdata = data; | ||
195 | } | ||
196 | static inline | ||
197 | void * ssb_get_drvdata(struct ssb_device *dev) | ||
198 | { | ||
199 | return dev->drvdata; | ||
200 | } | ||
201 | |||
202 | /* Devicetype specific user data. This is per device-type (not per device) */ | ||
203 | void ssb_set_devtypedata(struct ssb_device *dev, void *data); | ||
204 | static inline | ||
205 | void * ssb_get_devtypedata(struct ssb_device *dev) | ||
206 | { | ||
207 | return dev->devtypedata; | ||
208 | } | ||
209 | |||
210 | |||
211 | struct ssb_driver { | ||
212 | const char *name; | ||
213 | const struct ssb_device_id *id_table; | ||
214 | |||
215 | int (*probe)(struct ssb_device *dev, const struct ssb_device_id *id); | ||
216 | void (*remove)(struct ssb_device *dev); | ||
217 | int (*suspend)(struct ssb_device *dev, pm_message_t state); | ||
218 | int (*resume)(struct ssb_device *dev); | ||
219 | void (*shutdown)(struct ssb_device *dev); | ||
220 | |||
221 | struct device_driver drv; | ||
222 | }; | ||
223 | #define drv_to_ssb_drv(_drv) container_of(_drv, struct ssb_driver, drv) | ||
224 | |||
225 | extern int __ssb_driver_register(struct ssb_driver *drv, struct module *owner); | ||
226 | static inline int ssb_driver_register(struct ssb_driver *drv) | ||
227 | { | ||
228 | return __ssb_driver_register(drv, THIS_MODULE); | ||
229 | } | ||
230 | extern void ssb_driver_unregister(struct ssb_driver *drv); | ||
231 | |||
232 | |||
233 | |||
234 | |||
235 | enum ssb_bustype { | ||
236 | SSB_BUSTYPE_SSB, /* This SSB bus is the system bus */ | ||
237 | SSB_BUSTYPE_PCI, /* SSB is connected to PCI bus */ | ||
238 | SSB_BUSTYPE_PCMCIA, /* SSB is connected to PCMCIA bus */ | ||
239 | }; | ||
240 | |||
241 | /* board_vendor */ | ||
242 | #define SSB_BOARDVENDOR_BCM 0x14E4 /* Broadcom */ | ||
243 | #define SSB_BOARDVENDOR_DELL 0x1028 /* Dell */ | ||
244 | #define SSB_BOARDVENDOR_HP 0x0E11 /* HP */ | ||
245 | /* board_type */ | ||
246 | #define SSB_BOARD_BCM94306MP 0x0418 | ||
247 | #define SSB_BOARD_BCM4309G 0x0421 | ||
248 | #define SSB_BOARD_BCM4306CB 0x0417 | ||
249 | #define SSB_BOARD_BCM4309MP 0x040C | ||
250 | #define SSB_BOARD_MP4318 0x044A | ||
251 | #define SSB_BOARD_BU4306 0x0416 | ||
252 | #define SSB_BOARD_BU4309 0x040A | ||
253 | /* chip_package */ | ||
254 | #define SSB_CHIPPACK_BCM4712S 1 /* Small 200pin 4712 */ | ||
255 | #define SSB_CHIPPACK_BCM4712M 2 /* Medium 225pin 4712 */ | ||
256 | #define SSB_CHIPPACK_BCM4712L 0 /* Large 340pin 4712 */ | ||
257 | |||
258 | #include <linux/ssb/ssb_driver_chipcommon.h> | ||
259 | #include <linux/ssb/ssb_driver_mips.h> | ||
260 | #include <linux/ssb/ssb_driver_extif.h> | ||
261 | #include <linux/ssb/ssb_driver_pci.h> | ||
262 | |||
263 | struct ssb_bus { | ||
264 | /* The MMIO area. */ | ||
265 | void __iomem *mmio; | ||
266 | |||
267 | const struct ssb_bus_ops *ops; | ||
268 | |||
269 | /* The core in the basic address register window. (PCI bus only) */ | ||
270 | struct ssb_device *mapped_device; | ||
271 | /* Currently mapped PCMCIA segment. (bustype == SSB_BUSTYPE_PCMCIA only) */ | ||
272 | u8 mapped_pcmcia_seg; | ||
273 | /* Lock for core and segment switching. */ | ||
274 | spinlock_t bar_lock; | ||
275 | |||
276 | /* The bus this backplane is running on. */ | ||
277 | enum ssb_bustype bustype; | ||
278 | /* Pointer to the PCI bus (only valid if bustype == SSB_BUSTYPE_PCI). */ | ||
279 | struct pci_dev *host_pci; | ||
280 | /* Pointer to the PCMCIA device (only if bustype == SSB_BUSTYPE_PCMCIA). */ | ||
281 | struct pcmcia_device *host_pcmcia; | ||
282 | |||
283 | #ifdef CONFIG_SSB_PCIHOST | ||
284 | /* Mutex to protect the SPROM writing. */ | ||
285 | struct mutex pci_sprom_mutex; | ||
286 | #endif | ||
287 | |||
288 | /* ID information about the Chip. */ | ||
289 | u16 chip_id; | ||
290 | u16 chip_rev; | ||
291 | u8 chip_package; | ||
292 | |||
293 | /* List of devices (cores) on the backplane. */ | ||
294 | struct ssb_device devices[SSB_MAX_NR_CORES]; | ||
295 | u8 nr_devices; | ||
296 | |||
297 | /* Reference count. Number of suspended devices. */ | ||
298 | u8 suspend_cnt; | ||
299 | |||
300 | /* Software ID number for this bus. */ | ||
301 | unsigned int busnumber; | ||
302 | |||
303 | /* The ChipCommon device (if available). */ | ||
304 | struct ssb_chipcommon chipco; | ||
305 | /* The PCI-core device (if available). */ | ||
306 | struct ssb_pcicore pcicore; | ||
307 | /* The MIPS-core device (if available). */ | ||
308 | struct ssb_mipscore mipscore; | ||
309 | /* The EXTif-core device (if available). */ | ||
310 | struct ssb_extif extif; | ||
311 | |||
312 | /* The following structure elements are not available in early | ||
313 | * SSB initialization. Though, they are available for regular | ||
314 | * registered drivers at any stage. So be careful when | ||
315 | * using them in the ssb core code. */ | ||
316 | |||
317 | /* ID information about the PCB. */ | ||
318 | struct ssb_boardinfo boardinfo; | ||
319 | /* Contents of the SPROM. */ | ||
320 | struct ssb_sprom sprom; | ||
321 | |||
322 | /* Internal-only stuff follows. Do not touch. */ | ||
323 | struct list_head list; | ||
324 | #ifdef CONFIG_SSB_DEBUG | ||
325 | /* Is the bus already powered up? */ | ||
326 | bool powered_up; | ||
327 | int power_warn_count; | ||
328 | #endif /* DEBUG */ | ||
329 | }; | ||
330 | |||
331 | /* The initialization-invariants. */ | ||
332 | struct ssb_init_invariants { | ||
333 | struct ssb_boardinfo boardinfo; | ||
334 | struct ssb_sprom sprom; | ||
335 | }; | ||
336 | /* Type of function to fetch the invariants. */ | ||
337 | typedef int (*ssb_invariants_func_t)(struct ssb_bus *bus, | ||
338 | struct ssb_init_invariants *iv); | ||
339 | |||
340 | /* Register a SSB system bus. get_invariants() is called after the | ||
341 | * basic system devices are initialized. | ||
342 | * The invariants are usually fetched from some NVRAM. | ||
343 | * Put the invariants into the struct pointed to by iv. */ | ||
344 | extern int ssb_bus_ssbbus_register(struct ssb_bus *bus, | ||
345 | unsigned long baseaddr, | ||
346 | ssb_invariants_func_t get_invariants); | ||
347 | #ifdef CONFIG_SSB_PCIHOST | ||
348 | extern int ssb_bus_pcibus_register(struct ssb_bus *bus, | ||
349 | struct pci_dev *host_pci); | ||
350 | #endif /* CONFIG_SSB_PCIHOST */ | ||
351 | #ifdef CONFIG_SSB_PCMCIAHOST | ||
352 | extern int ssb_bus_pcmciabus_register(struct ssb_bus *bus, | ||
353 | struct pcmcia_device *pcmcia_dev, | ||
354 | unsigned long baseaddr); | ||
355 | #endif /* CONFIG_SSB_PCMCIAHOST */ | ||
356 | |||
357 | extern void ssb_bus_unregister(struct ssb_bus *bus); | ||
358 | |||
359 | extern u32 ssb_clockspeed(struct ssb_bus *bus); | ||
360 | |||
361 | /* Is the device enabled in hardware? */ | ||
362 | int ssb_device_is_enabled(struct ssb_device *dev); | ||
363 | /* Enable a device and pass device-specific SSB_TMSLOW flags. | ||
364 | * If no device-specific flags are available, use 0. */ | ||
365 | void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags); | ||
366 | /* Disable a device in hardware and pass SSB_TMSLOW flags (if any). */ | ||
367 | void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags); | ||
368 | |||
369 | |||
370 | /* Device MMIO register read/write functions. */ | ||
371 | static inline u16 ssb_read16(struct ssb_device *dev, u16 offset) | ||
372 | { | ||
373 | return dev->ops->read16(dev, offset); | ||
374 | } | ||
375 | static inline u32 ssb_read32(struct ssb_device *dev, u16 offset) | ||
376 | { | ||
377 | return dev->ops->read32(dev, offset); | ||
378 | } | ||
379 | static inline void ssb_write16(struct ssb_device *dev, u16 offset, u16 value) | ||
380 | { | ||
381 | dev->ops->write16(dev, offset, value); | ||
382 | } | ||
383 | static inline void ssb_write32(struct ssb_device *dev, u16 offset, u32 value) | ||
384 | { | ||
385 | dev->ops->write32(dev, offset, value); | ||
386 | } | ||
387 | |||
388 | |||
389 | /* Translation (routing) bits that need to be ORed to DMA | ||
390 | * addresses before they are given to a device. */ | ||
391 | extern u32 ssb_dma_translation(struct ssb_device *dev); | ||
392 | #define SSB_DMA_TRANSLATION_MASK 0xC0000000 | ||
393 | #define SSB_DMA_TRANSLATION_SHIFT 30 | ||
394 | |||
395 | extern int ssb_dma_set_mask(struct ssb_device *ssb_dev, u64 mask); | ||
396 | |||
397 | |||
398 | #ifdef CONFIG_SSB_PCIHOST | ||
399 | /* PCI-host wrapper driver */ | ||
400 | extern int ssb_pcihost_register(struct pci_driver *driver); | ||
401 | static inline void ssb_pcihost_unregister(struct pci_driver *driver) | ||
402 | { | ||
403 | pci_unregister_driver(driver); | ||
404 | } | ||
405 | #endif /* CONFIG_SSB_PCIHOST */ | ||
406 | |||
407 | |||
408 | /* If a driver is shutdown or suspended, call this to signal | ||
409 | * that the bus may be completely powered down. SSB will decide, | ||
410 | * if it's really time to power down the bus, based on if there | ||
411 | * are other devices that want to run. */ | ||
412 | extern int ssb_bus_may_powerdown(struct ssb_bus *bus); | ||
413 | /* Before initializing and enabling a device, call this to power-up the bus. | ||
414 | * If you want to allow use of dynamic-power-control, pass the flag. | ||
415 | * Otherwise static always-on powercontrol will be used. */ | ||
416 | extern int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl); | ||
417 | |||
418 | |||
419 | /* Various helper functions */ | ||
420 | extern u32 ssb_admatch_base(u32 adm); | ||
421 | extern u32 ssb_admatch_size(u32 adm); | ||
422 | |||
423 | |||
424 | #endif /* LINUX_SSB_H_ */ | ||
diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h new file mode 100644 index 000000000000..4cb995494662 --- /dev/null +++ b/include/linux/ssb/ssb_driver_chipcommon.h | |||
@@ -0,0 +1,396 @@ | |||
1 | #ifndef LINUX_SSB_CHIPCO_H_ | ||
2 | #define LINUX_SSB_CHIPCO_H_ | ||
3 | |||
4 | /* SonicsSiliconBackplane CHIPCOMMON core hardware definitions | ||
5 | * | ||
6 | * The chipcommon core provides chip identification, SB control, | ||
7 | * jtag, 0/1/2 uarts, clock frequency control, a watchdog interrupt timer, | ||
8 | * gpio interface, extbus, and support for serial and parallel flashes. | ||
9 | * | ||
10 | * Copyright 2005, Broadcom Corporation | ||
11 | * Copyright 2006, Michael Buesch <mb@bu3sch.de> | ||
12 | * | ||
13 | * Licensed under the GPL version 2. See COPYING for details. | ||
14 | */ | ||
15 | |||
16 | /** ChipCommon core registers. **/ | ||
17 | |||
18 | #define SSB_CHIPCO_CHIPID 0x0000 | ||
19 | #define SSB_CHIPCO_IDMASK 0x0000FFFF | ||
20 | #define SSB_CHIPCO_REVMASK 0x000F0000 | ||
21 | #define SSB_CHIPCO_REVSHIFT 16 | ||
22 | #define SSB_CHIPCO_PACKMASK 0x00F00000 | ||
23 | #define SSB_CHIPCO_PACKSHIFT 20 | ||
24 | #define SSB_CHIPCO_NRCORESMASK 0x0F000000 | ||
25 | #define SSB_CHIPCO_NRCORESSHIFT 24 | ||
26 | #define SSB_CHIPCO_CAP 0x0004 /* Capabilities */ | ||
27 | #define SSB_CHIPCO_CAP_NRUART 0x00000003 /* # of UARTs */ | ||
28 | #define SSB_CHIPCO_CAP_MIPSEB 0x00000004 /* MIPS in BigEndian Mode */ | ||
29 | #define SSB_CHIPCO_CAP_UARTCLK 0x00000018 /* UART clock select */ | ||
30 | #define SSB_CHIPCO_CAP_UARTCLK_INT 0x00000008 /* UARTs are driven by internal divided clock */ | ||
31 | #define SSB_CHIPCO_CAP_UARTGPIO 0x00000020 /* UARTs on GPIO 15-12 */ | ||
32 | #define SSB_CHIPCO_CAP_EXTBUS 0x000000C0 /* External buses present */ | ||
33 | #define SSB_CHIPCO_CAP_FLASHT 0x00000700 /* Flash Type */ | ||
34 | #define SSB_CHIPCO_FLASHT_NONE 0x00000000 /* No flash */ | ||
35 | #define SSB_CHIPCO_FLASHT_STSER 0x00000100 /* ST serial flash */ | ||
36 | #define SSB_CHIPCO_FLASHT_ATSER 0x00000200 /* Atmel serial flash */ | ||
37 | #define SSB_CHIPCO_FLASHT_PARA 0x00000700 /* Parallel flash */ | ||
38 | #define SSB_CHIPCO_CAP_PLLT 0x00038000 /* PLL Type */ | ||
39 | #define SSB_PLLTYPE_NONE 0x00000000 | ||
40 | #define SSB_PLLTYPE_1 0x00010000 /* 48Mhz base, 3 dividers */ | ||
41 | #define SSB_PLLTYPE_2 0x00020000 /* 48Mhz, 4 dividers */ | ||
42 | #define SSB_PLLTYPE_3 0x00030000 /* 25Mhz, 2 dividers */ | ||
43 | #define SSB_PLLTYPE_4 0x00008000 /* 48Mhz, 4 dividers */ | ||
44 | #define SSB_PLLTYPE_5 0x00018000 /* 25Mhz, 4 dividers */ | ||
45 | #define SSB_PLLTYPE_6 0x00028000 /* 100/200 or 120/240 only */ | ||
46 | #define SSB_PLLTYPE_7 0x00038000 /* 25Mhz, 4 dividers */ | ||
47 | #define SSB_CHIPCO_CAP_PCTL 0x00040000 /* Power Control */ | ||
48 | #define SSB_CHIPCO_CAP_OTPS 0x00380000 /* OTP size */ | ||
49 | #define SSB_CHIPCO_CAP_OTPS_SHIFT 19 | ||
50 | #define SSB_CHIPCO_CAP_OTPS_BASE 5 | ||
51 | #define SSB_CHIPCO_CAP_JTAGM 0x00400000 /* JTAG master present */ | ||
52 | #define SSB_CHIPCO_CAP_BROM 0x00800000 /* Internal boot ROM active */ | ||
53 | #define SSB_CHIPCO_CAP_64BIT 0x08000000 /* 64-bit Backplane */ | ||
54 | #define SSB_CHIPCO_CORECTL 0x0008 | ||
55 | #define SSB_CHIPCO_CORECTL_UARTCLK0 0x00000001 /* Drive UART with internal clock */ | ||
56 | #define SSB_CHIPCO_CORECTL_SE 0x00000002 /* sync clk out enable (corerev >= 3) */ | ||
57 | #define SSB_CHIPCO_BIST 0x000C | ||
58 | #define SSB_CHIPCO_OTPS 0x0010 /* OTP status */ | ||
59 | #define SSB_CHIPCO_OTPS_PROGFAIL 0x80000000 | ||
60 | #define SSB_CHIPCO_OTPS_PROTECT 0x00000007 | ||
61 | #define SSB_CHIPCO_OTPS_HW_PROTECT 0x00000001 | ||
62 | #define SSB_CHIPCO_OTPS_SW_PROTECT 0x00000002 | ||
63 | #define SSB_CHIPCO_OTPS_CID_PROTECT 0x00000004 | ||
64 | #define SSB_CHIPCO_OTPC 0x0014 /* OTP control */ | ||
65 | #define SSB_CHIPCO_OTPC_RECWAIT 0xFF000000 | ||
66 | #define SSB_CHIPCO_OTPC_PROGWAIT 0x00FFFF00 | ||
67 | #define SSB_CHIPCO_OTPC_PRW_SHIFT 8 | ||
68 | #define SSB_CHIPCO_OTPC_MAXFAIL 0x00000038 | ||
69 | #define SSB_CHIPCO_OTPC_VSEL 0x00000006 | ||
70 | #define SSB_CHIPCO_OTPC_SELVL 0x00000001 | ||
71 | #define SSB_CHIPCO_OTPP 0x0018 /* OTP prog */ | ||
72 | #define SSB_CHIPCO_OTPP_COL 0x000000FF | ||
73 | #define SSB_CHIPCO_OTPP_ROW 0x0000FF00 | ||
74 | #define SSB_CHIPCO_OTPP_ROW_SHIFT 8 | ||
75 | #define SSB_CHIPCO_OTPP_READERR 0x10000000 | ||
76 | #define SSB_CHIPCO_OTPP_VALUE 0x20000000 | ||
77 | #define SSB_CHIPCO_OTPP_READ 0x40000000 | ||
78 | #define SSB_CHIPCO_OTPP_START 0x80000000 | ||
79 | #define SSB_CHIPCO_OTPP_BUSY 0x80000000 | ||
80 | #define SSB_CHIPCO_IRQSTAT 0x0020 | ||
81 | #define SSB_CHIPCO_IRQMASK 0x0024 | ||
82 | #define SSB_CHIPCO_IRQ_GPIO 0x00000001 /* gpio intr */ | ||
83 | #define SSB_CHIPCO_IRQ_EXT 0x00000002 /* ro: ext intr pin (corerev >= 3) */ | ||
84 | #define SSB_CHIPCO_IRQ_WDRESET 0x80000000 /* watchdog reset occurred */ | ||
85 | #define SSB_CHIPCO_CHIPCTL 0x0028 /* Rev >= 11 only */ | ||
86 | #define SSB_CHIPCO_CHIPSTAT 0x002C /* Rev >= 11 only */ | ||
87 | #define SSB_CHIPCO_JCMD 0x0030 /* Rev >= 10 only */ | ||
88 | #define SSB_CHIPCO_JCMD_START 0x80000000 | ||
89 | #define SSB_CHIPCO_JCMD_BUSY 0x80000000 | ||
90 | #define SSB_CHIPCO_JCMD_PAUSE 0x40000000 | ||
91 | #define SSB_CHIPCO_JCMD0_ACC_MASK 0x0000F000 | ||
92 | #define SSB_CHIPCO_JCMD0_ACC_IRDR 0x00000000 | ||
93 | #define SSB_CHIPCO_JCMD0_ACC_DR 0x00001000 | ||
94 | #define SSB_CHIPCO_JCMD0_ACC_IR 0x00002000 | ||
95 | #define SSB_CHIPCO_JCMD0_ACC_RESET 0x00003000 | ||
96 | #define SSB_CHIPCO_JCMD0_ACC_IRPDR 0x00004000 | ||
97 | #define SSB_CHIPCO_JCMD0_ACC_PDR 0x00005000 | ||
98 | #define SSB_CHIPCO_JCMD0_IRW_MASK 0x00000F00 | ||
99 | #define SSB_CHIPCO_JCMD_ACC_MASK 0x000F0000 /* Changes for corerev 11 */ | ||
100 | #define SSB_CHIPCO_JCMD_ACC_IRDR 0x00000000 | ||
101 | #define SSB_CHIPCO_JCMD_ACC_DR 0x00010000 | ||
102 | #define SSB_CHIPCO_JCMD_ACC_IR 0x00020000 | ||
103 | #define SSB_CHIPCO_JCMD_ACC_RESET 0x00030000 | ||
104 | #define SSB_CHIPCO_JCMD_ACC_IRPDR 0x00040000 | ||
105 | #define SSB_CHIPCO_JCMD_ACC_PDR 0x00050000 | ||
106 | #define SSB_CHIPCO_JCMD_IRW_MASK 0x00001F00 | ||
107 | #define SSB_CHIPCO_JCMD_IRW_SHIFT 8 | ||
108 | #define SSB_CHIPCO_JCMD_DRW_MASK 0x0000003F | ||
109 | #define SSB_CHIPCO_JIR 0x0034 /* Rev >= 10 only */ | ||
110 | #define SSB_CHIPCO_JDR 0x0038 /* Rev >= 10 only */ | ||
111 | #define SSB_CHIPCO_JCTL 0x003C /* Rev >= 10 only */ | ||
112 | #define SSB_CHIPCO_JCTL_FORCE_CLK 4 /* Force clock */ | ||
113 | #define SSB_CHIPCO_JCTL_EXT_EN 2 /* Enable external targets */ | ||
114 | #define SSB_CHIPCO_JCTL_EN 1 /* Enable Jtag master */ | ||
115 | #define SSB_CHIPCO_FLASHCTL 0x0040 | ||
116 | #define SSB_CHIPCO_FLASHCTL_START 0x80000000 | ||
117 | #define SSB_CHIPCO_FLASHCTL_BUSY SSB_CHIPCO_FLASHCTL_START | ||
118 | #define SSB_CHIPCO_FLASHADDR 0x0044 | ||
119 | #define SSB_CHIPCO_FLASHDATA 0x0048 | ||
120 | #define SSB_CHIPCO_BCAST_ADDR 0x0050 | ||
121 | #define SSB_CHIPCO_BCAST_DATA 0x0054 | ||
122 | #define SSB_CHIPCO_GPIOIN 0x0060 | ||
123 | #define SSB_CHIPCO_GPIOOUT 0x0064 | ||
124 | #define SSB_CHIPCO_GPIOOUTEN 0x0068 | ||
125 | #define SSB_CHIPCO_GPIOCTL 0x006C | ||
126 | #define SSB_CHIPCO_GPIOPOL 0x0070 | ||
127 | #define SSB_CHIPCO_GPIOIRQ 0x0074 | ||
128 | #define SSB_CHIPCO_WATCHDOG 0x0080 | ||
129 | #define SSB_CHIPCO_GPIOTIMER 0x0088 /* LED powersave (corerev >= 16) */ | ||
130 | #define SSB_CHIPCO_GPIOTIMER_ONTIME_SHIFT 16 | ||
131 | #define SSB_CHIPCO_GPIOTOUTM 0x008C /* LED powersave (corerev >= 16) */ | ||
132 | #define SSB_CHIPCO_CLOCK_N 0x0090 | ||
133 | #define SSB_CHIPCO_CLOCK_SB 0x0094 | ||
134 | #define SSB_CHIPCO_CLOCK_PCI 0x0098 | ||
135 | #define SSB_CHIPCO_CLOCK_M2 0x009C | ||
136 | #define SSB_CHIPCO_CLOCK_MIPS 0x00A0 | ||
137 | #define SSB_CHIPCO_CLKDIV 0x00A4 /* Rev >= 3 only */ | ||
138 | #define SSB_CHIPCO_CLKDIV_SFLASH 0x0F000000 | ||
139 | #define SSB_CHIPCO_CLKDIV_SFLASH_SHIFT 24 | ||
140 | #define SSB_CHIPCO_CLKDIV_OTP 0x000F0000 | ||
141 | #define SSB_CHIPCO_CLKDIV_OTP_SHIFT 16 | ||
142 | #define SSB_CHIPCO_CLKDIV_JTAG 0x00000F00 | ||
143 | #define SSB_CHIPCO_CLKDIV_JTAG_SHIFT 8 | ||
144 | #define SSB_CHIPCO_CLKDIV_UART 0x000000FF | ||
145 | #define SSB_CHIPCO_PLLONDELAY 0x00B0 /* Rev >= 4 only */ | ||
146 | #define SSB_CHIPCO_FREFSELDELAY 0x00B4 /* Rev >= 4 only */ | ||
147 | #define SSB_CHIPCO_SLOWCLKCTL 0x00B8 /* 6 <= Rev <= 9 only */ | ||
148 | #define SSB_CHIPCO_SLOWCLKCTL_SRC 0x00000007 /* slow clock source mask */ | ||
149 | #define SSB_CHIPCO_SLOWCLKCTL_SRC_LPO 0x00000000 /* source of slow clock is LPO */ | ||
150 | #define SSB_CHIPCO_SLOWCLKCTL_SRC_XTAL 0x00000001 /* source of slow clock is crystal */ | ||
151 | #define SSB_CHIPCO_SLOECLKCTL_SRC_PCI 0x00000002 /* source of slow clock is PCI */ | ||
152 | #define SSB_CHIPCO_SLOWCLKCTL_LPOFREQ 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */ | ||
153 | #define SSB_CHIPCO_SLOWCLKCTL_LPOPD 0x00000400 /* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */ | ||
154 | #define SSB_CHIPCO_SLOWCLKCTL_FSLOW 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */ | ||
155 | #define SSB_CHIPCO_SLOWCLKCTL_IPLL 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors PLL clock disable requests from core */ | ||
156 | #define SSB_CHIPCO_SLOWCLKCTL_ENXTAL 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't disable crystal when appropriate */ | ||
157 | #define SSB_CHIPCO_SLOWCLKCTL_XTALPU 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */ | ||
158 | #define SSB_CHIPCO_SLOWCLKCTL_CLKDIV 0xFFFF0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */ | ||
159 | #define SSB_CHIPCO_SLOWCLKCTL_CLKDIV_SHIFT 16 | ||
160 | #define SSB_CHIPCO_SYSCLKCTL 0x00C0 /* Rev >= 3 only */ | ||
161 | #define SSB_CHIPCO_SYSCLKCTL_IDLPEN 0x00000001 /* ILPen: Enable Idle Low Power */ | ||
162 | #define SSB_CHIPCO_SYSCLKCTL_ALPEN 0x00000002 /* ALPen: Enable Active Low Power */ | ||
163 | #define SSB_CHIPCO_SYSCLKCTL_PLLEN 0x00000004 /* ForcePLLOn */ | ||
164 | #define SSB_CHIPCO_SYSCLKCTL_FORCEALP 0x00000008 /* Force ALP (or HT if ALPen is not set */ | ||
165 | #define SSB_CHIPCO_SYSCLKCTL_FORCEHT 0x00000010 /* Force HT */ | ||
166 | #define SSB_CHIPCO_SYSCLKCTL_CLKDIV 0xFFFF0000 /* ClkDiv (ILP = 1/(4+divisor)) */ | ||
167 | #define SSB_CHIPCO_SYSCLKCTL_CLKDIV_SHIFT 16 | ||
168 | #define SSB_CHIPCO_CLKSTSTR 0x00C4 /* Rev >= 3 only */ | ||
169 | #define SSB_CHIPCO_PCMCIA_CFG 0x0100 | ||
170 | #define SSB_CHIPCO_PCMCIA_MEMWAIT 0x0104 | ||
171 | #define SSB_CHIPCO_PCMCIA_ATTRWAIT 0x0108 | ||
172 | #define SSB_CHIPCO_PCMCIA_IOWAIT 0x010C | ||
173 | #define SSB_CHIPCO_IDE_CFG 0x0110 | ||
174 | #define SSB_CHIPCO_IDE_MEMWAIT 0x0114 | ||
175 | #define SSB_CHIPCO_IDE_ATTRWAIT 0x0118 | ||
176 | #define SSB_CHIPCO_IDE_IOWAIT 0x011C | ||
177 | #define SSB_CHIPCO_PROG_CFG 0x0120 | ||
178 | #define SSB_CHIPCO_PROG_WAITCNT 0x0124 | ||
179 | #define SSB_CHIPCO_FLASH_CFG 0x0128 | ||
180 | #define SSB_CHIPCO_FLASH_WAITCNT 0x012C | ||
181 | #define SSB_CHIPCO_UART0_DATA 0x0300 | ||
182 | #define SSB_CHIPCO_UART0_IMR 0x0304 | ||
183 | #define SSB_CHIPCO_UART0_FCR 0x0308 | ||
184 | #define SSB_CHIPCO_UART0_LCR 0x030C | ||
185 | #define SSB_CHIPCO_UART0_MCR 0x0310 | ||
186 | #define SSB_CHIPCO_UART0_LSR 0x0314 | ||
187 | #define SSB_CHIPCO_UART0_MSR 0x0318 | ||
188 | #define SSB_CHIPCO_UART0_SCRATCH 0x031C | ||
189 | #define SSB_CHIPCO_UART1_DATA 0x0400 | ||
190 | #define SSB_CHIPCO_UART1_IMR 0x0404 | ||
191 | #define SSB_CHIPCO_UART1_FCR 0x0408 | ||
192 | #define SSB_CHIPCO_UART1_LCR 0x040C | ||
193 | #define SSB_CHIPCO_UART1_MCR 0x0410 | ||
194 | #define SSB_CHIPCO_UART1_LSR 0x0414 | ||
195 | #define SSB_CHIPCO_UART1_MSR 0x0418 | ||
196 | #define SSB_CHIPCO_UART1_SCRATCH 0x041C | ||
197 | |||
198 | |||
199 | |||
200 | /** Clockcontrol masks and values **/ | ||
201 | |||
202 | /* SSB_CHIPCO_CLOCK_N */ | ||
203 | #define SSB_CHIPCO_CLK_N1 0x0000003F /* n1 control */ | ||
204 | #define SSB_CHIPCO_CLK_N2 0x00003F00 /* n2 control */ | ||
205 | #define SSB_CHIPCO_CLK_N2_SHIFT 8 | ||
206 | #define SSB_CHIPCO_CLK_PLLC 0x000F0000 /* pll control */ | ||
207 | #define SSB_CHIPCO_CLK_PLLC_SHIFT 16 | ||
208 | |||
209 | /* SSB_CHIPCO_CLOCK_SB/PCI/UART */ | ||
210 | #define SSB_CHIPCO_CLK_M1 0x0000003F /* m1 control */ | ||
211 | #define SSB_CHIPCO_CLK_M2 0x00003F00 /* m2 control */ | ||
212 | #define SSB_CHIPCO_CLK_M2_SHIFT 8 | ||
213 | #define SSB_CHIPCO_CLK_M3 0x003F0000 /* m3 control */ | ||
214 | #define SSB_CHIPCO_CLK_M3_SHIFT 16 | ||
215 | #define SSB_CHIPCO_CLK_MC 0x1F000000 /* mux control */ | ||
216 | #define SSB_CHIPCO_CLK_MC_SHIFT 24 | ||
217 | |||
218 | /* N3M Clock control magic field values */ | ||
219 | #define SSB_CHIPCO_CLK_F6_2 0x02 /* A factor of 2 in */ | ||
220 | #define SSB_CHIPCO_CLK_F6_3 0x03 /* 6-bit fields like */ | ||
221 | #define SSB_CHIPCO_CLK_F6_4 0x05 /* N1, M1 or M3 */ | ||
222 | #define SSB_CHIPCO_CLK_F6_5 0x09 | ||
223 | #define SSB_CHIPCO_CLK_F6_6 0x11 | ||
224 | #define SSB_CHIPCO_CLK_F6_7 0x21 | ||
225 | |||
226 | #define SSB_CHIPCO_CLK_F5_BIAS 5 /* 5-bit fields get this added */ | ||
227 | |||
228 | #define SSB_CHIPCO_CLK_MC_BYPASS 0x08 | ||
229 | #define SSB_CHIPCO_CLK_MC_M1 0x04 | ||
230 | #define SSB_CHIPCO_CLK_MC_M1M2 0x02 | ||
231 | #define SSB_CHIPCO_CLK_MC_M1M2M3 0x01 | ||
232 | #define SSB_CHIPCO_CLK_MC_M1M3 0x11 | ||
233 | |||
234 | /* Type 2 Clock control magic field values */ | ||
235 | #define SSB_CHIPCO_CLK_T2_BIAS 2 /* n1, n2, m1 & m3 bias */ | ||
236 | #define SSB_CHIPCO_CLK_T2M2_BIAS 3 /* m2 bias */ | ||
237 | |||
238 | #define SSB_CHIPCO_CLK_T2MC_M1BYP 1 | ||
239 | #define SSB_CHIPCO_CLK_T2MC_M2BYP 2 | ||
240 | #define SSB_CHIPCO_CLK_T2MC_M3BYP 4 | ||
241 | |||
242 | /* Type 6 Clock control magic field values */ | ||
243 | #define SSB_CHIPCO_CLK_T6_MMASK 1 /* bits of interest in m */ | ||
244 | #define SSB_CHIPCO_CLK_T6_M0 120000000 /* sb clock for m = 0 */ | ||
245 | #define SSB_CHIPCO_CLK_T6_M1 100000000 /* sb clock for m = 1 */ | ||
246 | #define SSB_CHIPCO_CLK_SB2MIPS_T6(sb) (2 * (sb)) | ||
247 | |||
248 | /* Common clock base */ | ||
249 | #define SSB_CHIPCO_CLK_BASE1 24000000 /* Half the clock freq */ | ||
250 | #define SSB_CHIPCO_CLK_BASE2 12500000 /* Alternate crystal on some PLL's */ | ||
251 | |||
252 | /* Clock control values for 200Mhz in 5350 */ | ||
253 | #define SSB_CHIPCO_CLK_5350_N 0x0311 | ||
254 | #define SSB_CHIPCO_CLK_5350_M 0x04020009 | ||
255 | |||
256 | |||
257 | /** Bits in the config registers **/ | ||
258 | |||
259 | #define SSB_CHIPCO_CFG_EN 0x0001 /* Enable */ | ||
260 | #define SSB_CHIPCO_CFG_EXTM 0x000E /* Extif Mode */ | ||
261 | #define SSB_CHIPCO_CFG_EXTM_ASYNC 0x0002 /* Async/Parallel flash */ | ||
262 | #define SSB_CHIPCO_CFG_EXTM_SYNC 0x0004 /* Synchronous */ | ||
263 | #define SSB_CHIPCO_CFG_EXTM_PCMCIA 0x0008 /* PCMCIA */ | ||
264 | #define SSB_CHIPCO_CFG_EXTM_IDE 0x000A /* IDE */ | ||
265 | #define SSB_CHIPCO_CFG_DS16 0x0010 /* Data size, 0=8bit, 1=16bit */ | ||
266 | #define SSB_CHIPCO_CFG_CLKDIV 0x0060 /* Sync: Clock divisor */ | ||
267 | #define SSB_CHIPCO_CFG_CLKEN 0x0080 /* Sync: Clock enable */ | ||
268 | #define SSB_CHIPCO_CFG_BSTRO 0x0100 /* Sync: Size/Bytestrobe */ | ||
269 | |||
270 | |||
271 | /** Flash-specific control/status values */ | ||
272 | |||
273 | /* flashcontrol opcodes for ST flashes */ | ||
274 | #define SSB_CHIPCO_FLASHCTL_ST_WREN 0x0006 /* Write Enable */ | ||
275 | #define SSB_CHIPCO_FLASHCTL_ST_WRDIS 0x0004 /* Write Disable */ | ||
276 | #define SSB_CHIPCO_FLASHCTL_ST_RDSR 0x0105 /* Read Status Register */ | ||
277 | #define SSB_CHIPCO_FLASHCTL_ST_WRSR 0x0101 /* Write Status Register */ | ||
278 | #define SSB_CHIPCO_FLASHCTL_ST_READ 0x0303 /* Read Data Bytes */ | ||
279 | #define SSB_CHIPCO_FLASHCTL_ST_PP 0x0302 /* Page Program */ | ||
280 | #define SSB_CHIPCO_FLASHCTL_ST_SE 0x02D8 /* Sector Erase */ | ||
281 | #define SSB_CHIPCO_FLASHCTL_ST_BE 0x00C7 /* Bulk Erase */ | ||
282 | #define SSB_CHIPCO_FLASHCTL_ST_DP 0x00B9 /* Deep Power-down */ | ||
283 | #define SSB_CHIPCO_FLASHCTL_ST_RSIG 0x03AB /* Read Electronic Signature */ | ||
284 | |||
285 | /* Status register bits for ST flashes */ | ||
286 | #define SSB_CHIPCO_FLASHSTA_ST_WIP 0x01 /* Write In Progress */ | ||
287 | #define SSB_CHIPCO_FLASHSTA_ST_WEL 0x02 /* Write Enable Latch */ | ||
288 | #define SSB_CHIPCO_FLASHSTA_ST_BP 0x1C /* Block Protect */ | ||
289 | #define SSB_CHIPCO_FLASHSTA_ST_BP_SHIFT 2 | ||
290 | #define SSB_CHIPCO_FLASHSTA_ST_SRWD 0x80 /* Status Register Write Disable */ | ||
291 | |||
292 | /* flashcontrol opcodes for Atmel flashes */ | ||
293 | #define SSB_CHIPCO_FLASHCTL_AT_READ 0x07E8 | ||
294 | #define SSB_CHIPCO_FLASHCTL_AT_PAGE_READ 0x07D2 | ||
295 | #define SSB_CHIPCO_FLASHCTL_AT_BUF1_READ /* FIXME */ | ||
296 | #define SSB_CHIPCO_FLASHCTL_AT_BUF2_READ /* FIXME */ | ||
297 | #define SSB_CHIPCO_FLASHCTL_AT_STATUS 0x01D7 | ||
298 | #define SSB_CHIPCO_FLASHCTL_AT_BUF1_WRITE 0x0384 | ||
299 | #define SSB_CHIPCO_FLASHCTL_AT_BUF2_WRITE 0x0387 | ||
300 | #define SSB_CHIPCO_FLASHCTL_AT_BUF1_ERASE_PRGM 0x0283 /* Erase program */ | ||
301 | #define SSB_CHIPCO_FLASHCTL_AT_BUF2_ERASE_PRGM 0x0286 /* Erase program */ | ||
302 | #define SSB_CHIPCO_FLASHCTL_AT_BUF1_PROGRAM 0x0288 | ||
303 | #define SSB_CHIPCO_FLASHCTL_AT_BUF2_PROGRAM 0x0289 | ||
304 | #define SSB_CHIPCO_FLASHCTL_AT_PAGE_ERASE 0x0281 | ||
305 | #define SSB_CHIPCO_FLASHCTL_AT_BLOCK_ERASE 0x0250 | ||
306 | #define SSB_CHIPCO_FLASHCTL_AT_BUF1_WRER_PRGM 0x0382 /* Write erase program */ | ||
307 | #define SSB_CHIPCO_FLASHCTL_AT_BUF2_WRER_PRGM 0x0385 /* Write erase program */ | ||
308 | #define SSB_CHIPCO_FLASHCTL_AT_BUF1_LOAD 0x0253 | ||
309 | #define SSB_CHIPCO_FLASHCTL_AT_BUF2_LOAD 0x0255 | ||
310 | #define SSB_CHIPCO_FLASHCTL_AT_BUF1_COMPARE 0x0260 | ||
311 | #define SSB_CHIPCO_FLASHCTL_AT_BUF2_COMPARE 0x0261 | ||
312 | #define SSB_CHIPCO_FLASHCTL_AT_BUF1_REPROGRAM 0x0258 | ||
313 | #define SSB_CHIPCO_FLASHCTL_AT_BUF2_REPROGRAM 0x0259 | ||
314 | |||
315 | /* Status register bits for Atmel flashes */ | ||
316 | #define SSB_CHIPCO_FLASHSTA_AT_READY 0x80 | ||
317 | #define SSB_CHIPCO_FLASHSTA_AT_MISMATCH 0x40 | ||
318 | #define SSB_CHIPCO_FLASHSTA_AT_ID 0x38 | ||
319 | #define SSB_CHIPCO_FLASHSTA_AT_ID_SHIFT 3 | ||
320 | |||
321 | |||
322 | /** OTP **/ | ||
323 | |||
324 | /* OTP regions */ | ||
325 | #define SSB_CHIPCO_OTP_HW_REGION SSB_CHIPCO_OTPS_HW_PROTECT | ||
326 | #define SSB_CHIPCO_OTP_SW_REGION SSB_CHIPCO_OTPS_SW_PROTECT | ||
327 | #define SSB_CHIPCO_OTP_CID_REGION SSB_CHIPCO_OTPS_CID_PROTECT | ||
328 | |||
329 | /* OTP regions (Byte offsets from otp size) */ | ||
330 | #define SSB_CHIPCO_OTP_SWLIM_OFF (-8) | ||
331 | #define SSB_CHIPCO_OTP_CIDBASE_OFF 0 | ||
332 | #define SSB_CHIPCO_OTP_CIDLIM_OFF 8 | ||
333 | |||
334 | /* Predefined OTP words (Word offset from otp size) */ | ||
335 | #define SSB_CHIPCO_OTP_BOUNDARY_OFF (-4) | ||
336 | #define SSB_CHIPCO_OTP_HWSIGN_OFF (-3) | ||
337 | #define SSB_CHIPCO_OTP_SWSIGN_OFF (-2) | ||
338 | #define SSB_CHIPCO_OTP_CIDSIGN_OFF (-1) | ||
339 | |||
340 | #define SSB_CHIPCO_OTP_CID_OFF 0 | ||
341 | #define SSB_CHIPCO_OTP_PKG_OFF 1 | ||
342 | #define SSB_CHIPCO_OTP_FID_OFF 2 | ||
343 | #define SSB_CHIPCO_OTP_RSV_OFF 3 | ||
344 | #define SSB_CHIPCO_OTP_LIM_OFF 4 | ||
345 | |||
346 | #define SSB_CHIPCO_OTP_SIGNATURE 0x578A | ||
347 | #define SSB_CHIPCO_OTP_MAGIC 0x4E56 | ||
348 | |||
349 | |||
350 | struct ssb_device; | ||
351 | struct ssb_serial_port; | ||
352 | |||
353 | struct ssb_chipcommon { | ||
354 | struct ssb_device *dev; | ||
355 | u32 capabilities; | ||
356 | /* Fast Powerup Delay constant */ | ||
357 | u16 fast_pwrup_delay; | ||
358 | }; | ||
359 | |||
360 | extern void ssb_chipcommon_init(struct ssb_chipcommon *cc); | ||
361 | |||
362 | #include <linux/pm.h> | ||
363 | extern void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state); | ||
364 | extern void ssb_chipco_resume(struct ssb_chipcommon *cc); | ||
365 | |||
366 | extern void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc, | ||
367 | u32 *plltype, u32 *n, u32 *m); | ||
368 | extern void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc, | ||
369 | u32 *plltype, u32 *n, u32 *m); | ||
370 | extern void ssb_chipco_timing_init(struct ssb_chipcommon *cc, | ||
371 | unsigned long ns_per_cycle); | ||
372 | |||
373 | enum ssb_clkmode { | ||
374 | SSB_CLKMODE_SLOW, | ||
375 | SSB_CLKMODE_FAST, | ||
376 | SSB_CLKMODE_DYNAMIC, | ||
377 | }; | ||
378 | |||
379 | extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, | ||
380 | enum ssb_clkmode mode); | ||
381 | |||
382 | extern void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, | ||
383 | u32 ticks); | ||
384 | |||
385 | u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask); | ||
386 | |||
387 | void ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value); | ||
388 | |||
389 | void ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value); | ||
390 | |||
391 | #ifdef CONFIG_SSB_SERIAL | ||
392 | extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc, | ||
393 | struct ssb_serial_port *ports); | ||
394 | #endif /* CONFIG_SSB_SERIAL */ | ||
395 | |||
396 | #endif /* LINUX_SSB_CHIPCO_H_ */ | ||
diff --git a/include/linux/ssb/ssb_driver_extif.h b/include/linux/ssb/ssb_driver_extif.h new file mode 100644 index 000000000000..a9164357b5ae --- /dev/null +++ b/include/linux/ssb/ssb_driver_extif.h | |||
@@ -0,0 +1,204 @@ | |||
1 | /* | ||
2 | * Hardware-specific External Interface I/O core definitions | ||
3 | * for the BCM47xx family of SiliconBackplane-based chips. | ||
4 | * | ||
5 | * The External Interface core supports a total of three external chip selects | ||
6 | * supporting external interfaces. One of the external chip selects is | ||
7 | * used for Flash, one is used for PCMCIA, and the other may be | ||
8 | * programmed to support either a synchronous interface or an | ||
9 | * asynchronous interface. The asynchronous interface can be used to | ||
10 | * support external devices such as UARTs and the BCM2019 Bluetooth | ||
11 | * baseband processor. | ||
12 | * The external interface core also contains 2 on-chip 16550 UARTs, clock | ||
13 | * frequency control, a watchdog interrupt timer, and a GPIO interface. | ||
14 | * | ||
15 | * Copyright 2005, Broadcom Corporation | ||
16 | * Copyright 2006, Michael Buesch | ||
17 | * | ||
18 | * Licensed under the GPL version 2. See COPYING for details. | ||
19 | */ | ||
20 | #ifndef LINUX_SSB_EXTIFCORE_H_ | ||
21 | #define LINUX_SSB_EXTIFCORE_H_ | ||
22 | |||
23 | /* external interface address space */ | ||
24 | #define SSB_EXTIF_PCMCIA_MEMBASE(x) (x) | ||
25 | #define SSB_EXTIF_PCMCIA_IOBASE(x) ((x) + 0x100000) | ||
26 | #define SSB_EXTIF_PCMCIA_CFGBASE(x) ((x) + 0x200000) | ||
27 | #define SSB_EXTIF_CFGIF_BASE(x) ((x) + 0x800000) | ||
28 | #define SSB_EXTIF_FLASH_BASE(x) ((x) + 0xc00000) | ||
29 | |||
30 | #define SSB_EXTIF_NR_GPIOOUT 5 | ||
31 | /* GPIO NOTE: | ||
32 | * The multiple instances of output and output enable registers | ||
33 | * are present to allow driver software for multiple cores to control | ||
34 | * gpio outputs without needing to share a single register pair. | ||
35 | * Use the following helper macro to get a register offset value. | ||
36 | */ | ||
37 | #define SSB_EXTIF_GPIO_OUT(index) ({ \ | ||
38 | BUILD_BUG_ON(index >= SSB_EXTIF_NR_GPIOOUT); \ | ||
39 | SSB_EXTIF_GPIO_OUT_BASE + ((index) * 8); \ | ||
40 | }) | ||
41 | #define SSB_EXTIF_GPIO_OUTEN(index) ({ \ | ||
42 | BUILD_BUG_ON(index >= SSB_EXTIF_NR_GPIOOUT); \ | ||
43 | SSB_EXTIF_GPIO_OUTEN_BASE + ((index) * 8); \ | ||
44 | }) | ||
45 | |||
46 | /** EXTIF core registers **/ | ||
47 | |||
48 | #define SSB_EXTIF_CTL 0x0000 | ||
49 | #define SSB_EXTIF_CTL_UARTEN (1 << 0) /* UART enable */ | ||
50 | #define SSB_EXTIF_EXTSTAT 0x0004 | ||
51 | #define SSB_EXTIF_EXTSTAT_EMODE (1 << 0) /* Endian mode (ro) */ | ||
52 | #define SSB_EXTIF_EXTSTAT_EIRQPIN (1 << 1) /* External interrupt pin (ro) */ | ||
53 | #define SSB_EXTIF_EXTSTAT_GPIOIRQPIN (1 << 2) /* GPIO interrupt pin (ro) */ | ||
54 | #define SSB_EXTIF_PCMCIA_CFG 0x0010 | ||
55 | #define SSB_EXTIF_PCMCIA_MEMWAIT 0x0014 | ||
56 | #define SSB_EXTIF_PCMCIA_ATTRWAIT 0x0018 | ||
57 | #define SSB_EXTIF_PCMCIA_IOWAIT 0x001C | ||
58 | #define SSB_EXTIF_PROG_CFG 0x0020 | ||
59 | #define SSB_EXTIF_PROG_WAITCNT 0x0024 | ||
60 | #define SSB_EXTIF_FLASH_CFG 0x0028 | ||
61 | #define SSB_EXTIF_FLASH_WAITCNT 0x002C | ||
62 | #define SSB_EXTIF_WATCHDOG 0x0040 | ||
63 | #define SSB_EXTIF_CLOCK_N 0x0044 | ||
64 | #define SSB_EXTIF_CLOCK_SB 0x0048 | ||
65 | #define SSB_EXTIF_CLOCK_PCI 0x004C | ||
66 | #define SSB_EXTIF_CLOCK_MII 0x0050 | ||
67 | #define SSB_EXTIF_GPIO_IN 0x0060 | ||
68 | #define SSB_EXTIF_GPIO_OUT_BASE 0x0064 | ||
69 | #define SSB_EXTIF_GPIO_OUTEN_BASE 0x0068 | ||
70 | #define SSB_EXTIF_EJTAG_OUTEN 0x0090 | ||
71 | #define SSB_EXTIF_GPIO_INTPOL 0x0094 | ||
72 | #define SSB_EXTIF_GPIO_INTMASK 0x0098 | ||
73 | #define SSB_EXTIF_UART_DATA 0x0300 | ||
74 | #define SSB_EXTIF_UART_TIMER 0x0310 | ||
75 | #define SSB_EXTIF_UART_FCR 0x0320 | ||
76 | #define SSB_EXTIF_UART_LCR 0x0330 | ||
77 | #define SSB_EXTIF_UART_MCR 0x0340 | ||
78 | #define SSB_EXTIF_UART_LSR 0x0350 | ||
79 | #define SSB_EXTIF_UART_MSR 0x0360 | ||
80 | #define SSB_EXTIF_UART_SCRATCH 0x0370 | ||
81 | |||
82 | |||
83 | |||
84 | |||
85 | /* pcmcia/prog/flash_config */ | ||
86 | #define SSB_EXTCFG_EN (1 << 0) /* enable */ | ||
87 | #define SSB_EXTCFG_MODE 0xE /* mode */ | ||
88 | #define SSB_EXTCFG_MODE_SHIFT 1 | ||
89 | #define SSB_EXTCFG_MODE_FLASH 0x0 /* flash/asynchronous mode */ | ||
90 | #define SSB_EXTCFG_MODE_SYNC 0x2 /* synchronous mode */ | ||
91 | #define SSB_EXTCFG_MODE_PCMCIA 0x4 /* pcmcia mode */ | ||
92 | #define SSB_EXTCFG_DS16 (1 << 4) /* destsize: 0=8bit, 1=16bit */ | ||
93 | #define SSB_EXTCFG_BSWAP (1 << 5) /* byteswap */ | ||
94 | #define SSB_EXTCFG_CLKDIV 0xC0 /* clock divider */ | ||
95 | #define SSB_EXTCFG_CLKDIV_SHIFT 6 | ||
96 | #define SSB_EXTCFG_CLKDIV_2 0x0 /* backplane/2 */ | ||
97 | #define SSB_EXTCFG_CLKDIV_3 0x40 /* backplane/3 */ | ||
98 | #define SSB_EXTCFG_CLKDIV_4 0x80 /* backplane/4 */ | ||
99 | #define SSB_EXTCFG_CLKEN (1 << 8) /* clock enable */ | ||
100 | #define SSB_EXTCFG_STROBE (1 << 9) /* size/bytestrobe (synch only) */ | ||
101 | |||
102 | /* pcmcia_memwait */ | ||
103 | #define SSB_PCMCIA_MEMW_0 0x0000003F /* waitcount0 */ | ||
104 | #define SSB_PCMCIA_MEMW_1 0x00001F00 /* waitcount1 */ | ||
105 | #define SSB_PCMCIA_MEMW_1_SHIFT 8 | ||
106 | #define SSB_PCMCIA_MEMW_2 0x001F0000 /* waitcount2 */ | ||
107 | #define SSB_PCMCIA_MEMW_2_SHIFT 16 | ||
108 | #define SSB_PCMCIA_MEMW_3 0x1F000000 /* waitcount3 */ | ||
109 | #define SSB_PCMCIA_MEMW_3_SHIFT 24 | ||
110 | |||
111 | /* pcmcia_attrwait */ | ||
112 | #define SSB_PCMCIA_ATTW_0 0x0000003F /* waitcount0 */ | ||
113 | #define SSB_PCMCIA_ATTW_1 0x00001F00 /* waitcount1 */ | ||
114 | #define SSB_PCMCIA_ATTW_1_SHIFT 8 | ||
115 | #define SSB_PCMCIA_ATTW_2 0x001F0000 /* waitcount2 */ | ||
116 | #define SSB_PCMCIA_ATTW_2_SHIFT 16 | ||
117 | #define SSB_PCMCIA_ATTW_3 0x1F000000 /* waitcount3 */ | ||
118 | #define SSB_PCMCIA_ATTW_3_SHIFT 24 | ||
119 | |||
120 | /* pcmcia_iowait */ | ||
121 | #define SSB_PCMCIA_IOW_0 0x0000003F /* waitcount0 */ | ||
122 | #define SSB_PCMCIA_IOW_1 0x00001F00 /* waitcount1 */ | ||
123 | #define SSB_PCMCIA_IOW_1_SHIFT 8 | ||
124 | #define SSB_PCMCIA_IOW_2 0x001F0000 /* waitcount2 */ | ||
125 | #define SSB_PCMCIA_IOW_2_SHIFT 16 | ||
126 | #define SSB_PCMCIA_IOW_3 0x1F000000 /* waitcount3 */ | ||
127 | #define SSB_PCMCIA_IOW_3_SHIFT 24 | ||
128 | |||
129 | /* prog_waitcount */ | ||
130 | #define SSB_PROG_WCNT_0 0x0000001F /* waitcount0 */ | ||
131 | #define SSB_PROG_WCNT_1 0x00001F00 /* waitcount1 */ | ||
132 | #define SSB_PROG_WCNT_1_SHIFT 8 | ||
133 | #define SSB_PROG_WCNT_2 0x001F0000 /* waitcount2 */ | ||
134 | #define SSB_PROG_WCNT_2_SHIFT 16 | ||
135 | #define SSB_PROG_WCNT_3 0x1F000000 /* waitcount3 */ | ||
136 | #define SSB_PROG_WCNT_3_SHIFT 24 | ||
137 | |||
138 | #define SSB_PROG_W0 0x0000000C | ||
139 | #define SSB_PROG_W1 0x00000A00 | ||
140 | #define SSB_PROG_W2 0x00020000 | ||
141 | #define SSB_PROG_W3 0x01000000 | ||
142 | |||
143 | /* flash_waitcount */ | ||
144 | #define SSB_FLASH_WCNT_0 0x0000001F /* waitcount0 */ | ||
145 | #define SSB_FLASH_WCNT_1 0x00001F00 /* waitcount1 */ | ||
146 | #define SSB_FLASH_WCNT_1_SHIFT 8 | ||
147 | #define SSB_FLASH_WCNT_2 0x001F0000 /* waitcount2 */ | ||
148 | #define SSB_FLASH_WCNT_2_SHIFT 16 | ||
149 | #define SSB_FLASH_WCNT_3 0x1F000000 /* waitcount3 */ | ||
150 | #define SSB_FLASH_WCNT_3_SHIFT 24 | ||
151 | |||
152 | /* watchdog */ | ||
153 | #define SSB_EXTIF_WATCHDOG_CLK 48000000 /* Hz */ | ||
154 | |||
155 | |||
156 | |||
157 | #ifdef CONFIG_SSB_DRIVER_EXTIF | ||
158 | |||
159 | struct ssb_extif { | ||
160 | struct ssb_device *dev; | ||
161 | }; | ||
162 | |||
163 | static inline bool ssb_extif_available(struct ssb_extif *extif) | ||
164 | { | ||
165 | return (extif->dev != NULL); | ||
166 | } | ||
167 | |||
168 | extern void ssb_extif_get_clockcontrol(struct ssb_extif *extif, | ||
169 | u32 *plltype, u32 *n, u32 *m); | ||
170 | |||
171 | extern void ssb_extif_timing_init(struct ssb_extif *extif, | ||
172 | unsigned long ns); | ||
173 | |||
174 | u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask); | ||
175 | |||
176 | void ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value); | ||
177 | |||
178 | void ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value); | ||
179 | |||
180 | #ifdef CONFIG_SSB_SERIAL | ||
181 | extern int ssb_extif_serial_init(struct ssb_extif *extif, | ||
182 | struct ssb_serial_port *ports); | ||
183 | #endif /* CONFIG_SSB_SERIAL */ | ||
184 | |||
185 | |||
186 | #else /* CONFIG_SSB_DRIVER_EXTIF */ | ||
187 | /* extif disabled */ | ||
188 | |||
189 | struct ssb_extif { | ||
190 | }; | ||
191 | |||
192 | static inline bool ssb_extif_available(struct ssb_extif *extif) | ||
193 | { | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static inline | ||
198 | void ssb_extif_get_clockcontrol(struct ssb_extif *extif, | ||
199 | u32 *plltype, u32 *n, u32 *m) | ||
200 | { | ||
201 | } | ||
202 | |||
203 | #endif /* CONFIG_SSB_DRIVER_EXTIF */ | ||
204 | #endif /* LINUX_SSB_EXTIFCORE_H_ */ | ||
diff --git a/include/linux/ssb/ssb_driver_mips.h b/include/linux/ssb/ssb_driver_mips.h new file mode 100644 index 000000000000..5f44e9740cd2 --- /dev/null +++ b/include/linux/ssb/ssb_driver_mips.h | |||
@@ -0,0 +1,46 @@ | |||
1 | #ifndef LINUX_SSB_MIPSCORE_H_ | ||
2 | #define LINUX_SSB_MIPSCORE_H_ | ||
3 | |||
4 | #ifdef CONFIG_SSB_DRIVER_MIPS | ||
5 | |||
6 | struct ssb_device; | ||
7 | |||
8 | struct ssb_serial_port { | ||
9 | void *regs; | ||
10 | unsigned long clockspeed; | ||
11 | unsigned int irq; | ||
12 | unsigned int baud_base; | ||
13 | unsigned int reg_shift; | ||
14 | }; | ||
15 | |||
16 | |||
17 | struct ssb_mipscore { | ||
18 | struct ssb_device *dev; | ||
19 | |||
20 | int nr_serial_ports; | ||
21 | struct ssb_serial_port serial_ports[4]; | ||
22 | |||
23 | u8 flash_buswidth; | ||
24 | u32 flash_window; | ||
25 | u32 flash_window_size; | ||
26 | }; | ||
27 | |||
28 | extern void ssb_mipscore_init(struct ssb_mipscore *mcore); | ||
29 | extern u32 ssb_cpu_clock(struct ssb_mipscore *mcore); | ||
30 | |||
31 | extern unsigned int ssb_mips_irq(struct ssb_device *dev); | ||
32 | |||
33 | |||
34 | #else /* CONFIG_SSB_DRIVER_MIPS */ | ||
35 | |||
36 | struct ssb_mipscore { | ||
37 | }; | ||
38 | |||
39 | static inline | ||
40 | void ssb_mipscore_init(struct ssb_mipscore *mcore) | ||
41 | { | ||
42 | } | ||
43 | |||
44 | #endif /* CONFIG_SSB_DRIVER_MIPS */ | ||
45 | |||
46 | #endif /* LINUX_SSB_MIPSCORE_H_ */ | ||
diff --git a/include/linux/ssb/ssb_driver_pci.h b/include/linux/ssb/ssb_driver_pci.h new file mode 100644 index 000000000000..9cfffb7b1a27 --- /dev/null +++ b/include/linux/ssb/ssb_driver_pci.h | |||
@@ -0,0 +1,106 @@ | |||
1 | #ifndef LINUX_SSB_PCICORE_H_ | ||
2 | #define LINUX_SSB_PCICORE_H_ | ||
3 | |||
4 | #ifdef CONFIG_SSB_DRIVER_PCICORE | ||
5 | |||
6 | /* PCI core registers. */ | ||
7 | #define SSB_PCICORE_CTL 0x0000 /* PCI Control */ | ||
8 | #define SSB_PCICORE_CTL_RST_OE 0x00000001 /* PCI_RESET Output Enable */ | ||
9 | #define SSB_PCICORE_CTL_RST 0x00000002 /* PCI_RESET driven out to pin */ | ||
10 | #define SSB_PCICORE_CTL_CLK_OE 0x00000004 /* Clock gate Output Enable */ | ||
11 | #define SSB_PCICORE_CTL_CLK 0x00000008 /* Gate for clock driven out to pin */ | ||
12 | #define SSB_PCICORE_ARBCTL 0x0010 /* PCI Arbiter Control */ | ||
13 | #define SSB_PCICORE_ARBCTL_INTERN 0x00000001 /* Use internal arbiter */ | ||
14 | #define SSB_PCICORE_ARBCTL_EXTERN 0x00000002 /* Use external arbiter */ | ||
15 | #define SSB_PCICORE_ARBCTL_PARKID 0x00000006 /* Mask, selects which agent is parked on an idle bus */ | ||
16 | #define SSB_PCICORE_ARBCTL_PARKID_LAST 0x00000000 /* Last requestor */ | ||
17 | #define SSB_PCICORE_ARBCTL_PARKID_4710 0x00000002 /* 4710 */ | ||
18 | #define SSB_PCICORE_ARBCTL_PARKID_EXT0 0x00000004 /* External requestor 0 */ | ||
19 | #define SSB_PCICORE_ARBCTL_PARKID_EXT1 0x00000006 /* External requestor 1 */ | ||
20 | #define SSB_PCICORE_ISTAT 0x0020 /* Interrupt status */ | ||
21 | #define SSB_PCICORE_ISTAT_INTA 0x00000001 /* PCI INTA# */ | ||
22 | #define SSB_PCICORE_ISTAT_INTB 0x00000002 /* PCI INTB# */ | ||
23 | #define SSB_PCICORE_ISTAT_SERR 0x00000004 /* PCI SERR# (write to clear) */ | ||
24 | #define SSB_PCICORE_ISTAT_PERR 0x00000008 /* PCI PERR# (write to clear) */ | ||
25 | #define SSB_PCICORE_ISTAT_PME 0x00000010 /* PCI PME# */ | ||
26 | #define SSB_PCICORE_IMASK 0x0024 /* Interrupt mask */ | ||
27 | #define SSB_PCICORE_IMASK_INTA 0x00000001 /* PCI INTA# */ | ||
28 | #define SSB_PCICORE_IMASK_INTB 0x00000002 /* PCI INTB# */ | ||
29 | #define SSB_PCICORE_IMASK_SERR 0x00000004 /* PCI SERR# */ | ||
30 | #define SSB_PCICORE_IMASK_PERR 0x00000008 /* PCI PERR# */ | ||
31 | #define SSB_PCICORE_IMASK_PME 0x00000010 /* PCI PME# */ | ||
32 | #define SSB_PCICORE_MBOX 0x0028 /* Backplane to PCI Mailbox */ | ||
33 | #define SSB_PCICORE_MBOX_F0_0 0x00000100 /* PCI function 0, INT 0 */ | ||
34 | #define SSB_PCICORE_MBOX_F0_1 0x00000200 /* PCI function 0, INT 1 */ | ||
35 | #define SSB_PCICORE_MBOX_F1_0 0x00000400 /* PCI function 1, INT 0 */ | ||
36 | #define SSB_PCICORE_MBOX_F1_1 0x00000800 /* PCI function 1, INT 1 */ | ||
37 | #define SSB_PCICORE_MBOX_F2_0 0x00001000 /* PCI function 2, INT 0 */ | ||
38 | #define SSB_PCICORE_MBOX_F2_1 0x00002000 /* PCI function 2, INT 1 */ | ||
39 | #define SSB_PCICORE_MBOX_F3_0 0x00004000 /* PCI function 3, INT 0 */ | ||
40 | #define SSB_PCICORE_MBOX_F3_1 0x00008000 /* PCI function 3, INT 1 */ | ||
41 | #define SSB_PCICORE_BCAST_ADDR 0x0050 /* Backplane Broadcast Address */ | ||
42 | #define SSB_PCICORE_BCAST_ADDR_MASK 0x000000FF | ||
43 | #define SSB_PCICORE_BCAST_DATA 0x0054 /* Backplane Broadcast Data */ | ||
44 | #define SSB_PCICORE_GPIO_IN 0x0060 /* rev >= 2 only */ | ||
45 | #define SSB_PCICORE_GPIO_OUT 0x0064 /* rev >= 2 only */ | ||
46 | #define SSB_PCICORE_GPIO_ENABLE 0x0068 /* rev >= 2 only */ | ||
47 | #define SSB_PCICORE_GPIO_CTL 0x006C /* rev >= 2 only */ | ||
48 | #define SSB_PCICORE_SBTOPCI0 0x0100 /* Backplane to PCI translation 0 (sbtopci0) */ | ||
49 | #define SSB_PCICORE_SBTOPCI0_MASK 0xFC000000 | ||
50 | #define SSB_PCICORE_SBTOPCI1 0x0104 /* Backplane to PCI translation 1 (sbtopci1) */ | ||
51 | #define SSB_PCICORE_SBTOPCI1_MASK 0xFC000000 | ||
52 | #define SSB_PCICORE_SBTOPCI2 0x0108 /* Backplane to PCI translation 2 (sbtopci2) */ | ||
53 | #define SSB_PCICORE_SBTOPCI2_MASK 0xC0000000 | ||
54 | |||
55 | /* SBtoPCIx */ | ||
56 | #define SSB_PCICORE_SBTOPCI_MEM 0x00000000 | ||
57 | #define SSB_PCICORE_SBTOPCI_IO 0x00000001 | ||
58 | #define SSB_PCICORE_SBTOPCI_CFG0 0x00000002 | ||
59 | #define SSB_PCICORE_SBTOPCI_CFG1 0x00000003 | ||
60 | #define SSB_PCICORE_SBTOPCI_PREF 0x00000004 /* Prefetch enable */ | ||
61 | #define SSB_PCICORE_SBTOPCI_BURST 0x00000008 /* Burst enable */ | ||
62 | #define SSB_PCICORE_SBTOPCI_MRM 0x00000020 /* Memory Read Multiple */ | ||
63 | #define SSB_PCICORE_SBTOPCI_RC 0x00000030 /* Read Command mask (rev >= 11) */ | ||
64 | #define SSB_PCICORE_SBTOPCI_RC_READ 0x00000000 /* Memory read */ | ||
65 | #define SSB_PCICORE_SBTOPCI_RC_READL 0x00000010 /* Memory read line */ | ||
66 | #define SSB_PCICORE_SBTOPCI_RC_READM 0x00000020 /* Memory read multiple */ | ||
67 | |||
68 | |||
69 | /* PCIcore specific boardflags */ | ||
70 | #define SSB_PCICORE_BFL_NOPCI 0x00000400 /* Board leaves PCI floating */ | ||
71 | |||
72 | |||
73 | struct ssb_pcicore { | ||
74 | struct ssb_device *dev; | ||
75 | u8 setup_done:1; | ||
76 | u8 hostmode:1; | ||
77 | u8 cardbusmode:1; | ||
78 | }; | ||
79 | |||
80 | extern void ssb_pcicore_init(struct ssb_pcicore *pc); | ||
81 | |||
82 | /* Enable IRQ routing for a specific device */ | ||
83 | extern int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, | ||
84 | struct ssb_device *dev); | ||
85 | |||
86 | |||
87 | #else /* CONFIG_SSB_DRIVER_PCICORE */ | ||
88 | |||
89 | |||
90 | struct ssb_pcicore { | ||
91 | }; | ||
92 | |||
93 | static inline | ||
94 | void ssb_pcicore_init(struct ssb_pcicore *pc) | ||
95 | { | ||
96 | } | ||
97 | |||
98 | static inline | ||
99 | int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, | ||
100 | struct ssb_device *dev) | ||
101 | { | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | #endif /* CONFIG_SSB_DRIVER_PCICORE */ | ||
106 | #endif /* LINUX_SSB_PCICORE_H_ */ | ||
diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h new file mode 100644 index 000000000000..47c7c71a5acf --- /dev/null +++ b/include/linux/ssb/ssb_regs.h | |||
@@ -0,0 +1,292 @@ | |||
1 | #ifndef LINUX_SSB_REGS_H_ | ||
2 | #define LINUX_SSB_REGS_H_ | ||
3 | |||
4 | |||
5 | /* SiliconBackplane Address Map. | ||
6 | * All regions may not exist on all chips. | ||
7 | */ | ||
8 | #define SSB_SDRAM_BASE 0x00000000U /* Physical SDRAM */ | ||
9 | #define SSB_PCI_MEM 0x08000000U /* Host Mode sb2pcitranslation0 (64 MB) */ | ||
10 | #define SSB_PCI_CFG 0x0c000000U /* Host Mode sb2pcitranslation1 (64 MB) */ | ||
11 | #define SSB_SDRAM_SWAPPED 0x10000000U /* Byteswapped Physical SDRAM */ | ||
12 | #define SSB_ENUM_BASE 0x18000000U /* Enumeration space base */ | ||
13 | #define SSB_ENUM_LIMIT 0x18010000U /* Enumeration space limit */ | ||
14 | |||
15 | #define SSB_FLASH2 0x1c000000U /* Flash Region 2 (region 1 shadowed here) */ | ||
16 | #define SSB_FLASH2_SZ 0x02000000U /* Size of Flash Region 2 */ | ||
17 | |||
18 | #define SSB_EXTIF_BASE 0x1f000000U /* External Interface region base address */ | ||
19 | #define SSB_FLASH1 0x1fc00000U /* Flash Region 1 */ | ||
20 | #define SSB_FLASH1_SZ 0x00400000U /* Size of Flash Region 1 */ | ||
21 | |||
22 | #define SSB_PCI_DMA 0x40000000U /* Client Mode sb2pcitranslation2 (1 GB) */ | ||
23 | #define SSB_PCI_DMA_SZ 0x40000000U /* Client Mode sb2pcitranslation2 size in bytes */ | ||
24 | #define SSB_PCIE_DMA_L32 0x00000000U /* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), low 32 bits */ | ||
25 | #define SSB_PCIE_DMA_H32 0x80000000U /* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */ | ||
26 | #define SSB_EUART (SSB_EXTIF_BASE + 0x00800000) | ||
27 | #define SSB_LED (SSB_EXTIF_BASE + 0x00900000) | ||
28 | |||
29 | |||
30 | /* Enumeration space constants */ | ||
31 | #define SSB_CORE_SIZE 0x1000 /* Size of a core MMIO area */ | ||
32 | #define SSB_MAX_NR_CORES ((SSB_ENUM_LIMIT - SSB_ENUM_BASE) / SSB_CORE_SIZE) | ||
33 | |||
34 | |||
35 | /* mips address */ | ||
36 | #define SSB_EJTAG 0xff200000 /* MIPS EJTAG space (2M) */ | ||
37 | |||
38 | |||
39 | /* SSB PCI config space registers. */ | ||
40 | #define SSB_PMCSR 0x44 | ||
41 | #define SSB_PE 0x100 | ||
42 | #define SSB_BAR0_WIN 0x80 /* Backplane address space 0 */ | ||
43 | #define SSB_BAR1_WIN 0x84 /* Backplane address space 1 */ | ||
44 | #define SSB_SPROMCTL 0x88 /* SPROM control */ | ||
45 | #define SSB_SPROMCTL_WE 0x10 /* SPROM write enable */ | ||
46 | #define SSB_BAR1_CONTROL 0x8c /* Address space 1 burst control */ | ||
47 | #define SSB_PCI_IRQS 0x90 /* PCI interrupts */ | ||
48 | #define SSB_PCI_IRQMASK 0x94 /* PCI IRQ control and mask (pcirev >= 6 only) */ | ||
49 | #define SSB_BACKPLANE_IRQS 0x98 /* Backplane Interrupts */ | ||
50 | #define SSB_GPIO_IN 0xB0 /* GPIO Input (pcirev >= 3 only) */ | ||
51 | #define SSB_GPIO_OUT 0xB4 /* GPIO Output (pcirev >= 3 only) */ | ||
52 | #define SSB_GPIO_OUT_ENABLE 0xB8 /* GPIO Output Enable/Disable (pcirev >= 3 only) */ | ||
53 | #define SSB_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */ | ||
54 | #define SSB_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */ | ||
55 | #define SSB_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */ | ||
56 | #define SSB_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */ | ||
57 | |||
58 | |||
59 | #define SSB_BAR0_MAX_RETRIES 50 | ||
60 | |||
61 | /* Silicon backplane configuration register definitions */ | ||
62 | #define SSB_IPSFLAG 0x0F08 | ||
63 | #define SSB_IPSFLAG_IRQ1 0x0000003F /* which sbflags get routed to mips interrupt 1 */ | ||
64 | #define SSB_IPSFLAG_IRQ1_SHIFT 0 | ||
65 | #define SSB_IPSFLAG_IRQ2 0x00003F00 /* which sbflags get routed to mips interrupt 2 */ | ||
66 | #define SSB_IPSFLAG_IRQ2_SHIFT 8 | ||
67 | #define SSB_IPSFLAG_IRQ3 0x003F0000 /* which sbflags get routed to mips interrupt 3 */ | ||
68 | #define SSB_IPSFLAG_IRQ3_SHIFT 16 | ||
69 | #define SSB_IPSFLAG_IRQ4 0x3F000000 /* which sbflags get routed to mips interrupt 4 */ | ||
70 | #define SSB_IPSFLAG_IRQ4_SHIFT 24 | ||
71 | #define SSB_TPSFLAG 0x0F18 | ||
72 | #define SSB_TPSFLAG_BPFLAG 0x0000003F /* Backplane flag # */ | ||
73 | #define SSB_TPSFLAG_ALWAYSIRQ 0x00000040 /* IRQ is always sent on the Backplane */ | ||
74 | #define SSB_TMERRLOGA 0x0F48 | ||
75 | #define SSB_TMERRLOG 0x0F50 | ||
76 | #define SSB_ADMATCH3 0x0F60 | ||
77 | #define SSB_ADMATCH2 0x0F68 | ||
78 | #define SSB_ADMATCH1 0x0F70 | ||
79 | #define SSB_IMSTATE 0x0F90 /* SB Initiator Agent State */ | ||
80 | #define SSB_IMSTATE_PC 0x0000000f /* Pipe Count */ | ||
81 | #define SSB_IMSTATE_AP_MASK 0x00000030 /* Arbitration Priority */ | ||
82 | #define SSB_IMSTATE_AP_BOTH 0x00000000 /* Use both timeslices and token */ | ||
83 | #define SSB_IMSTATE_AP_TS 0x00000010 /* Use timeslices only */ | ||
84 | #define SSB_IMSTATE_AP_TK 0x00000020 /* Use token only */ | ||
85 | #define SSB_IMSTATE_AP_RSV 0x00000030 /* Reserved */ | ||
86 | #define SSB_IMSTATE_IBE 0x00020000 /* In Band Error */ | ||
87 | #define SSB_IMSTATE_TO 0x00040000 /* Timeout */ | ||
88 | #define SSB_INTVEC 0x0F94 /* SB Interrupt Mask */ | ||
89 | #define SSB_INTVEC_PCI 0x00000001 /* Enable interrupts for PCI */ | ||
90 | #define SSB_INTVEC_ENET0 0x00000002 /* Enable interrupts for enet 0 */ | ||
91 | #define SSB_INTVEC_ILINE20 0x00000004 /* Enable interrupts for iline20 */ | ||
92 | #define SSB_INTVEC_CODEC 0x00000008 /* Enable interrupts for v90 codec */ | ||
93 | #define SSB_INTVEC_USB 0x00000010 /* Enable interrupts for usb */ | ||
94 | #define SSB_INTVEC_EXTIF 0x00000020 /* Enable interrupts for external i/f */ | ||
95 | #define SSB_INTVEC_ENET1 0x00000040 /* Enable interrupts for enet 1 */ | ||
96 | #define SSB_TMSLOW 0x0F98 /* SB Target State Low */ | ||
97 | #define SSB_TMSLOW_RESET 0x00000001 /* Reset */ | ||
98 | #define SSB_TMSLOW_REJECT_22 0x00000002 /* Reject (Backplane rev 2.2) */ | ||
99 | #define SSB_TMSLOW_REJECT_23 0x00000004 /* Reject (Backplane rev 2.3) */ | ||
100 | #define SSB_TMSLOW_CLOCK 0x00010000 /* Clock Enable */ | ||
101 | #define SSB_TMSLOW_FGC 0x00020000 /* Force Gated Clocks On */ | ||
102 | #define SSB_TMSLOW_PE 0x40000000 /* Power Management Enable */ | ||
103 | #define SSB_TMSLOW_BE 0x80000000 /* BIST Enable */ | ||
104 | #define SSB_TMSHIGH 0x0F9C /* SB Target State High */ | ||
105 | #define SSB_TMSHIGH_SERR 0x00000001 /* S-error */ | ||
106 | #define SSB_TMSHIGH_INT 0x00000002 /* Interrupt */ | ||
107 | #define SSB_TMSHIGH_BUSY 0x00000004 /* Busy */ | ||
108 | #define SSB_TMSHIGH_TO 0x00000020 /* Timeout. Backplane rev >= 2.3 only */ | ||
109 | #define SSB_TMSHIGH_COREFL 0x1FFF0000 /* Core specific flags */ | ||
110 | #define SSB_TMSHIGH_COREFL_SHIFT 16 | ||
111 | #define SSB_TMSHIGH_DMA64 0x10000000 /* 64bit DMA supported */ | ||
112 | #define SSB_TMSHIGH_GCR 0x20000000 /* Gated Clock Request */ | ||
113 | #define SSB_TMSHIGH_BISTF 0x40000000 /* BIST Failed */ | ||
114 | #define SSB_TMSHIGH_BISTD 0x80000000 /* BIST Done */ | ||
115 | #define SSB_BWA0 0x0FA0 | ||
116 | #define SSB_IMCFGLO 0x0FA8 | ||
117 | #define SSB_IMCFGLO_SERTO 0x00000007 /* Service timeout */ | ||
118 | #define SSB_IMCFGLO_REQTO 0x00000070 /* Request timeout */ | ||
119 | #define SSB_IMCFGLO_REQTO_SHIFT 4 | ||
120 | #define SSB_IMCFGLO_CONNID 0x00FF0000 /* Connection ID */ | ||
121 | #define SSB_IMCFGLO_CONNID_SHIFT 16 | ||
122 | #define SSB_IMCFGHI 0x0FAC | ||
123 | #define SSB_ADMATCH0 0x0FB0 | ||
124 | #define SSB_TMCFGLO 0x0FB8 | ||
125 | #define SSB_TMCFGHI 0x0FBC | ||
126 | #define SSB_BCONFIG 0x0FC0 | ||
127 | #define SSB_BSTATE 0x0FC8 | ||
128 | #define SSB_ACTCFG 0x0FD8 | ||
129 | #define SSB_FLAGST 0x0FE8 | ||
130 | #define SSB_IDLOW 0x0FF8 | ||
131 | #define SSB_IDLOW_CFGSP 0x00000003 /* Config Space */ | ||
132 | #define SSB_IDLOW_ADDRNGE 0x00000038 /* Address Ranges supported */ | ||
133 | #define SSB_IDLOW_ADDRNGE_SHIFT 3 | ||
134 | #define SSB_IDLOW_SYNC 0x00000040 | ||
135 | #define SSB_IDLOW_INITIATOR 0x00000080 | ||
136 | #define SSB_IDLOW_MIBL 0x00000F00 /* Minimum Backplane latency */ | ||
137 | #define SSB_IDLOW_MIBL_SHIFT 8 | ||
138 | #define SSB_IDLOW_MABL 0x0000F000 /* Maximum Backplane latency */ | ||
139 | #define SSB_IDLOW_MABL_SHIFT 12 | ||
140 | #define SSB_IDLOW_TIF 0x00010000 /* This Initiator is first */ | ||
141 | #define SSB_IDLOW_CCW 0x000C0000 /* Cycle counter width */ | ||
142 | #define SSB_IDLOW_CCW_SHIFT 18 | ||
143 | #define SSB_IDLOW_TPT 0x00F00000 /* Target ports */ | ||
144 | #define SSB_IDLOW_TPT_SHIFT 20 | ||
145 | #define SSB_IDLOW_INITP 0x0F000000 /* Initiator ports */ | ||
146 | #define SSB_IDLOW_INITP_SHIFT 24 | ||
147 | #define SSB_IDLOW_SSBREV 0xF0000000 /* Sonics Backplane Revision code */ | ||
148 | #define SSB_IDLOW_SSBREV_22 0x00000000 /* <= 2.2 */ | ||
149 | #define SSB_IDLOW_SSBREV_23 0x10000000 /* 2.3 */ | ||
150 | #define SSB_IDHIGH 0x0FFC /* SB Identification High */ | ||
151 | #define SSB_IDHIGH_RCLO 0x0000000F /* Revision Code (low part) */ | ||
152 | #define SSB_IDHIGH_CC 0x00008FF0 /* Core Code */ | ||
153 | #define SSB_IDHIGH_CC_SHIFT 4 | ||
154 | #define SSB_IDHIGH_RCHI 0x00007000 /* Revision Code (high part) */ | ||
155 | #define SSB_IDHIGH_RCHI_SHIFT 8 /* yes, shift 8 is right */ | ||
156 | #define SSB_IDHIGH_VC 0xFFFF0000 /* Vendor Code */ | ||
157 | #define SSB_IDHIGH_VC_SHIFT 16 | ||
158 | |||
159 | /* SPROM shadow area. If not otherwise noted, fields are | ||
160 | * two bytes wide. Note that the SPROM can _only_ be read | ||
161 | * in two-byte quantinies. | ||
162 | */ | ||
163 | #define SSB_SPROMSIZE_WORDS 64 | ||
164 | #define SSB_SPROMSIZE_BYTES (SSB_SPROMSIZE_WORDS * sizeof(u16)) | ||
165 | #define SSB_SPROM_BASE 0x1000 | ||
166 | #define SSB_SPROM_REVISION 0x107E | ||
167 | #define SSB_SPROM_REVISION_REV 0x00FF /* SPROM Revision number */ | ||
168 | #define SSB_SPROM_REVISION_CRC 0xFF00 /* SPROM CRC8 value */ | ||
169 | #define SSB_SPROM_REVISION_CRC_SHIFT 8 | ||
170 | /* SPROM Revision 1 */ | ||
171 | #define SSB_SPROM1_SPID 0x1004 /* Subsystem Product ID for PCI */ | ||
172 | #define SSB_SPROM1_SVID 0x1006 /* Subsystem Vendor ID for PCI */ | ||
173 | #define SSB_SPROM1_PID 0x1008 /* Product ID for PCI */ | ||
174 | #define SSB_SPROM1_IL0MAC 0x1048 /* 6 bytes MAC address for 802.11b/g */ | ||
175 | #define SSB_SPROM1_ET0MAC 0x104E /* 6 bytes MAC address for Ethernet */ | ||
176 | #define SSB_SPROM1_ET1MAC 0x1054 /* 6 bytes MAC address for 802.11a */ | ||
177 | #define SSB_SPROM1_ETHPHY 0x105A /* Ethernet PHY settings */ | ||
178 | #define SSB_SPROM1_ETHPHY_ET0A 0x001F /* MII Address for enet0 */ | ||
179 | #define SSB_SPROM1_ETHPHY_ET1A 0x03E0 /* MII Address for enet1 */ | ||
180 | #define SSB_SPROM1_ETHPHY_ET1A_SHIFT 5 | ||
181 | #define SSB_SPROM1_ETHPHY_ET0M (1<<14) /* MDIO for enet0 */ | ||
182 | #define SSB_SPROM1_ETHPHY_ET1M (1<<15) /* MDIO for enet1 */ | ||
183 | #define SSB_SPROM1_BINF 0x105C /* Board info */ | ||
184 | #define SSB_SPROM1_BINF_BREV 0x00FF /* Board Revision */ | ||
185 | #define SSB_SPROM1_BINF_CCODE 0x0F00 /* Country Code */ | ||
186 | #define SSB_SPROM1_BINF_CCODE_SHIFT 8 | ||
187 | #define SSB_SPROM1_BINF_ANTA 0x3000 /* Available A-PHY antennas */ | ||
188 | #define SSB_SPROM1_BINF_ANTA_SHIFT 12 | ||
189 | #define SSB_SPROM1_BINF_ANTBG 0xC000 /* Available B-PHY antennas */ | ||
190 | #define SSB_SPROM1_BINF_ANTBG_SHIFT 14 | ||
191 | #define SSB_SPROM1_PA0B0 0x105E | ||
192 | #define SSB_SPROM1_PA0B1 0x1060 | ||
193 | #define SSB_SPROM1_PA0B2 0x1062 | ||
194 | #define SSB_SPROM1_GPIOA 0x1064 /* General Purpose IO pins 0 and 1 */ | ||
195 | #define SSB_SPROM1_GPIOA_P0 0x00FF /* Pin 0 */ | ||
196 | #define SSB_SPROM1_GPIOA_P1 0xFF00 /* Pin 1 */ | ||
197 | #define SSB_SPROM1_GPIOA_P1_SHIFT 8 | ||
198 | #define SSB_SPROM1_GPIOB 0x1066 /* General Purpuse IO pins 2 and 3 */ | ||
199 | #define SSB_SPROM1_GPIOB_P2 0x00FF /* Pin 2 */ | ||
200 | #define SSB_SPROM1_GPIOB_P3 0xFF00 /* Pin 3 */ | ||
201 | #define SSB_SPROM1_GPIOB_P3_SHIFT 8 | ||
202 | #define SSB_SPROM1_MAXPWR 0x1068 /* Power Amplifier Max Power */ | ||
203 | #define SSB_SPROM1_MAXPWR_BG 0x00FF /* B-PHY and G-PHY (in dBm Q5.2) */ | ||
204 | #define SSB_SPROM1_MAXPWR_A 0xFF00 /* A-PHY (in dBm Q5.2) */ | ||
205 | #define SSB_SPROM1_MAXPWR_A_SHIFT 8 | ||
206 | #define SSB_SPROM1_PA1B0 0x106A | ||
207 | #define SSB_SPROM1_PA1B1 0x106C | ||
208 | #define SSB_SPROM1_PA1B2 0x106E | ||
209 | #define SSB_SPROM1_ITSSI 0x1070 /* Idle TSSI Target */ | ||
210 | #define SSB_SPROM1_ITSSI_BG 0x00FF /* B-PHY and G-PHY*/ | ||
211 | #define SSB_SPROM1_ITSSI_A 0xFF00 /* A-PHY */ | ||
212 | #define SSB_SPROM1_ITSSI_A_SHIFT 8 | ||
213 | #define SSB_SPROM1_BFLLO 0x1072 /* Boardflags (low 16 bits) */ | ||
214 | #define SSB_SPROM1_AGAIN 0x1074 /* Antenna Gain (in dBm Q5.2) */ | ||
215 | #define SSB_SPROM1_AGAIN_A 0x00FF /* A-PHY */ | ||
216 | #define SSB_SPROM1_AGAIN_BG 0xFF00 /* B-PHY and G-PHY */ | ||
217 | #define SSB_SPROM1_AGAIN_BG_SHIFT 8 | ||
218 | #define SSB_SPROM1_OEM 0x1076 /* 8 bytes OEM string (rev 1 only) */ | ||
219 | /* SPROM Revision 2 (inherits from rev 1) */ | ||
220 | #define SSB_SPROM2_BFLHI 0x1038 /* Boardflags (high 16 bits) */ | ||
221 | #define SSB_SPROM2_MAXP_A 0x103A /* A-PHY Max Power */ | ||
222 | #define SSB_SPROM2_MAXP_A_HI 0x00FF /* Max Power High */ | ||
223 | #define SSB_SPROM2_MAXP_A_LO 0xFF00 /* Max Power Low */ | ||
224 | #define SSB_SPROM2_MAXP_A_LO_SHIFT 8 | ||
225 | #define SSB_SPROM2_PA1LOB0 0x103C /* A-PHY PowerAmplifier Low Settings */ | ||
226 | #define SSB_SPROM2_PA1LOB1 0x103E /* A-PHY PowerAmplifier Low Settings */ | ||
227 | #define SSB_SPROM2_PA1LOB2 0x1040 /* A-PHY PowerAmplifier Low Settings */ | ||
228 | #define SSB_SPROM2_PA1HIB0 0x1042 /* A-PHY PowerAmplifier High Settings */ | ||
229 | #define SSB_SPROM2_PA1HIB1 0x1044 /* A-PHY PowerAmplifier High Settings */ | ||
230 | #define SSB_SPROM2_PA1HIB2 0x1046 /* A-PHY PowerAmplifier High Settings */ | ||
231 | #define SSB_SPROM2_OPO 0x1078 /* OFDM Power Offset from CCK Level */ | ||
232 | #define SSB_SPROM2_OPO_VALUE 0x00FF | ||
233 | #define SSB_SPROM2_OPO_UNUSED 0xFF00 | ||
234 | #define SSB_SPROM2_CCODE 0x107C /* Two char Country Code */ | ||
235 | /* SPROM Revision 3 (inherits from rev 2) */ | ||
236 | #define SSB_SPROM3_OFDMAPO 0x102C /* A-PHY OFDM Mid Power Offset (4 bytes, BigEndian) */ | ||
237 | #define SSB_SPROM3_OFDMALPO 0x1030 /* A-PHY OFDM Low Power Offset (4 bytes, BigEndian) */ | ||
238 | #define SSB_SPROM3_OFDMAHPO 0x1034 /* A-PHY OFDM High Power Offset (4 bytes, BigEndian) */ | ||
239 | #define SSB_SPROM3_GPIOLDC 0x1042 /* GPIO LED Powersave Duty Cycle (4 bytes, BigEndian) */ | ||
240 | #define SSB_SPROM3_GPIOLDC_OFF 0x0000FF00 /* Off Count */ | ||
241 | #define SSB_SPROM3_GPIOLDC_OFF_SHIFT 8 | ||
242 | #define SSB_SPROM3_GPIOLDC_ON 0x00FF0000 /* On Count */ | ||
243 | #define SSB_SPROM3_GPIOLDC_ON_SHIFT 16 | ||
244 | #define SSB_SPROM3_CCKPO 0x1078 /* CCK Power Offset */ | ||
245 | #define SSB_SPROM3_CCKPO_1M 0x000F /* 1M Rate PO */ | ||
246 | #define SSB_SPROM3_CCKPO_2M 0x00F0 /* 2M Rate PO */ | ||
247 | #define SSB_SPROM3_CCKPO_2M_SHIFT 4 | ||
248 | #define SSB_SPROM3_CCKPO_55M 0x0F00 /* 5.5M Rate PO */ | ||
249 | #define SSB_SPROM3_CCKPO_55M_SHIFT 8 | ||
250 | #define SSB_SPROM3_CCKPO_11M 0xF000 /* 11M Rate PO */ | ||
251 | #define SSB_SPROM3_CCKPO_11M_SHIFT 12 | ||
252 | #define SSB_SPROM3_OFDMGPO 0x107A /* G-PHY OFDM Power Offset (4 bytes, BigEndian) */ | ||
253 | |||
254 | /* Values for SSB_SPROM1_BINF_CCODE */ | ||
255 | enum { | ||
256 | SSB_SPROM1CCODE_WORLD = 0, | ||
257 | SSB_SPROM1CCODE_THAILAND, | ||
258 | SSB_SPROM1CCODE_ISRAEL, | ||
259 | SSB_SPROM1CCODE_JORDAN, | ||
260 | SSB_SPROM1CCODE_CHINA, | ||
261 | SSB_SPROM1CCODE_JAPAN, | ||
262 | SSB_SPROM1CCODE_USA_CANADA_ANZ, | ||
263 | SSB_SPROM1CCODE_EUROPE, | ||
264 | SSB_SPROM1CCODE_USA_LOW, | ||
265 | SSB_SPROM1CCODE_JAPAN_HIGH, | ||
266 | SSB_SPROM1CCODE_ALL, | ||
267 | SSB_SPROM1CCODE_NONE, | ||
268 | }; | ||
269 | |||
270 | /* Address-Match values and masks (SSB_ADMATCHxxx) */ | ||
271 | #define SSB_ADM_TYPE 0x00000003 /* Address type */ | ||
272 | #define SSB_ADM_TYPE0 0 | ||
273 | #define SSB_ADM_TYPE1 1 | ||
274 | #define SSB_ADM_TYPE2 2 | ||
275 | #define SSB_ADM_AD64 0x00000004 | ||
276 | #define SSB_ADM_SZ0 0x000000F8 /* Type0 size */ | ||
277 | #define SSB_ADM_SZ0_SHIFT 3 | ||
278 | #define SSB_ADM_SZ1 0x000001F8 /* Type1 size */ | ||
279 | #define SSB_ADM_SZ1_SHIFT 3 | ||
280 | #define SSB_ADM_SZ2 0x000001F8 /* Type2 size */ | ||
281 | #define SSB_ADM_SZ2_SHIFT 3 | ||
282 | #define SSB_ADM_EN 0x00000400 /* Enable */ | ||
283 | #define SSB_ADM_NEG 0x00000800 /* Negative decode */ | ||
284 | #define SSB_ADM_BASE0 0xFFFFFF00 /* Type0 base address */ | ||
285 | #define SSB_ADM_BASE0_SHIFT 8 | ||
286 | #define SSB_ADM_BASE1 0xFFFFF000 /* Type1 base address for the core */ | ||
287 | #define SSB_ADM_BASE1_SHIFT 12 | ||
288 | #define SSB_ADM_BASE2 0xFFFF0000 /* Type2 base address for the core */ | ||
289 | #define SSB_ADM_BASE2_SHIFT 16 | ||
290 | |||
291 | |||
292 | #endif /* LINUX_SSB_REGS_H_ */ | ||
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 8a09021d8c59..895ba3ac6208 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
@@ -484,6 +484,21 @@ static int do_parisc_entry(const char *filename, struct parisc_device_id *id, | |||
484 | return 1; | 484 | return 1; |
485 | } | 485 | } |
486 | 486 | ||
487 | /* Looks like: ssb:vNidNrevN. */ | ||
488 | static int do_ssb_entry(const char *filename, | ||
489 | struct ssb_device_id *id, char *alias) | ||
490 | { | ||
491 | id->vendor = TO_NATIVE(id->vendor); | ||
492 | id->coreid = TO_NATIVE(id->coreid); | ||
493 | id->revision = TO_NATIVE(id->revision); | ||
494 | |||
495 | strcpy(alias, "ssb:"); | ||
496 | ADD(alias, "v", id->vendor != SSB_ANY_VENDOR, id->vendor); | ||
497 | ADD(alias, "id", id->coreid != SSB_ANY_ID, id->coreid); | ||
498 | ADD(alias, "rev", id->revision != SSB_ANY_REV, id->revision); | ||
499 | return 1; | ||
500 | } | ||
501 | |||
487 | /* Ignore any prefix, eg. v850 prepends _ */ | 502 | /* Ignore any prefix, eg. v850 prepends _ */ |
488 | static inline int sym_is(const char *symbol, const char *name) | 503 | static inline int sym_is(const char *symbol, const char *name) |
489 | { | 504 | { |
@@ -599,6 +614,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
599 | do_table(symval, sym->st_size, | 614 | do_table(symval, sym->st_size, |
600 | sizeof(struct parisc_device_id), "parisc", | 615 | sizeof(struct parisc_device_id), "parisc", |
601 | do_parisc_entry, mod); | 616 | do_parisc_entry, mod); |
617 | else if (sym_is(symname, "__mod_ssb_device_table")) | ||
618 | do_table(symval, sym->st_size, | ||
619 | sizeof(struct ssb_device_id), "ssb", | ||
620 | do_ssb_entry, mod); | ||
602 | } | 621 | } |
603 | 622 | ||
604 | /* Now add out buffered information to the generated C source */ | 623 | /* Now add out buffered information to the generated C source */ |