2013-07-30 13:05:32

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH v4 0/8] wilink: add device tree support

Hi,

This patch series adds device tree support to the wlcore_sdio driver,
which is used by WiLink6, WiLink7 and WiLink8.

The first patches do some clean-up to make the data needed in the
wilink device tree node smaller. The remaining patches implement the
actual device tree node parsing in wlcore_sdio.

Regarding the XTAL clock issues, for now we don't support XTAL mode
with DT, but I have sent a proposal for a small change in the clock
framework to support this, but it's still under discussions [1].

The DTS file changes will be sent separately, since they need to go
via different trees.

A new version of the bindings documentation has been sent [2] and, if
no more comments are given to it, I'll apply it via my tree.

[1] http://news.gmane.org/find-root.php?message_id=1372971912-10877-1-git-send-email-coelho@ti.com
[2] http://news.gmane.org/find-root.php?message_id=1375109728-5931-1-git-send-email-coelho@ti.com

Changes in v4:

* Rebased on top of 3.11-rc3 (eg. no more changes on the board files
that were removed);

* Use the new irq_get_trigger_type() instead of
irqd_get_trigger_type() (thanks Javier);

* Added some missing const's (thanks Felipe);

* Reverted Tony's workaround to get WiLink to work on Panda while DT
was not supported yet.


Please review.


Luciano Coelho (8):
wl1251: split wl251 platform data to a separate structure
wlcore: set irq_flags in the board files instead of hiding behind a
quirk
wlcore: remove pwr_in_suspend from platform data
wl12xx: use frequency instead of enumerations for pdata clocks
wlcore: add initial device tree support to the sdio module
wlcore: sdio: add wilink clock providers
wlcore: sdio: get clocks from device tree
wlcore/wl12xx: check if we got correct clock data from DT

arch/arm/mach-davinci/board-da850-evm.c | 11 ++-
arch/arm/mach-omap2/board-omap3evm.c | 22 ++++-
arch/arm/mach-omap2/board-omap3pandora.c | 4 +-
arch/arm/mach-omap2/board-rx51-peripherals.c | 2 +-
arch/arm/mach-omap2/board-zoom-peripherals.c | 33 +++++++-
arch/arm/mach-omap2/devices.c | 39 ---------
drivers/net/wireless/ti/wilink_platform_data.c | 37 ++++++--
drivers/net/wireless/ti/wl1251/sdio.c | 12 +--
drivers/net/wireless/ti/wl1251/spi.c | 2 +-
drivers/net/wireless/ti/wl12xx/main.c | 78 +++++++++++++++--
drivers/net/wireless/ti/wl12xx/wl12xx.h | 28 +++++++
drivers/net/wireless/ti/wlcore/debugfs.c | 2 +-
drivers/net/wireless/ti/wlcore/main.c | 20 ++---
drivers/net/wireless/ti/wlcore/sdio.c | 112 +++++++++++++++++++++++--
drivers/net/wireless/ti/wlcore/wlcore.h | 5 +-
drivers/net/wireless/ti/wlcore/wlcore_i.h | 1 +
include/linux/wl12xx.h | 52 +++++-------
17 files changed, 340 insertions(+), 120 deletions(-)

--
1.8.3.2


2013-07-30 13:05:30

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH v4 1/8] wl1251: split wl251 platform data to a separate structure

Move the wl1251 part of the wl12xx platform data structure into a new
structure specifically for wl1251. Change the platform data built-in
block and board files accordingly.

Cc: Tony Lindgren <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
Acked-by: Tony Lindgren <[email protected]>
Reviewed-by: Felipe Balbi <[email protected]>
---
arch/arm/mach-omap2/board-omap3pandora.c | 4 +--
arch/arm/mach-omap2/board-rx51-peripherals.c | 2 +-
drivers/net/wireless/ti/wilink_platform_data.c | 37 +++++++++++++++++++++-----
drivers/net/wireless/ti/wl1251/sdio.c | 12 ++++-----
drivers/net/wireless/ti/wl1251/spi.c | 2 +-
include/linux/wl12xx.h | 22 ++++++++++++++-
6 files changed, 62 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index b1547a0..84d56e8 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -541,7 +541,7 @@ static struct spi_board_info omap3pandora_spi_board_info[] __initdata = {

static void __init pandora_wl1251_init(void)
{
- struct wl12xx_platform_data pandora_wl1251_pdata;
+ struct wl1251_platform_data pandora_wl1251_pdata;
int ret;

memset(&pandora_wl1251_pdata, 0, sizeof(pandora_wl1251_pdata));
@@ -555,7 +555,7 @@ static void __init pandora_wl1251_init(void)
goto fail_irq;

pandora_wl1251_pdata.use_eeprom = true;
- ret = wl12xx_set_platform_data(&pandora_wl1251_pdata);
+ ret = wl1251_set_platform_data(&pandora_wl1251_pdata);
if (ret < 0)
goto fail_irq;

diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 9c2dd10..01e5711 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -80,7 +80,7 @@ enum {
RX51_SPI_MIPID, /* LCD panel */
};

-static struct wl12xx_platform_data wl1251_pdata;
+static struct wl1251_platform_data wl1251_pdata;
static struct tsc2005_platform_data tsc2005_pdata;

#if defined(CONFIG_SENSORS_LIS3_I2C) || defined(CONFIG_SENSORS_LIS3_I2C_MODULE)
diff --git a/drivers/net/wireless/ti/wilink_platform_data.c b/drivers/net/wireless/ti/wilink_platform_data.c
index 998e958..a92bd3e 100644
--- a/drivers/net/wireless/ti/wilink_platform_data.c
+++ b/drivers/net/wireless/ti/wilink_platform_data.c
@@ -23,17 +23,17 @@
#include <linux/err.h>
#include <linux/wl12xx.h>

-static struct wl12xx_platform_data *platform_data;
+static struct wl12xx_platform_data *wl12xx_platform_data;

int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data)
{
- if (platform_data)
+ if (wl12xx_platform_data)
return -EBUSY;
if (!data)
return -EINVAL;

- platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
- if (!platform_data)
+ wl12xx_platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
+ if (!wl12xx_platform_data)
return -ENOMEM;

return 0;
@@ -41,9 +41,34 @@ int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data)

struct wl12xx_platform_data *wl12xx_get_platform_data(void)
{
- if (!platform_data)
+ if (!wl12xx_platform_data)
return ERR_PTR(-ENODEV);

- return platform_data;
+ return wl12xx_platform_data;
}
EXPORT_SYMBOL(wl12xx_get_platform_data);
+
+static struct wl1251_platform_data *wl1251_platform_data;
+
+int __init wl1251_set_platform_data(const struct wl1251_platform_data *data)
+{
+ if (wl1251_platform_data)
+ return -EBUSY;
+ if (!data)
+ return -EINVAL;
+
+ wl1251_platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
+ if (!wl1251_platform_data)
+ return -ENOMEM;
+
+ return 0;
+}
+
+struct wl1251_platform_data *wl1251_get_platform_data(void)
+{
+ if (!wl1251_platform_data)
+ return ERR_PTR(-ENODEV);
+
+ return wl1251_platform_data;
+}
+EXPORT_SYMBOL(wl1251_get_platform_data);
diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c
index e2b3d9c..b75a37a 100644
--- a/drivers/net/wireless/ti/wl1251/sdio.c
+++ b/drivers/net/wireless/ti/wl1251/sdio.c
@@ -227,7 +227,7 @@ static int wl1251_sdio_probe(struct sdio_func *func,
struct wl1251 *wl;
struct ieee80211_hw *hw;
struct wl1251_sdio *wl_sdio;
- const struct wl12xx_platform_data *wl12xx_board_data;
+ const struct wl1251_platform_data *wl1251_board_data;

hw = wl1251_alloc_hw();
if (IS_ERR(hw))
@@ -254,11 +254,11 @@ static int wl1251_sdio_probe(struct sdio_func *func,
wl->if_priv = wl_sdio;
wl->if_ops = &wl1251_sdio_ops;

- wl12xx_board_data = wl12xx_get_platform_data();
- if (!IS_ERR(wl12xx_board_data)) {
- wl->set_power = wl12xx_board_data->set_power;
- wl->irq = wl12xx_board_data->irq;
- wl->use_eeprom = wl12xx_board_data->use_eeprom;
+ wl1251_board_data = wl1251_get_platform_data();
+ if (!IS_ERR(wl1251_board_data)) {
+ wl->set_power = wl1251_board_data->set_power;
+ wl->irq = wl1251_board_data->irq;
+ wl->use_eeprom = wl1251_board_data->use_eeprom;
}

if (wl->irq) {
diff --git a/drivers/net/wireless/ti/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c
index c7dc6fe..6bbbfe6 100644
--- a/drivers/net/wireless/ti/wl1251/spi.c
+++ b/drivers/net/wireless/ti/wl1251/spi.c
@@ -238,7 +238,7 @@ static const struct wl1251_if_operations wl1251_spi_ops = {

static int wl1251_spi_probe(struct spi_device *spi)
{
- struct wl12xx_platform_data *pdata;
+ struct wl1251_platform_data *pdata;
struct ieee80211_hw *hw;
struct wl1251 *wl;
int ret;
diff --git a/include/linux/wl12xx.h b/include/linux/wl12xx.h
index a54fe82..b516b4f 100644
--- a/include/linux/wl12xx.h
+++ b/include/linux/wl12xx.h
@@ -48,11 +48,15 @@ enum {
WL12XX_TCXOCLOCK_33_6 = 7, /* 33.6 MHz */
};

-struct wl12xx_platform_data {
+struct wl1251_platform_data {
void (*set_power)(bool enable);
/* SDIO only: IRQ number if WLAN_IRQ line is used, 0 for SDIO IRQs */
int irq;
bool use_eeprom;
+};
+
+struct wl12xx_platform_data {
+ int irq;
int board_ref_clock;
int board_tcxo_clock;
unsigned long platform_quirks;
@@ -68,6 +72,10 @@ int wl12xx_set_platform_data(const struct wl12xx_platform_data *data);

struct wl12xx_platform_data *wl12xx_get_platform_data(void);

+int wl1251_set_platform_data(const struct wl1251_platform_data *data);
+
+struct wl1251_platform_data *wl1251_get_platform_data(void);
+
#else

static inline
@@ -82,6 +90,18 @@ struct wl12xx_platform_data *wl12xx_get_platform_data(void)
return ERR_PTR(-ENODATA);
}

+static inline
+int wl1251_set_platform_data(const struct wl1251_platform_data *data)
+{
+ return -ENOSYS;
+}
+
+static inline
+struct wl1251_platform_data *wl1251_get_platform_data(void)
+{
+ return ERR_PTR(-ENODATA);
+}
+
#endif

#endif
--
1.8.3.2

2013-07-30 13:05:41

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH v4 2/8] wlcore: set irq_flags in the board files instead of hiding behind a quirk

The platform_quirk element in the platform data was used to change the
way the IRQ is triggered. When set, the EDGE_IRQ quirk would change
the irqflags used and treat edge trigger differently from the rest.

Instead of hiding this irq flag setting behind the quirk, have the
board files set the flags during initialization. This will be more
meaningful than driver-specific quirks when we switch to DT.

Additionally, fix missing gpio_request() calls in the boarding files
(so that setting the flags actually works).

Cc: Tony Lindgren <[email protected]>
Cc: Sekhar Nori <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
Reviewed-by: Felipe Balbi <[email protected]>
Acked-by: Sekhar Nori <[email protected]>
---
arch/arm/mach-davinci/board-da850-evm.c | 8 +++++++-
arch/arm/mach-omap2/board-omap3evm.c | 19 ++++++++++++++++++
arch/arm/mach-omap2/board-zoom-peripherals.c | 30 +++++++++++++++++++++++++---
drivers/net/wireless/ti/wlcore/debugfs.c | 2 +-
drivers/net/wireless/ti/wlcore/main.c | 17 ++++++++--------
drivers/net/wireless/ti/wlcore/wlcore.h | 5 ++---
include/linux/wl12xx.h | 4 ----
7 files changed, 64 insertions(+), 21 deletions(-)

diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index bea6793..03de2e9 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -1377,7 +1377,6 @@ static const short da850_wl12xx_pins[] __initconst = {
static struct wl12xx_platform_data da850_wl12xx_wlan_data __initdata = {
.irq = -1,
.board_ref_clock = WL12XX_REFCLOCK_38,
- .platform_quirks = WL12XX_PLATFORM_QUIRK_EDGE_IRQ,
};

static __init int da850_wl12xx_init(void)
@@ -1408,6 +1407,13 @@ static __init int da850_wl12xx_init(void)
goto free_wlan_en;
}

+ ret = irq_set_irq_type(gpio_to_irq(DA850_WLAN_IRQ),
+ IRQ_TYPE_EDGE_RISING);
+ if (ret) {
+ pr_err("Could not set wl12xx irq type: %d\n", ret);
+ goto free;
+ }
+
da850_wl12xx_wlan_data.irq = gpio_to_irq(DA850_WLAN_IRQ);

ret = wl12xx_set_platform_data(&da850_wl12xx_wlan_data);
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 8c02626..9c7dfc5 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -614,12 +614,31 @@ static void __init omap3_evm_wl12xx_init(void)

/* WL12xx WLAN Init */
omap3evm_wlan_data.irq = gpio_to_irq(OMAP3EVM_WLAN_IRQ_GPIO);
+
+ ret = gpio_request_one(OMAP3EVM_WLAN_IRQ_GPIO, GPIOF_IN,
+ "OMAP3EVM_WLAN_IRQ_GPIO");
+ if (ret) {
+ pr_err("error requesting wl12xx gpio: %d\n", ret);
+ goto out;
+ }
+
+ ret = irq_set_irq_type(gpio_to_irq(OMAP3EVM_WLAN_IRQ_GPIO),
+ IRQ_TYPE_LEVEL_HIGH);
+ if (ret) {
+ pr_err("error setting wl12xx irq type: %d\n", ret);
+ goto free;
+ }
+
ret = wl12xx_set_platform_data(&omap3evm_wlan_data);
if (ret)
pr_err("error setting wl12xx data: %d\n", ret);
ret = platform_device_register(&omap3evm_wlan_regulator);
if (ret)
pr_err("error registering wl12xx device: %d\n", ret);
+out:
+ return;
+free:
+ gpio_free(OMAP3EVM_WLAN_IRQ_GPIO);
#endif
}

diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index a90375d..4f84cf9 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -339,16 +339,40 @@ static void enable_board_wakeup_source(void)
OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP);
}

-void __init zoom_peripherals_init(void)
+static void __init zoom_wilink_init(void)
{
int ret;

omap_zoom_wlan_data.irq = gpio_to_irq(OMAP_ZOOM_WLAN_IRQ_GPIO);
- ret = wl12xx_set_platform_data(&omap_zoom_wlan_data);

- if (ret)
+ ret = gpio_request_one(OMAP_ZOOM_WLAN_IRQ_GPIO, GPIOF_IN,
+ "OMAP_ZOOM_WLAN_IRQ_GPIO");
+ if (ret) {
+ pr_err("error requesting wl12xx gpio: %d\n", ret);
+ goto out;
+ }
+
+ ret = irq_set_irq_type(gpio_to_irq(OMAP_ZOOM_WLAN_IRQ_GPIO),
+ IRQ_TYPE_LEVEL_HIGH);
+ if (ret) {
+ pr_err("error setting wl12xx irq type: %d\n", ret);
+ goto free;
+ }
+
+ ret = wl12xx_set_platform_data(&omap_zoom_wlan_data);
+ if (ret) {
pr_err("error setting wl12xx data: %d\n", ret);
+ goto free;
+ }
+out:
+ return;
+free:
+ gpio_free(OMAP_ZOOM_WLAN_IRQ_GPIO);
+}

+void __init zoom_peripherals_init(void)
+{
+ zoom_wilink_init();
omap_hsmmc_init(mmc);
omap_i2c_init();
pwm_add_table(zoom_pwm_lookup, ARRAY_SIZE(zoom_pwm_lookup));
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c
index e17630c..9544477 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.c
+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
@@ -486,7 +486,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_HEX(irq);
/* TODO: ref_clock and tcxo_clock were moved to wl12xx priv */
DRIVER_STATE_PRINT_HEX(hw_pg_ver);
- DRIVER_STATE_PRINT_HEX(platform_quirks);
+ DRIVER_STATE_PRINT_HEX(irq_flags);
DRIVER_STATE_PRINT_HEX(chip.id);
DRIVER_STATE_PRINT_STR(chip.fw_ver_str);
DRIVER_STATE_PRINT_STR(chip.phy_fw_ver_str);
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index b8db55c..11dab9a 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -27,6 +27,7 @@
#include <linux/vmalloc.h>
#include <linux/wl12xx.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>

#include "wlcore.h"
#include "debug.h"
@@ -516,7 +517,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
* In case edge triggered interrupt must be used, we cannot iterate
* more than once without introducing race conditions with the hardirq.
*/
- if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ)
+ if (wl->irq_flags & IRQF_TRIGGER_RISING)
loopcount = 1;

wl1271_debug(DEBUG_IRQ, "IRQ work");
@@ -5765,7 +5766,6 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size,
wl->ap_ps_map = 0;
wl->ap_fw_ps_map = 0;
wl->quirks = 0;
- wl->platform_quirks = 0;
wl->system_hlid = WL12XX_SYSTEM_HLID;
wl->active_sta_count = 0;
wl->active_link_count = 0;
@@ -5901,7 +5901,7 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
struct platform_device *pdev = wl->pdev;
struct wlcore_platdev_data *pdev_data = pdev->dev.platform_data;
struct wl12xx_platform_data *pdata = pdev_data->pdata;
- unsigned long irqflags;
+
int ret;

if (fw) {
@@ -5928,16 +5928,15 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
wlcore_adjust_conf(wl);

wl->irq = platform_get_irq(pdev, 0);
- wl->platform_quirks = pdata->platform_quirks;
wl->if_ops = pdev_data->if_ops;

- if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ)
- irqflags = IRQF_TRIGGER_RISING;
- else
- irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
+ wl->irq_flags = irq_get_trigger_type(wl->irq);
+
+ /* Since we don't use the primary handler, we must set ONESHOT */
+ wl->irq_flags |= IRQF_ONESHOT;

ret = request_threaded_irq(wl->irq, NULL, wlcore_irq,
- irqflags, pdev->name, wl);
+ wl->irq_flags, pdev->name, wl);
if (ret < 0) {
wl1271_error("request_irq() failed: %d", ret);
goto out_free_nvs;
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 0034979..8306bde 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -185,6 +185,8 @@ struct wl1271 {

int irq;

+ int irq_flags;
+
spinlock_t wl_lock;

enum wlcore_state state;
@@ -384,9 +386,6 @@ struct wl1271 {
/* Quirks of specific hardware revisions */
unsigned int quirks;

- /* Platform limitations */
- unsigned int platform_quirks;
-
/* number of currently active RX BA sessions */
int ba_rx_session_count;

diff --git a/include/linux/wl12xx.h b/include/linux/wl12xx.h
index b516b4f..1bfcd19 100644
--- a/include/linux/wl12xx.h
+++ b/include/linux/wl12xx.h
@@ -59,13 +59,9 @@ struct wl12xx_platform_data {
int irq;
int board_ref_clock;
int board_tcxo_clock;
- unsigned long platform_quirks;
bool pwr_in_suspend;
};

-/* Platform does not support level trigger interrupts */
-#define WL12XX_PLATFORM_QUIRK_EDGE_IRQ BIT(0)
-
#ifdef CONFIG_WILINK_PLATFORM_DATA

int wl12xx_set_platform_data(const struct wl12xx_platform_data *data);
--
1.8.3.2

2013-07-30 13:05:48

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH v4 6/8] wlcore: sdio: add wilink clock providers

Add refclock and tcxoclock as clock providers in WiLink. These clocks
are not accesible outside the WiLink module, but they are registered
in the clock framework anyway. Only the WiLink chip consumes these
clocks.

In theory, the WiLink chip could be connected to external clocks
instead of using these internal clocks, so make the clock consumer
code generic enough. If external clocks are used, then the internal
clock device tree nodes are not necessary, but the external ones must
be specified.

Signed-off-by: Luciano Coelho <[email protected]>
Reviewed-by: Felipe Balbi <[email protected]>
---
drivers/net/wireless/ti/wlcore/sdio.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index 9370d7e..980bf3d 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -34,6 +34,7 @@
#include <linux/wl12xx.h>
#include <linux/pm_runtime.h>
#include <linux/printk.h>
+#include <linux/clk-provider.h>

#include "wlcore.h"
#include "wl12xx_80211.h"
@@ -214,10 +215,15 @@ static struct wl1271_if_operations sdio_ops = {
.set_block_size = wl1271_sdio_set_block_size,
};

+static const struct of_device_id wlcore_sdio_of_clk_match_table[] = {
+ { .compatible = "ti,wilink-clock" },
+};
+
static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
{
struct wl12xx_platform_data *pdata;
struct device_node *np = dev->of_node;
+ struct device_node *clock_node;

if (!np) {
np = of_find_matching_node(NULL, dev->driver->of_match_table);
@@ -241,6 +247,9 @@ static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
goto out_free;
}

+ for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table)
+ of_fixed_clk_setup(clock_node);
+
goto out;

out_free:
--
1.8.3.2

2013-07-30 13:05:54

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH v4 7/8] wlcore: sdio: get clocks from device tree

Read the clock nodes from the device tree and use them to set the
frequency for the refclock and the tcxo clock.

Also, call sdio_set_drvdata() earlier, so the glue is already set in
the driver data when we call wlcore_get_pdata_from_of() and we don't
need to pass it as a parameter.

Signed-off-by: Luciano Coelho <[email protected]>
Reviewed-by: Felipe Balbi <[email protected]>
---
drivers/net/wireless/ti/wlcore/sdio.c | 36 +++++++++++++++++++++++++++++++++--
1 file changed, 34 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index 980bf3d..60fce49 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -53,6 +53,7 @@ static bool dump = false;
struct wl12xx_sdio_glue {
struct device *dev;
struct platform_device *core;
+ struct clk *refclock, *tcxoclock;
};

static const struct sdio_device_id wl1271_devices[] = {
@@ -224,6 +225,7 @@ static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
struct wl12xx_platform_data *pdata;
struct device_node *np = dev->of_node;
struct device_node *clock_node;
+ struct wl12xx_sdio_glue *glue = sdio_get_drvdata(dev_to_sdio_func(dev));

if (!np) {
np = of_find_matching_node(NULL, dev->driver->of_match_table);
@@ -250,6 +252,26 @@ static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table)
of_fixed_clk_setup(clock_node);

+ /* TODO: make sure we have this when needed (ie. for WL6 and WL7) */
+ glue->refclock = of_clk_get_by_name(np, "refclock");
+ if (IS_ERR(glue->refclock)) {
+ dev_err(dev, "couldn't find refclock on the device tree\n");
+ glue->refclock = NULL;
+ } else {
+ clk_prepare_enable(glue->refclock);
+ pdata->ref_clock_freq = clk_get_rate(glue->refclock);
+ }
+
+ /* TODO: make sure we have this when needed (ie. for WL7) */
+ glue->tcxoclock = of_clk_get_by_name(np, "tcxoclock");
+ if (IS_ERR(glue->tcxoclock)) {
+ dev_err(dev, "couldn't find tcxoclock on the device tree\n");
+ glue->tcxoclock = NULL;
+ } else {
+ clk_prepare_enable(glue->tcxoclock);
+ pdata->ref_clock_freq = clk_get_rate(glue->tcxoclock);
+ }
+
goto out;

out_free:
@@ -294,6 +316,8 @@ static int wl1271_probe(struct sdio_func *func,
/* Use block mode for transferring over one block size of data */
func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;

+ sdio_set_drvdata(func, glue);
+
/* The pdata allocated here is freed when the device is freed,
* so we don't need an additional out label to free it in case
* of error further on.
@@ -319,8 +343,6 @@ static int wl1271_probe(struct sdio_func *func,
if (mmcflags & MMC_PM_KEEP_POWER)
pdev_data->pwr_in_suspend = true;

- sdio_set_drvdata(func, glue);
-
/* Tell PM core that we don't need the card to be powered now */
pm_runtime_put_noidle(&func->dev);

@@ -387,6 +409,16 @@ static void wl1271_remove(struct sdio_func *func)
{
struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func);

+ if (glue->refclock) {
+ clk_disable_unprepare(glue->refclock);
+ clk_put(glue->refclock);
+ }
+
+ if (glue->tcxoclock) {
+ clk_disable_unprepare(glue->tcxoclock);
+ clk_put(glue->tcxoclock);
+ }
+
/* Undo decrement done above in wl1271_probe */
pm_runtime_get_noresume(&func->dev);

--
1.8.3.2

2013-07-30 13:06:15

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH v4 8/8] wlcore/wl12xx: check if we got correct clock data from DT

The fref and the tcxo clocks settings are optional in some platforms.
WiLink8 doesn't need either, so we don't check the values. WiLink 6
only needs the fref clock, so we check that it is valid or return with
an error. WiLink7 needs both clocks, if either is not available we
return with an error.

Signed-off-by: Luciano Coelho <[email protected]>
Reviewed-by: Felipe Balbi <[email protected]>
---
drivers/net/wireless/ti/wl12xx/main.c | 20 +++++++++++++++++---
drivers/net/wireless/ti/wlcore/sdio.c | 4 ----
2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index a6c2a14..60d2ff4 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -927,6 +927,11 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
u16 sys_clk_cfg;
int ret;

+ if ((priv->ref_clock < 0) || (priv->tcxo_clock < 0)) {
+ wl1271_error("Missing fref and/or tcxo clock settings\n");
+ return -EINVAL;
+ }
+
/* For XTAL-only modes, FREF will be used after switching from TCXO */
if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL ||
priv->ref_clock == WL12XX_REFCLOCK_38_XTAL) {
@@ -976,6 +981,11 @@ static int wl127x_boot_clk(struct wl1271 *wl)
u32 clk;
int ret;

+ if (priv->ref_clock < 0) {
+ wl1271_error("Missing fref clock settings\n");
+ return -EINVAL;
+ }
+
if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION;

@@ -1758,7 +1768,7 @@ static int wl12xx_setup(struct wl1271 *wl)
wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, &wl12xx_ht_cap);
wl12xx_conf_init(wl);

- if (!fref_param) {
+ if (!fref_param && (pdata->ref_clock_freq > 0)) {
priv->ref_clock = wl12xx_get_clock_idx(wl12xx_refclock_table,
pdata->ref_clock_freq,
pdata->ref_clock_xtal);
@@ -1769,6 +1779,8 @@ static int wl12xx_setup(struct wl1271 *wl)

return priv->ref_clock;
}
+ } else if (!fref_param) {
+ priv->ref_clock = -EINVAL;
} else {
if (!strcmp(fref_param, "19.2"))
priv->ref_clock = WL12XX_REFCLOCK_19;
@@ -1786,7 +1798,7 @@ static int wl12xx_setup(struct wl1271 *wl)
wl1271_error("Invalid fref parameter %s", fref_param);
}

- if (!tcxo_param) {
+ if (!fref_param && (pdata->tcxo_clock_freq > 0)) {
priv->tcxo_clock = wl12xx_get_clock_idx(wl12xx_tcxoclock_table,
pdata->tcxo_clock_freq,
true);
@@ -1796,7 +1808,9 @@ static int wl12xx_setup(struct wl1271 *wl)

return priv->tcxo_clock;
}
- } else {
+ } else if (!fref_param) {
+ priv->tcxo_clock = -EINVAL;
+ }else {
if (!strcmp(tcxo_param, "19.2"))
priv->tcxo_clock = WL12XX_TCXOCLOCK_19_2;
else if (!strcmp(tcxo_param, "26"))
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index 60fce49..c76eb66 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -252,20 +252,16 @@ static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table)
of_fixed_clk_setup(clock_node);

- /* TODO: make sure we have this when needed (ie. for WL6 and WL7) */
glue->refclock = of_clk_get_by_name(np, "refclock");
if (IS_ERR(glue->refclock)) {
- dev_err(dev, "couldn't find refclock on the device tree\n");
glue->refclock = NULL;
} else {
clk_prepare_enable(glue->refclock);
pdata->ref_clock_freq = clk_get_rate(glue->refclock);
}

- /* TODO: make sure we have this when needed (ie. for WL7) */
glue->tcxoclock = of_clk_get_by_name(np, "tcxoclock");
if (IS_ERR(glue->tcxoclock)) {
- dev_err(dev, "couldn't find tcxoclock on the device tree\n");
glue->tcxoclock = NULL;
} else {
clk_prepare_enable(glue->tcxoclock);
--
1.8.3.2

2013-07-30 13:07:03

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH v4 4/8] wl12xx: use frequency instead of enumerations for pdata clocks

Instead of defining an enumeration with the FW specific values for the
different clock rates, use the actual frequency instead. Also add a
boolean to specify whether the clock is XTAL or not.

Change all board files to reflect this.

Additionally, this reverts commit 26f45c (ARM: OMAP2+: Legacy support
for wl12xx when booted with devicetree), since this is not be needed
anymore, now that DT support for WiLink is implemented.

Cc: Tony Lindgren <[email protected]>
Cc: Sekhar Nori <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
Reviewed-by: Felipe Balbi <[email protected]>
---
arch/arm/mach-davinci/board-da850-evm.c | 3 +-
arch/arm/mach-omap2/board-omap3evm.c | 3 +-
arch/arm/mach-omap2/board-zoom-peripherals.c | 3 +-
arch/arm/mach-omap2/devices.c | 39 -------------------
drivers/net/wireless/ti/wl12xx/main.c | 58 +++++++++++++++++++++++++++-
drivers/net/wireless/ti/wl12xx/wl12xx.h | 28 ++++++++++++++
include/linux/wl12xx.h | 27 ++-----------
7 files changed, 93 insertions(+), 68 deletions(-)

diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 03de2e9..6b2768f 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -1376,7 +1376,8 @@ static const short da850_wl12xx_pins[] __initconst = {

static struct wl12xx_platform_data da850_wl12xx_wlan_data __initdata = {
.irq = -1,
- .board_ref_clock = WL12XX_REFCLOCK_38,
+ .ref_clock_freq = 38400000,
+ .ref_clock_xtal = false,
};

static __init int da850_wl12xx_init(void)
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 9c7dfc5..4ccfcc0 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -460,7 +460,8 @@ static struct platform_device omap3evm_wlan_regulator = {
};

struct wl12xx_platform_data omap3evm_wlan_data __initdata = {
- .board_ref_clock = WL12XX_REFCLOCK_38, /* 38.4 MHz */
+ .ref_clock_freq = 38400000,
+ .ref_clock_xtal = false,
};
#endif

diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 4f84cf9..83a9a36 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -244,7 +244,8 @@ static struct platform_device *zoom_devices[] __initdata = {
};

static struct wl12xx_platform_data omap_zoom_wlan_data __initdata = {
- .board_ref_clock = WL12XX_REFCLOCK_26, /* 26 MHz */
+ .ref_clock_freq = 26000000,
+ .ref_clock_xtal = false,
};

static struct omap2_hsmmc_info mmc[] = {
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 3c1279f..10e6126 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -8,7 +8,6 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
-#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -19,7 +18,6 @@
#include <linux/of.h>
#include <linux/pinctrl/machine.h>
#include <linux/platform_data/omap4-keypad.h>
-#include <linux/wl12xx.h>
#include <linux/platform_data/mailbox-omap.h>

#include <asm/mach-types.h>
@@ -513,40 +511,6 @@ static void omap_init_vout(void)
static inline void omap_init_vout(void) {}
#endif

-#if IS_ENABLED(CONFIG_WL12XX)
-
-static struct wl12xx_platform_data wl12xx __initdata;
-
-void __init omap_init_wl12xx_of(void)
-{
- int ret;
-
- if (!of_have_populated_dt())
- return;
-
- if (of_machine_is_compatible("ti,omap4-sdp")) {
- wl12xx.board_ref_clock = WL12XX_REFCLOCK_26;
- wl12xx.board_tcxo_clock = WL12XX_TCXOCLOCK_26;
- wl12xx.irq = gpio_to_irq(53);
- } else if (of_machine_is_compatible("ti,omap4-panda")) {
- wl12xx.board_ref_clock = WL12XX_REFCLOCK_38;
- wl12xx.irq = gpio_to_irq(53);
- } else {
- return;
- }
-
- ret = wl12xx_set_platform_data(&wl12xx);
- if (ret) {
- pr_err("error setting wl12xx data: %d\n", ret);
- return;
- }
-}
-#else
-static inline void omap_init_wl12xx_of(void)
-{
-}
-#endif
-
/*-------------------------------------------------------------------------*/

static int __init omap2_init_devices(void)
@@ -570,9 +534,6 @@ static int __init omap2_init_devices(void)
omap_init_mcspi();
omap_init_sham();
omap_init_aes();
- } else {
- /* These can be removed when bindings are done */
- omap_init_wl12xx_of();
}
omap_init_sti();
omap_init_rng();
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 1c627da..a6c2a14 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1701,6 +1701,43 @@ static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
},
};

+static const struct wl12xx_clock wl12xx_refclock_table[] = {
+ { 19200000, false, WL12XX_REFCLOCK_19 },
+ { 26000000, false, WL12XX_REFCLOCK_26 },
+ { 26000000, true, WL12XX_REFCLOCK_26_XTAL },
+ { 38400000, false, WL12XX_REFCLOCK_38 },
+ { 38400000, true, WL12XX_REFCLOCK_38_XTAL },
+ { 52000000, false, WL12XX_REFCLOCK_52 },
+ { 0, false, 0 }
+};
+
+static const struct wl12xx_clock wl12xx_tcxoclock_table[] = {
+ { 16368000, true, WL12XX_TCXOCLOCK_16_368 },
+ { 16800000, true, WL12XX_TCXOCLOCK_16_8 },
+ { 19200000, true, WL12XX_TCXOCLOCK_19_2 },
+ { 26000000, true, WL12XX_TCXOCLOCK_26 },
+ { 32736000, true, WL12XX_TCXOCLOCK_32_736 },
+ { 33600000, true, WL12XX_TCXOCLOCK_33_6 },
+ { 38400000, true, WL12XX_TCXOCLOCK_38_4 },
+ { 52000000, true, WL12XX_TCXOCLOCK_52 },
+ { 0, false, 0 }
+};
+
+static int wl12xx_get_clock_idx(const struct wl12xx_clock *table,
+ u32 freq, bool xtal)
+{
+ int i = 0;
+
+ while(table[i].freq != 0) {
+ if ((table[i].freq == freq) &&
+ (table[i].xtal == xtal))
+ return table[i].hw_idx;
+ i++;
+ };
+
+ return -EINVAL;
+}
+
static int wl12xx_setup(struct wl1271 *wl)
{
struct wl12xx_priv *priv = wl->priv;
@@ -1722,7 +1759,16 @@ static int wl12xx_setup(struct wl1271 *wl)
wl12xx_conf_init(wl);

if (!fref_param) {
- priv->ref_clock = pdata->board_ref_clock;
+ priv->ref_clock = wl12xx_get_clock_idx(wl12xx_refclock_table,
+ pdata->ref_clock_freq,
+ pdata->ref_clock_xtal);
+ if (priv->ref_clock < 0) {
+ wl1271_error("Invalid ref_clock frequency (%d Hz, %s)",
+ pdata->ref_clock_freq,
+ pdata->ref_clock_xtal ? "XTAL" : "not XTAL");
+
+ return priv->ref_clock;
+ }
} else {
if (!strcmp(fref_param, "19.2"))
priv->ref_clock = WL12XX_REFCLOCK_19;
@@ -1741,7 +1787,15 @@ static int wl12xx_setup(struct wl1271 *wl)
}

if (!tcxo_param) {
- priv->tcxo_clock = pdata->board_tcxo_clock;
+ priv->tcxo_clock = wl12xx_get_clock_idx(wl12xx_tcxoclock_table,
+ pdata->tcxo_clock_freq,
+ true);
+ if (priv->tcxo_clock < 0) {
+ wl1271_error("Invalid tcxo_clock frequency (%d Hz)",
+ pdata->tcxo_clock_freq);
+
+ return priv->tcxo_clock;
+ }
} else {
if (!strcmp(tcxo_param, "19.2"))
priv->tcxo_clock = WL12XX_TCXOCLOCK_19_2;
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h
index 9e5484a..05f631b 100644
--- a/drivers/net/wireless/ti/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h
@@ -79,4 +79,32 @@ struct wl12xx_priv {
struct wl127x_rx_mem_pool_addr *rx_mem_addr;
};

+/* Reference clock values */
+enum {
+ WL12XX_REFCLOCK_19 = 0, /* 19.2 MHz */
+ WL12XX_REFCLOCK_26 = 1, /* 26 MHz */
+ WL12XX_REFCLOCK_38 = 2, /* 38.4 MHz */
+ WL12XX_REFCLOCK_52 = 3, /* 52 MHz */
+ WL12XX_REFCLOCK_38_XTAL = 4, /* 38.4 MHz, XTAL */
+ WL12XX_REFCLOCK_26_XTAL = 5, /* 26 MHz, XTAL */
+};
+
+/* TCXO clock values */
+enum {
+ WL12XX_TCXOCLOCK_19_2 = 0, /* 19.2MHz */
+ WL12XX_TCXOCLOCK_26 = 1, /* 26 MHz */
+ WL12XX_TCXOCLOCK_38_4 = 2, /* 38.4MHz */
+ WL12XX_TCXOCLOCK_52 = 3, /* 52 MHz */
+ WL12XX_TCXOCLOCK_16_368 = 4, /* 16.368 MHz */
+ WL12XX_TCXOCLOCK_32_736 = 5, /* 32.736 MHz */
+ WL12XX_TCXOCLOCK_16_8 = 6, /* 16.8 MHz */
+ WL12XX_TCXOCLOCK_33_6 = 7, /* 33.6 MHz */
+};
+
+struct wl12xx_clock {
+ u32 freq;
+ bool xtal;
+ u8 hw_idx;
+};
+
#endif /* __WL12XX_PRIV_H__ */
diff --git a/include/linux/wl12xx.h b/include/linux/wl12xx.h
index ab90b1c..11491ad 100644
--- a/include/linux/wl12xx.h
+++ b/include/linux/wl12xx.h
@@ -26,28 +26,6 @@

#include <linux/err.h>

-/* Reference clock values */
-enum {
- WL12XX_REFCLOCK_19 = 0, /* 19.2 MHz */
- WL12XX_REFCLOCK_26 = 1, /* 26 MHz */
- WL12XX_REFCLOCK_38 = 2, /* 38.4 MHz */
- WL12XX_REFCLOCK_52 = 3, /* 52 MHz */
- WL12XX_REFCLOCK_38_XTAL = 4, /* 38.4 MHz, XTAL */
- WL12XX_REFCLOCK_26_XTAL = 5, /* 26 MHz, XTAL */
-};
-
-/* TCXO clock values */
-enum {
- WL12XX_TCXOCLOCK_19_2 = 0, /* 19.2MHz */
- WL12XX_TCXOCLOCK_26 = 1, /* 26 MHz */
- WL12XX_TCXOCLOCK_38_4 = 2, /* 38.4MHz */
- WL12XX_TCXOCLOCK_52 = 3, /* 52 MHz */
- WL12XX_TCXOCLOCK_16_368 = 4, /* 16.368 MHz */
- WL12XX_TCXOCLOCK_32_736 = 5, /* 32.736 MHz */
- WL12XX_TCXOCLOCK_16_8 = 6, /* 16.8 MHz */
- WL12XX_TCXOCLOCK_33_6 = 7, /* 33.6 MHz */
-};
-
struct wl1251_platform_data {
void (*set_power)(bool enable);
/* SDIO only: IRQ number if WLAN_IRQ line is used, 0 for SDIO IRQs */
@@ -57,8 +35,9 @@ struct wl1251_platform_data {

struct wl12xx_platform_data {
int irq;
- int board_ref_clock;
- int board_tcxo_clock;
+ int ref_clock_freq; /* in Hertz */
+ bool ref_clock_xtal; /* specify whether the clock is XTAL or not */
+ int tcxo_clock_freq; /* in Hertz, tcxo is always XTAL */
};

#ifdef CONFIG_WILINK_PLATFORM_DATA
--
1.8.3.2

2013-07-30 13:05:39

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH v4 3/8] wlcore: remove pwr_in_suspend from platform data

The pwr_in_suspend flag depends on the MMC settings which can be
retrieved from the SDIO subsystem, so it doesn't need to be part of
the platform data structure. Move it to the platform device data that
is passed from SDIO to wlcore.

Signed-off-by: Luciano Coelho <[email protected]>
Reviewed-by: Felipe Balbi <[email protected]>
---
drivers/net/wireless/ti/wlcore/main.c | 3 +--
drivers/net/wireless/ti/wlcore/sdio.c | 2 +-
drivers/net/wireless/ti/wlcore/wlcore_i.h | 1 +
include/linux/wl12xx.h | 1 -
4 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 11dab9a..e771de0 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5900,7 +5900,6 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
struct wl1271 *wl = context;
struct platform_device *pdev = wl->pdev;
struct wlcore_platdev_data *pdev_data = pdev->dev.platform_data;
- struct wl12xx_platform_data *pdata = pdev_data->pdata;

int ret;

@@ -5947,7 +5946,7 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
if (!ret) {
wl->irq_wake_enabled = true;
device_init_wakeup(wl->dev, 1);
- if (pdata->pwr_in_suspend)
+ if (pdev_data->pwr_in_suspend)
wl->hw->wiphy->wowlan = &wlcore_wowlan_support;
}
#endif
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index 29ef249..4c7e8ac 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -260,7 +260,7 @@ static int wl1271_probe(struct sdio_func *func,
dev_dbg(glue->dev, "sdio PM caps = 0x%x\n", mmcflags);

if (mmcflags & MMC_PM_KEEP_POWER)
- pdev_data->pdata->pwr_in_suspend = true;
+ pdev_data->pwr_in_suspend = true;

sdio_set_drvdata(func, glue);

diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index e5e1464..f2c4227 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -209,6 +209,7 @@ struct wl1271_if_operations {
struct wlcore_platdev_data {
struct wl12xx_platform_data *pdata;
struct wl1271_if_operations *if_ops;
+ bool pwr_in_suspend;
};

#define MAX_NUM_KEYS 14
diff --git a/include/linux/wl12xx.h b/include/linux/wl12xx.h
index 1bfcd19..ab90b1c 100644
--- a/include/linux/wl12xx.h
+++ b/include/linux/wl12xx.h
@@ -59,7 +59,6 @@ struct wl12xx_platform_data {
int irq;
int board_ref_clock;
int board_tcxo_clock;
- bool pwr_in_suspend;
};

#ifdef CONFIG_WILINK_PLATFORM_DATA
--
1.8.3.2

2013-07-30 13:11:33

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH v4 5/8] wlcore: add initial device tree support to the sdio module

If platform data is not available, try to get the required information
from the device tree. Register an OF match table and parse the
appropriate device tree nodes.

Parse interrupt property only, for now.

Signed-off-by: Luciano Coelho <[email protected]>
Reviewed-by: Felipe Balbi <[email protected]>
---
drivers/net/wireless/ti/wlcore/sdio.c | 69 ++++++++++++++++++++++++++++++++---
1 file changed, 63 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c
index 4c7e8ac..9370d7e 100644
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -30,7 +30,7 @@
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
-#include <linux/gpio.h>
+#include <linux/of_irq.h>
#include <linux/wl12xx.h>
#include <linux/pm_runtime.h>
#include <linux/printk.h>
@@ -214,6 +214,43 @@ static struct wl1271_if_operations sdio_ops = {
.set_block_size = wl1271_sdio_set_block_size,
};

+static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
+{
+ struct wl12xx_platform_data *pdata;
+ struct device_node *np = dev->of_node;
+
+ if (!np) {
+ np = of_find_matching_node(NULL, dev->driver->of_match_table);
+ if (!np) {
+ dev_notice(dev, "device tree node not available\n");
+ pdata = ERR_PTR(-ENODEV);
+ goto out;
+ }
+ }
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(dev, "can't allocate platform data\n");
+ pdata = ERR_PTR(-ENODEV);
+ goto out;
+ }
+
+ pdata->irq = irq_of_parse_and_map(np, 0);
+ if (pdata->irq < 0) {
+ dev_err(dev, "can't get interrupt gpio from the device tree\n");
+ goto out_free;
+ }
+
+ goto out;
+
+out_free:
+ kfree(pdata);
+ pdata = ERR_PTR(-ENODEV);
+
+out:
+ return pdata;
+}
+
static int wl1271_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
@@ -248,11 +285,22 @@ static int wl1271_probe(struct sdio_func *func,
/* Use block mode for transferring over one block size of data */
func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;

+ /* The pdata allocated here is freed when the device is freed,
+ * so we don't need an additional out label to free it in case
+ * of error further on.
+ */
+
+ /* Try to get legacy platform data from the board file */
pdev_data->pdata = wl12xx_get_platform_data();
if (IS_ERR(pdev_data->pdata)) {
- ret = PTR_ERR(pdev_data->pdata);
- dev_err(glue->dev, "missing wlan platform data: %d\n", ret);
- goto out_free_glue;
+ dev_info(&func->dev,
+ "legacy platform data not found, trying device tree\n");
+
+ pdev_data->pdata = wlcore_get_pdata_from_of(&func->dev);
+ if (IS_ERR(pdev_data->pdata)) {
+ dev_err(&func->dev, "can't get platform data\n");
+ goto out_free_glue;
+ }
}

/* if sdio can keep power while host is suspended, enable wow */
@@ -386,16 +434,25 @@ static const struct dev_pm_ops wl1271_sdio_pm_ops = {
};
#endif

+static const struct of_device_id wlcore_sdio_of_match_table[] = {
+ { .compatible = "ti,wilink6" },
+ { .compatible = "ti,wilink7" },
+ { .compatible = "ti,wilink8" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, wlcore_sdio_of_match_table);
+
static struct sdio_driver wl1271_sdio_driver = {
.name = "wl1271_sdio",
.id_table = wl1271_devices,
.probe = wl1271_probe,
.remove = wl1271_remove,
-#ifdef CONFIG_PM
.drv = {
+#ifdef CONFIG_PM
.pm = &wl1271_sdio_pm_ops,
- },
#endif
+ .of_match_table = of_match_ptr(wlcore_sdio_of_match_table),
+ },
};

static int __init wl1271_init(void)
--
1.8.3.2

2013-07-30 22:35:41

by Mike Turquette

[permalink] [raw]
Subject: Re: [PATCH v4 6/8] wlcore: sdio: add wilink clock providers

Quoting Luciano Coelho (2013-07-30 06:04:34)
> +static const struct of_device_id wlcore_sdio_of_clk_match_table[] = {
> + { .compatible = "ti,wilink-clock" },
> +};
> +
> static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
> {
> struct wl12xx_platform_data *pdata;
> struct device_node *np = dev->of_node;
> + struct device_node *clock_node;
>
> if (!np) {
> np = of_find_matching_node(NULL, dev->driver->of_match_table);
> @@ -241,6 +247,9 @@ static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
> goto out_free;
> }
>
> + for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table)
> + of_fixed_clk_setup(clock_node);

Hi Luciano,

Any reason for establishing your own compatible string if you just plan
to use the fixed rate clock? You could just use "fixed-clock" compatible
in your DTS.

I will be posting patches this week which makes the fixed-rate clock a
proper driver and matches that compatible string to instantiate those
clocks. That means that your driver could probably remove the clock
setup code completely.

Regards,
Mike

> +
> goto out;
>
> out_free:
> --
> 1.8.3.2

2013-07-30 23:05:08

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH v4 6/8] wlcore: sdio: add wilink clock providers

On Tue, 2013-07-30 at 15:35 -0700, Mike Turquette wrote:
> Quoting Luciano Coelho (2013-07-30 06:04:34)
> > +static const struct of_device_id wlcore_sdio_of_clk_match_table[] = {
> > + { .compatible = "ti,wilink-clock" },
> > +};
> > +
> > static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
> > {
> > struct wl12xx_platform_data *pdata;
> > struct device_node *np = dev->of_node;
> > + struct device_node *clock_node;
> >
> > if (!np) {
> > np = of_find_matching_node(NULL, dev->driver->of_match_table);
> > @@ -241,6 +247,9 @@ static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
> > goto out_free;
> > }
> >
> > + for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table)
> > + of_fixed_clk_setup(clock_node);
>
> Hi Luciano,

Hi Mike,


> Any reason for establishing your own compatible string if you just plan
> to use the fixed rate clock? You could just use "fixed-clock" compatible
> in your DTS.

The reason is that I can't call of_clk_init(), because this function is
not exported and my module can't use it. I would have to link with the
clk code to be able to call it.

Also, I reckoned that, since these clock cannot be used by anyone else
than the WiLink module itself, it would make sense to have a different
compatible string.


> I will be posting patches this week which makes the fixed-rate clock a
> proper driver and matches that compatible string to instantiate those
> clocks. That means that your driver could probably remove the clock
> setup code completely.

Okay, if this is done, then I could probably use "fixed-clock" directly,
since the driver itself will take care of going through the DT and
initializing all the fixed-clocks.

--
Luca.

2014-02-28 07:27:11

by Yegor Yefremov

[permalink] [raw]
Subject: Re: [PATCH v4 0/8] wilink: add device tree support

On Tue, Jul 30, 2013 at 3:04 PM, Luciano Coelho <[email protected]> wrote:
> Hi,
>
> This patch series adds device tree support to the wlcore_sdio driver,
> which is used by WiLink6, WiLink7 and WiLink8.
>
> The first patches do some clean-up to make the data needed in the
> wilink device tree node smaller. The remaining patches implement the
> actual device tree node parsing in wlcore_sdio.
>
> Regarding the XTAL clock issues, for now we don't support XTAL mode
> with DT, but I have sent a proposal for a small change in the clock
> framework to support this, but it's still under discussions [1].
>
> The DTS file changes will be sent separately, since they need to go
> via different trees.
>
> A new version of the bindings documentation has been sent [2] and, if
> no more comments are given to it, I'll apply it via my tree.
>
> [1] http://news.gmane.org/find-root.php?message_id=1372971912-10877-1-git-send-email-coelho@ti.com
> [2] http://news.gmane.org/find-root.php?message_id=1375109728-5931-1-git-send-email-coelho@ti.com
>
> Changes in v4:
>
> * Rebased on top of 3.11-rc3 (eg. no more changes on the board files
> that were removed);
>
> * Use the new irq_get_trigger_type() instead of
> irqd_get_trigger_type() (thanks Javier);
>
> * Added some missing const's (thanks Felipe);
>
> * Reverted Tony's workaround to get WiLink to work on Panda while DT
> was not supported yet.
>
>
> Please review.

What is the state of the series? Who is now responsible for the
patches? What issues were still not handled?

Yegor

> Luciano Coelho (8):
> wl1251: split wl251 platform data to a separate structure
> wlcore: set irq_flags in the board files instead of hiding behind a
> quirk
> wlcore: remove pwr_in_suspend from platform data
> wl12xx: use frequency instead of enumerations for pdata clocks
> wlcore: add initial device tree support to the sdio module
> wlcore: sdio: add wilink clock providers
> wlcore: sdio: get clocks from device tree
> wlcore/wl12xx: check if we got correct clock data from DT
>
> arch/arm/mach-davinci/board-da850-evm.c | 11 ++-
> arch/arm/mach-omap2/board-omap3evm.c | 22 ++++-
> arch/arm/mach-omap2/board-omap3pandora.c | 4 +-
> arch/arm/mach-omap2/board-rx51-peripherals.c | 2 +-
> arch/arm/mach-omap2/board-zoom-peripherals.c | 33 +++++++-
> arch/arm/mach-omap2/devices.c | 39 ---------
> drivers/net/wireless/ti/wilink_platform_data.c | 37 ++++++--
> drivers/net/wireless/ti/wl1251/sdio.c | 12 +--
> drivers/net/wireless/ti/wl1251/spi.c | 2 +-
> drivers/net/wireless/ti/wl12xx/main.c | 78 +++++++++++++++--
> drivers/net/wireless/ti/wl12xx/wl12xx.h | 28 +++++++
> drivers/net/wireless/ti/wlcore/debugfs.c | 2 +-
> drivers/net/wireless/ti/wlcore/main.c | 20 ++---
> drivers/net/wireless/ti/wlcore/sdio.c | 112 +++++++++++++++++++++++--
> drivers/net/wireless/ti/wlcore/wlcore.h | 5 +-
> drivers/net/wireless/ti/wlcore/wlcore_i.h | 1 +
> include/linux/wl12xx.h | 52 +++++-------
> 17 files changed, 340 insertions(+), 120 deletions(-)
>
> --
> 1.8.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/

2014-02-28 09:22:14

by Alexandre Belloni

[permalink] [raw]
Subject: Re: [PATCH v4 0/8] wilink: add device tree support

On 28/02/2014 at 08:26:46 +0100, Yegor Yefremov wrote :
>
> What is the state of the series? Who is now responsible for the
> patches? What issues were still not handled?
>

We probably want to end that discussion before taking those bindings in:
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-February/232185.html

I've hit the issue, precisely using those bindings.

--
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

2014-02-28 12:29:57

by Luca Coelho

[permalink] [raw]
Subject: Re: [PATCH v4 0/8] wilink: add device tree support

On Fri, 2014-02-28 at 08:26 +0100, Yegor Yefremov wrote:
> On Tue, Jul 30, 2013 at 3:04 PM, Luciano Coelho <[email protected]> wrote:
> > Hi,
> >
> > This patch series adds device tree support to the wlcore_sdio driver,
> > which is used by WiLink6, WiLink7 and WiLink8.
> >
> > The first patches do some clean-up to make the data needed in the
> > wilink device tree node smaller. The remaining patches implement the
> > actual device tree node parsing in wlcore_sdio.
> >
> > Regarding the XTAL clock issues, for now we don't support XTAL mode
> > with DT, but I have sent a proposal for a small change in the clock
> > framework to support this, but it's still under discussions [1].
> >
> > The DTS file changes will be sent separately, since they need to go
> > via different trees.
> >
> > A new version of the bindings documentation has been sent [2] and, if
> > no more comments are given to it, I'll apply it via my tree.
> >
> > [1] http://news.gmane.org/find-root.php?message_id=1372971912-10877-1-git-send-email-coelho@ti.com
> > [2] http://news.gmane.org/find-root.php?message_id=1375109728-5931-1-git-send-email-coelho@ti.com
> >
> > Changes in v4:
> >
> > * Rebased on top of 3.11-rc3 (eg. no more changes on the board files
> > that were removed);
> >
> > * Use the new irq_get_trigger_type() instead of
> > irqd_get_trigger_type() (thanks Javier);
> >
> > * Added some missing const's (thanks Felipe);
> >
> > * Reverted Tony's workaround to get WiLink to work on Panda while DT
> > was not supported yet.
> >
> >
> > Please review.
>
> What is the state of the series? Who is now responsible for the
> patches? What issues were still not handled?

There were some comments about this series (or more precisely, the one
that added the bindings documentation[1]). Unfortunately, I have left
TI since and have no time to handle them. Feel free to pick it up and
continue from there.

[1] https://lkml.org/lkml/2013/7/30/712

--
Cheers,
Luca.

2014-02-28 14:12:20

by Luca Coelho

[permalink] [raw]
Subject: Re: [PATCH v4 0/8] wilink: add device tree support

On Fri, 2014-02-28 at 14:29 +0200, Luca Coelho wrote:
> On Fri, 2014-02-28 at 08:26 +0100, Yegor Yefremov wrote:
> > On Tue, Jul 30, 2013 at 3:04 PM, Luciano Coelho <[email protected]> wrote:
> > > Hi,
> > >
> > > This patch series adds device tree support to the wlcore_sdio driver,
> > > which is used by WiLink6, WiLink7 and WiLink8.
> > >
> > > The first patches do some clean-up to make the data needed in the
> > > wilink device tree node smaller. The remaining patches implement the
> > > actual device tree node parsing in wlcore_sdio.
> > >
> > > Regarding the XTAL clock issues, for now we don't support XTAL mode
> > > with DT, but I have sent a proposal for a small change in the clock
> > > framework to support this, but it's still under discussions [1].
> > >
> > > The DTS file changes will be sent separately, since they need to go
> > > via different trees.
> > >
> > > A new version of the bindings documentation has been sent [2] and, if
> > > no more comments are given to it, I'll apply it via my tree.
> > >
> > > [1] http://news.gmane.org/find-root.php?message_id=1372971912-10877-1-git-send-email-coelho@ti.com
> > > [2] http://news.gmane.org/find-root.php?message_id=1375109728-5931-1-git-send-email-coelho@ti.com
> > >
> > > Changes in v4:
> > >
> > > * Rebased on top of 3.11-rc3 (eg. no more changes on the board files
> > > that were removed);
> > >
> > > * Use the new irq_get_trigger_type() instead of
> > > irqd_get_trigger_type() (thanks Javier);
> > >
> > > * Added some missing const's (thanks Felipe);
> > >
> > > * Reverted Tony's workaround to get WiLink to work on Panda while DT
> > > was not supported yet.
> > >
> > >
> > > Please review.
> >
> > What is the state of the series? Who is now responsible for the
> > patches? What issues were still not handled?
>
> There were some comments about this series (or more precisely, the one
> that added the bindings documentation[1]). Unfortunately, I have left
> TI since and have no time to handle them. Feel free to pick it up and
> continue from there.
>
> [1] https://lkml.org/lkml/2013/7/30/712

There's also this thread, which I'm not sure has been resolved:

http://thread.gmane.org/gmane.linux.kernel/1520752

--
Luca.