Skip to content

Commit

Permalink
brcmfmac: switch to new platform data
Browse files Browse the repository at this point in the history
Platform data is only available for sdio. With this patch a new
platform data structure is being used which allows for platform
data for any device and configurable per device. This patch only
switches to the new structure and adds support for SDIO devices.

Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  • Loading branch information
Hante Meuleman authored and Kalle Valo committed Mar 7, 2016
1 parent 73ef9e6 commit 4d79289
Showing 10 changed files with 282 additions and 222 deletions.
15 changes: 2 additions & 13 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
Original file line number Diff line number Diff line change
@@ -103,7 +103,7 @@ static void brcmf_sdiod_dummy_irqhandler(struct sdio_func *func)

int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)
{
struct brcmfmac_sdio_platform_data *pdata;
struct brcmfmac_sdio_pd *pdata;
int ret = 0;
u8 data;
u32 addr, gpiocontrol;
@@ -173,7 +173,7 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)

int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev)
{
struct brcmfmac_sdio_platform_data *pdata;
struct brcmfmac_sdio_pd *pdata;

brcmf_dbg(SDIO, "Entering\n");

@@ -1164,17 +1164,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
dev_set_drvdata(&func->dev, bus_if);
dev_set_drvdata(&sdiodev->func[1]->dev, bus_if);
sdiodev->dev = &sdiodev->func[1]->dev;
sdiodev->pdata = brcmf_get_module_param(sdiodev->dev);

#ifdef CONFIG_PM_SLEEP
/* wowl can be supported when KEEP_POWER is true and (WAKE_SDIO_IRQ
* is true or when platform data OOB irq is true).
*/
if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) &&
((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) ||
(sdiodev->pdata && sdiodev->pdata->oob_irq_supported)))
bus_if->wowl_supported = true;
#endif

brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_DOWN);

4 changes: 2 additions & 2 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
Original file line number Diff line number Diff line change
@@ -6459,8 +6459,8 @@ int brcmf_cfg80211_wait_vif_event(struct brcmf_cfg80211_info *cfg,
static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2],
struct brcmf_fil_country_le *ccreq)
{
struct cc_translate *country_codes;
struct cc_entry *cc;
struct brcmfmac_pd_cc *country_codes;
struct brcmfmac_pd_cc_entry *cc;
s32 found_index;
int i;

43 changes: 37 additions & 6 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
Original file line number Diff line number Diff line change
@@ -80,7 +80,7 @@ module_param_named(ignore_probe_fail, brcmf_ignore_probe_fail, int, 0);
MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging");
#endif

static struct brcmfmac_sdio_platform_data *brcmfmac_pdata;
static struct brcmfmac_platform_data *brcmfmac_pdata;
struct brcmf_mp_global_t brcmf_mp_global;

int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
@@ -229,15 +229,46 @@ void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...)

static void brcmf_mp_attach(void)
{
/* If module param firmware path is set then this will always be used,
* if not set then if available use the platform data version. To make
* sure it gets initialized at all, always copy the module param version
*/
strlcpy(brcmf_mp_global.firmware_path, brcmf_firmware_path,
BRCMF_FW_ALTPATH_LEN);
if ((brcmfmac_pdata) && (brcmfmac_pdata->fw_alternative_path) &&
(brcmf_mp_global.firmware_path[0] == '\0')) {
strlcpy(brcmf_mp_global.firmware_path,
brcmfmac_pdata->fw_alternative_path,
BRCMF_FW_ALTPATH_LEN);
}
}

struct brcmfmac_sdio_platform_data *brcmf_get_module_param(struct device *dev)
struct brcmfmac_sdio_pd *brcmf_get_module_param(struct device *dev,
enum brcmf_bus_type bus_type,
u32 chip, u32 chiprev)
{
if (!brcmfmac_pdata)
brcmf_of_probe(dev, &brcmfmac_pdata);
return brcmfmac_pdata;
struct brcmfmac_sdio_pd *pdata;
struct brcmfmac_pd_device *device_pd;
int i;

if (brcmfmac_pdata) {
for (i = 0; i < brcmfmac_pdata->device_count; i++) {
device_pd = &brcmfmac_pdata->devices[i];
if ((device_pd->bus_type == bus_type) &&
(device_pd->id == chip) &&
((device_pd->rev == chiprev) ||
(device_pd->rev == -1))) {
brcmf_dbg(INFO, "Platform data for device found\n");
if (device_pd->bus_type == BRCMF_BUSTYPE_SDIO)
return &device_pd->bus.sdio;
break;
}
}
}
pdata = NULL;
brcmf_of_probe(dev, &pdata);

return pdata;
}

int brcmf_mp_device_attach(struct brcmf_pub *drvr)
@@ -287,7 +318,7 @@ static int brcmf_common_pd_remove(struct platform_device *pdev)
static struct platform_driver brcmf_pd = {
.remove = brcmf_common_pd_remove,
.driver = {
.name = BRCMFMAC_SDIO_PDATA_NAME,
.name = BRCMFMAC_PDATA_NAME,
}
};

35 changes: 5 additions & 30 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@
#define BRCMFMAC_COMMON_H

#include <linux/platform_device.h>
#include <linux/platform_data/brcmfmac-sdio.h>
#include <linux/platform_data/brcmfmac.h>
#include "fwil_types.h"

extern const u8 ALLFFMAC[ETH_ALEN];
@@ -42,33 +42,6 @@ struct brcmf_mp_global_t {

extern struct brcmf_mp_global_t brcmf_mp_global;

/**
* struct cc_entry - Struct for translating user space country code (iso3166) to
* firmware country code and revision.
*
* @iso3166: iso3166 alpha 2 country code string.
* @cc: firmware country code string.
* @rev: firmware country code revision.
*/
struct cc_entry {
char iso3166[BRCMF_COUNTRY_BUF_SZ];
char cc[BRCMF_COUNTRY_BUF_SZ];
s32 rev;
};

/**
* struct cc_translate - Struct for translating country codes as set by user
* space to a country code and rev which can be used by
* firmware.
*
* @table_size: number of entries in table (> 0)
* @table: dynamic array of 1 or more elements with translation information.
*/
struct cc_translate {
int table_size;
struct cc_entry table[0];
};

/**
* struct brcmf_mp_device - Device module paramaters.
*
@@ -88,10 +61,12 @@ struct brcmf_mp_device {
int fcmode;
bool roamoff;
bool ignore_probe_fail;
struct cc_translate *country_codes;
struct brcmfmac_pd_cc *country_codes;
};

struct brcmfmac_sdio_platform_data *brcmf_get_module_param(struct device *dev);
struct brcmfmac_sdio_pd *brcmf_get_module_param(struct device *dev,
enum brcmf_bus_type bus_type,
u32 chip, u32 chiprev);
int brcmf_mp_device_attach(struct brcmf_pub *drvr);
void brcmf_mp_device_detach(struct brcmf_pub *drvr);
#ifdef DEBUG
3 changes: 1 addition & 2 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
Original file line number Diff line number Diff line change
@@ -23,8 +23,7 @@
#include "common.h"
#include "of.h"

void
brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_platform_data **sdio)
void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd **sdio)
{
struct device_node *np = dev->of_node;
int irq;
5 changes: 2 additions & 3 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
Original file line number Diff line number Diff line change
@@ -15,10 +15,9 @@
*/
#ifdef CONFIG_OF
void
brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_platform_data **sdio);
brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd **sdio);
#else
static void brcmf_of_probe(struct device *dev,
struct brcmfmac_sdio_platform_data **sdio)
static void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd **sdio)
{
}
#endif /* CONFIG_OF */
77 changes: 47 additions & 30 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
Original file line number Diff line number Diff line change
@@ -33,8 +33,6 @@
#include <linux/bcma/bcma.h>
#include <linux/debugfs.h>
#include <linux/vmalloc.h>
#include <linux/platform_data/brcmfmac-sdio.h>
#include <linux/moduleparam.h>
#include <asm/unaligned.h>
#include <defs.h>
#include <brcmu_wifi.h>
@@ -44,6 +42,8 @@
#include "sdio.h"
#include "chip.h"
#include "firmware.h"
#include "core.h"
#include "common.h"

#define DCMD_RESP_TIMEOUT msecs_to_jiffies(2500)
#define CTL_DONE_TIMEOUT msecs_to_jiffies(2500)
@@ -3775,26 +3775,28 @@ static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = {
static bool
brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
{
struct brcmf_sdio_dev *sdiodev;
u8 clkctl = 0;
int err = 0;
int reg_addr;
u32 reg_val;
u32 drivestrength;

sdio_claim_host(bus->sdiodev->func[1]);
sdiodev = bus->sdiodev;
sdio_claim_host(sdiodev->func[1]);

pr_debug("F1 signature read @0x18000000=0x%4x\n",
brcmf_sdiod_regrl(bus->sdiodev, SI_ENUM_BASE, NULL));
brcmf_sdiod_regrl(sdiodev, SI_ENUM_BASE, NULL));

/*
* Force PLL off until brcmf_chip_attach()
* programs PLL control regs
*/

brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
BRCMF_INIT_CLKCTL1, &err);
if (!err)
clkctl = brcmf_sdiod_regrb(bus->sdiodev,
clkctl = brcmf_sdiod_regrb(sdiodev,
SBSDIO_FUNC1_CHIPCLKCSR, &err);

if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) {
@@ -3803,50 +3805,77 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
goto fail;
}

bus->ci = brcmf_chip_attach(bus->sdiodev, &brcmf_sdio_buscore_ops);
bus->ci = brcmf_chip_attach(sdiodev, &brcmf_sdio_buscore_ops);
if (IS_ERR(bus->ci)) {
brcmf_err("brcmf_chip_attach failed!\n");
bus->ci = NULL;
goto fail;
}
sdiodev->pdata = brcmf_get_module_param(sdiodev->dev,
BRCMF_BUSTYPE_SDIO,
bus->ci->chip,
bus->ci->chiprev);
/* platform specific configuration:
* alignments must be at least 4 bytes for ADMA
*/
bus->head_align = ALIGNMENT;
bus->sgentry_align = ALIGNMENT;
if (sdiodev->pdata) {
if (sdiodev->pdata->sd_head_align > ALIGNMENT)
bus->head_align = sdiodev->pdata->sd_head_align;
if (sdiodev->pdata->sd_sgentry_align > ALIGNMENT)
bus->sgentry_align = sdiodev->pdata->sd_sgentry_align;
}
/* allocate scatter-gather table. sg support
* will be disabled upon allocation failure.
*/
brcmf_sdiod_sgtable_alloc(sdiodev);

#ifdef CONFIG_PM_SLEEP
/* wowl can be supported when KEEP_POWER is true and (WAKE_SDIO_IRQ
* is true or when platform data OOB irq is true).
*/
if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) &&
((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) ||
(sdiodev->pdata && sdiodev->pdata->oob_irq_supported)))
sdiodev->bus_if->wowl_supported = true;
#endif

if (brcmf_sdio_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;
if ((sdiodev->pdata) && (sdiodev->pdata->drive_strength))
drivestrength = sdiodev->pdata->drive_strength;
else
drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH;
brcmf_sdio_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength);
brcmf_sdio_drivestrengthinit(sdiodev, bus->ci, drivestrength);

/* Set card control so an SDIO card reset does a WLAN backplane reset */
reg_val = brcmf_sdiod_regrb(bus->sdiodev,
SDIO_CCCR_BRCM_CARDCTRL, &err);
reg_val = brcmf_sdiod_regrb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, &err);
if (err)
goto fail;

reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET;

brcmf_sdiod_regwb(bus->sdiodev,
SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err);
brcmf_sdiod_regwb(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(brcmf_chip_get_pmu(bus->ci)->base, pmucontrol);
reg_val = brcmf_sdiod_regrl(bus->sdiodev, reg_addr, &err);
reg_val = brcmf_sdiod_regrl(sdiodev, reg_addr, &err);
if (err)
goto fail;

reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT);

brcmf_sdiod_regwl(bus->sdiodev, reg_addr, reg_val, &err);
brcmf_sdiod_regwl(sdiodev, reg_addr, reg_val, &err);
if (err)
goto fail;

sdio_release_host(bus->sdiodev->func[1]);
sdio_release_host(sdiodev->func[1]);

brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);

@@ -3867,7 +3896,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
return true;

fail:
sdio_release_host(bus->sdiodev->func[1]);
sdio_release_host(sdiodev->func[1]);
return false;
}

@@ -4045,18 +4074,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
bus->txminmax = BRCMF_TXMINMAX;
bus->tx_seq = SDPCM_SEQ_WRAP - 1;

/* platform specific configuration:
* alignments must be at least 4 bytes for ADMA
*/
bus->head_align = ALIGNMENT;
bus->sgentry_align = ALIGNMENT;
if (sdiodev->pdata) {
if (sdiodev->pdata->sd_head_align > ALIGNMENT)
bus->head_align = sdiodev->pdata->sd_head_align;
if (sdiodev->pdata->sd_sgentry_align > ALIGNMENT)
bus->sgentry_align = sdiodev->pdata->sd_sgentry_align;
}

/* single-threaded workqueue */
wq = alloc_ordered_workqueue("brcmf_wq/%s", WQ_MEM_RECLAIM,
dev_name(&sdiodev->func[1]->dev));
2 changes: 1 addition & 1 deletion drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
Original file line number Diff line number Diff line change
@@ -184,7 +184,7 @@ struct brcmf_sdio_dev {
struct brcmf_sdio *bus;
struct device *dev;
struct brcmf_bus *bus_if;
struct brcmfmac_sdio_platform_data *pdata;
struct brcmfmac_sdio_pd *pdata;
bool oob_irq_requested;
bool irq_en; /* irq enable flags */
spinlock_t irq_en_lock;
Loading

0 comments on commit 4d79289

Please sign in to comment.