aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorGrazvydas Ignotas <notasas@gmail.com>2010-03-11 10:44:57 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-03-15 15:32:03 -0400
commit3f9e750d130b4a4d9f8226642b46ed17d8357f40 (patch)
tree761497200ae8a5c2ca0ac3b7ce9b9e44dde23533 /drivers/net
parent3c9cb9c38a1368b1e3f187f23c1a56883ec656c2 (diff)
wl1251: fix ELP_CTRL register accesses when using SDIO
For some unknown reason ELP_CTRL can't be accesed using sdio_memcpy_* functions (any attemts to do so result in timeouts): wl1251: ERROR sdio write failed (-110) wl1251: ERROR sdio read failed (-110) wl1251: WARNING WLAN not ready To fix this, add special IO functions for ELP_CTRL access that are using sdio_readb/sdio_writeb. Similar handling is done in TI reference driver from Android code drop. Signed-off-by: Grazvydas Ignotas <notasas@gmail.com> Cc: Bob Copeland <me@bobcopeland.com> Acked-by: Kalle Valo <kalle.valo@iki.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/wl12xx/wl1251.h2
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_io.h20
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_main.c4
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_ps.c8
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_sdio.c28
5 files changed, 56 insertions, 6 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h
index 37c61c19cae5..4f5f02a26e62 100644
--- a/drivers/net/wireless/wl12xx/wl1251.h
+++ b/drivers/net/wireless/wl12xx/wl1251.h
@@ -256,6 +256,8 @@ struct wl1251_debugfs {
256struct wl1251_if_operations { 256struct wl1251_if_operations {
257 void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len); 257 void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len);
258 void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len); 258 void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len);
259 void (*read_elp)(struct wl1251 *wl, int addr, u32 *val);
260 void (*write_elp)(struct wl1251 *wl, int addr, u32 val);
259 void (*reset)(struct wl1251 *wl); 261 void (*reset)(struct wl1251 *wl);
260 void (*enable_irq)(struct wl1251 *wl); 262 void (*enable_irq)(struct wl1251 *wl);
261 void (*disable_irq)(struct wl1251 *wl); 263 void (*disable_irq)(struct wl1251 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.h b/drivers/net/wireless/wl12xx/wl1251_io.h
index b89d2ac62efb..c545e9d5f512 100644
--- a/drivers/net/wireless/wl12xx/wl1251_io.h
+++ b/drivers/net/wireless/wl12xx/wl1251_io.h
@@ -48,6 +48,26 @@ static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val)
48 wl->if_ops->write(wl, addr, &val, sizeof(u32)); 48 wl->if_ops->write(wl, addr, &val, sizeof(u32));
49} 49}
50 50
51static inline u32 wl1251_read_elp(struct wl1251 *wl, int addr)
52{
53 u32 response;
54
55 if (wl->if_ops->read_elp)
56 wl->if_ops->read_elp(wl, addr, &response);
57 else
58 wl->if_ops->read(wl, addr, &response, sizeof(u32));
59
60 return response;
61}
62
63static inline void wl1251_write_elp(struct wl1251 *wl, int addr, u32 val)
64{
65 if (wl->if_ops->write_elp)
66 wl->if_ops->write_elp(wl, addr, val);
67 else
68 wl->if_ops->write(wl, addr, &val, sizeof(u32));
69}
70
51/* Memory target IO, address is translated to partition 0 */ 71/* Memory target IO, address is translated to partition 0 */
52void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len); 72void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len);
53void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len); 73void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len);
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index 24ae6a360ac8..0155653b7105 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -146,8 +146,8 @@ static void wl1251_fw_wakeup(struct wl1251 *wl)
146 u32 elp_reg; 146 u32 elp_reg;
147 147
148 elp_reg = ELPCTRL_WAKE_UP; 148 elp_reg = ELPCTRL_WAKE_UP;
149 wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); 149 wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
150 elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); 150 elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
151 151
152 if (!(elp_reg & ELPCTRL_WLAN_READY)) 152 if (!(elp_reg & ELPCTRL_WLAN_READY))
153 wl1251_warning("WLAN not ready"); 153 wl1251_warning("WLAN not ready");
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c
index 851dfb65e474..b55cb2bd459a 100644
--- a/drivers/net/wireless/wl12xx/wl1251_ps.c
+++ b/drivers/net/wireless/wl12xx/wl1251_ps.c
@@ -45,7 +45,7 @@ void wl1251_elp_work(struct work_struct *work)
45 goto out; 45 goto out;
46 46
47 wl1251_debug(DEBUG_PSM, "chip to elp"); 47 wl1251_debug(DEBUG_PSM, "chip to elp");
48 wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); 48 wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
49 wl->elp = true; 49 wl->elp = true;
50 50
51out: 51out:
@@ -79,9 +79,9 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl)
79 start = jiffies; 79 start = jiffies;
80 timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT); 80 timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT);
81 81
82 wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); 82 wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
83 83
84 elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); 84 elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
85 85
86 /* 86 /*
87 * FIXME: we should wait for irq from chip but, as a temporary 87 * FIXME: we should wait for irq from chip but, as a temporary
@@ -93,7 +93,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl)
93 return -ETIMEDOUT; 93 return -ETIMEDOUT;
94 } 94 }
95 msleep(1); 95 msleep(1);
96 elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); 96 elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
97 } 97 }
98 98
99 wl1251_debug(DEBUG_PSM, "wakeup time: %u ms", 99 wl1251_debug(DEBUG_PSM, "wakeup time: %u ms",
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c
index cfca232dc8cb..2051ef06e9ec 100644
--- a/drivers/net/wireless/wl12xx/wl1251_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c
@@ -82,6 +82,32 @@ static void wl1251_sdio_write(struct wl1251 *wl, int addr,
82 sdio_release_host(func); 82 sdio_release_host(func);
83} 83}
84 84
85static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val)
86{
87 int ret = 0;
88 struct sdio_func *func = wl_to_func(wl);
89
90 sdio_claim_host(func);
91 *val = sdio_readb(func, addr, &ret);
92 sdio_release_host(func);
93
94 if (ret)
95 wl1251_error("sdio_readb failed (%d)", ret);
96}
97
98static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val)
99{
100 int ret = 0;
101 struct sdio_func *func = wl_to_func(wl);
102
103 sdio_claim_host(func);
104 sdio_writeb(func, val, addr, &ret);
105 sdio_release_host(func);
106
107 if (ret)
108 wl1251_error("sdio_writeb failed (%d)", ret);
109}
110
85static void wl1251_sdio_reset(struct wl1251 *wl) 111static void wl1251_sdio_reset(struct wl1251 *wl)
86{ 112{
87} 113}
@@ -111,6 +137,8 @@ static void wl1251_sdio_set_power(bool enable)
111static const struct wl1251_if_operations wl1251_sdio_ops = { 137static const struct wl1251_if_operations wl1251_sdio_ops = {
112 .read = wl1251_sdio_read, 138 .read = wl1251_sdio_read,
113 .write = wl1251_sdio_write, 139 .write = wl1251_sdio_write,
140 .write_elp = wl1251_sdio_write_elp,
141 .read_elp = wl1251_sdio_read_elp,
114 .reset = wl1251_sdio_reset, 142 .reset = wl1251_sdio_reset,
115 .enable_irq = wl1251_sdio_enable_irq, 143 .enable_irq = wl1251_sdio_enable_irq,
116 .disable_irq = wl1251_sdio_disable_irq, 144 .disable_irq = wl1251_sdio_disable_irq,