brcmfmac: switch to new platform data
authorHante Meuleman <meuleman@broadcom.com>
Wed, 17 Feb 2016 10:27:07 +0000 (11:27 +0100)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 7 Mar 2016 12:15:50 +0000 (14:15 +0200)
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>
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
include/linux/platform_data/brcmfmac-sdio.h [deleted file]
include/linux/platform_data/brcmfmac.h [new file with mode: 0644]

index 25cd71229c953e862716d08ccf482048d04127ed..bb4aece9ad2c7c46c5199563d4bc7ea5a018b37b 100644 (file)
@@ -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);
 
index 5609a79df1c16e7903e9ded2e50472e70515fdd8..5e3acaca7231a3c9bedea4c6fd339afd6244b68c 100644 (file)
@@ -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;
 
index 020901c2e0cac8acdec28ee99c9a32149b48f9ca..4bd3225cdea60cccf884758b8cf17f969f58f9a8 100644 (file)
@@ -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,
        }
 };
 
index 54a26ede808df730fd96fff7d110cd327b7b4183..a64e40e8bfda832ef1333dca0deb2367efc9095a 100644 (file)
@@ -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
index 8201d937b826663bee73207c2c211d096a31be46..ece0b65dd039e8c854d091ca1ed17d2e0274be99 100644 (file)
@@ -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;
index 84b474484ceacfb743421e2250d10baccca856a4..1ba951f9b542ed20c2b901868fa16dc0901e9cc4 100644 (file)
  */
 #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 */
index c790fa89db0591d1e1015b9b21383394d03ea027..6e367041f6914ca24bc824a04930d0fa19f83c15 100644 (file)
@@ -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));
index 23f223150cef2cf4ec768b196d906603b92f36b2..50df9cb21af2e13a07c39ff8926a01f0e042fc65 100644 (file)
@@ -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;
diff --git a/include/linux/platform_data/brcmfmac-sdio.h b/include/linux/platform_data/brcmfmac-sdio.h
deleted file mode 100644 (file)
index e75dcbf..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2013 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _LINUX_BRCMFMAC_PLATFORM_H
-#define _LINUX_BRCMFMAC_PLATFORM_H
-
-/*
- * Platform specific driver functions and data. Through the platform specific
- * device data functions can be provided to help the brcmfmac driver to
- * operate with the device in combination with the used platform.
- *
- * Use the platform data in the following (similar) way:
- *
- *
-#include <brcmfmac_platform.h>
-
-
-static void brcmfmac_power_on(void)
-{
-}
-
-static void brcmfmac_power_off(void)
-{
-}
-
-static void brcmfmac_reset(void)
-{
-}
-
-static struct brcmfmac_sdio_platform_data brcmfmac_sdio_pdata = {
-       .power_on               = brcmfmac_power_on,
-       .power_off              = brcmfmac_power_off,
-       .reset                  = brcmfmac_reset
-};
-
-static struct platform_device brcmfmac_device = {
-       .name                   = BRCMFMAC_SDIO_PDATA_NAME,
-       .id                     = PLATFORM_DEVID_NONE,
-       .dev.platform_data      = &brcmfmac_sdio_pdata
-};
-
-void __init brcmfmac_init_pdata(void)
-{
-       brcmfmac_sdio_pdata.oob_irq_supported = true;
-       brcmfmac_sdio_pdata.oob_irq_nr = gpio_to_irq(GPIO_BRCMF_SDIO_OOB);
-       brcmfmac_sdio_pdata.oob_irq_flags = IORESOURCE_IRQ |
-                                           IORESOURCE_IRQ_HIGHLEVEL;
-       platform_device_register(&brcmfmac_device);
-}
- *
- *
- * Note: the brcmfmac can be loaded as module or be statically built-in into
- * the kernel. If built-in then do note that it uses module_init (and
- * module_exit) routines which equal device_initcall. So if you intend to
- * create a module with the platform specific data for the brcmfmac and have
- * it built-in to the kernel then use a higher initcall then device_initcall
- * (see init.h). If this is not done then brcmfmac will load without problems
- * but will not pickup the platform data.
- *
- * When the driver does not "detect" platform driver data then it will continue
- * without reporting anything and just assume there is no data needed. Which is
- * probably true for most platforms.
- *
- * Explanation of the platform_data fields:
- *
- * drive_strength: is the preferred drive_strength to be used for the SDIO
- * pins. If 0 then a default value will be used. This is the target drive
- * strength, the exact drive strength which will be used depends on the
- * capabilities of the device.
- *
- * oob_irq_supported: does the board have support for OOB interrupts. SDIO
- * in-band interrupts are relatively slow and for having less overhead on
- * interrupt processing an out of band interrupt can be used. If the HW
- * supports this then enable this by setting this field to true and configure
- * the oob related fields.
- *
- * oob_irq_nr, oob_irq_flags: the OOB interrupt information. The values are
- * used for registering the irq using request_irq function.
- *
- * broken_sg_support: flag for broken sg list support of SDIO host controller.
- * Set this to true if the SDIO host controller has higher align requirement
- * than 32 bytes for each scatterlist item.
- *
- * sd_head_align: alignment requirement for start of data buffer
- *
- * sd_sgentry_align: length alignment requirement for each sg entry
- *
- * power_on: This function is called by the brcmfmac when the module gets
- * loaded. This can be particularly useful for low power devices. The platform
- * spcific routine may for example decide to power up the complete device.
- * If there is no use-case for this function then provide NULL.
- *
- * power_off: This function is called by the brcmfmac when the module gets
- * unloaded. At this point the device can be powered down or otherwise be reset.
- * So if an actual power_off is not supported but reset is then reset the device
- * when this function gets called. This can be particularly useful for low power
- * devices. If there is no use-case for this function (either power-down or
- * reset) then provide NULL.
- *
- * reset: This function can get called if the device communication broke down.
- * This functionality is particularly useful in case of SDIO type devices. It is
- * possible to reset a dongle via sdio data interface, but it requires that
- * this is fully functional. This function is chip/module specific and this
- * function should return only after the complete reset has completed.
- */
-
-#define BRCMFMAC_SDIO_PDATA_NAME       "brcmfmac_sdio"
-
-struct brcmfmac_sdio_platform_data {
-       unsigned int drive_strength;
-       bool oob_irq_supported;
-       unsigned int oob_irq_nr;
-       unsigned long oob_irq_flags;
-       bool broken_sg_support;
-       unsigned short sd_head_align;
-       unsigned short sd_sgentry_align;
-       void (*power_on)(void);
-       void (*power_off)(void);
-       void (*reset)(void);
-};
-
-#endif /* _LINUX_BRCMFMAC_PLATFORM_H */
diff --git a/include/linux/platform_data/brcmfmac.h b/include/linux/platform_data/brcmfmac.h
new file mode 100644 (file)
index 0000000..1d30bf2
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 201 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LINUX_BRCMFMAC_PLATFORM_H
+#define _LINUX_BRCMFMAC_PLATFORM_H
+
+
+#define BRCMFMAC_PDATA_NAME            "brcmfmac"
+
+#define BRCMFMAC_COUNTRY_BUF_SZ                4
+
+
+/*
+ * Platform specific driver functions and data. Through the platform specific
+ * device data functions and data can be provided to help the brcmfmac driver to
+ * operate with the device in combination with the used platform.
+ */
+
+
+/**
+ * Note: the brcmfmac can be loaded as module or be statically built-in into
+ * the kernel. If built-in then do note that it uses module_init (and
+ * module_exit) routines which equal device_initcall. So if you intend to
+ * create a module with the platform specific data for the brcmfmac and have
+ * it built-in to the kernel then use a higher initcall then device_initcall
+ * (see init.h). If this is not done then brcmfmac will load without problems
+ * but will not pickup the platform data.
+ *
+ * When the driver does not "detect" platform driver data then it will continue
+ * without reporting anything and just assume there is no data needed. Which is
+ * probably true for most platforms.
+ */
+
+/**
+ * enum brcmf_bus_type - Bus type identifier. Currently SDIO, USB and PCIE are
+ *                      supported.
+ */
+enum brcmf_bus_type {
+       BRCMF_BUSTYPE_SDIO,
+       BRCMF_BUSTYPE_USB,
+       BRCMF_BUSTYPE_PCIE
+};
+
+
+/**
+ * struct brcmfmac_sdio_pd - SDIO Device specific platform data.
+ *
+ * @txglomsz:          SDIO txglom size. Use 0 if default of driver is to be
+ *                     used.
+ * @drive_strength:    is the preferred drive_strength to be used for the SDIO
+ *                     pins. If 0 then a default value will be used. This is
+ *                     the target drive strength, the exact drive strength
+ *                     which will be used depends on the capabilities of the
+ *                     device.
+ * @oob_irq_supported: does the board have support for OOB interrupts. SDIO
+ *                     in-band interrupts are relatively slow and for having
+ *                     less overhead on interrupt processing an out of band
+ *                     interrupt can be used. If the HW supports this then
+ *                     enable this by setting this field to true and configure
+ *                     the oob related fields.
+ * @oob_irq_nr,
+ * @oob_irq_flags:     the OOB interrupt information. The values are used for
+ *                     registering the irq using request_irq function.
+ * @broken_sg_support: flag for broken sg list support of SDIO host controller.
+ *                     Set this to true if the SDIO host controller has higher
+ *                     align requirement than 32 bytes for each scatterlist
+ *                     item.
+ * @sd_head_align:     alignment requirement for start of data buffer.
+ * @sd_sgentry_align:  length alignment requirement for each sg entry.
+ * @reset:             This function can get called if the device communication
+ *                     broke down. This functionality is particularly useful in
+ *                     case of SDIO type devices. It is possible to reset a
+ *                     dongle via sdio data interface, but it requires that
+ *                     this is fully functional. This function is chip/module
+ *                     specific and this function should return only after the
+ *                     complete reset has completed.
+ */
+struct brcmfmac_sdio_pd {
+       int             txglomsz;
+       unsigned int    drive_strength;
+       bool            oob_irq_supported;
+       unsigned int    oob_irq_nr;
+       unsigned long   oob_irq_flags;
+       bool            broken_sg_support;
+       unsigned short  sd_head_align;
+       unsigned short  sd_sgentry_align;
+       void            (*reset)(void);
+};
+
+/**
+ * struct brcmfmac_pd_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 brcmfmac_pd_cc_entry {
+       char    iso3166[BRCMFMAC_COUNTRY_BUF_SZ];
+       char    cc[BRCMFMAC_COUNTRY_BUF_SZ];
+       s32     rev;
+};
+
+/**
+ * struct brcmfmac_pd_cc - 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:     array of 1 or more elements with translation information.
+ */
+struct brcmfmac_pd_cc {
+       int                             table_size;
+       struct brcmfmac_pd_cc_entry     table[0];
+};
+
+/**
+ * struct brcmfmac_pd_device - Device specific platform data. (id/rev/bus_type)
+ *                            is the unique identifier of the device.
+ *
+ * @id:                        ID of the device for which this data is. In case of SDIO
+ *                     or PCIE this is the chipid as identified by chip.c In
+ *                     case of USB this is the chipid as identified by the
+ *                     device query.
+ * @rev:               chip revision, see id.
+ * @bus_type:          The type of bus. Some chipid/rev exist for different bus
+ *                     types. Each bus type has its own set of settings.
+ * @feature_disable:   Bitmask of features to disable (override), See feature.c
+ *                     in brcmfmac for details.
+ * @country_codes:     If available, pointer to struct for translating country
+ *                     codes.
+ * @bus:               Bus specific (union) device settings. Currently only
+ *                     SDIO.
+ */
+struct brcmfmac_pd_device {
+       unsigned int            id;
+       unsigned int            rev;
+       enum brcmf_bus_type     bus_type;
+       unsigned int            feature_disable;
+       struct brcmfmac_pd_cc   *country_codes;
+       union {
+               struct brcmfmac_sdio_pd sdio;
+       } bus;
+};
+
+/**
+ * struct brcmfmac_platform_data - BRCMFMAC specific platform data.
+ *
+ * @power_on:  This function is called by the brcmfmac driver when the module
+ *             gets loaded. This can be particularly useful for low power
+ *             devices. The platform spcific routine may for example decide to
+ *             power up the complete device. If there is no use-case for this
+ *             function then provide NULL.
+ * @power_off: This function is called by the brcmfmac when the module gets
+ *             unloaded. At this point the devices can be powered down or
+ *             otherwise be reset. So if an actual power_off is not supported
+ *             but reset is supported by the devices then reset the devices
+ *             when this function gets called. This can be particularly useful
+ *             for low power devices. If there is no use-case for this
+ *             function then provide NULL.
+ */
+struct brcmfmac_platform_data {
+       void    (*power_on)(void);
+       void    (*power_off)(void);
+       char    *fw_alternative_path;
+       int     device_count;
+       struct brcmfmac_pd_device devices[0];
+};
+
+
+#endif /* _LINUX_BRCMFMAC_PLATFORM_H */