wl1251-modules: rc script: full unload on stop and LED hack
[openpandora.oe.git] / recipes / pandora-system / wl1251-modules / 0002-wl1251-fix-ELP_CTRL-register-accesses-when-using-SDI.patch
1 From 41489f2e50030ba25d07d918b61911ea0b0b81fa Mon Sep 17 00:00:00 2001
2 From: Grazvydas Ignotas <notasas@gmail.com>
3 Date: Mon, 8 Mar 2010 17:37:01 +0200
4 Subject: [PATCH 2/5] wl1251: fix ELP_CTRL register accesses when using SDIO
5
6 For some unknown reason ELP_CTRL can't be accesed using
7 sdio_memcpy_* functions (any attemts to do so result in timeouts):
8
9  wl1251: ERROR sdio write failed (-110)
10  wl1251: ERROR sdio read failed (-110)
11  wl1251: WARNING WLAN not ready
12
13 To fix this, add special IO functions for ELP_CTRL access that are
14 using sdio_readb/sdio_writeb. Similar handling is done in TI
15 reference driver from Android code drop.
16
17 Signed-off-by: Grazvydas Ignotas <notasas@gmail.com>
18 Cc: Bob Copeland <me@bobcopeland.com>
19 ---
20  drivers/net/wireless/wl12xx/wl1251.h      |    2 ++
21  drivers/net/wireless/wl12xx/wl1251_io.h   |   20 ++++++++++++++++++++
22  drivers/net/wireless/wl12xx/wl1251_main.c |    4 ++--
23  drivers/net/wireless/wl12xx/wl1251_ps.c   |    8 ++++----
24  drivers/net/wireless/wl12xx/wl1251_sdio.c |   28 ++++++++++++++++++++++++++++
25  5 files changed, 56 insertions(+), 6 deletions(-)
26
27 diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h
28 index 37c61c1..4f5f02a 100644
29 --- a/drivers/net/wireless/wl12xx/wl1251.h
30 +++ b/drivers/net/wireless/wl12xx/wl1251.h
31 @@ -256,6 +256,8 @@ struct wl1251_debugfs {
32  struct wl1251_if_operations {
33         void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len);
34         void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len);
35 +       void (*read_elp)(struct wl1251 *wl, int addr, u32 *val);
36 +       void (*write_elp)(struct wl1251 *wl, int addr, u32 val);
37         void (*reset)(struct wl1251 *wl);
38         void (*enable_irq)(struct wl1251 *wl);
39         void (*disable_irq)(struct wl1251 *wl);
40 diff --git a/drivers/net/wireless/wl12xx/wl1251_io.h b/drivers/net/wireless/wl12xx/wl1251_io.h
41 index b89d2ac..c545e9d 100644
42 --- a/drivers/net/wireless/wl12xx/wl1251_io.h
43 +++ b/drivers/net/wireless/wl12xx/wl1251_io.h
44 @@ -48,6 +48,26 @@ static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val)
45         wl->if_ops->write(wl, addr, &val, sizeof(u32));
46  }
47  
48 +static inline u32 wl1251_read_elp(struct wl1251 *wl, int addr)
49 +{
50 +       u32 response;
51 +
52 +       if (wl->if_ops->read_elp)
53 +               wl->if_ops->read_elp(wl, addr, &response);
54 +       else
55 +               wl->if_ops->read(wl, addr, &response, sizeof(u32));
56 +
57 +       return response;
58 +}
59 +
60 +static inline void wl1251_write_elp(struct wl1251 *wl, int addr, u32 val)
61 +{
62 +       if (wl->if_ops->write_elp)
63 +               wl->if_ops->write_elp(wl, addr, val);
64 +       else
65 +               wl->if_ops->write(wl, addr, &val, sizeof(u32));
66 +}
67 +
68  /* Memory target IO, address is translated to partition 0 */
69  void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len);
70  void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len);
71 diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
72 index 0ef2d9c..7a8e489 100644
73 --- a/drivers/net/wireless/wl12xx/wl1251_main.c
74 +++ b/drivers/net/wireless/wl12xx/wl1251_main.c
75 @@ -149,8 +149,8 @@ static void wl1251_fw_wakeup(struct wl1251 *wl)
76         u32 elp_reg;
77  
78         elp_reg = ELPCTRL_WAKE_UP;
79 -       wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
80 -       elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
81 +       wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
82 +       elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
83  
84         if (!(elp_reg & ELPCTRL_WLAN_READY))
85                 wl1251_warning("WLAN not ready");
86 diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c
87 index 851dfb6..b55cb2b 100644
88 --- a/drivers/net/wireless/wl12xx/wl1251_ps.c
89 +++ b/drivers/net/wireless/wl12xx/wl1251_ps.c
90 @@ -45,7 +45,7 @@ void wl1251_elp_work(struct work_struct *work)
91                 goto out;
92  
93         wl1251_debug(DEBUG_PSM, "chip to elp");
94 -       wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
95 +       wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
96         wl->elp = true;
97  
98  out:
99 @@ -79,9 +79,9 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl)
100         start = jiffies;
101         timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT);
102  
103 -       wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
104 +       wl1251_write_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
105  
106 -       elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
107 +       elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
108  
109         /*
110          * FIXME: we should wait for irq from chip but, as a temporary
111 @@ -93,7 +93,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl)
112                         return -ETIMEDOUT;
113                 }
114                 msleep(1);
115 -               elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
116 +               elp_reg = wl1251_read_elp(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
117         }
118  
119         wl1251_debug(DEBUG_PSM, "wakeup time: %u ms",
120 diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c
121 index 0aceb91..4df1a20 100644
122 --- a/drivers/net/wireless/wl12xx/wl1251_sdio.c
123 +++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c
124 @@ -81,6 +81,32 @@ static void wl1251_sdio_write(struct wl1251 *wl, int addr,
125         sdio_release_host(func);
126  }
127  
128 +static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val)
129 +{
130 +       int ret = 0;
131 +       struct sdio_func *func = wl_to_func(wl);
132 +
133 +       sdio_claim_host(func);
134 +       *val = sdio_readb(func, addr, &ret);
135 +       sdio_release_host(func);
136 +
137 +       if (ret)
138 +               wl1251_error("sdio_readb failed (%d)", ret);
139 +}
140 +
141 +static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val)
142 +{
143 +       int ret = 0;
144 +       struct sdio_func *func = wl_to_func(wl);
145 +
146 +       sdio_claim_host(func);
147 +       sdio_writeb(func, val, addr, &ret);
148 +       sdio_release_host(func);
149 +
150 +       if (ret)
151 +               wl1251_error("sdio_writeb failed (%d)", ret);
152 +}
153 +
154  static void wl1251_sdio_reset(struct wl1251 *wl)
155  {
156  }
157 @@ -110,6 +136,8 @@ static void wl1251_sdio_set_power(bool enable)
158  static const struct wl1251_if_operations wl1251_sdio_ops = {
159         .read = wl1251_sdio_read,
160         .write = wl1251_sdio_write,
161 +       .write_elp = wl1251_sdio_write_elp,
162 +       .read_elp = wl1251_sdio_read_elp,
163         .reset = wl1251_sdio_reset,
164         .enable_irq = wl1251_sdio_enable_irq,
165         .disable_irq = wl1251_sdio_disable_irq,
166 -- 
167 1.6.3.3
168