u32 addr, gpiocontrol;
unsigned long flags;
- pdata = sdiodev->pdata;
- if ((pdata) && (pdata->oob_irq_supported)) {
+ pdata = &sdiodev->settings->bus.sdio;
+ if (pdata->oob_irq_supported) {
brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n",
pdata->oob_irq_nr);
ret = request_irq(pdata->oob_irq_nr, brcmf_sdiod_oob_irqhandler,
brcmf_dbg(SDIO, "Entering\n");
- pdata = sdiodev->pdata;
- if ((pdata) && (pdata->oob_irq_supported)) {
+ pdata = &sdiodev->settings->bus.sdio;
+ if (pdata->oob_irq_supported) {
sdio_claim_host(sdiodev->func[1]);
brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
target_list = pktlist;
/* for host with broken sg support, prepare a page aligned list */
__skb_queue_head_init(&local_list);
- if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) {
+ if (!write && sdiodev->settings->bus.sdio.broken_sg_support) {
req_sz = 0;
skb_queue_walk(pktlist, pkt_next)
req_sz += pkt_next->len;
}
}
- if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) {
+ if (!write && sdiodev->settings->bus.sdio.broken_sg_support) {
local_pkt_next = local_list.next;
orig_offset = 0;
skb_queue_walk(pktlist, pkt_next) {
return;
nents = max_t(uint, BRCMF_DEFAULT_RXGLOM_SIZE,
- sdiodev->bus_if->drvr->settings->sdiod_txglomsz);
+ sdiodev->settings->bus.sdio.txglomsz);
nents += (nents >> 4) + 1;
WARN_ON(nents > sdiodev->max_segment_count);
sdiodev->sg_support = false;
}
- sdiodev->txglomsz = sdiodev->bus_if->drvr->settings->sdiod_txglomsz;
+ sdiodev->txglomsz = sdiodev->settings->bus.sdio.txglomsz;
}
#ifdef CONFIG_PM_SLEEP
sdio_flags = MMC_PM_KEEP_POWER;
if (sdiodev->wowl_enabled) {
- if (sdiodev->pdata->oob_irq_supported)
- enable_irq_wake(sdiodev->pdata->oob_irq_nr);
+ if (sdiodev->settings->bus.sdio.oob_irq_supported)
+ enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
else
sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
}
BRCMF_PROTO_MSGBUF
};
+struct brcmf_mp_device;
+
struct brcmf_bus_dcmd {
char *name;
char *param;
void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp);
/* Indication from bus module regarding presence/insertion of dongle. */
-int brcmf_attach(struct device *dev);
+int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings);
/* Indication from bus module regarding removal/absence of dongle */
void brcmf_detach(struct device *dev);
/* Indication from bus module that dongle should be reset */
}
}
-struct brcmfmac_sdio_pd *brcmf_get_module_param(struct device *dev,
- enum brcmf_bus_type bus_type,
- u32 chip, u32 chiprev)
+struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
+ enum brcmf_bus_type bus_type,
+ u32 chip, u32 chiprev)
{
- struct brcmfmac_sdio_pd *pdata;
+ struct brcmf_mp_device *settings;
struct brcmfmac_pd_device *device_pd;
+ bool found;
int i;
+ brcmf_dbg(INFO, "Enter, bus=%d, chip=%d, rev=%d\n", bus_type, chip,
+ chiprev);
+ settings = kzalloc(sizeof(*settings), GFP_ATOMIC);
+ if (!settings)
+ return NULL;
+
+ /* start by using the module paramaters */
+ settings->p2p_enable = !!brcmf_p2p_enable;
+ settings->feature_disable = brcmf_feature_disable;
+ settings->fcmode = brcmf_fcmode;
+ settings->roamoff = !!brcmf_roamoff;
+#ifdef DEBUG
+ settings->ignore_probe_fail = !!brcmf_ignore_probe_fail;
+#endif
+
+ if (bus_type == BRCMF_BUSTYPE_SDIO)
+ settings->bus.sdio.txglomsz = brcmf_sdiod_txglomsz;
+
+ /* See if there is any device specific platform data configured */
+ found = false;
if (brcmfmac_pdata) {
for (i = 0; i < brcmfmac_pdata->device_count; i++) {
device_pd = &brcmfmac_pdata->devices[i];
((device_pd->rev == chiprev) ||
(device_pd->rev == -1))) {
brcmf_dbg(INFO, "Platform data for device found\n");
+ settings->country_codes =
+ device_pd->country_codes;
if (device_pd->bus_type == BRCMF_BUSTYPE_SDIO)
- return &device_pd->bus.sdio;
+ memcpy(&settings->bus.sdio,
+ &device_pd->bus.sdio,
+ sizeof(settings->bus.sdio));
+ found = true;
break;
}
}
}
- pdata = NULL;
- brcmf_of_probe(dev, &pdata);
-
- return pdata;
-}
-
-int brcmf_mp_device_attach(struct brcmf_pub *drvr)
-{
- drvr->settings = kzalloc(sizeof(*drvr->settings), GFP_ATOMIC);
- if (!drvr->settings)
- return -ENOMEM;
-
- drvr->settings->sdiod_txglomsz = brcmf_sdiod_txglomsz;
- drvr->settings->p2p_enable = !!brcmf_p2p_enable;
- drvr->settings->feature_disable = brcmf_feature_disable;
- drvr->settings->fcmode = brcmf_fcmode;
- drvr->settings->roamoff = !!brcmf_roamoff;
-#ifdef DEBUG
- drvr->settings->ignore_probe_fail = !!brcmf_ignore_probe_fail;
-#endif
- return 0;
+ if ((bus_type == BRCMF_BUSTYPE_SDIO) && (!found)) {
+ /* No platform data for this device. In case of SDIO try OF
+ * (Open Firwmare) Device Tree.
+ */
+ brcmf_of_probe(dev, &settings->bus.sdio);
+ }
+ return settings;
}
-void brcmf_mp_device_detach(struct brcmf_pub *drvr)
+void brcmf_release_module_param(struct brcmf_mp_device *module_param)
{
- kfree(drvr->settings);
+ kfree(module_param);
}
static int __init brcmf_common_pd_probe(struct platform_device *pdev)
/**
* struct brcmf_mp_device - Device module paramaters.
*
- * @sdiod_txglomsz: SDIO txglom size.
- * @joinboost_5g_rssi: 5g rssi booost for preferred join selection.
* @p2p_enable: Legacy P2P0 enable (old wpa_supplicant).
* @feature_disable: Feature_disable bitmask.
* @fcmode: FWS flow control.
* @roamoff: Firmware roaming off?
+ * @ignore_probe_fail: Ignore probe failure.
* @country_codes: If available, pointer to struct for translating country codes
+ * @bus: Bus specific platform data. Only SDIO at the mmoment.
*/
struct brcmf_mp_device {
- int sdiod_txglomsz;
- int joinboost_5g_rssi;
- bool p2p_enable;
- int feature_disable;
- int fcmode;
- bool roamoff;
- bool ignore_probe_fail;
+ bool p2p_enable;
+ unsigned int feature_disable;
+ int fcmode;
+ bool roamoff;
+ bool ignore_probe_fail;
struct brcmfmac_pd_cc *country_codes;
+ union {
+ struct brcmfmac_sdio_pd sdio;
+ } bus;
};
-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
-static inline bool brcmf_ignoring_probe_fail(struct brcmf_pub *drvr)
-{
- return drvr->settings->ignore_probe_fail;
-}
-#else
-static inline bool brcmf_ignoring_probe_fail(struct brcmf_pub *drvr)
-{
- return false;
-}
-#endif
+struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
+ enum brcmf_bus_type bus_type,
+ u32 chip, u32 chiprev);
+void brcmf_release_module_param(struct brcmf_mp_device *module_param);
/* Sets dongle media info (drv_version, mac address). */
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
}
#endif
-int brcmf_attach(struct device *dev)
+int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings)
{
struct brcmf_pub *drvr = NULL;
int ret = 0;
drvr->hdrlen = 0;
drvr->bus_if = dev_get_drvdata(dev);
drvr->bus_if->drvr = drvr;
-
- /* Initialize device specific settings */
- if (brcmf_mp_device_attach(drvr))
- goto fail;
+ drvr->settings = settings;
/* attach debug facilities */
brcmf_debug_attach(drvr);
brcmf_net_detach(p2p_ifp->ndev);
drvr->iflist[0] = NULL;
drvr->iflist[1] = NULL;
- if (brcmf_ignoring_probe_fail(drvr))
+ if (drvr->settings->ignore_probe_fail)
ret = 0;
return ret;
brcmf_proto_detach(drvr);
- brcmf_mp_device_detach(drvr);
-
brcmf_debug_detach(drvr);
bus_if->drvr = NULL;
kfree(drvr);
#include "common.h"
#include "of.h"
-void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd **sdio)
+void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio)
{
struct device_node *np = dev->of_node;
int irq;
if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
return;
- *sdio = devm_kzalloc(dev, sizeof(*sdio), GFP_KERNEL);
- if (!(*sdio))
- return;
-
if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
- (*sdio)->drive_strength = val;
+ sdio->drive_strength = val;
/* make sure there are interrupts defined in the node */
if (!of_find_property(np, "interrupts", NULL))
}
irqf = irqd_get_trigger_type(irq_get_irq_data(irq));
- (*sdio)->oob_irq_supported = true;
- (*sdio)->oob_irq_nr = irq;
- (*sdio)->oob_irq_flags = irqf;
+ sdio->oob_irq_supported = true;
+ sdio->oob_irq_nr = irq;
+ sdio->oob_irq_flags = irqf;
}
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef CONFIG_OF
-void
-brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd **sdio);
+void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio);
#else
-static void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd **sdio)
+static void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio)
{
}
#endif /* CONFIG_OF */
#include "pcie.h"
#include "firmware.h"
#include "chip.h"
+#include "core.h"
+#include "common.h"
enum brcmf_pcie_state {
u16 (*read_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset);
void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
u16 value);
+ struct brcmf_mp_device *settings;
};
struct brcmf_pcie_ringbuf {
}
-static int brcmf_pcie_attach_bus(struct device *dev)
+static int brcmf_pcie_attach_bus(struct brcmf_pciedev_info *devinfo)
{
int ret;
/* Attach to the common driver interface */
- ret = brcmf_attach(dev);
+ ret = brcmf_attach(&devinfo->pdev->dev, devinfo->settings);
if (ret) {
brcmf_err("brcmf_attach failed\n");
} else {
- ret = brcmf_bus_start(dev);
+ ret = brcmf_bus_start(&devinfo->pdev->dev);
if (ret)
brcmf_err("dongle is not responding\n");
}
init_waitqueue_head(&devinfo->mbdata_resp_wait);
brcmf_pcie_intr_enable(devinfo);
- if (brcmf_pcie_attach_bus(bus->dev) == 0)
+ if (brcmf_pcie_attach_bus(devinfo) == 0)
return;
brcmf_pcie_bus_console_read(devinfo);
goto fail;
}
+ devinfo->settings = brcmf_get_module_param(&devinfo->pdev->dev,
+ BRCMF_BUSTYPE_PCIE,
+ devinfo->ci->chip,
+ devinfo->ci->chiprev);
+ if (!devinfo->settings) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
bus = kzalloc(sizeof(*bus), GFP_KERNEL);
if (!bus) {
ret = -ENOMEM;
brcmf_pcie_release_resource(devinfo);
if (devinfo->ci)
brcmf_chip_detach(devinfo->ci);
+ if (devinfo->settings)
+ brcmf_release_module_param(devinfo->settings);
kfree(pcie_bus_dev);
kfree(devinfo);
return ret;
if (devinfo->ci)
brcmf_chip_detach(devinfo->ci);
+ if (devinfo->settings)
+ brcmf_release_module_param(devinfo->settings);
kfree(devinfo);
dev_set_drvdata(&pdev->dev, NULL);
static inline void brcmf_sdio_clrintr(struct brcmf_sdio *bus)
{
+ struct brcmf_sdio_dev *sdiodev;
unsigned long flags;
- 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;
+ sdiodev = bus->sdiodev;
+ if (sdiodev->oob_irq_requested) {
+ spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
+ if (!sdiodev->irq_en && !atomic_read(&bus->ipend)) {
+ enable_irq(sdiodev->settings->bus.sdio.oob_irq_nr);
+ sdiodev->irq_en = true;
}
- spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags);
+ spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
}
}
sizeof(u32));
} else {
/* otherwise, set txglomalign */
- value = 4;
- if (sdiodev->pdata)
- value = sdiodev->pdata->sd_sgentry_align;
+ value = sdiodev->settings->bus.sdio.sd_sgentry_align;
/* SDIO ADMA requires at least 32 bit alignment */
value = max_t(u32, value, 4);
err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value,
bus->ci = NULL;
goto fail;
}
- sdiodev->pdata = brcmf_get_module_param(sdiodev->dev,
+ sdiodev->settings = brcmf_get_module_param(sdiodev->dev,
BRCMF_BUSTYPE_SDIO,
bus->ci->chip,
bus->ci->chiprev);
+ if (!sdiodev->settings) {
+ brcmf_err("Failed to get device parameters\n");
+ goto fail;
+ }
/* 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;
- }
+ if (sdiodev->settings->bus.sdio.sd_head_align > ALIGNMENT)
+ bus->head_align = sdiodev->settings->bus.sdio.sd_head_align;
+ if (sdiodev->settings->bus.sdio.sd_sgentry_align > ALIGNMENT)
+ bus->sgentry_align =
+ sdiodev->settings->bus.sdio.sd_sgentry_align;
+
/* allocate scatter-gather table. sg support
* will be disabled upon allocation failure.
*/
*/
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->settings->bus.sdio.oob_irq_supported)))
sdiodev->bus_if->wowl_supported = true;
#endif
goto fail;
}
- if ((sdiodev->pdata) && (sdiodev->pdata->drive_strength))
- drivestrength = sdiodev->pdata->drive_strength;
+ if (sdiodev->settings->bus.sdio.drive_strength)
+ drivestrength = sdiodev->settings->bus.sdio.drive_strength;
else
drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH;
brcmf_sdio_drivestrengthinit(sdiodev, bus->ci, drivestrength);
bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN;
/* Attach to the common layer, reserve hdr space */
- ret = brcmf_attach(bus->sdiodev->dev);
+ ret = brcmf_attach(bus->sdiodev->dev, bus->sdiodev->settings);
if (ret != 0) {
brcmf_err("brcmf_attach failed\n");
goto fail;
}
brcmf_chip_detach(bus->ci);
}
+ if (bus->sdiodev->settings)
+ brcmf_release_module_param(bus->sdiodev->settings);
kfree(bus->rxbuf);
kfree(bus->hdrbuf);
struct brcmf_sdio *bus;
struct device *dev;
struct brcmf_bus *bus_if;
- struct brcmfmac_sdio_pd *pdata;
+ struct brcmf_mp_device *settings;
bool oob_irq_requested;
bool irq_en; /* irq enable flags */
spinlock_t irq_en_lock;
#include "debug.h"
#include "firmware.h"
#include "usb.h"
+#include "core.h"
+#include "common.h"
#define IOCTL_RESP_TIMEOUT msecs_to_jiffies(2000)
struct urb *bulk_urb; /* used for FW download */
bool wowl_enabled;
+ struct brcmf_mp_device *settings;
};
static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
kfree(devinfo->tx_reqs);
kfree(devinfo->rx_reqs);
+
+ if (devinfo->settings)
+ brcmf_release_module_param(devinfo->settings);
}
int ret;
/* Attach to the common driver interface */
- ret = brcmf_attach(devinfo->dev);
+ ret = brcmf_attach(devinfo->dev, devinfo->settings);
if (ret) {
brcmf_err("brcmf_attach failed\n");
return ret;
bus->wowl_supported = true;
#endif
+ devinfo->settings = brcmf_get_module_param(bus->dev, BRCMF_BUSTYPE_USB,
+ bus_pub->devid,
+ bus_pub->chiprev);
+ if (!devinfo->settings) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
if (!brcmf_usb_dlneeded(devinfo)) {
ret = brcmf_usb_bus_setup(devinfo);
if (ret)