Skip to contentSkip to conversation

native support for wl1271 on ZOOM

PATCH Superseded Ohad Ben-Cohen 12 participants 62 messages Jul 21, 2010 – Aug 6, 2010

Subsystems (7)

v2 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v2 cover native support for wl1271 on ZOOM

This patch series adds native support for wl1271 on ZOOM.

Changes since v1:

- introduce a fixed regulator device to control the power of wl1271
- allow to propagate private board-specific data to SDIO function drivers
- allow SDIO function driver to control the card's power via new API
- make it possible to keep the card's power down (without depending on an explicit SDIO function driver power-down request)

Thanks to these changes, we no longer need a separate platform device (carrying e.g. the external irq information of the device), and no longer need to emulate virtual card detect events.

The two "board muxing" pathces were already taken by Tony, and are resent here just to make it easier for people to use/test these pathces.

The changes to the MMC core really needs careful review; there still might be some pitfalls that haven't been covered. E.g., one thing we plan to look at next is their bahvior together with SDIO Suspend/Resume.

Special thanks to Roger Quadros and Nicolas Pitre for their extensive review and helpful suggestions.

The patches are based on 2.6.35-rc5, and were tested on ZOOM3.

Thanks,

Ohad Ben-Cohen (20):
sdio: add TI + wl1271 ids
wireless: wl1271: remove SDIO IDs from driver
mmc: support embedded data field in mmc_host
omap zoom2: wlan board muxing
omap zoom3: wlan board muxing
wireless: wl1271: make wl12xx.h common to both spi and sdio
wireless: wl1271: support return value for the set power func
wireless: wl1271: take irq info from private board data
wireless: wl1271: make ref_clock configurable by board
omap: zoom: add fixed regulator device for wlan
omap: hsmmc: support mmc3 regulator power control
omap: hsmmc: allow board-specific settings of private mmc data
omap: zoom: add mmc3/wl1271 device support
mmc: sdio: fully reconfigure oldcard on resume
mmc: sdio: verify existence of resume handler
mmc: introduce API to control the card's power
mmc: sdio: relocate sdio_set_block_size call
mmc: sdio: enable a default power off mode of the card
omap: zoom: keep the MMC3 wl1271 device powered off
wireless: wl1271: call SDIO claim/release power API

 arch/arm/mach-omap2/board-zoom-peripherals.c |   54 +++++++++++++++++++
 arch/arm/mach-omap2/board-zoom2.c            |   13 +++++
 arch/arm/mach-omap2/board-zoom3.c            |   13 +++++
 arch/arm/mach-omap2/hsmmc.c                  |   15 ++++--
 arch/arm/mach-omap2/hsmmc.h                  |    2 +
 arch/arm/plat-omap/include/plat/mmc.h        |    5 ++
 drivers/mmc/core/bus.c                       |    3 +
 drivers/mmc/core/core.c                      |   50 ++++++++++++++++++
 drivers/mmc/core/sdio.c                      |   36 +++++++++++--
 drivers/mmc/core/sdio_bus.c                  |    9 ---
 drivers/mmc/core/sdio_io.c                   |   50 ++++++++++++++++++
 drivers/mmc/host/omap_hsmmc.c                |   72 +++++++++++++++++++++++---
 drivers/net/wireless/wl12xx/wl1251_sdio.c    |    2 +-
 drivers/net/wireless/wl12xx/wl1251_spi.c     |    2 +-
 drivers/net/wireless/wl12xx/wl1271.h         |    3 +-
 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    |   31 +++++------
 drivers/net/wireless/wl12xx/wl1271_spi.c     |    8 ++-
 include/linux/mmc/card.h                     |    2 +
 include/linux/mmc/host.h                     |   15 +++++
 include/linux/mmc/sdio_func.h                |    3 +
 include/linux/mmc/sdio_ids.h                 |    3 +
 include/linux/spi/wl12xx.h                   |   34 ------------
 include/linux/wl12xx.h                       |   35 ++++++++++++
 27 files changed, 393 insertions(+), 89 deletions(-)
 delete mode 100644 include/linux/spi/wl12xx.h
 create mode 100644 include/linux/wl12xx.h
#1 lore raw

PATCH v2 1/20 sdio: add TI + wl1271 ids

Add SDIO IDs for TI and for TI's wl1271 wlan device.

---
 include/linux/mmc/sdio_ids.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
include/linux/mmc/sdio_ids.h +3 -0
index 33b2ea0..0d313c6 100644
@@ -43,4 +43,7 @@
 #define SDIO_DEVICE_ID_SIANO_NOVA_A0		0x1100
 #define SDIO_DEVICE_ID_SIANO_STELLAR 		0x5347
 
+#define SDIO_VENDOR_ID_TI			0x0097
+#define SDIO_DEVICE_ID_TI_WL1271		0x4076
+
 #endif
Signature · 1 line
1.7.0.4
#2 lore raw

PATCH v2 1/20 sdio: add TI + wl1271 ids

Hi Ohad,

Quoted 12 lines

Add SDIO IDs for TI and for TI's wl1271 wlan device.

---
 include/linux/mmc/sdio_ids.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
include/linux/mmc/sdio_ids.h +0 -0
index 33b2ea0..0d313c6 100644

include/linux/mmc/sdio_ids.h line 48

Quoted 6 lines
include/linux/mmc/sdio_ids.h +3 -0
@@ -43,4 +43,7 @@
 #define SDIO_DEVICE_ID_SIANO_NOVA_A0		0x1100
 #define SDIO_DEVICE_ID_SIANO_STELLAR 		0x5347
 
+#define SDIO_VENDOR_ID_TI			0x0097
+#define SDIO_DEVICE_ID_TI_WL1271		0x4076
+

are we still doing this non-sense for no real reason. What is so wrong with keeping the IDs inside the driver code?

Personally I don't even see a point for these ID defines at all. Just use the bare numbers in SDIO_DEVICE and put a comment above what kind of device this is.

Regards

Marcel

#3 lore raw

PATCH v2 1/20 sdio: add TI + wl1271 ids

Hi Marcel,

Quoted 15 lines · Marcel Holtmann
Quoted 15 lines

Add SDIO IDs for TI and for TI's wl1271 wlan device.

---
?include/linux/mmc/sdio_ids.h | ? ?3 +++
?1 files changed, 3 insertions(+), 0 deletions(-)

include/linux/mmc/sdio_ids.h +0 -0
index 33b2ea0..0d313c6 100644
@@ -43,4 +43,7 @@

?#define SDIO_DEVICE_ID_SIANO_NOVA_A0 ? ? ? ? 0x1100 ?#define SDIO_DEVICE_ID_SIANO_STELLAR ? ? ? ? ? ? ? ? 0x5347

Quoted 6 lines

include/linux/mmc/sdio_ids.h

Quoted 3 lines
include/linux/mmc/sdio_ids.h +3 -0
+#define SDIO_VENDOR_ID_TI ? ? ? ? ? ? ? ? ? ?0x0097
+#define SDIO_DEVICE_ID_TI_WL1271 ? ? ? ? ? ? 0x4076
+

are we still doing this non-sense for no real reason. What is so wrong with keeping the IDs inside the driver code?

Either way we can't go so wrong here (having global VENDOR_IDs can potentially prevent redefinitions of the same ID in different drivers, but that's probably not that big of an
issue too).

But if we prefer people to stop adding IDs to this global pool, let's at least make it clear. We can probably seal it with some "please don't add new IDs if you don't have to" footnote (care to send such patch ? :)

Thanks,
Ohad.

Quoted 14 lines

Personally I don't even see a point for these ID defines at all. Just use the bare numbers in SDIO_DEVICE and put a comment above what kind of device this is.

Regards

Marcel

--
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 v2 2/20 wireless: wl1271: remove SDIO IDs from driver

In reply to Ohad Ben-Cohen

Remove SDIO IDs from the driver code since now it is included in linux/mmc/sdio_ids.h.

---
 drivers/net/wireless/wl12xx/wl1271_sdio.c |    8 --------
 1 files changed, 0 insertions(+), 8 deletions(-)
drivers/net/wireless/wl12xx/wl1271_sdio.c +0 -8
index d3d6f30..9903ae9 100644
@@ -37,14 +37,6 @@
 
 #define RX71_WL1271_IRQ_GPIO		42
 
-#ifndef SDIO_VENDOR_ID_TI
-#define SDIO_VENDOR_ID_TI		0x0097
-#endif
-
-#ifndef SDIO_DEVICE_ID_TI_WL1271
-#define SDIO_DEVICE_ID_TI_WL1271	0x4076
-#endif
-
 static const struct sdio_device_id wl1271_devices[] = {
 	{ SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) },
 	{}
Signature · 1 line
1.7.0.4
#5 lore raw

PATCH v2 3/20 mmc: support embedded data field in mmc_host

In reply to Ohad Ben-Cohen

Add support to set/get mmc_host private embedded data.

This is needed to allow software to dynamically create (and remove) SDIO functions which represents embedded SDIO devices.

Typically, it will be used to set the context of a driver that is creating a new SDIO function (and would then expect to be able to get that context back upon creation of the new sdio func).

---
 include/linux/mmc/host.h |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)
include/linux/mmc/host.h +12 -0
index f65913c..80db597 100644
@@ -209,6 +209,8 @@ struct mmc_host {
 	struct led_trigger	*led;		/* activity led */
 #endif
 
+	void			*embedded_data;
+
 	struct dentry		*debugfs_root;
 
 	unsigned long		private[0] ____cacheline_aligned;
@@ -264,5 +266,15 @@ static inline void mmc_set_disable_delay(struct mmc_host *host,
 	host->disable_delay = disable_delay;
 }
 
+static inline void *mmc_get_embedded_data(struct mmc_host *host)
+{
+	return host->embedded_data;
+}
+
+static inline void mmc_set_embedded_data(struct mmc_host *host, void *data)
+{
+	host->embedded_data = data;
+}
+
 #endif
 
Signature · 1 line
1.7.0.4
#6 lore raw

PATCH v2 3/20 mmc: support embedded data field in mmc_host

Hi Ohad,

Quoted 7 lines · Ohad Ben-Cohen

Add support to set/get mmc_host private embedded
data.

This is needed to allow software to dynamically create (and remove) SDIO functions which represents embedded SDIO devices.

<snip>

Quoted 6 lines
(quoted diff) +0 -0
@@ -209,6 +209,8 @@ struct mmc_host {

? ? ? ?struct led_trigger ? ? ?*led; ? ? ? ? ? /* activity led */ ?#endif

+ ? ? ? void ? ? ? ? ? ? ? ? ? ?*embedded_data;
+

To my understanding, this data doesn't belong to mmc_host. It's not a host data at all. E. g. imagine a GPIO IRQ for some SDIO chip -- it's totally unrelated to host.

I think a cleaner way would be to introduce something similar to what we have for SPI, e. g. struct sdio_board_info. This board info will contain platform-specific stuff and vendor id/chip id for each onboard SDIO device. Then the SDIO core will pick up the appropriate data basing on vendor id/chip id.

~Vitaly

#7 lore raw

PATCH v2 3/20 mmc: support embedded data field in mmc_host

Hi Vitaly,

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

Add support to set/get mmc_host private embedded
data.

This is needed to allow software to dynamically create (and remove) SDIO functions which represents embedded SDIO devices.

<snip>

Quoted 6 lines
(quoted diff) +0 -0
@@ -209,6 +209,8 @@ struct mmc_host {

? ? ? ?struct led_trigger ? ? ?*led; ? ? ? ? ? /* activity led */ ?#endif

+ ? ? ? void ? ? ? ? ? ? ? ? ? ?*embedded_data;
+

To my understanding, this data doesn't belong to mmc_host. It's not a host data at all. E. g. imagine a GPIO IRQ for some SDIO chip -- it's totally unrelated to host.

Quoted 5 lines

I think a cleaner way would be to introduce something similar to what we have for SPI, e. g. struct sdio_board_info. This board info will contain platform-specific stuff and vendor id/chip id for each onboard SDIO device. Then the SDIO core will pick up the appropriate data basing on vendor id/chip id.

Can you please elaborate some more about your proposal (specifically where does this sdio_board_info get set and how do function drivers access it) ?

If I understand you correctly, you suggest to have a global, board-specific table of sdio_board_info structures, which would be accessible to the SDIO core (through the host driver ?). When a new SDIO device is found the core would search this table for the appropriate sdio_board_info struct and make it accessible to the SDIO function driver ?

Thanks,
Ohad.

Quoted 3 lines

~Vitaly

#8 lore raw

PATCH v2 3/20 mmc: support embedded data field in mmc_host

Hi Ohad,

Quoted 14 lines · Ohad Ben-Cohen
Quoted 9 lines

To my understanding, this data doesn't belong to mmc_host. It's not a host data at all. E. g. imagine a GPIO IRQ for some SDIO chip -- it's totally unrelated to host.

I think a cleaner way would be to introduce something similar to what we have for SPI, e. g. struct sdio_board_info. This board info will contain platform-specific stuff and vendor id/chip id for each onboard SDIO device. Then the SDIO core will pick up the appropriate data basing on vendor id/chip id.

Can you please elaborate some more about your proposal (specifically where does this sdio_board_info get set and how do function drivers access it) ?

Quoted 6 lines

If I understand you correctly, you suggest to have a global, board-specific table of sdio_board_info structures, which would be accessible to the SDIO core (through the host driver ?). When a new SDIO device is found the core would search this table for the appropriate sdio_board_info struct and make it accessible to the SDIO function driver ?

Well, let's look at how it's implemented for SPI. There is the function spi_register_board_info in the SPI core which copies the board info into the local data structure (a linked list, actually). Whenever needed, the core walks through the list to find the appropriate board_info basing on some search key.

I think this may be the way to go for SDIO as well.

~Vitaly

#9 lore raw

PATCH v2 3/20 mmc: support embedded data field in mmc_host

Hi Vitaly,

Quoted 22 lines · Vitaly Wool
Quoted 14 lines · Ohad Ben-Cohen
Quoted 9 lines

To my understanding, this data doesn't belong to mmc_host. It's not a host data at all. E. g. imagine a GPIO IRQ for some SDIO chip -- it's totally unrelated to host.

I think a cleaner way would be to introduce something similar to what we have for SPI, e. g. struct sdio_board_info. This board info will contain platform-specific stuff and vendor id/chip id for each onboard SDIO device. Then the SDIO core will pick up the appropriate data basing on vendor id/chip id.

Can you please elaborate some more about your proposal (specifically where does this sdio_board_info get set and how do function drivers access it) ?

Quoted 6 lines

If I understand you correctly, you suggest to have a global, board-specific table of sdio_board_info structures, which would be accessible to the SDIO core (through the host driver ?). When a new SDIO device is found the core would search this table for the appropriate sdio_board_info struct and make it accessible to the SDIO function driver ?

Quoted 7 lines

Well, let's look at how it's implemented for SPI. There is the function spi_register_board_info in the SPI core which copies the board info into the local data structure (a linked list, actually). Whenever needed, the core walks through the list to find the appropriate board_info basing on some search key.

I think this may be the way to go for SDIO as well.

IMHO this is a bit overkill solution for our problem.

SPI is using these spi_board_info tables to populate the SPI device trees. These tables are registered early at the board-specific init code, and are later used by SPI core to populate the devices when the SPI master controller is registered.

SDIO doesn't normally needs any kind of hard coded data: most devices are dynamically probed and populated.

On rare cases like the wl1271, we have some platform-specific data we need to deliver the SDIO function driver (i.e. the irq info in this case). Since the device is hardwired to a specific controller, it does make some sense to pass this private data from the controller's info in the board files, through the host driver, and make it accessible through the specific host instance that drives this controller.

Btw, if our problem was be broader (e.g., needs to supply private data for non-hardwired devices), then I agree that a more complex mechanism, such as the one you suggest, would be needed. But currently the problem is very simple and the solution is even simpler: just add 1 private pointer to the host.

Hope you find this reasonable,

Thanks,
Ohad.

Quoted 3 lines

~Vitaly

#10 lore raw

PATCH v2 3/20 mmc: support embedded data field in mmc_host

Hi Ohad,

Quoted 15 lines · Ohad Ben-Cohen

SPI is using these spi_board_info tables to populate the SPI device trees. These tables are registered early at the board-specific init code, and are later used by SPI core to populate the devices when the SPI master controller is registered.

SDIO doesn't normally needs any kind of hard coded data: most devices are dynamically probed and populated.

On rare cases like the wl1271, we have some platform-specific data we need to deliver the SDIO function driver (i.e. the irq info in this case). Since the device is hardwired to a specific controller, it does make some sense to pass this private data from the controller's info in the board files, through the host driver, and make it accessible through the specific host instance that drives this controller.

Quoted 7 lines

Btw, if our problem was be broader (e.g., needs to supply private data for non-hardwired devices), then I agree that a more complex mechanism, such as the one you suggest, would be needed. But currently the problem is very simple and the solution is even simpler: just add 1 private pointer to the host.

Hope you find this reasonable,

no, actually I don't. I think this is a hack that intrudes into the area it completely doesn't belong to.

In fact, one can have 2 views on this problem: either this is a fairly generic problem we need to address, or this is a very specific corner case.
Your solution will be treated as a hack in both cases.

If we consider it a generic problem, then we need to find a generic solution, which is the board_info solution, for instance. FWIW, I2C also uses this approach now.

If we consider it to be a corner case, let's just add a dummy platform_device like it's done in WL1251 implementation and keep the MMC subsystem clean.

Thanks,
Vitaly

#11 lore raw

PATCH v2 3/20 mmc: support embedded data field in mmc_host

Hi Vitaly,

Quoted 32 lines · Vitaly Wool
Quoted 15 lines · Ohad Ben-Cohen

SPI is using these spi_board_info tables to populate the SPI device trees. These tables are registered early at the board-specific init code, and are later used by SPI core to populate the devices when the SPI master controller is registered.

SDIO doesn't normally needs any kind of hard coded data: most devices are dynamically probed and populated.

On rare cases like the wl1271, we have some platform-specific data we need to deliver the SDIO function driver (i.e. the irq info in this case). Since the device is hardwired to a specific controller, it does make some sense to pass this private data from the controller's info in the board files, through the host driver, and make it accessible through the specific host instance that drives this controller.

Quoted 7 lines

Btw, if our problem was be broader (e.g., needs to supply private data for non-hardwired devices), then I agree that a more complex mechanism, such as the one you suggest, would be needed. But currently the problem is very simple and the solution is even simpler: just add 1 private pointer to the host.

Hope you find this reasonable,

no, actually I don't. I think this is a hack that intrudes into the area it completely doesn't belong to.

In fact, one can have 2 views on this problem: either this is a fairly generic problem we need to address, or this is a very specific corner case.
Your solution will be treated as a hack in both cases.

Quoted 7 lines

If we consider it a generic problem, then we need to find a generic solution, which is the board_info solution, for instance. FWIW, I2C also uses this approach now.

If we consider it to be a corner case, let's just add a dummy platform_device like it's done in WL1251 implementation and keep the MMC subsystem clean.

Let's start by defining the problem exactly:

SDIO devices that are hardwired to a specific controller and have some platform data that needs to be available to the SDIO function driver.

It doesn't get more generic than that - it's not needed with common fully-enumerable SDIO devices (at least I'm not aware of such need), hence a generic mechanism of maintaining a global pile of platform data pointers, which can be queried with the device and vendor ID, really sounds like an overkill.

But it's not specific to the wl1271 device - I prefer to support this at the MMC level, so we wouldn't have to add an extra platform device for every SDIO function driver that needs to cope with such issue (we already have two drivers - wl1271_sdio.c and wl1251_sdio.c); Adding an extra platform device for every driver is just too much dummy code (that btw adds a well-hidden race condition between the two probe calls), which can be nicely eliminated if we just introduce this new per-host private data pointer.

So we have a SDIO device hardwired to a specific controller, that is driven by a specific host controller driver instance. This patch allows this specific host instance to carry platform data for the device that is hardwired to it. The platform data would be available only to SDIO function driver instances of that specific host controller. The solution is generic enough to support all SDIO function drivers with similar needs, and it's extremely simple.

I'm honestly trying to understand your concerns, but I'm afraid that just saying "it's a hack" is not too informative. Can you please explain what do you think is technically wrong with the proposed solution ? is it not general enough for other use cases ? will it break something ?

Thanks,
Ohad.

Quoted 4 lines

Thanks,
? Vitaly

#12 lore raw

PATCH v2 3/20 mmc: support embedded data field in mmc_host

Hi Ohad,

Quoted 5 lines · Ohad Ben-Cohen

I'm honestly trying to understand your concerns, but I'm afraid that just saying "it's a hack" is not too informative. Can you please explain what do you think is technically wrong with the proposed solution ? is it not general enough for other use cases ? will it break something ?

let's summarize the solution you're proposing.

You're trying to add embedded_data which will be scattered all over the place. The patches you introduce do the following:
- add the pointer to the mmc core header;
- add the primitive to set it from the controller driver;
- add the pointer to the board-specific header;
- add the structure to the board-specific C file and propagate its pointer to the controller driver;
- add setting the pointer in the core structure into the controller driver.

So if I'd like to set the *same* structure for the *same* WL1271 driver, provided that I'm working with the other platform, I'll need to do the following:
- add the pointer to the board-specific header;
- add the structure to the board-specific C file and propagate its pointer to the controller driver;
- add setting the pointer in the core structure into the controller driver.

This is far from being intuitive. This means we need to hack, generally speaking, all the MMC controller drivers to get it working on all platforms. This is error prone.

And I'm not even speaking about the fact that MMC controller driver should not deal with such things at all.

Thanks,
Vitaly

#13 lore raw

PATCH v2 3/20 mmc: support embedded data field in mmc_host

Hi Vitaly,

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

I'm honestly trying to understand your concerns, but I'm afraid that just saying "it's a hack" is not too informative. Can you please explain what do you think is technically wrong with the proposed solution ? is it not general enough for other use cases ? will it break something ?

So if I'd like to set the *same* structure for the *same* WL1271 driver, provided that I'm working with the other platform, I'll need to do the following:
- add the pointer to the board-specific header;
- add the structure to the board-specific C file and propagate its pointer to the controller driver;
- add setting the pointer in the core structure into the controller driver.

Quoted 3 lines

This is far from being intuitive. This means we need to hack, generally speaking, all the MMC controller drivers to get it working on all platforms. This is error prone.

You make it sound really complex.

Let's see what it means to add it to a totally different platform.

As an example, let's take Google's ADP1 which is based on a different host controller (msm-sdcc), and add the required support (untested of course, just a quick sketch, patch is based on android's msm git):

arch/arm/mach-msm/board-trout-mmc.c +7 -1
index 13755f5..df32b2f 100644
@@ -10,6 +10,7 @@
 #include <linux/mmc/sdio_ids.h>
 #include <linux/err.h>
 #include <linux/debugfs.h>
+#include <linux/wl12xx.h>
 
 #include <asm/gpio.h>
 #include <asm/io.h>
@@ -297,11 +298,16 @@ int trout_wifi_reset(int on)
 EXPORT_SYMBOL(trout_wifi_reset);
 #endif
 
+struct wl12xx_platform_data trout_wlan_data = {
+       .irq = 62, /* put here your irq number */
+       .board_ref_clock = 1, /* put here your ref clock */
+};
+
 static struct mmc_platform_data trout_wifi_data = {
        .ocr_mask               = MMC_VDD_28_29,
        .status                 = trout_wifi_status,
        .register_status_notify = trout_wifi_status_register,
-       .embedded_sdio          = &trout_wifi_emb_data,
+       .embedded_sdio          = &trout_wlan_data,
 };
 
 int __init trout_init_mmc(unsigned int sys_rev)
drivers/mmc/host/msm_sdcc.c +1 -0
index 1697d42..c40f0d1 100755
@@ -1261,6 +1261,7 @@ msmsdcc_probe(struct platform_device *pdev)
        mmc->f_min = msmsdcc_fmin;
        mmc->f_max = msmsdcc_fmax;
        mmc->ocr_avail = plat->ocr_mask;
+        mmc_set_embedded_data(mmc, plat->embedded_sdio);
 
        if (msmsdcc_4bit)
                mmc->caps |= MMC_CAP_4_BIT_DATA;

Is it really that complex ?

Thanks,
Ohad.

#14 lore raw

PATCH v2 3/20 mmc: support embedded data field in mmc_host

Quoted 22 lines · Ohad Ben-Cohen

Hi Vitaly,

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

I'm honestly trying to understand your concerns, but I'm afraid that just saying "it's a hack" is not too informative. Can you please explain what do you think is technically wrong with the proposed solution ? is it not general enough for other use cases ? will it break something ?

So if I'd like to set the *same* structure for the *same* WL1271 driver, provided that I'm working with the other platform, I'll need to do the following:
- add the pointer to the board-specific header;
- add the structure to the board-specific C file and propagate its pointer to the controller driver;
- add setting the pointer in the core structure into the controller driver.

Quoted 3 lines

This is far from being intuitive. This means we need to hack, generally speaking, all the MMC controller drivers to get it working on all platforms. This is error prone.

Quoted 7 lines

You make it sound really complex.

Let's see what it means to add it to a totally different platform.

As an example, let's take Google's ADP1 which is based on a different host controller (msm-sdcc), and add the required support (untested of course, just a quick sketch, patch is based on android's msm git):

What if some other driver gets attached and tries to use this platform data? This whole idea sounds extremely silly, cumbersome, error prone, and is inviting misuse by normal MMC sockets.

Why not arrange for a small piece of code to be built into the kernel when this driver is selected as a module or built-in, which handles the passing of platform data to the driver?

Something like:

wl12xx_platform_data.c:
#include <linux/module.h>
#include <whatever/required/for/wl12xx.h>

static struct wl12xx_platform_data *platform_data;

int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data)

{
	if (platform_data)
		return -EBUSY;
	platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
	if (!platform_data)
		return -ENOMEM;
	return 0;
}

int wl12xx_get_platform_data(struct wl12xx_platform_data *data)

{
	if (platform_data) {
		memcpy(data, platform_data, sizeof(*data));
		return 0;
	}
	return -ENODEV;
}

EXPORT_SYMBOL(wl12xx_get_platform_data);

And in the Kconfig, something like:

config WL12XX_PLATFORM_DATA

	bool
	depends on WL12XX != n
	default y

This means there'll be no confusion over who owns the 'embedded data', typechecking is preserved, and no possibility for the wrong driver to pick up the data.

#15 lore raw

PATCH v2 3/20 mmc: support embedded data field in mmc_host

Quoted 29 lines · Russell King - ARM Linux
Quoted 20 lines · Ohad Ben-Cohen
Quoted 15 lines · Vitaly Wool
Quoted 5 lines · Ohad Ben-Cohen

I'm honestly trying to understand your concerns, but I'm afraid that just saying "it's a hack" is not too informative. Can you please explain what do you think is technically wrong with the proposed solution ? is it not general enough for other use cases ? will it break something ?

So if I'd like to set the *same* structure for the *same* WL1271 driver, provided that I'm working with the other platform, I'll need to do the following:
- add the pointer to the board-specific header;
- add the structure to the board-specific C file and propagate its pointer to the controller driver;
- add setting the pointer in the core structure into the controller driver.

Quoted 3 lines

This is far from being intuitive. This means we need to hack, generally speaking, all the MMC controller drivers to get it working on all platforms. This is error prone.

Quoted 7 lines

You make it sound really complex.

Let's see what it means to add it to a totally different platform.

As an example, let's take Google's ADP1 which is based on a different host controller (msm-sdcc), and add the required support (untested of course, just a quick sketch, patch is based on android's msm git):

Quoted 7 lines

What if some other driver gets attached and tries to use this platform data? ?This whole idea sounds extremely silly, cumbersome, error prone, and is inviting misuse by normal MMC sockets.

Why not arrange for a small piece of code to be built into the kernel when this driver is selected as a module or built-in, which handles the passing of platform data to the driver?

It's interesting.

The only drawback I can see is that it has an inherent limitation of having only a single wl1271 device on board, but there are no such boards outside development/testing labs.

Vitaly would that work for you too ?

Thanks,
Ohad.

Quoted 40 lines

Something like:

wl12xx_platform_data.c:
#include <linux/module.h>
#include <whatever/required/for/wl12xx.h>

static struct wl12xx_platform_data *platform_data;

int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data) {
? ? ? ?if (platform_data)
? ? ? ? ? ? ? ?return -EBUSY;
? ? ? ?platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL); ? ? ? ?if (!platform_data)
? ? ? ? ? ? ? ?return -ENOMEM;
? ? ? ?return 0;
}

int wl12xx_get_platform_data(struct wl12xx_platform_data *data) {
? ? ? ?if (platform_data) {
? ? ? ? ? ? ? ?memcpy(data, platform_data, sizeof(*data)); ? ? ? ? ? ? ? ?return 0;
? ? ? ?}
? ? ? ?return -ENODEV;
}
EXPORT_SYMBOL(wl12xx_get_platform_data);

And in the Kconfig, something like:

config WL12XX_PLATFORM_DATA
? ? ? ?bool
? ? ? ?depends on WL12XX != n
? ? ? ?default y

This means there'll be no confusion over who owns the 'embedded data', typechecking is preserved, and no possibility for the wrong driver to pick up the data.

#16 lore raw

PATCH v2 3/20 mmc: support embedded data field in mmc_host

Quoted 39 lines · Ohad Ben-Cohen
Quoted 29 lines · Russell King - ARM Linux
Quoted 20 lines · Ohad Ben-Cohen
Quoted 15 lines · Vitaly Wool
Quoted 5 lines · Ohad Ben-Cohen

I'm honestly trying to understand your concerns, but I'm afraid that just saying "it's a hack" is not too informative. Can you please explain what do you think is technically wrong with the proposed solution ? is it not general enough for other use cases ? will it break something ?

So if I'd like to set the *same* structure for the *same* WL1271 driver, provided that I'm working with the other platform, I'll need to do the following:
- add the pointer to the board-specific header;
- add the structure to the board-specific C file and propagate its pointer to the controller driver;
- add setting the pointer in the core structure into the controller driver.

Quoted 3 lines

This is far from being intuitive. This means we need to hack, generally speaking, all the MMC controller drivers to get it working on all platforms. This is error prone.

Quoted 7 lines

You make it sound really complex.

Let's see what it means to add it to a totally different platform.

As an example, let's take Google's ADP1 which is based on a different host controller (msm-sdcc), and add the required support (untested of course, just a quick sketch, patch is based on android's msm git):

Quoted 7 lines

What if some other driver gets attached and tries to use this platform data? ?This whole idea sounds extremely silly, cumbersome, error prone, and is inviting misuse by normal MMC sockets.

Why not arrange for a small piece of code to be built into the kernel when this driver is selected as a module or built-in, which handles the passing of platform data to the driver?

Quoted 7 lines

It's interesting.

The only drawback I can see is that it has an inherent limitation of having only a single wl1271 device on board, but there are no such boards outside development/testing labs.

Vitaly would that work for you too ?

Works for me, but I've got a remark.
If we try to generalize that idea to handle multiple devices it will be similar to the following:

static struct wl12xx_platform_data platform_data[MAX_WL12XX_DEVICES];

int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data, int id);
int wl12xx_get_platform_data(struct wl12xx_platform_data *data, int id);

which will look pretty much like... yes, a simplified/customized version board_info applied to a single driver.

But anyway I'm fine with that.

~Vitaly

#17 lore raw

PATCH v2 3/20 mmc: support embedded data field in mmc_host

In reply to Ohad Ben-Cohen

2010/8/4 Ohad Ben-Cohen <[email protected]>:

Quoted 10 lines

On Wed, Aug 4, 2010 at 2:41 PM, Russell King - ARM Linux

Quoted 4 lines

Why not arrange for a small piece of code to be built into the kernel when this driver is selected as a module or built-in, which handles the passing of platform data to the driver?

It's interesting.

The only drawback I can see is that it has an inherent limitation of having only a single wl1271 device on board,

...which is exactly what the *_board_info scheme in the spi and i2c subsystems is designed to solve.

This is an established design pattern in the kernel with two precedents, what makes it so hard to implement this idea? There are plenty of examples all over the place.

What mainly matters to me is that the stuff can be separated cleanly and in a nicely structured manner into board-xxx.c files in the mach-xxx dirs, which is possible also with the simpler approach so whatever...

Yours,
Linus Walleij

#18 lore raw

PATCH v2 3/20 mmc: support embedded data field in mmc_host

Quoted 12 lines · Linus Walleij

2010/8/4 Ohad Ben-Cohen <[email protected]>:

Quoted 10 lines

On Wed, Aug 4, 2010 at 2:41 PM, Russell King - ARM Linux

Quoted 4 lines

Why not arrange for a small piece of code to be built into the kernel when this driver is selected as a module or built-in, which handles the passing of platform data to the driver?

It's interesting.

The only drawback I can see is that it has an inherent limitation of having only a single wl1271 device on board,

Quoted 6 lines

...which is exactly what the *_board_info scheme in the spi and i2c subsystems is designed to solve.

This is an established design pattern in the kernel with two precedents, what makes it so hard to implement this idea? There are plenty of examples all over the place.

How would a driver ask for the platform data of its specific device ?

Using DEVICE_ID and VENDOR_ID is wrong - those numbers do not identify a specific device instance (think of a board with two wl1271 devices. the only difference between them is the index of their mmc controller).

The only sane way to uniquely identify a specific device instance is to couple its platform data with the host controller the device is hardwired to.

So if we want to have an external sdio_board_info table to work, it would have to map a controller index to sdio_board_info objects. Something in the lines of:

int sdio_get_platform_data(struct sdio_board_info *data, struct sdio_func *func)

{
       if (platform_data[func->card->host->index]) {
               memcpy(data, platform_data[func->card->host->index],
sizeof(*data));
               return 0;
       }
       return -ENODEV;
}

typechecking is not preserved (the driver would have to cast data->platform_data), and there is a possibility for the wrong driver to pick up the data (at least as much as there was with the original proposal).

AFAICS, the difference between SDIO and I2C/SPI in that respect, is that SDIO devices are created dynamically when hardware is probed, whereas I2C/SPI uses the *_board_info table to populate the device tree. The I2C/SPI drivers then elegantly get the platform data in the probe call. In our case, the device is created dynamically, and the only way to couple it with the correct platform data is using the knowledge that it is hardwired to a specific host controller.

So using an external repository of platform data objects seem to have similar disadvantages like the original proposal, but with much more code.

We have Russell's suggestion which is nice and simple, but it has the 1 device limitation.

Or, we can go back to the approach of creating another platform device for that chip. That device's name should be "wl1271.x" where x is the index of the controller the device is hardwired to. Later, when the SDIO function probe is invoked, it would register the platform driver (after dynamically sprintf()ing the name using the func->card->host->index number), and then wait_for_completion_interruptible_timeout() for it to probe.

That seem to settle all the concerns raised: we get typechecking, no wrong driver getting the data, no 1 device limit, no races between the two probes.

Thanks,
Ohad.

#19 lore raw

PATCH v2 3/20 mmc: support embedded data field in mmc_host

Quoted 2 lines · Ohad Ben-Cohen

We have Russell's suggestion which is nice and simple, but it has the 1 device limitation.

You could make it generic by doing something like this:

#define set_device_data(name, type, index, data) \

 ({									\
    extern void __set_device_data(const char *, int, void *, size_t);	\
    BUILD_BUG_ON(!__same_type(type, *data));				\
    __set_device_data(name ":" #type, index, data, sizeof(type));	\

})

#define get_device_data(name, type, index) ({ \
extern void *__get_device_data(const char *, int); \
type *__ptr = __get_device_data(name ":" #type, index); \
__ptr; })

And now we have something that takes a string and index to use as a lookup key in some kind of list - and it's typesafe (because the lookup key is dependent on the stringified type.)

But... at this point I feel that we're getting too complicated, and will get shouted at to use something like DT which already solves this problem.

#20 lore raw

PATCH v2 3/20 mmc: support embedded data field in mmc_host

Quoted 18 lines · Russell King - ARM Linux
Quoted 2 lines · Ohad Ben-Cohen

We have Russell's suggestion which is nice and simple, but it has the 1 device limitation.

You could make it generic by doing something like this:

#define set_device_data(name, type, index, data) \

 ({									\
    extern void __set_device_data(const char *, int, void *, size_t);	\
    BUILD_BUG_ON(!__same_type(type, *data));				\
    __set_device_data(name ":" #type, index, data, sizeof(type));	\

})

#define get_device_data(name, type, index) ({ \
extern void *__get_device_data(const char *, int); \
type *__ptr = __get_device_data(name ":" #type, index); \
__ptr; })

Quoted 6 lines

And now we have something that takes a string and index to use as a lookup key in some kind of list - and it's typesafe (because the lookup key is dependent on the stringified type.)

But... at this point I feel that we're getting too complicated, and will get shouted at to use something like DT which already solves this problem.

DT is not generally available yet. A simple interim solution would still be worth it.

Nicolas

#21 lore raw

PATCH v2 4/20 omap zoom2: wlan board muxing

In reply to Ohad Ben-Cohen

Add board muxing to support the wlan wl1271 chip that is hardwired to mmc2 (third mmc controller) on the ZOOM2.

---
 arch/arm/mach-omap2/board-zoom2.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/board-zoom2.c +13 -0
index 803ef14..1520a2c 100644
@@ -71,6 +71,19 @@ static struct twl4030_platform_data zoom2_twldata = {
 
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
+	/* WLAN IRQ - GPIO 162 */
+	OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN POWER ENABLE - GPIO 101 */
+	OMAP3_MUX(CAM_D2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+	/* WLAN SDIO: MMC3 CMD */
+	OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN SDIO: MMC3 CLK */
+	OMAP3_MUX(ETK_CLK, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN SDIO: MMC3 DAT[0-3] */
+	OMAP3_MUX(ETK_D3, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(ETK_D4, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(ETK_D5, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(ETK_D6, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
 #else
Signature · 1 line
1.7.0.4
#22 lore raw

PATCH v2 5/20 omap zoom3: wlan board muxing

In reply to Ohad Ben-Cohen

Add board muxing to support the wlan wl1271 chip that is hardwired to mmc2 (third mmc controller) on the ZOOM3.

---
 arch/arm/mach-omap2/board-zoom3.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/board-zoom3.c +13 -0
index 3314704..7d17046 100644
@@ -46,6 +46,19 @@ static void __init omap_zoom_init_irq(void)
 
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
+	/* WLAN IRQ - GPIO 162 */
+	OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN POWER ENABLE - GPIO 101 */
+	OMAP3_MUX(CAM_D2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+	/* WLAN SDIO: MMC3 CMD */
+	OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN SDIO: MMC3 CLK */
+	OMAP3_MUX(ETK_CLK, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN SDIO: MMC3 DAT[0-3] */
+	OMAP3_MUX(ETK_D3, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(ETK_D4, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(ETK_D5, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(ETK_D6, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
 #else
Signature · 1 line
1.7.0.4
#23 lore raw

PATCH v2 6/20 wireless: wl1271: make wl12xx.h common to both spi and sdio

In reply to Ohad Ben-Cohen

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 c561332..416d5aa 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 e814742..4847b6a 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 5189b81..e866049 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
#24 lore raw

PATCH v2 7/20 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 6f1b6b5..a21cdb2 100644
@@ -340,7 +340,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 b7d9137..6bd748e 100644
@@ -620,7 +620,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 9903ae9..571c6b9 100644
@@ -144,7 +144,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);
 
@@ -159,6 +159,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 e866049..85a167f 100644
@@ -313,10 +313,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
#25 lore raw

PATCH v2 8/20 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 private data which is supplied by the sdio function.

---
 drivers/net/wireless/wl12xx/wl1271_sdio.c |   14 ++++++++------
 1 files changed, 8 insertions(+), 6 deletions(-)
drivers/net/wireless/wl12xx/wl1271_sdio.c +8 -6
index 571c6b9..75901a6 100644
@@ -28,15 +28,14 @@
 #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 <plat/gpio.h>
 
 #include "wl1271.h"
 #include "wl12xx_80211.h"
 #include "wl1271_io.h"
 
-
-#define RX71_WL1271_IRQ_GPIO		42
-
 static const struct sdio_device_id wl1271_devices[] = {
 	{ SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) },
 	{}
@@ -178,6 +177,7 @@ 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;
 	struct wl1271 *wl;
 	int ret;
 
@@ -197,9 +197,11 @@ static int __devinit wl1271_probe(struct sdio_func *func,
 	/* Grab access to FN0 for ELP reg. */
 	func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
 
-	wl->irq = gpio_to_irq(RX71_WL1271_IRQ_GPIO);
-	if (wl->irq < 0) {
-		ret = wl->irq;
+	wlan_data = mmc_get_embedded_data(func->card->host);
+	if (wlan_data && wlan_data->irq)
+		wl->irq = wlan_data->irq;
+	else {
+		ret = -EINVAL;
 		wl1271_error("could not get irq!");
 		goto out_free;
 	}
Signature · 1 line
1.7.0.4
#26 lore raw

PATCH v2 9/20 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 |    7 ++++---
 drivers/net/wireless/wl12xx/wl1271_spi.c  |    2 ++
 include/linux/wl12xx.h                    |    1 +
 6 files changed, 13 insertions(+), 8 deletions(-)
drivers/net/wireless/wl12xx/wl1271.h +1 -0
index a21cdb2..595f1a8 100644
@@ -357,6 +357,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 1a36d8a..d3f0521 100644
@@ -455,17 +455,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);
@@ -514,7 +515,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 +4 -3
index 75901a6..5967718 100644
@@ -198,11 +198,12 @@ static int __devinit wl1271_probe(struct sdio_func *func,
 	func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
 
 	wlan_data = mmc_get_embedded_data(func->card->host);
-	if (wlan_data && wlan_data->irq)
+	if (wlan_data) {
 		wl->irq = wlan_data->irq;
-	else {
+		wl->ref_clock = wlan_data->board_ref_clock;
+	} else {
 		ret = -EINVAL;
-		wl1271_error("could not get irq!");
+		wl1271_error("missing wlan data (needed for irq/ref_clk)!");
 		goto out_free;
 	}
 
drivers/net/wireless/wl12xx/wl1271_spi.c +2 -0
index 85a167f..501b8b4 100644
@@ -373,6 +373,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
#27 lore raw

PATCH v2 10/20 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 |   34 ++++++++++++++++++++++++++
 1 files changed, 34 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/board-zoom-peripherals.c +34 -0
index 6b39849..2fc0f4a 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,10 @@ static struct regulator_consumer_supply zoom_vmmc2_supply = {
 	.supply		= "vmmc",
 };
 
+static struct regulator_consumer_supply zoom_vmmc3_supply = {
+	.supply		= "vmmc",
+};
+
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
 static struct regulator_init_data zoom_vmmc1 = {
 	.constraints = {
@@ -151,6 +158,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 +313,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 v2 10/20 omap: zoom: add fixed regulator device for wlan

arch/arm/mach-omap2/board-zoom-peripherals.c static struct regulator_consumer_supply zoom_vmmc2_supply = { · line 114

Quoted 3 lines · Ohad Ben-Cohen
arch/arm/mach-omap2/board-zoom-peripherals.c +3 -0
+static struct regulator_consumer_supply zoom_vmmc3_supply = {
+	.supply		= "vmmc",
+};

This looks like a misconfiguration on the consumer - I'd strongly expect the consumer to have a dev_name specified also with the name being in terms of the consumer device.

#29 lore raw

PATCH v2 10/20 omap: zoom: add fixed regulator device for wlan

Quoted 9 lines · ext Mark Brown

arch/arm/mach-omap2/board-zoom-peripherals.c static struct regulator_consumer_supply zoom_vmmc2_supply = { · line 114

Quoted 3 lines · Ohad Ben-Cohen
arch/arm/mach-omap2/board-zoom-peripherals.c +3 -0
+static struct regulator_consumer_supply zoom_vmmc3_supply = {
+	.supply		= "vmmc",
+};

This looks like a misconfiguration on the consumer - I'd strongly expect the consumer to have a dev_name specified also with the name being in terms of the consumer device.

you need to add something like

.dev_name = "mmci-omap-hs.2"

regards,
-roger

#30 lore raw

PATCH v2 10/20 omap: zoom: add fixed regulator device for wlan

Quoted 12 lines · Roger Quadros
Quoted 10 lines · ext Mark Brown

arch/arm/mach-omap2/board-zoom-peripherals.c static struct regulator_consumer_supply zoom_vmmc2_supply = { · line 114

Quoted 3 lines · Ohad Ben-Cohen
arch/arm/mach-omap2/board-zoom-peripherals.c +3 -0
+static struct regulator_consumer_supply zoom_vmmc3_supply = {
+ ? ? ? .supply ? ? ? ? = "vmmc",
+};

This looks like a misconfiguration on the consumer - I'd strongly expect the consumer to have a dev_name specified also with the name being in terms of the consumer device.

Quoted 3 lines

you need to add something like

.dev_name ? ? ? = "mmci-omap-hs.2"

I already set the .dev member of the consumer in a similar manner to how all other regulators are configured in this board - please check out patch 13:

https://patchwork.kernel.org/patch/113418/

Does this look reasonable to you ?

Thanks,
Ohad.

Quoted 4 lines

regards,
-roger

#31 lore raw

PATCH v2 10/20 omap: zoom: add fixed regulator device for wlan

Quoted 10 lines · Ohad Ben-Cohen
Quoted 1 line · Roger Quadros

.dev_name ? ? ? = "mmci-omap-hs.2"

I already set the .dev member of the consumer in a similar manner to how all other regulators are configured in this board - please check out patch 13:

https://patchwork.kernel.org/patch/113418/

Does this look reasonable to you ?

You should really be using dev_name in preference to dev these days unless there's a *very* good reason.

#32 lore raw

PATCH v2 10/20 omap: zoom: add fixed regulator device for wlan

Quoted 8 lines · Mark Brown
Quoted 6 lines · Ohad Ben-Cohen
Quoted 1 line · Roger Quadros

.dev_name ? ? ? = "mmci-omap-hs.2"

I already set the .dev member of the consumer in a similar manner to how all other regulators are configured in this board - please check out patch 13:

Quoted 6 lines
Quoted 3 lines

https://patchwork.kernel.org/patch/113418/

Does this look reasonable to you ?

You should really be using dev_name in preference to dev these days unless there's a *very* good reason.

Changed, thank you.

I'll submit the updated patch now as a standalone patch as it has no dependencies on the whole series, and it could only help to start trimming that series down.

Quoted 1 line
#33 lore raw

PATCH v2 11/20 omap: hsmmc: support mmc3 regulator power control

In reply to Ohad Ben-Cohen

Prepare for mmc3 regulator power control by splitting the power control functions of mmc2 and mmc3, and expecting mmc3 to have a single, dedicated, regulator support.

---
 arch/arm/mach-omap2/hsmmc.c   |   10 ++++--
 drivers/mmc/host/omap_hsmmc.c |   67 ++++++++++++++++++++++++++++++++++++----
 2 files changed, 66 insertions(+), 11 deletions(-)
arch/arm/mach-omap2/hsmmc.c +6 -4
index 1ef54b0..5d3d789 100644
@@ -174,7 +174,7 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot,
 	}
 }
 
-static void hsmmc23_before_set_reg(struct device *dev, int slot,
+static void hsmmc2_before_set_reg(struct device *dev, int slot,
 				   int power_on, int vdd)
 {
 	struct omap_mmc_platform_data *mmc = dev->platform_data;
@@ -325,14 +325,16 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
 				c->transceiver = 1;
 			if (c->transceiver && c->wires > 4)
 				c->wires = 4;
-			/* FALLTHROUGH */
-		case 3:
 			if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
 				/* off-chip level shifting, or none */
-				mmc->slots[0].before_set_reg = hsmmc23_before_set_reg;
+				mmc->slots[0].before_set_reg = hsmmc2_before_set_reg;
 				mmc->slots[0].after_set_reg = NULL;
 			}
 			break;
+		case 3:
+			mmc->slots[0].before_set_reg = NULL;
+			mmc->slots[0].after_set_reg = NULL;
+			break;
 		default:
 			pr_err("MMC%d configuration not supported!\n", c->mmc);
 			kfree(mmc);
drivers/mmc/host/omap_hsmmc.c +60 -7

105 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#34 lore raw

PATCH v2 12/20 omap: hsmmc: allow board-specific settings of private mmc data

In reply to Ohad Ben-Cohen

Allow board-specific settings of private mmc data, in order to allow embedded SDIO devices to communicate board-specific parameters to the SDIO function driver (e.g., the external IRQ line of the wl1271).

---
 arch/arm/mach-omap2/hsmmc.c           |    2 ++
 arch/arm/mach-omap2/hsmmc.h           |    1 +
 arch/arm/plat-omap/include/plat/mmc.h |    2 ++
 drivers/mmc/host/omap_hsmmc.c         |    2 ++
 4 files changed, 7 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/hsmmc.c +2 -0
index 5d3d789..f06ddd2 100644
@@ -284,6 +284,8 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
 		if (c->vcc_aux_disable_is_sleep)
 			mmc->slots[0].vcc_aux_disable_is_sleep = 1;
 
+		mmc->slots[0].priv_data = c->priv_data;
+
 		/* NOTE:  MMC slots should have a Vcc regulator set up.
 		 * This may be from a TWL4030-family chip, another
 		 * controllable regulator, or a fixed supply.
arch/arm/mach-omap2/hsmmc.h +1 -0
index 36f0ba8..434a3ed 100644
@@ -23,6 +23,7 @@ struct omap2_hsmmc_info {
 	int	ocr_mask;	/* temporary HACK */
 	/* Remux (pad configuation) when powering on/off */
 	void (*remux)(struct device *dev, int slot, int power_on);
+	void	*priv_data;	/* private data to SDIO function driver */
 };
 
 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
arch/arm/plat-omap/include/plat/mmc.h +2 -0
index c835f1e..9db1617 100644
@@ -140,6 +140,8 @@ struct omap_mmc_platform_data {
 
 		unsigned int ban_openended:1;
 
+		/* card private data that should be used by function driver */
+		void *priv_data;
 	} slots[OMAP_MMC_MAX_SLOTS];
 };
 
drivers/mmc/host/omap_hsmmc.c +2 -0
index 4c5a669..4ac548e 100644
@@ -2157,6 +2157,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 	if (mmc_slot(host).nonremovable)
 		mmc->caps |= MMC_CAP_NONREMOVABLE;
 
+	mmc_set_embedded_data(mmc, mmc_slot(host).priv_data);
+
 	omap_hsmmc_conf_bus_power(host);
 
 	/* Select DMA lines */
Signature · 1 line
1.7.0.4
#35 lore raw

PATCH v2 13/20 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 |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/board-zoom-peripherals.c +19 -0
index 2fc0f4a..3230801 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[] = {
@@ -184,6 +187,12 @@ static struct platform_device omap_vwlan_device = {
 	},
 };
 
+struct wl12xx_platform_data omap_zoom_wlan_data = {
+	.irq = OMAP_GPIO_IRQ(OMAP_ZOOM_WLAN_IRQ_GPIO),
+	/* ZOOM ref clock is 26 MHz */
+	.board_ref_clock = 1,
+};
+
 static struct omap2_hsmmc_info mmc[] __initdata = {
 	{
 		.name		= "external",
@@ -201,6 +210,15 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
 		.nonremovable	= true,
 		.power_saving	= true,
 	},
+	{
+		.name		= "wl1271",
+		.mmc		= 3,
+		.wires		= 4,
+		.gpio_wp	= -EINVAL,
+		.gpio_cd	= -EINVAL,
+		.ocr_mask	= MMC_VDD_165_195,
+		.priv_data	= &omap_zoom_wlan_data,
+	},
 	{}      /* Terminator */
 };
 
@@ -217,6 +235,7 @@ static int zoom_twl_gpio_setup(struct device *dev,
 	zoom_vmmc1_supply.dev = mmc[0].dev;
 	zoom_vsim_supply.dev = mmc[0].dev;
 	zoom_vmmc2_supply.dev = mmc[1].dev;
+	zoom_vmmc3_supply.dev = mmc[2].dev;
 
 	return 0;
 }
Signature · 1 line
1.7.0.4
#36 lore raw

PATCH v2 14/20 mmc: sdio: fully reconfigure oldcard on resume

In reply to Ohad Ben-Cohen

On resume, let mmc_sdio_init_card go all the way, instead of skipping the reconfiguration of the card's speed and width.

This is needed to ensure cards wake up with their clock reconfigured (otherwise it's kept low).

This patch also removes the explicit bus width reconfiguration on resume, since now this is part of mmc_sdio_init_card.

---
 drivers/mmc/core/sdio.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)
drivers/mmc/core/sdio.c +0 -4
index b9dee28..645f173 100644
@@ -344,7 +344,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
 			goto err;
 		}
 		card = oldcard;
-		return 0;
 	}
 
 	/*
@@ -487,9 +486,6 @@ static int mmc_sdio_resume(struct mmc_host *host)
 	mmc_claim_host(host);
 	err = mmc_sdio_init_card(host, host->ocr, host->card,
 				 (host->pm_flags & MMC_PM_KEEP_POWER));
-	if (!err)
-		/* We may have switched to 1-bit mode during suspend. */
-		err = sdio_enable_wide(host->card);
 	if (!err && host->sdio_irqs)
 		mmc_signal_sdio_irq(host);
 	mmc_release_host(host);
Signature · 1 line
1.7.0.4
#37 lore raw

PATCH v2 15/20 mmc: sdio: verify existence of resume handler

In reply to Ohad Ben-Cohen

Before invoking a card's resume handler, verify one exists.

---
 drivers/mmc/core/sdio.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)
drivers/mmc/core/sdio.c +3 -1
index 645f173..37739f5 100644
@@ -504,7 +504,9 @@ static int mmc_sdio_resume(struct mmc_host *host)
 		struct sdio_func *func = host->card->sdio_func[i];
 		if (func && sdio_func_present(func) && func->dev.driver) {
 			const struct dev_pm_ops *pmops = func->dev.driver->pm;
-			err = pmops->resume(&func->dev);
+
+			if (pmops && pmops->resume)
+				err = pmops->resume(&func->dev);
 		}
 	}
 
Signature · 1 line
1.7.0.4
#38 lore raw

PATCH v2 16/20 mmc: introduce API to control the card's power

In reply to Ohad Ben-Cohen

Introduce the sdio_claim_power/sdio_release_power API (with correspoding mmc_claim_power/mmc_release_power) that controls the power of the card. A reference count scheme is employed, to allow SDIO function voting.

---
 drivers/mmc/core/bus.c        |    3 ++
 drivers/mmc/core/core.c       |   50 +++++++++++++++++++++++++++++++++++++++++
 drivers/mmc/core/sdio.c       |    5 ++++
 drivers/mmc/core/sdio_io.c    |   50 +++++++++++++++++++++++++++++++++++++++++
 include/linux/mmc/card.h      |    2 +
 include/linux/mmc/host.h      |    2 +
 include/linux/mmc/sdio_func.h |    3 ++
 7 files changed, 115 insertions(+), 0 deletions(-)
drivers/mmc/core/bus.c +3 -0
index 49d9dca..33151d5 100644
@@ -17,6 +17,7 @@
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
+#include <asm/atomic.h>
 
 #include "core.h"
 #include "sdio_cis.h"
@@ -207,6 +208,8 @@ struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)
 
 	card->host = host;
 
+	atomic_set(&card->power_claims, 0);
+
 	device_initialize(&card->dev);
 
 	card->dev.parent = mmc_classdev(host);
drivers/mmc/core/core.c +50 -0

56 lines not on this page · raw message

drivers/mmc/core/sdio.c +5 -0
index 37739f5..79e6fa1 100644
@@ -15,6 +15,7 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/sdio.h>
 #include <linux/mmc/sdio_func.h>
+#include <asm/atomic.h>
 
 #include "core.h"
 #include "bus.h"
@@ -72,6 +73,10 @@ static int sdio_init_func(struct mmc_card *card, unsigned int fn)
 
 	card->sdio_func[fn - 1] = func;
 
+	/* For each SDIO function initialized, increase the power claim
+	 * reference count of the card */
+	atomic_inc(&card->power_claims);
+
 	return 0;
 
 fail:
drivers/mmc/core/sdio_io.c +50 -0

56 lines not on this page · raw message

include/linux/mmc/card.h +2 -0
index d02d2c6..4073b43 100644
@@ -11,6 +11,7 @@
 #define LINUX_MMC_CARD_H
 
 #include <linux/mmc/core.h>
+#include <asm/atomic.h>
 
 struct mmc_cid {
 	unsigned int		manfid;
@@ -120,6 +121,7 @@ struct mmc_card {
 	struct sdio_func_tuple	*tuples;	/* unknown common tuples */
 
 	struct dentry		*debugfs_root;
+	atomic_t		power_claims;	/* ref count of power requests */
 };
 
 #define mmc_card_mmc(c)		((c)->type == MMC_TYPE_MMC)
include/linux/mmc/host.h +2 -0
index 80db597..3675d58 100644
@@ -234,6 +234,8 @@ static inline void *mmc_priv(struct mmc_host *host)
 
 extern int mmc_suspend_host(struct mmc_host *);
 extern int mmc_resume_host(struct mmc_host *);
+extern int mmc_release_power(struct mmc_host *);
+extern int mmc_claim_power(struct mmc_host *);
 
 extern void mmc_power_save_host(struct mmc_host *host);
 extern void mmc_power_restore_host(struct mmc_host *host);
include/linux/mmc/sdio_func.h +3 -0
index 31baaf8..e77b676 100644
@@ -116,6 +116,9 @@ extern void sdio_unregister_driver(struct sdio_driver *);
 /*
  * SDIO I/O operations
  */
+int sdio_claim_power(struct sdio_func *func);
+int sdio_release_power(struct sdio_func *func);
+
 extern void sdio_claim_host(struct sdio_func *func);
 extern void sdio_release_host(struct sdio_func *func);
 
Signature · 1 line
1.7.0.4
#39 lore raw

PATCH v2 17/20 mmc: sdio: relocate sdio_set_block_size call

In reply to Ohad Ben-Cohen

To support probing of SDIO function driver while the device is powered off, we need to relocate the sdio_set_block_size call from the bus probe to an earlier point where we know the device is still powered. In addition, we want the block size set also when cards are resumed.

---
 drivers/mmc/core/sdio.c     |   14 +++++++++++++-
 drivers/mmc/core/sdio_bus.c |    9 ---------
 2 files changed, 13 insertions(+), 10 deletions(-)
drivers/mmc/core/sdio.c +13 -1
index 79e6fa1..5c0fbfa 100644
@@ -73,6 +73,12 @@ static int sdio_init_func(struct mmc_card *card, unsigned int fn)
 
 	card->sdio_func[fn - 1] = func;
 
+	/* Set the default block size so the driver is sure it's something
+	 * sensible. */
+	ret = sdio_set_block_size(func, 0);
+	if (ret)
+		return ret;
+
 	/* For each SDIO function initialized, increase the power claim
 	 * reference count of the card */
 	atomic_inc(&card->power_claims);
@@ -510,7 +516,13 @@ static int mmc_sdio_resume(struct mmc_host *host)
 		if (func && sdio_func_present(func) && func->dev.driver) {
 			const struct dev_pm_ops *pmops = func->dev.driver->pm;
 
-			if (pmops && pmops->resume)
+			/* Set the default block size so the driver is sure
+			 * it's something sensible. */
+			mmc_claim_host(host);
+			err = sdio_set_block_size(func, 0);
+			mmc_release_host(host);
+
+			if (!err && pmops && pmops->resume)
 				err = pmops->resume(&func->dev);
 		}
 	}
drivers/mmc/core/sdio_bus.c +0 -9
index 4a890dc..87269f6 100644
@@ -119,20 +119,11 @@ static int sdio_bus_probe(struct device *dev)
 	struct sdio_driver *drv = to_sdio_driver(dev->driver);
 	struct sdio_func *func = dev_to_sdio_func(dev);
 	const struct sdio_device_id *id;
-	int ret;
 
 	id = sdio_match_device(func, drv);
 	if (!id)
 		return -ENODEV;
 
-	/* Set the default block size so the driver is sure it's something
-	 * sensible. */
-	sdio_claim_host(func);
-	ret = sdio_set_block_size(func, 0);
-	sdio_release_host(func);
-	if (ret)
-		return ret;
-
 	return drv->probe(func, id);
 }
 
Signature · 1 line
1.7.0.4
#40 lore raw

PATCH v2 18/20 mmc: sdio: enable a default power off mode of the card

In reply to Ohad Ben-Cohen

Add support for an SDIO device to stay powered off even without the presence of an SDIO function driver. A host should explicitly ask for it by means of MMC_CAP_DONT_POWER_CARD, and the SDIO function driver should know it needs to call sdio_claim_power before accessing the device.

---
 drivers/mmc/core/sdio.c  |   15 +++++++++++++--
 include/linux/mmc/host.h |    1 +
 2 files changed, 14 insertions(+), 2 deletions(-)
drivers/mmc/core/sdio.c +13 -2
index 5c0fbfa..164353f 100644
@@ -80,8 +80,9 @@ static int sdio_init_func(struct mmc_card *card, unsigned int fn)
 		return ret;
 
 	/* For each SDIO function initialized, increase the power claim
-	 * reference count of the card */
-	atomic_inc(&card->power_claims);
+	 * reference count of the card, unless explicitly requested not to */
+	if (!(card->host->caps & MMC_CAP_DONT_POWER_CARD))
+		atomic_inc(&card->power_claims);
 
 	return 0;
 
@@ -607,6 +608,16 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
 	mmc_release_host(host);
 
 	/*
+	 * If power is not required for this card, power it off.
+	 * The sdio function will need to call sdio_claim_power.
+	 */
+	if (!atomic_read(&card->power_claims)) {
+		pr_info("%s: power is not claimed, releasing\n",
+						mmc_hostname(host));
+		mmc_release_power(host);
+	}
+
+	/*
 	 * First add the card to the driver model...
 	 */
 	err = mmc_add_card(host->card);
include/linux/mmc/host.h +1 -0
index 3675d58..756cf38 100644
@@ -155,6 +155,7 @@ struct mmc_host {
 #define MMC_CAP_DISABLE		(1 << 7)	/* Can the host be disabled */
 #define MMC_CAP_NONREMOVABLE	(1 << 8)	/* Nonremovable e.g. eMMC */
 #define MMC_CAP_WAIT_WHILE_BUSY	(1 << 9)	/* Waits while card is busy */
+#define MMC_CAP_DONT_POWER_CARD	(1 << 10)	/* Keep the card powered off */
 
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
 
Signature · 1 line
1.7.0.4
#41 lore raw

PATCH v2 18/20 mmc: sdio: enable a default power off mode of the card

Quoted 7 lines · ext Ohad Ben-Cohen

Add support for an SDIO device to stay powered off even without the presence of an SDIO function driver. A host should explicitly ask for it by means of MMC_CAP_DONT_POWER_CARD, and the SDIO function driver should know it needs to call sdio_claim_power before accessing the device.

Shouldn't this be the default behaviour? If there is no function driver for any of the functions of the card, then sdio core shold power off the card.

I don't see a need for a special capability flag for this.

in fact MMC_CAP_DONT_POWER_CARD does not seem like an mmc host's capability flag, it seems more like a request from the board to keep the card powered off.

regards,
-roger

#42 lore raw

PATCH v2 18/20 mmc: sdio: enable a default power off mode of the card

Quoted 8 lines · Roger Quadros
Quoted 7 lines · ext Ohad Ben-Cohen

Add support for an SDIO device to stay powered off even without the presence of an SDIO function driver. A host should explicitly ask for it by means of MMC_CAP_DONT_POWER_CARD, and the SDIO function driver should know it needs to call sdio_claim_power before accessing the device.

Quoted 8 lines
Quoted 1 line

Shouldn't this be the default behaviour? If there is no function driver for any of the functions of the card, then sdio core shold power off the card.

I don't see a need for a special capability flag for this.

in fact MMC_CAP_DONT_POWER_CARD does not seem like an mmc host's capability

Totally agree.

I didn't want to change the current behavior of the cards/funcs so I looked for a way to explicitly power down only specific cards.

Alternatively we could power down all cards at the end mmc_attach_sdio, and then power them up selectively in sdio_bus_probe, just before calling probe. If the probe succeeds, the function driver takes over. If the probe fails, we can power them down again.

Is that what you meant ?

This would work both if the sdio function driver is already loaded, or will only be loaded at a later time. But I'm not too fond of the extra power on/off cycles that it will introduce for each card..

Thanks,
Ohad.

Quoted 6 lines

flag, it seems more like a request from the board to keep the card powered off.

regards,
-roger

#43 lore raw

PATCH v2 18/20 mmc: sdio: enable a default power off mode of the card

Quoted 20 lines · Ohad Ben-Cohen
Quoted 8 lines · Roger Quadros
Quoted 7 lines · ext Ohad Ben-Cohen

Add support for an SDIO device to stay powered off even without the presence of an SDIO function driver. A host should explicitly ask for it by means of MMC_CAP_DONT_POWER_CARD, and the SDIO function driver should know it needs to call sdio_claim_power before accessing the device.

Quoted 8 lines
Quoted 1 line

Shouldn't this be the default behaviour? If there is no function driver for any of the functions of the card, then sdio core shold power off the card.

I don't see a need for a special capability flag for this.

in fact MMC_CAP_DONT_POWER_CARD does not seem like an mmc host's capability

Totally agree.

Quoted 7 lines

I didn't want to change the current behavior of the cards/funcs so I looked for a way to explicitly power down only specific cards.

Alternatively we could power down all cards at the end mmc_attach_sdio, and then power them up selectively in sdio_bus_probe, just before calling probe. If the probe succeeds, the function driver takes over. If the probe fails, we can power them down again.

Exactly!

Quoted 5 lines

Is that what you meant ?

This would work both if the sdio function driver is already loaded, or will only be loaded at a later time. But I'm not too fond of the extra power on/off cycles that it will introduce for each card..

This is still way better than introducing knowledge about specific cards in the host drivers.

Nicolas

#44 lore raw

PATCH v2 18/20 mmc: sdio: enable a default power off mode of the card

Quoted 25 lines · Nicolas Pitre
Quoted 23 lines · Ohad Ben-Cohen
Quoted 8 lines · Roger Quadros
Quoted 7 lines · ext Ohad Ben-Cohen

Add support for an SDIO device to stay powered off even without the presence of an SDIO function driver. A host should explicitly ask for it by means of MMC_CAP_DONT_POWER_CARD, and the SDIO function driver should know it needs to call sdio_claim_power before accessing the device.

Quoted 8 lines
Quoted 1 line

Shouldn't this be the default behaviour? If there is no function driver for any of the functions of the card, then sdio core shold power off the card.

I don't see a need for a special capability flag for this.

in fact MMC_CAP_DONT_POWER_CARD does not seem like an mmc host's capability

Totally agree.

I didn't want to change the current behavior of the cards/funcs so I looked for a way to explicitly power down only specific cards.

Quoted 6 lines
Quoted 4 lines

Alternatively we could power down all cards at the end mmc_attach_sdio, and then power them up selectively in sdio_bus_probe, just before calling probe. If the probe succeeds, the function driver takes over. If the probe fails, we can power them down again.

Exactly!

Ok, v3 is on the way :)

(featuring no special host CAP, fix locking issues, and power down unclaimed cards also on resume)

#45 lore raw

PATCH v2 19/20 omap: zoom: keep the MMC3 wl1271 device powered off

In reply to Ohad Ben-Cohen

Keep the MMC3 wl1271 WLAN device powered off until its SDIO function driver requests otherwise.

---
 arch/arm/mach-omap2/board-zoom-peripherals.c |    1 +
 arch/arm/mach-omap2/hsmmc.c                  |    3 +++
 arch/arm/mach-omap2/hsmmc.h                  |    1 +
 arch/arm/plat-omap/include/plat/mmc.h        |    3 +++
 drivers/mmc/host/omap_hsmmc.c                |    3 +++
 5 files changed, 11 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/board-zoom-peripherals.c +1 -0
index 3230801..3ab9125 100644
@@ -217,6 +217,7 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
 		.ocr_mask	= MMC_VDD_165_195,
+		.dont_power_card = true,
 		.priv_data	= &omap_zoom_wlan_data,
 	},
 	{}      /* Terminator */
arch/arm/mach-omap2/hsmmc.c +3 -0
index f06ddd2..24c4144 100644
@@ -284,6 +284,9 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
 		if (c->vcc_aux_disable_is_sleep)
 			mmc->slots[0].vcc_aux_disable_is_sleep = 1;
 
+		if (c->dont_power_card)
+			mmc->slots[0].dont_power_card = 1;
+
 		mmc->slots[0].priv_data = c->priv_data;
 
 		/* NOTE:  MMC slots should have a Vcc regulator set up.
arch/arm/mach-omap2/hsmmc.h +1 -0
index 434a3ed..e200786 100644
@@ -23,6 +23,7 @@ struct omap2_hsmmc_info {
 	int	ocr_mask;	/* temporary HACK */
 	/* Remux (pad configuation) when powering on/off */
 	void (*remux)(struct device *dev, int slot, int power_on);
+	bool	dont_power_card;/* keep card power off at boot (default is n)*/
 	void	*priv_data;	/* private data to SDIO function driver */
 };
 
arch/arm/plat-omap/include/plat/mmc.h +3 -0
index 9db1617..d042494 100644
@@ -140,6 +140,9 @@ struct omap_mmc_platform_data {
 
 		unsigned int ban_openended:1;
 
+		/* keep this card powered off at boot (default is n) */
+		unsigned int dont_power_card:1;
+
 		/* card private data that should be used by function driver */
 		void *priv_data;
 	} slots[OMAP_MMC_MAX_SLOTS];
drivers/mmc/host/omap_hsmmc.c +3 -0
index 4ac548e..4fb6634 100644
@@ -2157,6 +2157,9 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 	if (mmc_slot(host).nonremovable)
 		mmc->caps |= MMC_CAP_NONREMOVABLE;
 
+	if (mmc_slot(host).dont_power_card)
+		mmc->caps |= MMC_CAP_DONT_POWER_CARD;
+
 	mmc_set_embedded_data(mmc, mmc_slot(host).priv_data);
 
 	omap_hsmmc_conf_bus_power(host);
Signature · 1 line
1.7.0.4
#46 lore raw

PATCH v2 19/20 omap: zoom: keep the MMC3 wl1271 device powered off

Ohad,

-----Original Message-----
From: Ohad Ben-Cohen [mailto:ohad at wizery.com]
Sent: Wednesday, July 21, 2010 12:34 PM
To: linux-wireless at vger.kernel.org; linux-mmc at vger.kernel.org; linux-omap at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org; linux at arm.linux.org.uk; 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 v2 19/20] omap: zoom: keep the MMC3 wl1271 device powered off

Keep the MMC3 wl1271 WLAN device powered off until its SDIO function driver requests otherwise.

---
 arch/arm/mach-omap2/board-zoom-peripherals.c |    1 +
 arch/arm/mach-omap2/hsmmc.c                  |    3 +++
 arch/arm/mach-omap2/hsmmc.h                  |    1 +
 arch/arm/plat-omap/include/plat/mmc.h        |    3 +++
 drivers/mmc/host/omap_hsmmc.c                |    3 +++
 5 files changed, 11 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/board-zoom-peripherals.c +1 -0
index 3230801..3ab9125 100644
@@ -217,6 +217,7 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
 		.ocr_mask	= MMC_VDD_165_195,
+		.dont_power_card = true,
 		.priv_data	= &omap_zoom_wlan_data,
 	},
 	{}      /* Terminator */
arch/arm/mach-omap2/hsmmc.c +3 -0
index f06ddd2..24c4144 100644
@@ -284,6 +284,9 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
 		if (c->vcc_aux_disable_is_sleep)
 			mmc->slots[0].vcc_aux_disable_is_sleep = 1;
 
+		if (c->dont_power_card)
+			mmc->slots[0].dont_power_card = 1;
+
 		mmc->slots[0].priv_data = c->priv_data;
 
 		/* NOTE:  MMC slots should have a Vcc regulator set up.
arch/arm/mach-omap2/hsmmc.h +1 -0
index 434a3ed..e200786 100644
@@ -23,6 +23,7 @@ struct omap2_hsmmc_info {
 	int	ocr_mask;	/* temporary HACK */
 	/* Remux (pad configuation) when powering on/off */
 	void (*remux)(struct device *dev, int slot, int power_on);
+	bool	dont_power_card;/* keep card power off at boot (default is n)*/
 	void	*priv_data;	/* private data to SDIO function driver */
 };
 
arch/arm/plat-omap/include/plat/mmc.h +3 -0
index 9db1617..d042494 100644
@@ -140,6 +140,9 @@ struct omap_mmc_platform_data {
 
 		unsigned int ban_openended:1;
 
+		/* keep this card powered off at boot (default is n) */
+		unsigned int dont_power_card:1;
+
 		/* card private data that should be used by function driver */
 		void *priv_data;
 	} slots[OMAP_MMC_MAX_SLOTS];
drivers/mmc/host/omap_hsmmc.c +3 -0
index 4ac548e..4fb6634 100644
@@ -2157,6 +2157,9 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 	if (mmc_slot(host).nonremovable)
 		mmc->caps |= MMC_CAP_NONREMOVABLE;
 
+	if (mmc_slot(host).dont_power_card)
+		mmc->caps |= MMC_CAP_DONT_POWER_CARD;
+
 	mmc_set_embedded_data(mmc, mmc_slot(host).priv_data);
 
 	omap_hsmmc_conf_bus_power(host);
Signature · 4 lines
1.7.0.4

[Benzy Gabay] small comment: Please make sure that all 127x related changes are not bounded only to MMC3. 
On OMAP4 WLAN is used on MMC5.
#47 lore raw

PATCH v2 19/20 omap: zoom: keep the MMC3 wl1271 device powered off

Hi Gever,

Quoted 30 lines · Benzy

From: Ohad Ben-Cohen [mailto:ohad at wizery.com]
Sent: Wednesday, July 21, 2010 12:34 PM
To: linux-wireless at vger.kernel.org; linux-mmc at vger.kernel.org; linux-omap at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org; linux at arm.linux.org.uk; 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 v2 19/20] omap: zoom: keep the MMC3 wl1271 device powered off

Keep the MMC3 wl1271 WLAN device powered off until its SDIO function driver requests otherwise.

---

?arch/arm/mach-omap2/board-zoom-peripherals.c | ? ?1 +
?arch/arm/mach-omap2/hsmmc.c ? ? ? ? ? ? ? ? ?| ? ?3 +++
?arch/arm/mach-omap2/hsmmc.h ? ? ? ? ? ? ? ? ?| ? ?1 +
?arch/arm/plat-omap/include/plat/mmc.h ? ? ? ?| ? ?3 +++
?drivers/mmc/host/omap_hsmmc.c ? ? ? ? ? ? ? ?| ? ?3 +++

?5 files changed, 11 insertions(+), 0 deletions(-)

arch/arm/mach-omap2/board-zoom-peripherals.c +1 -0
index 3230801..3ab9125 100644
@@ -217,6 +217,7 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
 ? ? ? ? ? ? ? ?.gpio_wp ? ? ? ?= -EINVAL,
 ? ? ? ? ? ? ? ?.gpio_cd ? ? ? ?= -EINVAL,
 ? ? ? ? ? ? ? ?.ocr_mask ? ? ? = MMC_VDD_165_195,
+ ? ? ? ? ? ? ? .dont_power_card = true,
 ? ? ? ? ? ? ? ?.priv_data ? ? ?= &omap_zoom_wlan_data,
 ? ? ? ?},

? ? ? ?{} ? ? ?/* Terminator */

...

Quoted 5 lines

--
1.7.0.4

[Benzy Gabay] small comment: Please make sure that all 127x related changes are not bounded only to MMC3. On OMAP4 WLAN is used on MMC5.

The only place MMC3 is bound is in the board files (see code snippet above), so that should be ok.

I can probably split this patch to make this more obvious just by reading the diffstat if you prefer.

Thanks,
Ohad.

Quoted 1 line
#48 lore raw

PATCH v2 19/20 omap: zoom: keep the MMC3 wl1271 device powered off

Ohad,

Quoted 58 lines

-----Original Message-----
From: Ohad Ben-Cohen [mailto:ohad at wizery.com]
Sent: Thursday, July 22, 2010 6:18 PM
To: Gabay, Benzy
Cc: linux-wireless at vger.kernel.org; linux-mmc at vger.kernel.org; linux- omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux at arm.linux.org.uk; Chikkature Rajashekar, Madhusudhan; Luciano Coelho; akpm at linux-foundation.org; San Mehat; Roger Quadros; Tony Lindgren; Nicolas Pitre; Pandita, Vikram; Kalle Valo
Subject: Re: [PATCH v2 19/20] omap: zoom: keep the MMC3 wl1271 device powered off

Hi Gever,

Quoted 3 lines · Benzy

From: Ohad Ben-Cohen [mailto:ohad at wizery.com]
Sent: Wednesday, July 21, 2010 12:34 PM
To: linux-wireless at vger.kernel.org; linux-mmc at vger.kernel.org; linux-

omap at vger.kernel.org

Quoted 1 line
Cc linux-arm-kernel at lists.infradead.org; linux at arm.linux.org.uk;

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

Quoted 1 line

Subject: [PATCH v2 19/20] omap: zoom: keep the MMC3 wl1271 device

powered off

Quoted 6 lines

Keep the MMC3 wl1271 WLAN device powered off until its SDIO function driver requests otherwise.

---

Review

Quoted 8 lines
?arch/arm/mach-omap2/board-zoom-peripherals.c | ? ?1 +
?arch/arm/mach-omap2/hsmmc.c ? ? ? ? ? ? ? ? ?| ? ?3 +++
?arch/arm/mach-omap2/hsmmc.h ? ? ? ? ? ? ? ? ?| ? ?1 +
?arch/arm/plat-omap/include/plat/mmc.h ? ? ? ?| ? ?3 +++
?drivers/mmc/host/omap_hsmmc.c ? ? ? ? ? ? ? ?| ? ?3 +++

?5 files changed, 11 insertions(+), 0 deletions(-)

(quoted diff) +0 -0

b/arch/arm/mach-omap2/board-zoom-peripherals.c

arch/arm/mach-omap2/board-zoom-peripherals.c static struct omap2_hsmmc_info mmc[] __initdata =

Quoted 4 lines

index 3230801..3ab9125 100644

arch/arm/mach-omap2/board-zoom-peripherals.c +0 -0
@@ -217,6 +217,7 @@ static struct omap2_hsmmc_info mmc[] __initdata =

{

Quoted 7 lines
arch/arm/mach-omap2/board-zoom-peripherals.c +1 -0
 ? ? ? ? ? ? ? ?.gpio_wp ? ? ? ?= -EINVAL,
 ? ? ? ? ? ? ? ?.gpio_cd ? ? ? ?= -EINVAL,
 ? ? ? ? ? ? ? ?.ocr_mask ? ? ? = MMC_VDD_165_195,
+ ? ? ? ? ? ? ? .dont_power_card = true,
 ? ? ? ? ? ? ? ?.priv_data ? ? ?= &omap_zoom_wlan_data,
 ? ? ? ?},

? ? ? ?{} ? ? ?/* Terminator */

...

Quoted 4 lines

--
1.7.0.4

[Benzy Gabay] small comment: Please make sure that all 127x related

changes are not bounded only to MMC3.

Quoted 8 lines
Quoted 1 line

On OMAP4 WLAN is used on MMC5.

The only place MMC3 is bound is in the board files (see code snippet above), so that should be ok.

I can probably split this patch to make this more obvious just by reading the diffstat if you prefer.

Yep. That will be great.

Benzy

Quoted 7 lines

Thanks,
Ohad.

Quoted 1 line
#49 lore raw

RE: [PATCH v2 19/20] omap: zoom: keep the MMC3 wl1271 device powered off

In reply to Ohad Ben-Cohen

Ohad,

-----Original Message-----
From: Ohad Ben-Cohen [mailto:[email protected]]
Sent: Wednesday, July 21, 2010 12:34 PM
To: [email protected]; [email protected]; [email protected]
Cc: [email protected]; [email protected]; Chikkature Rajashekar, Madhusudhan; Luciano Coelho; [email protected]; San Mehat; Roger Quadros; Tony Lindgren; Nicolas Pitre; Pandita, Vikram; Kalle Valo; Ohad Ben-Cohen
Subject: [PATCH v2 19/20] omap: zoom: keep the MMC3 wl1271 device powered off

Keep the MMC3 wl1271 WLAN device powered off until its SDIO function driver requests otherwise.

---
 arch/arm/mach-omap2/board-zoom-peripherals.c |    1 +
 arch/arm/mach-omap2/hsmmc.c                  |    3 +++
 arch/arm/mach-omap2/hsmmc.h                  |    1 +
 arch/arm/plat-omap/include/plat/mmc.h        |    3 +++
 drivers/mmc/host/omap_hsmmc.c                |    3 +++
 5 files changed, 11 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/board-zoom-peripherals.c +1 -0
index 3230801..3ab9125 100644
@@ -217,6 +217,7 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
 		.ocr_mask	= MMC_VDD_165_195,
+		.dont_power_card = true,
 		.priv_data	= &omap_zoom_wlan_data,
 	},
 	{}      /* Terminator */
arch/arm/mach-omap2/hsmmc.c +3 -0
index f06ddd2..24c4144 100644
@@ -284,6 +284,9 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
 		if (c->vcc_aux_disable_is_sleep)
 			mmc->slots[0].vcc_aux_disable_is_sleep = 1;
 
+		if (c->dont_power_card)
+			mmc->slots[0].dont_power_card = 1;
+
 		mmc->slots[0].priv_data = c->priv_data;
 
 		/* NOTE:  MMC slots should have a Vcc regulator set up.
arch/arm/mach-omap2/hsmmc.h +1 -0
index 434a3ed..e200786 100644
@@ -23,6 +23,7 @@ struct omap2_hsmmc_info {
 	int	ocr_mask;	/* temporary HACK */
 	/* Remux (pad configuation) when powering on/off */
 	void (*remux)(struct device *dev, int slot, int power_on);
+	bool	dont_power_card;/* keep card power off at boot (default is n)*/
 	void	*priv_data;	/* private data to SDIO function driver */
 };
 
arch/arm/plat-omap/include/plat/mmc.h +3 -0
index 9db1617..d042494 100644
@@ -140,6 +140,9 @@ struct omap_mmc_platform_data {
 
 		unsigned int ban_openended:1;
 
+		/* keep this card powered off at boot (default is n) */
+		unsigned int dont_power_card:1;
+
 		/* card private data that should be used by function driver */
 		void *priv_data;
 	} slots[OMAP_MMC_MAX_SLOTS];
drivers/mmc/host/omap_hsmmc.c +3 -0
index 4ac548e..4fb6634 100644
@@ -2157,6 +2157,9 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 	if (mmc_slot(host).nonremovable)
 		mmc->caps |= MMC_CAP_NONREMOVABLE;
 
+	if (mmc_slot(host).dont_power_card)
+		mmc->caps |= MMC_CAP_DONT_POWER_CARD;
+
 	mmc_set_embedded_data(mmc, mmc_slot(host).priv_data);
 
 	omap_hsmmc_conf_bus_power(host);
Signature · 4 lines
1.7.0.4

[Benzy Gabay] small comment: Please make sure that all 127x related changes are not bounded only to MMC3. 
On OMAP4 WLAN is used on MMC5.
#50 lore raw

PATCH v2 20/20 wireless: wl1271: call SDIO claim/release power API

In reply to Ohad Ben-Cohen

call SDIO claim/release power API to turn the wl1271 power on and off

---
 drivers/net/wireless/wl12xx/wl1271_sdio.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/net/wireless/wl12xx/wl1271_sdio.c +2 -0
index 5967718..a7e9ace 100644
@@ -152,11 +152,13 @@ static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
 	 * alive.
 	 */
 	if (enable) {
+		sdio_claim_power(func);
 		sdio_claim_host(func);
 		sdio_enable_func(func);
 	} else {
 		sdio_disable_func(func);
 		sdio_release_host(func);
+		sdio_release_power(func);
 	}
 
 	return 0;
Signature · 1 line
1.7.0.4
#51 lore raw

v2 cover native support for wl1271 on ZOOM

In reply to Ohad Ben-Cohen
Quoted 17 lines · Ohad Ben-Cohen

This patch series adds native support for wl1271 on ZOOM.

Changes since v1:

- introduce a fixed regulator device to control the power of wl1271
- allow to propagate private board-specific data to SDIO function drivers
- allow SDIO function driver to control the card's power via new API
- make it possible to keep the card's power down (without depending on an explicit SDIO function driver power-down request)

Thanks to these changes, we no longer need a separate platform device (carrying e.g. the external irq information of the device), and no longer need to emulate virtual card detect events.

The two "board muxing" pathces were already taken by Tony, and are resent here just to make it easier for people to use/test these pathces.

Quoted 6 lines

The changes to the MMC core really needs careful review; there still might be some pitfalls that haven't been covered. E.g., one thing we plan to look at next is their bahvior together with SDIO Suspend/Resume.

Special thanks to Roger Quadros and Nicolas Pitre for their extensive review and helpful suggestions.

FYI, I do intend to review those patches, but I'll be flying home in a couple hours, and once there I'll be gone on vacation for 2 weeks. So this review won't happen right away.

Nicolas

#52 lore raw

v2 cover native support for wl1271 on ZOOM

Quoted 23 lines · Nicolas Pitre
Quoted 21 lines · Ohad Ben-Cohen

This patch series adds native support for wl1271 on ZOOM.

Changes since v1:

- introduce a fixed regulator device to control the power of wl1271
- allow to propagate private board-specific data to SDIO function drivers
- allow SDIO function driver to control the card's power via new API
- make it possible to keep the card's power down (without depending ? on an explicit SDIO function driver power-down request)

Thanks to these changes, we no longer need a separate platform device (carrying e.g. the external irq information of the device), and no longer need to emulate virtual card detect events.

The two "board muxing" pathces were already taken by Tony, and are resent here just to make it easier for people to use/test these pathces.

The changes to the MMC core really needs careful review; there still might be some pitfalls that haven't been covered. E.g., one thing we plan to look at next is their bahvior together with SDIO Suspend/Resume.

Quoted 6 lines
Quoted 2 lines

Special thanks to Roger Quadros and Nicolas Pitre for their extensive review and helpful suggestions.

FYI, I do intend to review those patches, but I'll be flying home in a couple hours, and once there I'll be gone on vacation for 2 weeks. ?So this review won't happen right away.

Thanks, Nicolas.

Quoted 4 lines

Nicolas

#53 lore raw

v2 cover native support for wl1271 on ZOOM

In reply to Ohad Ben-Cohen
Quoted 1 line · Ohad Ben-Cohen

This patch series adds native support for wl1271 on ZOOM.

Just for the record, I'm fine with the wl1271 bits here going through the omap tree with the rest of the series.

John

Signature · 2 lines
John W. Linville		Someday the world will need a hero, and you
linville at tuxdriver.com			might be all we have.  Be ready.
#54 lore raw

v2 cover native support for wl1271 on ZOOM

Quoted 5 lines · John W. Linville
Quoted 1 line · Ohad Ben-Cohen

This patch series adds native support for wl1271 on ZOOM.

Just for the record, I'm fine with the wl1271 bits here going through the omap tree with the rest of the series.

Thanks, John.

Quoted 6 lines

John
--
John W. Linville ? ? ? ? ? ? ? ?Someday the world will need a hero, and you linville at tuxdriver.com ? ? ? ? ? ? ? ? ?might be all we have. ?Be ready.

#55 lore raw

v2 cover native support for wl1271 on ZOOM

In reply to John W. Linville
Quoted 5 lines · ext John W. Linville
Quoted 1 line · Ohad Ben-Cohen

This patch series adds native support for wl1271 on ZOOM.

Just for the record, I'm fine with the wl1271 bits here going through the omap tree with the rest of the series.

Yeah, I agree. This is probably the best way to keep things in sync.

Signature · 2 lines
Cheers,
Luca.
maintainer
#56 lore raw

v2 cover native support for wl1271 on ZOOM

Quoted 8 lines · Luciano Coelho
Quoted 5 lines · ext John W. Linville
Quoted 1 line · Ohad Ben-Cohen

This patch series adds native support for wl1271 on ZOOM.

Just for the record, I'm fine with the wl1271 bits here going through the omap tree with the rest of the series.

Yeah, I agree. This is probably the best way to keep things in sync.

OK, let's do that then.

Nicolas Pitre made a comment saying he wants to look at these patches more, are there other pending comments?

Regards,

Tony

#57 lore raw

v2 cover native support for wl1271 on ZOOM

Quoted 2 lines · Tony Lindgren

Nicolas Pitre made a comment saying he wants to look at these patches more, are there other pending comments?

I plan to post a v3 series this week with some of the comments that were already discussed after v2.

Thanks everyone for the attention,
Ohad.

Quoted 5 lines

Regards,

Tony

#58 lore raw

v2 cover native support for wl1271 on ZOOM

In reply to Tony Lindgren
Quoted 2 lines · Tony Lindgren

Nicolas Pitre made a comment saying he wants to look at these patches more, are there other pending comments?

Yep, I'm feeling quite uncomfortable with the way platform data is being passed over to sdio device now.

Also, specifically to 12xx, I'd like to see REF_CLOCK moved on and have this set by platform too (I haven't found anything like that in the patches but maybe I've overlooked that).

Thanks,
Vitaly

#59 lore raw

v2 cover native support for wl1271 on ZOOM

Quoted 3 lines · Vitaly Wool

Also, specifically to 12xx, I'd like to see REF_CLOCK moved on and have this set by platform too (I haven't found anything like that in the patches but maybe I've overlooked that).

Check out patch no. 9:

http://www.spinics.net/lists/arm-kernel/msg93836.html

Quoted 8 lines

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

#60 lore raw

v2 cover native support for wl1271 on ZOOM

Hi Ohad,

Quoted 2 lines · Ohad Ben-Cohen

Check out patch no. 9:

sorry for the confusion. However, I guess if the platform doesn't supply this value, we'll just consider it 0? Without any warning, right?

The problem is, we can't really distinguish between this field not set and value zero, and that means something is wrong with the design. The easiest way is probably changing the clock ids to start with 1.

Thanks,
Vitaly

#61 lore raw

v2 cover native support for wl1271 on ZOOM

Hi Vitaly,

Quoted 11 lines · Vitaly Wool
Quoted 2 lines · Ohad Ben-Cohen

Check out patch no. 9:

sorry for the confusion. However, I guess if the platform doesn't supply this value, we'll just consider it 0? Without any warning, right?

The problem is, we can't really distinguish between this field not set and value zero, and that means something is wrong with the design. The easiest way is probably changing the clock ids to start with 1.

I don't think it's a huge deal as adding new devices on board files is anyway something that is done carefully and not so often. Btw, we have this kind of mechanism in other locations of the kernel as well and it doesn't seem to be problematic (e.g. spi->chip_select, spi->mode, spi->irq, ...).

Having said that I don't mind applying your proposal either and pushing those defines by 1 in the driver. Luca what do you think ?

Thanks,
Ohad.

Quoted 4 lines

Thanks,
? Vitaly