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
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.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
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(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 6f1b6b5..a21cdb2 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -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);
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h
index bc806c7..4a5b92c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_io.h
+++ b/drivers/net/wireless/wl12xx/wl1271_io.h
@@ -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;
}
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index b7d9137..6bd748e 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -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);
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c
index 9903ae9..571c6b9 100644
--- a/drivers/net/wireless/wl12xx/wl1271_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c
@@ -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 = {
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
index e866049..85a167f 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -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 = {
--
1.7.0.4
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.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
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(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index a21cdb2..595f1a8 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -357,6 +357,7 @@ struct wl1271 {
void (*set_power)(bool enable);
int irq;
+ int ref_clock;
spinlock_t wl_lock;
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index 1a36d8a..d3f0521 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -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]);
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h
index f829699..f73b0b1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.h
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.h
@@ -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
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c
index 75901a6..5967718 100644
--- a/drivers/net/wireless/wl12xx/wl1271_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c
@@ -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;
}
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
index 85a167f..501b8b4 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -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");
diff --git a/include/linux/wl12xx.h b/include/linux/wl12xx.h
index 137ac89..ef6eed9 100644
--- a/include/linux/wl12xx.h
+++ b/include/linux/wl12xx.h
@@ -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
--
1.7.0.4
Ohad,
> -----Original Message-----
> From: Ohad Ben-Cohen [mailto:[email protected]]
> Sent: Thursday, July 22, 2010 6:18 PM
> To: Gabay, Benzy
> Cc: [email protected]; [email protected]; linux-
> [email protected]; [email protected];
> [email protected]; Chikkature Rajashekar, Madhusudhan; Luciano
> Coelho; [email protected]; 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,
>
> On Wed, Jul 21, 2010 at 9:55 PM, Gabay, Benzy <[email protected]> wrote:
> > From: Ohad Ben-Cohen [mailto:[email protected]]
> > Sent: Wednesday, July 21, 2010 12:34 PM
> > To: [email protected]; [email protected]; linux-
> [email protected]
> > Cc: [email protected]; [email protected];
> Chikkature Rajashekar, Madhusudhan; Luciano Coelho; akpm@linux-
> foundation.org; San Mehat; Roger Quadros; Tony Lindgren; Nicolas Pitre;
> Pandita, Vikram; Kalle Valo; Ohad Ben-Cohen
> > Subject: [PATCH 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.
> >
> > Signed-off-by: Ohad Ben-Cohen <[email protected]>
> > ---
> > ?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(-)
> >
> > diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c
> b/arch/arm/mach-omap2/board-zoom-peripherals.c
> > index 3230801..3ab9125 100644
> > --- a/arch/arm/mach-omap2/board-zoom-peripherals.c
> > +++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
> > @@ -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 */
> ...
> > --
> > 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.
Yep. That will be great.
Benzy
>
>
> Thanks,
> Ohad.
>
>
> >
On Sun, Jul 25, 2010 at 4:56 PM, Nicolas Pitre <[email protected]> wrote:
> On Sun, 25 Jul 2010, Ohad Ben-Cohen wrote:
>
>> On Thu, Jul 22, 2010 at 2:35 PM, Roger Quadros <[email protected]> wrote:
>> > On 07/21/2010 08:33 PM, ext Ohad Ben-Cohen wrote:
>> >>
>> >> 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.
>> >>
>> >> Signed-off-by: Ohad Ben-Cohen<[email protected]>
>> >
>> > 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.
>
> Exactly!
Ok, v3 is on the way :)
(featuring no special host CAP, fix locking issues, and power down
unclaimed cards also on resume)
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.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
drivers/mmc/core/sdio.c | 14 +++++++++++++-
drivers/mmc/core/sdio_bus.c | 9 ---------
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 79e6fa1..5c0fbfa 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -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);
}
}
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 4a890dc..87269f6 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -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);
}
--
1.7.0.4
Add SDIO IDs for TI and for TI's wl1271 wlan device.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
include/linux/mmc/sdio_ids.h | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h
index 33b2ea0..0d313c6 100644
--- a/include/linux/mmc/sdio_ids.h
+++ b/include/linux/mmc/sdio_ids.h
@@ -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
--
1.7.0.4
On Mon, Jul 26, 2010 at 10:30 PM, John W. Linville
<[email protected]> wrote:
> On Wed, Jul 21, 2010 at 08:33:34PM +0300, Ohad Ben-Cohen wrote:
>> 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.
>
> John
> --
> John W. Linville ? ? ? ? ? ? ? ?Someday the world will need a hero, and you
> [email protected] ? ? ? ? ? ? ? ? ?might be all we have. ?Be ready.
>
On Wed, Jul 21, 2010 at 08:33:44PM +0300, Ohad Ben-Cohen wrote:
> +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.
On Wed, Jul 21, 2010 at 08:33:34PM +0300, Ohad Ben-Cohen wrote:
> 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
--
John W. Linville Someday the world will need a hero, and you
[email protected] might be all we have. Be ready.
Add board muxing to support the wlan wl1271 chip that is
hardwired to mmc2 (third mmc controller) on the ZOOM2.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
arch/arm/mach-omap2/board-zoom2.c | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c
index 803ef14..1520a2c 100644
--- a/arch/arm/mach-omap2/board-zoom2.c
+++ b/arch/arm/mach-omap2/board-zoom2.c
@@ -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
--
1.7.0.4
Move wl12xx.h outside of the spi-specific location,
so it can be shared with both spi and sdio solutions.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
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
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c
index c561332..416d5aa 100644
--- a/drivers/net/wireless/wl12xx/wl1251_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c
@@ -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"
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c
index e814742..4847b6a 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.c
@@ -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"
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
index 5189b81..e866049 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -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"
diff --git a/include/linux/spi/wl12xx.h b/include/linux/spi/wl12xx.h
deleted file mode 100644
index a223ecb..0000000
--- a/include/linux/spi/wl12xx.h
+++ /dev/null
@@ -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
diff --git a/include/linux/wl12xx.h b/include/linux/wl12xx.h
new file mode 100644
index 0000000..137ac89
--- /dev/null
+++ b/include/linux/wl12xx.h
@@ -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
--
1.7.0.4
On Fri, Jul 23, 2010 at 02:13:38AM +0300, Ohad Ben-Cohen wrote:
> On Thu, Jul 22, 2010 at 2:16 PM, Roger Quadros <[email protected]> wrote:
> > .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.
Hi Vitaly,
On Wed, Jul 28, 2010 at 10:47 PM, Vitaly Wool <[email protected]> wrote:
> On Wed, Jul 21, 2010 at 7:33 PM, Ohad Ben-Cohen <[email protected]> wrote:
>> 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>
>> @@ -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.
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.
>
> ~Vitaly
>
Hi Gever,
On Wed, Jul 21, 2010 at 9:55 PM, Gabay, Benzy <[email protected]> wrote:
> 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.
>
> Signed-off-by: Ohad Ben-Cohen <[email protected]>
> ---
> ?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(-)
>
> diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
> index 3230801..3ab9125 100644
> --- a/arch/arm/mach-omap2/board-zoom-peripherals.c
> +++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
> @@ -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 */
...
> --
> 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.
>
Add board muxing to support the wlan wl1271 chip that is
hardwired to mmc2 (third mmc controller) on the ZOOM3.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
arch/arm/mach-omap2/board-zoom3.c | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/board-zoom3.c b/arch/arm/mach-omap2/board-zoom3.c
index 3314704..7d17046 100644
--- a/arch/arm/mach-omap2/board-zoom3.c
+++ b/arch/arm/mach-omap2/board-zoom3.c
@@ -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
--
1.7.0.4
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).
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
include/linux/mmc/host.h | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index f65913c..80db597 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -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
--
1.7.0.4
On Thu, Jul 22, 2010 at 2:16 PM, Roger Quadros <[email protected]> wrote:
> On 07/21/2010 08:59 PM, ext Mark Brown wrote:
>>
>> On Wed, Jul 21, 2010 at 08:33:44PM +0300, Ohad Ben-Cohen wrote:
>>
>>> +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"
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.
>
> regards,
> -roger
>
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).
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
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(-)
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 5d3d789..f06ddd2 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -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.
diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h
index 36f0ba8..434a3ed 100644
--- a/arch/arm/mach-omap2/hsmmc.h
+++ b/arch/arm/mach-omap2/hsmmc.h
@@ -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)
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
index c835f1e..9db1617 100644
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ b/arch/arm/plat-omap/include/plat/mmc.h
@@ -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];
};
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 4c5a669..4ac548e 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -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 */
--
1.7.0.4
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.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
arch/arm/mach-omap2/board-zoom-peripherals.c | 19 +++++++++++++++++++
1 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 2fc0f4a..3230801 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -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;
}
--
1.7.0.4
Before invoking a card's resume handler, verify one exists.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
drivers/mmc/core/sdio.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 645f173..37739f5 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -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);
}
}
--
1.7.0.4
Hi Ohad,
On Wed, Jul 21, 2010 at 7:33 PM, Ohad Ben-Cohen <[email protected]> wrote:
> 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>
> @@ -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
call SDIO claim/release power API to turn the wl1271
power on and off
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_sdio.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c
index 5967718..a7e9ace 100644
--- a/drivers/net/wireless/wl12xx/wl1271_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c
@@ -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;
--
1.7.0.4
Add a fixed regulator vmmc device to enable power control
of the wl1271 wlan device.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
arch/arm/mach-omap2/board-zoom-peripherals.c | 34 ++++++++++++++++++++++++++
1 files changed, 34 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 6b39849..2fc0f4a 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -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();
}
--
1.7.0.4
On Wed, 21 Jul 2010, Ohad Ben-Cohen wrote:
> 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.
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
On Fri, Jul 23, 2010 at 1:56 AM, Nicolas Pitre <[email protected]> wrote:
> On Wed, 21 Jul 2010, Ohad Ben-Cohen wrote:
>
>> 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.
>
> 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.
>
>
> Nicolas
>
On Sun, 25 Jul 2010, Ohad Ben-Cohen wrote:
> On Thu, Jul 22, 2010 at 2:35 PM, Roger Quadros <[email protected]> wrote:
> > On 07/21/2010 08:33 PM, ext Ohad Ben-Cohen wrote:
> >>
> >> 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.
> >>
> >> Signed-off-by: Ohad Ben-Cohen<[email protected]>
> >
> > 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.
Exactly!
> 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
On 07/21/2010 08:33 PM, ext Ohad Ben-Cohen wrote:
> 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.
>
> Signed-off-by: Ohad Ben-Cohen<[email protected]>
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
Remove the hard coded irq information, and instead take
the irq information from the board private data
which is supplied by the sdio function.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_sdio.c | 14 ++++++++------
1 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c
index 571c6b9..75901a6 100644
--- a/drivers/net/wireless/wl12xx/wl1271_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c
@@ -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;
}
--
1.7.0.4
Hi Ohad,
> Add SDIO IDs for TI and for TI's wl1271 wlan device.
>
> Signed-off-by: Ohad Ben-Cohen <[email protected]>
> ---
> include/linux/mmc/sdio_ids.h | 3 +++
> 1 files changed, 3 insertions(+), 0 deletions(-)
>
> diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h
> index 33b2ea0..0d313c6 100644
> --- a/include/linux/mmc/sdio_ids.h
> +++ b/include/linux/mmc/sdio_ids.h
> @@ -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
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.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
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(-)
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 49d9dca..33151d5 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -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);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 569e94d..ca5e3bf 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1334,6 +1334,56 @@ EXPORT_SYMBOL(mmc_resume_host);
#endif
+/**
+ * mmc_release_power - remove power from the card
+ * @host: mmc host
+ */
+int mmc_release_power(struct mmc_host *host)
+{
+ int err = 0;
+
+ mmc_bus_get(host);
+ if (host->bus_ops && !host->bus_dead) {
+ if (host->bus_ops->suspend)
+ err = host->bus_ops->suspend(host);
+ /* it's ok not to have a suspend handler */
+ err = err == -ENOSYS ? 0 : err;
+ }
+ mmc_bus_put(host);
+
+ if (!err)
+ mmc_power_off(host);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(mmc_release_power);
+
+/*
+ * mmc_claim_power - power up card
+ * @host: mmc host
+ */
+int mmc_claim_power(struct mmc_host *host)
+{
+ int err = 0;
+
+ mmc_bus_get(host);
+
+ mmc_power_up(host);
+ mmc_select_voltage(host, host->ocr);
+
+ BUG_ON(!host->bus_ops->resume);
+ err = host->bus_ops->resume(host);
+ if (err) {
+ printk(KERN_WARNING "%s: error %d during resume "
+ "(card was removed?)\n",
+ mmc_hostname(host), err);
+ }
+ mmc_bus_put(host);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(mmc_claim_power);
+
static int __init mmc_init(void)
{
int ret;
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 37739f5..79e6fa1 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -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:
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index 0f687cd..28ebc16 100644
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -17,6 +17,56 @@
#include "sdio_ops.h"
/**
+ * sdio_release_power - allow to release power of a certain SDIO function
+ * @func: SDIO function that is accessed
+ *
+ * Indicate to the core SDIO layer that we're not requiring that the
+ * function remain powered. If all functions for the card are in the
+ * same "no power" state, then the host controller can remove power from
+ * the card. Note: the function driver must preserve hardware states if
+ * necessary.
+ */
+int sdio_release_power(struct sdio_func *func)
+{
+ int ret = 0;
+ BUG_ON(!func);
+ BUG_ON(!func->card);
+
+ if (atomic_dec_and_test(&func->card->power_claims))
+ ret = mmc_release_power(func->card->host);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(sdio_release_power);
+
+/*
+ * sdio_claim_power - request power for a certain SDIO function
+ * @func: SDIO function that is accessed
+ *
+ * Indicate to the core SDIO layer that we want power back for this
+ * SDIO function. The power may or may not actually have been removed
+ * since last call to sdio_release_power(), so the function driver must
+ * not assume any preserved state at the hardware level and re-perform
+ * all the necessary hardware config. This function returns 0 when
+ * power is actually restored, or some error code if this cannot be
+ * achieved. One error reason might be that the card is no longer
+ * available on the bus (was removed while powered down and card
+ * detection didn't trigger yet).
+ */
+int sdio_claim_power(struct sdio_func *func)
+{
+ int ret = 0;
+ BUG_ON(!func);
+ BUG_ON(!func->card);
+
+ if (atomic_inc_return(&func->card->power_claims) == 1)
+ ret = mmc_claim_power(func->card->host);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(sdio_claim_power);
+
+/**
* sdio_claim_host - exclusively claim a bus for a certain SDIO function
* @func: SDIO function that will be accessed
*
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index d02d2c6..4073b43 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -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)
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 80db597..3675d58 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -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);
diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h
index 31baaf8..e77b676 100644
--- a/include/linux/mmc/sdio_func.h
+++ b/include/linux/mmc/sdio_func.h
@@ -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);
--
1.7.0.4
Hi Marcel,
On Wed, Jul 21, 2010 at 8:58 PM, Marcel Holtmann <[email protected]> wrote:
>> Add SDIO IDs for TI and for TI's wl1271 wlan device.
>>
>> Signed-off-by: Ohad Ben-Cohen <[email protected]>
>> ---
>> ?include/linux/mmc/sdio_ids.h | ? ?3 +++
>> ?1 files changed, 3 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h
>> index 33b2ea0..0d313c6 100644
>> --- a/include/linux/mmc/sdio_ids.h
>> +++ b/include/linux/mmc/sdio_ids.h
>> @@ -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?
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.
> 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 [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>
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.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
arch/arm/mach-omap2/hsmmc.c | 10 ++++--
drivers/mmc/host/omap_hsmmc.c | 67 ++++++++++++++++++++++++++++++++++++----
2 files changed, 66 insertions(+), 11 deletions(-)
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 1ef54b0..5d3d789 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -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);
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index b032828..4c5a669 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -258,7 +258,7 @@ static int omap_hsmmc_1_set_power(struct device *dev, int slot, int power_on,
return ret;
}
-static int omap_hsmmc_23_set_power(struct device *dev, int slot, int power_on,
+static int omap_hsmmc_2_set_power(struct device *dev, int slot, int power_on,
int vdd)
{
struct omap_hsmmc_host *host =
@@ -309,6 +309,31 @@ static int omap_hsmmc_23_set_power(struct device *dev, int slot, int power_on,
return ret;
}
+static int omap_hsmmc_3_set_power(struct device *dev, int slot, int power_on,
+ int vdd)
+{
+ struct omap_hsmmc_host *host =
+ platform_get_drvdata(to_platform_device(dev));
+ int ret = 0;
+
+ if (power_on) {
+ ret = mmc_regulator_set_ocr(host->vcc, vdd);
+ /* Enable interface voltage rail, if needed */
+ if (ret == 0 && host->vcc) {
+ ret = regulator_enable(host->vcc);
+ if (ret < 0)
+ ret = mmc_regulator_set_ocr(host->vcc, 0);
+ }
+ } else {
+ if (host->vcc)
+ ret = regulator_disable(host->vcc);
+ if (ret == 0)
+ ret = mmc_regulator_set_ocr(host->vcc, 0);
+ }
+
+ return ret;
+}
+
static int omap_hsmmc_1_set_sleep(struct device *dev, int slot, int sleep,
int vdd, int cardsleep)
{
@@ -319,7 +344,7 @@ static int omap_hsmmc_1_set_sleep(struct device *dev, int slot, int sleep,
return regulator_set_mode(host->vcc, mode);
}
-static int omap_hsmmc_23_set_sleep(struct device *dev, int slot, int sleep,
+static int omap_hsmmc_2_set_sleep(struct device *dev, int slot, int sleep,
int vdd, int cardsleep)
{
struct omap_hsmmc_host *host =
@@ -358,6 +383,31 @@ static int omap_hsmmc_23_set_sleep(struct device *dev, int slot, int sleep,
return regulator_enable(host->vcc_aux);
}
+static int omap_hsmmc_3_set_sleep(struct device *dev, int slot, int sleep,
+ int vdd, int cardsleep)
+{
+ struct omap_hsmmc_host *host =
+ platform_get_drvdata(to_platform_device(dev));
+ int err = 0;
+
+ /*
+ * If we don't see a Vcc regulator, assume it's a fixed
+ * voltage always-on regulator.
+ */
+ if (!host->vcc)
+ return 0;
+
+ if (cardsleep) {
+ /* VCC can be turned off if card is asleep */
+ if (sleep)
+ err = mmc_regulator_set_ocr(host->vcc, 0);
+ else
+ err = mmc_regulator_set_ocr(host->vcc, vdd);
+ }
+
+ return err;
+}
+
static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
{
struct regulator *reg;
@@ -370,10 +420,13 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
mmc_slot(host).set_sleep = omap_hsmmc_1_set_sleep;
break;
case OMAP_MMC2_DEVID:
- case OMAP_MMC3_DEVID:
/* Off-chip level shifting, or none */
- mmc_slot(host).set_power = omap_hsmmc_23_set_power;
- mmc_slot(host).set_sleep = omap_hsmmc_23_set_sleep;
+ mmc_slot(host).set_power = omap_hsmmc_2_set_power;
+ mmc_slot(host).set_sleep = omap_hsmmc_2_set_sleep;
+ break;
+ case OMAP_MMC3_DEVID:
+ mmc_slot(host).set_power = omap_hsmmc_3_set_power;
+ mmc_slot(host).set_sleep = omap_hsmmc_3_set_sleep;
break;
default:
pr_err("MMC%d configuration not supported!\n", host->id);
@@ -386,9 +439,9 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
/*
* HACK: until fixed.c regulator is usable,
* we don't require a main regulator
- * for MMC2 or MMC3
+ * for MMC2
*/
- if (host->id == OMAP_MMC1_DEVID) {
+ if (host->id != OMAP_MMC2_DEVID) {
ret = PTR_ERR(reg);
goto err;
}
--
1.7.0.4
On Thu, Jul 22, 2010 at 2:35 PM, Roger Quadros <[email protected]> wrote:
> On 07/21/2010 08:33 PM, ext Ohad Ben-Cohen wrote:
>>
>> 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.
>>
>> Signed-off-by: Ohad Ben-Cohen<[email protected]>
>
> 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.
> flag, it seems more like a request from the board to keep the card powered
> off.
>
> regards,
> -roger
>
Hi Ohad,
On Thu, Jul 29, 2010 at 8:00 AM, Ohad Ben-Cohen <[email protected]> wrote:
>> 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) ?
>
> 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
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.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
drivers/mmc/core/sdio.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index b9dee28..645f173 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -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);
--
1.7.0.4
On 07/21/2010 08:59 PM, ext Mark Brown wrote:
> On Wed, Jul 21, 2010 at 08:33:44PM +0300, Ohad Ben-Cohen wrote:
>
>> +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
On Fri, Jul 23, 2010 at 12:15 PM, Mark Brown
<[email protected]> wrote:
> On Fri, Jul 23, 2010 at 02:13:38AM +0300, Ohad Ben-Cohen wrote:
>> On Thu, Jul 22, 2010 at 2:16 PM, Roger Quadros <[email protected]> wrote:
>> > .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.
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.
>
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.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
drivers/mmc/core/sdio.c | 15 +++++++++++++--
include/linux/mmc/host.h | 1 +
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 5c0fbfa..164353f 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -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);
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 3675d58..756cf38 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -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 */
--
1.7.0.4
Remove SDIO IDs from the driver code since now it is
included in linux/mmc/sdio_ids.h.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_sdio.c | 8 --------
1 files changed, 0 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c
index d3d6f30..9903ae9 100644
--- a/drivers/net/wireless/wl12xx/wl1271_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c
@@ -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) },
{}
--
1.7.0.4
Keep the MMC3 wl1271 WLAN device powered off until its
SDIO function driver requests otherwise.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
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(-)
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 3230801..3ab9125 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -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 */
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index f06ddd2..24c4144 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -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.
diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h
index 434a3ed..e200786 100644
--- a/arch/arm/mach-omap2/hsmmc.h
+++ b/arch/arm/mach-omap2/hsmmc.h
@@ -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 */
};
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
index 9db1617..d042494 100644
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ b/arch/arm/plat-omap/include/plat/mmc.h
@@ -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];
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 4ac548e..4fb6634 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -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);
--
1.7.0.4
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.
Signed-off-by: Ohad Ben-Cohen <[email protected]>
---
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(-)
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 3230801..3ab9125 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -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 */
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index f06ddd2..24c4144 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -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.
diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h
index 434a3ed..e200786 100644
--- a/arch/arm/mach-omap2/hsmmc.h
+++ b/arch/arm/mach-omap2/hsmmc.h
@@ -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 */
};
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
index 9db1617..d042494 100644
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ b/arch/arm/plat-omap/include/plat/mmc.h
@@ -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];
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 4ac548e..4fb6634 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -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);
--
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.
On Mon, 2010-07-26 at 21:30 +0200, ext John W. Linville wrote:
> On Wed, Jul 21, 2010 at 08:33:34PM +0300, Ohad Ben-Cohen wrote:
> > 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.
--
Cheers,
Luca.
On Wed, Aug 04, 2010 at 02:24:39PM +0300, Ohad Ben-Cohen wrote:
> Hi Vitaly,
>
> On Tue, Aug 3, 2010 at 5:17 PM, Vitaly Wool <[email protected]> wrote:
> > On Mon, Aug 2, 2010 at 11:35 PM, Ohad Ben-Cohen <[email protected]> wrote:
> >> 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.
> >
> > 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):
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.
On Mon, Aug 2, 2010 at 2:42 PM, Tony Lindgren <[email protected]> wrote:
> 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.
>
> Regards,
>
> Tony
>
On Wed, Aug 4, 2010 at 2:42 PM, Ohad Ben-Cohen <[email protected]> wrote:
> On Wed, Aug 4, 2010 at 2:41 PM, Russell King - ARM Linux
> <[email protected]> wrote:
>> On Wed, Aug 04, 2010 at 02:24:39PM +0300, Ohad Ben-Cohen wrote:
>>> On Tue, Aug 3, 2010 at 5:17 PM, Vitaly Wool <[email protected]> wrote:
>>> > On Mon, Aug 2, 2010 at 11:35 PM, Ohad Ben-Cohen <[email protected]> wrote:
>>> >> 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.
>>> >
>>> > 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):
>>
>> 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 ?
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
Hi Vitaly,
On Tue, Aug 3, 2010 at 5:17 PM, Vitaly Wool <[email protected]> wrote:
> On Mon, Aug 2, 2010 at 11:35 PM, Ohad Ben-Cohen <[email protected]> wrote:
>> 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.
>
> 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):
diff --git a/arch/arm/mach-msm/board-trout-mmc.c b/arch/arm/mach-msm/board-trout
index 13755f5..df32b2f 100644
--- a/arch/arm/mach-msm/board-trout-mmc.c
+++ b/arch/arm/mach-msm/board-trout-mmc.c
@@ -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)
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 1697d42..c40f0d1 100755
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -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.
On Mon, Aug 2, 2010 at 6:12 PM, Vitaly Wool <[email protected]> wrote:
> 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
>
> Thanks,
> ? Vitaly
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>
Hi Vitaly,
On Mon, Aug 2, 2010 at 7:25 PM, Vitaly Wool <[email protected]> wrote:
> On Mon, Aug 2, 2010 at 5:54 PM, Ohad Ben-Cohen <[email protected]> wrote:
>> 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,
>
> 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.
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.
>
> Thanks,
> ? Vitaly
>
Hi Ohad,
On Mon, Aug 2, 2010 at 5:54 PM, Ohad Ben-Cohen <[email protected]> wrote:
> 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,
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
Hi Vitaly,
On Mon, Aug 2, 2010 at 7:19 PM, Vitaly Wool <[email protected]> wrote:
> On Mon, Aug 2, 2010 at 5:59 PM, Ohad Ben-Cohen <[email protected]> wrote:
>>
>> 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.
>
> Thanks,
> ? Vitaly
>
On Fri, Aug 06, 2010 at 01:02:24PM +0300, Ohad Ben-Cohen wrote:
> 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.
2010/8/4 Ohad Ben-Cohen <[email protected]>:
> On Wed, Aug 4, 2010 at 2:41 PM, Russell King - ARM Linux
>>
>> 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
* Luciano Coelho <[email protected]> [100802 11:10]:
> On Mon, 2010-07-26 at 21:30 +0200, ext John W. Linville wrote:
> > On Wed, Jul 21, 2010 at 08:33:34PM +0300, Ohad Ben-Cohen wrote:
> > > 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
Hi Ohad,
On Mon, Aug 2, 2010 at 5:59 PM, Ohad Ben-Cohen <[email protected]> wrote:
>
> 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
On Fri, Aug 6, 2010 at 10:07 AM, Linus Walleij
<[email protected]> wrote:
> 2010/8/4 Ohad Ben-Cohen <[email protected]>:
>> On Wed, Aug 4, 2010 at 2:41 PM, Russell King - ARM Linux
>>>
>>> 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.
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.
On Mon, Aug 2, 2010 at 1:42 PM, Tony Lindgren <[email protected]> wrote:
> 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
On Wed, Aug 4, 2010 at 2:41 PM, Russell King - ARM Linux
<[email protected]> wrote:
> On Wed, Aug 04, 2010 at 02:24:39PM +0300, Ohad Ben-Cohen wrote:
>> On Tue, Aug 3, 2010 at 5:17 PM, Vitaly Wool <[email protected]> wrote:
>> > On Mon, Aug 2, 2010 at 11:35 PM, Ohad Ben-Cohen <[email protected]> wrote:
>> >> 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.
>> >
>> > 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):
>
> 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.
>
> 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.
>
On Fri, 6 Aug 2010, Russell King - ARM Linux wrote:
> On Fri, Aug 06, 2010 at 01:02:24PM +0300, Ohad Ben-Cohen wrote:
> > 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.
DT is not generally available yet. A simple interim solution would
still be worth it.
Nicolas
Hi Vitaly,
On Thu, Jul 29, 2010 at 7:16 PM, Vitaly Wool <[email protected]> wrote:
> On Thu, Jul 29, 2010 at 8:00 AM, Ohad Ben-Cohen <[email protected]> wrote:
>>> 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) ?
>>
>> 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.
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.
>
> ~Vitaly
>
Hi Ohad,
On Mon, Aug 2, 2010 at 11:35 PM, Ohad Ben-Cohen <[email protected]> wrote:
> 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