summaryrefslogtreecommitdiff
path: root/mac80211/compat_wl18xx/drivers/net/wireless/ti/wlcore/sdio.c
diff options
context:
space:
mode:
Diffstat (limited to 'mac80211/compat_wl18xx/drivers/net/wireless/ti/wlcore/sdio.c')
-rw-r--r--mac80211/compat_wl18xx/drivers/net/wireless/ti/wlcore/sdio.c62
1 files changed, 60 insertions, 2 deletions
diff --git a/mac80211/compat_wl18xx/drivers/net/wireless/ti/wlcore/sdio.c b/mac80211/compat_wl18xx/drivers/net/wireless/ti/wlcore/sdio.c
index 4ed5a156..c9249fe3 100644
--- a/mac80211/compat_wl18xx/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/mac80211/compat_wl18xx/drivers/net/wireless/ti/wlcore/sdio.c
@@ -35,6 +35,7 @@
#include <linux/pm_runtime.h>
#include <linux/printk.h>
#include <linux/of.h>
+#include <linux/of_irq.h>
#include "wlcore.h"
#include "wl12xx_80211.h"
@@ -215,6 +216,49 @@ static struct wl1271_if_operations sdio_ops = {
.set_block_size = wl1271_sdio_set_block_size,
};
+#ifdef CONFIG_OF
+/* backport dt parsing function from upstream */
+static struct wl12xx_platform_data *wlcore_probe_of(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct wl12xx_platform_data *pdata;
+ bool need_put_node = false;
+
+ if (!np || !of_device_is_compatible(np, "ti,wlcore")) {
+ np = of_find_compatible_node(NULL, NULL, "ti,wlcore");
+ if (!np) {
+ dev_err(dev, "No platform data set\n");
+ return NULL;
+ }
+ need_put_node = true;
+ }
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(dev, "Can't allocate platform data\n");
+ goto err;
+ }
+
+ pdata->irq = irq_of_parse_and_map(np, 0);
+ if (!pdata->irq) {
+ dev_err(dev, "No irq in platform data\n");
+ goto err;
+ }
+
+ /* Optional fields */
+ of_property_read_u32(np, "board-ref-clock", &pdata->board_ref_clock);
+ of_property_read_u32(np, "board-tcxo-clock", &pdata->board_tcxo_clock);
+ of_property_read_u32(np, "platform-quirks", &pdata->platform_quirks);
+
+ return pdata;
+err:
+ if (need_put_node)
+ of_node_put(np);
+ kfree(pdata);
+ return NULL;
+}
+#endif
+
static const struct of_device_id wlcore_of_match[] = {
{
.compatible = "wlcore",
@@ -233,6 +277,12 @@ static struct wl12xx_platform_data *get_platform_data(struct device *dev)
return kmemdup(pdata, sizeof(*pdata), GFP_KERNEL);
#ifdef CONFIG_OF
+ /* first, try looking for "upstream" dt */
+ pdata = wlcore_probe_of(dev);
+ if (pdata)
+ return pdata;
+
+ /* if not found, look for our deprecated dt */
np = of_find_matching_node(NULL, wlcore_of_match);
if (!np) {
dev_err(dev, "No platform data set\n");
@@ -408,8 +458,16 @@ static int wl1271_suspend(struct device *dev)
dev_dbg(dev, "wl1271 suspend. wow_enabled: %d\n",
wl->wow_enabled);
- /* check whether sdio should keep power */
- if (wl->wow_enabled) {
+ /*
+ * check whether sdio should keep power.
+ * due to some mmc layer issues, the system automatically
+ * powers us up on resume, which later cause issues when
+ * we try to restore_power again explicitly.
+ * workaround it by always asking to keep power. this is
+ * fine as the driver controls the chip power anyway.
+ * TODO: remove it when mmc issue is fixed.
+ */
+ if (true || wl->wow_enabled) {
sdio_flags = sdio_get_host_pm_caps(func);
if (!(sdio_flags & MMC_PM_KEEP_POWER)) {