|
@@ -31,6 +31,7 @@
|
|
|
#include <linux/bcma/bcma.h>
|
|
|
#include <linux/debugfs.h>
|
|
|
#include <linux/vmalloc.h>
|
|
|
+#include <linux/platform_data/brcmfmac-sdio.h>
|
|
|
#include <asm/unaligned.h>
|
|
|
#include <defs.h>
|
|
|
#include <brcmu_wifi.h>
|
|
@@ -324,6 +325,9 @@ MODULE_FIRMWARE(BRCMF_SDIO_NV_NAME);
|
|
|
*/
|
|
|
#define BRCMF_IDLE_INTERVAL 1
|
|
|
|
|
|
+#define KSO_WAIT_US 50
|
|
|
+#define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US)
|
|
|
+
|
|
|
/*
|
|
|
* Conversion of 802.1D priority to precedence level
|
|
|
*/
|
|
@@ -333,95 +337,6 @@ static uint prio2prec(u32 prio)
|
|
|
(prio^2) : prio;
|
|
|
}
|
|
|
|
|
|
-/* core registers */
|
|
|
-struct sdpcmd_regs {
|
|
|
- u32 corecontrol; /* 0x00, rev8 */
|
|
|
- u32 corestatus; /* rev8 */
|
|
|
- u32 PAD[1];
|
|
|
- u32 biststatus; /* rev8 */
|
|
|
-
|
|
|
- /* PCMCIA access */
|
|
|
- u16 pcmciamesportaladdr; /* 0x010, rev8 */
|
|
|
- u16 PAD[1];
|
|
|
- u16 pcmciamesportalmask; /* rev8 */
|
|
|
- u16 PAD[1];
|
|
|
- u16 pcmciawrframebc; /* rev8 */
|
|
|
- u16 PAD[1];
|
|
|
- u16 pcmciaunderflowtimer; /* rev8 */
|
|
|
- u16 PAD[1];
|
|
|
-
|
|
|
- /* interrupt */
|
|
|
- u32 intstatus; /* 0x020, rev8 */
|
|
|
- u32 hostintmask; /* rev8 */
|
|
|
- u32 intmask; /* rev8 */
|
|
|
- u32 sbintstatus; /* rev8 */
|
|
|
- u32 sbintmask; /* rev8 */
|
|
|
- u32 funcintmask; /* rev4 */
|
|
|
- u32 PAD[2];
|
|
|
- u32 tosbmailbox; /* 0x040, rev8 */
|
|
|
- u32 tohostmailbox; /* rev8 */
|
|
|
- u32 tosbmailboxdata; /* rev8 */
|
|
|
- u32 tohostmailboxdata; /* rev8 */
|
|
|
-
|
|
|
- /* synchronized access to registers in SDIO clock domain */
|
|
|
- u32 sdioaccess; /* 0x050, rev8 */
|
|
|
- u32 PAD[3];
|
|
|
-
|
|
|
- /* PCMCIA frame control */
|
|
|
- u8 pcmciaframectrl; /* 0x060, rev8 */
|
|
|
- u8 PAD[3];
|
|
|
- u8 pcmciawatermark; /* rev8 */
|
|
|
- u8 PAD[155];
|
|
|
-
|
|
|
- /* interrupt batching control */
|
|
|
- u32 intrcvlazy; /* 0x100, rev8 */
|
|
|
- u32 PAD[3];
|
|
|
-
|
|
|
- /* counters */
|
|
|
- u32 cmd52rd; /* 0x110, rev8 */
|
|
|
- u32 cmd52wr; /* rev8 */
|
|
|
- u32 cmd53rd; /* rev8 */
|
|
|
- u32 cmd53wr; /* rev8 */
|
|
|
- u32 abort; /* rev8 */
|
|
|
- u32 datacrcerror; /* rev8 */
|
|
|
- u32 rdoutofsync; /* rev8 */
|
|
|
- u32 wroutofsync; /* rev8 */
|
|
|
- u32 writebusy; /* rev8 */
|
|
|
- u32 readwait; /* rev8 */
|
|
|
- u32 readterm; /* rev8 */
|
|
|
- u32 writeterm; /* rev8 */
|
|
|
- u32 PAD[40];
|
|
|
- u32 clockctlstatus; /* rev8 */
|
|
|
- u32 PAD[7];
|
|
|
-
|
|
|
- u32 PAD[128]; /* DMA engines */
|
|
|
-
|
|
|
- /* SDIO/PCMCIA CIS region */
|
|
|
- char cis[512]; /* 0x400-0x5ff, rev6 */
|
|
|
-
|
|
|
- /* PCMCIA function control registers */
|
|
|
- char pcmciafcr[256]; /* 0x600-6ff, rev6 */
|
|
|
- u16 PAD[55];
|
|
|
-
|
|
|
- /* PCMCIA backplane access */
|
|
|
- u16 backplanecsr; /* 0x76E, rev6 */
|
|
|
- u16 backplaneaddr0; /* rev6 */
|
|
|
- u16 backplaneaddr1; /* rev6 */
|
|
|
- u16 backplaneaddr2; /* rev6 */
|
|
|
- u16 backplaneaddr3; /* rev6 */
|
|
|
- u16 backplanedata0; /* rev6 */
|
|
|
- u16 backplanedata1; /* rev6 */
|
|
|
- u16 backplanedata2; /* rev6 */
|
|
|
- u16 backplanedata3; /* rev6 */
|
|
|
- u16 PAD[31];
|
|
|
-
|
|
|
- /* sprom "size" & "blank" info */
|
|
|
- u16 spromstatus; /* 0x7BE, rev2 */
|
|
|
- u32 PAD[464];
|
|
|
-
|
|
|
- u16 PAD[0x80];
|
|
|
-};
|
|
|
-
|
|
|
#ifdef DEBUG
|
|
|
/* Device console log buffer state */
|
|
|
struct brcmf_console {
|
|
@@ -588,12 +503,14 @@ struct brcmf_sdio {
|
|
|
|
|
|
bool txoff; /* Transmit flow-controlled */
|
|
|
struct brcmf_sdio_count sdcnt;
|
|
|
+ bool sr_enabled; /* SaveRestore enabled */
|
|
|
+ bool sleeping; /* SDIO bus sleeping */
|
|
|
};
|
|
|
|
|
|
/* clkstate */
|
|
|
#define CLK_NONE 0
|
|
|
#define CLK_SDONLY 1
|
|
|
-#define CLK_PENDING 2 /* Not used yet */
|
|
|
+#define CLK_PENDING 2
|
|
|
#define CLK_AVAIL 3
|
|
|
|
|
|
#ifdef DEBUG
|
|
@@ -601,7 +518,7 @@ static int qcount[NUMPRIO];
|
|
|
static int tx_packets[NUMPRIO];
|
|
|
#endif /* DEBUG */
|
|
|
|
|
|
-#define SDIO_DRIVE_STRENGTH 6 /* in milliamps */
|
|
|
+#define DEFAULT_SDIO_DRIVE_STRENGTH 6 /* in milliamps */
|
|
|
|
|
|
#define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL)
|
|
|
|
|
@@ -665,6 +582,62 @@ w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+brcmf_sdbrcm_kso_control(struct brcmf_sdio *bus, bool on)
|
|
|
+{
|
|
|
+ u8 wr_val = 0, rd_val, cmp_val, bmask;
|
|
|
+ int err = 0;
|
|
|
+ int try_cnt = 0;
|
|
|
+
|
|
|
+ brcmf_dbg(TRACE, "Enter\n");
|
|
|
+
|
|
|
+ wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
|
|
|
+ /* 1st KSO write goes to AOS wake up core if device is asleep */
|
|
|
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
|
|
|
+ wr_val, &err);
|
|
|
+ if (err) {
|
|
|
+ brcmf_err("SDIO_AOS KSO write error: %d\n", err);
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (on) {
|
|
|
+ /* device WAKEUP through KSO:
|
|
|
+ * write bit 0 & read back until
|
|
|
+ * both bits 0 (kso bit) & 1 (dev on status) are set
|
|
|
+ */
|
|
|
+ cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK |
|
|
|
+ SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK;
|
|
|
+ bmask = cmp_val;
|
|
|
+ usleep_range(2000, 3000);
|
|
|
+ } else {
|
|
|
+ /* Put device to sleep, turn off KSO */
|
|
|
+ cmp_val = 0;
|
|
|
+ /* only check for bit0, bit1(dev on status) may not
|
|
|
+ * get cleared right away
|
|
|
+ */
|
|
|
+ bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK;
|
|
|
+ }
|
|
|
+
|
|
|
+ do {
|
|
|
+ /* reliable KSO bit set/clr:
|
|
|
+ * the sdiod sleep write access is synced to PMU 32khz clk
|
|
|
+ * just one write attempt may fail,
|
|
|
+ * read it back until it matches written value
|
|
|
+ */
|
|
|
+ rd_val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
|
|
|
+ &err);
|
|
|
+ if (((rd_val & bmask) == cmp_val) && !err)
|
|
|
+ break;
|
|
|
+ brcmf_dbg(SDIO, "KSO wr/rd retry:%d (max: %d) ERR:%x\n",
|
|
|
+ try_cnt, MAX_KSO_ATTEMPTS, err);
|
|
|
+ udelay(KSO_WAIT_US);
|
|
|
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
|
|
|
+ wr_val, &err);
|
|
|
+ } while (try_cnt++ < MAX_KSO_ATTEMPTS);
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
#define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND)
|
|
|
|
|
|
#define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE)
|
|
@@ -680,6 +653,11 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
|
|
|
|
|
|
clkctl = 0;
|
|
|
|
|
|
+ if (bus->sr_enabled) {
|
|
|
+ bus->clkstate = (on ? CLK_AVAIL : CLK_SDONLY);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
if (on) {
|
|
|
/* Request HT Avail */
|
|
|
clkreq =
|
|
@@ -856,6 +834,63 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+brcmf_sdbrcm_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok)
|
|
|
+{
|
|
|
+ int err = 0;
|
|
|
+ brcmf_dbg(TRACE, "Enter\n");
|
|
|
+ brcmf_dbg(SDIO, "request %s currently %s\n",
|
|
|
+ (sleep ? "SLEEP" : "WAKE"),
|
|
|
+ (bus->sleeping ? "SLEEP" : "WAKE"));
|
|
|
+
|
|
|
+ /* If SR is enabled control bus state with KSO */
|
|
|
+ if (bus->sr_enabled) {
|
|
|
+ /* Done if we're already in the requested state */
|
|
|
+ if (sleep == bus->sleeping)
|
|
|
+ goto end;
|
|
|
+
|
|
|
+ /* Going to sleep */
|
|
|
+ if (sleep) {
|
|
|
+ /* Don't sleep if something is pending */
|
|
|
+ if (atomic_read(&bus->intstatus) ||
|
|
|
+ atomic_read(&bus->ipend) > 0 ||
|
|
|
+ (!atomic_read(&bus->fcstate) &&
|
|
|
+ brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
|
|
|
+ data_ok(bus)))
|
|
|
+ return -EBUSY;
|
|
|
+ err = brcmf_sdbrcm_kso_control(bus, false);
|
|
|
+ /* disable watchdog */
|
|
|
+ if (!err)
|
|
|
+ brcmf_sdbrcm_wd_timer(bus, 0);
|
|
|
+ } else {
|
|
|
+ bus->idlecount = 0;
|
|
|
+ err = brcmf_sdbrcm_kso_control(bus, true);
|
|
|
+ }
|
|
|
+ if (!err) {
|
|
|
+ /* Change state */
|
|
|
+ bus->sleeping = sleep;
|
|
|
+ brcmf_dbg(SDIO, "new state %s\n",
|
|
|
+ (sleep ? "SLEEP" : "WAKE"));
|
|
|
+ } else {
|
|
|
+ brcmf_err("error while changing bus sleep state %d\n",
|
|
|
+ err);
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+end:
|
|
|
+ /* control clocks */
|
|
|
+ if (sleep) {
|
|
|
+ if (!bus->sr_enabled)
|
|
|
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, pendok);
|
|
|
+ } else {
|
|
|
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, pendok);
|
|
|
+ }
|
|
|
+
|
|
|
+ return err;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
|
|
|
{
|
|
|
u32 intstatus = 0;
|
|
@@ -1960,7 +1995,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
|
|
|
sdio_claim_host(bus->sdiodev->func[1]);
|
|
|
|
|
|
/* Enable clock for device interrupts */
|
|
|
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
|
|
+ brcmf_sdbrcm_bus_sleep(bus, false, false);
|
|
|
|
|
|
/* Disable and clear interrupts at the chip level also */
|
|
|
w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask));
|
|
@@ -2012,23 +2047,19 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
|
|
|
bus->tx_seq = bus->rx_seq = 0;
|
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_BRCMFMAC_SDIO_OOB
|
|
|
static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
|
|
|
{
|
|
|
unsigned long flags;
|
|
|
|
|
|
- spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags);
|
|
|
- if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) {
|
|
|
- enable_irq(bus->sdiodev->irq);
|
|
|
- bus->sdiodev->irq_en = true;
|
|
|
+ if (bus->sdiodev->oob_irq_requested) {
|
|
|
+ spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags);
|
|
|
+ if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) {
|
|
|
+ enable_irq(bus->sdiodev->pdata->oob_irq_nr);
|
|
|
+ bus->sdiodev->irq_en = true;
|
|
|
+ }
|
|
|
+ spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags);
|
|
|
}
|
|
|
- spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags);
|
|
|
-}
|
|
|
-#else
|
|
|
-static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
|
|
|
-{
|
|
|
}
|
|
|
-#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
|
|
|
|
|
|
static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus)
|
|
|
{
|
|
@@ -2096,7 +2127,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
|
|
sdio_claim_host(bus->sdiodev->func[1]);
|
|
|
|
|
|
/* If waiting for HTAVAIL, check status */
|
|
|
- if (bus->clkstate == CLK_PENDING) {
|
|
|
+ if (!bus->sr_enabled && bus->clkstate == CLK_PENDING) {
|
|
|
u8 clkctl, devctl = 0;
|
|
|
|
|
|
#ifdef DEBUG
|
|
@@ -2142,7 +2173,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
|
|
}
|
|
|
|
|
|
/* Make sure backplane clock is on */
|
|
|
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true);
|
|
|
+ brcmf_sdbrcm_bus_sleep(bus, false, true);
|
|
|
|
|
|
/* Pending interrupt indicates new device status */
|
|
|
if (atomic_read(&bus->ipend) > 0) {
|
|
@@ -2288,8 +2319,9 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
|
|
|
if ((bus->clkstate != CLK_PENDING)
|
|
|
&& bus->idletime == BRCMF_IDLE_IMMEDIATE) {
|
|
|
bus->activity = false;
|
|
|
+ brcmf_dbg(SDIO, "idle state\n");
|
|
|
sdio_claim_host(bus->sdiodev->func[1]);
|
|
|
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
|
|
|
+ brcmf_sdbrcm_bus_sleep(bus, true, false);
|
|
|
sdio_release_host(bus->sdiodev->func[1]);
|
|
|
}
|
|
|
}
|
|
@@ -2362,69 +2394,6 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int
|
|
|
-brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
|
|
|
- uint size)
|
|
|
-{
|
|
|
- int bcmerror = 0;
|
|
|
- u32 sdaddr;
|
|
|
- uint dsize;
|
|
|
-
|
|
|
- /* Determine initial transfer parameters */
|
|
|
- sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
|
|
|
- if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
|
|
|
- dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
|
|
|
- else
|
|
|
- dsize = size;
|
|
|
-
|
|
|
- sdio_claim_host(bus->sdiodev->func[1]);
|
|
|
-
|
|
|
- /* Set the backplane window to include the start address */
|
|
|
- bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address);
|
|
|
- if (bcmerror) {
|
|
|
- brcmf_err("window change failed\n");
|
|
|
- goto xfer_done;
|
|
|
- }
|
|
|
-
|
|
|
- /* Do the transfer(s) */
|
|
|
- while (size) {
|
|
|
- brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
|
|
|
- write ? "write" : "read", dsize,
|
|
|
- sdaddr, address & SBSDIO_SBWINDOW_MASK);
|
|
|
- bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write,
|
|
|
- sdaddr, data, dsize);
|
|
|
- if (bcmerror) {
|
|
|
- brcmf_err("membytes transfer failed\n");
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- /* Adjust for next transfer (if any) */
|
|
|
- size -= dsize;
|
|
|
- if (size) {
|
|
|
- data += dsize;
|
|
|
- address += dsize;
|
|
|
- bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev,
|
|
|
- address);
|
|
|
- if (bcmerror) {
|
|
|
- brcmf_err("window change failed\n");
|
|
|
- break;
|
|
|
- }
|
|
|
- sdaddr = 0;
|
|
|
- dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-xfer_done:
|
|
|
- /* Return the window to backplane enumeration space for core access */
|
|
|
- if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, bus->sdiodev->sbwad))
|
|
|
- brcmf_err("FAILED to set window back to 0x%x\n",
|
|
|
- bus->sdiodev->sbwad);
|
|
|
-
|
|
|
- sdio_release_host(bus->sdiodev->func[1]);
|
|
|
-
|
|
|
- return bcmerror;
|
|
|
-}
|
|
|
-
|
|
|
#ifdef DEBUG
|
|
|
#define CONSOLE_LINE_MAX 192
|
|
|
|
|
@@ -2441,8 +2410,8 @@ static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus)
|
|
|
|
|
|
/* Read console log struct */
|
|
|
addr = bus->console_addr + offsetof(struct rte_console, log_le);
|
|
|
- rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&c->log_le,
|
|
|
- sizeof(c->log_le));
|
|
|
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, (u8 *)&c->log_le,
|
|
|
+ sizeof(c->log_le));
|
|
|
if (rv < 0)
|
|
|
return rv;
|
|
|
|
|
@@ -2467,7 +2436,7 @@ static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus)
|
|
|
|
|
|
/* Read the console buffer */
|
|
|
addr = le32_to_cpu(c->log_le.buf);
|
|
|
- rv = brcmf_sdbrcm_membytes(bus, false, addr, c->buf, c->bufsize);
|
|
|
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, c->buf, c->bufsize);
|
|
|
if (rv < 0)
|
|
|
return rv;
|
|
|
|
|
@@ -2592,7 +2561,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
|
|
|
|
|
|
/* Make sure backplane clock is on */
|
|
|
sdio_claim_host(bus->sdiodev->func[1]);
|
|
|
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
|
|
+ brcmf_sdbrcm_bus_sleep(bus, false, false);
|
|
|
sdio_release_host(bus->sdiodev->func[1]);
|
|
|
|
|
|
/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
|
|
@@ -2650,6 +2619,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
|
|
|
|
|
|
bus->activity = false;
|
|
|
sdio_claim_host(bus->sdiodev->func[1]);
|
|
|
+ brcmf_dbg(INFO, "idle\n");
|
|
|
brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
|
|
|
sdio_release_host(bus->sdiodev->func[1]);
|
|
|
} else {
|
|
@@ -2679,16 +2649,15 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
|
|
|
struct sdpcm_shared_le sh_le;
|
|
|
__le32 addr_le;
|
|
|
|
|
|
- shaddr = bus->ramsize - 4;
|
|
|
+ shaddr = bus->ci->rambase + bus->ramsize - 4;
|
|
|
|
|
|
/*
|
|
|
* Read last word in socram to determine
|
|
|
* address of sdpcm_shared structure
|
|
|
*/
|
|
|
sdio_claim_host(bus->sdiodev->func[1]);
|
|
|
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
|
|
- rv = brcmf_sdbrcm_membytes(bus, false, shaddr,
|
|
|
- (u8 *)&addr_le, 4);
|
|
|
+ brcmf_sdbrcm_bus_sleep(bus, false, false);
|
|
|
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4);
|
|
|
sdio_release_host(bus->sdiodev->func[1]);
|
|
|
if (rv < 0)
|
|
|
return rv;
|
|
@@ -2708,8 +2677,8 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
|
|
|
}
|
|
|
|
|
|
/* Read hndrte_shared structure */
|
|
|
- rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le,
|
|
|
- sizeof(struct sdpcm_shared_le));
|
|
|
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le,
|
|
|
+ sizeof(struct sdpcm_shared_le));
|
|
|
if (rv < 0)
|
|
|
return rv;
|
|
|
|
|
@@ -2745,22 +2714,22 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
|
|
|
|
|
|
/* obtain console information from device memory */
|
|
|
addr = sh->console_addr + offsetof(struct rte_console, log_le);
|
|
|
- rv = brcmf_sdbrcm_membytes(bus, false, addr,
|
|
|
- (u8 *)&sh_val, sizeof(u32));
|
|
|
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr,
|
|
|
+ (u8 *)&sh_val, sizeof(u32));
|
|
|
if (rv < 0)
|
|
|
return rv;
|
|
|
console_ptr = le32_to_cpu(sh_val);
|
|
|
|
|
|
addr = sh->console_addr + offsetof(struct rte_console, log_le.buf_size);
|
|
|
- rv = brcmf_sdbrcm_membytes(bus, false, addr,
|
|
|
- (u8 *)&sh_val, sizeof(u32));
|
|
|
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr,
|
|
|
+ (u8 *)&sh_val, sizeof(u32));
|
|
|
if (rv < 0)
|
|
|
return rv;
|
|
|
console_size = le32_to_cpu(sh_val);
|
|
|
|
|
|
addr = sh->console_addr + offsetof(struct rte_console, log_le.idx);
|
|
|
- rv = brcmf_sdbrcm_membytes(bus, false, addr,
|
|
|
- (u8 *)&sh_val, sizeof(u32));
|
|
|
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr,
|
|
|
+ (u8 *)&sh_val, sizeof(u32));
|
|
|
if (rv < 0)
|
|
|
return rv;
|
|
|
console_index = le32_to_cpu(sh_val);
|
|
@@ -2774,8 +2743,8 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
|
|
|
|
|
|
/* obtain the console data from device */
|
|
|
conbuf[console_size] = '\0';
|
|
|
- rv = brcmf_sdbrcm_membytes(bus, false, console_ptr, (u8 *)conbuf,
|
|
|
- console_size);
|
|
|
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, console_ptr, (u8 *)conbuf,
|
|
|
+ console_size);
|
|
|
if (rv < 0)
|
|
|
goto done;
|
|
|
|
|
@@ -2812,8 +2781,8 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
|
|
|
- sizeof(struct brcmf_trap_info));
|
|
|
+ error = brcmf_sdio_ramrw(bus->sdiodev, false, sh->trap_addr, (u8 *)&tr,
|
|
|
+ sizeof(struct brcmf_trap_info));
|
|
|
if (error < 0)
|
|
|
return error;
|
|
|
|
|
@@ -2856,14 +2825,14 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
|
|
|
|
|
|
sdio_claim_host(bus->sdiodev->func[1]);
|
|
|
if (sh->assert_file_addr != 0) {
|
|
|
- error = brcmf_sdbrcm_membytes(bus, false, sh->assert_file_addr,
|
|
|
- (u8 *)file, 80);
|
|
|
+ error = brcmf_sdio_ramrw(bus->sdiodev, false,
|
|
|
+ sh->assert_file_addr, (u8 *)file, 80);
|
|
|
if (error < 0)
|
|
|
return error;
|
|
|
}
|
|
|
if (sh->assert_exp_addr != 0) {
|
|
|
- error = brcmf_sdbrcm_membytes(bus, false, sh->assert_exp_addr,
|
|
|
- (u8 *)expr, 80);
|
|
|
+ error = brcmf_sdio_ramrw(bus->sdiodev, false,
|
|
|
+ sh->assert_exp_addr, (u8 *)expr, 80);
|
|
|
if (error < 0)
|
|
|
return error;
|
|
|
}
|
|
@@ -3021,84 +2990,8 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
|
|
|
return rxlen ? (int)rxlen : -ETIMEDOUT;
|
|
|
}
|
|
|
|
|
|
-static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus)
|
|
|
-{
|
|
|
- int bcmerror = 0;
|
|
|
- u32 varaddr;
|
|
|
- u32 varsizew;
|
|
|
- __le32 varsizew_le;
|
|
|
-#ifdef DEBUG
|
|
|
- char *nvram_ularray;
|
|
|
-#endif /* DEBUG */
|
|
|
-
|
|
|
- /* Even if there are no vars are to be written, we still
|
|
|
- need to set the ramsize. */
|
|
|
- varaddr = (bus->ramsize - 4) - bus->varsz;
|
|
|
-
|
|
|
- if (bus->vars) {
|
|
|
- /* Write the vars list */
|
|
|
- bcmerror = brcmf_sdbrcm_membytes(bus, true, varaddr,
|
|
|
- bus->vars, bus->varsz);
|
|
|
-#ifdef DEBUG
|
|
|
- /* Verify NVRAM bytes */
|
|
|
- brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n",
|
|
|
- bus->varsz);
|
|
|
- nvram_ularray = kmalloc(bus->varsz, GFP_ATOMIC);
|
|
|
- if (!nvram_ularray)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- /* Upload image to verify downloaded contents. */
|
|
|
- memset(nvram_ularray, 0xaa, bus->varsz);
|
|
|
-
|
|
|
- /* Read the vars list to temp buffer for comparison */
|
|
|
- bcmerror = brcmf_sdbrcm_membytes(bus, false, varaddr,
|
|
|
- nvram_ularray, bus->varsz);
|
|
|
- if (bcmerror) {
|
|
|
- brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n",
|
|
|
- bcmerror, bus->varsz, varaddr);
|
|
|
- }
|
|
|
- /* Compare the org NVRAM with the one read from RAM */
|
|
|
- if (memcmp(bus->vars, nvram_ularray, bus->varsz))
|
|
|
- brcmf_err("Downloaded NVRAM image is corrupted\n");
|
|
|
- else
|
|
|
- brcmf_err("Download/Upload/Compare of NVRAM ok\n");
|
|
|
-
|
|
|
- kfree(nvram_ularray);
|
|
|
-#endif /* DEBUG */
|
|
|
- }
|
|
|
-
|
|
|
- /* adjust to the user specified RAM */
|
|
|
- brcmf_dbg(INFO, "Physical memory size: %d\n", bus->ramsize);
|
|
|
- brcmf_dbg(INFO, "Vars are at %d, orig varsize is %d\n",
|
|
|
- varaddr, bus->varsz);
|
|
|
-
|
|
|
- /*
|
|
|
- * Determine the length token:
|
|
|
- * Varsize, converted to words, in lower 16-bits, checksum
|
|
|
- * in upper 16-bits.
|
|
|
- */
|
|
|
- if (bcmerror) {
|
|
|
- varsizew = 0;
|
|
|
- varsizew_le = cpu_to_le32(0);
|
|
|
- } else {
|
|
|
- varsizew = bus->varsz / 4;
|
|
|
- varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
|
|
|
- varsizew_le = cpu_to_le32(varsizew);
|
|
|
- }
|
|
|
-
|
|
|
- brcmf_dbg(INFO, "New varsize is %d, length token=0x%08x\n",
|
|
|
- bus->varsz, varsizew);
|
|
|
-
|
|
|
- /* Write the length token to the last word */
|
|
|
- bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->ramsize - 4),
|
|
|
- (u8 *)&varsizew_le, 4);
|
|
|
-
|
|
|
- return bcmerror;
|
|
|
-}
|
|
|
-
|
|
|
-static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
|
|
|
+static bool brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
|
|
|
{
|
|
|
- int bcmerror = 0;
|
|
|
struct chip_info *ci = bus->ci;
|
|
|
|
|
|
/* To enter download state, disable ARM and reset SOCRAM.
|
|
@@ -3107,41 +3000,19 @@ static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
|
|
|
if (enter) {
|
|
|
bus->alp_only = true;
|
|
|
|
|
|
- ci->coredisable(bus->sdiodev, ci, BCMA_CORE_ARM_CM3);
|
|
|
-
|
|
|
- ci->resetcore(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM);
|
|
|
-
|
|
|
- /* Clear the top bit of memory */
|
|
|
- if (bus->ramsize) {
|
|
|
- u32 zeros = 0;
|
|
|
- brcmf_sdbrcm_membytes(bus, true, bus->ramsize - 4,
|
|
|
- (u8 *)&zeros, 4);
|
|
|
- }
|
|
|
+ brcmf_sdio_chip_enter_download(bus->sdiodev, ci);
|
|
|
} else {
|
|
|
- if (!ci->iscoreup(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
|
|
|
- brcmf_err("SOCRAM core is down after reset?\n");
|
|
|
- bcmerror = -EBADE;
|
|
|
- goto fail;
|
|
|
- }
|
|
|
-
|
|
|
- bcmerror = brcmf_sdbrcm_write_vars(bus);
|
|
|
- if (bcmerror) {
|
|
|
- brcmf_err("no vars written to RAM\n");
|
|
|
- bcmerror = 0;
|
|
|
- }
|
|
|
-
|
|
|
- w_sdreg32(bus, 0xFFFFFFFF,
|
|
|
- offsetof(struct sdpcmd_regs, intstatus));
|
|
|
-
|
|
|
- ci->resetcore(bus->sdiodev, ci, BCMA_CORE_ARM_CM3);
|
|
|
+ if (!brcmf_sdio_chip_exit_download(bus->sdiodev, ci, bus->vars,
|
|
|
+ bus->varsz))
|
|
|
+ return false;
|
|
|
|
|
|
/* Allow HT Clock now that the ARM is running. */
|
|
|
bus->alp_only = false;
|
|
|
|
|
|
bus->sdiodev->bus_if->state = BRCMF_BUS_LOAD;
|
|
|
}
|
|
|
-fail:
|
|
|
- return bcmerror;
|
|
|
+
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_sdio *bus)
|
|
@@ -3156,10 +3027,11 @@ static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_sdio *bus)
|
|
|
|
|
|
static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
|
|
|
{
|
|
|
- int offset = 0;
|
|
|
+ int offset;
|
|
|
uint len;
|
|
|
u8 *memblock = NULL, *memptr;
|
|
|
int ret;
|
|
|
+ u8 idx;
|
|
|
|
|
|
brcmf_dbg(INFO, "Enter\n");
|
|
|
|
|
@@ -3180,10 +3052,15 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
|
|
|
memptr += (BRCMF_SDALIGN -
|
|
|
((u32)(unsigned long)memblock % BRCMF_SDALIGN));
|
|
|
|
|
|
+ offset = bus->ci->rambase;
|
|
|
+
|
|
|
/* Download image */
|
|
|
- while ((len =
|
|
|
- brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus))) {
|
|
|
- ret = brcmf_sdbrcm_membytes(bus, true, offset, memptr, len);
|
|
|
+ len = brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus);
|
|
|
+ idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_ARM_CR4);
|
|
|
+ if (BRCMF_MAX_CORENUM != idx)
|
|
|
+ memcpy(&bus->ci->rst_vec, memptr, sizeof(bus->ci->rst_vec));
|
|
|
+ while (len) {
|
|
|
+ ret = brcmf_sdio_ramrw(bus->sdiodev, true, offset, memptr, len);
|
|
|
if (ret) {
|
|
|
brcmf_err("error %d on writing %d membytes at 0x%08x\n",
|
|
|
ret, MEMBLOCK, offset);
|
|
@@ -3191,6 +3068,7 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
|
|
|
}
|
|
|
|
|
|
offset += MEMBLOCK;
|
|
|
+ len = brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus);
|
|
|
}
|
|
|
|
|
|
err:
|
|
@@ -3298,7 +3176,7 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
|
|
|
int bcmerror = -1;
|
|
|
|
|
|
/* Keep arm in reset */
|
|
|
- if (brcmf_sdbrcm_download_state(bus, true)) {
|
|
|
+ if (!brcmf_sdbrcm_download_state(bus, true)) {
|
|
|
brcmf_err("error placing ARM core in reset\n");
|
|
|
goto err;
|
|
|
}
|
|
@@ -3314,7 +3192,7 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
|
|
|
}
|
|
|
|
|
|
/* Take arm out of reset */
|
|
|
- if (brcmf_sdbrcm_download_state(bus, false)) {
|
|
|
+ if (!brcmf_sdbrcm_download_state(bus, false)) {
|
|
|
brcmf_err("error getting out of ARM core reset\n");
|
|
|
goto err;
|
|
|
}
|
|
@@ -3325,6 +3203,103 @@ err:
|
|
|
return bcmerror;
|
|
|
}
|
|
|
|
|
|
+static bool brcmf_sdbrcm_sr_capable(struct brcmf_sdio *bus)
|
|
|
+{
|
|
|
+ u32 addr, reg;
|
|
|
+
|
|
|
+ brcmf_dbg(TRACE, "Enter\n");
|
|
|
+
|
|
|
+ /* old chips with PMU version less than 17 don't support save restore */
|
|
|
+ if (bus->ci->pmurev < 17)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ /* read PMU chipcontrol register 3*/
|
|
|
+ addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_addr);
|
|
|
+ brcmf_sdio_regwl(bus->sdiodev, addr, 3, NULL);
|
|
|
+ addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_data);
|
|
|
+ reg = brcmf_sdio_regrl(bus->sdiodev, addr, NULL);
|
|
|
+
|
|
|
+ return (bool)reg;
|
|
|
+}
|
|
|
+
|
|
|
+static void brcmf_sdbrcm_sr_init(struct brcmf_sdio *bus)
|
|
|
+{
|
|
|
+ int err = 0;
|
|
|
+ u8 val;
|
|
|
+
|
|
|
+ brcmf_dbg(TRACE, "Enter\n");
|
|
|
+
|
|
|
+ val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL,
|
|
|
+ &err);
|
|
|
+ if (err) {
|
|
|
+ brcmf_err("error reading SBSDIO_FUNC1_WAKEUPCTRL\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
|
|
|
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL,
|
|
|
+ val, &err);
|
|
|
+ if (err) {
|
|
|
+ brcmf_err("error writing SBSDIO_FUNC1_WAKEUPCTRL\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Add CMD14 Support */
|
|
|
+ brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP,
|
|
|
+ (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
|
|
|
+ SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT),
|
|
|
+ &err);
|
|
|
+ if (err) {
|
|
|
+ brcmf_err("error writing SDIO_CCCR_BRCM_CARDCAP\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
|
|
|
+ SBSDIO_FORCE_HT, &err);
|
|
|
+ if (err) {
|
|
|
+ brcmf_err("error writing SBSDIO_FUNC1_CHIPCLKCSR\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* set flag */
|
|
|
+ bus->sr_enabled = true;
|
|
|
+ brcmf_dbg(INFO, "SR enabled\n");
|
|
|
+}
|
|
|
+
|
|
|
+/* enable KSO bit */
|
|
|
+static int brcmf_sdbrcm_kso_init(struct brcmf_sdio *bus)
|
|
|
+{
|
|
|
+ u8 val;
|
|
|
+ int err = 0;
|
|
|
+
|
|
|
+ brcmf_dbg(TRACE, "Enter\n");
|
|
|
+
|
|
|
+ /* KSO bit added in SDIO core rev 12 */
|
|
|
+ if (bus->ci->c_inf[1].rev < 12)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
|
|
|
+ &err);
|
|
|
+ if (err) {
|
|
|
+ brcmf_err("error reading SBSDIO_FUNC1_SLEEPCSR\n");
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
|
|
|
+ val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN <<
|
|
|
+ SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
|
|
|
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
|
|
|
+ val, &err);
|
|
|
+ if (err) {
|
|
|
+ brcmf_err("error writing SBSDIO_FUNC1_SLEEPCSR\n");
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
static bool
|
|
|
brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
|
|
|
{
|
|
@@ -3423,8 +3398,13 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
|
|
|
ret = -ENODEV;
|
|
|
}
|
|
|
|
|
|
- /* Restore previous clock setting */
|
|
|
- brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
|
|
|
+ if (brcmf_sdbrcm_sr_capable(bus)) {
|
|
|
+ brcmf_sdbrcm_sr_init(bus);
|
|
|
+ } else {
|
|
|
+ /* Restore previous clock setting */
|
|
|
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
|
|
|
+ saveclk, &err);
|
|
|
+ }
|
|
|
|
|
|
if (ret == 0) {
|
|
|
ret = brcmf_sdio_intr_register(bus->sdiodev);
|
|
@@ -3485,7 +3465,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
|
|
|
brcmf_dbg(TIMER, "Enter\n");
|
|
|
|
|
|
/* Poll period: check device if appropriate. */
|
|
|
- if (bus->poll && (++bus->polltick >= bus->pollrate)) {
|
|
|
+ if (!bus->sr_enabled &&
|
|
|
+ bus->poll && (++bus->polltick >= bus->pollrate)) {
|
|
|
u32 intstatus = 0;
|
|
|
|
|
|
/* Reset poll tick */
|
|
@@ -3536,7 +3517,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
|
|
|
bus->console.count -= bus->console_interval;
|
|
|
sdio_claim_host(bus->sdiodev->func[1]);
|
|
|
/* Make sure backplane clock is on */
|
|
|
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
|
|
+ brcmf_sdbrcm_bus_sleep(bus, false, false);
|
|
|
if (brcmf_sdbrcm_readconsole(bus) < 0)
|
|
|
/* stop on error */
|
|
|
bus->console_interval = 0;
|
|
@@ -3553,8 +3534,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
|
|
|
bus->activity = false;
|
|
|
brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
|
|
|
} else {
|
|
|
+ brcmf_dbg(SDIO, "idle\n");
|
|
|
sdio_claim_host(bus->sdiodev->func[1]);
|
|
|
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
|
|
|
+ brcmf_sdbrcm_bus_sleep(bus, true, false);
|
|
|
sdio_release_host(bus->sdiodev->func[1]);
|
|
|
}
|
|
|
}
|
|
@@ -3565,6 +3547,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
|
|
|
|
|
|
static bool brcmf_sdbrcm_chipmatch(u16 chipid)
|
|
|
{
|
|
|
+ if (chipid == BCM43143_CHIP_ID)
|
|
|
+ return true;
|
|
|
if (chipid == BCM43241_CHIP_ID)
|
|
|
return true;
|
|
|
if (chipid == BCM4329_CHIP_ID)
|
|
@@ -3573,6 +3557,8 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid)
|
|
|
return true;
|
|
|
if (chipid == BCM4334_CHIP_ID)
|
|
|
return true;
|
|
|
+ if (chipid == BCM4335_CHIP_ID)
|
|
|
+ return true;
|
|
|
return false;
|
|
|
}
|
|
|
|
|
@@ -3650,7 +3636,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
|
|
|
int err = 0;
|
|
|
int reg_addr;
|
|
|
u32 reg_val;
|
|
|
- u8 idx;
|
|
|
+ u32 drivestrength;
|
|
|
|
|
|
bus->alp_only = true;
|
|
|
|
|
@@ -3686,8 +3672,16 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci,
|
|
|
- SDIO_DRIVE_STRENGTH);
|
|
|
+ if (brcmf_sdbrcm_kso_init(bus)) {
|
|
|
+ brcmf_err("error enabling KSO\n");
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((bus->sdiodev->pdata) && (bus->sdiodev->pdata->drive_strength))
|
|
|
+ drivestrength = bus->sdiodev->pdata->drive_strength;
|
|
|
+ else
|
|
|
+ drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH;
|
|
|
+ brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength);
|
|
|
|
|
|
/* Get info on the SOCRAM cores... */
|
|
|
bus->ramsize = bus->ci->ramsize;
|
|
@@ -3696,12 +3690,37 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- /* Set core control so an SDIO reset does a backplane reset */
|
|
|
- idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
|
|
|
- reg_addr = bus->ci->c_inf[idx].base +
|
|
|
- offsetof(struct sdpcmd_regs, corecontrol);
|
|
|
- reg_val = brcmf_sdio_regrl(bus->sdiodev, reg_addr, NULL);
|
|
|
- brcmf_sdio_regwl(bus->sdiodev, reg_addr, reg_val | CC_BPRESEN, NULL);
|
|
|
+ /* Set card control so an SDIO card reset does a WLAN backplane reset */
|
|
|
+ reg_val = brcmf_sdio_regrb(bus->sdiodev,
|
|
|
+ SDIO_CCCR_BRCM_CARDCTRL, &err);
|
|
|
+ if (err)
|
|
|
+ goto fail;
|
|
|
+
|
|
|
+ reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET;
|
|
|
+
|
|
|
+ brcmf_sdio_regwb(bus->sdiodev,
|
|
|
+ SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err);
|
|
|
+ if (err)
|
|
|
+ goto fail;
|
|
|
+
|
|
|
+ /* set PMUControl so a backplane reset does PMU state reload */
|
|
|
+ reg_addr = CORE_CC_REG(bus->ci->c_inf[0].base,
|
|
|
+ pmucontrol);
|
|
|
+ reg_val = brcmf_sdio_regrl(bus->sdiodev,
|
|
|
+ reg_addr,
|
|
|
+ &err);
|
|
|
+ if (err)
|
|
|
+ goto fail;
|
|
|
+
|
|
|
+ reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT);
|
|
|
+
|
|
|
+ brcmf_sdio_regwl(bus->sdiodev,
|
|
|
+ reg_addr,
|
|
|
+ reg_val,
|
|
|
+ &err);
|
|
|
+ if (err)
|
|
|
+ goto fail;
|
|
|
+
|
|
|
|
|
|
sdio_release_host(bus->sdiodev->func[1]);
|
|
|
|
|
@@ -3755,6 +3774,10 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
|
|
|
bus->use_rxchain = false;
|
|
|
bus->sd_rxchain = false;
|
|
|
|
|
|
+ /* SR state */
|
|
|
+ bus->sleeping = false;
|
|
|
+ bus->sr_enabled = false;
|
|
|
+
|
|
|
return true;
|
|
|
}
|
|
|
|