Skip to contentSkip to conversation

native support for wl1271 on ZOOM

PATCH Superseded Ohad Ben-Cohen 5 participants 29 messages Aug 11, 2010 – Aug 16, 2010

Subsystems (7)

v4 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v4 cover native support for wl1271 on ZOOM

This patch series adds native support for wl1271 on ZOOM.

Changes since v3:
- slot is marked nonremovable
- no explicit slot ocr mask
- dont split hsmmc mmc23 power control

Patches are based on linux-next (as of Aug 7th), and tested on ZOOM2.

Please note that I am going to have a very limited email access in the next three weeks, so I might not respond right away.

Thanks,

Ohad Ben-Cohen (8):
wireless: wl1271: make wl12xx.h common to both spi and sdio
wireless: wl1271: support return value for the set power func
wireless: wl1271: add platform driver to get board data
wireless: wl1271: take irq info from private board data
wireless: wl1271: make ref_clock configurable by board
omap: hsmmc: remove unused variable
omap: zoom: add fixed regulator device for wlan
omap: zoom: add mmc3/wl1271 device support

 arch/arm/mach-omap2/board-zoom-peripherals.c |   69 +++++++++++++++
 drivers/mmc/host/omap_hsmmc.c                |    1 -
 drivers/net/wireless/wl12xx/wl1251_sdio.c    |    2 +-
 drivers/net/wireless/wl12xx/wl1251_spi.c     |    2 +-
 drivers/net/wireless/wl12xx/wl1271.h         |   15 +++-
 drivers/net/wireless/wl12xx/wl1271_boot.c    |    9 +-
 drivers/net/wireless/wl12xx/wl1271_boot.h    |    1 -
 drivers/net/wireless/wl12xx/wl1271_io.h      |    8 +-
 drivers/net/wireless/wl12xx/wl1271_main.c    |    4 +-
 drivers/net/wireless/wl12xx/wl1271_sdio.c    |  120 +++++++++++++++++++++++---
 drivers/net/wireless/wl12xx/wl1271_spi.c     |    8 ++-
 include/linux/spi/wl12xx.h                   |   34 -------
 include/linux/wl12xx.h                       |   35 ++++++++
 13 files changed, 245 insertions(+), 63 deletions(-)
 delete mode 100644 include/linux/spi/wl12xx.h
 create mode 100644 include/linux/wl12xx.h
#1 lore raw

PATCH v4 1/8 wireless: wl1271: make wl12xx.h common to both spi and sdio

Move wl12xx.h outside of the spi-specific location, so it can be shared with both spi and sdio solutions.

---
 drivers/net/wireless/wl12xx/wl1251_sdio.c |    2 +-
 drivers/net/wireless/wl12xx/wl1251_spi.c  |    2 +-
 drivers/net/wireless/wl12xx/wl1271_spi.c  |    2 +-
 include/linux/spi/wl12xx.h                |   34 -----------------------------
 include/linux/wl12xx.h                    |   34 +++++++++++++++++++++++++++++
 5 files changed, 37 insertions(+), 37 deletions(-)
 delete mode 100644 include/linux/spi/wl12xx.h
 create mode 100644 include/linux/wl12xx.h
drivers/net/wireless/wl12xx/wl1251_sdio.c +1 -1
index b901b61..a319df1 100644
@@ -24,7 +24,7 @@
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/sdio_ids.h>
 #include <linux/platform_device.h>
-#include <linux/spi/wl12xx.h>
+#include <linux/wl12xx.h>
 #include <linux/irq.h>
 
 #include "wl1251.h"
drivers/net/wireless/wl12xx/wl1251_spi.c +1 -1
index 27fdfaa..a6faf3e 100644
@@ -26,7 +26,7 @@
 #include <linux/slab.h>
 #include <linux/crc7.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/wl12xx.h>
+#include <linux/wl12xx.h>
 
 #include "wl1251.h"
 #include "wl1251_reg.h"
drivers/net/wireless/wl12xx/wl1271_spi.c +1 -1
index 4cb99c5..c3fdab7 100644
@@ -25,7 +25,7 @@
 #include <linux/module.h>
 #include <linux/crc7.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/wl12xx.h>
+#include <linux/wl12xx.h>
 #include <linux/slab.h>
 
 #include "wl1271.h"
include/linux/spi/wl12xx.h deleted +0 -34
deleted file mode 100644
index a223ecb..0000000
@@ -1,34 +0,0 @@
-/*
- * This file is part of wl12xx
- *
- * Copyright (C) 2009 Nokia Corporation
- *
- * Contact: Kalle Valo <[email protected]>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef _LINUX_SPI_WL12XX_H
-#define _LINUX_SPI_WL12XX_H
-
-struct wl12xx_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;
-};
-
-#endif
include/linux/wl12xx.h new file +34 -0
new file mode 100644
index 0000000..137ac89
@@ -0,0 +1,34 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Kalle Valo <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef _LINUX_WL12XX_H
+#define _LINUX_WL12XX_H
+
+struct wl12xx_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;
+};
+
+#endif
Signature · 1 line
1.7.0.4
#2 lore raw

PATCH v4 2/8 wireless: wl1271: support return value for the set power func

In reply to Ohad Ben-Cohen

Make it possible for the set power method to indicate a success/failure return value. This is needed to support more complex power on/off operations such as bringing up (and down) sdio functions.

---
 drivers/net/wireless/wl12xx/wl1271.h      |    2 +-
 drivers/net/wireless/wl12xx/wl1271_io.h   |    8 +++++---
 drivers/net/wireless/wl12xx/wl1271_main.c |    4 +++-
 drivers/net/wireless/wl12xx/wl1271_sdio.c |    4 +++-
 drivers/net/wireless/wl12xx/wl1271_spi.c  |    4 +++-
 5 files changed, 15 insertions(+), 7 deletions(-)
drivers/net/wireless/wl12xx/wl1271.h +1 -1
index dd3cee6..faa5925 100644
@@ -313,7 +313,7 @@ struct wl1271_if_operations {
 		     bool fixed);
 	void (*reset)(struct wl1271 *wl);
 	void (*init)(struct wl1271 *wl);
-	void (*power)(struct wl1271 *wl, bool enable);
+	int (*power)(struct wl1271 *wl, bool enable);
 	struct device* (*dev)(struct wl1271 *wl);
 	void (*enable_irq)(struct wl1271 *wl);
 	void (*disable_irq)(struct wl1271 *wl);
drivers/net/wireless/wl12xx/wl1271_io.h +5 -3
index bc806c7..4a5b92c 100644
@@ -144,10 +144,12 @@ static inline void wl1271_power_off(struct wl1271 *wl)
 	clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
 }
 
-static inline void wl1271_power_on(struct wl1271 *wl)
+static inline int wl1271_power_on(struct wl1271 *wl)
 {
-	wl->if_ops->power(wl, true);
-	set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+	int ret = wl->if_ops->power(wl, true);
+	if (ret == 0)
+		set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+	return ret;
 }
 
 
drivers/net/wireless/wl12xx/wl1271_main.c +3 -1
index 9d68f00..e6e0852 100644
@@ -621,7 +621,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
 	int ret = 0;
 
 	msleep(WL1271_PRE_POWER_ON_SLEEP);
-	wl1271_power_on(wl);
+	ret = wl1271_power_on(wl);
+	if (ret < 0)
+		goto out;
 	msleep(WL1271_POWER_ON_SLEEP);
 	wl1271_io_reset(wl);
 	wl1271_io_init(wl);
drivers/net/wireless/wl12xx/wl1271_sdio.c +3 -1
index 7059b5c..c41293a 100644
@@ -152,7 +152,7 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
 
 }
 
-static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
+static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
 {
 	struct sdio_func *func = wl_to_func(wl);
 
@@ -167,6 +167,8 @@ static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
 		sdio_disable_func(func);
 		sdio_release_host(func);
 	}
+
+	return 0;
 }
 
 static struct wl1271_if_operations sdio_ops = {
drivers/net/wireless/wl12xx/wl1271_spi.c +3 -1
index c3fdab7..de56d8d 100644
@@ -312,10 +312,12 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
 	return IRQ_HANDLED;
 }
 
-static void wl1271_spi_set_power(struct wl1271 *wl, bool enable)
+static int wl1271_spi_set_power(struct wl1271 *wl, bool enable)
 {
 	if (wl->set_power)
 		wl->set_power(enable);
+
+	return 0;
 }
 
 static struct wl1271_if_operations spi_ops = {
Signature · 1 line
1.7.0.4
#3 lore raw

PATCH v4 2/8 wireless: wl1271: support return value for the set power func

Ohad,

Quoted 47 lines

-----Original Message-----
From: linux-omap-owner at vger.kernel.org [mailto:linux-omap- owner at vger.kernel.org] On Behalf Of Ohad Ben-Cohen
Sent: Wednesday, August 11, 2010 11:52 PM
To: linux-wireless at vger.kernel.org; linux-mmc at vger.kernel.org; linux- omap at vger.kernel.org
Cc: Ido Yariv; Mark Brown; linux-arm-kernel at lists.infradead.org; Chikkature Rajashekar, Madhusudhan; Luciano Coelho; akpm at linux- foundation.org; San Mehat; Roger Quadros; Tony Lindgren; Nicolas Pitre; Pandita, Vikram; Kalle Valo; Ohad Ben-Cohen
Subject: [PATCH v4 2/8] wireless: wl1271: support return value for the set power func

Make it possible for the set power method to indicate a success/failure return value. This is needed to support more complex power on/off operations such as bringing up (and down) sdio functions.

---
 drivers/net/wireless/wl12xx/wl1271.h      |    2 +-
 drivers/net/wireless/wl12xx/wl1271_io.h   |    8 +++++---
 drivers/net/wireless/wl12xx/wl1271_main.c |    4 +++-
 drivers/net/wireless/wl12xx/wl1271_sdio.c |    4 +++-
 drivers/net/wireless/wl12xx/wl1271_spi.c  |    4 +++-
 5 files changed, 15 insertions(+), 7 deletions(-)
drivers/net/wireless/wl12xx/wl1271.h +1 -1
index dd3cee6..faa5925 100644
@@ -313,7 +313,7 @@ struct wl1271_if_operations {
 		     bool fixed);
 	void (*reset)(struct wl1271 *wl);
 	void (*init)(struct wl1271 *wl);
-	void (*power)(struct wl1271 *wl, bool enable);
+	int (*power)(struct wl1271 *wl, bool enable);
 	struct device* (*dev)(struct wl1271 *wl);
 	void (*enable_irq)(struct wl1271 *wl);
 	void (*disable_irq)(struct wl1271 *wl);
drivers/net/wireless/wl12xx/wl1271_io.h +0 -0
index bc806c7..4a5b92c 100644

drivers/net/wireless/wl12xx/wl1271_io.h static inline void wl1271_power_off(struct wl1271 · line 150

Quoted 10 lines
drivers/net/wireless/wl12xx/wl1271_io.h +2 -3
@@ -144,10 +144,12 @@ static inline void wl1271_power_off(struct wl1271
 *wl)
 	clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
 }
 
-static inline void wl1271_power_on(struct wl1271 *wl)
+static inline int wl1271_power_on(struct wl1271 *wl)
 {
-	wl->if_ops->power(wl, true);
-	set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+	int ret = wl->if_ops->power(wl, true);

Just a minor comment, need a blank line here?

Quoted 73 lines
drivers/net/wireless/wl12xx/wl1271_io.h +3 -0
+	if (ret == 0)
+		set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+	return ret;
 }
 
drivers/net/wireless/wl12xx/wl1271_main.c +3 -1
index 9d68f00..e6e0852 100644
@@ -621,7 +621,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
 	int ret = 0;
 
 	msleep(WL1271_PRE_POWER_ON_SLEEP);
-	wl1271_power_on(wl);
+	ret = wl1271_power_on(wl);
+	if (ret < 0)
+		goto out;
 	msleep(WL1271_POWER_ON_SLEEP);
 	wl1271_io_reset(wl);
 	wl1271_io_init(wl);
drivers/net/wireless/wl12xx/wl1271_sdio.c +3 -1
index 7059b5c..c41293a 100644
@@ -152,7 +152,7 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl,
 int addr, void *buf,
 
 }
 
-static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
+static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
 {
 	struct sdio_func *func = wl_to_func(wl);
@@ -167,6 +167,8 @@ static void wl1271_sdio_set_power(struct wl1271 *wl,
 bool enable)
 		sdio_disable_func(func);
 		sdio_release_host(func);
 	}
+
+	return 0;
 }
 

static struct wl1271_if_operations sdio_ops = {

drivers/net/wireless/wl12xx/wl1271_spi.c +3 -2
index c3fdab7..de56d8d 100644
@@ -312,10 +312,12 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
 	return IRQ_HANDLED;
 }
 
-static void wl1271_spi_set_power(struct wl1271 *wl, bool enable)
+static int wl1271_spi_set_power(struct wl1271 *wl, bool enable)
 {
 	if (wl->set_power)
 		wl->set_power(enable);
+
+	return 0;
 }
 
 static struct wl1271_if_operations spi_ops = {
--

1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#4 lore raw

PATCH v4 2/8 wireless: wl1271: support return value for the set power func

Quoted 4 lines · Tarun Kanti
Quoted 3 lines

- ? ? wl->if_ops->power(wl, true);
- ? ? set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+ ? ? int ret = wl->if_ops->power(wl, true);

Just a minor comment, need a blank line here?

Can't hurt, thanks.

Quoted 74 lines
Quoted 73 lines

+ ? ? if (ret == 0)
+ ? ? ? ? ? ? set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+ ? ? return ret;
?}

drivers/net/wireless/wl12xx/wl1271_main.c +3 -1
index 9d68f00..e6e0852 100644
@@ -621,7 +621,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
 ? ? ? int ret = 0;
 
 ? ? ? msleep(WL1271_PRE_POWER_ON_SLEEP);
- ? ? wl1271_power_on(wl);
+ ? ? ret = wl1271_power_on(wl);
+ ? ? if (ret < 0)
+ ? ? ? ? ? ? goto out;
 ? ? ? msleep(WL1271_POWER_ON_SLEEP);
 ? ? ? wl1271_io_reset(wl);
 ? ? ? wl1271_io_init(wl);
drivers/net/wireless/wl12xx/wl1271_sdio.c +3 -1
index 7059b5c..c41293a 100644
@@ -152,7 +152,7 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl,
 int addr, void *buf,
 
 ?}
 
-static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
+static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
 ?{
 ? ? ? struct sdio_func *func = wl_to_func(wl);
@@ -167,6 +167,8 @@ static void wl1271_sdio_set_power(struct wl1271 *wl,
 bool enable)
 ? ? ? ? ? ? ? sdio_disable_func(func);
 ? ? ? ? ? ? ? sdio_release_host(func);
 ? ? ? }
+
+ ? ? return 0;
 ?}
 

?static struct wl1271_if_operations sdio_ops = {

drivers/net/wireless/wl12xx/wl1271_spi.c +3 -2
index c3fdab7..de56d8d 100644
@@ -312,10 +312,12 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
 ? ? ? return IRQ_HANDLED;
 ?}
 
-static void wl1271_spi_set_power(struct wl1271 *wl, bool enable)
+static int wl1271_spi_set_power(struct wl1271 *wl, bool enable)
 ?{
 ? ? ? if (wl->set_power)
 ? ? ? ? ? ? ? wl->set_power(enable);
+
+ ? ? return 0;
 ?}
 
 ?static struct wl1271_if_operations spi_ops = {
--

1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html

#5 lore raw

RE: [PATCH v4 2/8] wireless: wl1271: support return value for the set power func

In reply to Ohad Ben-Cohen

Ohad,

Quoted 47 lines

-----Original Message-----
From: [email protected] [mailto:linux-omap- [email protected]] On Behalf Of Ohad Ben-Cohen
Sent: Wednesday, August 11, 2010 11:52 PM
To: [email protected]; [email protected]; linux- [email protected]
Cc: Ido Yariv; Mark Brown; [email protected]; Chikkature Rajashekar, Madhusudhan; Luciano Coelho; akpm@linux- foundation.org; San Mehat; Roger Quadros; Tony Lindgren; Nicolas Pitre; Pandita, Vikram; Kalle Valo; Ohad Ben-Cohen
Subject: [PATCH v4 2/8] wireless: wl1271: support return value for the set power func

Make it possible for the set power method to indicate a success/failure return value. This is needed to support more complex power on/off operations such as bringing up (and down) sdio functions.

---
 drivers/net/wireless/wl12xx/wl1271.h      |    2 +-
 drivers/net/wireless/wl12xx/wl1271_io.h   |    8 +++++---
 drivers/net/wireless/wl12xx/wl1271_main.c |    4 +++-
 drivers/net/wireless/wl12xx/wl1271_sdio.c |    4 +++-
 drivers/net/wireless/wl12xx/wl1271_spi.c  |    4 +++-
 5 files changed, 15 insertions(+), 7 deletions(-)
drivers/net/wireless/wl12xx/wl1271.h +1 -1
index dd3cee6..faa5925 100644
@@ -313,7 +313,7 @@ struct wl1271_if_operations {
 		     bool fixed);
 	void (*reset)(struct wl1271 *wl);
 	void (*init)(struct wl1271 *wl);
-	void (*power)(struct wl1271 *wl, bool enable);
+	int (*power)(struct wl1271 *wl, bool enable);
 	struct device* (*dev)(struct wl1271 *wl);
 	void (*enable_irq)(struct wl1271 *wl);
 	void (*disable_irq)(struct wl1271 *wl);
drivers/net/wireless/wl12xx/wl1271_io.h +0 -0
index bc806c7..4a5b92c 100644

drivers/net/wireless/wl12xx/wl1271_io.h static inline void wl1271_power_off(struct wl1271 · line 150

Quoted 10 lines
drivers/net/wireless/wl12xx/wl1271_io.h +2 -3
@@ -144,10 +144,12 @@ static inline void wl1271_power_off(struct wl1271
 *wl)
 	clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
 }
 
-static inline void wl1271_power_on(struct wl1271 *wl)
+static inline int wl1271_power_on(struct wl1271 *wl)
 {
-	wl->if_ops->power(wl, true);
-	set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+	int ret = wl->if_ops->power(wl, true);

Just a minor comment, need a blank line here?

Quoted 73 lines
drivers/net/wireless/wl12xx/wl1271_io.h +3 -0
+	if (ret == 0)
+		set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+	return ret;
 }
 
drivers/net/wireless/wl12xx/wl1271_main.c +3 -1
index 9d68f00..e6e0852 100644
@@ -621,7 +621,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
 	int ret = 0;
 
 	msleep(WL1271_PRE_POWER_ON_SLEEP);
-	wl1271_power_on(wl);
+	ret = wl1271_power_on(wl);
+	if (ret < 0)
+		goto out;
 	msleep(WL1271_POWER_ON_SLEEP);
 	wl1271_io_reset(wl);
 	wl1271_io_init(wl);
drivers/net/wireless/wl12xx/wl1271_sdio.c +3 -1
index 7059b5c..c41293a 100644
@@ -152,7 +152,7 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl,
 int addr, void *buf,
 
 }
 
-static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
+static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
 {
 	struct sdio_func *func = wl_to_func(wl);
@@ -167,6 +167,8 @@ static void wl1271_sdio_set_power(struct wl1271 *wl,
 bool enable)
 		sdio_disable_func(func);
 		sdio_release_host(func);
 	}
+
+	return 0;
 }
 

static struct wl1271_if_operations sdio_ops = {

drivers/net/wireless/wl12xx/wl1271_spi.c +3 -2
index c3fdab7..de56d8d 100644
@@ -312,10 +312,12 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
 	return IRQ_HANDLED;
 }
 
-static void wl1271_spi_set_power(struct wl1271 *wl, bool enable)
+static int wl1271_spi_set_power(struct wl1271 *wl, bool enable)
 {
 	if (wl->set_power)
 		wl->set_power(enable);
+
+	return 0;
 }
 
 static struct wl1271_if_operations spi_ops = {
--

1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#6 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

In reply to Ohad Ben-Cohen

Dynamically create and register a platform driver, that will be used to to receive board-specific information like irq and reference clock numbers.

The driver is created dynamically in order to avoid the 1-device limitation of a fixed platform driver name.

---
 drivers/net/wireless/wl12xx/wl1271.h      |   12 ++++
 drivers/net/wireless/wl12xx/wl1271_sdio.c |  103 +++++++++++++++++++++++++++--
 2 files changed, 108 insertions(+), 7 deletions(-)
drivers/net/wireless/wl12xx/wl1271.h +12 -0
index faa5925..013eabb 100644
@@ -31,6 +31,7 @@
 #include <linux/list.h>
 #include <linux/bitops.h>
 #include <net/mac80211.h>
+#include <linux/platform_device.h>
 
 #include "wl1271_conf.h"
 #include "wl1271_ini.h"
@@ -319,8 +320,19 @@ struct wl1271_if_operations {
 	void (*disable_irq)(struct wl1271 *wl);
 };
 
+/* exact size needed for "wl1271_plat.x" */
+#define WL12XX_PLAT_NAME_LEN 14
+
+struct wl12xx_plat_instance {
+	struct platform_driver pdriver;
+	char name[WL12XX_PLAT_NAME_LEN];
+	struct wl12xx_platform_data *pdata;
+	struct completion data_ready;
+};
+
 struct wl1271 {
 	struct platform_device *plat_dev;
+	struct wl12xx_plat_instance *pinstance;
 	struct ieee80211_hw *hw;
 	bool mac80211_registered;
 
drivers/net/wireless/wl12xx/wl1271_sdio.c +96 -7

149 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#7 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

Ohad,

Quoted 78 lines

-----Original Message-----
From: linux-omap-owner at vger.kernel.org [mailto:linux-omap- owner at vger.kernel.org] On Behalf Of Ohad Ben-Cohen
Sent: Wednesday, August 11, 2010 11:52 PM
To: linux-wireless at vger.kernel.org; linux-mmc at vger.kernel.org; linux- omap at vger.kernel.org
Cc: Ido Yariv; Mark Brown; linux-arm-kernel at lists.infradead.org; Chikkature Rajashekar, Madhusudhan; Luciano Coelho; akpm at linux- foundation.org; San Mehat; Roger Quadros; Tony Lindgren; Nicolas Pitre; Pandita, Vikram; Kalle Valo; Ohad Ben-Cohen
Subject: [PATCH v4 3/8] wireless: wl1271: add platform driver to get board data

Dynamically create and register a platform driver, that will be used to to receive board-specific information like irq and reference clock numbers.

The driver is created dynamically in order to avoid the 1-device limitation of a fixed platform driver name.

---
 drivers/net/wireless/wl12xx/wl1271.h      |   12 ++++
 drivers/net/wireless/wl12xx/wl1271_sdio.c |  103
+++++++++++++++++++++++++++--
 2 files changed, 108 insertions(+), 7 deletions(-)
drivers/net/wireless/wl12xx/wl1271.h +12 -0
index faa5925..013eabb 100644
@@ -31,6 +31,7 @@
 #include <linux/list.h>
 #include <linux/bitops.h>
 #include <net/mac80211.h>
+#include <linux/platform_device.h>
 
 #include "wl1271_conf.h"
 #include "wl1271_ini.h"
@@ -319,8 +320,19 @@ struct wl1271_if_operations {
 	void (*disable_irq)(struct wl1271 *wl);
 };
 
+/* exact size needed for "wl1271_plat.x" */
+#define WL12XX_PLAT_NAME_LEN 14
+
+struct wl12xx_plat_instance {
+	struct platform_driver pdriver;
+	char name[WL12XX_PLAT_NAME_LEN];
+	struct wl12xx_platform_data *pdata;
+	struct completion data_ready;
+};
+
 struct wl1271 {
 	struct platform_device *plat_dev;
+	struct wl12xx_plat_instance *pinstance;
 	struct ieee80211_hw *hw;
 	bool mac80211_registered;
 
drivers/net/wireless/wl12xx/wl1271_sdio.c +4 -0
index c41293a..68b512b 100644
@@ -28,7 +28,11 @@
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/wl12xx.h>
 #include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
 
 #include "wl1271.h"
 #include "wl12xx_80211.h"

drivers/net/wireless/wl12xx/wl1271_sdio.c static struct wl1271_if_operations sdio_ops = { · line 194

Quoted 9 lines
drivers/net/wireless/wl12xx/wl1271_sdio.c +6 -0
@@ -182,10 +186,84 @@ static struct wl1271_if_operations sdio_ops = {
 	.disable_irq	= wl1271_sdio_disable_interrupts
 };
 
+static int wl1271_plat_probe(struct platform_device *pdev)
+{
+	struct wl12xx_platform_data *pdata;
+	struct platform_driver *pdriver;
+	struct wl12xx_plat_instance *pinstance;
+

What about checking for pdev here before extracting pdata?

Quoted 145 lines
drivers/net/wireless/wl12xx/wl1271_sdio.c +68 -0
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		wl1271_error("no platform data");
+		return -ENODEV;
+	}
+
+	pdriver = container_of(pdev->dev.driver, struct platform_driver,
+								driver);
+	pinstance = container_of(pdriver, struct wl12xx_plat_instance,
 pdriver);
+
+	pinstance->pdata = pdata;
+
+	complete(&pinstance->data_ready);
+
+	return 0;
+}
+
+static struct wl12xx_platform_data *wl1271_get_data(struct wl1271 *wl,
 int id)
+{
+	int ret;
+	struct wl12xx_plat_instance *pinstance;
+
+	#define WL1271_PLAT_NAME "wl1271_plat.%d"
+
+	pinstance = kzalloc(sizeof(*pinstance), GFP_KERNEL);
+	if (!pinstance)
+		return ERR_PTR(-ENOMEM);
+
+	init_completion(&pinstance->data_ready);
+
+	pinstance->pdriver.probe = wl1271_plat_probe;
+
+	ret = snprintf(pinstance->name, sizeof(pinstance->name),
+						WL1271_PLAT_NAME, id);
+	if (ret >= WL12XX_PLAT_NAME_LEN) {
+		wl1271_error("truncated plat drv name\n");
+		goto out_free;
+	}
+
+	pinstance->pdriver.driver.name = pinstance->name;
+	pinstance->pdriver.driver.owner = THIS_MODULE;
+
+	ret = platform_driver_register(&pinstance->pdriver);
+	if (ret < 0) {
+		wl1271_error("failed to register plat driver: %d", ret);
+		goto out_free;
+	}
+
+	ret = wait_for_completion_interruptible_timeout(&pinstance-
 >data_ready,
+						msecs_to_jiffies(15000));
+	if (ret <= 0) {
+		wl1271_error("can't get platform device (%d)", ret);
+		ret = (ret == 0 ? -EAGAIN : ret);
+		goto unreg;
+	}
+
+	wl->pinstance = pinstance;
+
+	return pinstance->pdata;
+
+unreg:
+	platform_driver_unregister(&pinstance->pdriver);
+out_free:
+	kfree(pinstance);
+	return ERR_PTR(ret);
+}
+
 static int __devinit wl1271_probe(struct sdio_func *func,
 				  const struct sdio_device_id *id)
 {
 	struct ieee80211_hw *hw;
+	struct wl12xx_platform_data *wlan_data;
drivers/net/wireless/wl12xx/wl1271_sdio.c +9 -2
 	struct wl1271 *wl;
 	int ret;
@@ -205,17 +283,24 @@ static int __devinit wl1271_probe(struct sdio_func
 *func,
 	/* Grab access to FN0 for ELP reg. */
 	func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
 
+	wlan_data = wl1271_get_data(wl, func->card->host->index);
+	if (IS_ERR(wlan_data)) {
+		ret = PTR_ERR(wlan_data);
+		wl1271_error("missing wlan data (needed for irq/ref_clk)!");
+		goto out_free;
+	}
+
 	wl->irq = gpio_to_irq(RX71_WL1271_IRQ_GPIO);
 	if (wl->irq < 0) {
 		ret = wl->irq;
 		wl1271_error("could not get irq!");
-		goto out_free;
+		goto put_data;
 	}
 
 	ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
 	if (ret < 0) {
 		wl1271_error("request_irq() failed: %d", ret);
-		goto out_free;
+		goto put_data;
 	}
 
drivers/net/wireless/wl12xx/wl1271_sdio.c +9 -6
 	set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
@@ -236,13 +321,13 @@ static int __devinit wl1271_probe(struct sdio_func
 *func,
 
 	return 0;
 
- out_irq:
+out_irq:
 	free_irq(wl->irq, wl);
-
-
- out_free:
+put_data:
+	platform_driver_unregister(&wl->pinstance->pdriver);
+	kfree(wl->pinstance);
+out_free:
 	wl1271_free_hw(wl);
-
 	return ret;
 }
@@ -253,6 +338,10 @@ static void __devexit wl1271_remove(struct sdio_func
 *func)
 	free_irq(wl->irq, wl);
 
 	wl1271_unregister_hw(wl);
+
+	platform_driver_unregister(&wl->pinstance->pdriver);
+	kfree(wl->pinstance);
+
 	wl1271_free_hw(wl);
 }
 
--

1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#8 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

hi,

Quoted 11 lines · Tarun Kanti

drivers/net/wireless/wl12xx/wl1271_sdio.c static struct wl1271_if_operations sdio_ops = { · line 194

Quoted 10 lines
drivers/net/wireless/wl12xx/wl1271_sdio.c +6 -0
@@ -182,10 +186,84 @@ static struct wl1271_if_operations sdio_ops = {
 	.disable_irq	= wl1271_sdio_disable_interrupts
 };
 
+static int wl1271_plat_probe(struct platform_device *pdev)
+{
+	struct wl12xx_platform_data *pdata;
+	struct platform_driver *pdriver;
+	struct wl12xx_plat_instance *pinstance;
+

What about checking for pdev here before extracting pdata?

why ? if probe is called pdev is guaranteed to be valid, no ?

Quoted 8 lines

drivers/net/wireless/wl12xx/wl1271_sdio.c static struct wl1271_if_operations sdio_ops = { · line 202

Quoted 8 lines
drivers/net/wireless/wl12xx/wl1271_sdio.c +8 -0
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		wl1271_error("no platform data");
+		return -ENODEV;
+	}
+
+	pdriver = container_of(pdev->dev.driver, struct platform_driver,
+								driver);

but you shouldn't fiddle with the driver structure here. What are you actually trying to achieve here ? What's pinstance supposed to do ? are you trying to handle cases where you might have several wl12xx chips on the same board ? If that's the case you should have several platform devices, one for each chip. They'll only have different ids.

Signature · 3 lines
balbi

DefectiveByDesign.org
#9 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

Quoted 29 lines

-----Original Message-----
From: Felipe Balbi [mailto:felipe.balbi at nokia.com]
Sent: Thursday, August 12, 2010 12:18 AM
To: DebBarma, Tarun Kanti
Cc: Ohad Ben-Cohen; linux-wireless at vger.kernel.org; linux-
mmc at vger.kernel.org; linux-omap at vger.kernel.org; Ido Yariv; Mark Brown; linux-arm-kernel at lists.infradead.org; Chikkature Rajashekar, Madhusudhan; Coelho Luciano (Nokia-MS/Helsinki); akpm at linux-foundation.org; San Mehat; Quadros Roger (Nokia-MS/Helsinki); Tony Lindgren; Nicolas Pitre; Pandita, Vikram; Kalle Valo
Subject: Re: [PATCH v4 3/8] wireless: wl1271: add platform driver to get board data

hi,

Quoted 11 lines · Tarun Kanti

drivers/net/wireless/wl12xx/wl1271_sdio.c static struct wl1271_if_operations sdio_ops = { · line 194

Quoted 10 lines
drivers/net/wireless/wl12xx/wl1271_sdio.c +6 -0
@@ -182,10 +186,84 @@ static struct wl1271_if_operations sdio_ops = {
 	.disable_irq	= wl1271_sdio_disable_interrupts
 };
 
+static int wl1271_plat_probe(struct platform_device *pdev)
+{
+	struct wl12xx_platform_data *pdata;
+	struct platform_driver *pdriver;
+	struct wl12xx_plat_instance *pinstance;
+

What about checking for pdev here before extracting pdata?

Quoted 2 lines

why ? if probe is called pdev is guaranteed to be valid, no ?

True; however if we go by that argument than we can also assume pdata is valid, so that we would not need the below check. Still, I would go ahead and find out if there is any scenario where pdev can go wrong during device registration. Thanks.

Quoted 19 lines
Quoted 8 lines

drivers/net/wireless/wl12xx/wl1271_sdio.c static struct wl1271_if_operations sdio_ops = { · line 202

Quoted 8 lines
drivers/net/wireless/wl12xx/wl1271_sdio.c +8 -0
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		wl1271_error("no platform data");
+		return -ENODEV;
+	}
+
+	pdriver = container_of(pdev->dev.driver, struct platform_driver,
+								driver);

but you shouldn't fiddle with the driver structure here. What are you actually trying to achieve here ? What's pinstance supposed to do ? are you trying to handle cases where you might have several wl12xx chips on the same board ? If that's the case you should have several platform devices, one for each chip. They'll only have different ids.

--
balbi

DefectiveByDesign.org

#10 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

Hi,

Quoted 2 lines · Tarun Kanti

True; however if we go by that argument than we can also assume pdata is valid, so that we would not need the below check.

of course not. You can have devices that just play well with default values or devices where you don't need the flexibility of platform data. That's why we check.

platform_device pointers on the other hand, are guaranteed to be always true, if it isn't then you should oops, you deserve to oops because something is really really wrong.

Quoted 2 lines

Still, I would go ahead and find out if there is any scenario where pdev can go wrong during device registration. Thanks.

if that scenario ever happens, it's either a bug on your implementation or driver-core. In both cases you deserve to oops so we catch such problems at early stages.

Signature · 3 lines
balbi

DefectiveByDesign.org
#11 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

Quoted 21 lines

-----Original Message-----
From: Felipe Balbi [mailto:felipe.balbi at nokia.com]
Sent: Thursday, August 12, 2010 12:27 AM
To: DebBarma, Tarun Kanti
Cc: Balbi Felipe (Nokia-MS/Helsinki); Ohad Ben-Cohen; linux- wireless at vger.kernel.org; linux-mmc at vger.kernel.org; linux- omap at vger.kernel.org; Ido Yariv; Mark Brown; linux-arm-
kernel at lists.infradead.org; Chikkature Rajashekar, Madhusudhan; Coelho Luciano (Nokia-MS/Helsinki); akpm at linux-foundation.org; San Mehat; Quadros Roger (Nokia-MS/Helsinki); Tony Lindgren; Nicolas Pitre; Pandita, Vikram; Kalle Valo
Subject: Re: [PATCH v4 3/8] wireless: wl1271: add platform driver to get board data

Hi,

Quoted 2 lines · Tarun Kanti

True; however if we go by that argument than we can also assume pdata is valid, so that we would not need the below check.

Quoted 8 lines

of course not. You can have devices that just play well with default values or devices where you don't need the flexibility of platform data. That's why we check.

platform_device pointers on the other hand, are guaranteed to be always true, if it isn't then you should oops, you deserve to oops because something is really really wrong.

Sounds perfect!
What that means is _probe() function makes sense only for cases where we have valid platform data because we are returning right at the top if pdata is not valid. If this is the case I was curious to know why not framework make another check for valid pdata before calling _probe() instead of coming all the way to _probe() and then returning!

Quoted 11 lines
Quoted 2 lines

Still, I would go ahead and find out if there is any scenario where pdev can go wrong during device registration. Thanks.

if that scenario ever happens, it's either a bug on your implementation or driver-core. In both cases you deserve to oops so we catch such problems at early stages.

--
balbi

DefectiveByDesign.org

#12 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

Quoted 29 lines · Tarun Kanti
Quoted 21 lines

-----Original Message-----
From: Felipe Balbi [mailto:felipe.balbi at nokia.com]
Sent: Thursday, August 12, 2010 12:27 AM
To: DebBarma, Tarun Kanti
Cc: Balbi Felipe (Nokia-MS/Helsinki); Ohad Ben-Cohen; linux- wireless at vger.kernel.org; linux-mmc at vger.kernel.org; linux- omap at vger.kernel.org; Ido Yariv; Mark Brown; linux-arm-
kernel at lists.infradead.org; Chikkature Rajashekar, Madhusudhan; Coelho Luciano (Nokia-MS/Helsinki); akpm at linux-foundation.org; San Mehat; Quadros Roger (Nokia-MS/Helsinki); Tony Lindgren; Nicolas Pitre; Pandita, Vikram; Kalle Valo
Subject: Re: [PATCH v4 3/8] wireless: wl1271: add platform driver to get board data

Hi,

Quoted 2 lines · Tarun Kanti

True; however if we go by that argument than we can also assume pdata is valid, so that we would not need the below check.

Quoted 8 lines

of course not. You can have devices that just play well with default values or devices where you don't need the flexibility of platform data. That's why we check.

platform_device pointers on the other hand, are guaranteed to be always true, if it isn't then you should oops, you deserve to oops because something is really really wrong.

Quoted 6 lines

Sounds perfect!
What that means is _probe() function makes sense only for cases where we have valid platform data because we are returning right at the top if pdata is not valid. If this is the case I was curious to know why not framework make another check for valid pdata before calling _probe() instead of coming all the way to _probe() and then returning!

Platform devices are not for passing platform data around - they're for declaring platform hardware devices that we want drivers to handle - and it depends on the driver whether having platform data is appropriate or not.

This proposal is, IMHO, abusing the platform device/driver support to achieve its own goals. I've outlined a far simpler and easiler solution which avoids this kind of abuse, and given suggestions on how to extend it to support multiple instances.

#13 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

Quoted 42 lines · Russell King - ARM Linux
Quoted 29 lines · Tarun Kanti
Quoted 21 lines

-----Original Message-----
From: Felipe Balbi [mailto:felipe.balbi at nokia.com]
Sent: Thursday, August 12, 2010 12:27 AM
To: DebBarma, Tarun Kanti
Cc: Balbi Felipe (Nokia-MS/Helsinki); Ohad Ben-Cohen; linux- wireless at vger.kernel.org; linux-mmc at vger.kernel.org; linux- omap at vger.kernel.org; Ido Yariv; Mark Brown; linux-arm-
kernel at lists.infradead.org; Chikkature Rajashekar, Madhusudhan; Coelho Luciano (Nokia-MS/Helsinki); akpm at linux-foundation.org; San Mehat; Quadros Roger (Nokia-MS/Helsinki); Tony Lindgren; Nicolas Pitre; Pandita, Vikram; Kalle Valo
Subject: Re: [PATCH v4 3/8] wireless: wl1271: add platform driver to get board data

Hi,

Quoted 2 lines · Tarun Kanti

True; however if we go by that argument than we can also assume pdata is valid, so that we would not need the below check.

Quoted 8 lines

of course not. You can have devices that just play well with default values or devices where you don't need the flexibility of platform data. That's why we check.

platform_device pointers on the other hand, are guaranteed to be always true, if it isn't then you should oops, you deserve to oops because something is really really wrong.

Quoted 6 lines

Sounds perfect!
What that means is _probe() function makes sense only for cases where we have valid platform data because we are returning right at the top if pdata is not valid. If this is the case I was curious to know why not framework make another check for valid pdata before calling _probe() instead of coming all the way to _probe() and then returning!

Platform devices are not for passing platform data around - they're for declaring platform hardware devices that we want drivers to handle - and it depends on the driver whether having platform data is appropriate or not.

Quoted 4 lines

This proposal is, IMHO, abusing the platform device/driver support to achieve its own goals. ?I've outlined a far simpler and easiler solution which avoids this kind of abuse, and given suggestions on how to extend it to support multiple instances.

Thanks, Russell.

I'll give your suggestion a spin when I get back (I'm going to be away for some time now with no devices with me).

#14 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

In reply to Russell King - ARM Linux
Quoted 4 lines · Russell King - ARM Linux

I've outlined a far simpler and easiler solution
which avoids this kind of abuse, and given suggestions on how to extend it to support multiple instances.

Do you mean:
http://www.spinics.net/lists/arm-kernel/msg95338.html
?

I was under the impression you eventually discarded that approach in that post.

Please tell me if you still support it,

Thanks,
Ohad.

#15 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

Quoted 7 lines · Ohad Ben-Cohen
Quoted 4 lines · Russell King - ARM Linux

I've outlined a far simpler and easiler solution
which avoids this kind of abuse, and given suggestions on how to extend it to support multiple instances.

Quoted 6 lines

Do you mean:
http://www.spinics.net/lists/arm-kernel/msg95338.html
?

I was under the impression you eventually discarded that approach in that post.

Indeed.

I'm talking about my first suggestion:

http://lists.arm.linux.org.uk/lurker/message/20100804.114148.bf961e83.en.html

which was later expanded by Vitaly:

http://lists.arm.linux.org.uk/lurker/message/20100804.140119.f476c29c.en.html

I don't think anyone had any negative comments against that proposal.

#16 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

Quoted 19 lines · Russell King - ARM Linux
Quoted 7 lines · Ohad Ben-Cohen
Quoted 4 lines · Russell King - ARM Linux

I've outlined a far simpler and easiler solution
which avoids this kind of abuse, and given suggestions on how to extend it to support multiple instances.

Quoted 6 lines

Do you mean:
http://www.spinics.net/lists/arm-kernel/msg95338.html
?

I was under the impression you eventually discarded that approach in that post.

Indeed.

I'm talking about my first suggestion:

Quoted 7 lines

http://lists.arm.linux.org.uk/lurker/message/20100804.114148.bf961e83.en.html

which was later expanded by Vitaly:

http://lists.arm.linux.org.uk/lurker/message/20100804.140119.f476c29c.en.html

I don't think anyone had any negative comments against that proposal.

Thanks, I see what you mean now.

I'll give this a spin when I'm back (I'm away until e/o August)

Quoted 1 line
#17 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

In reply to Russell King - ARM Linux
Quoted 62 lines

-----Original Message-----
From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
Sent: Thursday, August 12, 2010 2:55 AM
To: DebBarma, Tarun Kanti
Cc: felipe.balbi at nokia.com; Ohad Ben-Cohen; Kalle Valo; Pandita, Vikram; akpm at linux-foundation.org; Quadros Roger (Nokia-MS/Helsinki); Tony Lindgren; linux-wireless at vger.kernel.org; Mark Brown; linux- mmc at vger.kernel.org; Nicolas Pitre; San Mehat; Chikkature Rajashekar, Madhusudhan; Coelho Luciano (Nokia-MS/Helsinki); linux-
omap at vger.kernel.org; Ido Yariv; linux-arm-kernel at lists.infradead.org
Subject: Re: [PATCH v4 3/8] wireless: wl1271: add platform driver to get board data

Quoted 10 lines · Tarun Kanti
Quoted 10 lines

-----Original Message-----
From: Felipe Balbi [mailto:felipe.balbi at nokia.com]
Sent: Thursday, August 12, 2010 12:27 AM
To: DebBarma, Tarun Kanti
Cc: Balbi Felipe (Nokia-MS/Helsinki); Ohad Ben-Cohen; linux- wireless at vger.kernel.org; linux-mmc at vger.kernel.org; linux- omap at vger.kernel.org; Ido Yariv; Mark Brown; linux-arm- kernel at lists.infradead.org; Chikkature Rajashekar, Madhusudhan; Coelho Luciano (Nokia-MS/Helsinki); akpm at linux-foundation.org; San Mehat;

Quadros

Quoted 1 line
Quoted 1 line

Roger (Nokia-MS/Helsinki); Tony Lindgren; Nicolas Pitre; Pandita,

Vikram;

Quoted 2 lines
Quoted 2 lines

Kalle Valo
Subject: Re: [PATCH v4 3/8] wireless: wl1271: add platform driver to

get

Quoted 5 lines
Quoted 5 lines

board data

Hi,

On Wed, Aug 11, 2010 at 08:52:54PM +0200, ext DebBarma, Tarun Kanti

Quoted 5 lines · wrote:
Quoted 5 lines
Quoted 2 lines

True; however if we go by that argument than we can also assume pdata is valid, so that we would not need the below check.

of course not. You can have devices that just play well with default values or devices where you don't need the flexibility of platform

data.

Quoted 3 lines
Quoted 3 lines

That's why we check.

platform_device pointers on the other hand, are guaranteed to be

always

Quoted 9 lines
Quoted 3 lines

true, if it isn't then you should oops, you deserve to oops because something is really really wrong.

Sounds perfect!
What that means is _probe() function makes sense only for cases where we have valid platform data because we are returning right at the top if pdata is not valid. If this is the case I was curious to know why not framework make another check for valid pdata before calling _probe() instead of coming all the way to _probe() and then returning!

Platform devices are not for passing platform data around - they're for declaring platform hardware devices that we want drivers to handle - and it depends on the driver whether having platform data is appropriate or not.

Quoted 4 lines

This proposal is, IMHO, abusing the platform device/driver support to achieve its own goals. I've outlined a far simpler and easiler solution which avoids this kind of abuse, and given suggestions on how to extend it to support multiple instances.

I guess I have not put my question in the right perspective. As you have said, platform devices are not meant for passing data around, it appeared to me contradictory when in the probe() we are just checking the pdata and proceeding/returning based upon its value, as if platform device has no other functions. So, the question should have been what else we could do in probe() with platform device other than manipulation of pdata, other than modification of the framework in the real sense.

Anyways, I will go through the suggestions you mentioned. Thanks for the clarifications.

#18 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

In reply to DebBarma, Tarun Kanti

Hi,

Quoted 6 lines · Tarun Kanti

Sounds perfect!
What that means is _probe() function makes sense only for cases where we have valid platform data because we are returning right at the top if pdata is not valid. If this is the case I was curious to know why not framework make another check for valid pdata before calling _probe() instead of coming all the way to _probe() and then returning!

because pdata is completely optional. pdev OTOH isn't. Without a matched platform_device, your probe() won't get called.

Signature · 3 lines
balbi

DefectiveByDesign.org
#19 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

In reply to DebBarma, Tarun Kanti
Quoted 2 lines · Tarun Kanti

True; however if we go by that argument than we can also assume pdata is valid, so that we would not need the below check.

If pdev was ever NULL in a probe function, the kernel deserves to OOPS so that you have a backtrace to fix the bugger.

Basically, a probe function is only called when the driver finds a matching device to bind to - so the device _must_ already exist and be valid. It's basically guaranteed. So checking for a NULL pdev is not only a waste of space, it's a waste of CPU time and developer time writing the check as well.

On the other hand, platform data passed in via a platform device _is_ liable to be NULL if whatever created the platform device didn't set the platform data up. So we can't guarantee that the platform data will exist. So a NULL check is appropriate here.

So, if an API in normal operation requires non-NULL data to be passed, don't bother checking for a NULL pointer. If you're passed a NULL pointer in this situation, you deserve to OOPS so you get a backtrace to fix the problem rather than silently ignoring the problem.

#20 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

In reply to Felipe Balbi

Hi Felipe,

Quoted 9 lines · Felipe Balbi
Quoted 8 lines
Quoted 8 lines

+ ? ? ? pdata = pdev->dev.platform_data;
+ ? ? ? if (!pdata) {
+ ? ? ? ? ? ? ? wl1271_error("no platform data");
+ ? ? ? ? ? ? ? return -ENODEV;
+ ? ? ? }
+
+ ? ? ? pdriver = container_of(pdev->dev.driver, struct platform_driver,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? driver);

Quoted 4 lines

but you shouldn't fiddle with the driver structure here. What are you actually trying to achieve here ? What's pinstance supposed to do ? are you trying to handle cases where you might have several wl12xx chips on the same board ?

Yes.

Think of several wl1271 devices, each of which is represented by two devices; an SDIO function, and a platform device. The SDIO function stands for a specific MMC controller the device is hardwired to, and the platform device stands for the external irq line that the device is hardwired to.

We must couple the SDIO function with the correct platform device, otherwise it will start getting the wrong interrupts. So after the SDIO function is probed, it registers a platform driver with the unique name that represents the platform device that it is coupled with. When the platform device is probed, it needs to deliver its platform data info to the specific SDIO function that it is bound with.

To avoid using some global data structure in that driver, we allocate a unique platform driver per each device, which makes it possible for the platform driver probe to find the SDIO function context by means of container_of.

Alternatively, we can also use some global structure in that file, most probably idr, which would also make it possible to reach the SDIO function contexts without going through the driver structure. The idr indexes would then be the MMC controller index, which should match the platform device id.

I'll try this out, it might actually look nicer.

Thanks,
Ohad.

Quoted 8 lines

If that's the case you should have several platform devices, one for each chip. They'll only have different ids.

--
balbi

DefectiveByDesign.org

#21 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

Hi Ohad,

Quoted 5 lines · Ohad Ben-Cohen

Think of several wl1271 devices, each of which is represented by two devices; an SDIO function, and a platform device. The SDIO function stands for a specific MMC controller the device is hardwired to, and the platform device stands for the external irq line that the device is hardwired to.

my view on this is that you're hunting the false problem here. I wonder how likely it is that two hardwired WL12xx chips are there on the same board.

It's theoretically possible that there's one hardwired device and one hot-pluggable one but the latter one can't have platform_data anyway.

So in my opinion, we either should keep things simple and consider 2 hardwired WL12XX's to be a very very unlikely case, or we'll end up discussing board_info once again.

Thanks,
Vitaly

#22 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

Hi Vitaly,

Quoted 7 lines · Vitaly Wool
Quoted 5 lines · Ohad Ben-Cohen

Think of several wl1271 devices, each of which is represented by two devices; an SDIO function, and a platform device. The SDIO function stands for a specific MMC controller the device is hardwired to, and the platform device stands for the external irq line that the device is hardwired to.

Quoted 6 lines

my view on this is that you're hunting the false problem here. I wonder how likely it is that two hardwired WL12xx chips are there on the same board.

It's theoretically possible that there's one hardwired device and one hot-pluggable one but the latter one can't have platform_data anyway.

We do have strange-looking setups with two hardwired devices (especially on new bring-ups), so it would be nice not to limit the driver to a single device. But I agree, it's far from being important.

Thanks,
Ohad.

Quoted 8 lines

So in my opinion, we either should keep things simple and consider 2 hardwired WL12XX's to be a very very unlikely case, or we'll end up discussing board_info once again.

Thanks,
? Vitaly

#23 lore raw

PATCH v4 3/8 wireless: wl1271: add platform driver to get board data

In reply to Ohad Ben-Cohen

Hi,

Quoted 19 lines · ext Ohad Ben-Cohen

Think of several wl1271 devices, each of which is represented by two devices; an SDIO function, and a platform device. The SDIO function stands for a specific MMC controller the device is hardwired to, and the platform device stands for the external irq line that the device is hardwired to.

We must couple the SDIO function with the correct platform device, otherwise it will start getting the wrong interrupts. So after the SDIO function is probed, it registers a platform driver with the unique name that represents the platform device that it is coupled with. When the platform device is probed, it needs to deliver its platform data info to the specific SDIO function that it is bound with.

To avoid using some global data structure in that driver, we allocate a unique platform driver per each device, which makes it possible for the platform driver probe to find the SDIO function context by means of container_of.

Quoted 7 lines

Alternatively, we can also use some global structure in that file, most probably idr, which would also make it possible to reach the SDIO function contexts without going through the driver structure. The idr indexes would then be the MMC controller index, which should match the platform device id.

I'll try this out, it might actually look nicer.

you need no globals and you don't need to fiddle with driver structures either.

Just make an sdio driver that platform_device_alloc() and pass in a platform_data, builds struct resources etc for each device found on the sdio bus. Similarly for the SPI-connected wifi chip.

You should never fiddle with internal structures. If you want to look at an example implementation, take a look at drivers/mfd/twl-core.c, there we use an i2c driver to instantiate several platform_devices. Nobody fiddles with driver structures and all the drivers are logically separated into their own source files.

Signature · 3 lines
balbi

DefectiveByDesign.org
#24 lore raw

PATCH v4 4/8 wireless: wl1271: take irq info from private board data

In reply to Ohad Ben-Cohen

Remove the hard coded irq information, and instead take the irq information from the board's platform data.

---
 drivers/net/wireless/wl12xx/wl1271_sdio.c |   18 +++++++++---------
 1 files changed, 9 insertions(+), 9 deletions(-)
drivers/net/wireless/wl12xx/wl1271_sdio.c +9 -9
index 68b512b..228f5af 100644
@@ -38,9 +38,6 @@
 #include "wl12xx_80211.h"
 #include "wl1271_io.h"
 
-
-#define RX71_WL1271_IRQ_GPIO		42
-
 #ifndef SDIO_VENDOR_ID_TI
 #define SDIO_VENDOR_ID_TI		0x0097
 #endif
@@ -191,6 +188,7 @@ static int wl1271_plat_probe(struct platform_device *pdev)
 	struct wl12xx_platform_data *pdata;
 	struct platform_driver *pdriver;
 	struct wl12xx_plat_instance *pinstance;
+	int irq;
 
 	pdata = pdev->dev.platform_data;
 	if (!pdata) {
@@ -198,6 +196,13 @@ static int wl1271_plat_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		wl1271_error("no platform irq data");
+		return -ENODEV;
+	}
+	pdata->irq = irq;
+
 	pdriver = container_of(pdev->dev.driver, struct platform_driver,
 								driver);
 	pinstance = container_of(pdriver, struct wl12xx_plat_instance, pdriver);
@@ -290,12 +295,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,
 		goto out_free;
 	}
 
-	wl->irq = gpio_to_irq(RX71_WL1271_IRQ_GPIO);
-	if (wl->irq < 0) {
-		ret = wl->irq;
-		wl1271_error("could not get irq!");
-		goto put_data;
-	}
+	wl->irq = wlan_data->irq;
 
 	ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
 	if (ret < 0) {
Signature · 1 line
1.7.0.4
#25 lore raw

PATCH v4 5/8 wireless: wl1271: make ref_clock configurable by board

In reply to Ohad Ben-Cohen

The wl1271 device is using a reference clock that may change between board to board.

Make the ref_clock parameter configurable by the board files that set up the device, instead of having a hard coded value in the driver source itself.

---
 drivers/net/wireless/wl12xx/wl1271.h      |    1 +
 drivers/net/wireless/wl12xx/wl1271_boot.c |    9 +++++----
 drivers/net/wireless/wl12xx/wl1271_boot.h |    1 -
 drivers/net/wireless/wl12xx/wl1271_sdio.c |    1 +
 drivers/net/wireless/wl12xx/wl1271_spi.c  |    2 ++
 include/linux/wl12xx.h                    |    1 +
 6 files changed, 10 insertions(+), 5 deletions(-)
drivers/net/wireless/wl12xx/wl1271.h +1 -0
index 013eabb..f0988a4 100644
@@ -342,6 +342,7 @@ struct wl1271 {
 
 	void (*set_power)(bool enable);
 	int irq;
+	int ref_clock;
 
 	spinlock_t wl_lock;
 
drivers/net/wireless/wl12xx/wl1271_boot.c +5 -4
index f36430b..95c636a 100644
@@ -457,17 +457,18 @@ int wl1271_boot(struct wl1271 *wl)
 {
 	int ret = 0;
 	u32 tmp, clk, pause;
+	int ref_clock = wl->ref_clock;
 
 	wl1271_boot_hw_version(wl);
 
-	if (REF_CLOCK == 0 || REF_CLOCK == 2 || REF_CLOCK == 4)
+	if (ref_clock == 0 || ref_clock == 2 || ref_clock == 4)
 		/* ref clk: 19.2/38.4/38.4-XTAL */
 		clk = 0x3;
-	else if (REF_CLOCK == 1 || REF_CLOCK == 3)
+	else if (ref_clock == 1 || ref_clock == 3)
 		/* ref clk: 26/52 */
 		clk = 0x5;
 
-	if (REF_CLOCK != 0) {
+	if (ref_clock != 0) {
 		u16 val;
 		/* Set clock type (open drain) */
 		val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE);
@@ -516,7 +517,7 @@ int wl1271_boot(struct wl1271 *wl)
 	wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
 
 	/* 2 */
-	clk |= (REF_CLOCK << 1) << 4;
+	clk |= (ref_clock << 1) << 4;
 	wl1271_write32(wl, DRPW_SCRATCH_START, clk);
 
 	wl1271_set_partition(wl, &part_table[PART_WORK]);
drivers/net/wireless/wl12xx/wl1271_boot.h +0 -1
index f829699..f73b0b1 100644
@@ -46,7 +46,6 @@ struct wl1271_static_data {
 /* delay between retries */
 #define INIT_LOOP_DELAY 50
 
-#define REF_CLOCK            2
 #define WU_COUNTER_PAUSE_VAL 0x3FF
 #define WELP_ARM_COMMAND_VAL 0x4
 
drivers/net/wireless/wl12xx/wl1271_sdio.c +1 -0
index 228f5af..2f558a6 100644
@@ -296,6 +296,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,
 	}
 
 	wl->irq = wlan_data->irq;
+	wl->ref_clock = wlan_data->board_ref_clock;
 
 	ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
 	if (ret < 0) {
drivers/net/wireless/wl12xx/wl1271_spi.c +2 -0
index de56d8d..ced0a9e 100644
@@ -372,6 +372,8 @@ static int __devinit wl1271_probe(struct spi_device *spi)
 		goto out_free;
 	}
 
+	wl->ref_clock = pdata->board_ref_clock;
+
 	wl->irq = spi->irq;
 	if (wl->irq < 0) {
 		wl1271_error("irq missing in platform data");
include/linux/wl12xx.h +1 -0
index 137ac89..ef6eed9 100644
@@ -29,6 +29,7 @@ struct wl12xx_platform_data {
 	/* SDIO only: IRQ number if WLAN_IRQ line is used, 0 for SDIO IRQs */
 	int irq;
 	bool use_eeprom;
+	int board_ref_clock;
 };
 
 #endif
Signature · 1 line
1.7.0.4
#26 lore raw

PATCH v4 6/8 omap: hsmmc: remove unused variable

In reply to Ohad Ben-Cohen

Make this go away:

drivers/mmc/host/omap_hsmmc.c: In function 'omap_hsmmc_suspend':
drivers/mmc/host/omap_hsmmc.c:2328: warning: unused variable 'state'

---
 drivers/mmc/host/omap_hsmmc.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)
drivers/mmc/host/omap_hsmmc.c +0 -1
index b032828..d50e917 100644
@@ -2272,7 +2272,6 @@ static int omap_hsmmc_suspend(struct device *dev)
 	int ret = 0;
 	struct platform_device *pdev = to_platform_device(dev);
 	struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
-	pm_message_t state = PMSG_SUSPEND; /* unused by MMC core */
 
 	if (host && host->suspended)
 		return 0;
Signature · 1 line
1.7.0.4
#27 lore raw

PATCH v4 7/8 omap: zoom: add fixed regulator device for wlan

In reply to Ohad Ben-Cohen

Add a fixed regulator vmmc device to enable power control of the wl1271 wlan device.

---
 arch/arm/mach-omap2/board-zoom-peripherals.c |   35 ++++++++++++++++++++++++++
 1 files changed, 35 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/board-zoom-peripherals.c +35 -0
index 6b39849..de88635 100644
@@ -16,6 +16,7 @@
 #include <linux/gpio.h>
 #include <linux/i2c/twl.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -27,6 +28,8 @@
 #include "mux.h"
 #include "hsmmc.h"
 
+#define OMAP_ZOOM_WLAN_PMENA_GPIO	(101)
+
 /* Zoom2 has Qwerty keyboard*/
 static int board_keymap[] = {
 	KEY(0, 0, KEY_E),
@@ -106,6 +109,11 @@ static struct regulator_consumer_supply zoom_vmmc2_supply = {
 	.supply		= "vmmc",
 };
 
+static struct regulator_consumer_supply zoom_vmmc3_supply = {
+	.supply		= "vmmc",
+	.dev_name	= "mmci-omap-hs.2",
+};
+
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
 static struct regulator_init_data zoom_vmmc1 = {
 	.constraints = {
@@ -151,6 +159,32 @@ static struct regulator_init_data zoom_vsim = {
 	.consumer_supplies      = &zoom_vsim_supply,
 };
 
+static struct regulator_init_data zoom_vmmc3 = {
+	.constraints = {
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &zoom_vmmc3_supply,
+};
+
+static struct fixed_voltage_config zoom_vwlan = {
+	.supply_name = "vwl1271",
+	.microvolts = 1800000, /* 1.8V */
+	.gpio = OMAP_ZOOM_WLAN_PMENA_GPIO,
+	.startup_delay = 70000, /* 70msec */
+	.enable_high = 1,
+	.enabled_at_boot = 0,
+	.init_data = &zoom_vmmc3,
+};
+
+static struct platform_device omap_vwlan_device = {
+	.name		= "reg-fixed-voltage",
+	.id		= 1,
+	.dev = {
+		.platform_data = &zoom_vwlan,
+	},
+};
+
 static struct omap2_hsmmc_info mmc[] __initdata = {
 	{
 		.name		= "external",
@@ -280,6 +314,7 @@ static void enable_board_wakeup_source(void)
 void __init zoom_peripherals_init(void)
 {
 	omap_i2c_init();
+	platform_device_register(&omap_vwlan_device);
 	usb_musb_init(&musb_board_data);
 	enable_board_wakeup_source();
 }
Signature · 1 line
1.7.0.4
#28 lore raw

PATCH v4 8/8 omap: zoom: add mmc3/wl1271 device support

In reply to Ohad Ben-Cohen

Add MMC3 support on ZOOM, which has the wl1271 device hardwired to.

The wl1271 is a 4-wire, 1.8V, embedded SDIO WLAN device with an external IRQ line, and power-controlled by a GPIO-based fixed regulator.

---
 arch/arm/mach-omap2/board-zoom-peripherals.c |   34 ++++++++++++++++++++++++++
 1 files changed, 34 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/board-zoom-peripherals.c +34 -0
index de88635..625ae56 100644
@@ -17,6 +17,8 @@
 #include <linux/i2c/twl.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
+#include <linux/mmc/host.h>
+#include <linux/wl12xx.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -29,6 +31,7 @@
 #include "hsmmc.h"
 
 #define OMAP_ZOOM_WLAN_PMENA_GPIO	(101)
+#define OMAP_ZOOM_WLAN_IRQ_GPIO		(162)
 
 /* Zoom2 has Qwerty keyboard*/
 static int board_keymap[] = {
@@ -185,6 +188,28 @@ static struct platform_device omap_vwlan_device = {
 	},
 };
 
+struct wl12xx_platform_data omap_zoom_wlan_data = {
+	/* ZOOM ref clock is 26 MHz */
+	.board_ref_clock = 1,
+};
+
+static struct resource omap_zoom_wl1271_resources[] = {
+	{
+		.start = OMAP_GPIO_IRQ(OMAP_ZOOM_WLAN_IRQ_GPIO),
+		.end = OMAP_GPIO_IRQ(OMAP_ZOOM_WLAN_IRQ_GPIO),
+		.flags = IORESOURCE_IRQ,
+	}
+};
+static struct platform_device omap_zoom_wl1271 = {
+	.name		= "wl1271_plat.2",
+	.id		= -1,
+	.resource	= omap_zoom_wl1271_resources,
+	.num_resources	= ARRAY_SIZE(omap_zoom_wl1271_resources),
+	.dev = {
+		.platform_data = &omap_zoom_wlan_data,
+	},
+};
+
 static struct omap2_hsmmc_info mmc[] __initdata = {
 	{
 		.name		= "external",
@@ -202,6 +227,14 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
 		.nonremovable	= true,
 		.power_saving	= true,
 	},
+	{
+		.name		= "wl1271",
+		.mmc		= 3,
+		.wires		= 4,
+		.gpio_wp	= -EINVAL,
+		.gpio_cd	= -EINVAL,
+		.nonremovable	= true,
+	},
 	{}      /* Terminator */
 };
 
@@ -313,6 +346,7 @@ static void enable_board_wakeup_source(void)
 
 void __init zoom_peripherals_init(void)
 {
+	platform_device_register(&omap_zoom_wl1271);
 	omap_i2c_init();
 	platform_device_register(&omap_vwlan_device);
 	usb_musb_init(&musb_board_data);
Signature · 1 line
1.7.0.4