Skip to content

Commit

Permalink
wl1251: fix ELP_CTRL register reads
Browse files Browse the repository at this point in the history
Reading the ELP_CTRL register with sdio_readb causes problems because
hardware seems to be performing a write using stuff bits in the request
(those bits contain write data in write request). This indicates that it
actually expects RAW (read after write) type of request, so perform that
when reading ELP_CTRL instead. Also cache last written value so we know
what to write when doing RAW request.

Because of the above it was not possible to wake the chip from ELP power
saving mode, PM had to be disabled to have the driver usable in SDIO
mode. After this patch PM is functional.

For backporting to 2.6.34 or earlier, this patch depends on
6c1f716, which adds the
required SDIO funcion.

Signed-off-by: Grazvydas Ignotas <notasas@gmail.com>
Acked-by: Kalle Valo <kvalo@adurom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Grazvydas Ignotas authored and John W. Linville committed Jun 8, 2010
1 parent abe37c4 commit 832c10f
Showing 1 changed file with 34 additions and 6 deletions.
40 changes: 34 additions & 6 deletions drivers/net/wireless/wl12xx/wl1251_sdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,17 @@
#define SDIO_DEVICE_ID_TI_WL1251 0x9066
#endif

struct wl1251_sdio {
struct sdio_func *func;
u32 elp_val;
};

static struct wl12xx_platform_data *wl12xx_board_data;

static struct sdio_func *wl_to_func(struct wl1251 *wl)
{
return wl->if_priv;
struct wl1251_sdio *wl_sdio = wl->if_priv;
return wl_sdio->func;
}

static void wl1251_sdio_interrupt(struct sdio_func *func)
Expand Down Expand Up @@ -90,10 +96,17 @@ static void wl1251_sdio_write(struct wl1251 *wl, int addr,
static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val)
{
int ret = 0;
struct sdio_func *func = wl_to_func(wl);

struct wl1251_sdio *wl_sdio = wl->if_priv;
struct sdio_func *func = wl_sdio->func;

/*
* The hardware only supports RAW (read after write) access for
* reading, regular sdio_readb won't work here (it interprets
* the unused bits of CMD52 as write data even if we send read
* request).
*/
sdio_claim_host(func);
*val = sdio_readb(func, addr, &ret);
*val = sdio_writeb_readb(func, wl_sdio->elp_val, addr, &ret);
sdio_release_host(func);

if (ret)
Expand All @@ -103,14 +116,17 @@ static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val)
static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val)
{
int ret = 0;
struct sdio_func *func = wl_to_func(wl);
struct wl1251_sdio *wl_sdio = wl->if_priv;
struct sdio_func *func = wl_sdio->func;

sdio_claim_host(func);
sdio_writeb(func, val, addr, &ret);
sdio_release_host(func);

if (ret)
wl1251_error("sdio_writeb failed (%d)", ret);
else
wl_sdio->elp_val = val;
}

static void wl1251_sdio_reset(struct wl1251 *wl)
Expand Down Expand Up @@ -197,13 +213,20 @@ static int wl1251_sdio_probe(struct sdio_func *func,
int ret;
struct wl1251 *wl;
struct ieee80211_hw *hw;
struct wl1251_sdio *wl_sdio;

hw = wl1251_alloc_hw();
if (IS_ERR(hw))
return PTR_ERR(hw);

wl = hw->priv;

wl_sdio = kzalloc(sizeof(*wl_sdio), GFP_KERNEL);
if (wl_sdio == NULL) {
ret = -ENOMEM;
goto out_free_hw;
}

sdio_claim_host(func);
ret = sdio_enable_func(func);
if (ret)
Expand All @@ -213,7 +236,8 @@ static int wl1251_sdio_probe(struct sdio_func *func,
sdio_release_host(func);

SET_IEEE80211_DEV(hw, &func->dev);
wl->if_priv = func;
wl_sdio->func = func;
wl->if_priv = wl_sdio;
wl->if_ops = &wl1251_sdio_ops;
wl->set_power = wl1251_sdio_set_power;

Expand Down Expand Up @@ -259,16 +283,20 @@ static int wl1251_sdio_probe(struct sdio_func *func,
sdio_disable_func(func);
release:
sdio_release_host(func);
kfree(wl_sdio);
out_free_hw:
wl1251_free_hw(wl);
return ret;
}

static void __devexit wl1251_sdio_remove(struct sdio_func *func)
{
struct wl1251 *wl = sdio_get_drvdata(func);
struct wl1251_sdio *wl_sdio = wl->if_priv;

if (wl->irq)
free_irq(wl->irq, wl);
kfree(wl_sdio);
wl1251_free_hw(wl);

sdio_claim_host(func);
Expand Down

0 comments on commit 832c10f

Please sign in to comment.