ssb: sync with wireless-2.6

SVN-Revision: 18022
This commit is contained in:
Felix Fietkau 2009-10-11 00:36:06 +00:00
parent 215ccb66e6
commit 0ba61fe414
4 changed files with 4338 additions and 0 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,558 @@
--- a/drivers/ssb/driver_chipcommon_pmu.c
+++ b/drivers/ssb/driver_chipcommon_pmu.c
@@ -28,6 +28,21 @@ static void ssb_chipco_pll_write(struct
chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, value);
}
+static void ssb_chipco_regctl_maskset(struct ssb_chipcommon *cc,
+ u32 offset, u32 mask, u32 set)
+{
+ u32 value;
+
+ chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR);
+ chipco_write32(cc, SSB_CHIPCO_REGCTL_ADDR, offset);
+ chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR);
+ value = chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA);
+ value &= mask;
+ value |= set;
+ chipco_write32(cc, SSB_CHIPCO_REGCTL_DATA, value);
+ chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA);
+}
+
struct pmu0_plltab_entry {
u16 freq; /* Crystal frequency in kHz.*/
u8 xf; /* Crystal frequency value for PMU control */
@@ -506,3 +521,82 @@ void ssb_pmu_init(struct ssb_chipcommon
ssb_pmu_pll_init(cc);
ssb_pmu_resources_init(cc);
}
+
+void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
+ enum ssb_pmu_ldo_volt_id id, u32 voltage)
+{
+ struct ssb_bus *bus = cc->dev->bus;
+ u32 addr, shift, mask;
+
+ switch (bus->chip_id) {
+ case 0x4328:
+ case 0x5354:
+ switch (id) {
+ case LDO_VOLT1:
+ addr = 2;
+ shift = 25;
+ mask = 0xF;
+ break;
+ case LDO_VOLT2:
+ addr = 3;
+ shift = 1;
+ mask = 0xF;
+ break;
+ case LDO_VOLT3:
+ addr = 3;
+ shift = 9;
+ mask = 0xF;
+ break;
+ case LDO_PAREF:
+ addr = 3;
+ shift = 17;
+ mask = 0x3F;
+ break;
+ default:
+ SSB_WARN_ON(1);
+ return;
+ }
+ break;
+ case 0x4312:
+ if (SSB_WARN_ON(id != LDO_PAREF))
+ return;
+ addr = 0;
+ shift = 21;
+ mask = 0x3F;
+ break;
+ default:
+ return;
+ }
+
+ ssb_chipco_regctl_maskset(cc, addr, ~(mask << shift),
+ (voltage & mask) << shift);
+}
+
+void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on)
+{
+ struct ssb_bus *bus = cc->dev->bus;
+ int ldo;
+
+ switch (bus->chip_id) {
+ case 0x4312:
+ ldo = SSB_PMURES_4312_PA_REF_LDO;
+ break;
+ case 0x4328:
+ ldo = SSB_PMURES_4328_PA_REF_LDO;
+ break;
+ case 0x5354:
+ ldo = SSB_PMURES_5354_PA_REF_LDO;
+ break;
+ default:
+ return;
+ }
+
+ if (on)
+ chipco_set32(cc, SSB_CHIPCO_PMU_MINRES_MSK, 1 << ldo);
+ else
+ chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, ~(1 << ldo));
+ chipco_read32(cc, SSB_CHIPCO_PMU_MINRES_MSK); //SPEC FIXME found via mmiotrace - dummy read?
+}
+
+EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage);
+EXPORT_SYMBOL(ssb_pmu_set_ldo_paref);
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -472,6 +472,8 @@ static int ssb_devices_register(struct s
case SSB_BUSTYPE_SSB:
dev->dma_mask = &dev->coherent_dma_mask;
break;
+ default:
+ break;
}
sdev->dev = dev;
@@ -1358,8 +1360,10 @@ static int __init ssb_modinit(void)
ssb_buses_lock();
err = ssb_attach_queued_buses();
ssb_buses_unlock();
- if (err)
+ if (err) {
bus_unregister(&ssb_bustype);
+ goto out;
+ }
err = b43_pci_ssb_bridge_init();
if (err) {
@@ -1375,7 +1379,7 @@ static int __init ssb_modinit(void)
/* don't fail SSB init because of this */
err = 0;
}
-
+out:
return err;
}
/* ssb must be initialized after PCI but before the ssb drivers.
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -169,8 +169,14 @@ err_pci:
/* Get the word-offset for a SSB_SPROM_XXX define. */
#define SPOFF(offset) (((offset) - SSB_SPROM_BASE) / sizeof(u16))
/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
-#define SPEX(_outvar, _offset, _mask, _shift) \
+#define SPEX16(_outvar, _offset, _mask, _shift) \
out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
+#define SPEX32(_outvar, _offset, _mask, _shift) \
+ out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \
+ in[SPOFF(_offset)]) & (_mask)) >> (_shift))
+#define SPEX(_outvar, _offset, _mask, _shift) \
+ SPEX16(_outvar, _offset, _mask, _shift)
+
static inline u8 ssb_crc8(u8 crc, u8 data)
{
@@ -474,12 +480,14 @@ static void sprom_extract_r8(struct ssb_
/* extract the MAC address */
for (i = 0; i < 3; i++) {
- v = in[SPOFF(SSB_SPROM1_IL0MAC) + i];
+ v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
}
SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
+ SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
+ SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
SSB_SPROM8_ANTAVAIL_A_SHIFT);
SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
@@ -490,12 +498,55 @@ static void sprom_extract_r8(struct ssb_
SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
SSB_SPROM8_ITSSI_A_SHIFT);
+ SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
+ SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
+ SSB_SPROM8_MAXP_AL_SHIFT);
SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
SSB_SPROM8_GPIOA_P1_SHIFT);
SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
SSB_SPROM8_GPIOB_P3_SHIFT);
+ SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
+ SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
+ SSB_SPROM8_TRI5G_SHIFT);
+ SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
+ SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
+ SSB_SPROM8_TRI5GH_SHIFT);
+ SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
+ SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
+ SSB_SPROM8_RXPO5G_SHIFT);
+ SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
+ SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
+ SSB_SPROM8_RSSISMC2G_SHIFT);
+ SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
+ SSB_SPROM8_RSSISAV2G_SHIFT);
+ SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
+ SSB_SPROM8_BXA2G_SHIFT);
+ SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
+ SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
+ SSB_SPROM8_RSSISMC5G_SHIFT);
+ SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
+ SSB_SPROM8_RSSISAV5G_SHIFT);
+ SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
+ SSB_SPROM8_BXA5G_SHIFT);
+ SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
+ SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
+ SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
+ SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
+ SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
+ SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
+ SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
+ SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
+ SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
+ SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
+ SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
+ SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
+ SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
+ SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
+ SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
+ SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
+ SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
/* Extract the antenna gain values. */
SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01,
@@ -549,6 +600,7 @@ static int sprom_extract(struct ssb_bus
ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
" revision %d detected. Will extract"
" v1\n", out->revision);
+ out->revision = 1;
sprom_extract_r123(out, in);
}
}
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -583,7 +583,7 @@ static int ssb_pcmcia_sprom_write_all(st
ssb_printk(".");
err = ssb_pcmcia_sprom_write(bus, i, sprom[i]);
if (err) {
- ssb_printk("\n" KERN_NOTICE PFX
+ ssb_printk(KERN_NOTICE PFX
"Failed to write to SPROM.\n");
failed = 1;
break;
@@ -591,7 +591,7 @@ static int ssb_pcmcia_sprom_write_all(st
}
err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS);
if (err) {
- ssb_printk("\n" KERN_NOTICE PFX
+ ssb_printk(KERN_NOTICE PFX
"Could not disable SPROM write access.\n");
failed = 1;
}
@@ -678,7 +678,8 @@ int ssb_pcmcia_get_invariants(struct ssb
sprom->board_rev = tuple.TupleData[1];
break;
case SSB_PCMCIA_CIS_PA:
- GOTO_ERROR_ON(tuple.TupleDataLen != 9,
+ GOTO_ERROR_ON((tuple.TupleDataLen != 9) &&
+ (tuple.TupleDataLen != 10),
"pa tpl size");
sprom->pa0b0 = tuple.TupleData[1] |
((u16)tuple.TupleData[2] << 8);
@@ -718,7 +719,8 @@ int ssb_pcmcia_get_invariants(struct ssb
sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1];
break;
case SSB_PCMCIA_CIS_BFLAGS:
- GOTO_ERROR_ON(tuple.TupleDataLen != 3,
+ GOTO_ERROR_ON((tuple.TupleDataLen != 3) &&
+ (tuple.TupleDataLen != 5),
"bfl tpl size");
sprom->boardflags_lo = tuple.TupleData[1] |
((u16)tuple.TupleData[2] << 8);
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -27,24 +27,54 @@ struct ssb_sprom {
u8 et1mdcport; /* MDIO for enet1 */
u8 board_rev; /* Board revision number from SPROM. */
u8 country_code; /* Country Code */
- u8 ant_available_a; /* A-PHY antenna available bits (up to 4) */
- u8 ant_available_bg; /* B/G-PHY antenna available bits (up to 4) */
+ u8 ant_available_a; /* 2GHz antenna available bits (up to 4) */
+ u8 ant_available_bg; /* 5GHz antenna available bits (up to 4) */
u16 pa0b0;
u16 pa0b1;
u16 pa0b2;
u16 pa1b0;
u16 pa1b1;
u16 pa1b2;
+ u16 pa1lob0;
+ u16 pa1lob1;
+ u16 pa1lob2;
+ u16 pa1hib0;
+ u16 pa1hib1;
+ u16 pa1hib2;
u8 gpio0; /* GPIO pin 0 */
u8 gpio1; /* GPIO pin 1 */
u8 gpio2; /* GPIO pin 2 */
u8 gpio3; /* GPIO pin 3 */
- u16 maxpwr_a; /* A-PHY Amplifier Max Power (in dBm Q5.2) */
- u16 maxpwr_bg; /* B/G-PHY Amplifier Max Power (in dBm Q5.2) */
+ u16 maxpwr_bg; /* 2.4GHz Amplifier Max Power (in dBm Q5.2) */
+ u16 maxpwr_al; /* 5.2GHz Amplifier Max Power (in dBm Q5.2) */
+ u16 maxpwr_a; /* 5.3GHz Amplifier Max Power (in dBm Q5.2) */
+ u16 maxpwr_ah; /* 5.8GHz Amplifier Max Power (in dBm Q5.2) */
u8 itssi_a; /* Idle TSSI Target for A-PHY */
u8 itssi_bg; /* Idle TSSI Target for B/G-PHY */
- u16 boardflags_lo; /* Boardflags (low 16 bits) */
- u16 boardflags_hi; /* Boardflags (high 16 bits) */
+ u8 tri2g; /* 2.4GHz TX isolation */
+ u8 tri5gl; /* 5.2GHz TX isolation */
+ u8 tri5g; /* 5.3GHz TX isolation */
+ u8 tri5gh; /* 5.8GHz TX isolation */
+ u8 rxpo2g; /* 2GHz RX power offset */
+ u8 rxpo5g; /* 5GHz RX power offset */
+ u8 rssisav2g; /* 2GHz RSSI params */
+ u8 rssismc2g;
+ u8 rssismf2g;
+ u8 bxa2g; /* 2GHz BX arch */
+ u8 rssisav5g; /* 5GHz RSSI params */
+ u8 rssismc5g;
+ u8 rssismf5g;
+ u8 bxa5g; /* 5GHz BX arch */
+ u16 cck2gpo; /* CCK power offset */
+ u32 ofdm2gpo; /* 2.4GHz OFDM power offset */
+ u32 ofdm5glpo; /* 5.2GHz OFDM power offset */
+ u32 ofdm5gpo; /* 5.3GHz OFDM power offset */
+ u32 ofdm5ghpo; /* 5.8GHz OFDM power offset */
+ u16 boardflags_lo; /* Board flags (bits 0-15) */
+ u16 boardflags_hi; /* Board flags (bits 16-31) */
+ u16 boardflags2_lo; /* Board flags (bits 32-47) */
+ u16 boardflags2_hi; /* Board flags (bits 48-63) */
+ /* TODO store board flags in a single u64 */
/* Antenna gain values for up to 4 antennas
* on each band. Values in dBm/4 (Q5.2). Negative gain means the
@@ -58,7 +88,7 @@ struct ssb_sprom {
} ghz5; /* 5GHz band */
} antenna_gain;
- /* TODO - add any parameters needed from rev 2, 3, or 4 SPROMs */
+ /* TODO - add any parameters needed from rev 2, 3, 4, 5 or 8 SPROMs */
};
/* Information about the PCB the circuitry is soldered on. */
@@ -208,6 +238,7 @@ enum ssb_bustype {
SSB_BUSTYPE_SSB, /* This SSB bus is the system bus */
SSB_BUSTYPE_PCI, /* SSB is connected to PCI bus */
SSB_BUSTYPE_PCMCIA, /* SSB is connected to PCMCIA bus */
+ SSB_BUSTYPE_SDIO, /* SSB is connected to SDIO bus */
};
/* board_vendor */
@@ -240,8 +271,12 @@ struct ssb_bus {
/* The core in the basic address register window. (PCI bus only) */
struct ssb_device *mapped_device;
- /* Currently mapped PCMCIA segment. (bustype == SSB_BUSTYPE_PCMCIA only) */
- u8 mapped_pcmcia_seg;
+ union {
+ /* Currently mapped PCMCIA segment. (bustype == SSB_BUSTYPE_PCMCIA only) */
+ u8 mapped_pcmcia_seg;
+ /* Current SSB base address window for SDIO. */
+ u32 sdio_sbaddr;
+ };
/* Lock for core and segment switching.
* On PCMCIA-host busses this is used to protect the whole MMIO access. */
spinlock_t bar_lock;
@@ -252,6 +287,11 @@ struct ssb_bus {
struct pci_dev *host_pci;
/* Pointer to the PCMCIA device (only if bustype == SSB_BUSTYPE_PCMCIA). */
struct pcmcia_device *host_pcmcia;
+ /* Pointer to the SDIO device (only if bustype == SSB_BUSTYPE_SDIO). */
+ struct sdio_func *host_sdio;
+
+ /* See enum ssb_quirks */
+ unsigned int quirks;
#ifdef CONFIG_SSB_SPROM
/* Mutex to protect the SPROM writing. */
@@ -306,6 +346,11 @@ struct ssb_bus {
#endif /* DEBUG */
};
+enum ssb_quirks {
+ /* SDIO connected card requires performing a read after writing a 32-bit value */
+ SSB_QUIRK_SDIO_READ_AFTER_WRITE32 = (1 << 0),
+};
+
/* The initialization-invariants. */
struct ssb_init_invariants {
/* Versioning information about the PCB. */
@@ -336,6 +381,12 @@ extern int ssb_bus_pcmciabus_register(st
struct pcmcia_device *pcmcia_dev,
unsigned long baseaddr);
#endif /* CONFIG_SSB_PCMCIAHOST */
+#ifdef CONFIG_SSB_SDIOHOST
+extern int ssb_bus_sdiobus_register(struct ssb_bus *bus,
+ struct sdio_func *sdio_func,
+ unsigned int quirks);
+#endif /* CONFIG_SSB_SDIOHOST */
+
extern void ssb_bus_unregister(struct ssb_bus *bus);
--- a/include/linux/ssb/ssb_driver_chipcommon.h
+++ b/include/linux/ssb/ssb_driver_chipcommon.h
@@ -629,5 +629,15 @@ extern int ssb_chipco_serial_init(struct
/* PMU support */
extern void ssb_pmu_init(struct ssb_chipcommon *cc);
+enum ssb_pmu_ldo_volt_id {
+ LDO_PAREF = 0,
+ LDO_VOLT1,
+ LDO_VOLT2,
+ LDO_VOLT3,
+};
+
+void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
+ enum ssb_pmu_ldo_volt_id id, u32 voltage);
+void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on);
#endif /* LINUX_SSB_CHIPCO_H_ */
--- a/include/linux/ssb/ssb_regs.h
+++ b/include/linux/ssb/ssb_regs.h
@@ -162,7 +162,7 @@
/* SPROM shadow area. If not otherwise noted, fields are
* two bytes wide. Note that the SPROM can _only_ be read
- * in two-byte quantinies.
+ * in two-byte quantities.
*/
#define SSB_SPROMSIZE_WORDS 64
#define SSB_SPROMSIZE_BYTES (SSB_SPROMSIZE_WORDS * sizeof(u16))
@@ -327,8 +327,11 @@
#define SSB_SPROM5_GPIOB_P3_SHIFT 8
/* SPROM Revision 8 */
-#define SSB_SPROM8_BFLLO 0x1084 /* Boardflags (low 16 bits) */
-#define SSB_SPROM8_BFLHI 0x1086 /* Boardflags Hi */
+#define SSB_SPROM8_BOARDREV 0x1082 /* Board revision */
+#define SSB_SPROM8_BFLLO 0x1084 /* Board flags (bits 0-15) */
+#define SSB_SPROM8_BFLHI 0x1086 /* Board flags (bits 16-31) */
+#define SSB_SPROM8_BFL2LO 0x1088 /* Board flags (bits 32-47) */
+#define SSB_SPROM8_BFL2HI 0x108A /* Board flags (bits 48-63) */
#define SSB_SPROM8_IL0MAC 0x108C /* 6 byte MAC address */
#define SSB_SPROM8_CCODE 0x1092 /* 2 byte country code */
#define SSB_SPROM8_ANTAVAIL 0x109C /* Antenna available bitfields*/
@@ -354,14 +357,63 @@
#define SSB_SPROM8_GPIOB_P2 0x00FF /* Pin 2 */
#define SSB_SPROM8_GPIOB_P3 0xFF00 /* Pin 3 */
#define SSB_SPROM8_GPIOB_P3_SHIFT 8
-#define SSB_SPROM8_MAXP_BG 0x10C0 /* Max Power BG in path 1 */
-#define SSB_SPROM8_MAXP_BG_MASK 0x00FF /* Mask for Max Power BG */
+#define SSB_SPROM8_RSSIPARM2G 0x10A4 /* RSSI params for 2GHz */
+#define SSB_SPROM8_RSSISMF2G 0x000F
+#define SSB_SPROM8_RSSISMC2G 0x00F0
+#define SSB_SPROM8_RSSISMC2G_SHIFT 4
+#define SSB_SPROM8_RSSISAV2G 0x0700
+#define SSB_SPROM8_RSSISAV2G_SHIFT 8
+#define SSB_SPROM8_BXA2G 0x1800
+#define SSB_SPROM8_BXA2G_SHIFT 11
+#define SSB_SPROM8_RSSIPARM5G 0x10A6 /* RSSI params for 5GHz */
+#define SSB_SPROM8_RSSISMF5G 0x000F
+#define SSB_SPROM8_RSSISMC5G 0x00F0
+#define SSB_SPROM8_RSSISMC5G_SHIFT 4
+#define SSB_SPROM8_RSSISAV5G 0x0700
+#define SSB_SPROM8_RSSISAV5G_SHIFT 8
+#define SSB_SPROM8_BXA5G 0x1800
+#define SSB_SPROM8_BXA5G_SHIFT 11
+#define SSB_SPROM8_TRI25G 0x10A8 /* TX isolation 2.4&5.3GHz */
+#define SSB_SPROM8_TRI2G 0x00FF /* TX isolation 2.4GHz */
+#define SSB_SPROM8_TRI5G 0xFF00 /* TX isolation 5.3GHz */
+#define SSB_SPROM8_TRI5G_SHIFT 8
+#define SSB_SPROM8_TRI5GHL 0x10AA /* TX isolation 5.2/5.8GHz */
+#define SSB_SPROM8_TRI5GL 0x00FF /* TX isolation 5.2GHz */
+#define SSB_SPROM8_TRI5GH 0xFF00 /* TX isolation 5.8GHz */
+#define SSB_SPROM8_TRI5GH_SHIFT 8
+#define SSB_SPROM8_RXPO 0x10AC /* RX power offsets */
+#define SSB_SPROM8_RXPO2G 0x00FF /* 2GHz RX power offset */
+#define SSB_SPROM8_RXPO5G 0xFF00 /* 5GHz RX power offset */
+#define SSB_SPROM8_RXPO5G_SHIFT 8
+#define SSB_SPROM8_MAXP_BG 0x10C0 /* Max Power 2GHz in path 1 */
+#define SSB_SPROM8_MAXP_BG_MASK 0x00FF /* Mask for Max Power 2GHz */
#define SSB_SPROM8_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */
#define SSB_SPROM8_ITSSI_BG_SHIFT 8
-#define SSB_SPROM8_MAXP_A 0x10C8 /* Max Power A in path 1 */
-#define SSB_SPROM8_MAXP_A_MASK 0x00FF /* Mask for Max Power A */
+#define SSB_SPROM8_PA0B0 0x10C2 /* 2GHz power amp settings */
+#define SSB_SPROM8_PA0B1 0x10C4
+#define SSB_SPROM8_PA0B2 0x10C6
+#define SSB_SPROM8_MAXP_A 0x10C8 /* Max Power 5.3GHz */
+#define SSB_SPROM8_MAXP_A_MASK 0x00FF /* Mask for Max Power 5.3GHz */
#define SSB_SPROM8_ITSSI_A 0xFF00 /* Mask for path 1 itssi_a */
#define SSB_SPROM8_ITSSI_A_SHIFT 8
+#define SSB_SPROM8_MAXP_AHL 0x10CA /* Max Power 5.2/5.8GHz */
+#define SSB_SPROM8_MAXP_AH_MASK 0x00FF /* Mask for Max Power 5.8GHz */
+#define SSB_SPROM8_MAXP_AL_MASK 0xFF00 /* Mask for Max Power 5.2GHz */
+#define SSB_SPROM8_MAXP_AL_SHIFT 8
+#define SSB_SPROM8_PA1B0 0x10CC /* 5.3GHz power amp settings */
+#define SSB_SPROM8_PA1B1 0x10CE
+#define SSB_SPROM8_PA1B2 0x10D0
+#define SSB_SPROM8_PA1LOB0 0x10D2 /* 5.2GHz power amp settings */
+#define SSB_SPROM8_PA1LOB1 0x10D4
+#define SSB_SPROM8_PA1LOB2 0x10D6
+#define SSB_SPROM8_PA1HIB0 0x10D8 /* 5.8GHz power amp settings */
+#define SSB_SPROM8_PA1HIB1 0x10DA
+#define SSB_SPROM8_PA1HIB2 0x10DC
+#define SSB_SPROM8_CCK2GPO 0x1140 /* CCK power offset */
+#define SSB_SPROM8_OFDM2GPO 0x1142 /* 2.4GHz OFDM power offset */
+#define SSB_SPROM8_OFDM5GPO 0x1146 /* 5.3GHz OFDM power offset */
+#define SSB_SPROM8_OFDM5GLPO 0x114A /* 5.2GHz OFDM power offset */
+#define SSB_SPROM8_OFDM5GHPO 0x114E /* 5.8GHz OFDM power offset */
/* Values for SSB_SPROM1_BINF_CCODE */
enum {
--- a/drivers/ssb/scan.c
+++ b/drivers/ssb/scan.c
@@ -175,6 +175,8 @@ static u32 scan_read32(struct ssb_bus *b
} else
ssb_pcmcia_switch_segment(bus, 0);
break;
+ default:
+ break;
}
return readl(bus->mmio + offset);
}
@@ -188,6 +190,8 @@ static int scan_switchcore(struct ssb_bu
return ssb_pci_switch_coreidx(bus, coreidx);
case SSB_BUSTYPE_PCMCIA:
return ssb_pcmcia_switch_coreidx(bus, coreidx);
+ default:
+ break;
}
return 0;
}
@@ -206,6 +210,8 @@ void ssb_iounmap(struct ssb_bus *bus)
SSB_BUG_ON(1); /* Can't reach this code. */
#endif
break;
+ default:
+ break;
}
bus->mmio = NULL;
bus->mapped_device = NULL;
@@ -230,6 +236,8 @@ static void __iomem *ssb_ioremap(struct
SSB_BUG_ON(1); /* Can't reach this code. */
#endif
break;
+ default:
+ break;
}
return mmio;

View File

@ -0,0 +1,506 @@
--- a/drivers/ssb/driver_chipcommon_pmu.c
+++ b/drivers/ssb/driver_chipcommon_pmu.c
@@ -28,6 +28,21 @@ static void ssb_chipco_pll_write(struct
chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, value);
}
+static void ssb_chipco_regctl_maskset(struct ssb_chipcommon *cc,
+ u32 offset, u32 mask, u32 set)
+{
+ u32 value;
+
+ chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR);
+ chipco_write32(cc, SSB_CHIPCO_REGCTL_ADDR, offset);
+ chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR);
+ value = chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA);
+ value &= mask;
+ value |= set;
+ chipco_write32(cc, SSB_CHIPCO_REGCTL_DATA, value);
+ chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA);
+}
+
struct pmu0_plltab_entry {
u16 freq; /* Crystal frequency in kHz.*/
u8 xf; /* Crystal frequency value for PMU control */
@@ -506,3 +521,82 @@ void ssb_pmu_init(struct ssb_chipcommon
ssb_pmu_pll_init(cc);
ssb_pmu_resources_init(cc);
}
+
+void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
+ enum ssb_pmu_ldo_volt_id id, u32 voltage)
+{
+ struct ssb_bus *bus = cc->dev->bus;
+ u32 addr, shift, mask;
+
+ switch (bus->chip_id) {
+ case 0x4328:
+ case 0x5354:
+ switch (id) {
+ case LDO_VOLT1:
+ addr = 2;
+ shift = 25;
+ mask = 0xF;
+ break;
+ case LDO_VOLT2:
+ addr = 3;
+ shift = 1;
+ mask = 0xF;
+ break;
+ case LDO_VOLT3:
+ addr = 3;
+ shift = 9;
+ mask = 0xF;
+ break;
+ case LDO_PAREF:
+ addr = 3;
+ shift = 17;
+ mask = 0x3F;
+ break;
+ default:
+ SSB_WARN_ON(1);
+ return;
+ }
+ break;
+ case 0x4312:
+ if (SSB_WARN_ON(id != LDO_PAREF))
+ return;
+ addr = 0;
+ shift = 21;
+ mask = 0x3F;
+ break;
+ default:
+ return;
+ }
+
+ ssb_chipco_regctl_maskset(cc, addr, ~(mask << shift),
+ (voltage & mask) << shift);
+}
+
+void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on)
+{
+ struct ssb_bus *bus = cc->dev->bus;
+ int ldo;
+
+ switch (bus->chip_id) {
+ case 0x4312:
+ ldo = SSB_PMURES_4312_PA_REF_LDO;
+ break;
+ case 0x4328:
+ ldo = SSB_PMURES_4328_PA_REF_LDO;
+ break;
+ case 0x5354:
+ ldo = SSB_PMURES_5354_PA_REF_LDO;
+ break;
+ default:
+ return;
+ }
+
+ if (on)
+ chipco_set32(cc, SSB_CHIPCO_PMU_MINRES_MSK, 1 << ldo);
+ else
+ chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, ~(1 << ldo));
+ chipco_read32(cc, SSB_CHIPCO_PMU_MINRES_MSK); //SPEC FIXME found via mmiotrace - dummy read?
+}
+
+EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage);
+EXPORT_SYMBOL(ssb_pmu_set_ldo_paref);
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -469,6 +469,8 @@ static int ssb_devices_register(struct s
dev->parent = &bus->host_pcmcia->dev;
#endif
break;
+ case SSB_BUSTYPE_SDIO:
+ break;
case SSB_BUSTYPE_SSB:
dev->dma_mask = &dev->coherent_dma_mask;
break;
@@ -1358,8 +1360,10 @@ static int __init ssb_modinit(void)
ssb_buses_lock();
err = ssb_attach_queued_buses();
ssb_buses_unlock();
- if (err)
+ if (err) {
bus_unregister(&ssb_bustype);
+ goto out;
+ }
err = b43_pci_ssb_bridge_init();
if (err) {
@@ -1375,7 +1379,7 @@ static int __init ssb_modinit(void)
/* don't fail SSB init because of this */
err = 0;
}
-
+out:
return err;
}
/* ssb must be initialized after PCI but before the ssb drivers.
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -169,8 +169,14 @@ err_pci:
/* Get the word-offset for a SSB_SPROM_XXX define. */
#define SPOFF(offset) (((offset) - SSB_SPROM_BASE) / sizeof(u16))
/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
-#define SPEX(_outvar, _offset, _mask, _shift) \
+#define SPEX16(_outvar, _offset, _mask, _shift) \
out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
+#define SPEX32(_outvar, _offset, _mask, _shift) \
+ out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \
+ in[SPOFF(_offset)]) & (_mask)) >> (_shift))
+#define SPEX(_outvar, _offset, _mask, _shift) \
+ SPEX16(_outvar, _offset, _mask, _shift)
+
static inline u8 ssb_crc8(u8 crc, u8 data)
{
@@ -474,12 +480,14 @@ static void sprom_extract_r8(struct ssb_
/* extract the MAC address */
for (i = 0; i < 3; i++) {
- v = in[SPOFF(SSB_SPROM1_IL0MAC) + i];
+ v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
}
SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
+ SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
+ SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
SSB_SPROM8_ANTAVAIL_A_SHIFT);
SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
@@ -490,12 +498,55 @@ static void sprom_extract_r8(struct ssb_
SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
SSB_SPROM8_ITSSI_A_SHIFT);
+ SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
+ SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
+ SSB_SPROM8_MAXP_AL_SHIFT);
SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
SSB_SPROM8_GPIOA_P1_SHIFT);
SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
SSB_SPROM8_GPIOB_P3_SHIFT);
+ SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
+ SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
+ SSB_SPROM8_TRI5G_SHIFT);
+ SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
+ SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
+ SSB_SPROM8_TRI5GH_SHIFT);
+ SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
+ SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
+ SSB_SPROM8_RXPO5G_SHIFT);
+ SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
+ SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
+ SSB_SPROM8_RSSISMC2G_SHIFT);
+ SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
+ SSB_SPROM8_RSSISAV2G_SHIFT);
+ SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
+ SSB_SPROM8_BXA2G_SHIFT);
+ SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
+ SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
+ SSB_SPROM8_RSSISMC5G_SHIFT);
+ SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
+ SSB_SPROM8_RSSISAV5G_SHIFT);
+ SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
+ SSB_SPROM8_BXA5G_SHIFT);
+ SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
+ SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
+ SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
+ SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
+ SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
+ SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
+ SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
+ SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
+ SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
+ SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
+ SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
+ SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
+ SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
+ SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
+ SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
+ SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
+ SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
/* Extract the antenna gain values. */
SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01,
@@ -549,6 +600,7 @@ static int sprom_extract(struct ssb_bus
ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
" revision %d detected. Will extract"
" v1\n", out->revision);
+ out->revision = 1;
sprom_extract_r123(out, in);
}
}
--- a/drivers/ssb/scan.c
+++ b/drivers/ssb/scan.c
@@ -175,6 +175,9 @@ static u32 scan_read32(struct ssb_bus *b
} else
ssb_pcmcia_switch_segment(bus, 0);
break;
+ case SSB_BUSTYPE_SDIO:
+ offset += current_coreidx * SSB_CORE_SIZE;
+ return ssb_sdio_scan_read32(bus, offset);
}
return readl(bus->mmio + offset);
}
@@ -188,6 +191,8 @@ static int scan_switchcore(struct ssb_bu
return ssb_pci_switch_coreidx(bus, coreidx);
case SSB_BUSTYPE_PCMCIA:
return ssb_pcmcia_switch_coreidx(bus, coreidx);
+ case SSB_BUSTYPE_SDIO:
+ break;
}
return 0;
}
@@ -206,6 +211,8 @@ void ssb_iounmap(struct ssb_bus *bus)
SSB_BUG_ON(1); /* Can't reach this code. */
#endif
break;
+ case SSB_BUSTYPE_SDIO:
+ break;
}
bus->mmio = NULL;
bus->mapped_device = NULL;
@@ -230,6 +237,8 @@ static void __iomem *ssb_ioremap(struct
SSB_BUG_ON(1); /* Can't reach this code. */
#endif
break;
+ case SSB_BUSTYPE_SDIO:
+ break;
}
return mmio;
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -27,24 +27,54 @@ struct ssb_sprom {
u8 et1mdcport; /* MDIO for enet1 */
u8 board_rev; /* Board revision number from SPROM. */
u8 country_code; /* Country Code */
- u8 ant_available_a; /* A-PHY antenna available bits (up to 4) */
- u8 ant_available_bg; /* B/G-PHY antenna available bits (up to 4) */
+ u8 ant_available_a; /* 2GHz antenna available bits (up to 4) */
+ u8 ant_available_bg; /* 5GHz antenna available bits (up to 4) */
u16 pa0b0;
u16 pa0b1;
u16 pa0b2;
u16 pa1b0;
u16 pa1b1;
u16 pa1b2;
+ u16 pa1lob0;
+ u16 pa1lob1;
+ u16 pa1lob2;
+ u16 pa1hib0;
+ u16 pa1hib1;
+ u16 pa1hib2;
u8 gpio0; /* GPIO pin 0 */
u8 gpio1; /* GPIO pin 1 */
u8 gpio2; /* GPIO pin 2 */
u8 gpio3; /* GPIO pin 3 */
- u16 maxpwr_a; /* A-PHY Amplifier Max Power (in dBm Q5.2) */
- u16 maxpwr_bg; /* B/G-PHY Amplifier Max Power (in dBm Q5.2) */
+ u16 maxpwr_bg; /* 2.4GHz Amplifier Max Power (in dBm Q5.2) */
+ u16 maxpwr_al; /* 5.2GHz Amplifier Max Power (in dBm Q5.2) */
+ u16 maxpwr_a; /* 5.3GHz Amplifier Max Power (in dBm Q5.2) */
+ u16 maxpwr_ah; /* 5.8GHz Amplifier Max Power (in dBm Q5.2) */
u8 itssi_a; /* Idle TSSI Target for A-PHY */
u8 itssi_bg; /* Idle TSSI Target for B/G-PHY */
- u16 boardflags_lo; /* Boardflags (low 16 bits) */
- u16 boardflags_hi; /* Boardflags (high 16 bits) */
+ u8 tri2g; /* 2.4GHz TX isolation */
+ u8 tri5gl; /* 5.2GHz TX isolation */
+ u8 tri5g; /* 5.3GHz TX isolation */
+ u8 tri5gh; /* 5.8GHz TX isolation */
+ u8 rxpo2g; /* 2GHz RX power offset */
+ u8 rxpo5g; /* 5GHz RX power offset */
+ u8 rssisav2g; /* 2GHz RSSI params */
+ u8 rssismc2g;
+ u8 rssismf2g;
+ u8 bxa2g; /* 2GHz BX arch */
+ u8 rssisav5g; /* 5GHz RSSI params */
+ u8 rssismc5g;
+ u8 rssismf5g;
+ u8 bxa5g; /* 5GHz BX arch */
+ u16 cck2gpo; /* CCK power offset */
+ u32 ofdm2gpo; /* 2.4GHz OFDM power offset */
+ u32 ofdm5glpo; /* 5.2GHz OFDM power offset */
+ u32 ofdm5gpo; /* 5.3GHz OFDM power offset */
+ u32 ofdm5ghpo; /* 5.8GHz OFDM power offset */
+ u16 boardflags_lo; /* Board flags (bits 0-15) */
+ u16 boardflags_hi; /* Board flags (bits 16-31) */
+ u16 boardflags2_lo; /* Board flags (bits 32-47) */
+ u16 boardflags2_hi; /* Board flags (bits 48-63) */
+ /* TODO store board flags in a single u64 */
/* Antenna gain values for up to 4 antennas
* on each band. Values in dBm/4 (Q5.2). Negative gain means the
@@ -58,7 +88,7 @@ struct ssb_sprom {
} ghz5; /* 5GHz band */
} antenna_gain;
- /* TODO - add any parameters needed from rev 2, 3, or 4 SPROMs */
+ /* TODO - add any parameters needed from rev 2, 3, 4, 5 or 8 SPROMs */
};
/* Information about the PCB the circuitry is soldered on. */
@@ -208,6 +238,7 @@ enum ssb_bustype {
SSB_BUSTYPE_SSB, /* This SSB bus is the system bus */
SSB_BUSTYPE_PCI, /* SSB is connected to PCI bus */
SSB_BUSTYPE_PCMCIA, /* SSB is connected to PCMCIA bus */
+ SSB_BUSTYPE_SDIO, /* SSB is connected to SDIO bus */
};
/* board_vendor */
@@ -240,8 +271,12 @@ struct ssb_bus {
/* The core in the basic address register window. (PCI bus only) */
struct ssb_device *mapped_device;
- /* Currently mapped PCMCIA segment. (bustype == SSB_BUSTYPE_PCMCIA only) */
- u8 mapped_pcmcia_seg;
+ union {
+ /* Currently mapped PCMCIA segment. (bustype == SSB_BUSTYPE_PCMCIA only) */
+ u8 mapped_pcmcia_seg;
+ /* Current SSB base address window for SDIO. */
+ u32 sdio_sbaddr;
+ };
/* Lock for core and segment switching.
* On PCMCIA-host busses this is used to protect the whole MMIO access. */
spinlock_t bar_lock;
@@ -252,6 +287,11 @@ struct ssb_bus {
struct pci_dev *host_pci;
/* Pointer to the PCMCIA device (only if bustype == SSB_BUSTYPE_PCMCIA). */
struct pcmcia_device *host_pcmcia;
+ /* Pointer to the SDIO device (only if bustype == SSB_BUSTYPE_SDIO). */
+ struct sdio_func *host_sdio;
+
+ /* See enum ssb_quirks */
+ unsigned int quirks;
#ifdef CONFIG_SSB_SPROM
/* Mutex to protect the SPROM writing. */
@@ -306,6 +346,11 @@ struct ssb_bus {
#endif /* DEBUG */
};
+enum ssb_quirks {
+ /* SDIO connected card requires performing a read after writing a 32-bit value */
+ SSB_QUIRK_SDIO_READ_AFTER_WRITE32 = (1 << 0),
+};
+
/* The initialization-invariants. */
struct ssb_init_invariants {
/* Versioning information about the PCB. */
--- a/include/linux/ssb/ssb_driver_chipcommon.h
+++ b/include/linux/ssb/ssb_driver_chipcommon.h
@@ -629,5 +629,15 @@ extern int ssb_chipco_serial_init(struct
/* PMU support */
extern void ssb_pmu_init(struct ssb_chipcommon *cc);
+enum ssb_pmu_ldo_volt_id {
+ LDO_PAREF = 0,
+ LDO_VOLT1,
+ LDO_VOLT2,
+ LDO_VOLT3,
+};
+
+void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
+ enum ssb_pmu_ldo_volt_id id, u32 voltage);
+void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on);
#endif /* LINUX_SSB_CHIPCO_H_ */
--- a/include/linux/ssb/ssb_regs.h
+++ b/include/linux/ssb/ssb_regs.h
@@ -162,7 +162,7 @@
/* SPROM shadow area. If not otherwise noted, fields are
* two bytes wide. Note that the SPROM can _only_ be read
- * in two-byte quantinies.
+ * in two-byte quantities.
*/
#define SSB_SPROMSIZE_WORDS 64
#define SSB_SPROMSIZE_BYTES (SSB_SPROMSIZE_WORDS * sizeof(u16))
@@ -327,8 +327,11 @@
#define SSB_SPROM5_GPIOB_P3_SHIFT 8
/* SPROM Revision 8 */
-#define SSB_SPROM8_BFLLO 0x1084 /* Boardflags (low 16 bits) */
-#define SSB_SPROM8_BFLHI 0x1086 /* Boardflags Hi */
+#define SSB_SPROM8_BOARDREV 0x1082 /* Board revision */
+#define SSB_SPROM8_BFLLO 0x1084 /* Board flags (bits 0-15) */
+#define SSB_SPROM8_BFLHI 0x1086 /* Board flags (bits 16-31) */
+#define SSB_SPROM8_BFL2LO 0x1088 /* Board flags (bits 32-47) */
+#define SSB_SPROM8_BFL2HI 0x108A /* Board flags (bits 48-63) */
#define SSB_SPROM8_IL0MAC 0x108C /* 6 byte MAC address */
#define SSB_SPROM8_CCODE 0x1092 /* 2 byte country code */
#define SSB_SPROM8_ANTAVAIL 0x109C /* Antenna available bitfields*/
@@ -354,14 +357,63 @@
#define SSB_SPROM8_GPIOB_P2 0x00FF /* Pin 2 */
#define SSB_SPROM8_GPIOB_P3 0xFF00 /* Pin 3 */
#define SSB_SPROM8_GPIOB_P3_SHIFT 8
-#define SSB_SPROM8_MAXP_BG 0x10C0 /* Max Power BG in path 1 */
-#define SSB_SPROM8_MAXP_BG_MASK 0x00FF /* Mask for Max Power BG */
+#define SSB_SPROM8_RSSIPARM2G 0x10A4 /* RSSI params for 2GHz */
+#define SSB_SPROM8_RSSISMF2G 0x000F
+#define SSB_SPROM8_RSSISMC2G 0x00F0
+#define SSB_SPROM8_RSSISMC2G_SHIFT 4
+#define SSB_SPROM8_RSSISAV2G 0x0700
+#define SSB_SPROM8_RSSISAV2G_SHIFT 8
+#define SSB_SPROM8_BXA2G 0x1800
+#define SSB_SPROM8_BXA2G_SHIFT 11
+#define SSB_SPROM8_RSSIPARM5G 0x10A6 /* RSSI params for 5GHz */
+#define SSB_SPROM8_RSSISMF5G 0x000F
+#define SSB_SPROM8_RSSISMC5G 0x00F0
+#define SSB_SPROM8_RSSISMC5G_SHIFT 4
+#define SSB_SPROM8_RSSISAV5G 0x0700
+#define SSB_SPROM8_RSSISAV5G_SHIFT 8
+#define SSB_SPROM8_BXA5G 0x1800
+#define SSB_SPROM8_BXA5G_SHIFT 11
+#define SSB_SPROM8_TRI25G 0x10A8 /* TX isolation 2.4&5.3GHz */
+#define SSB_SPROM8_TRI2G 0x00FF /* TX isolation 2.4GHz */
+#define SSB_SPROM8_TRI5G 0xFF00 /* TX isolation 5.3GHz */
+#define SSB_SPROM8_TRI5G_SHIFT 8
+#define SSB_SPROM8_TRI5GHL 0x10AA /* TX isolation 5.2/5.8GHz */
+#define SSB_SPROM8_TRI5GL 0x00FF /* TX isolation 5.2GHz */
+#define SSB_SPROM8_TRI5GH 0xFF00 /* TX isolation 5.8GHz */
+#define SSB_SPROM8_TRI5GH_SHIFT 8
+#define SSB_SPROM8_RXPO 0x10AC /* RX power offsets */
+#define SSB_SPROM8_RXPO2G 0x00FF /* 2GHz RX power offset */
+#define SSB_SPROM8_RXPO5G 0xFF00 /* 5GHz RX power offset */
+#define SSB_SPROM8_RXPO5G_SHIFT 8
+#define SSB_SPROM8_MAXP_BG 0x10C0 /* Max Power 2GHz in path 1 */
+#define SSB_SPROM8_MAXP_BG_MASK 0x00FF /* Mask for Max Power 2GHz */
#define SSB_SPROM8_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */
#define SSB_SPROM8_ITSSI_BG_SHIFT 8
-#define SSB_SPROM8_MAXP_A 0x10C8 /* Max Power A in path 1 */
-#define SSB_SPROM8_MAXP_A_MASK 0x00FF /* Mask for Max Power A */
+#define SSB_SPROM8_PA0B0 0x10C2 /* 2GHz power amp settings */
+#define SSB_SPROM8_PA0B1 0x10C4
+#define SSB_SPROM8_PA0B2 0x10C6
+#define SSB_SPROM8_MAXP_A 0x10C8 /* Max Power 5.3GHz */
+#define SSB_SPROM8_MAXP_A_MASK 0x00FF /* Mask for Max Power 5.3GHz */
#define SSB_SPROM8_ITSSI_A 0xFF00 /* Mask for path 1 itssi_a */
#define SSB_SPROM8_ITSSI_A_SHIFT 8
+#define SSB_SPROM8_MAXP_AHL 0x10CA /* Max Power 5.2/5.8GHz */
+#define SSB_SPROM8_MAXP_AH_MASK 0x00FF /* Mask for Max Power 5.8GHz */
+#define SSB_SPROM8_MAXP_AL_MASK 0xFF00 /* Mask for Max Power 5.2GHz */
+#define SSB_SPROM8_MAXP_AL_SHIFT 8
+#define SSB_SPROM8_PA1B0 0x10CC /* 5.3GHz power amp settings */
+#define SSB_SPROM8_PA1B1 0x10CE
+#define SSB_SPROM8_PA1B2 0x10D0
+#define SSB_SPROM8_PA1LOB0 0x10D2 /* 5.2GHz power amp settings */
+#define SSB_SPROM8_PA1LOB1 0x10D4
+#define SSB_SPROM8_PA1LOB2 0x10D6
+#define SSB_SPROM8_PA1HIB0 0x10D8 /* 5.8GHz power amp settings */
+#define SSB_SPROM8_PA1HIB1 0x10DA
+#define SSB_SPROM8_PA1HIB2 0x10DC
+#define SSB_SPROM8_CCK2GPO 0x1140 /* CCK power offset */
+#define SSB_SPROM8_OFDM2GPO 0x1142 /* 2.4GHz OFDM power offset */
+#define SSB_SPROM8_OFDM5GPO 0x1146 /* 5.3GHz OFDM power offset */
+#define SSB_SPROM8_OFDM5GLPO 0x114A /* 5.2GHz OFDM power offset */
+#define SSB_SPROM8_OFDM5GHPO 0x114E /* 5.8GHz OFDM power offset */
/* Values for SSB_SPROM1_BINF_CCODE */
enum {