aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/ssb/ssb.h
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2007-09-18 15:12:50 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:51:36 -0400
commit61e115a56d1aafd6e6a8a9fee8ac099a6128ac7b (patch)
treeadd97bf6a1207a4caea3a86cf13495ad3dc477de /include/linux/ssb/ssb.h
parent5ee3afba88f5a79d0bff07ddd87af45919259f91 (diff)
[SSB]: add Sonics Silicon Backplane bus support
SSB is an SoC bus used in a number of embedded devices. The most well-known of these devices is probably the Linksys WRT54G, but there are others as well. The bus is also used internally on the BCM43xx and BCM44xx devices from Broadcom. This patch also includes support for SSB ID tables in modules, so that SSB drivers can be loaded automatically. Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/ssb/ssb.h')
-rw-r--r--include/linux/ssb/ssb.h424
1 files changed, 424 insertions, 0 deletions
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
14struct pcmcia_device;
15struct ssb_bus;
16struct ssb_driver;
17
18
19struct 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
54struct 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
68struct 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
81struct ssb_sprom_r4 {
82 /* TODO */
83};
84
85struct 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. */
102struct ssb_boardinfo {
103 u16 vendor;
104 u16 type;
105 u16 rev;
106};
107
108
109struct ssb_device;
110/* Lowlevel read/write operations on the device MMIO.
111 * Internal, don't use that outside of ssb. */
112struct 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 */
159struct __ssb_dev_wrapper {
160 struct device dev;
161 struct ssb_device *sdev;
162};
163
164struct 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. */
182static inline
183struct 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 */
191static inline
192void ssb_set_drvdata(struct ssb_device *dev, void *data)
193{
194 dev->drvdata = data;
195}
196static inline
197void * 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) */
203void ssb_set_devtypedata(struct ssb_device *dev, void *data);
204static inline
205void * ssb_get_devtypedata(struct ssb_device *dev)
206{
207 return dev->devtypedata;
208}
209
210
211struct 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
225extern int __ssb_driver_register(struct ssb_driver *drv, struct module *owner);
226static inline int ssb_driver_register(struct ssb_driver *drv)
227{
228 return __ssb_driver_register(drv, THIS_MODULE);
229}
230extern void ssb_driver_unregister(struct ssb_driver *drv);
231
232
233
234
235enum 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
263struct 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. */
332struct ssb_init_invariants {
333 struct ssb_boardinfo boardinfo;
334 struct ssb_sprom sprom;
335};
336/* Type of function to fetch the invariants. */
337typedef 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. */
344extern 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
348extern 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
352extern 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
357extern void ssb_bus_unregister(struct ssb_bus *bus);
358
359extern u32 ssb_clockspeed(struct ssb_bus *bus);
360
361/* Is the device enabled in hardware? */
362int 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. */
365void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags);
366/* Disable a device in hardware and pass SSB_TMSLOW flags (if any). */
367void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags);
368
369
370/* Device MMIO register read/write functions. */
371static inline u16 ssb_read16(struct ssb_device *dev, u16 offset)
372{
373 return dev->ops->read16(dev, offset);
374}
375static inline u32 ssb_read32(struct ssb_device *dev, u16 offset)
376{
377 return dev->ops->read32(dev, offset);
378}
379static inline void ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
380{
381 dev->ops->write16(dev, offset, value);
382}
383static 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. */
391extern u32 ssb_dma_translation(struct ssb_device *dev);
392#define SSB_DMA_TRANSLATION_MASK 0xC0000000
393#define SSB_DMA_TRANSLATION_SHIFT 30
394
395extern int ssb_dma_set_mask(struct ssb_device *ssb_dev, u64 mask);
396
397
398#ifdef CONFIG_SSB_PCIHOST
399/* PCI-host wrapper driver */
400extern int ssb_pcihost_register(struct pci_driver *driver);
401static 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. */
412extern 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. */
416extern int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl);
417
418
419/* Various helper functions */
420extern u32 ssb_admatch_base(u32 adm);
421extern u32 ssb_admatch_size(u32 adm);
422
423
424#endif /* LINUX_SSB_H_ */